Index: chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc |
diff --git a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc |
index 791b24f96419f712762339330f2e8525e36dc091..c3ff3cc4770dc62490be154fe357638aa919a5da 100644 |
--- a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc |
+++ b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc |
@@ -9,15 +9,19 @@ |
#include <string> |
#include <unordered_map> |
+#include "base/files/file_enumerator.h" |
#include "base/files/file_util.h" |
+#include "base/json/json_file_value_serializer.h" |
#include "base/macros.h" |
#include "base/metrics/histogram_macros.h" |
+#include "base/path_service.h" |
#include "base/strings/string_number_conversions.h" |
#include "base/task_runner_util.h" |
#include "chrome/browser/profiles/profile.h" |
#include "chrome/browser/ui/app_list/arc/arc_app_list_prefs_factory.h" |
#include "chrome/browser/ui/app_list/arc/arc_app_utils.h" |
#include "chrome/browser/ui/app_list/arc/arc_package_syncable_service.h" |
+#include "chrome/common/chrome_paths.h" |
#include "chrome/common/pref_names.h" |
#include "components/arc/arc_bridge_service.h" |
#include "components/crx_file/id_util.h" |
@@ -27,26 +31,35 @@ |
namespace { |
-const char kName[] = "name"; |
-const char kPackageName[] = "package_name"; |
-const char kPackageVersion[] = "package_version"; |
const char kActivity[] = "activity"; |
-const char kShortcut[] = "shortcut"; |
-const char kIntentUri[] = "intent_uri"; |
+const char kAppPath[] = "app_path"; |
const char kIconResourceId[] = "icon_resource_id"; |
-const char kSticky[] = "sticky"; |
-const char kNotificationsEnabled[] = "notifications_enabled"; |
+const char kInstallTime[] = "install_time"; |
+const char kIntentUri[] = "intent_uri"; |
const char kLastBackupAndroidId[] = "last_backup_android_id"; |
const char kLastBackupTime[] = "last_backup_time"; |
const char kLastLaunchTime[] = "lastlaunchtime"; |
const char kLaunchable[] = "launchable"; |
+const char kName[] = "name"; |
+const char kNotificationsEnabled[] = "notifications_enabled"; |
+const char kOem[] = "oem"; |
+const char kOrientationLock[] = "orientation_lock"; |
+const char kPackageName[] = "package_name"; |
+const char kPackageVersion[] = "package_version"; |
+const char kSticky[] = "sticky"; |
+const char kShortcut[] = "shortcut"; |
const char kShouldSync[] = "should_sync"; |
const char kSystem[] = "system"; |
-const char kOrientationLock[] = "orientation_lock"; |
-const char kInstallTime[] = "install_time"; |
+const char kUninstalled[] = "uninstalled"; |
constexpr int kSetNotificationsEnabledMinVersion = 6; |
+// Sub-directory wher Arc apps forward declarations are stored. |
+const base::FilePath::CharType kArcDefaultDirectory[] = |
+ FILE_PATH_LITERAL("arc"); |
+const base::FilePath::CharType kArcTestDefaultDirectory[] = |
+ FILE_PATH_LITERAL("arc_default_apps"); |
+ |
// Provider of write access to a dictionary storing ARC prefs. |
class ScopedArcPrefUpdate : public DictionaryPrefUpdate { |
public: |
@@ -163,38 +176,7 @@ bool GetInt64FromPref(const base::DictionaryValue* dict, |
return true; |
} |
-// Add or update local pref for given package. |
-void AddOrUpdatePackagePrefs(PrefService* prefs, |
- const arc::mojom::ArcPackageInfo& package) { |
- DCHECK(IsArcEnabled()); |
- const std::string& package_name = package.package_name; |
- if (package_name.empty()) { |
- VLOG(2) << "Package name cannot be empty."; |
- return; |
- } |
- ScopedArcPrefUpdate update(prefs, package_name, prefs::kArcPackages); |
- base::DictionaryValue* package_dict = update.Get(); |
- const std::string id_str = |
- base::Int64ToString(package.last_backup_android_id); |
- const std::string time_str = base::Int64ToString(package.last_backup_time); |
- |
- package_dict->SetBoolean(kShouldSync, package.sync); |
- package_dict->SetInteger(kPackageVersion, package.package_version); |
- package_dict->SetString(kLastBackupAndroidId, id_str); |
- package_dict->SetString(kLastBackupTime, time_str); |
- package_dict->SetBoolean(kSystem, package.system); |
-} |
- |
-// Remove given package from local pref. |
-void RemovePackageFromPrefs(PrefService* prefs, |
- const std::string& package_name) { |
- DCHECK(IsArcEnabled()); |
- DictionaryPrefUpdate update(prefs, prefs::kArcPackages); |
- base::DictionaryValue* packages = update.Get(); |
- const bool removed = packages->RemoveWithoutPathExpansion(package_name, |
- nullptr); |
- DCHECK(removed); |
-} |
+bool use_test_default_apps_directory = false; |
} // namespace |
@@ -214,6 +196,11 @@ void ArcAppListPrefs::RegisterProfilePrefs( |
} |
// static |
+void ArcAppListPrefs::UseTestDefaultAppsDirectory() { |
+ use_test_default_apps_directory = true; |
+} |
+ |
+// static |
ArcAppListPrefs* ArcAppListPrefs::Get(content::BrowserContext* context) { |
return ArcAppListPrefsFactory::GetInstance()->GetForBrowserContext(context); |
} |
@@ -225,6 +212,91 @@ std::string ArcAppListPrefs::GetAppId(const std::string& package_name, |
return crx_file::id_util::GenerateId(input); |
} |
+// static |
+std::unique_ptr<ArcAppListPrefs::DefaultAppInfoMap> |
+ArcAppListPrefs::ReadDefaultAppsFromFileThread() { |
+ DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); |
+ |
+ std::unique_ptr<DefaultAppInfoMap> apps(new DefaultAppInfoMap); |
+ |
+ base::FilePath base_path; |
+ if (!use_test_default_apps_directory) { |
+ if (!base::PathService::Get(chrome::DIR_DEFAULT_APPS, &base_path)) |
+ return apps; |
+ base_path = base_path.Append(kArcDefaultDirectory); |
xiyuan
2016/08/26 19:32:29
chrome::DIR_DEFAULT_APPS is not used on ChromeOS.
khmel
2016/08/26 23:26:18
Yes, I also had doubts that this would be bad choi
|
+ } else { |
+ if (!base::PathService::Get(chrome::DIR_TEST_DATA, &base_path)) |
+ return apps; |
+ base_path = base_path.AppendASCII(kArcTestDefaultDirectory); |
+ } |
+ |
+ base::FilePath::StringType extension(".json"); |
+ base::FileEnumerator json_files( |
+ base_path, |
+ false, // Recursive. |
+ base::FileEnumerator::FILES); |
+ |
+ do { |
+ base::FilePath file = json_files.Next(); |
+ if (file.empty()) |
+ break; |
+ if (file.MatchesExtension(extension)) { |
+ JSONFileValueDeserializer deserializer(file); |
+ std::string error_msg; |
+ std::unique_ptr<base::Value> app_info = |
+ deserializer.Deserialize(nullptr, &error_msg); |
+ if (!app_info) { |
+ VLOG(2) << "Unable to deserialize json data: " << error_msg |
+ << " in file " << file.value() << "."; |
+ continue; |
+ } |
+ |
+ std::unique_ptr<base::DictionaryValue> app_info_dictionary = |
+ base::DictionaryValue::From(std::move(app_info)); |
+ CHECK(app_info_dictionary); |
+ |
+ std::string name; |
+ std::string package_name; |
+ std::string activity; |
+ std::string app_path; |
+ bool oem = false; |
+ |
+ app_info_dictionary->GetString(kName, &name); |
+ app_info_dictionary->GetString(kPackageName, &package_name); |
+ app_info_dictionary->GetString(kActivity, &activity); |
+ app_info_dictionary->GetString(kAppPath, &app_path); |
+ app_info_dictionary->GetBoolean(kOem, &oem); |
+ |
+ if (name.empty() || |
+ package_name.empty() || |
+ activity.empty() || |
+ app_path.empty()) { |
+ VLOG(2) << "Arc app declaration is incomplete in file " |
+ << file.value() << "."; |
+ continue; |
+ } |
+ |
+ const std::string app_id = ArcAppListPrefs::GetAppId( |
+ package_name, activity); |
+ std::unique_ptr<ArcAppListPrefs::DefaultAppInfo> app( |
+ new ArcAppListPrefs::DefaultAppInfo(name, |
+ package_name, |
+ activity, |
+ oem, |
+ base_path.Append(app_path))); |
+ apps.get()->insert( |
+ std::pair<std::string, |
+ std::unique_ptr<ArcAppListPrefs::DefaultAppInfo>>( |
+ app_id, std::move(app))); |
+ } else { |
+ DVLOG(1) << "Not considering: " << file.LossyDisplayName() |
+ << " (does not have a .json extension)"; |
+ } |
+ } while (true); |
+ |
+ return apps; |
+} |
+ |
ArcAppListPrefs::ArcAppListPrefs( |
Profile* profile, |
arc::InstanceHolder<arc::mojom::AppInstance>* app_instance_holder) |
@@ -236,6 +308,7 @@ ArcAppListPrefs::ArcAppListPrefs( |
weak_ptr_factory_(this) { |
DCHECK(profile); |
DCHECK(app_instance_holder); |
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
const base::FilePath& base_path = profile->GetPath(); |
base_path_ = base_path.AppendASCII(prefs::kArcApps); |
@@ -243,13 +316,14 @@ ArcAppListPrefs::ArcAppListPrefs( |
if (!auth_service) |
return; |
- if (auth_service->state() != arc::ArcAuthService::State::NOT_INITIALIZED) |
- OnOptInEnabled(auth_service->IsArcEnabled()); |
- auth_service->AddObserver(this); |
+ DCHECK(arc::ArcAuthService::IsAllowedForProfile(profile)); |
- app_instance_holder_->AddObserver(this); |
- if (!app_instance_holder_->instance()) |
- OnInstanceClosed(); |
+ // Once ready OnDefaultAppsReady is called. |
+ base::PostTaskAndReplyWithResult( |
+ content::BrowserThread::GetBlockingPool(), FROM_HERE, |
+ base::Bind(&ArcAppListPrefs::ReadDefaultAppsFromFileThread), |
+ base::Bind(&ArcAppListPrefs::OnDefaultAppsReady, |
+ weak_ptr_factory_.GetWeakPtr())); |
} |
ArcAppListPrefs::~ArcAppListPrefs() { |
@@ -265,7 +339,29 @@ ArcAppListPrefs::~ArcAppListPrefs() { |
auth_service->RemoveObserver(this); |
} |
+void ArcAppListPrefs::StartPrefs() { |
+ arc::ArcAuthService* auth_service = arc::ArcAuthService::Get(); |
+ CHECK(auth_service); |
+ |
+ if (auth_service->state() != arc::ArcAuthService::State::NOT_INITIALIZED) |
+ OnOptInEnabled(auth_service->IsArcEnabled()); |
+ auth_service->AddObserver(this); |
+ |
+ app_instance_holder_->AddObserver(this); |
+ if (!app_instance_holder_->instance()) |
+ OnInstanceClosed(); |
+} |
+ |
base::FilePath ArcAppListPrefs::GetAppPath(const std::string& app_id) const { |
+ const DefaultAppInfo* default_app = GetDefaultApp(app_id); |
+ if (default_app) { |
+ const base::DictionaryValue* app = nullptr; |
+ const base::DictionaryValue* apps = prefs_->GetDictionary(prefs::kArcApps); |
+ // If app is not ready yet, use resources from pre-build. |
+ if (!apps || !apps->GetDictionaryWithoutPathExpansion(app_id, &app)) |
+ return default_app->app_path; |
+ } |
+ |
return base_path_.AppendASCII(app_id); |
} |
@@ -419,16 +515,36 @@ std::unique_ptr<ArcAppListPrefs::PackageInfo> ArcAppListPrefs::GetPackage( |
} |
std::vector<std::string> ArcAppListPrefs::GetAppIds() const { |
- if (!IsArcEnabled()) |
- return std::vector<std::string>(); |
+ if (!IsArcEnabled()) { |
+ // Default Arc apps available before OptIn. |
+ std::vector<std::string> ids; |
+ for (const auto& default_app : default_apps_) { |
+ if (HasDefaultApp(default_app.first)) |
+ ids.push_back(default_app.first); |
+ } |
+ return ids; |
+ } |
return GetAppIdsNoArcEnabledCheck(); |
} |
std::vector<std::string> ArcAppListPrefs::GetAppIdsNoArcEnabledCheck() const { |
std::vector<std::string> ids; |
- // crx_file::id_util is de-facto utility for id generation. |
const base::DictionaryValue* apps = prefs_->GetDictionary(prefs::kArcApps); |
+ CHECK(apps); |
+ |
+ // Include default app ids into the list. In order not to list app twice, |
+ // at first step include default apps that do not exist yet. |
+ for (const auto& default_app : default_apps_) { |
+ const std::string& app_id = default_app.first; |
+ const base::DictionaryValue* app = nullptr; |
+ if (HasDefaultApp(default_app.first) && |
+ !apps->GetDictionaryWithoutPathExpansion(app_id, &app)) { |
+ ids.push_back(app_id); |
+ } |
+ } |
+ |
+ // crx_file::id_util is de-facto utility for id generation. |
for (base::DictionaryValue::Iterator app_id(*apps); !app_id.IsAtEnd(); |
app_id.Advance()) { |
if (!crx_file::id_util::IdIsValid(app_id.key())) |
@@ -442,13 +558,27 @@ std::vector<std::string> ArcAppListPrefs::GetAppIdsNoArcEnabledCheck() const { |
std::unique_ptr<ArcAppListPrefs::AppInfo> ArcAppListPrefs::GetApp( |
const std::string& app_id) const { |
- if (!IsArcEnabled()) |
+ // Information for default app is available before Arc enabled. |
+ const DefaultAppInfo* default_app = GetDefaultApp(app_id); |
+ if (!IsArcEnabled() && !default_app) |
return std::unique_ptr<AppInfo>(); |
const base::DictionaryValue* app = nullptr; |
const base::DictionaryValue* apps = prefs_->GetDictionary(prefs::kArcApps); |
- if (!apps || !apps->GetDictionaryWithoutPathExpansion(app_id, &app)) |
+ if (!apps || !apps->GetDictionaryWithoutPathExpansion(app_id, &app)) { |
+ // Default app may not be available at this point so create app info based |
+ // on its forward declaration. |
+ if (default_app) { |
+ return base::MakeUnique<AppInfo>( |
+ default_app->name, default_app->package_name, default_app->activity, |
+ std::string() /* intent_uri */, std::string() /* icon_resource_id */, |
+ base::Time() /* last_launch_time */, base::Time() /* install_time */, |
+ false /* sticky */, false /* notifications_enabled */, |
+ false /* ready */, true /* showInLauncher */, false /* shortcut */, |
+ true /* launchable */, arc::mojom::OrientationLock::NONE); |
+ } |
return std::unique_ptr<AppInfo>(); |
+ } |
std::string name; |
std::string package_name; |
@@ -497,6 +627,9 @@ std::unique_ptr<ArcAppListPrefs::AppInfo> ArcAppListPrefs::GetApp( |
} |
bool ArcAppListPrefs::IsRegistered(const std::string& app_id) const { |
+ if (HasDefaultApp(app_id)) |
+ return true; |
+ |
if (!IsArcEnabled()) |
return false; |
@@ -505,6 +638,11 @@ bool ArcAppListPrefs::IsRegistered(const std::string& app_id) const { |
return apps && apps->GetDictionaryWithoutPathExpansion(app_id, &app); |
} |
+bool ArcAppListPrefs::IsOem(const std::string& app_id) const { |
+ const DefaultAppInfo* app_info = GetDefaultApp(app_id); |
+ return app_info && app_info->oem; |
+} |
+ |
bool ArcAppListPrefs::IsShortcut(const std::string& app_id) const { |
std::unique_ptr<ArcAppListPrefs::AppInfo> app_info = GetApp(app_id); |
return app_info && app_info->shortcut; |
@@ -548,6 +686,9 @@ void ArcAppListPrefs::NotifyRegisteredApps() { |
NOTREACHED(); |
continue; |
} |
+ // Default apps are reported earlier. |
+ if (HasDefaultApp(app_id)) |
+ continue; |
FOR_EACH_OBSERVER(Observer, observer_list_, |
OnAppRegistered(app_id, *app_info)); |
} |
@@ -557,8 +698,10 @@ void ArcAppListPrefs::NotifyRegisteredApps() { |
void ArcAppListPrefs::RemoveAllApps() { |
std::vector<std::string> app_ids = GetAppIdsNoArcEnabledCheck(); |
- for (const auto& app_id : app_ids) |
- RemoveApp(app_id); |
+ for (const auto& app_id : app_ids) { |
+ if (!HasDefaultApp(app_id)) |
+ RemoveApp(app_id); |
+ } |
} |
void ArcAppListPrefs::OnOptInEnabled(bool enabled) { |
@@ -568,6 +711,64 @@ void ArcAppListPrefs::OnOptInEnabled(bool enabled) { |
RemoveAllApps(); |
} |
+void ArcAppListPrefs::OnDefaultAppsReady( |
+ std::unique_ptr<DefaultAppInfoMap> apps) { |
+ |
+ default_apps_.swap(*apps.get()); |
+ |
+ // Initially consider packages are installed. |
+ for (const auto& default_app : default_apps_) |
+ default_packages_[default_app.second->package_name] = false; |
+ |
+ // Apply uninstalled packages now. |
+ const std::vector<std::string> uninstalled_package_names = |
+ GetPackagesFromPrefs(false); |
+ for (const auto& uninstalled_package_name : uninstalled_package_names) |
+ MaybeMarkDefaultPackageUninstalled(uninstalled_package_name, true); |
+ |
+ // Report default apps first. |
+ for (const auto& default_app : default_apps_) { |
+ const std::string& app_id = default_app.first; |
+ std::unique_ptr<AppInfo> app_info = GetApp(app_id); |
+ if (app_info) { |
+ FOR_EACH_OBSERVER(Observer, observer_list_, |
+ OnAppRegistered(app_id, *app_info)); |
+ } |
+ } |
+ |
+ default_apps_read_ = true; |
+ StartPrefs(); |
+} |
+ |
+const ArcAppListPrefs::DefaultAppInfo* ArcAppListPrefs::GetDefaultApp( |
+ const std::string& app_id) const { |
+ const auto it = default_apps_.find(app_id); |
+ if (it == default_apps_.end()) |
+ return nullptr; |
+ // Check if its package was uninstalled. |
+ const auto it_package = default_packages_.find(it->second->package_name); |
+ DCHECK(it_package != default_packages_.end()); |
+ if (it_package->second) |
+ return nullptr; |
+ return it->second.get(); |
+} |
+ |
+bool ArcAppListPrefs::HasDefaultApp(const std::string& app_id) const { |
+ return GetDefaultApp(app_id) != nullptr; |
+} |
+ |
+bool ArcAppListPrefs::HasDefaultPackage(const std::string& package_name) const { |
+ return default_packages_.count(package_name); |
+} |
+ |
+void ArcAppListPrefs::MaybeMarkDefaultPackageUninstalled( |
+ const std::string& package_name, bool uninstalled) { |
+ auto it = default_packages_.find(package_name); |
+ if (it == default_packages_.end()) |
+ return; |
+ it->second = uninstalled; |
+} |
+ |
void ArcAppListPrefs::OnInstanceReady() { |
arc::mojom::AppInstance* app_instance = app_instance_holder_->instance(); |
if (!app_instance) { |
@@ -594,9 +795,9 @@ void ArcAppListPrefs::OnInstanceClosed() { |
} |
} |
-void ArcAppListPrefs::MayAddNonLaunchableApp(const std::string& name, |
- const std::string& package_name, |
- const std::string& activity) { |
+void ArcAppListPrefs::MaybeAddNonLaunchableApp(const std::string& name, |
+ const std::string& package_name, |
+ const std::string& activity) { |
DCHECK(IsArcEnabled()); |
if (IsRegistered(GetAppId(package_name, activity))) |
return; |
@@ -619,8 +820,8 @@ void ArcAppListPrefs::AddAppAndShortcut( |
const bool shortcut, |
const bool launchable, |
const arc::mojom::OrientationLock orientation_lock) { |
- std::string app_id = shortcut ? GetAppId(package_name, intent_uri) |
- : GetAppId(package_name, activity); |
+ const std::string app_id = shortcut ? GetAppId(package_name, intent_uri) |
+ : GetAppId(package_name, activity); |
const bool was_registered = IsRegistered(app_id); |
if (was_registered) { |
std::unique_ptr<ArcAppListPrefs::AppInfo> app_old_info = GetApp(app_id); |
@@ -701,13 +902,16 @@ void ArcAppListPrefs::RemoveApp(const std::string& app_id) { |
// From now, app is not available. |
ready_apps_.erase(app_id); |
+ // app_id may be released by observers, get the path first. It should be done |
+ // before removing prefs entry in order not to mix with pre-build default apps |
+ // files. |
+ const base::FilePath app_path = GetAppPath(app_id); |
+ |
// Remove from prefs. |
DictionaryPrefUpdate update(prefs_, prefs::kArcApps); |
base::DictionaryValue* apps = update.Get(); |
const bool removed = apps->Remove(app_id, nullptr); |
DCHECK(removed); |
- // app_id may be released by observers, get the path first. |
- const base::FilePath app_path = GetAppPath(app_id); |
FOR_EACH_OBSERVER(Observer, observer_list_, OnAppRemoved(app_id)); |
@@ -716,6 +920,45 @@ void ArcAppListPrefs::RemoveApp(const std::string& app_id) { |
FROM_HERE, base::Bind(&DeleteAppFolderFromFileThread, app_path)); |
} |
+void ArcAppListPrefs::AddOrUpdatePackagePrefs( |
+ PrefService* prefs, const arc::mojom::ArcPackageInfo& package) { |
+ DCHECK(IsArcEnabled()); |
+ const std::string& package_name = package.package_name; |
+ MaybeMarkDefaultPackageUninstalled(package_name, false); |
+ if (package_name.empty()) { |
+ VLOG(2) << "Package name cannot be empty."; |
+ return; |
+ } |
+ ScopedArcPrefUpdate update(prefs, package_name, prefs::kArcPackages); |
+ base::DictionaryValue* package_dict = update.Get(); |
+ const std::string id_str = |
+ base::Int64ToString(package.last_backup_android_id); |
+ const std::string time_str = base::Int64ToString(package.last_backup_time); |
+ |
+ package_dict->SetBoolean(kShouldSync, package.sync); |
+ package_dict->SetInteger(kPackageVersion, package.package_version); |
+ package_dict->SetString(kLastBackupAndroidId, id_str); |
+ package_dict->SetString(kLastBackupTime, time_str); |
+ package_dict->SetBoolean(kSystem, package.system); |
+} |
+ |
+void ArcAppListPrefs::RemovePackageFromPrefs(PrefService* prefs, |
+ const std::string& package_name) { |
+ DCHECK(IsArcEnabled()); |
+ MaybeMarkDefaultPackageUninstalled(package_name, true); |
+ if (!HasDefaultPackage(package_name)) { |
+ DictionaryPrefUpdate update(prefs, prefs::kArcPackages); |
+ base::DictionaryValue* packages = update.Get(); |
+ const bool removed = packages->RemoveWithoutPathExpansion(package_name, |
+ nullptr); |
+ DCHECK(removed); |
+ } else { |
+ ScopedArcPrefUpdate update(prefs, package_name, prefs::kArcPackages); |
+ base::DictionaryValue* package_dict = update.Get(); |
+ package_dict->SetBoolean(kUninstalled, true); |
xiyuan
2016/08/26 19:32:29
Note that AppListSyncableService has support to tr
khmel
2016/08/26 23:26:18
I took a look and it seems it has very special han
xiyuan
2016/08/29 19:21:56
Thanks for digging into it. It is fine as long as
|
+ } |
+} |
+ |
void ArcAppListPrefs::OnAppListRefreshed( |
mojo::Array<arc::mojom::AppInfoPtr> apps) { |
DCHECK(IsArcEnabled()); |
@@ -740,7 +983,9 @@ void ArcAppListPrefs::OnAppListRefreshed( |
// If this is a shortcut, we just mark it as ready. |
ready_apps_.insert(app_id); |
} else { |
- RemoveApp(app_id); |
+ // Default apps may not be installed yet at this moment. |
+ if (!HasDefaultApp(app_id)) |
+ RemoveApp(app_id); |
} |
} |
@@ -881,7 +1126,7 @@ void ArcAppListPrefs::OnTaskCreated(int32_t task_id, |
const mojo::String& package_name, |
const mojo::String& activity, |
const mojo::String& name) { |
- MayAddNonLaunchableApp(name, package_name, activity); |
+ MaybeAddNonLaunchableApp(name, package_name, activity); |
FOR_EACH_OBSERVER(Observer, observer_list_, |
OnTaskCreated(task_id, package_name, activity)); |
} |
@@ -952,14 +1197,25 @@ void ArcAppListPrefs::OnPackageListRefreshed( |
} |
std::vector<std::string> ArcAppListPrefs::GetPackagesFromPrefs() const { |
+ return GetPackagesFromPrefs(true); |
+} |
+ |
+std::vector<std::string> ArcAppListPrefs::GetPackagesFromPrefs( |
+ bool installed) const { |
std::vector<std::string> packages; |
- if (!IsArcEnabled()) |
+ if (!IsArcEnabled() && installed) |
return packages; |
const base::DictionaryValue* package_prefs = |
prefs_->GetDictionary(prefs::kArcPackages); |
for (base::DictionaryValue::Iterator package(*package_prefs); |
!package.IsAtEnd(); package.Advance()) { |
+ |
+ bool uninstalled = false; |
+ package_prefs->GetBoolean(kSystem, &uninstalled); |
+ if (installed != !uninstalled) |
+ continue; |
+ |
packages.push_back(package.key()); |
} |
@@ -1038,6 +1294,19 @@ ArcAppListPrefs::AppInfo::AppInfo(const std::string& name, |
// Complex class/struct needs an explicit out-of-line destructor |
ArcAppListPrefs::AppInfo::~AppInfo() {} |
+ArcAppListPrefs::DefaultAppInfo::DefaultAppInfo(const std::string& name, |
+ const std::string& package_name, |
+ const std::string& activity, |
+ bool oem, |
+ const base::FilePath app_path) |
+ : name(name), |
+ package_name(package_name), |
+ activity(activity), |
+ oem(oem), |
+ app_path(app_path) {} |
+ |
+ArcAppListPrefs::DefaultAppInfo::~DefaultAppInfo() {} |
+ |
ArcAppListPrefs::PackageInfo::PackageInfo(const std::string& package_name, |
int32_t package_version, |
int64_t last_backup_android_id, |