| // Copyright 2019 The Chromium Authors | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #include <string> | 
 |  | 
 | #include "base/command_line.h" | 
 | #include "chrome/browser/ui/browser.h" | 
 | #include "chrome/browser/ui/tabs/tab_strip_model.h" | 
 | #include "chrome/test/base/in_process_browser_test.h" | 
 | #include "chrome/test/base/ui_test_utils.h" | 
 | #include "components/permissions/test/permission_request_observer.h" | 
 | #include "content/public/browser/web_contents.h" | 
 | #include "content/public/common/content_switches.h" | 
 | #include "content/public/test/browser_test.h" | 
 | #include "content/public/test/browser_test_utils.h" | 
 | #include "net/test/embedded_test_server/embedded_test_server.h" | 
 | #include "net/test/embedded_test_server/http_request.h" | 
 | #include "net/test/embedded_test_server/http_response.h" | 
 | #include "testing/gmock/include/gmock/gmock-matchers.h" | 
 |  | 
 | namespace { | 
 |  | 
 | // Handles HTTP requests to |path| with |content| as the response body. | 
 | // |content| is expected to be JavaScript; the response mime type is always set | 
 | // to "text/javascript". | 
 | // Invokes |done_callback| after serving the HTTP request. | 
 | std::unique_ptr<net::test_server::HttpResponse> RespondWithJS( | 
 |     const std::string& path, | 
 |     const std::string& content, | 
 |     base::OnceClosure done_callback, | 
 |     const net::test_server::HttpRequest& request) { | 
 |   GURL request_url = request.GetURL(); | 
 |   if (request_url.GetPath() != path) { | 
 |     return nullptr; | 
 |   } | 
 |  | 
 |   auto response = std::make_unique<net::test_server::BasicHttpResponse>(); | 
 |   response->set_content_type("text/javascript"); | 
 |   response->set_content(content); | 
 |   std::move(done_callback).Run(); | 
 |   return response; | 
 | } | 
 |  | 
 | }  // namespace | 
 |  | 
 | class WakeLockBrowserTest : public InProcessBrowserTest { | 
 |  protected: | 
 |   // InProcessBrowserTest: | 
 |   void SetUpCommandLine(base::CommandLine* command_line) override; | 
 |  | 
 |   // Shorthand for starting the embedded web server and navigating to | 
 |   // simple.html. | 
 |   // Tests calling this usually call content::EvalJs() afterwards to run custom | 
 |   // code on the dummy page. | 
 |   void NavigateToSimplePage(); | 
 |  | 
 |   // Registers a handle for "/js-response" in the embedded web server that | 
 |   // responds with |script| as the response body, and then navigates to |path|. | 
 |   // |path| usually points to a page that will somehow make a request to | 
 |   // "/js-response". | 
 |   void NavigateToAndRespondWithScript(const std::string& path, | 
 |                                       const std::string& script); | 
 | }; | 
 |  | 
 | void WakeLockBrowserTest::SetUpCommandLine(base::CommandLine* command_line) { | 
 |   command_line->AppendSwitchASCII(switches::kEnableBlinkFeatures, | 
 |                                   "SystemWakeLock"); | 
 | } | 
 |  | 
 | void WakeLockBrowserTest::NavigateToSimplePage() { | 
 |   ASSERT_TRUE(embedded_test_server()->Start()); | 
 |   ASSERT_TRUE(ui_test_utils::NavigateToURL( | 
 |       browser(), embedded_test_server()->GetURL("/simple.html"))); | 
 | } | 
 |  | 
 | void WakeLockBrowserTest::NavigateToAndRespondWithScript( | 
 |     const std::string& path, | 
 |     const std::string& script) { | 
 |   base::RunLoop loop; | 
 |   embedded_test_server()->RegisterRequestHandler(base::BindRepeating( | 
 |       &RespondWithJS, "/js-response", script, loop.QuitClosure())); | 
 |   ASSERT_TRUE(embedded_test_server()->Start()); | 
 |   ASSERT_TRUE(ui_test_utils::NavigateToURL( | 
 |       browser(), embedded_test_server()->GetURL(path))); | 
 |   loop.Run(); | 
 | } | 
 |  | 
 | // https://w3c.github.io/screen-wake-lock/#the-request-method | 
 | // Screen locks are never allowed from workers. | 
 | IN_PROC_BROWSER_TEST_F(WakeLockBrowserTest, RequestScreenLockFromWorker) { | 
 |   permissions::PermissionRequestObserver observer( | 
 |       browser()->tab_strip_model()->GetActiveWebContents()); | 
 |   const std::string kWorkerScript = | 
 |       "navigator.wakeLock.request('screen').catch(err => " | 
 |       "    self.postMessage(err.name))"; | 
 |   NavigateToAndRespondWithScript( | 
 |       "/workers/create_dedicated_worker.html?worker_url=/js-response", | 
 |       kWorkerScript); | 
 |   EXPECT_EQ( | 
 |       "NotAllowedError", | 
 |       content::EvalJs(browser()->tab_strip_model()->GetActiveWebContents(), | 
 |                       "waitForMessage();")); | 
 |   EXPECT_FALSE(observer.request_shown()); | 
 | } | 
 |  | 
 | // Requests for a system lock should always be denied, and there should be no | 
 | // permission prompt. | 
 | IN_PROC_BROWSER_TEST_F(WakeLockBrowserTest, RequestSystemLockFromWorker) { | 
 |   permissions::PermissionRequestObserver observer( | 
 |       browser()->tab_strip_model()->GetActiveWebContents()); | 
 |   const std::string kWorkerScript = | 
 |       "navigator.wakeLock.request('system').catch(err => " | 
 |       "    self.postMessage(err.name))"; | 
 |   NavigateToAndRespondWithScript( | 
 |       "/workers/create_dedicated_worker.html?worker_url=/js-response", | 
 |       kWorkerScript); | 
 |   EXPECT_EQ( | 
 |       "NotAllowedError", | 
 |       content::EvalJs(browser()->tab_strip_model()->GetActiveWebContents(), | 
 |                       "waitForMessage();")); | 
 |   EXPECT_FALSE(observer.request_shown()); | 
 | } | 
 |  | 
 | IN_PROC_BROWSER_TEST_F(WakeLockBrowserTest, RequestPermissionScreen) { | 
 |   // Requests for a screen lock should always be granted, and there should be no | 
 |   // permission prompt. | 
 |   NavigateToSimplePage(); | 
 |  | 
 |   permissions::PermissionRequestObserver observer( | 
 |       browser()->tab_strip_model()->GetActiveWebContents()); | 
 |   EXPECT_EQ("granted", content::EvalJs( | 
 |                            browser()->tab_strip_model()->GetActiveWebContents(), | 
 |                            "navigator.wakeLock.request('screen').then(lock => {" | 
 |                            "    lock.release(); return 'granted'; });")); | 
 |   EXPECT_FALSE(observer.request_shown()); | 
 | } | 
 |  | 
 | IN_PROC_BROWSER_TEST_F(WakeLockBrowserTest, | 
 |                        RequestPermissionScreenNoUserGesture) { | 
 |   // Requests for a screen lock should always be granted, and there should be no | 
 |   // permission prompt. | 
 |   NavigateToSimplePage(); | 
 |  | 
 |   permissions::PermissionRequestObserver observer( | 
 |       browser()->tab_strip_model()->GetActiveWebContents()); | 
 |   EXPECT_EQ( | 
 |       "granted", | 
 |       content::EvalJs(browser()->tab_strip_model()->GetActiveWebContents(), | 
 |                       "navigator.wakeLock.request('screen').then(lock => {" | 
 |                       "    lock.release(); return 'granted'; });", | 
 |                       content::EvalJsOptions::EXECUTE_SCRIPT_NO_USER_GESTURE)); | 
 |   EXPECT_FALSE(observer.request_shown()); | 
 | } | 
 |  | 
 | IN_PROC_BROWSER_TEST_F(WakeLockBrowserTest, RequestPermissionSystem) { | 
 |   // Requests for a system lock should always be denied, and there should be no | 
 |   // permission prompt. | 
 |   NavigateToSimplePage(); | 
 |  | 
 |   permissions::PermissionRequestObserver observer( | 
 |       browser()->tab_strip_model()->GetActiveWebContents()); | 
 |   EXPECT_EQ( | 
 |       "NotAllowedError", | 
 |       content::EvalJs(browser()->tab_strip_model()->GetActiveWebContents(), | 
 |                       "navigator.wakeLock.request('system').catch(err => {" | 
 |                       "    return err.name; });")); | 
 |   EXPECT_FALSE(observer.request_shown()); | 
 | } | 
 |  | 
 | IN_PROC_BROWSER_TEST_F(WakeLockBrowserTest, | 
 |                        RequestPermissionSystemNoUserGesture) { | 
 |   // Requests for a system lock should always be denied, and there should be no | 
 |   // permission prompt. | 
 |   NavigateToSimplePage(); | 
 |  | 
 |   permissions::PermissionRequestObserver observer( | 
 |       browser()->tab_strip_model()->GetActiveWebContents()); | 
 |   EXPECT_EQ( | 
 |       "NotAllowedError", | 
 |       content::EvalJs(browser()->tab_strip_model()->GetActiveWebContents(), | 
 |                       "navigator.wakeLock.request('system').catch(err => {" | 
 |                       "    return err.name; });", | 
 |                       content::EvalJsOptions::EXECUTE_SCRIPT_NO_USER_GESTURE)); | 
 |   EXPECT_FALSE(observer.request_shown()); | 
 | } |