15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/extensions/default_app_order.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_file_value_serializer.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h"
13eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension_constants.h"
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/chromeos_paths.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chromeos {
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace default_app_order {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The single ExternalLoader instance.
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExternalLoader* loader_instance = NULL;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Reads external ordinal json file and returned the parsed value. Returns NULL
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// if the file does not exist or could not be parsed properly. Caller takes
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ownership of the returned value.
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::ListValue* ReadExternalOrdinalFile(const base::FilePath& path) {
307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!base::PathExists(path))
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  JSONFileValueSerializer serializer(path);
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string error_msg;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Value* value = serializer.Deserialize(NULL, &error_msg);
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!value) {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Unable to deserialize default app ordinals json data:"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << error_msg << ", file=" << path.value();
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::ListValue* ordinal_list_value = NULL;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (value->GetAsList(&ordinal_list_value))
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ordinal_list_value;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG(WARNING) << "Expect a JSON list in file " << path.value();
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Gets built-in default app order.
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GetDefault(std::vector<std::string>* app_ids) {
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(app_ids && app_ids->empty());
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* kDefaultAppOrder[] = {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extension_misc::kChromeAppId,
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extension_misc::kWebStoreAppId,
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    extension_misc::kGoogleSearchAppId,
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    extension_misc::kYoutubeAppId,
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    extension_misc::kGmailAppId,
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "ejjicmeblgpmajnghnpcppodonldlgfn",  // Calendar
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "kjebfhglflhjjjiceimfkgicifkhjlnm",  // Scratchpad
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "lneaknkopdijkpnocmklfnjbeapigfbh",  // Google Maps
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "apdfllckaahabafndbhieahigkjlhalf",  // Drive
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    extension_misc::kGoogleDocAppId,
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    extension_misc::kGoogleSheetsAppId,
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    extension_misc::kGoogleSlidesAppId,
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "dlppkpafhbajpcmmoheippocdidnckmm",  // Google+
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "kbpgddbgniojgndnhlkjbkpknjhppkbk",  // Google+ Hangouts
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "hhaomjibdihmijegdhdafkllkbggdgoj",  // Files
70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    extension_misc::kTipsAndTricksAppId,
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    extension_misc::kGooglePlayMusicAppId,
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "mmimngoggfoobjdlefbcabngfnmieonb",  // Play Books
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "fppdphmgcddhjeddoeghpjefkdlccljb",  // Play Movies
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "fobcpibfeplaikcclojfdhfdmbbeofai",  // Games
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "joodangkbfjnajiiifokapkpmhfnpleo",  // Calculator
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "hfhhnacclhffhdffklopdkcgdhifgngh",  // Camera
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "gbchcmhmhahfdphkhkmpfmihenigjmpp",  // Chrome Remote Desktop
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < arraysize(kDefaultAppOrder); ++i)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    app_ids->push_back(std::string(kDefaultAppOrder[i]));
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExternalLoader::ExternalLoader(bool async)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : loaded_(true /* manual_rest */, false /* initially_signaled */) {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!loader_instance);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loader_instance = this;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (async) {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::BrowserThread::PostBlockingPoolTask(FROM_HERE,
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&ExternalLoader::Load, base::Unretained(this)));
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Load();
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExternalLoader::~ExternalLoader() {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(loaded_.IsSignaled());
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(loader_instance, this);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loader_instance = NULL;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const std::vector<std::string>& ExternalLoader::GetAppIds() {
10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!loaded_.IsSignaled())
10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    LOG(ERROR) << "GetAppIds() called before loaded.";
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return app_ids_;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExternalLoader::Load() {
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath ordinals_file;
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK(PathService::Get(chromeos::FILE_DEFAULT_APP_ORDER, &ordinals_file));
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<base::ListValue> ordinals_value(
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ReadExternalOrdinalFile(ordinals_file));
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ordinals_value) {
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < ordinals_value->GetSize(); ++i) {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string app_id;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CHECK(ordinals_value->GetString(i, &app_id));
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      app_ids_.push_back(app_id);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GetDefault(&app_ids_);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loaded_.Signal();
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Get(std::vector<std::string>* app_ids) {
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |loader_instance| could be NULL for test.
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!loader_instance) {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GetDefault(app_ids);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *app_ids = loader_instance->GetAppIds();
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace default_app_order
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace chromeos
142