blob: 598450e3bcfd3766db240c810c81df352cdc5f24 [file] [log] [blame]
[email protected]779c3362010-01-30 01:09:331// Copyright (c) 2010 The Chromium Authors. All rights reserved.
[email protected]40bd6582009-12-04 23:49:512// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]b75b8292010-10-01 07:28:255#include <cmath>
6
[email protected]40bd6582009-12-04 23:49:517#include "chrome/browser/host_zoom_map.h"
8
[email protected]864b1362010-08-19 03:49:389#include "base/string_piece.h"
[email protected]40bd6582009-12-04 23:49:5110#include "base/utf_string_conversions.h"
[email protected]e36717272010-10-12 12:07:1311#include "chrome/browser/browser_thread.h"
[email protected]37858e52010-08-26 00:22:0212#include "chrome/browser/prefs/pref_service.h"
13#include "chrome/browser/prefs/scoped_pref_update.h"
[email protected]8ecad5e2010-12-02 21:18:3314#include "chrome/browser/profiles/profile.h"
[email protected]b75b8292010-10-01 07:28:2515#include "chrome/browser/renderer_host/render_process_host.h"
16#include "chrome/browser/renderer_host/render_view_host.h"
[email protected]3ef4bc632010-04-09 04:25:3117#include "chrome/common/notification_details.h"
[email protected]4db6ae42010-06-09 15:58:4718#include "chrome/common/notification_service.h"
[email protected]3ef4bc632010-04-09 04:25:3119#include "chrome/common/notification_source.h"
20#include "chrome/common/notification_type.h"
[email protected]40bd6582009-12-04 23:49:5121#include "chrome/common/pref_names.h"
[email protected]9d797f32010-04-23 07:17:5422#include "googleurl/src/gurl.h"
23#include "net/base/net_util.h"
[email protected]8bd0fe62011-01-17 06:44:3724#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
[email protected]b75b8292010-10-01 07:28:2525
26using WebKit::WebView;
[email protected]40bd6582009-12-04 23:49:5127
[email protected]3ef4bc632010-04-09 04:25:3128HostZoomMap::HostZoomMap(Profile* profile)
29 : profile_(profile),
30 updating_preferences_(false) {
31 Load();
[email protected]d0b8d092010-10-25 04:05:1732 default_zoom_level_ =
33 profile_->GetPrefs()->GetReal(prefs::kDefaultZoomLevel);
[email protected]3ef4bc632010-04-09 04:25:3134 registrar_.Add(this, NotificationType::PROFILE_DESTROYED,
35 Source<Profile>(profile));
[email protected]c18d4f482010-05-18 21:19:5036 // Don't observe pref changes (e.g. from sync) in Incognito; once we create
37 // the incognito window it should have no further connection to the main
38 // profile/prefs.
[email protected]2fb7dc982010-09-29 12:24:2839 if (!profile_->IsOffTheRecord()) {
40 pref_change_registrar_.Init(profile_->GetPrefs());
41 pref_change_registrar_.Add(prefs::kPerHostZoomLevels, this);
[email protected]d0b8d092010-10-25 04:05:1742 pref_change_registrar_.Add(prefs::kDefaultZoomLevel, this);
[email protected]2fb7dc982010-09-29 12:24:2843 }
[email protected]b75b8292010-10-01 07:28:2544
45 registrar_.Add(
46 this, NotificationType::RENDER_VIEW_HOST_WILL_CLOSE_RENDER_VIEW,
47 NotificationService::AllSources());
[email protected]3ef4bc632010-04-09 04:25:3148}
49
50void HostZoomMap::Load() {
51 if (!profile_)
52 return;
53
[email protected]20305ec2011-01-21 04:55:5254 base::AutoLock auto_lock(lock_);
[email protected]3ef4bc632010-04-09 04:25:3155 host_zoom_levels_.clear();
[email protected]40bd6582009-12-04 23:49:5156 const DictionaryValue* host_zoom_dictionary =
57 profile_->GetPrefs()->GetDictionary(prefs::kPerHostZoomLevels);
58 // Careful: The returned value could be NULL if the pref has never been set.
59 if (host_zoom_dictionary != NULL) {
60 for (DictionaryValue::key_iterator i(host_zoom_dictionary->begin_keys());
61 i != host_zoom_dictionary->end_keys(); ++i) {
[email protected]e7b418b2010-07-30 19:47:4762 const std::string& host(*i);
[email protected]b75b8292010-10-01 07:28:2563 double zoom_level = 0;
64
65 bool success = host_zoom_dictionary->GetRealWithoutPathExpansion(
[email protected]e7b418b2010-07-30 19:47:4766 host, &zoom_level);
[email protected]b75b8292010-10-01 07:28:2567 if (!success) {
68 // The data used to be stored as ints, so try that.
69 int int_zoom_level;
70 success = host_zoom_dictionary->GetIntegerWithoutPathExpansion(
71 host, &int_zoom_level);
72 if (success) {
73 zoom_level = static_cast<double>(int_zoom_level);
74 // Since the values were once stored as non-clamped, clamp now.
[email protected]b75b8292010-10-01 07:28:2575 double zoom_factor = WebView::zoomLevelToZoomFactor(zoom_level);
76 if (zoom_factor < WebView::minTextSizeMultiplier) {
77 zoom_level =
78 WebView::zoomFactorToZoomLevel(WebView::minTextSizeMultiplier);
79 } else if (zoom_factor > WebView::maxTextSizeMultiplier) {
80 zoom_level =
81 WebView::zoomFactorToZoomLevel(WebView::maxTextSizeMultiplier);
82 }
[email protected]b75b8292010-10-01 07:28:2583 }
84 }
[email protected]40bd6582009-12-04 23:49:5185 DCHECK(success);
[email protected]e7b418b2010-07-30 19:47:4786 host_zoom_levels_[host] = zoom_level;
[email protected]40bd6582009-12-04 23:49:5187 }
88 }
89}
90
91// static
92void HostZoomMap::RegisterUserPrefs(PrefService* prefs) {
93 prefs->RegisterDictionaryPref(prefs::kPerHostZoomLevels);
94}
95
[email protected]b75b8292010-10-01 07:28:2596double HostZoomMap::GetZoomLevel(const GURL& url) const {
[email protected]9d797f32010-04-23 07:17:5497 std::string host(net::GetHostOrSpecFromURL(url));
[email protected]20305ec2011-01-21 04:55:5298 base::AutoLock auto_lock(lock_);
[email protected]40bd6582009-12-04 23:49:5199 HostZoomLevels::const_iterator i(host_zoom_levels_.find(host));
[email protected]d0b8d092010-10-25 04:05:17100 return (i == host_zoom_levels_.end()) ? default_zoom_level_ : i->second;
[email protected]40bd6582009-12-04 23:49:51101}
102
[email protected]b75b8292010-10-01 07:28:25103void HostZoomMap::SetZoomLevel(const GURL& url, double level) {
[email protected]f8b3ef82010-10-11 02:45:52104 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
[email protected]3ef4bc632010-04-09 04:25:31105 if (!profile_)
106 return;
107
[email protected]9d797f32010-04-23 07:17:54108 std::string host(net::GetHostOrSpecFromURL(url));
[email protected]40bd6582009-12-04 23:49:51109
110 {
[email protected]20305ec2011-01-21 04:55:52111 base::AutoLock auto_lock(lock_);
[email protected]d0b8d092010-10-25 04:05:17112 if (level == default_zoom_level_)
[email protected]40bd6582009-12-04 23:49:51113 host_zoom_levels_.erase(host);
114 else
115 host_zoom_levels_[host] = level;
116 }
117
[email protected]4db6ae42010-06-09 15:58:47118 NotificationService::current()->Notify(NotificationType::ZOOM_LEVEL_CHANGED,
119 Source<Profile>(profile_),
[email protected]b75b8292010-10-01 07:28:25120 NotificationService::NoDetails());
[email protected]4db6ae42010-06-09 15:58:47121
[email protected]c18d4f482010-05-18 21:19:50122 // If we're in incognito mode, don't persist changes to the prefs. We'll keep
123 // them in memory only so they will be forgotten on exiting incognito.
124 if (profile_->IsOffTheRecord())
125 return;
126
[email protected]3ef4bc632010-04-09 04:25:31127 updating_preferences_ = true;
128 {
129 ScopedPrefUpdate update(profile_->GetPrefs(), prefs::kPerHostZoomLevels);
130 DictionaryValue* host_zoom_dictionary =
131 profile_->GetPrefs()->GetMutableDictionary(prefs::kPerHostZoomLevels);
[email protected]d0b8d092010-10-25 04:05:17132 if (level == default_zoom_level_) {
[email protected]57ecc4b2010-08-11 03:02:51133 host_zoom_dictionary->RemoveWithoutPathExpansion(host, NULL);
[email protected]3ef4bc632010-04-09 04:25:31134 } else {
135 host_zoom_dictionary->SetWithoutPathExpansion(
[email protected]b75b8292010-10-01 07:28:25136 host, Value::CreateRealValue(level));
[email protected]3ef4bc632010-04-09 04:25:31137 }
[email protected]40bd6582009-12-04 23:49:51138 }
[email protected]3ef4bc632010-04-09 04:25:31139 updating_preferences_ = false;
[email protected]40bd6582009-12-04 23:49:51140}
141
[email protected]b75b8292010-10-01 07:28:25142double HostZoomMap::GetTemporaryZoomLevel(int render_process_id,
143 int render_view_id) const {
[email protected]20305ec2011-01-21 04:55:52144 base::AutoLock auto_lock(lock_);
[email protected]b75b8292010-10-01 07:28:25145 for (size_t i = 0; i < temporary_zoom_levels_.size(); ++i) {
146 if (temporary_zoom_levels_[i].render_process_id == render_process_id &&
147 temporary_zoom_levels_[i].render_view_id == render_view_id) {
148 return temporary_zoom_levels_[i].zoom_level;
149 }
150 }
151 return 0;
152}
153
154void HostZoomMap::SetTemporaryZoomLevel(int render_process_id,
155 int render_view_id,
156 double level) {
[email protected]f8b3ef82010-10-11 02:45:52157 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
[email protected]b75b8292010-10-01 07:28:25158 if (!profile_)
159 return;
160
161 {
[email protected]20305ec2011-01-21 04:55:52162 base::AutoLock auto_lock(lock_);
[email protected]b75b8292010-10-01 07:28:25163 size_t i;
164 for (i = 0; i < temporary_zoom_levels_.size(); ++i) {
165 if (temporary_zoom_levels_[i].render_process_id == render_process_id &&
166 temporary_zoom_levels_[i].render_view_id == render_view_id) {
167 if (level) {
168 temporary_zoom_levels_[i].zoom_level = level;
169 } else {
170 temporary_zoom_levels_.erase(temporary_zoom_levels_.begin() + i);
171 }
172 break;
173 }
174 }
175
176 if (level && i == temporary_zoom_levels_.size()) {
177 TemporaryZoomLevel temp;
178 temp.render_process_id = render_process_id;
179 temp.render_view_id = render_view_id;
180 temp.zoom_level = level;
181 temporary_zoom_levels_.push_back(temp);
182 }
183 }
184
185 NotificationService::current()->Notify(NotificationType::ZOOM_LEVEL_CHANGED,
186 Source<Profile>(profile_),
187 NotificationService::NoDetails());
188}
189
[email protected]779c3362010-01-30 01:09:33190void HostZoomMap::ResetToDefaults() {
[email protected]f8b3ef82010-10-11 02:45:52191 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
[email protected]3ef4bc632010-04-09 04:25:31192 if (!profile_)
193 return;
[email protected]779c3362010-01-30 01:09:33194
[email protected]629a5cd12010-01-30 02:42:39195 {
[email protected]20305ec2011-01-21 04:55:52196 base::AutoLock auto_lock(lock_);
[email protected]629a5cd12010-01-30 02:42:39197 host_zoom_levels_.clear();
198 }
199
[email protected]3ef4bc632010-04-09 04:25:31200 updating_preferences_ = true;
[email protected]779c3362010-01-30 01:09:33201 profile_->GetPrefs()->ClearPref(prefs::kPerHostZoomLevels);
[email protected]3ef4bc632010-04-09 04:25:31202 updating_preferences_ = false;
203}
204
205void HostZoomMap::Shutdown() {
206 if (!profile_)
207 return;
208
[email protected]b75b8292010-10-01 07:28:25209 registrar_.RemoveAll();
[email protected]c18d4f482010-05-18 21:19:50210 if (!profile_->IsOffTheRecord())
[email protected]2fb7dc982010-09-29 12:24:28211 pref_change_registrar_.RemoveAll();
[email protected]3ef4bc632010-04-09 04:25:31212 profile_ = NULL;
213}
214
215void HostZoomMap::Observe(
216 NotificationType type,
217 const NotificationSource& source,
218 const NotificationDetails& details) {
[email protected]f8b3ef82010-10-11 02:45:52219 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
[email protected]3ef4bc632010-04-09 04:25:31220
[email protected]b75b8292010-10-01 07:28:25221 switch (type.value) {
222 case NotificationType::PROFILE_DESTROYED:
223 // If the profile is going away, we need to stop using it.
224 Shutdown();
225 break;
226 case NotificationType::RENDER_VIEW_HOST_WILL_CLOSE_RENDER_VIEW: {
[email protected]20305ec2011-01-21 04:55:52227 base::AutoLock auto_lock(lock_);
[email protected]b75b8292010-10-01 07:28:25228 int render_view_id = Source<RenderViewHost>(source)->routing_id();
229 int render_process_id = Source<RenderViewHost>(source)->process()->id();
[email protected]3ef4bc632010-04-09 04:25:31230
[email protected]b75b8292010-10-01 07:28:25231 for (size_t i = 0; i < temporary_zoom_levels_.size(); ++i) {
232 if (temporary_zoom_levels_[i].render_process_id == render_process_id &&
233 temporary_zoom_levels_[i].render_view_id == render_view_id) {
234 temporary_zoom_levels_.erase(temporary_zoom_levels_.begin() + i);
235 break;
236 }
237 }
238 break;
[email protected]3ef4bc632010-04-09 04:25:31239 }
[email protected]b75b8292010-10-01 07:28:25240 case NotificationType::PREF_CHANGED: {
241 // If we are updating our own preference, don't reload.
242 if (!updating_preferences_) {
243 std::string* name = Details<std::string>(details).ptr();
244 if (prefs::kPerHostZoomLevels == *name)
245 Load();
[email protected]d0b8d092010-10-25 04:05:17246 else if (prefs::kDefaultZoomLevel == *name) {
247 default_zoom_level_ =
248 profile_->GetPrefs()->GetReal(prefs::kDefaultZoomLevel);
249 }
[email protected]b75b8292010-10-01 07:28:25250 }
[email protected]2de28d92010-10-01 08:28:03251 break;
[email protected]b75b8292010-10-01 07:28:25252 }
253 default:
254 NOTREACHED() << "Unexpected preference observed.";
[email protected]3ef4bc632010-04-09 04:25:31255 }
[email protected]779c3362010-01-30 01:09:33256}
257
[email protected]40bd6582009-12-04 23:49:51258HostZoomMap::~HostZoomMap() {
[email protected]3ef4bc632010-04-09 04:25:31259 Shutdown();
[email protected]40bd6582009-12-04 23:49:51260}