| // 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/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( |
| blink::PermissionType permission, |
| 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); |
| if (permissions_manager) { |
| const blink::mojom::PermissionStatus permission_status = |
| permissions_manager->GetPermissionStatus(permission, 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, requesting_origin); |
| } |
| |
| blink::mojom::PermissionStatus permission_status = |
| GetPermissionStatusFromCastPermissionUserData( |
| permission, requesting_origin, cast_permission_user_data); |
| LOG(INFO) << __func__ << ": " |
| << (permission_status == blink::mojom::PermissionStatus::GRANTED |
| ? " grants " |
| : " doesn't grant ") |
| << "permission " << static_cast<int>(permission) |
| << " 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<blink::mojom::PermissionStatus>&)> |
| callback) { |
| std::vector<blink::mojom::PermissionStatus> permission_statuses; |
| for (auto permission : request_description.permissions) { |
| permission_statuses.push_back(GetPermissionStatusInternal( |
| permission, render_frame_host, request_description.requesting_origin)); |
| } |
| std::move(callback).Run(permission_statuses); |
| } |
| |
| 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<blink::mojom::PermissionStatus>&)> |
| callback) { |
| std::vector<blink::mojom::PermissionStatus> permission_statuses; |
| for (auto permission : request_description.permissions) { |
| permission_statuses.push_back(GetPermissionStatusInternal( |
| permission, render_frame_host, |
| render_frame_host->GetLastCommittedOrigin().GetURL())); |
| } |
| std::move(callback).Run(permission_statuses); |
| } |
| |
| blink::mojom::PermissionStatus CastPermissionManager::GetPermissionStatus( |
| blink::PermissionType permission, |
| const GURL& requesting_origin, |
| const GURL& embedding_origin) { |
| return GetPermissionStatusInternal(permission, requesting_origin); |
| } |
| |
| content::PermissionResult |
| CastPermissionManager::GetPermissionResultForOriginWithoutContext( |
| blink::PermissionType permission, |
| const url::Origin& requesting_origin, |
| const url::Origin& embedding_origin) { |
| blink::mojom::PermissionStatus status = GetPermissionStatus( |
| permission, requesting_origin.GetURL(), embedding_origin.GetURL()); |
| |
| return content::PermissionResult( |
| status, content::PermissionStatusSource::UNSPECIFIED); |
| } |
| |
| blink::mojom::PermissionStatus |
| CastPermissionManager::GetPermissionStatusForCurrentDocument( |
| blink::PermissionType permission, |
| content::RenderFrameHost* render_frame_host, |
| bool should_include_device_status) { |
| return GetPermissionStatusInternal( |
| permission, render_frame_host, |
| render_frame_host->GetLastCommittedOrigin().GetURL()); |
| } |
| |
| blink::mojom::PermissionStatus |
| CastPermissionManager::GetPermissionStatusForWorker( |
| blink::PermissionType permission, |
| content::RenderProcessHost* render_process_host, |
| const GURL& worker_origin) { |
| return GetPermissionStatusInternal(permission, worker_origin); |
| } |
| |
| blink::mojom::PermissionStatus |
| CastPermissionManager::GetPermissionStatusForEmbeddedRequester( |
| blink::PermissionType permission, |
| content::RenderFrameHost* render_frame_host, |
| const url::Origin& requesting_origin) { |
| return GetPermissionStatusInternal(permission, render_frame_host, |
| requesting_origin.GetURL()); |
| } |
| |
| } // namespace shell |
| } // namespace chromecast |