summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/browser.cc27
-rw-r--r--chrome/browser/chromeos/cros_settings.h2
-rw-r--r--chrome/browser/dom_ui/app_launcher_handler.cc58
-rw-r--r--chrome/browser/dom_ui/app_launcher_handler.h17
-rw-r--r--chrome/browser/dom_ui/ntp_resource_cache.cc14
-rw-r--r--chrome/browser/extensions/extension_prefs.cc96
-rw-r--r--chrome/browser/extensions/extension_prefs.h34
-rw-r--r--chrome/browser/prefs/pref_notifier.h2
-rw-r--r--chrome/browser/prefs/pref_service.h6
-rw-r--r--chrome/browser/resources/new_new_tab.html10
-rw-r--r--chrome/browser/resources/ntp/apps.js51
-rw-r--r--chrome/browser/resources/shared/css/menu.css17
-rw-r--r--chrome/browser/resources/shared/js/cr/ui/command.js6
-rw-r--r--chrome/browser/resources/shared/js/cr/ui/menu_item.js11
-rwxr-xr-xtools/grit/grit/format/html_inline.py16
15 files changed, 307 insertions, 60 deletions
diff --git a/chrome/browser/browser.cc b/chrome/browser/browser.cc
index 1d2c82f..13bfbc1 100644
--- a/chrome/browser/browser.cc
+++ b/chrome/browser/browser.cc
@@ -47,6 +47,7 @@
#include "chrome/browser/extensions/extension_browser_event_router.h"
#include "chrome/browser/extensions/extension_disabled_infobar_delegate.h"
#include "chrome/browser/extensions/extension_host.h"
+#include "chrome/browser/extensions/extension_prefs.h"
#include "chrome/browser/extensions/extension_tabs_module.h"
#include "chrome/browser/extensions/extensions_service.h"
#include "chrome/browser/find_bar.h"
@@ -556,16 +557,28 @@ TabContents* Browser::OpenApplicationTab(Profile* profile,
Extension* extension,
Browser** browser) {
Browser* local_browser = BrowserList::GetLastActiveWithProfile(profile);
+ TabContents* tab_contents = NULL;
if (!local_browser || local_browser->type() != Browser::TYPE_NORMAL)
- return NULL;
+ return tab_contents;
+
+ // Check the prefs for overridden mode.
+ ExtensionsService* extensions_service = profile->GetExtensionsService();
+ DCHECK(extensions_service);
- // TODO(erikkay): This doesn't seem like the right transition in all cases.
- PageTransition::Type transition = PageTransition::START_PAGE;
+ ExtensionPrefs::LaunchType launch_type =
+ extensions_service->extension_prefs()->GetLaunchType(extension->id());
+ int add_type = TabStripModel::ADD_SELECTED;
+ if (launch_type == ExtensionPrefs::LAUNCH_PINNED)
+ add_type |= TabStripModel::ADD_PINNED;
- return local_browser->AddTabWithURL(
- extension->GetFullLaunchURL(), GURL(), transition, -1,
- TabStripModel::ADD_PINNED | TabStripModel::ADD_SELECTED,
- NULL, "", browser);
+ // TODO(erikkay): START_PAGE doesn't seem like the right transition in all
+ // cases.
+ tab_contents = local_browser->AddTabWithURL(extension->GetFullLaunchURL(),
+ GURL(), PageTransition::START_PAGE, -1, add_type, NULL, "", browser);
+ if (launch_type == ExtensionPrefs::LAUNCH_FULLSCREEN)
+ local_browser->window()->SetFullscreen(true);
+
+ return tab_contents;
}
// static
diff --git a/chrome/browser/chromeos/cros_settings.h b/chrome/browser/chromeos/cros_settings.h
index 596b093..226ec08 100644
--- a/chrome/browser/chromeos/cros_settings.h
+++ b/chrome/browser/chromeos/cros_settings.h
@@ -62,7 +62,7 @@ class CrosSettings : public NonThreadSafe {
bool RemoveSettingsProvider(CrosSettingsProvider* provider);
// If the pref at the given path changes, we call the observer's Observe
- // method with NOTIFY_PREF_CHANGED.
+ // method with PREF_CHANGED.
void AddSettingsObserver(const char* path, NotificationObserver* obs);
void RemoveSettingsObserver(const char* path, NotificationObserver* obs);
diff --git a/chrome/browser/dom_ui/app_launcher_handler.cc b/chrome/browser/dom_ui/app_launcher_handler.cc
index d85c2c5..9c867d1 100644
--- a/chrome/browser/dom_ui/app_launcher_handler.cc
+++ b/chrome/browser/dom_ui/app_launcher_handler.cc
@@ -12,6 +12,7 @@
#include "chrome/browser/app_launched_animation.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
+#include "chrome/browser/extensions/extension_prefs.h"
#include "chrome/browser/extensions/extensions_service.h"
#include "chrome/browser/platform_util.h"
#include "chrome/browser/tab_contents/tab_contents.h"
@@ -68,6 +69,8 @@ void AppLauncherHandler::RegisterMessages() {
NewCallback(this, &AppLauncherHandler::HandleGetApps));
dom_ui_->RegisterMessageCallback("launchApp",
NewCallback(this, &AppLauncherHandler::HandleLaunchApp));
+ dom_ui_->RegisterMessageCallback("setLaunchType",
+ NewCallback(this, &AppLauncherHandler::HandleSetLaunchType));
dom_ui_->RegisterMessageCallback("uninstallApp",
NewCallback(this, &AppLauncherHandler::HandleUninstallApp));
}
@@ -81,7 +84,15 @@ void AppLauncherHandler::Observe(NotificationType type,
if (dom_ui_->tab_contents())
HandleGetApps(NULL);
break;
+ case NotificationType::PREF_CHANGED: {
+ if (!dom_ui_->tab_contents())
+ break;
+ DictionaryValue dictionary;
+ FillAppDictionary(&dictionary);
+ dom_ui_->CallJavascriptFunction(L"appsPrefChangeCallback", dictionary);
+ break;
+ }
default:
NOTREACHED();
}
@@ -89,6 +100,7 @@ void AppLauncherHandler::Observe(NotificationType type,
// static
void AppLauncherHandler::CreateAppInfo(Extension* extension,
+ ExtensionPrefs* extension_prefs,
DictionaryValue* value) {
value->Clear();
value->SetString("id", extension->id());
@@ -96,22 +108,18 @@ void AppLauncherHandler::CreateAppInfo(Extension* extension,
value->SetString("description", extension->description());
value->SetString("launch_url", extension->GetFullLaunchURL().spec());
value->SetString("options_url", extension->options_url().spec());
-
value->SetString("icon_big", GetIconURL(
extension, Extension::EXTENSION_ICON_LARGE,
"chrome://theme/IDR_APP_DEFAULT_ICON"));
value->SetString("icon_small", GetIconURL(
extension, Extension::EXTENSION_ICON_BITTY,
std::string("chrome://favicon/") + extension->GetFullLaunchURL().spec()));
+ value->SetInteger("launch_container", extension->launch_container());
+ value->SetInteger("launch_type",
+ extension_prefs->GetLaunchType(extension->id()));
}
-void AppLauncherHandler::HandleGetApps(const ListValue* args) {
- bool show_debug_link = CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kAppsDebug);
-
- DictionaryValue dictionary;
- dictionary.SetBoolean("showDebugLink", show_debug_link);
-
+void AppLauncherHandler::FillAppDictionary(DictionaryValue* dictionary) {
ListValue* list = new ListValue();
const ExtensionList* extensions = extensions_service_->extensions();
for (ExtensionList::const_iterator it = extensions->begin();
@@ -120,12 +128,16 @@ void AppLauncherHandler::HandleGetApps(const ListValue* args) {
// gets special treatment in ntp/apps.js.
if ((*it)->is_app() && (*it)->id() != extension_misc::kWebStoreAppId) {
DictionaryValue* app_info = new DictionaryValue();
- CreateAppInfo(*it, app_info);
+ CreateAppInfo(*it, extensions_service_->extension_prefs(), app_info);
list->Append(app_info);
}
}
+ dictionary->Set("apps", list);
+}
- dictionary.Set("apps", list);
+void AppLauncherHandler::HandleGetApps(const ListValue* args) {
+ DictionaryValue dictionary;
+ FillAppDictionary(&dictionary);
dom_ui_->CallJavascriptFunction(L"getAppsCallback", dictionary);
// First time we get here we set up the observer so that we can tell update
@@ -136,6 +148,11 @@ void AppLauncherHandler::HandleGetApps(const ListValue* args) {
registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
NotificationService::AllSources());
}
+ if (pref_change_registrar_.IsEmpty()) {
+ pref_change_registrar_.Init(
+ extensions_service_->extension_prefs()->pref_service());
+ pref_change_registrar_.Add(ExtensionPrefs::kExtensionsPref, this);
+ }
}
void AppLauncherHandler::HandleLaunchApp(const ListValue* args) {
@@ -165,7 +182,6 @@ void AppLauncherHandler::HandleLaunchApp(const ListValue* args) {
extensions_service_->GetExtensionById(extension_id, false);
DCHECK(extension);
Profile* profile = extensions_service_->profile();
- extension_misc::LaunchContainer container = extension->launch_container();
// To give a more "launchy" experience when using the NTP launcher, we close
// it automatically.
@@ -175,7 +191,7 @@ void AppLauncherHandler::HandleLaunchApp(const ListValue* args) {
old_contents = browser->GetSelectedTabContents();
AnimateAppIcon(extension, rect);
- Browser::OpenApplication(profile, extension, container);
+ Browser::OpenApplication(profile, extension, extension->launch_container());
if (old_contents &&
old_contents->GetURL().GetOrigin() ==
@@ -184,6 +200,24 @@ void AppLauncherHandler::HandleLaunchApp(const ListValue* args) {
}
}
+void AppLauncherHandler::HandleSetLaunchType(const ListValue* args) {
+ std::string extension_id;
+ int launch_type;
+ if (!args->GetString(0, &extension_id) ||
+ !ExtractInt(args, 1, &launch_type)) {
+ NOTREACHED();
+ return;
+ }
+
+ Extension* extension =
+ extensions_service_->GetExtensionById(extension_id, false);
+ DCHECK(extension);
+
+ extensions_service_->extension_prefs()->SetLaunchType(
+ extension_id,
+ static_cast<ExtensionPrefs::LaunchType>(launch_type));
+}
+
void AppLauncherHandler::AnimateAppIcon(Extension* extension,
const gfx::Rect& rect) {
// We make this check for the case of minimized windows, unit tests, etc.
diff --git a/chrome/browser/dom_ui/app_launcher_handler.h b/chrome/browser/dom_ui/app_launcher_handler.h
index ac29dfb..23c1753 100644
--- a/chrome/browser/dom_ui/app_launcher_handler.h
+++ b/chrome/browser/dom_ui/app_launcher_handler.h
@@ -9,11 +9,15 @@
#include "base/scoped_ptr.h"
#include "chrome/browser/dom_ui/dom_ui.h"
#include "chrome/browser/extensions/extension_install_ui.h"
+#include "chrome/browser/prefs/pref_change_registrar.h"
#include "chrome/common/notification_observer.h"
#include "chrome/common/notification_registrar.h"
class Extension;
+class ExtensionPrefs;
class ExtensionsService;
+class NotificationRegistrar;
+class PrefChangeRegistrar;
namespace gfx {
class Rect;
@@ -38,7 +42,12 @@ class AppLauncherHandler
const NotificationDetails& details);
// Populate a dictionary with the information from an extension.
- static void CreateAppInfo(Extension* extension, DictionaryValue* value);
+ static void CreateAppInfo(Extension* extension,
+ ExtensionPrefs* extension_prefs,
+ DictionaryValue* value);
+
+ // Populate the given dictionary with all installed app info.
+ void FillAppDictionary(DictionaryValue* value);
// Callback for the "getApps" message.
void HandleGetApps(const ListValue* args);
@@ -46,6 +55,9 @@ class AppLauncherHandler
// Callback for the "launchApp" message.
void HandleLaunchApp(const ListValue* args);
+ // Callback for the "setLaunchType" message.
+ void HandleSetLaunchType(const ListValue* args);
+
// Callback for the "uninstallApp" message.
void HandleUninstallApp(const ListValue* args);
@@ -69,6 +81,9 @@ class AppLauncherHandler
// when necessary.
NotificationRegistrar registrar_;
+ // Monitor extension preference changes so that the DOM UI can be notified.
+ PrefChangeRegistrar pref_change_registrar_;
+
// Used to show confirmation UI for uninstalling/enabling extensions in
// incognito mode.
scoped_ptr<ExtensionInstallUI> install_ui_;
diff --git a/chrome/browser/dom_ui/ntp_resource_cache.cc b/chrome/browser/dom_ui/ntp_resource_cache.cc
index bd7ff37..377d3eb 100644
--- a/chrome/browser/dom_ui/ntp_resource_cache.cc
+++ b/chrome/browser/dom_ui/ntp_resource_cache.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// 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.
@@ -268,11 +268,11 @@ void NTPResourceCache::CreateNewTabHTML() {
l10n_util::GetStringUTF16(IDS_NEW_TAB_TIPS));
localized_strings.SetString("close", l10n_util::GetStringUTF16(IDS_CLOSE));
localized_strings.SetString("history",
- l10n_util::GetStringUTF16(IDS_NEW_TAB_HISTORY));
+ l10n_util::GetStringUTF16(IDS_NEW_TAB_HISTORY));
localized_strings.SetString("downloads",
- l10n_util::GetStringUTF16(IDS_NEW_TAB_DOWNLOADS));
+ l10n_util::GetStringUTF16(IDS_NEW_TAB_DOWNLOADS));
localized_strings.SetString("help",
- l10n_util::GetStringUTF16(IDS_NEW_TAB_HELP));
+ l10n_util::GetStringUTF16(IDS_NEW_TAB_HELP));
localized_strings.SetString("helpurl",
GetUrlWithLang(GURL(kHelpContentUrl)));
localized_strings.SetString("appsettings",
@@ -281,6 +281,12 @@ void NTPResourceCache::CreateNewTabHTML() {
l10n_util::GetStringUTF16(IDS_NEW_TAB_APP_UNINSTALL));
localized_strings.SetString("appoptions",
l10n_util::GetStringUTF16(IDS_NEW_TAB_APP_OPTIONS));
+ localized_strings.SetString("applaunchtypepinned",
+ l10n_util::GetStringUTF16(IDS_APP_CONTEXT_MENU_OPEN_PINNED));
+ localized_strings.SetString("applaunchtyperegular",
+ l10n_util::GetStringUTF16(IDS_APP_CONTEXT_MENU_OPEN_REGULAR));
+ localized_strings.SetString("applaunchtypefullscreen",
+ l10n_util::GetStringUTF16(IDS_APP_CONTEXT_MENU_OPEN_FULLSCREEN));
localized_strings.SetString("web_store_title",
l10n_util::GetStringUTF16(IDS_EXTENSION_WEB_STORE_TITLE));
localized_strings.SetString("web_store_url",
diff --git a/chrome/browser/extensions/extension_prefs.cc b/chrome/browser/extensions/extension_prefs.cc
index 058ede3..3fbea88 100644
--- a/chrome/browser/extensions/extension_prefs.cc
+++ b/chrome/browser/extensions/extension_prefs.cc
@@ -14,11 +14,7 @@ using base::Time;
namespace {
-// Preferences keys
-
-// A preference that keeps track of per-extension settings. This is a dictionary
-// object read from the Preferences file, keyed off of extension id's.
-const char kExtensionsPref[] = "extensions.settings";
+// Additional preferences keys
// Where an extension was installed from. (see Extension::Location)
const char kPrefLocation[] = "location";
@@ -79,6 +75,10 @@ const char kPrefAllowFileAccess[] = "allowFileAccess";
// purchased apps.
const char kWebStoreLogin[] = "extensions.webstore_login";
+// A preference set by the the NTP to persist the desired launch container type
+// used for apps.
+const char kPrefLaunchType[] = "launchType";
+
} // namespace
////////////////////////////////////////////////////////////////////////////////
@@ -90,7 +90,8 @@ namespace {
// id. We can remove this in a couple of months. (See http://crbug.com/40017
// and http://crbug.com/39745 for more details).
static void CleanupBadExtensionKeys(PrefService* prefs) {
- DictionaryValue* dictionary = prefs->GetMutableDictionary(kExtensionsPref);
+ DictionaryValue* dictionary =
+ prefs->GetMutableDictionary(ExtensionPrefs::kExtensionsPref);
std::set<std::string> bad_keys;
for (DictionaryValue::key_iterator i = dictionary->begin_keys();
i != dictionary->end_keys(); ++i) {
@@ -121,6 +122,9 @@ ExtensionPrefs::ExtensionPrefs(PrefService* prefs, const FilePath& root_dir)
MakePathsRelative();
}
+// static
+const char ExtensionPrefs::kExtensionsPref[] = "extensions.settings";
+
static FilePath::StringType MakePathRelative(const FilePath& parent,
const FilePath& child,
bool *dirty) {
@@ -164,7 +168,7 @@ void ExtensionPrefs::MakePathsRelative() {
}
}
if (dirty)
- prefs_->ScheduleSavePersistentPrefs();
+ SavePrefsAndNotify();
}
void ExtensionPrefs::MakePathsAbsolute(DictionaryValue* dict) {
@@ -233,6 +237,36 @@ bool ExtensionPrefs::ReadExtensionPrefBoolean(
return ReadBooleanFromPref(ext, pref_key);
}
+bool ExtensionPrefs::ReadIntegerFromPref(
+ DictionaryValue* ext, const std::string& pref_key, int* out_value) {
+ if (!ext->HasKey(pref_key)) return false;
+ if (!ext->GetInteger(pref_key, out_value)) {
+ NOTREACHED() << "Failed to fetch " << pref_key << " flag.";
+ // In case we could not fetch the flag, we treat it as false.
+ return false;
+ }
+ return out_value != NULL;
+}
+
+bool ExtensionPrefs::ReadExtensionPrefInteger(
+ const std::string& extension_id, const std::string& pref_key,
+ int* out_value) {
+ const DictionaryValue* extensions = prefs_->GetDictionary(kExtensionsPref);
+ if (!extensions)
+ return false;
+ DictionaryValue* ext = NULL;
+ if (!extensions->GetDictionary(extension_id, &ext)) {
+ // No such extension yet.
+ return false;
+ }
+ return ReadIntegerFromPref(ext, pref_key, out_value);
+}
+
+void ExtensionPrefs::SavePrefsAndNotify() {
+ prefs_->ScheduleSavePersistentPrefs();
+ prefs_->pref_notifier()->OnUserPreferenceSet(kExtensionsPref);
+}
+
bool ExtensionPrefs::IsBlacklistBitSet(DictionaryValue* ext) {
return ReadBooleanFromPref(ext, kPrefBlacklist);
}
@@ -289,7 +323,7 @@ void ExtensionPrefs::SetDidExtensionEscalatePermissions(
Extension* extension, bool did_escalate) {
UpdateExtensionPref(extension->id(), kExtensionDidEscalatePermissions,
Value::CreateBooleanValue(did_escalate));
- prefs_->SavePersistentPrefs();
+ prefs_->ScheduleSavePersistentPrefs();
}
void ExtensionPrefs::UpdateBlacklist(
@@ -343,8 +377,7 @@ void ExtensionPrefs::UpdateBlacklist(
for (unsigned int i = 0; i < remove_pref_ids.size(); ++i) {
DeleteExtensionPrefs(remove_pref_ids[i]);
}
- // Update persistent registry
- prefs_->ScheduleSavePersistentPrefs();
+ SavePrefsAndNotify();
return;
}
@@ -368,7 +401,7 @@ void ExtensionPrefs::SetLastPingDayImpl(const Time& time,
}
std::string value = base::Int64ToString(time.ToInternalValue());
dictionary->SetString(kLastPingDay, value);
- prefs_->ScheduleSavePersistentPrefs();
+ SavePrefsAndNotify();
}
Time ExtensionPrefs::LastPingDay(const std::string& extension_id) const {
@@ -399,7 +432,7 @@ void ExtensionPrefs::SetIsIncognitoEnabled(const std::string& extension_id,
bool enabled) {
UpdateExtensionPref(extension_id, kPrefIncognitoEnabled,
Value::CreateBooleanValue(enabled));
- prefs_->SavePersistentPrefs();
+ SavePrefsAndNotify();
}
bool ExtensionPrefs::AllowFileAccess(const std::string& extension_id) {
@@ -410,7 +443,26 @@ void ExtensionPrefs::SetAllowFileAccess(const std::string& extension_id,
bool allow) {
UpdateExtensionPref(extension_id, kPrefAllowFileAccess,
Value::CreateBooleanValue(allow));
- prefs_->SavePersistentPrefs();
+ SavePrefsAndNotify();
+}
+
+ExtensionPrefs::LaunchType ExtensionPrefs::GetLaunchType(
+ const std::string& extension_id) {
+ int value;
+ if (ReadExtensionPrefInteger(extension_id, kPrefLaunchType, &value) && (
+ value == LAUNCH_PINNED ||
+ value == LAUNCH_REGULAR ||
+ value == LAUNCH_FULLSCREEN)) {
+ return static_cast<LaunchType>(value);
+ }
+ return LAUNCH_PINNED;
+}
+
+void ExtensionPrefs::SetLaunchType(const std::string& extension_id,
+ LaunchType launch_type) {
+ UpdateExtensionPref(extension_id, kPrefLaunchType,
+ Value::CreateIntegerValue(static_cast<int>(launch_type)));
+ SavePrefsAndNotify();
}
void ExtensionPrefs::GetKilledExtensionIds(std::set<std::string>* killed_ids) {
@@ -462,7 +514,7 @@ void ExtensionPrefs::SetToolbarOrder(
iter != extension_ids.end(); ++iter) {
toolbar_order->Append(new StringValue(*iter));
}
- prefs_->ScheduleSavePersistentPrefs();
+ SavePrefsAndNotify();
}
void ExtensionPrefs::OnExtensionInstalled(
@@ -484,7 +536,7 @@ void ExtensionPrefs::OnExtensionInstalled(
UpdateExtensionPref(id, kPrefManifest,
extension->manifest_value()->DeepCopy());
}
- prefs_->SavePersistentPrefs();
+ SavePrefsAndNotify();
}
void ExtensionPrefs::OnExtensionUninstalled(const std::string& extension_id,
@@ -497,7 +549,7 @@ void ExtensionPrefs::OnExtensionUninstalled(const std::string& extension_id,
if (!external_uninstall && Extension::IsExternalLocation(location)) {
UpdateExtensionPref(extension_id, kPrefState,
Value::CreateIntegerValue(Extension::KILLBIT));
- prefs_->ScheduleSavePersistentPrefs();
+ SavePrefsAndNotify();
} else {
DeleteExtensionPrefs(extension_id);
}
@@ -525,7 +577,7 @@ void ExtensionPrefs::SetExtensionState(Extension* extension,
Extension::State state) {
UpdateExtensionPref(extension->id(), kPrefState,
Value::CreateIntegerValue(state));
- prefs_->SavePersistentPrefs();
+ SavePrefsAndNotify();
}
std::string ExtensionPrefs::GetVersionString(const std::string& extension_id) {
@@ -546,7 +598,7 @@ void ExtensionPrefs::UpdateManifest(Extension* extension) {
if (extension->location() != Extension::LOAD) {
UpdateExtensionPref(extension->id(), kPrefManifest,
extension->manifest_value()->DeepCopy());
- prefs_->ScheduleSavePersistentPrefs();
+ SavePrefsAndNotify();
}
}
@@ -577,7 +629,7 @@ void ExtensionPrefs::DeleteExtensionPrefs(const std::string& extension_id) {
DictionaryValue* dict = prefs_->GetMutableDictionary(kExtensionsPref);
if (dict->HasKey(extension_id)) {
dict->Remove(extension_id, NULL);
- prefs_->ScheduleSavePersistentPrefs();
+ SavePrefsAndNotify();
}
}
@@ -717,7 +769,7 @@ void ExtensionPrefs::SetIdleInstallInfo(const std::string& extension_id,
info->SetString(kIdleInstallInfoFetchTime,
base::Int64ToString(fetch_time.ToInternalValue()));
extension_prefs->Set(kIdleInstallInfo, info);
- prefs_->ScheduleSavePersistentPrefs();
+ SavePrefsAndNotify();
}
bool ExtensionPrefs::RemoveIdleInstallInfo(const std::string& extension_id) {
@@ -725,7 +777,7 @@ bool ExtensionPrefs::RemoveIdleInstallInfo(const std::string& extension_id) {
if (!extension_prefs)
return false;
bool result = extension_prefs->Remove(kIdleInstallInfo, NULL);
- prefs_->ScheduleSavePersistentPrefs();
+ SavePrefsAndNotify();
return result;
}
@@ -807,7 +859,7 @@ bool ExtensionPrefs::GetWebStoreLogin(std::string* result) {
void ExtensionPrefs::SetWebStoreLogin(const std::string& login) {
prefs_->SetString(kWebStoreLogin, login);
- prefs_->ScheduleSavePersistentPrefs();
+ SavePrefsAndNotify();
}
// static
diff --git a/chrome/browser/extensions/extension_prefs.h b/chrome/browser/extensions/extension_prefs.h
index d753e08..01226cd 100644
--- a/chrome/browser/extensions/extension_prefs.h
+++ b/chrome/browser/extensions/extension_prefs.h
@@ -21,8 +21,21 @@
// from there.
class ExtensionPrefs {
public:
+ // Key name for a preference that keeps track of per-extension settings. This
+ // is a dictionary object read from the Preferences file, keyed off of
+ // extension ids.
+ static const char kExtensionsPref[];
+
typedef std::vector<linked_ptr<ExtensionInfo> > ExtensionsInfo;
+ // This enum is used for the launch type the user wants to use for an
+ // application.
+ enum LaunchType {
+ LAUNCH_PINNED,
+ LAUNCH_REGULAR,
+ LAUNCH_FULLSCREEN
+ };
+
explicit ExtensionPrefs(PrefService* prefs, const FilePath& root_dir_);
// Returns a copy of the Extensions prefs.
@@ -116,6 +129,9 @@ class ExtensionPrefs {
bool AllowFileAccess(const std::string& extension_id);
void SetAllowFileAccess(const std::string& extension_id, bool allow);
+ ExtensionPrefs::LaunchType GetLaunchType(const std::string& extension_id);
+ void SetLaunchType(const std::string& extension_id, LaunchType launch_type);
+
// Saves ExtensionInfo for each installed extension with the path to the
// version directory and the location. Blacklisted extensions won't be saved
// and neither will external extensions the user has explicitly uninstalled.
@@ -185,12 +201,30 @@ class ExtensionPrefs {
bool ReadExtensionPrefBoolean(const std::string& extension_id,
const std::string& pref_key);
+ // Reads an integer pref from |ext| with key |pref_key|.
+ // Return false if the value does not exist.
+ bool ReadIntegerFromPref(DictionaryValue* ext, const std::string& pref_key,
+ int* out_value);
+
+ // Reads an integer pref |pref_key| from extension with id |extension_id|.
+ bool ReadExtensionPrefInteger(const std::string& extension_id,
+ const std::string& pref_key,
+ int* out_value);
+
// Ensures and returns a mutable dictionary for extension |id|'s prefs.
DictionaryValue* GetOrCreateExtensionPref(const std::string& id);
// Same as above, but returns NULL if it doesn't exist.
DictionaryValue* GetExtensionPref(const std::string& id) const;
+ // Serializes the data and schedules a persistent save via the |PrefService|.
+ // Additionally fires a PREF_CHANGED notification with the top-level
+ // |kExtensionsPref| path set.
+ // TODO(andybons): Switch this to EXTENSION_PREF_CHANGED to be more granular.
+ // TODO(andybons): Use a ScopedPrefUpdate to update observers on changes to
+ // the mutable extension dictionary.
+ void SavePrefsAndNotify();
+
// Checks if kPrefBlacklist is set to true in the DictionaryValue.
// Return false if the value is false or kPrefBlacklist does not exist.
// This is used to decide if an extension is blacklisted.
diff --git a/chrome/browser/prefs/pref_notifier.h b/chrome/browser/prefs/pref_notifier.h
index d981310..98dc1e3 100644
--- a/chrome/browser/prefs/pref_notifier.h
+++ b/chrome/browser/prefs/pref_notifier.h
@@ -71,7 +71,7 @@ class PrefNotifier : public NonThreadSafe,
virtual void FireObservers(const char* path);
// If the pref at the given path changes, we call the observer's Observe
- // method with NOTIFY_PREF_CHANGED.
+ // method with PREF_CHANGED.
void AddPrefObserver(const char* path, NotificationObserver* obs);
void RemovePrefObserver(const char* path, NotificationObserver* obs);
diff --git a/chrome/browser/prefs/pref_service.h b/chrome/browser/prefs/pref_service.h
index 5cedd52..3e90db6 100644
--- a/chrome/browser/prefs/pref_service.h
+++ b/chrome/browser/prefs/pref_service.h
@@ -239,9 +239,9 @@ class PrefService : public NonThreadSafe {
friend class subtle::PrefMemberBase;
// If the pref at the given path changes, we call the observer's Observe
- // method with NOTIFY_PREF_CHANGED. Note that observers should not call
- // these methods directly but rather use a PrefChangeRegistrar to make sure
- // the observer gets cleaned up properly.
+ // method with PREF_CHANGED. Note that observers should not call these methods
+ // directly but rather use a PrefChangeRegistrar to make sure the observer
+ // gets cleaned up properly.
virtual void AddPrefObserver(const char* path, NotificationObserver* obs);
virtual void RemovePrefObserver(const char* path, NotificationObserver* obs);
diff --git a/chrome/browser/resources/new_new_tab.html b/chrome/browser/resources/new_new_tab.html
index 23e8e24..7290e32 100644
--- a/chrome/browser/resources/new_new_tab.html
+++ b/chrome/browser/resources/new_new_tab.html
@@ -176,10 +176,20 @@ if ('mode' in hashParams) {
<command id="apps-launch-command">
<command id="apps-options-command" i18n-values=".label:appoptions">
<command id="apps-uninstall-command" i18n-values=".label:appuninstall">
+<command id="apps-launch-type-pinned" i18n-values=".label:applaunchtypepinned"
+ launch-type="0">
+<command id="apps-launch-type-regular" i18n-values=".label:applaunchtyperegular"
+ launch-type="1">
+<command id="apps-launch-type-fullscreen"
+ i18n-values=".label:applaunchtypefullscreen" launch-type="2">
<menu id="app-context-menu">
<button class="default" command="#apps-launch-command"></button>
<hr>
+ <button command="#apps-launch-type-pinned" launch-type="0"></button>
+ <button command="#apps-launch-type-regular" launch-type="1"></button>
+ <button command="#apps-launch-type-fullscreen" launch-type="2"></button>
+ <hr>
<button command="#apps-options-command"></button>
<button command="#apps-uninstall-command"></button>
</menu>
diff --git a/chrome/browser/resources/ntp/apps.js b/chrome/browser/resources/ntp/apps.js
index d9098d5..b128f05 100644
--- a/chrome/browser/resources/ntp/apps.js
+++ b/chrome/browser/resources/ntp/apps.js
@@ -36,6 +36,15 @@ function getAppsCallback(data) {
}
}
+function appsPrefChangeCallback(data) {
+ // Currently the only pref that is watched is the launch type.
+ data.apps.forEach(function(app) {
+ var appLink = document.querySelector('.app a[app-id=' + app['id'] + ']');
+ if (appLink)
+ appLink.setAttribute('launch-type', app['launch_type']);
+ });
+}
+
var apps = (function() {
function createElement(app) {
@@ -44,6 +53,7 @@ var apps = (function() {
var a = div.appendChild(document.createElement('a'));
a.setAttribute('app-id', app['id']);
+ a.setAttribute('launch-type', app['launch_type']);
a.xtitle = a.textContent = app['name'];
a.href = app['launch_url'];
@@ -99,6 +109,20 @@ var apps = (function() {
return false;
}
+ // Keep in sync with LaunchType in extension_prefs.h
+ var LaunchType = {
+ LAUNCH_PINNED: 0,
+ LAUNCH_REGULAR: 1,
+ LAUNCH_FULLSCREEN: 2
+ };
+
+ // Keep in sync with LaunchContainer in extension.h
+ var LaunchContainer = {
+ LAUNCH_WINDOW: 0,
+ LAUNCH_PANEL: 1,
+ LAUNCH_TAB: 2
+ };
+
var currentApp;
function addContextMenu(el, app) {
@@ -113,6 +137,24 @@ var apps = (function() {
$('apps-launch-command').label = app['name'];
$('apps-options-command').canExecuteChange();
+ var appLinkSel = '.app a[app-id=' + app['id'] + ']';
+ var launchType =
+ el.querySelector(appLinkSel).getAttribute('launch-type');
+
+ var launchContainer = app['launch_container'];
+ var isPanel = launchContainer == LaunchContainer.LAUNCH_PANEL;
+
+ // Update the commands related to the launch type.
+ var launchTypeIds = ['apps-launch-type-pinned',
+ 'apps-launch-type-regular',
+ 'apps-launch-type-fullscreen'];
+ launchTypeIds.forEach(function(id) {
+ var command = $(id);
+ command.disabled = isPanel;
+ command.checked = !isPanel &&
+ launchType == command.getAttribute('launch-type');
+ });
+
return $('app-context-menu');
}
});
@@ -122,7 +164,8 @@ var apps = (function() {
if (!currentApp)
return;
- switch (e.command.id) {
+ var commandId = e.command.id;
+ switch (commandId) {
case 'apps-options-command':
window.location = currentApp['options_url'];
break;
@@ -132,6 +175,12 @@ var apps = (function() {
case 'apps-uninstall-command':
chrome.send('uninstallApp', [currentApp['id']]);
break;
+ case 'apps-launch-type-pinned':
+ case 'apps-launch-type-regular':
+ case 'apps-launch-type-fullscreen':
+ chrome.send('setLaunchType',
+ [currentApp['id'], e.command.getAttribute('launch-type')]);
+ break;
}
});
diff --git a/chrome/browser/resources/shared/css/menu.css b/chrome/browser/resources/shared/css/menu.css
index a891a42..19f5248 100644
--- a/chrome/browser/resources/shared/css/menu.css
+++ b/chrome/browser/resources/shared/css/menu.css
@@ -57,3 +57,20 @@ menu > :not(hr)[selected]:active {
background-color: #426dc9;
color: #fff;
}
+
+menu > [checked]:before {
+ content: url("../images/checkbox_black.png");
+ width: 9px;
+ height: 9px;
+ display: inline-block;
+ vertical-align: 50%;
+ margin: 0 5px;
+}
+
+menu > [checked] {
+ -webkit-padding-start: 0;
+}
+
+menu > [selected][checked]:active:before {
+ content: url("../images/checkbox_white.png");
+} \ No newline at end of file
diff --git a/chrome/browser/resources/shared/js/cr/ui/command.js b/chrome/browser/resources/shared/js/cr/ui/command.js
index 1011398..61294f3 100644
--- a/chrome/browser/resources/shared/js/cr/ui/command.js
+++ b/chrome/browser/resources/shared/js/cr/ui/command.js
@@ -172,6 +172,12 @@ cr.define('cr.ui', function() {
cr.defineProperty(Command, 'hidden', cr.PropertyKind.BOOL_ATTR);
/**
+ * Whether the command is checked or not.
+ * @type {boolean}
+ */
+ cr.defineProperty(Command, 'checked', cr.PropertyKind.BOOL_ATTR);
+
+ /**
* Dispatches a canExecute event on the target.
* @param {cr.ui.Command} command The command that we are testing for.
* @param {Element} target The target element to dispatch the event on.
diff --git a/chrome/browser/resources/shared/js/cr/ui/menu_item.js b/chrome/browser/resources/shared/js/cr/ui/menu_item.js
index d570f78..c3e3169 100644
--- a/chrome/browser/resources/shared/js/cr/ui/menu_item.js
+++ b/chrome/browser/resources/shared/js/cr/ui/menu_item.js
@@ -52,6 +52,7 @@ cr.define('cr.ui', function() {
this.command_.removeEventListener('labelChange', this);
this.command_.removeEventListener('disabledChange', this);
this.command_.removeEventListener('hiddenChange', this);
+ this.command_.removeEventListener('checkedChange', this);
}
if (typeof command == 'string' && command[0] == '#') {
@@ -71,6 +72,7 @@ cr.define('cr.ui', function() {
this.command_.addEventListener('labelChange', this);
this.command_.addEventListener('disabledChange', this);
this.command_.addEventListener('hiddenChange', this);
+ this.command_.addEventListener('checkedChange', this);
}
},
@@ -124,6 +126,9 @@ cr.define('cr.ui', function() {
case 'labelChange':
this.label = this.command.label;
break;
+ case 'checkedChange':
+ this.checked = this.command.checked;
+ break;
}
}
};
@@ -146,6 +151,12 @@ cr.define('cr.ui', function() {
*/
cr.defineProperty(MenuItem, 'selected', cr.PropertyKind.BOOL_ATTR);
+ /**
+ * Whether the menu item is checked or not.
+ * @type {boolean}
+ */
+ cr.defineProperty(MenuItem, 'checked', cr.PropertyKind.BOOL_ATTR);
+
// Export
return {
MenuItem: MenuItem
diff --git a/tools/grit/grit/format/html_inline.py b/tools/grit/grit/format/html_inline.py
index b23f951..71d0f68 100755
--- a/tools/grit/grit/format/html_inline.py
+++ b/tools/grit/grit/format/html_inline.py
@@ -136,12 +136,12 @@ def InlineFile(input_filename, output_filename, grd_node):
"""Helper function to inline external script files"""
return InlineFileContents(src_match, '<script>%s</script>')
- def InlineCssText(text, css_filepath):
+ def InlineCSSText(text, css_filepath):
"""Helper function that inlines external resources in CSS text"""
filepath = os.path.dirname(css_filepath)
- return InlineCssBackgroundImages(text, filepath)
+ return InlineCSSImages(text, filepath)
- def InlineCssFile(src_match, inlined_files=inlined_files):
+ def InlineCSSFile(src_match, inlined_files=inlined_files):
"""Helper function to inline external css files.
Args:
@@ -157,11 +157,11 @@ def InlineFile(input_filename, output_filename, grd_node):
inlined_files.add(filepath)
# When resolving CSS files we need to pass in the path so that relative URLs
# can be resolved.
- return '<style>%s</style>' % InlineCssText(ReadFile(filepath), filepath)
+ return '<style>%s</style>' % InlineCSSText(ReadFile(filepath), filepath)
- def InlineCssBackgroundImages(text, filepath=input_filepath):
+ def InlineCSSImages(text, filepath=input_filepath):
"""Helper function that inlines external images in CSS backgrounds."""
- return re.sub('background(?:-image)?:[ ]*url\((?:\'|\")' +
+ return re.sub('(?:content|background(?:-image)?):[ ]*url\((?:\'|\")' +
'(?P<filename>[^"\'\)\(]*)(?:\'|\")',
lambda m: SrcReplace(m, filepath),
text)
@@ -174,7 +174,7 @@ def InlineFile(input_filename, output_filename, grd_node):
flat_text = re.sub(
'<link rel="stylesheet".+?href="(?P<filename>[^"\']*)".*?>',
- InlineCssFile,
+ InlineCSSFile,
flat_text)
flat_text = re.sub(
@@ -194,7 +194,7 @@ def InlineFile(input_filename, output_filename, grd_node):
flat_text)
# TODO(arv): Only do this inside <style> tags.
- flat_text = InlineCssBackgroundImages(flat_text)
+ flat_text = InlineCSSImages(flat_text)
flat_text = re.sub('<link rel="icon".+?href="(?P<filename>[^"\']*)"',
SrcReplace,