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
|
// 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 "chrome/browser/extensions/api/page_capture/page_capture_api.h"
#include <memory>
#include "base/test/values_test_util.h"
#include "chrome/browser/extensions/extension_service_test_base.h"
#include "chrome/browser/extensions/extension_tab_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/test/base/test_browser_window.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/web_contents_tester.h"
#include "extensions/browser/api_test_utils.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_builder.h"
#include "url/gurl.h"
namespace extensions {
class PageCaptureApiUnitTest : public ExtensionServiceTestBase {
protected:
void SetUp() override {
ExtensionServiceTestBase::SetUp();
InitializeEmptyExtensionService();
browser_window_ = std::make_unique<TestBrowserWindow>();
Browser::CreateParams params(profile(), true);
params.type = Browser::TYPE_NORMAL;
params.window = browser_window_.get();
browser_ = std::unique_ptr<Browser>(Browser::Create(params));
}
void TearDown() override {
browser_.reset();
browser_window_.reset();
ExtensionServiceTestBase::TearDown();
}
Browser* browser() { return browser_.get(); }
private:
std::unique_ptr<TestBrowserWindow> browser_window_;
std::unique_ptr<Browser> browser_;
};
// Tests that if a page navigates during a call to pageCature.saveAsMHTML(), the
// API call will result in an error.
TEST_F(PageCaptureApiUnitTest, PageNavigationDuringSaveAsMHTML) {
scoped_refptr<const Extension> extension =
ExtensionBuilder("Page Capture").AddAPIPermission("pageCapture").Build();
auto function = base::MakeRefCounted<PageCaptureSaveAsMHTMLFunction>();
function->set_extension(extension.get());
// Add a visible tab.
std::unique_ptr<content::WebContents> web_contents =
content::WebContentsTester::CreateTestWebContents(profile(), nullptr);
content::WebContentsTester* web_contents_tester =
content::WebContentsTester::For(web_contents.get());
browser()->tab_strip_model()->AppendWebContents(std::move(web_contents),
/*foreground=*/true);
web_contents_tester->NavigateAndCommit(GURL("https://www.google.com"));
const int tab_id = ExtensionTabUtil::GetTabId(
browser()->tab_strip_model()->GetWebContentsAt(0));
// To capture the page as MHTML, the extension function needs to hop from the
// UI thread to the IO thread to create the temporary file, then back to the
// UI thread to actually save the page contents. Since the URL access is only
// checked initially and a navigation could happen during the thread hops, the
// extension function should result in an error if a navigation happens
// between the initial check and the actual capture. To simulate this we start
// the extension function running, then trigger a synchronous navigation
// using the WebContentsTester immediately which will happen before the
// messaging between threads finishes.
// Regression test for crbug.com/1494490
function->SetBrowserContextForTesting(profile());
function->SetArgs(
base::Value::List().Append(base::Value::Dict().Set("tabId", tab_id)));
api_test_utils::SendResponseHelper response_helper(function.get());
function->RunWithValidation().Execute();
web_contents_tester->NavigateAndCommit(GURL("https://www.chromium.org"));
response_helper.WaitForResponse();
const base::Value::List* results = function->GetResultListForTest();
ASSERT_TRUE(results);
EXPECT_TRUE(results->empty()) << "Did not expect a result";
CHECK(function->response_type());
EXPECT_EQ(ExtensionFunction::ResponseType::kFailed,
*function->response_type());
EXPECT_EQ("Tab navigated before capture could complete.",
function->GetError());
// Clean up.
browser()->tab_strip_model()->CloseAllTabs();
}
} // namespace extensions
|