1 // Copyright (c) 2012 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/chromeos/extensions/autotest_private/autotest_private_api.h"
6
7 #include <algorithm>
8 #include <deque>
9 #include <map>
10 #include <set>
11 #include <sstream>
12 #include <utility>
13
14 #include "ash/public/cpp/accelerators.h"
15 #include "ash/public/cpp/accessibility_controller.h"
16 #include "ash/public/cpp/ambient/ambient_ui_model.h"
17 #include "ash/public/cpp/app_list/app_list_types.h"
18 #include "ash/public/cpp/app_types.h"
19 #include "ash/public/cpp/ash_pref_names.h"
20 #include "ash/public/cpp/assistant/assistant_client.h"
21 #include "ash/public/cpp/autotest_ambient_api.h"
22 #include "ash/public/cpp/autotest_desks_api.h"
23 #include "ash/public/cpp/autotest_private_api_utils.h"
24 #include "ash/public/cpp/desks_helper.h"
25 #include "ash/public/cpp/login_screen.h"
26 #include "ash/public/cpp/metrics_util.h"
27 #include "ash/public/cpp/overview_test_api.h"
28 #include "ash/public/cpp/shelf_item.h"
29 #include "ash/public/cpp/shelf_model.h"
30 #include "ash/public/cpp/shelf_prefs.h"
31 #include "ash/public/cpp/shelf_test_api.h"
32 #include "ash/public/cpp/shelf_types.h"
33 #include "ash/public/cpp/shelf_ui_info.h"
34 #include "ash/public/cpp/split_view_test_api.h"
35 #include "ash/public/cpp/tablet_mode.h"
36 #include "ash/public/cpp/window_properties.h"
37 #include "ash/rotator/screen_rotation_animator.h"
38 #include "ash/shell.h"
39 #include "ash/wm/wm_event.h"
40 #include "base/base64.h"
41 #include "base/bind.h"
42 #include "base/feature_list.h"
43 #include "base/json/json_reader.h"
44 #include "base/lazy_instance.h"
45 #include "base/no_destructor.h"
46 #include "base/numerics/safe_conversions.h"
47 #include "base/optional.h"
48 #include "base/run_loop.h"
49 #include "base/scoped_observer.h"
50 #include "base/strings/strcat.h"
51 #include "base/strings/string_number_conversions.h"
52 #include "base/task/post_task.h"
53 #include "base/threading/sequenced_task_runner_handle.h"
54 #include "base/threading/thread_task_runner_handle.h"
55 #include "base/time/time.h"
56 #include "base/values.h"
57 #include "build/build_config.h"
58 #include "chrome/app/chrome_command_ids.h"
59 #include "chrome/browser/apps/app_service/app_service_proxy.h"
60 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
61 #include "chrome/browser/banners/app_banner_manager.h"
62 #include "chrome/browser/banners/app_banner_manager_desktop.h"
63 #include "chrome/browser/browser_process.h"
64 #include "chrome/browser/browser_process_platform_part.h"
65 #include "chrome/browser/chromeos/arc/arc_util.h"
66 #include "chrome/browser/chromeos/arc/session/arc_session_manager.h"
67 #include "chrome/browser/chromeos/arc/tracing/arc_app_performance_tracing.h"
68 #include "chrome/browser/chromeos/arc/tracing/arc_app_performance_tracing_session.h"
69 #include "chrome/browser/chromeos/assistant/assistant_util.h"
70 #include "chrome/browser/chromeos/crostini/crostini_export_import.h"
71 #include "chrome/browser/chromeos/crostini/crostini_features.h"
72 #include "chrome/browser/chromeos/crostini/crostini_installer.h"
73 #include "chrome/browser/chromeos/crostini/crostini_manager.h"
74 #include "chrome/browser/chromeos/crostini/crostini_pref_names.h"
75 #include "chrome/browser/chromeos/crostini/crostini_util.h"
76 #include "chrome/browser/chromeos/file_manager/path_util.h"
77 #include "chrome/browser/chromeos/guest_os/guest_os_registry_service.h"
78 #include "chrome/browser/chromeos/guest_os/guest_os_registry_service_factory.h"
79 #include "chrome/browser/chromeos/login/lock/screen_locker.h"
80 #include "chrome/browser/chromeos/plugin_vm/plugin_vm_installer.h"
81 #include "chrome/browser/chromeos/plugin_vm/plugin_vm_installer_factory.h"
82 #include "chrome/browser/chromeos/plugin_vm/plugin_vm_util.h"
83 #include "chrome/browser/chromeos/printing/cups_printers_manager.h"
84 #include "chrome/browser/chromeos/printing/cups_printers_manager_factory.h"
85 #include "chrome/browser/chromeos/settings/stats_reporting_controller.h"
86 #include "chrome/browser/chromeos/system/input_device_settings.h"
87 #include "chrome/browser/extensions/extension_service.h"
88 #include "chrome/browser/lifetime/application_lifetime.h"
89 #include "chrome/browser/policy/chrome_policy_conversions_client.h"
90 #include "chrome/browser/profiles/profile.h"
91 #include "chrome/browser/profiles/profile_manager.h"
92 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
93 #include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
94 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h"
95 #include "chrome/browser/ui/ash/launcher/shelf_spinner_controller.h"
96 #include "chrome/browser/ui/aura/accessibility/automation_manager_aura.h"
97 #include "chrome/browser/ui/browser.h"
98 #include "chrome/browser/ui/browser_commands.h"
99 #include "chrome/browser/ui/browser_dialogs.h"
100 #include "chrome/browser/ui/browser_list.h"
101 #include "chrome/browser/ui/browser_tabstrip.h"
102 #include "chrome/browser/ui/browser_window.h"
103 #include "chrome/browser/ui/toolbar/app_menu_model.h"
104 #include "chrome/browser/ui/views/crostini/crostini_uninstaller_view.h"
105 #include "chrome/browser/ui/views/plugin_vm/plugin_vm_installer_view.h"
106 #include "chrome/browser/ui/web_applications/system_web_app_ui_utils.h"
107 #include "chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_dialog.h"
108 #include "chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_ui.h"
109 #include "chrome/browser/web_applications/components/app_registrar.h"
110 #include "chrome/browser/web_applications/components/app_registrar_observer.h"
111 #include "chrome/browser/web_applications/components/web_app_provider_base.h"
112 #include "chrome/browser/web_applications/system_web_app_manager.h"
113 #include "chrome/browser/web_applications/web_app_provider.h"
114 #include "chrome/common/extensions/api/autotest_private.h"
115 #include "chrome/common/pref_names.h"
116 #include "chromeos/dbus/dbus_thread_manager.h"
117 #include "chromeos/dbus/session_manager/session_manager_client.h"
118 #include "chromeos/printing/printer_configuration.h"
119 #include "chromeos/services/assistant/public/cpp/assistant_prefs.h"
120 #include "chromeos/services/assistant/public/cpp/assistant_service.h"
121 #include "chromeos/services/machine_learning/public/cpp/service_connection.h"
122 #include "chromeos/settings/cros_settings_names.h"
123 #include "chromeos/ui/base/window_properties.h"
124 #include "chromeos/ui/frame/default_frame_header.h"
125 #include "chromeos/ui/frame/frame_header.h"
126 #include "chromeos/ui/frame/immersive/immersive_fullscreen_controller.h"
127 #include "components/arc/arc_prefs.h"
128 #include "components/arc/metrics/arc_metrics_constants.h"
129 #include "components/policy/core/browser/policy_conversions.h"
130 #include "components/policy/core/common/policy_service.h"
131 #include "components/services/app_service/public/mojom/types.mojom.h"
132 #include "components/user_manager/user_manager.h"
133 #include "content/public/browser/browser_thread.h"
134 #include "content/public/browser/navigation_controller.h"
135 #include "content/public/browser/tracing_controller.h"
136 #include "content/public/browser/web_contents.h"
137 #include "extensions/browser/event_router.h"
138 #include "extensions/browser/extension_action.h"
139 #include "extensions/browser/extension_action_manager.h"
140 #include "extensions/browser/extension_function_registry.h"
141 #include "extensions/browser/extension_registry.h"
142 #include "extensions/browser/extension_system.h"
143 #include "extensions/browser/extension_util.h"
144 #include "extensions/common/api/extension_action/action_info.h"
145 #include "extensions/common/manifest_handlers/background_info.h"
146 #include "extensions/common/manifest_handlers/options_page_info.h"
147 #include "extensions/common/permissions/api_permission_set.h"
148 #include "extensions/common/permissions/permission_set.h"
149 #include "extensions/common/permissions/permissions_data.h"
150 #include "mojo/public/cpp/bindings/receiver.h"
151 #include "net/base/filename_util.h"
152 #include "ui/aura/client/aura_constants.h"
153 #include "ui/aura/env.h"
154 #include "ui/aura/window.h"
155 #include "ui/aura/window_observer.h"
156 #include "ui/aura/window_tree_host.h"
157 #include "ui/base/accelerators/accelerator_history.h"
158 #include "ui/base/clipboard/clipboard.h"
159 #include "ui/base/clipboard/scoped_clipboard_writer.h"
160 #include "ui/base/ime/chromeos/ime_bridge.h"
161 #include "ui/base/ui_base_features.h"
162 #include "ui/compositor/throughput_tracker.h"
163 #include "ui/compositor/throughput_tracker_host.h"
164 #include "ui/display/display.h"
165 #include "ui/display/screen.h"
166 #include "ui/events/event_constants.h"
167 #include "ui/events/types/event_type.h"
168 #include "ui/message_center/message_center.h"
169 #include "ui/message_center/notification_list.h"
170 #include "ui/message_center/public/cpp/notification.h"
171 #include "ui/message_center/public/cpp/notification_types.h"
172 #include "ui/ozone/public/ozone_platform.h"
173 #include "ui/ozone/public/system_input_injector.h"
174 #include "ui/views/widget/widget.h"
175 #include "ui/wm/core/coordinate_conversion.h"
176 #include "ui/wm/core/cursor_manager.h"
177 #include "ui/wm/core/window_util.h"
178 #include "ui/wm/public/activation_client.h"
179 #include "url/gurl.h"
180
181 namespace extensions {
182 namespace {
183
184 using chromeos::PrinterClass;
185
186 constexpr char kCrostiniNotAvailableForCurrentUserError[] =
187 "Crostini is not available for the current user";
188
AccessArray(const volatile int arr[],const volatile int * index)189 int AccessArray(const volatile int arr[], const volatile int* index) {
190 return arr[*index];
191 }
192
GetHostPermissions(const Extension * ext,bool effective_perm)193 std::unique_ptr<base::ListValue> GetHostPermissions(const Extension* ext,
194 bool effective_perm) {
195 const PermissionsData* permissions_data = ext->permissions_data();
196 const URLPatternSet& pattern_set =
197 effective_perm ? static_cast<const URLPatternSet&>(
198 permissions_data->GetEffectiveHostPermissions(
199 PermissionsData::EffectiveHostPermissionsMode::
200 kIncludeTabSpecific))
201 : permissions_data->active_permissions().explicit_hosts();
202
203 auto permissions = std::make_unique<base::ListValue>();
204 for (URLPatternSet::const_iterator perm = pattern_set.begin();
205 perm != pattern_set.end(); ++perm) {
206 permissions->AppendString(perm->GetAsString());
207 }
208
209 return permissions;
210 }
211
GetAPIPermissions(const Extension * ext)212 std::unique_ptr<base::ListValue> GetAPIPermissions(const Extension* ext) {
213 auto permissions = std::make_unique<base::ListValue>();
214 std::set<std::string> perm_list =
215 ext->permissions_data()->active_permissions().GetAPIsAsStrings();
216 for (std::set<std::string>::const_iterator perm = perm_list.begin();
217 perm != perm_list.end(); ++perm) {
218 permissions->AppendString(*perm);
219 }
220 return permissions;
221 }
222
IsTestMode(content::BrowserContext * context)223 bool IsTestMode(content::BrowserContext* context) {
224 return AutotestPrivateAPI::GetFactoryInstance()->Get(context)->test_mode();
225 }
226
ConvertToString(message_center::NotificationType type)227 std::string ConvertToString(message_center::NotificationType type) {
228 switch (type) {
229 case message_center::NOTIFICATION_TYPE_SIMPLE:
230 return "simple";
231 case message_center::NOTIFICATION_TYPE_BASE_FORMAT:
232 return "base_format";
233 case message_center::NOTIFICATION_TYPE_IMAGE:
234 return "image";
235 case message_center::NOTIFICATION_TYPE_MULTIPLE:
236 return "multiple";
237 case message_center::NOTIFICATION_TYPE_PROGRESS:
238 return "progress";
239 case message_center::NOTIFICATION_TYPE_CUSTOM:
240 return "custom";
241 }
242 return "unknown";
243 }
244
MakeDictionaryFromNotification(const message_center::Notification & notification)245 std::unique_ptr<base::DictionaryValue> MakeDictionaryFromNotification(
246 const message_center::Notification& notification) {
247 auto result = std::make_unique<base::DictionaryValue>();
248 result->SetString("id", notification.id());
249 result->SetString("type", ConvertToString(notification.type()));
250 result->SetString("title", notification.title());
251 result->SetString("message", notification.message());
252 result->SetInteger("priority", notification.priority());
253 result->SetInteger("progress", notification.progress());
254 return result;
255 }
256
GetPrinterType(PrinterClass type)257 std::string GetPrinterType(PrinterClass type) {
258 switch (type) {
259 case PrinterClass::kSaved:
260 return "configured";
261 case PrinterClass::kEnterprise:
262 return "enterprise";
263 case PrinterClass::kAutomatic:
264 return "automatic";
265 case PrinterClass::kDiscovered:
266 return "discovered";
267 default:
268 return "unknown";
269 }
270 }
271
GetShelfItemType(ash::ShelfItemType type)272 api::autotest_private::ShelfItemType GetShelfItemType(ash::ShelfItemType type) {
273 switch (type) {
274 case ash::TYPE_APP:
275 return api::autotest_private::ShelfItemType::SHELF_ITEM_TYPE_APP;
276 case ash::TYPE_PINNED_APP:
277 return api::autotest_private::ShelfItemType::SHELF_ITEM_TYPE_PINNEDAPP;
278 case ash::TYPE_BROWSER_SHORTCUT:
279 return api::autotest_private::ShelfItemType::
280 SHELF_ITEM_TYPE_BROWSERSHORTCUT;
281 case ash::TYPE_DIALOG:
282 return api::autotest_private::ShelfItemType::SHELF_ITEM_TYPE_DIALOG;
283 case ash::TYPE_UNDEFINED:
284 return api::autotest_private::ShelfItemType::SHELF_ITEM_TYPE_NONE;
285 }
286 NOTREACHED();
287 return api::autotest_private::ShelfItemType::SHELF_ITEM_TYPE_NONE;
288 }
289
GetShelfItemStatus(ash::ShelfItemStatus status)290 api::autotest_private::ShelfItemStatus GetShelfItemStatus(
291 ash::ShelfItemStatus status) {
292 switch (status) {
293 case ash::STATUS_CLOSED:
294 return api::autotest_private::ShelfItemStatus::SHELF_ITEM_STATUS_CLOSED;
295 case ash::STATUS_RUNNING:
296 return api::autotest_private::ShelfItemStatus::SHELF_ITEM_STATUS_RUNNING;
297 case ash::STATUS_ATTENTION:
298 return api::autotest_private::ShelfItemStatus::
299 SHELF_ITEM_STATUS_ATTENTION;
300 }
301 NOTREACHED();
302 return api::autotest_private::ShelfItemStatus::SHELF_ITEM_STATUS_NONE;
303 }
304
GetAppType(apps::mojom::AppType type)305 api::autotest_private::AppType GetAppType(apps::mojom::AppType type) {
306 switch (type) {
307 case apps::mojom::AppType::kArc:
308 return api::autotest_private::AppType::APP_TYPE_ARC;
309 case apps::mojom::AppType::kBuiltIn:
310 return api::autotest_private::AppType::APP_TYPE_BUILTIN;
311 case apps::mojom::AppType::kCrostini:
312 return api::autotest_private::AppType::APP_TYPE_CROSTINI;
313 case apps::mojom::AppType::kExtension:
314 return api::autotest_private::AppType::APP_TYPE_EXTENSION;
315 case apps::mojom::AppType::kPluginVm:
316 return api::autotest_private::AppType::APP_TYPE_PLUGINVM;
317 case apps::mojom::AppType::kWeb:
318 return api::autotest_private::AppType::APP_TYPE_WEB;
319 case apps::mojom::AppType::kUnknown:
320 return api::autotest_private::AppType::APP_TYPE_NONE;
321 case apps::mojom::AppType::kMacOs:
322 return api::autotest_private::AppType::APP_TYPE_MACOS;
323 case apps::mojom::AppType::kLacros:
324 return api::autotest_private::AppType::APP_TYPE_LACROS;
325 case apps::mojom::AppType::kRemote:
326 return api::autotest_private::AppType::APP_TYPE_REMOTE;
327 case apps::mojom::AppType::kBorealis:
328 return api::autotest_private::AppType::APP_TYPE_BOREALIS;
329 }
330 NOTREACHED();
331 return api::autotest_private::AppType::APP_TYPE_NONE;
332 }
333
GetAppInstallSource(apps::mojom::InstallSource source)334 api::autotest_private::AppInstallSource GetAppInstallSource(
335 apps::mojom::InstallSource source) {
336 switch (source) {
337 case apps::mojom::InstallSource::kUnknown:
338 return api::autotest_private::AppInstallSource::
339 APP_INSTALL_SOURCE_UNKNOWN;
340 case apps::mojom::InstallSource::kSystem:
341 return api::autotest_private::AppInstallSource::APP_INSTALL_SOURCE_SYSTEM;
342 case apps::mojom::InstallSource::kPolicy:
343 return api::autotest_private::AppInstallSource::APP_INSTALL_SOURCE_POLICY;
344 case apps::mojom::InstallSource::kOem:
345 return api::autotest_private::AppInstallSource::APP_INSTALL_SOURCE_OEM;
346 case apps::mojom::InstallSource::kDefault:
347 return api::autotest_private::AppInstallSource::
348 APP_INSTALL_SOURCE_DEFAULT;
349 case apps::mojom::InstallSource::kSync:
350 return api::autotest_private::AppInstallSource::APP_INSTALL_SOURCE_SYNC;
351 case apps::mojom::InstallSource::kUser:
352 return api::autotest_private::AppInstallSource::APP_INSTALL_SOURCE_USER;
353 }
354 NOTREACHED();
355 return api::autotest_private::AppInstallSource::APP_INSTALL_SOURCE_NONE;
356 }
357
GetAppWindowType(ash::AppType type)358 api::autotest_private::AppWindowType GetAppWindowType(ash::AppType type) {
359 switch (type) {
360 case ash::AppType::ARC_APP:
361 return api::autotest_private::AppWindowType::APP_WINDOW_TYPE_ARCAPP;
362 case ash::AppType::SYSTEM_APP:
363 return api::autotest_private::AppWindowType::APP_WINDOW_TYPE_SYSTEMAPP;
364 case ash::AppType::CROSTINI_APP:
365 return api::autotest_private::AppWindowType::APP_WINDOW_TYPE_CROSTINIAPP;
366 case ash::AppType::CHROME_APP:
367 return api::autotest_private::AppWindowType::APP_WINDOW_TYPE_EXTENSIONAPP;
368 case ash::AppType::BROWSER:
369 return api::autotest_private::AppWindowType::APP_WINDOW_TYPE_BROWSER;
370 case ash::AppType::LACROS:
371 return api::autotest_private::AppWindowType::APP_WINDOW_TYPE_LACROS;
372 case ash::AppType::NON_APP:
373 return api::autotest_private::AppWindowType::APP_WINDOW_TYPE_NONE;
374 // TODO(oshima): Investigate if we want to have "extension" type.
375 }
376 NOTREACHED();
377 return api::autotest_private::AppWindowType::APP_WINDOW_TYPE_NONE;
378 }
379
GetAppReadiness(apps::mojom::Readiness readiness)380 api::autotest_private::AppReadiness GetAppReadiness(
381 apps::mojom::Readiness readiness) {
382 switch (readiness) {
383 case apps::mojom::Readiness::kReady:
384 return api::autotest_private::AppReadiness::APP_READINESS_READY;
385 case apps::mojom::Readiness::kDisabledByBlocklist:
386 return api::autotest_private::AppReadiness::
387 APP_READINESS_DISABLEDBYBLACKLIST;
388 case apps::mojom::Readiness::kDisabledByPolicy:
389 return api::autotest_private::AppReadiness::
390 APP_READINESS_DISABLEDBYPOLICY;
391 case apps::mojom::Readiness::kDisabledByUser:
392 return api::autotest_private::AppReadiness::APP_READINESS_DISABLEDBYUSER;
393 case apps::mojom::Readiness::kTerminated:
394 return api::autotest_private::AppReadiness::APP_READINESS_TERMINATED;
395 case apps::mojom::Readiness::kUninstalledByUser:
396 return api::autotest_private::AppReadiness::
397 APP_READINESS_UNINSTALLEDBYUSER;
398 case apps::mojom::Readiness::kUnknown:
399 return api::autotest_private::AppReadiness::APP_READINESS_NONE;
400 }
401 NOTREACHED();
402 return api::autotest_private::AppReadiness::APP_READINESS_NONE;
403 }
404
GetHotseatState(ash::HotseatState hotseat_state)405 api::autotest_private::HotseatState GetHotseatState(
406 ash::HotseatState hotseat_state) {
407 switch (hotseat_state) {
408 case ash::HotseatState::kNone:
409 return api::autotest_private::HotseatState::HOTSEAT_STATE_NONE;
410 case ash::HotseatState::kHidden:
411 return api::autotest_private::HotseatState::HOTSEAT_STATE_HIDDEN;
412 case ash::HotseatState::kShownClamshell:
413 return api::autotest_private::HotseatState::HOTSEAT_STATE_SHOWNCLAMSHELL;
414 case ash::HotseatState::kShownHomeLauncher:
415 return api::autotest_private::HotseatState::
416 HOTSEAT_STATE_SHOWNHOMELAUNCHER;
417 case ash::HotseatState::kExtended:
418 return api::autotest_private::HotseatState::HOTSEAT_STATE_EXTENDED;
419 }
420
421 NOTREACHED();
422 }
423
ConvertMojomOptionalBool(apps::mojom::OptionalBool optional)424 std::unique_ptr<bool> ConvertMojomOptionalBool(
425 apps::mojom::OptionalBool optional) {
426 switch (optional) {
427 case apps::mojom::OptionalBool::kTrue:
428 return std::make_unique<bool>(true);
429 case apps::mojom::OptionalBool::kFalse:
430 return std::make_unique<bool>(false);
431 case apps::mojom::OptionalBool::kUnknown:
432 return nullptr;
433 }
434 NOTREACHED();
435 return nullptr;
436 }
437
438 // Helper function to set whitelisted user pref based on |pref_name| with any
439 // specific pref validations. Returns error messages if any.
SetWhitelistedPref(Profile * profile,const std::string & pref_name,const base::Value & value)440 std::string SetWhitelistedPref(Profile* profile,
441 const std::string& pref_name,
442 const base::Value& value) {
443 // Special case for the preference that is stored in the "Local State"
444 // profile.
445 if (pref_name == prefs::kEnableAdbSideloadingRequested) {
446 DCHECK(value.is_bool());
447 g_browser_process->local_state()->Set(pref_name, value);
448 return std::string();
449 }
450
451 if (pref_name == chromeos::assistant::prefs::kAssistantEnabled) {
452 if (!value.is_bool())
453 return "Invalid value type.";
454 // Validate the Assistant service allowed state.
455 chromeos::assistant::AssistantAllowedState allowed_state =
456 assistant::IsAssistantAllowedForProfile(profile);
457 if (allowed_state != chromeos::assistant::AssistantAllowedState::ALLOWED) {
458 return base::StringPrintf("Assistant not allowed - state: %d",
459 allowed_state);
460 }
461 } else if (pref_name == chromeos::assistant::prefs::kAssistantConsentStatus) {
462 if (!value.is_int())
463 return "Invalid value type.";
464 if (!profile->GetPrefs()->GetBoolean(
465 chromeos::assistant::prefs::kAssistantEnabled)) {
466 return "Unable to set the pref because Assistant has not been enabled.";
467 }
468 } else if (pref_name ==
469 chromeos::assistant::prefs::kAssistantContextEnabled ||
470 pref_name ==
471 chromeos::assistant::prefs::kAssistantHotwordEnabled) {
472 if (!value.is_bool())
473 return "Invalid value type.";
474 // Assistant service must be enabled first for those prefs to take effect.
475 if (!profile->GetPrefs()->GetBoolean(
476 chromeos::assistant::prefs::kAssistantEnabled)) {
477 return std::string(
478 "Unable to set the pref because Assistant has not been enabled.");
479 }
480 } else if (pref_name ==
481 ash::prefs::kAssistantNumSessionsWhereOnboardingShown) {
482 if (!value.is_int())
483 return "Invalid value type.";
484 } else if (pref_name == ash::prefs::kAccessibilityVirtualKeyboardEnabled) {
485 DCHECK(value.is_bool());
486 } else if (pref_name == prefs::kLanguagePreloadEngines) {
487 DCHECK(value.is_string());
488 } else {
489 return "The pref " + pref_name + " is not whitelisted.";
490 }
491
492 // Set value for the specified user pref after validation.
493 profile->GetPrefs()->Set(pref_name, value);
494
495 return std::string();
496 }
497
498 // Returns the ARC app window that associates with |package_name|. Note there
499 // might be more than 1 windows that have the same package name. This function
500 // just returns the first window it finds.
GetArcAppWindow(const std::string & package_name)501 aura::Window* GetArcAppWindow(const std::string& package_name) {
502 for (auto* window : ChromeLauncherController::instance()->GetArcWindows()) {
503 std::string* pkg_name = window->GetProperty(ash::kArcPackageNameKey);
504 if (pkg_name && *pkg_name == package_name)
505 return window;
506 }
507 return nullptr;
508 }
509
510 // Gets expected window state type according to |event_type|.
GetExpectedWindowState(api::autotest_private::WMEventType event_type)511 chromeos::WindowStateType GetExpectedWindowState(
512 api::autotest_private::WMEventType event_type) {
513 switch (event_type) {
514 case api::autotest_private::WMEventType::WM_EVENT_TYPE_WMEVENTNORMAL:
515 return chromeos::WindowStateType::kNormal;
516 case api::autotest_private::WMEventType::WM_EVENT_TYPE_WMEVENTMAXIMIZE:
517 return chromeos::WindowStateType::kMaximized;
518 case api::autotest_private::WMEventType::WM_EVENT_TYPE_WMEVENTMINIMIZE:
519 return chromeos::WindowStateType::kMinimized;
520 case api::autotest_private::WMEventType::WM_EVENT_TYPE_WMEVENTFULLSCREEN:
521 return chromeos::WindowStateType::kFullscreen;
522 case api::autotest_private::WMEventType::WM_EVENT_TYPE_WMEVENTSNAPLEFT:
523 return chromeos::WindowStateType::kLeftSnapped;
524 case api::autotest_private::WMEventType::WM_EVENT_TYPE_WMEVENTSNAPRIGHT:
525 return chromeos::WindowStateType::kRightSnapped;
526 default:
527 NOTREACHED();
528 return chromeos::WindowStateType::kNormal;
529 }
530 }
531
ToWMEventType(api::autotest_private::WMEventType event_type)532 ash::WMEventType ToWMEventType(api::autotest_private::WMEventType event_type) {
533 switch (event_type) {
534 case api::autotest_private::WMEventType::WM_EVENT_TYPE_WMEVENTNORMAL:
535 return ash::WMEventType::WM_EVENT_NORMAL;
536 case api::autotest_private::WMEventType::WM_EVENT_TYPE_WMEVENTMAXIMIZE:
537 return ash::WMEventType::WM_EVENT_MAXIMIZE;
538 case api::autotest_private::WMEventType::WM_EVENT_TYPE_WMEVENTMINIMIZE:
539 return ash::WMEventType::WM_EVENT_MINIMIZE;
540 case api::autotest_private::WMEventType::WM_EVENT_TYPE_WMEVENTFULLSCREEN:
541 return ash::WMEventType::WM_EVENT_FULLSCREEN;
542 case api::autotest_private::WMEventType::WM_EVENT_TYPE_WMEVENTSNAPLEFT:
543 return ash::WMEventType::WM_EVENT_SNAP_LEFT;
544 case api::autotest_private::WMEventType::WM_EVENT_TYPE_WMEVENTSNAPRIGHT:
545 return ash::WMEventType::WM_EVENT_SNAP_RIGHT;
546 default:
547 NOTREACHED();
548 return ash::WMEventType::WM_EVENT_NORMAL;
549 }
550 }
551
ToWindowStateType(chromeos::WindowStateType state_type)552 api::autotest_private::WindowStateType ToWindowStateType(
553 chromeos::WindowStateType state_type) {
554 switch (state_type) {
555 // Consider adding DEFAULT type to idl.
556 case chromeos::WindowStateType::kDefault:
557 case chromeos::WindowStateType::kNormal:
558 return api::autotest_private::WindowStateType::WINDOW_STATE_TYPE_NORMAL;
559 case chromeos::WindowStateType::kMinimized:
560 return api::autotest_private::WindowStateType::
561 WINDOW_STATE_TYPE_MINIMIZED;
562 case chromeos::WindowStateType::kMaximized:
563 return api::autotest_private::WindowStateType::
564 WINDOW_STATE_TYPE_MAXIMIZED;
565 case chromeos::WindowStateType::kFullscreen:
566 return api::autotest_private::WindowStateType::
567 WINDOW_STATE_TYPE_FULLSCREEN;
568 case chromeos::WindowStateType::kLeftSnapped:
569 return api::autotest_private::WindowStateType::
570 WINDOW_STATE_TYPE_LEFTSNAPPED;
571 case chromeos::WindowStateType::kRightSnapped:
572 return api::autotest_private::WindowStateType::
573 WINDOW_STATE_TYPE_RIGHTSNAPPED;
574 case chromeos::WindowStateType::kPip:
575 return api::autotest_private::WindowStateType::WINDOW_STATE_TYPE_PIP;
576 default:
577 NOTREACHED();
578 return api::autotest_private::WindowStateType::WINDOW_STATE_TYPE_NONE;
579 }
580 }
581
GetPngDataAsString(scoped_refptr<base::RefCountedMemory> png_data)582 std::string GetPngDataAsString(scoped_refptr<base::RefCountedMemory> png_data) {
583 // Base64 encode the result so we can return it as a string.
584 std::string base64Png(png_data->front(),
585 png_data->front() + png_data->size());
586 base::Base64Encode(base64Png, &base64Png);
587 return base64Png;
588 }
589
ToRotation(api::autotest_private::RotationType rotation)590 display::Display::Rotation ToRotation(
591 api::autotest_private::RotationType rotation) {
592 switch (rotation) {
593 case api::autotest_private::RotationType::ROTATION_TYPE_ROTATE0:
594 return display::Display::ROTATE_0;
595 case api::autotest_private::RotationType::ROTATION_TYPE_ROTATE90:
596 return display::Display::ROTATE_90;
597 case api::autotest_private::RotationType::ROTATION_TYPE_ROTATE180:
598 return display::Display::ROTATE_180;
599 case api::autotest_private::RotationType::ROTATION_TYPE_ROTATE270:
600 return display::Display::ROTATE_270;
601 case api::autotest_private::RotationType::ROTATION_TYPE_ROTATEANY:
602 case api::autotest_private::RotationType::ROTATION_TYPE_NONE:
603 break;
604 }
605 NOTREACHED();
606 return display::Display::ROTATE_0;
607 }
608
ToBoundsDictionary(const gfx::Rect & bounds)609 api::autotest_private::Bounds ToBoundsDictionary(const gfx::Rect& bounds) {
610 api::autotest_private::Bounds result;
611 result.left = bounds.x();
612 result.top = bounds.y();
613 result.width = bounds.width();
614 result.height = bounds.height();
615 return result;
616 }
617
ToRect(const api::autotest_private::Bounds & result)618 gfx::Rect ToRect(const api::autotest_private::Bounds& result) {
619 return gfx::Rect(result.left, result.top, result.width, result.height);
620 }
621
ToBoundsDictionaryList(const std::vector<gfx::Rect> & items_bounds)622 std::vector<api::autotest_private::Bounds> ToBoundsDictionaryList(
623 const std::vector<gfx::Rect>& items_bounds) {
624 std::vector<api::autotest_private::Bounds> bounds_list;
625 for (const gfx::Rect& bounds : items_bounds)
626 bounds_list.push_back(ToBoundsDictionary(bounds));
627 return bounds_list;
628 }
629
ToLocationDictionary(const gfx::Point & point)630 api::autotest_private::Location ToLocationDictionary(const gfx::Point& point) {
631 api::autotest_private::Location result;
632 result.x = point.x();
633 result.y = point.y();
634 return result;
635 }
636
FindAppWindowById(const int64_t id)637 aura::Window* FindAppWindowById(const int64_t id) {
638 auto list = ash::GetAppWindowList();
639 auto iter =
640 std::find_if(list.begin(), list.end(),
641 [id](aura::Window* window) { return window->id() == id; });
642 if (iter == list.end())
643 return nullptr;
644 return *iter;
645 }
646
647 // Returns the first available Browser that is not a web app.
GetFirstRegularBrowser()648 Browser* GetFirstRegularBrowser() {
649 const BrowserList* list = BrowserList::GetInstance();
650 auto iter = std::find_if(list->begin(), list->end(), [](Browser* browser) {
651 return browser->app_controller() == nullptr;
652 });
653 if (iter == list->end())
654 return nullptr;
655 return *iter;
656 }
657
ToAppListViewState(api::autotest_private::LauncherStateType state)658 ash::AppListViewState ToAppListViewState(
659 api::autotest_private::LauncherStateType state) {
660 switch (state) {
661 case api::autotest_private::LauncherStateType::LAUNCHER_STATE_TYPE_CLOSED:
662 return ash::AppListViewState::kClosed;
663 case api::autotest_private::LauncherStateType::LAUNCHER_STATE_TYPE_PEEKING:
664 return ash::AppListViewState::kPeeking;
665 case api::autotest_private::LauncherStateType::LAUNCHER_STATE_TYPE_HALF:
666 return ash::AppListViewState::kHalf;
667 case api::autotest_private::LauncherStateType::
668 LAUNCHER_STATE_TYPE_FULLSCREENALLAPPS:
669 return ash::AppListViewState::kFullscreenAllApps;
670 case api::autotest_private::LauncherStateType::
671 LAUNCHER_STATE_TYPE_FULLSCREENSEARCH:
672 return ash::AppListViewState::kFullscreenSearch;
673 case api::autotest_private::LauncherStateType::LAUNCHER_STATE_TYPE_NONE:
674 break;
675 }
676 return ash::AppListViewState::kClosed;
677 }
678
ToOverviewAnimationState(api::autotest_private::OverviewStateType state)679 ash::OverviewAnimationState ToOverviewAnimationState(
680 api::autotest_private::OverviewStateType state) {
681 switch (state) {
682 case api::autotest_private::OverviewStateType::OVERVIEW_STATE_TYPE_SHOWN:
683 return ash::OverviewAnimationState::kEnterAnimationComplete;
684 case api::autotest_private::OverviewStateType::OVERVIEW_STATE_TYPE_HIDDEN:
685 return ash::OverviewAnimationState::kExitAnimationComplete;
686 case api::autotest_private::OverviewStateType::OVERVIEW_STATE_TYPE_NONE:
687 break;
688 }
689 NOTREACHED();
690 return ash::OverviewAnimationState::kExitAnimationComplete;
691 }
692
StringToKeyCode(const std::string & str)693 ui::KeyboardCode StringToKeyCode(const std::string& str) {
694 constexpr struct Map {
695 const char* str;
696 ui::KeyboardCode key_code;
697 } map[] = {
698 {"search", ui::VKEY_LWIN},
699 {"assistant", ui::VKEY_ASSISTANT},
700 };
701 DCHECK(base::IsStringASCII(str));
702 if (str.length() == 1) {
703 char c = str[0];
704 if (c >= 'a' && c <= 'z') {
705 return static_cast<ui::KeyboardCode>(static_cast<int>(ui::VKEY_A) +
706 (c - 'a'));
707 }
708 if (c >= '0' && c <= '9') {
709 return static_cast<ui::KeyboardCode>(static_cast<int>(ui::VKEY_0) +
710 (c - '0'));
711 }
712 } else {
713 for (auto& entry : map) {
714 if (str == entry.str)
715 return entry.key_code;
716 }
717 }
718 NOTREACHED();
719 return ui::VKEY_A;
720 }
721
GetActiveWindow()722 aura::Window* GetActiveWindow() {
723 std::vector<aura::Window*> list = ash::GetAppWindowList();
724 if (!list.size())
725 return nullptr;
726 return wm::GetActivationClient(list[0]->GetRootWindow())->GetActiveWindow();
727 }
728
IsFrameVisible(views::Widget * widget)729 bool IsFrameVisible(views::Widget* widget) {
730 views::NonClientFrameView* frame_view =
731 widget->non_client_view() ? widget->non_client_view()->frame_view()
732 : nullptr;
733 return frame_view && frame_view->GetEnabled() && frame_view->GetVisible();
734 }
735
ConvertPointToHost(aura::Window * root_window,gfx::PointF * location)736 void ConvertPointToHost(aura::Window* root_window, gfx::PointF* location) {
737 gfx::Point3F transformed_location_in_root(*location);
738 root_window->GetHost()->GetRootTransform().TransformPoint(
739 &transformed_location_in_root);
740 *location = transformed_location_in_root.AsPointF();
741 }
742
GetMouseEventFlags(api::autotest_private::MouseButton button)743 int GetMouseEventFlags(api::autotest_private::MouseButton button) {
744 switch (button) {
745 case api::autotest_private::MOUSE_BUTTON_LEFT:
746 return ui::EF_LEFT_MOUSE_BUTTON;
747 case api::autotest_private::MOUSE_BUTTON_RIGHT:
748 return ui::EF_RIGHT_MOUSE_BUTTON;
749 case api::autotest_private::MOUSE_BUTTON_MIDDLE:
750 return ui::EF_MIDDLE_MOUSE_BUTTON;
751 default:
752 NOTREACHED();
753 }
754 return ui::EF_NONE;
755 }
756
757 // Gets display id out of an optional DOMString display id argument. Returns
758 // false if optional display id is given but in bad format. Otherwise returns
759 // true and fills |display_id| with either the primary display id when the
760 // optional arg is not given or the parsed display id out of the arg
GetDisplayIdFromOptionalArg(const std::unique_ptr<std::string> & arg,int64_t * display_id)761 bool GetDisplayIdFromOptionalArg(const std::unique_ptr<std::string>& arg,
762 int64_t* display_id) {
763 if (arg.get() && !arg->empty()) {
764 return base::StringToInt64(*arg, display_id);
765 }
766
767 *display_id = display::Screen::GetScreen()->GetPrimaryDisplay().id();
768 return true;
769 }
770
771 struct SmoothnessTrackerInfo {
772 base::Optional<ui::ThroughputTracker> tracker;
773 ui::ThroughputTrackerHost::ReportCallback callback;
774 };
775 using DisplaySmoothnessTrackerInfos = std::map<int64_t, SmoothnessTrackerInfo>;
GetDisplaySmoothnessTrackerInfos()776 DisplaySmoothnessTrackerInfos* GetDisplaySmoothnessTrackerInfos() {
777 static base::NoDestructor<DisplaySmoothnessTrackerInfos> trackers;
778 return trackers.get();
779 }
780
781 // Forwards frame rate data to the callback for |display_id| and resets.
ForwardFrameRateDataAndReset(int64_t display_id,const cc::FrameSequenceMetrics::CustomReportData & data)782 void ForwardFrameRateDataAndReset(
783 int64_t display_id,
784 const cc::FrameSequenceMetrics::CustomReportData& data) {
785 auto* infos = GetDisplaySmoothnessTrackerInfos();
786 auto it = infos->find(display_id);
787 DCHECK(it != infos->end());
788 DCHECK(it->second.callback);
789
790 // Moves the callback out and erases the mapping first to allow new tracking
791 // for |display_id| to start before |callback| run returns.
792 // See https://crbug.com/1098886.
793 auto callback = std::move(it->second.callback);
794 infos->erase(it);
795 std::move(callback).Run(data);
796 }
797
ResolutionToString(chromeos::assistant::AssistantInteractionResolution resolution)798 std::string ResolutionToString(
799 chromeos::assistant::AssistantInteractionResolution resolution) {
800 using chromeos::assistant::AssistantInteractionResolution;
801 switch (resolution) {
802 case AssistantInteractionResolution::kNormal:
803 return "kNormal";
804 case AssistantInteractionResolution::kError:
805 return "kError";
806 case AssistantInteractionResolution::kInterruption:
807 return "kInterruption";
808 case AssistantInteractionResolution::kMicTimeout:
809 return "kMicTimeout";
810 case AssistantInteractionResolution::kMultiDeviceHotwordLoss:
811 return "kMultiDeviceHotwordLoss";
812 }
813
814 // Not reachable here.
815 DCHECK(false);
816 }
817
818 } // namespace
819
820 class WindowStateChangeObserver : public aura::WindowObserver {
821 public:
WindowStateChangeObserver(aura::Window * window,chromeos::WindowStateType expected_type,base::OnceCallback<void (bool)> callback)822 WindowStateChangeObserver(aura::Window* window,
823 chromeos::WindowStateType expected_type,
824 base::OnceCallback<void(bool)> callback)
825 : expected_type_(expected_type), callback_(std::move(callback)) {
826 DCHECK_NE(window->GetProperty(chromeos::kWindowStateTypeKey),
827 expected_type_);
828 scoped_observer_.Add(window);
829 }
~WindowStateChangeObserver()830 ~WindowStateChangeObserver() override {}
831
832 // aura::WindowObserver:
OnWindowPropertyChanged(aura::Window * window,const void * key,intptr_t old)833 void OnWindowPropertyChanged(aura::Window* window,
834 const void* key,
835 intptr_t old) override {
836 DCHECK(scoped_observer_.IsObserving(window));
837 if (key == chromeos::kWindowStateTypeKey &&
838 window->GetProperty(chromeos::kWindowStateTypeKey) == expected_type_) {
839 scoped_observer_.RemoveAll();
840 std::move(callback_).Run(/*success=*/true);
841 }
842 }
843
OnWindowDestroying(aura::Window * window)844 void OnWindowDestroying(aura::Window* window) override {
845 DCHECK(scoped_observer_.IsObserving(window));
846 scoped_observer_.RemoveAll();
847 std::move(callback_).Run(/*success=*/false);
848 }
849
850 private:
851 chromeos::WindowStateType expected_type_;
852 ScopedObserver<aura::Window, aura::WindowObserver> scoped_observer_{this};
853 base::OnceCallback<void(bool)> callback_;
854
855 DISALLOW_COPY_AND_ASSIGN(WindowStateChangeObserver);
856 };
857
858 class WindowBoundsChangeObserver : public aura::WindowObserver {
859 public:
WindowBoundsChangeObserver(aura::Window * window,const gfx::Rect & to_bounds,int64_t display_id,base::OnceCallback<void (const gfx::Rect &,int64_t,bool)> callback)860 WindowBoundsChangeObserver(
861 aura::Window* window,
862 const gfx::Rect& to_bounds,
863 int64_t display_id,
864 base::OnceCallback<void(const gfx::Rect&, int64_t, bool)> callback)
865 : callback_(std::move(callback)) {
866 auto* state = ash::WindowState::Get(window);
867 DCHECK(state);
868 wait_for_bounds_change_ = window->GetBoundsInRootWindow() != to_bounds;
869 wait_for_display_change_ = state->GetDisplay().id() != display_id;
870 DCHECK(wait_for_bounds_change_ || wait_for_display_change_);
871 scoped_observer_.Add(window);
872 }
873 ~WindowBoundsChangeObserver() override = default;
874
875 WindowBoundsChangeObserver(const WindowBoundsChangeObserver&) = delete;
876 WindowBoundsChangeObserver& operator=(const WindowBoundsChangeObserver&) =
877 delete;
878
879 // aura::WindowObserver:
OnWindowBoundsChanged(aura::Window * window,const gfx::Rect & old_bounds,const gfx::Rect & new_bounds,ui::PropertyChangeReason reason)880 void OnWindowBoundsChanged(aura::Window* window,
881 const gfx::Rect& old_bounds,
882 const gfx::Rect& new_bounds,
883 ui::PropertyChangeReason reason) override {
884 wait_for_bounds_change_ = false;
885 MaybeFinishObserving(window, /*success=*/true);
886 }
887
OnWindowAddedToRootWindow(aura::Window * window)888 void OnWindowAddedToRootWindow(aura::Window* window) override {
889 wait_for_display_change_ = false;
890 MaybeFinishObserving(window, /*success=*/true);
891 }
892
OnWindowDestroying(aura::Window * window)893 void OnWindowDestroying(aura::Window* window) override {
894 wait_for_display_change_ = false;
895 wait_for_bounds_change_ = false;
896 MaybeFinishObserving(window, /*success=*/false);
897 }
898
899 private:
MaybeFinishObserving(aura::Window * window,bool success)900 void MaybeFinishObserving(aura::Window* window, bool success) {
901 DCHECK(scoped_observer_.IsObserving(window));
902 if (!wait_for_bounds_change_ && !wait_for_display_change_) {
903 scoped_observer_.RemoveAll();
904 std::move(callback_).Run(window->GetBoundsInRootWindow(),
905 ash::WindowState::Get(window)->GetDisplay().id(),
906 success);
907 }
908 }
909
910 ScopedObserver<aura::Window, aura::WindowObserver> scoped_observer_{this};
911 bool wait_for_bounds_change_ = false;
912 bool wait_for_display_change_ = false;
913 base::OnceCallback<void(const gfx::Rect&, int64_t, bool)> callback_;
914 };
915
916 class EventGenerator {
917 public:
EventGenerator(aura::WindowTreeHost * host,base::OnceClosure closure)918 EventGenerator(aura::WindowTreeHost* host, base::OnceClosure closure)
919 : input_injector_(
920 ui::OzonePlatform::GetInstance()->CreateSystemInputInjector()),
921 host_(host),
922 interval_(base::TimeDelta::FromSeconds(1) /
923 std::max(host->compositor()->refresh_rate(), 60.0f)),
924 closure_(std::move(closure)),
925 weak_ptr_factory_(this) {
926 LOG_IF(ERROR, host->compositor()->refresh_rate() < 60.0f)
927 << "Refresh rate (" << host->compositor()->refresh_rate()
928 << ") is too low.";
929 }
930 ~EventGenerator() = default;
931
ScheduleMouseEvent(ui::EventType type,gfx::PointF location_in_host,int flags)932 void ScheduleMouseEvent(ui::EventType type,
933 gfx::PointF location_in_host,
934 int flags) {
935 if (flags == 0 &&
936 (type == ui::ET_MOUSE_PRESSED || type == ui::ET_MOUSE_RELEASED)) {
937 LOG(ERROR) << "No flags specified for mouse button changes";
938 }
939 tasks_.push_back(Task(type, location_in_host, flags));
940 }
941
Run()942 void Run() {
943 next_event_timestamp_ = base::TimeTicks::Now();
944 SendEvent();
945 }
946
interval() const947 const base::TimeDelta& interval() const { return interval_; }
948
949 private:
950 struct Task {
951 enum Status {
952 kNotScheduled,
953 kScheduled,
954 };
955
956 const ui::EventType type;
957 const gfx::PointF location_in_host;
958 const int flags;
959 Status status = kNotScheduled;
960
Taskextensions::EventGenerator::Task961 Task(ui::EventType type, gfx::PointF location_in_host, int flags)
962 : type(type), location_in_host(location_in_host), flags(flags) {}
963 };
964
SendEvent()965 void SendEvent() {
966 if (tasks_.empty()) {
967 std::move(closure_).Run();
968 return;
969 }
970 Task* task = &tasks_.front();
971 DCHECK_EQ(task->status, Task::kNotScheduled);
972 // A task can be processed asynchronously; the next task will be scheduled
973 // after the control returns to the message pump, assuming that implies the
974 // processing of the current task has finished.
975 // WindowEventDispatcherObserver was used but the way it works does not
976 // support nested loop in window move/resize or drag-n-drop. In such
977 // cases, the mouse move event triggers the nested loop does not finish
978 // until the nested loop quits. But this blocks future mouse events. Hence
979 // the operation does not finish and the nested loop does not quit.
980 task->status = Task::kScheduled;
981 switch (task->type) {
982 case ui::ET_MOUSE_PRESSED:
983 case ui::ET_MOUSE_RELEASED: {
984 bool pressed = (task->type == ui::ET_MOUSE_PRESSED);
985 if (task->flags & ui::EF_LEFT_MOUSE_BUTTON)
986 input_injector_->InjectMouseButton(ui::EF_LEFT_MOUSE_BUTTON, pressed);
987 if (task->flags & ui::EF_MIDDLE_MOUSE_BUTTON) {
988 input_injector_->InjectMouseButton(ui::EF_MIDDLE_MOUSE_BUTTON,
989 pressed);
990 }
991 if (task->flags & ui::EF_RIGHT_MOUSE_BUTTON) {
992 input_injector_->InjectMouseButton(ui::EF_RIGHT_MOUSE_BUTTON,
993 pressed);
994 }
995 break;
996 }
997 case ui::ET_MOUSE_MOVED:
998 case ui::ET_MOUSE_DRAGGED:
999 // The location should be offset by the origin of the root-window since
1000 // ui::SystemInputInjector expects so.
1001 input_injector_->MoveCursorTo(
1002 task->location_in_host +
1003 host_->GetBoundsInPixels().OffsetFromOrigin());
1004 break;
1005 default:
1006 NOTREACHED();
1007 }
1008
1009 // Post a task after scheduling the event and assumes that when the task
1010 // runs, it implies that the processing of the scheduled event is finished.
1011 base::SequencedTaskRunnerHandle::Get()->PostTask(
1012 FROM_HERE, base::BindOnce(&EventGenerator::OnFinishedProcessingEvent,
1013 weak_ptr_factory_.GetWeakPtr()));
1014 }
1015
OnFinishedProcessingEvent()1016 void OnFinishedProcessingEvent() {
1017 if (tasks_.empty())
1018 return;
1019
1020 DCHECK_EQ(tasks_.front().status, Task::kScheduled);
1021 tasks_.pop_front();
1022 auto runner = base::SequencedTaskRunnerHandle::Get();
1023 auto closure = base::BindOnce(&EventGenerator::SendEvent,
1024 weak_ptr_factory_.GetWeakPtr());
1025 // Non moving tasks can be done immediately.
1026 if (tasks_.empty() || tasks_.front().type == ui::ET_MOUSE_PRESSED ||
1027 tasks_.front().type == ui::ET_MOUSE_RELEASED) {
1028 runner->PostTask(FROM_HERE, std::move(closure));
1029 return;
1030 }
1031 next_event_timestamp_ += interval_;
1032 auto now = base::TimeTicks::Now();
1033 base::TimeDelta interval = next_event_timestamp_ - now;
1034 if (interval <= base::TimeDelta()) {
1035 // Looks like event handling could take too long time -- still generate
1036 // the next event with resetting the interval.
1037 LOG(ERROR) << "The handling of the event spent long time and there is "
1038 << "no time to delay. The next event is supposed to happen at "
1039 << next_event_timestamp_ << " but now at " << now << ". "
1040 << "Posting the next event immediately.";
1041 next_event_timestamp_ = now;
1042 runner->PostTask(FROM_HERE, std::move(closure));
1043 } else {
1044 runner->PostDelayedTask(FROM_HERE, std::move(closure), interval);
1045 }
1046 }
1047
1048 std::unique_ptr<ui::SystemInputInjector> input_injector_;
1049 aura::WindowTreeHost* host_;
1050 base::TimeTicks next_event_timestamp_;
1051 const base::TimeDelta interval_;
1052 base::OnceClosure closure_;
1053 std::deque<Task> tasks_;
1054
1055 base::WeakPtrFactory<EventGenerator> weak_ptr_factory_;
1056 };
1057
1058 ///////////////////////////////////////////////////////////////////////////////
1059 // AutotestPrivateInitializeEventsFunction
1060 ///////////////////////////////////////////////////////////////////////////////
1061
1062 AutotestPrivateInitializeEventsFunction::
1063 ~AutotestPrivateInitializeEventsFunction() = default;
1064
1065 ExtensionFunction::ResponseAction
Run()1066 AutotestPrivateInitializeEventsFunction::Run() {
1067 // AutotestPrivateAPI is lazily initialized, but needs to be created before
1068 // any of its events can be fired, so we get the instance here and return.
1069 AutotestPrivateAPI::GetFactoryInstance()->Get(browser_context());
1070 return RespondNow(NoArguments());
1071 }
1072
1073 ///////////////////////////////////////////////////////////////////////////////
1074 // AutotestPrivateLogoutFunction
1075 ///////////////////////////////////////////////////////////////////////////////
1076
1077 AutotestPrivateLogoutFunction::~AutotestPrivateLogoutFunction() = default;
1078
Run()1079 ExtensionFunction::ResponseAction AutotestPrivateLogoutFunction::Run() {
1080 DVLOG(1) << "AutotestPrivateLogoutFunction";
1081 if (!IsTestMode(browser_context()))
1082 chrome::AttemptUserExit();
1083 return RespondNow(NoArguments());
1084 }
1085
1086 ///////////////////////////////////////////////////////////////////////////////
1087 // AutotestPrivateRestartFunction
1088 ///////////////////////////////////////////////////////////////////////////////
1089
1090 AutotestPrivateRestartFunction::~AutotestPrivateRestartFunction() = default;
1091
Run()1092 ExtensionFunction::ResponseAction AutotestPrivateRestartFunction::Run() {
1093 DVLOG(1) << "AutotestPrivateRestartFunction";
1094 if (!IsTestMode(browser_context()))
1095 chrome::AttemptRestart();
1096 return RespondNow(NoArguments());
1097 }
1098
1099 ///////////////////////////////////////////////////////////////////////////////
1100 // AutotestPrivateShutdownFunction
1101 ///////////////////////////////////////////////////////////////////////////////
1102
1103 AutotestPrivateShutdownFunction::~AutotestPrivateShutdownFunction() = default;
1104
Run()1105 ExtensionFunction::ResponseAction AutotestPrivateShutdownFunction::Run() {
1106 std::unique_ptr<api::autotest_private::Shutdown::Params> params(
1107 api::autotest_private::Shutdown::Params::Create(*args_));
1108 EXTENSION_FUNCTION_VALIDATE(params.get());
1109 DVLOG(1) << "AutotestPrivateShutdownFunction " << params->force;
1110
1111 if (!IsTestMode(browser_context()))
1112 chrome::AttemptExit();
1113 return RespondNow(NoArguments());
1114 }
1115
1116 ///////////////////////////////////////////////////////////////////////////////
1117 // AutotestPrivateLoginStatusFunction
1118 ///////////////////////////////////////////////////////////////////////////////
1119
1120 AutotestPrivateLoginStatusFunction::~AutotestPrivateLoginStatusFunction() =
1121 default;
1122
Run()1123 ExtensionFunction::ResponseAction AutotestPrivateLoginStatusFunction::Run() {
1124 DVLOG(1) << "AutotestPrivateLoginStatusFunction";
1125 auto result = std::make_unique<base::DictionaryValue>();
1126 const user_manager::UserManager* user_manager =
1127 user_manager::UserManager::Get();
1128
1129 // default_screen_locker()->locked() is set when the UI is ready, so this
1130 // tells us both views based lockscreen UI and screenlocker are ready.
1131 const bool is_screen_locked =
1132 !!chromeos::ScreenLocker::default_screen_locker() &&
1133 chromeos::ScreenLocker::default_screen_locker()->locked();
1134
1135 if (user_manager) {
1136 result->SetBoolean("isLoggedIn", user_manager->IsUserLoggedIn());
1137 result->SetBoolean("isOwner", user_manager->IsCurrentUserOwner());
1138 result->SetBoolean("isScreenLocked", is_screen_locked);
1139 result->SetBoolean("isReadyForPassword",
1140 ash::LoginScreen::Get()->IsReadyForPassword());
1141 if (user_manager->IsUserLoggedIn()) {
1142 result->SetBoolean("isRegularUser",
1143 user_manager->IsLoggedInAsUserWithGaiaAccount());
1144 result->SetBoolean("isGuest", user_manager->IsLoggedInAsGuest());
1145 result->SetBoolean("isKiosk", user_manager->IsLoggedInAsKioskApp());
1146
1147 const user_manager::User* user = user_manager->GetActiveUser();
1148 result->SetString("email", user->GetAccountId().GetUserEmail());
1149 result->SetString("displayEmail", user->display_email());
1150
1151 std::string user_image;
1152 switch (user->image_index()) {
1153 case user_manager::User::USER_IMAGE_EXTERNAL:
1154 user_image = "file";
1155 break;
1156
1157 case user_manager::User::USER_IMAGE_PROFILE:
1158 user_image = "profile";
1159 break;
1160
1161 default:
1162 user_image = base::NumberToString(user->image_index());
1163 break;
1164 }
1165 result->SetString("userImage", user_image);
1166 }
1167 }
1168 return RespondNow(
1169 OneArgument(base::Value::FromUniquePtrValue(std::move(result))));
1170 }
1171
1172 ///////////////////////////////////////////////////////////////////////////////
1173 // AutotestPrivateLockScreenFunction
1174 ///////////////////////////////////////////////////////////////////////////////
1175
1176 AutotestPrivateLockScreenFunction::~AutotestPrivateLockScreenFunction() =
1177 default;
1178
Run()1179 ExtensionFunction::ResponseAction AutotestPrivateLockScreenFunction::Run() {
1180 DVLOG(1) << "AutotestPrivateLockScreenFunction";
1181
1182 chromeos::SessionManagerClient::Get()->RequestLockScreen();
1183 return RespondNow(NoArguments());
1184 }
1185
1186 ///////////////////////////////////////////////////////////////////////////////
1187 // AutotestPrivateGetAllEnterprisePoliciesFunction
1188 ///////////////////////////////////////////////////////////////////////////////
1189
1190 AutotestPrivateGetAllEnterprisePoliciesFunction::
1191 ~AutotestPrivateGetAllEnterprisePoliciesFunction() = default;
1192
1193 ExtensionFunction::ResponseAction
Run()1194 AutotestPrivateGetAllEnterprisePoliciesFunction::Run() {
1195 DVLOG(1) << "AutotestPrivateGetAllEnterprisePoliciesFunction";
1196
1197 auto client = std::make_unique<policy::ChromePolicyConversionsClient>(
1198 browser_context());
1199 base::Value all_policies_array =
1200 policy::DictionaryPolicyConversions(std::move(client))
1201 .EnableDeviceLocalAccountPolicies(true)
1202 .EnableDeviceInfo(true)
1203 .ToValue();
1204
1205 return RespondNow(OneArgument(std::move(all_policies_array)));
1206 }
1207
1208 ///////////////////////////////////////////////////////////////////////////////
1209 // AutotestPrivateRefreshEnterprisePoliciesFunction
1210 ///////////////////////////////////////////////////////////////////////////////
1211
1212 AutotestPrivateRefreshEnterprisePoliciesFunction::
1213 ~AutotestPrivateRefreshEnterprisePoliciesFunction() = default;
1214
1215 ExtensionFunction::ResponseAction
Run()1216 AutotestPrivateRefreshEnterprisePoliciesFunction::Run() {
1217 DVLOG(1) << "AutotestPrivateRefreshEnterprisePoliciesFunction";
1218
1219 g_browser_process->policy_service()->RefreshPolicies(base::BindOnce(
1220 &AutotestPrivateRefreshEnterprisePoliciesFunction::RefreshDone, this));
1221 return RespondLater();
1222 }
1223
RefreshDone()1224 void AutotestPrivateRefreshEnterprisePoliciesFunction::RefreshDone() {
1225 Respond(NoArguments());
1226 }
1227
1228 ///////////////////////////////////////////////////////////////////////////////
1229 // AutotestPrivateGetExtensionsInfoFunction
1230 ///////////////////////////////////////////////////////////////////////////////
1231
1232 AutotestPrivateGetExtensionsInfoFunction::
1233 ~AutotestPrivateGetExtensionsInfoFunction() = default;
1234
1235 ExtensionFunction::ResponseAction
Run()1236 AutotestPrivateGetExtensionsInfoFunction::Run() {
1237 DVLOG(1) << "AutotestPrivateGetExtensionsInfoFunction";
1238
1239 ExtensionService* service =
1240 ExtensionSystem::Get(browser_context())->extension_service();
1241 ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context());
1242 const ExtensionSet& extensions = registry->enabled_extensions();
1243 const ExtensionSet& disabled_extensions = registry->disabled_extensions();
1244 ExtensionActionManager* extension_action_manager =
1245 ExtensionActionManager::Get(browser_context());
1246
1247 auto extensions_values = std::make_unique<base::ListValue>();
1248 ExtensionList all;
1249 all.insert(all.end(), extensions.begin(), extensions.end());
1250 all.insert(all.end(), disabled_extensions.begin(), disabled_extensions.end());
1251 for (ExtensionList::const_iterator it = all.begin(); it != all.end(); ++it) {
1252 const Extension* extension = it->get();
1253 std::string id = extension->id();
1254 std::unique_ptr<base::DictionaryValue> extension_value(
1255 new base::DictionaryValue);
1256 extension_value->SetString("id", id);
1257 extension_value->SetString("version", extension->VersionString());
1258 extension_value->SetString("name", extension->name());
1259 extension_value->SetString("publicKey", extension->public_key());
1260 extension_value->SetString("description", extension->description());
1261 extension_value->SetString(
1262 "backgroundUrl", BackgroundInfo::GetBackgroundURL(extension).spec());
1263 extension_value->SetString(
1264 "optionsUrl", OptionsPageInfo::GetOptionsPage(extension).spec());
1265
1266 extension_value->Set("hostPermissions",
1267 GetHostPermissions(extension, false));
1268 extension_value->Set("effectiveHostPermissions",
1269 GetHostPermissions(extension, true));
1270 extension_value->Set("apiPermissions", GetAPIPermissions(extension));
1271
1272 Manifest::Location location = extension->location();
1273 extension_value->SetBoolean("isComponent", location == Manifest::COMPONENT);
1274 extension_value->SetBoolean("isInternal", location == Manifest::INTERNAL);
1275 extension_value->SetBoolean("isUserInstalled",
1276 location == Manifest::INTERNAL ||
1277 Manifest::IsUnpackedLocation(location));
1278 extension_value->SetBoolean("isEnabled", service->IsExtensionEnabled(id));
1279 extension_value->SetBoolean(
1280 "allowedInIncognito", util::IsIncognitoEnabled(id, browser_context()));
1281 const ExtensionAction* action =
1282 extension_action_manager->GetExtensionAction(*extension);
1283 extension_value->SetBoolean(
1284 "hasPageAction",
1285 action && action->action_type() == ActionInfo::TYPE_PAGE);
1286
1287 extensions_values->Append(std::move(extension_value));
1288 }
1289
1290 std::unique_ptr<base::DictionaryValue> return_value(
1291 new base::DictionaryValue);
1292 return_value->Set("extensions", std::move(extensions_values));
1293 return RespondNow(
1294 OneArgument(base::Value::FromUniquePtrValue(std::move(return_value))));
1295 }
1296
1297 ///////////////////////////////////////////////////////////////////////////////
1298 // AutotestPrivateSimulateAsanMemoryBugFunction
1299 ///////////////////////////////////////////////////////////////////////////////
1300
1301 AutotestPrivateSimulateAsanMemoryBugFunction::
1302 ~AutotestPrivateSimulateAsanMemoryBugFunction() = default;
1303
1304 ExtensionFunction::ResponseAction
Run()1305 AutotestPrivateSimulateAsanMemoryBugFunction::Run() {
1306 DVLOG(1) << "AutotestPrivateSimulateAsanMemoryBugFunction";
1307
1308 if (!IsTestMode(browser_context())) {
1309 // This array is volatile not to let compiler optimize us out.
1310 volatile int testarray[3] = {0, 0, 0};
1311
1312 // Cause Address Sanitizer to abort this process.
1313 volatile int index = 5;
1314 AccessArray(testarray, &index);
1315 }
1316 return RespondNow(NoArguments());
1317 }
1318
1319 ///////////////////////////////////////////////////////////////////////////////
1320 // AutotestPrivateSetTouchpadSensitivityFunction
1321 ///////////////////////////////////////////////////////////////////////////////
1322
1323 AutotestPrivateSetTouchpadSensitivityFunction::
1324 ~AutotestPrivateSetTouchpadSensitivityFunction() = default;
1325
1326 ExtensionFunction::ResponseAction
Run()1327 AutotestPrivateSetTouchpadSensitivityFunction::Run() {
1328 std::unique_ptr<api::autotest_private::SetTouchpadSensitivity::Params> params(
1329 api::autotest_private::SetTouchpadSensitivity::Params::Create(*args_));
1330 EXTENSION_FUNCTION_VALIDATE(params.get());
1331 DVLOG(1) << "AutotestPrivateSetTouchpadSensitivityFunction " << params->value;
1332
1333 chromeos::system::InputDeviceSettings::Get()->SetTouchpadSensitivity(
1334 params->value);
1335 return RespondNow(NoArguments());
1336 }
1337
1338 ///////////////////////////////////////////////////////////////////////////////
1339 // AutotestPrivateSetTapToClickFunction
1340 ///////////////////////////////////////////////////////////////////////////////
1341
1342 AutotestPrivateSetTapToClickFunction::~AutotestPrivateSetTapToClickFunction() =
1343 default;
1344
Run()1345 ExtensionFunction::ResponseAction AutotestPrivateSetTapToClickFunction::Run() {
1346 std::unique_ptr<api::autotest_private::SetTapToClick::Params> params(
1347 api::autotest_private::SetTapToClick::Params::Create(*args_));
1348 EXTENSION_FUNCTION_VALIDATE(params.get());
1349 DVLOG(1) << "AutotestPrivateSetTapToClickFunction " << params->enabled;
1350
1351 chromeos::system::InputDeviceSettings::Get()->SetTapToClick(params->enabled);
1352 return RespondNow(NoArguments());
1353 }
1354
1355 ///////////////////////////////////////////////////////////////////////////////
1356 // AutotestPrivateSetThreeFingerClickFunction
1357 ///////////////////////////////////////////////////////////////////////////////
1358
1359 AutotestPrivateSetThreeFingerClickFunction::
1360 ~AutotestPrivateSetThreeFingerClickFunction() = default;
1361
1362 ExtensionFunction::ResponseAction
Run()1363 AutotestPrivateSetThreeFingerClickFunction::Run() {
1364 std::unique_ptr<api::autotest_private::SetThreeFingerClick::Params> params(
1365 api::autotest_private::SetThreeFingerClick::Params::Create(*args_));
1366 EXTENSION_FUNCTION_VALIDATE(params.get());
1367 DVLOG(1) << "AutotestPrivateSetThreeFingerClickFunction " << params->enabled;
1368
1369 chromeos::system::InputDeviceSettings::Get()->SetThreeFingerClick(
1370 params->enabled);
1371 return RespondNow(NoArguments());
1372 }
1373
1374 ///////////////////////////////////////////////////////////////////////////////
1375 // AutotestPrivateSetTapDraggingFunction
1376 ///////////////////////////////////////////////////////////////////////////////
1377
1378 AutotestPrivateSetTapDraggingFunction::
1379 ~AutotestPrivateSetTapDraggingFunction() = default;
1380
Run()1381 ExtensionFunction::ResponseAction AutotestPrivateSetTapDraggingFunction::Run() {
1382 std::unique_ptr<api::autotest_private::SetTapDragging::Params> params(
1383 api::autotest_private::SetTapDragging::Params::Create(*args_));
1384 EXTENSION_FUNCTION_VALIDATE(params.get());
1385 DVLOG(1) << "AutotestPrivateSetTapDraggingFunction " << params->enabled;
1386
1387 chromeos::system::InputDeviceSettings::Get()->SetTapDragging(params->enabled);
1388 return RespondNow(NoArguments());
1389 }
1390
1391 ///////////////////////////////////////////////////////////////////////////////
1392 // AutotestPrivateSetNaturalScrollFunction
1393 ///////////////////////////////////////////////////////////////////////////////
1394
1395 AutotestPrivateSetNaturalScrollFunction::
1396 ~AutotestPrivateSetNaturalScrollFunction() = default;
1397
1398 ExtensionFunction::ResponseAction
Run()1399 AutotestPrivateSetNaturalScrollFunction::Run() {
1400 std::unique_ptr<api::autotest_private::SetNaturalScroll::Params> params(
1401 api::autotest_private::SetNaturalScroll::Params::Create(*args_));
1402 EXTENSION_FUNCTION_VALIDATE(params.get());
1403 DVLOG(1) << "AutotestPrivateSetNaturalScrollFunction " << params->enabled;
1404
1405 chromeos::system::InputDeviceSettings::Get()->SetNaturalScroll(
1406 params->enabled);
1407 return RespondNow(NoArguments());
1408 }
1409
1410 ///////////////////////////////////////////////////////////////////////////////
1411 // AutotestPrivateSetMouseSensitivityFunction
1412 ///////////////////////////////////////////////////////////////////////////////
1413
1414 AutotestPrivateSetMouseSensitivityFunction::
1415 ~AutotestPrivateSetMouseSensitivityFunction() = default;
1416
1417 ExtensionFunction::ResponseAction
Run()1418 AutotestPrivateSetMouseSensitivityFunction::Run() {
1419 std::unique_ptr<api::autotest_private::SetMouseSensitivity::Params> params(
1420 api::autotest_private::SetMouseSensitivity::Params::Create(*args_));
1421 EXTENSION_FUNCTION_VALIDATE(params.get());
1422 DVLOG(1) << "AutotestPrivateSetMouseSensitivityFunction " << params->value;
1423
1424 chromeos::system::InputDeviceSettings::Get()->SetMouseSensitivity(
1425 params->value);
1426 return RespondNow(NoArguments());
1427 }
1428
1429 ///////////////////////////////////////////////////////////////////////////////
1430 // AutotestPrivateSetPrimaryButtonRightFunction
1431 ///////////////////////////////////////////////////////////////////////////////
1432
1433 AutotestPrivateSetPrimaryButtonRightFunction::
1434 ~AutotestPrivateSetPrimaryButtonRightFunction() = default;
1435
1436 ExtensionFunction::ResponseAction
Run()1437 AutotestPrivateSetPrimaryButtonRightFunction::Run() {
1438 std::unique_ptr<api::autotest_private::SetPrimaryButtonRight::Params> params(
1439 api::autotest_private::SetPrimaryButtonRight::Params::Create(*args_));
1440 EXTENSION_FUNCTION_VALIDATE(params.get());
1441 DVLOG(1) << "AutotestPrivateSetPrimaryButtonRightFunction " << params->right;
1442
1443 chromeos::system::InputDeviceSettings::Get()->SetPrimaryButtonRight(
1444 params->right);
1445 return RespondNow(NoArguments());
1446 }
1447
1448 ///////////////////////////////////////////////////////////////////////////////
1449 // AutotestPrivateSetMouseReverseScrollFunction
1450 ///////////////////////////////////////////////////////////////////////////////
1451
1452 AutotestPrivateSetMouseReverseScrollFunction::
1453 ~AutotestPrivateSetMouseReverseScrollFunction() = default;
1454
1455 ExtensionFunction::ResponseAction
Run()1456 AutotestPrivateSetMouseReverseScrollFunction::Run() {
1457 std::unique_ptr<api::autotest_private::SetMouseReverseScroll::Params> params(
1458 api::autotest_private::SetMouseReverseScroll::Params::Create(*args_));
1459 EXTENSION_FUNCTION_VALIDATE(params.get());
1460 DVLOG(1) << "AutotestPrivateSetMouseReverseScrollFunction "
1461 << params->enabled;
1462
1463 chromeos::system::InputDeviceSettings::Get()->SetMouseReverseScroll(
1464 params->enabled);
1465 return RespondNow(NoArguments());
1466 }
1467
1468 ///////////////////////////////////////////////////////////////////////////////
1469 // AutotestPrivateGetVisibleNotificationsFunction
1470 ///////////////////////////////////////////////////////////////////////////////
1471
1472 AutotestPrivateGetVisibleNotificationsFunction::
1473 AutotestPrivateGetVisibleNotificationsFunction() = default;
1474 AutotestPrivateGetVisibleNotificationsFunction::
1475 ~AutotestPrivateGetVisibleNotificationsFunction() = default;
1476
1477 ExtensionFunction::ResponseAction
Run()1478 AutotestPrivateGetVisibleNotificationsFunction::Run() {
1479 DVLOG(1) << "AutotestPrivateGetVisibleNotificationsFunction";
1480
1481 message_center::NotificationList::Notifications notification_set =
1482 message_center::MessageCenter::Get()->GetVisibleNotifications();
1483 auto values = std::make_unique<base::ListValue>();
1484 for (auto* notification : notification_set)
1485 values->Append(MakeDictionaryFromNotification(*notification));
1486 return RespondNow(
1487 OneArgument(base::Value::FromUniquePtrValue(std::move(values))));
1488 }
1489
1490 ///////////////////////////////////////////////////////////////////////////////
1491 // AutotestPrivateRemoveAllNotificationsFunction
1492 ///////////////////////////////////////////////////////////////////////////////
1493
1494 AutotestPrivateRemoveAllNotificationsFunction::
1495 AutotestPrivateRemoveAllNotificationsFunction() = default;
1496 AutotestPrivateRemoveAllNotificationsFunction::
1497 ~AutotestPrivateRemoveAllNotificationsFunction() = default;
1498
1499 ExtensionFunction::ResponseAction
Run()1500 AutotestPrivateRemoveAllNotificationsFunction::Run() {
1501 DVLOG(1) << "AutotestPrivateRemoveAllNotificationsFunction";
1502
1503 message_center::MessageCenter::Get()->RemoveAllNotifications(
1504 /*by_user=*/false, message_center::MessageCenter::RemoveType::ALL);
1505 return RespondNow(NoArguments());
1506 }
1507
1508 ///////////////////////////////////////////////////////////////////////////////
1509 // AutotestPrivateGetArcStartTimeFunction
1510 ///////////////////////////////////////////////////////////////////////////////
1511
1512 AutotestPrivateGetArcStartTimeFunction::
1513 ~AutotestPrivateGetArcStartTimeFunction() = default;
1514
1515 ExtensionFunction::ResponseAction
Run()1516 AutotestPrivateGetArcStartTimeFunction::Run() {
1517 DVLOG(1) << "AutotestPrivateGetArcStartTimeFunction";
1518
1519 arc::ArcSessionManager* arc_session_manager = arc::ArcSessionManager::Get();
1520 if (!arc_session_manager)
1521 return RespondNow(Error("Could not find ARC session manager"));
1522
1523 double start_time =
1524 (arc_session_manager->arc_start_time() - base::TimeTicks())
1525 .InMillisecondsF();
1526 return RespondNow(OneArgument(base::Value(start_time)));
1527 }
1528
1529 ///////////////////////////////////////////////////////////////////////////////
1530 // AutotestPrivateGetArcStateFunction
1531 ///////////////////////////////////////////////////////////////////////////////
1532
1533 AutotestPrivateGetArcStateFunction::~AutotestPrivateGetArcStateFunction() =
1534 default;
1535
Run()1536 ExtensionFunction::ResponseAction AutotestPrivateGetArcStateFunction::Run() {
1537 DVLOG(1) << "AutotestPrivateGetArcStateFunction";
1538
1539 api::autotest_private::ArcState arc_state;
1540 Profile* const profile = Profile::FromBrowserContext(browser_context());
1541
1542 if (!arc::IsArcAllowedForProfile(profile))
1543 return RespondNow(Error("ARC is not available for the current user"));
1544
1545 arc_state.provisioned = arc::IsArcProvisioned(profile);
1546 arc_state.tos_needed = arc::IsArcTermsOfServiceNegotiationNeeded(profile);
1547 return RespondNow(
1548 OneArgument(base::Value::FromUniquePtrValue(arc_state.ToValue())));
1549 }
1550
1551 ///////////////////////////////////////////////////////////////////////////////
1552 // AutotestPrivateGetPlayStoreStateFunction
1553 ///////////////////////////////////////////////////////////////////////////////
1554
1555 AutotestPrivateGetPlayStoreStateFunction::
1556 ~AutotestPrivateGetPlayStoreStateFunction() = default;
1557
1558 ExtensionFunction::ResponseAction
Run()1559 AutotestPrivateGetPlayStoreStateFunction::Run() {
1560 DVLOG(1) << "AutotestPrivateGetPlayStoreStateFunction";
1561
1562 api::autotest_private::PlayStoreState play_store_state;
1563 play_store_state.allowed = false;
1564 Profile* profile = Profile::FromBrowserContext(browser_context());
1565 if (arc::IsArcAllowedForProfile(profile)) {
1566 play_store_state.allowed = true;
1567 play_store_state.enabled =
1568 std::make_unique<bool>(arc::IsArcPlayStoreEnabledForProfile(profile));
1569 play_store_state.managed = std::make_unique<bool>(
1570 arc::IsArcPlayStoreEnabledPreferenceManagedForProfile(profile));
1571 }
1572 return RespondNow(
1573 OneArgument(base::Value::FromUniquePtrValue(play_store_state.ToValue())));
1574 }
1575
1576 ///////////////////////////////////////////////////////////////////////////////
1577 // AutotestPrivateSetPlayStoreEnabledFunction
1578 ///////////////////////////////////////////////////////////////////////////////
1579
1580 AutotestPrivateSetPlayStoreEnabledFunction::
1581 ~AutotestPrivateSetPlayStoreEnabledFunction() = default;
1582
1583 ExtensionFunction::ResponseAction
Run()1584 AutotestPrivateSetPlayStoreEnabledFunction::Run() {
1585 std::unique_ptr<api::autotest_private::SetPlayStoreEnabled::Params> params(
1586 api::autotest_private::SetPlayStoreEnabled::Params::Create(*args_));
1587 EXTENSION_FUNCTION_VALIDATE(params);
1588 DVLOG(1) << "AutotestPrivateSetPlayStoreEnabledFunction " << params->enabled;
1589
1590 Profile* profile = Profile::FromBrowserContext(browser_context());
1591 if (arc::IsArcAllowedForProfile(profile)) {
1592 if (!arc::SetArcPlayStoreEnabledForProfile(profile, params->enabled)) {
1593 return RespondNow(
1594 Error("ARC enabled state cannot be changed for the current user"));
1595 }
1596 // kArcLocationServiceEnabled and kArcBackupRestoreEnabled are prefs that
1597 // set together with enabling ARC. That is why we set it here not using
1598 // SetWhitelistedPref. At this moment, we don't distinguish the actual
1599 // values and set kArcLocationServiceEnabled to true and leave
1600 // kArcBackupRestoreEnabled unmodified, which is acceptable for autotests
1601 // currently.
1602 profile->GetPrefs()->SetBoolean(arc::prefs::kArcLocationServiceEnabled,
1603 true);
1604 return RespondNow(NoArguments());
1605 } else {
1606 return RespondNow(Error("ARC is not available for the current user"));
1607 }
1608 }
1609
1610 ///////////////////////////////////////////////////////////////////////////////
1611 // AutotestPrivateIsAppShownFunction
1612 ///////////////////////////////////////////////////////////////////////////////
1613
1614 AutotestPrivateIsAppShownFunction::~AutotestPrivateIsAppShownFunction() =
1615 default;
1616
Run()1617 ExtensionFunction::ResponseAction AutotestPrivateIsAppShownFunction::Run() {
1618 std::unique_ptr<api::autotest_private::IsAppShown::Params> params(
1619 api::autotest_private::IsAppShown::Params::Create(*args_));
1620 EXTENSION_FUNCTION_VALIDATE(params);
1621 DVLOG(1) << "AutotestPrivateIsAppShownFunction " << params->app_id;
1622
1623 ChromeLauncherController* const controller =
1624 ChromeLauncherController::instance();
1625 if (!controller)
1626 return RespondNow(Error("Controller not available"));
1627
1628 const ash::ShelfItem* item =
1629 controller->GetItem(ash::ShelfID(params->app_id));
1630 // App must be running and not pending in deferred launch.
1631 const bool window_attached =
1632 item && item->status == ash::ShelfItemStatus::STATUS_RUNNING &&
1633 !controller->GetShelfSpinnerController()->HasApp(params->app_id);
1634 return RespondNow(OneArgument(base::Value(window_attached)));
1635 }
1636
1637 ///////////////////////////////////////////////////////////////////////////////
1638 // AutotestPrivateIsAppShownFunction
1639 ///////////////////////////////////////////////////////////////////////////////
1640
1641 AutotestPrivateIsArcProvisionedFunction::
1642 ~AutotestPrivateIsArcProvisionedFunction() = default;
1643
1644 ExtensionFunction::ResponseAction
Run()1645 AutotestPrivateIsArcProvisionedFunction::Run() {
1646 DVLOG(1) << "AutotestPrivateIsArcProvisionedFunction";
1647 return RespondNow(OneArgument(base::Value(
1648 arc::IsArcProvisioned(Profile::FromBrowserContext(browser_context())))));
1649 }
1650
1651 ///////////////////////////////////////////////////////////////////////////////
1652 // AutotestPrivateGetArcPackageFunction
1653 ///////////////////////////////////////////////////////////////////////////////
1654
1655 AutotestPrivateGetArcAppFunction::~AutotestPrivateGetArcAppFunction() = default;
1656
Run()1657 ExtensionFunction::ResponseAction AutotestPrivateGetArcAppFunction::Run() {
1658 std::unique_ptr<api::autotest_private::GetArcApp::Params> params(
1659 api::autotest_private::GetArcApp::Params::Create(*args_));
1660 EXTENSION_FUNCTION_VALIDATE(params);
1661 DVLOG(1) << "AutotestPrivateGetArcAppFunction " << params->app_id;
1662
1663 ArcAppListPrefs* const prefs =
1664 ArcAppListPrefs::Get(Profile::FromBrowserContext(browser_context()));
1665 if (!prefs)
1666 return RespondNow(Error("ARC is not available"));
1667
1668 std::unique_ptr<base::DictionaryValue> app_value;
1669 {
1670 const std::unique_ptr<ArcAppListPrefs::AppInfo> app_info =
1671 prefs->GetApp(params->app_id);
1672 if (!app_info)
1673 return RespondNow(Error("App is not available"));
1674
1675 app_value = std::make_unique<base::DictionaryValue>();
1676
1677 app_value->SetKey("name", base::Value(std::move(app_info->name)));
1678 app_value->SetKey("packageName",
1679 base::Value(std::move(app_info->package_name)));
1680 app_value->SetKey("activity", base::Value(std::move(app_info->activity)));
1681 app_value->SetKey("intentUri",
1682 base::Value(std::move(app_info->intent_uri)));
1683 app_value->SetKey("iconResourceId",
1684 base::Value(std::move(app_info->icon_resource_id)));
1685 app_value->SetKey("lastLaunchTime",
1686 base::Value(app_info->last_launch_time.ToJsTime()));
1687 app_value->SetKey("installTime",
1688 base::Value(app_info->install_time.ToJsTime()));
1689 app_value->SetKey("sticky", base::Value(app_info->sticky));
1690 app_value->SetKey("notificationsEnabled",
1691 base::Value(app_info->notifications_enabled));
1692 app_value->SetKey("ready", base::Value(app_info->ready));
1693 app_value->SetKey("suspended", base::Value(app_info->suspended));
1694 app_value->SetKey("showInLauncher",
1695 base::Value(app_info->show_in_launcher));
1696 app_value->SetKey("shortcut", base::Value(app_info->shortcut));
1697 app_value->SetKey("launchable", base::Value(app_info->launchable));
1698 }
1699
1700 return RespondNow(
1701 OneArgument(base::Value::FromUniquePtrValue(std::move(app_value))));
1702 }
1703
1704 ///////////////////////////////////////////////////////////////////////////////
1705 // AutotestPrivateGetArcPackageFunction
1706 ///////////////////////////////////////////////////////////////////////////////
1707
1708 AutotestPrivateGetArcPackageFunction::~AutotestPrivateGetArcPackageFunction() =
1709 default;
1710
Run()1711 ExtensionFunction::ResponseAction AutotestPrivateGetArcPackageFunction::Run() {
1712 std::unique_ptr<api::autotest_private::GetArcPackage::Params> params(
1713 api::autotest_private::GetArcPackage::Params::Create(*args_));
1714 EXTENSION_FUNCTION_VALIDATE(params);
1715 DVLOG(1) << "AutotestPrivateGetArcPackageFunction " << params->package_name;
1716
1717 ArcAppListPrefs* const prefs =
1718 ArcAppListPrefs::Get(Profile::FromBrowserContext(browser_context()));
1719 if (!prefs)
1720 return RespondNow(Error("ARC is not available"));
1721
1722 std::unique_ptr<base::DictionaryValue> package_value;
1723 {
1724 const std::unique_ptr<ArcAppListPrefs::PackageInfo> package_info =
1725 prefs->GetPackage(params->package_name);
1726 if (!package_info)
1727 return RespondNow(Error("Package is not available"));
1728
1729 package_value = std::make_unique<base::DictionaryValue>();
1730 package_value->SetKey("packageName",
1731 base::Value(std::move(package_info->package_name)));
1732 package_value->SetKey("packageVersion",
1733 base::Value(package_info->package_version));
1734 package_value->SetKey("lastBackupAndroidId",
1735 base::Value(base::NumberToString(
1736 package_info->last_backup_android_id)));
1737 package_value->SetKey("lastBackupTime",
1738 base::Value(base::Time::FromDeltaSinceWindowsEpoch(
1739 base::TimeDelta::FromMicroseconds(
1740 package_info->last_backup_time))
1741 .ToJsTime()));
1742 package_value->SetKey("shouldSync", base::Value(package_info->should_sync));
1743 package_value->SetKey("system", base::Value(package_info->system));
1744 package_value->SetKey("vpnProvider",
1745 base::Value(package_info->vpn_provider));
1746 }
1747 return RespondNow(
1748 OneArgument(base::Value::FromUniquePtrValue(std::move(package_value))));
1749 }
1750
1751 ///////////////////////////////////////////////////////////////////////////////
1752 // AutotestPrivateWaitForSystemWebAppsInstallFunction
1753 //////////////////////////////////////////////////////////////////////////////
1754
1755 AutotestPrivateWaitForSystemWebAppsInstallFunction::
1756 AutotestPrivateWaitForSystemWebAppsInstallFunction() = default;
1757
1758 AutotestPrivateWaitForSystemWebAppsInstallFunction::
1759 ~AutotestPrivateWaitForSystemWebAppsInstallFunction() = default;
1760
1761 ExtensionFunction::ResponseAction
Run()1762 AutotestPrivateWaitForSystemWebAppsInstallFunction::Run() {
1763 Profile* profile = Profile::FromBrowserContext(browser_context());
1764 web_app::WebAppProviderBase* provider =
1765 web_app::WebAppProviderBase::GetProviderBase(profile);
1766
1767 if (!provider)
1768 return RespondNow(Error("Web Apps are not available for profile."));
1769
1770 provider->system_web_app_manager().on_apps_synchronized().Post(
1771 FROM_HERE,
1772 base::BindOnce(
1773 &AutotestPrivateWaitForSystemWebAppsInstallFunction::Respond, this,
1774 NoArguments()));
1775 return RespondLater();
1776 }
1777
1778 ///////////////////////////////////////////////////////////////////////////////
1779 // AutotestPrivateGetRegisteredSystemWebAppsFunction
1780 //////////////////////////////////////////////////////////////////////////////
1781
1782 AutotestPrivateGetRegisteredSystemWebAppsFunction::
1783 AutotestPrivateGetRegisteredSystemWebAppsFunction() = default;
1784
1785 AutotestPrivateGetRegisteredSystemWebAppsFunction::
1786 ~AutotestPrivateGetRegisteredSystemWebAppsFunction() = default;
1787
1788 ExtensionFunction::ResponseAction
Run()1789 AutotestPrivateGetRegisteredSystemWebAppsFunction::Run() {
1790 Profile* profile = Profile::FromBrowserContext(browser_context());
1791 web_app::WebAppProviderBase* provider =
1792 web_app::WebAppProviderBase::GetProviderBase(profile);
1793
1794 if (!provider)
1795 return RespondNow(Error("Web Apps are not available for profile."));
1796
1797 std::vector<api::autotest_private::SystemApp> result;
1798
1799 for (const auto& type_and_info :
1800 provider->system_web_app_manager().GetRegisteredSystemAppsForTesting()) {
1801 api::autotest_private::SystemApp system_app;
1802 web_app::SystemAppInfo info = type_and_info.second;
1803 system_app.internal_name = info.internal_name;
1804 system_app.url = info.install_url.GetOrigin().spec();
1805 result.push_back(std::move(system_app));
1806 }
1807
1808 return RespondNow(ArgumentList(
1809 api::autotest_private::GetRegisteredSystemWebApps::Results::Create(
1810 result)));
1811 }
1812
1813 ///////////////////////////////////////////////////////////////////////////////
1814 // AutotestPrivateLaunchArcIntentFunction
1815 ///////////////////////////////////////////////////////////////////////////////
1816
1817 AutotestPrivateLaunchArcAppFunction::~AutotestPrivateLaunchArcAppFunction() =
1818 default;
1819
Run()1820 ExtensionFunction::ResponseAction AutotestPrivateLaunchArcAppFunction::Run() {
1821 std::unique_ptr<api::autotest_private::LaunchArcApp::Params> params(
1822 api::autotest_private::LaunchArcApp::Params::Create(*args_));
1823 EXTENSION_FUNCTION_VALIDATE(params);
1824 DVLOG(1) << "AutotestPrivateLaunchArcIntentFunction " << params->app_id << "/"
1825 << params->intent;
1826
1827 base::Optional<std::string> launch_intent;
1828 if (!params->intent.empty())
1829 launch_intent = params->intent;
1830 const bool result = arc::LaunchAppWithIntent(
1831 Profile::FromBrowserContext(browser_context()), params->app_id,
1832 launch_intent, 0 /* event_flags */,
1833 arc::UserInteractionType::APP_STARTED_FROM_EXTENSION_API,
1834 0 /* display_id */);
1835 return RespondNow(OneArgument(base::Value(result)));
1836 }
1837
1838 ///////////////////////////////////////////////////////////////////////////////
1839 // AutotestPrivateLaunchAppFunction
1840 ///////////////////////////////////////////////////////////////////////////////
1841
1842 AutotestPrivateLaunchAppFunction::~AutotestPrivateLaunchAppFunction() = default;
1843
Run()1844 ExtensionFunction::ResponseAction AutotestPrivateLaunchAppFunction::Run() {
1845 std::unique_ptr<api::autotest_private::LaunchApp::Params> params(
1846 api::autotest_private::LaunchApp::Params::Create(*args_));
1847 EXTENSION_FUNCTION_VALIDATE(params);
1848 DVLOG(1) << "AutotestPrivateLaunchAppFunction " << params->app_id;
1849
1850 ChromeLauncherController* const controller =
1851 ChromeLauncherController::instance();
1852 if (!controller)
1853 return RespondNow(Error("Controller not available"));
1854 controller->LaunchApp(ash::ShelfID(params->app_id),
1855 ash::ShelfLaunchSource::LAUNCH_FROM_UNKNOWN,
1856 0, /* event_flags */
1857 display::Screen::GetScreen()->GetPrimaryDisplay().id());
1858 return RespondNow(NoArguments());
1859 }
1860
1861 ///////////////////////////////////////////////////////////////////////////////
1862 // AutotestPrivateLaunchSystemWebAppFunction
1863 ///////////////////////////////////////////////////////////////////////////////
1864
1865 AutotestPrivateLaunchSystemWebAppFunction::
1866 ~AutotestPrivateLaunchSystemWebAppFunction() = default;
1867
1868 ExtensionFunction::ResponseAction
Run()1869 AutotestPrivateLaunchSystemWebAppFunction::Run() {
1870 std::unique_ptr<api::autotest_private::LaunchSystemWebApp::Params> params(
1871 api::autotest_private::LaunchSystemWebApp::Params::Create(*args_));
1872 EXTENSION_FUNCTION_VALIDATE(params);
1873 DVLOG(1) << "AutotestPrivateLaunchSystemWebAppFunction name: "
1874 << params->app_name << " url: " << params->url;
1875
1876 Profile* profile = Profile::FromBrowserContext(browser_context());
1877 auto* provider = web_app::WebAppProvider::Get(profile);
1878 if (!provider)
1879 return RespondNow(Error("Web Apps not enabled for profile."));
1880
1881 base::Optional<web_app::SystemAppType> app_type;
1882 for (const auto& type_and_info :
1883 provider->system_web_app_manager().GetRegisteredSystemAppsForTesting()) {
1884 if (type_and_info.second.internal_name == params->app_name) {
1885 app_type = type_and_info.first;
1886 break;
1887 }
1888 }
1889 if (!app_type.has_value())
1890 return RespondNow(Error("No mapped system web app found"));
1891
1892 auto* browser =
1893 web_app::LaunchSystemWebApp(profile, *app_type, GURL(params->url));
1894 if (!browser)
1895 return RespondNow(Error("Failed to launch system web app"));
1896 return RespondNow(NoArguments());
1897 }
1898
1899 ///////////////////////////////////////////////////////////////////////////////
1900 // AutotestPrivateCloseAppFunction
1901 ///////////////////////////////////////////////////////////////////////////////
1902
1903 AutotestPrivateCloseAppFunction::~AutotestPrivateCloseAppFunction() = default;
1904
Run()1905 ExtensionFunction::ResponseAction AutotestPrivateCloseAppFunction::Run() {
1906 std::unique_ptr<api::autotest_private::CloseApp::Params> params(
1907 api::autotest_private::CloseApp::Params::Create(*args_));
1908 EXTENSION_FUNCTION_VALIDATE(params);
1909 DVLOG(1) << "AutotestPrivateCloseAppFunction " << params->app_id;
1910
1911 ChromeLauncherController* const controller =
1912 ChromeLauncherController::instance();
1913 if (!controller)
1914 return RespondNow(Error("Controller not available"));
1915 controller->Close(ash::ShelfID(params->app_id));
1916 return RespondNow(NoArguments());
1917 }
1918
1919 ///////////////////////////////////////////////////////////////////////////////
1920 // AutotestPrivateGetClipboardTextDataFunction
1921 ///////////////////////////////////////////////////////////////////////////////
1922
1923 AutotestPrivateGetClipboardTextDataFunction::
1924 ~AutotestPrivateGetClipboardTextDataFunction() = default;
1925
1926 ExtensionFunction::ResponseAction
Run()1927 AutotestPrivateGetClipboardTextDataFunction::Run() {
1928 base::string16 data;
1929 // This clipboard data read is initiated an extension API, then the user
1930 // shouldn't see a notification if the clipboard is restricted by the rules of
1931 // data leak prevention policy.
1932 ui::DataTransferEndpoint data_dst = ui::DataTransferEndpoint(
1933 ui::EndpointType::kDefault, /*notify_if_restricted=*/false);
1934 ui::Clipboard::GetForCurrentThread()->ReadText(
1935 ui::ClipboardBuffer::kCopyPaste, &data_dst, &data);
1936 return RespondNow(OneArgument(base::Value(data)));
1937 }
1938
1939 ///////////////////////////////////////////////////////////////////////////////
1940 // AutotestPrivateSetClipboardTextDataFunction
1941 ///////////////////////////////////////////////////////////////////////////////
1942
1943 AutotestPrivateSetClipboardTextDataFunction::
1944 ~AutotestPrivateSetClipboardTextDataFunction() = default;
1945
1946 ExtensionFunction::ResponseAction
Run()1947 AutotestPrivateSetClipboardTextDataFunction::Run() {
1948 std::unique_ptr<api::autotest_private::SetClipboardTextData::Params> params(
1949 api::autotest_private::SetClipboardTextData::Params::Create(*args_));
1950 EXTENSION_FUNCTION_VALIDATE(params);
1951
1952 const base::string16 data = base::UTF8ToUTF16(params->data);
1953 ui::ScopedClipboardWriter clipboard_writer(ui::ClipboardBuffer::kCopyPaste);
1954 clipboard_writer.WriteText(data);
1955
1956 return RespondNow(NoArguments());
1957 }
1958
1959 ///////////////////////////////////////////////////////////////////////////////
1960 // AutotestPrivateSetCrostiniEnabledFunction
1961 ///////////////////////////////////////////////////////////////////////////////
1962
1963 AutotestPrivateSetCrostiniEnabledFunction::
1964 ~AutotestPrivateSetCrostiniEnabledFunction() = default;
1965
1966 ExtensionFunction::ResponseAction
Run()1967 AutotestPrivateSetCrostiniEnabledFunction::Run() {
1968 std::unique_ptr<api::autotest_private::SetCrostiniEnabled::Params> params(
1969 api::autotest_private::SetCrostiniEnabled::Params::Create(*args_));
1970 EXTENSION_FUNCTION_VALIDATE(params);
1971 DVLOG(1) << "AutotestPrivateSetCrostiniEnabledFunction " << params->enabled;
1972
1973 Profile* profile = Profile::FromBrowserContext(browser_context());
1974 if (!crostini::CrostiniFeatures::Get()->IsUIAllowed(profile))
1975 return RespondNow(Error(kCrostiniNotAvailableForCurrentUserError));
1976
1977 // Set the preference to indicate Crostini is enabled/disabled.
1978 profile->GetPrefs()->SetBoolean(crostini::prefs::kCrostiniEnabled,
1979 params->enabled);
1980 // Set the flag to indicate we are in testing mode so that Chrome doesn't
1981 // try to start the VM/container itself.
1982 crostini::CrostiniManager* crostini_manager =
1983 crostini::CrostiniManager::GetForProfile(profile);
1984 crostini_manager->set_skip_restart_for_testing();
1985 return RespondNow(NoArguments());
1986 }
1987
1988 ///////////////////////////////////////////////////////////////////////////////
1989 // AutotestPrivateRunCrostiniInstallerFunction
1990 ///////////////////////////////////////////////////////////////////////////////
1991
1992 AutotestPrivateRunCrostiniInstallerFunction::
1993 ~AutotestPrivateRunCrostiniInstallerFunction() = default;
1994
1995 ExtensionFunction::ResponseAction
Run()1996 AutotestPrivateRunCrostiniInstallerFunction::Run() {
1997 DVLOG(1) << "AutotestPrivateInstallCrostiniFunction";
1998
1999 Profile* profile = Profile::FromBrowserContext(browser_context());
2000 if (!crostini::CrostiniFeatures::Get()->IsUIAllowed(profile))
2001 return RespondNow(Error(kCrostiniNotAvailableForCurrentUserError));
2002
2003 // Run GUI installer which will install crostini vm / container and
2004 // start terminal app on completion. After starting the installer,
2005 // we call RestartCrostini and we will be put in the pending restarters
2006 // queue and be notified on success/otherwise of installation.
2007 chromeos::CrostiniInstallerDialog::Show(
2008 profile, base::BindOnce([](chromeos::CrostiniInstallerUI* installer_ui) {
2009 installer_ui->ClickInstallForTesting();
2010 }));
2011 crostini::CrostiniManager::GetForProfile(profile)->RestartCrostini(
2012 crostini::ContainerId::GetDefault(),
2013 base::BindOnce(
2014 &AutotestPrivateRunCrostiniInstallerFunction::CrostiniRestarted,
2015 this));
2016
2017 return RespondLater();
2018 }
2019
CrostiniRestarted(crostini::CrostiniResult result)2020 void AutotestPrivateRunCrostiniInstallerFunction::CrostiniRestarted(
2021 crostini::CrostiniResult result) {
2022 if (result == crostini::CrostiniResult::SUCCESS) {
2023 Respond(NoArguments());
2024 } else {
2025 Respond(Error("Error installing crostini"));
2026 }
2027 }
2028
2029 ///////////////////////////////////////////////////////////////////////////////
2030 // AutotestPrivateRunCrostiniUninstallerFunction
2031 ///////////////////////////////////////////////////////////////////////////////
2032
2033 AutotestPrivateRunCrostiniUninstallerFunction::
2034 ~AutotestPrivateRunCrostiniUninstallerFunction() = default;
2035
2036 ExtensionFunction::ResponseAction
Run()2037 AutotestPrivateRunCrostiniUninstallerFunction::Run() {
2038 DVLOG(1) << "AutotestPrivateRunCrostiniUninstallerFunction";
2039
2040 Profile* profile = Profile::FromBrowserContext(browser_context());
2041 if (!crostini::CrostiniFeatures::Get()->IsUIAllowed(profile))
2042 return RespondNow(Error(kCrostiniNotAvailableForCurrentUserError));
2043
2044 // Run GUI uninstaller which will remove crostini vm / container. We then
2045 // receive the callback with the result when that is complete.
2046 crostini::CrostiniManager::GetForProfile(profile)->AddRemoveCrostiniCallback(
2047 base::BindOnce(
2048 &AutotestPrivateRunCrostiniUninstallerFunction::CrostiniRemoved,
2049 this));
2050 CrostiniUninstallerView::Show(profile);
2051 CrostiniUninstallerView::GetActiveViewForTesting()->Accept();
2052 return RespondLater();
2053 }
2054
CrostiniRemoved(crostini::CrostiniResult result)2055 void AutotestPrivateRunCrostiniUninstallerFunction::CrostiniRemoved(
2056 crostini::CrostiniResult result) {
2057 if (result == crostini::CrostiniResult::SUCCESS)
2058 Respond(NoArguments());
2059 else
2060 Respond(Error("Error uninstalling crostini"));
2061 }
2062
2063 ///////////////////////////////////////////////////////////////////////////////
2064 // AutotestPrivateExportCrostiniFunction
2065 ///////////////////////////////////////////////////////////////////////////////
2066
2067 AutotestPrivateExportCrostiniFunction::
2068 ~AutotestPrivateExportCrostiniFunction() = default;
2069
Run()2070 ExtensionFunction::ResponseAction AutotestPrivateExportCrostiniFunction::Run() {
2071 std::unique_ptr<api::autotest_private::ExportCrostini::Params> params(
2072 api::autotest_private::ExportCrostini::Params::Create(*args_));
2073 EXTENSION_FUNCTION_VALIDATE(params);
2074 DVLOG(1) << "AutotestPrivateExportCrostiniFunction " << params->path;
2075
2076 Profile* profile = Profile::FromBrowserContext(browser_context());
2077 if (!crostini::CrostiniFeatures::Get()->IsUIAllowed(profile)) {
2078 return RespondNow(Error(kCrostiniNotAvailableForCurrentUserError));
2079 }
2080
2081 base::FilePath path(params->path);
2082 if (path.ReferencesParent()) {
2083 return RespondNow(Error("Invalid export path must not reference parent"));
2084 }
2085
2086 crostini::CrostiniExportImport::GetForProfile(profile)->ExportContainer(
2087 crostini::ContainerId::GetDefault(),
2088 file_manager::util::GetDownloadsFolderForProfile(profile).Append(path),
2089 base::BindOnce(&AutotestPrivateExportCrostiniFunction::CrostiniExported,
2090 this));
2091
2092 return RespondLater();
2093 }
2094
CrostiniExported(crostini::CrostiniResult result)2095 void AutotestPrivateExportCrostiniFunction::CrostiniExported(
2096 crostini::CrostiniResult result) {
2097 if (result == crostini::CrostiniResult::SUCCESS) {
2098 Respond(NoArguments());
2099 } else {
2100 Respond(Error("Error exporting crostini"));
2101 }
2102 }
2103
2104 ///////////////////////////////////////////////////////////////////////////////
2105 // AutotestPrivateImportCrostiniFunction
2106 ///////////////////////////////////////////////////////////////////////////////
2107
2108 AutotestPrivateImportCrostiniFunction::
2109 ~AutotestPrivateImportCrostiniFunction() = default;
2110
Run()2111 ExtensionFunction::ResponseAction AutotestPrivateImportCrostiniFunction::Run() {
2112 std::unique_ptr<api::autotest_private::ImportCrostini::Params> params(
2113 api::autotest_private::ImportCrostini::Params::Create(*args_));
2114 EXTENSION_FUNCTION_VALIDATE(params);
2115 DVLOG(1) << "AutotestPrivateImportCrostiniFunction " << params->path;
2116
2117 Profile* profile = Profile::FromBrowserContext(browser_context());
2118 if (!crostini::CrostiniFeatures::Get()->IsUIAllowed(profile))
2119 return RespondNow(Error(kCrostiniNotAvailableForCurrentUserError));
2120
2121 base::FilePath path(params->path);
2122 if (path.ReferencesParent()) {
2123 return RespondNow(Error("Invalid import path must not reference parent"));
2124 }
2125 crostini::CrostiniExportImport::GetForProfile(profile)->ImportContainer(
2126 crostini::ContainerId::GetDefault(),
2127 file_manager::util::GetDownloadsFolderForProfile(profile).Append(path),
2128 base::BindOnce(&AutotestPrivateImportCrostiniFunction::CrostiniImported,
2129 this));
2130
2131 return RespondLater();
2132 }
2133
CrostiniImported(crostini::CrostiniResult result)2134 void AutotestPrivateImportCrostiniFunction::CrostiniImported(
2135 crostini::CrostiniResult result) {
2136 if (result == crostini::CrostiniResult::SUCCESS) {
2137 Respond(NoArguments());
2138 } else {
2139 Respond(Error("Error importing crostini"));
2140 }
2141 }
2142
2143 ///////////////////////////////////////////////////////////////////////////////
2144 // AutotestPrivateSetPluginVMPolicyFunction
2145 ///////////////////////////////////////////////////////////////////////////////
2146
2147 AutotestPrivateSetPluginVMPolicyFunction::
2148 ~AutotestPrivateSetPluginVMPolicyFunction() = default;
2149
2150 ExtensionFunction::ResponseAction
Run()2151 AutotestPrivateSetPluginVMPolicyFunction::Run() {
2152 std::unique_ptr<api::autotest_private::SetPluginVMPolicy::Params> params(
2153 api::autotest_private::SetPluginVMPolicy::Params::Create(*args_));
2154 EXTENSION_FUNCTION_VALIDATE(params);
2155 DVLOG(1) << "AutotestPrivateSetPluginVMPolicyFunction " << params->image_url
2156 << ", " << params->image_hash << ", " << params->license_key;
2157
2158 Profile* profile = Profile::FromBrowserContext(browser_context());
2159 plugin_vm::SetFakePluginVmPolicy(profile, params->image_url,
2160 params->image_hash, params->license_key);
2161
2162 return RespondNow(NoArguments());
2163 }
2164
2165 ///////////////////////////////////////////////////////////////////////////////
2166 // AutotestPrivateShowPluginVMInstallerFunction
2167 ///////////////////////////////////////////////////////////////////////////////
2168
2169 AutotestPrivateShowPluginVMInstallerFunction::
2170 ~AutotestPrivateShowPluginVMInstallerFunction() = default;
2171
2172 ExtensionFunction::ResponseAction
Run()2173 AutotestPrivateShowPluginVMInstallerFunction::Run() {
2174 DVLOG(1) << "AutotestPrivateShowPluginVMInstallerFunction";
2175
2176 Profile* profile = Profile::FromBrowserContext(browser_context());
2177 plugin_vm::PluginVmInstallerFactory::GetForProfile(profile)
2178 ->SetFreeDiskSpaceForTesting(
2179 plugin_vm::PluginVmInstallerFactory::GetForProfile(profile)
2180 ->RequiredFreeDiskSpace());
2181 plugin_vm::ShowPluginVmInstallerView(profile);
2182
2183 return RespondNow(NoArguments());
2184 }
2185
2186 ///////////////////////////////////////////////////////////////////////////////
2187 // AutotestPrivateRegisterComponentFunction
2188 ///////////////////////////////////////////////////////////////////////////////
2189
2190 AutotestPrivateRegisterComponentFunction::
2191 ~AutotestPrivateRegisterComponentFunction() = default;
2192
2193 ExtensionFunction::ResponseAction
Run()2194 AutotestPrivateRegisterComponentFunction::Run() {
2195 std::unique_ptr<api::autotest_private::RegisterComponent::Params> params(
2196 api::autotest_private::RegisterComponent::Params::Create(*args_));
2197 EXTENSION_FUNCTION_VALIDATE(params);
2198 DVLOG(1) << "AutotestPrivateRegisterComponentFunction " << params->name
2199 << ", " << params->path;
2200
2201 g_browser_process->platform_part()
2202 ->cros_component_manager()
2203 ->RegisterCompatiblePath(params->name, base::FilePath(params->path));
2204
2205 return RespondNow(NoArguments());
2206 }
2207
2208 ///////////////////////////////////////////////////////////////////////////////
2209 // AutotestPrivateTakeScreenshotFunction
2210 ///////////////////////////////////////////////////////////////////////////////
2211
2212 AutotestPrivateTakeScreenshotFunction::
2213 ~AutotestPrivateTakeScreenshotFunction() = default;
2214
Run()2215 ExtensionFunction::ResponseAction AutotestPrivateTakeScreenshotFunction::Run() {
2216 DVLOG(1) << "AutotestPrivateTakeScreenshotFunction";
2217 auto grabber = std::make_unique<ui::ScreenshotGrabber>();
2218 // TODO(mash): Fix for mash, http://crbug.com/557397
2219 aura::Window* primary_root = ash::Shell::GetPrimaryRootWindow();
2220 // Pass the ScreenshotGrabber to the callback so that it stays alive for the
2221 // duration of the operation, it'll then get deallocated when the callback
2222 // completes.
2223 grabber->TakeScreenshot(
2224 primary_root, primary_root->bounds(),
2225 base::BindOnce(&AutotestPrivateTakeScreenshotFunction::ScreenshotTaken,
2226 this, std::move(grabber)));
2227 return RespondLater();
2228 }
2229
ScreenshotTaken(std::unique_ptr<ui::ScreenshotGrabber> grabber,ui::ScreenshotResult screenshot_result,scoped_refptr<base::RefCountedMemory> png_data)2230 void AutotestPrivateTakeScreenshotFunction::ScreenshotTaken(
2231 std::unique_ptr<ui::ScreenshotGrabber> grabber,
2232 ui::ScreenshotResult screenshot_result,
2233 scoped_refptr<base::RefCountedMemory> png_data) {
2234 if (screenshot_result != ui::ScreenshotResult::SUCCESS) {
2235 return Respond(Error(base::StrCat(
2236 {"Error taking screenshot ",
2237 base::NumberToString(static_cast<int>(screenshot_result))})));
2238 }
2239 Respond(OneArgument(base::Value(GetPngDataAsString(png_data))));
2240 }
2241
2242 ///////////////////////////////////////////////////////////////////////////////
2243 // AutotestPrivateTakeScreenshotForDisplayFunction
2244 ///////////////////////////////////////////////////////////////////////////////
2245 AutotestPrivateTakeScreenshotForDisplayFunction::
2246 ~AutotestPrivateTakeScreenshotForDisplayFunction() = default;
2247
2248 ExtensionFunction::ResponseAction
Run()2249 AutotestPrivateTakeScreenshotForDisplayFunction::Run() {
2250 std::unique_ptr<api::autotest_private::TakeScreenshotForDisplay::Params>
2251 params(api::autotest_private::TakeScreenshotForDisplay::Params::Create(
2252 *args_));
2253 EXTENSION_FUNCTION_VALIDATE(params);
2254 DVLOG(1) << "AutotestPrivateTakeScreenshotForDisplayFunction "
2255 << params->display_id;
2256 int64_t target_display_id;
2257 base::StringToInt64(params->display_id, &target_display_id);
2258 auto grabber = std::make_unique<ui::ScreenshotGrabber>();
2259
2260 for (auto* const window : ash::Shell::GetAllRootWindows()) {
2261 const int64_t display_id =
2262 display::Screen::GetScreen()->GetDisplayNearestWindow(window).id();
2263 if (display_id == target_display_id) {
2264 grabber->TakeScreenshot(
2265 window, window->bounds(),
2266 base::BindOnce(
2267 &AutotestPrivateTakeScreenshotForDisplayFunction::ScreenshotTaken,
2268 this, std::move(grabber)));
2269 return RespondLater();
2270 }
2271 }
2272 return RespondNow(Error(base::StrCat(
2273 {"Error taking screenshot for display ", params->display_id})));
2274 }
2275
ScreenshotTaken(std::unique_ptr<ui::ScreenshotGrabber> grabber,ui::ScreenshotResult screenshot_result,scoped_refptr<base::RefCountedMemory> png_data)2276 void AutotestPrivateTakeScreenshotForDisplayFunction::ScreenshotTaken(
2277 std::unique_ptr<ui::ScreenshotGrabber> grabber,
2278 ui::ScreenshotResult screenshot_result,
2279 scoped_refptr<base::RefCountedMemory> png_data) {
2280 if (screenshot_result != ui::ScreenshotResult::SUCCESS) {
2281 return Respond(Error(base::StrCat(
2282 {"Error taking screenshot ",
2283 base::NumberToString(static_cast<int>(screenshot_result))})));
2284 }
2285 Respond(OneArgument(base::Value(GetPngDataAsString(png_data))));
2286 }
2287
2288 ///////////////////////////////////////////////////////////////////////////////
2289 // AutotestPrivateGetPrinterListFunction
2290 ///////////////////////////////////////////////////////////////////////////////
2291
AutotestPrivateGetPrinterListFunction()2292 AutotestPrivateGetPrinterListFunction::AutotestPrivateGetPrinterListFunction()
2293 : results_(std::make_unique<base::Value>(base::Value::Type::LIST)) {}
2294
2295 AutotestPrivateGetPrinterListFunction::
~AutotestPrivateGetPrinterListFunction()2296 ~AutotestPrivateGetPrinterListFunction() {
2297 DCHECK(!printers_manager_);
2298 }
2299
Run()2300 ExtensionFunction::ResponseAction AutotestPrivateGetPrinterListFunction::Run() {
2301 // |printers_manager_| should be created on UI thread.
2302 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
2303
2304 DVLOG(1) << "AutotestPrivateGetPrinterListFunction";
2305
2306 Profile* profile = Profile::FromBrowserContext(browser_context());
2307 printers_manager_ = chromeos::CupsPrintersManager::Create(profile);
2308 printers_manager_->AddObserver(this);
2309
2310 // Set up a timer to finish waiting after 10 seconds
2311 timeout_timer_.Start(
2312 FROM_HERE, base::TimeDelta::FromSeconds(10),
2313 base::BindOnce(
2314 &AutotestPrivateGetPrinterListFunction::RespondWithTimeoutError,
2315 this));
2316
2317 return RespondLater();
2318 }
2319
DestroyPrintersManager()2320 void AutotestPrivateGetPrinterListFunction::DestroyPrintersManager() {
2321 // |printers_manager_| should be destroyed on UI thread.
2322 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
2323
2324 if (!printers_manager_)
2325 return;
2326
2327 printers_manager_->RemoveObserver(this);
2328 printers_manager_.reset();
2329 }
2330
RespondWithTimeoutError()2331 void AutotestPrivateGetPrinterListFunction::RespondWithTimeoutError() {
2332 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
2333
2334 if (did_respond())
2335 return;
2336
2337 DestroyPrintersManager();
2338 Respond(
2339 Error("Timeout occurred before Enterprise printers were initialized"));
2340 }
2341
RespondWithSuccess()2342 void AutotestPrivateGetPrinterListFunction::RespondWithSuccess() {
2343 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
2344
2345 if (did_respond())
2346 return;
2347
2348 timeout_timer_.AbandonAndStop();
2349 DestroyPrintersManager();
2350 Respond(OneArgument(base::Value::FromUniquePtrValue(std::move(results_))));
2351 }
2352
OnEnterprisePrintersInitialized()2353 void AutotestPrivateGetPrinterListFunction::OnEnterprisePrintersInitialized() {
2354 // |printers_manager_| should call this on UI thread.
2355 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
2356
2357 constexpr PrinterClass kClassesToFetch[] = {
2358 PrinterClass::kEnterprise,
2359 PrinterClass::kSaved,
2360 PrinterClass::kAutomatic,
2361 };
2362
2363 // We are ready to get the list of printers and finish.
2364 for (const auto& type : kClassesToFetch) {
2365 std::vector<chromeos::Printer> printer_list =
2366 printers_manager_->GetPrinters(type);
2367 for (const auto& printer : printer_list) {
2368 base::Value result(base::Value::Type::DICTIONARY);
2369 result.SetKey("printerName", base::Value(printer.display_name()));
2370 result.SetKey("printerId", base::Value(printer.id()));
2371 result.SetKey("printerType", base::Value(GetPrinterType(type)));
2372 results_->Append(std::move(result));
2373 }
2374 }
2375 // We have to respond in separate task on the same thread, because it will
2376 // cause a destruction of CupsPrintersManager which needs to happen after
2377 // we return and on the same thread.
2378 base::ThreadTaskRunnerHandle::Get()->PostTask(
2379 FROM_HERE,
2380 base::BindOnce(&AutotestPrivateGetPrinterListFunction::RespondWithSuccess,
2381 this));
2382 }
2383
2384 ///////////////////////////////////////////////////////////////////////////////
2385 // AutotestPrivateUpdatePrinterFunction
2386 ///////////////////////////////////////////////////////////////////////////////
2387
2388 AutotestPrivateUpdatePrinterFunction::~AutotestPrivateUpdatePrinterFunction() =
2389 default;
2390
Run()2391 ExtensionFunction::ResponseAction AutotestPrivateUpdatePrinterFunction::Run() {
2392 std::unique_ptr<api::autotest_private::UpdatePrinter::Params> params(
2393 api::autotest_private::UpdatePrinter::Params::Create(*args_));
2394 EXTENSION_FUNCTION_VALIDATE(params);
2395 DVLOG(1) << "AutotestPrivateUpdatePrinterFunction";
2396
2397 const api::autotest_private::Printer& js_printer = params->printer;
2398 chromeos::Printer printer(js_printer.printer_id ? *js_printer.printer_id
2399 : "");
2400 printer.set_display_name(js_printer.printer_name);
2401 if (js_printer.printer_desc)
2402 printer.set_description(*js_printer.printer_desc);
2403
2404 if (js_printer.printer_make_and_model)
2405 printer.set_make_and_model(*js_printer.printer_make_and_model);
2406
2407 if (js_printer.printer_uri) {
2408 std::string message;
2409 if (!printer.SetUri(*js_printer.printer_uri, &message)) {
2410 LOG(ERROR) << message;
2411 return RespondNow(Error("Incorrect URI: " + message));
2412 }
2413 }
2414
2415 if (js_printer.printer_ppd) {
2416 const GURL ppd =
2417 net::FilePathToFileURL(base::FilePath(*js_printer.printer_ppd));
2418 if (ppd.is_valid())
2419 printer.mutable_ppd_reference()->user_supplied_ppd_url = ppd.spec();
2420 else
2421 LOG(ERROR) << "Invalid ppd path: " << *js_printer.printer_ppd;
2422 }
2423 auto* printers_manager =
2424 chromeos::CupsPrintersManagerFactory::GetForBrowserContext(
2425 browser_context());
2426 printers_manager->SavePrinter(printer);
2427 return RespondNow(NoArguments());
2428 }
2429
2430 ///////////////////////////////////////////////////////////////////////////////
2431 // AutotestPrivateRemovePrinterFunction
2432 ///////////////////////////////////////////////////////////////////////////////
2433
2434 AutotestPrivateRemovePrinterFunction::~AutotestPrivateRemovePrinterFunction() =
2435 default;
2436
Run()2437 ExtensionFunction::ResponseAction AutotestPrivateRemovePrinterFunction::Run() {
2438 std::unique_ptr<api::autotest_private::RemovePrinter::Params> params(
2439 api::autotest_private::RemovePrinter::Params::Create(*args_));
2440 EXTENSION_FUNCTION_VALIDATE(params);
2441 DVLOG(1) << "AutotestPrivateRemovePrinterFunction " << params->printer_id;
2442
2443 auto* printers_manager =
2444 chromeos::CupsPrintersManagerFactory::GetForBrowserContext(
2445 browser_context());
2446 printers_manager->RemoveSavedPrinter(params->printer_id);
2447 return RespondNow(NoArguments());
2448 }
2449
2450 ///////////////////////////////////////////////////////////////////////////////
2451 // AutotestPrivateBootstrapMachineLearningServiceFunction
2452 ///////////////////////////////////////////////////////////////////////////////
2453
2454 AutotestPrivateBootstrapMachineLearningServiceFunction::
2455 AutotestPrivateBootstrapMachineLearningServiceFunction() = default;
2456 AutotestPrivateBootstrapMachineLearningServiceFunction::
2457 ~AutotestPrivateBootstrapMachineLearningServiceFunction() = default;
2458
2459 ExtensionFunction::ResponseAction
Run()2460 AutotestPrivateBootstrapMachineLearningServiceFunction::Run() {
2461 DVLOG(1) << "AutotestPrivateBootstrapMachineLearningServiceFunction";
2462
2463 // Load a model. This will first bootstrap the Mojo connection to ML Service.
2464 chromeos::machine_learning::ServiceConnection::GetInstance()
2465 ->LoadBuiltinModel(
2466 chromeos::machine_learning::mojom::BuiltinModelSpec::New(
2467 chromeos::machine_learning::mojom::BuiltinModelId::TEST_MODEL),
2468 model_.BindNewPipeAndPassReceiver(),
2469 base::BindOnce(
2470 &AutotestPrivateBootstrapMachineLearningServiceFunction::
2471 ModelLoaded,
2472 this));
2473 model_.set_disconnect_handler(base::BindOnce(
2474 &AutotestPrivateBootstrapMachineLearningServiceFunction::OnMojoDisconnect,
2475 this));
2476 return RespondLater();
2477 }
2478
ModelLoaded(chromeos::machine_learning::mojom::LoadModelResult result)2479 void AutotestPrivateBootstrapMachineLearningServiceFunction::ModelLoaded(
2480 chromeos::machine_learning::mojom::LoadModelResult result) {
2481 if (result == chromeos::machine_learning::mojom::LoadModelResult::OK) {
2482 Respond(NoArguments());
2483 } else {
2484 Respond(Error(base::StrCat(
2485 {"Model load error ", (std::ostringstream() << result).str()})));
2486 }
2487 }
2488
2489 void AutotestPrivateBootstrapMachineLearningServiceFunction::
OnMojoDisconnect()2490 OnMojoDisconnect() {
2491 Respond(Error("ML Service connection error"));
2492 }
2493
2494 ///////////////////////////////////////////////////////////////////////////////
2495 // AutotestPrivateSetAssistantEnabled
2496 ///////////////////////////////////////////////////////////////////////////////
2497
2498 AutotestPrivateSetAssistantEnabledFunction::
AutotestPrivateSetAssistantEnabledFunction()2499 AutotestPrivateSetAssistantEnabledFunction() {
2500 // |AddObserver| will immediately trigger |OnAssistantStatusChanged|.
2501 ash::AssistantState::Get()->AddObserver(this);
2502 }
2503
2504 AutotestPrivateSetAssistantEnabledFunction::
~AutotestPrivateSetAssistantEnabledFunction()2505 ~AutotestPrivateSetAssistantEnabledFunction() {
2506 ash::AssistantState::Get()->RemoveObserver(this);
2507 }
2508
2509 ExtensionFunction::ResponseAction
Run()2510 AutotestPrivateSetAssistantEnabledFunction::Run() {
2511 DVLOG(1) << "AutotestPrivateSetAssistantEnabledFunction";
2512
2513 std::unique_ptr<api::autotest_private::SetAssistantEnabled::Params> params(
2514 api::autotest_private::SetAssistantEnabled::Params::Create(*args_));
2515 EXTENSION_FUNCTION_VALIDATE(params);
2516
2517 Profile* profile = Profile::FromBrowserContext(browser_context());
2518 const std::string& err_msg =
2519 SetWhitelistedPref(profile, chromeos::assistant::prefs::kAssistantEnabled,
2520 base::Value(params->enabled));
2521 if (!err_msg.empty())
2522 return RespondNow(Error(err_msg));
2523
2524 // Any state that's not |NOT_READY| would be considered a ready state.
2525 const bool not_ready = (ash::AssistantState::Get()->assistant_status() ==
2526 chromeos::assistant::AssistantStatus::NOT_READY);
2527 const bool success = (params->enabled != not_ready);
2528 if (success)
2529 return RespondNow(NoArguments());
2530
2531 // Assistant service has not responded yet, set up a delayed timer to wait for
2532 // it and holder a reference to |this|. Also make sure we stop and respond
2533 // when timeout.
2534 enabled_ = params->enabled;
2535 timeout_timer_.Start(
2536 FROM_HERE, base::TimeDelta::FromMilliseconds(params->timeout_ms),
2537 base::BindOnce(&AutotestPrivateSetAssistantEnabledFunction::Timeout,
2538 this));
2539 return RespondLater();
2540 }
2541
OnAssistantStatusChanged(chromeos::assistant::AssistantStatus status)2542 void AutotestPrivateSetAssistantEnabledFunction::OnAssistantStatusChanged(
2543 chromeos::assistant::AssistantStatus status) {
2544 // Must check if the Optional contains value first to avoid possible
2545 // segmentation fault caused by Respond() below being called before
2546 // RespondLater() in Run(). This will happen due to AddObserver() call
2547 // in the constructor will trigger this function immediately.
2548 if (!enabled_.has_value())
2549 return;
2550
2551 const bool not_ready =
2552 (status == chromeos::assistant::AssistantStatus::NOT_READY);
2553 const bool success = (enabled_.value() != not_ready);
2554 if (!success)
2555 return;
2556
2557 Respond(NoArguments());
2558 enabled_.reset();
2559 timeout_timer_.AbandonAndStop();
2560 }
2561
Timeout()2562 void AutotestPrivateSetAssistantEnabledFunction::Timeout() {
2563 Respond(Error("Assistant service timed out"));
2564 }
2565
2566 ///////////////////////////////////////////////////////////////////////////////
2567 // AutotestPrivateEnableAssistantAndWaitForReadyFunction
2568 ///////////////////////////////////////////////////////////////////////////////
2569
2570 AutotestPrivateEnableAssistantAndWaitForReadyFunction::
2571 AutotestPrivateEnableAssistantAndWaitForReadyFunction() = default;
2572
2573 AutotestPrivateEnableAssistantAndWaitForReadyFunction::
~AutotestPrivateEnableAssistantAndWaitForReadyFunction()2574 ~AutotestPrivateEnableAssistantAndWaitForReadyFunction() {
2575 ash::AssistantState::Get()->RemoveObserver(this);
2576 }
2577
2578 ExtensionFunction::ResponseAction
Run()2579 AutotestPrivateEnableAssistantAndWaitForReadyFunction::Run() {
2580 DVLOG(1) << "AutotestPrivateEnableAssistantAndWaitForReadyFunction";
2581
2582 Profile* profile = Profile::FromBrowserContext(browser_context());
2583 const std::string& err_msg =
2584 SetWhitelistedPref(profile, chromeos::assistant::prefs::kAssistantEnabled,
2585 base::Value(true));
2586 if (!err_msg.empty())
2587 return RespondNow(Error(err_msg));
2588
2589 // Asynchronously subscribe to status changes to avoid a possible segmentation
2590 // fault caused by Respond() in the subscriber callback being called before
2591 // RespondLater() below.
2592 base::SequencedTaskRunnerHandle::Get()->PostTask(
2593 FROM_HERE,
2594 base::BindOnce(&AutotestPrivateEnableAssistantAndWaitForReadyFunction::
2595 SubscribeToStatusChanges,
2596 this));
2597
2598 // Prevent |this| from being freed before we get a response from the
2599 // Assistant.
2600 self_ = this;
2601
2602 return RespondLater();
2603 }
2604
2605 void AutotestPrivateEnableAssistantAndWaitForReadyFunction::
SubscribeToStatusChanges()2606 SubscribeToStatusChanges() {
2607 // |AddObserver| will immediately trigger |OnAssistantStatusChanged|.
2608 ash::AssistantState::Get()->AddObserver(this);
2609 }
2610
2611 void AutotestPrivateEnableAssistantAndWaitForReadyFunction::
OnAssistantStatusChanged(chromeos::assistant::AssistantStatus status)2612 OnAssistantStatusChanged(chromeos::assistant::AssistantStatus status) {
2613 if (status == chromeos::assistant::AssistantStatus::READY) {
2614 Respond(NoArguments());
2615 self_.reset();
2616 }
2617 }
2618
2619 // AssistantInteractionHelper is a helper class used to interact with Assistant
2620 // server and store interaction states for tests. It is shared by
2621 // |AutotestPrivateSendAssistantTextQueryFunction| and
2622 // |AutotestPrivateWaitForAssistantQueryStatusFunction|.
2623 class AssistantInteractionHelper
2624 : public chromeos::assistant::AssistantInteractionSubscriber {
2625 public:
2626 using OnInteractionFinishedCallback =
2627 base::OnceCallback<void(const base::Optional<std::string>& error)>;
2628
AssistantInteractionHelper()2629 AssistantInteractionHelper()
2630 : query_status_(std::make_unique<base::DictionaryValue>()) {}
2631
~AssistantInteractionHelper()2632 ~AssistantInteractionHelper() override {
2633 if (GetAssistant()) {
2634 GetAssistant()->RemoveAssistantInteractionSubscriber(this);
2635 }
2636 }
2637
Init(OnInteractionFinishedCallback on_interaction_finished_callback)2638 void Init(OnInteractionFinishedCallback on_interaction_finished_callback) {
2639 // Subscribe to Assistant interaction events.
2640 GetAssistant()->AddAssistantInteractionSubscriber(this);
2641
2642 on_interaction_finished_callback_ =
2643 std::move(on_interaction_finished_callback);
2644 }
2645
SendTextQuery(const std::string & query,bool allow_tts)2646 void SendTextQuery(const std::string& query, bool allow_tts) {
2647 // Start text interaction with Assistant server.
2648 GetAssistant()->StartTextInteraction(
2649 query, chromeos::assistant::AssistantQuerySource::kUnspecified,
2650 allow_tts);
2651
2652 query_status_->SetKey("queryText", base::Value(query));
2653 }
2654
GetQueryStatus()2655 std::unique_ptr<base::DictionaryValue> GetQueryStatus() {
2656 return std::move(query_status_);
2657 }
2658
GetAssistant()2659 chromeos::assistant::Assistant* GetAssistant() {
2660 auto* assistant_service = chromeos::assistant::AssistantService::Get();
2661 return assistant_service ? assistant_service->GetAssistant() : nullptr;
2662 }
2663
2664 private:
2665 // chromeos::assistant::AssistantInteractionSubscriber:
2666 using AssistantSuggestion = chromeos::assistant::AssistantSuggestion;
2667 using AssistantInteractionMetadata =
2668 chromeos::assistant::AssistantInteractionMetadata;
2669 using AssistantInteractionResolution =
2670 chromeos::assistant::AssistantInteractionResolution;
2671
OnInteractionStarted(const AssistantInteractionMetadata & metadata)2672 void OnInteractionStarted(
2673 const AssistantInteractionMetadata& metadata) override {
2674 const bool is_voice_interaction =
2675 chromeos::assistant::AssistantInteractionType::kVoice == metadata.type;
2676 query_status_->SetKey("isMicOpen", base::Value(is_voice_interaction));
2677 interaction_in_progress_ = true;
2678 }
2679
OnInteractionFinished(AssistantInteractionResolution resolution)2680 void OnInteractionFinished(
2681 AssistantInteractionResolution resolution) override {
2682 interaction_in_progress_ = false;
2683
2684 // Only invoke the callback when |result_| is not empty to avoid an early
2685 // return before the entire session is completed. This happens when
2686 // sending queries to modify device settings, e.g. "turn on bluetooth",
2687 // which results in a round trip due to the need to fetch device state
2688 // on the client and return that to the server as part of a follow-up
2689 // interaction.
2690 if (result_.empty())
2691 return;
2692
2693 query_status_->SetKey("queryResponse", std::move(result_));
2694
2695 if (on_interaction_finished_callback_) {
2696 if (resolution == AssistantInteractionResolution::kNormal) {
2697 SendSuccessResponse();
2698 } else {
2699 SendErrorResponse("Interaction closed with resolution " +
2700 ResolutionToString(resolution));
2701 }
2702 }
2703 }
2704
OnHtmlResponse(const std::string & response,const std::string & fallback)2705 void OnHtmlResponse(const std::string& response,
2706 const std::string& fallback) override {
2707 result_.SetKey("htmlResponse", base::Value(response));
2708 result_.SetKey("htmlFallback", base::Value(fallback));
2709 CheckResponseIsValid(__FUNCTION__);
2710 }
2711
OnTextResponse(const std::string & response)2712 void OnTextResponse(const std::string& response) override {
2713 result_.SetKey("text", base::Value(response));
2714 CheckResponseIsValid(__FUNCTION__);
2715 }
2716
OnOpenUrlResponse(const::GURL & url,bool in_background)2717 void OnOpenUrlResponse(const ::GURL& url, bool in_background) override {
2718 result_.SetKey("openUrl", base::Value(url.possibly_invalid_spec()));
2719 }
2720
OnOpenAppResponse(const chromeos::assistant::AndroidAppInfo & app_info)2721 bool OnOpenAppResponse(
2722 const chromeos::assistant::AndroidAppInfo& app_info) override {
2723 result_.SetKey("openAppResponse", base::Value(app_info.package_name));
2724 CheckResponseIsValid(__FUNCTION__);
2725 return false;
2726 }
2727
OnSpeechRecognitionFinalResult(const std::string & final_result)2728 void OnSpeechRecognitionFinalResult(
2729 const std::string& final_result) override {
2730 query_status_->SetKey("queryText", base::Value(final_result));
2731 }
2732
CheckResponseIsValid(const std::string & function_name)2733 void CheckResponseIsValid(const std::string& function_name) {
2734 if (!interaction_in_progress_) {
2735 // We should only get a response while the interaction is open
2736 // (started and not finished).
2737 SendErrorResponse(function_name +
2738 " was called after the interaction was closed");
2739 }
2740 }
2741
SendSuccessResponse()2742 void SendSuccessResponse() {
2743 std::move(on_interaction_finished_callback_).Run(base::nullopt);
2744 }
2745
SendErrorResponse(const std::string & error)2746 void SendErrorResponse(const std::string& error) {
2747 std::move(on_interaction_finished_callback_).Run(error);
2748 }
2749
2750 std::unique_ptr<base::DictionaryValue> query_status_;
2751 base::DictionaryValue result_;
2752 bool interaction_in_progress_ = false;
2753
2754 // Callback triggered when interaction finished with non-empty response.
2755 OnInteractionFinishedCallback on_interaction_finished_callback_;
2756
2757 DISALLOW_COPY_AND_ASSIGN(AssistantInteractionHelper);
2758 };
2759
2760 ///////////////////////////////////////////////////////////////////////////////
2761 // AutotestPrivateSendAssistantTextQueryFunction
2762 ///////////////////////////////////////////////////////////////////////////////
2763
2764 AutotestPrivateSendAssistantTextQueryFunction::
AutotestPrivateSendAssistantTextQueryFunction()2765 AutotestPrivateSendAssistantTextQueryFunction()
2766 : interaction_helper_(std::make_unique<AssistantInteractionHelper>()) {}
2767
2768 AutotestPrivateSendAssistantTextQueryFunction::
2769 ~AutotestPrivateSendAssistantTextQueryFunction() = default;
2770
2771 ExtensionFunction::ResponseAction
Run()2772 AutotestPrivateSendAssistantTextQueryFunction::Run() {
2773 DVLOG(1) << "AutotestPrivateSendAssistantTextQueryFunction";
2774
2775 std::unique_ptr<api::autotest_private::SendAssistantTextQuery::Params> params(
2776 api::autotest_private::SendAssistantTextQuery::Params::Create(*args_));
2777 EXTENSION_FUNCTION_VALIDATE(params);
2778
2779 Profile* profile = Profile::FromBrowserContext(browser_context());
2780 chromeos::assistant::AssistantAllowedState allowed_state =
2781 assistant::IsAssistantAllowedForProfile(profile);
2782 if (allowed_state != chromeos::assistant::AssistantAllowedState::ALLOWED) {
2783 return RespondNow(Error(base::StringPrintf(
2784 "Assistant not allowed - state: %d", allowed_state)));
2785 }
2786
2787 interaction_helper_->Init(
2788 base::BindOnce(&AutotestPrivateSendAssistantTextQueryFunction::
2789 OnInteractionFinishedCallback,
2790 this));
2791
2792 // Start text interaction with Assistant server.
2793 interaction_helper_->SendTextQuery(params->query, /*allow_tts=*/false);
2794
2795 // Set up a delayed timer to wait for the query response and hold a reference
2796 // to |this| to avoid being destructed. Also make sure we stop and respond
2797 // when timeout.
2798 timeout_timer_.Start(
2799 FROM_HERE, base::TimeDelta::FromMilliseconds(params->timeout_ms),
2800 base::BindOnce(&AutotestPrivateSendAssistantTextQueryFunction::Timeout,
2801 this));
2802
2803 return RespondLater();
2804 }
2805
2806 void AutotestPrivateSendAssistantTextQueryFunction::
OnInteractionFinishedCallback(const base::Optional<std::string> & error)2807 OnInteractionFinishedCallback(const base::Optional<std::string>& error) {
2808 if (error) {
2809 Respond(Error(error.value()));
2810 } else {
2811 Respond(OneArgument(base::Value::FromUniquePtrValue(
2812 interaction_helper_->GetQueryStatus())));
2813 }
2814
2815 // |timeout_timer_| need to be hold until |Respond(.)| is called to avoid
2816 // |this| being destructed.
2817 timeout_timer_.AbandonAndStop();
2818 }
2819
Timeout()2820 void AutotestPrivateSendAssistantTextQueryFunction::Timeout() {
2821 Respond(Error("Assistant response timeout."));
2822 }
2823
2824 ///////////////////////////////////////////////////////////////////////////////
2825 // AutotestPrivateWaitForAssistantQueryStatusFunction
2826 ///////////////////////////////////////////////////////////////////////////////
2827 AutotestPrivateWaitForAssistantQueryStatusFunction::
AutotestPrivateWaitForAssistantQueryStatusFunction()2828 AutotestPrivateWaitForAssistantQueryStatusFunction()
2829 : interaction_helper_(std::make_unique<AssistantInteractionHelper>()) {}
2830
2831 AutotestPrivateWaitForAssistantQueryStatusFunction::
2832 ~AutotestPrivateWaitForAssistantQueryStatusFunction() = default;
2833
2834 ExtensionFunction::ResponseAction
Run()2835 AutotestPrivateWaitForAssistantQueryStatusFunction::Run() {
2836 DVLOG(1) << "AutotestPrivateWaitForAssistantQueryStatusFunction";
2837
2838 std::unique_ptr<api::autotest_private::WaitForAssistantQueryStatus::Params>
2839 params(api::autotest_private::WaitForAssistantQueryStatus::Params::Create(
2840 *args_));
2841 EXTENSION_FUNCTION_VALIDATE(params);
2842
2843 Profile* profile = Profile::FromBrowserContext(browser_context());
2844 chromeos::assistant::AssistantAllowedState allowed_state =
2845 assistant::IsAssistantAllowedForProfile(profile);
2846 if (allowed_state != chromeos::assistant::AssistantAllowedState::ALLOWED) {
2847 return RespondNow(Error(base::StringPrintf(
2848 "Assistant not allowed - state: %d", allowed_state)));
2849 }
2850
2851 interaction_helper_->Init(
2852 base::BindOnce(&AutotestPrivateWaitForAssistantQueryStatusFunction::
2853 OnInteractionFinishedCallback,
2854 this));
2855
2856 // Start waiting for the response before time out.
2857 timeout_timer_.Start(
2858 FROM_HERE, base::TimeDelta::FromSeconds(params->timeout_s),
2859 base::BindOnce(
2860 &AutotestPrivateWaitForAssistantQueryStatusFunction::Timeout, this));
2861 return RespondLater();
2862 }
2863
2864 void AutotestPrivateWaitForAssistantQueryStatusFunction::
OnInteractionFinishedCallback(const base::Optional<std::string> & error)2865 OnInteractionFinishedCallback(const base::Optional<std::string>& error) {
2866 if (error) {
2867 Respond(Error(error.value()));
2868 } else {
2869 Respond(OneArgument(base::Value::FromUniquePtrValue(
2870 interaction_helper_->GetQueryStatus())));
2871 }
2872
2873 // |timeout_timer_| need to be hold until |Respond(.)| is called to avoid
2874 // |this| being destructed.
2875 timeout_timer_.AbandonAndStop();
2876 }
2877
Timeout()2878 void AutotestPrivateWaitForAssistantQueryStatusFunction::Timeout() {
2879 Respond(Error("No query response received before time out."));
2880 }
2881
2882 ///////////////////////////////////////////////////////////////////////////////
2883 // AutotestPrivateIsArcPackageListInitialRefreshedFunction
2884 ///////////////////////////////////////////////////////////////////////////////
2885
2886 AutotestPrivateIsArcPackageListInitialRefreshedFunction::
2887 AutotestPrivateIsArcPackageListInitialRefreshedFunction() = default;
2888
2889 AutotestPrivateIsArcPackageListInitialRefreshedFunction::
2890 ~AutotestPrivateIsArcPackageListInitialRefreshedFunction() = default;
2891
2892 ExtensionFunction::ResponseAction
Run()2893 AutotestPrivateIsArcPackageListInitialRefreshedFunction::Run() {
2894 DVLOG(1) << "AutotestPrivateIsArcPackageListInitialRefreshedFunction";
2895
2896 ArcAppListPrefs* const prefs =
2897 ArcAppListPrefs::Get(Profile::FromBrowserContext(browser_context()));
2898
2899 return RespondNow(
2900 OneArgument(base::Value(prefs->package_list_initial_refreshed())));
2901 }
2902
2903 ///////////////////////////////////////////////////////////////////////////////
2904 // AutotestPrivateSetWhitelistedPrefFunction
2905 ///////////////////////////////////////////////////////////////////////////////
2906
2907 AutotestPrivateSetWhitelistedPrefFunction::
2908 ~AutotestPrivateSetWhitelistedPrefFunction() = default;
2909
2910 ExtensionFunction::ResponseAction
Run()2911 AutotestPrivateSetWhitelistedPrefFunction::Run() {
2912 DVLOG(1) << "AutotestPrivateSetWhitelistedPrefFunction";
2913
2914 std::unique_ptr<api::autotest_private::SetWhitelistedPref::Params> params(
2915 api::autotest_private::SetWhitelistedPref::Params::Create(*args_));
2916 EXTENSION_FUNCTION_VALIDATE(params);
2917
2918 const std::string& pref_name = params->pref_name;
2919 const base::Value& value = *(params->value);
2920
2921 Profile* profile = Profile::FromBrowserContext(browser_context());
2922 const std::string& err_msg = SetWhitelistedPref(profile, pref_name, value);
2923
2924 if (!err_msg.empty())
2925 return RespondNow(Error(err_msg));
2926
2927 return RespondNow(NoArguments());
2928 }
2929
2930 ///////////////////////////////////////////////////////////////////////////////
2931 // AutotestPrivateSetCrostiniAppScaledFunction
2932 ///////////////////////////////////////////////////////////////////////////////
2933
2934 AutotestPrivateSetCrostiniAppScaledFunction::
2935 ~AutotestPrivateSetCrostiniAppScaledFunction() = default;
2936
2937 ExtensionFunction::ResponseAction
Run()2938 AutotestPrivateSetCrostiniAppScaledFunction::Run() {
2939 std::unique_ptr<api::autotest_private::SetCrostiniAppScaled::Params> params(
2940 api::autotest_private::SetCrostiniAppScaled::Params::Create(*args_));
2941 EXTENSION_FUNCTION_VALIDATE(params);
2942 DVLOG(1) << "AutotestPrivateSetCrostiniAppScaledFunction " << params->app_id
2943 << " " << params->scaled;
2944
2945 ChromeLauncherController* const controller =
2946 ChromeLauncherController::instance();
2947 if (!controller)
2948 return RespondNow(Error("Controller not available"));
2949
2950 auto* registry_service =
2951 guest_os::GuestOsRegistryServiceFactory::GetForProfile(
2952 controller->profile());
2953 if (!registry_service)
2954 return RespondNow(Error("Crostini registry not available"));
2955
2956 registry_service->SetAppScaled(params->app_id, params->scaled);
2957 return RespondNow(NoArguments());
2958 }
2959
2960 ///////////////////////////////////////////////////////////////////////////////
2961 // AutotestPrivateGetPrimaryDisplayScaleFactorFunction
2962 ///////////////////////////////////////////////////////////////////////////////
2963
2964 AutotestPrivateGetPrimaryDisplayScaleFactorFunction::
2965 ~AutotestPrivateGetPrimaryDisplayScaleFactorFunction() = default;
2966
2967 ExtensionFunction::ResponseAction
Run()2968 AutotestPrivateGetPrimaryDisplayScaleFactorFunction::Run() {
2969 DVLOG(1) << "AutotestPrivateGetPrimaryDisplayScaleFactorFunction";
2970
2971 display::Display primary_display =
2972 display::Screen::GetScreen()->GetPrimaryDisplay();
2973 float scale_factor = primary_display.device_scale_factor();
2974 return RespondNow(OneArgument(base::Value(scale_factor)));
2975 }
2976
2977 ///////////////////////////////////////////////////////////////////////////////
2978 // AutotestPrivateIsTabletModeEnabledFunction
2979 ///////////////////////////////////////////////////////////////////////////////
2980
2981 AutotestPrivateIsTabletModeEnabledFunction::
2982 ~AutotestPrivateIsTabletModeEnabledFunction() = default;
2983
2984 ExtensionFunction::ResponseAction
Run()2985 AutotestPrivateIsTabletModeEnabledFunction::Run() {
2986 DVLOG(1) << "AutotestPrivateIsTabletModeEnabledFunction";
2987
2988 return RespondNow(
2989 OneArgument(base::Value(ash::TabletMode::Get()->InTabletMode())));
2990 }
2991
2992 ///////////////////////////////////////////////////////////////////////////////
2993 // AutotestPrivateSetTabletModeEnabledFunction
2994 ///////////////////////////////////////////////////////////////////////////////
2995
2996 AutotestPrivateSetTabletModeEnabledFunction::
2997 ~AutotestPrivateSetTabletModeEnabledFunction() = default;
2998
2999 ExtensionFunction::ResponseAction
Run()3000 AutotestPrivateSetTabletModeEnabledFunction::Run() {
3001 DVLOG(1) << "AutotestPrivateSetTabletModeEnabledFunction";
3002
3003 std::unique_ptr<api::autotest_private::SetTabletModeEnabled::Params> params(
3004 api::autotest_private::SetTabletModeEnabled::Params::Create(*args_));
3005 EXTENSION_FUNCTION_VALIDATE(params);
3006 ash::TabletMode::Waiter waiter(params->enabled);
3007 ash::TabletMode::Get()->ForceUiTabletModeState(params->enabled);
3008 waiter.Wait();
3009 return RespondNow(
3010 OneArgument(base::Value(ash::TabletMode::Get()->InTabletMode())));
3011 }
3012
3013 ///////////////////////////////////////////////////////////////////////////////
3014 // AutotestPrivateGetAllInstalledAppsFunction
3015 ///////////////////////////////////////////////////////////////////////////////
3016 AutotestPrivateGetAllInstalledAppsFunction::
3017 AutotestPrivateGetAllInstalledAppsFunction() = default;
3018
3019 AutotestPrivateGetAllInstalledAppsFunction::
3020 ~AutotestPrivateGetAllInstalledAppsFunction() = default;
3021
3022 ExtensionFunction::ResponseAction
Run()3023 AutotestPrivateGetAllInstalledAppsFunction::Run() {
3024 DVLOG(1) << "AutotestPrivateGetAllInstalledAppsFunction";
3025
3026 Profile* const profile = Profile::FromBrowserContext(browser_context());
3027 apps::AppServiceProxy* proxy =
3028 apps::AppServiceProxyFactory::GetForProfile(profile);
3029
3030 std::vector<api::autotest_private::App> installed_apps;
3031 proxy->AppRegistryCache().ForEachApp([&installed_apps](
3032 const apps::AppUpdate& update) {
3033 api::autotest_private::App app;
3034 app.app_id = update.AppId();
3035 app.name = update.Name();
3036 app.short_name = update.ShortName();
3037 app.additional_search_terms = update.AdditionalSearchTerms();
3038 app.type = GetAppType(update.AppType());
3039 app.install_source = GetAppInstallSource(update.InstallSource());
3040 app.readiness = GetAppReadiness(update.Readiness());
3041 app.show_in_launcher = ConvertMojomOptionalBool(update.ShowInLauncher());
3042 app.show_in_search = ConvertMojomOptionalBool(update.ShowInSearch());
3043 installed_apps.emplace_back(std::move(app));
3044 });
3045
3046 return RespondNow(
3047 ArgumentList(api::autotest_private::GetAllInstalledApps::Results::Create(
3048 installed_apps)));
3049 }
3050
3051 ///////////////////////////////////////////////////////////////////////////////
3052 // AutotestPrivateGetShelfItemsFunction
3053 ///////////////////////////////////////////////////////////////////////////////
3054 AutotestPrivateGetShelfItemsFunction::AutotestPrivateGetShelfItemsFunction() =
3055 default;
3056
3057 AutotestPrivateGetShelfItemsFunction::~AutotestPrivateGetShelfItemsFunction() =
3058 default;
3059
Run()3060 ExtensionFunction::ResponseAction AutotestPrivateGetShelfItemsFunction::Run() {
3061 DVLOG(1) << "AutotestPrivateGetShelfItemsFunction";
3062
3063 ChromeLauncherController* const controller =
3064 ChromeLauncherController::instance();
3065 if (!controller)
3066 return RespondNow(Error("Controller not available"));
3067
3068 std::vector<api::autotest_private::ShelfItem> result_items;
3069 for (const auto& item : controller->shelf_model()->items()) {
3070 api::autotest_private::ShelfItem result_item;
3071 result_item.app_id = item.id.app_id;
3072 result_item.launch_id = item.id.launch_id;
3073 result_item.title = base::UTF16ToUTF8(item.title);
3074 result_item.type = GetShelfItemType(item.type);
3075 result_item.status = GetShelfItemStatus(item.status);
3076 result_item.shows_tooltip = item.shows_tooltip;
3077 result_item.pinned_by_policy = item.pinned_by_policy;
3078 result_item.has_notification = item.has_notification;
3079 result_items.emplace_back(std::move(result_item));
3080 }
3081
3082 return RespondNow(ArgumentList(
3083 api::autotest_private::GetShelfItems::Results::Create(result_items)));
3084 }
3085
3086 ///////////////////////////////////////////////////////////////////////////////
3087 // AutotestPrivateGetShelfAutoHideBehaviorFunction
3088 ///////////////////////////////////////////////////////////////////////////////
3089
3090 AutotestPrivateGetShelfAutoHideBehaviorFunction::
3091 AutotestPrivateGetShelfAutoHideBehaviorFunction() = default;
3092
3093 AutotestPrivateGetShelfAutoHideBehaviorFunction::
3094 ~AutotestPrivateGetShelfAutoHideBehaviorFunction() = default;
3095
3096 ExtensionFunction::ResponseAction
Run()3097 AutotestPrivateGetShelfAutoHideBehaviorFunction::Run() {
3098 DVLOG(1) << "AutotestPrivateGetShelfAutoHideBehaviorFunction";
3099
3100 std::unique_ptr<api::autotest_private::GetShelfAutoHideBehavior::Params>
3101 params(api::autotest_private::GetShelfAutoHideBehavior::Params::Create(
3102 *args_));
3103 EXTENSION_FUNCTION_VALIDATE(params);
3104
3105 int64_t display_id;
3106 if (!base::StringToInt64(params->display_id, &display_id)) {
3107 return RespondNow(Error(base::StrCat(
3108 {"Invalid display_id; expected string with numbers only, got ",
3109 params->display_id})));
3110 }
3111
3112 Profile* const profile = Profile::FromBrowserContext(browser_context());
3113 ash::ShelfAutoHideBehavior behavior =
3114 ash::GetShelfAutoHideBehaviorPref(profile->GetPrefs(), display_id);
3115 std::string str_behavior;
3116 switch (behavior) {
3117 case ash::ShelfAutoHideBehavior::kAlways:
3118 str_behavior = "always";
3119 break;
3120 case ash::ShelfAutoHideBehavior::kNever:
3121 str_behavior = "never";
3122 break;
3123 case ash::ShelfAutoHideBehavior::kAlwaysHidden:
3124 // SHELF_AUTO_HIDE_ALWAYS_HIDDEN not supported by shelf_prefs.cc
3125 return RespondNow(Error("SHELF_AUTO_HIDE_ALWAYS_HIDDEN not supported"));
3126 }
3127 return RespondNow(OneArgument(base::Value(std::move(str_behavior))));
3128 }
3129
3130 ///////////////////////////////////////////////////////////////////////////////
3131 // AutotestPrivateSetShelfAutoHideBehaviorFunction
3132 ///////////////////////////////////////////////////////////////////////////////
3133
3134 AutotestPrivateSetShelfAutoHideBehaviorFunction::
3135 AutotestPrivateSetShelfAutoHideBehaviorFunction() = default;
3136
3137 AutotestPrivateSetShelfAutoHideBehaviorFunction::
3138 ~AutotestPrivateSetShelfAutoHideBehaviorFunction() = default;
3139
3140 ExtensionFunction::ResponseAction
Run()3141 AutotestPrivateSetShelfAutoHideBehaviorFunction::Run() {
3142 DVLOG(1) << "AutotestPrivateSetShelfAutoHideBehaviorFunction";
3143
3144 std::unique_ptr<api::autotest_private::SetShelfAutoHideBehavior::Params>
3145 params(api::autotest_private::SetShelfAutoHideBehavior::Params::Create(
3146 *args_));
3147 EXTENSION_FUNCTION_VALIDATE(params);
3148
3149 ash::ShelfAutoHideBehavior behavior;
3150 if (params->behavior == "always") {
3151 behavior = ash::ShelfAutoHideBehavior::kAlways;
3152 } else if (params->behavior == "never") {
3153 behavior = ash::ShelfAutoHideBehavior::kNever;
3154 } else {
3155 return RespondNow(Error(
3156 base::StrCat({"Invalid behavior; expected 'always', 'never', got ",
3157 params->behavior})));
3158 }
3159 int64_t display_id;
3160 if (!base::StringToInt64(params->display_id, &display_id)) {
3161 return RespondNow(Error(base::StrCat(
3162 {"Invalid display_id; expected string with numbers only, got ",
3163 params->display_id})));
3164 }
3165
3166 Profile* const profile = Profile::FromBrowserContext(browser_context());
3167 ash::SetShelfAutoHideBehaviorPref(profile->GetPrefs(), display_id, behavior);
3168 return RespondNow(NoArguments());
3169 }
3170
3171 ///////////////////////////////////////////////////////////////////////////////
3172 // AutotestPrivateGetShelfAlignmentFunction
3173 ///////////////////////////////////////////////////////////////////////////////
3174
3175 AutotestPrivateGetShelfAlignmentFunction::
3176 AutotestPrivateGetShelfAlignmentFunction() = default;
3177
3178 AutotestPrivateGetShelfAlignmentFunction::
3179 ~AutotestPrivateGetShelfAlignmentFunction() = default;
3180
3181 ExtensionFunction::ResponseAction
Run()3182 AutotestPrivateGetShelfAlignmentFunction::Run() {
3183 DVLOG(1) << "AutotestPrivateGetShelfAlignmentFunction";
3184
3185 std::unique_ptr<api::autotest_private::GetShelfAlignment::Params> params(
3186 api::autotest_private::GetShelfAlignment::Params::Create(*args_));
3187 EXTENSION_FUNCTION_VALIDATE(params);
3188
3189 int64_t display_id;
3190 if (!base::StringToInt64(params->display_id, &display_id)) {
3191 return RespondNow(Error(base::StrCat(
3192 {"Invalid display_id; expected string with numbers only, got ",
3193 params->display_id})));
3194 }
3195
3196 Profile* const profile = Profile::FromBrowserContext(browser_context());
3197 ash::ShelfAlignment alignment =
3198 ash::GetShelfAlignmentPref(profile->GetPrefs(), display_id);
3199 api::autotest_private::ShelfAlignmentType alignment_type;
3200 switch (alignment) {
3201 case ash::ShelfAlignment::kBottom:
3202 alignment_type = api::autotest_private::ShelfAlignmentType::
3203 SHELF_ALIGNMENT_TYPE_BOTTOM;
3204 break;
3205 case ash::ShelfAlignment::kLeft:
3206 alignment_type =
3207 api::autotest_private::ShelfAlignmentType::SHELF_ALIGNMENT_TYPE_LEFT;
3208 break;
3209 case ash::ShelfAlignment::kRight:
3210 alignment_type =
3211 api::autotest_private::ShelfAlignmentType::SHELF_ALIGNMENT_TYPE_RIGHT;
3212 break;
3213 case ash::ShelfAlignment::kBottomLocked:
3214 // ShelfAlignment::kBottomLocked not supported by
3215 // shelf_prefs.cc
3216 return RespondNow(Error("ShelfAlignment::kBottomLocked not supported"));
3217 }
3218 return RespondNow(OneArgument(
3219 base::Value(api::autotest_private::ToString(alignment_type))));
3220 }
3221
3222 ///////////////////////////////////////////////////////////////////////////////
3223 // AutotestPrivateSetShelfAlignmentFunction
3224 ///////////////////////////////////////////////////////////////////////////////
3225
3226 AutotestPrivateSetShelfAlignmentFunction::
3227 AutotestPrivateSetShelfAlignmentFunction() = default;
3228
3229 AutotestPrivateSetShelfAlignmentFunction::
3230 ~AutotestPrivateSetShelfAlignmentFunction() = default;
3231
3232 ExtensionFunction::ResponseAction
Run()3233 AutotestPrivateSetShelfAlignmentFunction::Run() {
3234 DVLOG(1) << "AutotestPrivateSetShelfAlignmentFunction";
3235
3236 std::unique_ptr<api::autotest_private::SetShelfAlignment::Params> params(
3237 api::autotest_private::SetShelfAlignment::Params::Create(*args_));
3238 EXTENSION_FUNCTION_VALIDATE(params);
3239
3240 ash::ShelfAlignment alignment;
3241 switch (params->alignment) {
3242 case api::autotest_private::ShelfAlignmentType::SHELF_ALIGNMENT_TYPE_BOTTOM:
3243 alignment = ash::ShelfAlignment::kBottom;
3244 break;
3245 case api::autotest_private::ShelfAlignmentType::SHELF_ALIGNMENT_TYPE_LEFT:
3246 alignment = ash::ShelfAlignment::kLeft;
3247 break;
3248 case api::autotest_private::ShelfAlignmentType::SHELF_ALIGNMENT_TYPE_RIGHT:
3249 alignment = ash::ShelfAlignment::kRight;
3250 break;
3251 case api::autotest_private::ShelfAlignmentType::SHELF_ALIGNMENT_TYPE_NONE:
3252 return RespondNow(
3253 Error("Invalid None alignment; expected 'Bottom', 'Left', or "
3254 "'Right'"));
3255 }
3256 int64_t display_id;
3257 if (!base::StringToInt64(params->display_id, &display_id)) {
3258 return RespondNow(Error(base::StrCat(
3259 {"Invalid display_id; expected string with numbers only, got ",
3260 params->display_id})));
3261 }
3262
3263 Profile* const profile = Profile::FromBrowserContext(browser_context());
3264 ash::SetShelfAlignmentPref(profile->GetPrefs(), display_id, alignment);
3265 return RespondNow(NoArguments());
3266 }
3267
3268 ///////////////////////////////////////////////////////////////////////////////
3269 // AutotestPrivateWaitForOverviewStateFunction
3270 ///////////////////////////////////////////////////////////////////////////////
3271
3272 AutotestPrivateWaitForOverviewStateFunction::
3273 AutotestPrivateWaitForOverviewStateFunction() = default;
3274 AutotestPrivateWaitForOverviewStateFunction::
3275 ~AutotestPrivateWaitForOverviewStateFunction() = default;
3276
3277 ExtensionFunction::ResponseAction
Run()3278 AutotestPrivateWaitForOverviewStateFunction::Run() {
3279 std::unique_ptr<api::autotest_private::WaitForOverviewState::Params> params(
3280 api::autotest_private::WaitForOverviewState::Params::Create(*args_));
3281 EXTENSION_FUNCTION_VALIDATE(params);
3282 const ash::OverviewAnimationState overview_state =
3283 ToOverviewAnimationState(params->overview_state);
3284 ash::OverviewTestApi().WaitForOverviewState(
3285 overview_state,
3286 base::BindOnce(&AutotestPrivateWaitForOverviewStateFunction::Done, this));
3287 return did_respond() ? AlreadyResponded() : RespondLater();
3288 }
3289
Done(bool success)3290 void AutotestPrivateWaitForOverviewStateFunction::Done(bool success) {
3291 if (!success) {
3292 Respond(Error("Overview animation was canceled."));
3293 return;
3294 }
3295 Respond(NoArguments());
3296 }
3297
3298 ///////////////////////////////////////////////////////////////////////////////
3299 // AutotestPrivateSetOverviewModeStateFunction
3300 ///////////////////////////////////////////////////////////////////////////////
3301
3302 AutotestPrivateSetOverviewModeStateFunction::
3303 AutotestPrivateSetOverviewModeStateFunction() = default;
3304
3305 AutotestPrivateSetOverviewModeStateFunction::
3306 ~AutotestPrivateSetOverviewModeStateFunction() = default;
3307
3308 ExtensionFunction::ResponseAction
Run()3309 AutotestPrivateSetOverviewModeStateFunction::Run() {
3310 std::unique_ptr<api::autotest_private::SetOverviewModeState::Params> params(
3311 api::autotest_private::SetOverviewModeState::Params::Create(*args_));
3312 EXTENSION_FUNCTION_VALIDATE(params);
3313
3314 ash::OverviewTestApi().SetOverviewMode(
3315 params->start,
3316 base::BindOnce(
3317 &AutotestPrivateSetOverviewModeStateFunction::OnOverviewModeChanged,
3318 this, params->start));
3319 return did_respond() ? AlreadyResponded() : RespondLater();
3320 }
3321
OnOverviewModeChanged(bool for_start,bool finished)3322 void AutotestPrivateSetOverviewModeStateFunction::OnOverviewModeChanged(
3323 bool for_start,
3324 bool finished) {
3325 auto arg = OneArgument(base::Value(finished));
3326 // On starting the overview animation, it needs to wait for 1 extra second
3327 // to trigger the occlusion tracker.
3328 if (for_start) {
3329 base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
3330 FROM_HERE,
3331 base::BindOnce(&AutotestPrivateSetOverviewModeStateFunction::Respond,
3332 this, std::move(arg)),
3333 base::TimeDelta::FromSeconds(1));
3334 } else {
3335 Respond(std::move(arg));
3336 }
3337 }
3338
3339 ///////////////////////////////////////////////////////////////////////////////
3340 // AutotestPrivateShowVirtualKeyboardIfEnabledFunction
3341 ///////////////////////////////////////////////////////////////////////////////
3342
3343 AutotestPrivateShowVirtualKeyboardIfEnabledFunction::
3344 AutotestPrivateShowVirtualKeyboardIfEnabledFunction() = default;
3345 AutotestPrivateShowVirtualKeyboardIfEnabledFunction::
3346 ~AutotestPrivateShowVirtualKeyboardIfEnabledFunction() = default;
3347
3348 ExtensionFunction::ResponseAction
Run()3349 AutotestPrivateShowVirtualKeyboardIfEnabledFunction::Run() {
3350 if (!ui::IMEBridge::Get() ||
3351 !ui::IMEBridge::Get()->GetInputContextHandler() ||
3352 !ui::IMEBridge::Get()->GetInputContextHandler()->GetInputMethod()) {
3353 return RespondNow(NoArguments());
3354 }
3355
3356 ui::IMEBridge::Get()
3357 ->GetInputContextHandler()
3358 ->GetInputMethod()
3359 ->ShowVirtualKeyboardIfEnabled();
3360 return RespondNow(NoArguments());
3361 }
3362
3363 ///////////////////////////////////////////////////////////////////////////////
3364 // AutotestPrivateArcAppTracingStartFunction
3365 ///////////////////////////////////////////////////////////////////////////////
3366
3367 AutotestPrivateArcAppTracingStartFunction::
3368 AutotestPrivateArcAppTracingStartFunction() = default;
3369 AutotestPrivateArcAppTracingStartFunction::
3370 ~AutotestPrivateArcAppTracingStartFunction() = default;
3371
3372 ExtensionFunction::ResponseAction
Run()3373 AutotestPrivateArcAppTracingStartFunction::Run() {
3374 DVLOG(1) << "AutotestPrivateArcAppTracingStartFunction";
3375
3376 arc::ArcAppPerformanceTracing* const tracing =
3377 arc::ArcAppPerformanceTracing::GetForBrowserContext(browser_context());
3378 if (!tracing)
3379 return RespondNow(Error("No ARC performance tracing is available."));
3380
3381 if (!tracing->StartCustomTracing())
3382 return RespondNow(Error("Failed to start custom tracing."));
3383
3384 return RespondNow(NoArguments());
3385 }
3386
3387 ///////////////////////////////////////////////////////////////////////////////
3388 // AutotestPrivateArcAppTracingStopAndAnalyzeFunction
3389 ///////////////////////////////////////////////////////////////////////////////
3390
3391 AutotestPrivateArcAppTracingStopAndAnalyzeFunction::
3392 AutotestPrivateArcAppTracingStopAndAnalyzeFunction() = default;
3393 AutotestPrivateArcAppTracingStopAndAnalyzeFunction::
3394 ~AutotestPrivateArcAppTracingStopAndAnalyzeFunction() = default;
3395
3396 ExtensionFunction::ResponseAction
Run()3397 AutotestPrivateArcAppTracingStopAndAnalyzeFunction::Run() {
3398 DVLOG(1) << "AutotestPrivateArcAppTracingStopAndAnalyzeFunction";
3399
3400 arc::ArcAppPerformanceTracing* const tracing =
3401 arc::ArcAppPerformanceTracing::GetForBrowserContext(browser_context());
3402 if (!tracing)
3403 return RespondNow(Error("No ARC performance tracing is available."));
3404
3405 tracing->StopCustomTracing(base::BindOnce(
3406 &AutotestPrivateArcAppTracingStopAndAnalyzeFunction::OnTracingResult,
3407 this));
3408 return did_respond() ? AlreadyResponded() : RespondLater();
3409 }
3410
OnTracingResult(bool success,double fps,double commit_deviation,double render_quality)3411 void AutotestPrivateArcAppTracingStopAndAnalyzeFunction::OnTracingResult(
3412 bool success,
3413 double fps,
3414 double commit_deviation,
3415 double render_quality) {
3416 auto result = std::make_unique<base::Value>(base::Value::Type::DICTIONARY);
3417 result->SetBoolKey("success", success);
3418 result->SetDoubleKey("fps", fps);
3419 result->SetDoubleKey("commitDeviation", commit_deviation);
3420 result->SetDoubleKey("renderQuality", render_quality);
3421 Respond(OneArgument(base::Value::FromUniquePtrValue(std::move(result))));
3422 }
3423
3424 ///////////////////////////////////////////////////////////////////////////////
3425 // AutotestPrivateSetArcAppWindowFocusFunction
3426 ///////////////////////////////////////////////////////////////////////////////
3427
3428 AutotestPrivateSetArcAppWindowFocusFunction::
3429 AutotestPrivateSetArcAppWindowFocusFunction() = default;
3430 AutotestPrivateSetArcAppWindowFocusFunction::
3431 ~AutotestPrivateSetArcAppWindowFocusFunction() = default;
3432
3433 ExtensionFunction::ResponseAction
Run()3434 AutotestPrivateSetArcAppWindowFocusFunction::Run() {
3435 std::unique_ptr<api::autotest_private::SetArcAppWindowFocus::Params> params(
3436 api::autotest_private::SetArcAppWindowFocus::Params::Create(*args_));
3437 EXTENSION_FUNCTION_VALIDATE(params);
3438 DVLOG(1) << "AutotestPrivateSetArcAppWindowFocusFunction "
3439 << params->package_name;
3440 aura::Window* arc_window = GetArcAppWindow(params->package_name);
3441 if (!arc_window) {
3442 return RespondNow(Error(base::StrCat(
3443 {"No ARC app window was found for ", params->package_name})));
3444 }
3445 if (!arc_window->CanFocus()) {
3446 return RespondNow(Error(base::StrCat(
3447 {"ARC app window can't focus for ", params->package_name})));
3448 }
3449 // No matter whether it is focused already, set it focused.
3450 arc_window->Focus();
3451 if (!arc_window->HasFocus()) {
3452 return RespondNow(Error(base::StrCat(
3453 {"Failed to set focus for ARC App window ", params->package_name})));
3454 }
3455 return RespondNow(NoArguments());
3456 }
3457
3458 ///////////////////////////////////////////////////////////////////////////////
3459 // AutotestPrivateSwapWindowsInSplitViewFunction
3460 ///////////////////////////////////////////////////////////////////////////////
3461
3462 AutotestPrivateSwapWindowsInSplitViewFunction::
3463 AutotestPrivateSwapWindowsInSplitViewFunction() = default;
3464 AutotestPrivateSwapWindowsInSplitViewFunction::
3465 ~AutotestPrivateSwapWindowsInSplitViewFunction() = default;
3466
3467 ExtensionFunction::ResponseAction
Run()3468 AutotestPrivateSwapWindowsInSplitViewFunction::Run() {
3469 ash::SplitViewTestApi().SwapWindows();
3470 return RespondNow(NoArguments());
3471 }
3472
3473 ///////////////////////////////////////////////////////////////////////////////
3474 // AutotestPrivateWaitForDisplayRotationFunction
3475 ///////////////////////////////////////////////////////////////////////////////
3476
3477 AutotestPrivateWaitForDisplayRotationFunction::
3478 AutotestPrivateWaitForDisplayRotationFunction() = default;
3479 AutotestPrivateWaitForDisplayRotationFunction::
3480 ~AutotestPrivateWaitForDisplayRotationFunction() = default;
3481
3482 ExtensionFunction::ResponseAction
Run()3483 AutotestPrivateWaitForDisplayRotationFunction::Run() {
3484 DVLOG(1) << "AutotestPrivateWaitForDisplayRotationFunction";
3485
3486 std::unique_ptr<api::autotest_private::WaitForDisplayRotation::Params> params(
3487 api::autotest_private::WaitForDisplayRotation::Params::Create(*args_));
3488 EXTENSION_FUNCTION_VALIDATE(params);
3489 if (!base::StringToInt64(params->display_id, &display_id_)) {
3490 return RespondNow(Error(base::StrCat(
3491 {"Invalid display_id; expected string with numbers only, got ",
3492 params->display_id})));
3493 }
3494
3495 if (params->rotation ==
3496 api::autotest_private::RotationType::ROTATION_TYPE_ROTATEANY) {
3497 display::Display display;
3498 if (!display::Screen::GetScreen()->GetDisplayWithDisplayId(display_id_,
3499 &display)) {
3500 return RespondNow(Error(base::StrCat(
3501 {"Display is not found for display_id ", params->display_id})));
3502 }
3503 DCHECK(display.is_valid());
3504 if (!display.IsInternal()) {
3505 return RespondNow(
3506 Error("RotateAny is valid only for the internal display"));
3507 }
3508 auto* screen_orientation_controller =
3509 ash::Shell::Get()->screen_orientation_controller();
3510 if (screen_orientation_controller->user_rotation_locked()) {
3511 self_ = this;
3512 screen_orientation_controller->AddObserver(this);
3513 return RespondLater();
3514 }
3515 target_rotation_.reset();
3516 } else {
3517 target_rotation_ = ToRotation(params->rotation);
3518 }
3519
3520 auto result = CheckScreenRotationAnimation();
3521 if (result)
3522 return RespondNow(std::move(result));
3523 return RespondLater();
3524 }
3525
3526 void AutotestPrivateWaitForDisplayRotationFunction::
OnScreenCopiedBeforeRotation()3527 OnScreenCopiedBeforeRotation() {}
3528
3529 void AutotestPrivateWaitForDisplayRotationFunction::
OnScreenRotationAnimationFinished(ash::ScreenRotationAnimator * animator,bool canceled)3530 OnScreenRotationAnimationFinished(ash::ScreenRotationAnimator* animator,
3531 bool canceled) {
3532 animator->RemoveObserver(this);
3533
3534 display::Display display;
3535 display::Screen::GetScreen()->GetDisplayWithDisplayId(display_id_, &display);
3536 Respond(OneArgument(base::Value(display.is_valid() &&
3537 (!target_rotation_.has_value() ||
3538 display.rotation() == *target_rotation_))));
3539 self_.reset();
3540 }
3541
3542 void AutotestPrivateWaitForDisplayRotationFunction::
OnUserRotationLockChanged()3543 OnUserRotationLockChanged() {
3544 auto* screen_orientation_controller =
3545 ash::Shell::Get()->screen_orientation_controller();
3546 if (screen_orientation_controller->user_rotation_locked())
3547 return;
3548 screen_orientation_controller->RemoveObserver(this);
3549 self_.reset();
3550 target_rotation_.reset();
3551 auto result = CheckScreenRotationAnimation();
3552 // Wait for the rotation if unlocking causes rotation.
3553 if (result)
3554 Respond(std::move(result));
3555 }
3556
3557 ExtensionFunction::ResponseValue
CheckScreenRotationAnimation()3558 AutotestPrivateWaitForDisplayRotationFunction::CheckScreenRotationAnimation() {
3559 auto* root_window = ash::Shell::GetRootWindowForDisplayId(display_id_);
3560 if (!root_window) {
3561 return Error(base::StringPrintf(
3562 "Invalid display_id; no root window found for the display id %" PRId64,
3563 display_id_));
3564 }
3565 auto* animator = ash::ScreenRotationAnimator::GetForRootWindow(root_window);
3566 if (!animator->IsRotating()) {
3567 display::Display display;
3568 display::Screen::GetScreen()->GetDisplayWithDisplayId(display_id_,
3569 &display);
3570 // This should never fail.
3571 DCHECK(display.is_valid());
3572 return OneArgument(base::Value(!target_rotation_.has_value() ||
3573 display.rotation() == *target_rotation_));
3574 }
3575 self_ = this;
3576
3577 animator->AddObserver(this);
3578 return nullptr;
3579 }
3580
3581 ///////////////////////////////////////////////////////////////////////////////
3582 // AutotestPrivateGetAppWindowListFunction
3583 ///////////////////////////////////////////////////////////////////////////////
3584
3585 AutotestPrivateGetAppWindowListFunction::
3586 AutotestPrivateGetAppWindowListFunction() = default;
3587 AutotestPrivateGetAppWindowListFunction::
3588 ~AutotestPrivateGetAppWindowListFunction() = default;
3589
3590 ExtensionFunction::ResponseAction
Run()3591 AutotestPrivateGetAppWindowListFunction::Run() {
3592 // Use negative number to avoid potential collision with normal use if any.
3593 static int id_count = -10000;
3594
3595 base::Optional<ash::OverviewInfo> overview_info =
3596 ash::OverviewTestApi().GetOverviewInfo();
3597
3598 auto window_list = ash::GetAppWindowList();
3599 std::vector<api::autotest_private::AppWindowInfo> result_list;
3600
3601 for (auto* window : window_list) {
3602 if (window->id() == aura::Window::kInitialId)
3603 window->set_id(id_count--);
3604 api::autotest_private::AppWindowInfo window_info;
3605 window_info.id = window->id();
3606 window_info.name = window->GetName();
3607 window_info.window_type = GetAppWindowType(
3608 static_cast<ash::AppType>(window->GetProperty(aura::client::kAppType)));
3609 window_info.state_type =
3610 ToWindowStateType(window->GetProperty(chromeos::kWindowStateTypeKey));
3611 window_info.bounds_in_root =
3612 ToBoundsDictionary(window->GetBoundsInRootWindow());
3613 window_info.target_bounds = ToBoundsDictionary(window->GetTargetBounds());
3614 window_info.display_id = base::NumberToString(
3615 display::Screen::GetScreen()->GetDisplayNearestWindow(window).id());
3616 window_info.title = base::UTF16ToUTF8(window->GetTitle());
3617 window_info.is_animating = window->layer()->GetAnimator()->is_animating();
3618 window_info.is_visible = window->IsVisible();
3619 window_info.target_visibility = window->TargetVisibility();
3620 window_info.can_focus = window->CanFocus();
3621 window_info.has_focus = window->HasFocus();
3622 window_info.on_active_desk =
3623 ash::DesksHelper::Get()->BelongsToActiveDesk(window);
3624 window_info.is_active = wm::IsActiveWindow(window);
3625 window_info.has_capture = window->HasCapture();
3626 window_info.can_resize =
3627 (window->GetProperty(aura::client::kResizeBehaviorKey) &
3628 aura::client::kResizeBehaviorCanResize) != 0;
3629
3630 if (window->GetProperty(aura::client::kAppType) ==
3631 static_cast<int>(ash::AppType::ARC_APP)) {
3632 std::string* package_name = window->GetProperty(ash::kArcPackageNameKey);
3633 if (package_name) {
3634 window_info.arc_package_name =
3635 std::make_unique<std::string>(*package_name);
3636 } else {
3637 LOG(ERROR) << "The package name for window " << window->GetTitle()
3638 << " (ID: " << window->id()
3639 << ") isn't available even though it is an ARC window.";
3640 }
3641 }
3642
3643 // Frame information
3644 auto* immersive_controller = chromeos::ImmersiveFullscreenController::Get(
3645 views::Widget::GetWidgetForNativeWindow(window));
3646 if (immersive_controller) {
3647 // The widget that hosts the immersive frame can be different from the
3648 // application's widget itself. Use the widget from the immersive
3649 // controller to obtain the FrameHeader.
3650 auto* widget = immersive_controller->widget();
3651 if (immersive_controller->IsEnabled()) {
3652 window_info.frame_mode =
3653 api::autotest_private::FrameMode::FRAME_MODE_IMMERSIVE;
3654 window_info.is_frame_visible = immersive_controller->IsRevealed();
3655 } else {
3656 window_info.frame_mode =
3657 api::autotest_private::FrameMode::FRAME_MODE_NORMAL;
3658 window_info.is_frame_visible = IsFrameVisible(widget);
3659 }
3660 auto* frame_header = chromeos::FrameHeader::Get(widget);
3661 window_info.caption_height = frame_header->GetHeaderHeight();
3662
3663 const chromeos::CaptionButtonModel* button_model =
3664 frame_header->GetCaptionButtonModel();
3665 int caption_button_enabled_status = 0;
3666 int caption_button_visible_status = 0;
3667
3668 constexpr views::CaptionButtonIcon all_button_icons[] = {
3669 views::CAPTION_BUTTON_ICON_MINIMIZE,
3670 views::CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE,
3671 views::CAPTION_BUTTON_ICON_CLOSE,
3672 views::CAPTION_BUTTON_ICON_LEFT_SNAPPED,
3673 views::CAPTION_BUTTON_ICON_RIGHT_SNAPPED,
3674 views::CAPTION_BUTTON_ICON_BACK,
3675 views::CAPTION_BUTTON_ICON_LOCATION,
3676 views::CAPTION_BUTTON_ICON_MENU,
3677 views::CAPTION_BUTTON_ICON_ZOOM};
3678
3679 for (const auto button : all_button_icons) {
3680 if (button_model->IsEnabled(button))
3681 caption_button_enabled_status |= (1 << button);
3682 if (button_model->IsVisible(button))
3683 caption_button_visible_status |= (1 << button);
3684 }
3685 window_info.caption_button_enabled_status = caption_button_enabled_status;
3686 window_info.caption_button_visible_status = caption_button_visible_status;
3687 } else {
3688 auto* widget = views::Widget::GetWidgetForNativeWindow(window);
3689 // All widgets for app windows in chromeos should have a frame with
3690 // immersive controller. Non app windows may not have a frame and
3691 // frame mode will be NONE.
3692 DCHECK(!widget || widget->GetNativeWindow()->type() !=
3693 aura::client::WINDOW_TYPE_NORMAL);
3694 window_info.frame_mode =
3695 api::autotest_private::FrameMode::FRAME_MODE_NONE;
3696 window_info.is_frame_visible = false;
3697 }
3698
3699 // Overview info.
3700 if (overview_info.has_value()) {
3701 auto it = overview_info->find(window);
3702 if (it != overview_info->end()) {
3703 window_info.overview_info =
3704 std::make_unique<api::autotest_private::OverviewInfo>();
3705 window_info.overview_info->bounds =
3706 ToBoundsDictionary(it->second.bounds_in_screen);
3707 window_info.overview_info->is_dragged = it->second.is_dragged;
3708 }
3709 }
3710
3711 result_list.emplace_back(std::move(window_info));
3712 }
3713 return RespondNow(ArgumentList(
3714 api::autotest_private::GetAppWindowList::Results::Create(result_list)));
3715 }
3716
3717 ///////////////////////////////////////////////////////////////////////////////
3718 // AutotestPrivateSetAppWindowStateFunction
3719 ///////////////////////////////////////////////////////////////////////////////
3720
3721 AutotestPrivateSetAppWindowStateFunction::
3722 AutotestPrivateSetAppWindowStateFunction() = default;
3723 AutotestPrivateSetAppWindowStateFunction::
3724 ~AutotestPrivateSetAppWindowStateFunction() = default;
3725
3726 ExtensionFunction::ResponseAction
Run()3727 AutotestPrivateSetAppWindowStateFunction::Run() {
3728 std::unique_ptr<api::autotest_private::SetAppWindowState::Params> params(
3729 api::autotest_private::SetAppWindowState::Params::Create(*args_));
3730 EXTENSION_FUNCTION_VALIDATE(params);
3731 DVLOG(1) << "AutotestPrivateSetAppWindowStateFunction " << params->id;
3732
3733 aura::Window* window = FindAppWindowById(params->id);
3734 if (!window) {
3735 return RespondNow(Error(
3736 base::StringPrintf("No app window was found : id=%d", params->id)));
3737 }
3738
3739 chromeos::WindowStateType expected_state =
3740 GetExpectedWindowState(params->change.event_type);
3741 if (window->GetProperty(chromeos::kWindowStateTypeKey) == expected_state) {
3742 if (params->change.fail_if_no_change &&
3743 *(params->change.fail_if_no_change)) {
3744 return RespondNow(
3745 Error("The app window was already in the expected window state! "));
3746 } else {
3747 return RespondNow(OneArgument(base::Value(
3748 api::autotest_private::ToString(ToWindowStateType(expected_state)))));
3749 }
3750 }
3751
3752 window_state_observer_ = std::make_unique<WindowStateChangeObserver>(
3753 window, expected_state,
3754 base::BindOnce(
3755 &AutotestPrivateSetAppWindowStateFunction::WindowStateChanged, this,
3756 expected_state));
3757
3758 // TODO(crbug.com/990713): Make WMEvent trigger split view in tablet mode.
3759 if (ash::TabletMode::Get()->InTabletMode()) {
3760 if (expected_state == chromeos::WindowStateType::kLeftSnapped) {
3761 ash::SplitViewTestApi().SnapWindow(
3762 window, ash::SplitViewTestApi::SnapPosition::LEFT);
3763 return RespondLater();
3764 } else if (expected_state == chromeos::WindowStateType::kRightSnapped) {
3765 ash::SplitViewTestApi().SnapWindow(
3766 window, ash::SplitViewTestApi::SnapPosition::RIGHT);
3767 return RespondLater();
3768 }
3769 }
3770
3771 const ash::WMEvent event(ToWMEventType(params->change.event_type));
3772 ash::WindowState::Get(window)->OnWMEvent(&event);
3773
3774 return RespondLater();
3775 }
3776
WindowStateChanged(chromeos::WindowStateType expected_type,bool success)3777 void AutotestPrivateSetAppWindowStateFunction::WindowStateChanged(
3778 chromeos::WindowStateType expected_type,
3779 bool success) {
3780 if (!success) {
3781 Respond(Error(
3782 "The app window was destroyed while waiting for its state change! "));
3783 } else {
3784 Respond(OneArgument(base::Value(
3785 api::autotest_private::ToString(ToWindowStateType(expected_type)))));
3786 }
3787 }
3788
3789 ///////////////////////////////////////////////////////////////////////////////
3790 // AutotestPrivateCloseAppWindowFunction
3791 ///////////////////////////////////////////////////////////////////////////////
3792
3793 AutotestPrivateCloseAppWindowFunction::
3794 ~AutotestPrivateCloseAppWindowFunction() = default;
3795
Run()3796 ExtensionFunction::ResponseAction AutotestPrivateCloseAppWindowFunction::Run() {
3797 std::unique_ptr<api::autotest_private::CloseAppWindow::Params> params(
3798 api::autotest_private::CloseAppWindow::Params::Create(*args_));
3799 EXTENSION_FUNCTION_VALIDATE(params);
3800 DVLOG(1) << "AutotestPrivateCloseAppWindowFunction " << params->id;
3801
3802 auto* window = FindAppWindowById(params->id);
3803 if (!window) {
3804 return RespondNow(Error(
3805 base::StringPrintf("No app window was found : id=%d", params->id)));
3806 }
3807 auto* widget = views::Widget::GetWidgetForNativeWindow(window);
3808 widget->Close();
3809 return RespondNow(NoArguments());
3810 }
3811
3812 ///////////////////////////////////////////////////////////////////////////////
3813 // AutotestPrivateInstallPWAForCurrentURL
3814 ///////////////////////////////////////////////////////////////////////////////
3815
3816 // Used to notify when when a certain URL contains a WPA.
3817 class AutotestPrivateInstallPWAForCurrentURLFunction::PWABannerObserver
3818 : public banners::AppBannerManager::Observer {
3819 public:
PWABannerObserver(banners::AppBannerManager * manager,base::OnceCallback<void ()> callback)3820 PWABannerObserver(banners::AppBannerManager* manager,
3821 base::OnceCallback<void()> callback)
3822 : callback_(std::move(callback)), app_banner_manager_(manager) {
3823 DCHECK(manager);
3824 observer_.Add(manager);
3825
3826 // If PWA is already loaded, call callback immediately.
3827 Installable installable =
3828 app_banner_manager_->GetInstallableWebAppCheckResultForTesting();
3829 if (installable == Installable::kPromotable ||
3830 installable == Installable::kByUserRequest) {
3831 observer_.RemoveAll();
3832 std::move(callback_).Run();
3833 }
3834 }
~PWABannerObserver()3835 ~PWABannerObserver() override {}
3836
OnInstallableWebAppStatusUpdated()3837 void OnInstallableWebAppStatusUpdated() override {
3838 Installable installable =
3839 app_banner_manager_->GetInstallableWebAppCheckResultForTesting();
3840 switch (installable) {
3841 case Installable::kNo:
3842 FALLTHROUGH;
3843 case Installable::kNoAlreadyInstalled:
3844 FALLTHROUGH;
3845 case Installable::kUnknown:
3846 DCHECK(false) << "Unexpected AppBannerManager::Installable value (kNo "
3847 "or kNoAlreadyInstalled or kUnknown)";
3848 break;
3849
3850 case Installable::kPromotable:
3851 FALLTHROUGH;
3852 case Installable::kByUserRequest:
3853 observer_.RemoveAll();
3854 std::move(callback_).Run();
3855 break;
3856 }
3857 }
3858
3859 private:
3860 using Installable = banners::AppBannerManager::InstallableWebAppCheckResult;
3861
3862 ScopedObserver<banners::AppBannerManager, banners::AppBannerManager::Observer>
3863 observer_{this};
3864 base::OnceCallback<void()> callback_;
3865 banners::AppBannerManager* app_banner_manager_;
3866
3867 DISALLOW_COPY_AND_ASSIGN(PWABannerObserver);
3868 };
3869
3870 // Used to notify when a WPA is installed.
3871 class AutotestPrivateInstallPWAForCurrentURLFunction::PWARegistrarObserver
3872 : public web_app::AppRegistrarObserver {
3873 public:
PWARegistrarObserver(Profile * profile,base::OnceCallback<void (const web_app::AppId &)> callback)3874 PWARegistrarObserver(Profile* profile,
3875 base::OnceCallback<void(const web_app::AppId&)> callback)
3876 : callback_(std::move(callback)) {
3877 observer_.Add(
3878 &web_app::WebAppProviderBase::GetProviderBase(profile)->registrar());
3879 }
~PWARegistrarObserver()3880 ~PWARegistrarObserver() override {}
3881
OnWebAppInstalled(const web_app::AppId & app_id)3882 void OnWebAppInstalled(const web_app::AppId& app_id) override {
3883 observer_.RemoveAll();
3884 std::move(callback_).Run(app_id);
3885 }
3886
3887 private:
3888 ScopedObserver<web_app::AppRegistrar, web_app::AppRegistrarObserver>
3889 observer_{this};
3890 base::OnceCallback<void(const web_app::AppId&)> callback_;
3891
3892 DISALLOW_COPY_AND_ASSIGN(PWARegistrarObserver);
3893 };
3894
3895 AutotestPrivateInstallPWAForCurrentURLFunction::
3896 AutotestPrivateInstallPWAForCurrentURLFunction() = default;
3897 AutotestPrivateInstallPWAForCurrentURLFunction::
3898 ~AutotestPrivateInstallPWAForCurrentURLFunction() = default;
3899
3900 ExtensionFunction::ResponseAction
Run()3901 AutotestPrivateInstallPWAForCurrentURLFunction::Run() {
3902 DVLOG(1) << "AutotestPrivateInstallPWAForCurrentURLFunction";
3903
3904 std::unique_ptr<api::autotest_private::InstallPWAForCurrentURL::Params>
3905 params(api::autotest_private::InstallPWAForCurrentURL::Params::Create(
3906 *args_));
3907 EXTENSION_FUNCTION_VALIDATE(params);
3908
3909 Browser* browser = GetFirstRegularBrowser();
3910 if (!browser) {
3911 return RespondNow(Error("Failed to find regular browser"));
3912 }
3913 content::WebContents* web_contents =
3914 browser->tab_strip_model()->GetActiveWebContents();
3915
3916 banners::AppBannerManager* app_banner_manager =
3917 banners::AppBannerManagerDesktop::FromWebContents(web_contents);
3918 if (!app_banner_manager) {
3919 return RespondNow(Error("Failed to create AppBannerManager"));
3920 }
3921
3922 banner_observer_ = std::make_unique<PWABannerObserver>(
3923 app_banner_manager,
3924 base::BindOnce(&AutotestPrivateInstallPWAForCurrentURLFunction::PWALoaded,
3925 this));
3926
3927 // Adding timeout to catch:
3928 // - There is no way to know whether ExecuteCommand fails.
3929 // - Current URL might not have a valid PWA.
3930 timeout_timer_.Start(
3931 FROM_HERE, base::TimeDelta::FromMilliseconds(params->timeout_ms),
3932 base::BindOnce(
3933 &AutotestPrivateInstallPWAForCurrentURLFunction::PWATimeout, this));
3934 return RespondLater();
3935 }
3936
PWALoaded()3937 void AutotestPrivateInstallPWAForCurrentURLFunction::PWALoaded() {
3938 Profile* profile = Profile::FromBrowserContext(browser_context());
3939 Browser* browser = GetFirstRegularBrowser();
3940
3941 registrar_observer_ = std::make_unique<PWARegistrarObserver>(
3942 profile,
3943 base::BindOnce(
3944 &AutotestPrivateInstallPWAForCurrentURLFunction::PWAInstalled, this));
3945
3946 chrome::SetAutoAcceptPWAInstallConfirmationForTesting(true);
3947 if (!chrome::ExecuteCommand(browser, IDC_INSTALL_PWA)) {
3948 return Respond(Error("Failed to execute INSTALL_PWA command"));
3949 }
3950 }
3951
PWAInstalled(const web_app::AppId & app_id)3952 void AutotestPrivateInstallPWAForCurrentURLFunction::PWAInstalled(
3953 const web_app::AppId& app_id) {
3954 chrome::SetAutoAcceptPWAInstallConfirmationForTesting(false);
3955 Respond(OneArgument(base::Value(app_id)));
3956 timeout_timer_.AbandonAndStop();
3957 }
3958
PWATimeout()3959 void AutotestPrivateInstallPWAForCurrentURLFunction::PWATimeout() {
3960 chrome::SetAutoAcceptPWAInstallConfirmationForTesting(false);
3961 Respond(Error("Install PWA timed out"));
3962 }
3963
3964 ///////////////////////////////////////////////////////////////////////////////
3965 // AutotestPrivateActivateAcceleratorFunction
3966 ///////////////////////////////////////////////////////////////////////////////
3967
3968 AutotestPrivateActivateAcceleratorFunction::
3969 AutotestPrivateActivateAcceleratorFunction() = default;
3970 AutotestPrivateActivateAcceleratorFunction::
3971 ~AutotestPrivateActivateAcceleratorFunction() = default;
3972
3973 ExtensionFunction::ResponseAction
Run()3974 AutotestPrivateActivateAcceleratorFunction::Run() {
3975 std::unique_ptr<api::autotest_private::ActivateAccelerator::Params> params(
3976 api::autotest_private::ActivateAccelerator::Params::Create(*args_));
3977 EXTENSION_FUNCTION_VALIDATE(params);
3978
3979 int modifiers = (params->accelerator.control ? ui::EF_CONTROL_DOWN : 0) |
3980 (params->accelerator.shift ? ui::EF_SHIFT_DOWN : 0) |
3981 (params->accelerator.alt ? ui::EF_ALT_DOWN : 0) |
3982 (params->accelerator.search ? ui::EF_COMMAND_DOWN : 0);
3983 ui::Accelerator accelerator(
3984 StringToKeyCode(params->accelerator.key_code), modifiers,
3985 params->accelerator.pressed ? ui::Accelerator::KeyState::PRESSED
3986 : ui::Accelerator::KeyState::RELEASED);
3987 auto* accelerator_controller = ash::AcceleratorController::Get();
3988 accelerator_controller->GetAcceleratorHistory()->StoreCurrentAccelerator(
3989 accelerator);
3990
3991 if (!accelerator_controller->IsRegistered(accelerator)) {
3992 // If it's not ash accelerator, try aplication's accelerator.
3993 auto* window = GetActiveWindow();
3994 if (!window) {
3995 return RespondNow(
3996 Error(base::StringPrintf("Accelerator is not registered 1")));
3997 }
3998 auto* widget = views::Widget::GetWidgetForNativeWindow(window);
3999 if (!widget) {
4000 return RespondNow(
4001 Error(base::StringPrintf("Accelerator is not registered 2")));
4002 }
4003 bool result = widget->GetFocusManager()->ProcessAccelerator(accelerator);
4004 return RespondNow(OneArgument(base::Value(result)));
4005 }
4006 bool result = accelerator_controller->Process(accelerator);
4007 return RespondNow(OneArgument(base::Value(result)));
4008 }
4009
4010 ///////////////////////////////////////////////////////////////////////////////
4011 // AutotestPrivateWaitForLauncherStateFunction
4012 ///////////////////////////////////////////////////////////////////////////////
4013
4014 AutotestPrivateWaitForLauncherStateFunction::
4015 AutotestPrivateWaitForLauncherStateFunction() = default;
4016 AutotestPrivateWaitForLauncherStateFunction::
4017 ~AutotestPrivateWaitForLauncherStateFunction() = default;
4018
4019 ExtensionFunction::ResponseAction
Run()4020 AutotestPrivateWaitForLauncherStateFunction::Run() {
4021 std::unique_ptr<api::autotest_private::WaitForLauncherState::Params> params(
4022 api::autotest_private::WaitForLauncherState::Params::Create(*args_));
4023 EXTENSION_FUNCTION_VALIDATE(params);
4024 auto target_state = ToAppListViewState(params->launcher_state);
4025 if (WaitForLauncherState(
4026 target_state,
4027 base::BindOnce(&AutotestPrivateWaitForLauncherStateFunction::Done,
4028 this))) {
4029 return AlreadyResponded();
4030 }
4031 return RespondLater();
4032 }
4033
Done()4034 void AutotestPrivateWaitForLauncherStateFunction::Done() {
4035 Respond(NoArguments());
4036 }
4037
4038 ///////////////////////////////////////////////////////////////////////////////
4039 // AutotestPrivateCreateNewDeskFunction
4040 ///////////////////////////////////////////////////////////////////////////////
4041
4042 AutotestPrivateCreateNewDeskFunction::AutotestPrivateCreateNewDeskFunction() =
4043 default;
4044 AutotestPrivateCreateNewDeskFunction::~AutotestPrivateCreateNewDeskFunction() =
4045 default;
4046
Run()4047 ExtensionFunction::ResponseAction AutotestPrivateCreateNewDeskFunction::Run() {
4048 const bool success = ash::AutotestDesksApi().CreateNewDesk();
4049 return RespondNow(OneArgument(base::Value(success)));
4050 }
4051
4052 ///////////////////////////////////////////////////////////////////////////////
4053 // AutotestPrivateActivateDeskAtIndexFunction
4054 ///////////////////////////////////////////////////////////////////////////////
4055
4056 AutotestPrivateActivateDeskAtIndexFunction::
4057 AutotestPrivateActivateDeskAtIndexFunction() = default;
4058 AutotestPrivateActivateDeskAtIndexFunction::
4059 ~AutotestPrivateActivateDeskAtIndexFunction() = default;
4060
4061 ExtensionFunction::ResponseAction
Run()4062 AutotestPrivateActivateDeskAtIndexFunction::Run() {
4063 std::unique_ptr<api::autotest_private::ActivateDeskAtIndex::Params> params(
4064 api::autotest_private::ActivateDeskAtIndex::Params::Create(*args_));
4065 EXTENSION_FUNCTION_VALIDATE(params);
4066
4067 if (!ash::AutotestDesksApi().ActivateDeskAtIndex(
4068 params->index,
4069 base::BindOnce(
4070 &AutotestPrivateActivateDeskAtIndexFunction::OnAnimationComplete,
4071 this))) {
4072 return RespondNow(OneArgument(base::Value(false)));
4073 }
4074
4075 return RespondLater();
4076 }
4077
OnAnimationComplete()4078 void AutotestPrivateActivateDeskAtIndexFunction::OnAnimationComplete() {
4079 Respond(OneArgument(base::Value(true)));
4080 }
4081
4082 ///////////////////////////////////////////////////////////////////////////////
4083 // AutotestPrivateRemoveActiveDeskFunction
4084 ///////////////////////////////////////////////////////////////////////////////
4085
4086 AutotestPrivateRemoveActiveDeskFunction::
4087 AutotestPrivateRemoveActiveDeskFunction() = default;
4088 AutotestPrivateRemoveActiveDeskFunction::
4089 ~AutotestPrivateRemoveActiveDeskFunction() = default;
4090
4091 ExtensionFunction::ResponseAction
Run()4092 AutotestPrivateRemoveActiveDeskFunction::Run() {
4093 if (!ash::AutotestDesksApi().RemoveActiveDesk(base::BindOnce(
4094 &AutotestPrivateRemoveActiveDeskFunction::OnAnimationComplete,
4095 this))) {
4096 return RespondNow(OneArgument(base::Value(false)));
4097 }
4098
4099 return RespondLater();
4100 }
4101
OnAnimationComplete()4102 void AutotestPrivateRemoveActiveDeskFunction::OnAnimationComplete() {
4103 Respond(OneArgument(base::Value(true)));
4104 }
4105
4106 ///////////////////////////////////////////////////////////////////////////////
4107 // AutotestPrivateActivateAdjacentDesksToTargetIndexFunction
4108 ///////////////////////////////////////////////////////////////////////////////
4109
4110 AutotestPrivateActivateAdjacentDesksToTargetIndexFunction::
4111 AutotestPrivateActivateAdjacentDesksToTargetIndexFunction() = default;
4112 AutotestPrivateActivateAdjacentDesksToTargetIndexFunction::
4113 ~AutotestPrivateActivateAdjacentDesksToTargetIndexFunction() = default;
4114
4115 ExtensionFunction::ResponseAction
Run()4116 AutotestPrivateActivateAdjacentDesksToTargetIndexFunction::Run() {
4117 std::unique_ptr<
4118 api::autotest_private::ActivateAdjacentDesksToTargetIndex::Params>
4119 params(api::autotest_private::ActivateAdjacentDesksToTargetIndex::Params::
4120 Create(*args_));
4121 EXTENSION_FUNCTION_VALIDATE(params);
4122
4123 if (!ash::AutotestDesksApi().ActivateAdjacentDesksToTargetIndex(
4124 params->index,
4125 base::BindOnce(
4126 &AutotestPrivateActivateAdjacentDesksToTargetIndexFunction::
4127 OnAnimationComplete,
4128 this))) {
4129 return RespondNow(OneArgument(base::Value(false)));
4130 }
4131
4132 return RespondLater();
4133 }
4134
4135 void AutotestPrivateActivateAdjacentDesksToTargetIndexFunction::
OnAnimationComplete()4136 OnAnimationComplete() {
4137 Respond(OneArgument(base::Value(true)));
4138 }
4139
4140 ///////////////////////////////////////////////////////////////////////////////
4141 // AutotestPrivateMouseClickFunction
4142 ///////////////////////////////////////////////////////////////////////////////
4143
4144 AutotestPrivateMouseClickFunction::AutotestPrivateMouseClickFunction() =
4145 default;
4146
4147 AutotestPrivateMouseClickFunction::~AutotestPrivateMouseClickFunction() =
4148 default;
4149
Run()4150 ExtensionFunction::ResponseAction AutotestPrivateMouseClickFunction::Run() {
4151 std::unique_ptr<api::autotest_private::MouseClick::Params> params(
4152 api::autotest_private::MouseClick::Params::Create(*args_));
4153 EXTENSION_FUNCTION_VALIDATE(params);
4154
4155 auto* env = aura::Env::GetInstance();
4156 if (env->mouse_button_flags() != 0) {
4157 return RespondNow(Error(base::StringPrintf("Already pressed; flags %d",
4158 env->mouse_button_flags())));
4159 }
4160
4161 int64_t display_id = ash::Shell::Get()->cursor_manager()->GetDisplay().id();
4162 auto* root_window = ash::Shell::GetRootWindowForDisplayId(display_id);
4163 if (!root_window)
4164 return RespondNow(Error("Failed to find the root window"));
4165
4166 gfx::PointF location_in_host(env->last_mouse_location().x(),
4167 env->last_mouse_location().y());
4168 wm::ConvertPointFromScreen(root_window, &location_in_host);
4169 ConvertPointToHost(root_window, &location_in_host);
4170
4171 int flags = GetMouseEventFlags(params->button);
4172 event_generator_ = std::make_unique<EventGenerator>(
4173 root_window->GetHost(),
4174 base::BindOnce(&AutotestPrivateMouseClickFunction::Respond, this,
4175 NoArguments()));
4176 event_generator_->ScheduleMouseEvent(ui::ET_MOUSE_PRESSED, location_in_host,
4177 flags);
4178 event_generator_->ScheduleMouseEvent(ui::ET_MOUSE_RELEASED, location_in_host,
4179 flags);
4180 event_generator_->Run();
4181
4182 return RespondLater();
4183 }
4184
4185 ///////////////////////////////////////////////////////////////////////////////
4186 // AutotestPrivateMousePressFunction
4187 ///////////////////////////////////////////////////////////////////////////////
4188
4189 AutotestPrivateMousePressFunction::AutotestPrivateMousePressFunction() =
4190 default;
4191 AutotestPrivateMousePressFunction::~AutotestPrivateMousePressFunction() =
4192 default;
4193
Run()4194 ExtensionFunction::ResponseAction AutotestPrivateMousePressFunction::Run() {
4195 std::unique_ptr<api::autotest_private::MousePress::Params> params(
4196 api::autotest_private::MousePress::Params::Create(*args_));
4197 EXTENSION_FUNCTION_VALIDATE(params);
4198
4199 auto* env = aura::Env::GetInstance();
4200 int input_flags = GetMouseEventFlags(params->button);
4201 if ((input_flags | env->mouse_button_flags()) == env->mouse_button_flags())
4202 return RespondNow(NoArguments());
4203
4204 int64_t display_id = ash::Shell::Get()->cursor_manager()->GetDisplay().id();
4205 auto* root_window = ash::Shell::GetRootWindowForDisplayId(display_id);
4206 if (!root_window)
4207 return RespondNow(Error("Failed to find the root window"));
4208
4209 gfx::PointF location_in_host(env->last_mouse_location().x(),
4210 env->last_mouse_location().y());
4211 wm::ConvertPointFromScreen(root_window, &location_in_host);
4212 ConvertPointToHost(root_window, &location_in_host);
4213
4214 event_generator_ = std::make_unique<EventGenerator>(
4215 root_window->GetHost(),
4216 base::BindOnce(&AutotestPrivateMousePressFunction::Respond, this,
4217 NoArguments()));
4218 event_generator_->ScheduleMouseEvent(ui::ET_MOUSE_PRESSED, location_in_host,
4219 input_flags);
4220 event_generator_->Run();
4221
4222 return RespondLater();
4223 }
4224
4225 ///////////////////////////////////////////////////////////////////////////////
4226 // AutotestPrivateMouseReleaseFunction
4227 ///////////////////////////////////////////////////////////////////////////////
4228
4229 AutotestPrivateMouseReleaseFunction::AutotestPrivateMouseReleaseFunction() =
4230 default;
4231 AutotestPrivateMouseReleaseFunction::~AutotestPrivateMouseReleaseFunction() =
4232 default;
4233
Run()4234 ExtensionFunction::ResponseAction AutotestPrivateMouseReleaseFunction::Run() {
4235 std::unique_ptr<api::autotest_private::MouseRelease::Params> params(
4236 api::autotest_private::MouseRelease::Params::Create(*args_));
4237 EXTENSION_FUNCTION_VALIDATE(params);
4238
4239 auto* env = aura::Env::GetInstance();
4240
4241 int input_flags = GetMouseEventFlags(params->button);
4242 if ((env->mouse_button_flags() & (~input_flags)) == env->mouse_button_flags())
4243 return RespondNow(NoArguments());
4244
4245 int64_t display_id = ash::Shell::Get()->cursor_manager()->GetDisplay().id();
4246 auto* root_window = ash::Shell::GetRootWindowForDisplayId(display_id);
4247 if (!root_window)
4248 return RespondNow(Error("Failed to find the root window"));
4249
4250 gfx::PointF location_in_host(env->last_mouse_location().x(),
4251 env->last_mouse_location().y());
4252 wm::ConvertPointFromScreen(root_window, &location_in_host);
4253 ConvertPointToHost(root_window, &location_in_host);
4254
4255 event_generator_ = std::make_unique<EventGenerator>(
4256 root_window->GetHost(),
4257 base::BindOnce(&AutotestPrivateMouseReleaseFunction::Respond, this,
4258 NoArguments()));
4259 event_generator_->ScheduleMouseEvent(ui::ET_MOUSE_RELEASED, location_in_host,
4260 input_flags);
4261 event_generator_->Run();
4262
4263 return RespondLater();
4264 }
4265
4266 ///////////////////////////////////////////////////////////////////////////////
4267 // AutotestPrivateMouseMoveFunction
4268 ///////////////////////////////////////////////////////////////////////////////
4269
4270 AutotestPrivateMouseMoveFunction::AutotestPrivateMouseMoveFunction() = default;
4271 AutotestPrivateMouseMoveFunction::~AutotestPrivateMouseMoveFunction() = default;
Run()4272 ExtensionFunction::ResponseAction AutotestPrivateMouseMoveFunction::Run() {
4273 std::unique_ptr<api::autotest_private::MouseMove::Params> params(
4274 api::autotest_private::MouseMove::Params::Create(*args_));
4275 EXTENSION_FUNCTION_VALIDATE(params);
4276
4277 int64_t display_id = ash::Shell::Get()->cursor_manager()->GetDisplay().id();
4278 auto* root_window = ash::Shell::GetRootWindowForDisplayId(display_id);
4279 if (!root_window)
4280 return RespondNow(Error("Failed to find the root window"));
4281
4282 const gfx::PointF location_in_root(params->location.x, params->location.y);
4283 gfx::PointF location_in_screen = location_in_root;
4284 wm::ConvertPointToScreen(root_window, &location_in_screen);
4285 auto* env = aura::Env::GetInstance();
4286 const gfx::Point last_mouse_location(env->last_mouse_location());
4287 if (last_mouse_location == gfx::ToFlooredPoint(location_in_screen))
4288 return RespondNow(NoArguments());
4289
4290 gfx::PointF location_in_host = location_in_root;
4291 ConvertPointToHost(root_window, &location_in_host);
4292
4293 event_generator_ = std::make_unique<EventGenerator>(
4294 root_window->GetHost(),
4295 base::BindOnce(&AutotestPrivateMouseMoveFunction::Respond, this,
4296 NoArguments()));
4297 gfx::PointF start_in_host(last_mouse_location.x(), last_mouse_location.y());
4298 wm::ConvertPointFromScreen(root_window, &start_in_host);
4299 ConvertPointToHost(root_window, &start_in_host);
4300
4301 int64_t steps = std::max(
4302 base::ClampFloor<int64_t>(params->duration_in_ms /
4303 event_generator_->interval().InMillisecondsF()),
4304 static_cast<int64_t>(1));
4305 int flags = env->mouse_button_flags();
4306 ui::EventType type = (flags == 0) ? ui::ET_MOUSE_MOVED : ui::ET_MOUSE_DRAGGED;
4307 for (int64_t i = 1; i <= steps; ++i) {
4308 double progress = static_cast<double>(i) / static_cast<double>(steps);
4309 gfx::PointF point(gfx::Tween::FloatValueBetween(progress, start_in_host.x(),
4310 location_in_host.x()),
4311 gfx::Tween::FloatValueBetween(progress, start_in_host.y(),
4312 location_in_host.y()));
4313 event_generator_->ScheduleMouseEvent(type, point, flags);
4314 }
4315 event_generator_->Run();
4316 return RespondLater();
4317 }
4318
4319 ///////////////////////////////////////////////////////////////////////////////
4320 // AutotestPrivateSetMetricsEnabledFunction
4321 ///////////////////////////////////////////////////////////////////////////////
4322
4323 AutotestPrivateSetMetricsEnabledFunction::
4324 AutotestPrivateSetMetricsEnabledFunction() = default;
4325 AutotestPrivateSetMetricsEnabledFunction::
4326 ~AutotestPrivateSetMetricsEnabledFunction() = default;
4327
4328 ExtensionFunction::ResponseAction
Run()4329 AutotestPrivateSetMetricsEnabledFunction::Run() {
4330 std::unique_ptr<api::autotest_private::SetMetricsEnabled::Params> params(
4331 api::autotest_private::SetMetricsEnabled::Params::Create(*args_));
4332 EXTENSION_FUNCTION_VALIDATE(params);
4333 VLOG(1) << "AutotestPrivateSetMetricsEnabledFunction " << std::boolalpha
4334 << params->enabled;
4335
4336 target_value_ = params->enabled;
4337
4338 Profile* profile = Profile::FromBrowserContext(browser_context());
4339
4340 chromeos::StatsReportingController* stats_reporting_controller =
4341 chromeos::StatsReportingController::Get();
4342
4343 // Set the preference to indicate metrics are enabled/disabled.
4344 stats_reporting_controller->SetEnabled(profile, target_value_);
4345 if (stats_reporting_controller->IsEnabled() == target_value_) {
4346 VLOG(1) << "Value at target; returning early";
4347 return RespondNow(NoArguments());
4348 }
4349 stats_reporting_observer_subscription_ =
4350 chromeos::StatsReportingController::Get()->AddObserver(
4351 base::BindRepeating(&AutotestPrivateSetMetricsEnabledFunction::
4352 OnStatsReportingStateChanged,
4353 this));
4354 return RespondLater();
4355 }
4356
OnStatsReportingStateChanged()4357 void AutotestPrivateSetMetricsEnabledFunction::OnStatsReportingStateChanged() {
4358 bool actual = chromeos::StatsReportingController::Get()->IsEnabled();
4359 VLOG(1) << "AutotestPrivateSetMetricsEnabledFunction: actual: "
4360 << std::boolalpha << actual << " and expected: " << std::boolalpha
4361 << target_value_;
4362 if (actual == target_value_) {
4363 Respond(NoArguments());
4364 } else {
4365 Respond(Error("Failed to set metrics consent"));
4366 }
4367 stats_reporting_observer_subscription_.reset();
4368 }
4369
4370 ///////////////////////////////////////////////////////////////////////////////
4371 // AutotestPrivateStartTracingFunction
4372 ///////////////////////////////////////////////////////////////////////////////
4373 AutotestPrivateStartTracingFunction::AutotestPrivateStartTracingFunction() =
4374 default;
4375 AutotestPrivateStartTracingFunction::~AutotestPrivateStartTracingFunction() =
4376 default;
4377
Run()4378 ExtensionFunction::ResponseAction AutotestPrivateStartTracingFunction::Run() {
4379 std::unique_ptr<api::autotest_private::StartTracing::Params> params(
4380 api::autotest_private::StartTracing::Params::Create(*args_));
4381 EXTENSION_FUNCTION_VALIDATE(params);
4382 std::unique_ptr<base::Value> config_value = params->config.ToValue();
4383 base::trace_event::TraceConfig config(*config_value.get());
4384
4385 if (!content::TracingController::GetInstance()->StartTracing(
4386 config,
4387 base::BindOnce(&AutotestPrivateStartTracingFunction::OnStartTracing,
4388 this))) {
4389 return RespondNow(Error("Failed to start tracing"));
4390 }
4391
4392 return RespondLater();
4393 }
4394
OnStartTracing()4395 void AutotestPrivateStartTracingFunction::OnStartTracing() {
4396 Respond(NoArguments());
4397 }
4398
4399 ///////////////////////////////////////////////////////////////////////////////
4400 // AutotestPrivateStopTracingFunction
4401 ///////////////////////////////////////////////////////////////////////////////
4402 AutotestPrivateStopTracingFunction::AutotestPrivateStopTracingFunction() =
4403 default;
4404 AutotestPrivateStopTracingFunction::~AutotestPrivateStopTracingFunction() =
4405 default;
4406
Run()4407 ExtensionFunction::ResponseAction AutotestPrivateStopTracingFunction::Run() {
4408 if (!content::TracingController::GetInstance()->StopTracing(
4409 content::TracingController::CreateStringEndpoint(base::BindOnce(
4410 &AutotestPrivateStopTracingFunction::OnTracingComplete, this)))) {
4411 return RespondNow(Error("Failed to stop tracing"));
4412 }
4413 return RespondLater();
4414 }
4415
OnTracingComplete(std::unique_ptr<std::string> trace)4416 void AutotestPrivateStopTracingFunction::OnTracingComplete(
4417 std::unique_ptr<std::string> trace) {
4418 base::Value value(*trace.get());
4419 Respond(OneArgument(std::move(value)));
4420 }
4421
4422 ///////////////////////////////////////////////////////////////////////////////
4423 // AutotestPrivateSetArcTouchModeFunction
4424 ///////////////////////////////////////////////////////////////////////////////
4425 AutotestPrivateSetArcTouchModeFunction::
4426 AutotestPrivateSetArcTouchModeFunction() = default;
4427 AutotestPrivateSetArcTouchModeFunction::
4428 ~AutotestPrivateSetArcTouchModeFunction() = default;
4429
4430 ExtensionFunction::ResponseAction
Run()4431 AutotestPrivateSetArcTouchModeFunction::Run() {
4432 std::unique_ptr<api::autotest_private::SetArcTouchMode::Params> params(
4433 api::autotest_private::SetArcTouchMode::Params::Create(*args_));
4434 EXTENSION_FUNCTION_VALIDATE(params);
4435 DVLOG(1) << "AutotestPrivateSetArcTouchModeFunction " << params->enabled;
4436
4437 if (!arc::SetTouchMode(params->enabled))
4438 return RespondNow(Error("Could not send intent to ARC."));
4439
4440 return RespondNow(NoArguments());
4441 }
4442
4443 ////////////////////////////////////////////////////////////////////////////////
4444 // AutotestPrivatePinShelfIconFunction
4445 ////////////////////////////////////////////////////////////////////////////////
4446 AutotestPrivatePinShelfIconFunction::AutotestPrivatePinShelfIconFunction() =
4447 default;
4448 AutotestPrivatePinShelfIconFunction::~AutotestPrivatePinShelfIconFunction() =
4449 default;
4450
Run()4451 ExtensionFunction::ResponseAction AutotestPrivatePinShelfIconFunction::Run() {
4452 std::unique_ptr<api::autotest_private::PinShelfIcon::Params> params(
4453 api::autotest_private::PinShelfIcon::Params::Create(*args_));
4454 EXTENSION_FUNCTION_VALIDATE(params);
4455 DVLOG(1) << "AutotestPrivatePinShelfIconFunction " << params->app_id;
4456
4457 ChromeLauncherController* const controller =
4458 ChromeLauncherController::instance();
4459 if (!controller)
4460 return RespondNow(Error("Controller not available"));
4461
4462 controller->PinAppWithID(params->app_id);
4463 return RespondNow(NoArguments());
4464 }
4465
4466 ////////////////////////////////////////////////////////////////////////////////
4467 // AutotestPrivateGetScrollableShelfInfoForStateFunction
4468 ////////////////////////////////////////////////////////////////////////////////
4469 AutotestPrivateGetScrollableShelfInfoForStateFunction::
4470 AutotestPrivateGetScrollableShelfInfoForStateFunction() = default;
4471 AutotestPrivateGetScrollableShelfInfoForStateFunction::
4472 ~AutotestPrivateGetScrollableShelfInfoForStateFunction() = default;
4473
4474 ExtensionFunction::ResponseAction
Run()4475 AutotestPrivateGetScrollableShelfInfoForStateFunction::Run() {
4476 DVLOG(1) << "AutotestPrivateGetScrollableShelfInfoForStateFunction";
4477 std::unique_ptr<api::autotest_private::GetScrollableShelfInfoForState::Params>
4478 params(
4479 api::autotest_private::GetScrollableShelfInfoForState::Params::Create(
4480 *args_));
4481
4482 ash::ShelfTestApi shelf_test_api;
4483
4484 ash::ShelfState state;
4485
4486 if (params->state.scroll_distance)
4487 state.scroll_distance = *params->state.scroll_distance;
4488
4489 ash::ScrollableShelfInfo fetched_info =
4490 shelf_test_api.GetScrollableShelfInfoForState(state);
4491
4492 api::autotest_private::ScrollableShelfInfo info;
4493 info.main_axis_offset = fetched_info.main_axis_offset;
4494 info.page_offset = fetched_info.page_offset;
4495 info.left_arrow_bounds = ToBoundsDictionary(fetched_info.left_arrow_bounds);
4496 info.right_arrow_bounds = ToBoundsDictionary(fetched_info.right_arrow_bounds);
4497 info.is_animating = fetched_info.is_animating;
4498 info.is_overflow = fetched_info.is_overflow;
4499
4500 if (params->state.scroll_distance) {
4501 info.target_main_axis_offset =
4502 std::make_unique<double>(fetched_info.target_main_axis_offset);
4503 }
4504
4505 return RespondNow(
4506 OneArgument(base::Value::FromUniquePtrValue(info.ToValue())));
4507 }
4508
4509 ////////////////////////////////////////////////////////////////////////////////
4510 // AutotestPrivateGetShelfUIInfoForStateFunction
4511 ////////////////////////////////////////////////////////////////////////////////
4512 AutotestPrivateGetShelfUIInfoForStateFunction::
4513 AutotestPrivateGetShelfUIInfoForStateFunction() = default;
4514 AutotestPrivateGetShelfUIInfoForStateFunction::
4515 ~AutotestPrivateGetShelfUIInfoForStateFunction() = default;
4516
4517 ExtensionFunction::ResponseAction
Run()4518 AutotestPrivateGetShelfUIInfoForStateFunction::Run() {
4519 DVLOG(1) << "AutotestPrivateGetShelfUIInfoForStateFunction";
4520 std::unique_ptr<api::autotest_private::GetShelfUIInfoForState::Params> params(
4521 api::autotest_private::GetShelfUIInfoForState::Params::Create(*args_));
4522
4523 ash::ShelfState state;
4524 if (params->state.scroll_distance)
4525 state.scroll_distance = *params->state.scroll_distance;
4526
4527 api::autotest_private::ShelfUIInfo shelf_ui_info;
4528 ash::ShelfTestApi shelf_test_api;
4529
4530 // Fetch scrollable shelf ui information.
4531 {
4532 ash::ScrollableShelfInfo fetched_info =
4533 shelf_test_api.GetScrollableShelfInfoForState(state);
4534
4535 api::autotest_private::ScrollableShelfInfo scrollable_shelf_ui_info;
4536 scrollable_shelf_ui_info.main_axis_offset = fetched_info.main_axis_offset;
4537 scrollable_shelf_ui_info.page_offset = fetched_info.page_offset;
4538 scrollable_shelf_ui_info.left_arrow_bounds =
4539 ToBoundsDictionary(fetched_info.left_arrow_bounds);
4540 scrollable_shelf_ui_info.right_arrow_bounds =
4541 ToBoundsDictionary(fetched_info.right_arrow_bounds);
4542 scrollable_shelf_ui_info.is_animating = fetched_info.is_animating;
4543 scrollable_shelf_ui_info.is_overflow = fetched_info.is_overflow;
4544 scrollable_shelf_ui_info.icons_bounds_in_screen =
4545 ToBoundsDictionaryList(fetched_info.icons_bounds_in_screen);
4546 scrollable_shelf_ui_info.is_shelf_widget_animating =
4547 fetched_info.is_shelf_widget_animating;
4548
4549 if (state.scroll_distance) {
4550 scrollable_shelf_ui_info.target_main_axis_offset =
4551 std::make_unique<double>(fetched_info.target_main_axis_offset);
4552 }
4553
4554 shelf_ui_info.scrollable_shelf_info = std::move(scrollable_shelf_ui_info);
4555 }
4556
4557 // Fetch hotseat ui information.
4558 {
4559 ash::HotseatInfo hotseat_info = shelf_test_api.GetHotseatInfo();
4560 api::autotest_private::HotseatSwipeDescriptor swipe_up_descriptor;
4561 swipe_up_descriptor.swipe_start_location =
4562 ToLocationDictionary(hotseat_info.swipe_up.swipe_start_location);
4563 swipe_up_descriptor.swipe_end_location =
4564 ToLocationDictionary(hotseat_info.swipe_up.swipe_end_location);
4565
4566 api::autotest_private::HotseatInfo hotseat_ui_info;
4567 hotseat_ui_info.swipe_up = std::move(swipe_up_descriptor);
4568 hotseat_ui_info.is_animating = hotseat_info.is_animating;
4569 hotseat_ui_info.state = GetHotseatState(hotseat_info.hotseat_state);
4570
4571 shelf_ui_info.hotseat_info = std::move(hotseat_ui_info);
4572 }
4573
4574 return RespondNow(
4575 OneArgument(base::Value::FromUniquePtrValue(shelf_ui_info.ToValue())));
4576 }
4577
4578 ///////////////////////////////////////////////////////////////////////////////
4579 // AutotestPrivateSetWindowBoundsFunction
4580 ///////////////////////////////////////////////////////////////////////////////
4581
4582 AutotestPrivateSetWindowBoundsFunction::
4583 AutotestPrivateSetWindowBoundsFunction() = default;
4584 AutotestPrivateSetWindowBoundsFunction::
4585 ~AutotestPrivateSetWindowBoundsFunction() = default;
4586
4587 namespace {
4588
BuildSetWindowBoundsResult(const gfx::Rect & bounds_in_display,int64_t display_id)4589 std::unique_ptr<base::DictionaryValue> BuildSetWindowBoundsResult(
4590 const gfx::Rect& bounds_in_display,
4591 int64_t display_id) {
4592 auto result = std::make_unique<base::DictionaryValue>();
4593 result->SetDictionary("bounds",
4594 ToBoundsDictionary(bounds_in_display).ToValue());
4595 result->SetString("displayId", base::NumberToString(display_id));
4596 return result;
4597 }
4598
4599 } // namespace
4600
4601 ExtensionFunction::ResponseAction
Run()4602 AutotestPrivateSetWindowBoundsFunction::Run() {
4603 std::unique_ptr<api::autotest_private::SetWindowBounds::Params> params(
4604 api::autotest_private::SetWindowBounds::Params::Create(*args_));
4605 EXTENSION_FUNCTION_VALIDATE(params);
4606
4607 aura::Window* window = FindAppWindowById(params->id);
4608 if (!window) {
4609 return RespondNow(Error(
4610 base::StringPrintf("No app window was found : id=%d", params->id)));
4611 }
4612
4613 auto* state = ash::WindowState::Get(window);
4614 if (!state || chromeos::ToWindowShowState(state->GetStateType()) !=
4615 ui::SHOW_STATE_NORMAL) {
4616 return RespondNow(
4617 Error("Cannot set bounds of window not in normal show state."));
4618 }
4619
4620 int64_t display_id;
4621 if (!base::StringToInt64(params->display_id, &display_id)) {
4622 return RespondNow(Error(base::StrCat(
4623 {"Invalid display_id; expected string with numbers only, got ",
4624 params->display_id})));
4625 }
4626
4627 display::Display display;
4628 display::Screen::GetScreen()->GetDisplayWithDisplayId(display_id, &display);
4629 if (!display.is_valid()) {
4630 return RespondNow(
4631 Error("Given display ID does not correspond to a valid display"));
4632 }
4633
4634 auto* root_window = ash::Shell::GetRootWindowForDisplayId(display_id);
4635 if (!root_window)
4636 return RespondNow(Error("Failed to find the root window"));
4637
4638 gfx::Rect to_bounds = ToRect(params->bounds);
4639
4640 if (window->GetBoundsInRootWindow() == to_bounds &&
4641 state->GetDisplay().id() == display_id) {
4642 return RespondNow(OneArgument(base::Value::FromUniquePtrValue(
4643 BuildSetWindowBoundsResult(to_bounds, display_id))));
4644 }
4645
4646 window_bounds_observer_ = std::make_unique<WindowBoundsChangeObserver>(
4647 window, to_bounds, display_id,
4648 base::BindOnce(
4649 &AutotestPrivateSetWindowBoundsFunction::WindowBoundsChanged, this));
4650
4651 ::wm::ConvertRectToScreen(root_window, &to_bounds);
4652 window->SetBoundsInScreen(to_bounds, display);
4653
4654 return RespondLater();
4655 }
4656
WindowBoundsChanged(const gfx::Rect & bounds_in_display,int64_t display_id,bool success)4657 void AutotestPrivateSetWindowBoundsFunction::WindowBoundsChanged(
4658 const gfx::Rect& bounds_in_display,
4659 int64_t display_id,
4660 bool success) {
4661 if (!success) {
4662 Respond(Error(
4663 "The app window was destroyed while waiting for bounds to change!"));
4664 } else {
4665 Respond(OneArgument(base::Value::FromUniquePtrValue(
4666 BuildSetWindowBoundsResult(bounds_in_display, display_id))));
4667 }
4668 }
4669
4670 ///////////////////////////////////////////////////////////////////////////////
4671 // AutotestPrivateStartSmoothnessTrackingFunction
4672 ///////////////////////////////////////////////////////////////////////////////
4673
4674 AutotestPrivateStartSmoothnessTrackingFunction::
4675 ~AutotestPrivateStartSmoothnessTrackingFunction() = default;
4676
4677 ExtensionFunction::ResponseAction
Run()4678 AutotestPrivateStartSmoothnessTrackingFunction::Run() {
4679 auto params(
4680 api::autotest_private::StartSmoothnessTracking::Params::Create(*args_));
4681 EXTENSION_FUNCTION_VALIDATE(params);
4682
4683 int64_t display_id;
4684 if (!GetDisplayIdFromOptionalArg(params->display_id, &display_id)) {
4685 return RespondNow(
4686 Error(base::StrCat({"Invalid display id: ", *params->display_id})));
4687 }
4688
4689 auto* infos = GetDisplaySmoothnessTrackerInfos();
4690 if (infos->find(display_id) != infos->end()) {
4691 return RespondNow(
4692 Error(base::StrCat({"Smoothness already tracked for display: ",
4693 base::NumberToString(display_id)})));
4694 }
4695
4696 auto* root_window = ash::Shell::GetRootWindowForDisplayId(display_id);
4697 if (!root_window) {
4698 return RespondNow(Error(base::StrCat(
4699 {"Invalid display_id; no root window found for the display id ",
4700 base::NumberToString(display_id)})));
4701 }
4702
4703 auto tracker =
4704 root_window->layer()->GetCompositor()->RequestNewThroughputTracker();
4705 tracker.Start(base::BindOnce(&ForwardFrameRateDataAndReset, display_id));
4706 (*infos)[display_id].tracker = std::move(tracker);
4707 return RespondNow(NoArguments());
4708 }
4709
4710 ///////////////////////////////////////////////////////////////////////////////
4711 // AutotestPrivateStopSmoothnessTrackingFunction
4712 //////////////////////////////////////////////////////////////////////////////
4713
4714 AutotestPrivateStopSmoothnessTrackingFunction::
4715 ~AutotestPrivateStopSmoothnessTrackingFunction() = default;
4716
4717 ExtensionFunction::ResponseAction
Run()4718 AutotestPrivateStopSmoothnessTrackingFunction::Run() {
4719 auto params(
4720 api::autotest_private::StopSmoothnessTracking::Params::Create(*args_));
4721 EXTENSION_FUNCTION_VALIDATE(params);
4722
4723 int64_t display_id;
4724 if (!GetDisplayIdFromOptionalArg(params->display_id, &display_id)) {
4725 return RespondNow(
4726 Error(base::StrCat({"Invalid display id: ", *params->display_id})));
4727 }
4728
4729 auto* infos = GetDisplaySmoothnessTrackerInfos();
4730 auto it = infos->find(display_id);
4731 if (it == infos->end()) {
4732 return RespondNow(
4733 Error(base::StrCat({"Smoothness is not tracked for display: ",
4734 base::NumberToString(display_id)})));
4735 }
4736
4737 it->second.callback = base::BindOnce(
4738 &AutotestPrivateStopSmoothnessTrackingFunction::OnReportData, this);
4739 it->second.tracker->Stop();
4740
4741 return did_respond() ? AlreadyResponded() : RespondLater();
4742 }
4743
OnReportData(const cc::FrameSequenceMetrics::CustomReportData & data)4744 void AutotestPrivateStopSmoothnessTrackingFunction::OnReportData(
4745 const cc::FrameSequenceMetrics::CustomReportData& data) {
4746 api::autotest_private::ThroughputTrackerAnimationData result_data;
4747 result_data.frames_expected = data.frames_expected;
4748 result_data.frames_produced = data.frames_produced;
4749 result_data.jank_count = data.jank_count;
4750
4751 Respond(ArgumentList(
4752 api::autotest_private::StopSmoothnessTracking::Results::Create(
4753 result_data)));
4754 }
4755
4756 ///////////////////////////////////////////////////////////////////////////////
4757 // AutotestPrivateWaitForAmbientPhotoAnimationFunction
4758 //////////////////////////////////////////////////////////////////////////////
4759
4760 AutotestPrivateWaitForAmbientPhotoAnimationFunction::
4761 AutotestPrivateWaitForAmbientPhotoAnimationFunction() = default;
4762
4763 AutotestPrivateWaitForAmbientPhotoAnimationFunction::
4764 ~AutotestPrivateWaitForAmbientPhotoAnimationFunction() = default;
4765
4766 ExtensionFunction::ResponseAction
Run()4767 AutotestPrivateWaitForAmbientPhotoAnimationFunction::Run() {
4768 std::unique_ptr<api::autotest_private::WaitForAmbientPhotoAnimation::Params>
4769 params(
4770 api::autotest_private::WaitForAmbientPhotoAnimation::Params::Create(
4771 *args_));
4772 EXTENSION_FUNCTION_VALIDATE(params);
4773
4774 // Wait for photo transition animation completed in ambient mode.
4775 ash::AutotestAmbientApi().WaitForPhotoTransitionAnimationCompleted(
4776 params->num_completions,
4777 base::BindOnce(&AutotestPrivateWaitForAmbientPhotoAnimationFunction::
4778 OnPhotoTransitionAnimationCompleted,
4779 this));
4780
4781 // Set up a timer to finish waiting after |timeout_s|.
4782 timeout_timer_.Start(
4783 FROM_HERE, base::TimeDelta::FromSeconds(params->timeout),
4784 base::BindOnce(
4785 &AutotestPrivateWaitForAmbientPhotoAnimationFunction::Timeout, this));
4786
4787 return did_respond() ? AlreadyResponded() : RespondLater();
4788 }
4789
4790 void AutotestPrivateWaitForAmbientPhotoAnimationFunction::
OnPhotoTransitionAnimationCompleted()4791 OnPhotoTransitionAnimationCompleted() {
4792 if (did_respond())
4793 return;
4794
4795 Respond(NoArguments());
4796 }
4797
Timeout()4798 void AutotestPrivateWaitForAmbientPhotoAnimationFunction::Timeout() {
4799 if (did_respond())
4800 return;
4801
4802 Respond(Error("No enough animations completed before time out."));
4803 }
4804
4805 ///////////////////////////////////////////////////////////////////////////////
4806 // AutotestPrivateDisableSwitchAccessDialogFunction
4807 //////////////////////////////////////////////////////////////////////////////
4808
4809 AutotestPrivateDisableSwitchAccessDialogFunction::
4810 AutotestPrivateDisableSwitchAccessDialogFunction() = default;
4811
4812 AutotestPrivateDisableSwitchAccessDialogFunction::
4813 ~AutotestPrivateDisableSwitchAccessDialogFunction() = default;
4814
4815 ExtensionFunction::ResponseAction
Run()4816 AutotestPrivateDisableSwitchAccessDialogFunction::Run() {
4817 auto* accessibility_controller = ash::AccessibilityController::Get();
4818 accessibility_controller
4819 ->DisableSwitchAccessDisableConfirmationDialogTesting();
4820 return RespondNow(NoArguments());
4821 }
4822
4823 ///////////////////////////////////////////////////////////////////////////////
4824 // AutotestPrivateDisableAutomationFunction
4825 //////////////////////////////////////////////////////////////////////////////
4826
4827 AutotestPrivateDisableAutomationFunction::
4828 AutotestPrivateDisableAutomationFunction() = default;
4829
4830 AutotestPrivateDisableAutomationFunction::
4831 ~AutotestPrivateDisableAutomationFunction() = default;
4832
4833 ExtensionFunction::ResponseAction
Run()4834 AutotestPrivateDisableAutomationFunction::Run() {
4835 AutomationManagerAura::GetInstance()->Disable();
4836 return RespondNow(NoArguments());
4837 }
4838
4839 ///////////////////////////////////////////////////////////////////////////////
4840 // AutotestPrivateStartThroughputTrackerDataCollectionFunction
4841 //////////////////////////////////////////////////////////////////////////////
4842
4843 AutotestPrivateStartThroughputTrackerDataCollectionFunction::
4844 AutotestPrivateStartThroughputTrackerDataCollectionFunction() = default;
4845
4846 AutotestPrivateStartThroughputTrackerDataCollectionFunction::
4847 ~AutotestPrivateStartThroughputTrackerDataCollectionFunction() = default;
4848
4849 ExtensionFunction::ResponseAction
Run()4850 AutotestPrivateStartThroughputTrackerDataCollectionFunction::Run() {
4851 ash::metrics_util::StartDataCollection();
4852 return RespondNow(NoArguments());
4853 }
4854
4855 ///////////////////////////////////////////////////////////////////////////////
4856 // AutotestPrivateStopThroughputTrackerDataCollectionFunction
4857 //////////////////////////////////////////////////////////////////////////////
4858
4859 AutotestPrivateStopThroughputTrackerDataCollectionFunction::
4860 AutotestPrivateStopThroughputTrackerDataCollectionFunction() = default;
4861
4862 AutotestPrivateStopThroughputTrackerDataCollectionFunction::
4863 ~AutotestPrivateStopThroughputTrackerDataCollectionFunction() = default;
4864
4865 ExtensionFunction::ResponseAction
Run()4866 AutotestPrivateStopThroughputTrackerDataCollectionFunction::Run() {
4867 auto collected_data = ash::metrics_util::StopDataCollection();
4868 std::vector<api::autotest_private::ThroughputTrackerAnimationData>
4869 result_data;
4870 for (const auto& data : collected_data) {
4871 api::autotest_private::ThroughputTrackerAnimationData animation_data;
4872 animation_data.frames_expected = data.frames_expected;
4873 animation_data.frames_produced = data.frames_produced;
4874 animation_data.jank_count = data.jank_count;
4875 result_data.emplace_back(std::move(animation_data));
4876 }
4877
4878 return RespondNow(
4879 ArgumentList(api::autotest_private::StopThroughputTrackerDataCollection::
4880 Results::Create(result_data)));
4881 }
4882
4883 ///////////////////////////////////////////////////////////////////////////////
4884 // AutotestPrivateAPI
4885 ///////////////////////////////////////////////////////////////////////////////
4886
4887 static base::LazyInstance<BrowserContextKeyedAPIFactory<AutotestPrivateAPI>>::
4888 DestructorAtExit g_autotest_private_api_factory = LAZY_INSTANCE_INITIALIZER;
4889
4890 // static
4891 BrowserContextKeyedAPIFactory<AutotestPrivateAPI>*
GetFactoryInstance()4892 AutotestPrivateAPI::GetFactoryInstance() {
4893 return g_autotest_private_api_factory.Pointer();
4894 }
4895
4896 template <>
4897 KeyedService*
BuildServiceInstanceFor(content::BrowserContext * context) const4898 BrowserContextKeyedAPIFactory<AutotestPrivateAPI>::BuildServiceInstanceFor(
4899 content::BrowserContext* context) const {
4900 return new AutotestPrivateAPI(context);
4901 }
4902
AutotestPrivateAPI(content::BrowserContext * context)4903 AutotestPrivateAPI::AutotestPrivateAPI(content::BrowserContext* context)
4904 : clipboard_observer_(this), browser_context_(context), test_mode_(false) {
4905 clipboard_observer_.Add(ui::ClipboardMonitor::GetInstance());
4906 }
4907
4908 AutotestPrivateAPI::~AutotestPrivateAPI() = default;
4909
OnClipboardDataChanged()4910 void AutotestPrivateAPI::OnClipboardDataChanged() {
4911 EventRouter* event_router = EventRouter::Get(browser_context_);
4912 if (!event_router)
4913 return;
4914
4915 std::unique_ptr<base::ListValue> event_args =
4916 std::make_unique<base::ListValue>();
4917 std::unique_ptr<Event> event(
4918 new Event(events::AUTOTESTPRIVATE_ON_CLIPBOARD_DATA_CHANGED,
4919 api::autotest_private::OnClipboardDataChanged::kEventName,
4920 std::move(event_args)));
4921 event_router->BroadcastEvent(std::move(event));
4922 }
4923
4924 } // namespace extensions
4925