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.
7 #include "content/browser/host_zoom_map_impl.h"
9 #include "base/string_piece.h"
10 #include "base/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 "googleurl/src/gurl.h"
22 #include "net/base/net_util.h"
23 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
25 using WebKit::WebView
;
26 using content::BrowserThread
;
27 using content::RenderProcessHost
;
28 using content::RenderViewHost
;
30 static const char* kHostZoomMapKeyName
= "content_host_zoom_map";
34 HostZoomMap
* HostZoomMap::GetForBrowserContext(BrowserContext
* context
) {
35 HostZoomMapImpl
* rv
= static_cast<HostZoomMapImpl
*>(
36 context
->GetUserData(kHostZoomMapKeyName
));
38 rv
= new HostZoomMapImpl();
39 context
->SetUserData(kHostZoomMapKeyName
, rv
);
44 } // namespace content
46 HostZoomMapImpl::HostZoomMapImpl()
47 : default_zoom_level_(0.0) {
49 this, content::NOTIFICATION_RENDER_VIEW_HOST_WILL_CLOSE_RENDER_VIEW
,
50 content::NotificationService::AllSources());
53 void HostZoomMapImpl::CopyFrom(HostZoomMap
* copy_interface
) {
54 // This can only be called on the UI thread to avoid deadlocks, otherwise
58 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
59 HostZoomMapImpl
* copy
= static_cast<HostZoomMapImpl
*>(copy_interface
);
60 base::AutoLock
auto_lock(lock_
);
61 base::AutoLock
copy_auto_lock(copy
->lock_
);
62 for (HostZoomLevels::const_iterator
i(copy
->host_zoom_levels_
.begin());
63 i
!= copy
->host_zoom_levels_
.end(); ++i
) {
64 host_zoom_levels_
[i
->first
] = i
->second
;
68 double HostZoomMapImpl::GetZoomLevel(const std::string
& host
) const {
69 base::AutoLock
auto_lock(lock_
);
70 HostZoomLevels::const_iterator
i(host_zoom_levels_
.find(host
));
71 return (i
== host_zoom_levels_
.end()) ? default_zoom_level_
: i
->second
;
74 void HostZoomMapImpl::SetZoomLevel(const std::string
& host
, double level
) {
75 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
78 base::AutoLock
auto_lock(lock_
);
80 if (content::ZoomValuesEqual(level
, default_zoom_level_
))
81 host_zoom_levels_
.erase(host
);
83 host_zoom_levels_
[host
] = level
;
86 // Notify renderers from this browser context.
87 for (RenderProcessHost::iterator
i(RenderProcessHost::AllHostsIterator());
88 !i
.IsAtEnd(); i
.Advance()) {
89 RenderProcessHost
* render_process_host
= i
.GetCurrentValue();
90 if (HostZoomMap::GetForBrowserContext(
91 render_process_host
->GetBrowserContext()) == this) {
92 render_process_host
->Send(
93 new ViewMsg_SetZoomLevelForCurrentURL(host
, level
));
97 content::NotificationService::current()->Notify(
98 content::NOTIFICATION_ZOOM_LEVEL_CHANGED
,
99 content::Source
<HostZoomMap
>(this),
100 content::Details
<const std::string
>(&host
));
103 double HostZoomMapImpl::GetDefaultZoomLevel() const {
104 return default_zoom_level_
;
107 void HostZoomMapImpl::SetDefaultZoomLevel(double level
) {
108 default_zoom_level_
= level
;
111 double HostZoomMapImpl::GetTemporaryZoomLevel(int render_process_id
,
112 int render_view_id
) const {
113 base::AutoLock
auto_lock(lock_
);
114 for (size_t i
= 0; i
< temporary_zoom_levels_
.size(); ++i
) {
115 if (temporary_zoom_levels_
[i
].render_process_id
== render_process_id
&&
116 temporary_zoom_levels_
[i
].render_view_id
== render_view_id
) {
117 return temporary_zoom_levels_
[i
].zoom_level
;
123 void HostZoomMapImpl::SetTemporaryZoomLevel(int render_process_id
,
126 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
129 base::AutoLock
auto_lock(lock_
);
131 for (i
= 0; i
< temporary_zoom_levels_
.size(); ++i
) {
132 if (temporary_zoom_levels_
[i
].render_process_id
== render_process_id
&&
133 temporary_zoom_levels_
[i
].render_view_id
== render_view_id
) {
135 temporary_zoom_levels_
[i
].zoom_level
= level
;
137 temporary_zoom_levels_
.erase(temporary_zoom_levels_
.begin() + i
);
143 if (level
&& i
== temporary_zoom_levels_
.size()) {
144 TemporaryZoomLevel temp
;
145 temp
.render_process_id
= render_process_id
;
146 temp
.render_view_id
= render_view_id
;
147 temp
.zoom_level
= level
;
148 temporary_zoom_levels_
.push_back(temp
);
153 content::NotificationService::current()->Notify(
154 content::NOTIFICATION_ZOOM_LEVEL_CHANGED
,
155 content::Source
<HostZoomMap
>(this),
156 content::Details
<const std::string
>(&host
));
159 void HostZoomMapImpl::Observe(
161 const content::NotificationSource
& source
,
162 const content::NotificationDetails
& details
) {
164 case content::NOTIFICATION_RENDER_VIEW_HOST_WILL_CLOSE_RENDER_VIEW
: {
165 base::AutoLock
auto_lock(lock_
);
167 content::Source
<RenderViewHost
>(source
)->GetRoutingID();
168 int render_process_id
=
169 content::Source
<RenderViewHost
>(source
)->GetProcess()->GetID();
171 for (size_t i
= 0; i
< temporary_zoom_levels_
.size(); ++i
) {
172 if (temporary_zoom_levels_
[i
].render_process_id
== render_process_id
&&
173 temporary_zoom_levels_
[i
].render_view_id
== render_view_id
) {
174 temporary_zoom_levels_
.erase(temporary_zoom_levels_
.begin() + i
);
181 NOTREACHED() << "Unexpected preference observed.";
185 HostZoomMapImpl::~HostZoomMapImpl() {