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:
@@ -480,6 +480,11 @@ TEST_P(AppContextMenuTest, ArcMenu) {
|
|||||||
EXPECT_EQ(base::StringPrintf("ShortLabel %d", i),
|
EXPECT_EQ(base::StringPrintf("ShortLabel %d", i),
|
||||||
base::UTF16ToUTF8(menu->GetLabelAt(i + index)));
|
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.
|
// 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) {
|
void ArcAppContextMenu::ExecuteCommand(int command_id, int event_flags) {
|
||||||
switch (command_id) {
|
if (command_id == LAUNCH_NEW) {
|
||||||
case LAUNCH_NEW:
|
delegate()->ExecuteLaunchCommand(event_flags);
|
||||||
delegate()->ExecuteLaunchCommand(event_flags);
|
} else if (command_id == UNINSTALL) {
|
||||||
break;
|
arc::ShowArcAppUninstallDialog(profile(), controller(), app_id());
|
||||||
case UNINSTALL:
|
} else if (command_id == SHOW_APP_INFO) {
|
||||||
arc::ShowArcAppUninstallDialog(profile(), controller(), app_id());
|
ShowPackageInfo();
|
||||||
break;
|
} else if (command_id >= LAUNCH_APP_SHORTCUT_FIRST &&
|
||||||
case SHOW_APP_INFO:
|
command_id <= LAUNCH_APP_SHORTCUT_LAST) {
|
||||||
ShowPackageInfo();
|
ExecuteLaunchAppShortcutCommand(command_id);
|
||||||
break;
|
} else {
|
||||||
default:
|
app_list::AppContextMenu::ExecuteCommand(command_id, event_flags);
|
||||||
app_list::AppContextMenu::ExecuteCommand(command_id, event_flags);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,17 +131,30 @@ void ArcAppContextMenu::BuildAppShortcutsMenu(
|
|||||||
void ArcAppContextMenu::OnGetAppShortcutItems(
|
void ArcAppContextMenu::OnGetAppShortcutItems(
|
||||||
std::unique_ptr<ui::SimpleMenuModel> menu_model,
|
std::unique_ptr<ui::SimpleMenuModel> menu_model,
|
||||||
GetMenuModelCallback callback,
|
GetMenuModelCallback callback,
|
||||||
std::unique_ptr<arc::ArcAppShortcutItems> shortcut_items) {
|
std::unique_ptr<arc::ArcAppShortcutItems> app_shortcut_items) {
|
||||||
if (shortcut_items) {
|
app_shortcut_items_ = std::move(app_shortcut_items);
|
||||||
|
if (app_shortcut_items_) {
|
||||||
int command_id = LAUNCH_APP_SHORTCUT_FIRST;
|
int command_id = LAUNCH_APP_SHORTCUT_FIRST;
|
||||||
DCHECK_LT(command_id + shortcut_items->size(), LAUNCH_APP_SHORTCUT_LAST);
|
DCHECK_LT(command_id + app_shortcut_items_->size(),
|
||||||
for (const auto& item : *shortcut_items)
|
LAUNCH_APP_SHORTCUT_LAST);
|
||||||
|
for (const auto& item : *app_shortcut_items_)
|
||||||
menu_model->AddItemWithIcon(command_id++, item.short_label, item.icon);
|
menu_model->AddItemWithIcon(command_id++, item.short_label, item.icon);
|
||||||
}
|
}
|
||||||
std::move(callback).Run(std::move(menu_model));
|
std::move(callback).Run(std::move(menu_model));
|
||||||
arc_app_shortcuts_request_.reset();
|
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() {
|
void ArcAppContextMenu::ShowPackageInfo() {
|
||||||
const ArcAppListPrefs* arc_prefs = ArcAppListPrefs::Get(profile());
|
const ArcAppListPrefs* arc_prefs = ArcAppListPrefs::Get(profile());
|
||||||
DCHECK(arc_prefs);
|
DCHECK(arc_prefs);
|
||||||
|
@@ -45,10 +45,16 @@ class ArcAppContextMenu : public app_list::AppContextMenu {
|
|||||||
void OnGetAppShortcutItems(
|
void OnGetAppShortcutItems(
|
||||||
std::unique_ptr<ui::SimpleMenuModel> menu_model,
|
std::unique_ptr<ui::SimpleMenuModel> menu_model,
|
||||||
GetMenuModelCallback callback,
|
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();
|
void ShowPackageInfo();
|
||||||
|
|
||||||
|
// Caches the app shortcut items from OnGetAppShortcutItems().
|
||||||
|
std::unique_ptr<arc::ArcAppShortcutItems> app_shortcut_items_;
|
||||||
|
|
||||||
// Handles requesting app shortcuts from Android.
|
// Handles requesting app shortcuts from Android.
|
||||||
std::unique_ptr<arc::ArcAppShortcutsRequest> arc_app_shortcuts_request_;
|
std::unique_ptr<arc::ArcAppShortcutsRequest> arc_app_shortcuts_request_;
|
||||||
|
|
||||||
|
@@ -150,6 +150,15 @@ bool Launch(content::BrowserContext* context,
|
|||||||
return true;
|
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
|
} // namespace
|
||||||
|
|
||||||
const char kPlayStoreAppId[] = "cnbgggchhmkkdmeppjobngjoejnihlei";
|
const char kPlayStoreAppId[] = "cnbgggchhmkkdmeppjobngjoejnihlei";
|
||||||
@@ -184,7 +193,8 @@ bool LaunchPlayStoreWithUrl(const std::string& url) {
|
|||||||
arc::mojom::IntentHelperInstance* instance =
|
arc::mojom::IntentHelperInstance* instance =
|
||||||
GET_INTENT_HELPER_INSTANCE(HandleUrl);
|
GET_INTENT_HELPER_INSTANCE(HandleUrl);
|
||||||
if (!instance) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
instance->HandleUrl(url, kPlayStorePackage);
|
instance->HandleUrl(url, kPlayStorePackage);
|
||||||
@@ -212,11 +222,6 @@ bool LaunchAppWithIntent(content::BrowserContext* context,
|
|||||||
int64_t display_id) {
|
int64_t display_id) {
|
||||||
DCHECK(!launch_intent.has_value() || !launch_intent->empty());
|
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);
|
Profile* const profile = Profile::FromBrowserContext(context);
|
||||||
|
|
||||||
// Even when ARC is not allowed for the profile, ARC apps may still show up
|
// 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());
|
DCHECK(chrome_controller || !ash::Shell::HasInstance());
|
||||||
if (chrome_controller) {
|
if (chrome_controller) {
|
||||||
chrome_controller->GetArcDeferredLauncher()->RegisterDeferredLaunch(
|
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
|
// On some boards, ARC is booted with a restricted set of resources by
|
||||||
// default to avoid slowing down Chrome's user session restoration.
|
// default to avoid slowing down Chrome's user session restoration.
|
||||||
@@ -286,7 +291,37 @@ bool LaunchAppWithIntent(content::BrowserContext* context,
|
|||||||
}
|
}
|
||||||
arc::ArcBootPhaseMonitorBridge::RecordFirstAppLaunchDelayUMA(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,
|
bool LaunchSettingsAppActivity(content::BrowserContext* context,
|
||||||
|
@@ -109,6 +109,12 @@ bool LaunchAppWithIntent(content::BrowserContext* context,
|
|||||||
int event_flags,
|
int event_flags,
|
||||||
int64_t display_id);
|
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.
|
// Launches a specific activity within Settings app on ARC.
|
||||||
bool LaunchSettingsAppActivity(content::BrowserContext* context,
|
bool LaunchSettingsAppActivity(content::BrowserContext* context,
|
||||||
const std::string& activity,
|
const std::string& activity,
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
//
|
//
|
||||||
// Next MinVersion: 30
|
// Next MinVersion: 31
|
||||||
|
|
||||||
module arc.mojom;
|
module arc.mojom;
|
||||||
|
|
||||||
@@ -281,7 +281,7 @@ interface AppHost {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// TODO(lhchavez): Migrate all request/response messages to Mojo.
|
// TODO(lhchavez): Migrate all request/response messages to Mojo.
|
||||||
// Next method ID: 24
|
// Next method ID: 25
|
||||||
interface AppInstance {
|
interface AppInstance {
|
||||||
// DEPRECATED: Please use Init@21 instead.
|
// DEPRECATED: Please use Init@21 instead.
|
||||||
InitDeprecated@0(AppHost host_ptr);
|
InitDeprecated@0(AppHost host_ptr);
|
||||||
@@ -311,6 +311,11 @@ interface AppInstance {
|
|||||||
[MinVersion=23] LaunchApp@18(string package_name, string activity,
|
[MinVersion=23] LaunchApp@18(string package_name, string activity,
|
||||||
int64 display_id);
|
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,
|
[MinVersion=9] LaunchIntentDeprecated@12(string intent_uri,
|
||||||
Rect? dimension_on_screen);
|
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));
|
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,
|
void FakeAppInstance::RequestAppIcon(const std::string& package_name,
|
||||||
const std::string& activity,
|
const std::string& activity,
|
||||||
mojom::ScaleFactor scale_factor) {
|
mojom::ScaleFactor scale_factor) {
|
||||||
|
@@ -88,6 +88,9 @@ class FakeAppInstance : public mojom::AppInstance {
|
|||||||
void LaunchApp(const std::string& package_name,
|
void LaunchApp(const std::string& package_name,
|
||||||
const std::string& activity,
|
const std::string& activity,
|
||||||
int64_t display_id) override;
|
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,
|
void RequestAppIcon(const std::string& package_name,
|
||||||
const std::string& activity,
|
const std::string& activity,
|
||||||
mojom::ScaleFactor scale_factor) override;
|
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 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 {
|
const std::vector<std::unique_ptr<Request>>& launch_requests() const {
|
||||||
return launch_requests_;
|
return launch_requests_;
|
||||||
}
|
}
|
||||||
@@ -195,6 +202,8 @@ class FakeAppInstance : public mojom::AppInstance {
|
|||||||
int refresh_app_list_count_ = 0;
|
int refresh_app_list_count_ = 0;
|
||||||
// Number of requests to start PAI flows.
|
// Number of requests to start PAI flows.
|
||||||
int start_pai_request_count_ = 0;
|
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.
|
// Keeps information about launch requests.
|
||||||
std::vector<std::unique_ptr<Request>> launch_requests_;
|
std::vector<std::unique_ptr<Request>> launch_requests_;
|
||||||
// Keeps information about launch intents.
|
// Keeps information about launch intents.
|
||||||
|
Reference in New Issue
Block a user