* chore: bump chromium in DEPS to 142.0.7429.0 * chore: bump chromium in DEPS to 142.0.7430.0 * 6954508: Reland Migrate WrappableWithNamedPropertyInterceptor to gin::Wrappable | https://chromium-review.googlesource.com/c/chromium/src/+/6954508 * https://chromium-review.googlesource.com/c/chromium/src/+/6955633 * 5584820: Fix font face resolution when renderer is blocked | https://chromium-review.googlesource.com/c/chromium/src/+/5584820 * chore: export patches * chore: remove patch that keeley says is ok to remove in comments * chore: bump chromium in DEPS to 142.0.7432.0 * chore: export patches * chore: bump chromium in DEPS to 142.0.7434.0 * 6973697: Use type tags for data stored in V8 internal fields | https://chromium-review.googlesource.com/c/chromium/src/+/6973697 * 6976272: Revert Reland mac: click through content area in main window | https://chromium-review.googlesource.com/c/chromium/src/+/6976272 * chore: export patches * 6938086: Rename native_widget_types.h -> native_ui_types.h | https://chromium-review.googlesource.com/c/chromium/src/+/6938086 * 6951252: Correct PersistentCache backed code cache context grouping * chore: bump chromium in DEPS to 142.0.7436.0 * 6981628: Reland Use unordered_map in AcceleratorMap | https://chromium-review.googlesource.com/c/chromium/src/+/6981628 * chore: export patches * chore: resolve patch conflict with main * chore: merge conflict with main * chore: bump chromium in DEPS to 142.0.7438.0 * chore: bump chromium in DEPS to 142.0.7440.0 * chore: bump chromium in DEPS to 142.0.7442.0 * chore: bump chromium in DEPS to 142.0.7444.0 * chore: bump chromium in DEPS to 143.0.7445.0 * chore: bump chromium in DEPS to 143.0.7447.0 * chore: bump chromium in DEPS to 143.0.7449.0 * chore: bump chromium in DEPS to 143.0.7451.0 * 7001364: Migrate GURL accessors to Get* variants in //content | https://chromium-review.googlesource.com/c/chromium/src/+/7001364 * 6986521: Implicit second value 'any' instead of 'span-all' for fallback query | https://chromium-review.googlesource.com/c/chromium/src/+/6986521 * chore: update chromium patches * chore: update chromium patches * chore: update patches * fix: parse macOS SDK version across line break https://chromium-review.googlesource.com/c/chromium/src/+/6980166 * fix: replace v8::Object::SetPrototype() usage https://chromium-review.googlesource.com/c/v8/v8/+/6983465 https://github.com/nodejs/node/pull/55453 * fix: regenerate filenames.libcxx.gni https://chromium-review.googlesource.com/c/chromium/src/+/6980307 * fix: replace additional usages of SetPrototype https://chromium-review.googlesource.com/c/v8/v8/+/6983465 * build: use macos 15 minimum https://chromium-review.googlesource.com/c/chromium/src/+/6980166 * ci: ignore missing dir for strip_universal_deep * fix: js2c compilation failure https://chromium-review.googlesource.com/c/chromium/src/+/6950738 See patch description explaining MacOS 26 SDK headers incompatibility. * fixup! chore: export patches * feat: add new memory-eviction exit reason https://chromium-review.googlesource.com/c/chromium/src/+/6991933 * fix: set JSON reader parsing options https://chromium-review.googlesource.com/c/chromium/src/+/6992114 * fix: provide DeviceEmulationCacheBehavior param https://chromium-review.googlesource.com/c/chromium/src/+/6965238 * fix: views::NonClientFrameView -> views::FrameView https://chromium-review.googlesource.com/c/chromium/src/+/7005027 https://chromium-review.googlesource.com/c/chromium/src/+/6966937 * fix: check new forced colors enum value https://chromium-review.googlesource.com/c/chromium/src/+/6944403 * fix: migrate NetworkConditions -> MatchedNetworkConditions https://chromium-review.googlesource.com/c/chromium/src/+/6827307 * fix: migrate GURL string methods to Get*() https://chromium-review.googlesource.com/c/chromium/src/+/7007010 * fix: disable C++ modules in electron_lib builds https://chromium-review.googlesource.com/c/chromium/src/+/6950738 * fix: partially revert is_headless_mode removal https://chromium-review.googlesource.com/c/chromium/src/+/6955633 This patch should likely be reworked. For now, this partially reverts the removal of a required class property to restore behavior. * Revert "build: use macos 15 minimum" This reverts commit 2fc12d6acc1b24f3cbd0adb03122bf6b21eb14b9. Initially this change was made to test if it fixes libcxx compilation issues. As that's now resolved by disabling libcxx modules, this can be reverted. * fix: disable C++ modules in libnode builds * fixup! fix: replace v8::Object::SetPrototype() usage https://chromium-review.googlesource.com/c/v8/v8/+/6983465 https://github.com/nodejs/node/pull/55453 * fixup! fix: replace v8::Object::SetPrototype() usage https://chromium-review.googlesource.com/c/v8/v8/+/6983465 https://github.com/nodejs/node/pull/55453 * build: switch to macos-15 runner build/mac/find_sdk.py now requires macOS 15 SDK as a minimum version. The macos 15 runners default to an Xcode using the 15 SDK and removes older versions. * fixup! fix: check new forced colors enum value https://chromium-review.googlesource.com/c/chromium/src/+/6944403 * fixup! fix: migrate GURL string methods to Get*() https://chromium-review.googlesource.com/c/chromium/src/+/7007010 * fix: use std::u16string for Extension::Create() error parameter https://chromium-review.googlesource.com/c/chromium/src/+/6975452 * fix: add missing image_skia include https://chromium-review.googlesource.com/c/chromium/src/+/6986762 * fixup! fix: add missing image_skia include https://chromium-review.googlesource.com/c/chromium/src/+/6986762 * fix: remove outdated V8 flag https://chromium-review.googlesource.com/c/v8/v8/+/6948286 * fix: disable protocol handler DCHECK https://chromium-review.googlesource.com/c/chromium/src/+/6727594 Ignore the extension custom protocol handler registry DCHECK until we invest in supporting it. Replacing this DCHECK seems harmless and will unblock the roll. * fix: replace deprecated usage of SetPrototype https://chromium-review.googlesource.com/c/v8/v8/+/6983465 * fixup! fix: migrate NetworkConditions -> MatchedNetworkConditions https://chromium-review.googlesource.com/c/chromium/src/+/6827307 * fixup! fix: migrate GURL string methods to Get*() https://chromium-review.googlesource.com/c/chromium/src/+/7007010 * chore: remove patch already included in roll * chore: remove extraneous formatting added to patch * chore: remove fix_harden_blink_scriptstate_maybefrom.patch https://chromium-review.googlesource.com/c/chromium/src/+/6973697 No longer needed since the above CL landed. * 6973697: Use type tags for data stored in V8 internal fields https://chromium-review.googlesource.com/c/chromium/src/+/6973697 * chore: update patches * fixup! chore: export patches * chore: restore electron embedder data tag patch --------- Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com> Co-authored-by: Alice Zhao <alicelovescake@anthropic.com> Co-authored-by: Keeley Hammond <vertedinde@electronjs.org> Co-authored-by: Samuel Maddock <smaddock@slack-corp.com> Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>
400 lines
15 KiB
C++
400 lines
15 KiB
C++
// Copyright (c) 2017 GitHub, Inc.
|
|
// Use of this source code is governed by the MIT license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "shell/browser/web_contents_zoom_controller.h"
|
|
|
|
#include <string>
|
|
|
|
#include "content/public/browser/browser_thread.h"
|
|
#include "content/public/browser/navigation_details.h"
|
|
#include "content/public/browser/navigation_entry.h"
|
|
#include "content/public/browser/navigation_handle.h"
|
|
#include "content/public/browser/render_frame_host.h"
|
|
#include "content/public/browser/render_process_host.h"
|
|
#include "content/public/browser/render_view_host.h"
|
|
#include "content/public/browser/web_contents.h"
|
|
#include "content/public/browser/web_contents_user_data.h"
|
|
#include "content/public/common/page_type.h"
|
|
#include "net/base/url_util.h"
|
|
#include "shell/browser/web_contents_zoom_observer.h"
|
|
#include "third_party/blink/public/common/page/page_zoom.h"
|
|
|
|
using content::BrowserThread;
|
|
|
|
namespace electron {
|
|
|
|
namespace {
|
|
|
|
const double kPageZoomEpsilon = 0.001;
|
|
|
|
} // namespace
|
|
|
|
WebContentsZoomController::WebContentsZoomController(
|
|
content::WebContents* web_contents)
|
|
: content::WebContentsObserver(web_contents),
|
|
content::WebContentsUserData<WebContentsZoomController>(*web_contents) {
|
|
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
host_zoom_map_ = content::HostZoomMap::GetForWebContents(web_contents);
|
|
zoom_level_ = host_zoom_map_->GetDefaultZoomLevel();
|
|
default_zoom_factor_ = kPageZoomEpsilon;
|
|
|
|
zoom_subscription_ = host_zoom_map_->AddZoomLevelChangedCallback(
|
|
base::BindRepeating(&WebContentsZoomController::OnZoomLevelChanged,
|
|
base::Unretained(this)));
|
|
|
|
UpdateState(std::string());
|
|
}
|
|
|
|
WebContentsZoomController::~WebContentsZoomController() {
|
|
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
observers_.Notify(&WebContentsZoomObserver::OnZoomControllerDestroyed, this);
|
|
}
|
|
|
|
void WebContentsZoomController::AddObserver(WebContentsZoomObserver* observer) {
|
|
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
observers_.AddObserver(observer);
|
|
}
|
|
|
|
void WebContentsZoomController::RemoveObserver(
|
|
WebContentsZoomObserver* observer) {
|
|
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
observers_.RemoveObserver(observer);
|
|
}
|
|
|
|
void WebContentsZoomController::SetEmbedderZoomController(
|
|
WebContentsZoomController* controller) {
|
|
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
embedder_zoom_controller_ = controller;
|
|
}
|
|
|
|
bool WebContentsZoomController::SetZoomLevel(double level) {
|
|
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
// Cannot zoom in disabled mode. Also, don't allow changing zoom level on
|
|
// a crashed tab, an error page or an interstitial page.
|
|
if (zoom_mode_ == ZOOM_MODE_DISABLED ||
|
|
!web_contents()->GetPrimaryMainFrame()->IsRenderFrameLive())
|
|
return false;
|
|
|
|
// Do not actually rescale the page in manual mode.
|
|
if (zoom_mode_ == ZOOM_MODE_MANUAL) {
|
|
// If the zoom level hasn't changed, early out to avoid sending an event.
|
|
if (blink::ZoomValuesEqual(zoom_level_, level))
|
|
return true;
|
|
|
|
double old_zoom_level = zoom_level_;
|
|
zoom_level_ = level;
|
|
|
|
ZoomChangedEventData zoom_change_data(web_contents(), old_zoom_level,
|
|
zoom_level_, true /* temporary */,
|
|
zoom_mode_);
|
|
observers_.Notify(&WebContentsZoomObserver::OnZoomChanged,
|
|
zoom_change_data);
|
|
|
|
return true;
|
|
}
|
|
|
|
content::HostZoomMap* zoom_map =
|
|
content::HostZoomMap::GetForWebContents(web_contents());
|
|
DCHECK(zoom_map);
|
|
DCHECK(!event_data_);
|
|
event_data_ = std::make_unique<ZoomChangedEventData>(
|
|
web_contents(), GetZoomLevel(), level, false /* temporary */, zoom_mode_);
|
|
|
|
content::GlobalRenderFrameHostId rfh_id =
|
|
web_contents()->GetPrimaryMainFrame()->GetGlobalId();
|
|
if (zoom_mode_ == ZOOM_MODE_ISOLATED ||
|
|
zoom_map->UsesTemporaryZoomLevel(rfh_id)) {
|
|
zoom_map->SetTemporaryZoomLevel(rfh_id, level);
|
|
ZoomChangedEventData zoom_change_data(web_contents(), zoom_level_, level,
|
|
true /* temporary */, zoom_mode_);
|
|
observers_.Notify(&WebContentsZoomObserver::OnZoomChanged,
|
|
zoom_change_data);
|
|
} else {
|
|
const GURL url = content::HostZoomMap::GetURLForRenderFrameHost(rfh_id);
|
|
if (url.is_empty()) {
|
|
// If we exit without triggering an update, we should clear event_data_,
|
|
// else we may later trigger a DCHECK(event_data_).
|
|
event_data_.reset();
|
|
return false;
|
|
}
|
|
std::string host = net::GetHostOrSpecFromURL(url);
|
|
zoom_map->SetZoomLevelForHost(host, level);
|
|
}
|
|
|
|
DCHECK(!event_data_);
|
|
return true;
|
|
}
|
|
|
|
double WebContentsZoomController::GetZoomLevel() const {
|
|
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
return zoom_mode_ == ZOOM_MODE_MANUAL
|
|
? zoom_level_
|
|
: content::HostZoomMap::GetZoomLevel(web_contents());
|
|
}
|
|
|
|
void WebContentsZoomController::SetDefaultZoomFactor(double factor) {
|
|
default_zoom_factor_ = factor;
|
|
}
|
|
|
|
void WebContentsZoomController::SetTemporaryZoomLevel(double level) {
|
|
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
content::GlobalRenderFrameHostId old_rfh_id_ =
|
|
web_contents()->GetPrimaryMainFrame()->GetGlobalId();
|
|
host_zoom_map_->SetTemporaryZoomLevel(old_rfh_id_, level);
|
|
|
|
// Notify observers of zoom level changes.
|
|
ZoomChangedEventData zoom_change_data(web_contents(), zoom_level_, level,
|
|
true /* temporary */, zoom_mode_);
|
|
observers_.Notify(&WebContentsZoomObserver::OnZoomChanged, zoom_change_data);
|
|
}
|
|
|
|
bool WebContentsZoomController::UsesTemporaryZoomLevel() {
|
|
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
content::GlobalRenderFrameHostId rfh_id =
|
|
web_contents()->GetPrimaryMainFrame()->GetGlobalId();
|
|
return host_zoom_map_->UsesTemporaryZoomLevel(rfh_id);
|
|
}
|
|
|
|
void WebContentsZoomController::SetZoomMode(ZoomMode new_mode) {
|
|
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
if (new_mode == zoom_mode_)
|
|
return;
|
|
|
|
content::HostZoomMap* zoom_map =
|
|
content::HostZoomMap::GetForWebContents(web_contents());
|
|
DCHECK(zoom_map);
|
|
content::GlobalRenderFrameHostId rfh_id =
|
|
web_contents()->GetPrimaryMainFrame()->GetGlobalId();
|
|
double original_zoom_level = GetZoomLevel();
|
|
|
|
DCHECK(!event_data_);
|
|
event_data_ = std::make_unique<ZoomChangedEventData>(
|
|
web_contents(), original_zoom_level, original_zoom_level,
|
|
false /* temporary */, new_mode);
|
|
|
|
switch (new_mode) {
|
|
case ZOOM_MODE_DEFAULT: {
|
|
const GURL url = content::HostZoomMap::GetURLForRenderFrameHost(rfh_id);
|
|
|
|
if (!url.is_empty()) {
|
|
const std::string host = net::GetHostOrSpecFromURL(url);
|
|
const std::string scheme = url.GetScheme();
|
|
|
|
if (zoom_map->HasZoomLevel(scheme, host)) {
|
|
// If there are other tabs with the same origin, then set this tab's
|
|
// zoom level to match theirs. The temporary zoom level will be
|
|
// cleared below, but this call will make sure this tab re-draws at
|
|
// the correct zoom level.
|
|
double origin_zoom_level =
|
|
zoom_map->GetZoomLevelForHostAndScheme(scheme, host);
|
|
event_data_->new_zoom_level = origin_zoom_level;
|
|
zoom_map->SetTemporaryZoomLevel(rfh_id, origin_zoom_level);
|
|
} else {
|
|
// The host will need a level prior to removing the temporary level.
|
|
// We don't want the zoom level to change just because we entered
|
|
// default mode.
|
|
zoom_map->SetZoomLevelForHost(host, original_zoom_level);
|
|
}
|
|
}
|
|
// Remove per-tab zoom data for this tab. No event callback expected.
|
|
zoom_map->ClearTemporaryZoomLevel(rfh_id);
|
|
break;
|
|
}
|
|
case ZOOM_MODE_ISOLATED: {
|
|
// Unless the zoom mode was |ZOOM_MODE_DISABLED| before this call, the
|
|
// page needs an initial isolated zoom back to the same level it was at
|
|
// in the other mode.
|
|
if (zoom_mode_ != ZOOM_MODE_DISABLED) {
|
|
zoom_map->SetTemporaryZoomLevel(rfh_id, original_zoom_level);
|
|
} else {
|
|
// When we don't call any HostZoomMap set functions, we send the event
|
|
// manually.
|
|
observers_.Notify(&WebContentsZoomObserver::OnZoomChanged,
|
|
*event_data_);
|
|
event_data_.reset();
|
|
}
|
|
break;
|
|
}
|
|
case ZOOM_MODE_MANUAL: {
|
|
// Unless the zoom mode was |ZOOM_MODE_DISABLED| before this call, the
|
|
// page needs to be resized to the default zoom. While in manual mode,
|
|
// the zoom level is handled independently.
|
|
if (zoom_mode_ != ZOOM_MODE_DISABLED) {
|
|
zoom_map->SetTemporaryZoomLevel(rfh_id, GetDefaultZoomLevel());
|
|
zoom_level_ = original_zoom_level;
|
|
} else {
|
|
// When we don't call any HostZoomMap set functions, we send the event
|
|
// manually.
|
|
observers_.Notify(&WebContentsZoomObserver::OnZoomChanged,
|
|
*event_data_);
|
|
event_data_.reset();
|
|
}
|
|
break;
|
|
}
|
|
case ZOOM_MODE_DISABLED: {
|
|
// The page needs to be zoomed back to default before disabling the zoom
|
|
double new_zoom_level = GetDefaultZoomLevel();
|
|
event_data_->new_zoom_level = new_zoom_level;
|
|
zoom_map->SetTemporaryZoomLevel(rfh_id, new_zoom_level);
|
|
break;
|
|
}
|
|
}
|
|
// Any event data we've stored should have been consumed by this point.
|
|
DCHECK(!event_data_);
|
|
|
|
zoom_mode_ = new_mode;
|
|
}
|
|
|
|
void WebContentsZoomController::ResetZoomModeOnNavigationIfNeeded(
|
|
const GURL& url) {
|
|
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
if (zoom_mode_ != ZOOM_MODE_ISOLATED && zoom_mode_ != ZOOM_MODE_MANUAL)
|
|
return;
|
|
|
|
content::HostZoomMap* zoom_map =
|
|
content::HostZoomMap::GetForWebContents(web_contents());
|
|
zoom_level_ = zoom_map->GetDefaultZoomLevel();
|
|
double old_zoom_level = zoom_map->GetZoomLevel(web_contents());
|
|
double new_zoom_level = zoom_map->GetZoomLevelForHostAndScheme(
|
|
url.GetScheme(), net::GetHostOrSpecFromURL(url));
|
|
|
|
event_data_ = std::make_unique<ZoomChangedEventData>(
|
|
web_contents(), old_zoom_level, new_zoom_level, false, ZOOM_MODE_DEFAULT);
|
|
|
|
// The call to ClearTemporaryZoomLevel() doesn't generate any events from
|
|
// HostZoomMap, but the call to UpdateState() at the end of
|
|
// DidFinishNavigation will notify our observers.
|
|
// Note: it's possible the render_process/frame ids have disappeared (e.g.
|
|
// if we navigated to a new origin), but this won't cause a problem in the
|
|
// call below.
|
|
zoom_map->ClearTemporaryZoomLevel(
|
|
web_contents()->GetPrimaryMainFrame()->GetGlobalId());
|
|
zoom_mode_ = ZOOM_MODE_DEFAULT;
|
|
}
|
|
|
|
void WebContentsZoomController::DidFinishNavigation(
|
|
content::NavigationHandle* navigation_handle) {
|
|
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
if (!navigation_handle->IsInPrimaryMainFrame() ||
|
|
!navigation_handle->HasCommitted()) {
|
|
return;
|
|
}
|
|
|
|
if (navigation_handle->IsErrorPage())
|
|
content::HostZoomMap::SendErrorPageZoomLevelRefresh(web_contents());
|
|
|
|
if (!navigation_handle->IsSameDocument()) {
|
|
ResetZoomModeOnNavigationIfNeeded(navigation_handle->GetURL());
|
|
SetZoomFactorOnNavigationIfNeeded(navigation_handle->GetURL());
|
|
|
|
// If the main frame's content has changed, the new page may have a
|
|
// different zoom level from the old one.
|
|
UpdateState(std::string());
|
|
}
|
|
|
|
DCHECK(!event_data_);
|
|
}
|
|
|
|
void WebContentsZoomController::WebContentsDestroyed() {
|
|
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
// At this point we should no longer be sending any zoom events with this
|
|
// WebContents.
|
|
observers_.Notify(&WebContentsZoomObserver::OnZoomControllerDestroyed, this);
|
|
|
|
embedder_zoom_controller_ = nullptr;
|
|
}
|
|
|
|
void WebContentsZoomController::RenderFrameHostChanged(
|
|
content::RenderFrameHost* old_host,
|
|
content::RenderFrameHost* new_host) {
|
|
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
// If our associated HostZoomMap changes, update our subscription.
|
|
content::HostZoomMap* new_host_zoom_map =
|
|
content::HostZoomMap::GetForWebContents(web_contents());
|
|
if (new_host_zoom_map == host_zoom_map_)
|
|
return;
|
|
|
|
host_zoom_map_ = new_host_zoom_map;
|
|
zoom_subscription_ = host_zoom_map_->AddZoomLevelChangedCallback(
|
|
base::BindRepeating(&WebContentsZoomController::OnZoomLevelChanged,
|
|
base::Unretained(this)));
|
|
}
|
|
|
|
void WebContentsZoomController::SetZoomFactorOnNavigationIfNeeded(
|
|
const GURL& url) {
|
|
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
if (blink::ZoomValuesEqual(default_zoom_factor(), kPageZoomEpsilon))
|
|
return;
|
|
|
|
content::GlobalRenderFrameHostId old_rfh_id_ =
|
|
content::GlobalRenderFrameHostId(old_process_id_, old_view_id_);
|
|
|
|
if (host_zoom_map_->UsesTemporaryZoomLevel(old_rfh_id_)) {
|
|
host_zoom_map_->ClearTemporaryZoomLevel(old_rfh_id_);
|
|
}
|
|
|
|
if (embedder_zoom_controller_ &&
|
|
embedder_zoom_controller_->UsesTemporaryZoomLevel()) {
|
|
double level = embedder_zoom_controller_->GetZoomLevel();
|
|
SetTemporaryZoomLevel(level);
|
|
return;
|
|
}
|
|
|
|
// When kZoomFactor is available, it takes precedence over
|
|
// pref store values but if the host has zoom factor set explicitly
|
|
// then it takes precedence.
|
|
// pref store < kZoomFactor < setZoomLevel
|
|
std::string host = net::GetHostOrSpecFromURL(url);
|
|
std::string scheme = url.GetScheme();
|
|
double zoom_factor = default_zoom_factor();
|
|
double zoom_level = blink::ZoomFactorToZoomLevel(zoom_factor);
|
|
if (host_zoom_map_->HasZoomLevel(scheme, host)) {
|
|
zoom_level = host_zoom_map_->GetZoomLevelForHostAndScheme(scheme, host);
|
|
}
|
|
if (blink::ZoomValuesEqual(zoom_level, GetZoomLevel()))
|
|
return;
|
|
|
|
SetZoomLevel(zoom_level);
|
|
}
|
|
|
|
void WebContentsZoomController::OnZoomLevelChanged(
|
|
const content::HostZoomMap::ZoomLevelChange& change) {
|
|
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
UpdateState(change.host);
|
|
}
|
|
|
|
void WebContentsZoomController::UpdateState(const std::string& host) {
|
|
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
auto* rfh = web_contents()->GetPrimaryMainFrame();
|
|
// If |host| is empty, all observers should be updated.
|
|
if (!host.empty()) {
|
|
// Get the (non-virtual) url to be tracked by the HostZoomMap. Getting urls
|
|
// directly from a WebContents may result in a virtual url, so prefer using
|
|
// the value from the `rfh` instead, per https://crbug.com/40290372.
|
|
const GURL url =
|
|
content::HostZoomMap::GetURLForRenderFrameHost(rfh->GetGlobalId());
|
|
if (url.is_empty() || host != net::GetHostOrSpecFromURL(url)) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (event_data_) {
|
|
// For state changes initiated within the ZoomController, information about
|
|
// the change should be sent.
|
|
ZoomChangedEventData zoom_change_data = *event_data_;
|
|
event_data_.reset();
|
|
observers_.Notify(&WebContentsZoomObserver::OnZoomChanged,
|
|
zoom_change_data);
|
|
} else {
|
|
double zoom_level = GetZoomLevel();
|
|
ZoomChangedEventData zoom_change_data(web_contents(), zoom_level,
|
|
zoom_level, false, zoom_mode_);
|
|
observers_.Notify(&WebContentsZoomObserver::OnZoomChanged,
|
|
zoom_change_data);
|
|
}
|
|
}
|
|
|
|
WEB_CONTENTS_USER_DATA_KEY_IMPL(WebContentsZoomController);
|
|
|
|
} // namespace electron
|