Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / tab_helper.cc
index 26da0e1..810710d 100644 (file)
@@ -9,19 +9,18 @@
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/extensions/active_script_controller.h"
 #include "chrome/browser/extensions/activity_log/activity_log.h"
 #include "chrome/browser/extensions/api/declarative/rules_registry_service.h"
 #include "chrome/browser/extensions/api/declarative_content/content_rules_registry.h"
-#include "chrome/browser/extensions/crx_installer.h"
+#include "chrome/browser/extensions/api/webstore/webstore_api.h"
+#include "chrome/browser/extensions/bookmark_app_helper.h"
 #include "chrome/browser/extensions/error_console/error_console.h"
 #include "chrome/browser/extensions/extension_action.h"
 #include "chrome/browser/extensions/extension_action_manager.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_tab_util.h"
-#include "chrome/browser/extensions/favicon_downloader.h"
-#include "chrome/browser/extensions/image_loader.h"
-#include "chrome/browser/extensions/page_action_controller.h"
-#include "chrome/browser/extensions/script_executor.h"
+#include "chrome/browser/extensions/location_bar_controller.h"
 #include "chrome/browser/extensions/webstore_inline_installer.h"
 #include "chrome/browser/extensions/webstore_inline_installer_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/host_desktop.h"
-#include "chrome/browser/ui/web_applications/web_app_ui.h"
 #include "chrome/browser/web_applications/web_app.h"
 #include "chrome/common/chrome_switches.h"
+#include "chrome/common/extensions/chrome_extension_messages.h"
 #include "chrome/common/extensions/extension_constants.h"
-#include "chrome/common/extensions/extension_icon_set.h"
-#include "chrome/common/extensions/extension_messages.h"
 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
-#include "chrome/common/extensions/manifest_handlers/icons_handler.h"
 #include "chrome/common/render_messages.h"
 #include "chrome/common/url_constants.h"
 #include "content/public/browser/invalidate_type.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/render_widget_host_view.h"
 #include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_contents_view.h"
 #include "content/public/common/frame_navigate_params.h"
 #include "extensions/browser/extension_error.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_system.h"
+#include "extensions/browser/image_loader.h"
+#include "extensions/common/constants.h"
 #include "extensions/common/extension.h"
+#include "extensions/common/extension_icon_set.h"
+#include "extensions/common/extension_messages.h"
 #include "extensions/common/extension_resource.h"
 #include "extensions/common/extension_urls.h"
 #include "extensions/common/feature_switch.h"
-#include "skia/ext/image_operations.h"
-#include "skia/ext/platform_canvas.h"
-#include "ui/gfx/color_analysis.h"
-#include "ui/gfx/image/image.h"
+#include "extensions/common/manifest_handlers/icons_handler.h"
 
 #if defined(OS_CHROMEOS)
 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h"
 #endif
 
+#if defined(OS_WIN)
+#include "chrome/browser/web_applications/web_app_win.h"
+#endif
+
 using content::NavigationController;
 using content::NavigationEntry;
 using content::RenderViewHost;
