blob: 6d0910ed2480d57ec35253e4357270f5ce8630a7 [file] [log] [blame]
// Copyright 2019 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 "chrome/browser/extensions/api/messaging/native_messaging_test_util.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/version_info/version_info.h"
#include "extensions/test/extension_test_message_listener.h"
#include "extensions/test/result_catcher.h"
namespace extensions {
namespace {
// Returns the newly added WebContents.
content::WebContents* AddTab(Browser* browser, const GURL& url) {
int starting_tab_count = browser->tab_strip_model()->count();
ui_test_utils::NavigateToURLWithDisposition(
browser, url, WindowOpenDisposition::NEW_FOREGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
EXPECT_EQ(starting_tab_count + 1, browser->tab_strip_model()->count());
return browser->tab_strip_model()->GetActiveWebContents();
}
} // namespace
class ServiceWorkerMessagingTest : public ExtensionApiTest {
public:
ServiceWorkerMessagingTest()
: current_channel_(
// Extensions APIs from SW are only enabled on trunk.
// It is important to set the channel early so that this change is
// visible in renderers running with service workers (and no
// extension).
version_info::Channel::UNKNOWN) {}
~ServiceWorkerMessagingTest() override = default;
private:
ScopedCurrentChannel current_channel_;
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerMessagingTest);
};
// Tests one-way message from content script to SW extension using
// chrome.runtime.sendMessage.
IN_PROC_BROWSER_TEST_F(ServiceWorkerMessagingTest, TabToWorkerOneWay) {
ExtensionTestMessageListener worker_listener("WORKER_RUNNING", false);
const Extension* extension = LoadExtension(test_data_dir_.AppendASCII(
"service_worker/messaging/send_message_tab_to_worker_one_way"));
ASSERT_TRUE(extension);
EXPECT_TRUE(worker_listener.WaitUntilSatisfied());
ExtensionTestMessageListener test_listener("WORKER_RECEIVED_MESSAGE", false);
test_listener.set_failure_message("FAILURE");
{
ASSERT_TRUE(StartEmbeddedTestServer());
const GURL url =
embedded_test_server()->GetURL("/extensions/test_file.html");
content::WebContents* new_web_contents = AddTab(browser(), url);
EXPECT_TRUE(new_web_contents);
}
EXPECT_TRUE(test_listener.WaitUntilSatisfied());
}
// Tests chrome.runtime.sendMessage from content script to SW extension.
IN_PROC_BROWSER_TEST_F(ServiceWorkerMessagingTest, TabToWorker) {
ExtensionTestMessageListener worker_listener("WORKER_RUNNING", false);
const Extension* extension = LoadExtension(test_data_dir_.AppendASCII(
"service_worker/messaging/send_message_tab_to_worker"));
ASSERT_TRUE(extension);
EXPECT_TRUE(worker_listener.WaitUntilSatisfied());
ExtensionTestMessageListener reply_listener("CONTENT_SCRIPT_RECEIVED_REPLY",
false);
reply_listener.set_failure_message("FAILURE");
{
ASSERT_TRUE(StartEmbeddedTestServer());
const GURL url =
embedded_test_server()->GetURL("/extensions/test_file.html");
content::WebContents* new_web_contents = AddTab(browser(), url);
EXPECT_TRUE(new_web_contents);
}
EXPECT_TRUE(reply_listener.WaitUntilSatisfied());
}
// Tests chrome.runtime.sendNativeMessage from SW extension to a native
// messaging host.
IN_PROC_BROWSER_TEST_F(ServiceWorkerMessagingTest, NativeMessagingBasic) {
extensions::ScopedTestNativeMessagingHost test_host;
ASSERT_NO_FATAL_FAILURE(test_host.RegisterTestHost(false));
ASSERT_TRUE(RunExtensionTest("service_worker/messaging/send_native_message"))
<< message_;
}
// Tests chrome.runtime.connectNative from SW extension to a native messaging
// host.
IN_PROC_BROWSER_TEST_F(ServiceWorkerMessagingTest, ConnectNative) {
extensions::ScopedTestNativeMessagingHost test_host;
ASSERT_NO_FATAL_FAILURE(test_host.RegisterTestHost(false));
ASSERT_TRUE(RunExtensionTest("service_worker/messaging/connect_native"))
<< message_;
}
// Tests chrome.tabs.sendMessage from SW extension to content script.
IN_PROC_BROWSER_TEST_F(ServiceWorkerMessagingTest, WorkerToTab) {
ASSERT_TRUE(StartEmbeddedTestServer());
ASSERT_TRUE(
RunExtensionTest("service_worker/messaging/send_message_worker_to_tab"))
<< message_;
}
// Tests port creation (chrome.runtime.connect) from content script to an
// extension SW and disconnecting the port.
IN_PROC_BROWSER_TEST_F(ServiceWorkerMessagingTest,
TabToWorker_ConnectAndDisconnect) {
// Load an extension that will inject content script to |new_web_contents|.
const Extension* extension = LoadExtension(test_data_dir_.AppendASCII(
"service_worker/messaging/connect_to_worker/connect_and_disconnect"));
ASSERT_TRUE(extension);
// Load the tab with content script to open a Port to |extension|.
// Test concludes when extension gets notified about port being disconnected.
ResultCatcher catcher;
{
ASSERT_TRUE(StartEmbeddedTestServer());
content::WebContents* new_web_contents =
AddTab(browser(),
embedded_test_server()->GetURL("/extensions/test_file.html"));
EXPECT_TRUE(new_web_contents);
}
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
}
// Tests port creation (chrome.runtime.connect) from content script to an
// extension and sending message through the port.
// TODO(lazyboy): Refactor common parts with TabToWorker_ConnectAndDisconnect.
IN_PROC_BROWSER_TEST_F(ServiceWorkerMessagingTest,
TabToWorker_ConnectAndPostMessage) {
// Load an extension that will inject content script to |new_web_contents|.
const Extension* extension = LoadExtension(test_data_dir_.AppendASCII(
"service_worker/messaging/connect_to_worker/post_message"));
ASSERT_TRUE(extension);
// Load the tab with content script to send message to |extension| via port.
// Test concludes when the content script receives a reply.
ResultCatcher catcher;
{
ASSERT_TRUE(StartEmbeddedTestServer());
content::WebContents* new_web_contents =
AddTab(browser(),
embedded_test_server()->GetURL("/extensions/test_file.html"));
EXPECT_TRUE(new_web_contents);
}
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
}
// Tests chrome.runtime.onMessageExternal between two Service Worker based
// extensions.
IN_PROC_BROWSER_TEST_F(ServiceWorkerMessagingTest, ExternalMessageToWorker) {
const std::string kTargetExtensionId = "pkplfbidichfdicaijlchgnapepdginl";
// Load the receiver extension first.
const Extension* target_extension = LoadExtension(test_data_dir_.AppendASCII(
"service_worker/messaging/send_message_external/target"));
ASSERT_TRUE(target_extension);
EXPECT_EQ(kTargetExtensionId, target_extension->id());
// Then run the test from initiator extension.
ASSERT_TRUE(RunExtensionTest(
"service_worker/messaging/send_message_external/initiator"))
<< message_;
}
// Tests chrome.runtime.onConnectExternal between two Service Worker based
// extensions.
IN_PROC_BROWSER_TEST_F(ServiceWorkerMessagingTest, ConnectExternalToWorker) {
const std::string kTargetExtensionId = "pkplfbidichfdicaijlchgnapepdginl";
// Load the receiver extension first.
const Extension* target_extension = LoadExtension(test_data_dir_.AppendASCII(
"service_worker/messaging/connect_external/target"));
ASSERT_TRUE(target_extension);
EXPECT_EQ(kTargetExtensionId, target_extension->id());
// Then run the test from initiator extension.
ASSERT_TRUE(
RunExtensionTest("service_worker/messaging/connect_external/initiator"))
<< message_;
}
} // namespace extensions