blob: ee454ae59226202d1716d0153aa2d273ecaa3bd0 [file] [log] [blame]
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/url_rewrite/browser/url_request_rewrite_rules_manager.h"
#include "components/url_rewrite/browser/url_request_rewrite_rules_validation.h"
#include "content/public/browser/web_contents.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
namespace url_rewrite {
UrlRequestRewriteRulesManager::UrlRequestRewriteRulesManager() = default;
UrlRequestRewriteRulesManager::~UrlRequestRewriteRulesManager() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}
bool UrlRequestRewriteRulesManager::AddWebContents(
content::WebContents* web_contents) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(web_contents);
if (updaters_.count(web_contents) > 0) {
return false;
}
auto updater = std::make_unique<Updater>(web_contents, cached_rules_);
updaters_.emplace(web_contents, std::move(updater));
return true;
}
bool UrlRequestRewriteRulesManager::RemoveWebContents(
content::WebContents* web_contents) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(web_contents);
auto iter = updaters_.find(web_contents);
if (iter == updaters_.end()) {
return false;
}
updaters_.erase(iter);
return true;
}
bool UrlRequestRewriteRulesManager::OnRulesUpdated(
mojom::UrlRequestRewriteRulesPtr rules) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!ValidateRules(rules.get())) {
return false;
}
cached_rules_ =
base::MakeRefCounted<UrlRequestRewriteRules>(std::move(rules));
// Send the updated rules to the receivers.
for (const auto& updater_pair : updaters_) {
updater_pair.second->OnRulesUpdated(cached_rules_);
}
return true;
}
const scoped_refptr<UrlRequestRewriteRules>&
UrlRequestRewriteRulesManager::GetCachedRules() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return cached_rules_;
}
size_t UrlRequestRewriteRulesManager::GetUpdatersSizeForTesting() const {
return updaters_.size();
}
UrlRequestRewriteRulesManager::Updater::Updater(
content::WebContents* web_contents,
const scoped_refptr<UrlRequestRewriteRules>& cached_rules)
: content::WebContentsObserver(web_contents), cached_rules_(cached_rules) {
web_contents->ForEachRenderFrameHost(
[this](content::RenderFrameHost* render_frame_host) {
MaybeRegisterExistingRenderFrame(render_frame_host);
});
}
UrlRequestRewriteRulesManager::Updater::~Updater() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}
void UrlRequestRewriteRulesManager::Updater::OnRulesUpdated(
const scoped_refptr<UrlRequestRewriteRules>& cached_rules) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(cached_rules);
cached_rules_ = cached_rules;
// Send the updated rules to the updaters.
for (const auto& receiver_pair : active_remotes_) {
receiver_pair.second->OnRulesUpdated(mojo::Clone(cached_rules_->data));
}
}
void UrlRequestRewriteRulesManager::Updater::MaybeRegisterExistingRenderFrame(
content::RenderFrameHost* render_frame_host) {
if (render_frame_host->IsRenderFrameLive()) {
// Call RenderFrameCreated() for frames that were created before this
// observer started observing this WebContents.
RenderFrameCreated(render_frame_host);
}
}
void UrlRequestRewriteRulesManager::Updater::RenderFrameCreated(
content::RenderFrameHost* render_frame_host) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// Register the frame rules receiver.
mojo::AssociatedRemote<mojom::UrlRequestRulesReceiver> rules_receiver;
render_frame_host->GetRemoteAssociatedInterfaces()->GetInterface(
&rules_receiver);
auto iter = active_remotes_.emplace(render_frame_host->GetGlobalId(),
std::move(rules_receiver));
DCHECK(iter.second);
if (cached_rules_) {
// Send an initial set of rules.
iter.first->second->OnRulesUpdated(mojo::Clone(cached_rules_->data));
}
}
void UrlRequestRewriteRulesManager::Updater::RenderFrameDeleted(
content::RenderFrameHost* render_frame_host) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
size_t removed = active_remotes_.erase(render_frame_host->GetGlobalId());
DCHECK_EQ(removed, 1u);
}
} // namespace url_rewrite