diff options
-rw-r--r-- | chrome/app/generated_resources.grd | 13 | ||||
-rw-r--r-- | chrome/browser/dom_ui/app_launcher_handler.cc | 34 | ||||
-rw-r--r-- | chrome/browser/dom_ui/app_launcher_handler.h | 7 | ||||
-rw-r--r-- | chrome/browser/dom_ui/ntp_resource_cache.cc | 11 | ||||
-rw-r--r-- | chrome/browser/resources/new_new_tab.css | 50 | ||||
-rw-r--r-- | chrome/browser/resources/new_new_tab.html | 5 | ||||
-rw-r--r-- | chrome/browser/resources/new_new_tab.js | 87 | ||||
-rw-r--r-- | chrome/browser/resources/new_tab_theme.css | 3 | ||||
-rw-r--r-- | chrome/browser/resources/ntp/apps.css | 154 | ||||
-rw-r--r-- | chrome/browser/resources/ntp/apps.js | 116 |
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; + } +}; |