diff options
author | paulmeyer <paulmeyer@chromium.org> | 2015-04-01 12:33:48 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-04-01 19:34:35 +0000 |
commit | 65703af8f934586ad67700ced9fa8483c0f849d7 (patch) | |
tree | 25c1721bc66583f92c6d3f7b9e1d6be53ee393d5 | |
parent | 5872a39886df9e509a271acfa1d7944338c7eb48 (diff) | |
download | chromium_src-65703af8f934586ad67700ced9fa8483c0f849d7.zip chromium_src-65703af8f934586ad67700ced9fa8483c0f849d7.tar.gz chromium_src-65703af8f934586ad67700ced9fa8483c0f849d7.tar.bz2 |
This CL exposes zoom modes to the <webview> API.
The new api is proposed here: https://docs.google.com/a/google.com/document/d/1hIexgq7HvYbqTp19HklW6DcKW-5sgocmnCqUHDKsYo0/edit?usp=sharing
BUG=472674
Review URL: https://codereview.chromium.org/1047793003
Cr-Commit-Position: refs/heads/master@{#323300}
15 files changed, 427 insertions, 37 deletions
diff --git a/chrome/browser/apps/guest_view/web_view_browsertest.cc b/chrome/browser/apps/guest_view/web_view_browsertest.cc index 14b2f9f..9b82907 100644 --- a/chrome/browser/apps/guest_view/web_view_browsertest.cc +++ b/chrome/browser/apps/guest_view/web_view_browsertest.cc @@ -2628,6 +2628,18 @@ IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestResizeEvents) { TestHelper("testResizeEvents", "web_view/shim", NO_TEST_SERVER); } +IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestPerOriginZoomMode) { + TestHelper("testPerOriginZoomMode", "web_view/shim", NO_TEST_SERVER); +} + +IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestPerViewZoomMode) { + TestHelper("testPerViewZoomMode", "web_view/shim", NO_TEST_SERVER); +} + +IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestDisabledZoomMode) { + TestHelper("testDisabledZoomMode", "web_view/shim", NO_TEST_SERVER); +} + // This test verify that the set of rules registries of a webview will be // removed from RulesRegistryService after the webview is gone. // http://crbug.com/438327 diff --git a/chrome/common/extensions/api/tabs.json b/chrome/common/extensions/api/tabs.json index 4fe70c7..1fa5887 100644 --- a/chrome/common/extensions/api/tabs.json +++ b/chrome/common/extensions/api/tabs.json @@ -50,7 +50,7 @@ }, { "name": "disabled", - "description": "Disables all zooming in the tab. The tab will revert to default (100%) zoom, and all attempted zoom changes will be ignored." + "description": "Disables all zooming in the tab. The tab will revert to the default zoom level, and all attempted zoom changes will be ignored." } ] }, diff --git a/chrome/common/extensions/api/webview_tag.json b/chrome/common/extensions/api/webview_tag.json index 53f69c6..7f9fa03 100644 --- a/chrome/common/extensions/api/webview_tag.json +++ b/chrome/common/extensions/api/webview_tag.json @@ -312,6 +312,25 @@ "type": "object", "description": "Interface which provides access to webRequest events on the guest page. See the <a href=\"http://developer.chrome.com/extensions/webRequest\">chrome.webRequest</a> extensions API for details on webRequest life cycle and related concepts.<p>To illustrate how usage differs from the extensions webRequest API, consider the following example code which blocks any guest requests for URLs which match <code>*://www.evil.com/*</code>:</p><pre>webview.request.onBeforeRequest.addListener(\r function(details) { return {cancel: true}; },\r {urls: [\"*://www.evil.com/*\"]},\r [\"blocking\"]);</pre><p>Additionally, this interface supports declarative webRequest rules through <code>onRequest</code> and <code>onMessage</code> events. See <a href=\"http://developer.chrome.com/extensions/declarativeWebRequest.html\">declarativeWebRequest</a> for API details.</p>Note that conditions and actions for declarative webview webRequests should be instantiated from their <code>chrome.webViewRequest.*</code> counterparts. The following example code declaratively blocks all requests to <code>\"example.com\"</code> on the webview <code>myWebview</code>:</p><pre>var rule = {\r conditions: [\r new chrome.webViewRequest.RequestMatcher({ url: { hostSuffix: 'example.com' } })\r ],\r actions: [ new chrome.webViewRequest.CancelRequest() ]\r};\rmyWebview.request.onRequest.addRules([rule]);</pre>", "properties": {} + }, + { + "id": "ZoomMode", + "type": "string", + "description": "Defines the how zooming is handled in the webview.", + "enum": [ + { + "name": "per-origin", + "description": "Zoom changes will persist in the zoomed page's origin, i.e. all other webviews in the same partition that are navigated to that same origin will be zoomed as well. Moreover, <code>per-origin</code> zoom changes are saved with the origin, meaning that when navigating to other pages in the same origin, they will all be zoomed to the same zoom factor." + }, + { + "name": "per-view", + "description": "Zoom changes only take effect in this webview, and zoom changes in other webviews will not affect the zooming of this webview. Also, <code>per-view</code> zoom changes are reset on navigation; navigating a webview will always load pages with their per-origin zoom factors (within the scope of the partition)." + }, + { + "name": "disabled", + "description": "Disables all zooming in the webview. The content will revert to the default zoom level, and all attempted zoom changes will be ignored." + } + ] } ], "functions": [ @@ -455,6 +474,25 @@ ] }, { + "name": "getZoomMode", + "type": "function", + "description": "Gets the current zoom mode.", + "parameters": [ + { + "type": "function", + "name": "callback", + "description": "Called with the webview's current zoom mode.", + "parameters": [ + { + "$ref": "ZoomMode", + "name": "ZoomMode", + "description": "The webview's current zoom mode." + } + ] + } + ] + }, + { "name": "go", "type": "function", "description": "Navigates to a history entry using a history index relative to the current navigation. If the requested navigation is impossible, this method has no effect.", @@ -545,6 +583,25 @@ ] }, { + "name": "setZoomMode", + "type": "function", + "description": "Sets the zoom mode of the webview.", + "parameters": [ + { + "$ref": "ZoomMode", + "name": "ZoomMode", + "description": "Defines how zooming is handled in the webview." + }, + { + "type": "function", + "name": "callback", + "description": "Called after the zoom mode has been changed.", + "optional": true, + "parameters": [] + } + ] + }, + { "name": "stop", "type": "function", "description": "Stops loading the current <webview> navigation if in progress.", diff --git a/chrome/test/data/extensions/platform_apps/web_view/shim/main.js b/chrome/test/data/extensions/platform_apps/web_view/shim/main.js index 31d1c37..0b116a8 100644 --- a/chrome/test/data/extensions/platform_apps/web_view/shim/main.js +++ b/chrome/test/data/extensions/platform_apps/web_view/shim/main.js @@ -2043,7 +2043,7 @@ function testLoadDataAPI() { embedder.test.succeed(); }); }); - } + }; var loadstopListener1 = function(e) { webview.removeEventListener('loadstop', loadstopListener1); @@ -2055,7 +2055,7 @@ function testLoadDataAPI() { "BhIHRlc3QuPGJyPgogIDxpbWcgc3JjPSJ0ZXN0LmJtcCI+PGJyPgo8L2h0bWw+Cg==", embedder.testImageBaseURL, embedder.virtualURL); - } + }; webview.addEventListener('loadstop', loadstopListener1); document.body.appendChild(webview); @@ -2104,6 +2104,103 @@ function testResizeEvents() { document.body.appendChild(webview); }; +function testPerOriginZoomMode() { + var webview1 = new WebView(); + var webview2 = new WebView(); + webview1.src = 'about:blank'; + webview2.src = 'about:blank'; + + webview1.addEventListener('loadstop', function(e) { + document.body.appendChild(webview2); + }); + webview2.addEventListener('loadstop', function(e) { + webview1.getZoomMode(function(zoomMode) { + // Check that |webview1| is in 'per-origin' mode and zoom it. Check that + // both webviews zoomed. + embedder.test.assertEq(zoomMode, 'per-origin'); + webview1.setZoom(3.14, function() { + webview1.getZoom(function(zoom) { + embedder.test.assertEq(zoom, 3.14); + webview2.getZoom(function(zoom) { + embedder.test.assertEq(zoom, 3.14); + embedder.test.succeed(); + }); + }); + }); + }); + }); + + document.body.appendChild(webview1); +} + +function testPerViewZoomMode() { + var webview1 = new WebView(); + var webview2 = new WebView(); + webview1.src = 'about:blank'; + webview2.src = 'about:blank'; + + webview1.addEventListener('loadstop', function(e) { + document.body.appendChild(webview2); + }); + webview2.addEventListener('loadstop', function(e) { + // Set |webview2| to 'per-view' mode and zoom it. Make sure that the + // zoom did not affect |webview1|. + webview2.setZoomMode('per-view', function() { + webview2.getZoomMode(function(zoomMode) { + embedder.test.assertEq(zoomMode, 'per-view'); + webview2.setZoom(0.45, function() { + webview1.getZoom(function(zoom) { + embedder.test.assertFalse(zoom == 0.45); + webview2.getZoom(function(zoom) { + embedder.test.assertEq(zoom, 0.45); + embedder.test.succeed(); + }); + }); + }); + }); + }); + }); + + document.body.appendChild(webview1); +} + +function testDisabledZoomMode() { + var webview = new WebView(); + webview.src = 'about:blank'; + + var zoomchanged = false; + var zoomchangeListener = function(e) { + // TODO (paulmeyer): This is currently broken because ZoomObservers do not + // get the correct new zoom level when changing the zoom mode to + // 'disabled'. Will add back in after http://crbug.com/472621 is fixed. + //embedder.test.assertEq(e.newZoomFactor, 1); + zoomchanged = true; + }; + + webview.addEventListener('loadstop', function(e) { + // Set |webview| to 'disabled' mode and check that + // zooming is actually disabled. Also check that the + // "zoomchange" event pick up changes from changing the + // zoom mode. + webview.addEventListener('zoomchange', zoomchangeListener); + webview.setZoomMode('disabled', function() { + webview.getZoomMode(function(zoomMode) { + embedder.test.assertEq(zoomMode, 'disabled'); + webview.removeEventListener('zoomchange', zoomchangeListener); + webview.setZoom(1.39, function() { + webview.getZoom(function(zoom) { + embedder.test.assertEq(zoom, 1); + embedder.test.assertTrue(zoomchanged); + embedder.test.succeed(); + }); + }); + }); + }); + }); + + document.body.appendChild(webview); +} + embedder.test.testList = { 'testAllowTransparencyAttribute': testAllowTransparencyAttribute, 'testAutosizeHeight': testAutosizeHeight, @@ -2182,7 +2279,10 @@ embedder.test.testList = { 'testFindAPI': testFindAPI, 'testFindAPI_findupdate': testFindAPI, 'testLoadDataAPI': testLoadDataAPI, - 'testResizeEvents': testResizeEvents + 'testResizeEvents': testResizeEvents, + 'testPerOriginZoomMode': testPerOriginZoomMode, + 'testPerViewZoomMode': testPerViewZoomMode, + 'testDisabledZoomMode': testDisabledZoomMode, }; onload = function() { diff --git a/components/ui/zoom/zoom_controller.h b/components/ui/zoom/zoom_controller.h index ff78b86..0ea9f6b 100644 --- a/components/ui/zoom/zoom_controller.h +++ b/components/ui/zoom/zoom_controller.h @@ -57,8 +57,8 @@ class ZoomController : public content::WebContentsObserver, // These zoom changes can be handled manually by listening for the // |onZoomChange| event. Zooming in this mode is also on a per-tab basis. ZOOM_MODE_MANUAL, - // Disables all zooming in this tab. The tab will revert to default (100%) - // zoom, and all attempted zoom changes will be ignored. + // Disables all zooming in this tab. The tab will revert to the default + // zoom level, and all attempted zoom changes will be ignored. ZOOM_MODE_DISABLED, }; diff --git a/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc b/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc index b40c012..cb68550 100644 --- a/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc +++ b/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc @@ -23,6 +23,7 @@ using content::WebContents; using extensions::core_api::web_view_internal::SetPermission::Params; using extensions::core_api::extension_types::InjectDetails; +using ui_zoom::ZoomController; namespace web_view_internal = extensions::core_api::web_view_internal; namespace { @@ -332,12 +333,75 @@ bool WebViewInternalGetZoomFunction::RunAsyncSafe(WebViewGuest* guest) { web_view_internal::GetZoom::Params::Create(*args_)); EXTENSION_FUNCTION_VALIDATE(params.get()); - double zoom_factor = guest->zoom(); + double zoom_factor = guest->GetZoom(); SetResult(new base::FundamentalValue(zoom_factor)); SendResponse(true); return true; } +WebViewInternalSetZoomModeFunction::WebViewInternalSetZoomModeFunction() { +} + +WebViewInternalSetZoomModeFunction::~WebViewInternalSetZoomModeFunction() { +} + +bool WebViewInternalSetZoomModeFunction::RunAsyncSafe(WebViewGuest* guest) { + scoped_ptr<web_view_internal::SetZoomMode::Params> params( + web_view_internal::SetZoomMode::Params::Create(*args_)); + EXTENSION_FUNCTION_VALIDATE(params.get()); + + ZoomController::ZoomMode zoom_mode = ZoomController::ZOOM_MODE_DEFAULT; + switch (params->zoom_mode) { + case web_view_internal::ZOOM_MODE_PER_ORIGIN: + zoom_mode = ZoomController::ZOOM_MODE_DEFAULT; + break; + case web_view_internal::ZOOM_MODE_PER_VIEW: + zoom_mode = ZoomController::ZOOM_MODE_ISOLATED; + break; + case web_view_internal::ZOOM_MODE_DISABLED: + zoom_mode = ZoomController::ZOOM_MODE_DISABLED; + break; + default: + NOTREACHED(); + } + + guest->SetZoomMode(zoom_mode); + + SendResponse(true); + return true; +} + +WebViewInternalGetZoomModeFunction::WebViewInternalGetZoomModeFunction() { +} + +WebViewInternalGetZoomModeFunction::~WebViewInternalGetZoomModeFunction() { +} + +bool WebViewInternalGetZoomModeFunction::RunAsyncSafe(WebViewGuest* guest) { + scoped_ptr<web_view_internal::GetZoomMode::Params> params( + web_view_internal::GetZoomMode::Params::Create(*args_)); + EXTENSION_FUNCTION_VALIDATE(params.get()); + + web_view_internal::ZoomMode zoom_mode = web_view_internal::ZOOM_MODE_NONE; + switch (guest->GetZoomMode()) { + case ZoomController::ZOOM_MODE_DEFAULT: + zoom_mode = web_view_internal::ZOOM_MODE_PER_ORIGIN; + break; + case ZoomController::ZOOM_MODE_ISOLATED: + zoom_mode = web_view_internal::ZOOM_MODE_PER_VIEW; + break; + case ZoomController::ZOOM_MODE_DISABLED: + zoom_mode = web_view_internal::ZOOM_MODE_DISABLED; + break; + default: + NOTREACHED(); + } + + SetResult(new base::StringValue(web_view_internal::ToString(zoom_mode))); + SendResponse(true); + return true; +} + WebViewInternalFindFunction::WebViewInternalFindFunction() { } diff --git a/extensions/browser/api/guest_view/web_view/web_view_internal_api.h b/extensions/browser/api/guest_view/web_view/web_view_internal_api.h index cd23be2..650d530 100644 --- a/extensions/browser/api/guest_view/web_view/web_view_internal_api.h +++ b/extensions/browser/api/guest_view/web_view/web_view_internal_api.h @@ -211,6 +211,40 @@ class WebViewInternalGetZoomFunction : public WebViewInternalExtensionFunction { DISALLOW_COPY_AND_ASSIGN(WebViewInternalGetZoomFunction); }; +class WebViewInternalSetZoomModeFunction + : public WebViewInternalExtensionFunction { + public: + DECLARE_EXTENSION_FUNCTION("webViewInternal.setZoomMode", + WEBVIEWINTERNAL_SETZOOMMODE); + + WebViewInternalSetZoomModeFunction(); + + protected: + ~WebViewInternalSetZoomModeFunction() override; + + private: + bool RunAsyncSafe(WebViewGuest* guest) override; + + DISALLOW_COPY_AND_ASSIGN(WebViewInternalSetZoomModeFunction); +}; + +class WebViewInternalGetZoomModeFunction + : public WebViewInternalExtensionFunction { + public: + DECLARE_EXTENSION_FUNCTION("webViewInternal.getZoomMode", + WEBVIEWINTERNAL_GETZOOMMODE); + + WebViewInternalGetZoomModeFunction(); + + protected: + ~WebViewInternalGetZoomModeFunction() override; + + private: + bool RunAsyncSafe(WebViewGuest* guest) override; + + DISALLOW_COPY_AND_ASSIGN(WebViewInternalGetZoomModeFunction); +}; + class WebViewInternalFindFunction : public WebViewInternalExtensionFunction { public: DECLARE_EXTENSION_FUNCTION("webViewInternal.find", WEBVIEWINTERNAL_FIND); diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h index 5dda98d..5c0460b 100644 --- a/extensions/browser/extension_function_histogram_value.h +++ b/extensions/browser/extension_function_histogram_value.h @@ -1051,6 +1051,8 @@ enum HistogramValue { SETTINGSPRIVATE_GETPREF, NETWORKINGPRIVATE_FORGETNETWORK, EASYUNLOCKPRIVATE_HIDEERRORBUBBLE, + WEBVIEWINTERNAL_SETZOOMMODE, + WEBVIEWINTERNAL_GETZOOMMODE, // Last entry: Add new entries above and ensure to update // tools/metrics/histograms/histograms.xml. ENUM_BOUNDARY diff --git a/extensions/browser/guest_view/guest_view_base.cc b/extensions/browser/guest_view/guest_view_base.cc index 9a00f07..899037d 100644 --- a/extensions/browser/guest_view/guest_view_base.cc +++ b/extensions/browser/guest_view/guest_view_base.cc @@ -265,6 +265,11 @@ void GuestViewBase::InitWithWebContents( if (CanRunInDetachedState()) SetUpSizing(create_params); + // Observe guest zoom changes. + auto zoom_controller = + ui_zoom::ZoomController::FromWebContents(web_contents()); + zoom_controller->AddObserver(this); + // Give the derived class an opportunity to perform additional initialization. DidInitialize(create_params); } @@ -701,15 +706,26 @@ GuestViewBase::~GuestViewBase() { void GuestViewBase::OnZoomChanged( const ui_zoom::ZoomController::ZoomChangedEventData& data) { - auto guest_zoom_controller = - ui_zoom::ZoomController::FromWebContents(web_contents()); - if (content::ZoomValuesEqual(data.new_zoom_level, - guest_zoom_controller->GetZoomLevel())) { + if (data.web_contents == embedder_web_contents()) { + // The embedder's zoom level has changed. + auto guest_zoom_controller = + ui_zoom::ZoomController::FromWebContents(web_contents()); + if (content::ZoomValuesEqual(data.new_zoom_level, + guest_zoom_controller->GetZoomLevel())) { + return; + } + // When the embedder's zoom level doesn't match the guest's, then update the + // guest's zoom level to match. + guest_zoom_controller->SetZoomLevel(data.new_zoom_level); + + EmbedderZoomChanged(data.old_zoom_level, data.new_zoom_level); return; } - // When the embedder's zoom level doesn't match the guest's, then update the - // guest's zoom level to match. - guest_zoom_controller->SetZoomLevel(data.new_zoom_level); + + if (data.web_contents == web_contents()) { + // The guest's zoom level has changed. + GuestZoomChanged(data.old_zoom_level, data.new_zoom_level); + } } void GuestViewBase::DispatchEventToGuestProxy(Event* event) { diff --git a/extensions/browser/guest_view/guest_view_base.h b/extensions/browser/guest_view/guest_view_base.h index a7ea60a..ba9e721 100644 --- a/extensions/browser/guest_view/guest_view_base.h +++ b/extensions/browser/guest_view/guest_view_base.h @@ -112,6 +112,10 @@ class GuestViewBase : public content::BrowserPluginGuestDelegate, // web contents. virtual void EmbedderWillBeDestroyed() {} + // This method is called when the embedder's zoom changes. + virtual void EmbedderZoomChanged(double old_zoom_level, + double new_zoom_level) {} + // This method is called when the guest WebContents has been destroyed. This // object will be destroyed after this call returns. // @@ -125,6 +129,9 @@ class GuestViewBase : public content::BrowserPluginGuestDelegate, // work. virtual void GuestReady() {} + // This method is called when the guest's zoom changes. + virtual void GuestZoomChanged(double old_zoom_level, double new_zoom_level) {} + // This method is called when embedder WebContents's fullscreen is toggled. // // If the guest asked the embedder to enter fullscreen, the guest uses this @@ -296,7 +303,7 @@ class GuestViewBase : public content::BrowserPluginGuestDelegate, // ui_zoom::ZoomObserver implementation. void OnZoomChanged( - const ui_zoom::ZoomController::ZoomChangedEventData& data) override; + const ui_zoom::ZoomController::ZoomChangedEventData& data) final; // Dispatches an event to the guest proxy. void DispatchEventToGuestProxy(Event* event); diff --git a/extensions/browser/guest_view/web_view/web_view_guest.cc b/extensions/browser/guest_view/web_view/web_view_guest.cc index 9ed24ff..34c4a15 100644 --- a/extensions/browser/guest_view/web_view/web_view_guest.cc +++ b/extensions/browser/guest_view/web_view/web_view_guest.cc @@ -55,6 +55,7 @@ using content::RenderFrameHost; using content::ResourceType; using content::StoragePartition; using content::WebContents; +using ui_zoom::ZoomController; namespace extensions { @@ -169,6 +170,14 @@ void RemoveWebViewEventListenersOnIOThread( view_instance_id); } +double ConvertZoomLevelToZoomFactor(double zoom_level) { + double zoom_factor = content::ZoomLevelToZoomFactor(zoom_level); + // Because the conversion from zoom level to zoom factor isn't perfect, the + // resulting zoom factor is rounded to the nearest 6th decimal place. + zoom_factor = round(zoom_factor * 1000000) / 1000000; + return zoom_factor; +} + } // namespace // static @@ -443,6 +452,18 @@ bool WebViewGuest::IsDragAndDropEnabled() const { return true; } +void WebViewGuest::GuestZoomChanged(double old_zoom_level, + double new_zoom_level) { + // Dispatch the zoomchange event. + double old_zoom_factor = ConvertZoomLevelToZoomFactor(old_zoom_level); + double new_zoom_factor = ConvertZoomLevelToZoomFactor(new_zoom_level); + scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue()); + args->SetDouble(webview::kOldZoomFactor, old_zoom_factor); + args->SetDouble(webview::kNewZoomFactor, new_zoom_factor); + DispatchEventToView( + new GuestViewBase::Event(webview::kEventZoomChange, args.Pass())); +} + void WebViewGuest::WillDestroy() { if (!attached() && GetOpener()) GetOpener()->pending_new_windows_.erase(this); @@ -483,6 +504,16 @@ void WebViewGuest::FindReply(WebContents* source, final_update); } +double WebViewGuest::GetZoom() const { + double zoom_level = + ZoomController::FromWebContents(web_contents())->GetZoomLevel(); + return ConvertZoomLevelToZoomFactor(zoom_level); +} + +ZoomController::ZoomMode WebViewGuest::GetZoomMode() { + return ZoomController::FromWebContents(web_contents())->zoom_mode(); +} + bool WebViewGuest::HandleContextMenu( const content::ContextMenuParams& params) { if (!web_view_guest_delegate_) @@ -692,7 +723,6 @@ WebViewGuest::WebViewGuest(content::WebContents* owner_web_contents) is_overriding_user_agent_(false), guest_opaque_(true), javascript_dialog_helper_(this), - current_zoom_factor_(1.0), allow_scaling_(false), is_guest_fullscreen_(false), is_embedder_fullscreen_(false), @@ -731,13 +761,6 @@ void WebViewGuest::DidCommitProvisionalLoadForFrame( find_helper_.CancelAllFindSessions(); - // Update the current zoom factor for the new page. - ui_zoom::ZoomController* zoom_controller = - ui_zoom::ZoomController::FromWebContents(web_contents()); - DCHECK(zoom_controller); - current_zoom_factor_ = - content::ZoomLevelToZoomFactor(zoom_controller->GetZoomLevel()); - if (web_view_guest_delegate_) { web_view_guest_delegate_->OnDidCommitProvisionalLoadForFrame( !render_frame_host->GetParent()); @@ -1048,18 +1071,14 @@ void WebViewGuest::SetName(const std::string& name) { } void WebViewGuest::SetZoom(double zoom_factor) { - auto zoom_controller = - ui_zoom::ZoomController::FromWebContents(web_contents()); + auto zoom_controller = ZoomController::FromWebContents(web_contents()); DCHECK(zoom_controller); double zoom_level = content::ZoomFactorToZoomLevel(zoom_factor); zoom_controller->SetZoomLevel(zoom_level); +} - scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue()); - args->SetDouble(webview::kOldZoomFactor, current_zoom_factor_); - args->SetDouble(webview::kNewZoomFactor, zoom_factor); - DispatchEventToView( - new GuestViewBase::Event(webview::kEventZoomChange, args.Pass())); - current_zoom_factor_ = zoom_factor; +void WebViewGuest::SetZoomMode(ZoomController::ZoomMode zoom_mode) { + ZoomController::FromWebContents(web_contents())->SetZoomMode(zoom_mode); } void WebViewGuest::SetAllowTransparency(bool allow) { diff --git a/extensions/browser/guest_view/web_view/web_view_guest.h b/extensions/browser/guest_view/web_view/web_view_guest.h index 6bd2921..d6f3e32 100644 --- a/extensions/browser/guest_view/web_view/web_view_guest.h +++ b/extensions/browser/guest_view/web_view/web_view_guest.h @@ -62,6 +62,12 @@ class WebViewGuest : public GuestView<WebViewGuest>, int embedder_process_id, int web_view_instance_id); + // Get the current zoom. + double GetZoom() const; + + // Get the current zoom mode. + ui_zoom::ZoomController::ZoomMode GetZoomMode(); + // Request navigating the guest to the provided |src| URL. void NavigateGuest(const std::string& src, bool force_navigation); @@ -79,6 +85,9 @@ class WebViewGuest : public GuestView<WebViewGuest>, // Set the zoom factor. void SetZoom(double zoom_factor); + // Set the zoom mode. + void SetZoomMode(ui_zoom::ZoomController::ZoomMode zoom_mode); + void SetAllowScaling(bool allow); // Sets the transparency of the guest. @@ -106,6 +115,7 @@ class WebViewGuest : public GuestView<WebViewGuest>, void GuestReady() override; void GuestSizeChangedDueToAutoSize(const gfx::Size& old_size, const gfx::Size& new_size) override; + void GuestZoomChanged(double old_zoom_level, double new_zoom_level) override; bool IsAutoSizeSupported() const override; bool IsDragAndDropEnabled() const override; void WillAttachToEmbedder() override; @@ -176,9 +186,6 @@ class WebViewGuest : public GuestView<WebViewGuest>, const content::NotificationSource& source, const content::NotificationDetails& details) override; - // Returns the current zoom factor. - double zoom() const { return current_zoom_factor_; } - // Begin or continue a find request. void StartFindInternal( const base::string16& search_text, @@ -385,9 +392,6 @@ class WebViewGuest : public GuestView<WebViewGuest>, using PendingWindowMap = std::map<WebViewGuest*, NewWindowInfo>; PendingWindowMap pending_new_windows_; - // Stores the current zoom factor. - double current_zoom_factor_; - // Determines if this guest accepts pinch-zoom gestures. bool allow_scaling_; bool is_guest_fullscreen_; diff --git a/extensions/common/api/web_view_internal.json b/extensions/common/api/web_view_internal.json index 5440e90..c819408 100644 --- a/extensions/common/api/web_view_internal.json +++ b/extensions/common/api/web_view_internal.json @@ -63,6 +63,25 @@ "description": "Remove data accumulated on or after this date, represented in milliseconds since the epoch (accessible via the <code>getTime</code> method of the JavaScript <code>Date</code> object). If absent, defaults to 0 (which would remove all browsing data)." } } + }, + { + "id": "ZoomMode", + "type": "string", + "description": "Defines the how zooming is handled in the webview.", + "enum": [ + { + "name": "per-origin", + "description": "Zoom changes will persist in the zoomed page's origin, i.e. all other webviews in the same partition that are navigated to that same origin will be zoomed as well. Moreover, <code>per-origin</code> zoom changes are saved with the origin, meaning that when navigating to other pages in the same origin, they will all be zoomed to the same zoom factor." + }, + { + "name": "per-view", + "description": "Zoom changes only take effect in this webview, and zoom changes in other webviews will not affect the zooming of this webview. Also, <code>per-view</code> zoom changes are reset on navigation; navigating a webview will always load pages with their per-origin zoom factors (within the scope of the partition)." + }, + { + "name": "disabled", + "description": "Disables all zooming in the webview. The content will revert to the default zoom level, and all attempted zoom changes will be ignored." + } + ] } ], "functions": [ @@ -179,6 +198,54 @@ ] }, { + "name": "setZoomMode", + "type": "function", + "description": "Sets the zoom mode of the webview.", + "parameters": [ + { + "type": "integer", + "name": "instanceId", + "description": "The instance ID of the guest <webview> process." + }, + { + "$ref": "ZoomMode", + "name": "ZoomMode", + "description": "Defines how zooming is handled in the webview." + }, + { + "type": "function", + "name": "callback", + "description": "Called after the zoom mode has been changed.", + "optional": true, + "parameters": [] + } + ] + }, + { + "name": "getZoomMode", + "type": "function", + "description": "Gets the current zoom mode.", + "parameters": [ + { + "type": "integer", + "name": "instanceId", + "description": "The instance ID of the guest <webview> process." + }, + { + "type": "function", + "name": "callback", + "description": "Called with the webview's current zoom mode.", + "parameters": [ + { + "$ref": "ZoomMode", + "name": "ZoomMode", + "description": "The webview's current zoom mode." + } + ] + } + ] + }, + { "name": "find", "type": "function", "description": "Initiates a find-in-page request.", diff --git a/extensions/renderer/resources/guest_view/web_view/web_view_api_methods.js b/extensions/renderer/resources/guest_view/web_view/web_view_api_methods.js index f880a86..e42396e 100644 --- a/extensions/renderer/resources/guest_view/web_view/web_view_api_methods.js +++ b/extensions/renderer/resources/guest_view/web_view/web_view_api_methods.js @@ -42,6 +42,9 @@ var WEB_VIEW_API_METHODS = [ // Gets the current zoom factor. 'getZoom', + // Gets the current zoom mode of the webview. + 'getZoomMode', + // Navigates to a history entry using a history index relative to the current // navigation. 'go', @@ -70,6 +73,9 @@ var WEB_VIEW_API_METHODS = [ // Changes the zoom factor of the page. 'setZoom', + // Changes the zoom mode of the webview. + 'setZoomMode', + // Stops loading the current navigation if one is in progress. 'stop', diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index ee790d6..54d370a 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml @@ -49889,6 +49889,8 @@ Therefore, the affected-histogram name has to have at least one dot in it. <int value="990" label="SETTINGSPRIVATE_GETPREF"/> <int value="991" label="NETWORKINGPRIVATE_FORGETNETWORK"/> <int value="992" label="EASYUNLOCKPRIVATE_HIDEERRORBUBBLE"/> + <int value="993" label="WEBVIEWINTERNAL_SETZOOMMODE"/> + <int value="994" label="WEBVIEWINTERNAL_GETZOOMMODE"/> </enum> <enum name="ExtensionInstallCause" type="int"> |