Home | History | Annotate | Download | only in extensions
      1 // Copyright (c) 2012 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/chromeos/extensions/default_app_order.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/bind_helpers.h"
      9 #include "base/files/file_path.h"
     10 #include "base/files/file_util.h"
     11 #include "base/json/json_file_value_serializer.h"
     12 #include "base/path_service.h"
     13 #include "base/time/time.h"
     14 #include "chrome/browser/browser_process.h"
     15 #include "chrome/common/extensions/extension_constants.h"
     16 #include "chromeos/chromeos_paths.h"
     17 #include "content/public/browser/browser_thread.h"
     18 #include "extensions/common/constants.h"
     19 
     20 namespace chromeos {
     21 namespace default_app_order {
     22 namespace {
     23 
     24 // The single ExternalLoader instance.
     25 ExternalLoader* loader_instance = NULL;
     26 
     27 // Names used in JSON file.
     28 const char kOemAppsFolderAttr[] = "oem_apps_folder";
     29 const char kLocalizedContentAttr[] = "localized_content";
     30 const char kDefaultAttr[] = "default";
     31 const char kNameAttr[] = "name";
     32 const char kImportDefaultOrderAttr[] = "import_default_order";
     33 
     34 const char* kDefaultAppOrder[] = {
     35     extension_misc::kChromeAppId,
     36     extensions::kWebStoreAppId,
     37     extension_misc::kGoogleSearchAppId,
     38     extension_misc::kYoutubeAppId,
     39     extension_misc::kGmailAppId,
     40     "ejjicmeblgpmajnghnpcppodonldlgfn",  // Calendar
     41     "kjebfhglflhjjjiceimfkgicifkhjlnm",  // Scratchpad
     42     "lneaknkopdijkpnocmklfnjbeapigfbh",  // Google Maps
     43     "apdfllckaahabafndbhieahigkjlhalf",  // Drive
     44     extension_misc::kGoogleDocAppId,
     45     extension_misc::kGoogleSheetsAppId,
     46     extension_misc::kGoogleSlidesAppId,
     47     "dlppkpafhbajpcmmoheippocdidnckmm",  // Google+
     48     "kbpgddbgniojgndnhlkjbkpknjhppkbk",  // Google+ Hangouts
     49     "hhaomjibdihmijegdhdafkllkbggdgoj",  // Files
     50     extension_misc::kGooglePlayMusicAppId,
     51     "mmimngoggfoobjdlefbcabngfnmieonb",  // Play Books
     52     "gdijeikdkaembjbdobgfkoidjkpbmlkd",  // Play Movies & TV
     53     "fobcpibfeplaikcclojfdhfdmbbeofai",  // Games
     54     "joodangkbfjnajiiifokapkpmhfnpleo",  // Calculator
     55     "hfhhnacclhffhdffklopdkcgdhifgngh",  // Camera
     56     "gbchcmhmhahfdphkhkmpfmihenigjmpp",  // Chrome Remote Desktop
     57 };
     58 
     59 // Reads external ordinal json file and returned the parsed value. Returns NULL
     60 // if the file does not exist or could not be parsed properly. Caller takes
     61 // ownership of the returned value.
     62 base::ListValue* ReadExternalOrdinalFile(const base::FilePath& path) {
     63   if (!base::PathExists(path))
     64     return NULL;
     65 
     66   JSONFileValueSerializer serializer(path);
     67   std::string error_msg;
     68   base::Value* value = serializer.Deserialize(NULL, &error_msg);
     69   if (!value) {
     70     LOG(WARNING) << "Unable to deserialize default app ordinals json data:"
     71         << error_msg << ", file=" << path.value();
     72     return NULL;
     73   }
     74 
     75   base::ListValue* ordinal_list_value = NULL;
     76   if (value->GetAsList(&ordinal_list_value))
     77     return ordinal_list_value;
     78 
     79   LOG(WARNING) << "Expect a JSON list in file " << path.value();
     80   return NULL;
     81 }
     82 
     83 std::string GetLocaleSpecificStringImpl(
     84     const base::DictionaryValue* root,
     85     const std::string& locale,
     86     const std::string& dictionary_name,
     87     const std::string& entry_name) {
     88   const base::DictionaryValue* dictionary_content = NULL;
     89   if (!root || !root->GetDictionary(dictionary_name, &dictionary_content))
     90     return std::string();
     91 
     92   const base::DictionaryValue* locale_dictionary = NULL;
     93   if (dictionary_content->GetDictionary(locale, &locale_dictionary)) {
     94     std::string result;
     95     if (locale_dictionary->GetString(entry_name, &result))
     96       return result;
     97   }
     98 
     99   const base::DictionaryValue* default_dictionary = NULL;
    100   if (dictionary_content->GetDictionary(kDefaultAttr, &default_dictionary)) {
    101     std::string result;
    102     if (default_dictionary->GetString(entry_name, &result))
    103       return result;
    104   }
    105 
    106   return std::string();
    107 }
    108 
    109 // Gets built-in default app order.
    110 void GetDefault(std::vector<std::string>* app_ids) {
    111   for (size_t i = 0; i < arraysize(kDefaultAppOrder); ++i)
    112     app_ids->push_back(std::string(kDefaultAppOrder[i]));
    113 }
    114 
    115 }  // namespace
    116 
    117 const size_t kDefaultAppOrderCount = arraysize(kDefaultAppOrder);
    118 
    119 ExternalLoader::ExternalLoader(bool async)
    120     : loaded_(true /* manual_rest */, false /* initially_signaled */) {
    121   DCHECK(!loader_instance);
    122   loader_instance = this;
    123 
    124   if (async) {
    125     content::BrowserThread::PostBlockingPoolTask(FROM_HERE,
    126         base::Bind(&ExternalLoader::Load, base::Unretained(this)));
    127   } else {
    128     Load();
    129   }
    130 }
    131 
    132 ExternalLoader::~ExternalLoader() {
    133   DCHECK(loaded_.IsSignaled());
    134   DCHECK_EQ(loader_instance, this);
    135   loader_instance = NULL;
    136 }
    137 
    138 const std::vector<std::string>& ExternalLoader::GetAppIds() {
    139   if (!loaded_.IsSignaled())
    140     LOG(ERROR) << "GetAppIds() called before loaded.";
    141   return app_ids_;
    142 }
    143 
    144 const std::string& ExternalLoader::GetOemAppsFolderName() {
    145   if (!loaded_.IsSignaled())
    146     LOG(ERROR) << "GetOemAppsFolderName() called before loaded.";
    147   return oem_apps_folder_name_;
    148 }
    149 
    150 void ExternalLoader::Load() {
    151   base::FilePath ordinals_file;
    152   CHECK(PathService::Get(chromeos::FILE_DEFAULT_APP_ORDER, &ordinals_file));
    153 
    154   scoped_ptr<base::ListValue> ordinals_value(
    155       ReadExternalOrdinalFile(ordinals_file));
    156   if (ordinals_value) {
    157     std::string locale = g_browser_process->GetApplicationLocale();
    158     for (size_t i = 0; i < ordinals_value->GetSize(); ++i) {
    159       std::string app_id;
    160       base::DictionaryValue* dict = NULL;
    161       if (ordinals_value->GetString(i, &app_id)) {
    162         app_ids_.push_back(app_id);
    163       } else if (ordinals_value->GetDictionary(i, &dict)) {
    164         bool flag = false;
    165         if (dict->GetBoolean(kOemAppsFolderAttr, &flag) && flag) {
    166           oem_apps_folder_name_ = GetLocaleSpecificStringImpl(
    167               dict, locale, kLocalizedContentAttr, kNameAttr);
    168         } else if (dict->GetBoolean(kImportDefaultOrderAttr, &flag) && flag) {
    169           GetDefault(&app_ids_);
    170         } else {
    171           LOG(ERROR) << "Invalid syntax in default_app_order.json";
    172         }
    173       } else {
    174         LOG(ERROR) << "Invalid entry in default_app_order.json";
    175       }
    176     }
    177   } else {
    178     GetDefault(&app_ids_);
    179   }
    180 
    181   loaded_.Signal();
    182 }
    183 
    184 void Get(std::vector<std::string>* app_ids) {
    185   // |loader_instance| could be NULL for test.
    186   if (!loader_instance) {
    187     GetDefault(app_ids);
    188     return;
    189   }
    190 
    191   *app_ids = loader_instance->GetAppIds();
    192 }
    193 
    194 std::string GetOemAppsFolderName() {
    195   // |loader_instance| could be NULL for test.
    196   if (!loader_instance)
    197     return std::string();
    198   else
    199     return loader_instance->GetOemAppsFolderName();
    200 }
    201 
    202 }  // namespace default_app_order
    203 }  // namespace chromeos
    204