blob: 6de51c8f4dd71d976b8fc5d4b98ed1739d3e9668 [file] [log] [blame]
Devlin Croninfee2b4e2019-08-15 20:20:351// Copyright 2019 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/macros.h"
6#include "base/strings/utf_string_conversions.h"
7#include "chrome/browser/extensions/extension_browsertest.h"
8#include "chrome/browser/ui/browser.h"
Devlin Cronin221a0ca22019-08-23 19:58:529#include "chrome/browser/ui/extensions/browser_action_test_util.h"
Devlin Croninfee2b4e2019-08-15 20:20:3510#include "chrome/browser/ui/tabs/tab_strip_model.h"
11#include "chrome/test/base/ui_test_utils.h"
12#include "components/version_info/channel.h"
13#include "content/public/browser/web_contents.h"
14#include "extensions/common/extension.h"
15#include "extensions/common/features/feature_channel.h"
16#include "extensions/test/extension_test_message_listener.h"
17#include "extensions/test/result_catcher.h"
18#include "extensions/test/test_extension_dir.h"
19#include "net/dns/mock_host_resolver.h"
20#include "net/test/embedded_test_server/embedded_test_server.h"
21
22namespace extensions {
23
24class ManifestV3BrowserTest : public ExtensionBrowserTest {
25 public:
26 ManifestV3BrowserTest() {}
27 ~ManifestV3BrowserTest() override {}
28
29 void SetUpOnMainThread() override {
30 ExtensionBrowserTest::SetUpOnMainThread();
31 host_resolver()->AddRule("*", "127.0.0.1");
32 ASSERT_TRUE(embedded_test_server()->Start());
33 }
34
Devlin Cronin221a0ca22019-08-23 19:58:5235 // Loads and returns an extension while ignoring warnings.
36 const Extension* LoadMv3Extension(const base::FilePath& path) {
37 // We ignore the manifest warnings on the extension because it includes the
38 // "manifest v3 ain't quite ready yet" warning.
39 // TODO(devlin): We should probably introduce a flag to specifically ignore
40 // *that* warning, but no others.
41 return LoadExtensionWithFlags(path, kFlagIgnoreManifestWarnings);
42 }
43
Devlin Croninfee2b4e2019-08-15 20:20:3544 private:
45 ScopedCurrentChannel channel_override_{version_info::Channel::UNKNOWN};
46
47 DISALLOW_COPY_AND_ASSIGN(ManifestV3BrowserTest);
48};
49
50IN_PROC_BROWSER_TEST_F(ManifestV3BrowserTest, ProgrammaticScriptInjection) {
51 constexpr char kManifest[] =
52 R"({
53 "name": "Programmatic Script Injection",
54 "manifest_version": 3,
55 "version": "0.1",
56 "background": {
57 "service_worker": "worker.js"
58 },
59 "permissions": ["tabs"],
60 "host_permissions": ["*://example.com/*"]
61 })";
62 constexpr char kWorker[] =
63 R"(chrome.tabs.onUpdated.addListener(
64 function listener(tabId, changeInfo, tab) {
65 if (changeInfo.status != 'complete')
66 return;
67 let url = new URL(tab.url);
68 if (url.hostname != 'example.com')
69 return;
70 chrome.tabs.onUpdated.removeListener(listener);
71 chrome.tabs.executeScript(
72 tabId,
73 {code: "document.title = 'My New Title'; document.title;"},
74 (results) => {
75 chrome.test.assertNoLastError();
76 chrome.test.assertTrue(!!results);
77 chrome.test.assertEq(1, results.length);
78 chrome.test.assertEq('My New Title', results[0]);
79 chrome.test.notifyPass();
80 });
81 });
82 chrome.test.sendMessage('ready');)";
83
84 TestExtensionDir test_dir;
85 test_dir.WriteManifest(kManifest);
86 test_dir.WriteFile(FILE_PATH_LITERAL("worker.js"), kWorker);
87
88 ExtensionTestMessageListener listener("ready", /*will_reply=*/false);
Devlin Cronin221a0ca22019-08-23 19:58:5289 const Extension* extension = LoadMv3Extension(test_dir.UnpackedPath());
Devlin Croninfee2b4e2019-08-15 20:20:3590 ASSERT_TRUE(extension);
91 ASSERT_TRUE(listener.WaitUntilSatisfied());
92
93 ResultCatcher catcher;
94 ui_test_utils::NavigateToURL(
95 browser(), embedded_test_server()->GetURL("example.com", "/simple.html"));
96 ASSERT_TRUE(catcher.GetNextResult()) << catcher.message();
97
98 EXPECT_EQ(base::ASCIIToUTF16("My New Title"),
99 browser()->tab_strip_model()->GetActiveWebContents()->GetTitle());
100}
101
Devlin Cronin221a0ca22019-08-23 19:58:52102// A simple end-to-end test exercising the new action API in Manifest V3.
103// More robust tests for the action API are in extension_action_apitest.cc.
104IN_PROC_BROWSER_TEST_F(ManifestV3BrowserTest, ActionAPI) {
105 constexpr char kManifest[] =
106 R"({
107 "name": "Action API",
108 "manifest_version": 3,
109 "version": "0.1",
110 "background": { "service_worker": "worker.js" },
111 "action": {}
112 })";
113 constexpr char kWorker[] =
114 R"(chrome.action.onClicked.addListener((tab) => {
115 chrome.test.assertTrue(!!tab);
116 chrome.test.notifyPass();
117 });
118 chrome.test.sendMessage('ready');)";
119
120 TestExtensionDir test_dir;
121 test_dir.WriteManifest(kManifest);
122 test_dir.WriteFile(FILE_PATH_LITERAL("worker.js"), kWorker);
123
124 ExtensionTestMessageListener listener("ready", /*will_reply=*/false);
125 const Extension* extension = LoadMv3Extension(test_dir.UnpackedPath());
126 ASSERT_TRUE(extension);
127 ASSERT_TRUE(listener.WaitUntilSatisfied());
128
129 std::unique_ptr<BrowserActionTestUtil> action_test_util =
130 BrowserActionTestUtil::Create(browser());
131 ASSERT_EQ(1, action_test_util->NumberOfBrowserActions());
132 EXPECT_EQ(extension->id(), action_test_util->GetExtensionId(0));
133
134 ResultCatcher catcher;
135 action_test_util->Press(0);
136 ASSERT_TRUE(catcher.GetNextResult()) << catcher.message();
137}
138
Devlin Croninfee2b4e2019-08-15 20:20:35139} // namespace extensions