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