summaryrefslogtreecommitdiffstats
path: root/chrome/browser/web_resource
diff options
context:
space:
mode:
authorjstritar@chromium.org <jstritar@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-08 03:05:55 +0000
committerjstritar@chromium.org <jstritar@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-08 03:05:55 +0000
commit808c096eeadb6b7d701a76fb660fd18c4b1a9497 (patch)
tree7d80a2097013588ab0e68d03c73f852ba4dacdb3 /chrome/browser/web_resource
parent75185918cc565c908ce16346644d3008bb0ff91f (diff)
downloadchromium_src-808c096eeadb6b7d701a76fb660fd18c4b1a9497.zip
chromium_src-808c096eeadb6b7d701a76fb660fd18c4b1a9497.tar.gz
chromium_src-808c096eeadb6b7d701a76fb660fd18c4b1a9497.tar.bz2
Add support to download web store promo logos over https.
This lets you define apps promo logos as https URLs in the promo feed. The AppsPromoLogoDownloader only downloads the image over https and from *.google.com domains. AppsPromo caches the image until the URL changes in the promo feed. BUG=84506 TEST=*Promo* Review URL: http://codereview.chromium.org/7820003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@100089 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/web_resource')
-rw-r--r--chrome/browser/web_resource/promo_resource_service.cc31
-rw-r--r--chrome/browser/web_resource/promo_resource_service.h26
-rw-r--r--chrome/browser/web_resource/promo_resource_service_unittest.cc196
3 files changed, 209 insertions, 44 deletions
diff --git a/chrome/browser/web_resource/promo_resource_service.cc b/chrome/browser/web_resource/promo_resource_service.cc
index 09b0aee..1336fd0 100644
--- a/chrome/browser/web_resource/promo_resource_service.cc
+++ b/chrome/browser/web_resource/promo_resource_service.cc
@@ -316,13 +316,9 @@ void PromoResourceService::UnpackWebStoreSignal(
bool is_webstore_active = false;
bool signal_found = false;
- std::string promo_id = "";
- std::string promo_header = "";
- std::string promo_button = "";
+ AppsPromo::PromoData promo_data;
std::string promo_link = "";
- std::string promo_expire = "";
std::string promo_logo = "";
- int maximize_setting = 0;
int target_builds = 0;
if (!parsed_json.GetDictionary("topic", &topic_dict) ||
@@ -362,24 +358,26 @@ void PromoResourceService::UnpackWebStoreSignal(
name = name.substr(split+1);
split = name.find(':');
if (split == std::string::npos ||
- !base::StringToInt(name.substr(0, split), &maximize_setting))
+ !base::StringToInt(name.substr(0, split), &promo_data.user_group))
continue;
// (4) optional text that specifies a URL of a logo image
promo_logo = name.substr(split+1);
- if (!a_dic->GetString(kAnswerIdProperty, &promo_id) ||
- !a_dic->GetString(kWebStoreHeaderProperty, &promo_header) ||
- !a_dic->GetString(kWebStoreButtonProperty, &promo_button) ||
+ if (!a_dic->GetString(kAnswerIdProperty, &promo_data.id) ||
+ !a_dic->GetString(kWebStoreHeaderProperty, &promo_data.header) ||
+ !a_dic->GetString(kWebStoreButtonProperty, &promo_data.button) ||
!a_dic->GetString(kWebStoreLinkProperty, &promo_link) ||
- !a_dic->GetString(kWebStoreExpireProperty, &promo_expire))
+ !a_dic->GetString(kWebStoreExpireProperty, &promo_data.expire))
continue;
if (IsThisBuildTargeted(target_builds)) {
- // Store the first web store promo that targets the current build.
- AppsPromo::SetPromo(promo_id, promo_header, promo_button,
- GURL(promo_link), promo_expire, GURL(promo_logo),
- maximize_setting);
+ // The downloader will set the promo prefs and send the
+ // NOTIFICATION_WEB_STORE_PROMO_LOADED notification.
+ promo_data.link = GURL(promo_link);
+ promo_data.logo = GURL(promo_logo);
+ apps_promo_logo_fetcher_.reset(
+ new AppsPromoLogoFetcher(profile_, promo_data));
signal_found = true;
break;
}
@@ -392,11 +390,6 @@ void PromoResourceService::UnpackWebStoreSignal(
AppsPromo::SetWebStoreSupportedForLocale(is_webstore_active);
- NotificationService::current()->Notify(
- chrome::NOTIFICATION_WEB_STORE_PROMO_LOADED,
- Source<Profile>(profile_),
- NotificationService::NoDetails());
-
return;
}
diff --git a/chrome/browser/web_resource/promo_resource_service.h b/chrome/browser/web_resource/promo_resource_service.h
index 2350418..a68e2aa 100644
--- a/chrome/browser/web_resource/promo_resource_service.h
+++ b/chrome/browser/web_resource/promo_resource_service.h
@@ -11,6 +11,8 @@
#include "chrome/browser/web_resource/web_resource_service.h"
#include "chrome/common/chrome_version_info.h"
+class AppsPromoLogoFetcher;
+class PrefService;
class Profile;
namespace PromoResourceServiceUtil {
@@ -21,8 +23,6 @@ bool CanShowPromo(Profile* profile);
} // namespace PromoResourceServiceUtil
-class PrefService;
-
// A PromoResourceService fetches data from a web resource server to be used to
// dynamically change the appearance of the New Tab Page. For example, it has
// been used to fetch "tips" to be displayed on the NTP, or to display
@@ -52,6 +52,13 @@ class PromoResourceService
FRIEND_TEST_ALL_PREFIXES(PromoResourceServiceTest, UnpackWebStoreSignal);
FRIEND_TEST_ALL_PREFIXES(
PromoResourceServiceTest, UnpackPartialWebStoreSignal);
+ FRIEND_TEST_ALL_PREFIXES(
+ PromoResourceServiceTest, UnpackWebStoreSignalHttpsLogo);
+ FRIEND_TEST_ALL_PREFIXES(
+ PromoResourceServiceTest, UnpackWebStoreSignalHttpsLogoError);
+ FRIEND_TEST_ALL_PREFIXES(
+ PromoResourceServiceTest, UnpackWebStoreSignalHttpLogo);
+
// Identifies types of Chrome builds for promo targeting.
enum BuildType {
@@ -168,7 +175,7 @@ class PromoResourceService
// "answers": [
// {
// "answer_id": "1143011",
- // "name": "webstore_promo:15:",
+ // "name": "webstore_promo:15:1:https://www.google.com/logo.png",
// "question": "Browse thousands of apps and games for Chrome.",
// "inproduct_target": "Visit the Chrome Web Store",
// "inproduct": "https://chrome.google.com/webstore?hl=en",
@@ -184,11 +191,13 @@ class PromoResourceService
// inproduct_target: the promo button text
// inproduct: the promo button link
// tooltip: the text for the "hide this" link on the promo
- // name: starts with "webstore_promo" to identify the signal. the second
+ // name: starts with "webstore_promo" to identify the signal. The second
// part contains the release channels targeted (bitwise or of
- // BuildTypes). The third part is optional and specifies the URL of
- // the logo image. In the example above, the URL is empty so the
- // default webstore logo will be used.
+ // BuildTypes). The third part specifies what users should maximize
+ // the apps section of the NTP when first loading the promo (bitwise
+ // or of AppsPromo::UserGroup). The forth part is optional and
+ // specifies the URL of the logo image. If left out, the default
+ // webstore logo will be used. The logo can be an HTTPS or DATA URL.
// answer_id: the promo's id
void UnpackWebStoreSignal(const base::DictionaryValue& parsed_json);
@@ -202,6 +211,9 @@ class PromoResourceService
// Overrides the current Chrome release channel for testing purposes.
chrome::VersionInfo::Channel channel_;
+ // A helper that downloads the promo logo.
+ scoped_ptr<AppsPromoLogoFetcher> apps_promo_logo_fetcher_;
+
DISALLOW_COPY_AND_ASSIGN(PromoResourceService);
};
diff --git a/chrome/browser/web_resource/promo_resource_service_unittest.cc b/chrome/browser/web_resource/promo_resource_service_unittest.cc
index b196b12..a69385c 100644
--- a/chrome/browser/web_resource/promo_resource_service_unittest.cc
+++ b/chrome/browser/web_resource/promo_resource_service_unittest.cc
@@ -15,6 +15,7 @@
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_pref_service.h"
#include "chrome/test/base/testing_profile.h"
+#include "content/test/test_url_fetcher_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
class PromoResourceServiceTest : public testing::Test {
@@ -28,6 +29,7 @@ class PromoResourceServiceTest : public testing::Test {
TestingProfile profile_;
ScopedTestingLocalState local_state_;
scoped_refptr<PromoResourceService> web_resource_service_;
+ MessageLoop loop_;
};
// Verifies that custom dates read from a web resource server are written to
@@ -131,9 +133,6 @@ TEST_F(PromoResourceServiceTest, UnpackPromoSignal) {
scoped_ptr<DictionaryValue> test_json(static_cast<DictionaryValue*>(
base::JSONReader::Read(json, false)));
- // Initialize a message loop for this to run on.
- MessageLoop loop;
-
// Check that prefs are set correctly.
web_resource_service_->UnpackPromoSignal(*(test_json.get()));
PrefService* prefs = profile_.GetPrefs();
@@ -187,22 +186,24 @@ TEST_F(PromoResourceServiceTest, UnpackWebStoreSignal) {
scoped_ptr<DictionaryValue> test_json(static_cast<DictionaryValue*>(
base::JSONReader::Read(json, false)));
- // Initialize a message loop for this to run on.
- MessageLoop loop;
+ // Set the source logo URL to verify that it gets cleared.
+ AppsPromo::SetSourcePromoLogoURL(GURL("https://www.google.com/test.png"));
// Check that prefs are set correctly.
web_resource_service_->UnpackWebStoreSignal(*(test_json.get()));
- PrefService* prefs = profile_.GetPrefs();
- ASSERT_TRUE(prefs != NULL);
- EXPECT_EQ("341252", AppsPromo::GetPromoId());
- EXPECT_EQ("The header!", AppsPromo::GetPromoHeaderText());
- EXPECT_EQ("The button label!", AppsPromo::GetPromoButtonText());
- EXPECT_EQ(GURL("http://link.com"), AppsPromo::GetPromoLink());
- EXPECT_EQ("No thanks, hide this.", AppsPromo::GetPromoExpireText());
- EXPECT_EQ(AppsPromo::USERS_NEW, AppsPromo::GetPromoUserGroup());
- EXPECT_EQ(GURL("chrome://theme/IDR_WEBSTORE_ICON"),
- AppsPromo::GetPromoLogo());
+ AppsPromo::PromoData actual_data = AppsPromo::GetPromo();
+ EXPECT_EQ("341252", actual_data.id);
+ EXPECT_EQ("The header!", actual_data.header);
+ EXPECT_EQ("The button label!", actual_data.button);
+ EXPECT_EQ(GURL("http://link.com"), actual_data.link);
+ EXPECT_EQ("No thanks, hide this.", actual_data.expire);
+ EXPECT_EQ(AppsPromo::USERS_NEW, actual_data.user_group);
+
+ // When we don't download a logo, we revert to the default and clear the
+ // source pref.
+ EXPECT_EQ(GURL("chrome://theme/IDR_WEBSTORE_ICON"), actual_data.logo);
+ EXPECT_EQ(GURL(""), AppsPromo::GetSourcePromoLogoURL());
}
// Tests that the "web store active" flag is set even when the web store promo
@@ -221,15 +222,174 @@ TEST_F(PromoResourceServiceTest, UnpackPartialWebStoreSignal) {
scoped_ptr<DictionaryValue> test_json(static_cast<DictionaryValue*>(
base::JSONReader::Read(json, false)));
- // Initialize a message loop for this to run on.
- MessageLoop loop;
-
// Check that prefs are set correctly.
web_resource_service_->UnpackWebStoreSignal(*(test_json.get()));
EXPECT_FALSE(AppsPromo::IsPromoSupportedForLocale());
EXPECT_TRUE(AppsPromo::IsWebStoreSupportedForLocale());
}
+// Tests that we can successfully unpack web store signals with HTTPS
+// logos.
+TEST_F(PromoResourceServiceTest, UnpackWebStoreSignalHttpsLogo) {
+ web_resource_service_->set_channel(chrome::VersionInfo::CHANNEL_DEV);
+
+ std::string logo_url = "https://www.google.com/image/test.png";
+ std::string png_data = "!$#%,./nvl;iadh9oh82";
+ std::string png_base64 = "data:image/png;base64,ISQjJSwuL252bDtpYWRoOW9oODI=";
+
+ FakeURLFetcherFactory factory;
+ factory.SetFakeResponse(logo_url, png_data, true);
+
+ std::string json =
+ "{ "
+ " \"topic\": {"
+ " \"answers\": ["
+ " {"
+ " \"answer_id\": \"340252\","
+ " \"name\": \"webstore_promo:15:1:" + logo_url + "\","
+ " \"question\": \"Header!\","
+ " \"inproduct_target\": \"The button label!\","
+ " \"inproduct\": \"http://link.com\","
+ " \"tooltip\": \"No thanks, hide this.\""
+ " }"
+ " ]"
+ " }"
+ "}";
+
+ scoped_ptr<DictionaryValue> test_json(static_cast<DictionaryValue*>(
+ base::JSONReader::Read(json, false)));
+
+ // Update the promo multiple times to verify the logo is cached correctly.
+ for (size_t i = 0; i < 2; ++i) {
+ web_resource_service_->UnpackWebStoreSignal(*(test_json.get()));
+
+ // We should only need to run the message loop the first time since the
+ // image is then cached.
+ if (i == 0)
+ loop_.RunAllPending();
+
+ // Reset this scoped_ptr to prevent a DCHECK.
+ web_resource_service_->apps_promo_logo_fetcher_.reset();
+
+ AppsPromo::PromoData actual_data = AppsPromo::GetPromo();
+ EXPECT_EQ("340252", actual_data.id);
+ EXPECT_EQ("Header!", actual_data.header);
+ EXPECT_EQ("The button label!", actual_data.button);
+ EXPECT_EQ(GURL("http://link.com"), actual_data.link);
+ EXPECT_EQ("No thanks, hide this.", actual_data.expire);
+ EXPECT_EQ(AppsPromo::USERS_NEW, actual_data.user_group);
+
+ // The logo should now be a base64 DATA URL.
+ EXPECT_EQ(GURL(png_base64), actual_data.logo);
+
+ // And the source pref should hold the source HTTPS URL.
+ EXPECT_EQ(GURL(logo_url), AppsPromo::GetSourcePromoLogoURL());
+ }
+}
+
+// Tests that we revert to the default logo when the fetch fails.
+TEST_F(PromoResourceServiceTest, UnpackWebStoreSignalHttpsLogoError) {
+ web_resource_service_->set_channel(chrome::VersionInfo::CHANNEL_DEV);
+
+ std::string logo_url = "https://www.google.com/image/test.png";
+ std::string png_data = "!$#%,./nvl;iadh9oh82";
+ std::string png_base64 = "ISQjJSwuL252bDtpYWRoOW9oODI=";
+
+ FakeURLFetcherFactory factory;
+
+ // Have URLFetcher return a 500 error.
+ factory.SetFakeResponse(logo_url, png_data, false);
+
+ std::string json =
+ "{ "
+ " \"topic\": {"
+ " \"answers\": ["
+ " {"
+ " \"answer_id\": \"340252\","
+ " \"name\": \"webstore_promo:15:1:" + logo_url + "\","
+ " \"question\": \"Header!\","
+ " \"inproduct_target\": \"The button label!\","
+ " \"inproduct\": \"http://link.com\","
+ " \"tooltip\": \"No thanks, hide this.\""
+ " }"
+ " ]"
+ " }"
+ "}";
+
+ scoped_ptr<DictionaryValue> test_json(static_cast<DictionaryValue*>(
+ base::JSONReader::Read(json, false)));
+
+ web_resource_service_->UnpackWebStoreSignal(*(test_json.get()));
+
+ loop_.RunAllPending();
+
+ // Reset this scoped_ptr to prevent a DCHECK.
+ web_resource_service_->apps_promo_logo_fetcher_.reset();
+
+ AppsPromo::PromoData actual_data = AppsPromo::GetPromo();
+ EXPECT_EQ("340252", actual_data.id);
+ EXPECT_EQ("Header!", actual_data.header);
+ EXPECT_EQ("The button label!", actual_data.button);
+ EXPECT_EQ(GURL("http://link.com"), actual_data.link);
+ EXPECT_EQ("No thanks, hide this.", actual_data.expire);
+ EXPECT_EQ(AppsPromo::USERS_NEW, actual_data.user_group);
+
+ // Logos are the default values.
+ EXPECT_EQ(GURL("chrome://theme/IDR_WEBSTORE_ICON"), actual_data.logo);
+ EXPECT_EQ(GURL(""), AppsPromo::GetSourcePromoLogoURL());
+}
+
+// Tests that we don't download images over HTTP.
+TEST_F(PromoResourceServiceTest, UnpackWebStoreSignalHttpLogo) {
+ web_resource_service_->set_channel(chrome::VersionInfo::CHANNEL_DEV);
+
+ // Use an HTTP URL.
+ std::string logo_url = "http://www.google.com/image/test.png";
+ std::string png_data = "!$#%,./nvl;iadh9oh82";
+ std::string png_base64 = "ISQjJSwuL252bDtpYWRoOW9oODI=";
+
+ FakeURLFetcherFactory factory;
+ factory.SetFakeResponse(logo_url, png_data, true);
+
+ std::string json =
+ "{ "
+ " \"topic\": {"
+ " \"answers\": ["
+ " {"
+ " \"answer_id\": \"340252\","
+ " \"name\": \"webstore_promo:15:1:" + logo_url + "\","
+ " \"question\": \"Header!\","
+ " \"inproduct_target\": \"The button label!\","
+ " \"inproduct\": \"http://link.com\","
+ " \"tooltip\": \"No thanks, hide this.\""
+ " }"
+ " ]"
+ " }"
+ "}";
+
+ scoped_ptr<DictionaryValue> test_json(static_cast<DictionaryValue*>(
+ base::JSONReader::Read(json, false)));
+
+ web_resource_service_->UnpackWebStoreSignal(*(test_json.get()));
+
+ loop_.RunAllPending();
+
+ // Reset this scoped_ptr to prevent a DCHECK.
+ web_resource_service_->apps_promo_logo_fetcher_.reset();
+
+ AppsPromo::PromoData actual_data = AppsPromo::GetPromo();
+ EXPECT_EQ("340252", actual_data.id);
+ EXPECT_EQ("Header!", actual_data.header);
+ EXPECT_EQ("The button label!", actual_data.button);
+ EXPECT_EQ(GURL("http://link.com"), actual_data.link);
+ EXPECT_EQ("No thanks, hide this.", actual_data.expire);
+ EXPECT_EQ(AppsPromo::USERS_NEW, actual_data.user_group);
+
+ // Logos should be the default values because HTTP URLs are not valid.
+ EXPECT_EQ(GURL("chrome://theme/IDR_WEBSTORE_ICON"), actual_data.logo);
+ EXPECT_EQ(GURL(""), AppsPromo::GetSourcePromoLogoURL());
+}
+
TEST_F(PromoResourceServiceTest, IsBuildTargeted) {
// canary
const chrome::VersionInfo::Channel canary =