0

arc: add LaunchAppShortcutItem API and apply in ArcAppContextMenu

Changes:
Design doc: go/arc-app-shortcuts

Launch app shortcut has to be called by Android's LauncherApps'
startShortcut API. Thus provide a mojo API to do the work.

Bug: 803291
Test: tested on device with ag/3997639
Change-Id: Idece1c44836a9e43932b700b81d128883c15666d
Reviewed-on: https://chromium-review.googlesource.com/1041574
Commit-Queue: Qiang Xu <warx@google.com>
Reviewed-by: Luis Hector Chavez <lhchavez@chromium.org>
Reviewed-by: Yury Khmel <khmel@chromium.org>
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
Cr-Commit-Position: refs/heads/master@{#556106}
This commit is contained in:
Qiang Xu
2018-05-04 17:45:11 +00:00
committed by Commit Bot
parent 5cea78b92f
commit 0148a64a2c
8 changed files with 111 additions and 27 deletions

@ -480,6 +480,11 @@ TEST_P(AppContextMenuTest, ArcMenu) {
EXPECT_EQ(base::StringPrintf("ShortLabel %d", i),
base::UTF16ToUTF8(menu->GetLabelAt(i + index)));
}
// Test launching app shortcut item.
EXPECT_EQ(0, arc_test.app_instance()->launch_app_shortcut_item_count());
menu->ActivatedAt(menu->GetItemCount() - 1);
EXPECT_EQ(1, arc_test.app_instance()->launch_app_shortcut_item_count());
}
// This makes all apps non-ready.

