Chromium Code Reviews| Index: chrome/browser/extensions/apps_promo.cc |
| diff --git a/chrome/browser/extensions/apps_promo.cc b/chrome/browser/extensions/apps_promo.cc |
| index a137bacc23dec2b399f9e50ec0bf7fef8855c319..ed25eda6f3c671648c132b7e62bae828ea702374 100644 |
| --- a/chrome/browser/extensions/apps_promo.cc |
| +++ b/chrome/browser/extensions/apps_promo.cc |
| @@ -4,21 +4,44 @@ |
| #include "chrome/browser/extensions/apps_promo.h" |
| +#include "base/base64.h" |
| #include "base/command_line.h" |
| #include "base/metrics/histogram.h" |
| #include "chrome/browser/browser_process.h" |
| #include "chrome/browser/prefs/pref_service.h" |
| +#include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/ui/webui/ntp/shown_sections_handler.h" |
| #include "chrome/common/chrome_switches.h" |
| #include "chrome/common/extensions/extension.h" |
| +#include "chrome/common/chrome_notification_types.h" |
| #include "chrome/common/pref_names.h" |
| +#include "content/common/url_constants.h" |
| +#include "content/common/notification_service.h" |
| +#include "net/base/load_flags.h" |
| +#include "net/url_request/url_request_status.h" |
| const int AppsPromo::kDefaultAppsCounterMax = 10; |
| namespace { |
| // The default logo for the promo. |
| -const char kDefaultPromoLogo[] = "chrome://theme/IDR_WEBSTORE_ICON"; |
| +const char kDefaultLogo[] = "chrome://theme/IDR_WEBSTORE_ICON"; |
| + |
| +// The default promo data (this is only used for testing with |
| +// --force-apps-promo-visible). |
| +const char kDefaultHeader[] = "Browse thousands of apps and games for Chrome"; |
| +const char kDefaultButton[] = "Visit the Chrome Web Store"; |
| +const char kDefaultExpire[] = "No thanks"; |
| +const char kDefaultLink[] = "https://chrome.google.com/webstore"; |
| + |
| +// Http success status code. |
| +const int kHttpSuccess = 200; |
| + |
| +// The match pattern for valid logo URLs. |
| +const char kValidLogoPattern[] = "https://*.google.com/*.png"; |
| + |
| +// The prefix for 'data' URL images. |
| +const char kPNGDataURLPrefix[] = "data:image/png;base64,"; |
| // Returns the string pref at |path|, using |fallback| as the default (if there |
| // is no pref value present). |fallback| is used for debugging in concert with |
| @@ -35,6 +58,24 @@ std::string GetStringPref(const char* path, const std::string& fallback) { |
| } // namespace |
| +AppsPromo::PromoData::PromoData() {} |
| +AppsPromo::PromoData::PromoData(const std::string& id, |
| + const std::string& header, |
| + const std::string& button, |
| + const GURL& link, |
| + const std::string& expire, |
| + const GURL& logo, |
| + const int user_group) |
| + : id(id), |
| + header(header), |
| + button(button), |
| + link(link), |
| + expire(expire), |
| + logo(logo), |
| + user_group(user_group) {} |
| + |
| +AppsPromo::PromoData::~PromoData() {} |
| + |
| // static |
| void AppsPromo::RegisterPrefs(PrefService* local_state) { |
| std::string empty; |
| @@ -44,6 +85,7 @@ void AppsPromo::RegisterPrefs(PrefService* local_state) { |
| local_state->RegisterStringPref(prefs::kNTPWebStorePromoButton, empty); |
| local_state->RegisterStringPref(prefs::kNTPWebStorePromoLink, empty); |
| local_state->RegisterStringPref(prefs::kNTPWebStorePromoLogo, empty); |
| + local_state->RegisterStringPref(prefs::kNTPWebStorePromoLogoSource, empty); |
| local_state->RegisterStringPref(prefs::kNTPWebStorePromoExpire, empty); |
| local_state->RegisterIntegerPref(prefs::kNTPWebStorePromoUserGroup, 0); |
| } |
| @@ -62,21 +104,8 @@ void AppsPromo::RegisterUserPrefs(PrefService* prefs) { |
| std::string(), |
| PrefService::UNSYNCABLE_PREF); |
| prefs->RegisterBooleanPref(prefs::kNTPHideWebStorePromo, |
| - false, |
| - PrefService::UNSYNCABLE_PREF); |
| -} |
| - |
| -// static |
| -void AppsPromo::ClearPromo() { |
| - PrefService* local_state = g_browser_process->local_state(); |
| - local_state->ClearPref(prefs::kNTPWebStoreEnabled); |
| - local_state->ClearPref(prefs::kNTPWebStorePromoId); |
| - local_state->ClearPref(prefs::kNTPWebStorePromoHeader); |
| - local_state->ClearPref(prefs::kNTPWebStorePromoButton); |
| - local_state->ClearPref(prefs::kNTPWebStorePromoLink); |
| - local_state->ClearPref(prefs::kNTPWebStorePromoLogo); |
| - local_state->ClearPref(prefs::kNTPWebStorePromoExpire); |
| - local_state->ClearPref(prefs::kNTPWebStorePromoUserGroup); |
| + false, |
| + PrefService::UNSYNCABLE_PREF); |
| } |
| // static |
| @@ -100,68 +129,68 @@ bool AppsPromo::IsWebStoreSupportedForLocale() { |
| } |
| // static |
| -std::string AppsPromo::GetPromoButtonText() { |
| - return GetStringPref(prefs::kNTPWebStorePromoButton, "Click here now"); |
| +void AppsPromo::SetWebStoreSupportedForLocale(bool supported) { |
| + PrefService* local_state = g_browser_process->local_state(); |
| + local_state->SetBoolean(prefs::kNTPWebStoreEnabled, supported); |
| } |
| // static |
| -std::string AppsPromo::GetPromoId() { |
| - return GetStringPref(prefs::kNTPWebStorePromoId, ""); |
| +void AppsPromo::ClearPromo() { |
| + PrefService* local_state = g_browser_process->local_state(); |
| + local_state->ClearPref(prefs::kNTPWebStoreEnabled); |
| + local_state->ClearPref(prefs::kNTPWebStorePromoId); |
| + local_state->ClearPref(prefs::kNTPWebStorePromoHeader); |
| + local_state->ClearPref(prefs::kNTPWebStorePromoButton); |
| + local_state->ClearPref(prefs::kNTPWebStorePromoLink); |
| + local_state->ClearPref(prefs::kNTPWebStorePromoLogo); |
| + local_state->ClearPref(prefs::kNTPWebStorePromoLogoSource); |
| + local_state->ClearPref(prefs::kNTPWebStorePromoExpire); |
| + local_state->ClearPref(prefs::kNTPWebStorePromoUserGroup); |
| } |
| // static |
| -std::string AppsPromo::GetPromoHeaderText() { |
| - return GetStringPref(prefs::kNTPWebStorePromoHeader, "Get great apps!"); |
| -} |
| +AppsPromo::PromoData AppsPromo::GetPromo() { |
| + PromoData data; |
| + PrefService* local_state = g_browser_process->local_state(); |
| -// static |
| -GURL AppsPromo::GetPromoLink() { |
| - return GURL(GetStringPref(prefs::kNTPWebStorePromoLink, |
| - "https://chrome.google.com/webstore")); |
| -} |
| + data.id = GetStringPref(prefs::kNTPWebStorePromoId, ""); |
| + data.link = GURL(GetStringPref(prefs::kNTPWebStorePromoLink, kDefaultLink)); |
| + data.user_group = local_state->GetInteger(prefs::kNTPWebStorePromoUserGroup); |
| + data.header = GetStringPref(prefs::kNTPWebStorePromoHeader, kDefaultHeader); |
| + data.button = GetStringPref(prefs::kNTPWebStorePromoButton, kDefaultButton); |
| + data.expire = GetStringPref(prefs::kNTPWebStorePromoExpire, kDefaultExpire); |
| -// static |
| -GURL AppsPromo::GetPromoLogo() { |
| - PrefService* local_state = g_browser_process->local_state(); |
| GURL logo_url(local_state->GetString(prefs::kNTPWebStorePromoLogo)); |
| - if (logo_url.is_valid() && logo_url.SchemeIs("data")) |
| - return logo_url; |
| - return GURL(kDefaultPromoLogo); |
| -} |
| + if (logo_url.is_valid() && logo_url.SchemeIs(chrome::kDataScheme)) |
| + data.logo = logo_url; |
| + else |
| + data.logo = GURL(kDefaultLogo); |
| -// static |
| -std::string AppsPromo::GetPromoExpireText() { |
| - return GetStringPref(prefs::kNTPWebStorePromoExpire, "No thanks."); |
| + return data; |
| } |
| // static |
| -int AppsPromo::GetPromoUserGroup() { |
| +void AppsPromo::SetPromo(AppsPromo::PromoData data) { |
| PrefService* local_state = g_browser_process->local_state(); |
| - return local_state->GetInteger(prefs::kNTPWebStorePromoUserGroup); |
| + local_state->SetString(prefs::kNTPWebStorePromoId, data.id); |
| + local_state->SetString(prefs::kNTPWebStorePromoButton, data.button); |
| + local_state->SetString(prefs::kNTPWebStorePromoHeader, data.header); |
| + local_state->SetString(prefs::kNTPWebStorePromoLink, data.link.spec()); |
| + local_state->SetString(prefs::kNTPWebStorePromoLogo, data.logo.spec()); |
| + local_state->SetString(prefs::kNTPWebStorePromoExpire, data.expire); |
| + local_state->SetInteger(prefs::kNTPWebStorePromoUserGroup, data.user_group); |
| } |
| // static |
| -void AppsPromo::SetPromo(const std::string& id, |
| - const std::string& header_text, |
| - const std::string& button_text, |
| - const GURL& link, |
| - const std::string& expire_text, |
| - const GURL& logo, |
| - const int user_group) { |
| - PrefService* local_state = g_browser_process->local_state(); |
| - local_state->SetString(prefs::kNTPWebStorePromoId, id); |
| - local_state->SetString(prefs::kNTPWebStorePromoButton, button_text); |
| - local_state->SetString(prefs::kNTPWebStorePromoHeader, header_text); |
| - local_state->SetString(prefs::kNTPWebStorePromoLink, link.spec()); |
| - local_state->SetString(prefs::kNTPWebStorePromoLogo, logo.spec()); |
| - local_state->SetString(prefs::kNTPWebStorePromoExpire, expire_text); |
| - local_state->SetInteger(prefs::kNTPWebStorePromoUserGroup, user_group); |
| +GURL AppsPromo::GetSourcePromoLogoURL() { |
| + return GURL(GetStringPref(prefs::kNTPWebStorePromoLogoSource, "")); |
| } |
| // static |
| -void AppsPromo::SetWebStoreSupportedForLocale(bool supported) { |
| +void AppsPromo::SetSourcePromoLogoURL(GURL logo_source) { |
| PrefService* local_state = g_browser_process->local_state(); |
| - local_state->SetBoolean(prefs::kNTPWebStoreEnabled, supported); |
| + local_state->SetString(prefs::kNTPWebStorePromoLogoSource, |
| + logo_source.spec()); |
| } |
| AppsPromo::AppsPromo(PrefService* prefs) |
| @@ -246,15 +275,14 @@ void AppsPromo::ExpireDefaultApps() { |
| } |
| void AppsPromo::MaximizeAppsIfNecessary() { |
| - std::string promo_id = GetPromoId(); |
| - int maximize_setting = GetPromoUserGroup(); |
| + PromoData promo = GetPromo(); |
| // Maximize the apps section of the NTP if this is the first time viewing the |
| // specific promo and the current user group is targetted. |
| - if (GetLastPromoId() != promo_id) { |
| - if ((maximize_setting & GetCurrentUserGroup()) != 0) |
| + if (GetLastPromoId() != promo.id) { |
| + if ((promo.user_group & GetCurrentUserGroup()) != 0) |
| ShownSectionsHandler::SetShownSection(prefs_, APPS); |
| - SetLastPromoId(promo_id); |
| + SetLastPromoId(promo.id); |
| } |
| } |
| @@ -297,3 +325,74 @@ AppsPromo::UserGroup AppsPromo::GetCurrentUserGroup() const { |
| CHECK(last_promo_id); |
| return last_promo_id->IsDefaultValue() ? USERS_NEW : USERS_EXISTING; |
| } |
| + |
| +AppsPromoLogoDownloader::AppsPromoLogoDownloader( |
| + Profile* profile, |
| + AppsPromo::PromoData promo_data) |
| + : profile_(profile), |
| + promo_data_(promo_data) { |
| + if (ShouldFetchLogo()) { |
| + // Record the source URL so we know when it has changed. |
| + AppsPromo::SetSourcePromoLogoURL(promo_data_.logo); |
| + FetchLogo(); |
| + } else { |
| + // We only care about the source logo URL when we need to fetch it. |
| + AppsPromo::SetSourcePromoLogoURL(GURL()); |
|
Mihai Parparita -not on Chrome
2011/09/02 03:02:21
Given that you're resetting the source URL if the
jstritar
2011/09/02 20:17:05
Yes, thanks for finding that! I fixed the problem
|
| + SavePromo(); |
| + } |
| +} |
| + |
| +AppsPromoLogoDownloader::~AppsPromoLogoDownloader() {} |
| + |
| +void AppsPromoLogoDownloader::OnURLFetchComplete(const URLFetcher* source) { |
| + std::string data; |
| + std::string base64_data; |
| + |
| + CHECK(source == url_fetcher_.get()); |
| + CHECK(source->GetResponseAsString(&data)); |
| + |
| + if (source->status().is_success() && |
| + source->response_code() == kHttpSuccess && |
| + base::Base64Encode(data, &base64_data)) { |
| + promo_data_.logo = GURL(kPNGDataURLPrefix + base64_data); |
| + } else { |
| + // The logo wasn't downloaded correctly or we failed to encode it in |
| + // base64. Reset the source URL so we fetch it again next time. AppsPromo |
| + // will revert to the default logo. |
| + AppsPromo::SetSourcePromoLogoURL(GURL()); |
| + } |
| + |
| + SavePromo(); |
| +} |
| + |
| +void AppsPromoLogoDownloader::FetchLogo() { |
| + CHECK(promo_data_.logo.scheme() == chrome::kHttpsScheme); |
| + |
| + url_fetcher_.reset(URLFetcher::Create( |
| + 0, promo_data_.logo, URLFetcher::GET, this)); |
| + url_fetcher_->set_request_context( |
| + g_browser_process->system_request_context()); |
| + url_fetcher_->set_load_flags(net::LOAD_DO_NOT_SEND_COOKIES | |
| + net::LOAD_DO_NOT_SAVE_COOKIES); |
| + url_fetcher_->Start(); |
| +} |
| + |
| +void AppsPromoLogoDownloader::SavePromo() { |
| + AppsPromo::SetPromo(promo_data_); |
| + |
| + NotificationService::current()->Notify( |
| + chrome::NOTIFICATION_WEB_STORE_PROMO_LOADED, |
| + Source<Profile>(profile_), |
| + NotificationService::NoDetails()); |
| +} |
| + |
| +bool AppsPromoLogoDownloader::ShouldFetchLogo() { |
| + URLPattern allowed_urls(URLPattern::SCHEME_HTTPS, kValidLogoPattern); |
| + if (!allowed_urls.MatchesURL(promo_data_.logo)) |
| + return false; |
| + |
| + // To prevent us from downloading the same image over and over again, we only |
| + // fetch the logo if the source URL of the existing logo is different from |
| + // the new logo URL. |
| + return promo_data_.logo != AppsPromo::GetSourcePromoLogoURL(); |
| +} |