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