OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 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 "base/command_line.h" |
| 6 #include "base/strings/utf_string_conversions.h" |
| 7 #include "content/browser/wake_lock/wake_lock_dispatcher_host.h" |
| 8 #include "content/browser/web_contents/web_contents_impl.h" |
| 9 #include "content/public/common/content_switches.h" |
| 10 #include "content/public/test/browser_test_utils.h" |
| 11 #include "content/public/test/content_browser_test.h" |
| 12 #include "content/public/test/content_browser_test_utils.h" |
| 13 #include "content/public/test/test_navigation_observer.h" |
| 14 #include "content/shell/browser/shell.h" |
| 15 #include "content/test/content_browser_test_utils_internal.h" |
| 16 #include "net/dns/mock_host_resolver.h" |
| 17 #include "net/test/embedded_test_server/embedded_test_server.h" |
| 18 |
| 19 namespace content { |
| 20 |
| 21 class WakeLockWatcher : public WakeLockDispatcherHost::Observer { |
| 22 public: |
| 23 explicit WakeLockWatcher(WakeLockDispatcherHost* host) |
| 24 : host_(host) { |
| 25 host_->AddObserver(this); |
| 26 } |
| 27 |
| 28 virtual ~WakeLockWatcher() { |
| 29 host_->RemoveObserver(this); |
| 30 } |
| 31 |
| 32 void Wait() { |
| 33 loop_.Run(); |
| 34 } |
| 35 |
| 36 protected: |
| 37 void OnUpdate() override { |
| 38 loop_.Quit(); |
| 39 } |
| 40 |
| 41 WakeLockDispatcherHost* host_; |
| 42 base::RunLoop loop_; |
| 43 |
| 44 DISALLOW_COPY_AND_ASSIGN(WakeLockWatcher); |
| 45 }; |
| 46 |
| 47 class ChangeWakeLockWatcher : public WakeLockWatcher { |
| 48 public: |
| 49 explicit ChangeWakeLockWatcher(WakeLockDispatcherHost* host) |
| 50 : WakeLockWatcher(host) { |
| 51 has_blocker_ = host_->has_blocker_for_testing(); |
| 52 } |
| 53 |
| 54 private: |
| 55 void OnUpdate() override { |
| 56 if (host_->has_blocker_for_testing() != has_blocker_) |
| 57 loop_.Quit(); |
| 58 } |
| 59 |
| 60 bool has_blocker_; |
| 61 |
| 62 DISALLOW_COPY_AND_ASSIGN(ChangeWakeLockWatcher); |
| 63 }; |
| 64 |
| 65 class WakeLockTest : public ContentBrowserTest { |
| 66 public: |
| 67 void SetUpCommandLine(base::CommandLine* command_line) override { |
| 68 command_line->AppendSwitch( |
| 69 switches::kEnableExperimentalWebPlatformFeatures); |
| 70 command_line->AppendSwitch(switches::kSitePerProcess); |
| 71 } |
| 72 |
| 73 void SetUpOnMainThread() override { |
| 74 host_resolver()->AddRule("*", "127.0.0.1"); |
| 75 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); |
| 76 SetupCrossSiteRedirector(embedded_test_server()); |
| 77 } |
| 78 |
| 79 protected: |
| 80 bool IsScreenBlocked() const { |
| 81 const WakeLockDispatcherHost* dispatcher = GetWLDHForWebContents(); |
| 82 CHECK(dispatcher); |
| 83 return dispatcher->has_blocker_for_testing(); |
| 84 } |
| 85 |
| 86 void LoadTestURL(const char* url_name) const { |
| 87 GURL test_url = GetTestUrl("wake_lock", url_name); |
| 88 ASSERT_TRUE(NavigateToURL(shell(), test_url)); |
| 89 } |
| 90 |
| 91 void LoadTestURLAndLockScreen(const char* url_name) const { |
| 92 LoadTestURL(url_name); |
| 93 EXPECT_FALSE(IsScreenBlocked()); |
| 94 |
| 95 // Lock screen |
| 96 ExecuteJavaScriptAndWaitChangeStatus("screen.keepAwake = true;"); |
| 97 EXPECT_TRUE(IsScreenBlocked()); |
| 98 } |
| 99 |
| 100 void ExecuteJavaScript(const char* js) const { |
| 101 shell()->web_contents()->GetMainFrame()-> |
| 102 ExecuteJavaScript(base::UTF8ToUTF16(js)); |
| 103 } |
| 104 |
| 105 void ExecuteJavaScriptAndWait(const char* js) const { |
| 106 WakeLockWatcher watcher(GetWLDHForWebContents()); |
| 107 ExecuteJavaScript(js); |
| 108 watcher.Wait(); |
| 109 } |
| 110 |
| 111 void ExecuteJavaScriptAndWaitChangeStatus(const char* js) const { |
| 112 ChangeWakeLockWatcher watcher(GetWLDHForWebContents()); |
| 113 ExecuteJavaScript(js); |
| 114 watcher.Wait(); |
| 115 } |
| 116 |
| 117 bool ExecuteJavaScriptAndGetBool(const char* js) const { |
| 118 bool bool_value = false; |
| 119 scoped_ptr<base::Value> value = ExecuteScriptAndGetValue( |
| 120 shell()->web_contents()->GetMainFrame(), js); |
| 121 EXPECT_TRUE(value->GetAsBoolean(&bool_value)); |
| 122 return bool_value; |
| 123 } |
| 124 |
| 125 bool GetScreenKeepAwakeInJS() const { |
| 126 return ExecuteJavaScriptAndGetBool("screen.keepAwake"); |
| 127 } |
| 128 |
| 129 WakeLockDispatcherHost* GetWLDHForWebContents() const { |
| 130 WebContentsImpl* web_contents_impl = |
| 131 static_cast<WebContentsImpl*>(shell()->web_contents()); |
| 132 return web_contents_impl->wake_lock_dispatcher_host(); |
| 133 } |
| 134 }; |
| 135 |
| 136 IN_PROC_BROWSER_TEST_F(WakeLockTest, WakeLockApiIsPresent) { |
| 137 LoadTestURL("../title1.html"); |
| 138 |
| 139 EXPECT_FALSE(IsScreenBlocked()); |
| 140 EXPECT_TRUE(ExecuteJavaScriptAndGetBool( |
| 141 "typeof screen.keepAwake !== undefined")); |
| 142 } |
| 143 |
| 144 IN_PROC_BROWSER_TEST_F(WakeLockTest, LockAndUnlockScreenInMainFrame) { |
| 145 LoadTestURL("../title1.html"); |
| 146 |
| 147 // Screen is not locked on start |
| 148 EXPECT_FALSE(IsScreenBlocked()); |
| 149 |
| 150 // Check attribute 'screen.keepAwake' in JavaScript |
| 151 EXPECT_FALSE(GetScreenKeepAwakeInJS()); |
| 152 |
| 153 // Intention to lock screen |
| 154 ExecuteJavaScriptAndWaitChangeStatus("screen.keepAwake = true;"); |
| 155 |
| 156 // Check attribute |
| 157 EXPECT_TRUE(GetScreenKeepAwakeInJS()); |
| 158 EXPECT_TRUE(IsScreenBlocked()); |
| 159 |
| 160 // Set attribute to false, no longer keep screen awake |
| 161 ExecuteJavaScriptAndWaitChangeStatus("screen.keepAwake = false;"); |
| 162 |
| 163 // Check attribute in JS |
| 164 EXPECT_FALSE(GetScreenKeepAwakeInJS()); |
| 165 |
| 166 // Screen should not be locked now. |
| 167 EXPECT_FALSE(IsScreenBlocked()); |
| 168 } |
| 169 |
| 170 IN_PROC_BROWSER_TEST_F(WakeLockTest, ManyLockOneUnlock) { |
| 171 LoadTestURLAndLockScreen("../title1.html"); |
| 172 |
| 173 // Intention to lock screen in main frame when screen is locked |
| 174 ExecuteJavaScriptAndWait("screen.keepAwake = true;"); |
| 175 EXPECT_TRUE(IsScreenBlocked()); |
| 176 |
| 177 ExecuteJavaScriptAndWaitChangeStatus("screen.keepAwake = false;"); |
| 178 EXPECT_FALSE(IsScreenBlocked()); |
| 179 } |
| 180 |
| 181 IN_PROC_BROWSER_TEST_F(WakeLockTest, LockScreenInMainFrameAndNestedFrame) { |
| 182 LoadTestURL("page_with_iframe.html"); |
| 183 |
| 184 EXPECT_FALSE(IsScreenBlocked()); |
| 185 |
| 186 // Lock screen in nested frame |
| 187 ExecuteJavaScriptAndWaitChangeStatus( |
| 188 "document.getElementById('nested_frame')." |
| 189 "contentWindow.screen.keepAwake = true;"); |
| 190 |
| 191 // Screen is locked now |
| 192 EXPECT_TRUE(IsScreenBlocked()); |
| 193 |
| 194 // But in main frame screen.keepAwake is false |
| 195 EXPECT_FALSE(GetScreenKeepAwakeInJS()); |
| 196 |
| 197 // Lock screen in main frame |
| 198 ExecuteJavaScriptAndWait("screen.keepAwake = true;"); |
| 199 |
| 200 EXPECT_TRUE(GetScreenKeepAwakeInJS()); |
| 201 EXPECT_TRUE(IsScreenBlocked()); |
| 202 |
| 203 // Unlock screen in nested frame |
| 204 ExecuteJavaScriptAndWait("document.getElementById('nested_frame')." |
| 205 "contentWindow.screen.keepAwake = false;"); |
| 206 |
| 207 // screen.keepAwake in nested frame is false, but screen is locked now |
| 208 EXPECT_TRUE(IsScreenBlocked()); |
| 209 |
| 210 // Unlock screen in main frame |
| 211 ExecuteJavaScriptAndWaitChangeStatus("screen.keepAwake = false;"); |
| 212 |
| 213 // Screen is unlock now |
| 214 EXPECT_FALSE(GetScreenKeepAwakeInJS()); |
| 215 EXPECT_FALSE(IsScreenBlocked()); |
| 216 } |
| 217 |
| 218 IN_PROC_BROWSER_TEST_F(WakeLockTest, RemoveFrame) { |
| 219 LoadTestURL("page_with_iframe.html"); |
| 220 |
| 221 EXPECT_FALSE(IsScreenBlocked()); |
| 222 |
| 223 // Lock screen in nested frame |
| 224 ExecuteJavaScriptAndWaitChangeStatus( |
| 225 "document.getElementById('nested_frame')." |
| 226 "contentWindow.screen.keepAwake = true;"); |
| 227 |
| 228 EXPECT_TRUE(IsScreenBlocked()); |
| 229 |
| 230 // Remove nested frame |
| 231 ExecuteJavaScriptAndWaitChangeStatus( |
| 232 "var iframe = document.getElementById('nested_frame');" |
| 233 "iframe.parentNode.removeChild(iframe);"); |
| 234 |
| 235 // Screen is unlocked now |
| 236 EXPECT_FALSE(IsScreenBlocked()); |
| 237 } |
| 238 |
| 239 IN_PROC_BROWSER_TEST_F(WakeLockTest, UnlockAfterCrashTab) { |
| 240 LoadTestURLAndLockScreen("../title1.html"); |
| 241 |
| 242 // Tab is crashed |
| 243 ChangeWakeLockWatcher watcher(GetWLDHForWebContents()); |
| 244 CrashTab(shell()->web_contents()); |
| 245 watcher.Wait(); |
| 246 |
| 247 // Screen is unlocked now |
| 248 EXPECT_FALSE(IsScreenBlocked()); |
| 249 } |
| 250 |
| 251 IN_PROC_BROWSER_TEST_F(WakeLockTest, Navigation) { |
| 252 LoadTestURLAndLockScreen("../title1.html"); |
| 253 |
| 254 LoadTestURL("page_with_iframe.html"); |
| 255 |
| 256 EXPECT_FALSE(IsScreenBlocked()); |
| 257 } |
| 258 |
| 259 IN_PROC_BROWSER_TEST_F(WakeLockTest, NavigationToSelf) { |
| 260 LoadTestURLAndLockScreen("../title1.html"); |
| 261 |
| 262 LoadTestURL("../title1.html"); |
| 263 |
| 264 // Screen is unlocked now |
| 265 EXPECT_FALSE(IsScreenBlocked()); |
| 266 } |
| 267 |
| 268 IN_PROC_BROWSER_TEST_F(WakeLockTest, Reload) { |
| 269 LoadTestURLAndLockScreen("../title1.html"); |
| 270 |
| 271 ChangeWakeLockWatcher watcher(GetWLDHForWebContents()); |
| 272 shell()->Reload(); |
| 273 watcher.Wait(); |
| 274 |
| 275 EXPECT_FALSE(IsScreenBlocked()); |
| 276 } |
| 277 |
| 278 IN_PROC_BROWSER_TEST_F(WakeLockTest, FrameNavigation) { |
| 279 LoadTestURL("page_with_iframe.html"); |
| 280 |
| 281 EXPECT_FALSE(IsScreenBlocked()); |
| 282 |
| 283 // Lock screen in nested frame |
| 284 ExecuteJavaScriptAndWaitChangeStatus( |
| 285 "document.getElementById('nested_frame')." |
| 286 "contentWindow.screen.keepAwake = true;"); |
| 287 // Screen is locked now |
| 288 EXPECT_TRUE(IsScreenBlocked()); |
| 289 |
| 290 // Navigate frame |
| 291 ExecuteJavaScriptAndWaitChangeStatus( |
| 292 "document.getElementById('nested_frame')." |
| 293 "src = 'data:text/html,';"); |
| 294 |
| 295 // Screen is unlocked now |
| 296 EXPECT_FALSE(IsScreenBlocked()); |
| 297 } |
| 298 |
| 299 IN_PROC_BROWSER_TEST_F(WakeLockTest, OutOfProcessFrame) { |
| 300 LoadTestURL("page_with_iframe.html"); |
| 301 |
| 302 EXPECT_FALSE(IsScreenBlocked()); |
| 303 |
| 304 FrameTreeNode* root = |
| 305 static_cast<WebContentsImpl*>(shell()->web_contents())-> |
| 306 GetFrameTree()->root(); |
| 307 |
| 308 // Lock screen in same-site iframe |
| 309 ChangeWakeLockWatcher watcher(GetWLDHForWebContents()); |
| 310 FrameTreeNode* child = root->child_at(0); |
| 311 child->current_frame_host()-> |
| 312 ExecuteJavaScript(base::UTF8ToUTF16("screen.keepAwake = true;")); |
| 313 watcher.Wait(); |
| 314 EXPECT_TRUE(IsScreenBlocked()); |
| 315 |
| 316 // Load cross-site page into iframe. |
| 317 GURL url = embedded_test_server()->GetURL("foo.com", "/title2.html"); |
| 318 NavigateFrameToURL(root->child_at(0), url); |
| 319 |
| 320 // Ensure that we have created a new process for the subframe. |
| 321 RenderProcessHost* rph = child->current_frame_host()->GetProcess(); |
| 322 EXPECT_NE(shell()->web_contents()->GetRenderProcessHost(), rph); |
| 323 |
| 324 // Screen should not be locked now |
| 325 EXPECT_FALSE(IsScreenBlocked()); |
| 326 } |
| 327 |
| 328 IN_PROC_BROWSER_TEST_F(WakeLockTest, UnlockAfterCrashOutOfProcessFrame) { |
| 329 LoadTestURL("page_with_iframe.html"); |
| 330 |
| 331 EXPECT_FALSE(IsScreenBlocked()); |
| 332 |
| 333 FrameTreeNode* root = |
| 334 static_cast<WebContentsImpl*>(shell()->web_contents())-> |
| 335 GetFrameTree()->root(); |
| 336 FrameTreeNode* child = root->child_at(0); |
| 337 |
| 338 // Load cross-site page into iframe. |
| 339 GURL url = embedded_test_server()->GetURL("foo.com", "/title2.html"); |
| 340 NavigateFrameToURL(child, url); |
| 341 |
| 342 // Ensure that we have created a new process for the subframe. |
| 343 EXPECT_TRUE(child->current_frame_host()->IsCrossProcessSubframe()); |
| 344 |
| 345 // Lock screen in cross-site iframe |
| 346 ChangeWakeLockWatcher watcher(GetWLDHForWebContents()); |
| 347 child->current_frame_host()-> |
| 348 ExecuteJavaScript(base::UTF8ToUTF16("screen.keepAwake = true;")); |
| 349 watcher.Wait(); |
| 350 EXPECT_TRUE(IsScreenBlocked()); |
| 351 |
| 352 // Crash process that owns the out-of-process frame |
| 353 RenderProcessHost* rph = child->current_frame_host()->GetProcess(); |
| 354 ChangeWakeLockWatcher watcher_shutdown(GetWLDHForWebContents()); |
| 355 rph->Shutdown(0, true); |
| 356 watcher_shutdown.Wait(); |
| 357 |
| 358 // Screen should not be locked now |
| 359 EXPECT_FALSE(IsScreenBlocked()); |
| 360 } |
| 361 |
| 362 } // namespace content |
OLD | NEW |