blob: 53682a72955dbf276719dc8ccc617959fef37d45 [file] [log] [blame]
jyasskinc993ce8d2016-03-31 00:38:341// Copyright 2016 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// This file contains browsertests for Web Bluetooth that depend on behavior
6// defined in chrome/, not just in content/.
7
8#include "base/command_line.h"
9#include "base/metrics/field_trial.h"
10#include "chrome/browser/permissions/permission_context_base.h"
11#include "chrome/browser/ui/browser.h"
ortunob6374dd82016-05-27 03:04:0712#include "chrome/browser/ui/browser_commands.h"
jyasskinc993ce8d2016-03-31 00:38:3413#include "chrome/browser/ui/tabs/tab_strip_model.h"
14#include "chrome/test/base/in_process_browser_test.h"
15#include "chrome/test/base/ui_test_utils.h"
16#include "components/variations/variations_associated_data.h"
17#include "content/public/browser/render_frame_host.h"
ortunob6374dd82016-05-27 03:04:0718#include "content/public/browser/render_process_host.h"
jyasskinc993ce8d2016-03-31 00:38:3419#include "content/public/common/content_switches.h"
20#include "content/public/test/browser_test_utils.h"
21#include "device/bluetooth/bluetooth_adapter_factory.h"
22#include "device/bluetooth/test/mock_bluetooth_adapter.h"
23
ortunob6374dd82016-05-27 03:04:0724using device::MockBluetoothAdapter;
25using testing::Return;
26
27typedef testing::NiceMock<MockBluetoothAdapter> NiceMockBluetoothAdapter;
28
jyasskinc993ce8d2016-03-31 00:38:3429namespace {
30
31class WebBluetoothTest : public InProcessBrowserTest {
32 protected:
33 void SetUpCommandLine(base::CommandLine* command_line) override {
juncai3ad09e102016-10-28 03:08:0634 // TODO(juncai): Remove this switch once Web Bluetooth is supported on Linux
35 // and Windows.
36 // https://crbug.com/570344
37 // https://crbug.com/507419
38 command_line->AppendSwitch(
39 switches::kEnableExperimentalWebPlatformFeatures);
jyasskinc993ce8d2016-03-31 00:38:3440 InProcessBrowserTest::SetUpCommandLine(command_line);
41 }
42
43 void SetUpOnMainThread() override {
44 // Navigate to a secure context.
45 embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
46 ASSERT_TRUE(embedded_test_server()->Start());
47 ui_test_utils::NavigateToURL(
48 browser(),
49 embedded_test_server()->GetURL("localhost", "/simple_page.html"));
50 web_contents_ = browser()->tab_strip_model()->GetActiveWebContents();
51 EXPECT_THAT(
52 web_contents_->GetMainFrame()->GetLastCommittedOrigin().Serialize(),
53 testing::StartsWith("http://localhost:"));
54 }
55
56 content::WebContents* web_contents_ = nullptr;
57};
58
ortunob6374dd82016-05-27 03:04:0759IN_PROC_BROWSER_TEST_F(WebBluetoothTest, WebBluetoothAfterCrash) {
60 // Make sure we can use Web Bluetooth after the tab crashes.
61 // Set up adapter with one device.
62 scoped_refptr<NiceMockBluetoothAdapter> adapter(
63 new NiceMockBluetoothAdapter());
64 ON_CALL(*adapter, IsPresent()).WillByDefault(Return(false));
65
66 device::BluetoothAdapterFactory::SetAdapterForTesting(adapter);
67
68 std::string result;
69 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
70 web_contents_,
71 "navigator.bluetooth.requestDevice({filters: [{services: [0x180d]}]})"
72 " .catch(e => domAutomationController.send(e.toString()));",
73 &result));
74 EXPECT_EQ("NotFoundError: Bluetooth adapter not available.", result);
75
76 // Crash the renderer process.
77 content::RenderProcessHost* process = web_contents_->GetRenderProcessHost();
78 content::RenderProcessHostWatcher crash_observer(
79 process, content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
80 process->Shutdown(0, false);
81 crash_observer.Wait();
82
83 // Reload tab.
nick3b04f322016-08-31 19:29:1984 chrome::Reload(browser(), WindowOpenDisposition::CURRENT_TAB);
ortunob6374dd82016-05-27 03:04:0785 content::WaitForLoadStop(
86 browser()->tab_strip_model()->GetActiveWebContents());
87
88 // Use Web Bluetooth again.
89 std::string result_after_crash;
90 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
91 web_contents_,
92 "navigator.bluetooth.requestDevice({filters: [{services: [0x180d]}]})"
93 " .catch(e => domAutomationController.send(e.toString()));",
94 &result_after_crash));
95 EXPECT_EQ("NotFoundError: Bluetooth adapter not available.",
96 result_after_crash);
97}
98
jyasskinc993ce8d2016-03-31 00:38:3499IN_PROC_BROWSER_TEST_F(WebBluetoothTest, KillSwitchShouldBlock) {
100 // Fake the BluetoothAdapter to say it's present.
101 scoped_refptr<device::MockBluetoothAdapter> adapter =
102 new testing::NiceMock<device::MockBluetoothAdapter>;
ortunob6374dd82016-05-27 03:04:07103 EXPECT_CALL(*adapter, IsPresent()).WillRepeatedly(Return(true));
jyasskinc993ce8d2016-03-31 00:38:34104 device::BluetoothAdapterFactory::SetAdapterForTesting(adapter);
105
106 // Turn on the global kill switch.
107 std::map<std::string, std::string> params;
108 params["Bluetooth"] =
109 PermissionContextBase::kPermissionsKillSwitchBlockedValue;
110 variations::AssociateVariationParams(
111 PermissionContextBase::kPermissionsKillSwitchFieldStudy, "TestGroup",
112 params);
113 base::FieldTrialList::CreateFieldTrial(
114 PermissionContextBase::kPermissionsKillSwitchFieldStudy, "TestGroup");
115
116 std::string rejection;
117 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
118 web_contents_,
119 "navigator.bluetooth.requestDevice({filters: [{name: 'Hello'}]})"
120 " .then(() => { domAutomationController.send('Success'); },"
121 " reason => {"
122 " domAutomationController.send(reason.name + ': ' + reason.message);"
123 " });",
124 &rejection));
125 EXPECT_THAT(rejection,
126 testing::MatchesRegex("NotFoundError: .*globally disabled.*"));
127}
128
beaufort.francois01135bf2016-11-23 14:37:36129// Tests that using Finch field trial parameters for blocklist additions has
scheib74250322016-04-07 03:32:21130// the effect of rejecting requestDevice calls.
beaufort.francois01135bf2016-11-23 14:37:36131IN_PROC_BROWSER_TEST_F(WebBluetoothTest, BlocklistShouldBlock) {
scheib74250322016-04-07 03:32:21132 // Fake the BluetoothAdapter to say it's present.
133 scoped_refptr<device::MockBluetoothAdapter> adapter =
134 new testing::NiceMock<device::MockBluetoothAdapter>;
ortunob6374dd82016-05-27 03:04:07135 EXPECT_CALL(*adapter, IsPresent()).WillRepeatedly(Return(true));
scheib74250322016-04-07 03:32:21136 device::BluetoothAdapterFactory::SetAdapterForTesting(adapter);
137
beaufort.francois01135bf2016-11-23 14:37:36138 if (base::FieldTrialList::TrialExists("WebBluetoothBlocklist")) {
139 LOG(INFO) << "WebBluetoothBlocklist field trial already configured.";
140 ASSERT_NE(variations::GetVariationParamValue("WebBluetoothBlocklist",
141 "blocklist_additions")
scheibb0036842016-09-06 20:53:17142 .find("ed5f25a4"),
143 std::string::npos)
beaufort.francois01135bf2016-11-23 14:37:36144 << "ERROR: WebBluetoothBlocklist field trial being tested in\n"
scheibb0036842016-09-06 20:53:17145 "testing/variations/fieldtrial_testing_config_*.json must\n"
146 "include this test's random UUID 'ed5f25a4' in\n"
beaufort.francois01135bf2016-11-23 14:37:36147 "blocklist_additions.\n";
scheibb0036842016-09-06 20:53:17148 } else {
beaufort.francois01135bf2016-11-23 14:37:36149 LOG(INFO) << "Creating WebBluetoothBlocklist field trial for test.";
scheibb0036842016-09-06 20:53:17150 // Create a field trial with test parameter.
151 std::map<std::string, std::string> params;
beaufort.francois01135bf2016-11-23 14:37:36152 params["blocklist_additions"] = "ed5f25a4:e";
153 variations::AssociateVariationParams("WebBluetoothBlocklist", "TestGroup",
scheibb0036842016-09-06 20:53:17154 params);
beaufort.francois01135bf2016-11-23 14:37:36155 base::FieldTrialList::CreateFieldTrial("WebBluetoothBlocklist",
scheibb0036842016-09-06 20:53:17156 "TestGroup");
157 }
scheib74250322016-04-07 03:32:21158
159 std::string rejection;
160 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
161 web_contents_,
scheib45e66c72016-09-02 20:19:45162 "navigator.bluetooth.requestDevice({filters: [{services: [0xed5f25a4]}]})"
scheib74250322016-04-07 03:32:21163 " .then(() => { domAutomationController.send('Success'); },"
164 " reason => {"
165 " domAutomationController.send(reason.name + ': ' + reason.message);"
166 " });",
167 &rejection));
168 EXPECT_THAT(rejection,
beaufort.francois01135bf2016-11-23 14:37:36169 testing::MatchesRegex("SecurityError: .*blocklisted UUID.*"));
scheib74250322016-04-07 03:32:21170}
171
jyasskinc993ce8d2016-03-31 00:38:34172} // namespace