blob: 5b75a5577dbed831f06a478c28bb475ca12f6544 [file] [log] [blame]
Avi Drissman4e1b7bc32022-09-15 14:03:501// Copyright 2012 The Chromium Authors
[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]5c9250872012-01-30 17:24:055#include "content/browser/host_zoom_map_impl.h"
[email protected]40bd6582009-12-04 23:49:516
[email protected]fce823222014-05-30 16:24:307#include <algorithm>
[email protected]b9e7c479f2013-04-12 04:33:248#include <cmath>
Lukasz Anforowiczc773bbd2017-10-02 19:25:299#include <memory>
10#include <utility>
[email protected]b9e7c479f2013-04-12 04:33:2411
Lei Zhangd4f2c7ad2021-05-13 20:10:1212#include "base/containers/contains.h"
[email protected]74ebfb12013-06-07 20:48:0013#include "base/strings/utf_string_conversions.h"
Christian Dullwebercc736c12017-09-04 09:27:5014#include "base/time/default_clock.h"
[email protected]d407cc02011-09-13 16:01:4615#include "base/values.h"
Mark Schillaci1363e4a2021-10-04 19:10:0916#include "build/build_config.h"
danakje94b7c842020-09-16 18:47:4317#include "content/browser/renderer_host/navigation_entry_impl.h"
Miyoung Shindae09862022-11-02 01:27:3718#include "content/browser/renderer_host/render_frame_host_impl.h"
[email protected]f3b1a082011-11-18 00:34:3019#include "content/browser/renderer_host/render_process_host_impl.h"
[email protected]fce823222014-05-30 16:24:3020#include "content/browser/web_contents/web_contents_impl.h"
[email protected]4e2a25a2012-01-27 00:42:0821#include "content/public/browser/browser_context.h"
[email protected]c38831a12011-10-28 12:44:4922#include "content/public/browser/browser_thread.h"
W. James MacLeanf562b922025-03-13 15:36:1923#include "content/public/browser/content_browser_client.h"
Mark Schillacicddfa172022-07-28 19:57:1324#include "content/public/browser/host_zoom_map.h"
Lukasz Anforowiczc773bbd2017-10-02 19:25:2925#include "content/public/browser/render_frame_host.h"
[email protected]5fe3713a2012-02-22 08:31:5626#include "content/public/browser/resource_context.h"
wjmacleancaa7d6d2014-11-12 16:42:1127#include "content/public/browser/site_instance.h"
28#include "content/public/browser/storage_partition.h"
W. James MacLeanf562b922025-03-13 15:36:1929#include "content/public/common/content_client.h"
wjmacleande29ed52014-10-28 21:09:0630#include "content/public/common/url_constants.h"
tfarina7a4a7fd2016-01-20 14:23:4431#include "net/base/url_util.h"
danakj938b37a62019-09-24 18:35:5432#include "third_party/blink/public/common/page/page_zoom.h"
[email protected]40bd6582009-12-04 23:49:5133
Xiaohan Wang1ecfd002022-01-19 22:33:1034#if BUILDFLAG(IS_ANDROID)
Andrew Grievef46caa512024-05-23 16:59:3635#include "base/android/jni_string.h"
Mark Schillacic28765d2022-06-03 21:38:4436#include "content/public/browser/android/browser_context_handle.h"
Andrew Grievef46caa512024-05-23 16:59:3637
38// Must come after all headers that specialize FromJniType() / ToJniType().
39#include "content/public/android/content_jni_headers/HostZoomMapImpl_jni.h"
Mark Schillaci1363e4a2021-10-04 19:10:0940#endif
41
[email protected]5c9250872012-01-30 17:24:0542namespace content {
43
[email protected]d42bf472014-06-14 01:49:3844namespace {
45
W. James MacLean817a05e2025-02-18 15:51:1546GURL GetURLForRenderFrameHostPtr(const RenderFrameHost* rfh) {
47 if (!rfh) {
48 return GURL();
49 }
50
51 // If a user lands on an error page, and then modifies the zoom level, it
52 // should be attributed to the error-page host and not the page they were
53 // trying to reach.
54 return rfh->IsErrorDocument() ? GURL(kUnreachableWebDataURL)
55 : rfh->GetLastCommittedURL();
56}
57
Miyoung Shindae09862022-11-02 01:27:3758std::string GetHostFromProcessFrame(RenderFrameHostImpl* rfh) {
mostynb4c27d042015-03-18 21:47:4759 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Miyoung Shindae09862022-11-02 01:27:3760 if (!rfh)
[email protected]d42bf472014-06-14 01:49:3861 return std::string();
62
W. James MacLean817a05e2025-02-18 15:51:1563 const GURL url = GetURLForRenderFrameHostPtr(rfh);
[email protected]d42bf472014-06-14 01:49:3864
W. James MacLean817a05e2025-02-18 15:51:1565 return net::GetHostOrSpecFromURL(url);
[email protected]d42bf472014-06-14 01:49:3866}
67
W. James MacLeanf562b922025-03-13 15:36:1968// Allows HostZoomMap to grant independent zoom to subframes.
69BASE_FEATURE(kSubframeZoom, "SubframeZoom", base::FEATURE_ENABLED_BY_DEFAULT);
70
71// Returns true if local root subframes may have different zoom levels than
72// the primary main frame.
73bool IsIndependentSubframeZoomEnabled() {
74 // kSubframeZoom acts as a killswitch here. It is enabled by default, but
75 // only return true here if some feature that requires subframe zoom is also
76 // enabled.
77 return base::FeatureList::IsEnabled(kSubframeZoom) &&
78 (base::FeatureList::IsEnabled(features::kGuestViewMPArch) ||
79 GetContentClient()->browser()->ShouldEnableSubframeZoom());
80}
81
[email protected]d42bf472014-06-14 01:49:3882} // namespace
83
W. James MacLean817a05e2025-02-18 15:51:1584// static
85GURL HostZoomMap::GetURLForRenderFrameHost(GlobalRenderFrameHostId rfh_id) {
86 return GetURLForRenderFrameHostPtr(RenderFrameHost::FromID(rfh_id));
87}
88
89// static
90GURL HostZoomMap::GetURLForWebContents(WebContents* web_contents) {
91 return GetURLForRenderFrameHostPtr(web_contents->GetPrimaryMainFrame());
wjmacleande29ed52014-10-28 21:09:0692}
93
Robbie McElrath3e9db502023-05-08 23:02:4594// static
wjmacleanf9b6ec82014-08-27 14:33:2495HostZoomMap* HostZoomMap::GetDefaultForBrowserContext(BrowserContext* context) {
Robbie McElrath3e9db502023-05-08 23:02:4596 return GetForStoragePartition(context->GetDefaultStoragePartition());
wjmacleancaa7d6d2014-11-12 16:42:1197}
98
Robbie McElrath3e9db502023-05-08 23:02:4599// static
wjmacleancaa7d6d2014-11-12 16:42:11100HostZoomMap* HostZoomMap::Get(SiteInstance* instance) {
Robbie McElrath3e9db502023-05-08 23:02:45101 return GetForStoragePartition(
102 instance->GetBrowserContext()->GetStoragePartition(instance));
wjmacleancaa7d6d2014-11-12 16:42:11103}
104
Robbie McElrath3e9db502023-05-08 23:02:45105// static
Lucas Furukawa Gadanie1c5dfda2018-11-29 17:57:41106HostZoomMap* HostZoomMap::GetForWebContents(WebContents* contents) {
mcnee432e47d2015-11-09 19:37:46107 // TODO(wjmaclean): Update this behaviour to work with OOPIF.
108 // See crbug.com/528407.
Robbie McElrath3e9db502023-05-08 23:02:45109 return Get(contents->GetSiteInstance());
110}
111
112// static
113HostZoomMap* HostZoomMap::GetForStoragePartition(
114 StoragePartition* storage_partition) {
115 DCHECK_CURRENTLY_ON(BrowserThread::UI);
116 CHECK(storage_partition);
117 return storage_partition->GetHostZoomMap();
[email protected]5c9250872012-01-30 17:24:05118}
119
[email protected]fce823222014-05-30 16:24:30120// Helper function for setting/getting zoom levels for WebContents without
121// having to import HostZoomMapImpl everywhere.
W. James MacLean37af605e2025-01-20 16:59:38122
123// static
Lucas Furukawa Gadanie1c5dfda2018-11-29 17:57:41124double HostZoomMap::GetZoomLevel(WebContents* web_contents) {
W. James MacLean37af605e2025-01-20 16:59:38125 return GetZoomLevel(web_contents,
126 web_contents->GetPrimaryMainFrame()->GetGlobalId());
[email protected]fce823222014-05-30 16:24:30127}
128
W. James MacLean37af605e2025-01-20 16:59:38129// static
130double HostZoomMap::GetZoomLevel(WebContents* web_contents,
131 GlobalRenderFrameHostId rfh_id) {
Lei Zhang9d40e7902017-11-20 19:54:36132 DCHECK_CURRENTLY_ON(BrowserThread::UI);
wjmacleancaa7d6d2014-11-12 16:42:11133 HostZoomMapImpl* host_zoom_map = static_cast<HostZoomMapImpl*>(
W. James MacLean37af605e2025-01-20 16:59:38134 HostZoomMap::Get(RenderFrameHost::FromID(rfh_id)->GetSiteInstance()));
135 return host_zoom_map->GetZoomLevelForWebContents(
136 static_cast<WebContentsImpl*>(web_contents), rfh_id);
137}
138
139// static
140void HostZoomMap::SetZoomLevel(WebContents* web_contents, double level) {
141 HostZoomMap::SetZoomLevel(
142 web_contents, web_contents->GetPrimaryMainFrame()->GetGlobalId(), level);
143}
144
145// static
146void HostZoomMap::SetZoomLevel(WebContents* web_contents,
147 GlobalRenderFrameHostId rfh_id,
148 double level) {
149 DCHECK_CURRENTLY_ON(BrowserThread::UI);
150 HostZoomMapImpl* host_zoom_map = static_cast<HostZoomMapImpl*>(
151 HostZoomMap::Get(RenderFrameHost::FromID(rfh_id)->GetSiteInstance()));
[email protected]fce823222014-05-30 16:24:30152 host_zoom_map->SetZoomLevelForWebContents(
W. James MacLean37af605e2025-01-20 16:59:38153 static_cast<WebContentsImpl*>(web_contents), rfh_id, level);
[email protected]fce823222014-05-30 16:24:30154}
155
Lucas Furukawa Gadanie1c5dfda2018-11-29 17:57:41156void HostZoomMap::SendErrorPageZoomLevelRefresh(WebContents* web_contents) {
Lei Zhang9d40e7902017-11-20 19:54:36157 DCHECK_CURRENTLY_ON(BrowserThread::UI);
wjmacleande29ed52014-10-28 21:09:06158 HostZoomMapImpl* host_zoom_map =
159 static_cast<HostZoomMapImpl*>(HostZoomMap::GetDefaultForBrowserContext(
160 web_contents->GetBrowserContext()));
161 host_zoom_map->SendErrorPageZoomLevelRefresh();
162}
163
[email protected]5c9250872012-01-30 17:24:05164HostZoomMapImpl::HostZoomMapImpl()
Christian Dullwebercc736c12017-09-04 09:27:50165 : default_zoom_level_(0.0),
tzik67025f672017-11-29 05:04:44166 clock_(base::DefaultClock::GetInstance()) {
Lei Zhang9d40e7902017-11-20 19:54:36167 DCHECK_CURRENTLY_ON(BrowserThread::UI);
168}
[email protected]40bd6582009-12-04 23:49:51169
[email protected]5c9250872012-01-30 17:24:05170void HostZoomMapImpl::CopyFrom(HostZoomMap* copy_interface) {
mostynb4c27d042015-03-18 21:47:47171 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]5c9250872012-01-30 17:24:05172 HostZoomMapImpl* copy = static_cast<HostZoomMapImpl*>(copy_interface);
Lei Zhang9d40e7902017-11-20 19:54:36173 host_zoom_levels_.insert(copy->host_zoom_levels_.begin(),
174 copy->host_zoom_levels_.end());
175 for (const auto& it : copy->scheme_host_zoom_levels_) {
176 const std::string& host = it.first;
177 scheme_host_zoom_levels_[host] = HostZoomLevels();
178 scheme_host_zoom_levels_[host].insert(it.second.begin(), it.second.end());
[email protected]4e2a25a2012-01-27 00:42:08179 }
[email protected]19d26692013-01-12 19:56:33180 default_zoom_level_ = copy->default_zoom_level_;
kenod3fe1c222023-12-13 19:58:50181
182 host_zoom_levels_for_preview_.insert(
183 copy->host_zoom_levels_for_preview_.begin(),
184 copy->host_zoom_levels_for_preview_.end());
[email protected]4e2a25a2012-01-27 00:42:08185}
186
[email protected]367c5c1d2013-03-11 18:59:02187double HostZoomMapImpl::GetZoomLevelForHost(const std::string& host) const {
Lei Zhang9d40e7902017-11-20 19:54:36188 DCHECK_CURRENTLY_ON(BrowserThread::UI);
189 const auto it = host_zoom_levels_.find(host);
190 return it != host_zoom_levels_.end() ? it->second.level : default_zoom_level_;
[email protected]40bd6582009-12-04 23:49:51191}
192
[email protected]d42bf472014-06-14 01:49:38193bool HostZoomMapImpl::HasZoomLevel(const std::string& scheme,
Lucas Furukawa Gadani4b4eed02019-06-04 23:12:04194 const std::string& host) {
Lei Zhang9d40e7902017-11-20 19:54:36195 DCHECK_CURRENTLY_ON(BrowserThread::UI);
jdoerrie55ec69d2018-10-08 13:34:46196 auto scheme_iterator(scheme_host_zoom_levels_.find(scheme));
[email protected]d42bf472014-06-14 01:49:38197
198 const HostZoomLevels& zoom_levels =
199 (scheme_iterator != scheme_host_zoom_levels_.end())
200 ? scheme_iterator->second
201 : host_zoom_levels_;
202
Jan Wilken Dörrie77c581a2019-06-07 16:25:06203 return base::Contains(zoom_levels, host);
[email protected]d42bf472014-06-14 01:49:38204}
205
Lucas Furukawa Gadani4b4eed02019-06-04 23:12:04206double HostZoomMapImpl::GetZoomLevelForHostAndScheme(const std::string& scheme,
207 const std::string& host) {
Lei Zhang9d40e7902017-11-20 19:54:36208 DCHECK_CURRENTLY_ON(BrowserThread::UI);
jdoerrie55ec69d2018-10-08 13:34:46209 auto scheme_iterator(scheme_host_zoom_levels_.find(scheme));
wjmacleanc62490492015-02-13 22:02:07210 if (scheme_iterator != scheme_host_zoom_levels_.end()) {
jdoerrie55ec69d2018-10-08 13:34:46211 auto i(scheme_iterator->second.find(host));
wjmacleanc62490492015-02-13 22:02:07212 if (i != scheme_iterator->second.end())
Christian Dullwebercc736c12017-09-04 09:27:50213 return i->second.level;
wjmacleanc62490492015-02-13 22:02:07214 }
215
Lei Zhang9d40e7902017-11-20 19:54:36216 return GetZoomLevelForHost(host);
[email protected]367c5c1d2013-03-11 18:59:02217}
218
Mark Schillaci6fd675e2023-03-16 00:02:35219#if BUILDFLAG(IS_ANDROID)
Aishwarya Rajeshb56269c22024-01-25 18:34:08220double HostZoomMapImpl::GetZoomLevelForHostAndSchemeAndroid(
Mark Schillaci6fd675e2023-03-16 00:02:35221 const std::string& scheme,
Aishwarya Rajeshb56269c22024-01-25 18:34:08222 const std::string& host) {
Mark Schillaci6fd675e2023-03-16 00:02:35223 double zoom_level = GetZoomLevelForHostAndScheme(scheme, host);
224
Mark Schillaci6fd675e2023-03-16 00:02:35225 // On Android, we will use a zoom level that considers the current OS-level
Aishwarya Rajeshb56269c22024-01-25 18:34:08226 // setting. For this we pass the given |level| through JNI to the Java-side
227 // code, which can access the Android configuration and |fontScale|. This
228 // method will return the adjusted zoom level considering OS settings. Note
229 // that the OS |fontScale| will be factored in only when the Page Zoom feature
230 // is enabled.
Andrew Grievef46caa512024-05-23 16:59:36231 JNIEnv* env = jni_zero::AttachCurrentThread();
Aishwarya Rajeshb56269c22024-01-25 18:34:08232 double adjusted_zoom_level =
233 Java_HostZoomMapImpl_getAdjustedZoomLevel(env, zoom_level);
Mark Schillaci6fd675e2023-03-16 00:02:35234 return adjusted_zoom_level;
235}
236#endif
237
Lucas Furukawa Gadani4b4eed02019-06-04 23:12:04238HostZoomMap::ZoomLevelVector HostZoomMapImpl::GetAllZoomLevels() {
Lei Zhang9d40e7902017-11-20 19:54:36239 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]0f374052014-03-18 20:37:22240 HostZoomMap::ZoomLevelVector result;
Lei Zhang9d40e7902017-11-20 19:54:36241 result.reserve(host_zoom_levels_.size() + scheme_host_zoom_levels_.size());
242 for (const auto& entry : host_zoom_levels_) {
243 ZoomLevelChange change = {
244 HostZoomMap::ZOOM_CHANGED_FOR_HOST,
245 entry.first, // host
246 std::string(), // scheme
247 entry.second.level, // zoom level
248 entry.second.last_modified // last modified
249 };
250 result.push_back(change);
251 }
252 for (const auto& scheme_entry : scheme_host_zoom_levels_) {
253 const std::string& scheme = scheme_entry.first;
254 const HostZoomLevels& host_zoom_levels = scheme_entry.second;
255 for (const auto& entry : host_zoom_levels) {
Christian Dullwebercc736c12017-09-04 09:27:50256 ZoomLevelChange change = {
Lei Zhang9d40e7902017-11-20 19:54:36257 HostZoomMap::ZOOM_CHANGED_FOR_SCHEME_AND_HOST,
Christian Dullwebercc736c12017-09-04 09:27:50258 entry.first, // host
Lei Zhang9d40e7902017-11-20 19:54:36259 scheme, // scheme
Christian Dullwebercc736c12017-09-04 09:27:50260 entry.second.level, // zoom level
261 entry.second.last_modified // last modified
[email protected]0f374052014-03-18 20:37:22262 };
263 result.push_back(change);
264 }
[email protected]0f374052014-03-18 20:37:22265 }
266 return result;
267}
268
[email protected]367c5c1d2013-03-11 18:59:02269void HostZoomMapImpl::SetZoomLevelForHost(const std::string& host,
270 double level) {
Lei Zhang9d40e7902017-11-20 19:54:36271 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Christian Dullweberb7c59482018-01-29 11:25:01272 base::Time last_modified = clock_->Now();
Christian Dullwebercc736c12017-09-04 09:27:50273 SetZoomLevelForHostInternal(host, level, last_modified);
274}
275
276void HostZoomMapImpl::InitializeZoomLevelForHost(const std::string& host,
277 double level,
278 base::Time last_modified) {
Lei Zhang9d40e7902017-11-20 19:54:36279 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Christian Dullwebercc736c12017-09-04 09:27:50280 SetZoomLevelForHostInternal(host, level, last_modified);
281}
282
283void HostZoomMapImpl::SetZoomLevelForHostInternal(const std::string& host,
284 double level,
285 base::Time last_modified) {
mostynb4c27d042015-03-18 21:47:47286 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]3ef4bc632010-04-09 04:25:31287
Stefan Zager036a35c2024-06-13 20:53:34288 if (blink::ZoomValuesEqual(level, default_zoom_level_)) {
Lei Zhang9d40e7902017-11-20 19:54:36289 host_zoom_levels_.erase(host);
290 } else {
291 ZoomLevel& zoomLevel = host_zoom_levels_[host];
292 zoomLevel.level = level;
293 zoomLevel.last_modified = last_modified;
[email protected]40bd6582009-12-04 23:49:51294 }
295
[email protected]d42bf472014-06-14 01:49:38296 // TODO(wjmaclean) Should we use a GURL here? crbug.com/384486
akabac6bd1212018-06-25 20:10:48297 SendZoomLevelChange(std::string(), host);
[email protected]d42bf472014-06-14 01:49:38298
[email protected]367c5c1d2013-03-11 18:59:02299 HostZoomMap::ZoomLevelChange change;
300 change.mode = HostZoomMap::ZOOM_CHANGED_FOR_HOST;
301 change.host = host;
302 change.zoom_level = level;
Christian Dullwebercc736c12017-09-04 09:27:50303 change.last_modified = last_modified;
[email protected]367c5c1d2013-03-11 18:59:02304
[email protected]117832812013-10-02 07:06:02305 zoom_level_changed_callbacks_.Notify(change);
[email protected]367c5c1d2013-03-11 18:59:02306}
307
308void HostZoomMapImpl::SetZoomLevelForHostAndScheme(const std::string& scheme,
309 const std::string& host,
310 double level) {
mostynb4c27d042015-03-18 21:47:47311 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Lei Zhang9d40e7902017-11-20 19:54:36312 // No last_modified timestamp for scheme and host because they are
313 // not persistet and are used for special cases only.
314 scheme_host_zoom_levels_[scheme][host].level = level;
[email protected]367c5c1d2013-03-11 18:59:02315
akabac6bd1212018-06-25 20:10:48316 SendZoomLevelChange(scheme, host);
[email protected]4e2a25a2012-01-27 00:42:08317
[email protected]367c5c1d2013-03-11 18:59:02318 HostZoomMap::ZoomLevelChange change;
319 change.mode = HostZoomMap::ZOOM_CHANGED_FOR_SCHEME_AND_HOST;
320 change.host = host;
321 change.scheme = scheme;
322 change.zoom_level = level;
Christian Dullwebercc736c12017-09-04 09:27:50323 change.last_modified = base::Time();
[email protected]367c5c1d2013-03-11 18:59:02324
[email protected]117832812013-10-02 07:06:02325 zoom_level_changed_callbacks_.Notify(change);
[email protected]40bd6582009-12-04 23:49:51326}
327
Lucas Furukawa Gadani4b4eed02019-06-04 23:12:04328double HostZoomMapImpl::GetDefaultZoomLevel() {
mostynb4c27d042015-03-18 21:47:47329 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]5c9250872012-01-30 17:24:05330 return default_zoom_level_;
331}
332
W. James MacLean37af605e2025-01-20 16:59:38333void HostZoomMapImpl::SetDefaultZoomLevelInternal(double level,
334 WebContentsImpl* web_contents,
335 RenderFrameHostImpl* rfh) {
W. James MacLean37af605e2025-01-20 16:59:38336 std::string host;
337 std::string scheme;
338
W. James MacLean817a05e2025-02-18 15:51:15339 // Get the url from the RenderFrameHost directly, as calling
340 // WebContentsImpl::GetLastCommittedURL() may give us a virtual url that
341 // is different than the one stored in the map.
342 GURL url = GetURLForRenderFrameHostPtr(rfh);
W. James MacLean37af605e2025-01-20 16:59:38343 // It is possible for a WebContent's zoom level to be queried before
W. James MacLean817a05e2025-02-18 15:51:15344 // a navigation has occurred, in which case `url` will be empty.
345 scheme = url.scheme();
346 host = net::GetHostOrSpecFromURL(url);
W. James MacLean37af605e2025-01-20 16:59:38347
348 bool uses_default_zoom = !HasZoomLevel(scheme, host) &&
349 !UsesTemporaryZoomLevel(rfh->GetGlobalId());
350
351 if (uses_default_zoom) {
352 web_contents->UpdateZoom(rfh->GetGlobalId());
353
354 HostZoomMap::ZoomLevelChange change;
355 change.mode = HostZoomMap::ZOOM_CHANGED_FOR_HOST;
356 change.host = host;
357 change.zoom_level = level;
358
359 zoom_level_changed_callbacks_.Notify(change);
360 }
361}
362
[email protected]5c9250872012-01-30 17:24:05363void HostZoomMapImpl::SetDefaultZoomLevel(double level) {
mostynb4c27d042015-03-18 21:47:47364 DCHECK_CURRENTLY_ON(BrowserThread::UI);
wjmaclean64951902016-04-29 20:59:12365
Stefan Zager036a35c2024-06-13 20:53:34366 if (blink::ZoomValuesEqual(level, default_zoom_level_)) {
danakj938b37a62019-09-24 18:35:54367 return;
Stefan Zager036a35c2024-06-13 20:53:34368 }
wjmaclean64951902016-04-29 20:59:12369
[email protected]5c9250872012-01-30 17:24:05370 default_zoom_level_ = level;
wjmaclean64951902016-04-29 20:59:12371
372 // First, remove all entries that match the new default zoom level.
Lei Zhang9d40e7902017-11-20 19:54:36373 for (auto it = host_zoom_levels_.begin(); it != host_zoom_levels_.end();) {
Stefan Zager036a35c2024-06-13 20:53:34374 if (blink::ZoomValuesEqual(it->second.level, default_zoom_level_)) {
Lei Zhang9d40e7902017-11-20 19:54:36375 it = host_zoom_levels_.erase(it);
Stefan Zager036a35c2024-06-13 20:53:34376 } else {
Lei Zhang9d40e7902017-11-20 19:54:36377 it++;
Stefan Zager036a35c2024-06-13 20:53:34378 }
wjmaclean64951902016-04-29 20:59:12379 }
380
381 // Second, update zoom levels for all pages that do not have an overriding
382 // entry.
vmpstr10e0d5f2016-07-21 23:46:09383 for (auto* web_contents : WebContentsImpl::GetAllWebContents()) {
wjmaclean64951902016-04-29 20:59:12384 // Only change zoom for WebContents tied to the StoragePartition this
385 // HostZoomMap serves.
386 if (GetForWebContents(web_contents) != this)
387 continue;
388
W. James MacLean37af605e2025-01-20 16:59:38389 SetDefaultZoomLevelInternal(level, web_contents,
390 web_contents->GetPrimaryMainFrame());
391 }
wjmaclean64951902016-04-29 20:59:12392
W. James MacLeanf562b922025-03-13 15:36:19393 // If independent subframe zoom is enabled, then update zoom levels for
394 // subframes that do not have an overriding entry.
395 if (!IsIndependentSubframeZoomEnabled()) {
W. James MacLean37af605e2025-01-20 16:59:38396 return;
397 }
398 for (auto ftn_id : independent_zoom_frame_tree_nodes_) {
399 auto* rfh = FrameTreeNode::GloballyFindByID(ftn_id)->current_frame_host();
400 // `rfh` should be non-null here since, if it was deleted, then
401 // WebContentsObserver::FrameDeleted will have notified any ZoomControllers,
402 // and `independent_zoom_frame_tree_nodes_` will have been updated
403 // accordingly.
404 if (!UsesTemporaryZoomLevel(rfh->GetGlobalId())) {
405 auto* web_contents = WebContentsImpl::FromRenderFrameHostImpl(rfh);
406 if (web_contents && (rfh != web_contents->GetPrimaryMainFrame())) {
407 SetDefaultZoomLevelInternal(level, web_contents, rfh);
408 }
wjmaclean64951902016-04-29 20:59:12409 }
410 }
[email protected]5c9250872012-01-30 17:24:05411}
412
Peter Kasting7ba9440c2020-11-22 01:49:02413base::CallbackListSubscription HostZoomMapImpl::AddZoomLevelChangedCallback(
danakj6aa13ea2019-12-10 14:53:26414 ZoomLevelChangedCallback callback) {
Lei Zhang9d40e7902017-11-20 19:54:36415 DCHECK_CURRENTLY_ON(BrowserThread::UI);
danakj6aa13ea2019-12-10 14:53:26416 return zoom_level_changed_callbacks_.Add(std::move(callback));
[email protected]89c9aca2013-02-07 15:08:42417}
418
[email protected]fce823222014-05-30 16:24:30419double HostZoomMapImpl::GetZoomLevelForWebContents(
Lucas Furukawa Gadani4b4eed02019-06-04 23:12:04420 WebContentsImpl* web_contents_impl) {
W. James MacLean37af605e2025-01-20 16:59:38421 return GetZoomLevelForWebContents(
422 web_contents_impl,
423 web_contents_impl->GetPrimaryMainFrame()->GetGlobalId());
424}
425
426double HostZoomMapImpl::GetZoomLevelForWebContents(
427 WebContentsImpl* web_contents_impl,
428 GlobalRenderFrameHostId rfh_id) {
Lei Zhang9d40e7902017-11-20 19:54:36429 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]fce823222014-05-30 16:24:30430
Miyoung Shindae09862022-11-02 01:27:37431 if (UsesTemporaryZoomLevel(rfh_id))
432 return GetTemporaryZoomLevel(rfh_id);
[email protected]fce823222014-05-30 16:24:30433
W. James MacLean817a05e2025-02-18 15:51:15434 GURL url = GetURLForRenderFrameHost(rfh_id);
Mark Schillacicddfa172022-07-28 19:57:13435
Mark Schillacicddfa172022-07-28 19:57:13436#if BUILDFLAG(IS_ANDROID)
Aishwarya Rajeshb56269c22024-01-25 18:34:08437 return GetZoomLevelForHostAndSchemeAndroid(url.scheme(),
438 net::GetHostOrSpecFromURL(url));
Mark Schillacicddfa172022-07-28 19:57:13439#else
Mark Schillaci6fd675e2023-03-16 00:02:35440 return GetZoomLevelForHostAndScheme(url.scheme(),
441 net::GetHostOrSpecFromURL(url));
Mark Schillacicddfa172022-07-28 19:57:13442#endif
[email protected]fce823222014-05-30 16:24:30443}
444
445void HostZoomMapImpl::SetZoomLevelForWebContents(
Lucas Furukawa Gadanie1c5dfda2018-11-29 17:57:41446 WebContentsImpl* web_contents_impl,
W. James MacLean37af605e2025-01-20 16:59:38447 GlobalRenderFrameHostId rfh_id,
[email protected]fce823222014-05-30 16:24:30448 double level) {
Lei Zhang9d40e7902017-11-20 19:54:36449 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Miyoung Shindae09862022-11-02 01:27:37450
Miyoung Shindae09862022-11-02 01:27:37451 if (UsesTemporaryZoomLevel(rfh_id)) {
452 SetTemporaryZoomLevel(rfh_id, level);
[email protected]fce823222014-05-30 16:24:30453 } else {
W. James MacLean817a05e2025-02-18 15:51:15454 GURL url = GetURLForRenderFrameHost(rfh_id);
[email protected]acda0ef32014-06-05 23:13:30455 SetZoomLevelForHost(net::GetHostOrSpecFromURL(url), level);
[email protected]fce823222014-05-30 16:24:30456 }
457}
458
Miyoung Shindae09862022-11-02 01:27:37459bool HostZoomMapImpl::UsesTemporaryZoomLevel(
460 const GlobalRenderFrameHostId& rfh_id) {
Lei Zhang9d40e7902017-11-20 19:54:36461 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Miyoung Shindae09862022-11-02 01:27:37462 return base::Contains(temporary_zoom_levels_, rfh_id);
[email protected]fce823222014-05-30 16:24:30463}
464
Miyoung Shindae09862022-11-02 01:27:37465void HostZoomMapImpl::SetNoLongerUsesTemporaryZoomLevel(
466 const GlobalRenderFrameHostId& rfh_id) {
Mark Schillacicddfa172022-07-28 19:57:13467 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Miyoung Shindae09862022-11-02 01:27:37468 temporary_zoom_levels_.erase(rfh_id);
Mark Schillacicddfa172022-07-28 19:57:13469}
470
Miyoung Shindae09862022-11-02 01:27:37471double HostZoomMapImpl::GetTemporaryZoomLevel(
472 const GlobalRenderFrameHostId& rfh_id) const {
Lei Zhang9d40e7902017-11-20 19:54:36473 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Miyoung Shindae09862022-11-02 01:27:37474 const auto it = temporary_zoom_levels_.find(rfh_id);
475
Lei Zhang9d40e7902017-11-20 19:54:36476 return it != temporary_zoom_levels_.end() ? it->second : 0;
[email protected]b75b8292010-10-01 07:28:25477}
478
Miyoung Shindae09862022-11-02 01:27:37479void HostZoomMapImpl::SetTemporaryZoomLevel(
480 const GlobalRenderFrameHostId& rfh_id,
481 double level) {
mostynb4c27d042015-03-18 21:47:47482 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]b75b8292010-10-01 07:28:25483
Miyoung Shindae09862022-11-02 01:27:37484 RenderFrameHostImpl* rfh = RenderFrameHostImpl::FromID(rfh_id);
W. James MacLeanf562b922025-03-13 15:36:19485 if (IsIndependentSubframeZoomEnabled()) {
W. James MacLean37af605e2025-01-20 16:59:38486 CHECK(rfh->is_local_root());
487 } else {
488 DCHECK(rfh == rfh->GetOutermostMainFrame());
489 }
[email protected]b75b8292010-10-01 07:28:25490
Miyoung Shindae09862022-11-02 01:27:37491 temporary_zoom_levels_[rfh_id] = level;
492
493 WebContentsImpl* web_contents = WebContentsImpl::FromRenderFrameHostImpl(rfh);
W. James MacLean37af605e2025-01-20 16:59:38494 web_contents->UpdateZoom(rfh_id);
[email protected]d42bf472014-06-14 01:49:38495
[email protected]367c5c1d2013-03-11 18:59:02496 HostZoomMap::ZoomLevelChange change;
497 change.mode = HostZoomMap::ZOOM_CHANGED_TEMPORARY_ZOOM;
Miyoung Shindae09862022-11-02 01:27:37498 change.host = GetHostFromProcessFrame(rfh);
[email protected]367c5c1d2013-03-11 18:59:02499 change.zoom_level = level;
500
[email protected]117832812013-10-02 07:06:02501 zoom_level_changed_callbacks_.Notify(change);
[email protected]b75b8292010-10-01 07:28:25502}
503
Christian Dullwebercc736c12017-09-04 09:27:50504void HostZoomMapImpl::ClearZoomLevels(base::Time delete_begin,
505 base::Time delete_end) {
Lei Zhang9d40e7902017-11-20 19:54:36506 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Christian Dullwebercc736c12017-09-04 09:27:50507 double default_zoom_level = GetDefaultZoomLevel();
Lei Zhang9d40e7902017-11-20 19:54:36508 for (const auto& zoom_level : GetAllZoomLevels()) {
Christian Dullwebercc736c12017-09-04 09:27:50509 if (zoom_level.scheme.empty() && delete_begin <= zoom_level.last_modified &&
510 (delete_end.is_null() || zoom_level.last_modified < delete_end)) {
511 SetZoomLevelForHost(zoom_level.host, default_zoom_level);
512 }
513 }
514}
515
Miyoung Shindae09862022-11-02 01:27:37516void HostZoomMapImpl::ClearTemporaryZoomLevel(
517 const GlobalRenderFrameHostId& rfh_id) {
Lei Zhang9d40e7902017-11-20 19:54:36518 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Miyoung Shindae09862022-11-02 01:27:37519 auto it = temporary_zoom_levels_.find(rfh_id);
Lei Zhang9d40e7902017-11-20 19:54:36520 if (it == temporary_zoom_levels_.end())
521 return;
522
523 temporary_zoom_levels_.erase(it);
Miyoung Shindae09862022-11-02 01:27:37524 WebContentsImpl* web_contents = WebContentsImpl::FromRenderFrameHostImpl(
525 RenderFrameHostImpl::FromID(rfh_id));
W. James MacLean37af605e2025-01-20 16:59:38526 web_contents->UpdateZoom(rfh_id);
[email protected]d42bf472014-06-14 01:49:38527}
528
529void HostZoomMapImpl::SendZoomLevelChange(const std::string& scheme,
akabac6bd1212018-06-25 20:10:48530 const std::string& host) {
Lei Zhang9d40e7902017-11-20 19:54:36531 DCHECK_CURRENTLY_ON(BrowserThread::UI);
wjmaclean64951902016-04-29 20:59:12532 // We'll only send to WebContents not using temporary zoom levels. The one
533 // other case of interest is where the renderer is hosting a plugin document;
534 // that should be reflected in our temporary zoom level map, but we will
535 // double check on the renderer side to avoid the possibility of any races.
vmpstr10e0d5f2016-07-21 23:46:09536 for (auto* web_contents : WebContentsImpl::GetAllWebContents()) {
wjmaclean64951902016-04-29 20:59:12537 // Only send zoom level changes to WebContents that are using this
538 // HostZoomMap.
539 if (GetForWebContents(web_contents) != this)
540 continue;
541
Miyoung Shindae09862022-11-02 01:27:37542 if (!UsesTemporaryZoomLevel(
543 web_contents->GetPrimaryMainFrame()->GetGlobalId())) {
akabac6bd1212018-06-25 20:10:48544 web_contents->UpdateZoomIfNecessary(scheme, host);
Miyoung Shindae09862022-11-02 01:27:37545 }
[email protected]d42bf472014-06-14 01:49:38546 }
W. James MacLean37af605e2025-01-20 16:59:38547
548 // Also loop over the independently-zoomed FTNs that aren't primary
W. James MacLeanf562b922025-03-13 15:36:19549 // mainframes. If independent subframe zoom isn't enabled, then there will be
550 // no such frames, so early-out in that case.
551 if (!IsIndependentSubframeZoomEnabled()) {
W. James MacLean37af605e2025-01-20 16:59:38552 return;
553 }
554 for (auto ftn_id : independent_zoom_frame_tree_nodes_) {
555 auto* rfh = FrameTreeNode::GloballyFindByID(ftn_id)->current_frame_host();
556 if (!UsesTemporaryZoomLevel(rfh->GetGlobalId())) {
557 auto* web_contents = WebContentsImpl::FromRenderFrameHostImpl(rfh);
558 if (web_contents && (rfh != web_contents->GetPrimaryMainFrame())) {
559 web_contents->UpdateZoomIfNecessary(scheme, host, rfh);
560 }
561 }
562 }
[email protected]d42bf472014-06-14 01:49:38563}
564
wjmacleande29ed52014-10-28 21:09:06565void HostZoomMapImpl::SendErrorPageZoomLevelRefresh() {
Lei Zhang9d40e7902017-11-20 19:54:36566 DCHECK_CURRENTLY_ON(BrowserThread::UI);
wjmacleande29ed52014-10-28 21:09:06567 GURL error_url(kUnreachableWebDataURL);
568 std::string host = net::GetHostOrSpecFromURL(error_url);
wjmacleande29ed52014-10-28 21:09:06569
akabac6bd1212018-06-25 20:10:48570 SendZoomLevelChange(std::string(), host);
wjmacleande29ed52014-10-28 21:09:06571}
572
[email protected]5c9250872012-01-30 17:24:05573HostZoomMapImpl::~HostZoomMapImpl() {
mostynb4c27d042015-03-18 21:47:47574 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]40bd6582009-12-04 23:49:51575}
[email protected]46488322012-10-30 03:22:20576
tzik67025f672017-11-29 05:04:44577void HostZoomMapImpl::SetClockForTesting(base::Clock* clock) {
578 clock_ = clock;
Christian Dullwebercc736c12017-09-04 09:27:50579}
580
Xiaohan Wang1ecfd002022-01-19 22:33:10581#if BUILDFLAG(IS_ANDROID)
Mark Schillaci6fd675e2023-03-16 00:02:35582void HostZoomMapImpl::SetSystemFontScaleForTesting(float scale) {
Andrew Grievef46caa512024-05-23 16:59:36583 JNIEnv* env = jni_zero::AttachCurrentThread();
Mark Schillaci6fd675e2023-03-16 00:02:35584 Java_HostZoomMapImpl_setSystemFontScaleForTesting(env, scale); // IN-TEST
585}
586
Mark Schillaci7f43c6692024-10-31 17:52:26587void HostZoomMapImpl::SetShouldAdjustForOSLevelForTesting(
588 bool shouldAdjustForOSLevel) {
589 JNIEnv* env = jni_zero::AttachCurrentThread();
590 Java_HostZoomMapImpl_setShouldAdjustForOSLevelForTesting(
591 env, shouldAdjustForOSLevel); // IN-TEST
592}
593
Mark Schillaci8ff97492022-07-25 23:25:08594void HostZoomMapImpl::SetDefaultZoomLevelPrefCallback(
595 HostZoomMap::DefaultZoomChangedCallback callback) {
596 default_zoom_level_pref_callback_ = std::move(callback);
597}
598
599HostZoomMap::DefaultZoomChangedCallback*
600HostZoomMapImpl::GetDefaultZoomLevelPrefCallback() {
601 return &default_zoom_level_pref_callback_;
602}
603
Mark Schillaci1363e4a2021-10-04 19:10:09604void JNI_HostZoomMapImpl_SetZoomLevel(
605 JNIEnv* env,
606 const base::android::JavaParamRef<jobject>& j_web_contents,
Mark Schillacicddfa172022-07-28 19:57:13607 jdouble new_zoom_level,
608 jdouble adjusted_zoom_level) {
Mark Schillaci1363e4a2021-10-04 19:10:09609 WebContents* web_contents = WebContents::FromJavaWebContents(j_web_contents);
610 DCHECK(web_contents);
611
Miyoung Shindae09862022-11-02 01:27:37612 GlobalRenderFrameHostId rfh_id =
613 web_contents->GetPrimaryMainFrame()->GetGlobalId();
Mark Schillacicddfa172022-07-28 19:57:13614
615 // We want to set and save the new zoom level, but we want to actually render
616 // the adjusted level.
Mark Schillaci1363e4a2021-10-04 19:10:09617 HostZoomMap::SetZoomLevel(web_contents, new_zoom_level);
Mark Schillacicddfa172022-07-28 19:57:13618
619 HostZoomMapImpl* host_zoom_map = static_cast<HostZoomMapImpl*>(
620 HostZoomMap::GetForWebContents(web_contents));
Miyoung Shindae09862022-11-02 01:27:37621 host_zoom_map->SetTemporaryZoomLevel(rfh_id, adjusted_zoom_level);
Mark Schillacicddfa172022-07-28 19:57:13622
623 // We must now remove this webcontents from the list of temporary zoom levels,
624 // this is so that any future request will continue to update the underlying
625 // host/scheme save, and will not be perceived as "temporary".
626 // i.e. once temporary is set for a web_contents, the call to
627 // SetZoomLevelForWebContents will keep updating what is rendered, but will no
628 // longer call SetZoomLevelForHost, which saves the choice for that host.
Miyoung Shindae09862022-11-02 01:27:37629 host_zoom_map->SetNoLongerUsesTemporaryZoomLevel(rfh_id);
Mark Schillaci1363e4a2021-10-04 19:10:09630}
631
Aashna Shethebb96ad2023-08-25 21:13:50632void JNI_HostZoomMapImpl_SetZoomLevelForHost(
633 JNIEnv* env,
634 const base::android::JavaParamRef<jobject>& j_context,
635 const base::android::JavaParamRef<jstring>& j_host,
636 jdouble level) {
637 DCHECK_CURRENTLY_ON(BrowserThread::UI);
638
639 BrowserContext* context = BrowserContextFromJavaHandle(j_context);
640 if (!context) {
641 return;
642 }
643
644 HostZoomMap* host_zoom_map =
645 HostZoomMap::GetDefaultForBrowserContext(context);
646
647 std::string host(base::android::ConvertJavaStringToUTF8(env, j_host));
648 host_zoom_map->SetZoomLevelForHost(host, level);
649}
650
Mark Schillaci1363e4a2021-10-04 19:10:09651jdouble JNI_HostZoomMapImpl_GetZoomLevel(
652 JNIEnv* env,
653 const base::android::JavaParamRef<jobject>& j_web_contents) {
654 WebContents* web_contents = WebContents::FromJavaWebContents(j_web_contents);
655 DCHECK(web_contents);
656
657 return HostZoomMap::GetZoomLevel(web_contents);
658}
Mark Schillacic28765d2022-06-03 21:38:44659
660void JNI_HostZoomMapImpl_SetDefaultZoomLevel(
661 JNIEnv* env,
662 const base::android::JavaParamRef<jobject>& j_context,
663 jdouble new_default_zoom_level) {
664 DCHECK_CURRENTLY_ON(BrowserThread::UI);
665 BrowserContext* context = BrowserContextFromJavaHandle(j_context);
666 if (!context)
667 return;
668
669 HostZoomMapImpl* host_zoom_map = static_cast<HostZoomMapImpl*>(
670 HostZoomMap::GetDefaultForBrowserContext(context));
Mark Schillaci8ff97492022-07-25 23:25:08671
672 // If a callback has been set (e.g. by chrome_zoom_level_prefs to store an
673 // updated value in Prefs), call this now with the chosen zoom level.
674 if (host_zoom_map->GetDefaultZoomLevelPrefCallback()) {
675 host_zoom_map->GetDefaultZoomLevelPrefCallback()->Run(
676 new_default_zoom_level);
677 }
678
679 // Update the default zoom level for existing tabs. This must be done after
680 // the Pref is updated due to guard clause in chrome_zoom_level_prefs.
Mark Schillacic28765d2022-06-03 21:38:44681 host_zoom_map->SetDefaultZoomLevel(new_default_zoom_level);
682}
683
684jdouble JNI_HostZoomMapImpl_GetDefaultZoomLevel(
685 JNIEnv* env,
686 const base::android::JavaParamRef<jobject>& j_context) {
687 DCHECK_CURRENTLY_ON(BrowserThread::UI);
688 BrowserContext* context = BrowserContextFromJavaHandle(j_context);
689 if (!context)
690 return 0.0;
691
692 HostZoomMapImpl* host_zoom_map = static_cast<HostZoomMapImpl*>(
693 HostZoomMap::GetDefaultForBrowserContext(context));
694 return host_zoom_map->GetDefaultZoomLevel();
695}
Aishwarya Rajesh39ef1c62022-11-09 06:25:37696
Andrew Grievef46caa512024-05-23 16:59:36697std::vector<jni_zero::ScopedJavaLocalRef<jobject>>
Andrew Grieve6a51bed2024-03-11 17:37:48698JNI_HostZoomMapImpl_GetAllHostZoomLevels(
Aashna Shethebb96ad2023-08-25 21:13:50699 JNIEnv* env,
700 const base::android::JavaParamRef<jobject>& j_context) {
701 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Andrew Grievef46caa512024-05-23 16:59:36702 std::vector<jni_zero::ScopedJavaLocalRef<jobject>> ret;
Aashna Shethebb96ad2023-08-25 21:13:50703
704 // Get instance of HostZoomMap.
705 BrowserContext* context = BrowserContextFromJavaHandle(j_context);
706 if (!context) {
Andrew Grieve6a51bed2024-03-11 17:37:48707 return ret;
Aashna Shethebb96ad2023-08-25 21:13:50708 }
709
710 HostZoomMap* host_zoom_map =
711 HostZoomMap::GetDefaultForBrowserContext(context);
712
713 // Convert C++ vector of structs to vector of objects.
Aashna Shethebb96ad2023-08-25 21:13:50714 for (const auto& entry : host_zoom_map->GetAllZoomLevels()) {
715 switch (entry.mode) {
716 case HostZoomMap::ZOOM_CHANGED_FOR_HOST: {
Andrew Grieve6a51bed2024-03-11 17:37:48717 ret.push_back(Java_HostZoomMapImpl_buildSiteZoomInfo(env, entry.host,
718 entry.zoom_level));
Aashna Shethebb96ad2023-08-25 21:13:50719 break;
720 }
721 case HostZoomMap::ZOOM_CHANGED_FOR_SCHEME_AND_HOST:
Peter Boströmfc7ddc182024-10-31 19:37:21722 NOTREACHED();
Aashna Shethebb96ad2023-08-25 21:13:50723 case HostZoomMap::ZOOM_CHANGED_TEMPORARY_ZOOM:
Peter Boströmfc7ddc182024-10-31 19:37:21724 NOTREACHED();
Aashna Shethebb96ad2023-08-25 21:13:50725 }
726 }
727
Andrew Grieve6a51bed2024-03-11 17:37:48728 return ret;
Aashna Shethebb96ad2023-08-25 21:13:50729}
Mark Schillaci1363e4a2021-10-04 19:10:09730#endif
731
kenod3fe1c222023-12-13 19:58:50732double HostZoomMapImpl::GetZoomLevelForPreviewAndHost(const std::string& host) {
733 const auto it = host_zoom_levels_for_preview_.find(host);
734 return it != host_zoom_levels_for_preview_.end() ? it->second.level
735 : default_zoom_level_;
736}
737
738void HostZoomMapImpl::SetZoomLevelForPreviewAndHost(const std::string& host,
739 double level) {
Stefan Zager036a35c2024-06-13 20:53:34740 if (blink::ZoomValuesEqual(level, default_zoom_level_)) {
kenod3fe1c222023-12-13 19:58:50741 host_zoom_levels_for_preview_.erase(host);
742 } else {
743 ZoomLevel& zoomLevel = host_zoom_levels_for_preview_[host];
744 zoomLevel.level = level;
745 zoomLevel.last_modified = clock_->Now();
746 }
747}
748
W. James MacLean37af605e2025-01-20 16:59:38749void HostZoomMapImpl::SetIndependentZoomForFrameTreeNode(
750 WebContents* web_contents,
751 FrameTreeNodeId ftn_id) {
752 CHECK(web_contents);
W. James MacLeanf562b922025-03-13 15:36:19753 auto* rfh = static_cast<RenderFrameHostImpl*>(
754 web_contents->UnsafeFindFrameByFrameTreeNodeId(ftn_id));
755 CHECK(rfh->is_local_root());
W. James MacLean37af605e2025-01-20 16:59:38756 independent_zoom_frame_tree_nodes_.insert(ftn_id);
W. James MacLeanf562b922025-03-13 15:36:19757
758 // Force an update in case the `rfh` contains content with a different zoom.
759 static_cast<WebContentsImpl*>(web_contents)->UpdateZoom(rfh->GetGlobalId());
W. James MacLean37af605e2025-01-20 16:59:38760}
761
762void HostZoomMapImpl::ClearIndependentZoomForFrameTreeNode(
763 FrameTreeNodeId ftn_id) {
764 independent_zoom_frame_tree_nodes_.erase(ftn_id);
765}
766
W. James MacLeanf562b922025-03-13 15:36:19767bool HostZoomMapImpl::IsIndependentZoomFrameTreeNode(
768 FrameTreeNodeId ftn_id) const {
769 return independent_zoom_frame_tree_nodes_.contains(ftn_id);
770}
771
Kevin McNee3183a7792021-11-09 21:03:36772} // namespace content