1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/host_zoom_map_impl.h"
9 #include "base/strings/string_piece.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "base/values.h"
12 #include "content/browser/renderer_host/render_process_host_impl.h"
13 #include "content/browser/renderer_host/render_view_host_impl.h"
14 #include "content/common/view_messages.h"
15 #include "content/public/browser/browser_context.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "content/public/browser/notification_service.h"
18 #include "content/public/browser/notification_types.h"
19 #include "content/public/browser/resource_context.h"
20 #include "content/public/common/page_zoom.h"
21 #include "net/base/net_util.h"
23 static const char* kHostZoomMapKeyName
= "content_host_zoom_map";
27 HostZoomMap
* HostZoomMap::GetForBrowserContext(BrowserContext
* context
) {
28 HostZoomMapImpl
* rv
= static_cast<HostZoomMapImpl
*>(
29 context
->GetUserData(kHostZoomMapKeyName
));
31 rv
= new HostZoomMapImpl();
32 context
->SetUserData(kHostZoomMapKeyName
, rv
);
37 HostZoomMapImpl::HostZoomMapImpl()
38 : default_zoom_level_(0.0) {
40 this, NOTIFICATION_RENDER_VIEW_HOST_WILL_CLOSE_RENDER_VIEW
,
41 NotificationService::AllSources());
44 void HostZoomMapImpl::CopyFrom(HostZoomMap
* copy_interface
) {
45 // This can only be called on the UI thread to avoid deadlocks, otherwise
49 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
50 HostZoomMapImpl
* copy
= static_cast<HostZoomMapImpl
*>(copy_interface
);
51 base::AutoLock
auto_lock(lock_
);
52 base::AutoLock
copy_auto_lock(copy
->lock_
);
54 insert(copy
->host_zoom_levels_
.begin(), copy
->host_zoom_levels_
.end());
55 for (SchemeHostZoomLevels::const_iterator
i(copy
->
56 scheme_host_zoom_levels_
.begin());
57 i
!= copy
->scheme_host_zoom_levels_
.end(); ++i
) {
58 scheme_host_zoom_levels_
[i
->first
] = HostZoomLevels();
59 scheme_host_zoom_levels_
[i
->first
].
60 insert(i
->second
.begin(), i
->second
.end());
62 default_zoom_level_
= copy
->default_zoom_level_
;
65 double HostZoomMapImpl::GetZoomLevelForHost(const std::string
& host
) const {
66 base::AutoLock
auto_lock(lock_
);
67 HostZoomLevels::const_iterator
i(host_zoom_levels_
.find(host
));
68 return (i
== host_zoom_levels_
.end()) ? default_zoom_level_
: i
->second
;
71 double HostZoomMapImpl::GetZoomLevelForHostAndScheme(
72 const std::string
& scheme
,
73 const std::string
& host
) const {
75 base::AutoLock
auto_lock(lock_
);
76 SchemeHostZoomLevels::const_iterator
scheme_iterator(
77 scheme_host_zoom_levels_
.find(scheme
));
78 if (scheme_iterator
!= scheme_host_zoom_levels_
.end()) {
79 HostZoomLevels::const_iterator
i(scheme_iterator
->second
.find(host
));
80 if (i
!= scheme_iterator
->second
.end())
84 return GetZoomLevelForHost(host
);
87 HostZoomMap::ZoomLevelVector
HostZoomMapImpl::GetAllZoomLevels() const {
88 HostZoomMap::ZoomLevelVector result
;
90 base::AutoLock
auto_lock(lock_
);
91 result
.reserve(host_zoom_levels_
.size() + scheme_host_zoom_levels_
.size());
92 for (HostZoomLevels::const_iterator i
= host_zoom_levels_
.begin();
93 i
!= host_zoom_levels_
.end();
95 ZoomLevelChange change
= {HostZoomMap::ZOOM_CHANGED_FOR_HOST
,
97 std::string(), // scheme
98 i
->second
// zoom level
100 result
.push_back(change
);
102 for (SchemeHostZoomLevels::const_iterator i
=
103 scheme_host_zoom_levels_
.begin();
104 i
!= scheme_host_zoom_levels_
.end();
106 const std::string
& scheme
= i
->first
;
107 const HostZoomLevels
& host_zoom_levels
= i
->second
;
108 for (HostZoomLevels::const_iterator j
= host_zoom_levels
.begin();
109 j
!= host_zoom_levels
.end();
111 ZoomLevelChange change
= {HostZoomMap::ZOOM_CHANGED_FOR_SCHEME_AND_HOST
,
114 j
->second
// zoom level
116 result
.push_back(change
);
123 void HostZoomMapImpl::SetZoomLevelForHost(const std::string
& host
,
125 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
128 base::AutoLock
auto_lock(lock_
);
130 if (ZoomValuesEqual(level
, default_zoom_level_
))
131 host_zoom_levels_
.erase(host
);
133 host_zoom_levels_
[host
] = level
;
136 // Notify renderers from this browser context.
137 for (RenderProcessHost::iterator
i(RenderProcessHost::AllHostsIterator());
138 !i
.IsAtEnd(); i
.Advance()) {
139 RenderProcessHost
* render_process_host
= i
.GetCurrentValue();
140 if (HostZoomMap::GetForBrowserContext(
141 render_process_host
->GetBrowserContext()) == this) {
142 render_process_host
->Send(
143 new ViewMsg_SetZoomLevelForCurrentURL(std::string(), host
, level
));
146 HostZoomMap::ZoomLevelChange change
;
147 change
.mode
= HostZoomMap::ZOOM_CHANGED_FOR_HOST
;
149 change
.zoom_level
= level
;
151 zoom_level_changed_callbacks_
.Notify(change
);
154 void HostZoomMapImpl::SetZoomLevelForHostAndScheme(const std::string
& scheme
,
155 const std::string
& host
,
157 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
159 base::AutoLock
auto_lock(lock_
);
160 scheme_host_zoom_levels_
[scheme
][host
] = level
;
163 // Notify renderers from this browser context.
164 for (RenderProcessHost::iterator
i(RenderProcessHost::AllHostsIterator());
165 !i
.IsAtEnd(); i
.Advance()) {
166 RenderProcessHost
* render_process_host
= i
.GetCurrentValue();
167 if (HostZoomMap::GetForBrowserContext(
168 render_process_host
->GetBrowserContext()) == this) {
169 render_process_host
->Send(
170 new ViewMsg_SetZoomLevelForCurrentURL(scheme
, host
, level
));
174 HostZoomMap::ZoomLevelChange change
;
175 change
.mode
= HostZoomMap::ZOOM_CHANGED_FOR_SCHEME_AND_HOST
;
177 change
.scheme
= scheme
;
178 change
.zoom_level
= level
;
180 zoom_level_changed_callbacks_
.Notify(change
);
183 double HostZoomMapImpl::GetDefaultZoomLevel() const {
184 return default_zoom_level_
;
187 void HostZoomMapImpl::SetDefaultZoomLevel(double level
) {
188 default_zoom_level_
= level
;
191 scoped_ptr
<HostZoomMap::Subscription
>
192 HostZoomMapImpl::AddZoomLevelChangedCallback(
193 const ZoomLevelChangedCallback
& callback
) {
194 return zoom_level_changed_callbacks_
.Add(callback
);
197 double HostZoomMapImpl::GetTemporaryZoomLevel(int render_process_id
,
198 int render_view_id
) const {
199 base::AutoLock
auto_lock(lock_
);
200 for (size_t i
= 0; i
< temporary_zoom_levels_
.size(); ++i
) {
201 if (temporary_zoom_levels_
[i
].render_process_id
== render_process_id
&&
202 temporary_zoom_levels_
[i
].render_view_id
== render_view_id
) {
203 return temporary_zoom_levels_
[i
].zoom_level
;
209 void HostZoomMapImpl::SetTemporaryZoomLevel(int render_process_id
,
212 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
215 base::AutoLock
auto_lock(lock_
);
217 for (i
= 0; i
< temporary_zoom_levels_
.size(); ++i
) {
218 if (temporary_zoom_levels_
[i
].render_process_id
== render_process_id
&&
219 temporary_zoom_levels_
[i
].render_view_id
== render_view_id
) {
221 temporary_zoom_levels_
[i
].zoom_level
= level
;
223 temporary_zoom_levels_
.erase(temporary_zoom_levels_
.begin() + i
);
229 if (level
&& i
== temporary_zoom_levels_
.size()) {
230 TemporaryZoomLevel temp
;
231 temp
.render_process_id
= render_process_id
;
232 temp
.render_view_id
= render_view_id
;
233 temp
.zoom_level
= level
;
234 temporary_zoom_levels_
.push_back(temp
);
238 HostZoomMap::ZoomLevelChange change
;
239 change
.mode
= HostZoomMap::ZOOM_CHANGED_TEMPORARY_ZOOM
;
240 change
.zoom_level
= level
;
242 zoom_level_changed_callbacks_
.Notify(change
);
245 void HostZoomMapImpl::Observe(int type
,
246 const NotificationSource
& source
,
247 const NotificationDetails
& details
) {
249 case NOTIFICATION_RENDER_VIEW_HOST_WILL_CLOSE_RENDER_VIEW
: {
250 base::AutoLock
auto_lock(lock_
);
251 int render_view_id
= Source
<RenderViewHost
>(source
)->GetRoutingID();
252 int render_process_id
=
253 Source
<RenderViewHost
>(source
)->GetProcess()->GetID();
255 for (size_t i
= 0; i
< temporary_zoom_levels_
.size(); ++i
) {
256 if (temporary_zoom_levels_
[i
].render_process_id
== render_process_id
&&
257 temporary_zoom_levels_
[i
].render_view_id
== render_view_id
) {
258 temporary_zoom_levels_
.erase(temporary_zoom_levels_
.begin() + i
);
265 NOTREACHED() << "Unexpected preference observed.";
269 HostZoomMapImpl::~HostZoomMapImpl() {
272 } // namespace content