blob: b259aae88365dfe1907a2747c7e258e68a985af6 [file] [log] [blame]
// Copyright 2019 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 "chromeos/components/camera_app_ui/camera_app_helper_impl.h"
#include <utility>
#include "ash/public/cpp/tablet_mode.h"
#include "ash/public/cpp/window_properties.h"
#include "base/callback_helpers.h"
#include "base/strings/string_number_conversions.h"
#include "base/trace_event/trace_event.h"
#include "content/public/browser/web_contents.h"
#include "net/base/url_util.h"
#include "ui/aura/window.h"
namespace chromeos_camera {
namespace {
mojom::ScreenState ToMojoScreenState(ash::ScreenBacklightState s) {
switch (s) {
case ash::ScreenBacklightState::ON:
return mojom::ScreenState::ON;
case ash::ScreenBacklightState::OFF:
return mojom::ScreenState::OFF;
case ash::ScreenBacklightState::OFF_AUTO:
return mojom::ScreenState::OFF_AUTO;
default:
NOTREACHED();
}
}
mojom::FileMonitorResult ToMojoFileMonitorResult(
CameraAppUIDelegate::FileMonitorResult result) {
switch (result) {
case CameraAppUIDelegate::FileMonitorResult::DELETED:
return mojom::FileMonitorResult::DELETED;
case CameraAppUIDelegate::FileMonitorResult::CANCELED:
return mojom::FileMonitorResult::CANCELED;
case CameraAppUIDelegate::FileMonitorResult::ERROR:
return mojom::FileMonitorResult::ERROR;
default:
NOTREACHED();
}
}
bool HasExternalScreen() {
for (const auto& display : display::Screen::GetScreen()->GetAllDisplays()) {
if (!display.IsInternal()) {
return true;
}
}
return false;
}
absl::optional<uint32_t> ParseIntentIdFromUrl(const GURL& url) {
std::string id_str;
if (!net::GetValueForKeyInQuery(url, "intentId", &id_str)) {
return absl::nullopt;
}
uint32_t intent_id;
if (!base::StringToUint(id_str, &intent_id)) {
return absl::nullopt;
}
return intent_id;
}
} // namespace
CameraAppHelperImpl::CameraAppHelperImpl(
chromeos::CameraAppUI* camera_app_ui,
CameraResultCallback camera_result_callback,
SendBroadcastCallback send_broadcast_callback,
aura::Window* window)
: camera_app_ui_(camera_app_ui),
camera_result_callback_(std::move(camera_result_callback)),
send_broadcast_callback_(std::move(send_broadcast_callback)),
has_external_screen_(HasExternalScreen()),
pending_intent_id_(absl::nullopt),
window_(window) {
DCHECK(camera_app_ui);
DCHECK(window);
window->SetProperty(ash::kCanConsumeSystemKeysKey, true);
ash::TabletMode::Get()->AddObserver(this);
ash::ScreenBacklight::Get()->AddObserver(this);
}
CameraAppHelperImpl::~CameraAppHelperImpl() {
ash::TabletMode::Get()->RemoveObserver(this);
ash::ScreenBacklight::Get()->RemoveObserver(this);
if (pending_intent_id_.has_value()) {
camera_result_callback_.Run(*pending_intent_id_,
arc::mojom::CameraIntentAction::CANCEL, {},
base::DoNothing());
}
}
void CameraAppHelperImpl::Bind(
mojo::PendingReceiver<mojom::CameraAppHelper> receiver) {
receiver_.reset();
receiver_.Bind(std::move(receiver));
pending_intent_id_ = ParseIntentIdFromUrl(camera_app_ui_->url());
}
void CameraAppHelperImpl::HandleCameraResult(
uint32_t intent_id,
arc::mojom::CameraIntentAction action,
const std::vector<uint8_t>& data,
HandleCameraResultCallback callback) {
if (pending_intent_id_.has_value() && *pending_intent_id_ == intent_id &&
(action == arc::mojom::CameraIntentAction::FINISH ||
action == arc::mojom::CameraIntentAction::CANCEL)) {
pending_intent_id_ = absl::nullopt;
}
camera_result_callback_.Run(intent_id, action, data, std::move(callback));
}
void CameraAppHelperImpl::IsTabletMode(IsTabletModeCallback callback) {
std::move(callback).Run(ash::TabletMode::Get()->InTabletMode());
}
void CameraAppHelperImpl::StartPerfEventTrace(const std::string& event) {
TRACE_EVENT_BEGIN0("camera", event.c_str());
}
void CameraAppHelperImpl::StopPerfEventTrace(const std::string& event) {
TRACE_EVENT_END0("camera", event.c_str());
}
void CameraAppHelperImpl::SetTabletMonitor(
mojo::PendingRemote<TabletModeMonitor> monitor,
SetTabletMonitorCallback callback) {
tablet_mode_monitor_ = mojo::Remote<TabletModeMonitor>(std::move(monitor));
std::move(callback).Run(ash::TabletMode::Get()->InTabletMode());
}
void CameraAppHelperImpl::SetScreenStateMonitor(
mojo::PendingRemote<ScreenStateMonitor> monitor,
SetScreenStateMonitorCallback callback) {
screen_state_monitor_ = mojo::Remote<ScreenStateMonitor>(std::move(monitor));
auto&& mojo_state =
ToMojoScreenState(ash::ScreenBacklight::Get()->GetScreenBacklightState());
std::move(callback).Run(mojo_state);
}
void CameraAppHelperImpl::IsMetricsAndCrashReportingEnabled(
IsMetricsAndCrashReportingEnabledCallback callback) {
std::move(callback).Run(
camera_app_ui_->delegate()->IsMetricsAndCrashReportingEnabled());
}
void CameraAppHelperImpl::SetExternalScreenMonitor(
mojo::PendingRemote<ExternalScreenMonitor> monitor,
SetExternalScreenMonitorCallback callback) {
external_screen_monitor_ =
mojo::Remote<ExternalScreenMonitor>(std::move(monitor));
std::move(callback).Run(has_external_screen_);
}
void CameraAppHelperImpl::CheckExternalScreenState() {
if (has_external_screen_ == HasExternalScreen())
return;
has_external_screen_ = !has_external_screen_;
if (external_screen_monitor_.is_bound())
external_screen_monitor_->Update(has_external_screen_);
}
void CameraAppHelperImpl::OpenFileInGallery(const std::string& name) {
camera_app_ui_->delegate()->OpenFileInGallery(name);
}
void CameraAppHelperImpl::OpenFeedbackDialog(const std::string& placeholder) {
camera_app_ui_->delegate()->OpenFeedbackDialog(placeholder);
}
void CameraAppHelperImpl::SetCameraUsageMonitor(
mojo::PendingRemote<CameraUsageOwnershipMonitor> usage_monitor,
SetCameraUsageMonitorCallback callback) {
camera_app_ui_->app_window_manager()->SetCameraUsageMonitor(
window_, std::move(usage_monitor), std::move(callback));
}
void CameraAppHelperImpl::GetWindowStateController(
GetWindowStateControllerCallback callback) {
if (!window_state_controller_) {
window_state_controller_ =
std::make_unique<chromeos::CameraAppWindowStateController>(
views::Widget::GetWidgetForNativeWindow(window_));
}
mojo::PendingRemote<chromeos_camera::mojom::WindowStateController>
controller_remote;
window_state_controller_->AddReceiver(
controller_remote.InitWithNewPipeAndPassReceiver());
std::move(callback).Run(std::move(controller_remote));
}
void CameraAppHelperImpl::SendNewCaptureBroadcast(bool is_video,
const std::string& name) {
auto file_path = camera_app_ui_->delegate()->GetFilePathInArcByName(name);
if (file_path.empty()) {
LOG(ERROR) << "Drop the broadcast request due to invalid file path in ARC "
"generated by the file name: "
<< name;
return;
}
send_broadcast_callback_.Run(is_video, file_path);
}
void CameraAppHelperImpl::MonitorFileDeletion(
const std::string& name,
MonitorFileDeletionCallback callback) {
camera_app_ui_->delegate()->MonitorFileDeletion(
name, base::BindOnce(
[](MonitorFileDeletionCallback callback,
CameraAppUIDelegate::FileMonitorResult result) {
std::move(callback).Run(ToMojoFileMonitorResult(result));
},
std::move(callback)));
}
void CameraAppHelperImpl::OnTabletModeStarted() {
if (tablet_mode_monitor_.is_bound())
tablet_mode_monitor_->Update(true);
}
void CameraAppHelperImpl::OnTabletModeEnded() {
if (tablet_mode_monitor_.is_bound())
tablet_mode_monitor_->Update(false);
}
void CameraAppHelperImpl::OnScreenBacklightStateChanged(
ash::ScreenBacklightState screen_backlight_state) {
if (screen_state_monitor_.is_bound())
screen_state_monitor_->Update(ToMojoScreenState(screen_backlight_state));
}
void CameraAppHelperImpl::OnDisplayAdded(const display::Display& new_display) {
CheckExternalScreenState();
}
void CameraAppHelperImpl::OnDisplayRemoved(
const display::Display& old_display) {
CheckExternalScreenState();
}
} // namespace chromeos_camera