1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/apps/app_service/lacros_apps.h"
6
7 #include <utility>
8
9 #include "ash/public/cpp/app_menu_constants.h"
10 #include "base/bind.h"
11 #include "build/branding_buildflags.h"
12 #include "chrome/browser/apps/app_service/app_icon_factory.h"
13 #include "chrome/browser/apps/app_service/menu_util.h"
14 #include "chrome/browser/chromeos/crosapi/browser_manager.h"
15 #include "chrome/grit/chrome_unscaled_resources.h"
16 #include "chrome/grit/generated_resources.h"
17 #include "chromeos/constants/chromeos_features.h"
18 #include "components/services/app_service/public/mojom/types.mojom.h"
19 #include "extensions/common/constants.h"
20
21 namespace apps {
22
LacrosApps(const mojo::Remote<apps::mojom::AppService> & app_service)23 LacrosApps::LacrosApps(
24 const mojo::Remote<apps::mojom::AppService>& app_service) {
25 DCHECK(chromeos::features::IsLacrosSupportEnabled());
26 PublisherBase::Initialize(app_service, apps::mojom::AppType::kLacros);
27 }
28
29 LacrosApps::~LacrosApps() = default;
30
GetLacrosApp(bool is_ready)31 apps::mojom::AppPtr LacrosApps::GetLacrosApp(bool is_ready) {
32 apps::mojom::AppPtr app = apps::PublisherBase::MakeApp(
33 apps::mojom::AppType::kLacros, extension_misc::kLacrosAppId,
34 apps::mojom::Readiness::kReady,
35 "Lacros", // TODO(jamescook): Localized name.
36 apps::mojom::InstallSource::kSystem);
37 app->icon_key = NewIconKey(is_ready ? State::kReady : State::kLoading);
38 app->searchable = apps::mojom::OptionalBool::kTrue;
39 app->show_in_launcher = apps::mojom::OptionalBool::kTrue;
40 app->show_in_shelf = apps::mojom::OptionalBool::kTrue;
41 app->show_in_search = apps::mojom::OptionalBool::kTrue;
42 app->show_in_management = apps::mojom::OptionalBool::kFalse;
43 return app;
44 }
45
NewIconKey(State state)46 apps::mojom::IconKeyPtr LacrosApps::NewIconKey(State state) {
47 // Show different icons based on download state.
48 apps::IconEffects icon_effects;
49 switch (state) {
50 case State::kLoading:
51 icon_effects = apps::IconEffects::kPaused;
52 break;
53 case State::kError:
54 icon_effects = apps::IconEffects::kBlocked;
55 break;
56 case State::kReady:
57 icon_effects = apps::IconEffects::kNone;
58 break;
59 }
60 apps::mojom::IconKeyPtr icon_key =
61 icon_key_factory_.MakeIconKey(icon_effects);
62 #if BUILDFLAG(GOOGLE_CHROME_BRANDING)
63 // Canary icon only exists in branded builds.
64 icon_key->resource_id = IDR_PRODUCT_LOGO_256_CANARY;
65 #else
66 icon_key->resource_id = IDR_PRODUCT_LOGO_256;
67 #endif
68 return icon_key;
69 }
70
Connect(mojo::PendingRemote<apps::mojom::Subscriber> subscriber_remote,apps::mojom::ConnectOptionsPtr opts)71 void LacrosApps::Connect(
72 mojo::PendingRemote<apps::mojom::Subscriber> subscriber_remote,
73 apps::mojom::ConnectOptionsPtr opts) {
74 auto* browser_manager = crosapi::BrowserManager::Get();
75 bool is_ready = true;
76 // |browser_manager| may be null in tests. For tests, assume Lacros is ready.
77 if (browser_manager && !browser_manager->IsReady()) {
78 is_ready = false;
79 browser_manager->SetLoadCompleteCallback(base::BindOnce(
80 &LacrosApps::OnLoadComplete, weak_factory_.GetWeakPtr()));
81 }
82 std::vector<apps::mojom::AppPtr> apps;
83 apps.push_back(GetLacrosApp(is_ready));
84
85 mojo::Remote<apps::mojom::Subscriber> subscriber(
86 std::move(subscriber_remote));
87 subscriber->OnApps(std::move(apps));
88 subscribers_.Add(std::move(subscriber));
89 }
90
LoadIcon(const std::string & app_id,apps::mojom::IconKeyPtr icon_key,apps::mojom::IconType icon_type,int32_t size_hint_in_dip,bool allow_placeholder_icon,LoadIconCallback callback)91 void LacrosApps::LoadIcon(const std::string& app_id,
92 apps::mojom::IconKeyPtr icon_key,
93 apps::mojom::IconType icon_type,
94 int32_t size_hint_in_dip,
95 bool allow_placeholder_icon,
96 LoadIconCallback callback) {
97 if (icon_key &&
98 icon_key->resource_id != apps::mojom::IconKey::kInvalidResourceId) {
99 LoadIconFromResource(icon_type, size_hint_in_dip, icon_key->resource_id,
100 /*is_placeholder_icon=*/false,
101 static_cast<IconEffects>(icon_key->icon_effects),
102 std::move(callback));
103 return;
104 }
105 // On failure, we still run the callback, with the zero IconValue.
106 std::move(callback).Run(apps::mojom::IconValue::New());
107 }
108
Launch(const std::string & app_id,int32_t event_flags,apps::mojom::LaunchSource launch_source,int64_t display_id)109 void LacrosApps::Launch(const std::string& app_id,
110 int32_t event_flags,
111 apps::mojom::LaunchSource launch_source,
112 int64_t display_id) {
113 DCHECK_EQ(extension_misc::kLacrosAppId, app_id);
114 crosapi::BrowserManager::Get()->NewWindow();
115 }
116
GetMenuModel(const std::string & app_id,apps::mojom::MenuType menu_type,int64_t display_id,GetMenuModelCallback callback)117 void LacrosApps::GetMenuModel(const std::string& app_id,
118 apps::mojom::MenuType menu_type,
119 int64_t display_id,
120 GetMenuModelCallback callback) {
121 apps::mojom::MenuItemsPtr menu_items = apps::mojom::MenuItems::New();
122
123 // TODO(crbug.com/1108462): "New Window" menu should be hidden if
124 // incognito only mode is enforced by user's profile pref.
125 AddCommandItem((menu_type == apps::mojom::MenuType::kAppList)
126 ? ash::APP_CONTEXT_MENU_NEW_WINDOW
127 : ash::MENU_NEW_WINDOW,
128 IDS_APP_LIST_NEW_WINDOW, &menu_items);
129
130 std::move(callback).Run(std::move(menu_items));
131 }
132
OnLoadComplete(bool success)133 void LacrosApps::OnLoadComplete(bool success) {
134 apps::mojom::AppPtr app = apps::mojom::App::New();
135 app->app_type = apps::mojom::AppType::kLacros;
136 app->app_id = extension_misc::kLacrosAppId;
137 app->icon_key = NewIconKey(success ? State::kReady : State::kError);
138 Publish(std::move(app), subscribers_);
139 }
140
141 } // namespace apps
142