summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/browser_init.cc3
-rw-r--r--chrome/browser/browser_resources.grd3
-rw-r--r--chrome/browser/dom_ui/app_launcher_handler.cc16
-rw-r--r--chrome/browser/dom_ui/app_launcher_handler.h3
-rw-r--r--chrome/browser/dom_ui/new_tab_ui.cc12
-rw-r--r--chrome/browser/dom_ui/ntp_resource_cache.cc5
-rw-r--r--chrome/browser/extensions/default_apps.cc105
-rw-r--r--chrome/browser/extensions/default_apps.h83
-rw-r--r--chrome/browser/extensions/default_apps_unittest.cc132
-rw-r--r--chrome/browser/extensions/extension_updater.cc6
-rw-r--r--chrome/browser/extensions/extension_updater_unittest.cc13
-rw-r--r--chrome/browser/extensions/extensions_service.cc82
-rw-r--r--chrome/browser/extensions/extensions_service.h30
-rw-r--r--chrome/browser/extensions/extensions_service_unittest.cc2
-rw-r--r--chrome/browser/profile_impl.cc68
-rw-r--r--chrome/browser/profile_impl.h3
-rw-r--r--chrome/browser/resources/calendar_app/128.pngbin11807 -> 0 bytes
-rw-r--r--chrome/browser/resources/calendar_app/24.pngbin3798 -> 0 bytes
-rw-r--r--chrome/browser/resources/calendar_app/32.pngbin4325 -> 0 bytes
-rw-r--r--chrome/browser/resources/calendar_app/48.pngbin5299 -> 0 bytes
-rw-r--r--chrome/browser/resources/calendar_app/manifest.json24
-rw-r--r--chrome/browser/resources/docs_app/128.pngbin12522 -> 0 bytes
-rw-r--r--chrome/browser/resources/docs_app/24.pngbin3815 -> 0 bytes
-rw-r--r--chrome/browser/resources/docs_app/32.pngbin4425 -> 0 bytes
-rw-r--r--chrome/browser/resources/docs_app/48.pngbin5426 -> 0 bytes
-rw-r--r--chrome/browser/resources/docs_app/manifest.json44
-rw-r--r--chrome/browser/resources/gmail_app/128.pngbin12096 -> 0 bytes
-rw-r--r--chrome/browser/resources/gmail_app/24.pngbin3717 -> 0 bytes
-rw-r--r--chrome/browser/resources/gmail_app/32.pngbin4241 -> 0 bytes
-rw-r--r--chrome/browser/resources/gmail_app/48.pngbin5194 -> 0 bytes
-rw-r--r--chrome/browser/resources/gmail_app/manifest.json25
-rw-r--r--chrome/browser/resources/new_new_tab.html3
-rw-r--r--chrome/browser/resources/new_new_tab.js6
-rw-r--r--chrome/browser/resources/ntp/apps.css8
-rw-r--r--chrome/browser/resources/ntp/apps.js4
-rw-r--r--chrome/browser/shell_integration.cc2
-rw-r--r--chrome/browser/utility_process_host.cc3
-rw-r--r--chrome/chrome_browser.gypi37
-rw-r--r--chrome/chrome_dll.gypi3
-rw-r--r--chrome/chrome_tests.gypi1
-rw-r--r--chrome/common/chrome_switches.cc15
-rw-r--r--chrome/common/chrome_switches.h4
-rw-r--r--chrome/common/extensions/extension.cc16
-rw-r--r--chrome/common/extensions/extension.h14
-rw-r--r--chrome/common/extensions/extension_manifests_unittest.cc12
-rw-r--r--chrome/common/pref_names.cc7
-rw-r--r--chrome/common/pref_names.h2
-rw-r--r--chrome/installer/mini_installer/chrome.release3
48 files changed, 524 insertions, 275 deletions
diff --git a/chrome/browser/browser_init.cc b/chrome/browser/browser_init.cc
index 115eb41..621bb4e 100644
--- a/chrome/browser/browser_init.cc
+++ b/chrome/browser/browser_init.cc
@@ -587,8 +587,7 @@ bool BrowserInit::LaunchWithProfile::IsAppLaunch(std::string* app_url,
*app_url = command_line_.GetSwitchValueASCII(switches::kApp);
return true;
}
- if (!command_line_.HasSwitch(switches::kDisableApps) &&
- command_line_.HasSwitch(switches::kAppId)) {
+ if (command_line_.HasSwitch(switches::kAppId)) {
if (app_id)
*app_id = command_line_.GetSwitchValueASCII(switches::kAppId);
return true;
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd
index ed89389..f981d4f 100644
--- a/chrome/browser/browser_resources.grd
+++ b/chrome/browser/browser_resources.grd
@@ -24,9 +24,7 @@ without changes to the corresponding grd file. eter -->
<include name="IDR_ABOUT_SYNC_HTML" file="sync\resources\about_sync.html" flattenhtml="true" type="BINDATA" />
<include name="IDR_ABOUT_VERSION_HTML" file="resources\about_version.html" flattenhtml="true" type="BINDATA" />
<include name="IDR_BOOKMARKS_MANIFEST" file="resources\bookmark_manager\manifest.json" type="BINDATA" />
- <include name="IDR_CALENDAR_APP_MANIFEST" file="resources\calendar_app\manifest.json" type="BINDATA" />
<include name="IDR_CREDITS_HTML" file="resources\about_credits.html" flattenhtml="true" type="BINDATA" />
- <include name="IDR_DOCS_APP_MANIFEST" file="resources\docs_app\manifest.json" type="BINDATA" />
<include name="IDR_DOWNLOADS_HTML" file="resources\downloads.html" flattenhtml="true" type="BINDATA" />
<if expr="os == 'darwin'">
<include name="IDR_EXTENSIONS_INFOBAR_CSS" file="resources\extensions_infobar_mac.css" flattenhtml="true" type="BINDATA" />
@@ -36,7 +34,6 @@ without changes to the corresponding grd file. eter -->
</if>
<include name="IDR_EXTENSIONS_UI_HTML" file="resources\extensions_ui.html" flattenhtml="true" type="BINDATA" />
<include name="IDR_GAIA_LOGIN_HTML" file="sync\resources\gaia_login.html" flattenhtml="true" type="BINDATA" />
- <include name="IDR_GMAIL_APP_MANIFEST" file="resources\gmail_app\manifest.json" type="BINDATA" />
<include name="IDR_HISTORY_HTML" file="resources\history.html" flattenhtml="true" type="BINDATA" />
<include name="IDR_HISTORY2_HTML" file="resources\history2.html" flattenhtml="true" type="BINDATA" />
<include name="IDR_INCOGNITO_TAB_HTML" file="resources\incognito_tab.html" flattenhtml="true" type="BINDATA" />
diff --git a/chrome/browser/dom_ui/app_launcher_handler.cc b/chrome/browser/dom_ui/app_launcher_handler.cc
index 9c867d1..e834754 100644
--- a/chrome/browser/dom_ui/app_launcher_handler.cc
+++ b/chrome/browser/dom_ui/app_launcher_handler.cc
@@ -12,9 +12,11 @@
#include "chrome/browser/app_launched_animation.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
+#include "chrome/browser/extensions/default_apps.h"
#include "chrome/browser/extensions/extension_prefs.h"
#include "chrome/browser/extensions/extensions_service.h"
#include "chrome/browser/platform_util.h"
+#include "chrome/browser/profile.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/extension.h"
@@ -73,6 +75,8 @@ void AppLauncherHandler::RegisterMessages() {
NewCallback(this, &AppLauncherHandler::HandleSetLaunchType));
dom_ui_->RegisterMessageCallback("uninstallApp",
NewCallback(this, &AppLauncherHandler::HandleUninstallApp));
+ dom_ui_->RegisterMessageCallback("hideAppsPromo",
+ NewCallback(this, &AppLauncherHandler::HandleHideAppsPromo));
}
void AppLauncherHandler::Observe(NotificationType type,
@@ -133,6 +137,14 @@ void AppLauncherHandler::FillAppDictionary(DictionaryValue* dictionary) {
}
}
dictionary->Set("apps", list);
+
+ DefaultApps* default_apps = extensions_service_->default_apps();
+ if (default_apps->ShouldShowPromo(extensions_service_->GetAppIds())) {
+ dictionary->SetBoolean("showPromo", true);
+ default_apps->DidShowPromo();
+ } else {
+ dictionary->SetBoolean("showPromo", false);
+ }
}
void AppLauncherHandler::HandleGetApps(const ListValue* args) {
@@ -245,6 +257,10 @@ void AppLauncherHandler::HandleUninstallApp(const ListValue* args) {
GetExtensionInstallUI()->ConfirmUninstall(this, extension);
}
+void AppLauncherHandler::HandleHideAppsPromo(const ListValue* args) {
+ extensions_service_->default_apps()->SetPromoHidden();
+}
+
ExtensionInstallUI* AppLauncherHandler::GetExtensionInstallUI() {
if (!install_ui_.get())
install_ui_.reset(new ExtensionInstallUI(dom_ui_->GetProfile()));
diff --git a/chrome/browser/dom_ui/app_launcher_handler.h b/chrome/browser/dom_ui/app_launcher_handler.h
index 23c1753..c3ca622 100644
--- a/chrome/browser/dom_ui/app_launcher_handler.h
+++ b/chrome/browser/dom_ui/app_launcher_handler.h
@@ -61,6 +61,9 @@ class AppLauncherHandler
// Callback for the "uninstallApp" message.
void HandleUninstallApp(const ListValue* args);
+ // Callback for the "hideAppPromo" message.
+ void HandleHideAppsPromo(const ListValue* args);
+
private:
// ExtensionInstallUI::Delegate implementation, used for receiving
// notification about uninstall confirmation dialog selections.
diff --git a/chrome/browser/dom_ui/new_tab_ui.cc b/chrome/browser/dom_ui/new_tab_ui.cc
index 047efdc..6d9ac9d 100644
--- a/chrome/browser/dom_ui/new_tab_ui.cc
+++ b/chrome/browser/dom_ui/new_tab_ui.cc
@@ -441,13 +441,11 @@ NewTabUI::NewTabUI(TabContents* contents)
AddMessageHandler((new MetricsHandler())->Attach(this));
if (GetProfile()->IsSyncAccessible())
AddMessageHandler((new NewTabPageSyncHandler())->Attach(this));
- if (Extension::AppsAreEnabled()) {
- ExtensionsService* service = GetProfile()->GetExtensionsService();
- // We might not have an ExtensionsService (on ChromeOS when not logged in
- // for example).
- if (service)
- AddMessageHandler((new AppLauncherHandler(service))->Attach(this));
- }
+ ExtensionsService* service = GetProfile()->GetExtensionsService();
+ // We might not have an ExtensionsService (on ChromeOS when not logged in
+ // for example).
+ if (service)
+ AddMessageHandler((new AppLauncherHandler(service))->Attach(this));
AddMessageHandler((new NewTabPageSetHomePageHandler())->Attach(this));
}
diff --git a/chrome/browser/dom_ui/ntp_resource_cache.cc b/chrome/browser/dom_ui/ntp_resource_cache.cc
index 9e05662..571a71c 100644
--- a/chrome/browser/dom_ui/ntp_resource_cache.cc
+++ b/chrome/browser/dom_ui/ntp_resource_cache.cc
@@ -11,7 +11,6 @@
#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "app/theme_provider.h"
-#include "base/command_line.h"
#include "base/file_util.h"
#include "base/ref_counted_memory.h"
#include "base/string16.h"
@@ -304,10 +303,6 @@ void NTPResourceCache::CreateNewTabHTML() {
localized_strings.SetString("appspromotext2",
l10n_util::GetStringUTF16(IDS_APPS_PROMO_TEXT_2));
- localized_strings.SetString("appspromovisible",
- CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kForceAppsPromoVisible) ? "true" : "false");
-
// Don't initiate the sync related message passing with the page if the sync
// code is not present.
if (profile_->GetProfileSyncService())
diff --git a/chrome/browser/extensions/default_apps.cc b/chrome/browser/extensions/default_apps.cc
new file mode 100644
index 0000000..5614dfb
--- /dev/null
+++ b/chrome/browser/extensions/default_apps.cc
@@ -0,0 +1,105 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/default_apps.h"
+
+#include "base/command_line.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
+
+const int DefaultApps::kAppsPromoCounterMax = 10;
+
+// static
+void DefaultApps::RegisterUserPrefs(PrefService* prefs) {
+ prefs->RegisterBooleanPref(prefs::kDefaultAppsInstalled, false);
+ prefs->RegisterIntegerPref(prefs::kAppsPromoCounter, 0);
+}
+
+DefaultApps::DefaultApps(PrefService* prefs)
+ : prefs_(prefs) {
+ // gmail, calendar, docs
+ ids_.insert("pjkljhegncpnkpknbcohdijeoejaedia");
+ ids_.insert("ejjicmeblgpmajnghnpcppodonldlgfn");
+ ids_.insert("apdfllckaahabafndbhieahigkjlhalf");
+}
+
+const ExtensionIdSet* DefaultApps::GetAppsToInstall() const {
+ if (GetDefaultAppsInstalled())
+ return NULL;
+ else
+ return &ids_;
+}
+
+void DefaultApps::DidInstallApp(const ExtensionIdSet& installed_ids) {
+ // If all the default apps have been installed, stop trying to install them.
+ // Note that we use std::includes here instead of == because apps might have
+ // been manually installed while the the default apps were installing and we
+ // wouldn't want to keep trying to install them in that case.
+ if (!GetDefaultAppsInstalled() &&
+ std::includes(installed_ids.begin(), installed_ids.end(),
+ ids_.begin(), ids_.end())) {
+ SetDefaultAppsInstalled(true);
+ }
+}
+
+bool DefaultApps::ShouldShowPromo(const ExtensionIdSet& installed_ids) {
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kForceAppsPromoVisible)) {
+ return true;
+ }
+
+ if (GetDefaultAppsInstalled() && GetPromoCounter() < kAppsPromoCounterMax) {
+ // If we have the exact set of default apps, show the promo. If we don't
+ // have the exact set of default apps, this means that the user manually
+ // installed one. The promo doesn't make sense if it shows apps the user
+ // manually installed, so expire it immediately in that situation.
+ if (installed_ids == ids_)
+ return true;
+ else
+ SetPromoHidden();
+ }
+
+ return false;
+}
+
+void DefaultApps::DidShowPromo() {
+ if (!GetDefaultAppsInstalled()) {
+ NOTREACHED() << "Should not show promo until default apps are installed.";
+ return;
+ }
+
+ int promo_counter = GetPromoCounter();
+ if (promo_counter == kAppsPromoCounterMax) {
+ NOTREACHED() << "Promo has already been shown the maximum number of times.";
+ return;
+ }
+
+ if (promo_counter < kAppsPromoCounterMax)
+ SetPromoCounter(++promo_counter);
+ else
+ SetPromoHidden();
+}
+
+void DefaultApps::SetPromoHidden() {
+ SetPromoCounter(kAppsPromoCounterMax);
+}
+
+int DefaultApps::GetPromoCounter() const {
+ return prefs_->GetInteger(prefs::kAppsPromoCounter);
+}
+
+void DefaultApps::SetPromoCounter(int val) {
+ prefs_->SetInteger(prefs::kAppsPromoCounter, val);
+ prefs_->ScheduleSavePersistentPrefs();
+}
+
+bool DefaultApps::GetDefaultAppsInstalled() const {
+ return prefs_->GetBoolean(prefs::kDefaultAppsInstalled);
+}
+
+void DefaultApps::SetDefaultAppsInstalled(bool val) {
+ prefs_->SetBoolean(prefs::kDefaultAppsInstalled, val);
+ prefs_->ScheduleSavePersistentPrefs();
+}
diff --git a/chrome/browser/extensions/default_apps.h b/chrome/browser/extensions/default_apps.h
new file mode 100644
index 0000000..f61539f
--- /dev/null
+++ b/chrome/browser/extensions/default_apps.h
@@ -0,0 +1,83 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_DEFAULT_APPS_H_
+#define CHROME_BROWSER_EXTENSIONS_DEFAULT_APPS_H_
+#pragma once
+
+#include <set>
+#include <string>
+#include "chrome/common/extensions/extension.h"
+#include "base/gtest_prod_util.h"
+
+class PrefService;
+
+// Manages the installation of the set of default apps into Chrome, and the
+// promotion of those apps in the launcher.
+//
+// It implements the following rules:
+//
+// - Only install default apps once per-profile.
+// - Don't install default apps if any apps are already installed.
+// - Do not start showing the promo until all default apps have been installed.
+// - Do not show the promo if it has been hidden by the user.
+// - Do not show promo after one app has been manually installed or uninstalled.
+// - Do not show promo if the set of installed apps is different than the set of
+// default apps.
+// - Only show promo a certain amount of times.
+//
+// The promo can also be forced on with --force-apps-promo-visible.
+class DefaultApps {
+ public:
+ // The maximum number of times to show the apps promo.
+ static const int kAppsPromoCounterMax;
+
+ // Register our preferences.
+ static void RegisterUserPrefs(PrefService* prefs);
+
+ explicit DefaultApps(PrefService* prefs);
+
+ // Gets the list of default apps that should be installed. Can return NULL if
+ // no apps need to be installed.
+ const ExtensionIdSet* GetAppsToInstall() const;
+
+ // Should be called after each app is installed. Once installed_ids contains
+ // all the default apps, GetAppsToInstall() will start returning NULL.
+ void DidInstallApp(const ExtensionIdSet& installed_ids);
+
+ // Returns true if the apps promo should be displayed in the launcher. This
+ // starts returning true once the default apps have all been installed and
+ // stops after the promo expires.
+ bool ShouldShowPromo(const ExtensionIdSet& installed_ids);
+
+ // Should be called after each time the promo is installed.
+ void DidShowPromo();
+
+ // Force the promo to be hidden.
+ void SetPromoHidden();
+
+ private:
+ FRIEND_TEST_ALL_PREFIXES(DefaultApps, Basics);
+ FRIEND_TEST_ALL_PREFIXES(DefaultApps, HidePromo);
+ FRIEND_TEST_ALL_PREFIXES(DefaultApps, InstallingAnAppHidesPromo);
+ FRIEND_TEST_ALL_PREFIXES(DefaultApps,
+ ManualAppInstalledWhileInstallingDefaultApps);
+
+ bool GetDefaultAppsInstalled() const;
+ void SetDefaultAppsInstalled(bool val);
+
+ int GetPromoCounter() const;
+ void SetPromoCounter(int val);
+
+ // Our permanent state is stored in this PrefService instance.
+ PrefService* prefs_;
+
+ // The set of default extensions. Initialized to a static list in the
+ // constructor.
+ ExtensionIdSet ids_;
+
+ DISALLOW_COPY_AND_ASSIGN(DefaultApps);
+};
+
+#endif // CHROME_BROWSER_EXTENSIONS_DEFAULT_APPS_H_
diff --git a/chrome/browser/extensions/default_apps_unittest.cc b/chrome/browser/extensions/default_apps_unittest.cc
new file mode 100644
index 0000000..9e7b0d5
--- /dev/null
+++ b/chrome/browser/extensions/default_apps_unittest.cc
@@ -0,0 +1,132 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/default_apps.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/test/testing_pref_service.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+TEST(DefaultApps, Basics) {
+ TestingPrefService pref_service;
+ DefaultApps::RegisterUserPrefs(&pref_service);
+ DefaultApps default_apps(&pref_service);
+
+ ExtensionIdSet default_app_ids = *default_apps.GetAppsToInstall();
+ ASSERT_GT(default_app_ids.size(), 0u);
+ EXPECT_FALSE(default_apps.GetDefaultAppsInstalled());
+ EXPECT_EQ(0, default_apps.GetPromoCounter());
+
+ // The promo should not be shown until the default apps have been installed.
+ ExtensionIdSet installed_app_ids;
+ EXPECT_FALSE(default_apps.ShouldShowPromo(installed_app_ids));
+
+ // Simulate installing the apps one by one and notifying default_apps after
+ // each intallation. Nothing should change until we have installed all the
+ // default apps.
+ ExtensionIdSet extension_id_sets[] = {
+ default_app_ids,
+ default_app_ids,
+ default_app_ids
+ };
+ extension_id_sets[0].clear();
+ extension_id_sets[1].erase(extension_id_sets[1].begin());
+ extension_id_sets[2].erase(extension_id_sets[2].begin(),
+ ++extension_id_sets[2].begin());
+ for (size_t i = 0; i < arraysize(extension_id_sets); ++i) {
+ default_apps.DidInstallApp(extension_id_sets[i]);
+ EXPECT_TRUE(default_app_ids == *default_apps.GetAppsToInstall());
+ EXPECT_FALSE(default_apps.GetDefaultAppsInstalled());
+ EXPECT_FALSE(default_apps.ShouldShowPromo(extension_id_sets[i]));
+ }
+
+ // Simulate all the default apps being installed. Now we should stop getting
+ // default apps to install.
+ default_apps.DidInstallApp(default_app_ids);
+ EXPECT_EQ(NULL, default_apps.GetAppsToInstall());
+ EXPECT_TRUE(default_apps.GetDefaultAppsInstalled());
+
+ // And the promo should become available.
+ EXPECT_TRUE(default_apps.ShouldShowPromo(default_app_ids));
+
+ // The promo should be available up to the max allowed times, then stop.
+ for (int i = 0; i < DefaultApps::kAppsPromoCounterMax; ++i) {
+ EXPECT_TRUE(default_apps.ShouldShowPromo(default_app_ids));
+ default_apps.DidShowPromo();
+ EXPECT_EQ(i + 1, default_apps.GetPromoCounter());
+ }
+ EXPECT_FALSE(default_apps.ShouldShowPromo(default_app_ids));
+ EXPECT_EQ(DefaultApps::kAppsPromoCounterMax, default_apps.GetPromoCounter());
+}
+
+TEST(DefaultApps, HidePromo) {
+ TestingPrefService pref_service;
+ DefaultApps::RegisterUserPrefs(&pref_service);
+ DefaultApps default_apps(&pref_service);
+
+ ExtensionIdSet default_app_ids = *default_apps.GetAppsToInstall();
+ default_apps.DidInstallApp(default_app_ids);
+
+ EXPECT_TRUE(default_apps.ShouldShowPromo(default_app_ids));
+ default_apps.DidShowPromo();
+ EXPECT_EQ(1, default_apps.GetPromoCounter());
+
+ default_apps.SetPromoHidden();
+ EXPECT_FALSE(default_apps.ShouldShowPromo(default_app_ids));
+ EXPECT_EQ(DefaultApps::kAppsPromoCounterMax, default_apps.GetPromoCounter());
+}
+
+TEST(DefaultApps, InstallingAnAppHidesPromo) {
+ TestingPrefService pref_service;
+ DefaultApps::RegisterUserPrefs(&pref_service);
+ DefaultApps default_apps(&pref_service);
+
+ ExtensionIdSet default_app_ids = *default_apps.GetAppsToInstall();
+ ExtensionIdSet installed_app_ids = default_app_ids;
+ default_apps.DidInstallApp(installed_app_ids);
+
+ EXPECT_TRUE(default_apps.ShouldShowPromo(installed_app_ids));
+ default_apps.DidShowPromo();
+ EXPECT_EQ(1, default_apps.GetPromoCounter());
+
+ // Now simulate a new extension being installed. This should cause the promo
+ // to be hidden.
+ installed_app_ids.insert("foo");
+ EXPECT_FALSE(default_apps.ShouldShowPromo(installed_app_ids));
+ EXPECT_EQ(DefaultApps::kAppsPromoCounterMax, default_apps.GetPromoCounter());
+}
+
+TEST(DefaultApps, ManualAppInstalledWhileInstallingDefaultApps) {
+ // It is possible to have apps manually installed while the default apps are
+ // being installed. The network or server might be down, causing the default
+ // app installation to fail. The updater might take awhile to get around to
+ // updating, giving the user a chance to manually intall.
+ //
+ // In these cases, we should keep trying to install default apps until we have
+ // them all, and then stop, even if at that point, we have more apps than just
+ // the default ones.
+ TestingPrefService pref_service;
+ DefaultApps::RegisterUserPrefs(&pref_service);
+ DefaultApps default_apps(&pref_service);
+
+ // Simulate an app getting installed before the complete set of default apps.
+ // This shouldn't affect us installing default apps. We should keep trying.
+ ExtensionIdSet installed_ids;
+ installed_ids.insert("foo");
+ default_apps.DidInstallApp(installed_ids);
+ EXPECT_FALSE(default_apps.GetDefaultAppsInstalled());
+ EXPECT_TRUE(default_apps.GetAppsToInstall());
+
+ // Now add all the default apps in addition to the extra app. We should stop
+ // trying to install default apps.
+ installed_ids = *default_apps.GetAppsToInstall();
+ installed_ids.insert("foo");
+ default_apps.DidInstallApp(installed_ids);
+ EXPECT_TRUE(default_apps.GetDefaultAppsInstalled());
+ EXPECT_FALSE(default_apps.GetAppsToInstall());
+
+ // The promo shouldn't turn on though, because it would look weird with the
+ // user's extra, manually installed extensions.
+ EXPECT_FALSE(default_apps.ShouldShowPromo(installed_ids));
+ EXPECT_EQ(DefaultApps::kAppsPromoCounterMax, default_apps.GetPromoCounter());
+}
diff --git a/chrome/browser/extensions/extension_updater.cc b/chrome/browser/extensions/extension_updater.cc
index b2fca2b..42ccfba 100644
--- a/chrome/browser/extensions/extension_updater.cc
+++ b/chrome/browser/extensions/extension_updater.cc
@@ -182,11 +182,7 @@ void ManifestFetchesBuilder::AddPendingExtension(
scoped_ptr<Version> version(
Version::GetVersionFromString("0.0.0.0"));
- Extension::Location location =
- (info.is_from_sync ? Extension::INTERNAL
- : Extension::EXTERNAL_PREF_DOWNLOAD);
-
- AddExtensionData(location, id, *version,
+ AddExtensionData(info.install_source, id, *version,
info.expected_crx_type, info.update_url);
}
diff --git a/chrome/browser/extensions/extension_updater_unittest.cc b/chrome/browser/extensions/extension_updater_unittest.cc
index d183b7b..6ea4410 100644
--- a/chrome/browser/extensions/extension_updater_unittest.cc
+++ b/chrome/browser/extensions/extension_updater_unittest.cc
@@ -130,7 +130,7 @@ void CreateTestPendingExtensions(int count, const GURL& update_url,
(*pending_extensions)[id] =
PendingExtensionInfo(update_url, crx_type, kIsFromSync,
kInstallSilently, kInitialState,
- kInitialIncognitoEnabled);
+ kInitialIncognitoEnabled, Extension::INTERNAL);
}
}
@@ -568,7 +568,7 @@ class ExtensionUpdaterTest : public testing::Test {
pending_extensions[id] =
PendingExtensionInfo(test_url, kExpectedCrxType, kIsFromSync,
kInstallSilently, kInitialState,
- kInitialIncognitoEnabled);
+ kInitialIncognitoEnabled, Extension::INTERNAL);
service.set_pending_extensions(pending_extensions);
}
@@ -897,13 +897,15 @@ TEST(ExtensionUpdaterTest, TestManifestFetchesBuilderAddExtension) {
builder.AddPendingExtension(
GenerateId("foo"), PendingExtensionInfo(GURL("http:google.com:foo"),
PendingExtensionInfo::EXTENSION,
- false, false, true, false));
+ false, false, true, false,
+ Extension::INTERNAL));
EXPECT_TRUE(builder.GetFetches().empty());
// Extensions with empty IDs should be rejected.
builder.AddPendingExtension(
"", PendingExtensionInfo(GURL(), PendingExtensionInfo::EXTENSION,
- false, false, true, false));
+ false, false, true, false,
+ Extension::INTERNAL));
EXPECT_TRUE(builder.GetFetches().empty());
// TODO(akalin): Test that extensions with empty update URLs
@@ -914,7 +916,8 @@ TEST(ExtensionUpdaterTest, TestManifestFetchesBuilderAddExtension) {
builder.AddPendingExtension(
GenerateId("foo"), PendingExtensionInfo(GURL(),
PendingExtensionInfo::EXTENSION,
- false, false, true, false));
+ false, false, true, false,
+ Extension::INTERNAL));
std::vector<ManifestFetchData*> fetches = builder.GetFetches();
ASSERT_EQ(1u, fetches.size());
scoped_ptr<ManifestFetchData> fetch(fetches[0]);
diff --git a/chrome/browser/extensions/extensions_service.cc b/chrome/browser/extensions/extensions_service.cc
index 4ce8c9f..f86564d 100644
--- a/chrome/browser/extensions/extensions_service.cc
+++ b/chrome/browser/extensions/extensions_service.cc
@@ -23,6 +23,7 @@
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/debugger/devtools_manager.h"
#include "chrome/browser/extensions/crx_installer.h"
+#include "chrome/browser/extensions/default_apps.h"
#include "chrome/browser/extensions/extension_accessibility_api.h"
#include "chrome/browser/extensions/extension_bookmarks_module.h"
#include "chrome/browser/extensions/extension_browser_event_router.h"
@@ -129,13 +130,15 @@ PendingExtensionInfo::PendingExtensionInfo(
bool is_from_sync,
bool install_silently,
bool enable_on_install,
- bool enable_incognito_on_install)
+ bool enable_incognito_on_install,
+ Extension::Location location)
: update_url(update_url),
expected_crx_type(expected_crx_type),
is_from_sync(is_from_sync),
install_silently(install_silently),
enable_on_install(enable_on_install),
- enable_incognito_on_install(enable_incognito_on_install) {}
+ enable_incognito_on_install(enable_incognito_on_install),
+ install_source(location) {}
PendingExtensionInfo::PendingExtensionInfo()
: update_url(),
@@ -143,7 +146,8 @@ PendingExtensionInfo::PendingExtensionInfo()
is_from_sync(true),
install_silently(false),
enable_on_install(false),
- enable_incognito_on_install(false) {}
+ enable_incognito_on_install(false),
+ install_source(Extension::INVALID) {}
// ExtensionsService.
@@ -561,7 +565,8 @@ ExtensionsService::ExtensionsService(Profile* profile,
extensions_enabled_(true),
show_extensions_prompts_(true),
ready_(false),
- ALLOW_THIS_IN_INITIALIZER_LIST(toolbar_model_(this)) {
+ ALLOW_THIS_IN_INITIALIZER_LIST(toolbar_model_(this)),
+ default_apps_(profile->GetPrefs()) {
// Figure out if extension installation should be enabled.
if (command_line->HasSwitch(switches::kDisableExtensions)) {
extensions_enabled_ = false;
@@ -682,8 +687,8 @@ void ExtensionsService::UpdateExtension(const std::string& id,
this, // frontend
client));
installer->set_expected_id(id);
- if (is_pending_extension && !it->second.is_from_sync)
- installer->set_install_source(Extension::EXTERNAL_PREF_DOWNLOAD);
+ if (is_pending_extension)
+ installer->set_install_source(it->second.install_source);
installer->set_delete_source(true);
installer->set_original_url(download_url);
installer->InstallCrx(extension_path);
@@ -699,15 +704,16 @@ void ExtensionsService::AddPendingExtensionFromSync(
<< " which already exists";
return;
}
- AddPendingExtensionInternal(
- id, update_url, expected_crx_type, true, install_silently,
- enable_on_install, enable_incognito_on_install);
+
+ AddPendingExtensionInternal(id, update_url, expected_crx_type, true,
+ install_silently, enable_on_install,
+ enable_incognito_on_install,
+ Extension::INTERNAL);
}
void ExtensionsService::AddPendingExtensionFromExternalUpdateUrl(
const std::string& id, const GURL& update_url) {
// Add the extension to this list of extensions to update.
- // We do not know if the id refers to a theme, so make is_theme unknown.
const PendingExtensionInfo::ExpectedCrxType kExpectedCrxType =
PendingExtensionInfo::UNKNOWN;
const bool kIsFromSync = false;
@@ -723,18 +729,41 @@ void ExtensionsService::AddPendingExtensionFromExternalUpdateUrl(
AddPendingExtensionInternal(id, update_url, kExpectedCrxType, kIsFromSync,
kInstallSilently, kEnableOnInstall,
- kEnableIncognitoOnInstall);
+ kEnableIncognitoOnInstall,
+ Extension::EXTERNAL_PREF_DOWNLOAD);
+}
+
+void ExtensionsService::AddPendingExtensionFromDefaultAppList(
+ const std::string& id) {
+ // Add the extension to this list of extensions to update.
+ const PendingExtensionInfo::ExpectedCrxType kExpectedCrxType =
+ PendingExtensionInfo::APP;
+ const bool kIsFromSync = false;
+ const bool kInstallSilently = true;
+ const bool kEnableOnInstall = true;
+ const bool kEnableIncognitoOnInstall = true;
+
+ // This can legitimately happen if the user manually installed one of the
+ // default apps before this code ran.
+ if (GetExtensionByIdInternal(id, true, true))
+ return;
+
+ AddPendingExtensionInternal(id, GURL(), kExpectedCrxType, kIsFromSync,
+ kInstallSilently, kEnableOnInstall,
+ kEnableIncognitoOnInstall,
+ Extension::INTERNAL);
}
void ExtensionsService::AddPendingExtensionInternal(
const std::string& id, const GURL& update_url,
PendingExtensionInfo::ExpectedCrxType expected_crx_type,
bool is_from_sync, bool install_silently,
- bool enable_on_install, bool enable_incognito_on_install) {
+ bool enable_on_install, bool enable_incognito_on_install,
+ Extension::Location install_source) {
pending_extensions_[id] =
PendingExtensionInfo(update_url, expected_crx_type, is_from_sync,
install_silently, enable_on_install,
- enable_incognito_on_install);
+ enable_incognito_on_install, install_source);
}
void ExtensionsService::ReloadExtension(const std::string& extension_id) {
@@ -1514,8 +1543,11 @@ void ExtensionsService::OnExtensionInstalled(Extension* extension,
// Set initial state from pending extension data.
PendingExtensionInfo::ExpectedCrxType actual_crx_type =
- (extension->is_theme() ? PendingExtensionInfo::THEME
- : PendingExtensionInfo::EXTENSION);
+ PendingExtensionInfo::EXTENSION;
+ if (extension->is_app())
+ actual_crx_type = PendingExtensionInfo::APP;
+ else if (extension->is_theme())
+ actual_crx_type = PendingExtensionInfo::THEME;
if (expected_crx_type != PendingExtensionInfo::UNKNOWN &&
expected_crx_type != actual_crx_type) {
@@ -1626,6 +1658,12 @@ void ExtensionsService::OnExtensionInstalled(Extension* extension,
Details<Extension>(extension));
}
+ if (extension->is_app()) {
+ ExtensionIdSet installed_ids = GetAppIds();
+ installed_ids.insert(extension->id());
+ default_apps_.DidInstallApp(installed_ids);
+ }
+
// Transfer ownership of |extension| to OnExtensionLoaded.
OnExtensionLoaded(scoped_extension.release(), allow_privilege_increase);
}
@@ -1825,15 +1863,17 @@ void ExtensionsService::Observe(NotificationType type,
}
}
-bool ExtensionsService::HasApps() {
- if (!extensions_enabled_)
- return false;
+bool ExtensionsService::HasApps() const {
+ return !GetAppIds().empty();
+}
+ExtensionIdSet ExtensionsService::GetAppIds() const {
+ ExtensionIdSet result;
for (ExtensionList::const_iterator it = extensions_.begin();
it != extensions_.end(); ++it) {
- if ((*it)->is_app())
- return true;
+ if ((*it)->is_app() && (*it)->location() != Extension::COMPONENT)
+ result.insert((*it)->id());
}
- return false;
+ return result;
}
diff --git a/chrome/browser/extensions/extensions_service.h b/chrome/browser/extensions/extensions_service.h
index 71fbfd9..10f54c6 100644
--- a/chrome/browser/extensions/extensions_service.h
+++ b/chrome/browser/extensions/extensions_service.h
@@ -20,6 +20,7 @@
#include "base/time.h"
#include "base/tuple.h"
#include "chrome/browser/chrome_thread.h"
+#include "chrome/browser/extensions/default_apps.h"
#include "chrome/browser/extensions/extension_icon_manager.h"
#include "chrome/browser/extensions/extension_menu_manager.h"
#include "chrome/browser/extensions/extension_prefs.h"
@@ -51,6 +52,7 @@ struct PendingExtensionInfo {
enum ExpectedCrxType {
UNKNOWN, // Sometimes we don't know the type of a pending item. An
// update URL from external_extensions.json is one such case.
+ APP,
THEME,
EXTENSION
};
@@ -60,7 +62,8 @@ struct PendingExtensionInfo {
bool is_from_sync,
bool install_silently,
bool enable_on_install,
- bool enable_incognito_on_install);
+ bool enable_incognito_on_install,
+ Extension::Location install_source);
PendingExtensionInfo();
@@ -70,6 +73,7 @@ struct PendingExtensionInfo {
bool install_silently;
bool enable_on_install;
bool enable_incognito_on_install;
+ Extension::Location install_source;
};
// A PendingExtensionMap is a map from IDs of pending extensions to
@@ -169,6 +173,10 @@ class ExtensionsService
return !(extensions_.empty() && disabled_extensions_.empty());
}
+ const FilePath& install_directory() const { return install_directory_; }
+
+ DefaultApps* default_apps() { return &default_apps_; }
+
// Whether this extension can run in an incognito window.
bool IsIncognitoEnabled(const Extension* extension);
void SetIsIncognitoEnabled(Extension* extension, bool enabled);
@@ -177,8 +185,6 @@ class ExtensionsService
bool AllowFileAccess(const Extension* extension);
void SetAllowFileAccess(Extension* extension, bool allow);
- const FilePath& install_directory() const { return install_directory_; }
-
// Initialize and start all installed extensions.
void Init();
@@ -225,6 +231,10 @@ class ExtensionsService
void AddPendingExtensionFromExternalUpdateUrl(const std::string& id,
const GURL& update_url);
+ // Like the above. Always installed silently, and defaults update url
+ // from extension id.
+ void AddPendingExtensionFromDefaultAppList(const std::string& id);
+
// Reloads the specified extension.
void ReloadExtension(const std::string& extension_id);
@@ -386,8 +396,11 @@ class ExtensionsService
const NotificationSource& source,
const NotificationDetails& details);
- // Whether there are any apps installed.
- bool HasApps();
+ // Whether there are any apps installed. Component apps are not included.
+ bool HasApps() const;
+
+ // Gets the set of loaded app ids. Component apps are not included.
+ ExtensionIdSet GetAppIds() const;
private:
virtual ~ExtensionsService();
@@ -409,7 +422,8 @@ class ExtensionsService
const std::string& id, const GURL& update_url,
PendingExtensionInfo::ExpectedCrxType crx_type,
bool is_from_sync, bool install_silently,
- bool enable_on_install, bool enable_incognito_on_install);
+ bool enable_on_install, bool enable_incognito_on_install,
+ Extension::Location install_source);
// Handles sending notification that |extension| was loaded.
void NotifyExtensionLoaded(Extension* extension);
@@ -511,6 +525,10 @@ class ExtensionsService
typedef std::map<GURL, int> ProtectedStorageMap;
ProtectedStorageMap protected_storage_map_;
+ // Manages the installation of default apps and the promotion of them in the
+ // app launcher.
+ DefaultApps default_apps_;
+
FRIEND_TEST_ALL_PREFIXES(ExtensionsServiceTest,
UpdatePendingExtensionAlreadyInstalled);
FRIEND_TEST_ALL_PREFIXES(ExtensionsServiceTest,
diff --git a/chrome/browser/extensions/extensions_service_unittest.cc b/chrome/browser/extensions/extensions_service_unittest.cc
index fc6662e..6d49a3b 100644
--- a/chrome/browser/extensions/extensions_service_unittest.cc
+++ b/chrome/browser/extensions/extensions_service_unittest.cc
@@ -1716,7 +1716,7 @@ TEST_F(ExtensionsServiceTest, UpdatePendingExtensionAlreadyInstalled) {
good->id(), good->update_url(),
PendingExtensionInfo::EXTENSION,
kGoodIsFromSync, kGoodInstallSilently, kGoodInitialState,
- kGoodInitialIncognitoEnabled);
+ kGoodInitialIncognitoEnabled, Extension::INTERNAL);
UpdateExtension(good->id(), path, INSTALLED);
EXPECT_FALSE(ContainsKey(service_->pending_extensions(), kGoodId));
diff --git a/chrome/browser/profile_impl.cc b/chrome/browser/profile_impl.cc
index af95572..899e068daa 100644
--- a/chrome/browser/profile_impl.cc
+++ b/chrome/browser/profile_impl.cc
@@ -26,6 +26,7 @@
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/dom_ui/ntp_resource_cache.h"
#include "chrome/browser/download/download_manager.h"
+#include "chrome/browser/extensions/default_apps.h"
#include "chrome/browser/extensions/extension_devtools_manager.h"
#include "chrome/browser/extensions/extension_error_reporter.h"
#include "chrome/browser/extensions/extension_info_map.h"
@@ -168,15 +169,6 @@ bool HasACacheSubdir(const FilePath &dir) {
file_util::PathExists(GetMediaCachePath(dir));
}
-// Returns true if the default apps should be loaded (so that the app panel is
-// not empty).
-bool IncludeDefaultApps() {
-#if defined(OS_CHROMEOS) && defined(GOOGLE_CHROME_BUILD)
- return true;
-#endif
- return false;
-}
-
// Simple task to log the size of the current profile.
class ProfileSizeTask : public Task {
public:
@@ -240,6 +232,7 @@ Profile* Profile::CreateProfile(const FilePath& path) {
// static
void ProfileImpl::RegisterUserPrefs(PrefService* prefs) {
prefs->RegisterBooleanPref(prefs::kSavingBrowserHistoryDisabled, false);
+ DefaultApps::RegisterUserPrefs(prefs);
}
ProfileImpl::ProfileImpl(const FilePath& path)
@@ -375,6 +368,18 @@ void ProfileImpl::InitExtensions() {
GetPath().AppendASCII(ExtensionsService::kInstallDirectoryName),
true);
+ RegisterComponentExtensions();
+ extensions_service_->Init();
+ InstallDefaultApps();
+
+ // Load any extensions specified with --load-extension.
+ if (command_line->HasSwitch(switches::kLoadExtension)) {
+ FilePath path = command_line->GetSwitchValuePath(switches::kLoadExtension);
+ extensions_service_->LoadExtension(path);
+ }
+}
+
+void ProfileImpl::RegisterComponentExtensions() {
// Register the component extensions.
typedef std::list<std::pair<std::string, int> > ComponentExtensionList;
ComponentExtensionList component_extensions;
@@ -392,22 +397,9 @@ void ProfileImpl::InitExtensions() {
component_extensions.push_back(
std::make_pair("web_store", IDR_WEBSTORE_MANIFEST));
- // Some sample apps to make our lives easier while we are developing extension
- // apps. This way we don't have to constantly install these over and over.
- if (Extension::AppsAreEnabled() && IncludeDefaultApps()) {
- component_extensions.push_back(
- std::make_pair("gmail_app", IDR_GMAIL_APP_MANIFEST));
- component_extensions.push_back(
- std::make_pair("calendar_app", IDR_CALENDAR_APP_MANIFEST));
- component_extensions.push_back(
- std::make_pair("docs_app", IDR_DOCS_APP_MANIFEST));
- }
-
#if defined(OS_CHROMEOS) && defined(GOOGLE_CHROME_BUILD)
- if (Extension::AppsAreEnabled()) {
- component_extensions.push_back(
- std::make_pair("chat_manager", IDR_TALK_APP_MANIFEST));
- }
+ component_extensions.push_back(
+ std::make_pair("chat_manager", IDR_TALK_APP_MANIFEST));
#endif
for (ComponentExtensionList::iterator iter = component_extensions.begin();
@@ -425,13 +417,31 @@ void ProfileImpl::InitExtensions() {
extensions_service_->register_component_extension(
ExtensionsService::ComponentExtensionInfo(manifest, path));
}
+}
- extensions_service_->Init();
+void ProfileImpl::InstallDefaultApps() {
+#if !defined(OS_CHROMEOS)
+ // On desktop Chrome, we don't have default apps on by, err, default yet.
+ if (!CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableDefaultApps)) {
+ return;
+ }
+#endif
- // Load any extensions specified with --load-extension.
- if (command_line->HasSwitch(switches::kLoadExtension)) {
- FilePath path = command_line->GetSwitchValuePath(switches::kLoadExtension);
- extensions_service_->LoadExtension(path);
+ // The web store only supports en-US at the moment, so we don't install
+ // default apps in other locales.
+ if (g_browser_process->GetApplicationLocale() != "en-US")
+ return;
+
+ ExtensionsService* extensions_service = GetExtensionsService();
+ const ExtensionIdSet* app_ids =
+ extensions_service->default_apps()->GetAppsToInstall();
+ if (!app_ids)
+ return;
+
+ for (ExtensionIdSet::const_iterator iter = app_ids->begin();
+ iter != app_ids->end(); ++iter) {
+ extensions_service->AddPendingExtensionFromDefaultAppList(*iter);
}
}
diff --git a/chrome/browser/profile_impl.h b/chrome/browser/profile_impl.h
index efa00c1..7b926e6 100644
--- a/chrome/browser/profile_impl.h
+++ b/chrome/browser/profile_impl.h
@@ -151,6 +151,9 @@ class ProfileImpl : public Profile,
GetSessionService();
}
+ void RegisterComponentExtensions();
+ void InstallDefaultApps();
+
NotificationRegistrar registrar_;
PrefChangeRegistrar pref_change_registrar_;
diff --git a/chrome/browser/resources/calendar_app/128.png b/chrome/browser/resources/calendar_app/128.png
deleted file mode 100644
index 5ebe636..0000000
--- a/chrome/browser/resources/calendar_app/128.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/calendar_app/24.png b/chrome/browser/resources/calendar_app/24.png
deleted file mode 100644
index b3a971d..0000000
--- a/chrome/browser/resources/calendar_app/24.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/calendar_app/32.png b/chrome/browser/resources/calendar_app/32.png
deleted file mode 100644
index e1ac68d..0000000
--- a/chrome/browser/resources/calendar_app/32.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/calendar_app/48.png b/chrome/browser/resources/calendar_app/48.png
deleted file mode 100644
index 6bfde15..0000000
--- a/chrome/browser/resources/calendar_app/48.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/calendar_app/manifest.json b/chrome/browser/resources/calendar_app/manifest.json
deleted file mode 100644
index 8bcf843..0000000
--- a/chrome/browser/resources/calendar_app/manifest.json
+++ /dev/null
@@ -1,24 +0,0 @@
-{
- "key": "XX3fMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCf1MLMJ1mzNVJOVqaFFX+fQ7gJLVeZN+Sq3tKnZM33oWP82xDDs345/TsFTqGV3Nj5KvmjIN5NwcW/AeBOpVeOGFujFDSTOCZv0JDKkTXLyCegSwF+ljBi0TbCrsgv2T+8Jt891+hSyw5LPjXoTX2bKz+bu016tQnGnhb6fXyCBQIDAQAB",
- "name": "Google Calendar",
- "version": "1.3",
- "permissions": [ "notifications" ],
- "icons": {
- "128": "128.png",
- "24": "24.png",
- "32": "32.png",
- "48": "48.png"
- },
- "app": {
- "urls": [
- "*://www.google.com/calendar/"
- ],
- "browse_urls": [
- "https://www.google.com/accounts/"
- ],
- "launch": {
- "container": "tab",
- "web_url": "https://www.google.com/calendar/"
- }
- }
-}
diff --git a/chrome/browser/resources/docs_app/128.png b/chrome/browser/resources/docs_app/128.png
deleted file mode 100644
index 0b514a8..0000000
--- a/chrome/browser/resources/docs_app/128.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/docs_app/24.png b/chrome/browser/resources/docs_app/24.png
deleted file mode 100644
index 7260ac5..0000000
--- a/chrome/browser/resources/docs_app/24.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/docs_app/32.png b/chrome/browser/resources/docs_app/32.png
deleted file mode 100644
index 6ed8ecd..0000000
--- a/chrome/browser/resources/docs_app/32.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/docs_app/48.png b/chrome/browser/resources/docs_app/48.png
deleted file mode 100644
index 7440412..0000000
--- a/chrome/browser/resources/docs_app/48.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/docs_app/manifest.json b/chrome/browser/resources/docs_app/manifest.json
deleted file mode 100644
index 10e965c..0000000
--- a/chrome/browser/resources/docs_app/manifest.json
+++ /dev/null
@@ -1,44 +0,0 @@
-{
- "key": "XX1fMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCfjDZDDE/CHFEYjpPSDjdI3zphzGo7fSxO3+/pQs++FwvA+OpKKhmBga2Sa+f53ujDlPR8Q6mCvy1lXM4M4zD4Hg3lH2LC1wT/YXxJ28afRYW1yEo6/pbpHazij3+FneGMT2xcTyGvgoacJHXOTUqWyCN7qMOCiFDwQ6Uk1zJOPQIDAQAB",
- "name": "Google Docs",
- "version": "1",
- "icons": {
- "128": "128.png",
- "24": "24.png",
- "32": "32.png",
- "48": "48.png"
- },
- "app": {
- "urls": [
- "*://www.google.com/docs/",
- "*://docs.google.com/",
- "*://docs0.google.com/",
- "*://docs1.google.com/",
- "*://docs2.google.com/",
- "*://docs3.google.com/",
- "*://docs4.google.com/",
- "*://docs5.google.com/",
- "*://docs6.google.com/",
- "*://docs7.google.com/",
- "*://docs8.google.com/",
- "*://docs9.google.com/",
- "*://spreadsheets.google.com/",
- "*://spreadsheets0.google.com/",
- "*://spreadsheets1.google.com/",
- "*://spreadsheets2.google.com/",
- "*://spreadsheets3.google.com/",
- "*://spreadsheets4.google.com/",
- "*://spreadsheets5.google.com/",
- "*://spreadsheets6.google.com/",
- "*://spreadsheets7.google.com/",
- "*://spreadsheets8.google.com/",
- "*://spreadsheets9.google.com/"
- ],
- "browse_urls": [
- "https://www.google.com/accounts/"
- ],
- "launch": {
- "web_url": "https://docs.google.com/"
- }
- }
-}
diff --git a/chrome/browser/resources/gmail_app/128.png b/chrome/browser/resources/gmail_app/128.png
deleted file mode 100644
index 679e7a2..0000000
--- a/chrome/browser/resources/gmail_app/128.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/gmail_app/24.png b/chrome/browser/resources/gmail_app/24.png
deleted file mode 100644
index 8b14b22..0000000
--- a/chrome/browser/resources/gmail_app/24.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/gmail_app/32.png b/chrome/browser/resources/gmail_app/32.png
deleted file mode 100644
index bfd8aa4..0000000
--- a/chrome/browser/resources/gmail_app/32.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/gmail_app/48.png b/chrome/browser/resources/gmail_app/48.png
deleted file mode 100644
index bc1f9fd..0000000
--- a/chrome/browser/resources/gmail_app/48.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/gmail_app/manifest.json b/chrome/browser/resources/gmail_app/manifest.json
deleted file mode 100644
index 9dfcf98..0000000
--- a/chrome/browser/resources/gmail_app/manifest.json
+++ /dev/null
@@ -1,25 +0,0 @@
-{
- "key": "XX2fMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCfjDZDDE/CHFEYjpPSDjdI3zphzGo7fSxO3+/pQs++FwvA+OpKKhmBga2Sa+f53ujDlPR8Q6mCvy1lXM4M4zD4Hg3lH2LC1wT/YXxJ28afRYW1yEo6/pbpHazij3+FneGMT2xcTyGvgoacJHXOTUqWyCN7qMOCiFDwQ6Uk1zJOPQIDAQAB",
- "name": "Google Mail",
- "version": "1",
- "icons": {
- "128": "128.png",
- "24": "24.png",
- "32": "32.png",
- "48": "48.png"
- },
- "permissions": [ "notifications" ],
- "app": {
- "urls": [
- "*://mail.google.com/mail/",
- "*://gmail.com/",
- "*://www.gmail.com/"
- ],
- "browse_urls": [
- "https://www.google.com/accounts/"
- ],
- "launch": {
- "web_url": "https://mail.google.com/mail/"
- }
- }
-}
diff --git a/chrome/browser/resources/new_new_tab.html b/chrome/browser/resources/new_new_tab.html
index 9f78a10..e0f799e 100644
--- a/chrome/browser/resources/new_new_tab.html
+++ b/chrome/browser/resources/new_new_tab.html
@@ -5,8 +5,7 @@
hasattribution:hasattribution;
anim:anim;
syncispresent:syncispresent;
- customlogo:customlogo;
- appspromovisible:appspromovisible"
+ customlogo:customlogo"
install-animation-enabled="true">
<head>
<meta charset="utf-8">
diff --git a/chrome/browser/resources/new_new_tab.js b/chrome/browser/resources/new_new_tab.js
index 2373582..0a577d4 100644
--- a/chrome/browser/resources/new_new_tab.js
+++ b/chrome/browser/resources/new_new_tab.js
@@ -1101,4 +1101,10 @@ document.addEventListener('DOMContentLoaded', function() {
var promoText1 = $('apps-promo-text1');
promoText1.innerHTML = promoText1.textContent;
promoText1.querySelector('a').href = localStrings.getString('web_store_url');
+
+ $('apps-promo-hide').addEventListener('click', function() {
+ chrome.send('hideAppsPromo', []);
+ document.documentElement.classList.remove('apps-promo-visible');
+ layoutSections();
+ });
});
diff --git a/chrome/browser/resources/ntp/apps.css b/chrome/browser/resources/ntp/apps.css
index 45301ab..c92c7a9 100644
--- a/chrome/browser/resources/ntp/apps.css
+++ b/chrome/browser/resources/ntp/apps.css
@@ -102,7 +102,7 @@ menu > button.default {
display: none;
}
-html[appspromovisible=true] #apps-promo {
+html.apps-promo-visible #apps-promo {
display: block;
}
@@ -132,15 +132,15 @@ html[dir=rtl] #apps-promo-hide {
float: left;
}
-html[appspromovisible=true] .app[app-id=web-store-entry] {
+html.apps-promo-visible .app[app-id=web-store-entry] {
left: 25px;
}
-html[appspromovisible=true][dir=rtl] .app[app-id=web-store-entry] {
+html.apps-promo-visible[dir=rtl] .app[app-id=web-store-entry] {
right: 25px;
}
-html[appspromovisible=true] .app[app-id=web-store-entry] a {
+html.apps-promo-visible .app[app-id=web-store-entry] a {
font-weight: bold;
}
diff --git a/chrome/browser/resources/ntp/apps.js b/chrome/browser/resources/ntp/apps.js
index dd44532..e6f79a2 100644
--- a/chrome/browser/resources/ntp/apps.js
+++ b/chrome/browser/resources/ntp/apps.js
@@ -37,6 +37,10 @@ function getAppsCallback(data) {
addClosedMenuFooter(apps.menu, 'apps', MINIMIZED_APPS, Section.APPS);
apps.loaded = true;
+ if (data.showPromo)
+ document.documentElement.classList.add('apps-promo-visible');
+ else
+ document.documentElement.classList.remove('apps-promo-visible');
maybeDoneLoading();
if (data.apps.length > 0 && isDoneLoading()) {
diff --git a/chrome/browser/shell_integration.cc b/chrome/browser/shell_integration.cc
index 3ed45ae7..c51ed25 100644
--- a/chrome/browser/shell_integration.cc
+++ b/chrome/browser/shell_integration.cc
@@ -42,7 +42,7 @@ std::string ShellIntegration::GetCommandLineArgumentsCommon(const GURL& url,
// If |extension_app_id| is present, we use the kAppId switch rather than
// the kApp switch (the launch url will be read from the extension app
// during launch.
- if (!cmd.HasSwitch(switches::kDisableApps) && !extension_app_id.empty()) {
+ if (!extension_app_id.empty()) {
arguments_w += std::wstring(L"--") + ASCIIToWide(switches::kAppId) +
L"=\"" + ASCIIToWide(UTF16ToASCII(extension_app_id));
} else {
diff --git a/chrome/browser/utility_process_host.cc b/chrome/browser/utility_process_host.cc
index 5091169..74afd4d 100644
--- a/chrome/browser/utility_process_host.cc
+++ b/chrome/browser/utility_process_host.cc
@@ -121,9 +121,6 @@ bool UtilityProcessHost::StartProcess(const FilePath& exposed_dir) {
if (browser_command_line.HasSwitch(switches::kChromeFrame))
cmd_line->AppendSwitch(switches::kChromeFrame);
- if (browser_command_line.HasSwitch(switches::kDisableApps))
- cmd_line->AppendSwitch(switches::kDisableApps);
-
if (browser_command_line.HasSwitch(
switches::kEnableExperimentalExtensionApis)) {
cmd_line->AppendSwitch(switches::kEnableExperimentalExtensionApis);
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index f368c8c..bd284b7 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1414,6 +1414,8 @@
'browser/extensions/crashed_extension_infobar.h',
'browser/extensions/crx_installer.cc',
'browser/extensions/crx_installer.h',
+ 'browser/extensions/default_apps.cc',
+ 'browser/extensions/default_apps.h',
'browser/extensions/extension_accessibility_api.cc',
'browser/extensions/extension_accessibility_api.h',
'browser/extensions/extension_accessibility_api_constants.cc',
@@ -4033,41 +4035,6 @@
'target_name': 'component_extensions',
'type': 'none',
'msvs_guid': '50B52703-525F-404C-BFE2-C46D3375D73E',
- # TODO(aa): Once the msvs port supports it, change this to recursively
- # copy the entire directory instead of listing the files.
- # http://code.google.com/p/gyp/issues/detail?id=143.
- 'copies': [
- {
- 'destination': '<(PRODUCT_DIR)/resources/gmail_app',
- 'files': [
- 'browser/resources/gmail_app/manifest.json',
- 'browser/resources/gmail_app/128.png',
- 'browser/resources/gmail_app/48.png',
- 'browser/resources/gmail_app/32.png',
- 'browser/resources/gmail_app/24.png',
- ]
- },
- {
- 'destination': '<(PRODUCT_DIR)/resources/calendar_app',
- 'files': [
- 'browser/resources/calendar_app/manifest.json',
- 'browser/resources/calendar_app/128.png',
- 'browser/resources/calendar_app/48.png',
- 'browser/resources/calendar_app/32.png',
- 'browser/resources/calendar_app/24.png',
- ]
- },
- {
- 'destination': '<(PRODUCT_DIR)/resources/docs_app',
- 'files': [
- 'browser/resources/docs_app/manifest.json',
- 'browser/resources/docs_app/128.png',
- 'browser/resources/docs_app/48.png',
- 'browser/resources/docs_app/32.png',
- 'browser/resources/docs_app/24.png',
- ]
- },
- ],
'conditions': [
['OS=="linux" and chromeos==1 and branding=="Chrome"',{
'copies': [
diff --git a/chrome/chrome_dll.gypi b/chrome/chrome_dll.gypi
index c68a388..0a08369 100644
--- a/chrome/chrome_dll.gypi
+++ b/chrome/chrome_dll.gypi
@@ -445,9 +445,6 @@
'destination': '<(PRODUCT_DIR)/$(CONTENTS_FOLDER_PATH)/Resources',
'files': [
'<(PRODUCT_DIR)/resources/inspector/',
- '<(PRODUCT_DIR)/resources/gmail_app/',
- '<(PRODUCT_DIR)/resources/calendar_app/',
- '<(PRODUCT_DIR)/resources/docs_app/',
],
'conditions': [
['mac_breakpad==1', {
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 08144b3..4bea7d5 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1247,6 +1247,7 @@
'browser/download/save_package_unittest.cc',
'browser/encoding_menu_controller_unittest.cc',
'browser/extensions/convert_user_script_unittest.cc',
+ 'browser/extensions/default_apps_unittest.cc',
'browser/extensions/extension_icon_manager_unittest.cc',
'browser/extensions/extension_info_map_unittest.cc',
'browser/extensions/extension_menu_manager_unittest.cc',
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index 231edea..077e28a 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -131,9 +131,6 @@ const char kDisableAltWinstation[] = "disable-winsta";
// Disable the ApplicationCache.
const char kDisableApplicationCache[] = "disable-application-cache";
-// Disable extension apps.
-const char kDisableApps[] = "disable-apps";
-
// Replaces the audio IPC layer for <audio> and <video> with a mock audio
// device, useful when using remote desktop or machines without sound cards.
// This is temporary until we fix the underlying problem.
@@ -381,10 +378,6 @@ const char kEnableBackgroundMode[] = "enable-background-mode";
// Enables the benchmarking extensions.
const char kEnableBenchmarking[] = "enable-benchmarking";
-// This applies only when the process type is "service". Enables the
-// Chromoting Host Process within the service process.
-const char kEnableRemoting[] = "enable-remoting";
-
// This flag enables UI for clearing server data. Temporarily in place
// until there's a server endpoint deployed.
const char kEnableClearServerData[] = "enable-clear-server-data";
@@ -405,6 +398,10 @@ const char kEnableConnectBackupJobs[] = "enable-connect-backup-jobs";
// Link: headers.
const char kEnableContentPrefetch[] = "enable-content-prefetch";
+// Whether default apps should be installed in this profile. This flag has no
+// effect on Chrome OS because default apps are always enabled there.
+const char kEnableDefaultApps[] = "enable-default-apps";
+
// Enables device motion events.
const char kEnableDeviceMotion[] = "enable-device-motion";
@@ -471,6 +468,10 @@ const char kEnableNaClDebug[] = "enable-nacl-debug";
// Enable Native Web Worker support.
const char kEnableNativeWebWorkers[] = "enable-native-web-workers";
+// This applies only when the process type is "service". Enables the
+// Chromoting Host Process within the service process.
+const char kEnableRemoting[] = "enable-remoting";
+
// Enable content settings based on host *and* plug-in.
const char kEnableResourceContentSettings[] =
"enable-resource-content-settings";
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index d2cc319..13692aa 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -51,7 +51,6 @@ extern const char kDiagnostics[];
extern const char kDisableAcceleratedCompositing[];
extern const char kDisableAltWinstation[];
extern const char kDisableApplicationCache[];
-extern const char kDisableApps[];
extern const char kDisableAudio[];
extern const char kDisableAuthNegotiateCnameLookup[];
extern const char kDisableBackgroundNetworking[];
@@ -119,12 +118,12 @@ extern const char kEnableAeroPeekTabs[];
extern const char kEnableAuthNegotiatePort[];
extern const char kEnableBackgroundMode[];
extern const char kEnableBenchmarking[];
-extern const char kEnableRemoting[];
extern const char kEnableClearServerData[];
extern const char kEnableCloudPrintProxy[];
extern const char kEnableCloudPrint[];
extern const char kEnableConnectBackupJobs[];
extern const char kEnableContentPrefetch[];
+extern const char kEnableDefaultApps[];
extern const char kEnableDeviceMotion[];
extern const char kEnableDNSSECCerts[];
extern const char kEnableExperimentalExtensionApis[];
@@ -147,6 +146,7 @@ extern const char kEnableNativeWebWorkers[];
extern const char kEnablePreconnect[];
extern const char kEnablePreparsedJsCaching[];
extern const char kEnablePrintPreview[];
+extern const char kEnableRemoting[];
extern const char kEnableResourceContentSettings[];
extern const char kEnableSearchProviderApiV2[];
extern const char kEnableSecureInfoBars[];
diff --git a/chrome/common/extensions/extension.cc b/chrome/common/extensions/extension.cc
index b90f446..4a5dbcc 100644
--- a/chrome/common/extensions/extension.cc
+++ b/chrome/common/extensions/extension.cc
@@ -745,14 +745,8 @@ bool Extension::ContainsNonThemeKeys(const DictionaryValue& source) {
bool Extension::LoadIsApp(const DictionaryValue* manifest,
std::string* error) {
- if (manifest->HasKey(keys::kApp)) {
- if (!apps_enabled_) {
- *error = errors::kAppsNotEnabled;
- return false;
- } else {
- is_app_ = true;
- }
- }
+ if (manifest->HasKey(keys::kApp))
+ is_app_ = true;
return true;
}
@@ -971,7 +965,6 @@ Extension::Extension(const FilePath& path)
DCHECK(path.IsAbsolute());
static_data_ = mutable_static_data_;
- apps_enabled_ = AppsAreEnabled();
location_ = INVALID;
#if defined(OS_WIN)
@@ -1177,11 +1170,6 @@ GURL Extension::GetBaseURLFromExtensionId(const std::string& extension_id) {
chrome::kStandardSchemeSeparator + extension_id + "/");
}
-// static
-bool Extension::AppsAreEnabled() {
- return !CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableApps);
-}
-
bool Extension::InitFromValue(const DictionaryValue& source, bool require_key,
std::string* error) {
// Unit tests reuse Extension objects, so we need to reset mutable_static_data
diff --git a/chrome/common/extensions/extension.h b/chrome/common/extensions/extension.h
index fbb4246..0302771 100644
--- a/chrome/common/extensions/extension.h
+++ b/chrome/common/extensions/extension.h
@@ -170,9 +170,6 @@ class Extension {
const URLPatternList& host_patterns);
std::vector<std::string> GetDistinctHosts();
- bool apps_enabled() const { return apps_enabled_; }
- void set_apps_enabled(bool val) { apps_enabled_ = val; }
-
// Icon sizes used by the extension system.
static const int kIconSizes[];
@@ -316,11 +313,7 @@ class Extension {
// Returns the base extension url for a given |extension_id|.
static GURL GetBaseURLFromExtensionId(const std::string& extension_id);
- // Returns whether the browser has apps enabled (either as the default or if
- // it was explicitly turned on via a command line switch).
- static bool AppsAreEnabled();
-
- // Returns the launch URL for the extension/apps gallery. Can be set via the
+ // Returns the url prefix for the extension/apps gallery. Can be set via the
// --apps-gallery-url switch. The URL returned will not contain a trailing
// slash. Do not use this as a prefix/extent for the store. Instead see
// ExtensionsService::GetWebStoreApp or
@@ -647,10 +640,6 @@ class Extension {
// which override the handling of those URLs.
URLOverrideMap chrome_url_overrides_;
- // Whether apps-related features can be parsed during InitFromValue().
- // Defaults to the value from --enable-extension-apps.
- bool apps_enabled_;
-
// Whether this extension uses app features.
bool is_app_;
@@ -690,6 +679,7 @@ class Extension {
};
typedef std::vector<Extension*> ExtensionList;
+typedef std::set<std::string> ExtensionIdSet;
// Handy struct to pass core extension info around.
struct ExtensionInfo {
diff --git a/chrome/common/extensions/extension_manifests_unittest.cc b/chrome/common/extensions/extension_manifests_unittest.cc
index 5cdd909..9a660bc 100644
--- a/chrome/common/extensions/extension_manifests_unittest.cc
+++ b/chrome/common/extensions/extension_manifests_unittest.cc
@@ -46,7 +46,6 @@ class ExtensionManifestTest : public testing::Test {
scoped_ptr<Extension> extension(new Extension(path.DirName()));
extension->set_location(location);
- extension->set_apps_enabled(enable_apps_);
if (!extension->InitFromValue(*value, false, error))
return NULL;
@@ -119,17 +118,6 @@ class ExtensionManifestTest : public testing::Test {
bool enable_apps_;
};
-TEST_F(ExtensionManifestTest, AppsDisabledByDefault) {
-#if defined(OS_CHROMEOS)
- // On ChromeOS, apps are enabled by default.
- if (Extension::AppsAreEnabled())
- return;
-#endif
-
- enable_apps_ = false;
- LoadAndExpectError("launch_local_path.json", errors::kAppsNotEnabled);
-}
-
TEST_F(ExtensionManifestTest, ValidApp) {
scoped_ptr<Extension> extension(LoadAndExpectSuccess("valid_app.json"));
ASSERT_EQ(2u, extension->web_extent().patterns().size());
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index 30298e5..6fc57de 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -9,6 +9,13 @@ namespace prefs {
// *************** PROFILE PREFS ***************
// These are attached to the user profile
+// A counter that controls whether the apps promo is shown in the app launcher
+// or not.
+const char kAppsPromoCounter[] = "apps_promo_counter";
+
+// Whether we have installed default apps yet in this profile.
+const char kDefaultAppsInstalled[] = "default_apps_installed";
+
// A boolean specifying whether the New Tab page is the home page or not.
const char kHomePageIsNewTabPage[] = "homepage_is_newtabpage";
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index c88998c..08e1433 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -13,6 +13,8 @@
namespace prefs {
// Profile prefs
+extern const char kAppsPromoCounter[];
+extern const char kDefaultAppsInstalled[];
extern const char kHomePageIsNewTabPage[];
extern const char kHomePage[];
extern const char kSessionExitedCleanly[];
diff --git a/chrome/installer/mini_installer/chrome.release b/chrome/installer/mini_installer/chrome.release
index 7d26cfc..23225e4 100644
--- a/chrome/installer/mini_installer/chrome.release
+++ b/chrome/installer/mini_installer/chrome.release
@@ -40,9 +40,6 @@ resources.pak: %(VersionDir)s\
locales\*.dll: %(VersionDir)s\Locales
Resources\Inspector\*.*: %(VersionDir)s\Resources\Inspector
Resources\Inspector\Images\*.*: %(VersionDir)s\Resources\Inspector\Images
-Resources\gmail_app\*.*: %(VersionDir)s\Resources\gmail_app
-Resources\calendar_app\*.*: %(VersionDir)s\Resources\calendar_app
-Resources\docs_app\*.*: %(VersionDir)s\Resources\docs_app
servers\*.dll: %(VersionDir)s\
servers\*.exe: %(VersionDir)s\
chrome_frame_helper.exe: %(VersionDir)s\