Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(7381)

Unified Diff: chrome/renderer/extensions/chrome_extensions_renderer_client.cc

Issue 1394283003: Move more extensions code into ChromeExtensionsRendererClient. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: IWYU Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/renderer/extensions/chrome_extensions_renderer_client.cc
diff --git a/chrome/renderer/extensions/chrome_extensions_renderer_client.cc b/chrome/renderer/extensions/chrome_extensions_renderer_client.cc
index 15278e78cb9137358bc8bace77060190de2ef057..f0ffe3720a84ab16515cafc920cdc35ad5699c5c 100644
--- a/chrome/renderer/extensions/chrome_extensions_renderer_client.cc
+++ b/chrome/renderer/extensions/chrome_extensions_renderer_client.cc
@@ -4,9 +4,113 @@
#include "chrome/renderer/extensions/chrome_extensions_renderer_client.h"
+#include "base/command_line.h"
#include "base/lazy_instance.h"
#include "chrome/common/chrome_isolated_world_ids.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/extensions/extension_constants.h"
+#include "chrome/common/extensions/extension_metrics.h"
+#include "chrome/common/extensions/extension_process_policy.h"
+#include "chrome/common/url_constants.h"
#include "chrome/renderer/chrome_render_process_observer.h"
+#include "chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.h"
+#include "chrome/renderer/extensions/renderer_permissions_policy_delegate.h"
+#include "chrome/renderer/extensions/resource_request_policy.h"
+#include "chrome/renderer/media/cast_ipc_dispatcher.h"
+#include "content/public/common/content_constants.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/renderer/render_thread.h"
+#include "extensions/common/constants.h"
+#include "extensions/common/extension.h"
+#include "extensions/common/extension_set.h"
+#include "extensions/common/switches.h"
+#include "extensions/renderer/dispatcher.h"
+#include "extensions/renderer/extension_frame_helper.h"
+#include "extensions/renderer/extension_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/script_context.h"
+#include "third_party/WebKit/public/platform/WebURL.h"
+#include "third_party/WebKit/public/web/WebDocument.h"
+#include "third_party/WebKit/public/web/WebLocalFrame.h"
+#include "third_party/WebKit/public/web/WebPluginParams.h"
+
+using extensions::Extension;
+
+namespace {
+
+bool IsStandaloneExtensionProcess() {
+ return base::CommandLine::ForCurrentProcess()->HasSwitch(
+ extensions::switches::kExtensionProcess);
+}
+
+void IsGuestViewApiAvailableToScriptContext(
+ bool* api_is_available,
+ extensions::ScriptContext* context) {
+ if (context->GetAvailability("guestViewInternal").is_available()) {
+ *api_is_available = true;
+ }
+}
+
+// Returns true if the frame is navigating to an URL either into or out of an
+// extension app's extent.
+bool CrossesExtensionExtents(blink::WebLocalFrame* frame,
+ const GURL& new_url,
+ bool is_extension_url,
+ bool is_initial_navigation) {
+ DCHECK(!frame->parent());
+ GURL old_url(frame->document().url());
+
+ extensions::RendererExtensionRegistry* extension_registry =
+ extensions::RendererExtensionRegistry::Get();
+
+ // If old_url is still empty and this is an initial navigation, then this is
+ // a window.open operation. We should look at the opener URL. Note that the
+ // opener is a local frame in this case.
+ if (is_initial_navigation && old_url.is_empty() && frame->opener()) {
+ blink::WebLocalFrame* opener_frame = frame->opener()->toWebLocalFrame();
+
+ // If we're about to open a normal web page from a same-origin opener stuck
+ // in an extension process, we want to keep it in process to allow the
+ // opener to script it.
+ blink::WebDocument opener_document = opener_frame->document();
+ blink::WebSecurityOrigin opener_origin = opener_document.securityOrigin();
+ bool opener_is_extension_url = !opener_origin.isUnique() &&
+ extension_registry->GetExtensionOrAppByURL(
+ opener_document.url()) != nullptr;
+ if (!is_extension_url && !opener_is_extension_url &&
+ IsStandaloneExtensionProcess() &&
+ opener_origin.canRequest(blink::WebURL(new_url)))
+ return false;
+
+ // In all other cases, we want to compare against the URL that determines
+ // the type of process. In default Chrome, that's the URL of the opener's
+ // top frame and not the opener frame itself. In --site-per-process, we
+ // can use the opener frame itself.
+ // TODO(nick): Either wire this up to SiteIsolationPolicy, or to state on
+ // |opener_frame|/its ancestors.
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kSitePerProcess) ||
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kIsolateExtensions))
+ old_url = opener_frame->document().url();
+ else
+ old_url = opener_frame->top()->document().url();
+ }
+
+ // Only consider keeping non-app URLs in an app process if this window
+ // has an opener (in which case it might be an OAuth popup that tries to
+ // script an iframe within the app).
+ bool should_consider_workaround = !!frame->opener();
+
+ return extensions::CrossesExtensionProcessBoundary(
+ *extension_registry->GetMainThreadExtensionSet(), old_url, new_url,
+ should_consider_workaround);
+}
+
+} // namespace
ChromeExtensionsRendererClient::ChromeExtensionsRendererClient() {}
@@ -26,3 +130,176 @@ bool ChromeExtensionsRendererClient::IsIncognitoProcess() const {
int ChromeExtensionsRendererClient::GetLowestIsolatedWorldId() const {
return chrome::ISOLATED_WORLD_ID_EXTENSIONS;
}
+
+void ChromeExtensionsRendererClient::RenderThreadStarted() {
+ content::RenderThread* thread = content::RenderThread::Get();
+ extension_dispatcher_delegate_.reset(
+ new ChromeExtensionsDispatcherDelegate());
+ // ChromeRenderViewTest::SetUp() creates its own ExtensionDispatcher and
+ // injects it using SetExtensionDispatcher(). Don't overwrite it.
+ if (!extension_dispatcher_) {
+ extension_dispatcher_.reset(
+ new extensions::Dispatcher(extension_dispatcher_delegate_.get()));
+ }
+ permissions_policy_delegate_.reset(
+ new extensions::RendererPermissionsPolicyDelegate(
+ extension_dispatcher_.get()));
+ 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());
+ thread->AddFilter(new CastIPCDispatcher(thread->GetIOMessageLoopProxy()));
+}
+
+void ChromeExtensionsRendererClient::RenderFrameCreated(
+ content::RenderFrame* render_frame) {
+ new extensions::ExtensionsRenderFrameObserver(render_frame);
+ new extensions::ExtensionFrameHelper(render_frame,
+ extension_dispatcher_.get());
+ extension_dispatcher_->OnRenderFrameCreated(render_frame);
+}
+
+void ChromeExtensionsRendererClient::RenderViewCreated(
+ content::RenderView* render_view) {
+ new extensions::ExtensionHelper(render_view, extension_dispatcher_.get());
+}
+
+bool ChromeExtensionsRendererClient::OverrideCreatePlugin(
+ content::RenderFrame* render_frame,
+ const blink::WebPluginParams& params) {
+ if (params.mimeType.utf8() != content::kBrowserPluginMimeType)
+ return true;
+
+ bool guest_view_api_available = false;
+ extension_dispatcher_->script_context_set().ForEach(
+ render_frame, base::Bind(&IsGuestViewApiAvailableToScriptContext,
+ &guest_view_api_available));
+ return !guest_view_api_available;
+}
+
+bool ChromeExtensionsRendererClient::AllowPopup() {
+ extensions::ScriptContext* current_context =
+ extension_dispatcher_->script_context_set().GetCurrent();
+ if (!current_context || !current_context->extension())
+ return false;
+
+ // See http://crbug.com/117446 for the subtlety of this check.
+ switch (current_context->context_type()) {
+ case extensions::Feature::UNSPECIFIED_CONTEXT:
+ case extensions::Feature::WEB_PAGE_CONTEXT:
+ case extensions::Feature::UNBLESSED_EXTENSION_CONTEXT:
+ case extensions::Feature::WEBUI_CONTEXT:
+ case extensions::Feature::SERVICE_WORKER_CONTEXT:
+ return false;
+ case extensions::Feature::BLESSED_EXTENSION_CONTEXT:
+ case extensions::Feature::CONTENT_SCRIPT_CONTEXT:
+ return true;
+ case extensions::Feature::BLESSED_WEB_PAGE_CONTEXT:
+ return !current_context->web_frame()->parent();
+ default:
+ NOTREACHED();
+ return false;
+ }
+}
+
+bool ChromeExtensionsRendererClient::WillSendRequest(
+ blink::WebFrame* frame,
+ ui::PageTransition transition_type,
+ const GURL& url,
+ GURL* new_url) {
+ if (url.SchemeIs(extensions::kExtensionScheme) &&
+ !resource_request_policy_->CanRequestResource(url, frame,
+ transition_type)) {
+ *new_url = GURL(chrome::kExtensionInvalidRequestURL);
+ return true;
+ }
+
+ if (url.SchemeIs(extensions::kExtensionResourceScheme) &&
+ !resource_request_policy_->CanRequestExtensionResourceScheme(url,
+ frame)) {
+ *new_url = GURL(chrome::kExtensionResourceInvalidRequestURL);
+ return true;
+ }
+
+ return false;
+}
+
+void ChromeExtensionsRendererClient::SetExtensionDispatcherForTest(
+ scoped_ptr<extensions::Dispatcher> extension_dispatcher) {
+ extension_dispatcher_ = extension_dispatcher.Pass();
+ permissions_policy_delegate_.reset(
+ new extensions::RendererPermissionsPolicyDelegate(
+ extension_dispatcher_.get()));
+ content::RenderThread::Get()->RegisterExtension(
+ extensions::SafeBuiltins::CreateV8Extension());
+}
+
+extensions::Dispatcher*
+ChromeExtensionsRendererClient::GetExtensionDispatcherForTest() {
+ return extension_dispatcher();
+}
+
+// static
+bool ChromeExtensionsRendererClient::ShouldFork(blink::WebLocalFrame* frame,
+ const GURL& url,
+ bool is_initial_navigation,
+ bool is_server_redirect,
+ bool* send_referrer) {
+ const extensions::RendererExtensionRegistry* extension_registry =
+ extensions::RendererExtensionRegistry::Get();
+
+ // Determine if the new URL is an extension (excluding bookmark apps).
+ const Extension* new_url_extension = extensions::GetNonBookmarkAppExtension(
+ *extension_registry->GetMainThreadExtensionSet(), url);
+ bool is_extension_url = !!new_url_extension;
+
+ // If the navigation would cross an app extent boundary, we also need
+ // to defer to the browser to ensure process isolation. This is not necessary
+ // for server redirects, which will be transferred to a new process by the
+ // browser process when they are ready to commit. It is necessary for client
+ // redirects, which won't be transferred in the same way.
+ if (!is_server_redirect &&
+ CrossesExtensionExtents(frame, url, is_extension_url,
+ is_initial_navigation)) {
+ // Include the referrer in this case since we're going from a hosted web
+ // page. (the packaged case is handled previously by the extension
+ // navigation test)
+ *send_referrer = true;
+
+ const Extension* extension =
+ extension_registry->GetExtensionOrAppByURL(url);
+ if (extension && extension->is_app()) {
+ extensions::RecordAppLaunchType(
+ extension_misc::APP_LAUNCH_CONTENT_NAVIGATION, extension->GetType());
+ }
+ return true;
+ }
+
+ // If this is a reload, check whether it has the wrong process type. We
+ // should send it to the browser if it's an extension URL (e.g., hosted app)
+ // in a normal process, or if it's a process for an extension that has been
+ // uninstalled. Without --site-per-process mode, we never fork processes for
+ // subframes, so this check only makes sense for top-level frames.
+ // TODO(alexmos,nasko): Figure out how this check should work when reloading
+ // subframes in --site-per-process mode.
+ if (!frame->parent() && frame->document().url() == url) {
+ if (is_extension_url != IsStandaloneExtensionProcess())
+ return true;
+ }
+ return false;
+}
+
+// static
+content::BrowserPluginDelegate*
+ChromeExtensionsRendererClient::CreateBrowserPluginDelegate(
+ content::RenderFrame* render_frame,
+ 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, mime_type,
+ original_url);
+}
« no previous file with comments | « chrome/renderer/extensions/chrome_extensions_renderer_client.h ('k') | chrome/renderer/page_load_histograms.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698