1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/ui/zoom/zoom_controller.h" 6 7 #include "base/prefs/pref_service.h" 8 #include "base/process/kill.h" 9 #include "chrome/browser/profiles/profile.h" 10 #include "chrome/browser/ui/browser.h" 11 #include "chrome/browser/ui/tabs/tab_strip_model.h" 12 #include "chrome/common/pref_names.h" 13 #include "chrome/test/base/in_process_browser_test.h" 14 #include "chrome/test/base/ui_test_utils.h" 15 #include "content/public/browser/navigation_entry.h" 16 #include "content/public/browser/render_process_host.h" 17 #include "content/public/browser/render_view_host.h" 18 #include "content/public/browser/web_contents.h" 19 #include "content/public/common/page_type.h" 20 #include "content/public/test/browser_test_utils.h" 21 #include "testing/gmock/include/gmock/gmock.h" 22 23 typedef InProcessBrowserTest ZoomControllerBrowserTest; 24 25 bool operator==(const ZoomController::ZoomChangedEventData& lhs, 26 const ZoomController::ZoomChangedEventData& rhs) { 27 return lhs.web_contents == rhs.web_contents && 28 lhs.old_zoom_level == rhs.old_zoom_level && 29 lhs.new_zoom_level == rhs.new_zoom_level && 30 lhs.zoom_mode == rhs.zoom_mode && 31 lhs.can_show_bubble == rhs.can_show_bubble; 32 } 33 34 class ZoomChangedWatcher : public ZoomObserver { 35 public: 36 ZoomChangedWatcher( 37 content::WebContents* web_contents, 38 const ZoomController::ZoomChangedEventData& expected_event_data) 39 : web_contents_(web_contents), 40 expected_event_data_(expected_event_data), 41 message_loop_runner_(new content::MessageLoopRunner) { 42 ZoomController::FromWebContents(web_contents)->AddObserver(this); 43 } 44 virtual ~ZoomChangedWatcher() {} 45 46 void Wait() { message_loop_runner_->Run(); } 47 48 virtual void OnZoomChanged( 49 const ZoomController::ZoomChangedEventData& event_data) OVERRIDE { 50 if (event_data == expected_event_data_) 51 message_loop_runner_->Quit(); 52 } 53 54 private: 55 content::WebContents* web_contents_; 56 ZoomController::ZoomChangedEventData expected_event_data_; 57 scoped_refptr<content::MessageLoopRunner> message_loop_runner_; 58 59 DISALLOW_COPY_AND_ASSIGN(ZoomChangedWatcher); 60 }; 61 62 // TODO(wjmaclean): Enable this on Android when we can kill the process there. 63 #if defined(OS_ANDROID) 64 #define MAYBE_CrashedTabsDoNotChangeZoom DISABLED_CrashedTabsDoNotChangeZoom 65 #else 66 #define MAYBE_CrashedTabsDoNotChangeZoom CrashedTabsDoNotChangeZoom 67 #endif 68 IN_PROC_BROWSER_TEST_F(ZoomControllerBrowserTest, 69 MAYBE_CrashedTabsDoNotChangeZoom) { 70 // At the start of the test we are at a tab displaying about:blank. 71 content::WebContents* web_contents = 72 browser()->tab_strip_model()->GetActiveWebContents(); 73 74 ZoomController* zoom_controller = 75 ZoomController::FromWebContents(web_contents); 76 77 double old_zoom_level = zoom_controller->GetZoomLevel(); 78 double new_zoom_level = old_zoom_level + 0.5; 79 80 content::RenderProcessHost* host = web_contents->GetRenderProcessHost(); 81 { 82 content::RenderProcessHostWatcher crash_observer( 83 host, content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); 84 base::KillProcess(host->GetHandle(), 0, false); 85 crash_observer.Wait(); 86 } 87 EXPECT_FALSE(web_contents->GetRenderViewHost()->IsRenderViewLive()); 88 89 // The following attempt to change the zoom level for a crashed tab should 90 // fail. 91 zoom_controller->SetZoomLevel(new_zoom_level); 92 EXPECT_FLOAT_EQ(old_zoom_level, zoom_controller->GetZoomLevel()); 93 } 94 95 IN_PROC_BROWSER_TEST_F(ZoomControllerBrowserTest, OnPreferenceChanged) { 96 content::WebContents* web_contents = 97 browser()->tab_strip_model()->GetActiveWebContents(); 98 double new_default_zoom_level = 1.0; 99 // Since this page uses the default zoom level, the changes to the default 100 // zoom level will change the zoom level for this web_contents. 101 ZoomController::ZoomChangedEventData zoom_change_data( 102 web_contents, 103 new_default_zoom_level, 104 new_default_zoom_level, 105 ZoomController::ZOOM_MODE_DEFAULT, 106 true); 107 ZoomChangedWatcher zoom_change_watcher(web_contents, zoom_change_data); 108 // TODO(wjmaclean): Convert this to call partition-specific zoom level prefs 109 // when they become available. 110 browser()->profile()->GetPrefs()->SetDouble(prefs::kDefaultZoomLevel, 111 new_default_zoom_level); 112 // Because this test relies on a round-trip IPC to/from the renderer process, 113 // we need to wait for it to propagate. 114 zoom_change_watcher.Wait(); 115 } 116 117 IN_PROC_BROWSER_TEST_F(ZoomControllerBrowserTest, ErrorPagesDoNotZoom) { 118 ui_test_utils::NavigateToURL(browser(), GURL("http://kjfhkjsdf.com")); 119 content::WebContents* web_contents = 120 browser()->tab_strip_model()->GetActiveWebContents(); 121 122 ZoomController* zoom_controller = 123 ZoomController::FromWebContents(web_contents); 124 EXPECT_EQ( 125 content::PAGE_TYPE_ERROR, 126 web_contents->GetController().GetLastCommittedEntry()->GetPageType()); 127 128 double old_zoom_level = zoom_controller->GetZoomLevel(); 129 double new_zoom_level = old_zoom_level + 0.5; 130 131 // The following attempt to change the zoom level for an error page should 132 // fail. 133 zoom_controller->SetZoomLevel(new_zoom_level); 134 EXPECT_FLOAT_EQ(old_zoom_level, zoom_controller->GetZoomLevel()); 135 } 136