diff options
Diffstat (limited to 'chrome/browser/dom_ui/app_launcher_handler.cc')
-rw-r--r-- | chrome/browser/dom_ui/app_launcher_handler.cc | 236 |
1 files changed, 236 insertions, 0 deletions
diff --git a/chrome/browser/dom_ui/app_launcher_handler.cc b/chrome/browser/dom_ui/app_launcher_handler.cc new file mode 100644 index 0000000..ce6f273 --- /dev/null +++ b/chrome/browser/dom_ui/app_launcher_handler.cc @@ -0,0 +1,236 @@ +// 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/dom_ui/app_launcher_handler.h" + +#include "app/animation.h" +#include "app/l10n_util.h" +#include "app/resource_bundle.h" +#include "base/base64.h" +#include "base/utf_string_conversions.h" +#include "base/values.h" +#include "chrome/browser/app_launched_animation.h" +#include "chrome/browser/browser.h" +#include "chrome/browser/browser_list.h" +#include "chrome/browser/extensions/extensions_service.h" +#include "chrome/browser/platform_util.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/extensions/extension.h" +#include "chrome/common/extensions/extension_resource.h" +#include "chrome/common/notification_service.h" +#include "chrome/common/notification_type.h" +#include "chrome/common/url_constants.h" +#include "gfx/rect.h" +#include "grit/browser_resources.h" +#include "grit/generated_resources.h" + +namespace { + +// This extracts an int from a ListValue at the given |index|. +bool ExtractInt(const ListValue* list, size_t index, int* out_int) { + std::string string_value; + + if (list->GetString(index, &string_value)) { + *out_int = StringToInt(string_value); + return true; + } + + return false; +} + +} // namespace + +AppLauncherHandler::AppLauncherHandler(ExtensionsService* extension_service) + : extensions_service_(extension_service) { +} + +AppLauncherHandler::~AppLauncherHandler() {} + +DOMMessageHandler* AppLauncherHandler::Attach(DOMUI* dom_ui) { + // TODO(arv): Add initialization code to the Apps store etc. + return DOMMessageHandler::Attach(dom_ui); +} + +void AppLauncherHandler::RegisterMessages() { + dom_ui_->RegisterMessageCallback("getApps", + 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, + const NotificationSource& source, + const NotificationDetails& details) { + switch (type.value) { + case NotificationType::EXTENSION_LOADED: + case NotificationType::EXTENSION_UNLOADED: + if (dom_ui_->tab_contents()) + HandleGetApps(NULL); + break; + + default: + NOTREACHED(); + } +} + +// static +void AppLauncherHandler::CreateAppInfo(Extension* extension, + DictionaryValue* value) { + value->Clear(); + value->SetString(L"id", extension->id()); + 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(); + +#if defined(OS_POSIX) + std::string path = relative_path.value(); +#elif defined(OS_WIN) + std::string path = WideToUTF8(relative_path.value()); +#endif // OS_WIN + + GURL icon_url = extension->GetResourceURL(path); + value->SetString(L"icon", icon_url.spec()); +} + +void AppLauncherHandler::HandleGetApps(const Value* value) { + bool show_debug_link = CommandLine::ForCurrentProcess()->HasSwitch( + switches::kAppsDebug); + + DictionaryValue dictionary; + dictionary.SetBoolean(L"showDebugLink", show_debug_link); + + ListValue* list = new ListValue(); + const ExtensionList* extensions = extensions_service_->extensions(); + for (ExtensionList::const_iterator it = extensions->begin(); + it != extensions->end(); ++it) { + if ((*it)->is_app()) { + DictionaryValue* app_info = new DictionaryValue(); + CreateAppInfo(*it, app_info); + list->Append(app_info); + } + } + + dictionary.Set(L"apps", list); + dom_ui_->CallJavascriptFunction(L"getAppsCallback", dictionary); + + // First time we get here we set up the observer so that we can tell update + // the apps as they change. + if (registrar_.IsEmpty()) { + registrar_.Add(this, NotificationType::EXTENSION_LOADED, + NotificationService::AllSources()); + registrar_.Add(this, NotificationType::EXTENSION_UNLOADED, + NotificationService::AllSources()); + } +} + +void AppLauncherHandler::HandleLaunchApp(const Value* value) { + if (!value->IsType(Value::TYPE_LIST)) { + NOTREACHED(); + return; + } + + std::string extension_id; + std::string launch_container; + int left = 0; + int top = 0; + int width = 0; + int height = 0; + + const ListValue* list = static_cast<const ListValue*>(value); + if (!list->GetString(0, &extension_id) || + !list->GetString(1, &launch_container) || + !ExtractInt(list, 2, &left) || + !ExtractInt(list, 3, &top) || + !ExtractInt(list, 4, &width) || + !ExtractInt(list, 5, &height)) { + NOTREACHED(); + return; + } + + // The rect we get from the client is relative to the browser client viewport. + // Offset the rect by the tab contents bounds. + gfx::Rect rect(left, top, width, height); + gfx::Rect tab_contents_bounds; + dom_ui_->tab_contents()->GetContainerBounds(&tab_contents_bounds); + rect.Offset(tab_contents_bounds.origin()); + + // Override the default launch container. + Extension* extension = + extensions_service_->GetExtensionById(extension_id, false); + DCHECK(extension); + + Profile* profile = extensions_service_->profile(); + if (launch_container.empty()) { + AnimateAppIcon(extension, rect); + Browser::OpenApplication(profile, extension_id); + return; + } + + Extension::LaunchContainer container = extension->launch_container(); + if (launch_container == "tab") + container = Extension::LAUNCH_TAB; + else if (launch_container == "panel") + container = Extension::LAUNCH_PANEL; + else if (launch_container == "window") + container = Extension::LAUNCH_WINDOW; + else + NOTREACHED() << "Unexpected launch container: " << launch_container << "."; + + // To give a more "launchy" experience when using the NTP launcher, we close + // it automatically. + Browser* browser = BrowserList::GetLastActive(); + TabContents* old_contents = NULL; + if (browser) + old_contents = browser->GetSelectedTabContents(); + + AnimateAppIcon(extension, rect); + Browser::OpenApplication(profile, extension, container); + + if (old_contents && + old_contents->GetURL().GetOrigin() == + GURL(chrome::kChromeUINewTabURL).GetOrigin()) { + browser->CloseTabContents(old_contents); + } +} + +void AppLauncherHandler::AnimateAppIcon(Extension* extension, + const gfx::Rect& rect) { + // We make this check for the case of minimized windows, unit tests, etc. + if (platform_util::IsVisible(dom_ui_->tab_contents()->GetNativeView()) && + Animation::ShouldRenderRichAnimation()) { +#if defined(OS_WIN) + AppLaunchedAnimation::Show(extension, rect); +#else + NOTIMPLEMENTED(); +#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); +} |