blob: 4ec655aa834c3887d116f68f1d9b879cee47cee5 [file] [log] [blame]
[email protected]22401dc2014-03-21 01:38:571// Copyright 2014 The Chromium Authors. All rights reserved.
[email protected]c64631652009-04-29 22:24:312// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]22401dc2014-03-21 01:38:575#include "extensions/browser/extension_host.h"
[email protected]c64631652009-04-29 22:24:316
[email protected]88b50b62013-09-01 23:05:067#include "base/logging.h"
oysteine78b0b932014-12-10 18:06:388#include "base/metrics/field_trial.h"
kalman301145112015-02-07 00:43:459#include "base/metrics/histogram_macros.h"
robliao8f3cf262015-03-05 21:43:2810#include "base/profiler/scoped_tracker.h"
[email protected]00e7bef2013-06-10 20:35:1711#include "base/strings/string_util.h"
[email protected]112158af2013-06-07 23:46:1812#include "base/strings/utf_string_conversions.h"
[email protected]91abb922013-12-03 18:39:5613#include "content/public/browser/browser_context.h"
[email protected]79f06c7372011-11-21 18:00:3214#include "content/public/browser/content_browser_client.h"
15#include "content/public/browser/native_web_keyboard_event.h"
[email protected]c13be0d2011-11-22 02:09:5816#include "content/public/browser/notification_service.h"
17#include "content/public/browser/render_process_host.h"
[email protected]9c1662b2012-03-06 15:44:3318#include "content/public/browser/render_view_host.h"
[email protected]14ddecf2013-08-24 15:29:4219#include "content/public/browser/render_widget_host_view.h"
[email protected]b6583592012-01-25 19:52:3320#include "content/public/browser/site_instance.h"
[email protected]3a7d7d32012-01-05 17:44:0121#include "content/public/browser/web_contents.h"
jamescookda2505812015-03-20 18:01:1822#include "extensions/browser/bad_message.h"
[email protected]34423532013-11-21 18:13:1023#include "extensions/browser/event_router.h"
[email protected]88b50b62013-09-01 23:05:0624#include "extensions/browser/extension_error.h"
[email protected]6c0f179f2014-03-19 11:04:4125#include "extensions/browser/extension_host_delegate.h"
chirantan79788f62015-02-02 23:57:2526#include "extensions/browser/extension_host_observer.h"
kalmanfcece452015-02-18 18:20:4227#include "extensions/browser/extension_host_queue.h"
limasdfbbaa913d2015-03-02 23:52:3328#include "extensions/browser/extension_registry.h"
[email protected]59b0e602014-01-30 00:41:2429#include "extensions/browser/extension_system.h"
rdevlin.cronincb2ec659a2015-06-10 23:32:4130#include "extensions/browser/extension_web_contents_observer.h"
[email protected]6a0398b62013-12-16 22:54:5631#include "extensions/browser/extensions_browser_client.h"
kalmand49594b52015-02-27 17:27:1632#include "extensions/browser/load_monitoring_extension_host_queue.h"
[email protected]adf5a102014-07-31 12:44:0633#include "extensions/browser/notification_types.h"
[email protected]98b6d942013-11-10 00:34:0734#include "extensions/browser/process_manager.h"
[email protected]45f5b7d2014-01-22 23:47:1335#include "extensions/browser/runtime_data.h"
[email protected]cb2edf22013-04-01 20:25:2336#include "extensions/browser/view_type_utils.h"
[email protected]e4452d32013-11-15 23:07:4137#include "extensions/common/extension.h"
[email protected]fb820c02014-03-13 15:07:0838#include "extensions/common/extension_messages.h"
[email protected]88b50b62013-09-01 23:05:0639#include "extensions/common/extension_urls.h"
[email protected]5ef835a2013-11-08 20:42:5740#include "extensions/common/feature_switch.h"
[email protected]558878cc82013-11-09 01:25:5141#include "extensions/common/manifest_handlers/background_info.h"
[email protected]c051a1b2011-01-21 23:30:1742#include "ui/base/l10n/l10n_util.h"
[email protected]91abb922013-12-03 18:39:5643#include "ui/base/window_open_disposition.h"
[email protected]1ce88e82013-06-28 05:17:1044
[email protected]96e6a1032013-11-28 06:58:0345using content::BrowserContext;
[email protected]e5d549d2011-12-28 01:29:2046using content::OpenURLParams;
[email protected]2dcd62b2013-12-11 03:12:0047using content::RenderProcessHost;
[email protected]eaabba22012-03-07 15:02:1148using content::RenderViewHost;
[email protected]b6583592012-01-25 19:52:3349using content::SiteInstance;
[email protected]ea049a02011-12-25 21:37:0950using content::WebContents;
[email protected]3a1dc572012-07-31 22:25:1351
52namespace extensions {
[email protected]1d9f4132009-09-08 17:29:2553
[email protected]3a1dc572012-07-31 22:25:1354ExtensionHost::ExtensionHost(const Extension* extension,
[email protected]9adb9692010-10-29 23:14:0255 SiteInstance* site_instance,
56 const GURL& url,
[email protected]cb2edf22013-04-01 20:25:2357 ViewType host_type)
[email protected]6c0f179f2014-03-19 11:04:4158 : delegate_(ExtensionsBrowserClient::Get()->CreateExtensionHostDelegate()),
59 extension_(extension),
[email protected]2d2f6cfc2011-05-06 21:09:3360 extension_id_(extension->id()),
[email protected]96e6a1032013-11-28 06:58:0361 browser_context_(site_instance->GetBrowserContext()),
kalman89a8dc82015-02-17 22:21:5962 render_view_host_(nullptr),
rockot494f0072015-07-29 17:58:0763 is_render_view_creation_pending_(false),
kalmanfd474fa2015-03-16 22:30:5764 has_loaded_once_(false),
[email protected]e95ad332009-08-03 19:44:2565 document_element_available_(false),
[email protected]952a68e2011-11-17 00:36:1066 initial_url_(url),
[email protected]d9823b82013-11-27 16:37:1767 extension_host_type_(host_type) {
[email protected]45a73d52013-11-26 00:10:5568 // Not used for panels, see PanelHost.
69 DCHECK(host_type == VIEW_TYPE_EXTENSION_BACKGROUND_PAGE ||
70 host_type == VIEW_TYPE_EXTENSION_DIALOG ||
[email protected]45a73d52013-11-26 00:10:5571 host_type == VIEW_TYPE_EXTENSION_POPUP);
[email protected]3a7d7d32012-01-05 17:44:0172 host_contents_.reset(WebContents::Create(
[email protected]96e6a1032013-11-28 06:58:0373 WebContents::CreateParams(browser_context_, site_instance))),
[email protected]d8c660432011-12-22 20:51:2574 content::WebContentsObserver::Observe(host_contents_.get());
[email protected]6934a702011-12-20 00:04:5175 host_contents_->SetDelegate(this);
[email protected]cb2edf22013-04-01 20:25:2376 SetViewType(host_contents_.get(), host_type);
[email protected]9610ef242009-11-18 02:41:2677
[email protected]151a63d2011-12-20 22:32:5278 render_view_host_ = host_contents_->GetRenderViewHost();
[email protected]4f4d42a2011-12-02 02:42:4979
[email protected]6f39aee92010-01-26 22:33:5880 // Listen for when an extension is unloaded from the same profile, as it may
81 // be the same extension that this points to.
limasdfbbaa913d2015-03-02 23:52:3382 ExtensionRegistry::Get(browser_context_)->AddObserver(this);
[email protected]9be525e2014-01-10 20:52:4083
[email protected]1ce15972014-03-20 19:25:4884 // Set up web contents observers and pref observers.
[email protected]6c0f179f2014-03-19 11:04:4185 delegate_->OnExtensionHostCreated(host_contents());
rdevlin.cronincb2ec659a2015-06-10 23:32:4186
87 ExtensionWebContentsObserver::GetForWebContents(host_contents())->
88 dispatcher()->set_delegate(this);
[email protected]c64631652009-04-29 22:24:3189}
90
91ExtensionHost::~ExtensionHost() {
limasdfbbaa913d2015-03-02 23:52:3392 ExtensionRegistry::Get(browser_context_)->RemoveObserver(this);
93
[email protected]cb2edf22013-04-01 20:25:2394 if (extension_host_type_ == VIEW_TYPE_EXTENSION_BACKGROUND_PAGE &&
kalman301145112015-02-07 00:43:4595 extension_ && BackgroundInfo::HasLazyBackgroundPage(extension_) &&
96 load_start_.get()) {
97 UMA_HISTOGRAM_LONG_TIMES("Extensions.EventPageActiveTime2",
98 load_start_->Elapsed());
[email protected]36a438a2012-05-12 00:00:3399 }
kalmanfd474fa2015-03-16 22:30:57100
[email protected]ad50def52011-10-19 23:17:07101 content::NotificationService::current()->Notify(
[email protected]adf5a102014-07-31 12:44:06102 extensions::NOTIFICATION_EXTENSION_HOST_DESTROYED,
[email protected]96e6a1032013-11-28 06:58:03103 content::Source<BrowserContext>(browser_context_),
[email protected]6c2381d2011-10-19 02:52:53104 content::Details<ExtensionHost>(this));
ericwilligersd1e28152016-10-17 22:53:14105 for (auto& observer : observer_list_)
106 observer.OnExtensionHostDestroyed(this);
107 for (auto& observer : deferred_start_render_host_observer_list_)
108 observer.OnDeferredStartRenderHostDestroyed(this);
kalmanfd474fa2015-03-16 22:30:57109
110 // Remove ourselves from the queue as late as possible (before effectively
111 // destroying self, but after everything else) so that queues that are
112 // monitoring lifetime get a chance to see stop-loading events.
yozd61dfe192015-02-21 01:30:37113 delegate_->GetExtensionHostQueue()->Remove(this);
kalmanfd474fa2015-03-16 22:30:57114
115 // Deliberately stop observing |host_contents_| because its destruction
116 // events (like DidStopLoading, it turns out) can call back into
117 // ExtensionHost re-entrantly, when anything declared after |host_contents_|
118 // has already been destroyed.
kalman89a8dc82015-02-17 22:21:59119 content::WebContentsObserver::Observe(nullptr);
[email protected]c64631652009-04-29 22:24:31120}
121
[email protected]f3b1a082011-11-18 00:34:30122content::RenderProcessHost* ExtensionHost::render_process_host() const {
[email protected]9f76c1e2012-03-05 15:15:58123 return render_view_host()->GetProcess();
[email protected]8a17bd52009-06-06 08:19:49124}
125
[email protected]952a68e2011-11-17 00:36:10126RenderViewHost* ExtensionHost::render_view_host() const {
kalman89a8dc82015-02-17 22:21:59127 // TODO(mpcomplete): This can be null. How do we handle that?
[email protected]4f4d42a2011-12-02 02:42:49128 return render_view_host_;
[email protected]c64631652009-04-29 22:24:31129}
130
[email protected]7c6877d2009-06-19 13:56:25131bool ExtensionHost::IsRenderViewLive() const {
[email protected]952a68e2011-11-17 00:36:10132 return render_view_host()->IsRenderViewLive();
[email protected]7c6877d2009-06-19 13:56:25133}
134
[email protected]952a68e2011-11-17 00:36:10135void ExtensionHost::CreateRenderViewSoon() {
kalman301145112015-02-07 00:43:45136 if (render_process_host() && render_process_host()->HasConnection()) {
[email protected]844550002009-11-20 01:06:00137 // If the process is already started, go ahead and initialize the RenderView
138 // synchronously. The process creation is the real meaty part that we want
139 // to defer.
140 CreateRenderViewNow();
141 } else {
yozd61dfe192015-02-21 01:30:37142 delegate_->GetExtensionHostQueue()->Add(this);
[email protected]844550002009-11-20 01:06:00143 }
144}
145
146void ExtensionHost::CreateRenderViewNow() {
robliao8f3cf262015-03-05 21:43:28147 // TODO(robliao): Remove ScopedTracker below once crbug.com/464206 is fixed.
148 tracked_objects::ScopedTracker tracking_profile1(
149 FROM_HERE_WITH_EXPLICIT_FUNCTION(
150 "464206 ExtensionHost::CreateRenderViewNow1"));
rockot494f0072015-07-29 17:58:07151 if (!ExtensionRegistry::Get(browser_context_)
152 ->ready_extensions()
153 .Contains(extension_->id())) {
154 is_render_view_creation_pending_ = true;
155 return;
156 }
157 is_render_view_creation_pending_ = false;
[email protected]952a68e2011-11-17 00:36:10158 LoadInitialURL();
[email protected]7f256e092014-03-09 16:17:36159 if (IsBackgroundPage()) {
robliao8f3cf262015-03-05 21:43:28160 // TODO(robliao): Remove ScopedTracker below once crbug.com/464206 is fixed.
161 tracked_objects::ScopedTracker tracking_profile2(
162 FROM_HERE_WITH_EXPLICIT_FUNCTION(
163 "464206 ExtensionHost::CreateRenderViewNow2"));
[email protected]952a68e2011-11-17 00:36:10164 DCHECK(IsRenderViewLive());
oysteine78b0b932014-12-10 18:06:38165 if (extension_) {
oysteine7ad8e8a2015-06-12 23:09:04166 std::string group_name = base::FieldTrialList::FindFullName(
167 "ThrottleExtensionBackgroundPages");
168 if ((group_name == "ThrottlePersistent" &&
169 extensions::BackgroundInfo::HasPersistentBackgroundPage(
170 extension_)) ||
171 group_name == "ThrottleAll") {
oysteine78b0b932014-12-10 18:06:38172 host_contents_->WasHidden();
173 }
174 }
robliao8f3cf262015-03-05 21:43:28175 // TODO(robliao): Remove ScopedTracker below once crbug.com/464206 is fixed.
176 tracked_objects::ScopedTracker tracking_profile3(
177 FROM_HERE_WITH_EXPLICIT_FUNCTION(
178 "464206 ExtensionHost::CreateRenderViewNow3"));
[email protected]79beb8d2014-03-18 22:18:45179 // Connect orphaned dev-tools instances.
[email protected]6c0f179f2014-03-19 11:04:41180 delegate_->OnRenderViewCreatedForBackgroundPage(this);
[email protected]28b3a812011-11-08 01:03:43181 }
[email protected]c64631652009-04-29 22:24:31182}
183
kalmand49594b52015-02-27 17:27:16184void ExtensionHost::AddDeferredStartRenderHostObserver(
185 DeferredStartRenderHostObserver* observer) {
186 deferred_start_render_host_observer_list_.AddObserver(observer);
187}
188
189void ExtensionHost::RemoveDeferredStartRenderHostObserver(
190 DeferredStartRenderHostObserver* observer) {
191 deferred_start_render_host_observer_list_.RemoveObserver(observer);
192}
193
kalmanfcece452015-02-18 18:20:42194void ExtensionHost::Close() {
195 content::NotificationService::current()->Notify(
196 extensions::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE,
197 content::Source<BrowserContext>(browser_context_),
198 content::Details<ExtensionHost>(this));
199}
200
chirantan79788f62015-02-02 23:57:25201void ExtensionHost::AddObserver(ExtensionHostObserver* observer) {
202 observer_list_.AddObserver(observer);
203}
204
205void ExtensionHost::RemoveObserver(ExtensionHostObserver* observer) {
206 observer_list_.RemoveObserver(observer);
207}
208
chirantan669993c2015-03-05 23:38:33209void ExtensionHost::OnBackgroundEventDispatched(const std::string& event_name,
210 int event_id) {
211 CHECK(IsBackgroundPage());
212 unacked_messages_.insert(event_id);
ericwilligersd1e28152016-10-17 22:53:14213 for (auto& observer : observer_list_)
214 observer.OnBackgroundEventDispatched(this, event_name, event_id);
chirantan79788f62015-02-02 23:57:25215}
216
avic9cec102015-12-23 00:39:26217void ExtensionHost::OnNetworkRequestStarted(uint64_t request_id) {
ericwilligersd1e28152016-10-17 22:53:14218 for (auto& observer : observer_list_)
219 observer.OnNetworkRequestStarted(this, request_id);
chirantan79788f62015-02-02 23:57:25220}
221
avic9cec102015-12-23 00:39:26222void ExtensionHost::OnNetworkRequestDone(uint64_t request_id) {
ericwilligersd1e28152016-10-17 22:53:14223 for (auto& observer : observer_list_)
224 observer.OnNetworkRequestDone(this, request_id);
chirantan79788f62015-02-02 23:57:25225}
226
[email protected]952a68e2011-11-17 00:36:10227const GURL& ExtensionHost::GetURL() const {
228 return host_contents()->GetURL();
229}
[email protected]5979cf5a12009-09-15 21:22:56230
[email protected]952a68e2011-11-17 00:36:10231void ExtensionHost::LoadInitialURL() {
kalman301145112015-02-07 00:43:45232 load_start_.reset(new base::ElapsedTimer());
[email protected]f5fa20e2011-12-21 22:35:56233 host_contents_->GetController().LoadURL(
Sylvain Defresnec6ccc77d2014-09-19 10:19:35234 initial_url_, content::Referrer(), ui::PAGE_TRANSITION_LINK,
[email protected]95dacd02011-12-05 10:35:26235 std::string());
[email protected]bbc945542009-07-26 00:11:42236}
237
[email protected]45a73d52013-11-26 00:10:55238bool ExtensionHost::IsBackgroundPage() const {
kalmanfd474fa2015-03-16 22:30:57239 DCHECK_EQ(extension_host_type_, VIEW_TYPE_EXTENSION_BACKGROUND_PAGE);
[email protected]45a73d52013-11-26 00:10:55240 return true;
241}
242
rockot494f0072015-07-29 17:58:07243void ExtensionHost::OnExtensionReady(content::BrowserContext* browser_context,
244 const Extension* extension) {
245 if (is_render_view_creation_pending_)
246 CreateRenderViewNow();
247}
248
limasdfbbaa913d2015-03-02 23:52:33249void ExtensionHost::OnExtensionUnloaded(
250 content::BrowserContext* browser_context,
251 const Extension* extension,
limasdf0deef2042017-05-03 19:17:17252 UnloadedExtensionReason reason) {
limasdfbbaa913d2015-03-02 23:52:33253 // The extension object will be deleted after this notification has been sent.
254 // Null it out so that dirty pointer issues don't arise in cases when multiple
255 // ExtensionHost objects pointing to the same Extension are present.
256 if (extension_ == extension) {
257 extension_ = nullptr;
[email protected]0d158052009-09-28 16:54:09258 }
[email protected]e95ad332009-08-03 19:44:25259}
260
[email protected]58d5cfe2013-07-10 02:40:52261void ExtensionHost::RenderProcessGone(base::TerminationStatus status) {
[email protected]a4ed6282009-12-14 20:51:16262 // During browser shutdown, we may use sudden termination on an extension
263 // process, so it is expected to lose our connection to the render view.
264 // Do nothing.
[email protected]2dcd62b2013-12-11 03:12:00265 RenderProcessHost* process_host = host_contents_->GetRenderProcessHost();
266 if (process_host && process_host->FastShutdownStarted())
[email protected]a4ed6282009-12-14 20:51:16267 return;
268
[email protected]6f39aee92010-01-26 22:33:58269 // In certain cases, multiple ExtensionHost objects may have pointed to
270 // the same Extension at some point (one with a background page and a
271 // popup, for example). When the first ExtensionHost goes away, the extension
272 // is unloaded, and any other host that pointed to that extension will have
kalman89a8dc82015-02-17 22:21:59273 // its pointer to it null'd out so that any attempt to unload a dirty pointer
[email protected]6f39aee92010-01-26 22:33:58274 // will be averted.
275 if (!extension_)
276 return;
277
[email protected]c5dbef02011-05-13 05:06:09278 // TODO(aa): This is suspicious. There can be multiple views in an extension,
279 // and they aren't all going to use ExtensionHost. This should be in someplace
280 // more central, like EPM maybe.
[email protected]ad50def52011-10-19 23:17:07281 content::NotificationService::current()->Notify(
[email protected]adf5a102014-07-31 12:44:06282 extensions::NOTIFICATION_EXTENSION_PROCESS_TERMINATED,
[email protected]96e6a1032013-11-28 06:58:03283 content::Source<BrowserContext>(browser_context_),
[email protected]6c2381d2011-10-19 02:52:53284 content::Details<ExtensionHost>(this));
[email protected]e72bd1f2009-12-11 03:19:39285}
286
fdegans6ce28f52015-03-19 12:52:22287void ExtensionHost::DidStartLoading() {
kalmanfd474fa2015-03-16 22:30:57288 if (!has_loaded_once_) {
ericwilligersd1e28152016-10-17 22:53:14289 for (auto& observer : deferred_start_render_host_observer_list_)
290 observer.OnDeferredStartRenderHostDidStartFirstLoad(this);
kalmanfd474fa2015-03-16 22:30:57291 }
kalmand49594b52015-02-27 17:27:16292}
293
fdegans6ce28f52015-03-19 12:52:22294void ExtensionHost::DidStopLoading() {
kalmanfd474fa2015-03-16 22:30:57295 // Only record UMA for the first load. Subsequent loads will likely behave
296 // quite different, and it's first load we're most interested in.
297 bool first_load = !has_loaded_once_;
298 has_loaded_once_ = true;
299 if (first_load) {
300 RecordStopLoadingUMA();
301 OnDidStopFirstLoad();
Daniel Xie9851a4a2015-03-14 22:22:26302 content::NotificationService::current()->Notify(
kalmanfd474fa2015-03-16 22:30:57303 extensions::NOTIFICATION_EXTENSION_HOST_DID_STOP_FIRST_LOAD,
Daniel Xie9851a4a2015-03-14 22:22:26304 content::Source<BrowserContext>(browser_context_),
305 content::Details<ExtensionHost>(this));
ericwilligersd1e28152016-10-17 22:53:14306 for (auto& observer : deferred_start_render_host_observer_list_)
307 observer.OnDeferredStartRenderHostDidStopFirstLoad(this);
Daniel Xie9851a4a2015-03-14 22:22:26308 }
[email protected]ae461542009-06-19 19:03:41309}
[email protected]8206c7c2009-04-29 23:52:27310
kalmanfd474fa2015-03-16 22:30:57311void ExtensionHost::OnDidStopFirstLoad() {
312 DCHECK_EQ(extension_host_type_, VIEW_TYPE_EXTENSION_BACKGROUND_PAGE);
[email protected]45a73d52013-11-26 00:10:55313 // Nothing to do for background pages.
314}
315
[email protected]952a68e2011-11-17 00:36:10316void ExtensionHost::DocumentAvailableInMainFrame() {
[email protected]97c64012010-01-04 21:27:59317 // If the document has already been marked as available for this host, then
318 // bail. No need for the redundant setup. http://crbug.com/31170
319 if (document_element_available_)
320 return;
[email protected]e95ad332009-08-03 19:44:25321 document_element_available_ = true;
[email protected]d9823b82013-11-27 16:37:17322
rdevlin.cronin070802b2015-02-13 21:24:04323 if (extension_host_type_ == VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) {
324 ExtensionSystem::Get(browser_context_)
325 ->runtime_data()
326 ->SetBackgroundPageReady(extension_->id(), true);
327 content::NotificationService::current()->Notify(
328 extensions::NOTIFICATION_EXTENSION_BACKGROUND_PAGE_READY,
329 content::Source<const Extension>(extension_),
330 content::NotificationService::NoDetails());
331 }
[email protected]dd3c3e682010-05-12 18:51:26332}
[email protected]1c1c77a52009-11-03 00:37:31333
[email protected]a81343d232011-12-27 07:39:20334void ExtensionHost::CloseContents(WebContents* contents) {
[email protected]45a73d52013-11-26 00:10:55335 Close();
[email protected]b32631022009-10-06 16:11:44336}
337
rdevlin.cronin6f42c2522015-06-19 18:58:51338bool ExtensionHost::OnMessageReceived(const IPC::Message& message,
339 content::RenderFrameHost* host) {
340 bool handled = true;
341 IPC_BEGIN_MESSAGE_MAP(ExtensionHost, message)
342 IPC_MESSAGE_HANDLER(ExtensionHostMsg_EventAck, OnEventAck)
rdevlin.cronincfa895d2015-06-24 23:46:55343 IPC_MESSAGE_HANDLER(ExtensionHostMsg_IncrementLazyKeepaliveCount,
344 OnIncrementLazyKeepaliveCount)
345 IPC_MESSAGE_HANDLER(ExtensionHostMsg_DecrementLazyKeepaliveCount,
346 OnDecrementLazyKeepaliveCount)
rdevlin.cronin6f42c2522015-06-19 18:58:51347 IPC_MESSAGE_UNHANDLED(handled = false)
348 IPC_END_MESSAGE_MAP()
349 return handled;
350}
351
chirantan669993c2015-03-05 23:38:33352void ExtensionHost::OnEventAck(int event_id) {
[email protected]b68c07b2014-04-16 12:42:36353 EventRouter* router = EventRouter::Get(browser_context_);
[email protected]7042b682012-04-19 22:57:51354 if (router)
[email protected]96e6a1032013-11-28 06:58:03355 router->OnEventAck(browser_context_, extension_id());
chirantan79788f62015-02-02 23:57:25356
chirantan669993c2015-03-05 23:38:33357 // This should always be false since event acks are only sent by extensions
358 // with lazy background pages but it doesn't hurt to be extra careful.
359 if (!IsBackgroundPage()) {
360 NOTREACHED() << "Received EventAck from extension " << extension_id()
361 << ", which does not have a lazy background page.";
362 return;
363 }
364
365 // A compromised renderer could start sending out arbitrary event ids, which
chirantan79788f62015-02-02 23:57:25366 // may affect other renderers by causing downstream methods to think that
chirantan669993c2015-03-05 23:38:33367 // events for other extensions have been acked. Make sure that the event id
368 // sent by the renderer is one that this ExtensionHost expects to receive.
chirantan79788f62015-02-02 23:57:25369 // This way if a renderer _is_ compromised, it can really only affect itself.
chirantan669993c2015-03-05 23:38:33370 if (unacked_messages_.erase(event_id) > 0) {
ericwilligersd1e28152016-10-17 22:53:14371 for (auto& observer : observer_list_)
372 observer.OnBackgroundEventAcked(this, event_id);
chirantan79788f62015-02-02 23:57:25373 } else {
chirantan669993c2015-03-05 23:38:33374 // We have received an unexpected event id from the renderer. It might be
chirantan79788f62015-02-02 23:57:25375 // compromised or it might have some other issue. Kill it just to be safe.
376 DCHECK(render_process_host());
chirantan669993c2015-03-05 23:38:33377 LOG(ERROR) << "Killing renderer for extension " << extension_id() << " for "
378 << "sending an EventAck message with a bad event id.";
jamescookda2505812015-03-20 18:01:18379 bad_message::ReceivedBadMessage(render_process_host(),
380 bad_message::EH_BAD_EVENT_ID);
chirantan79788f62015-02-02 23:57:25381 }
[email protected]7042b682012-04-19 22:57:51382}
383
384void ExtensionHost::OnIncrementLazyKeepaliveCount() {
reillyg0ea3fa902014-10-28 15:30:23385 ProcessManager::Get(browser_context_)
386 ->IncrementLazyKeepaliveCount(extension());
[email protected]7042b682012-04-19 22:57:51387}
388
389void ExtensionHost::OnDecrementLazyKeepaliveCount() {
reillyg0ea3fa902014-10-28 15:30:23390 ProcessManager::Get(browser_context_)
391 ->DecrementLazyKeepaliveCount(extension());
[email protected]7042b682012-04-19 22:57:51392}
393
[email protected]45a73d52013-11-26 00:10:55394// content::WebContentsObserver
[email protected]7042b682012-04-19 22:57:51395
[email protected]952a68e2011-11-17 00:36:10396void ExtensionHost::RenderViewCreated(RenderViewHost* render_view_host) {
[email protected]4f4d42a2011-12-02 02:42:49397 render_view_host_ = render_view_host;
[email protected]63954792011-07-11 04:17:48398}
399
[email protected]4f4d42a2011-12-02 02:42:49400void ExtensionHost::RenderViewDeleted(RenderViewHost* render_view_host) {
401 // If our RenderViewHost is deleted, fall back to the host_contents' current
402 // RVH. There is sometimes a small gap between the pending RVH being deleted
403 // and RenderViewCreated being called, so we update it here.
404 if (render_view_host == render_view_host_)
[email protected]151a63d2011-12-20 22:32:52405 render_view_host_ = host_contents_->GetRenderViewHost();
[email protected]4f4d42a2011-12-02 02:42:49406}
407
mathiash72a5e462014-11-19 08:18:50408content::JavaScriptDialogManager* ExtensionHost::GetJavaScriptDialogManager(
409 WebContents* source) {
[email protected]6c0f179f2014-03-19 11:04:41410 return delegate_->GetJavaScriptDialogManager();
[email protected]63954792011-07-11 04:17:48411}
412
[email protected]2a6bc3e2011-12-28 23:51:33413void ExtensionHost::AddNewContents(WebContents* source,
414 WebContents* new_contents,
[email protected]952a68e2011-11-17 00:36:10415 WindowOpenDisposition disposition,
bokan107a47f2015-02-03 23:23:39416 const gfx::Rect& initial_rect,
[email protected]eda238a12012-09-07 23:44:00417 bool user_gesture,
418 bool* was_blocked) {
[email protected]44d8ce762010-10-26 21:06:18419 // First, if the creating extension view was associated with a tab contents,
420 // use that tab content's delegate. We must be careful here that the
421 // associated tab contents has the same profile as the new tab contents. In
422 // the case of extensions in 'spanning' incognito mode, they can mismatch.
423 // We don't want to end up putting a normal tab into an incognito window, or
424 // vice versa.
[email protected]c33f4ac52011-12-20 00:18:40425 // Note that we don't do this for popup windows, because we need to associate
426 // those with their extension_app_id.
nick3b04f322016-08-31 19:29:19427 if (disposition != WindowOpenDisposition::NEW_POPUP) {
[email protected]ea049a02011-12-25 21:37:09428 WebContents* associated_contents = GetAssociatedWebContents();
[email protected]c33f4ac52011-12-20 00:18:40429 if (associated_contents &&
[email protected]627e0512011-12-21 22:55:30430 associated_contents->GetBrowserContext() ==
431 new_contents->GetBrowserContext()) {
[email protected]eda238a12012-09-07 23:44:00432 WebContentsDelegate* delegate = associated_contents->GetDelegate();
433 if (delegate) {
434 delegate->AddNewContents(
bokan107a47f2015-02-03 23:23:39435 associated_contents, new_contents, disposition, initial_rect,
[email protected]eda238a12012-09-07 23:44:00436 user_gesture, was_blocked);
[email protected]a3421eb12012-11-20 13:47:09437 return;
[email protected]eda238a12012-09-07 23:44:00438 }
[email protected]c33f4ac52011-12-20 00:18:40439 }
[email protected]44d8ce762010-10-26 21:06:18440 }
441
[email protected]6c0f179f2014-03-19 11:04:41442 delegate_->CreateTab(
bokan107a47f2015-02-03 23:23:39443 new_contents, extension_id_, disposition, initial_rect, user_gesture);
[email protected]c64631652009-04-29 22:24:31444}
[email protected]28b3a812011-11-08 01:03:43445
[email protected]952a68e2011-11-17 00:36:10446void ExtensionHost::RenderViewReady() {
[email protected]8f51a1c82011-11-09 01:48:24447 content::NotificationService::current()->Notify(
[email protected]adf5a102014-07-31 12:44:06448 extensions::NOTIFICATION_EXTENSION_HOST_CREATED,
[email protected]96e6a1032013-11-28 06:58:03449 content::Source<BrowserContext>(browser_context_),
[email protected]8f51a1c82011-11-09 01:48:24450 content::Details<ExtensionHost>(this));
451}
[email protected]3a1dc572012-07-31 22:25:13452
[email protected]0b9383a2012-10-26 00:58:16453void ExtensionHost::RequestMediaAccessPermission(
454 content::WebContents* web_contents,
[email protected]33662e52013-01-07 21:31:09455 const content::MediaStreamRequest& request,
[email protected]0b9383a2012-10-26 00:58:16456 const content::MediaResponseCallback& callback) {
[email protected]6c0f179f2014-03-19 11:04:41457 delegate_->ProcessMediaAccessRequest(
[email protected]eb1a18ce2013-04-09 22:28:16458 web_contents, request, callback, extension());
[email protected]0b9383a2012-10-26 00:58:16459}
460
grunell657d4d82014-09-18 00:09:43461bool ExtensionHost::CheckMediaAccessPermission(
462 content::WebContents* web_contents,
463 const GURL& security_origin,
464 content::MediaStreamType type) {
465 return delegate_->CheckMediaAccessPermission(
466 web_contents, security_origin, type, extension());
467}
468
[email protected]7912e822014-04-16 02:37:03469bool ExtensionHost::IsNeverVisible(content::WebContents* web_contents) {
470 ViewType view_type = extensions::GetViewType(web_contents);
471 return view_type == extensions::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE;
472}
473
kalmanfd474fa2015-03-16 22:30:57474void ExtensionHost::RecordStopLoadingUMA() {
475 CHECK(load_start_.get());
476 if (extension_host_type_ == VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) {
477 if (extension_ && BackgroundInfo::HasLazyBackgroundPage(extension_)) {
478 UMA_HISTOGRAM_MEDIUM_TIMES("Extensions.EventPageLoadTime2",
479 load_start_->Elapsed());
480 } else {
481 UMA_HISTOGRAM_MEDIUM_TIMES("Extensions.BackgroundPageLoadTime2",
482 load_start_->Elapsed());
483 }
484 } else if (extension_host_type_ == VIEW_TYPE_EXTENSION_POPUP) {
485 UMA_HISTOGRAM_MEDIUM_TIMES("Extensions.PopupLoadTime2",
486 load_start_->Elapsed());
kalman0f101ac2015-05-06 01:23:17487 UMA_HISTOGRAM_MEDIUM_TIMES("Extensions.PopupCreateTime",
488 create_start_.Elapsed());
kalmanfd474fa2015-03-16 22:30:57489 }
490}
491
[email protected]3a1dc572012-07-31 22:25:13492} // namespace extensions