blob: c84973a42fe60952709035b5caf1378ff5651cec [file] [log] [blame]
// Copyright 2013 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 "chrome/renderer/worker_content_settings_client.h"
#include "base/memory/ptr_util.h"
#include "components/content_settings/renderer/content_settings_agent_impl.h"
#include "content/public/common/url_constants.h"
#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_thread.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/platform/url_conversion.h"
#include "third_party/blink/public/platform/web_security_origin.h"
#include "third_party/blink/public/web/web_document.h"
#include "third_party/blink/public/web/web_local_frame.h"
#include "url/origin.h"
WorkerContentSettingsClient::WorkerContentSettingsClient(
content::RenderFrame* render_frame)
: render_frame_id_(render_frame->GetRoutingID()) {
blink::WebLocalFrame* frame = render_frame->GetWebFrame();
const blink::WebDocument& document = frame->GetDocument();
if (document.GetSecurityOrigin().IsOpaque() ||
frame->Top()->GetSecurityOrigin().IsOpaque())
is_unique_origin_ = true;
document_origin_ = document.GetSecurityOrigin();
site_for_cookies_ = document.SiteForCookies();
top_frame_origin_ = document.TopFrameOrigin();
content::ChildThread::Get()->BindHostReceiver(
pending_content_settings_manager_.InitWithNewPipeAndPassReceiver());
content_settings::ContentSettingsAgentImpl* agent =
content_settings::ContentSettingsAgentImpl::Get(render_frame);
allow_running_insecure_content_ = agent->allow_running_insecure_content();
RendererContentSettingRules* rules = agent->GetRendererContentSettingRules();
if (rules) {
// Note: Makes a copy of the rules instead of directly using a pointer as
// there is no guarantee that the RenderFrame will exist throughout this
// object's lifetime.
content_setting_rules_ =
std::make_unique<RendererContentSettingRules>(*rules);
}
}
WorkerContentSettingsClient::WorkerContentSettingsClient(
const WorkerContentSettingsClient& other)
: is_unique_origin_(other.is_unique_origin_),
document_origin_(other.document_origin_),
site_for_cookies_(other.site_for_cookies_),
top_frame_origin_(other.top_frame_origin_),
allow_running_insecure_content_(other.allow_running_insecure_content_),
render_frame_id_(other.render_frame_id_) {
other.EnsureContentSettingsManager();
other.content_settings_manager_->Clone(
pending_content_settings_manager_.InitWithNewPipeAndPassReceiver());
if (other.content_setting_rules_)
content_setting_rules_ = std::make_unique<RendererContentSettingRules>(
*(other.content_setting_rules_));
}
WorkerContentSettingsClient::~WorkerContentSettingsClient() {}
std::unique_ptr<blink::WebContentSettingsClient>
WorkerContentSettingsClient::Clone() {
return base::WrapUnique(new WorkerContentSettingsClient(*this));
}
void WorkerContentSettingsClient::AllowStorageAccess(
StorageType storage_type,
base::OnceCallback<void(bool)> callback) {
if (is_unique_origin_) {
std::move(callback).Run(false);
return;
}
EnsureContentSettingsManager();
content_settings_manager_->AllowStorageAccess(
render_frame_id_,
content_settings::ContentSettingsAgentImpl::ConvertToMojoStorageType(
storage_type),
document_origin_, site_for_cookies_, top_frame_origin_,
std::move(callback));
}
bool WorkerContentSettingsClient::AllowStorageAccessSync(
StorageType storage_type) {
if (is_unique_origin_)
return false;
EnsureContentSettingsManager();
bool result = false;
content_settings_manager_->AllowStorageAccess(
render_frame_id_,
content_settings::ContentSettingsAgentImpl::ConvertToMojoStorageType(
storage_type),
document_origin_, site_for_cookies_, top_frame_origin_, &result);
return result;
}
bool WorkerContentSettingsClient::AllowRunningInsecureContent(
bool allowed_per_settings,
const blink::WebURL& url) {
if (!allow_running_insecure_content_ && !allowed_per_settings) {
EnsureContentSettingsManager();
content_settings_manager_->OnContentBlocked(
render_frame_id_, ContentSettingsType::MIXEDSCRIPT);
return false;
}
return true;
}
bool WorkerContentSettingsClient::AllowScriptFromSource(
bool enabled_per_settings,
const blink::WebURL& script_url) {
bool allow = enabled_per_settings;
if (allow && content_setting_rules_) {
GURL top_frame_origin_url = top_frame_origin_.GetURL();
// Allow DevTools to run worker scripts.
if (top_frame_origin_url.SchemeIs(content::kChromeDevToolsScheme))
return true;
for (const auto& rule : content_setting_rules_->script_rules) {
// The primary pattern was already matched in the browser process (see
// PageSpecificContentSettings::ReadyToCommitNavigation), so we only need
// to match the secondary pattern here.
if (rule.secondary_pattern.Matches(script_url)) {
allow = rule.GetContentSetting() != CONTENT_SETTING_BLOCK;
break;
}
}
}
if (!allow) {
EnsureContentSettingsManager();
content_settings_manager_->OnContentBlocked(
render_frame_id_, ContentSettingsType::JAVASCRIPT);
return false;
}
return true;
}
bool WorkerContentSettingsClient::ShouldAutoupgradeMixedContent() {
if (content_setting_rules_) {
if (content_setting_rules_->mixed_content_rules.size() > 0)
return content_setting_rules_->mixed_content_rules[0]
.GetContentSetting() != CONTENT_SETTING_ALLOW;
}
return false;
}
void WorkerContentSettingsClient::EnsureContentSettingsManager() const {
// Lazily bind `content_settings_manager_` so it is bound on the right thread.
if (content_settings_manager_)
return;
DCHECK(pending_content_settings_manager_);
content_settings_manager_.Bind(std::move(pending_content_settings_manager_));
}