Index: chrome/browser/ui/prefs/prefs_tab_helper.cc |
diff --git a/chrome/browser/ui/prefs/prefs_tab_helper.cc b/chrome/browser/ui/prefs/prefs_tab_helper.cc |
index bc10b77214e365bef9fdae55a6805fa20a7a5165..160aa585e82bb92037611753aed0a000fd2ba5af 100644 |
--- a/chrome/browser/ui/prefs/prefs_tab_helper.cc |
+++ b/chrome/browser/ui/prefs/prefs_tab_helper.cc |
@@ -4,9 +4,12 @@ |
#include "chrome/browser/ui/prefs/prefs_tab_helper.h" |
+#include <set> |
#include <string> |
- |
+ |
+#include "base/memory/singleton.h" |
#include "base/prefs/overlay_user_pref_store.h" |
+#include "base/prefs/pref_change_registrar.h" |
#include "base/prefs/pref_service.h" |
#include "base/strings/string_number_conversions.h" |
#include "base/strings/string_util.h" |
@@ -14,6 +17,7 @@ |
#include "base/strings/utf_string_conversions.h" |
#include "chrome/browser/browser_process.h" |
#include "chrome/browser/chrome_notification_types.h" |
+#include "chrome/browser/profiles/incognito_helpers.h" |
#include "chrome/browser/profiles/profile.h" |
#include "chrome/browser/renderer_preferences_util.h" |
#include "chrome/browser/ui/zoom/chrome_zoom_level_prefs.h" |
@@ -21,6 +25,9 @@ |
#include "chrome/common/pref_names.h" |
#include "chrome/common/pref_names_util.h" |
#include "chrome/grit/locale_settings.h" |
+#include "components/keyed_service/content/browser_context_dependency_manager.h" |
+#include "components/keyed_service/content/browser_context_keyed_service_factory.h" |
+#include "components/keyed_service/core/keyed_service.h" |
#include "components/pref_registry/pref_registry_syncable.h" |
#include "content/public/browser/notification_details.h" |
#include "content/public/browser/notification_service.h" |
@@ -328,25 +335,16 @@ void RegisterLocalizedFontPref( |
} // namespace |
-PrefsTabHelper::PrefsTabHelper(WebContents* contents) |
- : web_contents_(contents), |
- weak_ptr_factory_(this) { |
- PrefService* prefs = GetProfile()->GetPrefs(); |
- pref_change_registrar_.Init(prefs); |
- if (prefs) { |
- // If the tab is in an incognito profile, we track changes in the default |
- // zoom level of the parent profile instead. |
- Profile* profile_to_track = GetProfile()->GetOriginalProfile(); |
- chrome::ChromeZoomLevelPrefs* zoom_level_prefs = |
- profile_to_track->GetZoomLevelPrefs(); |
+// Watching all these settings per tab is slow when a user has a lot of tabs and |
+// and they use session restore. So watch them once per profile. |
+// http://crbug.com/452693 |
+class PrefWatcher : public KeyedService { |
+ public: |
+ explicit PrefWatcher(Profile* profile) : profile_(profile) { |
+ pref_change_registrar_.Init(profile_->GetPrefs()); |
base::Closure renderer_callback = base::Bind( |
- &PrefsTabHelper::UpdateRendererPreferences, base::Unretained(this)); |
- // Tests should not need to create a ZoomLevelPrefs. |
- if (zoom_level_prefs) { |
- default_zoom_level_subscription_ = |
- zoom_level_prefs->RegisterDefaultZoomLevelCallback(renderer_callback); |
- } |
+ &PrefWatcher::UpdateRendererPreferences, base::Unretained(this)); |
pref_change_registrar_.Add(prefs::kAcceptLanguages, renderer_callback); |
pref_change_registrar_.Add(prefs::kEnableDoNotTrack, renderer_callback); |
pref_change_registrar_.Add(prefs::kEnableReferrers, renderer_callback); |
@@ -356,7 +354,7 @@ PrefsTabHelper::PrefsTabHelper(WebContents* contents) |
#endif |
PrefChangeRegistrar::NamedChangeCallback webkit_callback = base::Bind( |
- &PrefsTabHelper::OnWebPrefChanged, base::Unretained(this)); |
+ &PrefWatcher::OnWebPrefChanged, base::Unretained(this)); |
for (int i = 0; i < kPrefsToObserveLength; ++i) { |
const char* pref_name = kPrefsToObserve[i]; |
pref_change_registrar_.Add(pref_name, webkit_callback); |
@@ -385,17 +383,109 @@ PrefsTabHelper::PrefsTabHelper(WebContents* contents) |
webkit_callback); |
} |
+ static PrefWatcher* Get(Profile* profile); |
+ |
+ void RegisterHelper(PrefsTabHelper* helper) { |
+ helpers_.insert(helper); |
+ } |
+ |
+ void UnregisterHelper(PrefsTabHelper* helper) { |
+ helpers_.erase(helper); |
+ } |
+ |
+ private: |
+ // KeyedService overrides: |
+ void Shutdown() override { |
+ pref_change_registrar_.RemoveAll(); |
+ } |
+ |
+ void UpdateRendererPreferences() { |
+ for (const auto& helper : helpers_) |
+ helper->UpdateRendererPreferences(); |
+ } |
+ |
+ void OnWebPrefChanged(const std::string& pref_name) { |
+ for (const auto& helper : helpers_) |
+ helper->OnWebPrefChanged(pref_name); |
+ } |
+ |
+ Profile* profile_; |
+ PrefChangeRegistrar pref_change_registrar_; |
+ std::set<PrefsTabHelper*> helpers_; |
+}; |
+ |
+class PrefWatcherFactory : public BrowserContextKeyedServiceFactory { |
+ public: |
+ static PrefWatcher* GetForProfile(Profile* profile) { |
+ return static_cast<PrefWatcher*>( |
+ GetInstance()->GetServiceForBrowserContext(profile, true)); |
+ } |
+ |
+ static PrefWatcherFactory* GetInstance() { |
+ return Singleton<PrefWatcherFactory>::get(); |
+ } |
+ |
+ private: |
+ friend struct DefaultSingletonTraits<PrefWatcherFactory>; |
+ |
+ PrefWatcherFactory() : BrowserContextKeyedServiceFactory( |
+ "PrefWatcher", |
+ BrowserContextDependencyManager::GetInstance()) { |
+ } |
+ |
+ ~PrefWatcherFactory() override {} |
+ |
+ // BrowserContextKeyedServiceFactory: |
+ KeyedService* BuildServiceInstanceFor( |
+ content::BrowserContext* browser_context) const override { |
+ return new PrefWatcher(Profile::FromBrowserContext(browser_context)); |
+ } |
+ |
+ content::BrowserContext* GetBrowserContextToUse( |
+ content::BrowserContext* context) const override { |
+ return chrome::GetBrowserContextOwnInstanceInIncognito(context); |
+ } |
+}; |
+ |
+// static |
+PrefWatcher* PrefWatcher::Get(Profile* profile) { |
+ return PrefWatcherFactory::GetForProfile(profile); |
+} |
+ |
+PrefsTabHelper::PrefsTabHelper(WebContents* contents) |
+ : web_contents_(contents), |
+ profile_(Profile::FromBrowserContext(web_contents_->GetBrowserContext())), |
+ weak_ptr_factory_(this) { |
+ PrefService* prefs = profile_->GetPrefs(); |
+ if (prefs) { |
+ // If the tab is in an incognito profile, we track changes in the default |
+ // zoom level of the parent profile instead. |
+ Profile* profile_to_track = profile_->GetOriginalProfile(); |
+ chrome::ChromeZoomLevelPrefs* zoom_level_prefs = |
+ profile_to_track->GetZoomLevelPrefs(); |
+ |
+ base::Closure renderer_callback = base::Bind( |
+ &PrefsTabHelper::UpdateRendererPreferences, base::Unretained(this)); |
+ // Tests should not need to create a ZoomLevelPrefs. |
+ if (zoom_level_prefs) { |
+ default_zoom_level_subscription_ = |
+ zoom_level_prefs->RegisterDefaultZoomLevelCallback(renderer_callback); |
+ } |
+ |
+ PrefWatcher::Get(profile_)->RegisterHelper(this); |
+ } |
+ |
content::RendererPreferences* render_prefs = |
web_contents_->GetMutableRendererPrefs(); |
renderer_preferences_util::UpdateFromSystemSettings(render_prefs, |
- GetProfile(), |
+ profile_, |
web_contents_); |
#if defined(OS_POSIX) && !defined(OS_MACOSX) && defined(ENABLE_THEMES) |
registrar_.Add(this, |
chrome::NOTIFICATION_BROWSER_THEME_CHANGED, |
content::Source<ThemeService>( |
- ThemeServiceFactory::GetForProfile(GetProfile()))); |
+ ThemeServiceFactory::GetForProfile(profile_))); |
#endif |
#if defined(USE_AURA) |
registrar_.Add(this, |
@@ -405,6 +495,7 @@ PrefsTabHelper::PrefsTabHelper(WebContents* contents) |
} |
PrefsTabHelper::~PrefsTabHelper() { |
+ PrefWatcher::Get(profile_)->UnregisterHelper(this); |
} |
// static |
@@ -575,6 +666,11 @@ void PrefsTabHelper::RegisterProfilePrefs( |
user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); |
} |
+// static |
+void PrefsTabHelper::GetServiceInstance() { |
+ PrefWatcherFactory::GetInstance(); |
+} |
+ |
void PrefsTabHelper::Observe(int type, |
const content::NotificationSource& source, |
const content::NotificationDetails& details) { |
@@ -604,14 +700,9 @@ void PrefsTabHelper::UpdateRendererPreferences() { |
content::RendererPreferences* prefs = |
web_contents_->GetMutableRendererPrefs(); |
renderer_preferences_util::UpdateFromSystemSettings( |
- prefs, GetProfile(), web_contents_); |
+ prefs, profile_, web_contents_); |
web_contents_->GetRenderViewHost()->SyncRendererPrefs(); |
} |
- |
-Profile* PrefsTabHelper::GetProfile() { |
- return Profile::FromBrowserContext(web_contents_->GetBrowserContext()); |
-} |
- |
void PrefsTabHelper::OnFontFamilyPrefChanged(const std::string& pref_name) { |
// When a font family pref's value goes from non-empty to the empty string, we |
// must add it to the usual WebPreferences struct passed to the renderer. |
@@ -630,7 +721,7 @@ void PrefsTabHelper::OnFontFamilyPrefChanged(const std::string& pref_name) { |
if (pref_names_util::ParseFontNamePrefPath(pref_name, |
&generic_family, |
&script)) { |
- PrefService* prefs = GetProfile()->GetPrefs(); |
+ PrefService* prefs = profile_->GetPrefs(); |
std::string pref_value = prefs->GetString(pref_name); |
if (pref_value.empty()) { |
WebPreferences web_prefs = |