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 |