blob: 162fd1d9e67ea1f48ef3a7ddccb0263ab9d65b2b [file] [log] [blame]
David Black71ab74d2018-04-12 06:52:311// Copyright 2018 The Chromium Authors. All rights reserved.
David Blacke8f815042018-03-28 18:59:372// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
David Black00fdce32018-05-10 20:59:145#include "ash/assistant/assistant_controller.h"
David Blacke8f815042018-03-28 18:59:376
David Blacke802d4062018-06-29 01:59:057#include "ash/assistant/assistant_controller_observer.h"
David Black9766ecd2018-06-20 18:29:118#include "ash/assistant/assistant_interaction_controller.h"
wutao16db603c2018-07-10 06:43:599#include "ash/assistant/assistant_notification_controller.h"
David Blackc22e4352018-07-11 21:29:4810#include "ash/assistant/assistant_screen_context_controller.h"
David Blackee6f32b52018-08-09 21:28:4611#include "ash/assistant/assistant_setup_controller.h"
David Black1d1b1b672018-06-20 21:41:5712#include "ash/assistant/assistant_ui_controller.h"
David Blackedaf0c32018-06-28 22:06:3913#include "ash/assistant/util/deep_link_util.h"
David Black2f7a70c32018-06-26 02:14:2214#include "ash/new_window_controller.h"
David Blacke1a4b9ed2018-04-19 19:55:0815#include "ash/session/session_controller.h"
David Blacke8f815042018-03-28 18:59:3716#include "ash/shell.h"
Yue Libf33defd2018-08-01 21:04:0617#include "ash/voice_interaction/voice_interaction_controller.h"
Muyuan Li0070f44d2018-05-16 02:57:2318#include "base/bind.h"
19#include "base/memory/scoped_refptr.h"
David Blacke1a4b9ed2018-04-19 19:55:0820#include "base/unguessable_token.h"
David Blacke8f815042018-03-28 18:59:3721
22namespace ash {
23
David Black00fdce32018-05-10 20:59:1424AssistantController::AssistantController()
Muyuan Lied7c76402018-08-07 23:59:0025 : assistant_volume_control_binding_(this),
26 assistant_interaction_controller_(
David Black2f7a70c32018-06-26 02:14:2227 std::make_unique<AssistantInteractionController>(this)),
wutao16db603c2018-07-10 06:43:5928 assistant_notification_controller_(
29 std::make_unique<AssistantNotificationController>(this)),
David Blackc22e4352018-07-11 21:29:4830 assistant_screen_context_controller_(
David Black1f58bcc2018-07-12 17:59:4031 std::make_unique<AssistantScreenContextController>(this)),
David Blackee6f32b52018-08-09 21:28:4632 assistant_setup_controller_(
33 std::make_unique<AssistantSetupController>(this)),
David Blackc22e4352018-07-11 21:29:4834 assistant_ui_controller_(std::make_unique<AssistantUiController>(this)),
Yue Libf33defd2018-08-01 21:04:0635 voice_interaction_binding_(this),
wutao16db603c2018-07-10 06:43:5936 weak_factory_(this) {
Yue Libf33defd2018-08-01 21:04:0637 mojom::VoiceInteractionObserverPtr ptr;
38 voice_interaction_binding_.Bind(mojo::MakeRequest(&ptr));
39 Shell::Get()->voice_interaction_controller()->AddObserver(std::move(ptr));
40
David Blackf946f832018-07-13 17:29:0941 AddObserver(this);
David Black1f58bcc2018-07-12 17:59:4042 NotifyConstructed();
Muyuan Lied7c76402018-08-07 23:59:0043 chromeos::CrasAudioHandler::Get()->AddAudioObserver(this);
David Black4703d7b2018-06-22 00:16:3944}
David Blacke8f815042018-03-28 18:59:3745
David Black4703d7b2018-06-22 00:16:3946AssistantController::~AssistantController() {
Muyuan Lied7c76402018-08-07 23:59:0047 chromeos::CrasAudioHandler::Get()->RemoveAudioObserver(this);
David Black1f58bcc2018-07-12 17:59:4048 NotifyDestroying();
David Blackf946f832018-07-13 17:29:0949 RemoveObserver(this);
David Black4703d7b2018-06-22 00:16:3950}
David Blacke8f815042018-03-28 18:59:3751
David Black00fdce32018-05-10 20:59:1452void AssistantController::BindRequest(
53 mojom::AssistantControllerRequest request) {
David Black75f9fec2018-05-17 22:10:3954 assistant_controller_bindings_.AddBinding(this, std::move(request));
David Blacke8f815042018-03-28 18:59:3755}
56
Muyuan Lied7c76402018-08-07 23:59:0057void AssistantController::BindRequest(
58 mojom::AssistantVolumeControlRequest request) {
59 assistant_volume_control_binding_.Bind(std::move(request));
60}
61
David Blacke802d4062018-06-29 01:59:0562void AssistantController::AddObserver(AssistantControllerObserver* observer) {
63 observers_.AddObserver(observer);
64}
65
66void AssistantController::RemoveObserver(
67 AssistantControllerObserver* observer) {
68 observers_.RemoveObserver(observer);
69}
70
David Black00fdce32018-05-10 20:59:1471void AssistantController::SetAssistant(
David Blacke8f815042018-03-28 18:59:3772 chromeos::assistant::mojom::AssistantPtr assistant) {
David Black4c3656c2018-04-19 17:31:4773 assistant_ = std::move(assistant);
74
David Black4703d7b2018-06-22 00:16:3975 // Provide reference to sub-controllers.
David Black9766ecd2018-06-20 18:29:1176 assistant_interaction_controller_->SetAssistant(assistant_.get());
wutao16db603c2018-07-10 06:43:5977 assistant_notification_controller_->SetAssistant(assistant_.get());
David Blackc22e4352018-07-11 21:29:4878 assistant_screen_context_controller_->SetAssistant(assistant_.get());
79 assistant_ui_controller_->SetAssistant(assistant_.get());
David Black4c3656c2018-04-19 17:31:4780}
81
David Black7ffd2842018-05-25 01:25:5382void AssistantController::SetAssistantImageDownloader(
83 mojom::AssistantImageDownloaderPtr assistant_image_downloader) {
84 assistant_image_downloader_ = std::move(assistant_image_downloader);
85}
86
David Blackee6f32b52018-08-09 21:28:4687// TODO(dmblack): Call SetAssistantSetup directly on AssistantSetupController
88// instead of going through AssistantController.
Yue Libf89f72a2018-06-18 16:51:1689void AssistantController::SetAssistantSetup(
90 mojom::AssistantSetupPtr assistant_setup) {
91 assistant_setup_ = std::move(assistant_setup);
David Blackee6f32b52018-08-09 21:28:4692 assistant_setup_controller_->SetAssistantSetup(assistant_setup_.get());
David Black9766ecd2018-06-20 18:29:1193}
94
95void AssistantController::SetWebContentsManager(
96 mojom::WebContentsManagerPtr web_contents_manager) {
97 web_contents_manager_ = std::move(web_contents_manager);
Yue Libf89f72a2018-06-18 16:51:1698}
99
David Blackc22e4352018-07-11 21:29:48100// TODO(dmblack): Expose AssistantScreenContextController over mojo rather
101// than implementing RequestScreenshot here in AssistantController.
Muyuan Li0070f44d2018-05-16 02:57:23102void AssistantController::RequestScreenshot(
103 const gfx::Rect& rect,
104 RequestScreenshotCallback callback) {
David Blackc22e4352018-07-11 21:29:48105 assistant_screen_context_controller_->RequestScreenshot(rect,
106 std::move(callback));
Muyuan Li0070f44d2018-05-16 02:57:23107}
108
David Black5326a8eb2018-06-12 22:05:34109void AssistantController::ManageWebContents(
David Blacke1a4b9ed2018-04-19 19:55:08110 const base::UnguessableToken& id_token,
David Black5326a8eb2018-06-12 22:05:34111 mojom::ManagedWebContentsParamsPtr params,
112 mojom::WebContentsManager::ManageWebContentsCallback callback) {
113 DCHECK(web_contents_manager_);
David Blacke1a4b9ed2018-04-19 19:55:08114
115 const mojom::UserSession* user_session =
116 Shell::Get()->session_controller()->GetUserSession(0);
117
118 if (!user_session) {
119 LOG(WARNING) << "Unable to retrieve active user session.";
David Black5326a8eb2018-06-12 22:05:34120 std::move(callback).Run(base::nullopt);
David Blacke1a4b9ed2018-04-19 19:55:08121 return;
122 }
123
David Black5326a8eb2018-06-12 22:05:34124 // Supply account ID.
125 params->account_id = user_session->user_info->account_id;
126
127 // Specify that we will handle top level browser requests.
David Black5326a8eb2018-06-12 22:05:34128 ash::mojom::ManagedWebContentsOpenUrlDelegatePtr ptr;
David Black2f7a70c32018-06-26 02:14:22129 web_contents_open_url_delegate_bindings_.AddBinding(this,
130 mojo::MakeRequest(&ptr));
David Black5326a8eb2018-06-12 22:05:34131 params->open_url_delegate_ptr_info = ptr.PassInterface();
132
133 web_contents_manager_->ManageWebContents(id_token, std::move(params),
134 std::move(callback));
David Blacke1a4b9ed2018-04-19 19:55:08135}
136
David Black5326a8eb2018-06-12 22:05:34137void AssistantController::ReleaseWebContents(
138 const base::UnguessableToken& id_token) {
139 web_contents_manager_->ReleaseWebContents(id_token);
David Blacke1a4b9ed2018-04-19 19:55:08140}
141
David Black5326a8eb2018-06-12 22:05:34142void AssistantController::ReleaseWebContents(
David Black3bfd968602018-04-24 22:07:46143 const std::vector<base::UnguessableToken>& id_tokens) {
David Black5326a8eb2018-06-12 22:05:34144 web_contents_manager_->ReleaseAllWebContents(id_tokens);
David Black3bfd968602018-04-24 22:07:46145}
146
David Black1a42f162018-08-13 23:07:01147void AssistantController::NavigateWebContentsBack(
148 const base::UnguessableToken& id_token,
149 mojom::WebContentsManager::NavigateWebContentsBackCallback callback) {
150 web_contents_manager_->NavigateWebContentsBack(id_token, std::move(callback));
151}
152
David Black7ffd2842018-05-25 01:25:53153void AssistantController::DownloadImage(
154 const GURL& url,
155 mojom::AssistantImageDownloader::DownloadCallback callback) {
156 DCHECK(assistant_image_downloader_);
157
158 const mojom::UserSession* user_session =
159 Shell::Get()->session_controller()->GetUserSession(0);
160
161 if (!user_session) {
162 LOG(WARNING) << "Unable to retrieve active user session.";
David Black5326a8eb2018-06-12 22:05:34163 std::move(callback).Run(gfx::ImageSkia());
David Black7ffd2842018-05-25 01:25:53164 return;
165 }
166
167 AccountId account_id = user_session->user_info->account_id;
168 assistant_image_downloader_->Download(account_id, url, std::move(callback));
169}
170
David Blackb0749ca52018-07-13 21:30:02171void AssistantController::OnDeepLinkReceived(
172 assistant::util::DeepLinkType type,
173 const std::map<std::string, std::string>& params) {
David Black7c07e30e2018-07-25 02:27:19174 using namespace assistant::util;
175
David Blackb0749ca52018-07-13 21:30:02176 switch (type) {
David Black7c07e30e2018-07-25 02:27:19177 case DeepLinkType::kFeedback:
David Blackb0749ca52018-07-13 21:30:02178 // TODO(dmblack): Possibly use a new FeedbackSource (this method defaults
179 // to kFeedbackSourceAsh). This may be useful for differentiating feedback
180 // UI and behavior for Assistant.
181 Shell::Get()->new_window_controller()->OpenFeedbackPage();
182 break;
David Black7c07e30e2018-07-25 02:27:19183 case DeepLinkType::kUnsupported:
184 case DeepLinkType::kExplore:
David Blackee6f32b52018-08-09 21:28:46185 case DeepLinkType::kOnboarding:
David Black7c07e30e2018-07-25 02:27:19186 case DeepLinkType::kQuery:
187 case DeepLinkType::kReminders:
188 case DeepLinkType::kSettings:
David Blackb0749ca52018-07-13 21:30:02189 // No action needed.
190 break;
David Black1859f9f2018-07-13 18:03:34191 }
David Blackf946f832018-07-13 17:29:09192}
193
David Black2f7a70c32018-06-26 02:14:22194void AssistantController::OnOpenUrlFromTab(const GURL& url) {
195 OpenUrl(url);
196}
197
Muyuan Lied7c76402018-08-07 23:59:00198void AssistantController::SetVolume(int volume, bool user_initiated) {
199 volume = std::min(100, volume);
200 volume = std::max(volume, 0);
201 chromeos::CrasAudioHandler::Get()->SetOutputVolumePercent(volume);
202}
203
204void AssistantController::SetMuted(bool muted) {
205 chromeos::CrasAudioHandler::Get()->SetOutputMute(muted);
206}
207
208void AssistantController::AddVolumeObserver(mojom::VolumeObserverPtr observer) {
209 volume_observer_.AddPtr(std::move(observer));
210
211 int output_volume =
212 chromeos::CrasAudioHandler::Get()->GetOutputVolumePercent();
213 bool mute = chromeos::CrasAudioHandler::Get()->IsOutputMuted();
214 OnOutputMuteChanged(mute, false /* system_adjust */);
215 OnOutputNodeVolumeChanged(0 /* node */, output_volume);
216}
217
218void AssistantController::OnOutputMuteChanged(bool mute_on,
219 bool system_adjust) {
220 volume_observer_.ForAllPtrs([mute_on](mojom::VolumeObserver* observer) {
221 observer->OnMuteStateChanged(mute_on);
222 });
223}
224
225void AssistantController::OnOutputNodeVolumeChanged(uint64_t node, int volume) {
226 // |node| refers to the active volume device, which we don't care here.
227 volume_observer_.ForAllPtrs([volume](mojom::VolumeObserver* observer) {
228 observer->OnVolumeChanged(volume);
229 });
230}
231
David Black2f7a70c32018-06-26 02:14:22232void AssistantController::OpenUrl(const GURL& url) {
David Blackedaf0c32018-06-28 22:06:39233 if (assistant::util::IsDeepLinkUrl(url)) {
David Black1f58bcc2018-07-12 17:59:40234 NotifyDeepLinkReceived(url);
David Blackedaf0c32018-06-28 22:06:39235 return;
236 }
David Black2f7a70c32018-06-26 02:14:22237
David Blackedaf0c32018-06-28 22:06:39238 Shell::Get()->new_window_controller()->NewTabWithUrl(url);
David Black1f58bcc2018-07-12 17:59:40239 NotifyUrlOpened(url);
240}
David Blacke802d4062018-06-29 01:59:05241
David Black1f58bcc2018-07-12 17:59:40242void AssistantController::NotifyConstructed() {
243 for (AssistantControllerObserver& observer : observers_)
244 observer.OnAssistantControllerConstructed();
245}
246
247void AssistantController::NotifyDestroying() {
248 for (AssistantControllerObserver& observer : observers_)
249 observer.OnAssistantControllerDestroying();
250}
251
252void AssistantController::NotifyDeepLinkReceived(const GURL& deep_link) {
David Blackb0749ca52018-07-13 21:30:02253 using namespace assistant::util;
254
255 // Retrieve deep link type and parsed parameters.
256 DeepLinkType type = GetDeepLinkType(deep_link);
257 const std::map<std::string, std::string> params =
258 GetDeepLinkParams(deep_link);
259
David Black1f58bcc2018-07-12 17:59:40260 for (AssistantControllerObserver& observer : observers_)
David Blackb0749ca52018-07-13 21:30:02261 observer.OnDeepLinkReceived(type, params);
David Black1f58bcc2018-07-12 17:59:40262}
263
264void AssistantController::NotifyUrlOpened(const GURL& url) {
David Blacke802d4062018-06-29 01:59:05265 for (AssistantControllerObserver& observer : observers_)
266 observer.OnUrlOpened(url);
David Black2f7a70c32018-06-26 02:14:22267}
268
Yue Libf33defd2018-08-01 21:04:06269void AssistantController::OnVoiceInteractionStatusChanged(
270 mojom::VoiceInteractionState state) {
Xiaohui Chen05715212018-08-08 15:52:28271 if (state == mojom::VoiceInteractionState::NOT_READY)
Yue Libf33defd2018-08-01 21:04:06272 assistant_ui_controller_->HideUi(AssistantSource::kUnspecified);
273}
274
wutao16db603c2018-07-10 06:43:59275base::WeakPtr<AssistantController> AssistantController::GetWeakPtr() {
276 return weak_factory_.GetWeakPtr();
277}
278
David Blacke8f815042018-03-28 18:59:37279} // namespace ash