blob: 665fc0809cca1b3ebcfa428ae79d762d9c8c5caa [file] [log] [blame]
[email protected]1ce15972014-03-20 19:25:481// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "extensions/browser/extension_web_contents_observer.h"
6
7#include "content/public/browser/child_process_security_policy.h"
rdevlin.cronin6ae04a012015-04-03 20:19:408#include "content/public/browser/render_frame_host.h"
[email protected]1ce15972014-03-20 19:25:489#include "content/public/browser/render_process_host.h"
10#include "content/public/browser/render_view_host.h"
11#include "content/public/browser/site_instance.h"
12#include "content/public/browser/web_contents.h"
13#include "content/public/common/url_constants.h"
14#include "extensions/browser/extension_prefs.h"
15#include "extensions/browser/extension_registry.h"
kmarshall166e5b42015-04-03 22:29:4316#include "extensions/browser/extensions_browser_client.h"
sammc143f3c52015-02-13 09:42:3817#include "extensions/browser/mojo/service_registration.h"
rdevlin.cronin6ae04a012015-04-03 20:19:4018#include "extensions/browser/process_manager.h"
[email protected]1ce15972014-03-20 19:25:4819#include "extensions/browser/view_type_utils.h"
20#include "extensions/common/constants.h"
emaxxe70f5e12015-05-29 11:26:0021#include "extensions/common/extension.h"
[email protected]1ce15972014-03-20 19:25:4822#include "extensions/common/extension_messages.h"
emaxxe3baba12015-10-19 22:45:0023#include "extensions/common/view_type.h"
[email protected]1ce15972014-03-20 19:25:4824
25namespace extensions {
26
rdevlin.cronincb2ec659a2015-06-10 23:32:4127// static
28ExtensionWebContentsObserver* ExtensionWebContentsObserver::GetForWebContents(
29 content::WebContents* web_contents) {
30 return ExtensionsBrowserClient::Get()->GetExtensionWebContentsObserver(
31 web_contents);
32}
33
[email protected]1ce15972014-03-20 19:25:4834ExtensionWebContentsObserver::ExtensionWebContentsObserver(
35 content::WebContents* web_contents)
36 : content::WebContentsObserver(web_contents),
rdevlin.cronincb2ec659a2015-06-10 23:32:4137 browser_context_(web_contents->GetBrowserContext()),
38 dispatcher_(browser_context_) {
rdevlin.cronin6f42c2522015-06-19 18:58:5139 web_contents->ForEachFrame(
40 base::Bind(&ExtensionWebContentsObserver::InitializeFrameHelper,
41 base::Unretained(this)));
rdevlin.cronincb2ec659a2015-06-10 23:32:4142 dispatcher_.set_delegate(this);
[email protected]0b365072014-03-22 06:14:1843}
[email protected]1ce15972014-03-20 19:25:4844
rdevlin.cronin6ae04a012015-04-03 20:19:4045ExtensionWebContentsObserver::~ExtensionWebContentsObserver() {
46}
[email protected]1ce15972014-03-20 19:25:4847
rdevlin.cronin6f42c2522015-06-19 18:58:5148void ExtensionWebContentsObserver::InitializeRenderFrame(
49 content::RenderFrameHost* render_frame_host) {
50 DCHECK(render_frame_host);
51 DCHECK(render_frame_host->IsRenderFrameLive());
52
53 // Notify the render frame of the view type.
54 render_frame_host->Send(new ExtensionMsg_NotifyRenderViewType(
55 render_frame_host->GetRoutingID(), GetViewType(web_contents())));
56
rdevlin.cronin86f5b702015-06-24 18:49:1757 const Extension* frame_extension = GetExtensionFromFrame(render_frame_host);
rdevlin.cronin6f42c2522015-06-19 18:58:5158 if (frame_extension) {
59 ExtensionsBrowserClient::Get()->RegisterMojoServices(render_frame_host,
60 frame_extension);
61 ProcessManager::Get(browser_context_)
62 ->RegisterRenderFrameHost(web_contents(), render_frame_host,
63 frame_extension);
64 }
rdevlin.cronin6f42c2522015-06-19 18:58:5165}
66
rdevlin.cronincb2ec659a2015-06-10 23:32:4167content::WebContents* ExtensionWebContentsObserver::GetAssociatedWebContents()
68 const {
69 return web_contents();
70}
71
[email protected]1ce15972014-03-20 19:25:4872void ExtensionWebContentsObserver::RenderViewCreated(
73 content::RenderViewHost* render_view_host) {
rdevlin.cronin6f42c2522015-06-19 18:58:5174 // TODO(devlin): Most/all of this should move to RenderFrameCreated.
[email protected]1ce15972014-03-20 19:25:4875 const Extension* extension = GetExtension(render_view_host);
76 if (!extension)
77 return;
78
[email protected]1ce15972014-03-20 19:25:4879 Manifest::Type type = extension->GetType();
[email protected]1ce15972014-03-20 19:25:4880
81 // Some extensions use file:// URLs.
82 if (type == Manifest::TYPE_EXTENSION ||
83 type == Manifest::TYPE_LEGACY_PACKAGED_APP) {
84 ExtensionPrefs* prefs = ExtensionPrefs::Get(browser_context_);
85 if (prefs->AllowFileAccess(extension->id())) {
86 content::ChildProcessSecurityPolicy::GetInstance()->GrantScheme(
paulmeyer1eefa26e2015-10-01 02:11:1387 render_view_host->GetProcess()->GetID(), url::kFileScheme);
[email protected]1ce15972014-03-20 19:25:4888 }
89 }
90
kalman8bcbc7592015-06-03 23:12:2791 // Tells the new view that it's hosted in an extension process.
92 //
93 // This will often be a rendant IPC, because activating extensions happens at
94 // the process level, not at the view level. However, without some mild
95 // refactoring this isn't trivial to do, and this way is simpler.
96 //
97 // Plus, we can delete the concept of activating an extension once site
98 // isolation is turned on.
99 render_view_host->Send(new ExtensionMsg_ActivateExtension(extension->id()));
[email protected]1ce15972014-03-20 19:25:48100}
101
sammc143f3c52015-02-13 09:42:38102void ExtensionWebContentsObserver::RenderFrameCreated(
103 content::RenderFrameHost* render_frame_host) {
rdevlin.cronin6f42c2522015-06-19 18:58:51104 InitializeRenderFrame(render_frame_host);
105}
106
107void ExtensionWebContentsObserver::RenderFrameDeleted(
108 content::RenderFrameHost* render_frame_host) {
109 ProcessManager::Get(browser_context_)
110 ->UnregisterRenderFrameHost(render_frame_host);
sammc143f3c52015-02-13 09:42:38111}
112
rdevlin.cronincb2ec659a2015-06-10 23:32:41113bool ExtensionWebContentsObserver::OnMessageReceived(
rdevlin.cronin92503ba2015-06-12 17:00:56114 const IPC::Message& message,
115 content::RenderFrameHost* render_frame_host) {
rdevlin.cronincb2ec659a2015-06-10 23:32:41116 bool handled = true;
rdevlin.cronin92503ba2015-06-12 17:00:56117 IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(
118 ExtensionWebContentsObserver, message, render_frame_host)
rdevlin.cronincb2ec659a2015-06-10 23:32:41119 IPC_MESSAGE_HANDLER(ExtensionHostMsg_Request, OnRequest)
120 IPC_MESSAGE_UNHANDLED(handled = false)
121 IPC_END_MESSAGE_MAP()
122 return handled;
123}
124
emaxxe70f5e12015-05-29 11:26:00125void ExtensionWebContentsObserver::PepperInstanceCreated() {
emaxxe3baba12015-10-19 22:45:00126 if (GetViewType(web_contents()) == VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) {
127 ProcessManager* const process_manager =
128 ProcessManager::Get(browser_context_);
129 const Extension* const extension =
130 process_manager->GetExtensionForWebContents(web_contents());
131 if (extension)
132 process_manager->IncrementLazyKeepaliveCount(extension);
133 }
emaxxe70f5e12015-05-29 11:26:00134}
135
136void ExtensionWebContentsObserver::PepperInstanceDeleted() {
emaxxe3baba12015-10-19 22:45:00137 if (GetViewType(web_contents()) == VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) {
138 ProcessManager* const process_manager =
139 ProcessManager::Get(browser_context_);
140 const Extension* const extension =
141 process_manager->GetExtensionForWebContents(web_contents());
142 if (extension)
143 process_manager->DecrementLazyKeepaliveCount(extension);
144 }
emaxxe70f5e12015-05-29 11:26:00145}
146
rdevlin.cronin86f5b702015-06-24 18:49:17147std::string ExtensionWebContentsObserver::GetExtensionIdFromFrame(
148 content::RenderFrameHost* render_frame_host) const {
149 content::SiteInstance* site_instance = render_frame_host->GetSiteInstance();
150 GURL url = render_frame_host->GetLastCommittedURL();
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}
160
161const Extension* ExtensionWebContentsObserver::GetExtensionFromFrame(
162 content::RenderFrameHost* render_frame_host) const {
163 return ExtensionRegistry::Get(
164 render_frame_host->GetProcess()->GetBrowserContext())
165 ->enabled_extensions()
166 .GetByID(GetExtensionIdFromFrame(render_frame_host));
167}
168
[email protected]1ce15972014-03-20 19:25:48169const Extension* ExtensionWebContentsObserver::GetExtension(
170 content::RenderViewHost* render_view_host) {
171 std::string extension_id = GetExtensionId(render_view_host);
172 if (extension_id.empty())
173 return NULL;
174
175 // May be null if the extension doesn't exist, for example if somebody typos
176 // a chrome-extension:// URL.
177 return ExtensionRegistry::Get(browser_context_)
178 ->GetExtensionById(extension_id, ExtensionRegistry::ENABLED);
179}
180
181// static
182std::string ExtensionWebContentsObserver::GetExtensionId(
183 content::RenderViewHost* render_view_host) {
184 // Note that due to ChromeContentBrowserClient::GetEffectiveURL(), hosted apps
185 // (excluding bookmark apps) will have a chrome-extension:// URL for their
186 // site, so we can ignore that wrinkle here.
187 const GURL& site = render_view_host->GetSiteInstance()->GetSiteURL();
188
189 if (!site.SchemeIs(kExtensionScheme))
190 return std::string();
191
192 return site.host();
193}
194
rdevlin.cronincb2ec659a2015-06-10 23:32:41195void ExtensionWebContentsObserver::OnRequest(
rdevlin.cronin92503ba2015-06-12 17:00:56196 content::RenderFrameHost* render_frame_host,
rdevlin.cronincb2ec659a2015-06-10 23:32:41197 const ExtensionHostMsg_Request_Params& params) {
rdevlin.cronin92503ba2015-06-12 17:00:56198 dispatcher_.Dispatch(params, render_frame_host);
rdevlin.cronincb2ec659a2015-06-10 23:32:41199}
200
rdevlin.cronin6f42c2522015-06-19 18:58:51201void ExtensionWebContentsObserver::InitializeFrameHelper(
202 content::RenderFrameHost* render_frame_host) {
203 // Since this is called for all existing RenderFrameHosts during the
204 // ExtensionWebContentsObserver's creation, it's possible that not all hosts
205 // are ready.
206 // We only initialize the frame if the renderer counterpart is live; otherwise
207 // we wait for the RenderFrameCreated notification.
208 if (render_frame_host->IsRenderFrameLive())
209 InitializeRenderFrame(render_frame_host);
210}
211
[email protected]1ce15972014-03-20 19:25:48212} // namespace extensions