| // Copyright 2016 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <vector> |
| |
| #include "base/strings/string_util.h" |
| #include "content/browser/frame_host/frame_tree_node.h" |
| #include "content/browser/frame_host/render_frame_host_impl.h" |
| #include "content/browser/web_contents/web_contents_impl.h" |
| #include "content/public/browser/host_zoom_map.h" |
| #include "content/public/browser/navigation_entry.h" |
| #include "content/public/browser/notification_service.h" |
| #include "content/public/browser/notification_types.h" |
| #include "content/public/common/page_zoom.h" |
| #include "content/public/test/browser_test_utils.h" |
| #include "content/public/test/content_browser_test.h" |
| #include "content/public/test/content_browser_test_utils.h" |
| #include "content/public/test/test_navigation_observer.h" |
| #include "content/shell/browser/shell.h" |
| #include "content/test/content_browser_test_utils_internal.h" |
| #include "net/dns/mock_host_resolver.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "url/gurl.h" |
| |
| namespace content { |
| |
| // This class contains basic tests of zoom functionality. |
| class ZoomBrowserTest : public ContentBrowserTest { |
| public: |
| ZoomBrowserTest() {} |
| |
| protected: |
| void SetUpOnMainThread() override { |
| host_resolver()->AddRule("*", "127.0.0.1"); |
| SetupCrossSiteRedirector(embedded_test_server()); |
| ASSERT_TRUE(embedded_test_server()->Start()); |
| } |
| |
| WebContentsImpl* web_contents() { |
| return static_cast<WebContentsImpl*>(shell()->web_contents()); |
| } |
| }; |
| |
| |
| // This class contains tests to make sure that subframes zoom in a manner |
| // consistent with the top-level frame, even when the subframes are cross-site. |
| // Particular things we want to make sure of: |
| // |
| // * Subframes should always have the same zoom level as their main frame, even |
| // if the subframe's domain has a different zoom level stored in HostZoomMap. |
| // |
| // * The condition above should continue to hold after a navigation of the |
| // subframe. |
| // |
| // * Zoom changes applied to the mainframe should propagate to all subframes, |
| // regardless of whether they are same site or cross-site to the frame they are |
| // children of. |
| // |
| // The tests in this file rely on the notion that, when a page zooms, that |
| // subframes have both (1) a change in their frame rect, and (2) a change in |
| // their frame's scale. Since the page should scale as a unit, this means the |
| // innerWidth value of any subframe should be the same before and after the |
| // zoom (though it may transiently take on a different value). The |
| // FrameSizeObserver serves to watch for onresize events, and observes when |
| // the innerWidth is correctly set. |
| class IFrameZoomBrowserTest : public ContentBrowserTest { |
| public: |
| IFrameZoomBrowserTest() {} |
| |
| protected: |
| void SetUpOnMainThread() override { |
| host_resolver()->AddRule("*", "127.0.0.1"); |
| SetupCrossSiteRedirector(embedded_test_server()); |
| ASSERT_TRUE(embedded_test_server()->Start()); |
| } |
| |
| WebContentsImpl* web_contents() { |
| return static_cast<WebContentsImpl*>(shell()->web_contents()); |
| } |
| }; |
| |
| namespace { |
| |
| const double kTolerance = 0.1; // In CSS pixels. |
| |
| double GetMainframeWindowBorder(const ToRenderFrameHost& adapter) { |
| double border; |
| const char kGetMainframeBorder[] = "window.domAutomationController.send(" |
| "window.outerWidth - window.innerWidth" |
| ");"; |
| EXPECT_TRUE( |
| ExecuteScriptAndExtractDouble(adapter, kGetMainframeBorder, &border)); |
| return border; |
| } |
| |
| double GetMainFrameZoomFactor(const ToRenderFrameHost& adapter, double border) { |
| double zoom_factor; |
| EXPECT_TRUE(ExecuteScriptAndExtractDouble( |
| adapter, |
| JsReplace("window.domAutomationController.send(" |
| " (window.outerWidth - $1) / window.innerWidth);", |
| border), |
| &zoom_factor)); |
| return zoom_factor; |
| } |
| |
| double GetSubframeWidth(const ToRenderFrameHost& adapter) { |
| double width; |
| EXPECT_TRUE(ExecuteScriptAndExtractDouble( |
| adapter, "window.domAutomationController.send(window.innerWidth);", |
| &width)); |
| return width; |
| } |
| |
| // This struct is used to track changes to subframes after a main frame zoom |
| // change, so that we can test subframe inner widths with assurance that all the |
| // changes have finished propagating. |
| struct FrameResizeObserver { |
| FrameResizeObserver(RenderFrameHost* host, |
| std::string label, |
| double inner_width, |
| double tolerance) |
| : frame_host(host), |
| msg_label(std::move(label)), |
| zoomed_correctly(false), |
| expected_inner_width(inner_width), |
| tolerance(tolerance) { |
| SetupOnResizeCallback(host, msg_label); |
| } |
| |
| void SetupOnResizeCallback(const ToRenderFrameHost& adapter, |
| const std::string& label) { |
| const char kOnResizeCallbackSetup[] = |
| "document.body.onresize = function(){" |
| " window.domAutomationController.send('%s ' + window.innerWidth);" |
| "};"; |
| EXPECT_TRUE(ExecuteScript( |
| adapter, base::StringPrintf(kOnResizeCallbackSetup, label.c_str()))); |
| } |
| |
| void Check(const std::string& status_msg) { |
| if (!base::StartsWith(status_msg, msg_label, base::CompareCase::SENSITIVE)) |
| return; |
| |
| double inner_width = std::stod(status_msg.substr(msg_label.length() + 1)); |
| zoomed_correctly = std::abs(expected_inner_width - inner_width) < tolerance; |
| } |
| |
| FrameResizeObserver* toThis() {return this;} |
| |
| RenderFrameHost* frame_host; |
| std::string msg_label; |
| bool zoomed_correctly; |
| double expected_inner_width; |
| double tolerance; |
| }; |
| |
| // This struct is used to wait until a resize has occurred. |
| struct ResizeObserver { |
| ResizeObserver(RenderFrameHost* host) |
| : frame_host(host) { |
| SetupOnResizeCallback(host); |
| } |
| |
| void SetupOnResizeCallback(const ToRenderFrameHost& adapter) { |
| const char kOnResizeCallbackSetup[] = |
| "document.body.onresize = function(){" |
| " window.domAutomationController.send('Resized');" |
| "};"; |
| EXPECT_TRUE(ExecuteScript( |
| adapter, kOnResizeCallbackSetup)); |
| } |
| |
| bool IsResizeCallback(const std::string& status_msg) { |
| return status_msg == "Resized"; |
| } |
| |
| RenderFrameHost* frame_host; |
| }; |
| |
| void WaitForResize(DOMMessageQueue& msg_queue, ResizeObserver& observer) { |
| std::string status; |
| while (msg_queue.WaitForMessage(&status)) { |
| // Strip the double quotes from the message. |
| status = status.substr(1, status.length() -2); |
| if (observer.IsResizeCallback(status)) |
| break; |
| } |
| } |
| |
| void WaitAndCheckFrameZoom( |
| DOMMessageQueue& msg_queue, |
| std::vector<FrameResizeObserver>& frame_observers) { |
| std::string status; |
| while (msg_queue.WaitForMessage(&status)) { |
| // Strip the double quotes from the message. |
| status = status.substr(1, status.length() -2); |
| |
| bool all_zoomed_correctly = true; |
| |
| // Use auto& to operate on a reference, and not a copy. |
| for (auto& observer : frame_observers) { |
| observer.Check(status); |
| all_zoomed_correctly = all_zoomed_correctly && observer.zoomed_correctly; |
| } |
| |
| if (all_zoomed_correctly) |
| break; |
| } |
| } |
| |
| } // namespace |
| |
| IN_PROC_BROWSER_TEST_F(ZoomBrowserTest, ZoomPreservedOnReload) { |
| std::string top_level_host("a.com"); |
| |
| GURL main_url(embedded_test_server()->GetURL( |
| top_level_host, "/cross_site_iframe_factory.html?a(b(a))")); |
| EXPECT_TRUE(NavigateToURL(shell(), main_url)); |
| NavigationEntry* entry = |
| web_contents()->GetController().GetLastCommittedEntry(); |
| ASSERT_TRUE(entry); |
| GURL loaded_url = HostZoomMap::GetURLFromEntry(entry); |
| EXPECT_EQ(top_level_host, loaded_url.host()); |
| |
| FrameTreeNode* root = |
| static_cast<WebContentsImpl*>(web_contents())->GetFrameTree()->root(); |
| double main_frame_window_border = GetMainframeWindowBorder(web_contents()); |
| |
| HostZoomMap* host_zoom_map = HostZoomMap::GetForWebContents(web_contents()); |
| double default_zoom_level = host_zoom_map->GetDefaultZoomLevel(); |
| EXPECT_EQ(0.0, default_zoom_level); |
| |
| EXPECT_DOUBLE_EQ( |
| 1.0, GetMainFrameZoomFactor(web_contents(), main_frame_window_border)); |
| |
| const double new_zoom_factor = 2.5; |
| |
| // Set the new zoom, wait for the page to be resized, and sanity-check that |
| // the zoom was applied. |
| { |
| DOMMessageQueue msg_queue; |
| ResizeObserver observer(root->current_frame_host()); |
| |
| const double new_zoom_level = |
| default_zoom_level + ZoomFactorToZoomLevel(new_zoom_factor); |
| host_zoom_map->SetZoomLevelForHost(top_level_host, new_zoom_level); |
| |
| WaitForResize(msg_queue, observer); |
| } |
| |
| // Make this comparison approximate for Nexus5X test; |
| // https://crbug.com/622858. |
| EXPECT_NEAR( |
| new_zoom_factor, |
| GetMainFrameZoomFactor(web_contents(), main_frame_window_border), |
| 0.01); |
| |
| // Now the actual test: Reload the page and check that the main frame is |
| // still properly zoomed. |
| WindowedNotificationObserver load_stop_observer( |
| NOTIFICATION_LOAD_STOP, |
| NotificationService::AllSources()); |
| shell()->Reload(); |
| load_stop_observer.Wait(); |
| |
| EXPECT_NEAR( |
| new_zoom_factor, |
| GetMainFrameZoomFactor(web_contents(), main_frame_window_border), |
| 0.01); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(IFrameZoomBrowserTest, SubframesZoomProperly) { |
| std::string top_level_host("a.com"); |
| GURL main_url(embedded_test_server()->GetURL( |
| top_level_host, "/cross_site_iframe_factory.html?a(b(a))")); |
| EXPECT_TRUE(NavigateToURL(shell(), main_url)); |
| NavigationEntry* entry = |
| web_contents()->GetController().GetLastCommittedEntry(); |
| ASSERT_TRUE(entry); |
| GURL loaded_url = HostZoomMap::GetURLFromEntry(entry); |
| EXPECT_EQ(top_level_host, loaded_url.host()); |
| |
| FrameTreeNode* root = |
| static_cast<WebContentsImpl*>(web_contents())->GetFrameTree()->root(); |
| RenderFrameHostImpl* child = root->child_at(0)->current_frame_host(); |
| RenderFrameHostImpl* grandchild = |
| root->child_at(0)->child_at(0)->current_frame_host(); |
| |
| // The following calls must be made when the page's scale factor = 1.0. |
| double scale_one_child_width = GetSubframeWidth(child); |
| double scale_one_grandchild_width = GetSubframeWidth(grandchild); |
| double main_frame_window_border = GetMainframeWindowBorder(web_contents()); |
| |
| HostZoomMap* host_zoom_map = HostZoomMap::GetForWebContents(web_contents()); |
| double default_zoom_level = host_zoom_map->GetDefaultZoomLevel(); |
| EXPECT_EQ(0.0, default_zoom_level); |
| |
| EXPECT_DOUBLE_EQ( |
| 1.0, GetMainFrameZoomFactor(web_contents(), main_frame_window_border)); |
| |
| const double new_zoom_factor = 2.5; |
| { |
| DOMMessageQueue msg_queue; |
| |
| std::vector<FrameResizeObserver> frame_observers; |
| frame_observers.emplace_back(child, "child", |
| scale_one_child_width, kTolerance); |
| frame_observers.emplace_back(grandchild, "grandchild", |
| scale_one_grandchild_width, kTolerance); |
| |
| const double new_zoom_level = |
| default_zoom_level + ZoomFactorToZoomLevel(new_zoom_factor); |
| host_zoom_map->SetZoomLevelForHost(top_level_host, new_zoom_level); |
| |
| WaitAndCheckFrameZoom(msg_queue, frame_observers); |
| } |
| |
| // Make this comparison approximate for Nexus5X test; |
| // https://crbug.com/622858. |
| EXPECT_NEAR( |
| new_zoom_factor, |
| GetMainFrameZoomFactor(web_contents(), main_frame_window_border), |
| 0.01); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(IFrameZoomBrowserTest, SubframesDontZoomIndependently) { |
| std::string top_level_host("a.com"); |
| GURL main_url(embedded_test_server()->GetURL( |
| top_level_host, "/cross_site_iframe_factory.html?a(b(a))")); |
| EXPECT_TRUE(NavigateToURL(shell(), main_url)); |
| NavigationEntry* entry = |
| web_contents()->GetController().GetLastCommittedEntry(); |
| ASSERT_TRUE(entry); |
| GURL loaded_url = HostZoomMap::GetURLFromEntry(entry); |
| EXPECT_EQ(top_level_host, loaded_url.host()); |
| |
| FrameTreeNode* root = |
| static_cast<WebContentsImpl*>(web_contents())->GetFrameTree()->root(); |
| RenderFrameHostImpl* child = root->child_at(0)->current_frame_host(); |
| RenderFrameHostImpl* grandchild = |
| root->child_at(0)->child_at(0)->current_frame_host(); |
| |
| // The following calls must be made when the page's scale factor = 1.0. |
| double scale_one_child_width = GetSubframeWidth(child); |
| double scale_one_grandchild_width = GetSubframeWidth(grandchild); |
| double main_frame_window_border = GetMainframeWindowBorder(web_contents()); |
| |
| HostZoomMap* host_zoom_map = HostZoomMap::GetForWebContents(web_contents()); |
| double default_zoom_level = host_zoom_map->GetDefaultZoomLevel(); |
| EXPECT_EQ(0.0, default_zoom_level); |
| |
| EXPECT_DOUBLE_EQ( |
| 1.0, GetMainFrameZoomFactor(web_contents(), main_frame_window_border)); |
| |
| const double new_zoom_factor = 2.0; |
| const double new_zoom_level = |
| default_zoom_level + ZoomFactorToZoomLevel(new_zoom_factor); |
| |
| // This should not cause the nested iframe to change its zoom. |
| host_zoom_map->SetZoomLevelForHost("b.com", new_zoom_level); |
| |
| EXPECT_DOUBLE_EQ( |
| 1.0, GetMainFrameZoomFactor(web_contents(), main_frame_window_border)); |
| EXPECT_EQ(scale_one_child_width, GetSubframeWidth(child)); |
| EXPECT_EQ(scale_one_grandchild_width, GetSubframeWidth(grandchild)); |
| |
| // When we navigate so that b.com is the top-level site, then it has the |
| // expected zoom. |
| GURL new_url = embedded_test_server()->GetURL("b.com", "/title1.html"); |
| EXPECT_TRUE(NavigateToURL(shell(), new_url)); |
| EXPECT_DOUBLE_EQ( |
| new_zoom_factor, |
| GetMainFrameZoomFactor(web_contents(), main_frame_window_border)); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(IFrameZoomBrowserTest, AllFramesGetDefaultZoom) { |
| std::string top_level_host("a.com"); |
| GURL main_url(embedded_test_server()->GetURL( |
| top_level_host, "/cross_site_iframe_factory.html?a(b(a))")); |
| EXPECT_TRUE(NavigateToURL(shell(), main_url)); |
| NavigationEntry* entry = |
| web_contents()->GetController().GetLastCommittedEntry(); |
| ASSERT_TRUE(entry); |
| GURL loaded_url = HostZoomMap::GetURLFromEntry(entry); |
| EXPECT_EQ(top_level_host, loaded_url.host()); |
| |
| FrameTreeNode* root = |
| static_cast<WebContentsImpl*>(web_contents())->GetFrameTree()->root(); |
| RenderFrameHostImpl* child = root->child_at(0)->current_frame_host(); |
| RenderFrameHostImpl* grandchild = |
| root->child_at(0)->child_at(0)->current_frame_host(); |
| |
| // The following calls must be made when the page's scale factor = 1.0. |
| double scale_one_child_width = GetSubframeWidth(child); |
| double scale_one_grandchild_width = GetSubframeWidth(grandchild); |
| double main_frame_window_border = GetMainframeWindowBorder(web_contents()); |
| |
| HostZoomMap* host_zoom_map = HostZoomMap::GetForWebContents(web_contents()); |
| double default_zoom_level = host_zoom_map->GetDefaultZoomLevel(); |
| EXPECT_EQ(0.0, default_zoom_level); |
| |
| EXPECT_DOUBLE_EQ( |
| 1.0, GetMainFrameZoomFactor(web_contents(), main_frame_window_border)); |
| |
| const double new_default_zoom_factor = 2.0; |
| { |
| DOMMessageQueue msg_queue; |
| |
| std::vector<FrameResizeObserver> frame_observers; |
| frame_observers.emplace_back(child, "child", |
| scale_one_child_width, kTolerance); |
| frame_observers.emplace_back(grandchild, "grandchild", |
| scale_one_grandchild_width, kTolerance); |
| |
| const double new_default_zoom_level = |
| default_zoom_level + ZoomFactorToZoomLevel(new_default_zoom_factor); |
| |
| host_zoom_map->SetZoomLevelForHost("b.com", new_default_zoom_level + 1.0); |
| host_zoom_map->SetDefaultZoomLevel(new_default_zoom_level); |
| |
| WaitAndCheckFrameZoom(msg_queue, frame_observers); |
| } |
| // Make this comparison approximate for Nexus5X test; |
| // https://crbug.com/622858. |
| EXPECT_NEAR( |
| new_default_zoom_factor, |
| GetMainFrameZoomFactor(web_contents(), main_frame_window_border), |
| 0.01 |
| ); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(IFrameZoomBrowserTest, SiblingFramesZoom) { |
| std::string top_level_host("a.com"); |
| GURL main_url(embedded_test_server()->GetURL( |
| top_level_host, "/cross_site_iframe_factory.html?a(b,b)")); |
| EXPECT_TRUE(NavigateToURL(shell(), main_url)); |
| NavigationEntry* entry = |
| web_contents()->GetController().GetLastCommittedEntry(); |
| ASSERT_TRUE(entry); |
| GURL loaded_url = HostZoomMap::GetURLFromEntry(entry); |
| EXPECT_EQ(top_level_host, loaded_url.host()); |
| |
| FrameTreeNode* root = |
| static_cast<WebContentsImpl*>(web_contents())->GetFrameTree()->root(); |
| RenderFrameHostImpl* child1 = root->child_at(0)->current_frame_host(); |
| RenderFrameHostImpl* child2 = root->child_at(1)->current_frame_host(); |
| |
| // The following calls must be made when the page's scale factor = 1.0. |
| double scale_one_child1_width = GetSubframeWidth(child1); |
| double scale_one_child2_width = GetSubframeWidth(child2); |
| double main_frame_window_border = GetMainframeWindowBorder(web_contents()); |
| |
| HostZoomMap* host_zoom_map = HostZoomMap::GetForWebContents(web_contents()); |
| double default_zoom_level = host_zoom_map->GetDefaultZoomLevel(); |
| EXPECT_EQ(0.0, default_zoom_level); |
| |
| EXPECT_DOUBLE_EQ( |
| 1.0, GetMainFrameZoomFactor(web_contents(), main_frame_window_border)); |
| |
| const double new_zoom_factor = 2.5; |
| { |
| DOMMessageQueue msg_queue; |
| |
| std::vector<FrameResizeObserver> frame_observers; |
| frame_observers.emplace_back(child1, "child1", |
| scale_one_child1_width, kTolerance); |
| frame_observers.emplace_back(child2, "child2", |
| scale_one_child2_width, kTolerance); |
| |
| const double new_zoom_level = |
| default_zoom_level + ZoomFactorToZoomLevel(new_zoom_factor); |
| host_zoom_map->SetZoomLevelForHost(top_level_host, new_zoom_level); |
| |
| WaitAndCheckFrameZoom(msg_queue, frame_observers); |
| } |
| |
| // Make this comparison approximate for Nexus5X test; |
| // https://crbug.com/622858. |
| EXPECT_NEAR( |
| new_zoom_factor, |
| GetMainFrameZoomFactor(web_contents(), main_frame_window_border), |
| 0.01); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(IFrameZoomBrowserTest, SubframeRetainsZoomOnNavigation) { |
| std::string top_level_host("a.com"); |
| GURL main_url(embedded_test_server()->GetURL( |
| top_level_host, "/cross_site_iframe_factory.html?a(b)")); |
| EXPECT_TRUE(NavigateToURL(shell(), main_url)); |
| NavigationEntry* entry = |
| web_contents()->GetController().GetLastCommittedEntry(); |
| ASSERT_TRUE(entry); |
| GURL loaded_url = HostZoomMap::GetURLFromEntry(entry); |
| EXPECT_EQ(top_level_host, loaded_url.host()); |
| |
| FrameTreeNode* root = |
| static_cast<WebContentsImpl*>(web_contents())->GetFrameTree()->root(); |
| RenderFrameHostImpl* child = root->child_at(0)->current_frame_host(); |
| |
| // The following calls must be made when the page's scale factor = 1.0. |
| double scale_one_child_width = GetSubframeWidth(child); |
| double main_frame_window_border = GetMainframeWindowBorder(web_contents()); |
| |
| HostZoomMap* host_zoom_map = HostZoomMap::GetForWebContents(web_contents()); |
| double default_zoom_level = host_zoom_map->GetDefaultZoomLevel(); |
| EXPECT_EQ(0.0, default_zoom_level); |
| |
| EXPECT_DOUBLE_EQ( |
| 1.0, GetMainFrameZoomFactor(web_contents(), main_frame_window_border)); |
| |
| const double new_zoom_factor = 0.5; |
| { |
| DOMMessageQueue msg_queue; |
| |
| std::vector<FrameResizeObserver> frame_observers; |
| frame_observers.emplace_back(child, "child", |
| scale_one_child_width, kTolerance); |
| |
| const double new_zoom_level = |
| default_zoom_level + ZoomFactorToZoomLevel(new_zoom_factor); |
| host_zoom_map->SetZoomLevelForHost(top_level_host, new_zoom_level); |
| |
| WaitAndCheckFrameZoom(msg_queue, frame_observers); |
| } |
| |
| // Make this comparison approximate for Nexus5X test; |
| // https://crbug.com/622858. |
| EXPECT_NEAR( |
| new_zoom_factor, |
| GetMainFrameZoomFactor(web_contents(), main_frame_window_border), |
| 0.01 |
| ); |
| |
| // Navigate child frame cross site, and make sure zoom is the same. |
| TestNavigationObserver observer(web_contents()); |
| GURL url = embedded_test_server()->GetURL("c.com", "/title1.html"); |
| NavigateFrameToURL(root->child_at(0), url); |
| EXPECT_TRUE(observer.last_navigation_succeeded()); |
| EXPECT_EQ(url, observer.last_navigation_url()); |
| |
| // Check that the child frame maintained the same scale after navigating |
| // cross-site. |
| double new_child_width = |
| GetSubframeWidth(root->child_at(0)->current_frame_host()); |
| EXPECT_EQ(scale_one_child_width, new_child_width); |
| } |
| |
| // http://crbug.com/609213 |
| IN_PROC_BROWSER_TEST_F(IFrameZoomBrowserTest, |
| RedirectToPageWithSubframeZoomsCorrectly) { |
| std::string initial_host("a.com"); |
| std::string redirected_host("b.com"); |
| EXPECT_TRUE(NavigateToURL(shell(), GURL(embedded_test_server()->GetURL( |
| initial_host, "/title2.html")))); |
| double main_frame_window_border = GetMainframeWindowBorder(web_contents()); |
| EXPECT_DOUBLE_EQ( |
| 1.0, GetMainFrameZoomFactor(web_contents(), main_frame_window_border)); |
| |
| // Set a zoom level for b.com before we navigate to it. |
| const double kZoomFactorForRedirectedHost = 1.5; |
| HostZoomMap* host_zoom_map = HostZoomMap::GetForWebContents(web_contents()); |
| host_zoom_map->SetZoomLevelForHost( |
| redirected_host, ZoomFactorToZoomLevel(kZoomFactorForRedirectedHost)); |
| |
| // Navigation to a.com doesn't change the zoom level, but when it redirects |
| // to b.com, and then a subframe loads, the zoom should change. |
| GURL redirect_url(embedded_test_server()->GetURL( |
| redirected_host, "/cross_site_iframe_factory.html?b(b)")); |
| GURL url(embedded_test_server()->GetURL( |
| initial_host, "/client-redirect?" + redirect_url.spec())); |
| |
| NavigateToURLBlockUntilNavigationsComplete(shell(), url, 2); |
| EXPECT_TRUE(IsLastCommittedEntryOfPageType(web_contents(), PAGE_TYPE_NORMAL)); |
| EXPECT_EQ(redirect_url, web_contents()->GetLastCommittedURL()); |
| |
| EXPECT_NEAR(kZoomFactorForRedirectedHost, |
| GetMainFrameZoomFactor(web_contents(), main_frame_window_border), |
| 0.01); |
| } |
| |
| // Tests that on cross-site navigation from a page that has a subframe, the |
| // appropriate zoom is applied to the new page. |
| // crbug.com/673065 |
| IN_PROC_BROWSER_TEST_F(IFrameZoomBrowserTest, |
| SubframesDontBreakConnectionToRenderer) { |
| std::string top_level_host("a.com"); |
| GURL main_url(embedded_test_server()->GetURL( |
| top_level_host, "/page_with_iframe_and_link.html")); |
| EXPECT_TRUE(NavigateToURL(shell(), main_url)); |
| NavigationEntry* entry = |
| web_contents()->GetController().GetLastCommittedEntry(); |
| ASSERT_TRUE(entry); |
| GURL loaded_url = HostZoomMap::GetURLFromEntry(entry); |
| EXPECT_EQ(top_level_host, loaded_url.host()); |
| |
| // The following calls must be made when the page's scale factor = 1.0. |
| double main_frame_window_border = GetMainframeWindowBorder(web_contents()); |
| |
| HostZoomMap* host_zoom_map = HostZoomMap::GetForWebContents(web_contents()); |
| double default_zoom_level = host_zoom_map->GetDefaultZoomLevel(); |
| EXPECT_EQ(0.0, default_zoom_level); |
| EXPECT_DOUBLE_EQ( |
| 1.0, GetMainFrameZoomFactor(web_contents(), main_frame_window_border)); |
| |
| // Set a zoom for a host that will be navigated to below. |
| const double new_zoom_factor = 2.0; |
| const double new_zoom_level = |
| default_zoom_level + ZoomFactorToZoomLevel(new_zoom_factor); |
| host_zoom_map->SetZoomLevelForHost("foo.com", new_zoom_level); |
| |
| // Navigate forward in the same RFH to a site with that host via a |
| // renderer-initiated navigation. |
| { |
| const char kReplacePortNumber[] = |
| "window.domAutomationController.send(setPortNumber(%d));"; |
| uint16_t port_number = embedded_test_server()->port(); |
| bool success = false; |
| EXPECT_TRUE(ExecuteScriptAndExtractBool( |
| shell(), base::StringPrintf(kReplacePortNumber, port_number), |
| &success)); |
| TestNavigationObserver observer(shell()->web_contents()); |
| GURL url = embedded_test_server()->GetURL("foo.com", "/title2.html"); |
| success = false; |
| EXPECT_TRUE(ExecuteScriptAndExtractBool( |
| shell(), "window.domAutomationController.send(clickCrossSiteLink());", |
| &success)); |
| EXPECT_TRUE(success); |
| EXPECT_TRUE(WaitForLoadStop(shell()->web_contents())); |
| EXPECT_EQ(url, observer.last_navigation_url()); |
| EXPECT_TRUE(observer.last_navigation_succeeded()); |
| } |
| |
| // Check that the requested zoom has been applied to the new site. |
| // NOTE: Local observation on Linux has shown that this comparison has to be |
| // approximate. As the common failure mode would be that the zoom is ~1 |
| // instead of ~2, this approximation shouldn't be problematic. |
| EXPECT_NEAR( |
| new_zoom_factor, |
| GetMainFrameZoomFactor(web_contents(), main_frame_window_border), |
| .1); |
| } |
| |
| } // namespace content |