Commit a1cd8de6 authored by Yusuke Sato's avatar Yusuke Sato Committed by Commit Bot

arcvm: Support board-specific default apps

On ARC, to support board-specific default apps, the arc-setup command
creates a symlink from /var/cache/arc_default_apps to
/usr/share/google-chrome/extensions/arc/<board>. This doesn't work on
ARCVM where arc-setup is not in use.

To support ARCVM, this CL checks the current board name in Chrome and
construct the /usr/share/google-chrome/extensions/arc/<board> path at
runtime.

BUG=b:144199481
TEST=try, ARCVM still starts

Change-Id: I8dc3f93010d55324914cf774e90c040ef7f0c66b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2020479
Commit-Queue: Yusuke Sato <yusukes@chromium.org>
Reviewed-by: default avatarYury Khmel <khmel@chromium.org>
Cr-Commit-Position: refs/heads/master@{#735207}
parent 2fa134e2
...@@ -4,12 +4,16 @@ ...@@ -4,12 +4,16 @@
#include "chrome/browser/ui/app_list/arc/arc_default_app_list.h" #include "chrome/browser/ui/app_list/arc/arc_default_app_list.h"
#include <string.h>
#include "base/barrier_closure.h" #include "base/barrier_closure.h"
#include "base/bind.h" #include "base/bind.h"
#include "base/files/file_enumerator.h" #include "base/files/file_enumerator.h"
#include "base/files/file_util.h" #include "base/files/file_util.h"
#include "base/json/json_file_value_serializer.h" #include "base/json/json_file_value_serializer.h"
#include "base/path_service.h" #include "base/path_service.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/task/post_task.h" #include "base/task/post_task.h"
#include "chrome/browser/chromeos/arc/arc_util.h" #include "chrome/browser/chromeos/arc/arc_util.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
...@@ -17,6 +21,7 @@ ...@@ -17,6 +21,7 @@
#include "chrome/browser/ui/app_list/arc/arc_app_scoped_pref_update.h" #include "chrome/browser/ui/app_list/arc/arc_app_scoped_pref_update.h"
#include "chrome/browser/ui/app_list/arc/arc_app_utils.h" #include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
#include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_paths.h"
#include "components/arc/arc_util.h"
#include "components/pref_registry/pref_registry_syncable.h" #include "components/pref_registry/pref_registry_syncable.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_registry.h"
...@@ -40,6 +45,8 @@ const base::FilePath::CharType kArcTestBoardDirectory[] = ...@@ -40,6 +45,8 @@ const base::FilePath::CharType kArcTestBoardDirectory[] =
FILE_PATH_LITERAL("arc_board_default_apps"); FILE_PATH_LITERAL("arc_board_default_apps");
const base::FilePath::CharType kBoardDirectory[] = const base::FilePath::CharType kBoardDirectory[] =
FILE_PATH_LITERAL("/var/cache/arc_default_apps"); FILE_PATH_LITERAL("/var/cache/arc_default_apps");
const base::FilePath::CharType kBuildProp[] =
FILE_PATH_LITERAL("/usr/share/arcvm/properties/build.prop");
bool use_test_apps_directory = false; bool use_test_apps_directory = false;
...@@ -123,6 +130,30 @@ bool IsAppHidden(const PrefService* prefs, const std::string& app_id) { ...@@ -123,6 +130,30 @@ bool IsAppHidden(const PrefService* prefs, const std::string& app_id) {
return app_dict->GetBoolean(kHidden, &hidden) && hidden; return app_dict->GetBoolean(kHidden, &hidden) && hidden;
} }
std::string GetBoardName(const base::FilePath& build_prop_path) {
constexpr char kKeyToFind[] = "ro.product.board=";
std::string content;
if (!base::ReadFileToString(build_prop_path, &content)) {
PLOG(ERROR) << "Failed to read " << build_prop_path;
return std::string();
}
const std::vector<std::string> lines = base::SplitString(
content, "\n", base::WhitespaceHandling::KEEP_WHITESPACE,
base::SplitResult::SPLIT_WANT_ALL);
for (const auto& line : lines) {
if (!base::StartsWith(line, kKeyToFind, base::CompareCase::SENSITIVE))
continue;
const std::string board = line.substr(strlen(kKeyToFind));
VLOG(2) << "Current board is " << board;
return board;
}
LOG(ERROR) << "Failed to find " << kKeyToFind << " in " << build_prop_path;
return std::string();
}
} // namespace } // namespace
// static // static
...@@ -136,6 +167,12 @@ void ArcDefaultAppList::RegisterProfilePrefs( ...@@ -136,6 +167,12 @@ void ArcDefaultAppList::RegisterProfilePrefs(
registry->RegisterDictionaryPref(kDefaultApps); registry->RegisterDictionaryPref(kDefaultApps);
} }
// static
std::string ArcDefaultAppList::GetBoardNameForTesting(
const base::FilePath& build_prop_path) {
return GetBoardName(build_prop_path);
}
ArcDefaultAppList::ArcDefaultAppList(Profile* profile, ArcDefaultAppList::ArcDefaultAppList(Profile* profile,
base::OnceClosure ready_callback) base::OnceClosure ready_callback)
: profile_(profile), ready_callback_(std::move(ready_callback)) { : profile_(profile), ready_callback_(std::move(ready_callback)) {
...@@ -155,8 +192,18 @@ ArcDefaultAppList::ArcDefaultAppList(Profile* profile, ...@@ -155,8 +192,18 @@ ArcDefaultAppList::ArcDefaultAppList(Profile* profile,
const bool valid_path = base::PathService::Get( const bool valid_path = base::PathService::Get(
chrome::DIR_STANDALONE_EXTERNAL_EXTENSIONS, &base_path); chrome::DIR_STANDALONE_EXTERNAL_EXTENSIONS, &base_path);
DCHECK(valid_path); DCHECK(valid_path);
sources.push_back(base_path.Append(kArcDirectory)); const base::FilePath base_arc_path = base_path.Append(kArcDirectory);
sources.push_back(base::FilePath(kBoardDirectory)); sources.push_back(base_arc_path);
if (arc::IsArcVmEnabled()) {
// ARCVM environment doesn't have the symlink. Get the board name on the
// fly instead.
// TODO(yusukes): Do the same for ARC and remove the arc-setup code for
// creating the symlink.
sources.push_back(
base_arc_path.Append(GetBoardName(base::FilePath(kBuildProp))));
} else {
sources.push_back(base::FilePath(kBoardDirectory));
}
} else { } else {
const bool valid_path = const bool valid_path =
base::PathService::Get(chrome::DIR_TEST_DATA, &base_path); base::PathService::Get(chrome::DIR_TEST_DATA, &base_path);
......
...@@ -61,6 +61,8 @@ class ArcDefaultAppList { ...@@ -61,6 +61,8 @@ class ArcDefaultAppList {
static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
static void UseTestAppsDirectory(); static void UseTestAppsDirectory();
static std::string GetBoardNameForTesting(
const base::FilePath& build_prop_path);
// Returns default app info if it is found in defaults and its package is not // Returns default app info if it is found in defaults and its package is not
// marked as uninstalled. // marked as uninstalled.
......
// Copyright 2020 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/arc_default_app_list.h"
#include <string>
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
std::string GetBoardName(const std::string& content) {
base::ScopedTempDir scoped_dir;
CHECK(scoped_dir.CreateUniqueTempDir());
base::FilePath path;
CHECK(base::CreateTemporaryFileInDir(scoped_dir.GetPath(), &path));
CHECK(base::WriteFile(path, content.data(), content.size()) ==
static_cast<int>(content.size()));
return ArcDefaultAppList::GetBoardNameForTesting(path);
}
TEST(ArcDefaultAppListTest, GetBoardName) {
// Verify it returns "" when the path doesn't exist.
EXPECT_TRUE(ArcDefaultAppList::GetBoardNameForTesting(
(base::FilePath("/non/existent")))
.empty());
// Verify it returns "" when "^ro.product.board=" doesn't exist in the file.
EXPECT_TRUE(GetBoardName("").empty());
EXPECT_TRUE(GetBoardName("ro.product.xxxxx=").empty());
EXPECT_TRUE(GetBoardName("ro.product.board").empty());
EXPECT_TRUE(GetBoardName("#ro.product.board=abc").empty());
// Verify it return the value part when found.
EXPECT_EQ("a", GetBoardName("ro.product.board=a"));
EXPECT_EQ("abc", GetBoardName("ro.product.board=abc"));
EXPECT_EQ("abc", GetBoardName("ro.product.board=abc\n"));
EXPECT_EQ("abc", GetBoardName("\nro.product.board=abc\n"));
// Test the multi-line cases.
EXPECT_EQ("a", GetBoardName("ro.product.board=a\nro.product.xxxxx=x"));
EXPECT_EQ("a", GetBoardName("ro.product.xxxxx=x\nro.product.board=a"));
EXPECT_EQ("a",
GetBoardName(
"ro.product.xxxxx=x\nro.product.board=a\nro.product.yyyyy=y"));
EXPECT_TRUE(GetBoardName(
"ro.product.xxxxx=x\n#ro.product.board=a\nro.product.yyyyy=y")
.empty());
}
} // namespace
...@@ -4309,6 +4309,7 @@ test("unit_tests") { ...@@ -4309,6 +4309,7 @@ test("unit_tests") {
"../browser/ui/app_list/arc/arc_app_test.h", "../browser/ui/app_list/arc/arc_app_test.h",
"../browser/ui/app_list/arc/arc_app_unittest.cc", "../browser/ui/app_list/arc/arc_app_unittest.cc",
"../browser/ui/app_list/arc/arc_app_utils_unittest.cc", "../browser/ui/app_list/arc/arc_app_utils_unittest.cc",
"../browser/ui/app_list/arc/arc_default_app_list_unittest.cc",
"../browser/ui/app_list/arc/arc_vpn_provider_unittest.cc", "../browser/ui/app_list/arc/arc_vpn_provider_unittest.cc",
"../browser/ui/app_list/arc/mock_arc_app_list_prefs_observer.cc", "../browser/ui/app_list/arc/mock_arc_app_list_prefs_observer.cc",
"../browser/ui/app_list/arc/mock_arc_app_list_prefs_observer.h", "../browser/ui/app_list/arc/mock_arc_app_list_prefs_observer.h",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment