diff options
Diffstat (limited to 'chrome')
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 Binary files differdeleted file mode 100644 index 5ebe636..0000000 --- a/chrome/browser/resources/calendar_app/128.png +++ /dev/null diff --git a/chrome/browser/resources/calendar_app/24.png b/chrome/browser/resources/calendar_app/24.png Binary files differdeleted file mode 100644 index b3a971d..0000000 --- a/chrome/browser/resources/calendar_app/24.png +++ /dev/null diff --git a/chrome/browser/resources/calendar_app/32.png b/chrome/browser/resources/calendar_app/32.png Binary files differdeleted file mode 100644 index e1ac68d..0000000 --- a/chrome/browser/resources/calendar_app/32.png +++ /dev/null diff --git a/chrome/browser/resources/calendar_app/48.png b/chrome/browser/resources/calendar_app/48.png Binary files differdeleted file mode 100644 index 6bfde15..0000000 --- a/chrome/browser/resources/calendar_app/48.png +++ /dev/null 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 Binary files differdeleted file mode 100644 index 0b514a8..0000000 --- a/chrome/browser/resources/docs_app/128.png +++ /dev/null diff --git a/chrome/browser/resources/docs_app/24.png b/chrome/browser/resources/docs_app/24.png Binary files differdeleted file mode 100644 index 7260ac5..0000000 --- a/chrome/browser/resources/docs_app/24.png +++ /dev/null diff --git a/chrome/browser/resources/docs_app/32.png b/chrome/browser/resources/docs_app/32.png Binary files differdeleted file mode 100644 index 6ed8ecd..0000000 --- a/chrome/browser/resources/docs_app/32.png +++ /dev/null diff --git a/chrome/browser/resources/docs_app/48.png b/chrome/browser/resources/docs_app/48.png Binary files differdeleted file mode 100644 index 7440412..0000000 --- a/chrome/browser/resources/docs_app/48.png +++ /dev/null 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 Binary files differdeleted file mode 100644 index 679e7a2..0000000 --- a/chrome/browser/resources/gmail_app/128.png +++ /dev/null diff --git a/chrome/browser/resources/gmail_app/24.png b/chrome/browser/resources/gmail_app/24.png Binary files differdeleted file mode 100644 index 8b14b22..0000000 --- a/chrome/browser/resources/gmail_app/24.png +++ /dev/null diff --git a/chrome/browser/resources/gmail_app/32.png b/chrome/browser/resources/gmail_app/32.png Binary files differdeleted file mode 100644 index bfd8aa4..0000000 --- a/chrome/browser/resources/gmail_app/32.png +++ /dev/null diff --git a/chrome/browser/resources/gmail_app/48.png b/chrome/browser/resources/gmail_app/48.png Binary files differdeleted file mode 100644 index bc1f9fd..0000000 --- a/chrome/browser/resources/gmail_app/48.png +++ /dev/null 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\ |