-
Notifications
You must be signed in to change notification settings - Fork 6.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Extensions] Move BackgroundScriptExecutor to its own file
Move BackgroundScriptExecutor from browsertest_util.[h|cc] to its own file in background_script_executor.[h|cc]. It's a large enough and self-contained class that it doesn't need to be bundled in with other util methods. Update all callers, includes, and tests. This CL has no behavior change. Bug: 1319642 Change-Id: Id71576f0af30ede2bce225e16daae18d9d52dd7b Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3636097 Commit-Queue: Devlin Cronin <rdevlin.cronin@chromium.org> Reviewed-by: Tim <tjudkins@chromium.org> Cr-Commit-Position: refs/heads/main@{#1001173}
- Loading branch information
Showing
9 changed files
with
369 additions
and
316 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,203 @@ | ||
// Copyright 2022 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 "extensions/browser/background_script_executor.h" | ||
|
||
#include "base/callback.h" | ||
#include "base/json/json_reader.h" | ||
#include "content/public/browser/browser_context.h" | ||
#include "content/public/browser/service_worker_context.h" | ||
#include "content/public/browser/storage_partition.h" | ||
#include "content/public/test/browser_test_utils.h" | ||
#include "content/public/test/service_worker_test_helpers.h" | ||
#include "extensions/browser/extension_host.h" | ||
#include "extensions/browser/extension_registry.h" | ||
#include "extensions/browser/extension_util.h" | ||
#include "extensions/browser/process_manager.h" | ||
#include "extensions/browser/script_result_queue.h" | ||
#include "extensions/common/manifest_handlers/background_info.h" | ||
#include "testing/gtest/include/gtest/gtest.h" | ||
|
||
namespace extensions { | ||
|
||
namespace { | ||
|
||
// Returns a log-friendly script string. | ||
std::string GetScriptToLog(const std::string& script) { | ||
// The maximum script size for which to print on failure. | ||
static constexpr int kMaxFailingScriptSizeToLog = 1000; | ||
return (script.size() < kMaxFailingScriptSizeToLog) ? script | ||
: "<script too large>"; | ||
} | ||
|
||
} // namespace | ||
|
||
BackgroundScriptExecutor::BackgroundScriptExecutor( | ||
content::BrowserContext* browser_context) | ||
: browser_context_(browser_context), | ||
registry_(ExtensionRegistry::Get(browser_context_)), | ||
process_manager_(ProcessManager::Get(browser_context_)) {} | ||
|
||
BackgroundScriptExecutor::~BackgroundScriptExecutor() = default; | ||
|
||
base::Value BackgroundScriptExecutor::ExecuteScript( | ||
const ExtensionId& extension_id, | ||
const std::string& script, | ||
ResultCapture result_capture, | ||
browsertest_util::ScriptUserActivation script_user_activation) { | ||
if (result_capture == ResultCapture::kNone) { | ||
AddTestFailure( | ||
"Cannot wait for a result with no result capture. " | ||
"Use ExecuteScriptAsync() instead"); | ||
return base::Value(); | ||
} | ||
|
||
ExecuteScriptAsync(extension_id, script, result_capture, | ||
script_user_activation); | ||
return WaitForResult(); | ||
} | ||
|
||
// static | ||
base::Value BackgroundScriptExecutor::ExecuteScript( | ||
content::BrowserContext* browser_context, | ||
const ExtensionId& extension_id, | ||
const std::string& script, | ||
ResultCapture result_capture, | ||
browsertest_util::ScriptUserActivation script_user_activation) { | ||
return BackgroundScriptExecutor(browser_context) | ||
.ExecuteScript(extension_id, script, result_capture, | ||
script_user_activation); | ||
} | ||
|
||
bool BackgroundScriptExecutor::ExecuteScriptAsync( | ||
const ExtensionId& extension_id, | ||
const std::string& script, | ||
ResultCapture result_capture, | ||
browsertest_util::ScriptUserActivation script_user_activation) { | ||
extension_ = registry_->enabled_extensions().GetByID(extension_id); | ||
script_ = script; | ||
result_capture_method_ = result_capture; | ||
if (!extension_) { | ||
AddTestFailure("No enabled extension with id: " + extension_id); | ||
return false; | ||
} | ||
|
||
if (BackgroundInfo::IsServiceWorkerBased(extension_)) { | ||
background_type_ = BackgroundType::kServiceWorker; | ||
DCHECK_NE(ResultCapture::kWindowDomAutomationController, | ||
result_capture_method_) | ||
<< "Cannot use domAutomationController in a worker."; | ||
DCHECK_EQ(browsertest_util::ScriptUserActivation::kDontActivate, | ||
script_user_activation) | ||
<< "Cannot provide a user gesture to service worker scripts"; | ||
return ExecuteScriptInServiceWorker(); | ||
} | ||
|
||
if (BackgroundInfo::HasBackgroundPage(extension_)) { | ||
background_type_ = BackgroundType::kPage; | ||
return ExecuteScriptInBackgroundPage(script_user_activation); | ||
} | ||
|
||
AddTestFailure( | ||
"Attempting to execute a background script for an extension" | ||
" with no background context"); | ||
return false; | ||
} | ||
|
||
// static | ||
bool BackgroundScriptExecutor::ExecuteScriptAsync( | ||
content::BrowserContext* browser_context, | ||
const ExtensionId& extension_id, | ||
const std::string& script, | ||
browsertest_util::ScriptUserActivation script_user_activation) { | ||
return BackgroundScriptExecutor(browser_context) | ||
.ExecuteScriptAsync(extension_id, script, ResultCapture::kNone, | ||
script_user_activation); | ||
} | ||
|
||
base::Value BackgroundScriptExecutor::WaitForResult() { | ||
DCHECK(background_type_); | ||
DCHECK_NE(ResultCapture::kNone, result_capture_method_) | ||
<< "Trying to wait for a result when no result was expected."; | ||
|
||
if (result_capture_method_ == ResultCapture::kSendScriptResult) { | ||
DCHECK(script_result_queue_); | ||
return script_result_queue_->GetNextResult(); | ||
} | ||
|
||
DCHECK_EQ(ResultCapture::kWindowDomAutomationController, | ||
result_capture_method_); | ||
DCHECK(message_queue_); | ||
std::string next_message; | ||
if (!message_queue_->WaitForMessage(&next_message)) { | ||
AddTestFailure("Failed to wait for message"); | ||
return base::Value(); | ||
} | ||
absl::optional<base::Value> value = | ||
base::JSONReader::Read(next_message, base::JSON_ALLOW_TRAILING_COMMAS); | ||
if (!value) { | ||
AddTestFailure("Received bad message: " + next_message); | ||
return base::Value(); | ||
} | ||
return std::move(*value); | ||
} | ||
|
||
bool BackgroundScriptExecutor::ExecuteScriptInServiceWorker() { | ||
std::vector<WorkerId> worker_ids = | ||
process_manager_->GetServiceWorkersForExtension(extension_->id()); | ||
if (worker_ids.size() != 1u) { | ||
AddTestFailure("Incorrect number of workers registered for extension"); | ||
return false; | ||
} | ||
|
||
if (result_capture_method_ == ResultCapture::kSendScriptResult) | ||
script_result_queue_ = std::make_unique<ScriptResultQueue>(); | ||
|
||
content::ServiceWorkerContext* service_worker_context = | ||
util::GetStoragePartitionForExtensionId(extension_->id(), | ||
browser_context_) | ||
->GetServiceWorkerContext(); | ||
service_worker_context->ExecuteScriptForTest( // IN-TEST | ||
script_, worker_ids[0].version_id, base::DoNothing()); | ||
return true; | ||
} | ||
|
||
bool BackgroundScriptExecutor::ExecuteScriptInBackgroundPage( | ||
browsertest_util::ScriptUserActivation script_user_activation) { | ||
ExtensionHost* host = | ||
process_manager_->GetBackgroundHostForExtension(extension_->id()); | ||
if (!host) { | ||
AddTestFailure("Extension does not have an active background page"); | ||
return false; | ||
} | ||
|
||
switch (result_capture_method_) { | ||
case ResultCapture::kNone: | ||
break; | ||
case ResultCapture::kSendScriptResult: | ||
script_result_queue_ = std::make_unique<ScriptResultQueue>(); | ||
break; | ||
case ResultCapture::kWindowDomAutomationController: | ||
message_queue_ = | ||
std::make_unique<content::DOMMessageQueue>(host->host_contents()); | ||
break; | ||
} | ||
|
||
if (script_user_activation == | ||
browsertest_util::ScriptUserActivation::kActivate) { | ||
content::ExecuteScriptAsync(host->host_contents(), script_); | ||
} else { | ||
NOTREACHED() << "Not yet supported. Use ExecuteScriptInBackgroundPage()."; | ||
} | ||
return true; | ||
} | ||
|
||
void BackgroundScriptExecutor::AddTestFailure(const std::string& message) { | ||
ADD_FAILURE() << "Background script execution failed: " << message | ||
<< ". Extension: " | ||
<< (extension_ ? extension_->name() : "<not found>") | ||
<< ", script: " << GetScriptToLog(script_); | ||
} | ||
|
||
} // namespace extensions |
Oops, something went wrong.