Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / extensions / tab_helper.cc
blobc38dc4a69635f92719b066cee72978a7941c6c94
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()
85 : tab_helper_(NULL) {
88 TabHelper::ScriptExecutionObserver::~ScriptExecutionObserver() {
89 if (tab_helper_)
90 tab_helper_->RemoveScriptExecutionObserver(this);
93 // static
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);
111 ++sizes_it;
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
117 ? bitmaps_it->second
118 : skia::ImageOperations::Resize(
119 bitmaps_it->second, skia::ImageOperations::RESIZE_LANCZOS3,
120 size, size));
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(
142 web_contents,
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));
148 } else {
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_));
164 #endif
166 registrar_.Add(this,
167 content::NOTIFICATION_LOAD_STOP,
168 content::Source<NavigationController>(
169 &web_contents->GetController()));
171 registrar_.Add(this,
172 chrome::NOTIFICATION_CRX_INSTALLER_DONE,
173 content::Source<CrxInstaller>(NULL));
175 registrar_.Add(this,
176 chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR,
177 content::NotificationService::AllSources());
179 registrar_.Add(this,
180 chrome::NOTIFICATION_EXTENSION_UNLOADED,
181 content::NotificationService::AllSources());
184 TabHelper::~TabHelper() {
185 #if defined(ENABLE_EXTENSIONS)
186 RemoveScriptExecutionObserver(ActivityLog::GetInstance(profile_));
187 #endif
190 void TabHelper::CreateApplicationShortcuts() {
191 DCHECK(CanCreateApplicationShortcuts());
192 NavigationEntry* entry =
193 web_contents()->GetController().GetLastCommittedEntry();
194 if (!entry)
195 return;
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();
208 if (!entry)
209 return;
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)
220 return false;
221 #else
222 return web_app::IsValidUrl(web_contents()->GetURL()) &&
223 pending_web_app_action_ == NONE;
224 #endif
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);
241 if (extension)
242 SetExtensionApp(extension);
245 void TabHelper::SetExtensionAppIconById(const std::string& extension_app_id) {
246 const Extension* extension = GetExtension(extension_app_id);
247 if (extension)
248 UpdateExtensionAppIcon(extension);
251 SkBitmap* TabHelper::GetExtensionAppIcon() {
252 if (extension_app_icon_.empty())
253 return NULL;
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)
273 Profile* profile =
274 Profile::FromBrowserContext(web_contents()->GetBrowserContext());
275 ExtensionService* service = profile->GetExtensionService();
276 if (!service)
277 return;
279 UpdateExtensionAppIcon(service->GetInstalledExtensionByUrl(params.url));
281 if (details.is_in_page)
282 return;
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) {
301 bool handled = true;
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,
313 OnWatchedPageChange)
314 IPC_MESSAGE_HANDLER(ChromeViewHostMsg_DetailedConsoleMessageAdded,
315 OnDetailedConsoleMessageAdded)
316 IPC_MESSAGE_UNHANDLED(handled = false)
317 IPC_END_MESSAGE_MAP()
318 return handled;
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(
340 bool success,
341 const std::map<GURL, std::vector<SkBitmap> >& bitmaps) {
342 // The tab has navigated away during the icon download. Cancel the hosted app
343 // creation.
344 if (!success) {
345 favicon_downloader_.reset();
346 return;
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())
375 continue;
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,
386 allowed_sizes));
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);
397 Profile* profile =
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))
426 return;
428 switch (pending_web_app_action_) {
429 case CREATE_SHORTCUT: {
430 chrome::ShowCreateWebAppShortcutsDialog(
431 web_contents()->GetView()->GetTopLevelNativeWindow(),
432 web_contents());
433 break;
435 case CREATE_HOSTED_APP: {
436 CreateHostedApp();
437 break;
439 case UPDATE_SHORTCUT: {
440 web_app::UpdateShortcutForTabContents(web_contents());
441 break;
443 default:
444 NOTREACHED();
445 break;
448 // The hosted app action will be cleared once the installation completes or
449 // fails.
450 if (pending_web_app_action_ != CREATE_HOSTED_APP)
451 pending_web_app_action_ = NONE;
452 #endif
455 void TabHelper::OnInlineWebstoreInstall(
456 int install_id,
457 int return_route_id,
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(
465 web_contents(),
466 webstore_item_id,
467 requestor_url,
468 callback));
469 installer->BeginInstall();
472 void TabHelper::OnGetAppInstallState(const GURL& requestor_url,
473 int return_route_id,
474 int callback_id) {
475 Profile* profile =
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();
481 std::string state;
482 if (extensions->GetHostedAppByURL(requestor_url))
483 state = extension_misc::kAppStateInstalled;
484 else if (disabled->GetHostedAppByURL(requestor_url))
485 state = extension_misc::kAppStateDisabled;
486 else
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,
500 int32 on_page_id,
501 const GURL& on_url) {
502 FOR_EACH_OBSERVER(ScriptExecutionObserver, script_execution_observers_,
503 OnScriptsExecuted(web_contents(),
504 executing_scripts_map,
505 on_page_id,
506 on_url));
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(),
531 source,
532 message,
533 stack_trace,
534 web_contents() ?
535 web_contents()->GetLastCommittedURL() : GURL::EmptyGURL(),
536 static_cast<logging::LogSeverity>(severity_level),
537 rvh->GetRoutingID(),
538 rvh->GetProcess()->GetID())));
542 const Extension* TabHelper::GetExtension(const std::string& extension_app_id) {
543 if (extension_app_id.empty())
544 return NULL;
546 Profile* profile =
547 Profile::FromBrowserContext(web_contents()->GetBrowserContext());
548 ExtensionService* extension_service = profile->GetExtensionService();
549 if (!extension_service || !extension_service->is_ready())
550 return NULL;
552 const Extension* extension =
553 extension_service->GetExtensionById(extension_app_id, false);
554 return extension;
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.
563 if (extension) {
564 Profile* profile =
565 Profile::FromBrowserContext(web_contents()->GetBrowserContext());
566 extensions::ImageLoader* loader = extensions::ImageLoader::Get(profile);
567 loader->LoadImageAsync(
568 extension,
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,
601 int return_route_id,
602 bool success,
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) {
619 switch (type) {
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();
631 if (entry)
632 GetApplicationInfo(entry->GetPageID());
633 else
634 pending_web_app_action_ = NONE;
636 break;
638 case chrome::NOTIFICATION_CRX_INSTALLER_DONE: {
639 if (pending_web_app_action_ != CREATE_HOSTED_APP)
640 return;
642 pending_web_app_action_ = NONE;
644 const Extension* extension =
645 content::Details<const Extension>(details).ptr();
646 if (!extension || !extension->from_bookmark())
647 return;
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()));
660 return;
663 // Android does not implement browser_finder.cc.
664 #if !defined(OS_ANDROID)
665 Browser* browser =
666 chrome::FindBrowserWithWebContents(web_contents());
667 if (browser) {
668 browser->OpenURL(
669 content::OpenURLParams(GURL(chrome::kChromeUIAppsURL),
670 content::Referrer(),
671 NEW_FOREGROUND_TAB,
672 content::PAGE_TRANSITION_LINK,
673 false));
675 #endif
677 case chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR: {
678 if (pending_web_app_action_ == CREATE_HOSTED_APP)
679 pending_web_app_action_ = NONE;
680 break;
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());
687 break;
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