blob: ee40d6f220d3af8936a91e8e23ba5f0a7f3aef7a [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 Cronine458a222019-12-30 22:39:379#include "chrome/browser/ui/extensions/extension_action_test_helper.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.
Jan Wilken Dörrie50d916f2020-01-16 14:17:48104//
105// Test is flaky: https://crbug.com/1042671
106IN_PROC_BROWSER_TEST_F(ManifestV3BrowserTest, DISABLED_ActionAPI) {
Devlin Cronin221a0ca22019-08-23 19:58:52107 constexpr char kManifest[] =
108 R"({
109 "name": "Action API",
110 "manifest_version": 3,
111 "version": "0.1",
112 "background": { "service_worker": "worker.js" },
113 "action": {}
114 })";
115 constexpr char kWorker[] =
116 R"(chrome.action.onClicked.addListener((tab) => {
117 chrome.test.assertTrue(!!tab);
118 chrome.test.notifyPass();
119 });
120 chrome.test.sendMessage('ready');)";
121
122 TestExtensionDir test_dir;
123 test_dir.WriteManifest(kManifest);
124 test_dir.WriteFile(FILE_PATH_LITERAL("worker.js"), kWorker);
125
126 ExtensionTestMessageListener listener("ready", /*will_reply=*/false);
127 const Extension* extension = LoadMv3Extension(test_dir.UnpackedPath());
128 ASSERT_TRUE(extension);
129 ASSERT_TRUE(listener.WaitUntilSatisfied());
130
Devlin Cronine458a222019-12-30 22:39:37131 std::unique_ptr<ExtensionActionTestHelper> action_test_util =
132 ExtensionActionTestHelper::Create(browser());
Devlin Cronin221a0ca22019-08-23 19:58:52133 ASSERT_EQ(1, action_test_util->NumberOfBrowserActions());
134 EXPECT_EQ(extension->id(), action_test_util->GetExtensionId(0));
135
136 ResultCatcher catcher;
137 action_test_util->Press(0);
138 ASSERT_TRUE(catcher.GetNextResult()) << catcher.message();
139}
140
Devlin Croninfee2b4e2019-08-15 20:20:35141} // namespace extensions