blob: a0c16f2478e8e61a51f221a39f9de2036b7268ec [file] [log] [blame]
// Copyright 2014 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 "libcef/renderer/extensions/extensions_renderer_client.h"
#include "libcef/common/cef_messages.h"
#include "libcef/renderer/extensions/extensions_dispatcher_delegate.h"
#include "libcef/renderer/render_thread_observer.h"
#include "base/command_line.h"
#include "chrome/common/url_constants.h"
#include "chrome/renderer/extensions/extension_process_policy.h"
#include "chrome/renderer/extensions/resource_request_policy.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/content_switches.h"
#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_thread.h"
#include "extensions/common/constants.h"
#include "extensions/common/permissions/permissions_data.h"
#include "extensions/common/switches.h"
#include "extensions/renderer/dispatcher.h"
#include "extensions/renderer/extension_frame_helper.h"
#include "extensions/renderer/extensions_render_frame_observer.h"
#include "extensions/renderer/guest_view/extensions_guest_view_container.h"
#include "extensions/renderer/guest_view/extensions_guest_view_container_dispatcher.h"
#include "extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.h"
#include "extensions/renderer/renderer_extension_registry.h"
#include "extensions/renderer/script_context.h"
#include "third_party/blink/public/web/web_document.h"
#include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/blink/public/web/web_plugin_params.h"
namespace extensions {
namespace {
void IsGuestViewApiAvailableToScriptContext(
bool* api_is_available,
extensions::ScriptContext* context) {
if (context->GetAvailability("guestViewInternal").is_available()) {
*api_is_available = true;
}
}
} // namespace
CefExtensionsRendererClient::CefExtensionsRendererClient() {}
CefExtensionsRendererClient::~CefExtensionsRendererClient() {}
bool CefExtensionsRendererClient::IsIncognitoProcess() const {
return CefRenderThreadObserver::is_incognito_process();
}
int CefExtensionsRendererClient::GetLowestIsolatedWorldId() const {
// CEF doesn't need to reserve world IDs for anything other than extensions,
// so we always return 1. Note that 0 is reserved for the global world.
return 1;
}
extensions::Dispatcher* CefExtensionsRendererClient::GetDispatcher() {
return extension_dispatcher_.get();
}
void CefExtensionsRendererClient::OnExtensionLoaded(
const extensions::Extension& extension) {
resource_request_policy_->OnExtensionLoaded(extension);
}
void CefExtensionsRendererClient::OnExtensionUnloaded(
const extensions::ExtensionId& extension_id) {
resource_request_policy_->OnExtensionUnloaded(extension_id);
}
bool CefExtensionsRendererClient::ExtensionAPIEnabledForServiceWorkerScript(
const GURL& scope,
const GURL& script_url) const {
// TODO(extensions): Implement to support background sevice worker scripts
// in extensions
return false;
}
void CefExtensionsRendererClient::RenderThreadStarted() {
content::RenderThread* thread = content::RenderThread::Get();
extension_dispatcher_.reset(new extensions::Dispatcher(
std::make_unique<extensions::CefExtensionsDispatcherDelegate>()));
extension_dispatcher_->OnRenderThreadStarted(thread);
resource_request_policy_.reset(
new extensions::ResourceRequestPolicy(extension_dispatcher_.get()));
guest_view_container_dispatcher_.reset(
new extensions::ExtensionsGuestViewContainerDispatcher());
thread->AddObserver(extension_dispatcher_.get());
thread->AddObserver(guest_view_container_dispatcher_.get());
}
void CefExtensionsRendererClient::RenderFrameCreated(
content::RenderFrame* render_frame,
service_manager::BinderRegistry* registry) {
new extensions::ExtensionsRenderFrameObserver(render_frame, registry);
new extensions::ExtensionFrameHelper(render_frame,
extension_dispatcher_.get());
extension_dispatcher_->OnRenderFrameCreated(render_frame);
}
bool CefExtensionsRendererClient::OverrideCreatePlugin(
content::RenderFrame* render_frame,
const blink::WebPluginParams& params) {
if (params.mime_type.Utf8() != content::kBrowserPluginMimeType)
return true;
bool guest_view_api_available = false;
extension_dispatcher_->script_context_set_iterator()->ForEach(
render_frame, base::Bind(&IsGuestViewApiAvailableToScriptContext,
&guest_view_api_available));
return !guest_view_api_available;
}
void CefExtensionsRendererClient::WillSendRequest(
blink::WebLocalFrame* frame,
ui::PageTransition transition_type,
const blink::WebURL& url,
const net::SiteForCookies& site_for_cookies,
const url::Origin* initiator_origin,
GURL* new_url,
bool* attach_same_site_cookies) {
if (initiator_origin &&
initiator_origin->scheme() == extensions::kExtensionScheme) {
const extensions::RendererExtensionRegistry* extension_registry =
extensions::RendererExtensionRegistry::Get();
const Extension* extension =
extension_registry->GetByID(initiator_origin->host());
if (extension) {
int tab_id = extensions::ExtensionFrameHelper::Get(
content::RenderFrame::FromWebFrame(frame))
->tab_id();
GURL request_url(url);
if (extension->permissions_data()->GetPageAccess(request_url, tab_id,
nullptr) ==
extensions::PermissionsData::PageAccess::kAllowed ||
extension->permissions_data()->GetContentScriptAccess(
request_url, tab_id, nullptr) ==
extensions::PermissionsData::PageAccess::kAllowed) {
*attach_same_site_cookies = true;
}
}
}
// Check whether the request should be allowed. If not allowed, we reset the
// URL to something invalid to prevent the request and cause an error.
if (url.ProtocolIs(extensions::kExtensionScheme) &&
!resource_request_policy_->CanRequestResource(GURL(url), frame,
transition_type)) {
*new_url = GURL(chrome::kExtensionInvalidRequestURL);
}
}
void CefExtensionsRendererClient::RunScriptsAtDocumentStart(
content::RenderFrame* render_frame) {
extension_dispatcher_->RunScriptsAtDocumentStart(render_frame);
}
void CefExtensionsRendererClient::RunScriptsAtDocumentEnd(
content::RenderFrame* render_frame) {
extension_dispatcher_->RunScriptsAtDocumentEnd(render_frame);
}
void CefExtensionsRendererClient::RunScriptsAtDocumentIdle(
content::RenderFrame* render_frame) {
extension_dispatcher_->RunScriptsAtDocumentIdle(render_frame);
}
// static
bool CefExtensionsRendererClient::IsStandaloneExtensionProcess() {
return base::CommandLine::ForCurrentProcess()->HasSwitch(
extensions::switches::kExtensionProcess);
}
// static
content::BrowserPluginDelegate*
CefExtensionsRendererClient::CreateBrowserPluginDelegate(
content::RenderFrame* render_frame,
const content::WebPluginInfo& info,
const std::string& mime_type,
const GURL& original_url) {
if (mime_type == content::kBrowserPluginMimeType)
return new extensions::ExtensionsGuestViewContainer(render_frame);
return new extensions::MimeHandlerViewContainer(render_frame, info, mime_type,
original_url);
}
} // namespace extensions