@@ -81,144 +81,18 @@ DEFINE_WEB_CONTENTS_USER_DATA_KEY(extensions::TabHelper);
 
 namespace extensions {
 
-TabHelper::ScriptExecutionObserver::ScriptExecutionObserver(
-    TabHelper* tab_helper)
-    : tab_helper_(tab_helper) {
-  tab_helper_->AddScriptExecutionObserver(this);
-}
-
-TabHelper::ScriptExecutionObserver::ScriptExecutionObserver()
-    : tab_helper_(NULL) {
-}
-
-TabHelper::ScriptExecutionObserver::~ScriptExecutionObserver() {
-  if (tab_helper_)
-    tab_helper_->RemoveScriptExecutionObserver(this);
-}
-
-// static
-std::map<int, SkBitmap> TabHelper::ConstrainBitmapsToSizes(
-    const std::vector<SkBitmap>& bitmaps,
-    const std::set<int>& sizes) {
-  std::map<int, SkBitmap> output_bitmaps;
-  std::map<int, SkBitmap> ordered_bitmaps;
-  for (std::vector<SkBitmap>::const_iterator it = bitmaps.begin();
-       it != bitmaps.end(); ++it) {
-    DCHECK(it->width() == it->height());
-    ordered_bitmaps[it->width()] = *it;
-  }
-
-  std::set<int>::const_iterator sizes_it = sizes.begin();
-  std::map<int, SkBitmap>::const_iterator bitmaps_it = ordered_bitmaps.begin();
-  while (sizes_it != sizes.end() && bitmaps_it != ordered_bitmaps.end()) {
-    int size = *sizes_it;
-    // Find the closest not-smaller bitmap.
-    bitmaps_it = ordered_bitmaps.lower_bound(size);
-    ++sizes_it;
-    // Ensure the bitmap is valid and smaller than the next allowed size.
-    if (bitmaps_it != ordered_bitmaps.end() &&
-        (sizes_it == sizes.end() || bitmaps_it->second.width() < *sizes_it)) {
-      // Resize the bitmap if it does not exactly match the desired size.
-      output_bitmaps[size] = bitmaps_it->second.width() == size
-          ? bitmaps_it->second
-          : skia::ImageOperations::Resize(
-                bitmaps_it->second, skia::ImageOperations::RESIZE_LANCZOS3,
-                size, size);
-    }
-  }
-  return output_bitmaps;
-}
-
-// static
-void TabHelper::GenerateContainerIcon(std::map<int, SkBitmap>* bitmaps,
-                                      int output_size) {
-  std::map<int, SkBitmap>::const_iterator it =
-      bitmaps->lower_bound(output_size);
-  // Do nothing if there is no icon smaller than the desired size or there is
-  // already an icon of |output_size|.
-  if (it == bitmaps->begin() || bitmaps->count(output_size))
-    return;
-
-  --it;
-  // This is the biggest icon smaller than |output_size|.
-  const SkBitmap& base_icon = it->second;
-
-  const size_t kBorderRadius = 5;
-  const size_t kColorStripHeight = 3;
-  const SkColor kBorderColor = 0xFFD5D5D5;
-  const SkColor kBackgroundColor = 0xFFFFFFFF;
-
-  // Create a separate canvas for the color strip.
-  scoped_ptr<SkCanvas> color_strip_canvas(
-      skia::CreateBitmapCanvas(output_size, output_size, false));
-  DCHECK(color_strip_canvas);
-
-  // Draw a rounded rect of the |base_icon|'s dominant color.
-  SkPaint color_strip_paint;
-  color_utils::GridSampler sampler;
-  color_strip_paint.setFlags(SkPaint::kAntiAlias_Flag);
-  color_strip_paint.setColor(
-      color_utils::CalculateKMeanColorOfPNG(
-          gfx::Image::CreateFrom1xBitmap(base_icon).As1xPNGBytes(),
-          100, 665, &sampler));
-  color_strip_canvas->drawRoundRect(
-      SkRect::MakeWH(output_size, output_size),
-      kBorderRadius, kBorderRadius, color_strip_paint);
-
-  // Erase the top of the rounded rect to leave a color strip.
-  SkPaint clear_paint;
-  clear_paint.setColor(SK_ColorTRANSPARENT);
-  clear_paint.setXfermodeMode(SkXfermode::kSrc_Mode);
-  color_strip_canvas->drawRect(
-      SkRect::MakeWH(output_size, output_size - kColorStripHeight),
-      clear_paint);
-
-  // Draw each element to an output canvas.
-  scoped_ptr<SkCanvas> canvas(
-      skia::CreateBitmapCanvas(output_size, output_size, false));
-  DCHECK(canvas);
-
-  // Draw the background.
-  SkPaint background_paint;
-  background_paint.setColor(kBackgroundColor);
-  background_paint.setFlags(SkPaint::kAntiAlias_Flag);
-  canvas->drawRoundRect(
-      SkRect::MakeWH(output_size, output_size),
-      kBorderRadius, kBorderRadius, background_paint);
-
-  // Draw the color strip.
-  canvas->drawBitmap(color_strip_canvas->getDevice()->accessBitmap(false),
-                     0, 0);
-
-  // Draw the border.
-  SkPaint border_paint;
-  border_paint.setColor(kBorderColor);
-  border_paint.setStyle(SkPaint::kStroke_Style);
-  border_paint.setFlags(SkPaint::kAntiAlias_Flag);
-  canvas->drawRoundRect(
-      SkRect::MakeWH(output_size, output_size),
-      kBorderRadius, kBorderRadius, border_paint);
-
-  // Draw the centered base icon to the output canvas.
-  canvas->drawBitmap(base_icon,
-                     (output_size - base_icon.width()) / 2,
-                     (output_size - base_icon.height()) / 2);
-
-  const SkBitmap& generated_icon =
-      canvas->getDevice()->accessBitmap(false);
-  generated_icon.deepCopyTo(&(*bitmaps)[output_size],
-                            generated_icon.getConfig());
-}
-
 TabHelper::TabHelper(content::WebContents* web_contents)
     : content::WebContentsObserver(web_contents),
       extension_app_(NULL),
       extension_function_dispatcher_(
-          Profile::FromBrowserContext(web_contents->GetBrowserContext()), this),
+          Profile::FromBrowserContext(web_contents->GetBrowserContext()),
+          this),
       pending_web_app_action_(NONE),
