123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348 |
- // Copyright 2018 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 "ash/assistant/assistant_controller_impl.h"
- #include <algorithm>
- #include <utility>
- #include "ash/accessibility/accessibility_controller_impl.h"
- #include "ash/assistant/util/deep_link_util.h"
- #include "ash/capture_mode/capture_mode_controller.h"
- #include "ash/constants/ash_features.h"
- #include "ash/public/cpp/android_intent_helper.h"
- #include "ash/public/cpp/new_window_delegate.h"
- #include "ash/public/mojom/assistant_volume_control.mojom.h"
- #include "ash/session/session_controller_impl.h"
- #include "ash/shell.h"
- #include "base/bind.h"
- #include "base/memory/scoped_refptr.h"
- #include "chromeos/ash/services/assistant/public/cpp/assistant_browser_delegate.h"
- #include "chromeos/ash/services/assistant/public/cpp/assistant_prefs.h"
- #include "chromeos/ash/services/assistant/public/cpp/assistant_service.h"
- #include "chromeos/ash/services/assistant/public/cpp/features.h"
- #include "chromeos/services/libassistant/public/cpp/assistant_feedback.h"
- #include "components/prefs/pref_registry_simple.h"
- #include "net/traffic_annotation/network_traffic_annotation.h"
- #include "url/gurl.h"
- namespace ash {
- AssistantControllerImpl::AssistantControllerImpl() {
- assistant_state_controller_.AddObserver(this);
- CrasAudioHandler::Get()->AddAudioObserver(this);
- AddObserver(this);
- // The Assistant service needs to have accessibility state synced with ash
- // and be notified of any accessibility status changes in the future to
- // provide an opportunity to turn on/off A11Y features.
- Shell::Get()->accessibility_controller()->AddObserver(this);
- color_mode_observer_.Observe(DarkLightModeControllerImpl::Get());
- NotifyConstructed();
- }
- AssistantControllerImpl::~AssistantControllerImpl() {
- NotifyDestroying();
- CrasAudioHandler::Get()->RemoveAudioObserver(this);
- Shell::Get()->accessibility_controller()->RemoveObserver(this);
- assistant_state_controller_.RemoveObserver(this);
- RemoveObserver(this);
- }
- // static
- void AssistantControllerImpl::RegisterProfilePrefs(
- PrefRegistrySimple* registry) {
- AssistantInteractionControllerImpl::RegisterProfilePrefs(registry);
- AssistantUiControllerImpl::RegisterProfilePrefs(registry);
- }
- void AssistantControllerImpl::BindReceiver(
- mojo::PendingReceiver<mojom::AssistantVolumeControl> receiver) {
- assistant_volume_control_receiver_.Bind(std::move(receiver));
- }
- void AssistantControllerImpl::SetAssistant(assistant::Assistant* assistant) {
- assistant_ = assistant;
- // Provide reference to sub-controllers.
- assistant_alarm_timer_controller_.SetAssistant(assistant);
- assistant_interaction_controller_.SetAssistant(assistant);
- assistant_notification_controller_.SetAssistant(assistant);
- assistant_ui_controller_.SetAssistant(assistant);
- OnAccessibilityStatusChanged();
- bool dark_mode_enabled = false;
- if (ash::features::IsProductivityLauncherEnabled() ||
- ash::features::IsDarkLightModeEnabled()) {
- dark_mode_enabled = DarkLightModeControllerImpl::Get()->IsDarkModeEnabled();
- }
- OnColorModeChanged(dark_mode_enabled);
- if (assistant) {
- for (AssistantControllerObserver& observer : observers_)
- observer.OnAssistantReady();
- }
- }
- void AssistantControllerImpl::SendAssistantFeedback(
- bool assistant_debug_info_allowed,
- const std::string& feedback_description,
- const std::string& screenshot_png) {
- chromeos::assistant::AssistantFeedback assistant_feedback;
- assistant_feedback.assistant_debug_info_allowed =
- assistant_debug_info_allowed;
- assistant_feedback.description = feedback_description;
- assistant_feedback.screenshot_png =
- std::vector<uint8_t>(screenshot_png.begin(), screenshot_png.end());
- assistant_->SendAssistantFeedback(std::move(assistant_feedback));
- }
- void AssistantControllerImpl::StartSpeakerIdEnrollmentFlow() {
- setup_controller()->StartOnboarding(false /* relaunch */,
- FlowType::kSpeakerIdEnrollment);
- }
- void AssistantControllerImpl::DownloadImage(
- const GURL& url,
- ImageDownloader::DownloadCallback callback) {
- constexpr net::NetworkTrafficAnnotationTag kNetworkTrafficAnnotationTag =
- net::DefineNetworkTrafficAnnotation("image_downloader", R"(
- semantics {
- sender: "Google Assistant"
- description:
- "The Google Assistant requires dynamic loading of images to "
- "provide a media rich user experience. Images are downloaded "
- "on an as needed basis."
- trigger:
- "Generally triggered in direct response to a user issued "
- "query. A single query may necessitate the downloading of "
- "multiple images."
- data: "None."
- destination: GOOGLE_OWNED_SERVICE
- }
- policy {
- cookies_allowed: NO
- setting:
- "The Google Assistant can be enabled/disabled in Chrome "
- "Settings and is subject to eligibility requirements."
- policy_exception_justification:
- "The users can disable this feature. This does not send/store "
- "user data."
- })");
- ImageDownloader::Get()->Download(url, kNetworkTrafficAnnotationTag,
- std::move(callback));
- }
- void AssistantControllerImpl::AddObserver(
- AssistantControllerObserver* observer) {
- observers_.AddObserver(observer);
- }
- void AssistantControllerImpl::RemoveObserver(
- AssistantControllerObserver* observer) {
- observers_.RemoveObserver(observer);
- }
- void AssistantControllerImpl::OpenUrl(const GURL& url,
- bool in_background,
- bool from_server) {
- // app_list search result will be opened by `OpenUrl()`. However, the
- // `assistant_` may not be ready. Show a toast to indicate it.
- if (!assistant_) {
- assistant_ui_controller_.ShowUnboundErrorToast();
- return;
- }
- if (assistant::util::IsDeepLinkUrl(url)) {
- NotifyDeepLinkReceived(url);
- return;
- }
- auto* android_helper = AndroidIntentHelper::GetInstance();
- if (IsAndroidIntent(url) && !android_helper) {
- NOTREACHED();
- return;
- }
- // Give observers an opportunity to perform any necessary handling before we
- // open the specified |url| in a new browser tab.
- NotifyOpeningUrl(url, in_background, from_server);
- if (IsAndroidIntent(url)) {
- android_helper->LaunchAndroidIntent(url.spec());
- } else {
- assistant::AssistantBrowserDelegate::Get()->OpenUrl(url);
- }
- NotifyUrlOpened(url, from_server);
- }
- void AssistantControllerImpl::OpenAssistantSettings() {
- // Launch Assistant settings via deeplink.
- OpenUrl(assistant::util::CreateAssistantSettingsDeepLink(),
- /*in_background=*/false, /*from_server=*/false);
- }
- base::WeakPtr<ash::AssistantController> AssistantControllerImpl::GetWeakPtr() {
- return weak_factory_.GetWeakPtr();
- }
- void AssistantControllerImpl::OnDeepLinkReceived(
- assistant::util::DeepLinkType type,
- const std::map<std::string, std::string>& params) {
- using assistant::util::DeepLinkParam;
- using assistant::util::DeepLinkType;
- switch (type) {
- case DeepLinkType::kChromeSettings: {
- // Chrome Settings deep links are opened in a new browser tab.
- OpenUrl(
- assistant::util::GetChromeSettingsUrl(
- assistant::util::GetDeepLinkParam(params, DeepLinkParam::kPage)),
- /*in_background=*/false, /*from_server=*/false);
- break;
- }
- case DeepLinkType::kFeedback:
- NewWindowDelegate::GetInstance()->OpenFeedbackPage(
- NewWindowDelegate::FeedbackSource::kFeedbackSourceAssistant);
- // Close the assistant UI so that the feedback page is visible.
- assistant_ui_controller_.CloseUi(
- assistant::AssistantExitPoint::kUnspecified);
- break;
- case DeepLinkType::kScreenshot:
- // We close the UI before taking the screenshot as it's probably not the
- // user's intention to include the Assistant in the picture.
- assistant_ui_controller_.CloseUi(
- assistant::AssistantExitPoint::kScreenshot);
- CaptureModeController::Get()->CaptureScreenshotsOfAllDisplays();
- break;
- case DeepLinkType::kTaskManager:
- // Open task manager window.
- NewWindowDelegate::GetInstance()->ShowTaskManager();
- break;
- case DeepLinkType::kUnsupported:
- case DeepLinkType::kAlarmTimer:
- case DeepLinkType::kLists:
- case DeepLinkType::kNotes:
- case DeepLinkType::kOnboarding:
- case DeepLinkType::kQuery:
- case DeepLinkType::kReminders:
- case DeepLinkType::kSettings:
- // No action needed.
- break;
- }
- }
- void AssistantControllerImpl::SetVolume(int volume, bool user_initiated) {
- volume = std::min(100, volume);
- volume = std::max(volume, 0);
- CrasAudioHandler::Get()->SetOutputVolumePercent(volume);
- }
- void AssistantControllerImpl::SetMuted(bool muted) {
- CrasAudioHandler::Get()->SetOutputMute(muted);
- }
- void AssistantControllerImpl::AddVolumeObserver(
- mojo::PendingRemote<mojom::VolumeObserver> observer) {
- volume_observers_.Add(std::move(observer));
- int output_volume = CrasAudioHandler::Get()->GetOutputVolumePercent();
- bool mute = CrasAudioHandler::Get()->IsOutputMuted();
- OnOutputMuteChanged(mute);
- OnOutputNodeVolumeChanged(0 /* node */, output_volume);
- }
- void AssistantControllerImpl::OnOutputMuteChanged(bool mute_on) {
- for (auto& observer : volume_observers_)
- observer->OnMuteStateChanged(mute_on);
- }
- void AssistantControllerImpl::OnOutputNodeVolumeChanged(uint64_t node,
- int volume) {
- // |node| refers to the active volume device, which we don't care here.
- for (auto& observer : volume_observers_)
- observer->OnVolumeChanged(volume);
- }
- void AssistantControllerImpl::OnAccessibilityStatusChanged() {
- if (!assistant_)
- return;
- // The Assistant service needs to be informed of changes to accessibility
- // state so that it can turn on/off A11Y features appropriately.
- assistant_->OnAccessibilityStatusChanged(
- Shell::Get()->accessibility_controller()->spoken_feedback().enabled());
- }
- void AssistantControllerImpl::OnColorModeChanged(bool dark_mode_enabled) {
- if (!assistant_)
- return;
- assistant_->OnColorModeChanged(dark_mode_enabled);
- }
- bool AssistantControllerImpl::IsAssistantReady() const {
- return !!assistant_;
- }
- void AssistantControllerImpl::NotifyConstructed() {
- for (AssistantControllerObserver& observer : observers_)
- observer.OnAssistantControllerConstructed();
- }
- void AssistantControllerImpl::NotifyDestroying() {
- for (AssistantControllerObserver& observer : observers_)
- observer.OnAssistantControllerDestroying();
- }
- void AssistantControllerImpl::NotifyDeepLinkReceived(const GURL& deep_link) {
- using assistant::util::DeepLinkType;
- // Retrieve deep link type and parsed parameters.
- DeepLinkType type = assistant::util::GetDeepLinkType(deep_link);
- const std::map<std::string, std::string> params =
- assistant::util::GetDeepLinkParams(deep_link);
- for (AssistantControllerObserver& observer : observers_)
- observer.OnDeepLinkReceived(type, params);
- }
- void AssistantControllerImpl::NotifyOpeningUrl(const GURL& url,
- bool in_background,
- bool from_server) {
- for (AssistantControllerObserver& observer : observers_)
- observer.OnOpeningUrl(url, in_background, from_server);
- }
- void AssistantControllerImpl::NotifyUrlOpened(const GURL& url,
- bool from_server) {
- for (AssistantControllerObserver& observer : observers_)
- observer.OnUrlOpened(url, from_server);
- }
- void AssistantControllerImpl::OnAssistantStatusChanged(
- assistant::AssistantStatus status) {
- if (status == assistant::AssistantStatus::NOT_READY)
- assistant_ui_controller_.CloseUi(
- assistant::AssistantExitPoint::kUnspecified);
- }
- void AssistantControllerImpl::OnLockedFullScreenStateChanged(bool enabled) {
- if (enabled)
- assistant_ui_controller_.CloseUi(
- assistant::AssistantExitPoint::kUnspecified);
- }
- void AssistantControllerImpl::BindVolumeControl(
- mojo::PendingReceiver<mojom::AssistantVolumeControl> receiver) {
- Shell::Get()->assistant_controller()->BindReceiver(std::move(receiver));
- }
- } // namespace ash
|