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/test/test_timeouts.h" |
| 7 #include "content/browser/wake_lock/wake_lock_service_context.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_utils.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 namespace { |
| 22 |
| 23 const char kBlinkWakeLockFeature[] = "WakeLock"; |
| 24 |
| 25 } // namespace |
| 26 |
| 27 class WakeLockTest : public ContentBrowserTest { |
| 28 public: |
| 29 void SetUpCommandLine(base::CommandLine* command_line) override { |
| 30 command_line->AppendSwitchASCII(switches::kEnableBlinkFeatures, |
| 31 kBlinkWakeLockFeature); |
| 32 command_line->AppendSwitch(switches::kSitePerProcess); |
| 33 } |
| 34 |
| 35 void SetUpOnMainThread() override { |
| 36 host_resolver()->AddRule("*", "127.0.0.1"); |
| 37 EXPECT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); |
| 38 // To prevent occlusion events from changing page visibility. |
| 39 GetWebContents()->IncrementCapturerCount(gfx::Size()); |
| 40 } |
| 41 |
| 42 void TearDownOnMainThread() override { |
| 43 GetWebContents()->DecrementCapturerCount(); |
| 44 } |
| 45 |
| 46 protected: |
| 47 WebContents* GetWebContents() { return shell()->web_contents(); } |
| 48 |
| 49 WebContentsImpl* GetWebContentsImpl() { |
| 50 return static_cast<WebContentsImpl*>(GetWebContents()); |
| 51 } |
| 52 |
| 53 RenderFrameHost* GetMainFrame() { return GetWebContents()->GetMainFrame(); } |
| 54 |
| 55 FrameTreeNode* GetNestedFrameNode() { |
| 56 FrameTreeNode* root = GetWebContentsImpl()->GetFrameTree()->root(); |
| 57 CHECK_EQ(1U, root->child_count()); |
| 58 return root->child_at(0); |
| 59 } |
| 60 |
| 61 RenderFrameHost* GetNestedFrame() { |
| 62 return GetNestedFrameNode()->current_frame_host(); |
| 63 } |
| 64 |
| 65 WakeLockServiceContext* GetWakeLockServiceContext() { |
| 66 return GetWebContentsImpl()->GetWakeLockServiceContext(); |
| 67 } |
| 68 |
| 69 bool HasWakeLock() { |
| 70 return GetWakeLockServiceContext()->HasWakeLockForTests(); |
| 71 } |
| 72 |
| 73 void WaitForPossibleUpdate() { |
| 74 // As Mojo channels have no common FIFO order in respect to each other and |
| 75 // to the Chromium IPC, we cannot assume that when screen.keepAwake state |
| 76 // is changed from within a script, WakeLockService will receive an update |
| 77 // request before ExecuteScript() returns. Therefore, some time slack is |
| 78 // needed to make sure that WakeLockService has received any possible update |
| 79 // requests before checking the resulting wake lock state. |
| 80 base::PlatformThread::Sleep(TestTimeouts::tiny_timeout()); |
| 81 RunAllPendingInMessageLoop(); |
| 82 } |
| 83 |
| 84 void ScreenWakeLockInMainFrame() { |
| 85 EXPECT_TRUE(ExecuteScript(GetMainFrame(), "screen.keepAwake = true;")); |
| 86 WaitForPossibleUpdate(); |
| 87 EXPECT_TRUE(HasWakeLock()); |
| 88 } |
| 89 |
| 90 bool EvaluateAsBool(const ToRenderFrameHost& adapter, |
| 91 const std::string& expr) { |
| 92 bool result; |
| 93 CHECK(ExecuteScriptAndExtractBool( |
| 94 adapter, "window.domAutomationController.send(" + expr + ");", |
| 95 &result)); |
| 96 return result; |
| 97 } |
| 98 }; |
| 99 |
| 100 IN_PROC_BROWSER_TEST_F(WakeLockTest, WakeLockApiIsPresent) { |
| 101 NavigateToURL(shell(), embedded_test_server()->GetURL("/simple_page.html")); |
| 102 EXPECT_TRUE( |
| 103 EvaluateAsBool(GetMainFrame(), "typeof screen.keepAwake !== undefined")); |
| 104 } |
| 105 |
| 106 IN_PROC_BROWSER_TEST_F(WakeLockTest, LockAndUnlockScreenInMainFrame) { |
| 107 NavigateToURL(shell(), embedded_test_server()->GetURL("/simple_page.html")); |
| 108 |
| 109 // Should not have screen wake lock initially. |
| 110 EXPECT_FALSE(HasWakeLock()); |
| 111 |
| 112 // Check attribute 'screen.keepAwake' in main frame. |
| 113 EXPECT_FALSE(EvaluateAsBool(GetMainFrame(), "screen.keepAwake")); |
| 114 |
| 115 // Set keep awake flag in main frame. |
| 116 EXPECT_TRUE(ExecuteScript(GetMainFrame(), "screen.keepAwake = true;")); |
| 117 WaitForPossibleUpdate(); |
| 118 |
| 119 // Keep awake flag should be set in main frame. |
| 120 EXPECT_TRUE(EvaluateAsBool(GetMainFrame(), "screen.keepAwake")); |
| 121 |
| 122 // Should create screen wake lock. |
| 123 EXPECT_TRUE(HasWakeLock()); |
| 124 |
| 125 // Reset keep awake flag in main frame. |
| 126 EXPECT_TRUE(ExecuteScript(GetMainFrame(), "screen.keepAwake = false;")); |
| 127 WaitForPossibleUpdate(); |
| 128 |
| 129 // Keep awake flag should not be set in main frame. |
| 130 EXPECT_FALSE(EvaluateAsBool(GetMainFrame(), "screen.keepAwake")); |
| 131 |
| 132 // Should release screen wake lock. |
| 133 EXPECT_FALSE(HasWakeLock()); |
| 134 } |
| 135 |
| 136 IN_PROC_BROWSER_TEST_F(WakeLockTest, MultipleLockThenUnlock) { |
| 137 NavigateToURL(shell(), embedded_test_server()->GetURL("/simple_page.html")); |
| 138 |
| 139 // Set keep awake flag. |
| 140 EXPECT_TRUE(ExecuteScript(GetMainFrame(), "screen.keepAwake = true;")); |
| 141 WaitForPossibleUpdate(); |
| 142 |
| 143 // Set keep awake flag again. |
| 144 EXPECT_TRUE(ExecuteScript(GetMainFrame(), "screen.keepAwake = true;")); |
| 145 WaitForPossibleUpdate(); |
| 146 |
| 147 // Screen should still be locked. |
| 148 EXPECT_TRUE(HasWakeLock()); |
| 149 |
| 150 // Reset keep awake flag. |
| 151 EXPECT_TRUE(ExecuteScript(GetMainFrame(), "screen.keepAwake = false;")); |
| 152 WaitForPossibleUpdate(); |
| 153 |
| 154 // Should release screen wake lock. |
| 155 EXPECT_FALSE(HasWakeLock()); |
| 156 } |
| 157 |
| 158 IN_PROC_BROWSER_TEST_F(WakeLockTest, LockInMainFrameAndNestedFrame) { |
| 159 NavigateToURL(shell(), |
| 160 embedded_test_server()->GetURL("/frame_tree/2-4.html")); |
| 161 EXPECT_FALSE(HasWakeLock()); |
| 162 |
| 163 // Lock screen in nested frame. |
| 164 EXPECT_TRUE(ExecuteScript(GetNestedFrame(), "screen.keepAwake = true;")); |
| 165 WaitForPossibleUpdate(); |
| 166 |
| 167 // Should create screen wake lock. |
| 168 EXPECT_TRUE(HasWakeLock()); |
| 169 |
| 170 // screen.keepAwake should be false in the main frame. |
| 171 EXPECT_FALSE(EvaluateAsBool(GetMainFrame(), "screen.keepAwake")); |
| 172 |
| 173 // Lock screen in main frame. |
| 174 EXPECT_TRUE(ExecuteScript(GetMainFrame(), "screen.keepAwake = true;")); |
| 175 WaitForPossibleUpdate(); |
| 176 |
| 177 // screen.keepAwake should be true in the main frame. |
| 178 EXPECT_TRUE(EvaluateAsBool(GetMainFrame(), "screen.keepAwake")); |
| 179 |
| 180 // Screen wake lock should not change. |
| 181 EXPECT_TRUE(HasWakeLock()); |
| 182 |
| 183 // Unlock screen in nested frame. |
| 184 EXPECT_TRUE(ExecuteScript(GetNestedFrame(), "screen.keepAwake = false;")); |
| 185 WaitForPossibleUpdate(); |
| 186 |
| 187 // Screen wake lock should be present, as the main frame is still requesting |
| 188 // it. |
| 189 EXPECT_TRUE(HasWakeLock()); |
| 190 |
| 191 // Unlock screen in main frame. |
| 192 EXPECT_TRUE(ExecuteScript(GetMainFrame(), "screen.keepAwake = false;")); |
| 193 WaitForPossibleUpdate(); |
| 194 |
| 195 // Screen wake lock should be released, as no frames are requesting it. |
| 196 EXPECT_FALSE(HasWakeLock()); |
| 197 } |
| 198 |
| 199 IN_PROC_BROWSER_TEST_F(WakeLockTest, FrameRemoved) { |
| 200 NavigateToURL(shell(), |
| 201 embedded_test_server()->GetURL("/frame_tree/2-4.html")); |
| 202 EXPECT_FALSE(HasWakeLock()); |
| 203 |
| 204 // Lock screen in nested frame. |
| 205 EXPECT_TRUE(ExecuteScript(GetNestedFrame(), "screen.keepAwake = true;")); |
| 206 WaitForPossibleUpdate(); |
| 207 |
| 208 EXPECT_TRUE(HasWakeLock()); |
| 209 |
| 210 // Remove nested frame. |
| 211 EXPECT_TRUE(ExecuteScript(GetMainFrame(), |
| 212 "var iframe = document.getElementById('3-1-id');" |
| 213 "iframe.parentNode.removeChild(iframe);")); |
| 214 |
| 215 // Screen wake lock should be released. |
| 216 EXPECT_FALSE(HasWakeLock()); |
| 217 } |
| 218 |
| 219 IN_PROC_BROWSER_TEST_F(WakeLockTest, UnlockAfterTabCrashed) { |
| 220 NavigateToURL(shell(), embedded_test_server()->GetURL("/simple_page.html")); |
| 221 ScreenWakeLockInMainFrame(); |
| 222 |
| 223 // Crash the tab. |
| 224 CrashTab(GetWebContents()); |
| 225 |
| 226 // Screen wake lock should be released. |
| 227 EXPECT_FALSE(HasWakeLock()); |
| 228 } |
| 229 |
| 230 IN_PROC_BROWSER_TEST_F(WakeLockTest, UnlockAfterNavigation) { |
| 231 NavigateToURL(shell(), embedded_test_server()->GetURL("/simple_page.html")); |
| 232 ScreenWakeLockInMainFrame(); |
| 233 |
| 234 // Navigate to a different document. |
| 235 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html")); |
| 236 |
| 237 // Screen wake lock should be released after navigation. |
| 238 EXPECT_FALSE(HasWakeLock()); |
| 239 } |
| 240 |
| 241 IN_PROC_BROWSER_TEST_F(WakeLockTest, UnlockAfterNavigationToSelf) { |
| 242 NavigateToURL(shell(), embedded_test_server()->GetURL("/simple_page.html")); |
| 243 ScreenWakeLockInMainFrame(); |
| 244 |
| 245 // Navigate to the same document. |
| 246 NavigateToURL(shell(), embedded_test_server()->GetURL("/simple_page.html")); |
| 247 |
| 248 // Screen wake lock should be released after navigation to the same URL. |
| 249 EXPECT_FALSE(HasWakeLock()); |
| 250 } |
| 251 |
| 252 IN_PROC_BROWSER_TEST_F(WakeLockTest, KeepLockAfterInPageNavigation) { |
| 253 GURL test_url( |
| 254 embedded_test_server()->GetURL("/session_history/fragment.html")); |
| 255 GURL test_in_page_url(test_url.spec() + "#a"); |
| 256 |
| 257 NavigateToURL(shell(), test_url); |
| 258 ScreenWakeLockInMainFrame(); |
| 259 |
| 260 NavigateToURL(shell(), test_in_page_url); |
| 261 EXPECT_TRUE(HasWakeLock()); |
| 262 } |
| 263 |
| 264 IN_PROC_BROWSER_TEST_F(WakeLockTest, UnlockAfterReload) { |
| 265 NavigateToURL(shell(), embedded_test_server()->GetURL("/simple_page.html")); |
| 266 ScreenWakeLockInMainFrame(); |
| 267 |
| 268 shell()->Reload(); |
| 269 WaitForLoadStop(GetWebContents()); |
| 270 |
| 271 // Screen wake lock should be released after reload. |
| 272 EXPECT_FALSE(HasWakeLock()); |
| 273 } |
| 274 |
| 275 IN_PROC_BROWSER_TEST_F(WakeLockTest, BrowserInitiatedFrameNavigation) { |
| 276 NavigateToURL(shell(), |
| 277 embedded_test_server()->GetURL("/frame_tree/2-4.html")); |
| 278 |
| 279 EXPECT_FALSE(HasWakeLock()); |
| 280 |
| 281 // Lock screen in nested frame. |
| 282 EXPECT_TRUE(ExecuteScript(GetNestedFrame(), "screen.keepAwake = true;")); |
| 283 WaitForPossibleUpdate(); |
| 284 |
| 285 // Screen wake lock should be present. |
| 286 EXPECT_TRUE(HasWakeLock()); |
| 287 |
| 288 // Navigate the nested frame (browser-initiated). |
| 289 NavigateFrameToURL(GetNestedFrameNode(), |
| 290 embedded_test_server()->GetURL("/simple_page.html")); |
| 291 WaitForPossibleUpdate(); |
| 292 |
| 293 // Screen wake lock should be released. |
| 294 EXPECT_FALSE(HasWakeLock()); |
| 295 } |
| 296 |
| 297 IN_PROC_BROWSER_TEST_F(WakeLockTest, RendererInitiatedFrameNavigation) { |
| 298 NavigateToURL(shell(), |
| 299 embedded_test_server()->GetURL("/frame_tree/2-4.html")); |
| 300 |
| 301 EXPECT_FALSE(HasWakeLock()); |
| 302 |
| 303 // Lock screen in nested frame. |
| 304 EXPECT_TRUE(ExecuteScript(GetNestedFrame(), "screen.keepAwake = true;")); |
| 305 WaitForPossibleUpdate(); |
| 306 |
| 307 // Screen wake lock should be present. |
| 308 EXPECT_TRUE(HasWakeLock()); |
| 309 |
| 310 // Navigate the nested frame (renderer-initiated). |
| 311 NavigateIframeToURL(GetWebContents(), "3-1-id", |
| 312 embedded_test_server()->GetURL("/simple_page.html")); |
| 313 WaitForPossibleUpdate(); |
| 314 |
| 315 // Screen wake lock should be released. |
| 316 EXPECT_FALSE(HasWakeLock()); |
| 317 } |
| 318 |
| 319 IN_PROC_BROWSER_TEST_F(WakeLockTest, OutOfProcessFrame) { |
| 320 NavigateToURL(shell(), embedded_test_server()->GetURL( |
| 321 "a.com", "/cross_site_iframe_factory.html?a(a)")); |
| 322 EXPECT_FALSE(HasWakeLock()); |
| 323 |
| 324 // Ensure that the nested frame is same-process. |
| 325 EXPECT_FALSE(GetNestedFrame()->IsCrossProcessSubframe()); |
| 326 |
| 327 // Lock screen in same-site nested frame. |
| 328 EXPECT_TRUE(ExecuteScript(GetNestedFrame(), "screen.keepAwake = true;")); |
| 329 WaitForPossibleUpdate(); |
| 330 EXPECT_TRUE(HasWakeLock()); |
| 331 |
| 332 // Navigate nested frame to a cross-site document. |
| 333 NavigateFrameToURL(GetNestedFrameNode(), embedded_test_server()->GetURL( |
| 334 "b.com", "/simple_page.html")); |
| 335 WaitForPossibleUpdate(); |
| 336 |
| 337 // Ensure that a new process has been created for the nested frame. |
| 338 EXPECT_TRUE(GetNestedFrame()->IsCrossProcessSubframe()); |
| 339 |
| 340 // Screen wake lock should be released. |
| 341 EXPECT_FALSE(HasWakeLock()); |
| 342 |
| 343 // Lock screen in the cross-site nested frame. |
| 344 EXPECT_TRUE(ExecuteScript(GetNestedFrame(), "screen.keepAwake = true;")); |
| 345 WaitForPossibleUpdate(); |
| 346 |
| 347 // Screen wake lock should be created. |
| 348 EXPECT_TRUE(HasWakeLock()); |
| 349 } |
| 350 |
| 351 IN_PROC_BROWSER_TEST_F(WakeLockTest, UnlockAfterCrashOutOfProcessFrame) { |
| 352 // Load a page with cross-site iframe. |
| 353 NavigateToURL(shell(), embedded_test_server()->GetURL( |
| 354 "a.com", "/cross_site_iframe_factory.html?a(b)")); |
| 355 EXPECT_FALSE(HasWakeLock()); |
| 356 |
| 357 // Ensure that a new process has been created for the nested frame. |
| 358 EXPECT_TRUE(GetNestedFrame()->IsCrossProcessSubframe()); |
| 359 |
| 360 // Lock screen in cross-site nested frame. |
| 361 EXPECT_TRUE(ExecuteScript(GetNestedFrame(), "screen.keepAwake = true;")); |
| 362 WaitForPossibleUpdate(); |
| 363 EXPECT_TRUE(HasWakeLock()); |
| 364 |
| 365 // Crash process that owns the out-of-process frame. |
| 366 RenderProcessHostWatcher watcher( |
| 367 GetNestedFrame()->GetProcess(), |
| 368 RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); |
| 369 GetNestedFrame()->GetProcess()->Shutdown(0, false); |
| 370 watcher.Wait(); |
| 371 |
| 372 // Screen wake lock should be released. |
| 373 EXPECT_FALSE(HasWakeLock()); |
| 374 } |
| 375 |
| 376 } // namespace content |
OLD | NEW |