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