15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/webui/ntp/app_launcher_handler.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "apps/metrics_names.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/auto_reset.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/i18n/rtl.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/field_trial.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h"
171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/prefs/scoped_user_pref_update.h"
18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/browser_process.h"
217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/crx_installer.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_system.h"
25a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/extensions/launch_util.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/favicon/favicon_service_factory.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/ui/app_list/app_list_util.h"
298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "chrome/browser/ui/browser_dialogs.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_finder.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_tabstrip.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_window.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/extensions/application_launch.h"
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/extensions/extension_enable_flow.h"
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h"
36868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/ui/webui/extensions/extension_basic_info.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/webui/extensions/extension_icon_source.h"
38558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "chrome/browser/ui/webui/ntp/core_app_launcher_handler.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/webui/ntp/new_tab_ui.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension_constants.h"
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension_icon_set.h"
42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
439ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "chrome/common/favicon/favicon_types.h"
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h"
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/url_constants.h"
46b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "chrome/common/web_application_info.h"
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h"
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_ui.h"
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/common/favicon_url.h"
50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/app_sorting.h"
51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/management_policy.h"
52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/constants.h"
53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h"
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/browser_resources.h"
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/generated_resources.h"
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "ui/base/webui/web_ui_util.h"
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/favicon_size.h"
597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WebContents;
62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using extensions::AppSorting;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using extensions::CrxInstaller;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using extensions::Extension;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using extensions::ExtensionPrefs;
661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)using extensions::UnloadedExtensionInfo;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ShouldDisplayInNewTabPage(const Extension* app, PrefService* prefs) {
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool blocked_by_policy =
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    (app->id() == extension_misc::kWebStoreAppId ||
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     app->id() == extension_misc::kEnterpriseWebStoreAppId) &&
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    prefs->GetBoolean(prefs::kHideWebStoreIcon);
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return app->ShouldDisplayInNewTabPage() && !blocked_by_policy;
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid RecordAppLauncherPromoHistogram(
797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      apps::AppLauncherPromoHistogramValues value) {
807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK_LT(value, apps::APP_LAUNCHER_PROMO_MAX);
817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  UMA_HISTOGRAM_ENUMERATION(
827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      "Apps.AppLauncherPromo", value, apps::APP_LAUNCHER_PROMO_MAX);
837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
85a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// This is used to avoid a DCHECK due to an unhandled WebUI callback. The
86a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// JavaScript used to switch between pages sends "pageSelected" which is used
87a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// in the context of the NTP for recording metrics we don't need here.
88a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void NoOpCallback(const ListValue* args) {}
89a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AppLauncherHandler::AppInstallInfo::AppInstallInfo() {}
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AppLauncherHandler::AppInstallInfo::~AppInstallInfo() {}
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AppLauncherHandler::AppLauncherHandler(ExtensionService* extension_service)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : extension_service_(extension_service),
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ignore_changes_(false),
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      attempted_bookmark_app_install_(false),
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      has_loaded_apps_(false) {
1014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (IsAppLauncherEnabled())
1027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    RecordAppLauncherPromoHistogram(apps::APP_LAUNCHER_PROMO_ALREADY_INSTALLED);
1034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  else if (ShouldShowAppLauncherPromo())
1047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    RecordAppLauncherPromoHistogram(apps::APP_LAUNCHER_PROMO_SHOWN);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AppLauncherHandler::~AppLauncherHandler() {}
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppLauncherHandler::CreateAppInfo(
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Extension* extension,
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExtensionService* service,
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DictionaryValue* value) {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  value->Clear();
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The Extension class 'helpfully' wraps bidi control characters that
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // impede our ability to determine directionality.
117a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 short_name = UTF8ToUTF16(extension->short_name());
118d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  base::i18n::UnadjustStringForLocaleDirection(&short_name);
119d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  NewTabUI::SetUrlTitleAndDirection(
120d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      value,
121d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      short_name,
122d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      extensions::AppLaunchInfo::GetFullLaunchURL(extension));
123d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
124a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 name = UTF8ToUTF16(extension->name());
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::i18n::UnadjustStringForLocaleDirection(&name);
126d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  NewTabUI::SetFullNameAndDirection(name, value);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool enabled = service->IsExtensionEnabled(extension->id()) &&
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !service->GetTerminatedExtension(extension->id());
130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  extensions::GetExtensionBasicInfo(extension, enabled, value);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  value->SetBoolean("mayDisable", extensions::ExtensionSystem::Get(
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      service->profile())->management_policy()->UserMayModifySettings(
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      extension, NULL));
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool icon_big_exists = true;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Instead of setting grayscale here, we do it in apps_page.js.
138a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  GURL icon_big = extensions::ExtensionIconSource::GetIconURL(
139a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      extension,
140a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      extension_misc::EXTENSION_ICON_LARGE,
141a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      ExtensionIconSet::MATCH_BIGGER,
142a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      false,
143a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      &icon_big_exists);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  value->SetString("icon_big", icon_big.spec());
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  value->SetBoolean("icon_big_exists", icon_big_exists);
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool icon_small_exists = true;
147a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  GURL icon_small = extensions::ExtensionIconSource::GetIconURL(
148a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      extension,
149a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      extension_misc::EXTENSION_ICON_BITTY,
150a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      ExtensionIconSet::MATCH_BIGGER,
151a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      false,
152a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      &icon_small_exists);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  value->SetString("icon_small", icon_small.spec());
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  value->SetBoolean("icon_small_exists", icon_small_exists);
155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  value->SetInteger("launch_container",
156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                    extensions::AppLaunchInfo::GetLaunchContainer(extension));
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionPrefs* prefs = service->extension_prefs();
158a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  value->SetInteger("launch_type", extensions::GetLaunchType(prefs, extension));
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  value->SetBoolean("is_component",
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    extension->location() == extensions::Manifest::COMPONENT);
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  value->SetBoolean("is_webstore",
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      extension->id() == extension_misc::kWebStoreAppId);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
164f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  AppSorting* sorting = prefs->app_sorting();
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  syncer::StringOrdinal page_ordinal = sorting->GetPageOrdinal(extension->id());
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!page_ordinal.IsValid()) {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Make sure every app has a page ordinal (some predate the page ordinal).
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The webstore app should be on the first page.
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    page_ordinal = extension->id() == extension_misc::kWebStoreAppId ?
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sorting->CreateFirstAppPageOrdinal() :
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sorting->GetNaturalAppPageOrdinal();
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sorting->SetPageOrdinal(extension->id(), page_ordinal);
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  value->SetInteger("page_index",
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sorting->PageStringOrdinalAsInteger(page_ordinal));
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  syncer::StringOrdinal app_launch_ordinal =
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sorting->GetAppLaunchOrdinal(extension->id());
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!app_launch_ordinal.IsValid()) {
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Make sure every app has a launch ordinal (some predate the launch
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // ordinal). The webstore's app launch ordinal is always set to the first
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // position.
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    app_launch_ordinal = extension->id() == extension_misc::kWebStoreAppId ?
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sorting->CreateFirstAppLaunchOrdinal(page_ordinal) :
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sorting->CreateNextAppLaunchOrdinal(page_ordinal);
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sorting->SetAppLaunchOrdinal(extension->id(), app_launch_ordinal);
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  value->SetString("app_launch_ordinal", app_launch_ordinal.ToInternalValue());
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppLauncherHandler::RegisterMessages() {
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registrar_.Add(this, chrome::NOTIFICATION_APP_INSTALLED_TO_NTP,
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::Source<WebContents>(web_ui()->GetWebContents()));
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Some tests don't have a local state.
1964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#if defined(ENABLE_APP_LIST)
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (g_browser_process->local_state()) {
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    local_state_pref_change_registrar_.Init(g_browser_process->local_state());
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    local_state_pref_change_registrar_.Add(
2004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        prefs::kShowAppLauncherPromo,
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        base::Bind(&AppLauncherHandler::OnLocalStatePreferenceChanged,
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   base::Unretained(this)));
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
2044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#endif
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->RegisterMessageCallback("getApps",
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&AppLauncherHandler::HandleGetApps,
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this)));
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->RegisterMessageCallback("launchApp",
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&AppLauncherHandler::HandleLaunchApp,
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this)));
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->RegisterMessageCallback("setLaunchType",
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&AppLauncherHandler::HandleSetLaunchType,
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this)));
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->RegisterMessageCallback("uninstallApp",
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&AppLauncherHandler::HandleUninstallApp,
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this)));
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->RegisterMessageCallback("createAppShortcut",
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&AppLauncherHandler::HandleCreateAppShortcut,
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this)));
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->RegisterMessageCallback("reorderApps",
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&AppLauncherHandler::HandleReorderApps,
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this)));
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->RegisterMessageCallback("setPageIndex",
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&AppLauncherHandler::HandleSetPageIndex,
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this)));
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->RegisterMessageCallback("saveAppPageName",
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&AppLauncherHandler::HandleSaveAppPageName,
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this)));
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->RegisterMessageCallback("generateAppForLink",
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&AppLauncherHandler::HandleGenerateAppForLink,
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this)));
232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  web_ui()->RegisterMessageCallback("stopShowingAppLauncherPromo",
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&AppLauncherHandler::StopShowingAppLauncherPromo,
234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)));
235eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  web_ui()->RegisterMessageCallback("onLearnMore",
236eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      base::Bind(&AppLauncherHandler::OnLearnMore,
237eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                 base::Unretained(this)));
238a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  web_ui()->RegisterMessageCallback("pageSelected", base::Bind(&NoOpCallback));
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppLauncherHandler::Observe(int type,
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const content::NotificationSource& source,
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const content::NotificationDetails& details) {
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (type == chrome::NOTIFICATION_APP_INSTALLED_TO_NTP) {
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    highlight_app_id_ = *content::Details<const std::string>(details).ptr();
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (has_loaded_apps_)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SetAppToBeHighlighted();
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ignore_changes_ || !has_loaded_apps_)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (type) {
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case chrome::NOTIFICATION_EXTENSION_LOADED: {
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const Extension* extension =
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          content::Details<const Extension>(details).ptr();
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!extension->is_app())
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
261868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs();
262868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (!ShouldDisplayInNewTabPage(extension, prefs))
263868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        return;
264868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scoped_ptr<DictionaryValue> app_info(GetAppInfo(extension));
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (app_info.get()) {
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        visible_apps_.insert(extension->id());
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ExtensionPrefs* prefs = extension_service_->extension_prefs();
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        scoped_ptr<base::FundamentalValue> highlight(Value::CreateBooleanValue(
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              prefs->IsFromBookmark(extension->id()) &&
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              attempted_bookmark_app_install_));
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        attempted_bookmark_app_install_ = false;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        web_ui()->CallJavascriptFunction(
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            "ntp.appAdded", *app_info, *highlight);
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case chrome::NOTIFICATION_EXTENSION_UNLOADED:
2813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case chrome::NOTIFICATION_EXTENSION_UNINSTALLED: {
2823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      const Extension* extension = NULL;
2833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      bool uninstalled = false;
2843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      if (type == chrome::NOTIFICATION_EXTENSION_UNINSTALLED) {
2853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        extension = content::Details<const Extension>(details).ptr();
2863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        uninstalled = true;
2873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      } else {  // NOTIFICATION_EXTENSION_UNLOADED
2881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        if (content::Details<UnloadedExtensionInfo>(details)->reason ==
2891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)            UnloadedExtensionInfo::REASON_UNINSTALL) {
2903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          // Uninstalls are tracked by NOTIFICATION_EXTENSION_UNINSTALLED.
2913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          return;
2923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        }
2933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        extension = content::Details<extensions::UnloadedExtensionInfo>(
2943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            details)->extension;
2953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        uninstalled = false;
2963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      }
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!extension->is_app())
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
300868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs();
301868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (!ShouldDisplayInNewTabPage(extension, prefs))
302868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        return;
303868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scoped_ptr<DictionaryValue> app_info(GetAppInfo(extension));
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (app_info.get()) {
30658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        if (uninstalled)
30758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          visible_apps_.erase(extension->id());
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        scoped_ptr<base::FundamentalValue> uninstall_value(
3103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            Value::CreateBooleanValue(uninstalled));
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        scoped_ptr<base::FundamentalValue> from_page(
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            Value::CreateBooleanValue(!extension_id_prompting_.empty()));
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        web_ui()->CallJavascriptFunction(
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            "ntp.appRemoved", *app_info, *uninstall_value, *from_page);
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case chrome::NOTIFICATION_EXTENSION_LAUNCHER_REORDERED: {
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::string* id =
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          content::Details<const std::string>(details).ptr();
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (id) {
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const Extension* extension =
323868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            extension_service_->GetInstalledExtension(*id);
3249ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch        if (!extension) {
3259ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch          // Extension could still be downloading or installing.
3269ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch          return;
3279ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch        }
3289ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DictionaryValue app_info;
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CreateAppInfo(extension,
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      extension_service_,
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      &app_info);
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        web_ui()->CallJavascriptFunction("ntp.appMoved", app_info);
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        HandleGetApps(NULL);
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR: {
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CrxInstaller* crx_installer = content::Source<CrxInstaller>(source).ptr();
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!Profile::FromWebUI(web_ui())->IsSameProfile(
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              crx_installer->profile())) {
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Fall through.
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case chrome::NOTIFICATION_EXTENSION_LOAD_ERROR: {
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      attempted_bookmark_app_install_ = false;
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppLauncherHandler::FillAppDictionary(DictionaryValue* dictionary) {
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // CreateAppInfo and ClearOrdinals can change the extension prefs.
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::AutoReset<bool> auto_reset(&ignore_changes_, true);
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ListValue* list = new ListValue();
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs();
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::set<std::string>::iterator it = visible_apps_.begin();
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != visible_apps_.end(); ++it) {
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Extension* extension = extension_service_->GetInstalledExtension(*it);
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (extension && ShouldDisplayInNewTabPage(extension, prefs)) {
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DictionaryValue* app_info = GetAppInfo(extension);
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      list->Append(app_info);
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dictionary->Set("apps", list);
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(estade): remove these settings when the old NTP is removed. The new
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NTP does it in js.
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // App windows are not yet implemented on mac.
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dictionary->SetBoolean("disableAppWindowLaunch", true);
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dictionary->SetBoolean("disableCreateAppShortcut", true);
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS)
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Making shortcut does not make sense on ChromeOS because it does not have
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a desktop.
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dictionary->SetBoolean("disableCreateAppShortcut", true);
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ListValue* app_page_names = prefs->GetList(prefs::kNtpAppPageNames);
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!app_page_names || !app_page_names->GetSize()) {
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ListPrefUpdate update(prefs, prefs::kNtpAppPageNames);
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ListValue* list = update.Get();
392a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    list->Set(0, new base::StringValue(
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        l10n_util::GetStringUTF16(IDS_APP_DEFAULT_PAGE_NAME)));
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dictionary->Set("appPageNames",
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    static_cast<ListValue*>(list->DeepCopy()));
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dictionary->Set("appPageNames",
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    static_cast<ListValue*>(app_page_names->DeepCopy()));
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DictionaryValue* AppLauncherHandler::GetAppInfo(const Extension* extension) {
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DictionaryValue* app_info = new DictionaryValue();
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // CreateAppInfo can change the extension prefs.
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::AutoReset<bool> auto_reset(&ignore_changes_, true);
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CreateAppInfo(extension,
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                extension_service_,
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                app_info);
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return app_info;
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppLauncherHandler::HandleGetApps(const ListValue* args) {
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DictionaryValue dictionary;
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Tell the client whether to show the promo for this view. We don't do this
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in the case of PREF_CHANGED because:
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a) At that point in time, depending on the pref that changed, it can look
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //    like the set of apps installed has changed, and we will mark the promo
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //    expired.
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // b) Conceptually, it doesn't really make sense to count a
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //    prefchange-triggered refresh as a promo 'view'.
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Profile* profile = Profile::FromWebUI(web_ui());
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The first time we load the apps we must add all current app to the list
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // of apps visible on the NTP.
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!has_loaded_apps_) {
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ExtensionSet* extensions = extension_service_->extensions();
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (ExtensionSet::const_iterator it = extensions->begin();
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         it != extensions->end(); ++it) {
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      visible_apps_.insert((*it)->id());
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extensions = extension_service_->disabled_extensions();
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (ExtensionSet::const_iterator it = extensions->begin();
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         it != extensions->end(); ++it) {
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      visible_apps_.insert((*it)->id());
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extensions = extension_service_->terminated_extensions();
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (ExtensionSet::const_iterator it = extensions->begin();
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         it != extensions->end(); ++it) {
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      visible_apps_.insert((*it)->id());
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetAppToBeHighlighted();
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FillAppDictionary(&dictionary);
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->CallJavascriptFunction("ntp.getAppsCallback", dictionary);
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First time we get here we set up the observer so that we can tell update
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the apps as they change.
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!has_loaded_apps_) {
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::Closure callback = base::Bind(
455c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        &AppLauncherHandler::OnExtensionPreferenceChanged,
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Unretained(this));
457c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    extension_pref_change_registrar_.Init(
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        extension_service_->extension_prefs()->pref_service());
4593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    extension_pref_change_registrar_.Add(prefs::kExtensionsPref, callback);
460c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    extension_pref_change_registrar_.Add(prefs::kNtpAppPageNames, callback);
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED,
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        content::Source<Profile>(profile));
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        content::Source<Profile>(profile));
4663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNINSTALLED,
4673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        content::Source<Profile>(profile));
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LAUNCHER_REORDERED,
469f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        content::Source<AppSorting>(
470f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            extension_service_->extension_prefs()->app_sorting()));
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR,
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        content::Source<CrxInstaller>(NULL));
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOAD_ERROR,
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        content::Source<Profile>(profile));
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  has_loaded_apps_ = true;
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppLauncherHandler::HandleLaunchApp(const ListValue* args) {
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string extension_id;
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(args->GetString(0, &extension_id));
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double source = -1.0;
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(args->GetDouble(1, &source));
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url;
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (args->GetSize() > 2)
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(args->GetString(2, &url));
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extension_misc::AppLaunchBucket launch_bucket =
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<extension_misc::AppLaunchBucket>(
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          static_cast<int>(source));
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(launch_bucket >= 0 &&
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        launch_bucket < extension_misc::APP_LAUNCH_BUCKET_BOUNDARY);
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Extension* extension =
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      extension_service_->GetExtensionById(extension_id, false);
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Prompt the user to re-enable the application if disabled.
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!extension) {
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PromptToEnableApp(extension_id);
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Profile* profile = extension_service_->profile();
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WindowOpenDisposition disposition = args->GetSize() > 3 ?
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        webui::GetDispositionFromClick(args, 3) : CURRENT_TAB;
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (extension_id != extension_misc::kWebStoreAppId) {
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CHECK_NE(launch_bucket, extension_misc::APP_LAUNCH_BUCKET_INVALID);
510558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    CoreAppLauncherHandler::RecordAppLaunchType(launch_bucket,
511558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch                                                extension->GetType());
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
513a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    CoreAppLauncherHandler::RecordWebStoreLaunch();
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (disposition == NEW_FOREGROUND_TAB || disposition == NEW_BACKGROUND_TAB ||
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      disposition == NEW_WINDOW) {
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(jamescook): Proper support for background tabs.
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AppLaunchParams params(profile, extension,
5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           disposition == NEW_WINDOW ?
521a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                               extensions::LAUNCH_CONTAINER_WINDOW :
522a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                               extensions::LAUNCH_CONTAINER_TAB,
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           disposition);
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    params.override_url = GURL(url);
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OpenApplication(params);
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // To give a more "launchy" experience when using the NTP launcher, we close
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // it automatically.
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Browser* browser = chrome::FindBrowserWithWebContents(
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        web_ui()->GetWebContents());
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebContents* old_contents = NULL;
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (browser)
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      old_contents = browser->tab_strip_model()->GetActiveWebContents();
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AppLaunchParams params(profile, extension,
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           old_contents ? CURRENT_TAB : NEW_FOREGROUND_TAB);
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    params.override_url = GURL(url);
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebContents* new_contents = OpenApplication(params);
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This will also destroy the handler, so do not perform any actions after.
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (new_contents != old_contents && browser &&
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        browser->tab_strip_model()->count() > 1) {
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      chrome::CloseWebContents(browser, old_contents, true);
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppLauncherHandler::HandleSetLaunchType(const ListValue* args) {
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string extension_id;
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double launch_type;
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(args->GetString(0, &extension_id));
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(args->GetDouble(1, &launch_type));
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Extension* extension =
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      extension_service_->GetExtensionById(extension_id, true);
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!extension)
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't update the page; it already knows about the launch type change.
5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::AutoReset<bool> auto_reset(&ignore_changes_, true);
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
562a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  extensions::SetLaunchType(
563a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      extension_service_->extension_prefs(),
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      extension_id,
565a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      static_cast<extensions::LaunchType>(
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          static_cast<int>(launch_type)));
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppLauncherHandler::HandleUninstallApp(const ListValue* args) {
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string extension_id;
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(args->GetString(0, &extension_id));
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  const Extension* extension = extension_service_->GetInstalledExtension(
5748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      extension_id);
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!extension)
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!extensions::ExtensionSystem::Get(extension_service_->profile())->
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          management_policy()->UserMayModifySettings(extension, NULL)) {
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Attempt to uninstall an extension that is non-usermanagable "
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << "was made. Extension id : " << extension->id();
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!extension_id_prompting_.empty())
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;  // Only one prompt at a time.
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extension_id_prompting_ = extension_id;
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool dont_confirm = false;
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (args->GetBoolean(1, &dont_confirm) && dont_confirm) {
5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::AutoReset<bool> auto_reset(&ignore_changes_, true);
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExtensionUninstallAccepted();
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GetExtensionUninstallDialog()->ConfirmUninstall(extension);
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppLauncherHandler::HandleCreateAppShortcut(const ListValue* args) {
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string extension_id;
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(args->GetString(0, &extension_id));
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Extension* extension =
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      extension_service_->GetExtensionById(extension_id, true);
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!extension)
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Browser* browser = chrome::FindBrowserWithWebContents(
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        web_ui()->GetWebContents());
6098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  chrome::ShowCreateChromeAppShortcutsDialog(
6108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      browser->window()->GetNativeWindow(), browser->profile(), extension,
6118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      base::Closure());
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppLauncherHandler::HandleReorderApps(const ListValue* args) {
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(args->GetSize() == 2);
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string dragged_app_id;
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ListValue* app_order;
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(args->GetString(0, &dragged_app_id));
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(args->GetList(1, &app_order));
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string predecessor_to_moved_ext;
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string successor_to_moved_ext;
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < app_order->GetSize(); ++i) {
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string value;
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (app_order->GetString(i, &value) && value == dragged_app_id) {
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (i > 0)
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CHECK(app_order->GetString(i - 1, &predecessor_to_moved_ext));
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (i + 1 < app_order->GetSize())
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CHECK(app_order->GetString(i + 1, &successor_to_moved_ext));
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't update the page; it already knows the apps have been reordered.
6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::AutoReset<bool> auto_reset(&ignore_changes_, true);
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extension_service_->extension_prefs()->SetAppDraggedByUser(dragged_app_id);
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extension_service_->OnExtensionMoved(dragged_app_id,
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       predecessor_to_moved_ext,
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       successor_to_moved_ext);
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppLauncherHandler::HandleSetPageIndex(const ListValue* args) {
644f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  AppSorting* app_sorting =
645f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      extension_service_->extension_prefs()->app_sorting();
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string extension_id;
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double page_index;
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(args->GetString(0, &extension_id));
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(args->GetDouble(1, &page_index));
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const syncer::StringOrdinal& page_ordinal =
652f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      app_sorting->PageIntegerAsStringOrdinal(static_cast<size_t>(page_index));
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't update the page; it already knows the apps have been reordered.
6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::AutoReset<bool> auto_reset(&ignore_changes_, true);
656f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  app_sorting->SetPageOrdinal(extension_id, page_ordinal);
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppLauncherHandler::HandleSaveAppPageName(const ListValue* args) {
660a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 name;
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(args->GetString(0, &name));
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double page_index;
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(args->GetDouble(1, &page_index));
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::AutoReset<bool> auto_reset(&ignore_changes_, true);
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs();
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ListPrefUpdate update(prefs, prefs::kNtpAppPageNames);
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ListValue* list = update.Get();
670a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  list->Set(static_cast<size_t>(page_index), new base::StringValue(name));
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppLauncherHandler::HandleGenerateAppForLink(const ListValue* args) {
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url;
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(args->GetString(0, &url));
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL launch_url(url);
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
678a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 title;
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(args->GetString(1, &title));
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double page_index;
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(args->GetDouble(2, &page_index));
683f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  AppSorting* app_sorting =
684f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      extension_service_->extension_prefs()->app_sorting();
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const syncer::StringOrdinal& page_ordinal =
686f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      app_sorting->PageIntegerAsStringOrdinal(static_cast<size_t>(page_index));
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Profile* profile = Profile::FromWebUI(web_ui());
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FaviconService* favicon_service =
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FaviconServiceFactory::GetForProfile(profile, Profile::EXPLICIT_ACCESS);
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!favicon_service) {
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "No favicon service";
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<AppInstallInfo> install_info(new AppInstallInfo());
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  install_info->is_bookmark_app = true;
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  install_info->title = title;
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  install_info->app_url = launch_url;
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  install_info->page_ordinal = page_ordinal;
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  favicon_service->GetFaviconImageForURL(
703f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      FaviconService::FaviconForURLParams(launch_url,
70490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                          chrome::FAVICON,
7052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                          gfx::kFaviconSize),
7062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&AppLauncherHandler::OnFaviconForApp,
7072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 base::Unretained(this),
7082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 base::Passed(&install_info)),
7092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      &cancelable_task_tracker_);
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
712c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AppLauncherHandler::StopShowingAppLauncherPromo(
713c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::ListValue* args) {
7144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#if defined(ENABLE_APP_LIST)
715c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  g_browser_process->local_state()->SetBoolean(
7164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      prefs::kShowAppLauncherPromo, false);
717eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  RecordAppLauncherPromoHistogram(apps::APP_LAUNCHER_PROMO_DISMISSED);
7184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#endif
719eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
720eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
721eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid AppLauncherHandler::OnLearnMore(const base::ListValue* args) {
722eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  RecordAppLauncherPromoHistogram(apps::APP_LAUNCHER_PROMO_LEARN_MORE);
723c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
724c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppLauncherHandler::OnFaviconForApp(
7262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<AppInstallInfo> install_info,
72790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const chrome::FaviconImageResult& image_result) {
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<WebApplicationInfo> web_app(new WebApplicationInfo());
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_app->is_bookmark_app = install_info->is_bookmark_app;
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_app->title = install_info->title;
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_app->app_url = install_info->app_url;
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_app->urls.push_back(install_info->app_url);
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!image_result.image.IsEmpty()) {
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebApplicationInfo::IconInfo icon;
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    icon.data = image_result.image.AsBitmap();
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    icon.width = icon.data.width();
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    icon.height = icon.data.height();
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    web_app->icons.push_back(icon);
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<CrxInstaller> installer(
743ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      CrxInstaller::CreateSilent(extension_service_));
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  installer->set_error_on_unsupported_requirements(true);
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  installer->set_page_ordinal(install_info->page_ordinal);
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  installer->InstallWebApp(*web_app);
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  attempted_bookmark_app_install_ = true;
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppLauncherHandler::SetAppToBeHighlighted() {
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (highlight_app_id_.empty())
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StringValue app_id(highlight_app_id_);
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->CallJavascriptFunction("ntp.setAppToBeHighlighted", app_id);
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  highlight_app_id_.clear();
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
759c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AppLauncherHandler::OnExtensionPreferenceChanged() {
7602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DictionaryValue dictionary;
7612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FillAppDictionary(&dictionary);
7622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  web_ui()->CallJavascriptFunction("ntp.appsPrefChangeCallback", dictionary);
7632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
765c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AppLauncherHandler::OnLocalStatePreferenceChanged() {
7664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#if defined(ENABLE_APP_LIST)
767c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  web_ui()->CallJavascriptFunction(
768c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "ntp.appLauncherPromoPrefChangeCallback",
769c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::FundamentalValue(g_browser_process->local_state()->GetBoolean(
7704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          prefs::kShowAppLauncherPromo)));
7714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#endif
772c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
773c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppLauncherHandler::CleanupAfterUninstall() {
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extension_id_prompting_.clear();
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppLauncherHandler::PromptToEnableApp(const std::string& extension_id) {
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!extension_id_prompting_.empty())
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;  // Only one prompt at a time.
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extension_id_prompting_ = extension_id;
7832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  extension_enable_flow_.reset(new ExtensionEnableFlow(
7842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Profile::FromWebUI(web_ui()), extension_id, this));
7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  extension_enable_flow_->StartForWebContents(web_ui()->GetWebContents());
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppLauncherHandler::ExtensionUninstallAccepted() {
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Do the uninstall work here.
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!extension_id_prompting_.empty());
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The extension can be uninstalled in another window while the UI was
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // showing. Do nothing in that case.
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Extension* extension =
7958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      extension_service_->GetInstalledExtension(extension_id_prompting_);
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!extension)
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extension_service_->UninstallExtension(extension_id_prompting_,
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         false /* external_uninstall */, NULL);
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CleanupAfterUninstall();
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppLauncherHandler::ExtensionUninstallCanceled() {
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CleanupAfterUninstall();
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AppLauncherHandler::ExtensionEnableFlowFinished() {
8092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(extension_id_prompting_, extension_enable_flow_->extension_id());
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We bounce this off the NTP so the browser can update the apps icon.
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we don't launch the app asynchronously, then the app's disabled
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // icon disappears but isn't replaced by the enabled icon, making a poor
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // visual experience.
8152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StringValue app_id(extension_id_prompting_);
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->CallJavascriptFunction("ntp.launchAppAfterEnable", app_id);
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  extension_enable_flow_.reset();
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extension_id_prompting_ = "";
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AppLauncherHandler::ExtensionEnableFlowAborted(bool user_initiated) {
8232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(extension_id_prompting_, extension_enable_flow_->extension_id());
8242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We record the histograms here because ExtensionUninstallCanceled is also
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // called when the extension uninstall dialog is canceled.
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Extension* extension =
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      extension_service_->GetExtensionById(extension_id_prompting_, true);
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string histogram_name = user_initiated ?
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Extensions.Permissions_ReEnableCancel" :
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Extensions.Permissions_ReEnableAbort";
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionService::RecordPermissionMessagesHistogram(
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      extension, histogram_name.c_str());
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  extension_enable_flow_.reset();
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CleanupAfterUninstall();
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionUninstallDialog* AppLauncherHandler::GetExtensionUninstallDialog() {
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!extension_uninstall_dialog_.get()) {
8412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Browser* browser = chrome::FindBrowserWithWebContents(
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        web_ui()->GetWebContents());
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extension_uninstall_dialog_.reset(
8442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        ExtensionUninstallDialog::Create(extension_service_->profile(),
8452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         browser, this));
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return extension_uninstall_dialog_.get();
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
849