@ -88,18 +88,17 @@ bool ArcAppContextMenu::IsCommandIdEnabled(int command_id) const {
}
void ArcAppContextMenu::ExecuteCommand(int command_id, int event_flags) {
switch (command_id) {
case LAUNCH_NEW:
delegate()->ExecuteLaunchCommand(event_flags);
break;
case UNINSTALL:
arc::ShowArcAppUninstallDialog(profile(), controller(), app_id());
break;
case SHOW_APP_INFO:
ShowPackageInfo();
break;
default:
app_list::AppContextMenu::ExecuteCommand(command_id, event_flags);
if (command_id == LAUNCH_NEW) {
delegate()->ExecuteLaunchCommand(event_flags);
} else if (command_id == UNINSTALL) {
arc::ShowArcAppUninstallDialog(profile(), controller(), app_id());
} else if (command_id == SHOW_APP_INFO) {
ShowPackageInfo();
} else if (command_id >= LAUNCH_APP_SHORTCUT_FIRST &&
command_id <= LAUNCH_APP_SHORTCUT_LAST) {
ExecuteLaunchAppShortcutCommand(command_id);
} else {
app_list::AppContextMenu::ExecuteCommand(command_id, event_flags);
}
}
@ -132,17 +131,30 @@ void ArcAppContextMenu::BuildAppShortcutsMenu(
void ArcAppContextMenu::OnGetAppShortcutItems(
std::unique_ptr<ui::SimpleMenuModel> menu_model,
GetMenuModelCallback callback,
std::unique_ptr<arc::ArcAppShortcutItems> shortcut_items) {
if (shortcut_items) {
std::unique_ptr<arc::ArcAppShortcutItems> app_shortcut_items) {
app_shortcut_items_ = std::move(app_shortcut_items);
if (app_shortcut_items_) {
int command_id = LAUNCH_APP_SHORTCUT_FIRST;
DCHECK_LT(command_id + shortcut_items->size(), LAUNCH_APP_SHORTCUT_LAST);
for (const auto& item : *shortcut_items)
DCHECK_LT(command_id + app_shortcut_items_->size(),
LAUNCH_APP_SHORTCUT_LAST);
for (const auto& item : *app_shortcut_items_)
menu_model->AddItemWithIcon(command_id++, item.short_label, item.icon);
}
std::move(callback).Run(std::move(menu_model));
arc_app_shortcuts_request_.reset();
}
void ArcAppContextMenu::ExecuteLaunchAppShortcutCommand(int command_id) {
DCHECK(command_id >= LAUNCH_APP_SHORTCUT_FIRST &&
command_id <= LAUNCH_APP_SHORTCUT_LAST);
size_t index = command_id - LAUNCH_APP_SHORTCUT_FIRST;
DCHECK(app_shortcut_items_);
DCHECK_LT(index, app_shortcut_items_->size());
arc::LaunchAppShortcutItem(profile(), app_id(),
app_shortcut_items_->at(index).shortcut_id,
controller()->GetAppListDisplayId());
}
void ArcAppContextMenu::ShowPackageInfo() {
const ArcAppListPrefs* arc_prefs = ArcAppListPrefs::Get(profile());
DCHECK(arc_prefs);

@ -45,10 +45,16 @@ class ArcAppContextMenu : public app_list::AppContextMenu {
void OnGetAppShortcutItems(
std::unique_ptr<ui::SimpleMenuModel> menu_model,
GetMenuModelCallback callback,
std::unique_ptr<arc::ArcAppShortcutItems> shortcut_items);
std::unique_ptr<arc::ArcAppShortcutItems> app_shortcut_items);
// Executes launching app shortcut item.
void ExecuteLaunchAppShortcutCommand(int command_id);
void ShowPackageInfo();
// Caches the app shortcut items from OnGetAppShortcutItems().
std::unique_ptr<arc::ArcAppShortcutItems> app_shortcut_items_;
// Handles requesting app shortcuts from Android.
std::unique_ptr<arc::ArcAppShortcutsRequest> arc_app_shortcuts_request_;

@ -150,6 +150,15 @@ bool Launch(content::BrowserContext* context,
return true;
}
// Returns primary display id if |display_id| is invalid.
int64_t GetValidDisplayId(int64_t display_id) {
if (display_id != display::kInvalidDisplayId)
return display_id;
if (auto* screen = display::Screen::GetScreen())
return screen->GetPrimaryDisplay().id();
return display::kInvalidDisplayId;
}
} // namespace
const char kPlayStoreAppId[] = "cnbgggchhmkkdmeppjobngjoejnihlei";
@ -184,7 +193,8 @@ bool LaunchPlayStoreWithUrl(const std::string& url) {
arc::mojom::IntentHelperInstance* instance =
GET_INTENT_HELPER_INSTANCE(HandleUrl);
if (!instance) {
VLOG(1) << "Cannot find a mojo instance, ARC is unreachable";
VLOG(1) << "Cannot find a mojo instance, ARC is unreachable or mojom"
<< " version mismatch";
return false;
}
instance->HandleUrl(url, kPlayStorePackage);
@ -212,11 +222,6 @@ bool LaunchAppWithIntent(content::BrowserContext* context,
int64_t display_id) {
DCHECK(!launch_intent.has_value() || !launch_intent->empty());
if (display_id == display::kInvalidDisplayId) {
if (auto* screen = display::Screen::GetScreen())
display_id = screen->GetPrimaryDisplay().id();
}
Profile* const profile = Profile::FromBrowserContext(context);
// Even when ARC is not allowed for the profile, ARC apps may still show up
@ -273,7 +278,7 @@ bool LaunchAppWithIntent(content::BrowserContext* context,
DCHECK(chrome_controller || !ash::Shell::HasInstance());
if (chrome_controller) {
chrome_controller->GetArcDeferredLauncher()->RegisterDeferredLaunch(
app_id, event_flags, display_id);
app_id, event_flags, GetValidDisplayId(display_id));
// On some boards, ARC is booted with a restricted set of resources by
// default to avoid slowing down Chrome's user session restoration.
@ -286,7 +291,37 @@ bool LaunchAppWithIntent(content::BrowserContext* context,
}
arc::ArcBootPhaseMonitorBridge::RecordFirstAppLaunchDelayUMA(context);
return Launch(context, app_id, launch_intent, event_flags, display_id);
return Launch(context, app_id, launch_intent, event_flags,
GetValidDisplayId(display_id));
}
bool LaunchAppShortcutItem(content::BrowserContext* context,
const std::string& app_id,
const std::string& shortcut_id,
int64_t display_id) {
std::unique_ptr<ArcAppListPrefs::AppInfo> app_info =
ArcAppListPrefs::Get(context)->GetApp(app_id);
if (!app_info) {
LOG(ERROR) << "App " << app_id << " is not available.";
return false;
}
mojom::AppInstance* app_instance =
ArcServiceManager::Get()
? ARC_GET_INSTANCE_FOR_METHOD(
ArcServiceManager::Get()->arc_bridge_service()->app(),
LaunchAppShortcutItem)
: nullptr;
if (!app_instance) {
LOG(ERROR) << "Cannot find a mojo instance, ARC is unreachable or mojom"
<< " version mismatch.";
return false;
}
app_instance->LaunchAppShortcutItem(app_info->package_name, shortcut_id,
GetValidDisplayId(display_id));
return true;
}
bool LaunchSettingsAppActivity(content::BrowserContext* context,

@ -109,6 +109,12 @@ bool LaunchAppWithIntent(content::BrowserContext* context,
int event_flags,
int64_t display_id);
// Launches App Shortcut that was published by Android's ShortcutManager.
bool LaunchAppShortcutItem(content::BrowserContext* context,
const std::string& app_id,
const std::string& shortcut_id,
int64_t display_id);
// Launches a specific activity within Settings app on ARC.
bool LaunchSettingsAppActivity(content::BrowserContext* context,
const std::string& activity,

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Next MinVersion: 30
// Next MinVersion: 31
module arc.mojom;
@ -281,7 +281,7 @@ interface AppHost {
};
// TODO(lhchavez): Migrate all request/response messages to Mojo.
// Next method ID: 24
// Next method ID: 25
interface AppInstance {
// DEPRECATED: Please use Init@21 instead.
InitDeprecated@0(AppHost host_ptr);
@ -311,6 +311,11 @@ interface AppInstance {
[MinVersion=23] LaunchApp@18(string package_name, string activity,
int64 display_id);
// Sends a request to ARC for the Android launcher to launch the specified app
// shortcut.
[MinVersion=30] LaunchAppShortcutItem@24(
string package_name, string shortcut_id, int64 display_id);
[MinVersion=9] LaunchIntentDeprecated@12(string intent_uri,
Rect? dimension_on_screen);

@ -74,6 +74,12 @@ void FakeAppInstance::LaunchApp(const std::string& package_name,
launch_requests_.push_back(std::make_unique<Request>(package_name, activity));
}
void FakeAppInstance::LaunchAppShortcutItem(const std::string& package_name,
const std::string& shortcut_id,
int64_t display_id) {
++launch_app_shortcut_item_count_;
}
void FakeAppInstance::RequestAppIcon(const std::string& package_name,
const std::string& activity,
mojom::ScaleFactor scale_factor) {

@ -88,6 +88,9 @@ class FakeAppInstance : public mojom::AppInstance {
void LaunchApp(const std::string& package_name,
const std::string& activity,
int64_t display_id) override;
void LaunchAppShortcutItem(const std::string& package_name,
const std::string& shortcut_id,
int64_t display_id) override;
void RequestAppIcon(const std::string& package_name,
const std::string& activity,
mojom::ScaleFactor scale_factor) override;
@ -170,6 +173,10 @@ class FakeAppInstance : public mojom::AppInstance {
int start_pai_request_count() const { return start_pai_request_count_; }
int launch_app_shortcut_item_count() const {
return launch_app_shortcut_item_count_;
}
const std::vector<std::unique_ptr<Request>>& launch_requests() const {
return launch_requests_;
}
@ -195,6 +202,8 @@ class FakeAppInstance : public mojom::AppInstance {
int refresh_app_list_count_ = 0;
// Number of requests to start PAI flows.
int start_pai_request_count_ = 0;
// Keeps information about launch app shortcut requests.
int launch_app_shortcut_item_count_ = 0;
// Keeps information about launch requests.
std::vector<std::unique_ptr<Request>> launch_requests_;
// Keeps information about launch intents.