diff options
-rw-r--r-- | chrome/app/theme/theme_resources.grd | 2 | ||||
-rw-r--r-- | chrome/browser/dom_ui/new_tab_ui.cc | 3 | ||||
-rw-r--r-- | chrome/browser/dom_ui/ntp_resource_cache.cc | 4 | ||||
-rw-r--r-- | chrome/browser/dom_ui/tips_handler.cc | 10 | ||||
-rw-r--r-- | chrome/browser/profile.cc | 4 | ||||
-rw-r--r-- | chrome/browser/profile.h | 3 | ||||
-rw-r--r-- | chrome/browser/profile_impl.cc | 8 | ||||
-rw-r--r-- | chrome/browser/profile_impl.h | 1 | ||||
-rw-r--r-- | chrome/browser/profile_manager.cc | 3 | ||||
-rw-r--r-- | chrome/browser/resources/new_new_tab.html | 3 | ||||
-rw-r--r-- | chrome/browser/resources/new_new_tab.js | 15 | ||||
-rw-r--r-- | chrome/browser/web_resource/web_resource_service.cc | 126 | ||||
-rw-r--r-- | chrome/browser/web_resource/web_resource_service.h | 48 | ||||
-rw-r--r-- | chrome/common/pref_names.cc | 21 | ||||
-rw-r--r-- | chrome/common/pref_names.h | 7 |
15 files changed, 183 insertions, 75 deletions
diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd index 1a20a67..b97feaf 100644 --- a/chrome/app/theme/theme_resources.grd +++ b/chrome/app/theme/theme_resources.grd @@ -253,12 +253,14 @@ <include name="IDR_PRODUCT_LOGO" file="google_chrome/product_logo.png" type="BINDATA" /> <include name="IDR_PRODUCT_LOGO_16" file="google_chrome/product_logo_16.png" type="BINDATA" /> <include name="IDR_PRODUCT_LOGO_WHITE" file="google_chrome/product_logo_white.png" type="BINDATA" /> + <include name="IDR_CUSTOM_PRODUCT_LOGO" file="google_chrome/product_logo.png" type="BINDATA" /> </if> <if expr="not pp_ifdef('_google_chrome')"> <include name="IDR_PRODUCT_ICON_32" file="chromium/chromium_icon_32.png" type="BINDATA" /> <include name="IDR_PRODUCT_LOGO" file="chromium/product_logo.png" type="BINDATA" /> <include name="IDR_PRODUCT_LOGO_WHITE" file="chromium/product_logo_white.png" type="BINDATA" /> <include name="IDR_PRODUCT_LOGO_16" file="chromium/product_logo_16.png" type="BINDATA" /> + <include name="IDR_CUSTOM_PRODUCT_LOGO" file="chromium/product_logo.png" type="BINDATA" /> </if> <!-- NOTE: product_logo_*.* files beyond what's listed above are referenced by installer code; don't remove them unless you know what diff --git a/chrome/browser/dom_ui/new_tab_ui.cc b/chrome/browser/dom_ui/new_tab_ui.cc index 2545845..7438d80 100644 --- a/chrome/browser/dom_ui/new_tab_ui.cc +++ b/chrome/browser/dom_ui/new_tab_ui.cc @@ -26,6 +26,7 @@ #include "chrome/browser/dom_ui/new_tab_page_sync_handler.h" #include "chrome/browser/dom_ui/ntp_resource_cache.h" #include "chrome/browser/dom_ui/shown_sections_handler.h" +#include "chrome/browser/dom_ui/tips_handler.h" #include "chrome/browser/metrics/user_metrics.h" #include "chrome/browser/themes/browser_theme_provider.h" #include "chrome/browser/prefs/pref_service.h" @@ -518,6 +519,8 @@ void NewTabUI::RegisterUserPrefs(PrefService* prefs) { MostVisitedHandler::RegisterUserPrefs(prefs); ShownSectionsHandler::RegisterUserPrefs(prefs); + if (NewTabUI::WebResourcesEnabled()) + TipsHandler::RegisterUserPrefs(prefs); UpdateUserPrefsVersion(prefs); } diff --git a/chrome/browser/dom_ui/ntp_resource_cache.cc b/chrome/browser/dom_ui/ntp_resource_cache.cc index a3e5020..169aea0 100644 --- a/chrome/browser/dom_ui/ntp_resource_cache.cc +++ b/chrome/browser/dom_ui/ntp_resource_cache.cc @@ -288,6 +288,10 @@ void NTPResourceCache::CreateNewTabHTML() { l10n_util::GetStringUTF16(IDS_EXTENSION_WEB_STORE_TITLE)); localized_strings.SetString("web_store_url", GetUrlWithLang(GURL(Extension::ChromeStoreURL()))); + localized_strings.SetString("customlogo", + profile_->GetPrefs()->FindPreference(prefs::kNTPCustomLogo) && + profile_->GetPrefs()->GetBoolean(prefs::kNTPCustomLogo) ? + "true" : "false"); // Don't initiate the sync related message passing with the page if the sync // code is not present. diff --git a/chrome/browser/dom_ui/tips_handler.cc b/chrome/browser/dom_ui/tips_handler.cc index be4ab75..4858b61 100644 --- a/chrome/browser/dom_ui/tips_handler.cc +++ b/chrome/browser/dom_ui/tips_handler.cc @@ -21,7 +21,7 @@ DOMMessageHandler* TipsHandler::Attach(DOMUI* dom_ui) { dom_ui_ = dom_ui; tips_cache_ = dom_ui_->GetProfile()->GetPrefs()-> - GetMutableDictionary(prefs::kNTPTipsCache); + GetMutableDictionary(prefs::kNTPWebResourceCache); return DOMMessageHandler::Attach(dom_ui); } @@ -45,8 +45,8 @@ void TipsHandler::HandleGetTips(const ListValue* args) { // We need to check here because the new tab page calls for tips before // the tip service starts up. PrefService* current_prefs = dom_ui_->GetProfile()->GetPrefs(); - if (current_prefs->HasPrefPath(prefs::kNTPTipsServer)) { - std::string server = current_prefs->GetString(prefs::kNTPTipsServer); + if (current_prefs->HasPrefPath(prefs::kNTPWebResourceServer)) { + std::string server = current_prefs->GetString(prefs::kNTPWebResourceServer); std::string locale = g_browser_process->GetApplicationLocale(); if (!EndsWith(server, locale, false)) { dom_ui_->CallJavascriptFunction(L"tips", list_value); @@ -97,8 +97,8 @@ void TipsHandler::SendTip(const std::string& tip, const std::string& tip_type, // static void TipsHandler::RegisterUserPrefs(PrefService* prefs) { - prefs->RegisterDictionaryPref(prefs::kNTPTipsCache); - prefs->RegisterStringPref(prefs::kNTPTipsServer, + prefs->RegisterDictionaryPref(prefs::kNTPWebResourceCache); + prefs->RegisterStringPref(prefs::kNTPWebResourceServer, WebResourceService::kDefaultResourceServer); } diff --git a/chrome/browser/profile.cc b/chrome/browser/profile.cc index a843377..e222bd0d 100644 --- a/chrome/browser/profile.cc +++ b/chrome/browser/profile.cc @@ -494,6 +494,10 @@ class OffTheRecordProfileImpl : public Profile, NOTREACHED(); } + virtual void InitWebResources() { + NOTREACHED(); + } + virtual NTPResourceCache* GetNTPResourceCache() { // Just return the real profile resource cache. return profile_->GetNTPResourceCache(); diff --git a/chrome/browser/profile.h b/chrome/browser/profile.h index 68eec93..bbd710c 100644 --- a/chrome/browser/profile.h +++ b/chrome/browser/profile.h @@ -432,6 +432,9 @@ class Profile { virtual void InitExtensions() = 0; + // Start up service that gathers data from a web resource feed. + virtual void InitWebResources() = 0; + // Returns the new tab page resource cache. virtual NTPResourceCache* GetNTPResourceCache() = 0; diff --git a/chrome/browser/profile_impl.cc b/chrome/browser/profile_impl.cc index 723eabc..c8498d2 100644 --- a/chrome/browser/profile_impl.cc +++ b/chrome/browser/profile_impl.cc @@ -440,6 +440,14 @@ void ProfileImpl::InitExtensions() { } } +void ProfileImpl::InitWebResources() { + if (web_resource_service_) + return; + + web_resource_service_ = new WebResourceService(this); + web_resource_service_->StartAfterDelay(); +} + NTPResourceCache* ProfileImpl::GetNTPResourceCache() { if (!ntp_resource_cache_.get()) ntp_resource_cache_.reset(new NTPResourceCache(this)); diff --git a/chrome/browser/profile_impl.h b/chrome/browser/profile_impl.h index 79e4438..e378290 100644 --- a/chrome/browser/profile_impl.h +++ b/chrome/browser/profile_impl.h @@ -96,6 +96,7 @@ class ProfileImpl : public Profile, virtual StatusTray* GetStatusTray(); virtual void MarkAsCleanShutdown(); virtual void InitExtensions(); + virtual void InitWebResources(); virtual NTPResourceCache* GetNTPResourceCache(); virtual FilePath last_selected_directory(); virtual void set_last_selected_directory(const FilePath& path); diff --git a/chrome/browser/profile_manager.cc b/chrome/browser/profile_manager.cc index 7c7da9b..35aa664 100644 --- a/chrome/browser/profile_manager.cc +++ b/chrome/browser/profile_manager.cc @@ -180,6 +180,9 @@ bool ProfileManager::AddProfile(Profile* profile, bool init_extensions) { profiles_.insert(profiles_.end(), profile); if (init_extensions) profile->InitExtensions(); + const CommandLine& command_line = *CommandLine::ForCurrentProcess(); + if (!command_line.HasSwitch(switches::kDisableWebResources)) + profile->InitWebResources(); return true; } diff --git a/chrome/browser/resources/new_new_tab.html b/chrome/browser/resources/new_new_tab.html index 99f8e77..e1c6574 100644 --- a/chrome/browser/resources/new_new_tab.html +++ b/chrome/browser/resources/new_new_tab.html @@ -4,7 +4,8 @@ bookmarkbarattached:bookmarkbarattached; hasattribution:hasattribution; anim:anim; - syncispresent:syncispresent"> + syncispresent:syncispresent; + customlogo:customlogo"> <head> <meta charset="utf-8"> <title i18n-content="title"></title> diff --git a/chrome/browser/resources/new_new_tab.js b/chrome/browser/resources/new_new_tab.js index 8a2691d..e472072 100644 --- a/chrome/browser/resources/new_new_tab.js +++ b/chrome/browser/resources/new_new_tab.js @@ -515,9 +515,18 @@ function themeChanged(hasAttribution) { } function updateAttribution() { - var imageId = - document.documentElement.getAttribute('hasattribution') == 'true' ? - 'IDR_THEME_NTP_ATTRIBUTION' : 'IDR_PRODUCT_LOGO'; + // Default value for standard NTP with no theme attribution or custom logo. + logEvent('updateAttribution called'); + var imageId = 'IDR_PRODUCT_LOGO'; + // Theme attribution always overrides custom logos. + if (document.documentElement.getAttribute('hasattribution') == 'true') { + logEvent('updateAttribution called with THEME ATTR'); + imageId = 'IDR_THEME_NTP_ATTRIBUTION'; + } else if (document.documentElement.getAttribute('customlogo') == 'true') { + logEvent('updateAttribution with CUSTOMLOGO'); + imageId = 'IDR_CUSTOM_PRODUCT_LOGO'; + } + $('attribution-img').src = 'chrome://theme/' + imageId + '?' + Date.now(); } diff --git a/chrome/browser/web_resource/web_resource_service.cc b/chrome/browser/web_resource/web_resource_service.cc index 16e0c33..ce34d1b 100644 --- a/chrome/browser/web_resource/web_resource_service.cc +++ b/chrome/browser/web_resource/web_resource_service.cc @@ -16,6 +16,8 @@ #include "chrome/browser/profile.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/net/url_fetcher.h" +#include "chrome/common/notification_service.h" +#include "chrome/common/notification_type.h" #include "chrome/common/pref_names.h" #include "googleurl/src/gurl.h" #include "net/base/load_flags.h" @@ -23,6 +25,7 @@ const char* WebResourceService::kCurrentTipPrefName = "current_tip"; const char* WebResourceService::kTipCachePrefName = "tips"; +const char* WebResourceService::kCustomLogoId = "1"; class WebResourceService::WebResourceFetcher : public URLFetcher::Delegate { @@ -192,12 +195,8 @@ const char* WebResourceService::kDefaultResourceServer = "https://clients2.google.com/tools/service/npredir?r=chrometips_win&hl="; #endif -const char* WebResourceService::kResourceDirectoryName = - "Resources"; - WebResourceService::WebResourceService(Profile* profile) : prefs_(profile->GetPrefs()), - web_resource_dir_(profile->GetPath().AppendASCII(kResourceDirectoryName)), in_fetch_(false) { Init(); } @@ -207,21 +206,22 @@ WebResourceService::~WebResourceService() { } void WebResourceService::Init() { resource_dispatcher_host_ = g_browser_process->resource_dispatcher_host(); web_resource_fetcher_ = new WebResourceFetcher(this); - prefs_->RegisterStringPref(prefs::kNTPTipsCacheUpdate, "0"); + prefs_->RegisterStringPref(prefs::kNTPWebResourceCacheUpdate, "0"); + prefs_->RegisterBooleanPref(prefs::kNTPCustomLogo, false); std::string locale = g_browser_process->GetApplicationLocale(); - if (prefs_->HasPrefPath(prefs::kNTPTipsServer)) { - web_resource_server_ = prefs_->GetString(prefs::kNTPTipsServer); + if (prefs_->HasPrefPath(prefs::kNTPWebResourceServer)) { + web_resource_server_ = prefs_->GetString(prefs::kNTPWebResourceServer); // If we are in the correct locale, initialization is done. if (EndsWith(web_resource_server_, locale, false)) return; } - // If we have not yet set a server, or if the tips server is set to the wrong - // locale, reset the server and force an immediate update of tips. + // If we have not yet set a server, or if the web resource server is set to + // the wrong locale, reset the server and force an immediate update. web_resource_server_ = kDefaultResourceServer; web_resource_server_.append(locale); - prefs_->SetString(prefs::kNTPTipsCacheUpdate, ""); + prefs_->SetString(prefs::kNTPWebResourceCacheUpdate, ""); } void WebResourceService::EndFetch() { @@ -230,9 +230,48 @@ void WebResourceService::EndFetch() { void WebResourceService::OnWebResourceUnpacked( const DictionaryValue& parsed_json) { + UnpackLogoSignal(parsed_json); + EndFetch(); +} + +void WebResourceService::StartAfterDelay() { + int delay = kStartResourceFetchDelay; + // Check whether we have ever put a value in the web resource cache; + // if so, pull it out and see if it's time to update again. + if (prefs_->HasPrefPath(prefs::kNTPWebResourceCacheUpdate)) { + std::string last_update_pref = + prefs_->GetString(prefs::kNTPWebResourceCacheUpdate); + if (!last_update_pref.empty()) { + double last_update_value; + base::StringToDouble(last_update_pref, &last_update_value); + int ms_until_update = kCacheUpdateDelay - + static_cast<int>((base::Time::Now() - base::Time::FromDoubleT( + last_update_value)).InMilliseconds()); + + delay = ms_until_update > kCacheUpdateDelay ? + kCacheUpdateDelay : (ms_until_update < kStartResourceFetchDelay ? + kStartResourceFetchDelay : ms_until_update); + } + } + + // Start fetch and wait for UpdateResourceCache. + web_resource_fetcher_->StartAfterDelay(static_cast<int>(delay)); +} + +void WebResourceService::UpdateResourceCache(const std::string& json_data) { + UnpackerClient* client = new UnpackerClient(this, json_data); + client->Start(); + + // Update resource server and cache update time in preferences. + prefs_->SetString(prefs::kNTPWebResourceCacheUpdate, + base::DoubleToString(base::Time::Now().ToDoubleT())); + prefs_->SetString(prefs::kNTPWebResourceServer, web_resource_server_); +} + +void WebResourceService::UnpackTips(const DictionaryValue& parsed_json) { // Get dictionary of cached preferences. web_resource_cache_ = - prefs_->GetMutableDictionary(prefs::kNTPTipsCache); + prefs_->GetMutableDictionary(prefs::kNTPWebResourceCache); // The list of individual tips. ListValue* tip_holder = new ListValue(); @@ -241,6 +280,7 @@ void WebResourceService::OnWebResourceUnpacked( DictionaryValue* topic_dict; ListValue* answer_list; std::string topic_id; + std::string answer_id; std::string inproduct; int tip_counter = 0; @@ -259,45 +299,45 @@ void WebResourceService::OnWebResourceUnpacked( } tip_counter++; } - // If we have tips, set current tip to zero. - if (!inproduct.empty()) + // If tips exist, set current index to 0. + if (!inproduct.empty()) { web_resource_cache_->SetInteger( WebResourceService::kCurrentTipPrefName, 0); + } } } - EndFetch(); } -void WebResourceService::StartAfterDelay() { - int delay = kStartResourceFetchDelay; - // Check whether we have ever put a value in the web resource cache; - // if so, pull it out and see if it's time to update again. - if (prefs_->HasPrefPath(prefs::kNTPTipsCacheUpdate)) { - std::string last_update_pref = - prefs_->GetString(prefs::kNTPTipsCacheUpdate); - if (!last_update_pref.empty()) { - double last_update_value; - base::StringToDouble(last_update_pref, &last_update_value); - int ms_until_update = kCacheUpdateDelay - - static_cast<int>((base::Time::Now() - base::Time::FromDoubleT( - last_update_value)).InMilliseconds()); +void WebResourceService::UnpackLogoSignal(const DictionaryValue& parsed_json) { + DictionaryValue* topic_dict; + ListValue* answer_list; + std::string logo_id; - delay = ms_until_update > kCacheUpdateDelay ? - kCacheUpdateDelay : (ms_until_update < kStartResourceFetchDelay ? - kStartResourceFetchDelay : ms_until_update); + if (parsed_json.GetDictionary("topic", &topic_dict)) { + if (topic_dict->GetList("answers", &answer_list)) { + for (ListValue::const_iterator tip_iter = answer_list->begin(); + tip_iter != answer_list->end(); ++tip_iter) { + if (!(*tip_iter)->IsType(Value::TYPE_DICTIONARY)) + continue; + DictionaryValue* a_dic = + static_cast<DictionaryValue*>(*tip_iter); + if (a_dic->GetString("logo_id", &logo_id)) { + prefs_->SetBoolean(prefs::kNTPCustomLogo, + LowerCaseEqualsASCII(logo_id, kCustomLogoId)); + NotificationService* service = NotificationService::current(); + service->Notify(NotificationType::BROWSER_THEME_CHANGED, + Source<WebResourceService>(this), + NotificationService::NoDetails()); + return; + } + } } } - - // Start fetch and wait for UpdateResourceCache. - web_resource_fetcher_->StartAfterDelay(static_cast<int>(delay)); -} - -void WebResourceService::UpdateResourceCache(const std::string& json_data) { - UnpackerClient* client = new UnpackerClient(this, json_data); - client->Start(); - - // Update resource server and cache update time in preferences. - prefs_->SetString(prefs::kNTPTipsCacheUpdate, - base::DoubleToString(base::Time::Now().ToDoubleT())); - prefs_->SetString(prefs::kNTPTipsServer, web_resource_server_); + // If no logo_id is found in the tips, show regular logo. + prefs_->SetBoolean(prefs::kNTPCustomLogo, + LowerCaseEqualsASCII(logo_id, kCustomLogoId)); + NotificationService* service = NotificationService::current(); + service->Notify(NotificationType::BROWSER_THEME_CHANGED, + Source<WebResourceService>(this), + NotificationService::NoDetails()); } diff --git a/chrome/browser/web_resource/web_resource_service.h b/chrome/browser/web_resource/web_resource_service.h index 28e952b..fd46e76 100644 --- a/chrome/browser/web_resource/web_resource_service.h +++ b/chrome/browser/web_resource/web_resource_service.h @@ -30,6 +30,7 @@ class WebResourceService static const char* kCurrentTipPrefName; static const char* kTipCachePrefName; + static const char* kCustomLogoId; // Default server from which to gather resources. static const char* kDefaultResourceServer; @@ -50,12 +51,44 @@ class WebResourceService // Puts parsed json data in the right places, and writes to prefs file. void OnWebResourceUnpacked(const DictionaryValue& parsed_json); + // Unpack the web resource as a set of tips. Expects json in the form of: + // { + // "lang": "en", + // "topic": { + // "topid_id": "24013", + // "topics": [ + // ], + // "answers": [ + // { + // "answer_id": "18625", + // "inproduct": "Text here will be shown as a tip", + // }, + // ... + // ] + // } + // } + // + void UnpackTips(const DictionaryValue& parsed_json); + + // Unpack the web resource as a custom logo signal. Expects json in the form + // of: + // { + // "topic": { + // "answers": [ + // { + // "logo_id": "1" + // }, + // ... + // ] + // } + // } + // + void UnpackLogoSignal(const DictionaryValue& parsed_json); + // We need to be able to load parsed resource data into preferences file, // and get proper install directory. PrefService* prefs_; - FilePath web_resource_dir_; - // Server from which we are currently pulling web resource data. std::string web_resource_server_; @@ -72,18 +105,11 @@ class WebResourceService // kCacheUpdateDelay time, and silently exit. bool in_fetch_; - // Maximum number of cached resources available. - static const int kMaxResourceCacheSize = 6; - // Delay on first fetch so we don't interfere with startup. static const int kStartResourceFetchDelay = 5000; - // Delay between calls to update the cache (48 hours). - static const int kCacheUpdateDelay = 48 * 60 * 60 * 1000; - - // Name of directory inside the profile where we will store resource-related - // data (for now, thumbnail images). - static const char* kResourceDirectoryName; + // Delay between calls to update the cache (12 hours). + static const int kCacheUpdateDelay = 12 * 60 * 60 * 1000; DISALLOW_COPY_AND_ASSIGN(WebResourceService); }; diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index 84a8cc85..78ca687 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc @@ -874,27 +874,30 @@ const char kNTPMostVisitedURLsBlacklist[] = "ntp.most_visited_blacklist"; // Page. const char kNTPMostVisitedPinnedURLs[] = "ntp.pinned_urls"; -// Data downloaded from resource pages (JSON, RSS) to be displayed in the -// recommendations portion of the NTP. -const char kNTPTipsCache[] = "ntp.tips_cache"; +// Data downloaded from resource pages (JSON, RSS) to be used to dynamically +// deliver data for the new tab page. +const char kNTPWebResourceCache[] = "ntp.web_resource_cache"; -// Last time of update of tips_cache. -const char kNTPTipsCacheUpdate[] = "ntp.tips_cache_update"; +// Last time of update of web_resource_cache. +const char kNTPWebResourceCacheUpdate[] = "ntp.web_resource_cache_update"; -// Last server used to fill tips_cache. -const char kNTPTipsServer[] = "ntp.tips_server"; +// Last server used to fill web_resource_cache. +const char kNTPWebResourceServer[] = "ntp.web_resource_server"; // Which sections should be visible on the new tab page // 1 - Show the most visited sites in a grid // 2 - Show the most visited sites as a list // 4 - Show the recent section -// 8 - Show tips -// 16 - show sync status +// 8 - (Show tips -- DEPRECATED) +// 16 - Show sync status const char kNTPShownSections[] = "ntp.shown_sections"; // This pref is used for migrating the prefs for the NTP const char kNTPPrefVersion[] = "ntp.pref_version"; +// Used if the NTP should show a custom logo rather than the standard one. +const char kNTPCustomLogo[] = "ntp.custom_logo"; + // A boolean specifying whether dev tools window should be opened docked. const char kDevToolsOpenDocked[] = "devtools.open_docked"; diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index 1bacef4..c9ea3b6 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h @@ -321,11 +321,12 @@ extern const char kExtensionSidebarWidth[]; extern const char kNTPMostVisitedURLsBlacklist[]; extern const char kNTPMostVisitedPinnedURLs[]; -extern const char kNTPTipsCache[]; -extern const char kNTPTipsCacheUpdate[]; -extern const char kNTPTipsServer[]; +extern const char kNTPWebResourceCache[]; +extern const char kNTPWebResourceCacheUpdate[]; +extern const char kNTPWebResourceServer[]; extern const char kNTPShownSections[]; extern const char kNTPPrefVersion[]; +extern const char kNTPCustomLogo[]; extern const char kDevToolsOpenDocked[]; extern const char kDevToolsSplitLocation[]; |