Chromium Code Reviews| 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 |