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

Side by Side Diff: extensions/browser/extension_web_contents_observer.cc

Issue 1413853005: Track all extension frames in ProcessManager, inspect extensionoptions (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Nits, treat hosted apps as extensions, no test flakiness Created 5 years 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
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 "extensions/browser/extension_web_contents_observer.h" 5 #include "extensions/browser/extension_web_contents_observer.h"
6 6
7 #include "components/guest_view/browser/guest_view_base.h"
7 #include "content/public/browser/child_process_security_policy.h" 8 #include "content/public/browser/child_process_security_policy.h"
9 #include "content/public/browser/navigation_details.h"
8 #include "content/public/browser/render_frame_host.h" 10 #include "content/public/browser/render_frame_host.h"
9 #include "content/public/browser/render_process_host.h" 11 #include "content/public/browser/render_process_host.h"
10 #include "content/public/browser/render_view_host.h" 12 #include "content/public/browser/render_view_host.h"
11 #include "content/public/browser/site_instance.h" 13 #include "content/public/browser/site_instance.h"
12 #include "content/public/browser/web_contents.h" 14 #include "content/public/browser/web_contents.h"
13 #include "content/public/common/url_constants.h" 15 #include "content/public/common/url_constants.h"
14 #include "extensions/browser/extension_prefs.h" 16 #include "extensions/browser/extension_prefs.h"
15 #include "extensions/browser/extension_registry.h" 17 #include "extensions/browser/extension_registry.h"
16 #include "extensions/browser/extensions_browser_client.h" 18 #include "extensions/browser/extensions_browser_client.h"
17 #include "extensions/browser/mojo/service_registration.h" 19 #include "extensions/browser/mojo/service_registration.h"
18 #include "extensions/browser/process_manager.h" 20 #include "extensions/browser/process_manager.h"
19 #include "extensions/browser/view_type_utils.h" 21 #include "extensions/browser/view_type_utils.h"
20 #include "extensions/common/constants.h" 22 #include "extensions/common/constants.h"
21 #include "extensions/common/extension.h" 23 #include "extensions/common/extension.h"
22 #include "extensions/common/extension_messages.h" 24 #include "extensions/common/extension_messages.h"
23 #include "extensions/common/view_type.h" 25 #include "extensions/common/view_type.h"
24 26
25 namespace extensions { 27 namespace extensions {
26 28
29 namespace {
30
31 bool IsExtensionURL(const GURL& url) {
32 return url.SchemeIs(kExtensionScheme) || url.SchemeIs(content::kGuestScheme);
Devlin 2015/12/01 00:58:20 nit: comment why we include guest scheme.
robwu 2015/12/01 17:19:57 The only reason for putting kGuestScheme here is b
33 }
34
35 } // namespace
36
27 // static 37 // static
28 ExtensionWebContentsObserver* ExtensionWebContentsObserver::GetForWebContents( 38 ExtensionWebContentsObserver* ExtensionWebContentsObserver::GetForWebContents(
29 content::WebContents* web_contents) { 39 content::WebContents* web_contents) {
30 return ExtensionsBrowserClient::Get()->GetExtensionWebContentsObserver( 40 return ExtensionsBrowserClient::Get()->GetExtensionWebContentsObserver(
31 web_contents); 41 web_contents);
32 } 42 }
33 43
34 ExtensionWebContentsObserver::ExtensionWebContentsObserver( 44 ExtensionWebContentsObserver::ExtensionWebContentsObserver(
35 content::WebContents* web_contents) 45 content::WebContents* web_contents)
36 : content::WebContentsObserver(web_contents), 46 : content::WebContentsObserver(web_contents),
37 browser_context_(web_contents->GetBrowserContext()), 47 browser_context_(web_contents->GetBrowserContext()),
38 dispatcher_(browser_context_) { 48 dispatcher_(browser_context_) {
39 web_contents->ForEachFrame( 49 web_contents->ForEachFrame(
40 base::Bind(&ExtensionWebContentsObserver::InitializeFrameHelper, 50 base::Bind(&ExtensionWebContentsObserver::InitializeFrameHelper,
41 base::Unretained(this))); 51 base::Unretained(this)));
42 dispatcher_.set_delegate(this); 52 dispatcher_.set_delegate(this);
43 } 53 }
44 54
45 ExtensionWebContentsObserver::~ExtensionWebContentsObserver() { 55 ExtensionWebContentsObserver::~ExtensionWebContentsObserver() {
46 } 56 }
47 57
48 void ExtensionWebContentsObserver::InitializeRenderFrame( 58 void ExtensionWebContentsObserver::InitializeRenderFrame(
49 content::RenderFrameHost* render_frame_host) { 59 content::RenderFrameHost* render_frame_host) {
50 DCHECK(render_frame_host); 60 DCHECK(render_frame_host);
51 DCHECK(render_frame_host->IsRenderFrameLive()); 61 DCHECK(render_frame_host->IsRenderFrameLive());
52 62
63 ViewType view_type = GetViewType(web_contents());
64 if (view_type == VIEW_TYPE_INVALID) {
65 // This is expected to happen only for non-extension pages (e.g. devtools)
66 // and GuestViews.
67 DCHECK(guest_view::GuestViewBase::FromWebContents(web_contents()) ||
68 !IsExtensionURL(render_frame_host->GetSiteInstance()->GetSiteURL()));
69 return;
70 }
71
72 // At the initialization of the render frame, the last committed URL is not
73 // reliable, so do not take it into account in determining whether it is an
74 // extension frame.
75 const Extension* frame_extension =
76 GetExtensionFromFrame(render_frame_host, false);
77 // TODO(robwu): Add DCHECK that verifies that |frame_extension| always exists
78 // if OOP frames is enabled.
79 if (!frame_extension)
80 return;
81
53 // Notify the render frame of the view type. 82 // Notify the render frame of the view type.
54 render_frame_host->Send(new ExtensionMsg_NotifyRenderViewType( 83 render_frame_host->Send(new ExtensionMsg_NotifyRenderViewType(
55 render_frame_host->GetRoutingID(), GetViewType(web_contents()))); 84 render_frame_host->GetRoutingID(), view_type));
56 85
57 const Extension* frame_extension = GetExtensionFromFrame(render_frame_host); 86 ExtensionsBrowserClient::Get()->RegisterMojoServices(render_frame_host,
58 if (frame_extension) { 87 frame_extension);
59 ExtensionsBrowserClient::Get()->RegisterMojoServices(render_frame_host, 88 ProcessManager::Get(browser_context_)
60 frame_extension); 89 ->RegisterRenderFrameHost(web_contents(), render_frame_host,
61 ProcessManager::Get(browser_context_) 90 frame_extension);
62 ->RegisterRenderFrameHost(web_contents(), render_frame_host,
63 frame_extension);
64 }
65 } 91 }
66 92
67 content::WebContents* ExtensionWebContentsObserver::GetAssociatedWebContents() 93 content::WebContents* ExtensionWebContentsObserver::GetAssociatedWebContents()
68 const { 94 const {
69 return web_contents(); 95 return web_contents();
70 } 96 }
71 97
72 void ExtensionWebContentsObserver::RenderViewCreated( 98 void ExtensionWebContentsObserver::RenderViewCreated(
73 content::RenderViewHost* render_view_host) { 99 content::RenderViewHost* render_view_host) {
74 // TODO(devlin): Most/all of this should move to RenderFrameCreated. 100 // TODO(devlin): Most/all of this should move to RenderFrameCreated.
(...skipping 28 matching lines...) Expand all
103 content::RenderFrameHost* render_frame_host) { 129 content::RenderFrameHost* render_frame_host) {
104 InitializeRenderFrame(render_frame_host); 130 InitializeRenderFrame(render_frame_host);
105 } 131 }
106 132
107 void ExtensionWebContentsObserver::RenderFrameDeleted( 133 void ExtensionWebContentsObserver::RenderFrameDeleted(
108 content::RenderFrameHost* render_frame_host) { 134 content::RenderFrameHost* render_frame_host) {
109 ProcessManager::Get(browser_context_) 135 ProcessManager::Get(browser_context_)
110 ->UnregisterRenderFrameHost(render_frame_host); 136 ->UnregisterRenderFrameHost(render_frame_host);
111 } 137 }
112 138
139 void ExtensionWebContentsObserver::DidCommitProvisionalLoadForFrame(
140 content::RenderFrameHost* render_frame_host,
141 const GURL& url,
142 ui::PageTransition transition_type) {
143 ProcessManager* pm = ProcessManager::Get(browser_context_);
144
145 if (pm->IsRenderFrameHostRegistered(render_frame_host)) {
146 const Extension* frame_extension =
147 GetExtensionFromFrame(render_frame_host, true);
148
149 if (!frame_extension)
150 pm->UnregisterRenderFrameHost(render_frame_host);
151 }
152 }
153
154 void ExtensionWebContentsObserver::DidNavigateAnyFrame(
155 content::RenderFrameHost* render_frame_host,
156 const content::LoadCommittedDetails& details,
157 const content::FrameNavigateParams& params) {
158 if (details.is_in_page)
159 return;
160
161 const Extension* frame_extension =
162 GetExtensionFromFrame(render_frame_host, true);
163 ProcessManager* pm = ProcessManager::Get(browser_context_);
164
165 if (!frame_extension) {
166 // Should have been unregistered by DidCommitProvisionalLoadForFrame.
167 DCHECK(!pm->IsRenderFrameHostRegistered(render_frame_host));
168 return;
169 }
170
171 if (pm->IsRenderFrameHostRegistered(render_frame_host)) {
172 // Notify ProcessManager, because some clients do not just want to know
173 // whether the frame is in an extension process, but also whether the frame
174 // was navigated.
175 pm->DidNavigateRenderFrameHost(render_frame_host);
176 } else {
177 pm->RegisterRenderFrameHost(web_contents(), render_frame_host,
178 frame_extension);
179 }
180 }
181
113 bool ExtensionWebContentsObserver::OnMessageReceived( 182 bool ExtensionWebContentsObserver::OnMessageReceived(
114 const IPC::Message& message, 183 const IPC::Message& message,
115 content::RenderFrameHost* render_frame_host) { 184 content::RenderFrameHost* render_frame_host) {
116 bool handled = true; 185 bool handled = true;
117 IPC_BEGIN_MESSAGE_MAP_WITH_PARAM( 186 IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(
118 ExtensionWebContentsObserver, message, render_frame_host) 187 ExtensionWebContentsObserver, message, render_frame_host)
119 IPC_MESSAGE_HANDLER(ExtensionHostMsg_Request, OnRequest) 188 IPC_MESSAGE_HANDLER(ExtensionHostMsg_Request, OnRequest)
120 IPC_MESSAGE_UNHANDLED(handled = false) 189 IPC_MESSAGE_UNHANDLED(handled = false)
121 IPC_END_MESSAGE_MAP() 190 IPC_END_MESSAGE_MAP()
122 return handled; 191 return handled;
(...skipping 16 matching lines...) Expand all
139 ProcessManager::Get(browser_context_); 208 ProcessManager::Get(browser_context_);
140 const Extension* const extension = 209 const Extension* const extension =
141 process_manager->GetExtensionForWebContents(web_contents()); 210 process_manager->GetExtensionForWebContents(web_contents());
142 if (extension) 211 if (extension)
143 process_manager->DecrementLazyKeepaliveCount(extension); 212 process_manager->DecrementLazyKeepaliveCount(extension);
144 } 213 }
145 } 214 }
146 215
147 std::string ExtensionWebContentsObserver::GetExtensionIdFromFrame( 216 std::string ExtensionWebContentsObserver::GetExtensionIdFromFrame(
148 content::RenderFrameHost* render_frame_host) const { 217 content::RenderFrameHost* render_frame_host) const {
149 content::SiteInstance* site_instance = render_frame_host->GetSiteInstance(); 218 const Extension* extension = GetExtensionFromFrame(render_frame_host, true);
150 GURL url = render_frame_host->GetLastCommittedURL(); 219 return extension ? extension->id() : std::string();
151 if (!url.is_empty()) {
152 if (site_instance->GetSiteURL().GetOrigin() != url.GetOrigin())
153 return std::string();
154 } else {
155 url = site_instance->GetSiteURL();
156 }
157
158 return url.SchemeIs(kExtensionScheme) ? url.host() : std::string();
159 } 220 }
160 221
161 const Extension* ExtensionWebContentsObserver::GetExtensionFromFrame( 222 const Extension* ExtensionWebContentsObserver::GetExtensionFromFrame(
162 content::RenderFrameHost* render_frame_host) const { 223 content::RenderFrameHost* render_frame_host,
163 return ExtensionRegistry::Get( 224 bool verify_url) const {
164 render_frame_host->GetProcess()->GetBrowserContext()) 225 const GURL site_url(render_frame_host->GetSiteInstance()->GetSiteURL());
165 ->enabled_extensions() 226 if (!IsExtensionURL(site_url))
166 .GetByID(GetExtensionIdFromFrame(render_frame_host)); 227 return nullptr;
228
229 const std::string& extension_id = site_url.host();
230 const Extension* extension =
231 ExtensionRegistry::Get(
232 render_frame_host->GetProcess()->GetBrowserContext())
233 ->enabled_extensions()
234 .GetByID(extension_id);
235 if (!extension)
236 return nullptr;
237
238 // This verify_url logic can completely be removed once site isolation is
239 // fully enabled.
240 if (verify_url) {
241 GURL url(render_frame_host->GetLastCommittedURL());
Devlin 2015/12/01 00:58:20 const&?
242 if (extension->is_hosted_app() && extension->web_extent().MatchesURL(url))
243 return extension;
244
245 if (!IsExtensionURL(url)) {
246 // Any about:* frame (in particular about:blank and about:srcdoc) runs in
247 // the security context of the parent page that created it. Treat such
248 // frames as extension pages iff the parent frame is registered.
249 if (url.SchemeIs(url::kAboutScheme) && render_frame_host->GetParent())
250 return GetExtensionFromFrame(render_frame_host->GetParent(), true);
251 return nullptr;
252 }
253 if (url.host() != extension_id) {
Devlin 2015/12/01 00:58:20 nit: try to be consistent with wrapping {} in sing
254 return nullptr;
255 }
256 }
257
258 return extension;
167 } 259 }
168 260
169 const Extension* ExtensionWebContentsObserver::GetExtension( 261 const Extension* ExtensionWebContentsObserver::GetExtension(
170 content::RenderViewHost* render_view_host) { 262 content::RenderViewHost* render_view_host) {
171 std::string extension_id = GetExtensionId(render_view_host); 263 std::string extension_id = GetExtensionId(render_view_host);
172 if (extension_id.empty()) 264 if (extension_id.empty())
173 return NULL; 265 return NULL;
174 266
175 // May be null if the extension doesn't exist, for example if somebody typos 267 // May be null if the extension doesn't exist, for example if somebody typos
176 // a chrome-extension:// URL. 268 // a chrome-extension:// URL.
(...skipping 26 matching lines...) Expand all
203 // Since this is called for all existing RenderFrameHosts during the 295 // Since this is called for all existing RenderFrameHosts during the
204 // ExtensionWebContentsObserver's creation, it's possible that not all hosts 296 // ExtensionWebContentsObserver's creation, it's possible that not all hosts
205 // are ready. 297 // are ready.
206 // We only initialize the frame if the renderer counterpart is live; otherwise 298 // We only initialize the frame if the renderer counterpart is live; otherwise
207 // we wait for the RenderFrameCreated notification. 299 // we wait for the RenderFrameCreated notification.
208 if (render_frame_host->IsRenderFrameLive()) 300 if (render_frame_host->IsRenderFrameLive())
209 InitializeRenderFrame(render_frame_host); 301 InitializeRenderFrame(render_frame_host);
210 } 302 }
211 303
212 } // namespace extensions 304 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698