OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/extensions/tab_helper.h" | 5 #include "chrome/browser/extensions/tab_helper.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/strings/string_util.h" | 8 #include "base/strings/string_util.h" |
9 #include "base/strings/utf_string_conversions.h" | 9 #include "base/strings/utf_string_conversions.h" |
10 #include "chrome/browser/chrome_notification_types.h" | 10 #include "chrome/browser/chrome_notification_types.h" |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
65 | 65 |
66 using content::NavigationController; | 66 using content::NavigationController; |
67 using content::NavigationEntry; | 67 using content::NavigationEntry; |
68 using content::RenderViewHost; | 68 using content::RenderViewHost; |
69 using content::WebContents; | 69 using content::WebContents; |
70 | 70 |
71 DEFINE_WEB_CONTENTS_USER_DATA_KEY(extensions::TabHelper); | 71 DEFINE_WEB_CONTENTS_USER_DATA_KEY(extensions::TabHelper); |
72 | 72 |
73 namespace extensions { | 73 namespace extensions { |
74 | 74 |
75 // Encapsulates the logic to decide which ContentRulesRegistries need to be | |
76 // invoked, depending on whether this WebContents is associated with an Original | |
77 // or OffTheRecord profile. In the latter case, we need to invoke on both the | |
78 // Original and OffTheRecord ContentRulesRegistries since the Original registry | |
79 // handles spanning-mode incognito extensions. | |
80 template <class Func> | |
81 void TabHelper::InvokeForContentRulesRegistries(const Func& func) { | |
not at google - send to devlin
2015/06/09 20:38:11
Usually methods are defined in the .cc file in the
Mike Wittman
2015/06/09 22:05:56
I could swear that the template function had to be
| |
82 RulesRegistryService* rules_registry_service = | |
83 RulesRegistryService::Get(profile_); | |
84 if (rules_registry_service) { | |
85 func(rules_registry_service->content_rules_registry()); | |
86 if (profile_->IsOffTheRecord()) { | |
87 // The original profile's content rules registry handles rules for | |
88 // spanning extensions in incognito profiles, so invoke it also. | |
89 RulesRegistryService* original_profile_rules_registry_service = | |
90 RulesRegistryService::Get(profile_->GetOriginalProfile()); | |
91 DCHECK_NE(rules_registry_service, | |
92 original_profile_rules_registry_service); | |
93 if (original_profile_rules_registry_service) | |
94 func(original_profile_rules_registry_service->content_rules_registry()); | |
95 } | |
96 } | |
97 } | |
98 | |
75 TabHelper::TabHelper(content::WebContents* web_contents) | 99 TabHelper::TabHelper(content::WebContents* web_contents) |
76 : content::WebContentsObserver(web_contents), | 100 : content::WebContentsObserver(web_contents), |
101 profile_(Profile::FromBrowserContext(web_contents->GetBrowserContext())), | |
77 extension_app_(NULL), | 102 extension_app_(NULL), |
78 extension_function_dispatcher_( | 103 extension_function_dispatcher_(profile_, this), |
79 Profile::FromBrowserContext(web_contents->GetBrowserContext()), | |
80 this), | |
81 pending_web_app_action_(NONE), | 104 pending_web_app_action_(NONE), |
82 last_committed_nav_entry_unique_id_(0), | 105 last_committed_nav_entry_unique_id_(0), |
83 update_shortcut_on_load_complete_(false), | 106 update_shortcut_on_load_complete_(false), |
84 script_executor_( | 107 script_executor_( |
85 new ScriptExecutor(web_contents, &script_execution_observers_)), | 108 new ScriptExecutor(web_contents, &script_execution_observers_)), |
86 location_bar_controller_(new LocationBarController(web_contents)), | 109 location_bar_controller_(new LocationBarController(web_contents)), |
87 active_script_controller_(new ActiveScriptController(web_contents)), | 110 active_script_controller_(new ActiveScriptController(web_contents)), |
88 webstore_inline_installer_factory_(new WebstoreInlineInstallerFactory()), | 111 webstore_inline_installer_factory_(new WebstoreInlineInstallerFactory()), |
89 image_loader_ptr_factory_(this), | 112 image_loader_ptr_factory_(this), |
90 weak_ptr_factory_(this) { | 113 weak_ptr_factory_(this) { |
91 // The ActiveTabPermissionManager requires a session ID; ensure this | 114 // The ActiveTabPermissionManager requires a session ID; ensure this |
92 // WebContents has one. | 115 // WebContents has one. |
93 SessionTabHelper::CreateForWebContents(web_contents); | 116 SessionTabHelper::CreateForWebContents(web_contents); |
94 if (web_contents->GetRenderViewHost()) | 117 if (web_contents->GetRenderViewHost()) |
95 SetTabId(web_contents->GetRenderViewHost()); | 118 SetTabId(web_contents->GetRenderViewHost()); |
96 active_tab_permission_granter_.reset(new ActiveTabPermissionGranter( | 119 active_tab_permission_granter_.reset(new ActiveTabPermissionGranter( |
97 web_contents, | 120 web_contents, |
98 SessionTabHelper::IdForTab(web_contents), | 121 SessionTabHelper::IdForTab(web_contents), |
99 Profile::FromBrowserContext(web_contents->GetBrowserContext()))); | 122 profile_)); |
100 | |
101 // If more classes need to listen to global content script activity, then | |
102 // a separate routing class with an observer interface should be written. | |
103 profile_ = Profile::FromBrowserContext(web_contents->GetBrowserContext()); | |
104 | 123 |
105 AddScriptExecutionObserver(ActivityLog::GetInstance(profile_)); | 124 AddScriptExecutionObserver(ActivityLog::GetInstance(profile_)); |
106 | 125 |
126 InvokeForContentRulesRegistries([this](ContentRulesRegistry* registry) { | |
127 registry->MonitorWebContentsForRuleEvaluation(this->web_contents()); | |
128 }); | |
129 | |
107 registrar_.Add(this, | 130 registrar_.Add(this, |
108 content::NOTIFICATION_LOAD_STOP, | 131 content::NOTIFICATION_LOAD_STOP, |
109 content::Source<NavigationController>( | 132 content::Source<NavigationController>( |
110 &web_contents->GetController())); | 133 &web_contents->GetController())); |
111 } | 134 } |
112 | 135 |
113 TabHelper::~TabHelper() { | 136 TabHelper::~TabHelper() { |
114 RemoveScriptExecutionObserver(ActivityLog::GetInstance(profile_)); | 137 RemoveScriptExecutionObserver(ActivityLog::GetInstance(profile_)); |
115 } | 138 } |
116 | 139 |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
197 pending_web_app_action_ = NONE; | 220 pending_web_app_action_ = NONE; |
198 } | 221 } |
199 | 222 |
200 void TabHelper::RenderViewCreated(RenderViewHost* render_view_host) { | 223 void TabHelper::RenderViewCreated(RenderViewHost* render_view_host) { |
201 SetTabId(render_view_host); | 224 SetTabId(render_view_host); |
202 } | 225 } |
203 | 226 |
204 void TabHelper::DidNavigateMainFrame( | 227 void TabHelper::DidNavigateMainFrame( |
205 const content::LoadCommittedDetails& details, | 228 const content::LoadCommittedDetails& details, |
206 const content::FrameNavigateParams& params) { | 229 const content::FrameNavigateParams& params) { |
207 RulesRegistryService* rules_registry_service = | 230 InvokeForContentRulesRegistries( |
208 RulesRegistryService::Get(profile_); | 231 [this, &details, ¶ms](ContentRulesRegistry* registry) { |
209 if (rules_registry_service) { | 232 registry->DidNavigateMainFrame(web_contents(), details, params); |
210 rules_registry_service->content_rules_registry()-> | 233 }); |
211 DidNavigateMainFrame(web_contents(), details, params); | |
212 // The original profile's content rules registry handles rules for spanning | |
213 // extensions in incognito profiles, so let it know about the navigation | |
214 // also. | |
215 if (profile_->IsOffTheRecord()) { | |
216 RulesRegistryService* incognito_rules_registry_service = | |
217 RulesRegistryService::Get(profile_->GetOriginalProfile()); | |
218 // The content and web request rules registries depend on separate | |
219 // instances for original/incognito profiles. See the comment on | |
220 // ChromeContentRulesRegistry. | |
221 DCHECK_NE(rules_registry_service, incognito_rules_registry_service); | |
222 if (incognito_rules_registry_service) { | |
223 incognito_rules_registry_service->content_rules_registry()-> | |
224 DidNavigateMainFrame(web_contents(), details, params); | |
225 } | |
226 } | |
227 } | |
228 | 234 |
229 content::BrowserContext* context = web_contents()->GetBrowserContext(); | 235 content::BrowserContext* context = web_contents()->GetBrowserContext(); |
230 ExtensionRegistry* registry = ExtensionRegistry::Get(context); | 236 ExtensionRegistry* registry = ExtensionRegistry::Get(context); |
231 const ExtensionSet& enabled_extensions = registry->enabled_extensions(); | 237 const ExtensionSet& enabled_extensions = registry->enabled_extensions(); |
232 | 238 |
233 if (util::IsNewBookmarkAppsEnabled()) { | 239 if (util::IsNewBookmarkAppsEnabled()) { |
234 Browser* browser = chrome::FindBrowserWithWebContents(web_contents()); | 240 Browser* browser = chrome::FindBrowserWithWebContents(web_contents()); |
235 if (browser && browser->is_app()) { | 241 if (browser && browser->is_app()) { |
236 const Extension* extension = registry->GetExtensionById( | 242 const Extension* extension = registry->GetExtensionById( |
237 web_app::GetExtensionIdFromApplicationName(browser->app_name()), | 243 web_app::GetExtensionIdFromApplicationName(browser->app_name()), |
(...skipping 18 matching lines...) Expand all Loading... | |
256 IPC_BEGIN_MESSAGE_MAP(TabHelper, message) | 262 IPC_BEGIN_MESSAGE_MAP(TabHelper, message) |
257 IPC_MESSAGE_HANDLER(ChromeViewHostMsg_DidGetWebApplicationInfo, | 263 IPC_MESSAGE_HANDLER(ChromeViewHostMsg_DidGetWebApplicationInfo, |
258 OnDidGetWebApplicationInfo) | 264 OnDidGetWebApplicationInfo) |
259 IPC_MESSAGE_HANDLER(ExtensionHostMsg_InlineWebstoreInstall, | 265 IPC_MESSAGE_HANDLER(ExtensionHostMsg_InlineWebstoreInstall, |
260 OnInlineWebstoreInstall) | 266 OnInlineWebstoreInstall) |
261 IPC_MESSAGE_HANDLER(ExtensionHostMsg_GetAppInstallState, | 267 IPC_MESSAGE_HANDLER(ExtensionHostMsg_GetAppInstallState, |
262 OnGetAppInstallState); | 268 OnGetAppInstallState); |
263 IPC_MESSAGE_HANDLER(ExtensionHostMsg_Request, OnRequest) | 269 IPC_MESSAGE_HANDLER(ExtensionHostMsg_Request, OnRequest) |
264 IPC_MESSAGE_HANDLER(ExtensionHostMsg_ContentScriptsExecuting, | 270 IPC_MESSAGE_HANDLER(ExtensionHostMsg_ContentScriptsExecuting, |
265 OnContentScriptsExecuting) | 271 OnContentScriptsExecuting) |
266 IPC_MESSAGE_HANDLER(ExtensionHostMsg_OnWatchedPageChange, | |
267 OnWatchedPageChange) | |
268 IPC_MESSAGE_UNHANDLED(handled = false) | 272 IPC_MESSAGE_UNHANDLED(handled = false) |
269 IPC_END_MESSAGE_MAP() | 273 IPC_END_MESSAGE_MAP() |
270 return handled; | 274 return handled; |
271 } | 275 } |
272 | 276 |
273 bool TabHelper::OnMessageReceived(const IPC::Message& message, | 277 bool TabHelper::OnMessageReceived(const IPC::Message& message, |
274 content::RenderFrameHost* render_frame_host) { | 278 content::RenderFrameHost* render_frame_host) { |
275 bool handled = true; | 279 bool handled = true; |
276 IPC_BEGIN_MESSAGE_MAP(TabHelper, message) | 280 IPC_BEGIN_MESSAGE_MAP(TabHelper, message) |
277 IPC_MESSAGE_HANDLER(ExtensionHostMsg_DetailedConsoleMessageAdded, | 281 IPC_MESSAGE_HANDLER(ExtensionHostMsg_DetailedConsoleMessageAdded, |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
348 // Check that the listener is reasonable. We should never get anything other | 352 // Check that the listener is reasonable. We should never get anything other |
349 // than an install stage listener, a download listener, or both. | 353 // than an install stage listener, a download listener, or both. |
350 if ((listeners_mask & ~(api::webstore::INSTALL_STAGE_LISTENER | | 354 if ((listeners_mask & ~(api::webstore::INSTALL_STAGE_LISTENER | |
351 api::webstore::DOWNLOAD_PROGRESS_LISTENER)) != 0 || | 355 api::webstore::DOWNLOAD_PROGRESS_LISTENER)) != 0 || |
352 requestor_url.is_empty()) { | 356 requestor_url.is_empty()) { |
353 NOTREACHED(); | 357 NOTREACHED(); |
354 return; | 358 return; |
355 } | 359 } |
356 // Inform the Webstore API that an inline install is happening, in case the | 360 // Inform the Webstore API that an inline install is happening, in case the |
357 // page requested status updates. | 361 // page requested status updates. |
358 Profile* profile = | 362 ExtensionRegistry* registry = ExtensionRegistry::Get(profile_); |
359 Profile::FromBrowserContext(web_contents()->GetBrowserContext()); | |
360 | |
361 ExtensionRegistry* registry = ExtensionRegistry::Get(profile); | |
362 if (registry->disabled_extensions().Contains(webstore_item_id) && | 363 if (registry->disabled_extensions().Contains(webstore_item_id) && |
363 (ExtensionPrefs::Get(profile)->GetDisableReasons(webstore_item_id) & | 364 (ExtensionPrefs::Get(profile_)->GetDisableReasons(webstore_item_id) & |
364 Extension::DISABLE_PERMISSIONS_INCREASE) != 0) { | 365 Extension::DISABLE_PERMISSIONS_INCREASE) != 0) { |
365 // The extension was disabled due to permissions increase. Prompt for | 366 // The extension was disabled due to permissions increase. Prompt for |
366 // re-enable. | 367 // re-enable. |
367 // TODO(devlin): We should also prompt for re-enable for other reasons, | 368 // TODO(devlin): We should also prompt for re-enable for other reasons, |
368 // like user-disabled. | 369 // like user-disabled. |
369 // For clarity, explicitly end any prior reenable process. | 370 // For clarity, explicitly end any prior reenable process. |
370 extension_reenabler_.reset(); | 371 extension_reenabler_.reset(); |
371 extension_reenabler_ = ExtensionReenabler::PromptForReenable( | 372 extension_reenabler_ = ExtensionReenabler::PromptForReenable( |
372 registry->disabled_extensions().GetByID(webstore_item_id), | 373 registry->disabled_extensions().GetByID(webstore_item_id), |
373 profile, | 374 profile_, |
374 web_contents(), | 375 web_contents(), |
375 requestor_url, | 376 requestor_url, |
376 base::Bind(&TabHelper::OnReenableComplete, | 377 base::Bind(&TabHelper::OnReenableComplete, |
377 weak_ptr_factory_.GetWeakPtr(), | 378 weak_ptr_factory_.GetWeakPtr(), |
378 install_id, | 379 install_id, |
379 return_route_id)); | 380 return_route_id)); |
380 } else { | 381 } else { |
381 // TODO(devlin): We should adddress the case of the extension already | 382 // TODO(devlin): We should adddress the case of the extension already |
382 // being installed and enabled. | 383 // being installed and enabled. |
383 WebstoreAPI::Get(profile)->OnInlineInstallStart( | 384 WebstoreAPI::Get(profile_)->OnInlineInstallStart( |
384 return_route_id, this, webstore_item_id, listeners_mask); | 385 return_route_id, this, webstore_item_id, listeners_mask); |
385 | 386 |
386 WebstoreStandaloneInstaller::Callback callback = | 387 WebstoreStandaloneInstaller::Callback callback = |
387 base::Bind(&TabHelper::OnInlineInstallComplete, | 388 base::Bind(&TabHelper::OnInlineInstallComplete, |
388 base::Unretained(this), | 389 base::Unretained(this), |
389 install_id, | 390 install_id, |
390 return_route_id); | 391 return_route_id); |
391 scoped_refptr<WebstoreInlineInstaller> installer( | 392 scoped_refptr<WebstoreInlineInstaller> installer( |
392 webstore_inline_installer_factory_->CreateInstaller( | 393 webstore_inline_installer_factory_->CreateInstaller( |
393 web_contents(), | 394 web_contents(), |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
425 | 426 |
426 void TabHelper::OnContentScriptsExecuting( | 427 void TabHelper::OnContentScriptsExecuting( |
427 const ScriptExecutionObserver::ExecutingScriptsMap& executing_scripts_map, | 428 const ScriptExecutionObserver::ExecutingScriptsMap& executing_scripts_map, |
428 const GURL& on_url) { | 429 const GURL& on_url) { |
429 FOR_EACH_OBSERVER( | 430 FOR_EACH_OBSERVER( |
430 ScriptExecutionObserver, | 431 ScriptExecutionObserver, |
431 script_execution_observers_, | 432 script_execution_observers_, |
432 OnScriptsExecuted(web_contents(), executing_scripts_map, on_url)); | 433 OnScriptsExecuted(web_contents(), executing_scripts_map, on_url)); |
433 } | 434 } |
434 | 435 |
435 void TabHelper::OnWatchedPageChange( | |
436 const std::vector<std::string>& css_selectors) { | |
437 if (ExtensionSystem::Get(profile_)->extension_service() && | |
438 RulesRegistryService::Get(profile_)) { | |
439 RulesRegistryService::Get(profile_)->content_rules_registry()->Apply( | |
440 web_contents(), css_selectors); | |
441 } | |
442 } | |
443 | |
444 void TabHelper::OnDetailedConsoleMessageAdded( | 436 void TabHelper::OnDetailedConsoleMessageAdded( |
445 const base::string16& message, | 437 const base::string16& message, |
446 const base::string16& source, | 438 const base::string16& source, |
447 const StackTrace& stack_trace, | 439 const StackTrace& stack_trace, |
448 int32 severity_level) { | 440 int32 severity_level) { |
449 if (IsSourceFromAnExtension(source)) { | 441 if (IsSourceFromAnExtension(source)) { |
450 content::RenderViewHost* rvh = web_contents()->GetRenderViewHost(); | 442 content::RenderViewHost* rvh = web_contents()->GetRenderViewHost(); |
451 ErrorConsole::Get(profile_)->ReportError( | 443 ErrorConsole::Get(profile_)->ReportError( |
452 scoped_ptr<ExtensionError>(new RuntimeError( | 444 scoped_ptr<ExtensionError>(new RuntimeError( |
453 extension_app_ ? extension_app_->id() : std::string(), | 445 extension_app_ ? extension_app_->id() : std::string(), |
(...skipping 18 matching lines...) Expand all Loading... | |
472 extension_app_id); | 464 extension_app_id); |
473 } | 465 } |
474 | 466 |
475 void TabHelper::UpdateExtensionAppIcon(const Extension* extension) { | 467 void TabHelper::UpdateExtensionAppIcon(const Extension* extension) { |
476 extension_app_icon_.reset(); | 468 extension_app_icon_.reset(); |
477 // Ensure previously enqueued callbacks are ignored. | 469 // Ensure previously enqueued callbacks are ignored. |
478 image_loader_ptr_factory_.InvalidateWeakPtrs(); | 470 image_loader_ptr_factory_.InvalidateWeakPtrs(); |
479 | 471 |
480 // Enqueue OnImageLoaded callback. | 472 // Enqueue OnImageLoaded callback. |
481 if (extension) { | 473 if (extension) { |
482 Profile* profile = | 474 ImageLoader* loader = ImageLoader::Get(profile_); |
483 Profile::FromBrowserContext(web_contents()->GetBrowserContext()); | |
484 ImageLoader* loader = ImageLoader::Get(profile); | |
485 loader->LoadImageAsync( | 475 loader->LoadImageAsync( |
486 extension, | 476 extension, |
487 IconsInfo::GetIconResource(extension, | 477 IconsInfo::GetIconResource(extension, |
488 extension_misc::EXTENSION_ICON_SMALL, | 478 extension_misc::EXTENSION_ICON_SMALL, |
489 ExtensionIconSet::MATCH_BIGGER), | 479 ExtensionIconSet::MATCH_BIGGER), |
490 gfx::Size(extension_misc::EXTENSION_ICON_SMALL, | 480 gfx::Size(extension_misc::EXTENSION_ICON_SMALL, |
491 extension_misc::EXTENSION_ICON_SMALL), | 481 extension_misc::EXTENSION_ICON_SMALL), |
492 base::Bind(&TabHelper::OnImageLoaded, | 482 base::Bind(&TabHelper::OnImageLoaded, |
493 image_loader_ptr_factory_.GetWeakPtr())); | 483 image_loader_ptr_factory_.GetWeakPtr())); |
494 } | 484 } |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
594 } | 584 } |
595 } | 585 } |
596 | 586 |
597 void TabHelper::SetTabId(RenderViewHost* render_view_host) { | 587 void TabHelper::SetTabId(RenderViewHost* render_view_host) { |
598 render_view_host->Send( | 588 render_view_host->Send( |
599 new ExtensionMsg_SetTabId(render_view_host->GetRoutingID(), | 589 new ExtensionMsg_SetTabId(render_view_host->GetRoutingID(), |
600 SessionTabHelper::IdForTab(web_contents()))); | 590 SessionTabHelper::IdForTab(web_contents()))); |
601 } | 591 } |
602 | 592 |
603 } // namespace extensions | 593 } // namespace extensions |
OLD | NEW |