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
3 // found in the LICENSE file.
5 #include "chrome/browser/extensions/tab_helper.h"
7 #include "base/logging.h"
8 #include "base/strings/string_util.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "chrome/browser/chrome_notification_types.h"
11 #include "chrome/browser/extensions/activity_log/activity_log.h"
12 #include "chrome/browser/extensions/api/declarative/rules_registry_service.h"
13 #include "chrome/browser/extensions/api/declarative_content/content_rules_registry.h"
14 #include "chrome/browser/extensions/crx_installer.h"
15 #include "chrome/browser/extensions/error_console/error_console.h"
16 #include "chrome/browser/extensions/extension_action.h"
17 #include "chrome/browser/extensions/extension_action_manager.h"
18 #include "chrome/browser/extensions/extension_service.h"
19 #include "chrome/browser/extensions/extension_system.h"
20 #include "chrome/browser/extensions/extension_tab_util.h"
21 #include "chrome/browser/extensions/favicon_downloader.h"
22 #include "chrome/browser/extensions/image_loader.h"
23 #include "chrome/browser/extensions/page_action_controller.h"
24 #include "chrome/browser/extensions/script_badge_controller.h"
25 #include "chrome/browser/extensions/script_bubble_controller.h"
26 #include "chrome/browser/extensions/script_executor.h"
27 #include "chrome/browser/extensions/webstore_inline_installer.h"
28 #include "chrome/browser/extensions/webstore_inline_installer_factory.h"
29 #include "chrome/browser/profiles/profile.h"
30 #include "chrome/browser/sessions/session_id.h"
31 #include "chrome/browser/sessions/session_tab_helper.h"
32 #include "chrome/browser/shell_integration.h"
33 #include "chrome/browser/ui/app_list/app_list_service.h"
34 #include "chrome/browser/ui/app_list/app_list_util.h"
35 #include "chrome/browser/ui/browser_commands.h"
36 #include "chrome/browser/ui/browser_dialogs.h"
37 #include "chrome/browser/ui/browser_finder.h"
38 #include "chrome/browser/ui/host_desktop.h"
39 #include "chrome/browser/ui/web_applications/web_app_ui.h"
40 #include "chrome/browser/web_applications/web_app.h"
41 #include "chrome/common/extensions/extension_constants.h"
42 #include "chrome/common/extensions/extension_icon_set.h"
43 #include "chrome/common/extensions/extension_messages.h"
44 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
45 #include "chrome/common/extensions/manifest_handlers/icons_handler.h"
46 #include "chrome/common/render_messages.h"
47 #include "chrome/common/url_constants.h"
48 #include "content/public/browser/invalidate_type.h"
49 #include "content/public/browser/navigation_controller.h"
50 #include "content/public/browser/navigation_details.h"
51 #include "content/public/browser/navigation_entry.h"
52 #include "content/public/browser/notification_service.h"
53 #include "content/public/browser/notification_source.h"
54 #include "content/public/browser/notification_types.h"
55 #include "content/public/browser/render_process_host.h"
56 #include "content/public/browser/render_view_host.h"
57 #include "content/public/browser/render_widget_host_view.h"
58 #include "content/public/browser/web_contents.h"
59 #include "content/public/browser/web_contents_view.h"
60 #include "content/public/common/frame_navigate_params.h"
61 #include "extensions/browser/extension_error.h"
62 #include "extensions/common/extension.h"
63 #include "extensions/common/extension_resource.h"
64 #include "extensions/common/extension_urls.h"
65 #include "extensions/common/feature_switch.h"
66 #include "skia/ext/image_operations.h"
67 #include "ui/gfx/image/image.h"
69 using content::NavigationController
;
70 using content::NavigationEntry
;
71 using content::RenderViewHost
;
72 using content::WebContents
;
74 DEFINE_WEB_CONTENTS_USER_DATA_KEY(extensions::TabHelper
);
76 namespace extensions
{
78 TabHelper::ScriptExecutionObserver::ScriptExecutionObserver(
79 TabHelper
* tab_helper
)
80 : tab_helper_(tab_helper
) {
81 tab_helper_
->AddScriptExecutionObserver(this);
84 TabHelper::ScriptExecutionObserver::ScriptExecutionObserver()
88 TabHelper::ScriptExecutionObserver::~ScriptExecutionObserver() {
90 tab_helper_
->RemoveScriptExecutionObserver(this);
94 std::vector
<SkBitmap
> TabHelper::ConstrainBitmapsToSizes(
95 const std::vector
<SkBitmap
>& bitmaps
,
96 const std::set
<int>& sizes
) {
97 std::vector
<SkBitmap
> output_bitmaps
;
98 std::map
<int, SkBitmap
> ordered_bitmaps
;
99 for (std::vector
<SkBitmap
>::const_iterator it
= bitmaps
.begin();
100 it
!= bitmaps
.end(); ++it
) {
101 DCHECK(it
->width() == it
->height());
102 ordered_bitmaps
[it
->width()] = *it
;
105 std::set
<int>::const_iterator sizes_it
= sizes
.begin();
106 std::map
<int, SkBitmap
>::const_iterator bitmaps_it
= ordered_bitmaps
.begin();
107 while (sizes_it
!= sizes
.end() && bitmaps_it
!= ordered_bitmaps
.end()) {
108 int size
= *sizes_it
;
109 // Find the closest not-smaller bitmap.
110 bitmaps_it
= ordered_bitmaps
.lower_bound(size
);
112 // Ensure the bitmap is valid and smaller than the next allowed size.
113 if (bitmaps_it
!= ordered_bitmaps
.end() &&
114 (sizes_it
== sizes
.end() || bitmaps_it
->second
.width() < *sizes_it
)) {
115 // Resize the bitmap if it does not exactly match the desired size.
116 output_bitmaps
.push_back(bitmaps_it
->second
.width() == size
118 : skia::ImageOperations::Resize(
119 bitmaps_it
->second
, skia::ImageOperations::RESIZE_LANCZOS3
,
123 return output_bitmaps
;
126 TabHelper::TabHelper(content::WebContents
* web_contents
)
127 : content::WebContentsObserver(web_contents
),
128 extension_app_(NULL
),
129 extension_function_dispatcher_(
130 Profile::FromBrowserContext(web_contents
->GetBrowserContext()), this),
131 pending_web_app_action_(NONE
),
132 script_executor_(new ScriptExecutor(web_contents
,
133 &script_execution_observers_
)),
134 image_loader_ptr_factory_(this),
135 webstore_inline_installer_factory_(new WebstoreInlineInstallerFactory()) {
136 // The ActiveTabPermissionManager requires a session ID; ensure this
137 // WebContents has one.
138 SessionTabHelper::CreateForWebContents(web_contents
);
139 if (web_contents
->GetRenderViewHost())
140 SetTabId(web_contents
->GetRenderViewHost());
141 active_tab_permission_granter_
.reset(new ActiveTabPermissionGranter(
143 SessionID::IdForTab(web_contents
),
144 Profile::FromBrowserContext(web_contents
->GetBrowserContext())));
145 if (FeatureSwitch::script_badges()->IsEnabled()) {
146 location_bar_controller_
.reset(
147 new ScriptBadgeController(web_contents
, this));
149 location_bar_controller_
.reset(
150 new PageActionController(web_contents
));
153 if (FeatureSwitch::script_bubble()->IsEnabled()) {
154 script_bubble_controller_
.reset(
155 new ScriptBubbleController(web_contents
, this));
158 // If more classes need to listen to global content script activity, then
159 // a separate routing class with an observer interface should be written.
160 profile_
= Profile::FromBrowserContext(web_contents
->GetBrowserContext());
162 #if defined(ENABLE_EXTENSIONS)
163 AddScriptExecutionObserver(ActivityLog::GetInstance(profile_
));
167 content::NOTIFICATION_LOAD_STOP
,
168 content::Source
<NavigationController
>(
169 &web_contents
->GetController()));
172 chrome::NOTIFICATION_CRX_INSTALLER_DONE
,
173 content::Source
<CrxInstaller
>(NULL
));
176 chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR
,
177 content::NotificationService::AllSources());
180 chrome::NOTIFICATION_EXTENSION_UNLOADED
,
181 content::NotificationService::AllSources());
184 TabHelper::~TabHelper() {
185 #if defined(ENABLE_EXTENSIONS)
186 RemoveScriptExecutionObserver(ActivityLog::GetInstance(profile_
));
190 void TabHelper::CreateApplicationShortcuts() {
191 DCHECK(CanCreateApplicationShortcuts());
192 NavigationEntry
* entry
=
193 web_contents()->GetController().GetLastCommittedEntry();
197 pending_web_app_action_
= CREATE_SHORTCUT
;
199 // Start fetching web app info for CreateApplicationShortcut dialog and show
200 // the dialog when the data is available in OnDidGetApplicationInfo.
201 GetApplicationInfo(entry
->GetPageID());
204 void TabHelper::CreateHostedAppFromWebContents() {
205 DCHECK(CanCreateApplicationShortcuts());
206 NavigationEntry
* entry
=
207 web_contents()->GetController().GetLastCommittedEntry();
211 pending_web_app_action_
= CREATE_HOSTED_APP
;
213 // Start fetching web app info for CreateApplicationShortcut dialog and show
214 // the dialog when the data is available in OnDidGetApplicationInfo.
215 GetApplicationInfo(entry
->GetPageID());
218 bool TabHelper::CanCreateApplicationShortcuts() const {
219 #if defined(OS_MACOSX)
222 return web_app::IsValidUrl(web_contents()->GetURL()) &&
223 pending_web_app_action_
== NONE
;
227 void TabHelper::SetExtensionApp(const Extension
* extension
) {
228 DCHECK(!extension
|| AppLaunchInfo::GetFullLaunchURL(extension
).is_valid());
229 extension_app_
= extension
;
231 UpdateExtensionAppIcon(extension_app_
);
233 content::NotificationService::current()->Notify(
234 chrome::NOTIFICATION_TAB_CONTENTS_APPLICATION_EXTENSION_CHANGED
,
235 content::Source
<TabHelper
>(this),
236 content::NotificationService::NoDetails());
239 void TabHelper::SetExtensionAppById(const std::string
& extension_app_id
) {
240 const Extension
* extension
= GetExtension(extension_app_id
);
242 SetExtensionApp(extension
);
245 void TabHelper::SetExtensionAppIconById(const std::string
& extension_app_id
) {
246 const Extension
* extension
= GetExtension(extension_app_id
);
248 UpdateExtensionAppIcon(extension
);
251 SkBitmap
* TabHelper::GetExtensionAppIcon() {
252 if (extension_app_icon_
.empty())
255 return &extension_app_icon_
;
258 void TabHelper::RenderViewCreated(RenderViewHost
* render_view_host
) {
259 SetTabId(render_view_host
);
262 void TabHelper::DidNavigateMainFrame(
263 const content::LoadCommittedDetails
& details
,
264 const content::FrameNavigateParams
& params
) {
265 #if defined(ENABLE_EXTENSIONS)
266 if (ExtensionSystem::Get(profile_
)->extension_service() &&
267 RulesRegistryService::Get(profile_
)) {
268 RulesRegistryService::Get(profile_
)->content_rules_registry()->
269 DidNavigateMainFrame(web_contents(), details
, params
);
271 #endif // defined(ENABLE_EXTENSIONS)
274 Profile::FromBrowserContext(web_contents()->GetBrowserContext());
275 ExtensionService
* service
= profile
->GetExtensionService();
279 UpdateExtensionAppIcon(service
->GetInstalledExtensionByUrl(params
.url
));
281 if (details
.is_in_page
)
284 ExtensionActionManager
* extension_action_manager
=
285 ExtensionActionManager::Get(profile
);
286 for (ExtensionSet::const_iterator it
= service
->extensions()->begin();
287 it
!= service
->extensions()->end(); ++it
) {
288 ExtensionAction
* browser_action
=
289 extension_action_manager
->GetBrowserAction(*it
->get());
290 if (browser_action
) {
291 browser_action
->ClearAllValuesForTab(SessionID::IdForTab(web_contents()));
292 content::NotificationService::current()->Notify(
293 chrome::NOTIFICATION_EXTENSION_BROWSER_ACTION_UPDATED
,
294 content::Source
<ExtensionAction
>(browser_action
),
295 content::NotificationService::NoDetails());
300 bool TabHelper::OnMessageReceived(const IPC::Message
& message
) {
302 IPC_BEGIN_MESSAGE_MAP(TabHelper
, message
)
303 IPC_MESSAGE_HANDLER(ExtensionHostMsg_DidGetApplicationInfo
,
304 OnDidGetApplicationInfo
)
305 IPC_MESSAGE_HANDLER(ExtensionHostMsg_InlineWebstoreInstall
,
306 OnInlineWebstoreInstall
)
307 IPC_MESSAGE_HANDLER(ExtensionHostMsg_GetAppInstallState
,
308 OnGetAppInstallState
);
309 IPC_MESSAGE_HANDLER(ExtensionHostMsg_Request
, OnRequest
)
310 IPC_MESSAGE_HANDLER(ExtensionHostMsg_ContentScriptsExecuting
,
311 OnContentScriptsExecuting
)
312 IPC_MESSAGE_HANDLER(ExtensionHostMsg_OnWatchedPageChange
,
314 IPC_MESSAGE_HANDLER(ChromeViewHostMsg_DetailedConsoleMessageAdded
,
315 OnDetailedConsoleMessageAdded
)
316 IPC_MESSAGE_UNHANDLED(handled
= false)
317 IPC_END_MESSAGE_MAP()
321 void TabHelper::CreateHostedApp() {
322 // Add urls from the WebApplicationInfo.
323 std::vector
<GURL
> web_app_info_icon_urls
;
324 for (std::vector
<WebApplicationInfo::IconInfo
>::const_iterator it
=
325 web_app_info_
.icons
.begin();
326 it
!= web_app_info_
.icons
.end(); ++it
) {
327 if (it
->url
.is_valid())
328 web_app_info_icon_urls
.push_back(it
->url
);
331 favicon_downloader_
.reset(
332 new FaviconDownloader(web_contents(),
333 web_app_info_icon_urls
,
334 base::Bind(&TabHelper::FinishCreateHostedApp
,
335 base::Unretained(this))));
336 favicon_downloader_
->Start();
339 void TabHelper::FinishCreateHostedApp(
341 const std::map
<GURL
, std::vector
<SkBitmap
> >& bitmaps
) {
342 // The tab has navigated away during the icon download. Cancel the hosted app
345 favicon_downloader_
.reset();
349 WebApplicationInfo
install_info(web_app_info_
);
350 if (install_info
.app_url
.is_empty())
351 install_info
.app_url
= web_contents()->GetURL();
353 if (install_info
.title
.empty())
354 install_info
.title
= web_contents()->GetTitle();
355 if (install_info
.title
.empty())
356 install_info
.title
= base::UTF8ToUTF16(install_info
.app_url
.spec());
358 install_info
.urls
.push_back(install_info
.app_url
);
359 install_info
.is_bookmark_app
= true;
361 // Add the downloaded icons. Extensions only allow certain icon sizes. First
362 // populate icons that match the allowed sizes exactly and then downscale
363 // remaining icons to the closest allowed size that doesn't yet have an icon.
364 std::set
<int> allowed_sizes(
365 extension_misc::kExtensionIconSizes
,
366 extension_misc::kExtensionIconSizes
+
367 extension_misc::kNumExtensionIconSizes
);
368 std::vector
<SkBitmap
> downloaded_icons
;
369 for (FaviconDownloader::FaviconMap::const_iterator map_it
= bitmaps
.begin();
370 map_it
!= bitmaps
.end(); ++map_it
) {
371 for (std::vector
<SkBitmap
>::const_iterator bitmap_it
=
372 map_it
->second
.begin();
373 bitmap_it
!= map_it
->second
.end(); ++bitmap_it
) {
374 if (bitmap_it
->empty() || bitmap_it
->width() != bitmap_it
->height())
377 downloaded_icons
.push_back(*bitmap_it
);
381 // If there are icons that don't match the accepted icon sizes, find the
382 // closest bigger icon to the accepted sizes and resize the icon to it. An
383 // icon will be resized and used for at most one size.
384 std::vector
<SkBitmap
> resized_bitmaps(
385 TabHelper::ConstrainBitmapsToSizes(downloaded_icons
,
387 for (std::vector
<SkBitmap
>::const_iterator resized_bitmaps_it
=
388 resized_bitmaps
.begin();
389 resized_bitmaps_it
!= resized_bitmaps
.end(); ++resized_bitmaps_it
) {
390 WebApplicationInfo::IconInfo icon_info
;
391 icon_info
.data
= *resized_bitmaps_it
;
392 icon_info
.width
= icon_info
.data
.width();
393 icon_info
.height
= icon_info
.data
.height();
394 install_info
.icons
.push_back(icon_info
);
398 Profile::FromBrowserContext(web_contents()->GetBrowserContext());
399 scoped_refptr
<extensions::CrxInstaller
> installer(
400 extensions::CrxInstaller::CreateSilent(profile
->GetExtensionService()));
401 installer
->set_error_on_unsupported_requirements(true);
402 installer
->InstallWebApp(install_info
);
403 favicon_downloader_
.reset();
406 void TabHelper::DidCloneToNewWebContents(WebContents
* old_web_contents
,
407 WebContents
* new_web_contents
) {
408 // When the WebContents that this is attached to is cloned, give the new clone
409 // a TabHelper and copy state over.
410 CreateForWebContents(new_web_contents
);
411 TabHelper
* new_helper
= FromWebContents(new_web_contents
);
413 new_helper
->SetExtensionApp(extension_app());
414 new_helper
->extension_app_icon_
= extension_app_icon_
;
417 void TabHelper::OnDidGetApplicationInfo(int32 page_id
,
418 const WebApplicationInfo
& info
) {
419 // Android does not implement BrowserWindow.
420 #if !defined(OS_MACOSX) && !defined(OS_ANDROID)
421 web_app_info_
= info
;
423 NavigationEntry
* entry
=
424 web_contents()->GetController().GetLastCommittedEntry();
425 if (!entry
|| (entry
->GetPageID() != page_id
))
428 switch (pending_web_app_action_
) {
429 case CREATE_SHORTCUT
: {
430 chrome::ShowCreateWebAppShortcutsDialog(
431 web_contents()->GetView()->GetTopLevelNativeWindow(),
435 case CREATE_HOSTED_APP
: {
439 case UPDATE_SHORTCUT
: {
440 web_app::UpdateShortcutForTabContents(web_contents());
448 // The hosted app action will be cleared once the installation completes or
450 if (pending_web_app_action_
!= CREATE_HOSTED_APP
)
451 pending_web_app_action_
= NONE
;
455 void TabHelper::OnInlineWebstoreInstall(
458 const std::string
& webstore_item_id
,
459 const GURL
& requestor_url
) {
460 WebstoreStandaloneInstaller::Callback callback
=
461 base::Bind(&TabHelper::OnInlineInstallComplete
, base::Unretained(this),
462 install_id
, return_route_id
);
463 scoped_refptr
<WebstoreInlineInstaller
> installer(
464 webstore_inline_installer_factory_
->CreateInstaller(
469 installer
->BeginInstall();
472 void TabHelper::OnGetAppInstallState(const GURL
& requestor_url
,
476 Profile::FromBrowserContext(web_contents()->GetBrowserContext());
477 ExtensionService
* extension_service
= profile
->GetExtensionService();
478 const ExtensionSet
* extensions
= extension_service
->extensions();
479 const ExtensionSet
* disabled
= extension_service
->disabled_extensions();
482 if (extensions
->GetHostedAppByURL(requestor_url
))
483 state
= extension_misc::kAppStateInstalled
;
484 else if (disabled
->GetHostedAppByURL(requestor_url
))
485 state
= extension_misc::kAppStateDisabled
;
487 state
= extension_misc::kAppStateNotInstalled
;
489 Send(new ExtensionMsg_GetAppInstallStateResponse(
490 return_route_id
, state
, callback_id
));
493 void TabHelper::OnRequest(const ExtensionHostMsg_Request_Params
& request
) {
494 extension_function_dispatcher_
.Dispatch(request
,
495 web_contents()->GetRenderViewHost());
498 void TabHelper::OnContentScriptsExecuting(
499 const ScriptExecutionObserver::ExecutingScriptsMap
& executing_scripts_map
,
501 const GURL
& on_url
) {
502 FOR_EACH_OBSERVER(ScriptExecutionObserver
, script_execution_observers_
,
503 OnScriptsExecuted(web_contents(),
504 executing_scripts_map
,
509 void TabHelper::OnWatchedPageChange(
510 const std::vector
<std::string
>& css_selectors
) {
511 #if defined(ENABLE_EXTENSIONS)
512 if (ExtensionSystem::Get(profile_
)->extension_service() &&
513 RulesRegistryService::Get(profile_
)) {
514 RulesRegistryService::Get(profile_
)->content_rules_registry()->Apply(
515 web_contents(), css_selectors
);
517 #endif // defined(ENABLE_EXTENSIONS)
520 void TabHelper::OnDetailedConsoleMessageAdded(
521 const base::string16
& message
,
522 const base::string16
& source
,
523 const StackTrace
& stack_trace
,
524 int32 severity_level
) {
525 if (IsSourceFromAnExtension(source
)) {
526 content::RenderViewHost
* rvh
= web_contents()->GetRenderViewHost();
527 ErrorConsole::Get(profile_
)->ReportError(
528 scoped_ptr
<ExtensionError
>(new RuntimeError(
529 extension_app_
? extension_app_
->id() : std::string(),
530 profile_
->IsOffTheRecord(),
535 web_contents()->GetLastCommittedURL() : GURL::EmptyGURL(),
536 static_cast<logging::LogSeverity
>(severity_level
),
538 rvh
->GetProcess()->GetID())));
542 const Extension
* TabHelper::GetExtension(const std::string
& extension_app_id
) {
543 if (extension_app_id
.empty())
547 Profile::FromBrowserContext(web_contents()->GetBrowserContext());
548 ExtensionService
* extension_service
= profile
->GetExtensionService();
549 if (!extension_service
|| !extension_service
->is_ready())
552 const Extension
* extension
=
553 extension_service
->GetExtensionById(extension_app_id
, false);
557 void TabHelper::UpdateExtensionAppIcon(const Extension
* extension
) {
558 extension_app_icon_
.reset();
559 // Ensure previously enqueued callbacks are ignored.
560 image_loader_ptr_factory_
.InvalidateWeakPtrs();
562 // Enqueue OnImageLoaded callback.
565 Profile::FromBrowserContext(web_contents()->GetBrowserContext());
566 extensions::ImageLoader
* loader
= extensions::ImageLoader::Get(profile
);
567 loader
->LoadImageAsync(
569 IconsInfo::GetIconResource(extension
,
570 extension_misc::EXTENSION_ICON_SMALL
,
571 ExtensionIconSet::MATCH_BIGGER
),
572 gfx::Size(extension_misc::EXTENSION_ICON_SMALL
,
573 extension_misc::EXTENSION_ICON_SMALL
),
574 base::Bind(&TabHelper::OnImageLoaded
,
575 image_loader_ptr_factory_
.GetWeakPtr()));
579 void TabHelper::SetAppIcon(const SkBitmap
& app_icon
) {
580 extension_app_icon_
= app_icon
;
581 web_contents()->NotifyNavigationStateChanged(content::INVALIDATE_TYPE_TITLE
);
584 void TabHelper::SetWebstoreInlineInstallerFactoryForTests(
585 WebstoreInlineInstallerFactory
* factory
) {
586 webstore_inline_installer_factory_
.reset(factory
);
589 void TabHelper::OnImageLoaded(const gfx::Image
& image
) {
590 if (!image
.IsEmpty()) {
591 extension_app_icon_
= *image
.ToSkBitmap();
592 web_contents()->NotifyNavigationStateChanged(content::INVALIDATE_TYPE_TAB
);
596 WindowController
* TabHelper::GetExtensionWindowController() const {
597 return ExtensionTabUtil::GetWindowControllerOfTab(web_contents());
600 void TabHelper::OnInlineInstallComplete(int install_id
,
603 const std::string
& error
) {
604 Send(new ExtensionMsg_InlineWebstoreInstallResponse(
605 return_route_id
, install_id
, success
, success
? std::string() : error
));
608 WebContents
* TabHelper::GetAssociatedWebContents() const {
609 return web_contents();
612 void TabHelper::GetApplicationInfo(int32 page_id
) {
613 Send(new ExtensionMsg_GetApplicationInfo(routing_id(), page_id
));
616 void TabHelper::Observe(int type
,
617 const content::NotificationSource
& source
,
618 const content::NotificationDetails
& details
) {
620 case content::NOTIFICATION_LOAD_STOP
: {
621 const NavigationController
& controller
=
622 *content::Source
<NavigationController
>(source
).ptr();
623 DCHECK_EQ(controller
.GetWebContents(), web_contents());
625 if (pending_web_app_action_
== UPDATE_SHORTCUT
) {
626 // Schedule a shortcut update when web application info is available if
627 // last committed entry is not NULL. Last committed entry could be NULL
628 // when an interstitial page is injected (e.g. bad https certificate,
629 // malware site etc). When this happens, we abort the shortcut update.
630 NavigationEntry
* entry
= controller
.GetLastCommittedEntry();
632 GetApplicationInfo(entry
->GetPageID());
634 pending_web_app_action_
= NONE
;
638 case chrome::NOTIFICATION_CRX_INSTALLER_DONE
: {
639 if (pending_web_app_action_
!= CREATE_HOSTED_APP
)
642 pending_web_app_action_
= NONE
;
644 const Extension
* extension
=
645 content::Details
<const Extension
>(details
).ptr();
646 if (!extension
|| !extension
->from_bookmark())
649 // If enabled, launch the app launcher and highlight the new app.
650 // Otherwise, open the chrome://apps page in a new foreground tab.
651 if (IsAppLauncherEnabled()) {
652 AppListService::Get(chrome::GetHostDesktopTypeForNativeView(
653 web_contents()->GetView()->GetNativeView()))->
654 ShowForProfile(profile_
);
656 content::NotificationService::current()->Notify(
657 chrome::NOTIFICATION_APP_INSTALLED_TO_APPLIST
,
658 content::Source
<Profile
>(profile_
),
659 content::Details
<const std::string
>(&extension
->id()));
663 // Android does not implement browser_finder.cc.
664 #if !defined(OS_ANDROID)
666 chrome::FindBrowserWithWebContents(web_contents());
669 content::OpenURLParams(GURL(chrome::kChromeUIAppsURL
),
672 content::PAGE_TRANSITION_LINK
,
677 case chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR
: {
678 if (pending_web_app_action_
== CREATE_HOSTED_APP
)
679 pending_web_app_action_
= NONE
;
682 case chrome::NOTIFICATION_EXTENSION_UNLOADED
: {
683 if (script_bubble_controller_
) {
684 script_bubble_controller_
->OnExtensionUnloaded(
685 content::Details
<extensions::UnloadedExtensionInfo
>(
686 details
)->extension
->id());
693 void TabHelper::SetTabId(RenderViewHost
* render_view_host
) {
694 render_view_host
->Send(
695 new ExtensionMsg_SetTabId(render_view_host
->GetRoutingID(),
696 SessionID::IdForTab(web_contents())));
699 } // namespace extensions