blob: d3a0871b1118cc522c47500edc623534fda67993 [file] [log] [blame]
[email protected]39ef0a7c52014-05-11 01:40:001// 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
rdevlin.cronin8408b4f92016-03-15 19:14:145#include "chrome/browser/extensions/extension_action_runner.h"
[email protected]39ef0a7c52014-05-11 01:40:006
dchengc963c7142016-04-08 03:55:227#include <memory>
8
rdevlin.cronin4a78c48b2016-03-24 00:02:299#include "base/auto_reset.h"
[email protected]ac02ac52014-05-20 01:11:2610#include "base/bind.h"
11#include "base/bind_helpers.h"
fdoray283082bd2016-06-02 20:18:4612#include "base/location.h"
asvitkineaa060312016-09-01 22:44:1313#include "base/metrics/histogram_macros.h"
fdoray283082bd2016-06-02 20:18:4614#include "base/single_thread_task_runner.h"
[email protected]39ef0a7c52014-05-11 01:40:0015#include "base/stl_util.h"
fdoray283082bd2016-06-02 20:18:4616#include "base/threading/thread_task_runner_handle.h"
[email protected]78cd68e2014-05-22 20:33:5217#include "chrome/browser/extensions/active_tab_permission_granter.h"
rdevlin.croninaeffd182014-08-26 17:04:0018#include "chrome/browser/extensions/api/extension_action/extension_action_api.h"
[email protected]39ef0a7c52014-05-11 01:40:0019#include "chrome/browser/extensions/extension_action.h"
[email protected]6a24a0392014-08-12 21:31:3320#include "chrome/browser/extensions/extension_action_manager.h"
[email protected]e1670582014-08-15 23:05:4121#include "chrome/browser/extensions/permissions_updater.h"
[email protected]eac223a2014-05-13 17:39:5722#include "chrome/browser/extensions/tab_helper.h"
[email protected]6a24a0392014-08-12 21:31:3323#include "chrome/browser/profiles/profile.h"
[email protected]e3f90c602014-08-18 12:41:5924#include "chrome/browser/sessions/session_tab_helper.h"
rdevlin.cronin4a78c48b2016-03-24 00:02:2925#include "chrome/browser/ui/browser_finder.h"
26#include "chrome/browser/ui/browser_window.h"
27#include "chrome/browser/ui/extensions/blocked_action_bubble_delegate.h"
28#include "chrome/browser/ui/toolbar/toolbar_actions_bar.h"
[email protected]39ef0a7c52014-05-11 01:40:0029#include "chrome/common/extensions/api/extension_action/action_info.h"
[email protected]fdd28372014-08-21 02:27:2630#include "components/crx_file/id_util.h"
[email protected]39ef0a7c52014-05-11 01:40:0031#include "content/public/browser/navigation_controller.h"
32#include "content/public/browser/navigation_entry.h"
jam29737c42017-02-01 16:26:0833#include "content/public/browser/navigation_handle.h"
[email protected]ac02ac52014-05-20 01:11:2634#include "content/public/browser/render_view_host.h"
[email protected]39ef0a7c52014-05-11 01:40:0035#include "content/public/browser/web_contents.h"
36#include "extensions/browser/extension_registry.h"
37#include "extensions/common/extension.h"
38#include "extensions/common/extension_messages.h"
39#include "extensions/common/extension_set.h"
[email protected]23a85362014-07-07 23:26:1940#include "extensions/common/manifest.h"
[email protected]e1670582014-08-15 23:05:4141#include "extensions/common/permissions/permission_set.h"
[email protected]39ef0a7c52014-05-11 01:40:0042#include "extensions/common/permissions/permissions_data.h"
43#include "ipc/ipc_message_macros.h"
44
45namespace extensions {
46
rdevlin.cronin4a78c48b2016-03-24 00:02:2947namespace {
48
49// The blocked actions that require a page refresh to run.
50const int kRefreshRequiredActionsMask =
51 BLOCKED_ACTION_WEB_REQUEST | BLOCKED_ACTION_SCRIPT_AT_START;
52}
53
rdevlin.cronin8408b4f92016-03-15 19:14:1454ExtensionActionRunner::PendingScript::PendingScript(
rdevlin.cronin8d034e52016-02-02 22:46:3255 UserScript::RunLocation run_location,
56 const base::Closure& permit_script)
57 : run_location(run_location), permit_script(permit_script) {}
58
rdevlin.cronin8408b4f92016-03-15 19:14:1459ExtensionActionRunner::PendingScript::PendingScript(
vmpstrb8aacbe2016-02-26 02:00:4860 const PendingScript& other) = default;
61
rdevlin.cronin8408b4f92016-03-15 19:14:1462ExtensionActionRunner::PendingScript::~PendingScript() {}
rdevlin.cronin8d034e52016-02-02 22:46:3263
rdevlin.cronin8408b4f92016-03-15 19:14:1464ExtensionActionRunner::ExtensionActionRunner(content::WebContents* web_contents)
[email protected]39ef0a7c52014-05-11 01:40:0065 : content::WebContentsObserver(web_contents),
rdevlin.cronin1f877032015-02-20 00:12:4266 num_page_requests_(0),
rdevlin.cronin699ca6ff2014-09-29 23:59:5767 browser_context_(web_contents->GetBrowserContext()),
rdevlin.croninb8dffe562015-02-07 00:58:0168 was_used_on_page_(false),
rdevlin.cronin4a78c48b2016-03-24 00:02:2969 ignore_active_tab_granted_(false),
70 extension_registry_observer_(this),
71 weak_factory_(this) {
[email protected]ac02ac52014-05-20 01:11:2672 CHECK(web_contents);
rdevlin.cronin699ca6ff2014-09-29 23:59:5773 extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_));
[email protected]39ef0a7c52014-05-11 01:40:0074}
75
rdevlin.cronin8408b4f92016-03-15 19:14:1476ExtensionActionRunner::~ExtensionActionRunner() {
[email protected]39ef0a7c52014-05-11 01:40:0077 LogUMA();
78}
79
[email protected]eac223a2014-05-13 17:39:5780// static
rdevlin.cronin8408b4f92016-03-15 19:14:1481ExtensionActionRunner* ExtensionActionRunner::GetForWebContents(
[email protected]eac223a2014-05-13 17:39:5782 content::WebContents* web_contents) {
83 if (!web_contents)
84 return NULL;
85 TabHelper* tab_helper = TabHelper::FromWebContents(web_contents);
rdevlin.cronin8408b4f92016-03-15 19:14:1486 return tab_helper ? tab_helper->extension_action_runner() : NULL;
[email protected]eac223a2014-05-13 17:39:5787}
88
rdevlin.cronin343fd102016-03-17 00:24:5489ExtensionAction::ShowAction ExtensionActionRunner::RunAction(
90 const Extension* extension,
91 bool grant_tab_permissions) {
rdevlin.cronin343fd102016-03-17 00:24:5492 if (grant_tab_permissions) {
rdevlin.cronin4a78c48b2016-03-24 00:02:2993 int blocked = GetBlockedActions(extension);
94 if ((blocked & kRefreshRequiredActionsMask) != 0) {
95 ShowBlockedActionBubble(extension);
96 return ExtensionAction::ACTION_NONE;
97 }
rdevlin.cronin343fd102016-03-17 00:24:5498 TabHelper::FromWebContents(web_contents())
99 ->active_tab_permission_granter()
100 ->GrantIfRequested(extension);
101 // If the extension had blocked actions, granting active tab will have
102 // run the extension. Don't execute further since clicking should run
103 // blocked actions *or* the normal extension action, not both.
rdevlin.cronin4a78c48b2016-03-24 00:02:29104 if (blocked != BLOCKED_ACTION_NONE)
rdevlin.cronin343fd102016-03-17 00:24:54105 return ExtensionAction::ACTION_NONE;
106 }
107
108 ExtensionAction* extension_action =
109 ExtensionActionManager::Get(browser_context_)
110 ->GetExtensionAction(*extension);
111
112 // Anything that gets here should have a page or browser action.
113 DCHECK(extension_action);
Mikel Astiz2f127c422018-04-05 19:10:27114 int tab_id = SessionTabHelper::IdForTab(web_contents()).id();
rdevlin.cronin343fd102016-03-17 00:24:54115 if (!extension_action->GetIsVisible(tab_id))
116 return ExtensionAction::ACTION_NONE;
117
118 if (extension_action->HasPopup(tab_id))
119 return ExtensionAction::ACTION_SHOW_POPUP;
120
121 ExtensionActionAPI::Get(browser_context_)
isandrk12962022017-05-04 15:27:33122 ->DispatchExtensionActionClicked(*extension_action, web_contents(),
123 extension);
rdevlin.cronin343fd102016-03-17 00:24:54124 return ExtensionAction::ACTION_NONE;
[email protected]11814f52014-05-23 06:50:35125}
126
rdevlin.cronin343fd102016-03-17 00:24:54127void ExtensionActionRunner::RunBlockedActions(const Extension* extension) {
skyostil32fa6b3f92016-08-12 13:15:43128 DCHECK(base::ContainsKey(pending_scripts_, extension->id()) ||
rdevlin.croninacb745922016-02-17 20:37:44129 web_request_blocked_.count(extension->id()) != 0);
130
131 // Clicking to run the extension counts as granting it permission to run on
132 // the given tab.
133 // The extension may already have active tab at this point, but granting
134 // it twice is essentially a no-op.
135 TabHelper::FromWebContents(web_contents())
136 ->active_tab_permission_granter()
137 ->GrantIfRequested(extension);
138
139 RunPendingScriptsForExtension(extension);
140 web_request_blocked_.erase(extension->id());
141
142 // The extension ran, so we need to tell the ExtensionActionAPI that we no
143 // longer want to act.
144 NotifyChange(extension);
rdevlin.cronine9c71122014-08-25 23:47:21145}
146
rdevlin.cronin343fd102016-03-17 00:24:54147void ExtensionActionRunner::OnActiveTabPermissionGranted(
148 const Extension* extension) {
rdevlin.cronin4a78c48b2016-03-24 00:02:29149 if (!ignore_active_tab_granted_ && WantsToRun(extension))
rdevlin.cronin343fd102016-03-17 00:24:54150 RunBlockedActions(extension);
151}
152
rdevlin.cronin8408b4f92016-03-15 19:14:14153void ExtensionActionRunner::OnWebRequestBlocked(const Extension* extension) {
rdevlin.cronin8d034e52016-02-02 22:46:32154 web_request_blocked_.insert(extension->id());
155}
156
rdevlin.cronin8408b4f92016-03-15 19:14:14157int ExtensionActionRunner::GetBlockedActions(const Extension* extension) {
rdevlin.cronin8d034e52016-02-02 22:46:32158 int blocked_actions = BLOCKED_ACTION_NONE;
159 if (web_request_blocked_.count(extension->id()) != 0)
160 blocked_actions |= BLOCKED_ACTION_WEB_REQUEST;
161 auto iter = pending_scripts_.find(extension->id());
162 if (iter != pending_scripts_.end()) {
163 for (const PendingScript& script : iter->second) {
164 switch (script.run_location) {
165 case UserScript::DOCUMENT_START:
166 blocked_actions |= BLOCKED_ACTION_SCRIPT_AT_START;
167 break;
168 case UserScript::DOCUMENT_END:
169 case UserScript::DOCUMENT_IDLE:
170 case UserScript::BROWSER_DRIVEN:
171 blocked_actions |= BLOCKED_ACTION_SCRIPT_OTHER;
172 break;
173 case UserScript::UNDEFINED:
174 case UserScript::RUN_DEFERRED:
175 case UserScript::RUN_LOCATION_LAST:
176 NOTREACHED();
177 }
178 }
179 }
180
181 return blocked_actions;
182}
183
rdevlin.cronin8408b4f92016-03-15 19:14:14184bool ExtensionActionRunner::WantsToRun(const Extension* extension) {
rdevlin.cronin8d034e52016-02-02 22:46:32185 return GetBlockedActions(extension) != BLOCKED_ACTION_NONE;
[email protected]e1670582014-08-15 23:05:41186}
187
rdevlin.cronin4a78c48b2016-03-24 00:02:29188void ExtensionActionRunner::RunForTesting(const Extension* extension) {
189 if (WantsToRun(extension)) {
190 TabHelper::FromWebContents(web_contents())
191 ->active_tab_permission_granter()
192 ->GrantIfRequested(extension);
193 }
194}
195
Devlin Cronin3e532b82018-05-03 21:27:19196PermissionsData::PageAccess
rdevlin.cronin8408b4f92016-03-15 19:14:14197ExtensionActionRunner::RequiresUserConsentForScriptInjection(
[email protected]23a85362014-07-07 23:26:19198 const Extension* extension,
199 UserScript::InjectionType type) {
200 CHECK(extension);
201
[email protected]23a85362014-07-07 23:26:19202 // Allow the extension if it's been explicitly granted permission.
203 if (permitted_extensions_.count(extension->id()) > 0)
Devlin Cronin3e532b82018-05-03 21:27:19204 return PermissionsData::PageAccess::kAllowed;
[email protected]23a85362014-07-07 23:26:19205
206 GURL url = web_contents()->GetVisibleURL();
Mikel Astiz2f127c422018-04-05 19:10:27207 int tab_id = SessionTabHelper::IdForTab(web_contents()).id();
[email protected]23a85362014-07-07 23:26:19208 switch (type) {
209 case UserScript::CONTENT_SCRIPT:
210 return extension->permissions_data()->GetContentScriptAccess(
rob889ceeb2016-01-25 19:41:08211 extension, url, tab_id, nullptr);
[email protected]23a85362014-07-07 23:26:19212 case UserScript::PROGRAMMATIC_SCRIPT:
rob889ceeb2016-01-25 19:41:08213 return extension->permissions_data()->GetPageAccess(extension, url,
214 tab_id, nullptr);
[email protected]23a85362014-07-07 23:26:19215 }
216
217 NOTREACHED();
Devlin Cronin3e532b82018-05-03 21:27:19218 return PermissionsData::PageAccess::kDenied;
[email protected]23a85362014-07-07 23:26:19219}
220
rdevlin.cronin8408b4f92016-03-15 19:14:14221void ExtensionActionRunner::RequestScriptInjection(
[email protected]23a85362014-07-07 23:26:19222 const Extension* extension,
rdevlin.cronin8d034e52016-02-02 22:46:32223 UserScript::RunLocation run_location,
[email protected]23a85362014-07-07 23:26:19224 const base::Closure& callback) {
225 CHECK(extension);
rdevlin.cronin8d034e52016-02-02 22:46:32226 PendingScriptList& list = pending_scripts_[extension->id()];
227 list.push_back(PendingScript(run_location, callback));
[email protected]23a85362014-07-07 23:26:19228
rdevlin.cronin699ca6ff2014-09-29 23:59:57229 // If this was the first entry, we need to notify that a new extension wants
230 // to run.
231 if (list.size() == 1u)
232 NotifyChange(extension);
rdevlin.croninb8dffe562015-02-07 00:58:01233
234 was_used_on_page_ = true;
[email protected]23a85362014-07-07 23:26:19235}
236
rdevlin.cronin8408b4f92016-03-15 19:14:14237void ExtensionActionRunner::RunPendingScriptsForExtension(
[email protected]11814f52014-05-23 06:50:35238 const Extension* extension) {
[email protected]ac02ac52014-05-20 01:11:26239 DCHECK(extension);
[email protected]ac02ac52014-05-20 01:11:26240
241 content::NavigationEntry* visible_entry =
242 web_contents()->GetController().GetVisibleEntry();
243 // Refuse to run if there's no visible entry, because we have no idea of
244 // determining if it's the proper page. This should rarely, if ever, happen.
245 if (!visible_entry)
[email protected]11814f52014-05-23 06:50:35246 return;
[email protected]ac02ac52014-05-20 01:11:26247
[email protected]ac02ac52014-05-20 01:11:26248 // We add this to the list of permitted extensions and erase pending entries
249 // *before* running them to guard against the crazy case where running the
250 // callbacks adds more entries.
251 permitted_extensions_.insert(extension->id());
[email protected]23a85362014-07-07 23:26:19252
rdevlin.cronin8d034e52016-02-02 22:46:32253 PendingScriptMap::iterator iter = pending_scripts_.find(extension->id());
254 if (iter == pending_scripts_.end())
[email protected]23a85362014-07-07 23:26:19255 return;
256
rdevlin.cronin8d034e52016-02-02 22:46:32257 PendingScriptList scripts;
258 iter->second.swap(scripts);
259 pending_scripts_.erase(extension->id());
[email protected]ac02ac52014-05-20 01:11:26260
261 // Run all pending injections for the given extension.
rdevlin.cronin8d034e52016-02-02 22:46:32262 for (PendingScript& pending_script : scripts)
263 pending_script.permit_script.Run();
[email protected]ac02ac52014-05-20 01:11:26264}
265
rdevlin.cronin8408b4f92016-03-15 19:14:14266void ExtensionActionRunner::OnRequestScriptInjectionPermission(
[email protected]ac02ac52014-05-20 01:11:26267 const std::string& extension_id,
[email protected]23a85362014-07-07 23:26:19268 UserScript::InjectionType script_type,
rdevlin.cronin8d034e52016-02-02 22:46:32269 UserScript::RunLocation run_location,
avia2f4804a2015-12-24 23:11:13270 int64_t request_id) {
[email protected]fdd28372014-08-21 02:27:26271 if (!crx_file::id_util::IdIsValid(extension_id)) {
[email protected]ac02ac52014-05-20 01:11:26272 NOTREACHED() << "'" << extension_id << "' is not a valid id.";
273 return;
274 }
275
rdevlin.cronin8408b4f92016-03-15 19:14:14276 const Extension* extension = ExtensionRegistry::Get(browser_context_)
277 ->enabled_extensions()
278 .GetByID(extension_id);
[email protected]ac02ac52014-05-20 01:11:26279 // We shouldn't allow extensions which are no longer enabled to run any
280 // scripts. Ignore the request.
281 if (!extension)
282 return;
283
rdevlin.cronin1f877032015-02-20 00:12:42284 ++num_page_requests_;
285
[email protected]23a85362014-07-07 23:26:19286 switch (RequiresUserConsentForScriptInjection(extension, script_type)) {
Devlin Cronin3e532b82018-05-03 21:27:19287 case PermissionsData::PageAccess::kAllowed:
[email protected]23a85362014-07-07 23:26:19288 PermitScriptInjection(request_id);
289 break;
Devlin Cronin3e532b82018-05-03 21:27:19290 case PermissionsData::PageAccess::kWithheld:
[email protected]23a85362014-07-07 23:26:19291 // This base::Unretained() is safe, because the callback is only invoked
292 // by this object.
293 RequestScriptInjection(
rdevlin.cronin8d034e52016-02-02 22:46:32294 extension, run_location,
rdevlin.cronin8408b4f92016-03-15 19:14:14295 base::Bind(&ExtensionActionRunner::PermitScriptInjection,
rdevlin.cronin8d034e52016-02-02 22:46:32296 base::Unretained(this), request_id));
[email protected]23a85362014-07-07 23:26:19297 break;
Devlin Cronin3e532b82018-05-03 21:27:19298 case PermissionsData::PageAccess::kDenied:
[email protected]23a85362014-07-07 23:26:19299 // We should usually only get a "deny access" if the page changed (as the
300 // renderer wouldn't have requested permission if the answer was always
301 // "no"). Just let the request fizzle and die.
302 break;
[email protected]0d8d6972014-06-03 22:41:02303 }
304}
305
rdevlin.cronin8408b4f92016-03-15 19:14:14306void ExtensionActionRunner::PermitScriptInjection(int64_t request_id) {
[email protected]23a85362014-07-07 23:26:19307 // This only sends the response to the renderer - the process of adding the
308 // extension to the list of |permitted_extensions_| is done elsewhere.
rdevlin.cronin4bb32d72015-06-02 21:55:01309 // TODO(devlin): Instead of sending this to all frames, we should include the
310 // routing_id in the permission request message, and send only to the proper
311 // frame (sending it to all frames doesn't hurt, but isn't as efficient).
312 web_contents()->SendToAllFrames(new ExtensionMsg_PermitScriptInjection(
313 MSG_ROUTING_NONE, // Routing id is set by the |web_contents|.
314 request_id));
[email protected]39ef0a7c52014-05-11 01:40:00315}
316
rdevlin.cronin8408b4f92016-03-15 19:14:14317void ExtensionActionRunner::NotifyChange(const Extension* extension) {
rdevlin.cronin699ca6ff2014-09-29 23:59:57318 ExtensionActionAPI* extension_action_api =
319 ExtensionActionAPI::Get(browser_context_);
320 ExtensionAction* extension_action =
rdevlin.cronin8408b4f92016-03-15 19:14:14321 ExtensionActionManager::Get(browser_context_)
322 ->GetExtensionAction(*extension);
rdevlin.cronin699ca6ff2014-09-29 23:59:57323 // If the extension has an action, we need to notify that it's updated.
324 if (extension_action) {
rdevlin.cronin8408b4f92016-03-15 19:14:14325 extension_action_api->NotifyChange(extension_action, web_contents(),
326 browser_context_);
rdevlin.cronin699ca6ff2014-09-29 23:59:57327 }
328
329 // We also notify that page actions may have changed.
330 extension_action_api->NotifyPageActionsChanged(web_contents());
331}
332
rdevlin.cronin8408b4f92016-03-15 19:14:14333void ExtensionActionRunner::LogUMA() const {
rdevlin.croninb8dffe562015-02-07 00:58:01334 // We only log the permitted extensions metric if the feature was used at all
335 // on the page, because otherwise the data will be boring.
336 if (was_used_on_page_) {
[email protected]ac02ac52014-05-20 01:11:26337 UMA_HISTOGRAM_COUNTS_100(
338 "Extensions.ActiveScriptController.PermittedExtensions",
339 permitted_extensions_.size());
340 UMA_HISTOGRAM_COUNTS_100(
341 "Extensions.ActiveScriptController.DeniedExtensions",
rdevlin.cronin8d034e52016-02-02 22:46:32342 pending_scripts_.size());
[email protected]ac02ac52014-05-20 01:11:26343 }
[email protected]39ef0a7c52014-05-11 01:40:00344}
345
rdevlin.cronin4a78c48b2016-03-24 00:02:29346void ExtensionActionRunner::ShowBlockedActionBubble(
347 const Extension* extension) {
348 Browser* browser = chrome::FindBrowserWithWebContents(web_contents());
349 ToolbarActionsBar* toolbar_actions_bar =
350 browser ? browser->window()->GetToolbarActionsBar() : nullptr;
351 if (toolbar_actions_bar) {
352 auto callback =
353 base::Bind(&ExtensionActionRunner::OnBlockedActionBubbleClosed,
354 weak_factory_.GetWeakPtr(), extension->id());
355 if (default_bubble_close_action_for_testing_) {
fdoray283082bd2016-06-02 20:18:46356 base::ThreadTaskRunnerHandle::Get()->PostTask(
rdevlin.cronin4a78c48b2016-03-24 00:02:29357 FROM_HERE,
tzik8d880ee2017-04-20 19:46:24358 base::BindOnce(callback, *default_bubble_close_action_for_testing_));
rdevlin.cronin4a78c48b2016-03-24 00:02:29359 } else {
ricea91d6fc122016-08-30 08:47:14360 toolbar_actions_bar->ShowToolbarActionBubble(
Jinho Bangb5216cec2018-01-17 19:43:11361 std::make_unique<BlockedActionBubbleDelegate>(callback,
ricea91d6fc122016-08-30 08:47:14362 extension->id()));
rdevlin.cronin4a78c48b2016-03-24 00:02:29363 }
364 }
365}
366
367void ExtensionActionRunner::OnBlockedActionBubbleClosed(
368 const std::string& extension_id,
369 ToolbarActionsBarBubbleDelegate::CloseAction action) {
370 // If the user agreed to refresh the page, do so.
371 if (action == ToolbarActionsBarBubbleDelegate::CLOSE_EXECUTE) {
372 const Extension* extension = ExtensionRegistry::Get(browser_context_)
373 ->enabled_extensions()
374 .GetByID(extension_id);
375 if (!extension)
376 return;
377 {
378 // Ignore the active tab permission being granted because we don't want
379 // to run scripts right before we refresh the page.
380 base::AutoReset<bool> ignore_active_tab(&ignore_active_tab_granted_,
381 true);
382 TabHelper::FromWebContents(web_contents())
383 ->active_tab_permission_granter()
384 ->GrantIfRequested(extension);
385 }
toyoshim6142d96f2016-12-19 09:07:25386 web_contents()->GetController().Reload(content::ReloadType::NORMAL, false);
rdevlin.cronin4a78c48b2016-03-24 00:02:29387 }
388}
389
rdevlin.cronin8408b4f92016-03-15 19:14:14390bool ExtensionActionRunner::OnMessageReceived(
rdevlin.cronin45dca7f2015-06-08 19:47:03391 const IPC::Message& message,
392 content::RenderFrameHost* render_frame_host) {
rdevlin.cronin6e7e5edc2014-08-29 16:23:23393 bool handled = true;
rdevlin.cronin8408b4f92016-03-15 19:14:14394 IPC_BEGIN_MESSAGE_MAP(ExtensionActionRunner, message)
rdevlin.cronin6e7e5edc2014-08-29 16:23:23395 IPC_MESSAGE_HANDLER(ExtensionHostMsg_RequestScriptInjectionPermission,
396 OnRequestScriptInjectionPermission)
397 IPC_MESSAGE_UNHANDLED(handled = false)
398 IPC_END_MESSAGE_MAP()
399 return handled;
400}
401
jam29737c42017-02-01 16:26:08402void ExtensionActionRunner::DidFinishNavigation(
403 content::NavigationHandle* navigation_handle) {
404 if (!navigation_handle->IsInMainFrame() ||
405 !navigation_handle->HasCommitted() ||
eugenebuta11672fb2017-03-07 17:13:51406 navigation_handle->IsSameDocument()) {
rdevlin.cronin50942232014-08-27 17:40:56407 return;
jam29737c42017-02-01 16:26:08408 }
rdevlin.cronin50942232014-08-27 17:40:56409
410 LogUMA();
rdevlin.cronin1f877032015-02-20 00:12:42411 num_page_requests_ = 0;
rdevlin.cronin50942232014-08-27 17:40:56412 permitted_extensions_.clear();
rdevlin.cronin8d034e52016-02-02 22:46:32413 pending_scripts_.clear();
414 web_request_blocked_.clear();
rdevlin.croninb8dffe562015-02-07 00:58:01415 was_used_on_page_ = false;
rdevlin.cronin4a78c48b2016-03-24 00:02:29416 weak_factory_.InvalidateWeakPtrs();
rdevlin.cronin50942232014-08-27 17:40:56417}
418
rdevlin.cronin8408b4f92016-03-15 19:14:14419void ExtensionActionRunner::OnExtensionUnloaded(
rdevlin.cronin6e7e5edc2014-08-29 16:23:23420 content::BrowserContext* browser_context,
421 const Extension* extension,
limasdf0deef2042017-05-03 19:17:17422 UnloadedExtensionReason reason) {
rdevlin.cronin8d034e52016-02-02 22:46:32423 PendingScriptMap::iterator iter = pending_scripts_.find(extension->id());
424 if (iter != pending_scripts_.end()) {
425 pending_scripts_.erase(iter);
rdevlin.cronin8408b4f92016-03-15 19:14:14426 ExtensionActionAPI::Get(browser_context_)
427 ->NotifyPageActionsChanged(web_contents());
rdevlin.cronin6e7e5edc2014-08-29 16:23:23428 }
429}
430
[email protected]39ef0a7c52014-05-11 01:40:00431} // namespace extensions