blob: b10a089eb52bcc88ed7448bc17ec3936a83bd95d [file] [log] [blame]
// Copyright 2017 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/arc/voice_interaction/highlighter_controller_client.h"
#include <utility>
#include "ash/public/interfaces/constants.mojom.h"
#include "base/time/time.h"
#include "chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service.h"
#include "content/public/common/service_manager_connection.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "services/service_manager/public/cpp/connector.h"
namespace arc {
namespace {
constexpr int kSelectionReportDelayMs = 600;
}
HighlighterControllerClient::HighlighterControllerClient(
ArcVoiceInteractionFrameworkService* service)
: binding_(this), service_(service) {}
HighlighterControllerClient::~HighlighterControllerClient() = default;
void HighlighterControllerClient::Attach() {
ConnectToHighlighterController();
ash::mojom::HighlighterControllerClientPtr client;
binding_.Bind(mojo::MakeRequest(&client));
highlighter_controller_->SetClient(std::move(client));
}
void HighlighterControllerClient::Detach() {
binding_.Close();
}
void HighlighterControllerClient::SimulateSelectionTimeoutForTesting() {
DCHECK(delay_timer_ && delay_timer_->IsRunning());
delay_timer_->FireNow();
delay_timer_.reset();
}
void HighlighterControllerClient::FlushMojoForTesting() {
highlighter_controller_.FlushForTesting();
}
void HighlighterControllerClient::Exit() {
highlighter_controller_->ExitHighlighterMode();
}
void HighlighterControllerClient::ConnectToHighlighterController() {
// Connector can be overridden for testing.
if (!connector_) {
connector_ =
content::ServiceManagerConnection::GetForProcess()->GetConnector();
}
connector_->BindInterface(ash::mojom::kServiceName, &highlighter_controller_);
}
void HighlighterControllerClient::HandleSelection(const gfx::Rect& rect) {
// Delay the actual voice interaction service invocation for better
// visual synchronization with the metalayer animation.
delay_timer_ = std::make_unique<base::OneShotTimer>();
delay_timer_->Start(
FROM_HERE, base::TimeDelta::FromMilliseconds(kSelectionReportDelayMs),
base::Bind(&HighlighterControllerClient::ReportSelection,
base::Unretained(this), rect));
}
void HighlighterControllerClient::HandleEnabledStateChange(bool enabled) {
// ArcVoiceInteractionFrameworkService::HideMetalayer() causes the container
// to show a toast-like prompt. This toast is redundant and causes
// unnecessary flicker if the full voice interaction UI is about to be
// displayed soon. |start_session_pending| is a good signal that the session
// is about to start, but it is not guaranteed: 1) The user might re-enter the
// metalayer mode before the timer fires.
// In this case the container will keep showing the prompt for the
// metalayer mode.
// 2) The session might fail to start due to a peculiar combination of
// failures on the way to the voice interaction UI. This is an open
// problem.
if (enabled)
service_->ShowMetalayer();
else if (!start_session_pending())
service_->HideMetalayer();
}
void HighlighterControllerClient::ReportSelection(const gfx::Rect& rect) {
service_->StartSessionFromUserInteraction(rect);
}
} // namespace arc