[email protected] | 9f76c1e | 2012-03-05 15:15:58 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
[email protected] | 40bd658 | 2009-12-04 23:49:51 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
[email protected] | 5c925087 | 2012-01-30 17:24:05 | [diff] [blame] | 5 | #include "content/browser/host_zoom_map_impl.h" |
[email protected] | 40bd658 | 2009-12-04 23:49:51 | [diff] [blame] | 6 | |
[email protected] | fce82322 | 2014-05-30 16:24:30 | [diff] [blame] | 7 | #include <algorithm> |
[email protected] | b9e7c479f | 2013-04-12 04:33:24 | [diff] [blame] | 8 | #include <cmath> |
Lukasz Anforowicz | c773bbd | 2017-10-02 19:25:29 | [diff] [blame^] | 9 | #include <memory> |
| 10 | #include <utility> |
[email protected] | b9e7c479f | 2013-04-12 04:33:24 | [diff] [blame] | 11 | |
| 12 | #include "base/strings/string_piece.h" |
[email protected] | 74ebfb1 | 2013-06-07 20:48:00 | [diff] [blame] | 13 | #include "base/strings/utf_string_conversions.h" |
Christian Dullweber | cc736c1 | 2017-09-04 09:27:50 | [diff] [blame] | 14 | #include "base/time/default_clock.h" |
[email protected] | d407cc0 | 2011-09-13 16:01:46 | [diff] [blame] | 15 | #include "base/values.h" |
[email protected] | fce82322 | 2014-05-30 16:24:30 | [diff] [blame] | 16 | #include "content/browser/frame_host/navigation_entry_impl.h" |
[email protected] | f3b1a08 | 2011-11-18 00:34:30 | [diff] [blame] | 17 | #include "content/browser/renderer_host/render_process_host_impl.h" |
[email protected] | b3c41c0b | 2012-03-06 15:48:32 | [diff] [blame] | 18 | #include "content/browser/renderer_host/render_view_host_impl.h" |
[email protected] | fce82322 | 2014-05-30 16:24:30 | [diff] [blame] | 19 | #include "content/browser/web_contents/web_contents_impl.h" |
[email protected] | 4e2a25a | 2012-01-27 00:42:08 | [diff] [blame] | 20 | #include "content/common/view_messages.h" |
| 21 | #include "content/public/browser/browser_context.h" |
[email protected] | c38831a1 | 2011-10-28 12:44:49 | [diff] [blame] | 22 | #include "content/public/browser/browser_thread.h" |
Lukasz Anforowicz | c773bbd | 2017-10-02 19:25:29 | [diff] [blame^] | 23 | #include "content/public/browser/render_frame_host.h" |
[email protected] | 5fe3713a | 2012-02-22 08:31:56 | [diff] [blame] | 24 | #include "content/public/browser/resource_context.h" |
wjmaclean | caa7d6d | 2014-11-12 16:42:11 | [diff] [blame] | 25 | #include "content/public/browser/site_instance.h" |
| 26 | #include "content/public/browser/storage_partition.h" |
[email protected] | 0f08340 | 2011-11-22 02:59:01 | [diff] [blame] | 27 | #include "content/public/common/page_zoom.h" |
wjmaclean | de29ed5 | 2014-10-28 21:09:06 | [diff] [blame] | 28 | #include "content/public/common/url_constants.h" |
tfarina | 7a4a7fd | 2016-01-20 14:23:44 | [diff] [blame] | 29 | #include "net/base/url_util.h" |
[email protected] | 40bd658 | 2009-12-04 23:49:51 | [diff] [blame] | 30 | |
[email protected] | 5c925087 | 2012-01-30 17:24:05 | [diff] [blame] | 31 | namespace content { |
| 32 | |
[email protected] | d42bf47 | 2014-06-14 01:49:38 | [diff] [blame] | 33 | namespace { |
| 34 | |
| 35 | std::string GetHostFromProcessView(int render_process_id, int render_view_id) { |
mostynb | 4c27d04 | 2015-03-18 21:47:47 | [diff] [blame] | 36 | DCHECK_CURRENTLY_ON(BrowserThread::UI); |
[email protected] | d42bf47 | 2014-06-14 01:49:38 | [diff] [blame] | 37 | RenderViewHost* render_view_host = |
| 38 | RenderViewHost::FromID(render_process_id, render_view_id); |
| 39 | if (!render_view_host) |
| 40 | return std::string(); |
| 41 | |
| 42 | WebContents* web_contents = WebContents::FromRenderViewHost(render_view_host); |
| 43 | |
| 44 | NavigationEntry* entry = |
| 45 | web_contents->GetController().GetLastCommittedEntry(); |
| 46 | if (!entry) |
| 47 | return std::string(); |
| 48 | |
wjmaclean | de29ed5 | 2014-10-28 21:09:06 | [diff] [blame] | 49 | return net::GetHostOrSpecFromURL(HostZoomMap::GetURLFromEntry(entry)); |
[email protected] | d42bf47 | 2014-06-14 01:49:38 | [diff] [blame] | 50 | } |
| 51 | |
| 52 | } // namespace |
| 53 | |
wjmaclean | de29ed5 | 2014-10-28 21:09:06 | [diff] [blame] | 54 | GURL HostZoomMap::GetURLFromEntry(const NavigationEntry* entry) { |
| 55 | switch (entry->GetPageType()) { |
| 56 | case PAGE_TYPE_ERROR: |
| 57 | return GURL(kUnreachableWebDataURL); |
| 58 | // TODO(wjmaclean): In future, give interstitial pages special treatment as |
| 59 | // well. |
| 60 | default: |
| 61 | return entry->GetURL(); |
| 62 | } |
| 63 | } |
| 64 | |
wjmaclean | f9b6ec8 | 2014-08-27 14:33:24 | [diff] [blame] | 65 | HostZoomMap* HostZoomMap::GetDefaultForBrowserContext(BrowserContext* context) { |
wjmaclean | caa7d6d | 2014-11-12 16:42:11 | [diff] [blame] | 66 | StoragePartition* partition = |
| 67 | BrowserContext::GetDefaultStoragePartition(context); |
| 68 | DCHECK(partition); |
| 69 | return partition->GetHostZoomMap(); |
| 70 | } |
| 71 | |
| 72 | HostZoomMap* HostZoomMap::Get(SiteInstance* instance) { |
| 73 | StoragePartition* partition = BrowserContext::GetStoragePartition( |
| 74 | instance->GetBrowserContext(), instance); |
| 75 | DCHECK(partition); |
| 76 | return partition->GetHostZoomMap(); |
| 77 | } |
| 78 | |
| 79 | HostZoomMap* HostZoomMap::GetForWebContents(const WebContents* contents) { |
mcnee | 432e47d | 2015-11-09 19:37:46 | [diff] [blame] | 80 | // TODO(wjmaclean): Update this behaviour to work with OOPIF. |
| 81 | // See crbug.com/528407. |
wjmaclean | caa7d6d | 2014-11-12 16:42:11 | [diff] [blame] | 82 | StoragePartition* partition = |
| 83 | BrowserContext::GetStoragePartition(contents->GetBrowserContext(), |
| 84 | contents->GetSiteInstance()); |
| 85 | DCHECK(partition); |
| 86 | return partition->GetHostZoomMap(); |
[email protected] | 5c925087 | 2012-01-30 17:24:05 | [diff] [blame] | 87 | } |
| 88 | |
[email protected] | fce82322 | 2014-05-30 16:24:30 | [diff] [blame] | 89 | // Helper function for setting/getting zoom levels for WebContents without |
| 90 | // having to import HostZoomMapImpl everywhere. |
| 91 | double HostZoomMap::GetZoomLevel(const WebContents* web_contents) { |
wjmaclean | caa7d6d | 2014-11-12 16:42:11 | [diff] [blame] | 92 | HostZoomMapImpl* host_zoom_map = static_cast<HostZoomMapImpl*>( |
| 93 | HostZoomMap::GetForWebContents(web_contents)); |
[email protected] | fce82322 | 2014-05-30 16:24:30 | [diff] [blame] | 94 | return host_zoom_map->GetZoomLevelForWebContents( |
| 95 | *static_cast<const WebContentsImpl*>(web_contents)); |
| 96 | } |
| 97 | |
ccameron | b7c1d6c | 2015-03-09 17:08:24 | [diff] [blame] | 98 | bool HostZoomMap::PageScaleFactorIsOne(const WebContents* web_contents) { |
| 99 | HostZoomMapImpl* host_zoom_map = static_cast<HostZoomMapImpl*>( |
| 100 | HostZoomMap::GetForWebContents(web_contents)); |
| 101 | return host_zoom_map->PageScaleFactorIsOneForWebContents( |
| 102 | *static_cast<const WebContentsImpl*>(web_contents)); |
| 103 | } |
| 104 | |
[email protected] | fce82322 | 2014-05-30 16:24:30 | [diff] [blame] | 105 | void HostZoomMap::SetZoomLevel(const WebContents* web_contents, double level) { |
wjmaclean | caa7d6d | 2014-11-12 16:42:11 | [diff] [blame] | 106 | HostZoomMapImpl* host_zoom_map = static_cast<HostZoomMapImpl*>( |
| 107 | HostZoomMap::GetForWebContents(web_contents)); |
[email protected] | fce82322 | 2014-05-30 16:24:30 | [diff] [blame] | 108 | host_zoom_map->SetZoomLevelForWebContents( |
| 109 | *static_cast<const WebContentsImpl*>(web_contents), level); |
| 110 | } |
| 111 | |
wjmaclean | de29ed5 | 2014-10-28 21:09:06 | [diff] [blame] | 112 | void HostZoomMap::SendErrorPageZoomLevelRefresh( |
| 113 | const WebContents* web_contents) { |
| 114 | HostZoomMapImpl* host_zoom_map = |
| 115 | static_cast<HostZoomMapImpl*>(HostZoomMap::GetDefaultForBrowserContext( |
| 116 | web_contents->GetBrowserContext())); |
| 117 | host_zoom_map->SendErrorPageZoomLevelRefresh(); |
| 118 | } |
| 119 | |
[email protected] | 5c925087 | 2012-01-30 17:24:05 | [diff] [blame] | 120 | HostZoomMapImpl::HostZoomMapImpl() |
Christian Dullweber | cc736c1 | 2017-09-04 09:27:50 | [diff] [blame] | 121 | : default_zoom_level_(0.0), |
| 122 | store_last_modified_(false), |
| 123 | clock_(new base::DefaultClock) {} |
[email protected] | 40bd658 | 2009-12-04 23:49:51 | [diff] [blame] | 124 | |
[email protected] | 5c925087 | 2012-01-30 17:24:05 | [diff] [blame] | 125 | void HostZoomMapImpl::CopyFrom(HostZoomMap* copy_interface) { |
[email protected] | 4e2a25a | 2012-01-27 00:42:08 | [diff] [blame] | 126 | // This can only be called on the UI thread to avoid deadlocks, otherwise |
| 127 | // UI: a.CopyFrom(b); |
| 128 | // IO: b.CopyFrom(a); |
| 129 | // can deadlock. |
mostynb | 4c27d04 | 2015-03-18 21:47:47 | [diff] [blame] | 130 | DCHECK_CURRENTLY_ON(BrowserThread::UI); |
[email protected] | 5c925087 | 2012-01-30 17:24:05 | [diff] [blame] | 131 | HostZoomMapImpl* copy = static_cast<HostZoomMapImpl*>(copy_interface); |
[email protected] | 4e2a25a | 2012-01-27 00:42:08 | [diff] [blame] | 132 | base::AutoLock auto_lock(lock_); |
| 133 | base::AutoLock copy_auto_lock(copy->lock_); |
[email protected] | 367c5c1d | 2013-03-11 18:59:02 | [diff] [blame] | 134 | host_zoom_levels_. |
| 135 | insert(copy->host_zoom_levels_.begin(), copy->host_zoom_levels_.end()); |
| 136 | for (SchemeHostZoomLevels::const_iterator i(copy-> |
| 137 | scheme_host_zoom_levels_.begin()); |
| 138 | i != copy->scheme_host_zoom_levels_.end(); ++i) { |
| 139 | scheme_host_zoom_levels_[i->first] = HostZoomLevels(); |
| 140 | scheme_host_zoom_levels_[i->first]. |
| 141 | insert(i->second.begin(), i->second.end()); |
[email protected] | 4e2a25a | 2012-01-27 00:42:08 | [diff] [blame] | 142 | } |
[email protected] | 19d2669 | 2013-01-12 19:56:33 | [diff] [blame] | 143 | default_zoom_level_ = copy->default_zoom_level_; |
[email protected] | 4e2a25a | 2012-01-27 00:42:08 | [diff] [blame] | 144 | } |
| 145 | |
[email protected] | 367c5c1d | 2013-03-11 18:59:02 | [diff] [blame] | 146 | double HostZoomMapImpl::GetZoomLevelForHost(const std::string& host) const { |
[email protected] | 20305ec | 2011-01-21 04:55:52 | [diff] [blame] | 147 | base::AutoLock auto_lock(lock_); |
wjmaclean | c6249049 | 2015-02-13 22:02:07 | [diff] [blame] | 148 | return GetZoomLevelForHostInternal(host); |
| 149 | } |
| 150 | |
| 151 | double HostZoomMapImpl::GetZoomLevelForHostInternal( |
| 152 | const std::string& host) const { |
[email protected] | 40bd658 | 2009-12-04 23:49:51 | [diff] [blame] | 153 | HostZoomLevels::const_iterator i(host_zoom_levels_.find(host)); |
Christian Dullweber | cc736c1 | 2017-09-04 09:27:50 | [diff] [blame] | 154 | return (i == host_zoom_levels_.end()) ? default_zoom_level_ : i->second.level; |
[email protected] | 40bd658 | 2009-12-04 23:49:51 | [diff] [blame] | 155 | } |
| 156 | |
[email protected] | d42bf47 | 2014-06-14 01:49:38 | [diff] [blame] | 157 | bool HostZoomMapImpl::HasZoomLevel(const std::string& scheme, |
| 158 | const std::string& host) const { |
| 159 | base::AutoLock auto_lock(lock_); |
| 160 | |
| 161 | SchemeHostZoomLevels::const_iterator scheme_iterator( |
| 162 | scheme_host_zoom_levels_.find(scheme)); |
| 163 | |
| 164 | const HostZoomLevels& zoom_levels = |
| 165 | (scheme_iterator != scheme_host_zoom_levels_.end()) |
| 166 | ? scheme_iterator->second |
| 167 | : host_zoom_levels_; |
| 168 | |
| 169 | HostZoomLevels::const_iterator i(zoom_levels.find(host)); |
| 170 | return i != zoom_levels.end(); |
| 171 | } |
| 172 | |
wjmaclean | c6249049 | 2015-02-13 22:02:07 | [diff] [blame] | 173 | double HostZoomMapImpl::GetZoomLevelForHostAndSchemeInternal( |
| 174 | const std::string& scheme, |
| 175 | const std::string& host) const { |
| 176 | SchemeHostZoomLevels::const_iterator scheme_iterator( |
| 177 | scheme_host_zoom_levels_.find(scheme)); |
| 178 | if (scheme_iterator != scheme_host_zoom_levels_.end()) { |
| 179 | HostZoomLevels::const_iterator i(scheme_iterator->second.find(host)); |
| 180 | if (i != scheme_iterator->second.end()) |
Christian Dullweber | cc736c1 | 2017-09-04 09:27:50 | [diff] [blame] | 181 | return i->second.level; |
wjmaclean | c6249049 | 2015-02-13 22:02:07 | [diff] [blame] | 182 | } |
| 183 | |
| 184 | return GetZoomLevelForHostInternal(host); |
| 185 | } |
| 186 | |
[email protected] | 367c5c1d | 2013-03-11 18:59:02 | [diff] [blame] | 187 | double HostZoomMapImpl::GetZoomLevelForHostAndScheme( |
| 188 | const std::string& scheme, |
| 189 | const std::string& host) const { |
wjmaclean | c6249049 | 2015-02-13 22:02:07 | [diff] [blame] | 190 | base::AutoLock auto_lock(lock_); |
| 191 | return GetZoomLevelForHostAndSchemeInternal(scheme, host); |
[email protected] | 367c5c1d | 2013-03-11 18:59:02 | [diff] [blame] | 192 | } |
| 193 | |
[email protected] | 0f37405 | 2014-03-18 20:37:22 | [diff] [blame] | 194 | HostZoomMap::ZoomLevelVector HostZoomMapImpl::GetAllZoomLevels() const { |
| 195 | HostZoomMap::ZoomLevelVector result; |
| 196 | { |
| 197 | base::AutoLock auto_lock(lock_); |
| 198 | result.reserve(host_zoom_levels_.size() + scheme_host_zoom_levels_.size()); |
Christian Dullweber | cc736c1 | 2017-09-04 09:27:50 | [diff] [blame] | 199 | for (const auto& entry : host_zoom_levels_) { |
| 200 | ZoomLevelChange change = { |
| 201 | HostZoomMap::ZOOM_CHANGED_FOR_HOST, |
| 202 | entry.first, // host |
| 203 | std::string(), // scheme |
| 204 | entry.second.level, // zoom level |
| 205 | entry.second.last_modified // last modified |
[email protected] | 0f37405 | 2014-03-18 20:37:22 | [diff] [blame] | 206 | }; |
| 207 | result.push_back(change); |
| 208 | } |
Christian Dullweber | cc736c1 | 2017-09-04 09:27:50 | [diff] [blame] | 209 | for (const auto& scheme_entry : scheme_host_zoom_levels_) { |
| 210 | const std::string& scheme = scheme_entry.first; |
| 211 | const HostZoomLevels& host_zoom_levels = scheme_entry.second; |
| 212 | for (const auto& entry : host_zoom_levels) { |
| 213 | ZoomLevelChange change = { |
| 214 | HostZoomMap::ZOOM_CHANGED_FOR_SCHEME_AND_HOST, |
| 215 | entry.first, // host |
| 216 | scheme, // scheme |
| 217 | entry.second.level, // zoom level |
| 218 | entry.second.last_modified // last modified |
[email protected] | 0f37405 | 2014-03-18 20:37:22 | [diff] [blame] | 219 | }; |
| 220 | result.push_back(change); |
| 221 | } |
| 222 | } |
| 223 | } |
| 224 | return result; |
| 225 | } |
| 226 | |
[email protected] | 367c5c1d | 2013-03-11 18:59:02 | [diff] [blame] | 227 | void HostZoomMapImpl::SetZoomLevelForHost(const std::string& host, |
| 228 | double level) { |
Christian Dullweber | cc736c1 | 2017-09-04 09:27:50 | [diff] [blame] | 229 | base::Time last_modified = |
| 230 | store_last_modified_ ? clock_->Now() : base::Time(); |
| 231 | SetZoomLevelForHostInternal(host, level, last_modified); |
| 232 | } |
| 233 | |
| 234 | void HostZoomMapImpl::InitializeZoomLevelForHost(const std::string& host, |
| 235 | double level, |
| 236 | base::Time last_modified) { |
| 237 | SetZoomLevelForHostInternal(host, level, last_modified); |
| 238 | } |
| 239 | |
| 240 | void HostZoomMapImpl::SetZoomLevelForHostInternal(const std::string& host, |
| 241 | double level, |
| 242 | base::Time last_modified) { |
mostynb | 4c27d04 | 2015-03-18 21:47:47 | [diff] [blame] | 243 | DCHECK_CURRENTLY_ON(BrowserThread::UI); |
[email protected] | 3ef4bc63 | 2010-04-09 04:25:31 | [diff] [blame] | 244 | |
[email protected] | 40bd658 | 2009-12-04 23:49:51 | [diff] [blame] | 245 | { |
[email protected] | 20305ec | 2011-01-21 04:55:52 | [diff] [blame] | 246 | base::AutoLock auto_lock(lock_); |
[email protected] | 0f08340 | 2011-11-22 02:59:01 | [diff] [blame] | 247 | |
Christian Dullweber | cc736c1 | 2017-09-04 09:27:50 | [diff] [blame] | 248 | if (ZoomValuesEqual(level, default_zoom_level_)) { |
[email protected] | 40bd658 | 2009-12-04 23:49:51 | [diff] [blame] | 249 | host_zoom_levels_.erase(host); |
Christian Dullweber | cc736c1 | 2017-09-04 09:27:50 | [diff] [blame] | 250 | } else { |
| 251 | ZoomLevel& zoomLevel = host_zoom_levels_[host]; |
| 252 | zoomLevel.level = level; |
| 253 | zoomLevel.last_modified = last_modified; |
| 254 | } |
[email protected] | 40bd658 | 2009-12-04 23:49:51 | [diff] [blame] | 255 | } |
| 256 | |
[email protected] | d42bf47 | 2014-06-14 01:49:38 | [diff] [blame] | 257 | // TODO(wjmaclean) Should we use a GURL here? crbug.com/384486 |
| 258 | SendZoomLevelChange(std::string(), host, level); |
| 259 | |
[email protected] | 367c5c1d | 2013-03-11 18:59:02 | [diff] [blame] | 260 | HostZoomMap::ZoomLevelChange change; |
| 261 | change.mode = HostZoomMap::ZOOM_CHANGED_FOR_HOST; |
| 262 | change.host = host; |
| 263 | change.zoom_level = level; |
Christian Dullweber | cc736c1 | 2017-09-04 09:27:50 | [diff] [blame] | 264 | change.last_modified = last_modified; |
[email protected] | 367c5c1d | 2013-03-11 18:59:02 | [diff] [blame] | 265 | |
[email protected] | 11783281 | 2013-10-02 07:06:02 | [diff] [blame] | 266 | zoom_level_changed_callbacks_.Notify(change); |
[email protected] | 367c5c1d | 2013-03-11 18:59:02 | [diff] [blame] | 267 | } |
| 268 | |
| 269 | void HostZoomMapImpl::SetZoomLevelForHostAndScheme(const std::string& scheme, |
| 270 | const std::string& host, |
| 271 | double level) { |
mostynb | 4c27d04 | 2015-03-18 21:47:47 | [diff] [blame] | 272 | DCHECK_CURRENTLY_ON(BrowserThread::UI); |
[email protected] | 367c5c1d | 2013-03-11 18:59:02 | [diff] [blame] | 273 | { |
| 274 | base::AutoLock auto_lock(lock_); |
Christian Dullweber | cc736c1 | 2017-09-04 09:27:50 | [diff] [blame] | 275 | // No last_modified timestamp for scheme and host because they are |
| 276 | // not persistet and are used for special cases only. |
| 277 | scheme_host_zoom_levels_[scheme][host].level = level; |
[email protected] | 367c5c1d | 2013-03-11 18:59:02 | [diff] [blame] | 278 | } |
| 279 | |
[email protected] | d42bf47 | 2014-06-14 01:49:38 | [diff] [blame] | 280 | SendZoomLevelChange(scheme, host, level); |
[email protected] | 4e2a25a | 2012-01-27 00:42:08 | [diff] [blame] | 281 | |
[email protected] | 367c5c1d | 2013-03-11 18:59:02 | [diff] [blame] | 282 | HostZoomMap::ZoomLevelChange change; |
| 283 | change.mode = HostZoomMap::ZOOM_CHANGED_FOR_SCHEME_AND_HOST; |
| 284 | change.host = host; |
| 285 | change.scheme = scheme; |
| 286 | change.zoom_level = level; |
Christian Dullweber | cc736c1 | 2017-09-04 09:27:50 | [diff] [blame] | 287 | change.last_modified = base::Time(); |
[email protected] | 367c5c1d | 2013-03-11 18:59:02 | [diff] [blame] | 288 | |
[email protected] | 11783281 | 2013-10-02 07:06:02 | [diff] [blame] | 289 | zoom_level_changed_callbacks_.Notify(change); |
[email protected] | 40bd658 | 2009-12-04 23:49:51 | [diff] [blame] | 290 | } |
| 291 | |
[email protected] | 5c925087 | 2012-01-30 17:24:05 | [diff] [blame] | 292 | double HostZoomMapImpl::GetDefaultZoomLevel() const { |
mostynb | 4c27d04 | 2015-03-18 21:47:47 | [diff] [blame] | 293 | DCHECK_CURRENTLY_ON(BrowserThread::UI); |
[email protected] | 5c925087 | 2012-01-30 17:24:05 | [diff] [blame] | 294 | return default_zoom_level_; |
| 295 | } |
| 296 | |
| 297 | void HostZoomMapImpl::SetDefaultZoomLevel(double level) { |
mostynb | 4c27d04 | 2015-03-18 21:47:47 | [diff] [blame] | 298 | DCHECK_CURRENTLY_ON(BrowserThread::UI); |
wjmaclean | 6495190 | 2016-04-29 20:59:12 | [diff] [blame] | 299 | |
| 300 | if (ZoomValuesEqual(level, default_zoom_level_)) |
| 301 | return; |
| 302 | |
[email protected] | 5c925087 | 2012-01-30 17:24:05 | [diff] [blame] | 303 | default_zoom_level_ = level; |
wjmaclean | 6495190 | 2016-04-29 20:59:12 | [diff] [blame] | 304 | |
| 305 | // First, remove all entries that match the new default zoom level. |
| 306 | { |
| 307 | base::AutoLock auto_lock(lock_); |
| 308 | for (auto it = host_zoom_levels_.begin(); it != host_zoom_levels_.end(); ) { |
Christian Dullweber | cc736c1 | 2017-09-04 09:27:50 | [diff] [blame] | 309 | if (ZoomValuesEqual(it->second.level, default_zoom_level_)) |
wjmaclean | 6495190 | 2016-04-29 20:59:12 | [diff] [blame] | 310 | it = host_zoom_levels_.erase(it); |
| 311 | else |
| 312 | it++; |
| 313 | } |
| 314 | } |
| 315 | |
| 316 | // Second, update zoom levels for all pages that do not have an overriding |
| 317 | // entry. |
vmpstr | 10e0d5f | 2016-07-21 23:46:09 | [diff] [blame] | 318 | for (auto* web_contents : WebContentsImpl::GetAllWebContents()) { |
wjmaclean | 6495190 | 2016-04-29 20:59:12 | [diff] [blame] | 319 | // Only change zoom for WebContents tied to the StoragePartition this |
| 320 | // HostZoomMap serves. |
| 321 | if (GetForWebContents(web_contents) != this) |
| 322 | continue; |
| 323 | |
Lukasz Anforowicz | c773bbd | 2017-10-02 19:25:29 | [diff] [blame^] | 324 | int render_process_id = |
| 325 | web_contents->GetRenderViewHost()->GetProcess()->GetID(); |
wjmaclean | 6495190 | 2016-04-29 20:59:12 | [diff] [blame] | 326 | int render_view_id = web_contents->GetRenderViewHost()->GetRoutingID(); |
| 327 | |
| 328 | // Get the url from the navigation controller directly, as calling |
| 329 | // WebContentsImpl::GetLastCommittedURL() may give us a virtual url that |
| 330 | // is different than the one stored in the map. |
| 331 | GURL url; |
| 332 | std::string host; |
| 333 | std::string scheme; |
| 334 | |
| 335 | NavigationEntry* entry = |
| 336 | web_contents->GetController().GetLastCommittedEntry(); |
| 337 | // It is possible for a WebContent's zoom level to be queried before |
| 338 | // a navigation has occurred. |
| 339 | if (entry) { |
| 340 | url = GetURLFromEntry(entry); |
| 341 | scheme = url.scheme(); |
| 342 | host = net::GetHostOrSpecFromURL(url); |
| 343 | } |
| 344 | |
| 345 | bool uses_default_zoom = |
| 346 | !HasZoomLevel(scheme, host) && |
| 347 | !UsesTemporaryZoomLevel(render_process_id, render_view_id); |
| 348 | |
| 349 | if (uses_default_zoom) { |
| 350 | web_contents->UpdateZoom(level); |
| 351 | |
| 352 | HostZoomMap::ZoomLevelChange change; |
| 353 | change.mode = HostZoomMap::ZOOM_CHANGED_FOR_HOST; |
| 354 | change.host = host; |
| 355 | change.zoom_level = level; |
| 356 | |
| 357 | zoom_level_changed_callbacks_.Notify(change); |
| 358 | } |
| 359 | } |
[email protected] | 5c925087 | 2012-01-30 17:24:05 | [diff] [blame] | 360 | } |
| 361 | |
dcheng | 5971627 | 2016-04-09 05:19:08 | [diff] [blame] | 362 | std::unique_ptr<HostZoomMap::Subscription> |
[email protected] | 11783281 | 2013-10-02 07:06:02 | [diff] [blame] | 363 | HostZoomMapImpl::AddZoomLevelChangedCallback( |
[email protected] | 89c9aca | 2013-02-07 15:08:42 | [diff] [blame] | 364 | const ZoomLevelChangedCallback& callback) { |
[email protected] | 11783281 | 2013-10-02 07:06:02 | [diff] [blame] | 365 | return zoom_level_changed_callbacks_.Add(callback); |
[email protected] | 89c9aca | 2013-02-07 15:08:42 | [diff] [blame] | 366 | } |
| 367 | |
[email protected] | fce82322 | 2014-05-30 16:24:30 | [diff] [blame] | 368 | double HostZoomMapImpl::GetZoomLevelForWebContents( |
| 369 | const WebContentsImpl& web_contents_impl) const { |
Lukasz Anforowicz | c773bbd | 2017-10-02 19:25:29 | [diff] [blame^] | 370 | int render_process_id = |
| 371 | web_contents_impl.GetRenderViewHost()->GetProcess()->GetID(); |
[email protected] | fce82322 | 2014-05-30 16:24:30 | [diff] [blame] | 372 | int routing_id = web_contents_impl.GetRenderViewHost()->GetRoutingID(); |
| 373 | |
| 374 | if (UsesTemporaryZoomLevel(render_process_id, routing_id)) |
| 375 | return GetTemporaryZoomLevel(render_process_id, routing_id); |
| 376 | |
[email protected] | acda0ef3 | 2014-06-05 23:13:30 | [diff] [blame] | 377 | // Get the url from the navigation controller directly, as calling |
| 378 | // WebContentsImpl::GetLastCommittedURL() may give us a virtual url that |
| 379 | // is different than is stored in the map. |
[email protected] | fce82322 | 2014-05-30 16:24:30 | [diff] [blame] | 380 | GURL url; |
| 381 | NavigationEntry* entry = |
| 382 | web_contents_impl.GetController().GetLastCommittedEntry(); |
[email protected] | acda0ef3 | 2014-06-05 23:13:30 | [diff] [blame] | 383 | // It is possible for a WebContent's zoom level to be queried before |
| 384 | // a navigation has occurred. |
[email protected] | fce82322 | 2014-05-30 16:24:30 | [diff] [blame] | 385 | if (entry) |
wjmaclean | de29ed5 | 2014-10-28 21:09:06 | [diff] [blame] | 386 | url = GetURLFromEntry(entry); |
[email protected] | fce82322 | 2014-05-30 16:24:30 | [diff] [blame] | 387 | return GetZoomLevelForHostAndScheme(url.scheme(), |
| 388 | net::GetHostOrSpecFromURL(url)); |
| 389 | } |
| 390 | |
| 391 | void HostZoomMapImpl::SetZoomLevelForWebContents( |
| 392 | const WebContentsImpl& web_contents_impl, |
| 393 | double level) { |
Lukasz Anforowicz | c773bbd | 2017-10-02 19:25:29 | [diff] [blame^] | 394 | int render_process_id = |
| 395 | web_contents_impl.GetRenderViewHost()->GetProcess()->GetID(); |
[email protected] | fce82322 | 2014-05-30 16:24:30 | [diff] [blame] | 396 | int render_view_id = web_contents_impl.GetRenderViewHost()->GetRoutingID(); |
| 397 | if (UsesTemporaryZoomLevel(render_process_id, render_view_id)) { |
[email protected] | fce82322 | 2014-05-30 16:24:30 | [diff] [blame] | 398 | SetTemporaryZoomLevel(render_process_id, render_view_id, level); |
| 399 | } else { |
[email protected] | acda0ef3 | 2014-06-05 23:13:30 | [diff] [blame] | 400 | // Get the url from the navigation controller directly, as calling |
| 401 | // WebContentsImpl::GetLastCommittedURL() may give us a virtual url that |
| 402 | // is different than what the render view is using. If the two don't match, |
| 403 | // the attempt to set the zoom will fail. |
[email protected] | acda0ef3 | 2014-06-05 23:13:30 | [diff] [blame] | 404 | NavigationEntry* entry = |
| 405 | web_contents_impl.GetController().GetLastCommittedEntry(); |
[email protected] | f3b3e5e | 2014-06-10 15:47:41 | [diff] [blame] | 406 | // Tests may invoke this function with a null entry, but we don't |
| 407 | // want to save zoom levels in this case. |
| 408 | if (!entry) |
| 409 | return; |
| 410 | |
wjmaclean | de29ed5 | 2014-10-28 21:09:06 | [diff] [blame] | 411 | GURL url = GetURLFromEntry(entry); |
[email protected] | acda0ef3 | 2014-06-05 23:13:30 | [diff] [blame] | 412 | SetZoomLevelForHost(net::GetHostOrSpecFromURL(url), level); |
[email protected] | fce82322 | 2014-05-30 16:24:30 | [diff] [blame] | 413 | } |
| 414 | } |
| 415 | |
| 416 | void HostZoomMapImpl::SetZoomLevelForView(int render_process_id, |
| 417 | int render_view_id, |
| 418 | double level, |
| 419 | const std::string& host) { |
| 420 | if (UsesTemporaryZoomLevel(render_process_id, render_view_id)) |
| 421 | SetTemporaryZoomLevel(render_process_id, render_view_id, level); |
| 422 | else |
| 423 | SetZoomLevelForHost(host, level); |
| 424 | } |
| 425 | |
ccameron | b7c1d6c | 2015-03-09 17:08:24 | [diff] [blame] | 426 | void HostZoomMapImpl::SetPageScaleFactorIsOneForView(int render_process_id, |
| 427 | int render_view_id, |
| 428 | bool is_one) { |
| 429 | { |
| 430 | base::AutoLock auto_lock(lock_); |
| 431 | view_page_scale_factors_are_one_[RenderViewKey(render_process_id, |
| 432 | render_view_id)] = is_one; |
| 433 | } |
| 434 | HostZoomMap::ZoomLevelChange change; |
| 435 | change.mode = HostZoomMap::PAGE_SCALE_IS_ONE_CHANGED; |
| 436 | zoom_level_changed_callbacks_.Notify(change); |
| 437 | } |
| 438 | |
| 439 | bool HostZoomMapImpl::PageScaleFactorIsOneForWebContents( |
| 440 | const WebContentsImpl& web_contents_impl) const { |
Lukasz Anforowicz | c773bbd | 2017-10-02 19:25:29 | [diff] [blame^] | 441 | if (!web_contents_impl.GetRenderViewHost()->GetProcess()) |
ccameron | b7c1d6c | 2015-03-09 17:08:24 | [diff] [blame] | 442 | return true; |
| 443 | base::AutoLock auto_lock(lock_); |
Lukasz Anforowicz | c773bbd | 2017-10-02 19:25:29 | [diff] [blame^] | 444 | auto found = view_page_scale_factors_are_one_.find(RenderViewKey( |
| 445 | web_contents_impl.GetRenderViewHost()->GetProcess()->GetID(), |
| 446 | web_contents_impl.GetRenderViewHost()->GetRoutingID())); |
ccameron | b7c1d6c | 2015-03-09 17:08:24 | [diff] [blame] | 447 | if (found == view_page_scale_factors_are_one_.end()) |
| 448 | return true; |
| 449 | return found->second; |
| 450 | } |
| 451 | |
| 452 | void HostZoomMapImpl::ClearPageScaleFactorIsOneForView(int render_process_id, |
| 453 | int render_view_id) { |
| 454 | base::AutoLock auto_lock(lock_); |
| 455 | view_page_scale_factors_are_one_.erase( |
| 456 | RenderViewKey(render_process_id, render_view_id)); |
| 457 | } |
| 458 | |
[email protected] | fce82322 | 2014-05-30 16:24:30 | [diff] [blame] | 459 | bool HostZoomMapImpl::UsesTemporaryZoomLevel(int render_process_id, |
| 460 | int render_view_id) const { |
[email protected] | d42bf47 | 2014-06-14 01:49:38 | [diff] [blame] | 461 | RenderViewKey key(render_process_id, render_view_id); |
[email protected] | fce82322 | 2014-05-30 16:24:30 | [diff] [blame] | 462 | |
| 463 | base::AutoLock auto_lock(lock_); |
skyostil | 66bd6791 | 2016-08-12 12:33:11 | [diff] [blame] | 464 | return base::ContainsKey(temporary_zoom_levels_, key); |
[email protected] | fce82322 | 2014-05-30 16:24:30 | [diff] [blame] | 465 | } |
| 466 | |
[email protected] | 5c925087 | 2012-01-30 17:24:05 | [diff] [blame] | 467 | double HostZoomMapImpl::GetTemporaryZoomLevel(int render_process_id, |
| 468 | int render_view_id) const { |
[email protected] | 20305ec | 2011-01-21 04:55:52 | [diff] [blame] | 469 | base::AutoLock auto_lock(lock_); |
[email protected] | d42bf47 | 2014-06-14 01:49:38 | [diff] [blame] | 470 | RenderViewKey key(render_process_id, render_view_id); |
skyostil | 66bd6791 | 2016-08-12 12:33:11 | [diff] [blame] | 471 | if (!base::ContainsKey(temporary_zoom_levels_, key)) |
[email protected] | d42bf47 | 2014-06-14 01:49:38 | [diff] [blame] | 472 | return 0; |
[email protected] | fce82322 | 2014-05-30 16:24:30 | [diff] [blame] | 473 | |
[email protected] | d42bf47 | 2014-06-14 01:49:38 | [diff] [blame] | 474 | return temporary_zoom_levels_.find(key)->second; |
[email protected] | b75b829 | 2010-10-01 07:28:25 | [diff] [blame] | 475 | } |
| 476 | |
[email protected] | 5c925087 | 2012-01-30 17:24:05 | [diff] [blame] | 477 | void HostZoomMapImpl::SetTemporaryZoomLevel(int render_process_id, |
| 478 | int render_view_id, |
| 479 | double level) { |
mostynb | 4c27d04 | 2015-03-18 21:47:47 | [diff] [blame] | 480 | DCHECK_CURRENTLY_ON(BrowserThread::UI); |
[email protected] | b75b829 | 2010-10-01 07:28:25 | [diff] [blame] | 481 | |
| 482 | { |
[email protected] | d42bf47 | 2014-06-14 01:49:38 | [diff] [blame] | 483 | RenderViewKey key(render_process_id, render_view_id); |
[email protected] | 20305ec | 2011-01-21 04:55:52 | [diff] [blame] | 484 | base::AutoLock auto_lock(lock_); |
[email protected] | d42bf47 | 2014-06-14 01:49:38 | [diff] [blame] | 485 | temporary_zoom_levels_[key] = level; |
[email protected] | b75b829 | 2010-10-01 07:28:25 | [diff] [blame] | 486 | } |
| 487 | |
wjmaclean | 6495190 | 2016-04-29 20:59:12 | [diff] [blame] | 488 | WebContentsImpl* web_contents = |
| 489 | static_cast<WebContentsImpl*>(WebContents::FromRenderViewHost( |
| 490 | RenderViewHost::FromID(render_process_id, render_view_id))); |
| 491 | web_contents->SetTemporaryZoomLevel(level, true); |
[email protected] | d42bf47 | 2014-06-14 01:49:38 | [diff] [blame] | 492 | |
[email protected] | 367c5c1d | 2013-03-11 18:59:02 | [diff] [blame] | 493 | HostZoomMap::ZoomLevelChange change; |
| 494 | change.mode = HostZoomMap::ZOOM_CHANGED_TEMPORARY_ZOOM; |
[email protected] | d42bf47 | 2014-06-14 01:49:38 | [diff] [blame] | 495 | change.host = GetHostFromProcessView(render_process_id, render_view_id); |
[email protected] | 367c5c1d | 2013-03-11 18:59:02 | [diff] [blame] | 496 | change.zoom_level = level; |
| 497 | |
[email protected] | 11783281 | 2013-10-02 07:06:02 | [diff] [blame] | 498 | zoom_level_changed_callbacks_.Notify(change); |
[email protected] | b75b829 | 2010-10-01 07:28:25 | [diff] [blame] | 499 | } |
| 500 | |
wjmaclean | c6249049 | 2015-02-13 22:02:07 | [diff] [blame] | 501 | double HostZoomMapImpl::GetZoomLevelForView(const GURL& url, |
| 502 | int render_process_id, |
| 503 | int render_view_id) const { |
| 504 | RenderViewKey key(render_process_id, render_view_id); |
| 505 | base::AutoLock auto_lock(lock_); |
| 506 | |
skyostil | 66bd6791 | 2016-08-12 12:33:11 | [diff] [blame] | 507 | if (base::ContainsKey(temporary_zoom_levels_, key)) |
wjmaclean | c6249049 | 2015-02-13 22:02:07 | [diff] [blame] | 508 | return temporary_zoom_levels_.find(key)->second; |
| 509 | |
| 510 | return GetZoomLevelForHostAndSchemeInternal(url.scheme(), |
| 511 | net::GetHostOrSpecFromURL(url)); |
| 512 | } |
| 513 | |
Christian Dullweber | cc736c1 | 2017-09-04 09:27:50 | [diff] [blame] | 514 | void HostZoomMapImpl::ClearZoomLevels(base::Time delete_begin, |
| 515 | base::Time delete_end) { |
| 516 | double default_zoom_level = GetDefaultZoomLevel(); |
| 517 | for (auto& zoom_level : GetAllZoomLevels()) { |
| 518 | if (zoom_level.scheme.empty() && delete_begin <= zoom_level.last_modified && |
| 519 | (delete_end.is_null() || zoom_level.last_modified < delete_end)) { |
| 520 | SetZoomLevelForHost(zoom_level.host, default_zoom_level); |
| 521 | } |
| 522 | } |
| 523 | } |
| 524 | |
| 525 | void HostZoomMapImpl::SetStoreLastModified(bool store_last_modified) { |
| 526 | store_last_modified_ = store_last_modified; |
| 527 | } |
| 528 | |
[email protected] | d42bf47 | 2014-06-14 01:49:38 | [diff] [blame] | 529 | void HostZoomMapImpl::ClearTemporaryZoomLevel(int render_process_id, |
| 530 | int render_view_id) { |
| 531 | { |
| 532 | base::AutoLock auto_lock(lock_); |
| 533 | RenderViewKey key(render_process_id, render_view_id); |
| 534 | TemporaryZoomLevels::iterator it = temporary_zoom_levels_.find(key); |
| 535 | if (it == temporary_zoom_levels_.end()) |
| 536 | return; |
| 537 | temporary_zoom_levels_.erase(it); |
| 538 | } |
wjmaclean | 6495190 | 2016-04-29 20:59:12 | [diff] [blame] | 539 | WebContentsImpl* web_contents = |
| 540 | static_cast<WebContentsImpl*>(WebContents::FromRenderViewHost( |
| 541 | RenderViewHost::FromID(render_process_id, render_view_id))); |
| 542 | web_contents->SetTemporaryZoomLevel(GetZoomLevelForHost( |
| 543 | GetHostFromProcessView(render_process_id, render_view_id)), false); |
[email protected] | d42bf47 | 2014-06-14 01:49:38 | [diff] [blame] | 544 | } |
| 545 | |
| 546 | void HostZoomMapImpl::SendZoomLevelChange(const std::string& scheme, |
| 547 | const std::string& host, |
| 548 | double level) { |
wjmaclean | 6495190 | 2016-04-29 20:59:12 | [diff] [blame] | 549 | // We'll only send to WebContents not using temporary zoom levels. The one |
| 550 | // other case of interest is where the renderer is hosting a plugin document; |
| 551 | // that should be reflected in our temporary zoom level map, but we will |
| 552 | // double check on the renderer side to avoid the possibility of any races. |
vmpstr | 10e0d5f | 2016-07-21 23:46:09 | [diff] [blame] | 553 | for (auto* web_contents : WebContentsImpl::GetAllWebContents()) { |
wjmaclean | 6495190 | 2016-04-29 20:59:12 | [diff] [blame] | 554 | // Only send zoom level changes to WebContents that are using this |
| 555 | // HostZoomMap. |
| 556 | if (GetForWebContents(web_contents) != this) |
| 557 | continue; |
| 558 | |
Lukasz Anforowicz | c773bbd | 2017-10-02 19:25:29 | [diff] [blame^] | 559 | int render_process_id = |
| 560 | web_contents->GetRenderViewHost()->GetProcess()->GetID(); |
wjmaclean | 6495190 | 2016-04-29 20:59:12 | [diff] [blame] | 561 | int render_view_id = web_contents->GetRenderViewHost()->GetRoutingID(); |
| 562 | |
| 563 | if (!UsesTemporaryZoomLevel(render_process_id, render_view_id)) |
| 564 | web_contents->UpdateZoomIfNecessary(scheme, host, level); |
[email protected] | d42bf47 | 2014-06-14 01:49:38 | [diff] [blame] | 565 | } |
| 566 | } |
| 567 | |
wjmaclean | de29ed5 | 2014-10-28 21:09:06 | [diff] [blame] | 568 | void HostZoomMapImpl::SendErrorPageZoomLevelRefresh() { |
| 569 | GURL error_url(kUnreachableWebDataURL); |
| 570 | std::string host = net::GetHostOrSpecFromURL(error_url); |
| 571 | double error_page_zoom_level = GetZoomLevelForHost(host); |
| 572 | |
| 573 | SendZoomLevelChange(std::string(), host, error_page_zoom_level); |
| 574 | } |
| 575 | |
Sam McNally | e741fd66 | 2017-08-30 02:07:50 | [diff] [blame] | 576 | void HostZoomMapImpl::WillCloseRenderView(int render_process_id, |
| 577 | int render_view_id) { |
| 578 | ClearTemporaryZoomLevel(render_process_id, render_view_id); |
| 579 | ClearPageScaleFactorIsOneForView(render_process_id, render_view_id); |
| 580 | } |
| 581 | |
[email protected] | 5c925087 | 2012-01-30 17:24:05 | [diff] [blame] | 582 | HostZoomMapImpl::~HostZoomMapImpl() { |
mostynb | 4c27d04 | 2015-03-18 21:47:47 | [diff] [blame] | 583 | DCHECK_CURRENTLY_ON(BrowserThread::UI); |
[email protected] | 40bd658 | 2009-12-04 23:49:51 | [diff] [blame] | 584 | } |
[email protected] | 4648832 | 2012-10-30 03:22:20 | [diff] [blame] | 585 | |
Christian Dullweber | cc736c1 | 2017-09-04 09:27:50 | [diff] [blame] | 586 | void HostZoomMapImpl::SetClockForTesting(std::unique_ptr<base::Clock> clock) { |
| 587 | clock_ = std::move(clock); |
| 588 | } |
| 589 | |
[email protected] | 4648832 | 2012-10-30 03:22:20 | [diff] [blame] | 590 | } // namespace content |