We need to manually add a ChromeExtensionWebContentsObserver to the WebView's WebContents now that the |enable_extension_apis| parameter is gone from the constructor, which we used to set to |true| causing the BubbleContentsWrapper to do it for us. Chromium change: https://github.com/chromium/chromium/commit/183029096a06ae326108700c8f6272c6cec9b174 commit 183029096a06ae326108700c8f6272c6cec9b174 Author: Lukasz Anforowicz <lukasza@chromium.org> Date: Tue Nov 16 19:45:05 2021 +0000 Introduce ContentBrowserClient::AttachUniversalWebContentsObservers. Problem description =================== Before this CL, there was a discrepancy in how Chrome Extensions were handled in the Browser process VS the Renderer processes: 1. Code in a Renderer process ensures that content scripts are injected into *all* elligible documents (ones with URLs that match patterns requested by an extension). This Renderer-side code is agnostic to whether the document is in a browser tab or in a different flavor of WebContents. This universal applicability of content scripts is desirable - if a user installs an extension to modify certain documents (e.g. change the behavior of https://example.com) then such user intent should be respected in all WebContents hosting such documents. 2. Code in the Browser process would create ExtensionWebContentsObserver (EWCO) only for some, but not for all WebContents. This was because when creating a new flavour of WebContents it was possible to miss the responsibility to construct EWCO - we've identified multiple WebContents flavours were EWCO was missing. The discrepancy between the Browser and the Rednderer processes would mean that some content scripts are injected but: A. They cannot talk to extensions::mojom::LocalFrameHost (which is bound by EWCO::BindLocalFrameHost) and therefore extension API calls do not work B. They are not recognized by ContentScriptTracker (which relies on notifications like EWCO::ReadyToCommitNavigation). This was responsible for majority of DumpWithoutCrashing reports tracked in https://crbug.com/1212918. Changes in this CL ================== This CL adds a new method to ContentBrowserClient - AttachUniversalWebContentsObservers (which gets called by the //content layer for every WebContents after it gets created and initialized). Implementation of the new method in ChromeContentBrowserClient constructs ChromeExtensionWebContentsObserver for each WebContents. For more background (and discussion of alternative approaches for addressing the problem) please see the document here: https://docs.google.com/document/d/1zITHyso0axNdAZV3qySgsoWW-p6jOEKbWqoVJbOW92c/edit?usp=sharing Bug: 1212918
138 lines
5.1 KiB
C++
138 lines
5.1 KiB
C++
/* Copyright (c) 2021 The Brave Authors. All rights reserved.
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include <memory>
|
|
#include <utility>
|
|
|
|
#include "brave/components/speedreader/speedreader_result_delegate.h"
|
|
#include "brave/components/speedreader/speedreader_rewriter_service.h"
|
|
#include "brave/components/speedreader/speedreader_throttle.h"
|
|
#include "brave/components/speedreader/speedreader_util.h"
|
|
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
|
|
#include "chrome/test/base/testing_browser_process.h"
|
|
#include "chrome/test/base/testing_profile.h"
|
|
#include "chrome/test/base/testing_profile_manager.h"
|
|
#include "components/content_settings/core/browser/host_content_settings_map.h"
|
|
#include "content/public/browser/browser_task_traits.h"
|
|
#include "content/public/browser/browser_thread.h"
|
|
#include "content/public/browser/site_instance.h"
|
|
#include "content/public/test/browser_task_environment.h"
|
|
#include "content/public/test/test_renderer_host.h"
|
|
#include "content/public/test/web_contents_tester.h"
|
|
#include "testing/gtest/include/gtest/gtest.h"
|
|
|
|
namespace speedreader {
|
|
|
|
namespace {
|
|
|
|
constexpr char kTestProfileName[] = "TestProfile";
|
|
|
|
class TestSpeedreaderResultDelegate : public SpeedreaderResultDelegate {
|
|
protected:
|
|
void OnDistillComplete() override {}
|
|
};
|
|
|
|
} // anonymous namespace
|
|
|
|
class SpeedreaderThrottleTest : public testing::Test {
|
|
public:
|
|
SpeedreaderThrottleTest() = default;
|
|
~SpeedreaderThrottleTest() override = default;
|
|
SpeedreaderThrottleTest(const SpeedreaderThrottleTest&) = delete;
|
|
SpeedreaderThrottleTest& operator=(const SpeedreaderThrottleTest&) = delete;
|
|
|
|
void SetUp() override {
|
|
profile_manager_ = std::make_unique<TestingProfileManager>(
|
|
TestingBrowserProcess::GetGlobal());
|
|
EXPECT_TRUE(profile_manager_->SetUp());
|
|
profile_ = profile_manager_->CreateTestingProfile(kTestProfileName);
|
|
auto instance = content::SiteInstance::CreateForURL(profile_, url());
|
|
web_contents_ =
|
|
content::WebContentsTester::CreateTestWebContents(profile_, instance);
|
|
}
|
|
|
|
void TearDown() override {
|
|
web_contents_.reset();
|
|
profile_manager_->DeleteTestingProfile(kTestProfileName);
|
|
}
|
|
|
|
GURL url() { return GURL("https://brave.com"); }
|
|
|
|
TestingProfile* profile() { return profile_; }
|
|
|
|
content::WebContents* web_contents() { return web_contents_.get(); }
|
|
|
|
HostContentSettingsMap* content_settings() {
|
|
return HostContentSettingsMapFactory::GetForProfile(profile());
|
|
}
|
|
|
|
std::unique_ptr<SpeedReaderThrottle> speedreader_throttle(
|
|
const GURL& url,
|
|
bool check_disabled_sites = false) {
|
|
auto runner = content::GetUIThreadTaskRunner({});
|
|
return SpeedReaderThrottle::MaybeCreateThrottleFor(
|
|
nullptr, content_settings(),
|
|
base::WeakPtr<TestSpeedreaderResultDelegate>(), url,
|
|
check_disabled_sites, runner);
|
|
}
|
|
|
|
private:
|
|
content::BrowserTaskEnvironment task_environment_;
|
|
content::RenderViewHostTestEnabler render_view_host_test_enabler_;
|
|
std::unique_ptr<content::WebContents> web_contents_;
|
|
std::unique_ptr<TestingProfileManager> profile_manager_;
|
|
TestingProfile* profile_;
|
|
TestSpeedreaderResultDelegate delegate_;
|
|
};
|
|
|
|
TEST_F(SpeedreaderThrottleTest, AllowThrottle) {
|
|
auto throttle = speedreader_throttle(url(), false /* check_disabled_sites */);
|
|
EXPECT_NE(throttle.get(), nullptr);
|
|
}
|
|
|
|
TEST_F(SpeedreaderThrottleTest, ToggleThrottle) {
|
|
auto runner = content::GetUIThreadTaskRunner({});
|
|
std::unique_ptr<SpeedReaderThrottle> throttle;
|
|
|
|
speedreader::SetEnabledForSite(content_settings(), url(), false);
|
|
throttle = speedreader_throttle(url(), true /* check_disabled_sites */);
|
|
EXPECT_EQ(throttle.get(), nullptr);
|
|
// no other domains are affected by the rule.
|
|
throttle =
|
|
speedreader_throttle(GURL("kevin.com"), true /* check_disabled_sites */);
|
|
EXPECT_NE(throttle.get(), nullptr);
|
|
|
|
speedreader::SetEnabledForSite(content_settings(), url(), true);
|
|
throttle = speedreader_throttle(url(), true /* check_disabled_sites */);
|
|
EXPECT_NE(throttle.get(), nullptr);
|
|
}
|
|
|
|
TEST_F(SpeedreaderThrottleTest, ThrottleIgnoreDisabled) {
|
|
auto runner = content::GetUIThreadTaskRunner({});
|
|
std::unique_ptr<SpeedReaderThrottle> throttle;
|
|
|
|
speedreader::SetEnabledForSite(content_settings(), url(), false);
|
|
|
|
throttle = speedreader_throttle(url(), true /* check_disabled_sites */);
|
|
EXPECT_EQ(throttle.get(), nullptr);
|
|
|
|
throttle = speedreader_throttle(url(), false /* check_disabled_sites */);
|
|
EXPECT_NE(throttle.get(), nullptr);
|
|
}
|
|
|
|
TEST_F(SpeedreaderThrottleTest, ThrottleNestedURL) {
|
|
auto runner = content::GetUIThreadTaskRunner({});
|
|
std::unique_ptr<SpeedReaderThrottle> throttle;
|
|
|
|
// Even though we call this function on SetSiteSpeedreadable, it should apply
|
|
// to all of brave.com.
|
|
speedreader::SetEnabledForSite(
|
|
content_settings(), GURL("https://brave.com/some/nested/page"), false);
|
|
throttle = speedreader_throttle(url(), true /* check_disabled_sites */);
|
|
EXPECT_EQ(throttle.get(), nullptr);
|
|
}
|
|
|
|
} // namespace speedreader
|