| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h" |
| |
| #include <set> |
| #include <sstream> |
| #include <utility> |
| |
| #include "ash/public/cpp/app_types.h" |
| #include "ash/public/cpp/ash_pref_names.h" |
| #include "ash/public/cpp/autotest_private_api_utils.h" |
| #include "ash/public/cpp/desks_helper.h" |
| #include "ash/public/cpp/login_screen.h" |
| #include "ash/public/cpp/overview_test_api.h" |
| #include "ash/public/cpp/shelf_item.h" |
| #include "ash/public/cpp/shelf_model.h" |
| #include "ash/public/cpp/shelf_prefs.h" |
| #include "ash/public/cpp/shelf_types.h" |
| #include "ash/public/cpp/split_view_test_api.h" |
| #include "ash/public/cpp/tablet_mode.h" |
| #include "ash/public/cpp/window_properties.h" |
| #include "ash/public/mojom/constants.mojom.h" |
| #include "ash/rotator/screen_rotation_animator.h" |
| #include "ash/shell.h" |
| #include "ash/wm/wm_event.h" |
| #include "base/base64.h" |
| #include "base/bind.h" |
| #include "base/feature_list.h" |
| #include "base/json/json_reader.h" |
| #include "base/lazy_instance.h" |
| #include "base/metrics/histogram_base.h" |
| #include "base/metrics/histogram_samples.h" |
| #include "base/metrics/statistics_recorder.h" |
| #include "base/run_loop.h" |
| #include "base/scoped_observer.h" |
| #include "base/strings/strcat.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/task/post_task.h" |
| #include "base/threading/thread_task_runner_handle.h" |
| #include "base/time/time.h" |
| #include "base/values.h" |
| #include "build/build_config.h" |
| #include "chrome/browser/apps/app_service/app_service_proxy.h" |
| #include "chrome/browser/apps/app_service/app_service_proxy_factory.h" |
| #include "chrome/browser/browser_process.h" |
| #include "chrome/browser/browser_process_platform_part.h" |
| #include "chrome/browser/chromeos/arc/arc_util.h" |
| #include "chrome/browser/chromeos/arc/session/arc_session_manager.h" |
| #include "chrome/browser/chromeos/arc/tracing/arc_app_performance_tracing.h" |
| #include "chrome/browser/chromeos/arc/tracing/arc_app_performance_tracing_session.h" |
| #include "chrome/browser/chromeos/assistant/assistant_util.h" |
| #include "chrome/browser/chromeos/crostini/crostini_export_import.h" |
| #include "chrome/browser/chromeos/crostini/crostini_installer.h" |
| #include "chrome/browser/chromeos/crostini/crostini_manager.h" |
| #include "chrome/browser/chromeos/crostini/crostini_pref_names.h" |
| #include "chrome/browser/chromeos/crostini/crostini_registry_service.h" |
| #include "chrome/browser/chromeos/crostini/crostini_registry_service_factory.h" |
| #include "chrome/browser/chromeos/crostini/crostini_util.h" |
| #include "chrome/browser/chromeos/file_manager/path_util.h" |
| #include "chrome/browser/chromeos/login/lock/screen_locker.h" |
| #include "chrome/browser/chromeos/printing/cups_printers_manager.h" |
| #include "chrome/browser/chromeos/system/input_device_settings.h" |
| #include "chrome/browser/extensions/extension_action.h" |
| #include "chrome/browser/extensions/extension_action_manager.h" |
| #include "chrome/browser/extensions/extension_service.h" |
| #include "chrome/browser/lifetime/application_lifetime.h" |
| #include "chrome/browser/policy/policy_conversions.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/profiles/profile_manager.h" |
| #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h" |
| #include "chrome/browser/ui/app_list/arc/arc_app_utils.h" |
| #include "chrome/browser/ui/ash/assistant/assistant_client.h" |
| #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h" |
| #include "chrome/browser/ui/ash/launcher/shelf_spinner_controller.h" |
| #include "chrome/browser/ui/views/crostini/crostini_installer_view.h" |
| #include "chrome/browser/ui/views/crostini/crostini_uninstaller_view.h" |
| #include "chrome/common/chrome_features.h" |
| #include "chrome/common/extensions/api/autotest_private.h" |
| #include "chrome/common/extensions/api/extension_action/action_info.h" |
| #include "chrome/common/pref_names.h" |
| #include "chrome/services/app_service/public/mojom/types.mojom.h" |
| #include "chromeos/dbus/dbus_thread_manager.h" |
| #include "chromeos/dbus/session_manager/session_manager_client.h" |
| #include "chromeos/printing/printer_configuration.h" |
| #include "chromeos/services/assistant/public/cpp/assistant_prefs.h" |
| #include "chromeos/services/assistant/public/mojom/assistant.mojom.h" |
| #include "chromeos/services/machine_learning/public/cpp/service_connection.h" |
| #include "components/arc/arc_prefs.h" |
| #include "components/arc/metrics/arc_metrics_constants.h" |
| #include "components/policy/core/common/policy_service.h" |
| #include "components/user_manager/user_manager.h" |
| #include "content/public/browser/histogram_fetcher.h" |
| #include "extensions/browser/event_router.h" |
| #include "extensions/browser/extension_function_registry.h" |
| #include "extensions/browser/extension_registry.h" |
| #include "extensions/browser/extension_system.h" |
| #include "extensions/browser/extension_util.h" |
| #include "extensions/common/manifest_handlers/background_info.h" |
| #include "extensions/common/manifest_handlers/options_page_info.h" |
| #include "extensions/common/permissions/api_permission_set.h" |
| #include "extensions/common/permissions/permission_set.h" |
| #include "extensions/common/permissions/permissions_data.h" |
| #include "mojo/public/cpp/bindings/associated_binding.h" |
| #include "mojo/public/cpp/bindings/receiver.h" |
| #include "net/base/filename_util.h" |
| #include "ui/aura/client/aura_constants.h" |
| #include "ui/aura/window.h" |
| #include "ui/aura/window_observer.h" |
| #include "ui/base/clipboard/clipboard.h" |
| #include "ui/base/clipboard/scoped_clipboard_writer.h" |
| #include "ui/base/ime/ime_bridge.h" |
| #include "ui/base/ui_base_features.h" |
| #include "ui/display/display.h" |
| #include "ui/display/screen.h" |
| #include "ui/message_center/message_center.h" |
| #include "ui/message_center/notification_list.h" |
| #include "ui/message_center/public/cpp/notification.h" |
| #include "ui/message_center/public/cpp/notification_types.h" |
| #include "ui/views/widget/widget.h" |
| #include "ui/wm/core/window_util.h" |
| |
| namespace extensions { |
| namespace { |
| |
| using chromeos::PrinterClass; |
| |
| constexpr char kCrostiniNotAvailableForCurrentUserError[] = |
| "Crostini is not available for the current user"; |
| |
| // Amount of time to give other processes to report their histograms. |
| constexpr base::TimeDelta kHistogramsRefreshTimeout = |
| base::TimeDelta::FromSeconds(10); |
| |
| int AccessArray(const volatile int arr[], const volatile int* index) { |
| return arr[*index]; |
| } |
| |
| std::unique_ptr<base::ListValue> GetHostPermissions(const Extension* ext, |
| bool effective_perm) { |
| const PermissionsData* permissions_data = ext->permissions_data(); |
| const URLPatternSet& pattern_set = |
| effective_perm ? static_cast<const URLPatternSet&>( |
| permissions_data->GetEffectiveHostPermissions( |
| PermissionsData::EffectiveHostPermissionsMode:: |
| kIncludeTabSpecific)) |
| : permissions_data->active_permissions().explicit_hosts(); |
| |
| auto permissions = std::make_unique<base::ListValue>(); |
| for (URLPatternSet::const_iterator perm = pattern_set.begin(); |
| perm != pattern_set.end(); ++perm) { |
| permissions->AppendString(perm->GetAsString()); |
| } |
| |
| return permissions; |
| } |
| |
| std::unique_ptr<base::ListValue> GetAPIPermissions(const Extension* ext) { |
| auto permissions = std::make_unique<base::ListValue>(); |
| std::set<std::string> perm_list = |
| ext->permissions_data()->active_permissions().GetAPIsAsStrings(); |
| for (std::set<std::string>::const_iterator perm = perm_list.begin(); |
| perm != perm_list.end(); ++perm) { |
| permissions->AppendString(*perm); |
| } |
| return permissions; |
| } |
| |
| bool IsTestMode(content::BrowserContext* context) { |
| return AutotestPrivateAPI::GetFactoryInstance()->Get(context)->test_mode(); |
| } |
| |
| std::string ConvertToString(message_center::NotificationType type) { |
| switch (type) { |
| case message_center::NOTIFICATION_TYPE_SIMPLE: |
| return "simple"; |
| case message_center::NOTIFICATION_TYPE_BASE_FORMAT: |
| return "base_format"; |
| case message_center::NOTIFICATION_TYPE_IMAGE: |
| return "image"; |
| case message_center::NOTIFICATION_TYPE_MULTIPLE: |
| return "multiple"; |
| case message_center::NOTIFICATION_TYPE_PROGRESS: |
| return "progress"; |
| case message_center::NOTIFICATION_TYPE_CUSTOM: |
| return "custom"; |
| } |
| return "unknown"; |
| } |
| |
| std::unique_ptr<base::DictionaryValue> MakeDictionaryFromNotification( |
| const message_center::Notification& notification) { |
| auto result = std::make_unique<base::DictionaryValue>(); |
| result->SetString("id", notification.id()); |
| result->SetString("type", ConvertToString(notification.type())); |
| result->SetString("title", notification.title()); |
| result->SetString("message", notification.message()); |
| result->SetInteger("priority", notification.priority()); |
| result->SetInteger("progress", notification.progress()); |
| return result; |
| } |
| |
| std::string GetPrinterType(PrinterClass type) { |
| switch (type) { |
| case PrinterClass::kSaved: |
| return "configured"; |
| case PrinterClass::kEnterprise: |
| return "enterprise"; |
| case PrinterClass::kAutomatic: |
| return "automatic"; |
| case PrinterClass::kDiscovered: |
| return "discovered"; |
| default: |
| return "unknown"; |
| } |
| } |
| |
| api::autotest_private::ShelfItemType GetShelfItemType(ash::ShelfItemType type) { |
| switch (type) { |
| case ash::TYPE_APP: |
| return api::autotest_private::ShelfItemType::SHELF_ITEM_TYPE_APP; |
| case ash::TYPE_PINNED_APP: |
| return api::autotest_private::ShelfItemType::SHELF_ITEM_TYPE_PINNEDAPP; |
| case ash::TYPE_BROWSER_SHORTCUT: |
| return api::autotest_private::ShelfItemType:: |
| SHELF_ITEM_TYPE_BROWSERSHORTCUT; |
| case ash::TYPE_DIALOG: |
| return api::autotest_private::ShelfItemType::SHELF_ITEM_TYPE_DIALOG; |
| case ash::TYPE_UNDEFINED: |
| return api::autotest_private::ShelfItemType::SHELF_ITEM_TYPE_NONE; |
| } |
| NOTREACHED(); |
| return api::autotest_private::ShelfItemType::SHELF_ITEM_TYPE_NONE; |
| } |
| |
| api::autotest_private::ShelfItemStatus GetShelfItemStatus( |
| ash::ShelfItemStatus status) { |
| switch (status) { |
| case ash::STATUS_CLOSED: |
| return api::autotest_private::ShelfItemStatus::SHELF_ITEM_STATUS_CLOSED; |
| case ash::STATUS_RUNNING: |
| return api::autotest_private::ShelfItemStatus::SHELF_ITEM_STATUS_RUNNING; |
| case ash::STATUS_ATTENTION: |
| return api::autotest_private::ShelfItemStatus:: |
| SHELF_ITEM_STATUS_ATTENTION; |
| } |
| NOTREACHED(); |
| return api::autotest_private::ShelfItemStatus::SHELF_ITEM_STATUS_NONE; |
| } |
| |
| api::autotest_private::AppType GetAppType(apps::mojom::AppType type) { |
| switch (type) { |
| case apps::mojom::AppType::kArc: |
| return api::autotest_private::AppType::APP_TYPE_ARC; |
| case apps::mojom::AppType::kBuiltIn: |
| return api::autotest_private::AppType::APP_TYPE_BUILTIN; |
| case apps::mojom::AppType::kCrostini: |
| return api::autotest_private::AppType::APP_TYPE_CROSTINI; |
| case apps::mojom::AppType::kExtension: |
| return api::autotest_private::AppType::APP_TYPE_EXTENSION; |
| case apps::mojom::AppType::kWeb: |
| return api::autotest_private::AppType::APP_TYPE_WEB; |
| case apps::mojom::AppType::kUnknown: |
| return api::autotest_private::AppType::APP_TYPE_NONE; |
| } |
| NOTREACHED(); |
| return api::autotest_private::AppType::APP_TYPE_NONE; |
| } |
| |
| api::autotest_private::AppWindowType GetAppWindowType(ash::AppType type) { |
| switch (type) { |
| case ash::AppType::ARC_APP: |
| return api::autotest_private::AppWindowType::APP_WINDOW_TYPE_ARCAPP; |
| case ash::AppType::SYSTEM_APP: |
| return api::autotest_private::AppWindowType::APP_WINDOW_TYPE_SYSTEMAPP; |
| case ash::AppType::CROSTINI_APP: |
| return api::autotest_private::AppWindowType::APP_WINDOW_TYPE_CROSTINIAPP; |
| case ash::AppType::CHROME_APP: |
| return api::autotest_private::AppWindowType::APP_WINDOW_TYPE_EXTENSIONAPP; |
| case ash::AppType::BROWSER: |
| return api::autotest_private::AppWindowType::APP_WINDOW_TYPE_BROWSER; |
| case ash::AppType::NON_APP: |
| return api::autotest_private::AppWindowType::APP_WINDOW_TYPE_NONE; |
| // TODO(oshima): Investigate if we want to have "extension" type. |
| } |
| NOTREACHED(); |
| return api::autotest_private::AppWindowType::APP_WINDOW_TYPE_NONE; |
| } |
| |
| api::autotest_private::AppReadiness GetAppReadiness( |
| apps::mojom::Readiness readiness) { |
| switch (readiness) { |
| case apps::mojom::Readiness::kReady: |
| return api::autotest_private::AppReadiness::APP_READINESS_READY; |
| case apps::mojom::Readiness::kDisabledByBlacklist: |
| return api::autotest_private::AppReadiness:: |
| APP_READINESS_DISABLEDBYBLACKLIST; |
| case apps::mojom::Readiness::kDisabledByPolicy: |
| return api::autotest_private::AppReadiness:: |
| APP_READINESS_DISABLEDBYPOLICY; |
| case apps::mojom::Readiness::kDisabledByUser: |
| return api::autotest_private::AppReadiness::APP_READINESS_DISABLEDBYUSER; |
| case apps::mojom::Readiness::kTerminated: |
| return api::autotest_private::AppReadiness::APP_READINESS_TERMINATED; |
| case apps::mojom::Readiness::kUninstalledByUser: |
| return api::autotest_private::AppReadiness:: |
| APP_READINESS_UNINSTALLEDBYUSER; |
| case apps::mojom::Readiness::kUnknown: |
| return api::autotest_private::AppReadiness::APP_READINESS_NONE; |
| } |
| NOTREACHED(); |
| return api::autotest_private::AppReadiness::APP_READINESS_NONE; |
| } |
| |
| std::unique_ptr<bool> ConvertMojomOptionalBool( |
| apps::mojom::OptionalBool optional) { |
| switch (optional) { |
| case apps::mojom::OptionalBool::kTrue: |
| return std::make_unique<bool>(true); |
| case apps::mojom::OptionalBool::kFalse: |
| return std::make_unique<bool>(false); |
| case apps::mojom::OptionalBool::kUnknown: |
| return nullptr; |
| } |
| NOTREACHED(); |
| return nullptr; |
| } |
| |
| // Helper function to set whitelisted user pref based on |pref_name| with any |
| // specific pref validations. Returns error messages if any. |
| std::string SetWhitelistedPref(Profile* profile, |
| const std::string& pref_name, |
| const base::Value& value) { |
| if (pref_name == chromeos::assistant::prefs::kAssistantEnabled || |
| pref_name == chromeos::assistant::prefs::kAssistantHotwordEnabled) { |
| DCHECK(value.is_bool()); |
| ash::mojom::AssistantAllowedState allowed_state = |
| assistant::IsAssistantAllowedForProfile(profile); |
| if (allowed_state != ash::mojom::AssistantAllowedState::ALLOWED) { |
| return base::StringPrintf("Assistant not allowed - state: %d", |
| allowed_state); |
| } |
| } else if (pref_name == ash::prefs::kAccessibilityVirtualKeyboardEnabled) { |
| DCHECK(value.is_bool()); |
| } else if (pref_name == prefs::kLanguagePreloadEngines) { |
| DCHECK(value.is_string()); |
| } else { |
| return "The pref " + pref_name + "is not whitelisted."; |
| } |
| |
| // Set value for the specified user pref after validation. |
| profile->GetPrefs()->Set(pref_name, value); |
| |
| return std::string(); |
| } |
| |
| // Returns the ARC app window that associates with |package_name|. Note there |
| // might be more than 1 windows that have the same package name. This function |
| // just returns the first window it finds. |
| aura::Window* GetArcAppWindow(const std::string& package_name) { |
| for (auto* window : ChromeLauncherController::instance()->GetArcWindows()) { |
| std::string* pkg_name = window->GetProperty(ash::kArcPackageNameKey); |
| if (pkg_name && *pkg_name == package_name) |
| return window; |
| } |
| return nullptr; |
| } |
| |
| // Gets expected window state type according to |event_type|. |
| ash::WindowStateType GetExpectedWindowState( |
| api::autotest_private::WMEventType event_type) { |
| switch (event_type) { |
| case api::autotest_private::WMEventType::WM_EVENT_TYPE_WMEVENTNORMAL: |
| return ash::WindowStateType::kNormal; |
| case api::autotest_private::WMEventType::WM_EVENT_TYPE_WMEVENTMAXIMIZE: |
| return ash::WindowStateType::kMaximized; |
| case api::autotest_private::WMEventType::WM_EVENT_TYPE_WMEVENTMINIMIZE: |
| return ash::WindowStateType::kMinimized; |
| case api::autotest_private::WMEventType::WM_EVENT_TYPE_WMEVENTFULLSCREEN: |
| return ash::WindowStateType::kFullscreen; |
| case api::autotest_private::WMEventType::WM_EVENT_TYPE_WMEVENTSNAPLEFT: |
| return ash::WindowStateType::kLeftSnapped; |
| case api::autotest_private::WMEventType::WM_EVENT_TYPE_WMEVENTSNAPRIGHT: |
| return ash::WindowStateType::kRightSnapped; |
| default: |
| NOTREACHED(); |
| return ash::WindowStateType::kNormal; |
| } |
| } |
| |
| ash::WMEventType ToWMEventType(api::autotest_private::WMEventType event_type) { |
| switch (event_type) { |
| case api::autotest_private::WMEventType::WM_EVENT_TYPE_WMEVENTNORMAL: |
| return ash::WMEventType::WM_EVENT_NORMAL; |
| case api::autotest_private::WMEventType::WM_EVENT_TYPE_WMEVENTMAXIMIZE: |
| return ash::WMEventType::WM_EVENT_MAXIMIZE; |
| case api::autotest_private::WMEventType::WM_EVENT_TYPE_WMEVENTMINIMIZE: |
| return ash::WMEventType::WM_EVENT_MINIMIZE; |
| case api::autotest_private::WMEventType::WM_EVENT_TYPE_WMEVENTFULLSCREEN: |
| return ash::WMEventType::WM_EVENT_FULLSCREEN; |
| case api::autotest_private::WMEventType::WM_EVENT_TYPE_WMEVENTSNAPLEFT: |
| return ash::WMEventType::WM_EVENT_SNAP_LEFT; |
| case api::autotest_private::WMEventType::WM_EVENT_TYPE_WMEVENTSNAPRIGHT: |
| return ash::WMEventType::WM_EVENT_SNAP_RIGHT; |
| default: |
| NOTREACHED(); |
| return ash::WMEventType::WM_EVENT_NORMAL; |
| } |
| } |
| |
| api::autotest_private::WindowStateType ToWindowStateType( |
| ash::WindowStateType state_type) { |
| switch (state_type) { |
| case ash::WindowStateType::kNormal: |
| return api::autotest_private::WindowStateType::WINDOW_STATE_TYPE_NORMAL; |
| case ash::WindowStateType::kMinimized: |
| return api::autotest_private::WindowStateType:: |
| WINDOW_STATE_TYPE_MINIMIZED; |
| case ash::WindowStateType::kMaximized: |
| return api::autotest_private::WindowStateType:: |
| WINDOW_STATE_TYPE_MAXIMIZED; |
| case ash::WindowStateType::kFullscreen: |
| return api::autotest_private::WindowStateType:: |
| WINDOW_STATE_TYPE_FULLSCREEN; |
| case ash::WindowStateType::kLeftSnapped: |
| return api::autotest_private::WindowStateType:: |
| WINDOW_STATE_TYPE_LEFTSNAPPED; |
| case ash::WindowStateType::kRightSnapped: |
| return api::autotest_private::WindowStateType:: |
| WINDOW_STATE_TYPE_RIGHTSNAPPED; |
| case ash::WindowStateType::kPip: |
| return api::autotest_private::WindowStateType::WINDOW_STATE_TYPE_PIP; |
| default: |
| NOTREACHED(); |
| return api::autotest_private::WindowStateType::WINDOW_STATE_TYPE_NONE; |
| } |
| } |
| |
| std::string GetPngDataAsString(scoped_refptr<base::RefCountedMemory> png_data) { |
| // Base64 encode the result so we can return it as a string. |
| std::string base64Png(png_data->front(), |
| png_data->front() + png_data->size()); |
| base::Base64Encode(base64Png, &base64Png); |
| return base64Png; |
| } |
| |
| display::Display::Rotation ToRotation( |
| api::autotest_private::RotationType rotation) { |
| switch (rotation) { |
| case api::autotest_private::RotationType::ROTATION_TYPE_ROTATE0: |
| return display::Display::ROTATE_0; |
| case api::autotest_private::RotationType::ROTATION_TYPE_ROTATE90: |
| return display::Display::ROTATE_90; |
| case api::autotest_private::RotationType::ROTATION_TYPE_ROTATE180: |
| return display::Display::ROTATE_180; |
| case api::autotest_private::RotationType::ROTATION_TYPE_ROTATE270: |
| return display::Display::ROTATE_270; |
| case api::autotest_private::RotationType::ROTATION_TYPE_NONE: |
| break; |
| } |
| NOTREACHED(); |
| return display::Display::ROTATE_0; |
| } |
| |
| api::autotest_private::Bounds ToBoundsDictionary(const gfx::Rect& bounds) { |
| api::autotest_private::Bounds result; |
| result.left = bounds.x(); |
| result.top = bounds.y(); |
| result.width = bounds.width(); |
| result.height = bounds.height(); |
| return result; |
| } |
| |
| aura::Window* FindAppWindowById(const int64_t id) { |
| auto list = ash::GetAppWindowList(); |
| auto iter = |
| std::find_if(list.begin(), list.end(), |
| [id](aura::Window* window) { return window->id() == id; }); |
| if (iter == list.end()) |
| return nullptr; |
| return *iter; |
| } |
| |
| } // namespace |
| |
| class WindowStateChangeObserver : public aura::WindowObserver { |
| public: |
| WindowStateChangeObserver(aura::Window* window, |
| ash::WindowStateType expected_type, |
| base::OnceCallback<void(bool)> callback) |
| : expected_type_(expected_type), callback_(std::move(callback)) { |
| DCHECK_NE(window->GetProperty(ash::kWindowStateTypeKey), expected_type_); |
| scoped_observer_.Add(window); |
| } |
| ~WindowStateChangeObserver() override {} |
| |
| // aura::WindowObserver: |
| void OnWindowPropertyChanged(aura::Window* window, |
| const void* key, |
| intptr_t old) override { |
| DCHECK(scoped_observer_.IsObserving(window)); |
| if (key == ash::kWindowStateTypeKey && |
| window->GetProperty(ash::kWindowStateTypeKey) == expected_type_) { |
| scoped_observer_.RemoveAll(); |
| std::move(callback_).Run(/*success=*/true); |
| } |
| } |
| |
| void OnWindowDestroying(aura::Window* window) override { |
| DCHECK(scoped_observer_.IsObserving(window)); |
| scoped_observer_.RemoveAll(); |
| std::move(callback_).Run(/*success=*/false); |
| } |
| |
| private: |
| ash::WindowStateType expected_type_; |
| ScopedObserver<aura::Window, aura::WindowObserver> scoped_observer_{this}; |
| base::OnceCallback<void(bool)> callback_; |
| |
| DISALLOW_COPY_AND_ASSIGN(WindowStateChangeObserver); |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateInitializeEventsFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateInitializeEventsFunction:: |
| ~AutotestPrivateInitializeEventsFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateInitializeEventsFunction::Run() { |
| // AutotestPrivateAPI is lazily initialized, but needs to be created before |
| // any of its events can be fired, so we get the instance here and return. |
| AutotestPrivateAPI::GetFactoryInstance()->Get(browser_context()); |
| return RespondNow(NoArguments()); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateLogoutFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateLogoutFunction::~AutotestPrivateLogoutFunction() = default; |
| |
| ExtensionFunction::ResponseAction AutotestPrivateLogoutFunction::Run() { |
| DVLOG(1) << "AutotestPrivateLogoutFunction"; |
| if (!IsTestMode(browser_context())) |
| chrome::AttemptUserExit(); |
| return RespondNow(NoArguments()); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateRestartFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateRestartFunction::~AutotestPrivateRestartFunction() = default; |
| |
| ExtensionFunction::ResponseAction AutotestPrivateRestartFunction::Run() { |
| DVLOG(1) << "AutotestPrivateRestartFunction"; |
| if (!IsTestMode(browser_context())) |
| chrome::AttemptRestart(); |
| return RespondNow(NoArguments()); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateShutdownFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateShutdownFunction::~AutotestPrivateShutdownFunction() = default; |
| |
| ExtensionFunction::ResponseAction AutotestPrivateShutdownFunction::Run() { |
| std::unique_ptr<api::autotest_private::Shutdown::Params> params( |
| api::autotest_private::Shutdown::Params::Create(*args_)); |
| EXTENSION_FUNCTION_VALIDATE(params.get()); |
| DVLOG(1) << "AutotestPrivateShutdownFunction " << params->force; |
| |
| if (!IsTestMode(browser_context())) |
| chrome::AttemptExit(); |
| return RespondNow(NoArguments()); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateLoginStatusFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateLoginStatusFunction::~AutotestPrivateLoginStatusFunction() = |
| default; |
| |
| ExtensionFunction::ResponseAction AutotestPrivateLoginStatusFunction::Run() { |
| DVLOG(1) << "AutotestPrivateLoginStatusFunction"; |
| auto result = std::make_unique<base::DictionaryValue>(); |
| const user_manager::UserManager* user_manager = |
| user_manager::UserManager::Get(); |
| |
| // default_screen_locker()->locked() is set when the UI is ready, so this |
| // tells us both views based lockscreen UI and screenlocker are ready. |
| const bool is_screen_locked = |
| !!chromeos::ScreenLocker::default_screen_locker() && |
| chromeos::ScreenLocker::default_screen_locker()->locked(); |
| |
| if (user_manager) { |
| result->SetBoolean("isLoggedIn", user_manager->IsUserLoggedIn()); |
| result->SetBoolean("isOwner", user_manager->IsCurrentUserOwner()); |
| result->SetBoolean("isScreenLocked", is_screen_locked); |
| result->SetBoolean("isReadyForPassword", |
| ash::LoginScreen::Get()->IsReadyForPassword()); |
| if (user_manager->IsUserLoggedIn()) { |
| result->SetBoolean("isRegularUser", |
| user_manager->IsLoggedInAsUserWithGaiaAccount()); |
| result->SetBoolean("isGuest", user_manager->IsLoggedInAsGuest()); |
| result->SetBoolean("isKiosk", user_manager->IsLoggedInAsKioskApp()); |
| |
| const user_manager::User* user = user_manager->GetActiveUser(); |
| result->SetString("email", user->GetAccountId().GetUserEmail()); |
| result->SetString("displayEmail", user->display_email()); |
| |
| std::string user_image; |
| switch (user->image_index()) { |
| case user_manager::User::USER_IMAGE_EXTERNAL: |
| user_image = "file"; |
| break; |
| |
| case user_manager::User::USER_IMAGE_PROFILE: |
| user_image = "profile"; |
| break; |
| |
| default: |
| user_image = base::NumberToString(user->image_index()); |
| break; |
| } |
| result->SetString("userImage", user_image); |
| } |
| } |
| return RespondNow(OneArgument(std::move(result))); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateLockScreenFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateLockScreenFunction::~AutotestPrivateLockScreenFunction() = |
| default; |
| |
| ExtensionFunction::ResponseAction AutotestPrivateLockScreenFunction::Run() { |
| DVLOG(1) << "AutotestPrivateLockScreenFunction"; |
| |
| chromeos::SessionManagerClient::Get()->RequestLockScreen(); |
| return RespondNow(NoArguments()); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateGetAllEnterprisePoliciesFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateGetAllEnterprisePoliciesFunction:: |
| ~AutotestPrivateGetAllEnterprisePoliciesFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateGetAllEnterprisePoliciesFunction::Run() { |
| DVLOG(1) << "AutotestPrivateGetAllEnterprisePoliciesFunction"; |
| |
| base::Value all_policies_array = policy::DictionaryPolicyConversions() |
| .WithBrowserContext(browser_context()) |
| .EnableDeviceLocalAccountPolicies(true) |
| .EnableDeviceInfo(true) |
| .ToValue(); |
| |
| return RespondNow(OneArgument( |
| base::Value::ToUniquePtrValue(std::move(all_policies_array)))); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateRefreshEnterprisePoliciesFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateRefreshEnterprisePoliciesFunction:: |
| ~AutotestPrivateRefreshEnterprisePoliciesFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateRefreshEnterprisePoliciesFunction::Run() { |
| DVLOG(1) << "AutotestPrivateRefreshEnterprisePoliciesFunction"; |
| |
| g_browser_process->policy_service()->RefreshPolicies(base::Bind( |
| &AutotestPrivateRefreshEnterprisePoliciesFunction::RefreshDone, this)); |
| return RespondLater(); |
| } |
| |
| void AutotestPrivateRefreshEnterprisePoliciesFunction::RefreshDone() { |
| Respond(NoArguments()); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateGetExtensionsInfoFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateGetExtensionsInfoFunction:: |
| ~AutotestPrivateGetExtensionsInfoFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateGetExtensionsInfoFunction::Run() { |
| DVLOG(1) << "AutotestPrivateGetExtensionsInfoFunction"; |
| |
| ExtensionService* service = |
| ExtensionSystem::Get(browser_context())->extension_service(); |
| ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context()); |
| const ExtensionSet& extensions = registry->enabled_extensions(); |
| const ExtensionSet& disabled_extensions = registry->disabled_extensions(); |
| ExtensionActionManager* extension_action_manager = |
| ExtensionActionManager::Get(browser_context()); |
| |
| auto extensions_values = std::make_unique<base::ListValue>(); |
| ExtensionList all; |
| all.insert(all.end(), extensions.begin(), extensions.end()); |
| all.insert(all.end(), disabled_extensions.begin(), disabled_extensions.end()); |
| for (ExtensionList::const_iterator it = all.begin(); it != all.end(); ++it) { |
| const Extension* extension = it->get(); |
| std::string id = extension->id(); |
| std::unique_ptr<base::DictionaryValue> extension_value( |
| new base::DictionaryValue); |
| extension_value->SetString("id", id); |
| extension_value->SetString("version", extension->VersionString()); |
| extension_value->SetString("name", extension->name()); |
| extension_value->SetString("publicKey", extension->public_key()); |
| extension_value->SetString("description", extension->description()); |
| extension_value->SetString( |
| "backgroundUrl", BackgroundInfo::GetBackgroundURL(extension).spec()); |
| extension_value->SetString( |
| "optionsUrl", OptionsPageInfo::GetOptionsPage(extension).spec()); |
| |
| extension_value->Set("hostPermissions", |
| GetHostPermissions(extension, false)); |
| extension_value->Set("effectiveHostPermissions", |
| GetHostPermissions(extension, true)); |
| extension_value->Set("apiPermissions", GetAPIPermissions(extension)); |
| |
| Manifest::Location location = extension->location(); |
| extension_value->SetBoolean("isComponent", location == Manifest::COMPONENT); |
| extension_value->SetBoolean("isInternal", location == Manifest::INTERNAL); |
| extension_value->SetBoolean("isUserInstalled", |
| location == Manifest::INTERNAL || |
| Manifest::IsUnpackedLocation(location)); |
| extension_value->SetBoolean("isEnabled", service->IsExtensionEnabled(id)); |
| extension_value->SetBoolean( |
| "allowedInIncognito", util::IsIncognitoEnabled(id, browser_context())); |
| const ExtensionAction* action = |
| extension_action_manager->GetExtensionAction(*extension); |
| extension_value->SetBoolean( |
| "hasPageAction", |
| action && action->action_type() == ActionInfo::TYPE_PAGE); |
| |
| extensions_values->Append(std::move(extension_value)); |
| } |
| |
| std::unique_ptr<base::DictionaryValue> return_value( |
| new base::DictionaryValue); |
| return_value->Set("extensions", std::move(extensions_values)); |
| return RespondNow(OneArgument(std::move(return_value))); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateSimulateAsanMemoryBugFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateSimulateAsanMemoryBugFunction:: |
| ~AutotestPrivateSimulateAsanMemoryBugFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateSimulateAsanMemoryBugFunction::Run() { |
| DVLOG(1) << "AutotestPrivateSimulateAsanMemoryBugFunction"; |
| |
| if (!IsTestMode(browser_context())) { |
| // This array is volatile not to let compiler optimize us out. |
| volatile int testarray[3] = {0, 0, 0}; |
| |
| // Cause Address Sanitizer to abort this process. |
| volatile int index = 5; |
| AccessArray(testarray, &index); |
| } |
| return RespondNow(NoArguments()); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateSetTouchpadSensitivityFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateSetTouchpadSensitivityFunction:: |
| ~AutotestPrivateSetTouchpadSensitivityFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateSetTouchpadSensitivityFunction::Run() { |
| std::unique_ptr<api::autotest_private::SetTouchpadSensitivity::Params> params( |
| api::autotest_private::SetTouchpadSensitivity::Params::Create(*args_)); |
| EXTENSION_FUNCTION_VALIDATE(params.get()); |
| DVLOG(1) << "AutotestPrivateSetTouchpadSensitivityFunction " << params->value; |
| |
| chromeos::system::InputDeviceSettings::Get()->SetTouchpadSensitivity( |
| params->value); |
| return RespondNow(NoArguments()); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateSetTapToClickFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateSetTapToClickFunction::~AutotestPrivateSetTapToClickFunction() = |
| default; |
| |
| ExtensionFunction::ResponseAction AutotestPrivateSetTapToClickFunction::Run() { |
| std::unique_ptr<api::autotest_private::SetTapToClick::Params> params( |
| api::autotest_private::SetTapToClick::Params::Create(*args_)); |
| EXTENSION_FUNCTION_VALIDATE(params.get()); |
| DVLOG(1) << "AutotestPrivateSetTapToClickFunction " << params->enabled; |
| |
| chromeos::system::InputDeviceSettings::Get()->SetTapToClick(params->enabled); |
| return RespondNow(NoArguments()); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateSetThreeFingerClickFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateSetThreeFingerClickFunction:: |
| ~AutotestPrivateSetThreeFingerClickFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateSetThreeFingerClickFunction::Run() { |
| std::unique_ptr<api::autotest_private::SetThreeFingerClick::Params> params( |
| api::autotest_private::SetThreeFingerClick::Params::Create(*args_)); |
| EXTENSION_FUNCTION_VALIDATE(params.get()); |
| DVLOG(1) << "AutotestPrivateSetThreeFingerClickFunction " << params->enabled; |
| |
| chromeos::system::InputDeviceSettings::Get()->SetThreeFingerClick( |
| params->enabled); |
| return RespondNow(NoArguments()); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateSetTapDraggingFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateSetTapDraggingFunction:: |
| ~AutotestPrivateSetTapDraggingFunction() = default; |
| |
| ExtensionFunction::ResponseAction AutotestPrivateSetTapDraggingFunction::Run() { |
| std::unique_ptr<api::autotest_private::SetTapDragging::Params> params( |
| api::autotest_private::SetTapDragging::Params::Create(*args_)); |
| EXTENSION_FUNCTION_VALIDATE(params.get()); |
| DVLOG(1) << "AutotestPrivateSetTapDraggingFunction " << params->enabled; |
| |
| chromeos::system::InputDeviceSettings::Get()->SetTapDragging(params->enabled); |
| return RespondNow(NoArguments()); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateSetNaturalScrollFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateSetNaturalScrollFunction:: |
| ~AutotestPrivateSetNaturalScrollFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateSetNaturalScrollFunction::Run() { |
| std::unique_ptr<api::autotest_private::SetNaturalScroll::Params> params( |
| api::autotest_private::SetNaturalScroll::Params::Create(*args_)); |
| EXTENSION_FUNCTION_VALIDATE(params.get()); |
| DVLOG(1) << "AutotestPrivateSetNaturalScrollFunction " << params->enabled; |
| |
| chromeos::system::InputDeviceSettings::Get()->SetNaturalScroll( |
| params->enabled); |
| return RespondNow(NoArguments()); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateSetMouseSensitivityFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateSetMouseSensitivityFunction:: |
| ~AutotestPrivateSetMouseSensitivityFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateSetMouseSensitivityFunction::Run() { |
| std::unique_ptr<api::autotest_private::SetMouseSensitivity::Params> params( |
| api::autotest_private::SetMouseSensitivity::Params::Create(*args_)); |
| EXTENSION_FUNCTION_VALIDATE(params.get()); |
| DVLOG(1) << "AutotestPrivateSetMouseSensitivityFunction " << params->value; |
| |
| chromeos::system::InputDeviceSettings::Get()->SetMouseSensitivity( |
| params->value); |
| return RespondNow(NoArguments()); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateSetPrimaryButtonRightFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateSetPrimaryButtonRightFunction:: |
| ~AutotestPrivateSetPrimaryButtonRightFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateSetPrimaryButtonRightFunction::Run() { |
| std::unique_ptr<api::autotest_private::SetPrimaryButtonRight::Params> params( |
| api::autotest_private::SetPrimaryButtonRight::Params::Create(*args_)); |
| EXTENSION_FUNCTION_VALIDATE(params.get()); |
| DVLOG(1) << "AutotestPrivateSetPrimaryButtonRightFunction " << params->right; |
| |
| chromeos::system::InputDeviceSettings::Get()->SetPrimaryButtonRight( |
| params->right); |
| return RespondNow(NoArguments()); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateSetMouseReverseScrollFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateSetMouseReverseScrollFunction:: |
| ~AutotestPrivateSetMouseReverseScrollFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateSetMouseReverseScrollFunction::Run() { |
| std::unique_ptr<api::autotest_private::SetMouseReverseScroll::Params> params( |
| api::autotest_private::SetMouseReverseScroll::Params::Create(*args_)); |
| EXTENSION_FUNCTION_VALIDATE(params.get()); |
| DVLOG(1) << "AutotestPrivateSetMouseReverseScrollFunction " |
| << params->enabled; |
| |
| chromeos::system::InputDeviceSettings::Get()->SetMouseReverseScroll( |
| params->enabled); |
| return RespondNow(NoArguments()); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateGetVisibleNotificationsFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateGetVisibleNotificationsFunction:: |
| AutotestPrivateGetVisibleNotificationsFunction() = default; |
| AutotestPrivateGetVisibleNotificationsFunction:: |
| ~AutotestPrivateGetVisibleNotificationsFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateGetVisibleNotificationsFunction::Run() { |
| DVLOG(1) << "AutotestPrivateGetVisibleNotificationsFunction"; |
| |
| message_center::NotificationList::Notifications notification_set = |
| message_center::MessageCenter::Get()->GetVisibleNotifications(); |
| auto values = std::make_unique<base::ListValue>(); |
| for (auto* notification : notification_set) |
| values->Append(MakeDictionaryFromNotification(*notification)); |
| return RespondNow(OneArgument(std::move(values))); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateGetArcStartTimeFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateGetArcStartTimeFunction:: |
| ~AutotestPrivateGetArcStartTimeFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateGetArcStartTimeFunction::Run() { |
| DVLOG(1) << "AutotestPrivateGetArcStartTimeFunction"; |
| |
| arc::ArcSessionManager* arc_session_manager = arc::ArcSessionManager::Get(); |
| if (!arc_session_manager) |
| return RespondNow(Error("Could not find ARC session manager")); |
| |
| double start_time = |
| (arc_session_manager->arc_start_time() - base::TimeTicks()) |
| .InMillisecondsF(); |
| return RespondNow(OneArgument(std::make_unique<base::Value>(start_time))); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateGetArcStateFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateGetArcStateFunction::~AutotestPrivateGetArcStateFunction() = |
| default; |
| |
| ExtensionFunction::ResponseAction AutotestPrivateGetArcStateFunction::Run() { |
| DVLOG(1) << "AutotestPrivateGetArcStateFunction"; |
| |
| api::autotest_private::ArcState arc_state; |
| Profile* const profile = Profile::FromBrowserContext(browser_context()); |
| |
| if (!arc::IsArcAllowedForProfile(profile)) |
| return RespondNow(Error("ARC is not available for the current user")); |
| |
| arc_state.provisioned = arc::IsArcProvisioned(profile); |
| arc_state.tos_needed = arc::IsArcTermsOfServiceNegotiationNeeded(profile); |
| return RespondNow(OneArgument(arc_state.ToValue())); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateGetPlayStoreStateFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateGetPlayStoreStateFunction:: |
| ~AutotestPrivateGetPlayStoreStateFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateGetPlayStoreStateFunction::Run() { |
| DVLOG(1) << "AutotestPrivateGetPlayStoreStateFunction"; |
| |
| api::autotest_private::PlayStoreState play_store_state; |
| play_store_state.allowed = false; |
| Profile* profile = Profile::FromBrowserContext(browser_context()); |
| if (arc::IsArcAllowedForProfile(profile)) { |
| play_store_state.allowed = true; |
| play_store_state.enabled = |
| std::make_unique<bool>(arc::IsArcPlayStoreEnabledForProfile(profile)); |
| play_store_state.managed = std::make_unique<bool>( |
| arc::IsArcPlayStoreEnabledPreferenceManagedForProfile(profile)); |
| } |
| return RespondNow(OneArgument(play_store_state.ToValue())); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateSetPlayStoreEnabledFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateSetPlayStoreEnabledFunction:: |
| ~AutotestPrivateSetPlayStoreEnabledFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateSetPlayStoreEnabledFunction::Run() { |
| std::unique_ptr<api::autotest_private::SetPlayStoreEnabled::Params> params( |
| api::autotest_private::SetPlayStoreEnabled::Params::Create(*args_)); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| DVLOG(1) << "AutotestPrivateSetPlayStoreEnabledFunction " << params->enabled; |
| |
| Profile* profile = Profile::FromBrowserContext(browser_context()); |
| if (arc::IsArcAllowedForProfile(profile)) { |
| if (!arc::SetArcPlayStoreEnabledForProfile(profile, params->enabled)) { |
| return RespondNow( |
| Error("ARC enabled state cannot be changed for the current user")); |
| } |
| // kArcLocationServiceEnabled and kArcBackupRestoreEnabled are prefs that |
| // set together with enabling ARC. That is why we set it here not using |
| // SetWhitelistedPref. At this moment, we don't distinguish the actual |
| // values and set kArcLocationServiceEnabled to true and leave |
| // kArcBackupRestoreEnabled unmodified, which is acceptable for autotests |
| // currently. |
| profile->GetPrefs()->SetBoolean(arc::prefs::kArcLocationServiceEnabled, |
| true); |
| return RespondNow(NoArguments()); |
| } else { |
| return RespondNow(Error("ARC is not available for the current user")); |
| } |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateGetHistogramFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateGetHistogramFunction::~AutotestPrivateGetHistogramFunction() = |
| default; |
| |
| ExtensionFunction::ResponseAction AutotestPrivateGetHistogramFunction::Run() { |
| std::unique_ptr<api::autotest_private::GetHistogram::Params> params( |
| api::autotest_private::GetHistogram::Params::Create(*args_)); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| DVLOG(1) << "AutotestPrivateGetHistogramFunction " << params->name; |
| |
| // Collect histogram data from other processes before responding. Otherwise, |
| // we'd report stale data for histograms that are e.g. recorded by renderers. |
| content::FetchHistogramsAsynchronously( |
| base::ThreadTaskRunnerHandle::Get(), |
| base::BindRepeating( |
| &AutotestPrivateGetHistogramFunction::RespondOnHistogramsFetched, |
| this, params->name), |
| kHistogramsRefreshTimeout); |
| return RespondLater(); |
| } |
| |
| void AutotestPrivateGetHistogramFunction::RespondOnHistogramsFetched( |
| const std::string& name) { |
| // Incorporate the data collected by content::FetchHistogramsAsynchronously(). |
| base::StatisticsRecorder::ImportProvidedHistograms(); |
| Respond(GetHistogram(name)); |
| } |
| |
| ExtensionFunction::ResponseValue |
| AutotestPrivateGetHistogramFunction::GetHistogram(const std::string& name) { |
| const base::HistogramBase* histogram = |
| base::StatisticsRecorder::FindHistogram(name); |
| if (!histogram) |
| return Error(base::StrCat({"Histogram ", name, " not found"})); |
| |
| std::unique_ptr<base::HistogramSamples> samples = |
| histogram->SnapshotSamples(); |
| api::autotest_private::Histogram result; |
| |
| for (std::unique_ptr<base::SampleCountIterator> it = samples->Iterator(); |
| !it->Done(); it->Next()) { |
| base::HistogramBase::Sample min = 0; |
| int64_t max = 0; |
| base::HistogramBase::Count count = 0; |
| it->Get(&min, &max, &count); |
| |
| api::autotest_private::HistogramBucket bucket; |
| bucket.min = min; |
| bucket.max = max; |
| bucket.count = count; |
| result.buckets.push_back(std::move(bucket)); |
| } |
| |
| return OneArgument(result.ToValue()); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateIsAppShownFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateIsAppShownFunction::~AutotestPrivateIsAppShownFunction() = |
| default; |
| |
| ExtensionFunction::ResponseAction AutotestPrivateIsAppShownFunction::Run() { |
| std::unique_ptr<api::autotest_private::IsAppShown::Params> params( |
| api::autotest_private::IsAppShown::Params::Create(*args_)); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| DVLOG(1) << "AutotestPrivateIsAppShownFunction " << params->app_id; |
| |
| ChromeLauncherController* const controller = |
| ChromeLauncherController::instance(); |
| if (!controller) |
| return RespondNow(Error("Controller not available")); |
| |
| const ash::ShelfItem* item = |
| controller->GetItem(ash::ShelfID(params->app_id)); |
| // App must be running and not pending in deferred launch. |
| const bool window_attached = |
| item && item->status == ash::ShelfItemStatus::STATUS_RUNNING && |
| !controller->GetShelfSpinnerController()->HasApp(params->app_id); |
| return RespondNow( |
| OneArgument(std::make_unique<base::Value>(window_attached))); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateIsAppShownFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateIsArcProvisionedFunction:: |
| ~AutotestPrivateIsArcProvisionedFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateIsArcProvisionedFunction::Run() { |
| DVLOG(1) << "AutotestPrivateIsArcProvisionedFunction"; |
| return RespondNow(OneArgument(std::make_unique<base::Value>( |
| arc::IsArcProvisioned(Profile::FromBrowserContext(browser_context()))))); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateGetArcPackageFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateGetArcAppFunction::~AutotestPrivateGetArcAppFunction() = default; |
| |
| ExtensionFunction::ResponseAction AutotestPrivateGetArcAppFunction::Run() { |
| std::unique_ptr<api::autotest_private::GetArcApp::Params> params( |
| api::autotest_private::GetArcApp::Params::Create(*args_)); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| DVLOG(1) << "AutotestPrivateGetArcAppFunction " << params->app_id; |
| |
| ArcAppListPrefs* const prefs = |
| ArcAppListPrefs::Get(Profile::FromBrowserContext(browser_context())); |
| if (!prefs) |
| return RespondNow(Error("ARC is not available")); |
| |
| std::unique_ptr<base::DictionaryValue> app_value; |
| { |
| const std::unique_ptr<ArcAppListPrefs::AppInfo> app_info = |
| prefs->GetApp(params->app_id); |
| if (!app_info) |
| return RespondNow(Error("App is not available")); |
| |
| app_value = std::make_unique<base::DictionaryValue>(); |
| |
| app_value->SetKey("name", base::Value(std::move(app_info->name))); |
| app_value->SetKey("packageName", |
| base::Value(std::move(app_info->package_name))); |
| app_value->SetKey("activity", base::Value(std::move(app_info->activity))); |
| app_value->SetKey("intentUri", |
| base::Value(std::move(app_info->intent_uri))); |
| app_value->SetKey("iconResourceId", |
| base::Value(std::move(app_info->icon_resource_id))); |
| app_value->SetKey("lastLaunchTime", |
| base::Value(app_info->last_launch_time.ToJsTime())); |
| app_value->SetKey("installTime", |
| base::Value(app_info->install_time.ToJsTime())); |
| app_value->SetKey("sticky", base::Value(app_info->sticky)); |
| app_value->SetKey("notificationsEnabled", |
| base::Value(app_info->notifications_enabled)); |
| app_value->SetKey("ready", base::Value(app_info->ready)); |
| app_value->SetKey("suspended", base::Value(app_info->suspended)); |
| app_value->SetKey("showInLauncher", |
| base::Value(app_info->show_in_launcher)); |
| app_value->SetKey("shortcut", base::Value(app_info->shortcut)); |
| app_value->SetKey("launchable", base::Value(app_info->launchable)); |
| } |
| |
| return RespondNow(OneArgument(std::move(app_value))); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateGetArcPackageFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateGetArcPackageFunction::~AutotestPrivateGetArcPackageFunction() = |
| default; |
| |
| ExtensionFunction::ResponseAction AutotestPrivateGetArcPackageFunction::Run() { |
| std::unique_ptr<api::autotest_private::GetArcPackage::Params> params( |
| api::autotest_private::GetArcPackage::Params::Create(*args_)); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| DVLOG(1) << "AutotestPrivateGetArcPackageFunction " << params->package_name; |
| |
| ArcAppListPrefs* const prefs = |
| ArcAppListPrefs::Get(Profile::FromBrowserContext(browser_context())); |
| if (!prefs) |
| return RespondNow(Error("ARC is not available")); |
| |
| std::unique_ptr<base::DictionaryValue> package_value; |
| { |
| const std::unique_ptr<ArcAppListPrefs::PackageInfo> package_info = |
| prefs->GetPackage(params->package_name); |
| if (!package_info) |
| return RespondNow(Error("Package is not available")); |
| |
| package_value = std::make_unique<base::DictionaryValue>(); |
| package_value->SetKey("packageName", |
| base::Value(std::move(package_info->package_name))); |
| package_value->SetKey("packageVersion", |
| base::Value(package_info->package_version)); |
| package_value->SetKey("lastBackupAndroidId", |
| base::Value(base::NumberToString( |
| package_info->last_backup_android_id))); |
| package_value->SetKey("lastBackupTime", |
| base::Value(base::Time::FromDeltaSinceWindowsEpoch( |
| base::TimeDelta::FromMicroseconds( |
| package_info->last_backup_time)) |
| .ToJsTime())); |
| package_value->SetKey("shouldSync", base::Value(package_info->should_sync)); |
| package_value->SetKey("system", base::Value(package_info->system)); |
| package_value->SetKey("vpnProvider", |
| base::Value(package_info->vpn_provider)); |
| } |
| return RespondNow(OneArgument(std::move(package_value))); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateLaunchArcIntentFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateLaunchArcAppFunction::~AutotestPrivateLaunchArcAppFunction() = |
| default; |
| |
| ExtensionFunction::ResponseAction AutotestPrivateLaunchArcAppFunction::Run() { |
| std::unique_ptr<api::autotest_private::LaunchArcApp::Params> params( |
| api::autotest_private::LaunchArcApp::Params::Create(*args_)); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| DVLOG(1) << "AutotestPrivateLaunchArcIntentFunction " << params->app_id << "/" |
| << params->intent; |
| |
| base::Optional<std::string> launch_intent; |
| if (!params->intent.empty()) |
| launch_intent = params->intent; |
| const bool result = arc::LaunchAppWithIntent( |
| Profile::FromBrowserContext(browser_context()), params->app_id, |
| launch_intent, 0 /* event_flags */, |
| arc::UserInteractionType::APP_STARTED_FROM_EXTENSION_API, |
| 0 /* display_id */); |
| return RespondNow(OneArgument(std::make_unique<base::Value>(result))); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateLaunchAppFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateLaunchAppFunction::~AutotestPrivateLaunchAppFunction() = default; |
| |
| ExtensionFunction::ResponseAction AutotestPrivateLaunchAppFunction::Run() { |
| std::unique_ptr<api::autotest_private::LaunchApp::Params> params( |
| api::autotest_private::LaunchApp::Params::Create(*args_)); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| DVLOG(1) << "AutotestPrivateLaunchAppFunction " << params->app_id; |
| |
| ChromeLauncherController* const controller = |
| ChromeLauncherController::instance(); |
| if (!controller) |
| return RespondNow(Error("Controller not available")); |
| controller->LaunchApp(ash::ShelfID(params->app_id), |
| ash::ShelfLaunchSource::LAUNCH_FROM_UNKNOWN, |
| 0, /* event_flags */ |
| display::Screen::GetScreen()->GetPrimaryDisplay().id()); |
| return RespondNow(NoArguments()); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateCloseAppFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateCloseAppFunction::~AutotestPrivateCloseAppFunction() = default; |
| |
| ExtensionFunction::ResponseAction AutotestPrivateCloseAppFunction::Run() { |
| std::unique_ptr<api::autotest_private::CloseApp::Params> params( |
| api::autotest_private::CloseApp::Params::Create(*args_)); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| DVLOG(1) << "AutotestPrivateCloseAppFunction " << params->app_id; |
| |
| ChromeLauncherController* const controller = |
| ChromeLauncherController::instance(); |
| if (!controller) |
| return RespondNow(Error("Controller not available")); |
| controller->Close(ash::ShelfID(params->app_id)); |
| return RespondNow(NoArguments()); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateGetClipboardTextDataFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateGetClipboardTextDataFunction:: |
| ~AutotestPrivateGetClipboardTextDataFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateGetClipboardTextDataFunction::Run() { |
| base::string16 data; |
| ui::Clipboard::GetForCurrentThread()->ReadText( |
| ui::ClipboardBuffer::kCopyPaste, &data); |
| return RespondNow( |
| OneArgument(base::Value::ToUniquePtrValue(base::Value(data)))); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateSetClipboardTextDataFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateSetClipboardTextDataFunction:: |
| ~AutotestPrivateSetClipboardTextDataFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateSetClipboardTextDataFunction::Run() { |
| std::unique_ptr<api::autotest_private::SetClipboardTextData::Params> params( |
| api::autotest_private::SetClipboardTextData::Params::Create(*args_)); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| |
| const base::string16 data = base::UTF8ToUTF16(params->data); |
| ui::ScopedClipboardWriter clipboard_writer(ui::ClipboardBuffer::kCopyPaste); |
| clipboard_writer.WriteText(data); |
| |
| return RespondNow(NoArguments()); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateSetCrostiniEnabledFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateSetCrostiniEnabledFunction:: |
| ~AutotestPrivateSetCrostiniEnabledFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateSetCrostiniEnabledFunction::Run() { |
| std::unique_ptr<api::autotest_private::SetCrostiniEnabled::Params> params( |
| api::autotest_private::SetCrostiniEnabled::Params::Create(*args_)); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| DVLOG(1) << "AutotestPrivateSetCrostiniEnabledFunction " << params->enabled; |
| |
| Profile* profile = Profile::FromBrowserContext(browser_context()); |
| if (!crostini::IsCrostiniUIAllowedForProfile(profile)) |
| return RespondNow(Error(kCrostiniNotAvailableForCurrentUserError)); |
| |
| // Set the preference to indicate Crostini is enabled/disabled. |
| profile->GetPrefs()->SetBoolean(crostini::prefs::kCrostiniEnabled, |
| params->enabled); |
| // Set the flag to indicate we are in testing mode so that Chrome doesn't |
| // try to start the VM/container itself. |
| crostini::CrostiniManager* crostini_manager = |
| crostini::CrostiniManager::GetForProfile(profile); |
| crostini_manager->set_skip_restart_for_testing(); |
| return RespondNow(NoArguments()); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateRunCrostiniInstallerFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateRunCrostiniInstallerFunction:: |
| ~AutotestPrivateRunCrostiniInstallerFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateRunCrostiniInstallerFunction::Run() { |
| DVLOG(1) << "AutotestPrivateInstallCrostiniFunction"; |
| |
| Profile* profile = Profile::FromBrowserContext(browser_context()); |
| if (!crostini::IsCrostiniUIAllowedForProfile(profile)) |
| return RespondNow(Error(kCrostiniNotAvailableForCurrentUserError)); |
| |
| // Run GUI installer which will install crostini vm / container and |
| // start terminal app on completion. After starting the installer, |
| // we call RestartCrostini and we will be put in the pending restarters |
| // queue and be notified on success/otherwise of installation. |
| CrostiniInstallerView::Show( |
| profile, crostini::CrostiniInstaller::GetForProfile(profile)); |
| CrostiniInstallerView::GetActiveViewForTesting()->Accept(); |
| crostini::CrostiniManager::GetForProfile(profile)->RestartCrostini( |
| crostini::kCrostiniDefaultVmName, crostini::kCrostiniDefaultContainerName, |
| base::BindOnce( |
| &AutotestPrivateRunCrostiniInstallerFunction::CrostiniRestarted, |
| this)); |
| |
| return RespondLater(); |
| } |
| |
| void AutotestPrivateRunCrostiniInstallerFunction::CrostiniRestarted( |
| crostini::CrostiniResult result) { |
| if (result == crostini::CrostiniResult::SUCCESS) { |
| Respond(NoArguments()); |
| } else { |
| Respond(Error("Error installing crostini")); |
| } |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateRunCrostiniUninstallerFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateRunCrostiniUninstallerFunction:: |
| ~AutotestPrivateRunCrostiniUninstallerFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateRunCrostiniUninstallerFunction::Run() { |
| DVLOG(1) << "AutotestPrivateRunCrostiniUninstallerFunction"; |
| |
| Profile* profile = Profile::FromBrowserContext(browser_context()); |
| if (!crostini::IsCrostiniUIAllowedForProfile(profile)) |
| return RespondNow(Error(kCrostiniNotAvailableForCurrentUserError)); |
| |
| // Run GUI uninstaller which will remove crostini vm / container. We then |
| // receive the callback with the result when that is complete. |
| crostini::CrostiniManager::GetForProfile(profile)->AddRemoveCrostiniCallback( |
| base::BindOnce( |
| &AutotestPrivateRunCrostiniUninstallerFunction::CrostiniRemoved, |
| this)); |
| CrostiniUninstallerView::Show(profile); |
| CrostiniUninstallerView::GetActiveViewForTesting()->Accept(); |
| return RespondLater(); |
| } |
| |
| void AutotestPrivateRunCrostiniUninstallerFunction::CrostiniRemoved( |
| crostini::CrostiniResult result) { |
| if (result == crostini::CrostiniResult::SUCCESS) |
| Respond(NoArguments()); |
| else |
| Respond(Error("Error uninstalling crostini")); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateExportCrostiniFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateExportCrostiniFunction:: |
| ~AutotestPrivateExportCrostiniFunction() = default; |
| |
| ExtensionFunction::ResponseAction AutotestPrivateExportCrostiniFunction::Run() { |
| std::unique_ptr<api::autotest_private::ExportCrostini::Params> params( |
| api::autotest_private::ExportCrostini::Params::Create(*args_)); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| DVLOG(1) << "AutotestPrivateExportCrostiniFunction " << params->path; |
| |
| Profile* profile = Profile::FromBrowserContext(browser_context()); |
| if (!crostini::IsCrostiniUIAllowedForProfile(profile)) { |
| return RespondNow(Error(kCrostiniNotAvailableForCurrentUserError)); |
| } |
| |
| base::FilePath path(params->path); |
| if (path.ReferencesParent()) { |
| return RespondNow(Error("Invalid export path must not reference parent")); |
| } |
| |
| crostini::CrostiniExportImport::GetForProfile(profile)->ExportContainer( |
| crostini::ContainerId(crostini::kCrostiniDefaultVmName, |
| crostini::kCrostiniDefaultContainerName), |
| file_manager::util::GetDownloadsFolderForProfile(profile).Append(path), |
| base::BindOnce(&AutotestPrivateExportCrostiniFunction::CrostiniExported, |
| this)); |
| |
| return RespondLater(); |
| } |
| |
| void AutotestPrivateExportCrostiniFunction::CrostiniExported( |
| crostini::CrostiniResult result) { |
| if (result == crostini::CrostiniResult::SUCCESS) { |
| Respond(NoArguments()); |
| } else { |
| Respond(Error("Error exporting crostini")); |
| } |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateImportCrostiniFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateImportCrostiniFunction:: |
| ~AutotestPrivateImportCrostiniFunction() = default; |
| |
| ExtensionFunction::ResponseAction AutotestPrivateImportCrostiniFunction::Run() { |
| std::unique_ptr<api::autotest_private::ImportCrostini::Params> params( |
| api::autotest_private::ImportCrostini::Params::Create(*args_)); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| DVLOG(1) << "AutotestPrivateImportCrostiniFunction " << params->path; |
| |
| Profile* profile = Profile::FromBrowserContext(browser_context()); |
| if (!crostini::IsCrostiniUIAllowedForProfile(profile)) |
| return RespondNow(Error(kCrostiniNotAvailableForCurrentUserError)); |
| |
| base::FilePath path(params->path); |
| if (path.ReferencesParent()) { |
| return RespondNow(Error("Invalid import path must not reference parent")); |
| } |
| crostini::CrostiniExportImport::GetForProfile(profile)->ImportContainer( |
| crostini::ContainerId(crostini::kCrostiniDefaultVmName, |
| crostini::kCrostiniDefaultContainerName), |
| file_manager::util::GetDownloadsFolderForProfile(profile).Append(path), |
| base::BindOnce(&AutotestPrivateImportCrostiniFunction::CrostiniImported, |
| this)); |
| |
| return RespondLater(); |
| } |
| |
| void AutotestPrivateImportCrostiniFunction::CrostiniImported( |
| crostini::CrostiniResult result) { |
| if (result == crostini::CrostiniResult::SUCCESS) { |
| Respond(NoArguments()); |
| } else { |
| Respond(Error("Error importing crostini")); |
| } |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateRegisterComponentFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateRegisterComponentFunction:: |
| ~AutotestPrivateRegisterComponentFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateRegisterComponentFunction::Run() { |
| std::unique_ptr<api::autotest_private::RegisterComponent::Params> params( |
| api::autotest_private::RegisterComponent::Params::Create(*args_)); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| DVLOG(1) << "AutotestPrivateRegisterComponentFunction " << params->name |
| << ", " << params->path; |
| |
| g_browser_process->platform_part() |
| ->cros_component_manager() |
| ->RegisterCompatiblePath(params->name, base::FilePath(params->path)); |
| |
| return RespondNow(NoArguments()); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateTakeScreenshotFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateTakeScreenshotFunction:: |
| ~AutotestPrivateTakeScreenshotFunction() = default; |
| |
| ExtensionFunction::ResponseAction AutotestPrivateTakeScreenshotFunction::Run() { |
| DVLOG(1) << "AutotestPrivateTakeScreenshotFunction"; |
| auto grabber = std::make_unique<ui::ScreenshotGrabber>(); |
| // TODO(mash): Fix for mash, http://crbug.com/557397 |
| aura::Window* primary_root = ash::Shell::GetPrimaryRootWindow(); |
| // Pass the ScreenshotGrabber to the callback so that it stays alive for the |
| // duration of the operation, it'll then get deallocated when the callback |
| // completes. |
| grabber->TakeScreenshot( |
| primary_root, primary_root->bounds(), |
| base::BindOnce(&AutotestPrivateTakeScreenshotFunction::ScreenshotTaken, |
| this, base::Passed(&grabber))); |
| return RespondLater(); |
| } |
| |
| void AutotestPrivateTakeScreenshotFunction::ScreenshotTaken( |
| std::unique_ptr<ui::ScreenshotGrabber> grabber, |
| ui::ScreenshotResult screenshot_result, |
| scoped_refptr<base::RefCountedMemory> png_data) { |
| if (screenshot_result != ui::ScreenshotResult::SUCCESS) { |
| return Respond(Error(base::StrCat( |
| {"Error taking screenshot ", |
| base::NumberToString(static_cast<int>(screenshot_result))}))); |
| } |
| Respond( |
| OneArgument(std::make_unique<base::Value>(GetPngDataAsString(png_data)))); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateTakeScreenshotForDisplayFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| AutotestPrivateTakeScreenshotForDisplayFunction:: |
| ~AutotestPrivateTakeScreenshotForDisplayFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateTakeScreenshotForDisplayFunction::Run() { |
| std::unique_ptr<api::autotest_private::TakeScreenshotForDisplay::Params> |
| params(api::autotest_private::TakeScreenshotForDisplay::Params::Create( |
| *args_)); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| DVLOG(1) << "AutotestPrivateTakeScreenshotForDisplayFunction " |
| << params->display_id; |
| int64_t target_display_id; |
| base::StringToInt64(params->display_id, &target_display_id); |
| auto grabber = std::make_unique<ui::ScreenshotGrabber>(); |
| |
| for (auto* const window : ash::Shell::GetAllRootWindows()) { |
| const int64_t display_id = |
| display::Screen::GetScreen()->GetDisplayNearestWindow(window).id(); |
| if (display_id == target_display_id) { |
| grabber->TakeScreenshot( |
| window, window->bounds(), |
| base::BindOnce( |
| &AutotestPrivateTakeScreenshotForDisplayFunction::ScreenshotTaken, |
| this, base::Passed(&grabber))); |
| return RespondLater(); |
| } |
| } |
| return RespondNow(Error(base::StrCat( |
| {"Error taking screenshot for display ", params->display_id}))); |
| } |
| |
| void AutotestPrivateTakeScreenshotForDisplayFunction::ScreenshotTaken( |
| std::unique_ptr<ui::ScreenshotGrabber> grabber, |
| ui::ScreenshotResult screenshot_result, |
| scoped_refptr<base::RefCountedMemory> png_data) { |
| if (screenshot_result != ui::ScreenshotResult::SUCCESS) { |
| return Respond(Error(base::StrCat( |
| {"Error taking screenshot ", |
| base::NumberToString(static_cast<int>(screenshot_result))}))); |
| } |
| Respond( |
| OneArgument(std::make_unique<base::Value>(GetPngDataAsString(png_data)))); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateGetPrinterListFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateGetPrinterListFunction::AutotestPrivateGetPrinterListFunction() |
| : results_(std::make_unique<base::Value>(base::Value::Type::LIST)) {} |
| |
| AutotestPrivateGetPrinterListFunction:: |
| ~AutotestPrivateGetPrinterListFunction() { |
| printers_manager_->RemoveObserver(this); |
| } |
| |
| ExtensionFunction::ResponseAction AutotestPrivateGetPrinterListFunction::Run() { |
| DVLOG(1) << "AutotestPrivateGetPrinterListFunction"; |
| |
| Profile* profile = Profile::FromBrowserContext(browser_context()); |
| printers_manager_ = chromeos::CupsPrintersManager::Create(profile); |
| printers_manager_->AddObserver(this); |
| |
| // Set up a timer to finish waiting after 10 seconds |
| timeout_timer_.Start( |
| FROM_HERE, base::TimeDelta::FromSeconds(10), |
| base::BindOnce( |
| &AutotestPrivateGetPrinterListFunction::RespondWithTimeoutError, |
| this)); |
| |
| return RespondLater(); |
| } |
| |
| void AutotestPrivateGetPrinterListFunction::RespondWithTimeoutError() { |
| if (did_respond()) |
| return; |
| Respond( |
| Error("Timeout occurred before Enterprise printers were initialized")); |
| } |
| |
| void AutotestPrivateGetPrinterListFunction::RespondWithSuccess() { |
| if (did_respond()) |
| return; |
| Respond(OneArgument(std::move(results_))); |
| timeout_timer_.AbandonAndStop(); |
| } |
| |
| void AutotestPrivateGetPrinterListFunction::OnEnterprisePrintersInitialized() { |
| constexpr PrinterClass kClassesToFetch[] = { |
| PrinterClass::kEnterprise, |
| PrinterClass::kSaved, |
| PrinterClass::kAutomatic, |
| }; |
| |
| // We are ready to get the list of printers and finish. |
| base::Value::ListStorage& vresults = results_->GetList(); |
| for (const auto& type : kClassesToFetch) { |
| std::vector<chromeos::Printer> printer_list = |
| printers_manager_->GetPrinters(type); |
| for (const auto& printer : printer_list) { |
| base::Value result(base::Value::Type::DICTIONARY); |
| result.SetKey("printerName", base::Value(printer.display_name())); |
| result.SetKey("printerId", base::Value(printer.id())); |
| result.SetKey("printerType", base::Value(GetPrinterType(type))); |
| vresults.push_back(std::move(result)); |
| } |
| } |
| // We have to respond in separate task, because it will cause a destruction of |
| // CupsPrintersManager |
| PostTask( |
| FROM_HERE, |
| base::BindOnce(&AutotestPrivateGetPrinterListFunction::RespondWithSuccess, |
| this)); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateUpdatePrinterFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateUpdatePrinterFunction::~AutotestPrivateUpdatePrinterFunction() = |
| default; |
| |
| ExtensionFunction::ResponseAction AutotestPrivateUpdatePrinterFunction::Run() { |
| std::unique_ptr<api::autotest_private::UpdatePrinter::Params> params( |
| api::autotest_private::UpdatePrinter::Params::Create(*args_)); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| DVLOG(1) << "AutotestPrivateUpdatePrinterFunction"; |
| |
| const api::autotest_private::Printer& js_printer = params->printer; |
| chromeos::Printer printer(js_printer.printer_id ? *js_printer.printer_id |
| : ""); |
| printer.set_display_name(js_printer.printer_name); |
| if (js_printer.printer_desc) |
| printer.set_description(*js_printer.printer_desc); |
| |
| if (js_printer.printer_make_and_model) |
| printer.set_make_and_model(*js_printer.printer_make_and_model); |
| |
| if (js_printer.printer_uri) |
| printer.set_uri(*js_printer.printer_uri); |
| |
| if (js_printer.printer_ppd) { |
| const GURL ppd = |
| net::FilePathToFileURL(base::FilePath(*js_printer.printer_ppd)); |
| if (ppd.is_valid()) |
| printer.mutable_ppd_reference()->user_supplied_ppd_url = ppd.spec(); |
| else |
| LOG(ERROR) << "Invalid ppd path: " << *js_printer.printer_ppd; |
| } |
| auto printers_manager = chromeos::CupsPrintersManager::Create( |
| Profile::FromBrowserContext(browser_context())); |
| printers_manager->SavePrinter(printer); |
| return RespondNow(NoArguments()); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateRemovePrinterFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateRemovePrinterFunction::~AutotestPrivateRemovePrinterFunction() = |
| default; |
| |
| ExtensionFunction::ResponseAction AutotestPrivateRemovePrinterFunction::Run() { |
| std::unique_ptr<api::autotest_private::RemovePrinter::Params> params( |
| api::autotest_private::RemovePrinter::Params::Create(*args_)); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| DVLOG(1) << "AutotestPrivateRemovePrinterFunction " << params->printer_id; |
| |
| auto printers_manager = chromeos::CupsPrintersManager::Create( |
| Profile::FromBrowserContext(browser_context())); |
| printers_manager->RemoveSavedPrinter(params->printer_id); |
| return RespondNow(NoArguments()); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateBootstrapMachineLearningServiceFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateBootstrapMachineLearningServiceFunction:: |
| AutotestPrivateBootstrapMachineLearningServiceFunction() = default; |
| AutotestPrivateBootstrapMachineLearningServiceFunction:: |
| ~AutotestPrivateBootstrapMachineLearningServiceFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateBootstrapMachineLearningServiceFunction::Run() { |
| DVLOG(1) << "AutotestPrivateBootstrapMachineLearningServiceFunction"; |
| |
| // Load a model. This will first bootstrap the Mojo connection to ML Service. |
| chromeos::machine_learning::ServiceConnection::GetInstance() |
| ->LoadBuiltinModel( |
| chromeos::machine_learning::mojom::BuiltinModelSpec::New( |
| chromeos::machine_learning::mojom::BuiltinModelId::TEST_MODEL), |
| mojo::MakeRequest(&model_), |
| base::BindOnce( |
| &AutotestPrivateBootstrapMachineLearningServiceFunction:: |
| ModelLoaded, |
| this)); |
| model_.set_connection_error_handler(base::BindOnce( |
| &AutotestPrivateBootstrapMachineLearningServiceFunction::ConnectionError, |
| this)); |
| return RespondLater(); |
| } |
| |
| void AutotestPrivateBootstrapMachineLearningServiceFunction::ModelLoaded( |
| chromeos::machine_learning::mojom::LoadModelResult result) { |
| if (result == chromeos::machine_learning::mojom::LoadModelResult::OK) { |
| Respond(NoArguments()); |
| } else { |
| Respond(Error(base::StrCat( |
| {"Model load error ", (std::ostringstream() << result).str()}))); |
| } |
| } |
| |
| void AutotestPrivateBootstrapMachineLearningServiceFunction::ConnectionError() { |
| Respond(Error("ML Service connection error")); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateSetAssistantEnabled |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateSetAssistantEnabledFunction:: |
| AutotestPrivateSetAssistantEnabledFunction() { |
| // |AddObserver| will immediately trigger |OnAssistantStatusChanged|. |
| ash::AssistantState::Get()->AddObserver(this); |
| } |
| |
| AutotestPrivateSetAssistantEnabledFunction:: |
| ~AutotestPrivateSetAssistantEnabledFunction() { |
| ash::AssistantState::Get()->RemoveObserver(this); |
| } |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateSetAssistantEnabledFunction::Run() { |
| DVLOG(1) << "AutotestPrivateSetAssistantEnabledFunction"; |
| |
| std::unique_ptr<api::autotest_private::SetAssistantEnabled::Params> params( |
| api::autotest_private::SetAssistantEnabled::Params::Create(*args_)); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| |
| Profile* profile = Profile::FromBrowserContext(browser_context()); |
| const std::string& err_msg = |
| SetWhitelistedPref(profile, chromeos::assistant::prefs::kAssistantEnabled, |
| base::Value(params->enabled)); |
| if (!err_msg.empty()) |
| return RespondNow(Error(err_msg)); |
| |
| // Any state that's not |NOT_READY| would be considered a ready state. |
| const bool not_ready = (ash::AssistantState::Get()->assistant_state() == |
| ash::mojom::AssistantState::NOT_READY); |
| const bool success = (params->enabled != not_ready); |
| if (success) |
| return RespondNow(NoArguments()); |
| |
| // Assistant service has not responded yet, set up a delayed timer to wait for |
| // it and holder a reference to |this|. Also make sure we stop and respond |
| // when timeout. |
| enabled_ = params->enabled; |
| timeout_timer_.Start( |
| FROM_HERE, base::TimeDelta::FromMilliseconds(params->timeout_ms), |
| base::BindOnce(&AutotestPrivateSetAssistantEnabledFunction::Timeout, |
| this)); |
| return RespondLater(); |
| } |
| |
| void AutotestPrivateSetAssistantEnabledFunction::OnAssistantStatusChanged( |
| ash::mojom::AssistantState state) { |
| // Must check if the Optional contains value first to avoid possible |
| // segmentation fault caused by Respond() below being called before |
| // RespondLater() in Run(). This will happen due to AddObserver() call |
| // in the constructor will trigger this function immediately. |
| if (!enabled_.has_value()) |
| return; |
| |
| const bool not_ready = (state == ash::mojom::AssistantState::NOT_READY); |
| const bool success = (enabled_.value() != not_ready); |
| if (!success) |
| return; |
| |
| Respond(NoArguments()); |
| enabled_.reset(); |
| timeout_timer_.AbandonAndStop(); |
| } |
| |
| void AutotestPrivateSetAssistantEnabledFunction::Timeout() { |
| Respond(Error("Assistant service timed out")); |
| } |
| |
| // AssistantInteractionHelper is a helper class used to interact with Assistant |
| // server and store interaction states for tests. It is shared by |
| // |AutotestPrivateSendAssistantTextQueryFunction| and |
| // |AutotestPrivateWaitForAssistantQueryStatusFunction|. |
| class AssistantInteractionHelper |
| : public chromeos::assistant::mojom::AssistantInteractionSubscriber { |
| public: |
| using OnInteractionFinishedCallback = base::OnceCallback<void(bool)>; |
| |
| AssistantInteractionHelper() |
| : query_status_(std::make_unique<base::DictionaryValue>()) {} |
| |
| ~AssistantInteractionHelper() override = default; |
| |
| void Init(OnInteractionFinishedCallback on_interaction_finished_callback) { |
| // Bind to Assistant service interface. |
| AssistantClient::Get()->BindAssistant(mojo::MakeRequest(&assistant_)); |
| |
| // Subscribe to Assistant interaction events. |
| assistant_->AddAssistantInteractionSubscriber( |
| assistant_interaction_subscriber_receiver_.BindNewPipeAndPassRemote()); |
| |
| on_interaction_finished_callback_ = |
| std::move(on_interaction_finished_callback); |
| } |
| |
| void SendTextQuery(const std::string& query, bool allow_tts) { |
| // Start text interaction with Assistant server. |
| assistant_->StartTextInteraction(query, allow_tts); |
| |
| query_status_->SetKey("queryText", base::Value(query)); |
| } |
| |
| std::unique_ptr<base::DictionaryValue> GetQueryStatus() { |
| return std::move(query_status_); |
| } |
| |
| private: |
| // chromeos::assistant::mojom::AssistantInteractionSubscriber: |
| using AssistantSuggestionPtr = |
| chromeos::assistant::mojom::AssistantSuggestionPtr; |
| using AssistantInteractionMetadataPtr = |
| chromeos::assistant::mojom::AssistantInteractionMetadataPtr; |
| using AssistantInteractionResolution = |
| chromeos::assistant::mojom::AssistantInteractionResolution; |
| |
| void OnInteractionStarted(AssistantInteractionMetadataPtr metadata) override { |
| const bool is_voice_interaction = |
| chromeos::assistant::mojom::AssistantInteractionType::kVoice == |
| metadata->type; |
| query_status_->SetKey("isMicOpen", base::Value(is_voice_interaction)); |
| } |
| |
| void OnInteractionFinished( |
| AssistantInteractionResolution resolution) override { |
| // Only invoke the callback when |result_| is not empty to avoid an early |
| // return before the entire session is completed. This happens when |
| // sending queries to modify device settings, e.g. "turn on bluetooth", |
| // which results in a round trip due to the need to fetch device state |
| // on the client and return that to the server as part of a follow-up |
| // interaction. |
| if (result_.empty()) |
| return; |
| |
| query_status_->SetKey("queryResponse", std::move(result_)); |
| |
| if (on_interaction_finished_callback_) { |
| const bool success = |
| (resolution == AssistantInteractionResolution::kNormal) ? true |
| : false; |
| std::move(on_interaction_finished_callback_).Run(success); |
| } |
| } |
| |
| void OnHtmlResponse(const std::string& response, |
| const std::string& fallback) override { |
| result_.SetKey("htmlResponse", base::Value(response)); |
| result_.SetKey("htmlFallback", base::Value(fallback)); |
| } |
| |
| void OnTextResponse(const std::string& response) override { |
| result_.SetKey("text", base::Value(response)); |
| } |
| |
| void OnSpeechRecognitionFinalResult( |
| const std::string& final_result) override { |
| query_status_->SetKey("queryText", base::Value(final_result)); |
| } |
| |
| void OnSuggestionsResponse( |
| std::vector<AssistantSuggestionPtr> response) override {} |
| void OnOpenUrlResponse(const GURL& url, bool in_background) override {} |
| void OnOpenAppResponse(chromeos::assistant::mojom::AndroidAppInfoPtr app_info, |
| OnOpenAppResponseCallback callback) override {} |
| void OnSpeechRecognitionStarted() override {} |
| void OnSpeechRecognitionIntermediateResult( |
| const std::string& high_confidence_text, |
| const std::string& low_confidence_text) override {} |
| void OnSpeechRecognitionEndOfUtterance() override {} |
| void OnSpeechLevelUpdated(float speech_level) override {} |
| void OnTtsStarted(bool due_to_error) override {} |
| void OnWaitStarted() override {} |
| |
| chromeos::assistant::mojom::AssistantPtr assistant_; |
| mojo::Receiver<chromeos::assistant::mojom::AssistantInteractionSubscriber> |
| assistant_interaction_subscriber_receiver_{this}; |
| std::unique_ptr<base::DictionaryValue> query_status_; |
| base::DictionaryValue result_; |
| |
| // Callback triggered when interaction finished with non-empty response. |
| OnInteractionFinishedCallback on_interaction_finished_callback_; |
| |
| DISALLOW_COPY_AND_ASSIGN(AssistantInteractionHelper); |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateSendAssistantTextQueryFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateSendAssistantTextQueryFunction:: |
| AutotestPrivateSendAssistantTextQueryFunction() |
| : interaction_helper_(std::make_unique<AssistantInteractionHelper>()) {} |
| |
| AutotestPrivateSendAssistantTextQueryFunction:: |
| ~AutotestPrivateSendAssistantTextQueryFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateSendAssistantTextQueryFunction::Run() { |
| DVLOG(1) << "AutotestPrivateSendAssistantTextQueryFunction"; |
| |
| std::unique_ptr<api::autotest_private::SendAssistantTextQuery::Params> params( |
| api::autotest_private::SendAssistantTextQuery::Params::Create(*args_)); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| |
| Profile* profile = Profile::FromBrowserContext(browser_context()); |
| ash::mojom::AssistantAllowedState allowed_state = |
| assistant::IsAssistantAllowedForProfile(profile); |
| if (allowed_state != ash::mojom::AssistantAllowedState::ALLOWED) { |
| return RespondNow(Error(base::StringPrintf( |
| "Assistant not allowed - state: %d", allowed_state))); |
| } |
| |
| interaction_helper_->Init( |
| base::BindOnce(&AutotestPrivateSendAssistantTextQueryFunction:: |
| OnInteractionFinishedCallback, |
| this)); |
| |
| // Start text interaction with Assistant server. |
| interaction_helper_->SendTextQuery(params->query, /*allow_tts=*/false); |
| |
| // Set up a delayed timer to wait for the query response and hold a reference |
| // to |this| to avoid being destructed. Also make sure we stop and respond |
| // when timeout. |
| timeout_timer_.Start( |
| FROM_HERE, base::TimeDelta::FromMilliseconds(params->timeout_ms), |
| base::BindOnce(&AutotestPrivateSendAssistantTextQueryFunction::Timeout, |
| this)); |
| |
| return RespondLater(); |
| } |
| |
| void AutotestPrivateSendAssistantTextQueryFunction:: |
| OnInteractionFinishedCallback(bool success) { |
| if (!success) { |
| Respond(Error("Interaction ends abnormally.")); |
| timeout_timer_.AbandonAndStop(); |
| return; |
| } |
| |
| Respond(OneArgument(interaction_helper_->GetQueryStatus())); |
| timeout_timer_.AbandonAndStop(); |
| } |
| |
| void AutotestPrivateSendAssistantTextQueryFunction::Timeout() { |
| Respond(Error("Assistant response timeout.")); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateWaitForAssistantQueryStatusFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| AutotestPrivateWaitForAssistantQueryStatusFunction:: |
| AutotestPrivateWaitForAssistantQueryStatusFunction() |
| : interaction_helper_(std::make_unique<AssistantInteractionHelper>()) {} |
| |
| AutotestPrivateWaitForAssistantQueryStatusFunction:: |
| ~AutotestPrivateWaitForAssistantQueryStatusFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateWaitForAssistantQueryStatusFunction::Run() { |
| DVLOG(1) << "AutotestPrivateWaitForAssistantQueryStatusFunction"; |
| |
| std::unique_ptr<api::autotest_private::WaitForAssistantQueryStatus::Params> |
| params(api::autotest_private::WaitForAssistantQueryStatus::Params::Create( |
| *args_)); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| |
| Profile* profile = Profile::FromBrowserContext(browser_context()); |
| ash::mojom::AssistantAllowedState allowed_state = |
| assistant::IsAssistantAllowedForProfile(profile); |
| if (allowed_state != ash::mojom::AssistantAllowedState::ALLOWED) { |
| return RespondNow(Error(base::StringPrintf( |
| "Assistant not allowed - state: %d", allowed_state))); |
| } |
| |
| interaction_helper_->Init( |
| base::BindOnce(&AutotestPrivateWaitForAssistantQueryStatusFunction:: |
| OnInteractionFinishedCallback, |
| this)); |
| |
| // Start waiting for the response before time out. |
| timeout_timer_.Start( |
| FROM_HERE, base::TimeDelta::FromSeconds(params->timeout_s), |
| base::BindOnce( |
| &AutotestPrivateWaitForAssistantQueryStatusFunction::Timeout, this)); |
| return RespondLater(); |
| } |
| |
| void AutotestPrivateWaitForAssistantQueryStatusFunction:: |
| OnInteractionFinishedCallback(bool success) { |
| if (!success) { |
| Respond(Error("Interaction ends abnormally.")); |
| timeout_timer_.AbandonAndStop(); |
| return; |
| } |
| |
| Respond(OneArgument(interaction_helper_->GetQueryStatus())); |
| timeout_timer_.AbandonAndStop(); |
| } |
| |
| void AutotestPrivateWaitForAssistantQueryStatusFunction::Timeout() { |
| Respond(Error("No query response received before time out.")); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateSetWhitelistedPrefFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateSetWhitelistedPrefFunction:: |
| ~AutotestPrivateSetWhitelistedPrefFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateSetWhitelistedPrefFunction::Run() { |
| DVLOG(1) << "AutotestPrivateSetWhitelistedPrefFunction"; |
| |
| std::unique_ptr<api::autotest_private::SetWhitelistedPref::Params> params( |
| api::autotest_private::SetWhitelistedPref::Params::Create(*args_)); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| |
| const std::string& pref_name = params->pref_name; |
| const base::Value& value = *(params->value); |
| |
| Profile* profile = Profile::FromBrowserContext(browser_context()); |
| const std::string& err_msg = SetWhitelistedPref(profile, pref_name, value); |
| |
| if (!err_msg.empty()) |
| return RespondNow(Error(err_msg)); |
| |
| return RespondNow(NoArguments()); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateSetCrostiniAppScaledFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateSetCrostiniAppScaledFunction:: |
| ~AutotestPrivateSetCrostiniAppScaledFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateSetCrostiniAppScaledFunction::Run() { |
| std::unique_ptr<api::autotest_private::SetCrostiniAppScaled::Params> params( |
| api::autotest_private::SetCrostiniAppScaled::Params::Create(*args_)); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| DVLOG(1) << "AutotestPrivateSetCrostiniAppScaledFunction " << params->app_id |
| << " " << params->scaled; |
| |
| ChromeLauncherController* const controller = |
| ChromeLauncherController::instance(); |
| if (!controller) |
| return RespondNow(Error("Controller not available")); |
| |
| crostini::CrostiniRegistryService* registry_service = |
| crostini::CrostiniRegistryServiceFactory::GetForProfile( |
| controller->profile()); |
| if (!registry_service) |
| return RespondNow(Error("Crostini registry not available")); |
| |
| registry_service->SetAppScaled(params->app_id, params->scaled); |
| return RespondNow(NoArguments()); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateGetPrimaryDisplayScaleFactorFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateGetPrimaryDisplayScaleFactorFunction:: |
| ~AutotestPrivateGetPrimaryDisplayScaleFactorFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateGetPrimaryDisplayScaleFactorFunction::Run() { |
| DVLOG(1) << "AutotestPrivateGetPrimaryDisplayScaleFactorFunction"; |
| |
| display::Display primary_display = |
| display::Screen::GetScreen()->GetPrimaryDisplay(); |
| float scale_factor = primary_display.device_scale_factor(); |
| return RespondNow(OneArgument(std::make_unique<base::Value>(scale_factor))); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateIsTabletModeEnabledFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateIsTabletModeEnabledFunction:: |
| ~AutotestPrivateIsTabletModeEnabledFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateIsTabletModeEnabledFunction::Run() { |
| DVLOG(1) << "AutotestPrivateIsTabletModeEnabledFunction"; |
| |
| return RespondNow(OneArgument( |
| std::make_unique<base::Value>(ash::TabletMode::Get()->InTabletMode()))); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateSetTabletModeEnabledFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateSetTabletModeEnabledFunction:: |
| ~AutotestPrivateSetTabletModeEnabledFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateSetTabletModeEnabledFunction::Run() { |
| DVLOG(1) << "AutotestPrivateSetTabletModeEnabledFunction"; |
| |
| std::unique_ptr<api::autotest_private::SetTabletModeEnabled::Params> params( |
| api::autotest_private::SetTabletModeEnabled::Params::Create(*args_)); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| ash::TabletMode::Waiter waiter(params->enabled); |
| ash::TabletMode::Get()->SetEnabledForTest(params->enabled); |
| waiter.Wait(); |
| return RespondNow(OneArgument( |
| std::make_unique<base::Value>(ash::TabletMode::Get()->InTabletMode()))); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateGetAllInstalledAppsFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| AutotestPrivateGetAllInstalledAppsFunction:: |
| AutotestPrivateGetAllInstalledAppsFunction() = default; |
| |
| AutotestPrivateGetAllInstalledAppsFunction:: |
| ~AutotestPrivateGetAllInstalledAppsFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateGetAllInstalledAppsFunction::Run() { |
| DVLOG(1) << "AutotestPrivateGetAllInstalledAppsFunction"; |
| |
| Profile* const profile = Profile::FromBrowserContext(browser_context()); |
| apps::AppServiceProxy* proxy = |
| apps::AppServiceProxyFactory::GetForProfile(profile); |
| |
| if (!proxy) |
| return RespondNow(Error("App Service not available")); |
| |
| std::vector<api::autotest_private::App> installed_apps; |
| proxy->AppRegistryCache().ForEachApp([&installed_apps]( |
| const apps::AppUpdate& update) { |
| api::autotest_private::App app; |
| app.app_id = update.AppId(); |
| app.name = update.Name(); |
| app.short_name = update.ShortName(); |
| app.additional_search_terms = update.AdditionalSearchTerms(); |
| app.type = GetAppType(update.AppType()); |
| app.readiness = GetAppReadiness(update.Readiness()); |
| app.show_in_launcher = ConvertMojomOptionalBool(update.ShowInLauncher()); |
| app.show_in_search = ConvertMojomOptionalBool(update.ShowInSearch()); |
| installed_apps.emplace_back(std::move(app)); |
| }); |
| |
| return RespondNow( |
| ArgumentList(api::autotest_private::GetAllInstalledApps::Results::Create( |
| installed_apps))); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateGetShelfItemsFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| AutotestPrivateGetShelfItemsFunction::AutotestPrivateGetShelfItemsFunction() = |
| default; |
| |
| AutotestPrivateGetShelfItemsFunction::~AutotestPrivateGetShelfItemsFunction() = |
| default; |
| |
| ExtensionFunction::ResponseAction AutotestPrivateGetShelfItemsFunction::Run() { |
| DVLOG(1) << "AutotestPrivateGetShelfItemsFunction"; |
| |
| ChromeLauncherController* const controller = |
| ChromeLauncherController::instance(); |
| if (!controller) |
| return RespondNow(Error("Controller not available")); |
| |
| std::vector<api::autotest_private::ShelfItem> result_items; |
| for (const auto& item : controller->shelf_model()->items()) { |
| api::autotest_private::ShelfItem result_item; |
| result_item.app_id = item.id.app_id; |
| result_item.launch_id = item.id.launch_id; |
| result_item.title = base::UTF16ToUTF8(item.title); |
| result_item.type = GetShelfItemType(item.type); |
| result_item.status = GetShelfItemStatus(item.status); |
| result_item.shows_tooltip = item.shows_tooltip; |
| result_item.pinned_by_policy = item.pinned_by_policy; |
| result_item.has_notification = item.has_notification; |
| result_items.emplace_back(std::move(result_item)); |
| } |
| |
| return RespondNow(ArgumentList( |
| api::autotest_private::GetShelfItems::Results::Create(result_items))); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateGetShelfAutoHideBehaviorFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateGetShelfAutoHideBehaviorFunction:: |
| AutotestPrivateGetShelfAutoHideBehaviorFunction() = default; |
| |
| AutotestPrivateGetShelfAutoHideBehaviorFunction:: |
| ~AutotestPrivateGetShelfAutoHideBehaviorFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateGetShelfAutoHideBehaviorFunction::Run() { |
| DVLOG(1) << "AutotestPrivateGetShelfAutoHideBehaviorFunction"; |
| |
| std::unique_ptr<api::autotest_private::GetShelfAutoHideBehavior::Params> |
| params(api::autotest_private::GetShelfAutoHideBehavior::Params::Create( |
| *args_)); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| |
| int64_t display_id; |
| if (!base::StringToInt64(params->display_id, &display_id)) { |
| return RespondNow(Error(base::StrCat( |
| {"Invalid display_id; expected string with numbers only, got ", |
| params->display_id}))); |
| } |
| |
| Profile* const profile = Profile::FromBrowserContext(browser_context()); |
| ash::ShelfAutoHideBehavior behavior = |
| ash::GetShelfAutoHideBehaviorPref(profile->GetPrefs(), display_id); |
| std::string str_behavior; |
| switch (behavior) { |
| case ash::ShelfAutoHideBehavior::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS: |
| str_behavior = "always"; |
| break; |
| case ash::ShelfAutoHideBehavior::SHELF_AUTO_HIDE_BEHAVIOR_NEVER: |
| str_behavior = "never"; |
| break; |
| case ash::ShelfAutoHideBehavior::SHELF_AUTO_HIDE_ALWAYS_HIDDEN: |
| // SHELF_AUTO_HIDE_ALWAYS_HIDDEN not supported by shelf_prefs.cc |
| return RespondNow(Error("SHELF_AUTO_HIDE_ALWAYS_HIDDEN not supported")); |
| } |
| return RespondNow( |
| OneArgument(std::make_unique<base::Value>(std::move(str_behavior)))); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateSetShelfAutoHideBehaviorFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateSetShelfAutoHideBehaviorFunction:: |
| AutotestPrivateSetShelfAutoHideBehaviorFunction() = default; |
| |
| AutotestPrivateSetShelfAutoHideBehaviorFunction:: |
| ~AutotestPrivateSetShelfAutoHideBehaviorFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateSetShelfAutoHideBehaviorFunction::Run() { |
| DVLOG(1) << "AutotestPrivateSetShelfAutoHideBehaviorFunction"; |
| |
| std::unique_ptr<api::autotest_private::SetShelfAutoHideBehavior::Params> |
| params(api::autotest_private::SetShelfAutoHideBehavior::Params::Create( |
| *args_)); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| |
| ash::ShelfAutoHideBehavior behavior; |
| if (params->behavior == "always") { |
| behavior = ash::ShelfAutoHideBehavior::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS; |
| } else if (params->behavior == "never") { |
| behavior = ash::ShelfAutoHideBehavior::SHELF_AUTO_HIDE_BEHAVIOR_NEVER; |
| } else { |
| return RespondNow(Error( |
| base::StrCat({"Invalid behavior; expected 'always', 'never', got ", |
| params->behavior}))); |
| } |
| int64_t display_id; |
| if (!base::StringToInt64(params->display_id, &display_id)) { |
| return RespondNow(Error(base::StrCat( |
| {"Invalid display_id; expected string with numbers only, got ", |
| params->display_id}))); |
| } |
| |
| Profile* const profile = Profile::FromBrowserContext(browser_context()); |
| ash::SetShelfAutoHideBehaviorPref(profile->GetPrefs(), display_id, behavior); |
| return RespondNow(NoArguments()); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateGetShelfAlignmentFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateGetShelfAlignmentFunction:: |
| AutotestPrivateGetShelfAlignmentFunction() = default; |
| |
| AutotestPrivateGetShelfAlignmentFunction:: |
| ~AutotestPrivateGetShelfAlignmentFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateGetShelfAlignmentFunction::Run() { |
| DVLOG(1) << "AutotestPrivateGetShelfAlignmentFunction"; |
| |
| std::unique_ptr<api::autotest_private::GetShelfAlignment::Params> params( |
| api::autotest_private::GetShelfAlignment::Params::Create(*args_)); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| |
| int64_t display_id; |
| if (!base::StringToInt64(params->display_id, &display_id)) { |
| return RespondNow(Error(base::StrCat( |
| {"Invalid display_id; expected string with numbers only, got ", |
| params->display_id}))); |
| } |
| |
| Profile* const profile = Profile::FromBrowserContext(browser_context()); |
| ash::ShelfAlignment alignment = |
| ash::GetShelfAlignmentPref(profile->GetPrefs(), display_id); |
| api::autotest_private::ShelfAlignmentType alignment_type; |
| switch (alignment) { |
| case ash::ShelfAlignment::SHELF_ALIGNMENT_BOTTOM: |
| alignment_type = api::autotest_private::ShelfAlignmentType:: |
| SHELF_ALIGNMENT_TYPE_BOTTOM; |
| break; |
| case ash::ShelfAlignment::SHELF_ALIGNMENT_LEFT: |
| alignment_type = |
| api::autotest_private::ShelfAlignmentType::SHELF_ALIGNMENT_TYPE_LEFT; |
| break; |
| case ash::ShelfAlignment::SHELF_ALIGNMENT_RIGHT: |
| alignment_type = |
| api::autotest_private::ShelfAlignmentType::SHELF_ALIGNMENT_TYPE_RIGHT; |
| break; |
| case ash::ShelfAlignment::SHELF_ALIGNMENT_BOTTOM_LOCKED: |
| // SHELF_ALIGNMENT_BOTTOM_LOCKED not supported by shelf_prefs.cc |
| return RespondNow(Error("SHELF_ALIGNMENT_BOTTOM_LOCKED not supported")); |
| } |
| return RespondNow(OneArgument(std::make_unique<base::Value>( |
| api::autotest_private::ToString(alignment_type)))); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateSetShelfAlignmentFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateSetShelfAlignmentFunction:: |
| AutotestPrivateSetShelfAlignmentFunction() = default; |
| |
| AutotestPrivateSetShelfAlignmentFunction:: |
| ~AutotestPrivateSetShelfAlignmentFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateSetShelfAlignmentFunction::Run() { |
| DVLOG(1) << "AutotestPrivateSetShelfAlignmentFunction"; |
| |
| std::unique_ptr<api::autotest_private::SetShelfAlignment::Params> params( |
| api::autotest_private::SetShelfAlignment::Params::Create(*args_)); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| |
| ash::ShelfAlignment alignment; |
| switch (params->alignment) { |
| case api::autotest_private::ShelfAlignmentType::SHELF_ALIGNMENT_TYPE_BOTTOM: |
| alignment = ash::ShelfAlignment::SHELF_ALIGNMENT_BOTTOM; |
| break; |
| case api::autotest_private::ShelfAlignmentType::SHELF_ALIGNMENT_TYPE_LEFT: |
| alignment = ash::ShelfAlignment::SHELF_ALIGNMENT_LEFT; |
| break; |
| case api::autotest_private::ShelfAlignmentType::SHELF_ALIGNMENT_TYPE_RIGHT: |
| alignment = ash::ShelfAlignment::SHELF_ALIGNMENT_RIGHT; |
| break; |
| case api::autotest_private::ShelfAlignmentType::SHELF_ALIGNMENT_TYPE_NONE: |
| return RespondNow( |
| Error("Invalid None alignment; expected 'Bottom', 'Left', or " |
| "'Right'")); |
| } |
| int64_t display_id; |
| if (!base::StringToInt64(params->display_id, &display_id)) { |
| return RespondNow(Error(base::StrCat( |
| {"Invalid display_id; expected string with numbers only, got ", |
| params->display_id}))); |
| } |
| |
| Profile* const profile = Profile::FromBrowserContext(browser_context()); |
| ash::SetShelfAlignmentPref(profile->GetPrefs(), display_id, alignment); |
| return RespondNow(NoArguments()); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateSetOverviewModeStateFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateSetOverviewModeStateFunction:: |
| AutotestPrivateSetOverviewModeStateFunction() = default; |
| |
| AutotestPrivateSetOverviewModeStateFunction:: |
| ~AutotestPrivateSetOverviewModeStateFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateSetOverviewModeStateFunction::Run() { |
| std::unique_ptr<api::autotest_private::SetOverviewModeState::Params> params( |
| api::autotest_private::SetOverviewModeState::Params::Create(*args_)); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| |
| ash::OverviewTestApi().SetOverviewMode( |
| params->start, |
| base::BindOnce( |
| &AutotestPrivateSetOverviewModeStateFunction::OnOverviewModeChanged, |
| this, params->start)); |
| return did_respond() ? AlreadyResponded() : RespondLater(); |
| } |
| |
| void AutotestPrivateSetOverviewModeStateFunction::OnOverviewModeChanged( |
| bool for_start, |
| bool finished) { |
| auto arg = OneArgument(std::make_unique<base::Value>(finished)); |
| // On starting the overview animation, it needs to wait for 1 extra second |
| // to trigger the occlusion tracker. |
| if (for_start) { |
| base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( |
| FROM_HERE, |
| base::BindOnce(&AutotestPrivateSetOverviewModeStateFunction::Respond, |
| this, std::move(arg)), |
| base::TimeDelta::FromSeconds(1)); |
| } else { |
| Respond(std::move(arg)); |
| } |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateShowVirtualKeyboardIfEnabledFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateShowVirtualKeyboardIfEnabledFunction:: |
| AutotestPrivateShowVirtualKeyboardIfEnabledFunction() = default; |
| AutotestPrivateShowVirtualKeyboardIfEnabledFunction:: |
| ~AutotestPrivateShowVirtualKeyboardIfEnabledFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateShowVirtualKeyboardIfEnabledFunction::Run() { |
| if (!ui::IMEBridge::Get() || |
| !ui::IMEBridge::Get()->GetInputContextHandler() || |
| !ui::IMEBridge::Get()->GetInputContextHandler()->GetInputMethod()) { |
| return RespondNow(NoArguments()); |
| } |
| |
| ui::IMEBridge::Get() |
| ->GetInputContextHandler() |
| ->GetInputMethod() |
| ->ShowVirtualKeyboardIfEnabled(); |
| return RespondNow(NoArguments()); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateGetArcAppWindowInfoFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateGetArcAppWindowInfoFunction:: |
| AutotestPrivateGetArcAppWindowInfoFunction() = default; |
| AutotestPrivateGetArcAppWindowInfoFunction:: |
| ~AutotestPrivateGetArcAppWindowInfoFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateGetArcAppWindowInfoFunction::Run() { |
| std::unique_ptr<api::autotest_private::GetArcAppWindowInfo::Params> params( |
| api::autotest_private::GetArcAppWindowInfo::Params::Create(*args_)); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| DVLOG(1) << "AutotestPrivateGetArcAppWindowInfoFunction " |
| << params->package_name; |
| |
| aura::Window* arc_window = GetArcAppWindow(params->package_name); |
| if (!arc_window) { |
| return RespondNow(Error(base::StrCat( |
| {"No ARC app window was found for ", params->package_name}))); |
| } |
| |
| const gfx::Rect bounds = arc_window->GetBoundsInRootWindow(); |
| const bool is_animating = arc_window->layer()->GetAnimator()->is_animating(); |
| const auto* screen = display::Screen::GetScreen(); |
| const int64_t display_id = |
| !screen ? -1 : screen->GetDisplayNearestWindow(arc_window).id(); |
| |
| api::autotest_private::ArcAppWindowInfo result; |
| result.bounds = ToBoundsDictionary(bounds); |
| result.display_id = display_id; |
| result.is_animating = is_animating; |
| result.is_visible = arc_window->IsVisible(); |
| |
| return RespondNow(OneArgument( |
| api::autotest_private::GetArcAppWindowInfo::Results::Create(result))); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateArcAppTracingStartFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateArcAppTracingStartFunction:: |
| AutotestPrivateArcAppTracingStartFunction() = default; |
| AutotestPrivateArcAppTracingStartFunction:: |
| ~AutotestPrivateArcAppTracingStartFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateArcAppTracingStartFunction::Run() { |
| DVLOG(1) << "AutotestPrivateArcAppTracingStartFunction"; |
| |
| arc::ArcAppPerformanceTracing* const tracing = |
| arc::ArcAppPerformanceTracing::GetForBrowserContext(browser_context()); |
| if (!tracing) |
| return RespondNow(Error("No ARC performance tracing is available.")); |
| |
| if (!tracing->StartCustomTracing()) |
| return RespondNow(Error("Failed to start custom tracing.")); |
| |
| return RespondNow(NoArguments()); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateArcAppTracingStopAndAnalyzeFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateArcAppTracingStopAndAnalyzeFunction:: |
| AutotestPrivateArcAppTracingStopAndAnalyzeFunction() = default; |
| AutotestPrivateArcAppTracingStopAndAnalyzeFunction:: |
| ~AutotestPrivateArcAppTracingStopAndAnalyzeFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateArcAppTracingStopAndAnalyzeFunction::Run() { |
| DVLOG(1) << "AutotestPrivateArcAppTracingStopAndAnalyzeFunction"; |
| |
| arc::ArcAppPerformanceTracing* const tracing = |
| arc::ArcAppPerformanceTracing::GetForBrowserContext(browser_context()); |
| if (!tracing) |
| return RespondNow(Error("No ARC performance tracing is available.")); |
| |
| tracing->StopCustomTracing(base::BindOnce( |
| &AutotestPrivateArcAppTracingStopAndAnalyzeFunction::OnTracingResult, |
| this)); |
| return did_respond() ? AlreadyResponded() : RespondLater(); |
| } |
| |
| void AutotestPrivateArcAppTracingStopAndAnalyzeFunction::OnTracingResult( |
| bool success, |
| double fps, |
| double commit_deviation, |
| double render_quality) { |
| auto result = std::make_unique<base::Value>(base::Value::Type::DICTIONARY); |
| result->SetBoolKey("success", success); |
| result->SetDoubleKey("fps", fps); |
| result->SetDoubleKey("commitDeviation", commit_deviation); |
| result->SetDoubleKey("renderQuality", render_quality); |
| Respond(OneArgument(std::move(result))); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateSetArcAppWindowStateFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateSetArcAppWindowStateFunction:: |
| AutotestPrivateSetArcAppWindowStateFunction() = default; |
| AutotestPrivateSetArcAppWindowStateFunction:: |
| ~AutotestPrivateSetArcAppWindowStateFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateSetArcAppWindowStateFunction::Run() { |
| std::unique_ptr<api::autotest_private::SetArcAppWindowState::Params> params( |
| api::autotest_private::SetArcAppWindowState::Params::Create(*args_)); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| DVLOG(1) << "AutotestPrivateSetArcAppWindowStateFunction " |
| << params->package_name; |
| |
| aura::Window* arc_window = GetArcAppWindow(params->package_name); |
| if (!arc_window) { |
| return RespondNow(Error(base::StrCat( |
| {"No ARC app window was found for ", params->package_name}))); |
| } |
| |
| ash::WindowStateType expected_state = |
| GetExpectedWindowState(params->change.event_type); |
| if (arc_window->GetProperty(ash::kWindowStateTypeKey) == expected_state) { |
| if (params->change.fail_if_no_change && |
| *(params->change.fail_if_no_change)) { |
| return RespondNow(Error( |
| "The ARC app window is already in the expected window state! ")); |
| } else { |
| return RespondNow(OneArgument(std::make_unique<base::Value>( |
| api::autotest_private::ToString(ToWindowStateType(expected_state))))); |
| } |
| } |
| |
| window_state_observer_ = std::make_unique<WindowStateChangeObserver>( |
| arc_window, expected_state, |
| base::BindOnce( |
| &AutotestPrivateSetArcAppWindowStateFunction::WindowStateChanged, |
| this, expected_state)); |
| |
| // TODO(crbug.com/990713): Make WMEvent trigger split view in tablet mode. |
| if (ash::TabletMode::Get()->InTabletMode()) { |
| if (expected_state == ash::WindowStateType::kLeftSnapped) { |
| ash::SplitViewTestApi().SnapWindow( |
| arc_window, ash::SplitViewTestApi::SnapPosition::LEFT); |
| } else if (expected_state == ash::WindowStateType::kRightSnapped) { |
| ash::SplitViewTestApi().SnapWindow( |
| arc_window, ash::SplitViewTestApi::SnapPosition::RIGHT); |
| } |
| return RespondLater(); |
| } |
| |
| const ash::WMEvent event(ToWMEventType(params->change.event_type)); |
| ash::WindowState::Get(arc_window)->OnWMEvent(&event); |
| |
| return RespondLater(); |
| } |
| |
| void AutotestPrivateSetArcAppWindowStateFunction::WindowStateChanged( |
| ash::WindowStateType expected_type, |
| bool success) { |
| if (!success) { |
| Respond(Error( |
| "ARC app window was destroyed while waiting for its state change! ")); |
| } else { |
| Respond(OneArgument(std::make_unique<base::Value>( |
| api::autotest_private::ToString(ToWindowStateType(expected_type))))); |
| } |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateGetArcAppWindowStateFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateGetArcAppWindowStateFunction:: |
| AutotestPrivateGetArcAppWindowStateFunction() = default; |
| AutotestPrivateGetArcAppWindowStateFunction:: |
| ~AutotestPrivateGetArcAppWindowStateFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateGetArcAppWindowStateFunction::Run() { |
| std::unique_ptr<api::autotest_private::GetArcAppWindowState::Params> params( |
| api::autotest_private::GetArcAppWindowState::Params::Create(*args_)); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| DVLOG(1) << "AutotestPrivateGetArcAppWindowStateFunction " |
| << params->package_name; |
| |
| aura::Window* arc_window = GetArcAppWindow(params->package_name); |
| if (!arc_window) { |
| return RespondNow(Error(base::StrCat( |
| {"No ARC app window was found for ", params->package_name}))); |
| } |
| |
| return RespondNow(OneArgument(std::make_unique<base::Value>( |
| api::autotest_private::ToString(ToWindowStateType( |
| arc_window->GetProperty(ash::kWindowStateTypeKey)))))); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateSetArcAppWindowFocusFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateSetArcAppWindowFocusFunction:: |
| AutotestPrivateSetArcAppWindowFocusFunction() = default; |
| AutotestPrivateSetArcAppWindowFocusFunction:: |
| ~AutotestPrivateSetArcAppWindowFocusFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateSetArcAppWindowFocusFunction::Run() { |
| std::unique_ptr<api::autotest_private::SetArcAppWindowFocus::Params> params( |
| api::autotest_private::SetArcAppWindowFocus::Params::Create(*args_)); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| DVLOG(1) << "AutotestPrivateSetArcAppWindowFocusFunction " |
| << params->package_name; |
| aura::Window* arc_window = GetArcAppWindow(params->package_name); |
| if (!arc_window) { |
| return RespondNow(Error(base::StrCat( |
| {"No ARC app window was found for ", params->package_name}))); |
| } |
| if (!arc_window->CanFocus()) { |
| return RespondNow(Error(base::StrCat( |
| {"ARC app window can't focus for ", params->package_name}))); |
| } |
| // No matter whether it is focused already, set it focused. |
| arc_window->Focus(); |
| if (!arc_window->HasFocus()) { |
| return RespondNow(Error(base::StrCat( |
| {"Failed to set focus for ARC App window ", params->package_name}))); |
| } |
| return RespondNow(NoArguments()); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateSwapWindowsInSplitViewFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateSwapWindowsInSplitViewFunction:: |
| AutotestPrivateSwapWindowsInSplitViewFunction() = default; |
| AutotestPrivateSwapWindowsInSplitViewFunction:: |
| ~AutotestPrivateSwapWindowsInSplitViewFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateSwapWindowsInSplitViewFunction::Run() { |
| ash::SplitViewTestApi().SwapWindows(); |
| return RespondNow(NoArguments()); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateWaitForDisplayRotationFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateWaitForDisplayRotationFunction:: |
| AutotestPrivateWaitForDisplayRotationFunction() = default; |
| AutotestPrivateWaitForDisplayRotationFunction:: |
| ~AutotestPrivateWaitForDisplayRotationFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateWaitForDisplayRotationFunction::Run() { |
| DVLOG(1) << "AutotestPrivateWaitForDisplayRotationFunction"; |
| |
| std::unique_ptr<api::autotest_private::WaitForDisplayRotation::Params> params( |
| api::autotest_private::WaitForDisplayRotation::Params::Create(*args_)); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| target_rotation_ = ToRotation(params->rotation); |
| |
| if (!base::StringToInt64(params->display_id, &display_id_)) { |
| return RespondNow(Error(base::StrCat( |
| {"Invalid display_id; expected string with numbers only, got ", |
| params->display_id}))); |
| } |
| auto* root_window = ash::Shell::GetRootWindowForDisplayId(display_id_); |
| if (!root_window) { |
| return RespondNow(Error(base::StrCat( |
| {"Invalid display_id; no root window found for the display id ", |
| params->display_id}))); |
| } |
| auto* animator = ash::ScreenRotationAnimator::GetForRootWindow(root_window); |
| if (!animator->IsRotating()) { |
| display::Display display; |
| display::Screen::GetScreen()->GetDisplayWithDisplayId(display_id_, |
| &display); |
| // This should never fail. |
| DCHECK(display.is_valid()); |
| return RespondNow(OneArgument( |
| std::make_unique<base::Value>(display.rotation() == target_rotation_))); |
| } |
| self_ = this; |
| |
| animator->AddObserver(this); |
| return RespondLater(); |
| } |
| |
| void AutotestPrivateWaitForDisplayRotationFunction:: |
| OnScreenCopiedBeforeRotation() {} |
| |
| void AutotestPrivateWaitForDisplayRotationFunction:: |
| OnScreenRotationAnimationFinished(ash::ScreenRotationAnimator* animator, |
| bool canceled) { |
| animator->RemoveObserver(this); |
| |
| display::Display display; |
| display::Screen::GetScreen()->GetDisplayWithDisplayId(display_id_, &display); |
| Respond(OneArgument(std::make_unique<base::Value>( |
| display.is_valid() && display.rotation() == target_rotation_))); |
| self_.reset(); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateGetAppWindowListFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateGetAppWindowListFunction:: |
| AutotestPrivateGetAppWindowListFunction() = default; |
| AutotestPrivateGetAppWindowListFunction:: |
| ~AutotestPrivateGetAppWindowListFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateGetAppWindowListFunction::Run() { |
| // Use nagative number to avoid potential collision with normal use if any. |
| static int id_count = -10000; |
| |
| auto window_list = ash::GetAppWindowList(); |
| std::vector<api::autotest_private::AppWindowInfo> result_list; |
| |
| for (auto* window : window_list) { |
| if (window->id() == aura::Window::kInitialId) |
| window->set_id(id_count--); |
| api::autotest_private::AppWindowInfo window_info; |
| window_info.id = window->id(); |
| window_info.name = window->GetName(); |
| window_info.window_type = GetAppWindowType( |
| static_cast<ash::AppType>(window->GetProperty(aura::client::kAppType))); |
| window_info.state_type = |
| ToWindowStateType(window->GetProperty(ash::kWindowStateTypeKey)); |
| window_info.bounds_in_root = |
| ToBoundsDictionary(window->GetBoundsInRootWindow()); |
| window_info.target_bounds = ToBoundsDictionary(window->GetTargetBounds()); |
| window_info.display_id = |
| display::Screen::GetScreen()->GetDisplayNearestWindow(window).id(); |
| window_info.title = base::UTF16ToUTF8(window->GetTitle()); |
| window_info.is_animating = window->layer()->GetAnimator()->is_animating(); |
| window_info.is_visible = window->IsVisible(); |
| window_info.target_visibility = window->TargetVisibility(); |
| window_info.can_focus = window->CanFocus(); |
| window_info.has_focus = window->HasFocus(); |
| window_info.on_active_desk = |
| ash::DesksHelper::Get()->BelongsToActiveDesk(window); |
| window_info.is_active = wm::IsActiveWindow(window); |
| window_info.has_capture = window->HasCapture(); |
| |
| if (window->GetProperty(aura::client::kAppType) == |
| static_cast<int>(ash::AppType::ARC_APP)) { |
| window_info.arc_package_name = std::make_unique<std::string>( |
| *window->GetProperty(ash::kArcPackageNameKey)); |
| } |
| result_list.emplace_back(std::move(window_info)); |
| } |
| return RespondNow(ArgumentList( |
| api::autotest_private::GetAppWindowList::Results::Create(result_list))); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateSetAppWindowStateFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateSetAppWindowStateFunction:: |
| AutotestPrivateSetAppWindowStateFunction() = default; |
| AutotestPrivateSetAppWindowStateFunction:: |
| ~AutotestPrivateSetAppWindowStateFunction() = default; |
| |
| ExtensionFunction::ResponseAction |
| AutotestPrivateSetAppWindowStateFunction::Run() { |
| std::unique_ptr<api::autotest_private::SetAppWindowState::Params> params( |
| api::autotest_private::SetAppWindowState::Params::Create(*args_)); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| DVLOG(1) << "AutotestPrivateSetAppWindowStateFunction " << params->id; |
| |
| aura::Window* window = FindAppWindowById(params->id); |
| if (!window) { |
| return RespondNow(Error( |
| base::StringPrintf("No app window was found : id=%d", params->id))); |
| } |
| |
| ash::WindowStateType expected_state = |
| GetExpectedWindowState(params->change.event_type); |
| if (window->GetProperty(ash::kWindowStateTypeKey) == expected_state) { |
| if (params->change.fail_if_no_change && |
| *(params->change.fail_if_no_change)) { |
| return RespondNow( |
| Error("The app window was already in the expected window state! ")); |
| } else { |
| return RespondNow(OneArgument(std::make_unique<base::Value>( |
| api::autotest_private::ToString(ToWindowStateType(expected_state))))); |
| } |
| } |
| |
| window_state_observer_ = std::make_unique<WindowStateChangeObserver>( |
| window, expected_state, |
| base::BindOnce( |
| &AutotestPrivateSetAppWindowStateFunction::WindowStateChanged, this, |
| expected_state)); |
| |
| // TODO(crbug.com/990713): Make WMEvent trigger split view in tablet mode. |
| if (ash::TabletMode::Get()->InTabletMode()) { |
| if (expected_state == ash::WindowStateType::kLeftSnapped) { |
| ash::SplitViewTestApi().SnapWindow( |
| window, ash::SplitViewTestApi::SnapPosition::LEFT); |
| } else if (expected_state == ash::WindowStateType::kRightSnapped) { |
| ash::SplitViewTestApi().SnapWindow( |
| window, ash::SplitViewTestApi::SnapPosition::RIGHT); |
| } |
| return RespondLater(); |
| } |
| |
| const ash::WMEvent event(ToWMEventType(params->change.event_type)); |
| ash::WindowState::Get(window)->OnWMEvent(&event); |
| |
| return RespondLater(); |
| } |
| |
| void AutotestPrivateSetAppWindowStateFunction::WindowStateChanged( |
| ash::WindowStateType expected_type, |
| bool success) { |
| if (!success) { |
| Respond(Error( |
| "The app window was destroyed while waiting for its state change! ")); |
| } else { |
| Respond(OneArgument(std::make_unique<base::Value>( |
| api::autotest_private::ToString(ToWindowStateType(expected_type))))); |
| } |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateCloseAppWindowFunction |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| AutotestPrivateCloseAppWindowFunction:: |
| ~AutotestPrivateCloseAppWindowFunction() = default; |
| |
| ExtensionFunction::ResponseAction AutotestPrivateCloseAppWindowFunction::Run() { |
| std::unique_ptr<api::autotest_private::CloseAppWindow::Params> params( |
| api::autotest_private::CloseAppWindow::Params::Create(*args_)); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| DVLOG(1) << "AutotestPrivateCloseAppWindowFunction " << params->id; |
| |
| auto* window = FindAppWindowById(params->id); |
| if (!window) { |
| return RespondNow(Error( |
| base::StringPrintf("No app window was found : id=%d", params->id))); |
| } |
| auto* widget = views::Widget::GetWidgetForNativeWindow(window); |
| widget->Close(); |
| return RespondNow(NoArguments()); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AutotestPrivateAPI |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| static base::LazyInstance<BrowserContextKeyedAPIFactory<AutotestPrivateAPI>>:: |
| DestructorAtExit g_autotest_private_api_factory = LAZY_INSTANCE_INITIALIZER; |
| |
| // static |
| BrowserContextKeyedAPIFactory<AutotestPrivateAPI>* |
| AutotestPrivateAPI::GetFactoryInstance() { |
| return g_autotest_private_api_factory.Pointer(); |
| } |
| |
| template <> |
| KeyedService* |
| BrowserContextKeyedAPIFactory<AutotestPrivateAPI>::BuildServiceInstanceFor( |
| content::BrowserContext* context) const { |
| return new AutotestPrivateAPI(context); |
| } |
| |
| AutotestPrivateAPI::AutotestPrivateAPI(content::BrowserContext* context) |
| : clipboard_observer_(this), browser_context_(context), test_mode_(false) { |
| clipboard_observer_.Add(ui::ClipboardMonitor::GetInstance()); |
| } |
| |
| AutotestPrivateAPI::~AutotestPrivateAPI() = default; |
| |
| void AutotestPrivateAPI::OnClipboardDataChanged() { |
| EventRouter* event_router = EventRouter::Get(browser_context_); |
| if (!event_router) |
| return; |
| |
| std::unique_ptr<base::ListValue> event_args = |
| std::make_unique<base::ListValue>(); |
| std::unique_ptr<Event> event( |
| new Event(events::AUTOTESTPRIVATE_ON_CLIPBOARD_DATA_CHANGED, |
| api::autotest_private::OnClipboardDataChanged::kEventName, |
| std::move(event_args))); |
| event_router->BroadcastEvent(std::move(event)); |
| } |
| |
| } // namespace extensions |