blob: b82eba827cdfd1fb576a71c716ddea1e4bf148af [file] [log] [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/chromeos/video_conference/video_conference_web_app.h"
#include <memory>
#include <string>
#include <utility>
#include "base/check.h"
#include "base/logging.h"
#include "base/time/time.h"
#include "base/unguessable_token.h"
#include "chrome/browser/chromeos/video_conference/video_conference_manager_client_common.h"
#include "chrome/browser/chromeos/video_conference/video_conference_ukm_helper.h"
#include "chromeos/crosapi/mojom/video_conference.mojom-shared.h"
#include "chromeos/crosapi/mojom/video_conference.mojom.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/page.h"
#include "content/public/browser/permission_controller.h"
#include "content/public/browser/permission_descriptor_util.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h"
#include "extensions/browser/process_manager.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "third_party/blink/public/common/permissions/permission_utils.h"
namespace video_conference {
WEB_CONTENTS_USER_DATA_KEY_IMPL(VideoConferenceWebApp);
VideoConferenceWebApp::~VideoConferenceWebApp() = default;
void VideoConferenceWebApp::ActivateApp() {
auto& web_contents = GetWebContents();
web_contents.GetDelegate()->ActivateContents(&web_contents);
}
void VideoConferenceWebApp::SetCapturingStatus(VideoConferenceMediaType device,
bool is_capturing) {
vc_ukm_helper_->RegisterCapturingUpdate(device, is_capturing);
switch (device) {
case VideoConferenceMediaType::kCamera:
state_.is_capturing_camera = is_capturing;
break;
case VideoConferenceMediaType::kMicrophone:
state_.is_capturing_microphone = is_capturing;
break;
case VideoConferenceMediaType::kScreen:
state_.is_capturing_screen = is_capturing;
break;
}
}
VideoConferencePermissions VideoConferenceWebApp::GetPermissions() {
// Permissions don't work the same way for extensions so we equate permissions
// to capturing status for them.
if (state_.is_extension) {
return {.has_camera_permission = state_.is_capturing_camera,
.has_microphone_permission = state_.is_capturing_microphone};
}
auto& web_contents = GetWebContents();
auto* permission_controller =
web_contents.GetBrowserContext()->GetPermissionController();
CHECK(permission_controller);
bool has_camera_permission = false;
bool has_microphone_permission = false;
// Get permission from each render frame host.
web_contents.GetPrimaryMainFrame()->ForEachRenderFrameHost(
[&](content::RenderFrameHost* rfh) {
auto camera_status =
permission_controller->GetPermissionStatusForCurrentDocument(
content::PermissionDescriptorUtil::
CreatePermissionDescriptorForPermissionType(
blink::PermissionType::VIDEO_CAPTURE),
rfh);
auto microphone_status =
permission_controller->GetPermissionStatusForCurrentDocument(
content::PermissionDescriptorUtil::
CreatePermissionDescriptorForPermissionType(
blink::PermissionType::AUDIO_CAPTURE),
rfh);
has_camera_permission |=
camera_status == blink::mojom::PermissionStatus::GRANTED;
has_microphone_permission |=
microphone_status == blink::mojom::PermissionStatus::GRANTED;
});
return {has_camera_permission, has_microphone_permission};
}
bool VideoConferenceWebApp::IsInactiveExtension() {
return state_.is_extension &&
!(state_.is_capturing_camera || state_.is_capturing_microphone ||
state_.is_capturing_screen);
}
void VideoConferenceWebApp::OnWebContentsFocused(
content::RenderWidgetHost* render_widget_host) {
state_.last_activity_time = base::Time::Now();
}
void VideoConferenceWebApp::WebContentsDestroyed() {
remove_media_app_callback_.Run(state_.id);
}
void VideoConferenceWebApp::PrimaryPageChanged(content::Page& page) {
remove_media_app_callback_.Run(state_.id);
}
void VideoConferenceWebApp::TitleWasSet(content::NavigationEntry* entry) {
std::u16string new_title = std::u16string{entry->GetTitle()};
auto title_change_info = crosapi::mojom::TitleChangeInfo::New(
/*id=*/state_.id, /*new_title=*/std::move(new_title));
client_update_callback_.Run(crosapi::mojom::VideoConferenceClientUpdate::New(
/*added_or_removed_app=*/crosapi::mojom::VideoConferenceAppUpdate::kNone,
/*title_change_info=*/std::move(title_change_info)));
}
VideoConferenceWebApp::VideoConferenceWebApp(
content::WebContents* web_contents,
base::UnguessableToken id,
base::RepeatingCallback<void(const base::UnguessableToken&)>
remove_media_app_callback,
base::RepeatingCallback<void(
crosapi::mojom::VideoConferenceClientUpdatePtr)> client_update_callback)
: content::WebContentsObserver(web_contents),
content::WebContentsUserData<VideoConferenceWebApp>(*web_contents),
remove_media_app_callback_(std::move(remove_media_app_callback)),
client_update_callback_(std::move(client_update_callback)),
state_{.id = std::move(id),
.last_activity_time = base::Time::Now(),
.is_capturing_microphone = false,
.is_capturing_camera = false,
.is_capturing_screen = false},
vc_ukm_helper_(std::make_unique<VideoConferenceUkmHelper>(
ukm::UkmRecorder::Get(),
web_contents->GetPrimaryMainFrame()->GetPageUkmSourceId())) {
CHECK(remove_media_app_callback_);
auto* source =
extensions::ProcessManager::Get(web_contents->GetBrowserContext());
state_.is_extension = !!source->GetExtensionForWebContents(web_contents);
}
} // namespace video_conference