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

Side by Side Diff: chrome/renderer/extensions/chrome_extensions_renderer_client.cc

Issue 2386503002: With --isolate-extensions, forking (via OpenURL) for extensions is not needed.
Patch Set: Rebasing... Created 3 years, 7 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 unified diff | Download patch
« no previous file with comments | « chrome/renderer/chrome_content_renderer_client.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/renderer/extensions/chrome_extensions_renderer_client.h" 5 #include "chrome/renderer/extensions/chrome_extensions_renderer_client.h"
6 6
7 #include <memory> 7 #include <memory>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/command_line.h" 10 #include "base/command_line.h"
11 #include "base/lazy_instance.h" 11 #include "base/lazy_instance.h"
12 #include "chrome/common/chrome_isolated_world_ids.h" 12 #include "chrome/common/chrome_isolated_world_ids.h"
13 #include "chrome/common/chrome_switches.h" 13 #include "chrome/common/chrome_switches.h"
14 #include "chrome/common/extensions/extension_constants.h" 14 #include "chrome/common/extensions/extension_constants.h"
15 #include "chrome/common/extensions/extension_metrics.h" 15 #include "chrome/common/extensions/extension_metrics.h"
16 #include "chrome/common/extensions/extension_process_policy.h"
17 #include "chrome/common/url_constants.h" 16 #include "chrome/common/url_constants.h"
18 #include "chrome/renderer/chrome_render_thread_observer.h" 17 #include "chrome/renderer/chrome_render_thread_observer.h"
19 #include "chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.h" 18 #include "chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.h"
20 #include "chrome/renderer/extensions/renderer_permissions_policy_delegate.h" 19 #include "chrome/renderer/extensions/renderer_permissions_policy_delegate.h"
21 #include "chrome/renderer/extensions/resource_request_policy.h" 20 #include "chrome/renderer/extensions/resource_request_policy.h"
22 #include "chrome/renderer/media/cast_ipc_dispatcher.h" 21 #include "chrome/renderer/media/cast_ipc_dispatcher.h"
23 #include "content/public/common/content_constants.h" 22 #include "content/public/common/content_constants.h"
24 #include "content/public/common/content_switches.h" 23 #include "content/public/common/content_switches.h"
25 #include "content/public/renderer/render_thread.h" 24 #include "content/public/renderer/render_thread.h"
26 #include "extensions/common/constants.h" 25 #include "extensions/common/constants.h"
27 #include "extensions/common/extension.h" 26 #include "extensions/common/extension.h"
28 #include "extensions/common/extension_set.h" 27 #include "extensions/common/extension_set.h"
28 #include "extensions/common/manifest_handlers/app_isolation_info.h"
29 #include "extensions/common/switches.h" 29 #include "extensions/common/switches.h"
30 #include "extensions/renderer/dispatcher.h" 30 #include "extensions/renderer/dispatcher.h"
31 #include "extensions/renderer/extension_frame_helper.h" 31 #include "extensions/renderer/extension_frame_helper.h"
32 #include "extensions/renderer/extension_helper.h" 32 #include "extensions/renderer/extension_helper.h"
33 #include "extensions/renderer/extensions_render_frame_observer.h" 33 #include "extensions/renderer/extensions_render_frame_observer.h"
34 #include "extensions/renderer/guest_view/extensions_guest_view_container.h" 34 #include "extensions/renderer/guest_view/extensions_guest_view_container.h"
35 #include "extensions/renderer/guest_view/extensions_guest_view_container_dispatc her.h" 35 #include "extensions/renderer/guest_view/extensions_guest_view_container_dispatc her.h"
36 #include "extensions/renderer/guest_view/mime_handler_view/mime_handler_view_con tainer.h" 36 #include "extensions/renderer/guest_view/mime_handler_view/mime_handler_view_con tainer.h"
37 #include "extensions/renderer/script_context.h" 37 #include "extensions/renderer/script_context.h"
38 #include "third_party/WebKit/public/platform/WebURL.h" 38 #include "third_party/WebKit/public/platform/WebURL.h"
39 #include "third_party/WebKit/public/web/WebDocument.h" 39 #include "third_party/WebKit/public/web/WebDocument.h"
40 #include "third_party/WebKit/public/web/WebLocalFrame.h" 40 #include "third_party/WebKit/public/web/WebLocalFrame.h"
41 #include "third_party/WebKit/public/web/WebPluginParams.h" 41 #include "third_party/WebKit/public/web/WebPluginParams.h"
42 #include "url/gurl.h"
42 43
43 using extensions::Extension; 44 using extensions::Extension;
44 45
45 namespace { 46 namespace {
46 47
47 bool IsStandaloneExtensionProcess() { 48 bool IsStandaloneExtensionProcess() {
48 return base::CommandLine::ForCurrentProcess()->HasSwitch( 49 return base::CommandLine::ForCurrentProcess()->HasSwitch(
49 extensions::switches::kExtensionProcess); 50 extensions::switches::kExtensionProcess);
50 } 51 }
51 52
52 void IsGuestViewApiAvailableToScriptContext( 53 void IsGuestViewApiAvailableToScriptContext(
53 bool* api_is_available, 54 bool* api_is_available,
54 extensions::ScriptContext* context) { 55 extensions::ScriptContext* context) {
55 if (context->GetAvailability("guestViewInternal").is_available()) { 56 if (context->GetAvailability("guestViewInternal").is_available()) {
56 *api_is_available = true; 57 *api_is_available = true;
57 } 58 }
58 } 59 }
59 60
61 // Returns the extension for the given URL. Excludes extension objects for
62 // bookmark apps, which do not use the app process model.
63 const Extension* GetNonBookmarkAppExtension(
64 const extensions::ExtensionSet& extensions,
65 const GURL& url) {
66 // Exclude bookmark apps, which do not use the app process model.
67 const Extension* extension = extensions.GetExtensionOrAppByURL(url);
68 if (extension && extension->from_bookmark())
69 extension = NULL;
70 return extension;
71 }
72
73 bool IsHostedApp(const extensions::ExtensionSet& extensions, const GURL& url) {
74 const extensions::Extension* extension =
75 GetNonBookmarkAppExtension(extensions, url);
76 return extension && extension->is_app();
77 }
78
79 // Check if navigating a toplevel page from |old_url| to |new_url| would cross
80 // an extension process boundary (e.g. navigating from a web URL into an
81 // extension URL).
82 // We temporarily consider a workaround where we will keep non-app URLs in
83 // an app process, but only if |should_consider_workaround| is true. See
84 // http://crbug.com/59285.
85 bool CrossesExtensionProcessBoundary(const extensions::ExtensionSet& extensions,
86 const GURL& old_url,
87 const GURL& new_url,
88 bool should_consider_workaround) {
89 const extensions::Extension* old_url_extension =
90 GetNonBookmarkAppExtension(extensions, old_url);
91 const extensions::Extension* new_url_extension =
92 GetNonBookmarkAppExtension(extensions, new_url);
93
94 // TODO(creis): Temporary workaround for crbug.com/59285: Do not swap process
95 // to navigate from a hosted app to a normal page or another hosted app
96 // (unless either is the web store). This is because some OAuth providers
97 // use non-app popups that communicate with non-app iframes inside the app
98 // (e.g., Facebook). This would require out-of-process iframes to support.
99 // See http://crbug.com/99379.
100 // Note that we skip this exception for isolated apps, which require strict
101 // process separation from non-app pages.
102 if (should_consider_workaround) {
103 bool old_url_is_hosted_app =
104 old_url_extension && !old_url_extension->web_extent().is_empty() &&
105 !extensions::AppIsolationInfo::HasIsolatedStorage(old_url_extension);
106 bool new_url_is_normal_or_hosted =
107 !new_url_extension ||
108 (!new_url_extension->web_extent().is_empty() &&
109 !extensions::AppIsolationInfo::HasIsolatedStorage(new_url_extension));
110 bool either_is_web_store =
111 (old_url_extension &&
112 old_url_extension->id() == extensions::kWebStoreAppId) ||
113 (new_url_extension &&
114 new_url_extension->id() == extensions::kWebStoreAppId);
115 if (old_url_is_hosted_app && new_url_is_normal_or_hosted &&
116 !either_is_web_store)
117 return false;
118 }
119
120 return old_url_extension != new_url_extension;
121 }
122
60 // Returns true if the frame is navigating to an URL either into or out of an 123 // Returns true if the frame is navigating to an URL either into or out of an
61 // extension app's extent. 124 // extension app's extent.
62 bool CrossesExtensionExtents(blink::WebLocalFrame* frame, 125 bool CrossesHostedAppExtents(blink::WebLocalFrame* frame,
63 const GURL& new_url, 126 const GURL& new_url,
64 bool is_extension_url, 127 bool is_extension_url,
65 bool is_initial_navigation) { 128 bool is_initial_navigation) {
66 DCHECK(!frame->Parent()); 129 DCHECK(!frame->Parent());
67 GURL old_url(frame->GetDocument().Url()); 130 GURL old_url(frame->GetDocument().Url());
68 131
69 extensions::RendererExtensionRegistry* extension_registry = 132 extensions::RendererExtensionRegistry* extension_registry =
70 extensions::RendererExtensionRegistry::Get(); 133 extensions::RendererExtensionRegistry::Get();
134 const extensions::ExtensionSet& main_thread_extensions =
135 *extension_registry->GetMainThreadExtensionSet();
71 136
72 // If old_url is still empty and this is an initial navigation, then this is 137 // If old_url is still empty and this is an initial navigation, then this is
73 // a window.open operation. We should look at the opener URL. Note that the 138 // a window.open operation. We should look at the opener URL. Note that the
74 // opener is a local frame in this case. 139 // opener is a local frame in this case.
75 if (is_initial_navigation && old_url.is_empty() && frame->Opener()) { 140 if (is_initial_navigation && old_url.is_empty() && frame->Opener()) {
76 blink::WebLocalFrame* opener_frame = frame->Opener()->ToWebLocalFrame(); 141 blink::WebLocalFrame* opener_frame = frame->Opener()->ToWebLocalFrame();
77 142
78 // We want to compare against the URL that determines the type of 143 // We want to compare against the URL that determines the type of
79 // process. Use the URL of the opener's local frame root, which will 144 // process. Use the URL of the opener's local frame root, which will
80 // correctly handle any site isolation modes (e.g. --site-per-process). 145 // correctly handle any site isolation modes (e.g. --site-per-process).
(...skipping 13 matching lines...) Expand all
94 extension_registry->GetExtensionOrAppByURL(old_url); 159 extension_registry->GetExtensionOrAppByURL(old_url);
95 bool opener_is_web_store = 160 bool opener_is_web_store =
96 opener_top_extension && 161 opener_top_extension &&
97 opener_top_extension->id() == extensions::kWebStoreAppId; 162 opener_top_extension->id() == extensions::kWebStoreAppId;
98 if (!is_extension_url && !opener_is_extension_url && !opener_is_web_store && 163 if (!is_extension_url && !opener_is_extension_url && !opener_is_web_store &&
99 IsStandaloneExtensionProcess() && 164 IsStandaloneExtensionProcess() &&
100 opener_origin.CanRequest(blink::WebURL(new_url))) 165 opener_origin.CanRequest(blink::WebURL(new_url)))
101 return false; 166 return false;
102 } 167 }
103 168
169 // With --isolate-extensions, forking is no longer needed to isolate
170 // extensions into separate renderer processes (i.e. isolation should
171 // be enforced by the transfer logic).
172 bool old_or_new_is_hosted_app =
173 IsHostedApp(main_thread_extensions, old_url) ||
174 IsHostedApp(main_thread_extensions, new_url);
175 if (!old_or_new_is_hosted_app)
176 return false;
177
104 // Only consider keeping non-app URLs in an app process if this window 178 // Only consider keeping non-app URLs in an app process if this window
105 // has an opener (in which case it might be an OAuth popup that tries to 179 // has an opener (in which case it might be an OAuth popup that tries to
106 // script an iframe within the app). 180 // script an iframe within the app).
107 bool should_consider_workaround = !!frame->Opener(); 181 bool should_consider_workaround = !!frame->Opener();
108 182
109 return extensions::CrossesExtensionProcessBoundary( 183 return CrossesExtensionProcessBoundary(main_thread_extensions, old_url,
110 *extension_registry->GetMainThreadExtensionSet(), old_url, new_url, 184 new_url, should_consider_workaround);
111 should_consider_workaround);
112 } 185 }
113 186
114 } // namespace 187 } // namespace
115 188
116 ChromeExtensionsRendererClient::ChromeExtensionsRendererClient() {} 189 ChromeExtensionsRendererClient::ChromeExtensionsRendererClient() {}
117 190
118 ChromeExtensionsRendererClient::~ChromeExtensionsRendererClient() {} 191 ChromeExtensionsRendererClient::~ChromeExtensionsRendererClient() {}
119 192
120 // static 193 // static
121 ChromeExtensionsRendererClient* ChromeExtensionsRendererClient::GetInstance() { 194 ChromeExtensionsRendererClient* ChromeExtensionsRendererClient::GetInstance() {
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 // static 312 // static
240 bool ChromeExtensionsRendererClient::ShouldFork(blink::WebLocalFrame* frame, 313 bool ChromeExtensionsRendererClient::ShouldFork(blink::WebLocalFrame* frame,
241 const GURL& url, 314 const GURL& url,
242 bool is_initial_navigation, 315 bool is_initial_navigation,
243 bool is_server_redirect, 316 bool is_server_redirect,
244 bool* send_referrer) { 317 bool* send_referrer) {
245 const extensions::RendererExtensionRegistry* extension_registry = 318 const extensions::RendererExtensionRegistry* extension_registry =
246 extensions::RendererExtensionRegistry::Get(); 319 extensions::RendererExtensionRegistry::Get();
247 320
248 // Determine if the new URL is an extension (excluding bookmark apps). 321 // Determine if the new URL is an extension (excluding bookmark apps).
249 const Extension* new_url_extension = extensions::GetNonBookmarkAppExtension( 322 const Extension* new_url_extension = GetNonBookmarkAppExtension(
250 *extension_registry->GetMainThreadExtensionSet(), url); 323 *extension_registry->GetMainThreadExtensionSet(), url);
251 bool is_extension_url = !!new_url_extension; 324 bool is_extension_url = !!new_url_extension;
252 325
253 // If the navigation would cross an app extent boundary, we also need 326 // If the navigation would cross an app extent boundary, we also need
254 // to defer to the browser to ensure process isolation. This is not necessary 327 // to defer to the browser to ensure process isolation. This is not necessary
255 // for server redirects, which will be transferred to a new process by the 328 // for server redirects, which will be transferred to a new process by the
256 // browser process when they are ready to commit. It is necessary for client 329 // browser process when they are ready to commit. It is necessary for client
257 // redirects, which won't be transferred in the same way. 330 // redirects, which won't be transferred in the same way.
258 if (!is_server_redirect && 331 if (!is_server_redirect &&
259 CrossesExtensionExtents(frame, url, is_extension_url, 332 CrossesHostedAppExtents(frame, url, is_extension_url,
260 is_initial_navigation)) { 333 is_initial_navigation)) {
261 // Include the referrer in this case since we're going from a hosted web 334 // Include the referrer in this case since we're going from a hosted web
262 // page. (the packaged case is handled previously by the extension 335 // page. (the packaged case is handled previously by the extension
263 // navigation test) 336 // navigation test)
264 *send_referrer = true; 337 *send_referrer = true;
265 338
266 const Extension* extension = 339 const Extension* extension =
267 extension_registry->GetExtensionOrAppByURL(url); 340 extension_registry->GetExtensionOrAppByURL(url);
268 if (extension && extension->is_app()) { 341 if (extension && extension->is_app()) {
269 extensions::RecordAppLaunchType( 342 extensions::RecordAppLaunchType(
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
305 378
306 void ChromeExtensionsRendererClient::RunScriptsAtDocumentEnd( 379 void ChromeExtensionsRendererClient::RunScriptsAtDocumentEnd(
307 content::RenderFrame* render_frame) { 380 content::RenderFrame* render_frame) {
308 extension_dispatcher_->RunScriptsAtDocumentEnd(render_frame); 381 extension_dispatcher_->RunScriptsAtDocumentEnd(render_frame);
309 } 382 }
310 383
311 void ChromeExtensionsRendererClient::RunScriptsAtDocumentIdle( 384 void ChromeExtensionsRendererClient::RunScriptsAtDocumentIdle(
312 content::RenderFrame* render_frame) { 385 content::RenderFrame* render_frame) {
313 extension_dispatcher_->RunScriptsAtDocumentIdle(render_frame); 386 extension_dispatcher_->RunScriptsAtDocumentIdle(render_frame);
314 } 387 }
OLDNEW
« no previous file with comments | « chrome/renderer/chrome_content_renderer_client.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698