summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorarv@chromium.org <arv@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-06-21 18:57:23 +0000
committerarv@chromium.org <arv@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-06-21 18:57:23 +0000
commit3c92499fe304b9b65d647e3d78303aab3cd931c9 (patch)
tree5d277bf1419334a3798b26f3d5e5a4bdefbcc6eb /chrome
parentb5fe86e4e754ea16b709cfb65dc497fe03a7f077 (diff)
downloadchromium_src-3c92499fe304b9b65d647e3d78303aab3cd931c9.zip
chromium_src-3c92499fe304b9b65d647e3d78303aab3cd931c9.tar.gz
chromium_src-3c92499fe304b9b65d647e3d78303aab3cd931c9.tar.bz2
NTP: Add ability to uninstall apps from the ntp.
BUG=44915 TEST=Start chrome with --enable-apps (and optionally --enable-accelerated-compositing). Install some apps. Now hover over the app icon and click the wrench icon. Review URL: http://codereview.chromium.org/2832014 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@50368 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/app/generated_resources.grd13
-rw-r--r--chrome/browser/dom_ui/app_launcher_handler.cc34
-rw-r--r--chrome/browser/dom_ui/app_launcher_handler.h7
-rw-r--r--chrome/browser/dom_ui/ntp_resource_cache.cc11
-rw-r--r--chrome/browser/resources/new_new_tab.css50
-rw-r--r--chrome/browser/resources/new_new_tab.html5
-rw-r--r--chrome/browser/resources/new_new_tab.js87
-rw-r--r--chrome/browser/resources/new_tab_theme.css3
-rw-r--r--chrome/browser/resources/ntp/apps.css154
-rw-r--r--chrome/browser/resources/ntp/apps.js116
10 files changed, 328 insertions, 152 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 89e68b6a..5ae7ddb 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -6207,11 +6207,22 @@ Keep your key file in a safe place. You will need it to create new versions of y
desc="The action text to show as the close link for the notification shown after the user has set his/her home page.">
Close
</message>
-
<message name="IDS_NEW_TAB_MAKE_THIS_HOMEPAGE"
desc="Text for link that sets new tab page as home page">
Make this my home page
</message>
+ <message name="IDS_NEW_TAB_APP_SETTINGS"
+ desc="Text for the tooltip that is used for the button that shows the settings for an app icon.">
+ Settings
+ </message>
+ <message name="IDS_NEW_TAB_APP_UNINSTALL"
+ desc="Text for the button that allows uninstalling an app.">
+ Uninstall
+ </message>
+ <message name="IDS_NEW_TAB_APP_OPTIONS"
+ desc="Text for the button that takes the user to the options of an app.">
+ Options
+ </message>
<!-- SafeBrowsing -->
<message name="IDS_SAFE_BROWSING_MALWARE_TITLE" desc="SafeBrowsing Malware HTML title">
diff --git a/chrome/browser/dom_ui/app_launcher_handler.cc b/chrome/browser/dom_ui/app_launcher_handler.cc
index 31384cb..9dbdafb 100644
--- a/chrome/browser/dom_ui/app_launcher_handler.cc
+++ b/chrome/browser/dom_ui/app_launcher_handler.cc
@@ -55,6 +55,8 @@ void AppLauncherHandler::RegisterMessages() {
NewCallback(this, &AppLauncherHandler::HandleGetApps));
dom_ui_->RegisterMessageCallback("launchApp",
NewCallback(this, &AppLauncherHandler::HandleLaunchApp));
+ dom_ui_->RegisterMessageCallback("uninstallApp",
+ NewCallback(this, &AppLauncherHandler::HandleUninstallApp));
}
void AppLauncherHandler::Observe(NotificationType type,
@@ -80,6 +82,7 @@ void AppLauncherHandler::CreateAppInfo(Extension* extension,
value->SetString(L"name", extension->name());
value->SetString(L"description", extension->description());
value->SetString(L"launch_url", extension->GetFullLaunchURL().spec());
+ value->SetString(L"options_url", extension->options_url().spec());
FilePath relative_path =
extension->GetIconPath(Extension::EXTENSION_ICON_LARGE).relative_path();
@@ -95,20 +98,10 @@ void AppLauncherHandler::CreateAppInfo(Extension* extension,
}
void AppLauncherHandler::HandleGetApps(const Value* value) {
- std::string gallery_title;
- std::string gallery_url;
-
- // TODO(aa): Decide the final values for these and remove the switches.
- gallery_title = CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
- switches::kAppsGalleryTitle);
- gallery_url = CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
- switches::kAppsGalleryURL);
bool show_debug_link = CommandLine::ForCurrentProcess()->HasSwitch(
switches::kAppsDebug);
DictionaryValue dictionary;
- dictionary.SetString(L"galleryTitle", gallery_title);
- dictionary.SetString(L"galleryURL", gallery_url);
dictionary.SetBoolean(L"showDebugLink", show_debug_link);
ListValue* list = new ListValue();
@@ -217,3 +210,24 @@ void AppLauncherHandler::AnimateAppIcon(Extension* extension,
#endif
}
}
+
+void AppLauncherHandler::HandleUninstallApp(const Value* value) {
+ if (!value->IsType(Value::TYPE_LIST)) {
+ NOTREACHED();
+ return;
+ }
+
+ std::string extension_id;
+ const ListValue* list = static_cast<const ListValue*>(value);
+ if (!list->GetString(0, &extension_id)) {
+ NOTREACHED();
+ return;
+ }
+
+ // Make sure that the extension exists.
+ Extension* extension =
+ extensions_service_->GetExtensionById(extension_id, false);
+ DCHECK(extension);
+
+ extensions_service_->UninstallExtension(extension_id, false);
+}
diff --git a/chrome/browser/dom_ui/app_launcher_handler.h b/chrome/browser/dom_ui/app_launcher_handler.h
index f169580..b20923c 100644
--- a/chrome/browser/dom_ui/app_launcher_handler.h
+++ b/chrome/browser/dom_ui/app_launcher_handler.h
@@ -35,12 +35,15 @@ class AppLauncherHandler
// Populate a dictionary with the information from an extension.
static void CreateAppInfo(Extension* extension, DictionaryValue* value);
- // Callback for the "getAll" message.
+ // Callback for the "getApps" message.
void HandleGetApps(const Value* value);
- // Callback for the "launch" message.
+ // Callback for the "launchApp" message.
void HandleLaunchApp(const Value* value);
+ // Callback for the "uninstallApp" message.
+ void HandleUninstallApp(const Value* value);
+
private:
// Starts the animation of the app icon.
void AnimateAppIcon(Extension* extension, const gfx::Rect& rect);
diff --git a/chrome/browser/dom_ui/ntp_resource_cache.cc b/chrome/browser/dom_ui/ntp_resource_cache.cc
index 829a431..9ad62b7 100644
--- a/chrome/browser/dom_ui/ntp_resource_cache.cc
+++ b/chrome/browser/dom_ui/ntp_resource_cache.cc
@@ -286,6 +286,12 @@ void NTPResourceCache::CreateNewTabHTML() {
localized_strings.SetString(L"tips",
l10n_util::GetString(IDS_NEW_TAB_TIPS));
localized_strings.SetString(L"close", l10n_util::GetString(IDS_CLOSE));
+ localized_strings.SetString(L"appsettings",
+ l10n_util::GetString(IDS_NEW_TAB_APP_SETTINGS));
+ localized_strings.SetString(L"appuninstall",
+ l10n_util::GetString(IDS_NEW_TAB_APP_UNINSTALL));
+ localized_strings.SetString(L"appoptions",
+ l10n_util::GetString(IDS_NEW_TAB_APP_OPTIONS));
// Don't initiate the sync related message passing with the page if the sync
// code is not present.
@@ -301,6 +307,11 @@ void NTPResourceCache::CreateNewTabHTML() {
Animation::ShouldRenderRichAnimation() ? "true" : "false";
localized_strings.SetString(L"anim", anim);
+ const CommandLine* command_line = CommandLine::ForCurrentProcess();
+ bool has_3d =
+ command_line->HasSwitch(switches::kEnableAcceleratedCompositing);
+ localized_strings.SetString(L"has_3d", has_3d ? "true" : "false");
+
// Pass the shown_sections pref early so that we can prevent flicker.
ShownSectionsHandler::SetFirstAppLauncherRunPref(profile_->GetPrefs());
const int shown_sections = profile_->GetPrefs()->GetInteger(
diff --git a/chrome/browser/resources/new_new_tab.css b/chrome/browser/resources/new_new_tab.css
index a38fe18..0a8f22a 100644
--- a/chrome/browser/resources/new_new_tab.css
+++ b/chrome/browser/resources/new_new_tab.css
@@ -476,53 +476,3 @@ html[dir=rtl] #option-menu > [command=hide]:before {
margin-right: 10px;
}
}
-
-/* Apps */
-
-@-webkit-keyframes bounce {
- 0% {
- -webkit-transform: scale(0, 0);
- }
-
- 60% {
- -webkit-transform: scale(1.2, 1.2);
- }
-
- 100% {
- -webkit-transform: scale(1, 1);
- }
-}
-
-#apps-section a,
-#apps-section a[new=installed] {
- -webkit-box-sizing: border-box;
- -webkit-transition: background-color .15s;
- background: rgba(255, 255, 255, 0) /* transparent white */
- no-repeat center 10px;
- background-size: 96px 96px;
- border-radius: 10px;
- color: black;
- display: inline-block;
- font-weight: bold;
- margin: 5px 3px;
- overflow: hidden;
- padding: 111px 10px 10px; /* 10 + 96 + 5 */
- text-align: center;
- text-decoration: none;
- text-overflow: ellipsis;
- white-space: nowrap;
- width: 124px; /* 920 / 7 - margin * 2 */
-}
-
-#apps-section a[new=new] {
- opacity: 0;
-}
-
-#apps-section a[new=installed] {
- -webkit-animation: bounce .5s ease-in-out;
- -webkit-transition: opacity .5s;
-}
-
-#apps-section #gallery-entry {
- background-image: url('app_gallery_icon.png');
-}
diff --git a/chrome/browser/resources/new_new_tab.html b/chrome/browser/resources/new_new_tab.html
index 8a6339f..5768f5a 100644
--- a/chrome/browser/resources/new_new_tab.html
+++ b/chrome/browser/resources/new_new_tab.html
@@ -4,7 +4,8 @@
bookmarkbarattached:bookmarkbarattached;
hasattribution:hasattribution;
anim:anim;
- syncispresent:syncispresent">
+ syncispresent:syncispresent;
+ has_3d:has_3d">
<meta charset="utf-8">
<title i18n-content="title"></title>
@@ -58,6 +59,7 @@ registerCallback('setShownSections');
<!-- template data placeholder -->
<link rel="stylesheet" href="new_new_tab.css">
<link rel="stylesheet" href="ntp/most_visited.css">
+<link rel="stylesheet" href="ntp/apps.css">
<link rel="stylesheet" href="shared/css/menu.css">
<script>
@@ -216,4 +218,5 @@ i18nTemplate.process(document, templateData);
<script src="ntp/util.js"></script>
<script src="ntp/most_visited.js"></script>
<script src="new_new_tab.js"></script>
+<script src="ntp/apps.js"></script>
</html>
diff --git a/chrome/browser/resources/new_new_tab.js b/chrome/browser/resources/new_new_tab.js
index 8fc13a7..6d28923 100644
--- a/chrome/browser/resources/new_new_tab.js
+++ b/chrome/browser/resources/new_new_tab.js
@@ -11,93 +11,6 @@ function updateSimpleSection(id, section) {
$(id).classList.add('hidden');
}
-function getAppsCallback(data) {
- logEvent('recieved apps');
- var appsSection = $('apps-section');
- var debugSection = $('debug');
- appsSection.innerHTML = '';
-
- data.apps.forEach(function(app) {
- appsSection.appendChild(apps.createElement(app));
- });
-
- if (data.galleryTitle && data.galleryURL) {
- appsSection.appendChild(apps.createGalleryElement(
- data.galleryTitle, data.galleryURL));
- }
-
- // TODO(aa): Figure out what to do with the debug mode when we turn apps on
- // for everyone.
- if (appsSection.hasChildNodes()) {
- appsSection.classList.remove('disabled');
- if (data.showDebugLink) {
- debugSection.classList.remove('disabled');
- }
- } else {
- appsSection.classList.add('disabled');
- debugSection.classList.add('disabled');
- }
-}
-
-var apps = {
- /**
- * @this {!HTMLAnchorElement}
- */
- handleClick_: function() {
- var launchType = '';
- var inputElements = document.querySelectorAll(
- '#apps-launch-control input');
- for (var i = 0, input; input = inputElements[i]; i++) {
- if (input.checked) {
- launchType = input.value;
- break;
- }
- }
-
- // TODO(arv): Handle zoom?
- var rect = this.getBoundingClientRect();
- var cs = getComputedStyle(this);
- var size = cs.backgroundSize.split(/\s+/); // background-size has the
- // format '123px 456px'.
- var width = parseInt(size[0], 10);
- var height = parseInt(size[1], 10);
- // We are using background-position-x 50%.
- var left = rect.left + ((rect.width - width) >> 1); // Integer divide by 2.
- var top = rect.top + parseInt(cs.backgroundPositionY, 10);
-
- chrome.send('launchApp', [this.id, launchType,
- String(left), String(top),
- String(width), String(height)]);
- return false;
- },
-
- createElement: function(app) {
- var a = document.createElement('a');
- a.xtitle = a.textContent = app['name'];
- a.href = app['launch_url'];
- a.id = app['id'];
- a.onclick = apps.handleClick_;
- a.style.backgroundImage = url(app['icon']);
- if (hashParams['app-id'] == app['id']) {
- a.setAttribute('new', 'new');
- // Delay changing the attribute a bit to let the page settle down a bit.
- setTimeout(function() {
- a.setAttribute('new', 'installed');
- }, 500);
- }
- return a;
- },
-
- createGalleryElement: function(title, url) {
- var a = document.createElement('a');
- a.title = title;
- a.href = url;
- a.id = 'gallery-entry';
- a.textContent = title;
- return a;
- }
-};
-
var tipCache = {};
function tips(data) {
diff --git a/chrome/browser/resources/new_tab_theme.css b/chrome/browser/resources/new_tab_theme.css
index baa328e..b0c0b5d 100644
--- a/chrome/browser/resources/new_tab_theme.css
+++ b/chrome/browser/resources/new_tab_theme.css
@@ -132,7 +132,8 @@ body {
color: $8; /* COLOR_NTP_TEXT */
}
-#apps-section a:hover {
+#apps-section .app:hover > .front > a,
+#apps-section .app > .back {
color: $$3; /* COLOR_NTP_SECTION_TEXT */
background-color: $$1; /* COLOR_NTP_SECTION */;
}
diff --git a/chrome/browser/resources/ntp/apps.css b/chrome/browser/resources/ntp/apps.css
new file mode 100644
index 0000000..f54cd93
--- /dev/null
+++ b/chrome/browser/resources/ntp/apps.css
@@ -0,0 +1,154 @@
+/* Apps */
+
+#apps-section .app,
+#apps-section .app[new=installed] {
+ -webkit-box-sizing: border-box;
+ -webkit-perspective: 400;
+ border-radius: 10px;
+ color: black;
+ display: inline-block;
+ margin: 5px 3px;
+ position: relative;
+ height: 136px;
+ width: 124px; /* 920 / 7 - margin * 2 */
+}
+
+.app > .front,
+.app > .back,
+.app a {
+ border-radius: 10px;
+ bottom: 0;
+ left: 0;
+ position: absolute;
+ right: 0;
+ top: 0;
+}
+
+.app > .front,
+.app > .back {
+ -webkit-backface-visibility: hidden;
+ -webkit-transition: -webkit-transform .15s;
+}
+
+.app a {
+ -webkit-transition: background-color .5s;
+ background: rgba(255, 255, 255, 0) /* transparent white */
+ no-repeat center 10px;
+ background-size: 96px 96px;
+ font-weight: bold;
+ overflow: hidden;
+ padding: 111px 10px 10px; /* 10 + 96 + 5 */
+ text-align: center;
+ text-decoration: none;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.app .flip {
+ background-color: transparent;
+ border: 0;
+ height: 14px;
+ padding: 0;
+ position: absolute;
+ right: 5px;
+ top: 5px;
+ width: 14px;
+}
+
+.app > .front > .flip {
+ -webkit-transition: opacity .3s;
+ -webkit-transition-delay: 0;
+ background-image: url(chrome://theme/balloon_wrench);
+ opacity: 0;
+}
+
+.app > .front > .flip:hover {
+ -webkit-transition: none;
+ background-image: url(chrome://theme/balloon_wrench_hover);
+}
+
+.app:hover > .front > .flip,
+.app > .front > .flip:focus {
+ -webkit-transition-delay: .5s;
+ opacity: .9;
+}
+
+.app > .back > .flip {
+ background-image: url(chrome://theme/balloon_close);
+ opacity: .9;
+}
+
+.app > .back > .flip:hover {
+ background-image: url(chrome://theme/balloon_close_hover);
+}
+
+.app > .back {
+ padding: 10px;
+}
+
+.app > .back > h2 {
+ font-size: 100%;
+ margin: 10px 0;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.app > .back > button:not(.flip) {
+ width: 100%;
+}
+
+@-webkit-keyframes bounce {
+ 0% {
+ -webkit-transform: scale(0, 0);
+ }
+
+ 60% {
+ -webkit-transform: scale(1.2, 1.2);
+ }
+
+ 100% {
+ -webkit-transform: scale(1, 1);
+ }
+}
+
+#apps-section .app[new=new] {
+ opacity: 0;
+}
+
+#apps-section .app[new=installed] {
+ -webkit-animation: bounce .5s ease-in-out;
+ -webkit-transition: opacity .5s;
+}
+
+/* Make items on the wrong side non focusable by hiding them. */
+.app:not(.config) > .back button,
+.app.config > .front button,
+.app.config > .front a {
+ display: none;
+}
+
+html[has_3d=true] .app.config > .front {
+ -webkit-transform: rotateY(180deg);
+}
+
+html[has_3d=true] .app > .back {
+ -webkit-transform: rotateY(-180deg);
+}
+
+html[has_3d=true] .app.config > .back {
+ -webkit-transform: rotateY(0deg);
+}
+
+html[has_3d=false] .app.config > .front {
+ display: none;
+}
+
+html[has_3d=false] .app > .back {
+ display: none;
+}
+
+html[has_3d=false] .app.config > .back {
+ display: block;
+}
+
diff --git a/chrome/browser/resources/ntp/apps.js b/chrome/browser/resources/ntp/apps.js
new file mode 100644
index 0000000..9a5cc19
--- /dev/null
+++ b/chrome/browser/resources/ntp/apps.js
@@ -0,0 +1,116 @@
+// 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.
+
+function getAppsCallback(data) {
+ logEvent('recieved apps');
+ var appsSection = $('apps-section');
+ var debugSection = $('debug');
+ appsSection.textContent = '';
+
+ data.apps.forEach(function(app) {
+ appsSection.appendChild(apps.createElement(app));
+ });
+
+
+ // TODO(aa): Figure out what to do with the debug mode when we turn apps on
+ // for everyone.
+ if (appsSection.hasChildNodes()) {
+ appsSection.classList.remove('disabled');
+ if (data.showDebugLink) {
+ debugSection.classList.remove('disabled');
+ }
+ } else {
+ appsSection.classList.add('disabled');
+ debugSection.classList.add('disabled');
+ }
+}
+
+var apps = {
+ /**
+ * @this {!HTMLAnchorElement}
+ */
+ handleClick_: function() {
+ var launchType = '';
+ var inputElements = document.querySelectorAll(
+ '#apps-launch-control input');
+ for (var i = 0, input; input = inputElements[i]; i++) {
+ if (input.checked) {
+ launchType = input.value;
+ break;
+ }
+ }
+
+ // TODO(arv): Handle zoom?
+ var rect = this.getBoundingClientRect();
+ var cs = getComputedStyle(this);
+ var size = cs.backgroundSize.split(/\s+/); // background-size has the
+ // format '123px 456px'.
+ var width = parseInt(size[0], 10);
+ var height = parseInt(size[1], 10);
+ // We are using background-position-x 50%.
+ var left = rect.left + ((rect.width - width) >> 1); // Integer divide by 2.
+ var top = rect.top + parseInt(cs.backgroundPositionY, 10);
+
+ chrome.send('launchApp', [this.id, launchType,
+ String(left), String(top),
+ String(width), String(height)]);
+ return false;
+ },
+
+ createElement: function(app) {
+ var div = document.createElement('div');
+ div.className = 'app';
+
+ var front = div.appendChild(document.createElement('div'));
+ front.className = 'front';
+
+ var a = front.appendChild(document.createElement('a'));
+ a.id = app['id'];
+ a.xtitle = a.textContent = app['name'];
+ a.href = app['launch_url'];
+
+ a.onclick = apps.handleClick_;
+ a.style.backgroundImage = url(app['icon']);
+ if (hashParams['app-id'] == app['id']) {
+ div.setAttribute('new', 'new');
+ // Delay changing the attribute a bit to let the page settle down a bit.
+ setTimeout(function() {
+ div.setAttribute('new', 'installed');
+ }, 500);
+ }
+
+ var settingsButton = front.appendChild(document.createElement('button'));
+ settingsButton.className = 'flip';
+ settingsButton.title = localStrings.getString('appsettings');
+
+ var back = div.appendChild(document.createElement('div'));
+ back.className = 'back';
+
+ var header = back.appendChild(document.createElement('h2'));
+ header.textContent = app['name'];
+
+ var optionsButton = back.appendChild(document.createElement('button'));
+ optionsButton.textContent = localStrings.getString('appoptions');
+ optionsButton.disabled = !app['options_url'];
+ optionsButton.onclick = function() {
+ window.location = app['options_url'];
+ };
+
+ var uninstallButton = back.appendChild(document.createElement('button'));
+ uninstallButton.textContent = uninstallButton.xtitle =
+ localStrings.getString('appuninstall');
+ uninstallButton.onclick = function() {
+ chrome.send('uninstallApp', [app['id']]);
+ };
+
+ var closeButton = back.appendChild(document.createElement('button'));
+ closeButton.title = localStrings.getString('close');
+ closeButton.className = 'flip';
+ closeButton.onclick = settingsButton.onclick = function() {
+ div.classList.toggle('config');
+ };
+
+ return div;
+ }
+};