Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(703)

Unified Diff: chrome/browser/ui/app_list/arc_app_prefs.cc

Issue 1413153007: arc-app-launcher: Minimal support for ARC app launcher. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/app_list/arc_app_prefs.cc
diff --git a/chrome/browser/ui/app_list/arc_app_prefs.cc b/chrome/browser/ui/app_list/arc_app_prefs.cc
new file mode 100644
index 0000000000000000000000000000000000000000..c1624cc7d69169ad905538381264ed9712aa1a2c
--- /dev/null
+++ b/chrome/browser/ui/app_list/arc_app_prefs.cc
@@ -0,0 +1,299 @@
+// Copyright 2015 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/ui/app_list/arc_app_prefs.h"
+
+#include "base/files/file_util.h"
+#include "base/prefs/scoped_user_pref_update.h"
+#include "base/task_runner_util.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/app_list/arc_app_prefs_factory.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "components/crx_file/id_util.h"
+#include "components/pref_registry/pref_registry_syncable.h"
+#include "content/public/browser/browser_thread.h"
+
+namespace {
+
+const char kArcApps[] = "arcapps";
+const char kName[] = "name";
+const char kPackage[] = "package";
+const char kActivity[] = "activity";
+const char kIcons[] = "icons";
+
+// Provider of write access to a dictionary storing arc app prefs.
+class ScopedArcAppPrefUpdate : public DictionaryPrefUpdate {
+ public:
+ ScopedArcAppPrefUpdate(PrefService* service, const std::string& id)
+ : DictionaryPrefUpdate(service, kArcApps),
+ id_(id) {}
+
+ ~ScopedArcAppPrefUpdate() override {}
+
+ // DictionaryPrefUpdate overrides:
+ base::DictionaryValue* Get() override {
+ base::DictionaryValue* dict = DictionaryPrefUpdate::Get();
+ base::DictionaryValue* app = NULL;
+ if (!dict->GetDictionary(id_, &app)) {
+ app = new base::DictionaryValue();
+ dict->SetWithoutPathExpansion(id_, app);
+ }
+ return app;
+ }
+
+ private:
+ const std::string id_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedArcAppPrefUpdate);
+};
+
+base::FilePath GetIconPath(const base::FilePath& base_path,
+ ui::ScaleFactor scale_factor) {
+ switch (scale_factor) {
elijahtaylor1 2015/10/28 06:32:39 it's not clear what all of these icon sizes are fo
khmel1 2015/10/29 08:12:18 Required icon is determined by scale factor of Dis
+ case ui::SCALE_FACTOR_100P:
+ return base_path.AppendASCII("icon_100p.png");
+ case ui::SCALE_FACTOR_125P:
+ return base_path.AppendASCII("icon_125p.png");
+ case ui::SCALE_FACTOR_133P:
+ return base_path.AppendASCII("icon_133p.png");
+ case ui::SCALE_FACTOR_140P:
+ return base_path.AppendASCII("icon_140p.png");
+ case ui::SCALE_FACTOR_150P:
+ return base_path.AppendASCII("icon_150p.png");
+ case ui::SCALE_FACTOR_180P:
+ return base_path.AppendASCII("icon_180p.png");
+ case ui::SCALE_FACTOR_200P:
+ return base_path.AppendASCII("icon_200p.png");
+ case ui::SCALE_FACTOR_250P:
+ return base_path.AppendASCII("icon_250p.png");
+ case ui::SCALE_FACTOR_300P:
+ return base_path.AppendASCII("icon_300p.png");
+ default:
+ CHECK(false);
+ return base::FilePath();
+ }
+}
+
+} // namespace
+
+// static
+ArcAppPrefs* ArcAppPrefs::Create(content::BrowserContext* browser_context,
+ const base::FilePath& base_path,
+ PrefService* prefs) {
+ return new ArcAppPrefs(browser_context, base_path, prefs);
+}
+
+// static
+void ArcAppPrefs::RegisterProfilePrefs(
+ user_prefs::PrefRegistrySyncable* registry) {
+ registry->RegisterDictionaryPref(
+ kArcApps,
+ user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
+}
+
+// static
+ArcAppPrefs* ArcAppPrefs::Get(content::BrowserContext* context) {
+ return ArcAppPrefsFactory::GetInstance()->GetForBrowserContext(context);
+}
+
+// static
+std::string ArcAppPrefs::GetAppId(const std::string& package,
+ const std::string& activity) {
+ std::string input = package + "#" + activity;
+ return crx_file::id_util::GenerateId(input);
elijahtaylor1 2015/10/28 06:32:39 does this need to be a CRX style ID? It would be
khmel1 2015/10/29 08:12:18 My first impl was the same as you suggested. Howev
+}
+
+ArcAppPrefs::ArcAppPrefs(content::BrowserContext* browser_context,
+ const base::FilePath& base_path,
+ PrefService* prefs)
+ : browser_context_(browser_context),
+ prefs_(prefs) {
elijahtaylor1 2015/10/28 06:32:39 alignment
khmel1 2015/10/29 08:12:18 Done.
+ base_path_ = base_path.AppendASCII(kArcApps);
+
+ chromeos::DBusThreadManager::Get()->GetArcBridgeClient()->
+ AddAppObserver(this);
+ chromeos::DBusThreadManager::Get()->GetArcBridgeClient()->Refresh();
+}
+
+ArcAppPrefs::~ArcAppPrefs() {
+ chromeos::DBusThreadManager::Get()->GetArcBridgeClient()->
+ RemoveAppObserver(this);
+}
+
+void ArcAppPrefs::AddObserver(Observer* observer) {
+ observer_list_.AddObserver(observer);
+}
+
+void ArcAppPrefs::RemoveObserver(Observer* observer) {
+ observer_list_.RemoveObserver(observer);
+}
+
+std::vector<std::string> ArcAppPrefs::GetAppIds() const {
+ std::vector<std::string> ids;
+
+ const base::DictionaryValue* apps = prefs_->GetDictionary(kArcApps);
+ for (base::DictionaryValue::Iterator app_id(*apps);
+ !app_id.IsAtEnd(); app_id.Advance()) {
+ if (!crx_file::id_util::IdIsValid(app_id.key()))
+ continue;
+ ids.push_back(app_id.key());
+ }
+
+ return ids;
+}
+
+scoped_ptr<ArcAppPrefs::AppInfo> ArcAppPrefs::GetApp(
+ const std::string& app_id) const {
+ const base::DictionaryValue* app = NULL;
+ const base::DictionaryValue* apps = prefs_->GetDictionary(kArcApps);
+ if (!apps ||
+ !apps->GetDictionaryWithoutPathExpansion(app_id, &app))
+ return scoped_ptr<AppInfo>();
+
+ scoped_ptr<AppInfo> app_info(new AppInfo);
+ app->GetString(kName, &app_info->name);
+ app->GetString(kPackage, &app_info->package);
+ app->GetString(kActivity, &app_info->activity);
+ app_info->enabled = enable_apps_.count(app_id) > 0;
+
+ base::FilePath app_path = base_path_.AppendASCII(app_id);
+
+ int icon_flags = 0;
+ if (app->GetInteger(kIcons, &icon_flags)) {
+ for (int i = ui::SCALE_FACTOR_100P; i < ui::NUM_SCALE_FACTORS; ++i) {
+ if (icon_flags & (1 << i)) {
+ IconInfo icon_info;
+ icon_info.scale_factor = static_cast<ui::ScaleFactor>(i);
+ icon_info.path = GetIconPath(app_path, icon_info.scale_factor);
+ app_info->icons.push_back(icon_info);
+ }
+ }
+ }
+
+ return app_info.Pass();
+}
+
+bool ArcAppPrefs::IsRegistered(const std::string& app_id) {
+ const base::DictionaryValue* app = NULL;
+ const base::DictionaryValue* apps = prefs_->GetDictionary(kArcApps);
+ if (!apps || !apps->GetDictionary(app_id, &app)) {
+ return false;
+ }
+ return true;
+}
+
+void ArcAppPrefs::OnAppReady(const chromeos::ArcBridgeClient::AppInfo& app) {
+ std::string app_id = GetAppId(app.package, app.activity);
+ bool was_registered = IsRegistered(app_id);
+
+ ScopedArcAppPrefUpdate update(prefs_, app_id);
+ base::DictionaryValue* app_dict = update.Get();
+ app_dict->SetString(kName, app.name);
+ app_dict->SetString(kPackage, app.package);
+ app_dict->SetString(kActivity, app.activity);
+
+ // From now, app is ready.
+ if (!enable_apps_.count(app_id)) {
+ enable_apps_.insert(app_id);
+ }
+
+ AppInfo app_info;
+ app_info.name = app.name;
+ app_info.enabled = true;
+
+ if (was_registered) {
+ FOR_EACH_OBSERVER(Observer,
+ observer_list_,
+ OnAppEnabled(app_id, true));
+ } else {
+ FOR_EACH_OBSERVER(Observer,
+ observer_list_,
+ OnAppRegistered(app_id, app_info));
+ }
+
+ if (!app.icon.empty()) {
+ // Currently only default 100p icon is supported.
+ InstallIcon(app_id, ui::SCALE_FACTOR_100P, app.icon);
+ }
+}
+
+void ArcAppPrefs::OnAppsRefreshed(
+ const std::vector<chromeos::ArcBridgeClient::AppInfo>& apps) {
+ std::set<std::string> old_enable_apps_;
+ old_enable_apps_.swap(enable_apps_);
+
+ for (size_t i = 0; i < apps.size(); ++i) {
+ OnAppReady(apps[i]);
+ }
+
+ // Detect unavailable apps after current refresh.
+ std::set<std::string>::const_iterator it;
+ for (it = old_enable_apps_.begin(); it != old_enable_apps_.end(); ++it) {
+ const std::string app_id = *it;
+ if (!enable_apps_.count(app_id)) {
+ FOR_EACH_OBSERVER(Observer,
+ observer_list_,
+ OnAppEnabled(app_id, false));
+ }
+ }
+}
+
+void ArcAppPrefs::InstallIcon(const std::string& app_id,
+ ui::ScaleFactor scale_factor,
+ const std::vector<uint8>& contentPng) {
+ base::Closure task = base::Bind(&ArcAppPrefs::InstallIconFromFileThread,
+ base::Unretained(this),
+ app_id,
+ scale_factor,
+ contentPng);
+ content::BrowserThread::PostTask(content::BrowserThread::FILE,
+ FROM_HERE,
+ task);
+}
+
+void ArcAppPrefs::InstallIconFromFileThread(
+ const std::string& app_id,
+ ui::ScaleFactor scale_factor,
+ const std::vector<uint8>& contentPng) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
+
+ DCHECK(!contentPng.empty());
+
+ IconInfo icon_info;
+
+ base::FilePath app_path = base_path_.AppendASCII(app_id);
+ base::CreateDirectory(app_path);
+ icon_info.scale_factor = scale_factor;
+ icon_info.path = GetIconPath(app_path, scale_factor);
+
+ int wrote = base::WriteFile(icon_info.path,
+ reinterpret_cast<const char*>(&contentPng[0]),
+ contentPng.size());
+ DCHECK(wrote == static_cast<int>(contentPng.size()));
+
+ base::Closure task = base::Bind(&ArcAppPrefs::OnIconInstalled,
+ base::Unretained(this),
+ app_id,
+ icon_info);
+ content::BrowserThread::PostTask(content::BrowserThread::UI,
+ FROM_HERE,
+ task);
+}
+
+void ArcAppPrefs::OnIconInstalled(const std::string& app_id,
+ const IconInfo& icon_info) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+ FOR_EACH_OBSERVER(Observer,
+ observer_list_,
+ OnAppIconUpdated(app_id, icon_info));
+
+ // Set flag that icon is available for specific scale factor.
+ ScopedArcAppPrefUpdate update(prefs_, app_id);
+ base::DictionaryValue* app_dict = update.Get();
+ int icon_flags = 0;
+ app_dict->GetInteger(kIcons, &icon_flags);
+ icon_flags |= (1 << icon_info.scale_factor);
+ app_dict->SetInteger(kIcons, icon_flags);
+}

Powered by Google App Engine
This is Rietveld 408576698