[email protected] | 22401dc | 2014-03-21 01:38:57 | [diff] [blame] | 1 | // Copyright 2014 The Chromium Authors. All rights reserved. |
[email protected] | c6463165 | 2009-04-29 22:24:31 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
[email protected] | 22401dc | 2014-03-21 01:38:57 | [diff] [blame] | 5 | #include "extensions/browser/extension_host.h" |
[email protected] | c6463165 | 2009-04-29 22:24:31 | [diff] [blame] | 6 | |
[email protected] | 88b50b6 | 2013-09-01 23:05:06 | [diff] [blame] | 7 | #include "base/logging.h" |
oysteine | 78b0b93 | 2014-12-10 18:06:38 | [diff] [blame] | 8 | #include "base/metrics/field_trial.h" |
kalman | 30114511 | 2015-02-07 00:43:45 | [diff] [blame] | 9 | #include "base/metrics/histogram_macros.h" |
robliao | 8f3cf26 | 2015-03-05 21:43:28 | [diff] [blame] | 10 | #include "base/profiler/scoped_tracker.h" |
[email protected] | 00e7bef | 2013-06-10 20:35:17 | [diff] [blame] | 11 | #include "base/strings/string_util.h" |
[email protected] | 112158af | 2013-06-07 23:46:18 | [diff] [blame] | 12 | #include "base/strings/utf_string_conversions.h" |
[email protected] | 91abb92 | 2013-12-03 18:39:56 | [diff] [blame] | 13 | #include "content/public/browser/browser_context.h" |
[email protected] | 79f06c737 | 2011-11-21 18:00:32 | [diff] [blame] | 14 | #include "content/public/browser/content_browser_client.h" |
| 15 | #include "content/public/browser/native_web_keyboard_event.h" |
[email protected] | c13be0d | 2011-11-22 02:09:58 | [diff] [blame] | 16 | #include "content/public/browser/notification_service.h" |
| 17 | #include "content/public/browser/render_process_host.h" |
[email protected] | 9c1662b | 2012-03-06 15:44:33 | [diff] [blame] | 18 | #include "content/public/browser/render_view_host.h" |
[email protected] | 14ddecf | 2013-08-24 15:29:42 | [diff] [blame] | 19 | #include "content/public/browser/render_widget_host_view.h" |
[email protected] | b658359 | 2012-01-25 19:52:33 | [diff] [blame] | 20 | #include "content/public/browser/site_instance.h" |
[email protected] | 3a7d7d3 | 2012-01-05 17:44:01 | [diff] [blame] | 21 | #include "content/public/browser/web_contents.h" |
jamescook | da250581 | 2015-03-20 18:01:18 | [diff] [blame] | 22 | #include "extensions/browser/bad_message.h" |
[email protected] | 3442353 | 2013-11-21 18:13:10 | [diff] [blame] | 23 | #include "extensions/browser/event_router.h" |
[email protected] | 88b50b6 | 2013-09-01 23:05:06 | [diff] [blame] | 24 | #include "extensions/browser/extension_error.h" |
[email protected] | 6c0f179f | 2014-03-19 11:04:41 | [diff] [blame] | 25 | #include "extensions/browser/extension_host_delegate.h" |
chirantan | 79788f6 | 2015-02-02 23:57:25 | [diff] [blame] | 26 | #include "extensions/browser/extension_host_observer.h" |
kalman | fcece45 | 2015-02-18 18:20:42 | [diff] [blame] | 27 | #include "extensions/browser/extension_host_queue.h" |
limasdf | bbaa913d | 2015-03-02 23:52:33 | [diff] [blame] | 28 | #include "extensions/browser/extension_registry.h" |
[email protected] | 59b0e60 | 2014-01-30 00:41:24 | [diff] [blame] | 29 | #include "extensions/browser/extension_system.h" |
rdevlin.cronin | cb2ec659a | 2015-06-10 23:32:41 | [diff] [blame] | 30 | #include "extensions/browser/extension_web_contents_observer.h" |
[email protected] | 6a0398b6 | 2013-12-16 22:54:56 | [diff] [blame] | 31 | #include "extensions/browser/extensions_browser_client.h" |
kalman | d49594b5 | 2015-02-27 17:27:16 | [diff] [blame] | 32 | #include "extensions/browser/load_monitoring_extension_host_queue.h" |
[email protected] | adf5a10 | 2014-07-31 12:44:06 | [diff] [blame] | 33 | #include "extensions/browser/notification_types.h" |
[email protected] | 98b6d94 | 2013-11-10 00:34:07 | [diff] [blame] | 34 | #include "extensions/browser/process_manager.h" |
[email protected] | 45f5b7d | 2014-01-22 23:47:13 | [diff] [blame] | 35 | #include "extensions/browser/runtime_data.h" |
[email protected] | cb2edf2 | 2013-04-01 20:25:23 | [diff] [blame] | 36 | #include "extensions/browser/view_type_utils.h" |
[email protected] | e4452d3 | 2013-11-15 23:07:41 | [diff] [blame] | 37 | #include "extensions/common/extension.h" |
[email protected] | fb820c0 | 2014-03-13 15:07:08 | [diff] [blame] | 38 | #include "extensions/common/extension_messages.h" |
[email protected] | 88b50b6 | 2013-09-01 23:05:06 | [diff] [blame] | 39 | #include "extensions/common/extension_urls.h" |
[email protected] | 5ef835a | 2013-11-08 20:42:57 | [diff] [blame] | 40 | #include "extensions/common/feature_switch.h" |
[email protected] | 558878cc8 | 2013-11-09 01:25:51 | [diff] [blame] | 41 | #include "extensions/common/manifest_handlers/background_info.h" |
[email protected] | c051a1b | 2011-01-21 23:30:17 | [diff] [blame] | 42 | #include "ui/base/l10n/l10n_util.h" |
[email protected] | 91abb92 | 2013-12-03 18:39:56 | [diff] [blame] | 43 | #include "ui/base/window_open_disposition.h" |
[email protected] | 1ce88e8 | 2013-06-28 05:17:10 | [diff] [blame] | 44 | |
[email protected] | 96e6a103 | 2013-11-28 06:58:03 | [diff] [blame] | 45 | using content::BrowserContext; |
[email protected] | e5d549d | 2011-12-28 01:29:20 | [diff] [blame] | 46 | using content::OpenURLParams; |
[email protected] | 2dcd62b | 2013-12-11 03:12:00 | [diff] [blame] | 47 | using content::RenderProcessHost; |
[email protected] | eaabba2 | 2012-03-07 15:02:11 | [diff] [blame] | 48 | using content::RenderViewHost; |
[email protected] | b658359 | 2012-01-25 19:52:33 | [diff] [blame] | 49 | using content::SiteInstance; |
[email protected] | ea049a0 | 2011-12-25 21:37:09 | [diff] [blame] | 50 | using content::WebContents; |
[email protected] | 3a1dc57 | 2012-07-31 22:25:13 | [diff] [blame] | 51 | |
| 52 | namespace extensions { |
[email protected] | 1d9f413 | 2009-09-08 17:29:25 | [diff] [blame] | 53 | |
[email protected] | 3a1dc57 | 2012-07-31 22:25:13 | [diff] [blame] | 54 | ExtensionHost::ExtensionHost(const Extension* extension, |
[email protected] | 9adb969 | 2010-10-29 23:14:02 | [diff] [blame] | 55 | SiteInstance* site_instance, |
| 56 | const GURL& url, |
[email protected] | cb2edf2 | 2013-04-01 20:25:23 | [diff] [blame] | 57 | ViewType host_type) |
[email protected] | 6c0f179f | 2014-03-19 11:04:41 | [diff] [blame] | 58 | : delegate_(ExtensionsBrowserClient::Get()->CreateExtensionHostDelegate()), |
| 59 | extension_(extension), |
[email protected] | 2d2f6cfc | 2011-05-06 21:09:33 | [diff] [blame] | 60 | extension_id_(extension->id()), |
[email protected] | 96e6a103 | 2013-11-28 06:58:03 | [diff] [blame] | 61 | browser_context_(site_instance->GetBrowserContext()), |
kalman | 89a8dc8 | 2015-02-17 22:21:59 | [diff] [blame] | 62 | render_view_host_(nullptr), |
rockot | 494f007 | 2015-07-29 17:58:07 | [diff] [blame] | 63 | is_render_view_creation_pending_(false), |
kalman | fd474fa | 2015-03-16 22:30:57 | [diff] [blame] | 64 | has_loaded_once_(false), |
[email protected] | e95ad33 | 2009-08-03 19:44:25 | [diff] [blame] | 65 | document_element_available_(false), |
[email protected] | 952a68e | 2011-11-17 00:36:10 | [diff] [blame] | 66 | initial_url_(url), |
[email protected] | d9823b8 | 2013-11-27 16:37:17 | [diff] [blame] | 67 | extension_host_type_(host_type) { |
[email protected] | 45a73d5 | 2013-11-26 00:10:55 | [diff] [blame] | 68 | // Not used for panels, see PanelHost. |
| 69 | DCHECK(host_type == VIEW_TYPE_EXTENSION_BACKGROUND_PAGE || |
| 70 | host_type == VIEW_TYPE_EXTENSION_DIALOG || |
[email protected] | 45a73d5 | 2013-11-26 00:10:55 | [diff] [blame] | 71 | host_type == VIEW_TYPE_EXTENSION_POPUP); |
[email protected] | 3a7d7d3 | 2012-01-05 17:44:01 | [diff] [blame] | 72 | host_contents_.reset(WebContents::Create( |
[email protected] | 96e6a103 | 2013-11-28 06:58:03 | [diff] [blame] | 73 | WebContents::CreateParams(browser_context_, site_instance))), |
[email protected] | d8c66043 | 2011-12-22 20:51:25 | [diff] [blame] | 74 | content::WebContentsObserver::Observe(host_contents_.get()); |
[email protected] | 6934a70 | 2011-12-20 00:04:51 | [diff] [blame] | 75 | host_contents_->SetDelegate(this); |
[email protected] | cb2edf2 | 2013-04-01 20:25:23 | [diff] [blame] | 76 | SetViewType(host_contents_.get(), host_type); |
[email protected] | 9610ef24 | 2009-11-18 02:41:26 | [diff] [blame] | 77 | |
[email protected] | 151a63d | 2011-12-20 22:32:52 | [diff] [blame] | 78 | render_view_host_ = host_contents_->GetRenderViewHost(); |
[email protected] | 4f4d42a | 2011-12-02 02:42:49 | [diff] [blame] | 79 | |
[email protected] | 6f39aee9 | 2010-01-26 22:33:58 | [diff] [blame] | 80 | // Listen for when an extension is unloaded from the same profile, as it may |
| 81 | // be the same extension that this points to. |
limasdf | bbaa913d | 2015-03-02 23:52:33 | [diff] [blame] | 82 | ExtensionRegistry::Get(browser_context_)->AddObserver(this); |
[email protected] | 9be525e | 2014-01-10 20:52:40 | [diff] [blame] | 83 | |
[email protected] | 1ce1597 | 2014-03-20 19:25:48 | [diff] [blame] | 84 | // Set up web contents observers and pref observers. |
[email protected] | 6c0f179f | 2014-03-19 11:04:41 | [diff] [blame] | 85 | delegate_->OnExtensionHostCreated(host_contents()); |
rdevlin.cronin | cb2ec659a | 2015-06-10 23:32:41 | [diff] [blame] | 86 | |
| 87 | ExtensionWebContentsObserver::GetForWebContents(host_contents())-> |
| 88 | dispatcher()->set_delegate(this); |
[email protected] | c6463165 | 2009-04-29 22:24:31 | [diff] [blame] | 89 | } |
| 90 | |
| 91 | ExtensionHost::~ExtensionHost() { |
limasdf | bbaa913d | 2015-03-02 23:52:33 | [diff] [blame] | 92 | ExtensionRegistry::Get(browser_context_)->RemoveObserver(this); |
| 93 | |
[email protected] | cb2edf2 | 2013-04-01 20:25:23 | [diff] [blame] | 94 | if (extension_host_type_ == VIEW_TYPE_EXTENSION_BACKGROUND_PAGE && |
kalman | 30114511 | 2015-02-07 00:43:45 | [diff] [blame] | 95 | extension_ && BackgroundInfo::HasLazyBackgroundPage(extension_) && |
| 96 | load_start_.get()) { |
| 97 | UMA_HISTOGRAM_LONG_TIMES("Extensions.EventPageActiveTime2", |
| 98 | load_start_->Elapsed()); |
[email protected] | 36a438a | 2012-05-12 00:00:33 | [diff] [blame] | 99 | } |
kalman | fd474fa | 2015-03-16 22:30:57 | [diff] [blame] | 100 | |
[email protected] | ad50def5 | 2011-10-19 23:17:07 | [diff] [blame] | 101 | content::NotificationService::current()->Notify( |
[email protected] | adf5a10 | 2014-07-31 12:44:06 | [diff] [blame] | 102 | extensions::NOTIFICATION_EXTENSION_HOST_DESTROYED, |
[email protected] | 96e6a103 | 2013-11-28 06:58:03 | [diff] [blame] | 103 | content::Source<BrowserContext>(browser_context_), |
[email protected] | 6c2381d | 2011-10-19 02:52:53 | [diff] [blame] | 104 | content::Details<ExtensionHost>(this)); |
ericwilligers | d1e2815 | 2016-10-17 22:53:14 | [diff] [blame] | 105 | for (auto& observer : observer_list_) |
| 106 | observer.OnExtensionHostDestroyed(this); |
| 107 | for (auto& observer : deferred_start_render_host_observer_list_) |
| 108 | observer.OnDeferredStartRenderHostDestroyed(this); |
kalman | fd474fa | 2015-03-16 22:30:57 | [diff] [blame] | 109 | |
| 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. |
yoz | d61dfe19 | 2015-02-21 01:30:37 | [diff] [blame] | 113 | delegate_->GetExtensionHostQueue()->Remove(this); |
kalman | fd474fa | 2015-03-16 22:30:57 | [diff] [blame] | 114 | |
| 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. |
kalman | 89a8dc8 | 2015-02-17 22:21:59 | [diff] [blame] | 119 | content::WebContentsObserver::Observe(nullptr); |
[email protected] | c6463165 | 2009-04-29 22:24:31 | [diff] [blame] | 120 | } |
| 121 | |
[email protected] | f3b1a08 | 2011-11-18 00:34:30 | [diff] [blame] | 122 | content::RenderProcessHost* ExtensionHost::render_process_host() const { |
[email protected] | 9f76c1e | 2012-03-05 15:15:58 | [diff] [blame] | 123 | return render_view_host()->GetProcess(); |
[email protected] | 8a17bd5 | 2009-06-06 08:19:49 | [diff] [blame] | 124 | } |
| 125 | |
[email protected] | 952a68e | 2011-11-17 00:36:10 | [diff] [blame] | 126 | RenderViewHost* ExtensionHost::render_view_host() const { |
kalman | 89a8dc8 | 2015-02-17 22:21:59 | [diff] [blame] | 127 | // TODO(mpcomplete): This can be null. How do we handle that? |
[email protected] | 4f4d42a | 2011-12-02 02:42:49 | [diff] [blame] | 128 | return render_view_host_; |
[email protected] | c6463165 | 2009-04-29 22:24:31 | [diff] [blame] | 129 | } |
| 130 | |
[email protected] | 7c6877d | 2009-06-19 13:56:25 | [diff] [blame] | 131 | bool ExtensionHost::IsRenderViewLive() const { |
[email protected] | 952a68e | 2011-11-17 00:36:10 | [diff] [blame] | 132 | return render_view_host()->IsRenderViewLive(); |
[email protected] | 7c6877d | 2009-06-19 13:56:25 | [diff] [blame] | 133 | } |
| 134 | |
[email protected] | 952a68e | 2011-11-17 00:36:10 | [diff] [blame] | 135 | void ExtensionHost::CreateRenderViewSoon() { |
kalman | 30114511 | 2015-02-07 00:43:45 | [diff] [blame] | 136 | if (render_process_host() && render_process_host()->HasConnection()) { |
[email protected] | 84455000 | 2009-11-20 01:06:00 | [diff] [blame] | 137 | // 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 { |
yoz | d61dfe19 | 2015-02-21 01:30:37 | [diff] [blame] | 142 | delegate_->GetExtensionHostQueue()->Add(this); |
[email protected] | 84455000 | 2009-11-20 01:06:00 | [diff] [blame] | 143 | } |
| 144 | } |
| 145 | |
| 146 | void ExtensionHost::CreateRenderViewNow() { |
robliao | 8f3cf26 | 2015-03-05 21:43:28 | [diff] [blame] | 147 | // 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")); |
rockot | 494f007 | 2015-07-29 17:58:07 | [diff] [blame] | 151 | 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] | 952a68e | 2011-11-17 00:36:10 | [diff] [blame] | 158 | LoadInitialURL(); |
[email protected] | 7f256e09 | 2014-03-09 16:17:36 | [diff] [blame] | 159 | if (IsBackgroundPage()) { |
robliao | 8f3cf26 | 2015-03-05 21:43:28 | [diff] [blame] | 160 | // 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] | 952a68e | 2011-11-17 00:36:10 | [diff] [blame] | 164 | DCHECK(IsRenderViewLive()); |
oysteine | 78b0b93 | 2014-12-10 18:06:38 | [diff] [blame] | 165 | if (extension_) { |
oysteine | 7ad8e8a | 2015-06-12 23:09:04 | [diff] [blame] | 166 | std::string group_name = base::FieldTrialList::FindFullName( |
| 167 | "ThrottleExtensionBackgroundPages"); |
| 168 | if ((group_name == "ThrottlePersistent" && |
| 169 | extensions::BackgroundInfo::HasPersistentBackgroundPage( |
| 170 | extension_)) || |
| 171 | group_name == "ThrottleAll") { |
oysteine | 78b0b93 | 2014-12-10 18:06:38 | [diff] [blame] | 172 | host_contents_->WasHidden(); |
| 173 | } |
| 174 | } |
robliao | 8f3cf26 | 2015-03-05 21:43:28 | [diff] [blame] | 175 | // 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] | 79beb8d | 2014-03-18 22:18:45 | [diff] [blame] | 179 | // Connect orphaned dev-tools instances. |
[email protected] | 6c0f179f | 2014-03-19 11:04:41 | [diff] [blame] | 180 | delegate_->OnRenderViewCreatedForBackgroundPage(this); |
[email protected] | 28b3a81 | 2011-11-08 01:03:43 | [diff] [blame] | 181 | } |
[email protected] | c6463165 | 2009-04-29 22:24:31 | [diff] [blame] | 182 | } |
| 183 | |
kalman | d49594b5 | 2015-02-27 17:27:16 | [diff] [blame] | 184 | void ExtensionHost::AddDeferredStartRenderHostObserver( |
| 185 | DeferredStartRenderHostObserver* observer) { |
| 186 | deferred_start_render_host_observer_list_.AddObserver(observer); |
| 187 | } |
| 188 | |
| 189 | void ExtensionHost::RemoveDeferredStartRenderHostObserver( |
| 190 | DeferredStartRenderHostObserver* observer) { |
| 191 | deferred_start_render_host_observer_list_.RemoveObserver(observer); |
| 192 | } |
| 193 | |
kalman | fcece45 | 2015-02-18 18:20:42 | [diff] [blame] | 194 | void 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 | |
chirantan | 79788f6 | 2015-02-02 23:57:25 | [diff] [blame] | 201 | void ExtensionHost::AddObserver(ExtensionHostObserver* observer) { |
| 202 | observer_list_.AddObserver(observer); |
| 203 | } |
| 204 | |
| 205 | void ExtensionHost::RemoveObserver(ExtensionHostObserver* observer) { |
| 206 | observer_list_.RemoveObserver(observer); |
| 207 | } |
| 208 | |
chirantan | 669993c | 2015-03-05 23:38:33 | [diff] [blame] | 209 | void ExtensionHost::OnBackgroundEventDispatched(const std::string& event_name, |
| 210 | int event_id) { |
| 211 | CHECK(IsBackgroundPage()); |
| 212 | unacked_messages_.insert(event_id); |
ericwilligers | d1e2815 | 2016-10-17 22:53:14 | [diff] [blame] | 213 | for (auto& observer : observer_list_) |
| 214 | observer.OnBackgroundEventDispatched(this, event_name, event_id); |
chirantan | 79788f6 | 2015-02-02 23:57:25 | [diff] [blame] | 215 | } |
| 216 | |
avi | c9cec10 | 2015-12-23 00:39:26 | [diff] [blame] | 217 | void ExtensionHost::OnNetworkRequestStarted(uint64_t request_id) { |
ericwilligers | d1e2815 | 2016-10-17 22:53:14 | [diff] [blame] | 218 | for (auto& observer : observer_list_) |
| 219 | observer.OnNetworkRequestStarted(this, request_id); |
chirantan | 79788f6 | 2015-02-02 23:57:25 | [diff] [blame] | 220 | } |
| 221 | |
avi | c9cec10 | 2015-12-23 00:39:26 | [diff] [blame] | 222 | void ExtensionHost::OnNetworkRequestDone(uint64_t request_id) { |
ericwilligers | d1e2815 | 2016-10-17 22:53:14 | [diff] [blame] | 223 | for (auto& observer : observer_list_) |
| 224 | observer.OnNetworkRequestDone(this, request_id); |
chirantan | 79788f6 | 2015-02-02 23:57:25 | [diff] [blame] | 225 | } |
| 226 | |
[email protected] | 952a68e | 2011-11-17 00:36:10 | [diff] [blame] | 227 | const GURL& ExtensionHost::GetURL() const { |
| 228 | return host_contents()->GetURL(); |
| 229 | } |
[email protected] | 5979cf5a1 | 2009-09-15 21:22:56 | [diff] [blame] | 230 | |
[email protected] | 952a68e | 2011-11-17 00:36:10 | [diff] [blame] | 231 | void ExtensionHost::LoadInitialURL() { |
kalman | 30114511 | 2015-02-07 00:43:45 | [diff] [blame] | 232 | load_start_.reset(new base::ElapsedTimer()); |
[email protected] | f5fa20e | 2011-12-21 22:35:56 | [diff] [blame] | 233 | host_contents_->GetController().LoadURL( |
Sylvain Defresne | c6ccc77d | 2014-09-19 10:19:35 | [diff] [blame] | 234 | initial_url_, content::Referrer(), ui::PAGE_TRANSITION_LINK, |
[email protected] | 95dacd0 | 2011-12-05 10:35:26 | [diff] [blame] | 235 | std::string()); |
[email protected] | bbc94554 | 2009-07-26 00:11:42 | [diff] [blame] | 236 | } |
| 237 | |
[email protected] | 45a73d5 | 2013-11-26 00:10:55 | [diff] [blame] | 238 | bool ExtensionHost::IsBackgroundPage() const { |
kalman | fd474fa | 2015-03-16 22:30:57 | [diff] [blame] | 239 | DCHECK_EQ(extension_host_type_, VIEW_TYPE_EXTENSION_BACKGROUND_PAGE); |
[email protected] | 45a73d5 | 2013-11-26 00:10:55 | [diff] [blame] | 240 | return true; |
| 241 | } |
| 242 | |
rockot | 494f007 | 2015-07-29 17:58:07 | [diff] [blame] | 243 | void ExtensionHost::OnExtensionReady(content::BrowserContext* browser_context, |
| 244 | const Extension* extension) { |
| 245 | if (is_render_view_creation_pending_) |
| 246 | CreateRenderViewNow(); |
| 247 | } |
| 248 | |
limasdf | bbaa913d | 2015-03-02 23:52:33 | [diff] [blame] | 249 | void ExtensionHost::OnExtensionUnloaded( |
| 250 | content::BrowserContext* browser_context, |
| 251 | const Extension* extension, |
limasdf | 0deef204 | 2017-05-03 19:17:17 | [diff] [blame] | 252 | UnloadedExtensionReason reason) { |
limasdf | bbaa913d | 2015-03-02 23:52:33 | [diff] [blame] | 253 | // 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] | 0d15805 | 2009-09-28 16:54:09 | [diff] [blame] | 258 | } |
[email protected] | e95ad33 | 2009-08-03 19:44:25 | [diff] [blame] | 259 | } |
| 260 | |
[email protected] | 58d5cfe | 2013-07-10 02:40:52 | [diff] [blame] | 261 | void ExtensionHost::RenderProcessGone(base::TerminationStatus status) { |
[email protected] | a4ed628 | 2009-12-14 20:51:16 | [diff] [blame] | 262 | // 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] | 2dcd62b | 2013-12-11 03:12:00 | [diff] [blame] | 265 | RenderProcessHost* process_host = host_contents_->GetRenderProcessHost(); |
| 266 | if (process_host && process_host->FastShutdownStarted()) |
[email protected] | a4ed628 | 2009-12-14 20:51:16 | [diff] [blame] | 267 | return; |
| 268 | |
[email protected] | 6f39aee9 | 2010-01-26 22:33:58 | [diff] [blame] | 269 | // 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 |
kalman | 89a8dc8 | 2015-02-17 22:21:59 | [diff] [blame] | 273 | // its pointer to it null'd out so that any attempt to unload a dirty pointer |
[email protected] | 6f39aee9 | 2010-01-26 22:33:58 | [diff] [blame] | 274 | // will be averted. |
| 275 | if (!extension_) |
| 276 | return; |
| 277 | |
[email protected] | c5dbef0 | 2011-05-13 05:06:09 | [diff] [blame] | 278 | // 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] | ad50def5 | 2011-10-19 23:17:07 | [diff] [blame] | 281 | content::NotificationService::current()->Notify( |
[email protected] | adf5a10 | 2014-07-31 12:44:06 | [diff] [blame] | 282 | extensions::NOTIFICATION_EXTENSION_PROCESS_TERMINATED, |
[email protected] | 96e6a103 | 2013-11-28 06:58:03 | [diff] [blame] | 283 | content::Source<BrowserContext>(browser_context_), |
[email protected] | 6c2381d | 2011-10-19 02:52:53 | [diff] [blame] | 284 | content::Details<ExtensionHost>(this)); |
[email protected] | e72bd1f | 2009-12-11 03:19:39 | [diff] [blame] | 285 | } |
| 286 | |
fdegans | 6ce28f5 | 2015-03-19 12:52:22 | [diff] [blame] | 287 | void ExtensionHost::DidStartLoading() { |
kalman | fd474fa | 2015-03-16 22:30:57 | [diff] [blame] | 288 | if (!has_loaded_once_) { |
ericwilligers | d1e2815 | 2016-10-17 22:53:14 | [diff] [blame] | 289 | for (auto& observer : deferred_start_render_host_observer_list_) |
| 290 | observer.OnDeferredStartRenderHostDidStartFirstLoad(this); |
kalman | fd474fa | 2015-03-16 22:30:57 | [diff] [blame] | 291 | } |
kalman | d49594b5 | 2015-02-27 17:27:16 | [diff] [blame] | 292 | } |
| 293 | |
fdegans | 6ce28f5 | 2015-03-19 12:52:22 | [diff] [blame] | 294 | void ExtensionHost::DidStopLoading() { |
kalman | fd474fa | 2015-03-16 22:30:57 | [diff] [blame] | 295 | // 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 Xie | 9851a4a | 2015-03-14 22:22:26 | [diff] [blame] | 302 | content::NotificationService::current()->Notify( |
kalman | fd474fa | 2015-03-16 22:30:57 | [diff] [blame] | 303 | extensions::NOTIFICATION_EXTENSION_HOST_DID_STOP_FIRST_LOAD, |
Daniel Xie | 9851a4a | 2015-03-14 22:22:26 | [diff] [blame] | 304 | content::Source<BrowserContext>(browser_context_), |
| 305 | content::Details<ExtensionHost>(this)); |
ericwilligers | d1e2815 | 2016-10-17 22:53:14 | [diff] [blame] | 306 | for (auto& observer : deferred_start_render_host_observer_list_) |
| 307 | observer.OnDeferredStartRenderHostDidStopFirstLoad(this); |
Daniel Xie | 9851a4a | 2015-03-14 22:22:26 | [diff] [blame] | 308 | } |
[email protected] | ae46154 | 2009-06-19 19:03:41 | [diff] [blame] | 309 | } |
[email protected] | 8206c7c | 2009-04-29 23:52:27 | [diff] [blame] | 310 | |
kalman | fd474fa | 2015-03-16 22:30:57 | [diff] [blame] | 311 | void ExtensionHost::OnDidStopFirstLoad() { |
| 312 | DCHECK_EQ(extension_host_type_, VIEW_TYPE_EXTENSION_BACKGROUND_PAGE); |
[email protected] | 45a73d5 | 2013-11-26 00:10:55 | [diff] [blame] | 313 | // Nothing to do for background pages. |
| 314 | } |
| 315 | |
[email protected] | 952a68e | 2011-11-17 00:36:10 | [diff] [blame] | 316 | void ExtensionHost::DocumentAvailableInMainFrame() { |
[email protected] | 97c6401 | 2010-01-04 21:27:59 | [diff] [blame] | 317 | // 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] | e95ad33 | 2009-08-03 19:44:25 | [diff] [blame] | 321 | document_element_available_ = true; |
[email protected] | d9823b8 | 2013-11-27 16:37:17 | [diff] [blame] | 322 | |
rdevlin.cronin | 070802b | 2015-02-13 21:24:04 | [diff] [blame] | 323 | 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] | dd3c3e68 | 2010-05-12 18:51:26 | [diff] [blame] | 332 | } |
[email protected] | 1c1c77a5 | 2009-11-03 00:37:31 | [diff] [blame] | 333 | |
[email protected] | a81343d23 | 2011-12-27 07:39:20 | [diff] [blame] | 334 | void ExtensionHost::CloseContents(WebContents* contents) { |
[email protected] | 45a73d5 | 2013-11-26 00:10:55 | [diff] [blame] | 335 | Close(); |
[email protected] | b3263102 | 2009-10-06 16:11:44 | [diff] [blame] | 336 | } |
| 337 | |
rdevlin.cronin | 6f42c252 | 2015-06-19 18:58:51 | [diff] [blame] | 338 | bool 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.cronin | cfa895d | 2015-06-24 23:46:55 | [diff] [blame] | 343 | IPC_MESSAGE_HANDLER(ExtensionHostMsg_IncrementLazyKeepaliveCount, |
| 344 | OnIncrementLazyKeepaliveCount) |
| 345 | IPC_MESSAGE_HANDLER(ExtensionHostMsg_DecrementLazyKeepaliveCount, |
| 346 | OnDecrementLazyKeepaliveCount) |
rdevlin.cronin | 6f42c252 | 2015-06-19 18:58:51 | [diff] [blame] | 347 | IPC_MESSAGE_UNHANDLED(handled = false) |
| 348 | IPC_END_MESSAGE_MAP() |
| 349 | return handled; |
| 350 | } |
| 351 | |
chirantan | 669993c | 2015-03-05 23:38:33 | [diff] [blame] | 352 | void ExtensionHost::OnEventAck(int event_id) { |
[email protected] | b68c07b | 2014-04-16 12:42:36 | [diff] [blame] | 353 | EventRouter* router = EventRouter::Get(browser_context_); |
[email protected] | 7042b68 | 2012-04-19 22:57:51 | [diff] [blame] | 354 | if (router) |
[email protected] | 96e6a103 | 2013-11-28 06:58:03 | [diff] [blame] | 355 | router->OnEventAck(browser_context_, extension_id()); |
chirantan | 79788f6 | 2015-02-02 23:57:25 | [diff] [blame] | 356 | |
chirantan | 669993c | 2015-03-05 23:38:33 | [diff] [blame] | 357 | // 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 |
chirantan | 79788f6 | 2015-02-02 23:57:25 | [diff] [blame] | 366 | // may affect other renderers by causing downstream methods to think that |
chirantan | 669993c | 2015-03-05 23:38:33 | [diff] [blame] | 367 | // 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. |
chirantan | 79788f6 | 2015-02-02 23:57:25 | [diff] [blame] | 369 | // This way if a renderer _is_ compromised, it can really only affect itself. |
chirantan | 669993c | 2015-03-05 23:38:33 | [diff] [blame] | 370 | if (unacked_messages_.erase(event_id) > 0) { |
ericwilligers | d1e2815 | 2016-10-17 22:53:14 | [diff] [blame] | 371 | for (auto& observer : observer_list_) |
| 372 | observer.OnBackgroundEventAcked(this, event_id); |
chirantan | 79788f6 | 2015-02-02 23:57:25 | [diff] [blame] | 373 | } else { |
chirantan | 669993c | 2015-03-05 23:38:33 | [diff] [blame] | 374 | // We have received an unexpected event id from the renderer. It might be |
chirantan | 79788f6 | 2015-02-02 23:57:25 | [diff] [blame] | 375 | // compromised or it might have some other issue. Kill it just to be safe. |
| 376 | DCHECK(render_process_host()); |
chirantan | 669993c | 2015-03-05 23:38:33 | [diff] [blame] | 377 | LOG(ERROR) << "Killing renderer for extension " << extension_id() << " for " |
| 378 | << "sending an EventAck message with a bad event id."; |
jamescook | da250581 | 2015-03-20 18:01:18 | [diff] [blame] | 379 | bad_message::ReceivedBadMessage(render_process_host(), |
| 380 | bad_message::EH_BAD_EVENT_ID); |
chirantan | 79788f6 | 2015-02-02 23:57:25 | [diff] [blame] | 381 | } |
[email protected] | 7042b68 | 2012-04-19 22:57:51 | [diff] [blame] | 382 | } |
| 383 | |
| 384 | void ExtensionHost::OnIncrementLazyKeepaliveCount() { |
reillyg | 0ea3fa90 | 2014-10-28 15:30:23 | [diff] [blame] | 385 | ProcessManager::Get(browser_context_) |
| 386 | ->IncrementLazyKeepaliveCount(extension()); |
[email protected] | 7042b68 | 2012-04-19 22:57:51 | [diff] [blame] | 387 | } |
| 388 | |
| 389 | void ExtensionHost::OnDecrementLazyKeepaliveCount() { |
reillyg | 0ea3fa90 | 2014-10-28 15:30:23 | [diff] [blame] | 390 | ProcessManager::Get(browser_context_) |
| 391 | ->DecrementLazyKeepaliveCount(extension()); |
[email protected] | 7042b68 | 2012-04-19 22:57:51 | [diff] [blame] | 392 | } |
| 393 | |
[email protected] | 45a73d5 | 2013-11-26 00:10:55 | [diff] [blame] | 394 | // content::WebContentsObserver |
[email protected] | 7042b68 | 2012-04-19 22:57:51 | [diff] [blame] | 395 | |
[email protected] | 952a68e | 2011-11-17 00:36:10 | [diff] [blame] | 396 | void ExtensionHost::RenderViewCreated(RenderViewHost* render_view_host) { |
[email protected] | 4f4d42a | 2011-12-02 02:42:49 | [diff] [blame] | 397 | render_view_host_ = render_view_host; |
[email protected] | 6395479 | 2011-07-11 04:17:48 | [diff] [blame] | 398 | } |
| 399 | |
[email protected] | 4f4d42a | 2011-12-02 02:42:49 | [diff] [blame] | 400 | void 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] | 151a63d | 2011-12-20 22:32:52 | [diff] [blame] | 405 | render_view_host_ = host_contents_->GetRenderViewHost(); |
[email protected] | 4f4d42a | 2011-12-02 02:42:49 | [diff] [blame] | 406 | } |
| 407 | |
mathiash | 72a5e46 | 2014-11-19 08:18:50 | [diff] [blame] | 408 | content::JavaScriptDialogManager* ExtensionHost::GetJavaScriptDialogManager( |
| 409 | WebContents* source) { |
[email protected] | 6c0f179f | 2014-03-19 11:04:41 | [diff] [blame] | 410 | return delegate_->GetJavaScriptDialogManager(); |
[email protected] | 6395479 | 2011-07-11 04:17:48 | [diff] [blame] | 411 | } |
| 412 | |
[email protected] | 2a6bc3e | 2011-12-28 23:51:33 | [diff] [blame] | 413 | void ExtensionHost::AddNewContents(WebContents* source, |
| 414 | WebContents* new_contents, |
[email protected] | 952a68e | 2011-11-17 00:36:10 | [diff] [blame] | 415 | WindowOpenDisposition disposition, |
bokan | 107a47f | 2015-02-03 23:23:39 | [diff] [blame] | 416 | const gfx::Rect& initial_rect, |
[email protected] | eda238a1 | 2012-09-07 23:44:00 | [diff] [blame] | 417 | bool user_gesture, |
| 418 | bool* was_blocked) { |
[email protected] | 44d8ce76 | 2010-10-26 21:06:18 | [diff] [blame] | 419 | // 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] | c33f4ac5 | 2011-12-20 00:18:40 | [diff] [blame] | 425 | // Note that we don't do this for popup windows, because we need to associate |
| 426 | // those with their extension_app_id. |
nick | 3b04f32 | 2016-08-31 19:29:19 | [diff] [blame] | 427 | if (disposition != WindowOpenDisposition::NEW_POPUP) { |
[email protected] | ea049a0 | 2011-12-25 21:37:09 | [diff] [blame] | 428 | WebContents* associated_contents = GetAssociatedWebContents(); |
[email protected] | c33f4ac5 | 2011-12-20 00:18:40 | [diff] [blame] | 429 | if (associated_contents && |
[email protected] | 627e051 | 2011-12-21 22:55:30 | [diff] [blame] | 430 | associated_contents->GetBrowserContext() == |
| 431 | new_contents->GetBrowserContext()) { |
[email protected] | eda238a1 | 2012-09-07 23:44:00 | [diff] [blame] | 432 | WebContentsDelegate* delegate = associated_contents->GetDelegate(); |
| 433 | if (delegate) { |
| 434 | delegate->AddNewContents( |
bokan | 107a47f | 2015-02-03 23:23:39 | [diff] [blame] | 435 | associated_contents, new_contents, disposition, initial_rect, |
[email protected] | eda238a1 | 2012-09-07 23:44:00 | [diff] [blame] | 436 | user_gesture, was_blocked); |
[email protected] | a3421eb1 | 2012-11-20 13:47:09 | [diff] [blame] | 437 | return; |
[email protected] | eda238a1 | 2012-09-07 23:44:00 | [diff] [blame] | 438 | } |
[email protected] | c33f4ac5 | 2011-12-20 00:18:40 | [diff] [blame] | 439 | } |
[email protected] | 44d8ce76 | 2010-10-26 21:06:18 | [diff] [blame] | 440 | } |
| 441 | |
[email protected] | 6c0f179f | 2014-03-19 11:04:41 | [diff] [blame] | 442 | delegate_->CreateTab( |
bokan | 107a47f | 2015-02-03 23:23:39 | [diff] [blame] | 443 | new_contents, extension_id_, disposition, initial_rect, user_gesture); |
[email protected] | c6463165 | 2009-04-29 22:24:31 | [diff] [blame] | 444 | } |
[email protected] | 28b3a81 | 2011-11-08 01:03:43 | [diff] [blame] | 445 | |
[email protected] | 952a68e | 2011-11-17 00:36:10 | [diff] [blame] | 446 | void ExtensionHost::RenderViewReady() { |
[email protected] | 8f51a1c8 | 2011-11-09 01:48:24 | [diff] [blame] | 447 | content::NotificationService::current()->Notify( |
[email protected] | adf5a10 | 2014-07-31 12:44:06 | [diff] [blame] | 448 | extensions::NOTIFICATION_EXTENSION_HOST_CREATED, |
[email protected] | 96e6a103 | 2013-11-28 06:58:03 | [diff] [blame] | 449 | content::Source<BrowserContext>(browser_context_), |
[email protected] | 8f51a1c8 | 2011-11-09 01:48:24 | [diff] [blame] | 450 | content::Details<ExtensionHost>(this)); |
| 451 | } |
[email protected] | 3a1dc57 | 2012-07-31 22:25:13 | [diff] [blame] | 452 | |
[email protected] | 0b9383a | 2012-10-26 00:58:16 | [diff] [blame] | 453 | void ExtensionHost::RequestMediaAccessPermission( |
| 454 | content::WebContents* web_contents, |
[email protected] | 33662e5 | 2013-01-07 21:31:09 | [diff] [blame] | 455 | const content::MediaStreamRequest& request, |
[email protected] | 0b9383a | 2012-10-26 00:58:16 | [diff] [blame] | 456 | const content::MediaResponseCallback& callback) { |
[email protected] | 6c0f179f | 2014-03-19 11:04:41 | [diff] [blame] | 457 | delegate_->ProcessMediaAccessRequest( |
[email protected] | eb1a18ce | 2013-04-09 22:28:16 | [diff] [blame] | 458 | web_contents, request, callback, extension()); |
[email protected] | 0b9383a | 2012-10-26 00:58:16 | [diff] [blame] | 459 | } |
| 460 | |
grunell | 657d4d8 | 2014-09-18 00:09:43 | [diff] [blame] | 461 | bool 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] | 7912e82 | 2014-04-16 02:37:03 | [diff] [blame] | 469 | bool 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 | |
kalman | fd474fa | 2015-03-16 22:30:57 | [diff] [blame] | 474 | void 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()); |
kalman | 0f101ac | 2015-05-06 01:23:17 | [diff] [blame] | 487 | UMA_HISTOGRAM_MEDIUM_TIMES("Extensions.PopupCreateTime", |
| 488 | create_start_.Elapsed()); |
kalman | fd474fa | 2015-03-16 22:30:57 | [diff] [blame] | 489 | } |
| 490 | } |
| 491 | |
[email protected] | 3a1dc57 | 2012-07-31 22:25:13 | [diff] [blame] | 492 | } // namespace extensions |