blob: 86cd394e48c7dd43e23b35d63eb56e8e3d4edca3 [file] [log] [blame]
// Copyright (c) 2012 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 <atomic>
#include "base/base_switches.h"
#include "base/command_line.h"
#include "base/threading/thread_restrictions.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/extensions/active_tab_permission_granter.h"
#include "chrome/browser/extensions/api/page_capture/page_capture_api.h"
#include "chrome/browser/extensions/extension_action_runner.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/extensions/extension_util.h"
#include "chrome/browser/extensions/tab_helper.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/ui_test_utils.h"
#include "chromeos/login/login_state/scoped_test_public_session_login_state.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/test_utils.h"
#include "extensions/browser/extension_dialog_auto_confirm.h"
#include "extensions/common/permissions/permission_set.h"
#include "extensions/common/permissions/permissions_data.h"
#include "extensions/common/scoped_worker_based_extensions_channel.h"
#include "extensions/common/url_pattern_set.h"
#include "extensions/test/extension_test_message_listener.h"
#include "extensions/test/result_catcher.h"
#include "net/dns/mock_host_resolver.h"
#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "chromeos/login/login_state/login_state.h"
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
namespace extensions {
using ContextType = ExtensionApiTest::ContextType;
class PageCaptureSaveAsMHTMLDelegate
: public PageCaptureSaveAsMHTMLFunction::TestDelegate {
public:
PageCaptureSaveAsMHTMLDelegate() {
PageCaptureSaveAsMHTMLFunction::SetTestDelegate(this);
}
virtual ~PageCaptureSaveAsMHTMLDelegate() {
PageCaptureSaveAsMHTMLFunction::SetTestDelegate(NULL);
}
void OnTemporaryFileCreated(
scoped_refptr<storage::ShareableFileReference> file) override {
file->AddFinalReleaseCallback(
base::BindOnce(&PageCaptureSaveAsMHTMLDelegate::OnReleaseCallback,
base::Unretained(this)));
++temp_file_count_;
}
void WaitForFinalRelease() {
if (temp_file_count_ > 0)
run_loop_.Run();
}
int temp_file_count() const { return temp_file_count_; }
private:
void OnReleaseCallback(const base::FilePath& path) {
if (--temp_file_count_ == 0)
release_closure_.Run();
}
base::RunLoop run_loop_;
base::RepeatingClosure release_closure_ = run_loop_.QuitClosure();
std::atomic<int> temp_file_count_{0};
};
class ExtensionPageCaptureApiTest
: public ExtensionApiTest,
public testing::WithParamInterface<ContextType> {
public:
ExtensionPageCaptureApiTest() {
// Service Workers are currently only available on certain channels, so set
// the channel for those tests.
if (GetParam() == ContextType::kServiceWorker)
current_channel_ = std::make_unique<ScopedWorkerBasedExtensionsChannel>();
}
void SetUpCommandLine(base::CommandLine* command_line) override {
ExtensionApiTest::SetUpCommandLine(command_line);
command_line->AppendSwitchASCII(switches::kJavaScriptFlags, "--expose-gc");
}
void SetUpOnMainThread() override {
ExtensionApiTest::SetUpOnMainThread();
host_resolver()->AddRule("*", "127.0.0.1");
}
bool RunTest(const std::string& extension_name) {
return RunTestWithArg(extension_name, nullptr);
}
bool RunTestWithArg(const std::string& extension_name,
const char* custom_arg) {
return RunTestWithFlagsAndArg(extension_name, custom_arg,
kFlagEnableFileAccess);
}
bool RunTestWithFlagsAndArg(const std::string& extension_name,
const char* custom_arg,
int browser_test_flags) {
if (GetParam() == ContextType::kServiceWorker)
browser_test_flags |= kFlagRunAsServiceWorkerBasedExtension;
return RunExtensionTestWithFlagsAndArg(extension_name, custom_arg,
browser_test_flags, kFlagNone);
}
void WaitForFileCleanup(PageCaptureSaveAsMHTMLDelegate* delegate) {
// Garbage collection in SW-based extensions doesn't clean up the temp
// file.
if (GetParam() != ContextType::kServiceWorker)
delegate->WaitForFinalRelease();
}
private:
std::unique_ptr<ScopedWorkerBasedExtensionsChannel> current_channel_;
};
INSTANTIATE_TEST_SUITE_P(PersistentBackground,
ExtensionPageCaptureApiTest,
::testing::Values(ContextType::kPersistentBackground));
INSTANTIATE_TEST_SUITE_P(ServiceWorker,
ExtensionPageCaptureApiTest,
::testing::Values(ContextType::kServiceWorker));
// Flaky on all platforms: https://crbug.com/1156323
IN_PROC_BROWSER_TEST_P(ExtensionPageCaptureApiTest,
DISABLED_SaveAsMHTMLWithoutFileAccess) {
ASSERT_TRUE(StartEmbeddedTestServer());
PageCaptureSaveAsMHTMLDelegate delegate;
ASSERT_TRUE(RunTestWithFlagsAndArg("page_capture",
"ONLY_PAGE_CAPTURE_PERMISSION", kFlagNone))
<< message_;
WaitForFileCleanup(&delegate);
}
IN_PROC_BROWSER_TEST_P(ExtensionPageCaptureApiTest, SaveAsMHTMLWithFileAccess) {
ASSERT_TRUE(StartEmbeddedTestServer());
PageCaptureSaveAsMHTMLDelegate delegate;
ASSERT_TRUE(RunTest("page_capture")) << message_;
WaitForFileCleanup(&delegate);
}
#if BUILDFLAG(IS_CHROMEOS_ASH)
IN_PROC_BROWSER_TEST_P(ExtensionPageCaptureApiTest,
PublicSessionRequestAllowed) {
ASSERT_TRUE(StartEmbeddedTestServer());
PageCaptureSaveAsMHTMLDelegate delegate;
chromeos::ScopedTestPublicSessionLoginState login_state;
// Resolve Permission dialog with Allow.
ScopedTestDialogAutoConfirm auto_confirm(ScopedTestDialogAutoConfirm::ACCEPT);
ASSERT_TRUE(RunTest("page_capture")) << message_;
WaitForFileCleanup(&delegate);
}
IN_PROC_BROWSER_TEST_P(ExtensionPageCaptureApiTest,
PublicSessionRequestDenied) {
ASSERT_TRUE(StartEmbeddedTestServer());
PageCaptureSaveAsMHTMLDelegate delegate;
chromeos::ScopedTestPublicSessionLoginState login_state;
// Resolve Permission dialog with Deny.
ScopedTestDialogAutoConfirm auto_confirm(ScopedTestDialogAutoConfirm::CANCEL);
ASSERT_TRUE(RunTestWithArg("page_capture", "REQUEST_DENIED")) << message_;
EXPECT_EQ(0, delegate.temp_file_count());
}
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
} // namespace extensions