Index: content/browser/wake_lock/wake_lock_browsertest.cc |
diff --git a/content/browser/wake_lock/wake_lock_browsertest.cc b/content/browser/wake_lock/wake_lock_browsertest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..be4409a3f752ef6cf7da5abfce5593ab26c39c89 |
--- /dev/null |
+++ b/content/browser/wake_lock/wake_lock_browsertest.cc |
@@ -0,0 +1,362 @@ |
+// Copyright 2015 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 "base/command_line.h" |
+#include "base/strings/utf_string_conversions.h" |
+#include "content/browser/wake_lock/wake_lock_dispatcher_host.h" |
+#include "content/browser/web_contents/web_contents_impl.h" |
+#include "content/public/common/content_switches.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 "net/test/embedded_test_server/embedded_test_server.h" |
+ |
+namespace content { |
+ |
+class WakeLockWatcher : public WakeLockDispatcherHost::Observer { |
+ public: |
+ explicit WakeLockWatcher(WakeLockDispatcherHost* host) |
+ : host_(host) { |
+ host_->AddObserver(this); |
+ } |
+ |
+ virtual ~WakeLockWatcher() { |
+ host_->RemoveObserver(this); |
+ } |
+ |
+ void Wait() { |
+ loop_.Run(); |
+ } |
+ |
+ protected: |
+ void OnUpdate() override { |
+ loop_.Quit(); |
+ } |
+ |
+ WakeLockDispatcherHost* host_; |
+ base::RunLoop loop_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(WakeLockWatcher); |
+}; |
+ |
+class ChangeWakeLockWatcher : public WakeLockWatcher { |
+ public: |
+ explicit ChangeWakeLockWatcher(WakeLockDispatcherHost* host) |
+ : WakeLockWatcher(host) { |
+ has_blocker_ = host_->has_blocker_for_testing(); |
+ } |
+ |
+ private: |
+ void OnUpdate() override { |
+ if (host_->has_blocker_for_testing() != has_blocker_) |
+ loop_.Quit(); |
+ } |
+ |
+ bool has_blocker_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(ChangeWakeLockWatcher); |
+}; |
+ |
+class WakeLockTest : public ContentBrowserTest { |
+ public: |
+ void SetUpCommandLine(base::CommandLine* command_line) override { |
+ command_line->AppendSwitch( |
+ switches::kEnableExperimentalWebPlatformFeatures); |
+ command_line->AppendSwitch(switches::kSitePerProcess); |
+ } |
+ |
+ void SetUpOnMainThread() override { |
+ host_resolver()->AddRule("*", "127.0.0.1"); |
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); |
+ SetupCrossSiteRedirector(embedded_test_server()); |
+ } |
+ |
+ protected: |
+ bool IsScreenBlocked() const { |
+ const WakeLockDispatcherHost* dispatcher = GetWLDHForWebContents(); |
+ CHECK(dispatcher); |
+ return dispatcher->has_blocker_for_testing(); |
+ } |
+ |
+ void LoadTestURL(const char* url_name) const { |
+ GURL test_url = GetTestUrl("wake_lock", url_name); |
+ ASSERT_TRUE(NavigateToURL(shell(), test_url)); |
+ } |
+ |
+ void LoadTestURLAndLockScreen(const char* url_name) const { |
+ LoadTestURL(url_name); |
+ EXPECT_FALSE(IsScreenBlocked()); |
+ |
+ // Lock screen |
+ ExecuteJavaScriptAndWaitChangeStatus("screen.keepAwake = true;"); |
+ EXPECT_TRUE(IsScreenBlocked()); |
+ } |
+ |
+ void ExecuteJavaScript(const char* js) const { |
+ shell()->web_contents()->GetMainFrame()-> |
+ ExecuteJavaScript(base::UTF8ToUTF16(js)); |
+ } |
+ |
+ void ExecuteJavaScriptAndWait(const char* js) const { |
+ WakeLockWatcher watcher(GetWLDHForWebContents()); |
+ ExecuteJavaScript(js); |
+ watcher.Wait(); |
+ } |
+ |
+ void ExecuteJavaScriptAndWaitChangeStatus(const char* js) const { |
+ ChangeWakeLockWatcher watcher(GetWLDHForWebContents()); |
+ ExecuteJavaScript(js); |
+ watcher.Wait(); |
+ } |
+ |
+ bool ExecuteJavaScriptAndGetBool(const char* js) const { |
+ bool bool_value = false; |
+ scoped_ptr<base::Value> value = ExecuteScriptAndGetValue( |
+ shell()->web_contents()->GetMainFrame(), js); |
+ EXPECT_TRUE(value->GetAsBoolean(&bool_value)); |
+ return bool_value; |
+ } |
+ |
+ bool GetScreenKeepAwakeInJS() const { |
+ return ExecuteJavaScriptAndGetBool("screen.keepAwake"); |
+ } |
+ |
+ WakeLockDispatcherHost* GetWLDHForWebContents() const { |
+ WebContentsImpl* web_contents_impl = |
+ static_cast<WebContentsImpl*>(shell()->web_contents()); |
+ return web_contents_impl->wake_lock_dispatcher_host(); |
+ } |
+}; |
+ |
+IN_PROC_BROWSER_TEST_F(WakeLockTest, WakeLockApiIsPresent) { |
+ LoadTestURL("../title1.html"); |
+ |
+ EXPECT_FALSE(IsScreenBlocked()); |
+ EXPECT_TRUE(ExecuteJavaScriptAndGetBool( |
+ "typeof screen.keepAwake !== undefined")); |
+} |
+ |
+IN_PROC_BROWSER_TEST_F(WakeLockTest, LockAndUnlockScreenInMainFrame) { |
+ LoadTestURL("../title1.html"); |
+ |
+ // Screen is not locked on start |
+ EXPECT_FALSE(IsScreenBlocked()); |
+ |
+ // Check attribute 'screen.keepAwake' in JavaScript |
+ EXPECT_FALSE(GetScreenKeepAwakeInJS()); |
+ |
+ // Intention to lock screen |
+ ExecuteJavaScriptAndWaitChangeStatus("screen.keepAwake = true;"); |
+ |
+ // Check attribute |
+ EXPECT_TRUE(GetScreenKeepAwakeInJS()); |
+ EXPECT_TRUE(IsScreenBlocked()); |
+ |
+ // Set attribute to false, no longer keep screen awake |
+ ExecuteJavaScriptAndWaitChangeStatus("screen.keepAwake = false;"); |
+ |
+ // Check attribute in JS |
+ EXPECT_FALSE(GetScreenKeepAwakeInJS()); |
+ |
+ // Screen should not be locked now. |
+ EXPECT_FALSE(IsScreenBlocked()); |
+} |
+ |
+IN_PROC_BROWSER_TEST_F(WakeLockTest, ManyLockOneUnlock) { |
+ LoadTestURLAndLockScreen("../title1.html"); |
+ |
+ // Intention to lock screen in main frame when screen is locked |
+ ExecuteJavaScriptAndWait("screen.keepAwake = true;"); |
+ EXPECT_TRUE(IsScreenBlocked()); |
+ |
+ ExecuteJavaScriptAndWaitChangeStatus("screen.keepAwake = false;"); |
+ EXPECT_FALSE(IsScreenBlocked()); |
+} |
+ |
+IN_PROC_BROWSER_TEST_F(WakeLockTest, LockScreenInMainFrameAndNestedFrame) { |
+ LoadTestURL("page_with_iframe.html"); |
+ |
+ EXPECT_FALSE(IsScreenBlocked()); |
+ |
+ // Lock screen in nested frame |
+ ExecuteJavaScriptAndWaitChangeStatus( |
+ "document.getElementById('nested_frame')." |
+ "contentWindow.screen.keepAwake = true;"); |
+ |
+ // Screen is locked now |
+ EXPECT_TRUE(IsScreenBlocked()); |
+ |
+ // But in main frame screen.keepAwake is false |
+ EXPECT_FALSE(GetScreenKeepAwakeInJS()); |
+ |
+ // Lock screen in main frame |
+ ExecuteJavaScriptAndWait("screen.keepAwake = true;"); |
+ |
+ EXPECT_TRUE(GetScreenKeepAwakeInJS()); |
+ EXPECT_TRUE(IsScreenBlocked()); |
+ |
+ // Unlock screen in nested frame |
+ ExecuteJavaScriptAndWait("document.getElementById('nested_frame')." |
+ "contentWindow.screen.keepAwake = false;"); |
+ |
+ // screen.keepAwake in nested frame is false, but screen is locked now |
+ EXPECT_TRUE(IsScreenBlocked()); |
+ |
+ // Unlock screen in main frame |
+ ExecuteJavaScriptAndWaitChangeStatus("screen.keepAwake = false;"); |
+ |
+ // Screen is unlock now |
+ EXPECT_FALSE(GetScreenKeepAwakeInJS()); |
+ EXPECT_FALSE(IsScreenBlocked()); |
+} |
+ |
+IN_PROC_BROWSER_TEST_F(WakeLockTest, RemoveFrame) { |
+ LoadTestURL("page_with_iframe.html"); |
+ |
+ EXPECT_FALSE(IsScreenBlocked()); |
+ |
+ // Lock screen in nested frame |
+ ExecuteJavaScriptAndWaitChangeStatus( |
+ "document.getElementById('nested_frame')." |
+ "contentWindow.screen.keepAwake = true;"); |
+ |
+ EXPECT_TRUE(IsScreenBlocked()); |
+ |
+ // Remove nested frame |
+ ExecuteJavaScriptAndWaitChangeStatus( |
+ "var iframe = document.getElementById('nested_frame');" |
+ "iframe.parentNode.removeChild(iframe);"); |
+ |
+ // Screen is unlocked now |
+ EXPECT_FALSE(IsScreenBlocked()); |
+} |
+ |
+IN_PROC_BROWSER_TEST_F(WakeLockTest, UnlockAfterCrashTab) { |
+ LoadTestURLAndLockScreen("../title1.html"); |
+ |
+ // Tab is crashed |
+ ChangeWakeLockWatcher watcher(GetWLDHForWebContents()); |
+ CrashTab(shell()->web_contents()); |
+ watcher.Wait(); |
+ |
+ // Screen is unlocked now |
+ EXPECT_FALSE(IsScreenBlocked()); |
+} |
+ |
+IN_PROC_BROWSER_TEST_F(WakeLockTest, Navigation) { |
+ LoadTestURLAndLockScreen("../title1.html"); |
+ |
+ LoadTestURL("page_with_iframe.html"); |
+ |
+ EXPECT_FALSE(IsScreenBlocked()); |
+} |
+ |
+IN_PROC_BROWSER_TEST_F(WakeLockTest, NavigationToSelf) { |
+ LoadTestURLAndLockScreen("../title1.html"); |
+ |
+ LoadTestURL("../title1.html"); |
+ |
+ // Screen is unlocked now |
+ EXPECT_FALSE(IsScreenBlocked()); |
+} |
+ |
+IN_PROC_BROWSER_TEST_F(WakeLockTest, Reload) { |
+ LoadTestURLAndLockScreen("../title1.html"); |
+ |
+ ChangeWakeLockWatcher watcher(GetWLDHForWebContents()); |
+ shell()->Reload(); |
+ watcher.Wait(); |
+ |
+ EXPECT_FALSE(IsScreenBlocked()); |
+} |
+ |
+IN_PROC_BROWSER_TEST_F(WakeLockTest, FrameNavigation) { |
+ LoadTestURL("page_with_iframe.html"); |
+ |
+ EXPECT_FALSE(IsScreenBlocked()); |
+ |
+ // Lock screen in nested frame |
+ ExecuteJavaScriptAndWaitChangeStatus( |
+ "document.getElementById('nested_frame')." |
+ "contentWindow.screen.keepAwake = true;"); |
+ // Screen is locked now |
+ EXPECT_TRUE(IsScreenBlocked()); |
+ |
+ // Navigate frame |
+ ExecuteJavaScriptAndWaitChangeStatus( |
+ "document.getElementById('nested_frame')." |
+ "src = 'data:text/html,';"); |
+ |
+ // Screen is unlocked now |
+ EXPECT_FALSE(IsScreenBlocked()); |
+} |
+ |
+IN_PROC_BROWSER_TEST_F(WakeLockTest, OutOfProcessFrame) { |
+ LoadTestURL("page_with_iframe.html"); |
+ |
+ EXPECT_FALSE(IsScreenBlocked()); |
+ |
+ FrameTreeNode* root = |
+ static_cast<WebContentsImpl*>(shell()->web_contents())-> |
+ GetFrameTree()->root(); |
+ |
+ // Lock screen in same-site iframe |
+ ChangeWakeLockWatcher watcher(GetWLDHForWebContents()); |
+ FrameTreeNode* child = root->child_at(0); |
+ child->current_frame_host()-> |
+ ExecuteJavaScript(base::UTF8ToUTF16("screen.keepAwake = true;")); |
+ watcher.Wait(); |
+ EXPECT_TRUE(IsScreenBlocked()); |
+ |
+ // Load cross-site page into iframe. |
+ GURL url = embedded_test_server()->GetURL("foo.com", "/title2.html"); |
+ NavigateFrameToURL(root->child_at(0), url); |
+ |
+ // Ensure that we have created a new process for the subframe. |
+ RenderProcessHost* rph = child->current_frame_host()->GetProcess(); |
+ EXPECT_NE(shell()->web_contents()->GetRenderProcessHost(), rph); |
+ |
+ // Screen should not be locked now |
+ EXPECT_FALSE(IsScreenBlocked()); |
+} |
+ |
+IN_PROC_BROWSER_TEST_F(WakeLockTest, UnlockAfterCrashOutOfProcessFrame) { |
+ LoadTestURL("page_with_iframe.html"); |
+ |
+ EXPECT_FALSE(IsScreenBlocked()); |
+ |
+ FrameTreeNode* root = |
+ static_cast<WebContentsImpl*>(shell()->web_contents())-> |
+ GetFrameTree()->root(); |
+ FrameTreeNode* child = root->child_at(0); |
+ |
+ // Load cross-site page into iframe. |
+ GURL url = embedded_test_server()->GetURL("foo.com", "/title2.html"); |
+ NavigateFrameToURL(child, url); |
+ |
+ // Ensure that we have created a new process for the subframe. |
+ EXPECT_TRUE(child->current_frame_host()->IsCrossProcessSubframe()); |
+ |
+ // Lock screen in cross-site iframe |
+ ChangeWakeLockWatcher watcher(GetWLDHForWebContents()); |
+ child->current_frame_host()-> |
+ ExecuteJavaScript(base::UTF8ToUTF16("screen.keepAwake = true;")); |
+ watcher.Wait(); |
+ EXPECT_TRUE(IsScreenBlocked()); |
+ |
+ // Crash process that owns the out-of-process frame |
+ RenderProcessHost* rph = child->current_frame_host()->GetProcess(); |
+ ChangeWakeLockWatcher watcher_shutdown(GetWLDHForWebContents()); |
+ rph->Shutdown(0, true); |
+ watcher_shutdown.Wait(); |
+ |
+ // Screen should not be locked now |
+ EXPECT_FALSE(IsScreenBlocked()); |
+} |
+ |
+} // namespace content |