Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(140)

Unified Diff: components/zoom/zoom_controller.cc

Issue 2630583002: Add setting to isolate zoom changes by default. (Closed)
Patch Set: ... and tell closure_compiler. Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « components/zoom/zoom_controller.h ('k') | components/zoom/zoom_prefs_delegate.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: components/zoom/zoom_controller.cc
diff --git a/components/zoom/zoom_controller.cc b/components/zoom/zoom_controller.cc
index 8d258a5d7adb3ddaf7c36df2848d1be6af680252..dd0231226f9bf9a0488b38421ed6aacd17f47cd8 100644
--- a/components/zoom/zoom_controller.cc
+++ b/components/zoom/zoom_controller.cc
@@ -6,12 +6,15 @@
#include "components/zoom/zoom_event_manager.h"
#include "components/zoom/zoom_observer.h"
+#include "content/public/browser/browser_context.h"
#include "content/public/browser/host_zoom_map.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/storage_partition.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/page_type.h"
#include "content/public/common/page_zoom.h"
@@ -36,12 +39,43 @@ double ZoomController::GetZoomLevelForWebContents(
ZoomController::ZoomController(content::WebContents* web_contents)
: content::WebContentsObserver(web_contents),
can_show_bubble_(true),
- zoom_mode_(ZOOM_MODE_DEFAULT),
+ default_scope_is_per_origin_(ZoomPrefsDelegate::kZoomScopeSettingDefault),
zoom_level_(1.0),
browser_context_(web_contents->GetBrowserContext()) {
host_zoom_map_ = content::HostZoomMap::GetForWebContents(web_contents);
zoom_level_ = host_zoom_map_->GetDefaultZoomLevel();
+ ZoomPrefsDelegate* zoom_prefs_delegate = static_cast<ZoomPrefsDelegate*>(
+ content::BrowserContext::GetStoragePartition(
+ browser_context_, web_contents->GetSiteInstance())
+ ->GetZoomLevelDelegate());
+ if (zoom_prefs_delegate) {
+ default_scope_is_per_origin_ =
+ zoom_prefs_delegate->GetZoomScopeIsPerOriginPref();
+ // TODO(mcnee) If the need to navigate between StoragePartitions is
+ // introduced by a new feature, we will need to add logic to update this
+ // subscription.
+ default_zoom_scope_subscription_ =
+ zoom_prefs_delegate->RegisterDefaultZoomScopeCallback(
+ base::Bind(&ZoomController::OnDefaultZoomScopeChanged,
+ base::Unretained(this)));
+ }
+ zoom_mode_ =
+ default_scope_is_per_origin_ ? ZOOM_MODE_DEFAULT : ZOOM_MODE_ISOLATED;
+
+ // When in isolated zoom, a temporary zoom level needs to be set to override
+ // any existing per-host zoom levels.
+ // If this WebContents is a clone of another, don't overwrite the temporary
+ // level we've inherited.
+ int render_process_id = web_contents->GetRenderProcessHost()->GetID();
+ int render_view_id = web_contents->GetRenderViewHost()->GetRoutingID();
+ if (zoom_mode_ == ZOOM_MODE_ISOLATED &&
+ !host_zoom_map_->UsesTemporaryZoomLevel(render_process_id,
+ render_view_id)) {
+ host_zoom_map_->SetTemporaryZoomLevel(render_process_id, render_view_id,
+ zoom_level_);
+ }
+
zoom_subscription_ = host_zoom_map_->AddZoomLevelChangedCallback(
base::Bind(&ZoomController::OnZoomLevelChanged, base::Unretained(this)));
@@ -180,7 +214,8 @@ void ZoomController::SetZoomMode(ZoomMode new_mode) {
DCHECK(!event_data_);
event_data_.reset(new ZoomChangedEventData(
web_contents(), original_zoom_level, original_zoom_level, new_mode,
- new_mode != ZOOM_MODE_DEFAULT));
+ new_mode != (default_scope_is_per_origin_ ? ZOOM_MODE_DEFAULT
+ : ZOOM_MODE_ISOLATED)));
switch (new_mode) {
case ZOOM_MODE_DEFAULT: {
@@ -261,28 +296,58 @@ void ZoomController::SetZoomMode(ZoomMode new_mode) {
}
void ZoomController::ResetZoomModeOnNavigationIfNeeded(const GURL& url) {
- if (zoom_mode_ != ZOOM_MODE_ISOLATED && zoom_mode_ != ZOOM_MODE_MANUAL)
+ if (zoom_mode_ != (default_scope_is_per_origin_ ? ZOOM_MODE_ISOLATED
+ : ZOOM_MODE_DEFAULT) &&
+ zoom_mode_ != ZOOM_MODE_MANUAL)
return;
int render_process_id = web_contents()->GetRenderProcessHost()->GetID();
int render_view_id = web_contents()->GetRenderViewHost()->GetRoutingID();
content::HostZoomMap* zoom_map =
content::HostZoomMap::GetForWebContents(web_contents());
+ double old_zoom_level = GetZoomLevel();
+ // Set |zoom_level_| after calling GetZoomLevel() so we get the correct old
+ // zoom level if we're resetting from manual.
zoom_level_ = zoom_map->GetDefaultZoomLevel();
- double old_zoom_level = zoom_map->GetZoomLevel(web_contents());
- double new_zoom_level = zoom_map->GetZoomLevelForHostAndScheme(
- url.scheme(), net::GetHostOrSpecFromURL(url));
+ ZoomMode new_mode;
+ double new_zoom_level;
+ if (default_scope_is_per_origin_) {
+ new_mode = ZOOM_MODE_DEFAULT;
+ new_zoom_level = zoom_map->GetZoomLevelForHostAndScheme(
+ url.scheme(), net::GetHostOrSpecFromURL(url));
+ } else {
+ new_mode = ZOOM_MODE_ISOLATED;
+ new_zoom_level = zoom_level_;
+ }
event_data_.reset(new ZoomChangedEventData(web_contents(), old_zoom_level,
- new_zoom_level, ZOOM_MODE_DEFAULT,
+ new_zoom_level, new_mode,
false /* can_show_bubble */));
- // The call to ClearTemporaryZoomLevel() doesn't generate any events from
- // HostZoomMap, but the call to UpdateState() at the end of this function
- // will notify our observers.
- // Note: it's possible the render_process/view 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(render_process_id, render_view_id);
- zoom_mode_ = ZOOM_MODE_DEFAULT;
+ if (default_scope_is_per_origin_) {
+ // The call to ClearTemporaryZoomLevel() doesn't generate any events from
+ // HostZoomMap, but the call to UpdateState() at the end of this function
+ // will notify our observers.
+ // Note: it's possible the render_process/view 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(render_process_id, render_view_id);
+ } else {
+ // If we're resetting to isolated zoom, a temporary zoom level needs to
+ // be set to override any existing per-host zoom levels.
+ zoom_map->SetTemporaryZoomLevel(render_process_id, render_view_id,
+ new_zoom_level);
+ }
+ zoom_mode_ = new_mode;
+}
+
+void ZoomController::UpdateZoomModeOnScopeChangeIfNeeded() {
+ if (zoom_mode_ != ZOOM_MODE_DEFAULT && zoom_mode_ != ZOOM_MODE_ISOLATED)
+ return;
+
+ // When going from per-tab to per-host, if there isn't an existing per-host
+ // zoom level set and we have a non-default temporary zoom level, this
+ // ZoomController will set the per-host zoom level.
+ SetZoomMode(default_scope_is_per_origin_ ? ZOOM_MODE_DEFAULT
+ : ZOOM_MODE_ISOLATED);
}
void ZoomController::DidFinishNavigation(
@@ -303,6 +368,9 @@ void ZoomController::DidFinishNavigation(
}
void ZoomController::WebContentsDestroyed() {
+ // Once our WebContents is destroyed, we can no longer respond to zoom scope
+ // changes.
+ default_zoom_scope_subscription_.reset();
// At this point we should no longer be sending any zoom events with this
// WebContents.
observers_.Clear();
@@ -311,9 +379,19 @@ void ZoomController::WebContentsDestroyed() {
void ZoomController::RenderFrameHostChanged(
content::RenderFrameHost* old_host,
content::RenderFrameHost* new_host) {
- // If our associated HostZoomMap changes, update our event subscription.
content::HostZoomMap* new_host_zoom_map =
content::HostZoomMap::GetForWebContents(web_contents());
+
+ // The HostZoomMap records temporary zoom levels per RenderView. When zooming
+ // is per-tab and our RenderView changes, we need to copy the level for our
+ // new RenderView so that the tab's zoom level is preserved.
+ if (old_host && !default_scope_is_per_origin_ &&
+ zoom_mode_ == ZOOM_MODE_ISOLATED) {
+ PreserveTemporaryZoomLevel(host_zoom_map_, new_host_zoom_map, old_host,
+ new_host);
+ }
+
+ // If our associated HostZoomMap changes, update our event subscription.
if (new_host_zoom_map == host_zoom_map_)
return;
@@ -322,11 +400,66 @@ void ZoomController::RenderFrameHostChanged(
base::Bind(&ZoomController::OnZoomLevelChanged, base::Unretained(this)));
}
+void ZoomController::PreserveTemporaryZoomLevel(
+ const content::HostZoomMap* old_zoom_map,
+ content::HostZoomMap* new_zoom_map,
+ content::RenderFrameHost* old_host,
+ content::RenderFrameHost* new_host) const {
+ const content::RenderViewHost* old_view_host = old_host->GetRenderViewHost();
+ const content::RenderViewHost* new_view_host = new_host->GetRenderViewHost();
+
+ DCHECK(old_zoom_map->UsesTemporaryZoomLevel(
+ old_view_host->GetProcess()->GetID(), old_view_host->GetRoutingID()));
+
+ const double level = old_zoom_map->GetTemporaryZoomLevel(
+ old_view_host->GetProcess()->GetID(), old_view_host->GetRoutingID());
+ new_zoom_map->SetTemporaryZoomLevel(new_view_host->GetProcess()->GetID(),
+ new_view_host->GetRoutingID(), level);
+}
+
+void ZoomController::PreserveTemporaryZoomLevel(
+ content::WebContents* old_web_contents,
+ content::WebContents* new_web_contents) const {
+ if (default_scope_is_per_origin_ || zoom_mode_ != ZOOM_MODE_ISOLATED)
+ return;
+
+ content::RenderFrameHost* old_host = old_web_contents->GetMainFrame();
+ content::RenderFrameHost* new_host = new_web_contents->GetMainFrame();
+ const content::HostZoomMap* old_host_zoom_map =
+ content::HostZoomMap::GetForWebContents(old_web_contents);
+ content::HostZoomMap* new_host_zoom_map =
+ content::HostZoomMap::GetForWebContents(new_web_contents);
+
+ PreserveTemporaryZoomLevel(old_host_zoom_map, new_host_zoom_map, old_host,
+ new_host);
+}
+
+void ZoomController::DidCloneToNewWebContents(
+ content::WebContents* old_web_contents,
+ content::WebContents* new_web_contents) {
+ // If a WebContents is cloned when zooming is per-tab, have the clone inherit
+ // the original's zoom level.
+ PreserveTemporaryZoomLevel(old_web_contents, new_web_contents);
+}
+
+void ZoomController::WebContentsReplaced(
+ content::WebContents* new_web_contents) {
+ // A tab may replace its WebContents with another, but from the user's
+ // perspective, this is still the same tab, so we need to preserve the
+ // per-tab zoom.
+ PreserveTemporaryZoomLevel(web_contents(), new_web_contents);
+}
+
void ZoomController::OnZoomLevelChanged(
const content::HostZoomMap::ZoomLevelChange& change) {
UpdateState(change.host);
}
+void ZoomController::OnDefaultZoomScopeChanged() {
+ default_scope_is_per_origin_ = !default_scope_is_per_origin_;
+ UpdateZoomModeOnScopeChangeIfNeeded();
+}
+
void ZoomController::UpdateState(const std::string& host) {
// If |host| is empty, all observers should be updated.
if (!host.empty()) {
« no previous file with comments | « components/zoom/zoom_controller.h ('k') | components/zoom/zoom_prefs_delegate.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698