blob: fab532d5842418c5e03e2cf5fd0ab82155465d07 [file] [log] [blame]
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromecast/browser/cast_permission_manager.h"
#include "base/functional/callback.h"
#include "base/logging.h"
#include "chromecast/base/metrics/cast_metrics_helper.h"
#include "chromecast/browser/cast_permission_user_data.h"
#include "chromecast/common/activity_url_filter.h"
#include "components/cast_receiver/browser/public/permissions_manager.h"
#include "content/public/browser/permission_controller.h"
#include "content/public/browser/permission_result.h"
#include "content/public/browser/web_contents.h"
#include "third_party/blink/public/common/permissions/permission_utils.h"
namespace {
bool IsRequestingOriginAllowed(
const GURL& requesting_origin,
const GURL& app_web_url,
const std::vector<std::string>& additional_feature_permission_origins) {
// |app_web_url| is allowed by default.
if (requesting_origin == app_web_url.DeprecatedGetOriginAsURL()) {
return true;
}
chromecast::ActivityUrlFilter activity_url_filter(
additional_feature_permission_origins);
return activity_url_filter.UrlMatchesWhitelist(requesting_origin);
}
blink::mojom::PermissionStatus GetPermissionStatusFromCastPermissionUserData(
blink::PermissionType permission,
const GURL& requesting_origin,
chromecast::shell::CastPermissionUserData* cast_permission_user_data) {
std::string app_id = cast_permission_user_data->GetAppId();
GURL app_web_url = cast_permission_user_data->GetAppWebUrl();
// We expect to grant blink::PermissionType::PROTECTED_MEDIA_IDENTIFIER
// to origins same as |app_web_url| by default.
if (requesting_origin != app_web_url.DeprecatedGetOriginAsURL() ||
permission != blink::PermissionType::PROTECTED_MEDIA_IDENTIFIER) {
chromecast::metrics::CastMetricsHelper::GetInstance()
->RecordApplicationEventWithValue(
app_id, /*session_id=*/"", /*sdk_version=*/"",
"Cast.Platform.PermissionRequestWithFrame",
static_cast<int>(permission));
}
if (!cast_permission_user_data->GetEnforceFeaturePermissions()) {
return blink::mojom::PermissionStatus::GRANTED;
}
// Permissions that are granted by default should have been added to the
// FeaturePermissions in CastPermissionUserData.
bool permitted =
cast_permission_user_data->GetFeaturePermissions().count(
static_cast<int32_t>(permission)) > 0 &&
IsRequestingOriginAllowed(
requesting_origin, app_web_url,
cast_permission_user_data->GetAdditionalFeaturePermissionOrigins());
return permitted ? blink::mojom::PermissionStatus::GRANTED
: ::blink::mojom::PermissionStatus::DENIED;
}
} // namespace
namespace chromecast {
namespace shell {
// TODO(b/191718807): Be more restrictive on the permissions.
// Currently, only collect metrics.
blink::mojom::PermissionStatus GetPermissionStatusInternal(
blink::PermissionType permission,
const GURL& requesting_origin) {
// We expect to grant blink::PermissionType::BACKGROUND_SYNC by
// default.
if (permission != blink::PermissionType::BACKGROUND_SYNC) {
metrics::CastMetricsHelper::GetInstance()->RecordApplicationEventWithValue(
"Cast.Platform.PermissionRequestWithoutFrame",
static_cast<int>(permission));
}
blink::mojom::PermissionStatus permission_status =
blink::mojom::PermissionStatus::GRANTED;
LOG(INFO) << __func__ << ": "
<< (permission_status == blink::mojom::PermissionStatus::GRANTED
? " grants "
: " doesn't grant ")
<< "permission " << static_cast<int>(permission)
<< " out of frame context.";
return permission_status;
}
blink::mojom::PermissionStatus GetPermissionStatusInternal(
const blink::mojom::PermissionDescriptorPtr& permission_descriptor,
content::RenderFrameHost* render_frame_host,
const GURL& requesting_origin) {
content::WebContents* web_contents =
content::WebContents::FromRenderFrameHost(render_frame_host);
const cast_receiver::PermissionsManager* permissions_manager =
cast_receiver::PermissionsManager::GetInstance(*web_contents);
const auto permission_type =
blink::PermissionDescriptorToPermissionType(permission_descriptor);
if (permissions_manager) {
const blink::mojom::PermissionStatus permission_status =
permissions_manager->GetPermissionStatus(permission_type,
requesting_origin);
if (permission_status == blink::mojom::PermissionStatus::GRANTED) {
return permission_status;
}
}
DCHECK(render_frame_host);
CastPermissionUserData* cast_permission_user_data =
CastPermissionUserData::FromWebContents(web_contents);
if (!cast_permission_user_data) {
LOG(ERROR) << __func__ << ": No permission data in frame!";
return GetPermissionStatusInternal(permission_type, requesting_origin);
}
blink::mojom::PermissionStatus permission_status =
GetPermissionStatusFromCastPermissionUserData(
permission_type, requesting_origin, cast_permission_user_data);
LOG(INFO) << __func__ << ": "
<< (permission_status == blink::mojom::PermissionStatus::GRANTED
? " grants "
: " doesn't grant ")
<< "permission " << static_cast<int>(permission_type)
<< " to frame associated with app: "
<< cast_permission_user_data->GetAppId();
return permission_status;
}
CastPermissionManager::CastPermissionManager() {}
CastPermissionManager::~CastPermissionManager() {}
void CastPermissionManager::RequestPermissions(
content::RenderFrameHost* render_frame_host,
const content::PermissionRequestDescription& request_description,
base::OnceCallback<void(const std::vector<content::PermissionResult>&)>
callback) {
std::vector<content::PermissionResult> permission_results;
for (const auto& permission : request_description.permissions) {
permission_results.emplace_back(GetPermissionStatusInternal(
permission, render_frame_host, request_description.requesting_origin));
}
std::move(callback).Run(permission_results);
}
void CastPermissionManager::ResetPermission(blink::PermissionType permission,
const GURL& requesting_origin,
const GURL& embedding_origin) {}
void CastPermissionManager::RequestPermissionsFromCurrentDocument(
content::RenderFrameHost* render_frame_host,
const content::PermissionRequestDescription& request_description,
base::OnceCallback<void(const std::vector<content::PermissionResult>&)>
callback) {
std::vector<content::PermissionResult> permission_results;
for (const auto& permission : request_description.permissions) {
permission_results.emplace_back(GetPermissionStatusInternal(
permission, render_frame_host,
render_frame_host->GetLastCommittedOrigin().GetURL()));
}
std::move(callback).Run(permission_results);
}
blink::mojom::PermissionStatus CastPermissionManager::GetPermissionStatus(
const blink::mojom::PermissionDescriptorPtr& permission,
const GURL& requesting_origin,
const GURL& embedding_origin) {
return GetPermissionStatusInternal(
blink::PermissionDescriptorToPermissionType(permission),
requesting_origin);
}
content::PermissionResult
CastPermissionManager::GetPermissionResultForOriginWithoutContext(
const blink::mojom::PermissionDescriptorPtr& permission_descriptor,
const url::Origin& requesting_origin,
const url::Origin& embedding_origin) {
blink::mojom::PermissionStatus status =
GetPermissionStatus(permission_descriptor, requesting_origin.GetURL(),
embedding_origin.GetURL());
return content::PermissionResult(status);
}
content::PermissionResult
CastPermissionManager::GetPermissionResultForCurrentDocument(
const blink::mojom::PermissionDescriptorPtr& permission_descriptor,
content::RenderFrameHost* render_frame_host,
bool should_include_device_status) {
return content::PermissionResult(GetPermissionStatusInternal(
permission_descriptor, render_frame_host,
render_frame_host->GetLastCommittedOrigin().GetURL()));
}
content::PermissionResult CastPermissionManager::GetPermissionResultForWorker(
const blink::mojom::PermissionDescriptorPtr& permission_descriptor,
content::RenderProcessHost* render_process_host,
const GURL& worker_origin) {
return content::PermissionResult(
GetPermissionStatus(permission_descriptor, worker_origin, worker_origin));
}
content::PermissionResult
CastPermissionManager::GetPermissionResultForEmbeddedRequester(
const blink::mojom::PermissionDescriptorPtr& permission_descriptor,
content::RenderFrameHost* render_frame_host,
const url::Origin& requesting_origin) {
return content::PermissionResult(GetPermissionStatusInternal(
permission_descriptor, render_frame_host, requesting_origin.GetURL()));
}
} // namespace shell
} // namespace chromecast