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.
4 
5 #include "content/browser/host_zoom_map_impl.h"
6 
7 #include <algorithm>
8 #include <cmath>
9 #include <memory>
10 #include <utility>
11 
12 #include "base/strings/string_piece.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "base/time/default_clock.h"
15 #include "base/values.h"
16 #include "content/browser/renderer_host/navigation_entry_impl.h"
17 #include "content/browser/renderer_host/render_process_host_impl.h"
18 #include "content/browser/renderer_host/render_view_host_impl.h"
19 #include "content/browser/web_contents/web_contents_impl.h"
20 #include "content/public/browser/browser_context.h"
21 #include "content/public/browser/browser_thread.h"
22 #include "content/public/browser/render_frame_host.h"
23 #include "content/public/browser/resource_context.h"
24 #include "content/public/browser/site_instance.h"
25 #include "content/public/browser/storage_partition.h"
26 #include "content/public/common/url_constants.h"
27 #include "net/base/url_util.h"
28 #include "third_party/blink/public/common/page/page_zoom.h"
29 
30 namespace content {
31 
32 namespace {
33 
GetHostFromProcessView(int render_process_id,int render_view_id)34 std::string GetHostFromProcessView(int render_process_id, int render_view_id) {
35   DCHECK_CURRENTLY_ON(BrowserThread::UI);
36   RenderViewHost* render_view_host =
37       RenderViewHost::FromID(render_process_id, render_view_id);
38   if (!render_view_host)
39     return std::string();
40 
41   WebContents* web_contents = WebContents::FromRenderViewHost(render_view_host);
42 
43   NavigationEntry* entry =
44       web_contents->GetController().GetLastCommittedEntry();
45   if (!entry)
46     return std::string();
47 
48   return net::GetHostOrSpecFromURL(HostZoomMap::GetURLFromEntry(entry));
49 }
50 
51 }  // namespace
52 
GetURLFromEntry(NavigationEntry * entry)53 GURL HostZoomMap::GetURLFromEntry(NavigationEntry* entry) {
54   DCHECK_CURRENTLY_ON(BrowserThread::UI);
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 
GetDefaultForBrowserContext(BrowserContext * context)65 HostZoomMap* HostZoomMap::GetDefaultForBrowserContext(BrowserContext* context) {
66   DCHECK_CURRENTLY_ON(BrowserThread::UI);
67   StoragePartition* partition =
68       BrowserContext::GetDefaultStoragePartition(context);
69   DCHECK(partition);
70   return partition->GetHostZoomMap();
71 }
72 
Get(SiteInstance * instance)73 HostZoomMap* HostZoomMap::Get(SiteInstance* instance) {
74   DCHECK_CURRENTLY_ON(BrowserThread::UI);
75   StoragePartition* partition = BrowserContext::GetStoragePartition(
76       instance->GetBrowserContext(), instance);
77   DCHECK(partition);
78   return partition->GetHostZoomMap();
79 }
80 
GetForWebContents(WebContents * contents)81 HostZoomMap* HostZoomMap::GetForWebContents(WebContents* contents) {
82   DCHECK_CURRENTLY_ON(BrowserThread::UI);
83   // TODO(wjmaclean): Update this behaviour to work with OOPIF.
84   // See crbug.com/528407.
85   StoragePartition* partition =
86       BrowserContext::GetStoragePartition(contents->GetBrowserContext(),
87                                           contents->GetSiteInstance());
88   DCHECK(partition);
89   return partition->GetHostZoomMap();
90 }
91 
92 // Helper function for setting/getting zoom levels for WebContents without
93 // having to import HostZoomMapImpl everywhere.
GetZoomLevel(WebContents * web_contents)94 double HostZoomMap::GetZoomLevel(WebContents* web_contents) {
95   DCHECK_CURRENTLY_ON(BrowserThread::UI);
96   HostZoomMapImpl* host_zoom_map = static_cast<HostZoomMapImpl*>(
97       HostZoomMap::GetForWebContents(web_contents));
98   return host_zoom_map->GetZoomLevelForWebContents(
99       static_cast<WebContentsImpl*>(web_contents));
100 }
101 
PageScaleFactorIsOne(WebContents * web_contents)102 bool HostZoomMap::PageScaleFactorIsOne(WebContents* web_contents) {
103   DCHECK_CURRENTLY_ON(BrowserThread::UI);
104   HostZoomMapImpl* host_zoom_map = static_cast<HostZoomMapImpl*>(
105       HostZoomMap::GetForWebContents(web_contents));
106   return host_zoom_map->PageScaleFactorIsOneForWebContents(
107       static_cast<WebContentsImpl*>(web_contents));
108 }
109 
SetZoomLevel(WebContents * web_contents,double level)110 void HostZoomMap::SetZoomLevel(WebContents* web_contents, double level) {
111   DCHECK_CURRENTLY_ON(BrowserThread::UI);
112   HostZoomMapImpl* host_zoom_map = static_cast<HostZoomMapImpl*>(
113       HostZoomMap::GetForWebContents(web_contents));
114   host_zoom_map->SetZoomLevelForWebContents(
115       static_cast<WebContentsImpl*>(web_contents), level);
116 }
117 
SendErrorPageZoomLevelRefresh(WebContents * web_contents)118 void HostZoomMap::SendErrorPageZoomLevelRefresh(WebContents* web_contents) {
119   DCHECK_CURRENTLY_ON(BrowserThread::UI);
120   HostZoomMapImpl* host_zoom_map =
121       static_cast<HostZoomMapImpl*>(HostZoomMap::GetDefaultForBrowserContext(
122           web_contents->GetBrowserContext()));
123   host_zoom_map->SendErrorPageZoomLevelRefresh();
124 }
125 
HostZoomMapImpl()126 HostZoomMapImpl::HostZoomMapImpl()
127     : default_zoom_level_(0.0),
128       clock_(base::DefaultClock::GetInstance()) {
129   DCHECK_CURRENTLY_ON(BrowserThread::UI);
130 }
131 
CopyFrom(HostZoomMap * copy_interface)132 void HostZoomMapImpl::CopyFrom(HostZoomMap* copy_interface) {
133   DCHECK_CURRENTLY_ON(BrowserThread::UI);
134   HostZoomMapImpl* copy = static_cast<HostZoomMapImpl*>(copy_interface);
135   host_zoom_levels_.insert(copy->host_zoom_levels_.begin(),
136                            copy->host_zoom_levels_.end());
137   for (const auto& it : copy->scheme_host_zoom_levels_) {
138     const std::string& host = it.first;
139     scheme_host_zoom_levels_[host] = HostZoomLevels();
140     scheme_host_zoom_levels_[host].insert(it.second.begin(), it.second.end());
141   }
142   default_zoom_level_ = copy->default_zoom_level_;
143 }
144 
GetZoomLevelForHost(const std::string & host) const145 double HostZoomMapImpl::GetZoomLevelForHost(const std::string& host) const {
146   DCHECK_CURRENTLY_ON(BrowserThread::UI);
147   const auto it = host_zoom_levels_.find(host);
148   return it != host_zoom_levels_.end() ? it->second.level : default_zoom_level_;
149 }
150 
HasZoomLevel(const std::string & scheme,const std::string & host)151 bool HostZoomMapImpl::HasZoomLevel(const std::string& scheme,
152                                    const std::string& host) {
153   DCHECK_CURRENTLY_ON(BrowserThread::UI);
154   auto scheme_iterator(scheme_host_zoom_levels_.find(scheme));
155 
156   const HostZoomLevels& zoom_levels =
157       (scheme_iterator != scheme_host_zoom_levels_.end())
158           ? scheme_iterator->second
159           : host_zoom_levels_;
160 
161   return base::Contains(zoom_levels, host);
162 }
163 
GetZoomLevelForHostAndScheme(const std::string & scheme,const std::string & host)164 double HostZoomMapImpl::GetZoomLevelForHostAndScheme(const std::string& scheme,
165                                                      const std::string& host) {
166   DCHECK_CURRENTLY_ON(BrowserThread::UI);
167   auto scheme_iterator(scheme_host_zoom_levels_.find(scheme));
168   if (scheme_iterator != scheme_host_zoom_levels_.end()) {
169     auto i(scheme_iterator->second.find(host));
170     if (i != scheme_iterator->second.end())
171       return i->second.level;
172   }
173 
174   return GetZoomLevelForHost(host);
175 }
176 
GetAllZoomLevels()177 HostZoomMap::ZoomLevelVector HostZoomMapImpl::GetAllZoomLevels() {
178   DCHECK_CURRENTLY_ON(BrowserThread::UI);
179   HostZoomMap::ZoomLevelVector result;
180   result.reserve(host_zoom_levels_.size() + scheme_host_zoom_levels_.size());
181   for (const auto& entry : host_zoom_levels_) {
182     ZoomLevelChange change = {
183         HostZoomMap::ZOOM_CHANGED_FOR_HOST,
184         entry.first,                // host
185         std::string(),              // scheme
186         entry.second.level,         // zoom level
187         entry.second.last_modified  // last modified
188     };
189     result.push_back(change);
190   }
191   for (const auto& scheme_entry : scheme_host_zoom_levels_) {
192     const std::string& scheme = scheme_entry.first;
193     const HostZoomLevels& host_zoom_levels = scheme_entry.second;
194     for (const auto& entry : host_zoom_levels) {
195       ZoomLevelChange change = {
196           HostZoomMap::ZOOM_CHANGED_FOR_SCHEME_AND_HOST,
197           entry.first,                // host
198           scheme,                     // scheme
199           entry.second.level,         // zoom level
200           entry.second.last_modified  // last modified
201       };
202       result.push_back(change);
203     }
204   }
205   return result;
206 }
207 
SetZoomLevelForHost(const std::string & host,double level)208 void HostZoomMapImpl::SetZoomLevelForHost(const std::string& host,
209                                           double level) {
210   DCHECK_CURRENTLY_ON(BrowserThread::UI);
211   base::Time last_modified = clock_->Now();
212   SetZoomLevelForHostInternal(host, level, last_modified);
213 }
214 
InitializeZoomLevelForHost(const std::string & host,double level,base::Time last_modified)215 void HostZoomMapImpl::InitializeZoomLevelForHost(const std::string& host,
216                                                  double level,
217                                                  base::Time last_modified) {
218   DCHECK_CURRENTLY_ON(BrowserThread::UI);
219   SetZoomLevelForHostInternal(host, level, last_modified);
220 }
221 
SetZoomLevelForHostInternal(const std::string & host,double level,base::Time last_modified)222 void HostZoomMapImpl::SetZoomLevelForHostInternal(const std::string& host,
223                                                   double level,
224                                                   base::Time last_modified) {
225   DCHECK_CURRENTLY_ON(BrowserThread::UI);
226 
227   if (blink::PageZoomValuesEqual(level, default_zoom_level_)) {
228     host_zoom_levels_.erase(host);
229   } else {
230     ZoomLevel& zoomLevel = host_zoom_levels_[host];
231     zoomLevel.level = level;
232     zoomLevel.last_modified = last_modified;
233   }
234 
235   // TODO(wjmaclean) Should we use a GURL here? crbug.com/384486
236   SendZoomLevelChange(std::string(), host);
237 
238   HostZoomMap::ZoomLevelChange change;
239   change.mode = HostZoomMap::ZOOM_CHANGED_FOR_HOST;
240   change.host = host;
241   change.zoom_level = level;
242   change.last_modified = last_modified;
243 
244   zoom_level_changed_callbacks_.Notify(change);
245 }
246 
SetZoomLevelForHostAndScheme(const std::string & scheme,const std::string & host,double level)247 void HostZoomMapImpl::SetZoomLevelForHostAndScheme(const std::string& scheme,
248                                                    const std::string& host,
249                                                    double level) {
250   DCHECK_CURRENTLY_ON(BrowserThread::UI);
251   // No last_modified timestamp for scheme and host because they are
252   // not persistet and are used for special cases only.
253   scheme_host_zoom_levels_[scheme][host].level = level;
254 
255   SendZoomLevelChange(scheme, host);
256 
257   HostZoomMap::ZoomLevelChange change;
258   change.mode = HostZoomMap::ZOOM_CHANGED_FOR_SCHEME_AND_HOST;
259   change.host = host;
260   change.scheme = scheme;
261   change.zoom_level = level;
262   change.last_modified = base::Time();
263 
264   zoom_level_changed_callbacks_.Notify(change);
265 }
266 
GetDefaultZoomLevel()267 double HostZoomMapImpl::GetDefaultZoomLevel() {
268   DCHECK_CURRENTLY_ON(BrowserThread::UI);
269   return default_zoom_level_;
270 }
271 
SetDefaultZoomLevel(double level)272 void HostZoomMapImpl::SetDefaultZoomLevel(double level) {
273   DCHECK_CURRENTLY_ON(BrowserThread::UI);
274 
275   if (blink::PageZoomValuesEqual(level, default_zoom_level_))
276     return;
277 
278   default_zoom_level_ = level;
279 
280   // First, remove all entries that match the new default zoom level.
281   for (auto it = host_zoom_levels_.begin(); it != host_zoom_levels_.end();) {
282     if (blink::PageZoomValuesEqual(it->second.level, default_zoom_level_))
283       it = host_zoom_levels_.erase(it);
284     else
285       it++;
286   }
287 
288   // Second, update zoom levels for all pages that do not have an overriding
289   // entry.
290   for (auto* web_contents : WebContentsImpl::GetAllWebContents()) {
291     // Only change zoom for WebContents tied to the StoragePartition this
292     // HostZoomMap serves.
293     if (GetForWebContents(web_contents) != this)
294       continue;
295 
296     int render_process_id =
297         web_contents->GetRenderViewHost()->GetProcess()->GetID();
298     int render_view_id = web_contents->GetRenderViewHost()->GetRoutingID();
299 
300     // Get the url from the navigation controller directly, as calling
301     // WebContentsImpl::GetLastCommittedURL() may give us a virtual url that
302     // is different than the one stored in the map.
303     GURL url;
304     std::string host;
305     std::string scheme;
306 
307     NavigationEntry* entry =
308         web_contents->GetController().GetLastCommittedEntry();
309     // It is possible for a WebContent's zoom level to be queried before
310     // a navigation has occurred.
311     if (entry) {
312       url = GetURLFromEntry(entry);
313       scheme = url.scheme();
314       host = net::GetHostOrSpecFromURL(url);
315     }
316 
317     bool uses_default_zoom =
318         !HasZoomLevel(scheme, host) &&
319         !UsesTemporaryZoomLevel(render_process_id, render_view_id);
320 
321     if (uses_default_zoom) {
322       web_contents->UpdateZoom();
323 
324       HostZoomMap::ZoomLevelChange change;
325       change.mode = HostZoomMap::ZOOM_CHANGED_FOR_HOST;
326       change.host = host;
327       change.zoom_level = level;
328 
329       zoom_level_changed_callbacks_.Notify(change);
330     }
331   }
332 }
333 
334 std::unique_ptr<HostZoomMap::Subscription>
AddZoomLevelChangedCallback(ZoomLevelChangedCallback callback)335 HostZoomMapImpl::AddZoomLevelChangedCallback(
336     ZoomLevelChangedCallback callback) {
337   DCHECK_CURRENTLY_ON(BrowserThread::UI);
338   return zoom_level_changed_callbacks_.Add(std::move(callback));
339 }
340 
GetZoomLevelForWebContents(WebContentsImpl * web_contents_impl)341 double HostZoomMapImpl::GetZoomLevelForWebContents(
342     WebContentsImpl* web_contents_impl) {
343   DCHECK_CURRENTLY_ON(BrowserThread::UI);
344   int render_process_id =
345       web_contents_impl->GetRenderViewHost()->GetProcess()->GetID();
346   int routing_id = web_contents_impl->GetRenderViewHost()->GetRoutingID();
347 
348   if (UsesTemporaryZoomLevel(render_process_id, routing_id))
349     return GetTemporaryZoomLevel(render_process_id, routing_id);
350 
351   // Get the url from the navigation controller directly, as calling
352   // WebContentsImpl::GetLastCommittedURL() may give us a virtual url that
353   // is different than is stored in the map.
354   GURL url;
355   NavigationEntry* entry =
356       web_contents_impl->GetController().GetLastCommittedEntry();
357   // It is possible for a WebContent's zoom level to be queried before
358   // a navigation has occurred.
359   if (entry)
360     url = GetURLFromEntry(entry);
361   return GetZoomLevelForHostAndScheme(url.scheme(),
362                                       net::GetHostOrSpecFromURL(url));
363 }
364 
SetZoomLevelForWebContents(WebContentsImpl * web_contents_impl,double level)365 void HostZoomMapImpl::SetZoomLevelForWebContents(
366     WebContentsImpl* web_contents_impl,
367     double level) {
368   DCHECK_CURRENTLY_ON(BrowserThread::UI);
369   int render_process_id =
370       web_contents_impl->GetRenderViewHost()->GetProcess()->GetID();
371   int render_view_id = web_contents_impl->GetRenderViewHost()->GetRoutingID();
372   if (UsesTemporaryZoomLevel(render_process_id, render_view_id)) {
373     SetTemporaryZoomLevel(render_process_id, render_view_id, level);
374   } else {
375     // Get the url from the navigation controller directly, as calling
376     // WebContentsImpl::GetLastCommittedURL() may give us a virtual url that
377     // is different than what the render view is using. If the two don't match,
378     // the attempt to set the zoom will fail.
379     NavigationEntry* entry =
380         web_contents_impl->GetController().GetLastCommittedEntry();
381     // Tests may invoke this function with a null entry, but we don't
382     // want to save zoom levels in this case.
383     if (!entry)
384       return;
385 
386     GURL url = GetURLFromEntry(entry);
387     SetZoomLevelForHost(net::GetHostOrSpecFromURL(url), level);
388   }
389 }
390 
SetPageScaleFactorIsOneForView(int render_process_id,int render_view_id,bool is_one)391 void HostZoomMapImpl::SetPageScaleFactorIsOneForView(int render_process_id,
392                                                      int render_view_id,
393                                                      bool is_one) {
394   DCHECK_CURRENTLY_ON(BrowserThread::UI);
395   view_page_scale_factors_are_one_[RenderViewKey(render_process_id,
396                                                  render_view_id)] = is_one;
397   HostZoomMap::ZoomLevelChange change;
398   change.mode = HostZoomMap::PAGE_SCALE_IS_ONE_CHANGED;
399   zoom_level_changed_callbacks_.Notify(change);
400 }
401 
PageScaleFactorIsOneForWebContents(WebContentsImpl * web_contents_impl) const402 bool HostZoomMapImpl::PageScaleFactorIsOneForWebContents(
403     WebContentsImpl* web_contents_impl) const {
404   DCHECK_CURRENTLY_ON(BrowserThread::UI);
405   if (!web_contents_impl->GetRenderViewHost()->GetProcess())
406     return true;
407 
408   const auto it = view_page_scale_factors_are_one_.find(RenderViewKey(
409       web_contents_impl->GetRenderViewHost()->GetProcess()->GetID(),
410       web_contents_impl->GetRenderViewHost()->GetRoutingID()));
411   return it != view_page_scale_factors_are_one_.end() ? it->second : true;
412 }
413 
ClearPageScaleFactorIsOneForView(int render_process_id,int render_view_id)414 void HostZoomMapImpl::ClearPageScaleFactorIsOneForView(int render_process_id,
415                                                        int render_view_id) {
416   DCHECK_CURRENTLY_ON(BrowserThread::UI);
417   view_page_scale_factors_are_one_.erase(
418       RenderViewKey(render_process_id, render_view_id));
419 }
420 
UsesTemporaryZoomLevel(int render_process_id,int render_view_id)421 bool HostZoomMapImpl::UsesTemporaryZoomLevel(int render_process_id,
422                                              int render_view_id) {
423   DCHECK_CURRENTLY_ON(BrowserThread::UI);
424   RenderViewKey key(render_process_id, render_view_id);
425   return base::Contains(temporary_zoom_levels_, key);
426 }
427 
GetTemporaryZoomLevel(int render_process_id,int render_view_id) const428 double HostZoomMapImpl::GetTemporaryZoomLevel(int render_process_id,
429                                               int render_view_id) const {
430   DCHECK_CURRENTLY_ON(BrowserThread::UI);
431   RenderViewKey key(render_process_id, render_view_id);
432   const auto it = temporary_zoom_levels_.find(key);
433   return it != temporary_zoom_levels_.end() ? it->second : 0;
434 }
435 
SetTemporaryZoomLevel(int render_process_id,int render_view_id,double level)436 void HostZoomMapImpl::SetTemporaryZoomLevel(int render_process_id,
437                                             int render_view_id,
438                                             double level) {
439   DCHECK_CURRENTLY_ON(BrowserThread::UI);
440 
441   RenderViewKey key(render_process_id, render_view_id);
442   temporary_zoom_levels_[key] = level;
443 
444   WebContentsImpl* web_contents =
445       static_cast<WebContentsImpl*>(WebContents::FromRenderViewHost(
446           RenderViewHost::FromID(render_process_id, render_view_id)));
447   web_contents->UpdateZoom();
448 
449   HostZoomMap::ZoomLevelChange change;
450   change.mode = HostZoomMap::ZOOM_CHANGED_TEMPORARY_ZOOM;
451   change.host = GetHostFromProcessView(render_process_id, render_view_id);
452   change.zoom_level = level;
453 
454   zoom_level_changed_callbacks_.Notify(change);
455 }
456 
ClearZoomLevels(base::Time delete_begin,base::Time delete_end)457 void HostZoomMapImpl::ClearZoomLevels(base::Time delete_begin,
458                                       base::Time delete_end) {
459   DCHECK_CURRENTLY_ON(BrowserThread::UI);
460   double default_zoom_level = GetDefaultZoomLevel();
461   for (const auto& zoom_level : GetAllZoomLevels()) {
462     if (zoom_level.scheme.empty() && delete_begin <= zoom_level.last_modified &&
463         (delete_end.is_null() || zoom_level.last_modified < delete_end)) {
464       SetZoomLevelForHost(zoom_level.host, default_zoom_level);
465     }
466   }
467 }
468 
ClearTemporaryZoomLevel(int render_process_id,int render_view_id)469 void HostZoomMapImpl::ClearTemporaryZoomLevel(int render_process_id,
470                                               int render_view_id) {
471   DCHECK_CURRENTLY_ON(BrowserThread::UI);
472   RenderViewKey key(render_process_id, render_view_id);
473   auto it = temporary_zoom_levels_.find(key);
474   if (it == temporary_zoom_levels_.end())
475     return;
476 
477   temporary_zoom_levels_.erase(it);
478   WebContentsImpl* web_contents =
479       static_cast<WebContentsImpl*>(WebContents::FromRenderViewHost(
480           RenderViewHost::FromID(render_process_id, render_view_id)));
481   web_contents->UpdateZoom();
482 }
483 
SendZoomLevelChange(const std::string & scheme,const std::string & host)484 void HostZoomMapImpl::SendZoomLevelChange(const std::string& scheme,
485                                           const std::string& host) {
486   DCHECK_CURRENTLY_ON(BrowserThread::UI);
487   // We'll only send to WebContents not using temporary zoom levels. The one
488   // other case of interest is where the renderer is hosting a plugin document;
489   // that should be reflected in our temporary zoom level map, but we will
490   // double check on the renderer side to avoid the possibility of any races.
491   for (auto* web_contents : WebContentsImpl::GetAllWebContents()) {
492     // Only send zoom level changes to WebContents that are using this
493     // HostZoomMap.
494     if (GetForWebContents(web_contents) != this)
495       continue;
496 
497     int render_process_id =
498         web_contents->GetRenderViewHost()->GetProcess()->GetID();
499     int render_view_id = web_contents->GetRenderViewHost()->GetRoutingID();
500 
501     if (!UsesTemporaryZoomLevel(render_process_id, render_view_id))
502       web_contents->UpdateZoomIfNecessary(scheme, host);
503   }
504 }
505 
SendErrorPageZoomLevelRefresh()506 void HostZoomMapImpl::SendErrorPageZoomLevelRefresh() {
507   DCHECK_CURRENTLY_ON(BrowserThread::UI);
508   GURL error_url(kUnreachableWebDataURL);
509   std::string host = net::GetHostOrSpecFromURL(error_url);
510 
511   SendZoomLevelChange(std::string(), host);
512 }
513 
WillCloseRenderView(int render_process_id,int render_view_id)514 void HostZoomMapImpl::WillCloseRenderView(int render_process_id,
515                                           int render_view_id) {
516   DCHECK_CURRENTLY_ON(BrowserThread::UI);
517   ClearTemporaryZoomLevel(render_process_id, render_view_id);
518   ClearPageScaleFactorIsOneForView(render_process_id, render_view_id);
519 }
520 
~HostZoomMapImpl()521 HostZoomMapImpl::~HostZoomMapImpl() {
522   DCHECK_CURRENTLY_ON(BrowserThread::UI);
523 }
524 
SetClockForTesting(base::Clock * clock)525 void HostZoomMapImpl::SetClockForTesting(base::Clock* clock) {
526   clock_ = clock;
527 }
528 
529 }  // namespace content
530