1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
|
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <string_view>
#include "base/strings/stringprintf.h"
#include "base/test/values_test_util.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/extensions/extension_tab_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/extensions/extension_action_test_helper.h"
#include "components/version_info/channel.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/test/browser_test.h"
#include "extensions/browser/background_script_executor.h"
#include "extensions/browser/extension_api_frame_id_map.h"
#include "extensions/browser/extension_host.h"
#include "extensions/browser/extension_host_test_helper.h"
#include "extensions/browser/script_executor.h"
#include "extensions/test/test_extension_dir.h"
namespace extensions {
// A test suite for `runtime.getContexts()` tests that need to be run as
// interactive UI tests (e.g. due to requiring focus).
class RuntimeGetContextsInteractiveApiTest : public ExtensionApiTest {
public:
RuntimeGetContextsInteractiveApiTest() = default;
RuntimeGetContextsInteractiveApiTest(
const RuntimeGetContextsInteractiveApiTest&) = delete;
RuntimeGetContextsInteractiveApiTest& operator=(
const RuntimeGetContextsInteractiveApiTest&) = delete;
~RuntimeGetContextsInteractiveApiTest() override = default;
// Runs `chrome.runtime.getContexts()` and returns the result as a
// base::Value.
base::Value GetContexts(const Extension& extension, std::string_view filter) {
static constexpr char kScriptTemplate[] =
R"((async () => {
chrome.test.sendScriptResult(
await chrome.runtime.getContexts(%s));
})();)";
std::string script = base::StringPrintf(kScriptTemplate, filter.data());
return BackgroundScriptExecutor::ExecuteScript(
profile(), extension.id(), script,
BackgroundScriptExecutor::ResultCapture::kSendScriptResult);
}
};
// Tests retrieving popup contexts using `chrome.runtime.getContexts()`.
// This needs to run as an interactive ui test because extension popups are
// closed on focus loss.
IN_PROC_BROWSER_TEST_F(RuntimeGetContextsInteractiveApiTest, GetPopupContext) {
static constexpr char kManifest[] =
R"({
"name": "Get Contexts",
"version": "0.1",
"manifest_version": 3,
"background": {
"service_worker": "background.js"
},
"action": { "default_popup": "popup.html" }
})";
TestExtensionDir test_dir;
test_dir.WriteManifest(kManifest);
test_dir.WriteFile(FILE_PATH_LITERAL("background.js"),
"// Intentionally blank");
test_dir.WriteFile(FILE_PATH_LITERAL("popup.html"),
"<html>I'm a popup!</html>");
const Extension* extension = LoadExtension(test_dir.UnpackedPath());
ASSERT_TRUE(extension);
std::unique_ptr<ExtensionActionTestHelper> toolbar_helper =
ExtensionActionTestHelper::Create(browser());
ExtensionHostTestHelper popup_waiter(profile(), extension->id());
popup_waiter.RestrictToType(mojom::ViewType::kExtensionPopup);
toolbar_helper->Press(extension->id());
ExtensionHost* popup_host = popup_waiter.WaitForHostCompletedFirstLoad();
content::RenderFrameHost* popup_frame =
popup_host->web_contents()->GetPrimaryMainFrame();
int expected_frame_id = ExtensionApiFrameIdMap::GetFrameId(popup_frame);
std::string expected_context_id =
ExtensionApiFrameIdMap::GetContextId(popup_frame).AsLowercaseString();
std::string expected_document_id =
ExtensionApiFrameIdMap::GetDocumentId(popup_frame).ToString();
std::string expected_frame_url =
extension->ResolveExtensionURL("popup.html").spec();
std::string expected_origin = extension->origin().Serialize();
// Query for popup-based contexts. There should only be one.
base::Value background_contexts =
GetContexts(*extension, R"({"contextTypes": ["POPUP"]})");
// Verify the properties of the returned context.
// NOTE: Currently, extension popups are considered to have a window ID of -1.
// This makes sense (they aren't really "in" a window), but there's also a
// good argument for using the window ID of the Browser they're anchored to.
// We may want to revisit this in the future.
static constexpr char kExpectedTemplate[] =
R"([{
"contextType": "POPUP",
"contextId": "%s",
"tabId": -1,
"windowId": -1,
"frameId": %d,
"documentId": "%s",
"documentUrl": "%s",
"documentOrigin": "%s",
"incognito": false
}])";
std::string expected =
base::StringPrintf(kExpectedTemplate, expected_context_id.c_str(),
expected_frame_id, expected_document_id.c_str(),
expected_frame_url.c_str(), expected_origin.c_str());
EXPECT_THAT(background_contexts, base::test::IsJson(expected));
}
} // namespace extensions
|