-      script_executor_(new ScriptExecutor(web_contents,
-                                          &script_execution_observers_)),
-      location_bar_controller_(new PageActionController(web_contents)),
+      last_committed_page_id_(-1),
+      update_shortcut_on_load_complete_(false),
+      script_executor_(
+          new ScriptExecutor(web_contents, &script_execution_observers_)),
+      location_bar_controller_(new LocationBarController(web_contents)),
       image_loader_ptr_factory_(this),
       webstore_inline_installer_factory_(new WebstoreInlineInstallerFactory()) {
   // The ActiveTabPermissionManager requires a session ID; ensure this
@@ -235,56 +109,30 @@ TabHelper::TabHelper(content::WebContents* web_contents)
   // a separate routing class with an observer interface should be written.
   profile_ = Profile::FromBrowserContext(web_contents->GetBrowserContext());
 
-#if defined(ENABLE_EXTENSIONS)
   AddScriptExecutionObserver(ActivityLog::GetInstance(profile_));
-#endif
 
   registrar_.Add(this,
                  content::NOTIFICATION_LOAD_STOP,
                  content::Source<NavigationController>(
                      &web_contents->GetController()));
-
-  registrar_.Add(this,
-                 chrome::NOTIFICATION_CRX_INSTALLER_DONE,
-                 content::Source<CrxInstaller>(NULL));
-
-  registrar_.Add(this,
-                 chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR,
-                 content::NotificationService::AllSources());
 }
 
 TabHelper::~TabHelper() {
-#if defined(ENABLE_EXTENSIONS)
   RemoveScriptExecutionObserver(ActivityLog::GetInstance(profile_));
-#endif
 }
 
 void TabHelper::CreateApplicationShortcuts() {
   DCHECK(CanCreateApplicationShortcuts());
-  NavigationEntry* entry =
-      web_contents()->GetController().GetLastCommittedEntry();
-  if (!entry)
-    return;
-
-  pending_web_app_action_ = CREATE_SHORTCUT;
-
   // Start fetching web app info for CreateApplicationShortcut dialog and show
   // the dialog when the data is available in OnDidGetApplicationInfo.
-  GetApplicationInfo(entry->GetPageID());
+  GetApplicationInfo(CREATE_SHORTCUT);
 }
 
 void TabHelper::CreateHostedAppFromWebContents() {
-  DCHECK(CanCreateApplicationShortcuts());
-  NavigationEntry* entry =
-      web_contents()->GetController().GetLastCommittedEntry();
-  if (!entry)
-    return;
-
-  pending_web_app_action_ = CREATE_HOSTED_APP;
-
+  DCHECK(CanCreateBookmarkApp());
   // Start fetching web app info for CreateApplicationShortcut dialog and show
   // the dialog when the data is available in OnDidGetApplicationInfo.
-  GetApplicationInfo(entry->GetPageID());
+  GetApplicationInfo(CREATE_HOSTED_APP);
 }
 
 bool TabHelper::CanCreateApplicationShortcuts() const {
@@ -296,6 +144,24 @@ bool TabHelper::CanCreateApplicationShortcuts() const {
 #endif
 }
 
+bool TabHelper::CanCreateBookmarkApp() const {
+#if defined(OS_MACOSX)
+  return false;
+#else
+  return IsValidBookmarkAppUrl(web_contents()->GetURL()) &&
+         pending_web_app_action_ == NONE;
+#endif
+}
+
+void TabHelper::AddScriptExecutionObserver(ScriptExecutionObserver* observer) {
+  script_execution_observers_.AddObserver(observer);
+}
+
+void TabHelper::RemoveScriptExecutionObserver(
+    ScriptExecutionObserver* observer) {
+  script_execution_observers_.RemoveObserver(observer);
+}
+
 void TabHelper::SetExtensionApp(const Extension* extension) {
   DCHECK(!extension || AppLaunchInfo::GetFullLaunchURL(extension).is_valid());
   if (extension_app_ == extension)
@@ -330,6 +196,25 @@ SkBitmap* TabHelper::GetExtensionAppIcon() {
   return &extension_app_icon_;
 }
 
+void TabHelper::FinishCreateBookmarkApp(
+    const Extension* extension,
+    const WebApplicationInfo& web_app_info) {
+  pending_web_app_action_ = NONE;
+
+  // There was an error with downloading the icons or installing the app.
+  if (!extension)
+    return;
+
+#if defined(OS_CHROMEOS)
+  ChromeLauncherController::instance()->PinAppWithID(extension->id());
+#endif
+
+  Browser* browser = chrome::FindBrowserWithWebContents(web_contents());
+  if (browser) {
+    browser->window()->ShowBookmarkAppBubble(web_app_info, extension->id());
+  }
+}
+
 void TabHelper::RenderViewCreated(RenderViewHost* render_view_host) {
   SetTabId(render_view_host);
 }
@@ -337,48 +222,46 @@ void TabHelper::RenderViewCreated(RenderViewHost* render_view_host) {
 void TabHelper::DidNavigateMainFrame(
     const content::LoadCommittedDetails& details,
     const content::FrameNavigateParams& params) {
-#if defined(ENABLE_EXTENSIONS)
   if (ExtensionSystem::Get(profile_)->extension_service() &&
       RulesRegistryService::Get(profile_)) {
     RulesRegistryService::Get(profile_)->content_rules_registry()->
         DidNavigateMainFrame(web_contents(), details, params);
   }
-#endif  // defined(ENABLE_EXTENSIONS)
 
-  Profile* profile =
-      Profile::FromBrowserContext(web_contents()->GetBrowserContext());
-  ExtensionService* service = profile->GetExtensionService();
-  if (!service)
-    return;
+  content::BrowserContext* context = web_contents()->GetBrowserContext();
+  ExtensionRegistry* registry = ExtensionRegistry::Get(context);
+  const ExtensionSet& enabled_extensions = registry->enabled_extensions();
 
   if (CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kEnableStreamlinedHostedApps)) {
-#if !defined(OS_ANDROID)
     Browser* browser = chrome::FindBrowserWithWebContents(web_contents());
     if (browser && browser->is_app()) {
-      SetExtensionApp(service->GetInstalledExtension(
-          web_app::GetExtensionIdFromApplicationName(browser->app_name())));
+      SetExtensionApp(registry->GetExtensionById(
+          web_app::GetExtensionIdFromApplicationName(browser->app_name()),
+          ExtensionRegistry::EVERYTHING));
     } else {
-      UpdateExtensionAppIcon(service->GetInstalledExtensionByUrl(params.url));
+      UpdateExtensionAppIcon(
+          enabled_extensions.GetExtensionOrAppByURL(params.url));
     }
-#endif
   } else {
-    UpdateExtensionAppIcon(service->GetInstalledExtensionByUrl(params.url));
+    UpdateExtensionAppIcon(
+        enabled_extensions.GetExtensionOrAppByURL(params.url));
   }
 
   if (details.is_in_page)
     return;
 
   ExtensionActionManager* extension_action_manager =
-      ExtensionActionManager::Get(profile);
-  for (ExtensionSet::const_iterator it = service->extensions()->begin();
-       it != service->extensions()->end(); ++it) {
+      ExtensionActionManager::Get(Profile::FromBrowserContext(context));
+  for (ExtensionSet::const_iterator it = enabled_extensions.begin();
+       it != enabled_extensions.end();
+       ++it) {
     ExtensionAction* browser_action =
         extension_action_manager->GetBrowserAction(*it->get());
     if (browser_action) {
       browser_action->ClearAllValuesForTab(SessionID::IdForTab(web_contents()));
       content::NotificationService::current()->Notify(
-          chrome::NOTIFICATION_EXTENSION_BROWSER_ACTION_UPDATED,
+          extensions::NOTIFICATION_EXTENSION_BROWSER_ACTION_UPDATED,
           content::Source<ExtensionAction>(browser_action),
           content::NotificationService::NoDetails());
     }
@@ -388,7 +271,7 @@ void TabHelper::DidNavigateMainFrame(
 bool TabHelper::OnMessageReceived(const IPC::Message& message) {
   bool handled = true;
   IPC_BEGIN_MESSAGE_MAP(TabHelper, message)
-    IPC_MESSAGE_HANDLER(ExtensionHostMsg_DidGetApplicationInfo,
+    IPC_MESSAGE_HANDLER(ChromeExtensionHostMsg_DidGetApplicationInfo,
                         OnDidGetApplicationInfo)
     IPC_MESSAGE_HANDLER(ExtensionHostMsg_InlineWebstoreInstall,
                         OnInlineWebstoreInstall)
@@ -399,120 +282,20 @@ bool TabHelper::OnMessageReceived(const IPC::Message& message) {
                         OnContentScriptsExecuting)
     IPC_MESSAGE_HANDLER(ExtensionHostMsg_OnWatchedPageChange,
                         OnWatchedPageChange)
-    IPC_MESSAGE_HANDLER(ChromeViewHostMsg_DetailedConsoleMessageAdded,
-                        OnDetailedConsoleMessageAdded)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
   return handled;
 }
 
-void TabHelper::CreateHostedApp() {
-  // Add urls from the WebApplicationInfo.
-  std::vector<GURL> web_app_info_icon_urls;
-  for (std::vector<WebApplicationInfo::IconInfo>::const_iterator it =
-           web_app_info_.icons.begin();
-       it != web_app_info_.icons.end(); ++it) {
-    if (it->url.is_valid())
-      web_app_info_icon_urls.push_back(it->url);
-  }
-
-  favicon_downloader_.reset(
-      new FaviconDownloader(web_contents(),
-                            web_app_info_icon_urls,
-                            base::Bind(&TabHelper::FinishCreateHostedApp,
-                                       base::Unretained(this))));
-  favicon_downloader_->Start();
-}
-
-// TODO(calamity): Move hosted app generation into its own file.
-void TabHelper::FinishCreateHostedApp(
-    bool success,
-    const std::map<GURL, std::vector<SkBitmap> >& bitmaps) {
-  // The tab has navigated away during the icon download. Cancel the hosted app
-  // creation.
-  if (!success) {
-    favicon_downloader_.reset();
-    return;
-  }
-
-  if (web_app_info_.app_url.is_empty())
-    web_app_info_.app_url = web_contents()->GetURL();
-
-  if (web_app_info_.title.empty())
-    web_app_info_.title = web_contents()->GetTitle();
-  if (web_app_info_.title.empty())
-    web_app_info_.title = base::UTF8ToUTF16(web_app_info_.app_url.spec());
-
-  // Add the downloaded icons. Extensions only allow certain icon sizes. First
-  // populate icons that match the allowed sizes exactly and then downscale
-  // remaining icons to the closest allowed size that doesn't yet have an icon.
-  std::set<int> allowed_sizes(
-      extension_misc::kExtensionIconSizes,
-      extension_misc::kExtensionIconSizes +
-          extension_misc::kNumExtensionIconSizes);
-  std::vector<SkBitmap> downloaded_icons;
-  for (FaviconDownloader::FaviconMap::const_iterator map_it = bitmaps.begin();
-       map_it != bitmaps.end(); ++map_it) {
-    for (std::vector<SkBitmap>::const_iterator bitmap_it =
-             map_it->second.begin();
-         bitmap_it != map_it->second.end(); ++bitmap_it) {
-      if (bitmap_it->empty() || bitmap_it->width() != bitmap_it->height())
-        continue;
-
-      downloaded_icons.push_back(*bitmap_it);
-    }
-  }
-
-  // If there are icons that don't match the accepted icon sizes, find the
-  // closest bigger icon to the accepted sizes and resize the icon to it. An
-  // icon will be resized and used for at most one size.
-  std::map<int, SkBitmap> resized_bitmaps(
-      TabHelper::ConstrainBitmapsToSizes(downloaded_icons,
-                                         allowed_sizes));
-
-  // Generate container icons from smaller icons.
-  const int kIconSizesToGenerate[] = {
-    extension_misc::EXTENSION_ICON_SMALL,
-    extension_misc::EXTENSION_ICON_MEDIUM,
-  };
-  const std::set<int> generate_sizes(
-      kIconSizesToGenerate,
-      kIconSizesToGenerate + arraysize(kIconSizesToGenerate));
-
-  // Only generate icons if larger icons don't exist. This means the app
-  // launcher and the taskbar will do their best downsizing large icons and
-  // these container icons are only generated as a last resort against upscaling
-  // a smaller icon.
-  if (resized_bitmaps.lower_bound(*generate_sizes.rbegin()) ==
-      resized_bitmaps.end()) {
-    // Generate these from biggest to smallest so we don't end up with
-    // concentric container icons.
-    for (std::set<int>::const_reverse_iterator it = generate_sizes.rbegin();
-         it != generate_sizes.rend(); ++it) {
-      TabHelper::GenerateContainerIcon(&resized_bitmaps, *it);
-    }
-  }
-
-  // Populate a the icon data into the WebApplicationInfo we are using to
-  // install the bookmark app.
-  for (std::map<int, SkBitmap>::const_iterator resized_bitmaps_it =
-           resized_bitmaps.begin();
-       resized_bitmaps_it != resized_bitmaps.end(); ++resized_bitmaps_it) {
-    WebApplicationInfo::IconInfo icon_info;
-    icon_info.data = resized_bitmaps_it->second;
-    icon_info.width = icon_info.data.width();
-    icon_info.height = icon_info.data.height();
-    web_app_info_.icons.push_back(icon_info);
-  }
-
-  // Install the app.
-  Profile* profile =
-      Profile::FromBrowserContext(web_contents()->GetBrowserContext());
-  scoped_refptr<extensions::CrxInstaller> installer(
-      extensions::CrxInstaller::CreateSilent(profile->GetExtensionService()));
-  installer->set_error_on_unsupported_requirements(true);
-  installer->InstallWebApp(web_app_info_);
-  favicon_downloader_.reset();
+bool TabHelper::OnMessageReceived(const IPC::Message& message,
+                                  content::RenderFrameHost* render_frame_host) {
+  bool handled = true;
+  IPC_BEGIN_MESSAGE_MAP(TabHelper, message)
+    IPC_MESSAGE_HANDLER(ChromeViewHostMsg_DetailedConsoleMessageAdded,
+                        OnDetailedConsoleMessageAdded)
+    IPC_MESSAGE_UNHANDLED(handled = false)
+  IPC_END_MESSAGE_MAP()
+  return handled;
 }
 
 void TabHelper::DidCloneToNewWebContents(WebContents* old_web_contents,
@@ -526,26 +309,37 @@ void TabHelper::DidCloneToNewWebContents(WebContents* old_web_contents,
   new_helper->extension_app_icon_ = extension_app_icon_;
 }
 
-void TabHelper::OnDidGetApplicationInfo(int32 page_id,
-                                        const WebApplicationInfo& info) {
-  // Android does not implement BrowserWindow.
-#if !defined(OS_MACOSX) && !defined(OS_ANDROID)
+void TabHelper::OnDidGetApplicationInfo(const WebApplicationInfo& info) {
+#if !defined(OS_MACOSX)
   web_app_info_ = info;
 
   NavigationEntry* entry =
       web_contents()->GetController().GetLastCommittedEntry();
-  if (!entry || (entry->GetPageID() != page_id))
+  if (!entry || last_committed_page_id_ != entry->GetPageID())
     return;
+  last_committed_page_id_ = -1;
 
   switch (pending_web_app_action_) {
     case CREATE_SHORTCUT: {
       chrome::ShowCreateWebAppShortcutsDialog(
-          web_contents()->GetView()->GetTopLevelNativeWindow(),
+          web_contents()->GetTopLevelNativeWindow(),
           web_contents());
       break;
     }
     case CREATE_HOSTED_APP: {
-      CreateHostedApp();
+      if (web_app_info_.app_url.is_empty())
+        web_app_info_.app_url = web_contents()->GetURL();
+
+      if (web_app_info_.title.empty())
+        web_app_info_.title = web_contents()->GetTitle();
+      if (web_app_info_.title.empty())
+        web_app_info_.title = base::UTF8ToUTF16(web_app_info_.app_url.spec());
+
+      bookmark_app_helper_.reset(new BookmarkAppHelper(
+          ExtensionSystem::Get(profile_)->extension_service(),
+          web_app_info_, web_contents()));
+      bookmark_app_helper_->Create(base::Bind(
+          &TabHelper::FinishCreateBookmarkApp, base::Unretained(this)));
       break;
     }
     case UPDATE_SHORTCUT: {
@@ -564,14 +358,30 @@ void TabHelper::OnDidGetApplicationInfo(int32 page_id,
 #endif
 }
 
-void TabHelper::OnInlineWebstoreInstall(
-    int install_id,
-    int return_route_id,
-    const std::string& webstore_item_id,
-    const GURL& requestor_url) {
+void TabHelper::OnInlineWebstoreInstall(int install_id,
+                                        int return_route_id,
+                                        const std::string& webstore_item_id,
+                                        const GURL& requestor_url,
+                                        int listeners_mask) {
+  // Check that the listener is reasonable. We should never get anything other
+  // than an install stage listener, a download listener, or both.
+  if ((listeners_mask & ~(api::webstore::INSTALL_STAGE_LISTENER |
+                          api::webstore::DOWNLOAD_PROGRESS_LISTENER)) != 0) {
+    NOTREACHED();
+    return;
+  }
+  // Inform the Webstore API that an inline install is happening, in case the
+  // page requested status updates.
+  Profile* profile =
+      Profile::FromBrowserContext(web_contents()->GetBrowserContext());
+  WebstoreAPI::Get(profile)->OnInlineInstallStart(
+      return_route_id, this, webstore_item_id, listeners_mask);
+
   WebstoreStandaloneInstaller::Callback callback =
-      base::Bind(&TabHelper::OnInlineInstallComplete, base::Unretained(this),
-                 install_id, return_route_id);
+      base::Bind(&TabHelper::OnInlineInstallComplete,
+                 base::Unretained(this),
+                 install_id,
+                 return_route_id);
   scoped_refptr<WebstoreInlineInstaller> installer(
       webstore_inline_installer_factory_->CreateInstaller(
           web_contents(),
@@ -608,24 +418,20 @@ void TabHelper::OnRequest(const ExtensionHostMsg_Request_Params& request) {
 
 void TabHelper::OnContentScriptsExecuting(
     const ScriptExecutionObserver::ExecutingScriptsMap& executing_scripts_map,
-    int32 on_page_id,
     const GURL& on_url) {
-  FOR_EACH_OBSERVER(ScriptExecutionObserver, script_execution_observers_,
-                    OnScriptsExecuted(web_contents(),
-                                      executing_scripts_map,
-                                      on_page_id,
-                                      on_url));
+  FOR_EACH_OBSERVER(
+      ScriptExecutionObserver,
+      script_execution_observers_,
+      OnScriptsExecuted(web_contents(), executing_scripts_map, on_url));
 }
 
 void TabHelper::OnWatchedPageChange(
     const std::vector<std::string>& css_selectors) {
-#if defined(ENABLE_EXTENSIONS)
   if (ExtensionSystem::Get(profile_)->extension_service() &&
       RulesRegistryService::Get(profile_)) {
     RulesRegistryService::Get(profile_)->content_rules_registry()->Apply(
         web_contents(), css_selectors);
   }
-#endif  // defined(ENABLE_EXTENSIONS)
 }
 
 void TabHelper::OnDetailedConsoleMessageAdded(
@@ -654,15 +460,9 @@ const Extension* TabHelper::GetExtension(const std::string& extension_app_id) {
   if (extension_app_id.empty())
     return NULL;
 
-  Profile* profile =
-      Profile::FromBrowserContext(web_contents()->GetBrowserContext());
-  ExtensionService* extension_service = profile->GetExtensionService();
-  if (!extension_service || !extension_service->is_ready())
-    return NULL;
-
-  const Extension* extension =
-      extension_service->GetExtensionById(extension_app_id, false);
-  return extension;
+  content::BrowserContext* context = web_contents()->GetBrowserContext();
+  return ExtensionRegistry::Get(context)->enabled_extensions().GetByID(
+      extension_app_id);
 }
 
 void TabHelper::UpdateExtensionAppIcon(const Extension* extension) {
@@ -674,7 +474,7 @@ void TabHelper::UpdateExtensionAppIcon(const Extension* extension) {
   if (extension) {
     Profile* profile =
         Profile::FromBrowserContext(web_contents()->GetBrowserContext());
-    extensions::ImageLoader* loader = extensions::ImageLoader::Get(profile);
+    ImageLoader* loader = ImageLoader::Get(profile);
     loader->LoadImageAsync(
         extension,
         IconsInfo::GetIconResource(extension,
@@ -711,72 +511,48 @@ WindowController* TabHelper::GetExtensionWindowController() const  {
 void TabHelper::OnInlineInstallComplete(int install_id,
                                         int return_route_id,
                                         bool success,
-                                        const std::string& error) {
+                                        const std::string& error,
+                                        webstore_install::Result result) {
   Send(new ExtensionMsg_InlineWebstoreInstallResponse(
-      return_route_id, install_id, success, success ? std::string() : error));
+      return_route_id,
+      install_id,
+      success,
+      success ? std::string() : error,
+      result));
 }
 
 WebContents* TabHelper::GetAssociatedWebContents() const {
   return web_contents();
 }
 
-void TabHelper::GetApplicationInfo(int32 page_id) {
-  Send(new ExtensionMsg_GetApplicationInfo(routing_id(), page_id));
+void TabHelper::GetApplicationInfo(WebAppAction action) {
+  NavigationEntry* entry =
+      web_contents()->GetController().GetLastCommittedEntry();
+  if (!entry)
+    return;
+
+  pending_web_app_action_ = action;
+  last_committed_page_id_ = entry->GetPageID();
+
+  Send(new ChromeExtensionMsg_GetApplicationInfo(routing_id()));
 }
 
 void TabHelper::Observe(int type,
                         const content::NotificationSource& source,
                         const content::NotificationDetails& details) {
-  switch (type) {
-    case content::NOTIFICATION_LOAD_STOP: {
-      const NavigationController& controller =
-          *content::Source<NavigationController>(source).ptr();
-      DCHECK_EQ(controller.GetWebContents(), web_contents());
-
-      if (pending_web_app_action_ == UPDATE_SHORTCUT) {
-        // Schedule a shortcut update when web application info is available if
-        // last committed entry is not NULL. Last committed entry could be NULL
-        // when an interstitial page is injected (e.g. bad https certificate,
-        // malware site etc). When this happens, we abort the shortcut update.
-        NavigationEntry* entry = controller.GetLastCommittedEntry();
-        if (entry)
-          GetApplicationInfo(entry->GetPageID());
-        else
-          pending_web_app_action_ = NONE;
-      }
-      break;
-    }
-    case chrome::NOTIFICATION_CRX_INSTALLER_DONE: {
-      if (pending_web_app_action_ != CREATE_HOSTED_APP)
-        return;
-
-      pending_web_app_action_ = NONE;
-
-      const Extension* extension =
-          content::Details<const Extension>(details).ptr();
-      if (!extension ||
-          AppLaunchInfo::GetLaunchWebURL(extension) != web_app_info_.app_url)
-        return;
-
-#if defined(OS_CHROMEOS)
-      ChromeLauncherController::instance()->PinAppWithID(extension->id());
-#endif
-
-      // Android does not implement browser_finder.cc.
-#if !defined(OS_ANDROID)
-      Browser* browser =
-          chrome::FindBrowserWithWebContents(web_contents());
-      if (browser) {
-        browser->window()->ShowBookmarkAppBubble(web_app_info_,
-                                                 extension->id());
-      }
-#endif
-    }
-    case chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR: {
-      if (pending_web_app_action_ == CREATE_HOSTED_APP)
-        pending_web_app_action_ = NONE;
-      break;
-    }
+  DCHECK_EQ(content::NOTIFICATION_LOAD_STOP, type);
+  const NavigationController& controller =
+      *content::Source<NavigationController>(source).ptr();
+  DCHECK_EQ(controller.GetWebContents(), web_contents());
+
+  if (update_shortcut_on_load_complete_) {
+    update_shortcut_on_load_complete_ = false;
+    // Schedule a shortcut update when web application info is available if
+    // last committed entry is not NULL. Last committed entry could be NULL
+    // when an interstitial page is injected (e.g. bad https certificate,
+    // malware site etc). When this happens, we abort the shortcut update.
+    if (controller.GetLastCommittedEntry())
+      GetApplicationInfo(UPDATE_SHORTCUT);
   }
 }