blob: 250274ef9dbf71e0d42d8371ae4ead647f94c974 [file] [log] [blame]
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/service_worker_context.h"
#include "content/public/common/content_paths.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/service_worker_test_helpers.h"
#include "extensions/browser/background_script_executor.h"
#include "extensions/browser/extension_util.h"
#include "extensions/browser/script_executor.h"
#include "extensions/browser/script_result_queue.h"
#include "extensions/browser/service_worker/service_worker_test_utils.h"
#include "extensions/test/extension_test_message_listener.h"
#include "extensions/test/result_catcher.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/test_data_directory.h"
namespace extensions {
class ExtensionWebSocketApiTest : public ExtensionApiTest {
public:
ExtensionWebSocketApiTest() = default;
~ExtensionWebSocketApiTest() override = default;
void SetUpOnMainThread() override {
ExtensionApiTest::SetUpOnMainThread();
ASSERT_TRUE(StartEmbeddedTestServer());
ASSERT_TRUE(StartWebSocketServer(net::GetWebSocketTestDataDirectory()));
}
// Runs a specific setup for service worker-based extensions. We open a web
// socket, set the idle timeout for the worker to one second, then wait for
// two seconds of web socket activity. If the worker is still alive and
// responds, it indicates the web socket correctly extended the worker's
// lifetime.
// `test_directory` indicates the path from which to load the extension,
// since different extensions test different kinds of web socket activity.
void RunServiceWorkerWebSocketTest(const char* test_directory);
};
void ExtensionWebSocketApiTest::RunServiceWorkerWebSocketTest(
const char* test_directory) {
ExtensionTestMessageListener socket_ready_listener("socket ready");
service_worker_test_utils::TestRegistrationObserver observer(
browser()->profile());
ResultCatcher catcher;
const Extension* extension =
LoadExtension(test_data_dir_.AppendASCII(test_directory));
ASSERT_TRUE(extension);
observer.WaitForWorkerStart();
// Open the web socket in the extension.
base::Value open_result = BackgroundScriptExecutor::ExecuteScript(
profile(), extension->id(), "openSocket()",
BackgroundScriptExecutor::ResultCapture::kSendScriptResult);
EXPECT_EQ("open", open_result);
// Tricky: `content::SetServiceWorkerIdleDelay() can only be called when the
// idle timer is already active; that is, when there are no pending events.
// Run until idle to let the result from the BackgroundScriptExecutor fully
// finish, and then set the idle delay to 1s.
base::RunLoop().RunUntilIdle();
// Set idle timeout to 1 second.
content::ServiceWorkerContext* context =
util::GetServiceWorkerContextForExtensionId(extension->id(),
browser()->profile());
content::SetServiceWorkerIdleDelay(
context, observer.GetServiceWorkerVersionId(), base::Seconds(1));
// Wait for two seconds of web socket activity, after which the socket will
// be closed and the extension will return. If we make it to the two seconds,
// the test succeeded (because the service worker didn't time out, indicating
// the web socket extended its lifetime).
base::Value close_result = BackgroundScriptExecutor::ExecuteScript(
profile(), extension->id(), "perform2SecondsOfWebSocketActivity()",
BackgroundScriptExecutor::ResultCapture::kSendScriptResult);
EXPECT_EQ("closed", close_result);
}
IN_PROC_BROWSER_TEST_F(ExtensionWebSocketApiTest, BasicWebSocketUsage) {
ASSERT_TRUE(RunExtensionTest("websocket")) << message_;
}
// Tests that client-side web socket activity (like sending messages) resets the
// service worker idle timer for service worker-based extensions.
// TODO(devlin): This test uses an echoing web socket, so it has both sending
// and receiving messages. It'd be better if this verified it purely via
// sending messages.
IN_PROC_BROWSER_TEST_F(ExtensionWebSocketApiTest,
SendingWebSocketMessagesResetsServiceWorkerIdleTime) {
RunServiceWorkerWebSocketTest("websocket_idle_timer_send_messages");
}
// Tests that server-initiated web socket activity (incoming messages from the
// server) resets the service worker idle timer for service worker-based
// extensions.
// Regression test for https://cbrug.com/1476142.
IN_PROC_BROWSER_TEST_F(ExtensionWebSocketApiTest,
ReceivingWebSocketMessagesResetsServiceWorkerIdleTime) {
RunServiceWorkerWebSocketTest("websocket_idle_timer_server_pings");
}
} // namespace extensions