// 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())); 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 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