Home | History | Annotate | Download | only in app_list
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/ui/webui/app_list/start_page_handler.h"
      6 
      7 #include <string>
      8 
      9 #include "base/bind.h"
     10 #include "base/memory/scoped_ptr.h"
     11 #include "base/values.h"
     12 #include "base/version.h"
     13 #include "chrome/browser/omaha_query_params/omaha_query_params.h"
     14 #include "chrome/browser/profiles/profile.h"
     15 #include "chrome/browser/search/hotword_service.h"
     16 #include "chrome/browser/ui/app_list/app_list_controller_delegate.h"
     17 #include "chrome/browser/ui/app_list/app_list_service.h"
     18 #include "chrome/browser/ui/app_list/recommended_apps.h"
     19 #include "chrome/browser/ui/app_list/start_page_service.h"
     20 #include "chrome/browser/ui/host_desktop.h"
     21 #include "chrome/browser/ui/webui/extensions/extension_icon_source.h"
     22 #include "chrome/common/pref_names.h"
     23 #include "content/public/browser/web_ui.h"
     24 #include "extensions/browser/extension_registry.h"
     25 #include "extensions/browser/extension_system.h"
     26 #include "extensions/common/constants.h"
     27 #include "extensions/common/extension.h"
     28 #include "extensions/common/extension_icon_set.h"
     29 #include "ui/app_list/app_list_switches.h"
     30 #include "ui/app_list/speech_ui_model_observer.h"
     31 #include "ui/events/event_constants.h"
     32 
     33 namespace app_list {
     34 
     35 namespace {
     36 
     37 #if defined(OS_CHROMEOS)
     38 const char kOldHotwordExtensionVersionString[] = "0.1.1.5014_0";
     39 #endif
     40 
     41 scoped_ptr<base::DictionaryValue> CreateAppInfo(
     42     const extensions::Extension* app) {
     43   scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
     44   dict->SetString("appId", app->id());
     45   dict->SetString("textTitle", app->short_name());
     46   dict->SetString("title", app->name());
     47 
     48   const bool grayscale = false;
     49   bool icon_exists = true;
     50   GURL icon_url = extensions::ExtensionIconSource::GetIconURL(
     51       app,
     52       extension_misc::EXTENSION_ICON_MEDIUM,
     53       ExtensionIconSet::MATCH_BIGGER,
     54       grayscale,
     55       &icon_exists);
     56   dict->SetString("iconUrl", icon_url.spec());
     57 
     58   return dict.Pass();
     59 }
     60 
     61 }  // namespace
     62 
     63 StartPageHandler::StartPageHandler()
     64     : recommended_apps_(NULL),
     65       extension_registry_observer_(this) {
     66 }
     67 
     68 StartPageHandler::~StartPageHandler() {
     69   if (recommended_apps_)
     70     recommended_apps_->RemoveObserver(this);
     71 }
     72 
     73 void StartPageHandler::RegisterMessages() {
     74   web_ui()->RegisterMessageCallback(
     75       "initialize",
     76       base::Bind(&StartPageHandler::HandleInitialize, base::Unretained(this)));
     77   web_ui()->RegisterMessageCallback(
     78       "launchApp",
     79       base::Bind(&StartPageHandler::HandleLaunchApp, base::Unretained(this)));
     80   web_ui()->RegisterMessageCallback(
     81       "speechResult",
     82       base::Bind(&StartPageHandler::HandleSpeechResult,
     83                  base::Unretained(this)));
     84   web_ui()->RegisterMessageCallback(
     85       "speechSoundLevel",
     86       base::Bind(&StartPageHandler::HandleSpeechSoundLevel,
     87                  base::Unretained(this)));
     88   web_ui()->RegisterMessageCallback(
     89       "setSpeechRecognitionState",
     90       base::Bind(&StartPageHandler::HandleSpeechRecognition,
     91                  base::Unretained(this)));
     92 }
     93 
     94 void StartPageHandler::OnExtensionLoaded(
     95     content::BrowserContext* browser_context,
     96     const extensions::Extension* extension) {
     97 #if defined(OS_CHROMEOS)
     98   DCHECK_EQ(Profile::FromWebUI(web_ui()),
     99             Profile::FromBrowserContext(browser_context));
    100   if (extension->id() == extension_misc::kHotwordExtensionId)
    101     OnHotwordEnabledChanged();
    102 #endif
    103 }
    104 
    105 void StartPageHandler::OnExtensionUnloaded(
    106     content::BrowserContext* browser_context,
    107     const extensions::Extension* extension,
    108     extensions::UnloadedExtensionInfo::Reason reason) {
    109 #if defined(OS_CHROMEOS)
    110   DCHECK_EQ(Profile::FromWebUI(web_ui()),
    111             Profile::FromBrowserContext(browser_context));
    112   if (extension->id() == extension_misc::kHotwordExtensionId)
    113     OnHotwordEnabledChanged();
    114 #endif
    115 }
    116 
    117 void StartPageHandler::OnRecommendedAppsChanged() {
    118   SendRecommendedApps();
    119 }
    120 
    121 void StartPageHandler::SendRecommendedApps() {
    122   const RecommendedApps::Apps& recommends = recommended_apps_->apps();
    123 
    124   base::ListValue recommended_list;
    125   for (size_t i = 0; i < recommends.size(); ++i) {
    126     recommended_list.Append(CreateAppInfo(recommends[i].get()).release());
    127   }
    128 
    129   web_ui()->CallJavascriptFunction("appList.startPage.setRecommendedApps",
    130                                    recommended_list);
    131 }
    132 
    133 #if defined(OS_CHROMEOS)
    134 void StartPageHandler::OnHotwordEnabledChanged() {
    135   // If the hotword extension is new enough, we should use the new
    136   // hotwordPrivate API to provide the feature.
    137   // TODO(mukai): remove this after everything gets stable.
    138   Profile* profile = Profile::FromWebUI(web_ui());
    139 
    140   extensions::ExtensionRegistry* registry =
    141       extensions::ExtensionRegistry::Get(profile);
    142   const extensions::Extension* hotword_extension =
    143       registry->GetExtensionById(extension_misc::kHotwordExtensionId,
    144                                  extensions::ExtensionRegistry::ENABLED);
    145   if (hotword_extension &&
    146       hotword_extension->version()->CompareTo(
    147           base::Version(kOldHotwordExtensionVersionString)) <= 0) {
    148     StartPageService* service = StartPageService::Get(profile);
    149     web_ui()->CallJavascriptFunction(
    150         "appList.startPage.setHotwordEnabled",
    151         base::FundamentalValue(service->HotwordEnabled()));
    152   }
    153 }
    154 #endif
    155 
    156 void StartPageHandler::HandleInitialize(const base::ListValue* args) {
    157   Profile* profile = Profile::FromWebUI(web_ui());
    158   StartPageService* service = StartPageService::Get(profile);
    159   if (!service)
    160     return;
    161 
    162   recommended_apps_ = service->recommended_apps();
    163   recommended_apps_->AddObserver(this);
    164 
    165   SendRecommendedApps();
    166 
    167 #if defined(OS_CHROMEOS)
    168   if (app_list::switches::IsVoiceSearchEnabled() &&
    169       HotwordService::DoesHotwordSupportLanguage(profile)) {
    170     OnHotwordEnabledChanged();
    171     pref_change_registrar_.Init(profile->GetPrefs());
    172     pref_change_registrar_.Add(
    173         prefs::kHotwordSearchEnabled,
    174         base::Bind(&StartPageHandler::OnHotwordEnabledChanged,
    175                    base::Unretained(this)));
    176 
    177     extension_registry_observer_.Add(
    178         extensions::ExtensionRegistry::Get(profile));
    179   }
    180 #endif
    181 
    182   web_ui()->CallJavascriptFunction(
    183       "appList.startPage.setNaclArch",
    184       base::StringValue(chrome::OmahaQueryParams::GetNaclArch()));
    185 
    186   if (!app_list::switches::IsExperimentalAppListEnabled()) {
    187     web_ui()->CallJavascriptFunction(
    188         "appList.startPage.onAppListShown",
    189         base::FundamentalValue(service->HotwordEnabled()));
    190   }
    191 }
    192 
    193 void StartPageHandler::HandleLaunchApp(const base::ListValue* args) {
    194   std::string app_id;
    195   CHECK(args->GetString(0, &app_id));
    196 
    197   Profile* profile = Profile::FromWebUI(web_ui());
    198   const extensions::Extension* app =
    199       extensions::ExtensionRegistry::Get(profile)
    200           ->GetExtensionById(app_id, extensions::ExtensionRegistry::EVERYTHING);
    201   if (!app) {
    202     NOTREACHED();
    203     return;
    204   }
    205 
    206   AppListControllerDelegate* controller = AppListService::Get(
    207       chrome::GetHostDesktopTypeForNativeView(
    208           web_ui()->GetWebContents()->GetNativeView()))->
    209               GetControllerDelegate();
    210   controller->ActivateApp(profile,
    211                           app,
    212                           AppListControllerDelegate::LAUNCH_FROM_APP_LIST,
    213                           ui::EF_NONE);
    214 }
    215 
    216 void StartPageHandler::HandleSpeechResult(const base::ListValue* args) {
    217   base::string16 query;
    218   bool is_final = false;
    219   CHECK(args->GetString(0, &query));
    220   CHECK(args->GetBoolean(1, &is_final));
    221 
    222   StartPageService::Get(Profile::FromWebUI(web_ui()))->OnSpeechResult(
    223       query, is_final);
    224 }
    225 
    226 void StartPageHandler::HandleSpeechSoundLevel(const base::ListValue* args) {
    227   double level;
    228   CHECK(args->GetDouble(0, &level));
    229 
    230   StartPageService* service =
    231       StartPageService::Get(Profile::FromWebUI(web_ui()));
    232   if (service)
    233     service->OnSpeechSoundLevelChanged(static_cast<int16>(level));
    234 }
    235 
    236 void StartPageHandler::HandleSpeechRecognition(const base::ListValue* args) {
    237   std::string state_string;
    238   CHECK(args->GetString(0, &state_string));
    239 
    240   SpeechRecognitionState new_state = SPEECH_RECOGNITION_OFF;
    241   if (state_string == "READY")
    242     new_state = SPEECH_RECOGNITION_READY;
    243   else if (state_string == "HOTWORD_RECOGNIZING")
    244     new_state = SPEECH_RECOGNITION_HOTWORD_LISTENING;
    245   else if (state_string == "RECOGNIZING")
    246     new_state = SPEECH_RECOGNITION_RECOGNIZING;
    247   else if (state_string == "IN_SPEECH")
    248     new_state = SPEECH_RECOGNITION_IN_SPEECH;
    249   else if (state_string == "STOPPING")
    250     new_state = SPEECH_RECOGNITION_STOPPING;
    251   else if (state_string == "NETWORK_ERROR")
    252     new_state = SPEECH_RECOGNITION_NETWORK_ERROR;
    253 
    254   StartPageService* service =
    255       StartPageService::Get(Profile::FromWebUI(web_ui()));
    256   if (service)
    257     service->OnSpeechRecognitionStateChanged(new_state);
    258 }
    259 
    260 }  // namespace app_list
    261