blob: 9b82d782a3143c0e23c0802c4ca015651def2a3c [file] [log] [blame]
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_PERMISSIONS_PERMISSION_REQUEST_H_
#define COMPONENTS_PERMISSIONS_PERMISSION_REQUEST_H_
#include <memory>
#include <optional>
#include <string>
#include "base/functional/callback.h"
#include "base/memory/weak_ptr.h"
#include "build/build_config.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/content_settings/core/common/content_settings_types.h"
#include "components/permissions/permission_hats_trigger_helper.h"
#include "components/permissions/permission_request_data.h"
#include "components/permissions/permission_request_enums.h"
#include "components/permissions/request_type.h"
#include "content/public/browser/global_routing_id.h"
#include "url/gurl.h"
namespace permissions {
enum class RequestType;
// Describes the interface a feature making permission requests should
// implement. A class of this type is registered with the permission request
// manager to receive updates about the result of the permissions request
// from the bubble or infobar. It should live until it is unregistered or until
// RequestFinished is called.
// Note that no particular guarantees are made about what exact UI surface
// is presented to the user. The delegate may be coalesced with other bubble
// requests, or depending on the situation, not shown at all.
class PermissionRequest {
public:
// If `result` is CONTENT_SETTING_ALLOW, the permission was granted by the
// user. If it's CONTENT_SETTING_BLOCK, the permission was blocked by the
// user. If it's CONTENT_SETTING_DEFAULT, the permission was ignored or
// dismissed without an explicit decision. No other ContentSetting value will
// be passed into this callback.
// If `is_one_time` is true, the decision will last until all tabs of
// `requesting_origin_` are closed or navigated away from.
using PermissionDecidedCallback = base::RepeatingCallback<void(
ContentSetting /*result*/,
bool /*is_one_time*/,
bool /*is_final_decision*/,
const PermissionRequestData& /*request_data*/)>;
// `permission_decided_callback` is called when the permission request is
// resolved by the user (see comment on PermissionDecidedCallback above).
// `delete_callback` is called when the permission request is no longer needed
// by the permission system. Therefore, it is safe to delete `this` inside
// `delete_callback`. It will always be called eventually by the permission
// system.
// `delete_callback` may be called before `permission_decided_callback`, for
// example if the tab is closed without user interaction. In this case, the
// javascript promise from the requesting origin will not be resolved.
PermissionRequest(std::unique_ptr<PermissionRequestData> request_data,
PermissionDecidedCallback permission_decided_callback,
base::OnceClosure delete_callback,
bool uses_automatic_embargo = true);
PermissionRequest(const PermissionRequest&) = delete;
PermissionRequest& operator=(const PermissionRequest&) = delete;
enum ChipTextType {
LOUD_REQUEST,
QUIET_REQUEST,
ALLOW_CONFIRMATION,
ALLOW_ONCE_CONFIRMATION,
BLOCKED_CONFIRMATION,
ACCESSIBILITY_ALLOWED_CONFIRMATION,
ACCESSIBILITY_ALLOWED_ONCE_CONFIRMATION,
ACCESSIBILITY_BLOCKED_CONFIRMATION
};
virtual ~PermissionRequest();
GURL requesting_origin() const { return data_->requesting_origin; }
RequestType request_type() const;
// Whether |this| and |other_request| are duplicates and therefore don't both
// need to be shown in the UI.
virtual bool IsDuplicateOf(PermissionRequest* other_request) const;
#if BUILDFLAG(IS_ANDROID)
// A message text with formatting information.
struct AnnotatedMessageText {
// |text| specifies the text string itself.
// |bolded_ranges| defines a (potentially empty) list of ranges represented
// as pairs of <textOffset, rangeSize>, which shall be used by the UI to
// format the specified ranges as bold text.
AnnotatedMessageText(std::u16string text,
std::vector<std::pair<size_t, size_t>> bolded_ranges);
~AnnotatedMessageText();
AnnotatedMessageText(const AnnotatedMessageText& other) = delete;
AnnotatedMessageText& operator=(const AnnotatedMessageText& other) = delete;
std::u16string text;
// A list of ranges defined as pairs of <offset, size> which
// will be used by Clank to format the ranges in |text| as bold.
std::vector<std::pair<size_t, size_t>> bolded_ranges;
};
virtual AnnotatedMessageText GetDialogAnnotatedMessageText(
const GURL& embedding_origin) const;
// Returns prompt text appropriate for displaying in an Android dialog.
static AnnotatedMessageText GetDialogAnnotatedMessageText(
std::u16string requesting_origin_formatted_for_display,
int message_id,
bool format_origin_bold);
#endif
// Returns a weak pointer to this instance.
base::WeakPtr<PermissionRequest> GetWeakPtr();
#if !BUILDFLAG(IS_ANDROID)
// Returns whether displaying a confirmation chip for the request is
// supported.
bool IsConfirmationChipSupported();
// Returns prompt icon appropriate for displaying on the chip button in the
// location bar.
IconId GetIconForChip();
// Returns prompt icon appropriate for displaying on the quiet chip button in
// the location bar.
IconId GetBlockedIconForChip();
// Returns prompt text appropriate for displaying on the chip button in the
// location bar.
std::optional<std::u16string> GetRequestChipText(ChipTextType type) const;
// Returns prompt text appropriate for displaying under the dialog title
// "[domain] wants to:".
virtual std::u16string GetMessageTextFragment() const;
#endif
// Returns the text to be used in the "allow always" button of the
// permission prompt.
// If not provided, the generic text for this button will be used instead.
// The default implementation returns std::nullopt (ie, use generic text).
virtual std::optional<std::u16string> GetAllowAlwaysText() const;
// Returns the text to be used in the "block" button of the permission
// prompt.
//
// If not provided, the generic text for this button will be used instead.
// The default implementation returns std::nullopt (ie, use generic text).
virtual std::optional<std::u16string> GetBlockText() const;
// Whether the request was initiated by the user clicking on the permission
// element.
bool IsEmbeddedPermissionElementInitiated() const;
// Returns the position of the element that caused the prompt to open.
std::optional<gfx::Rect> GetAnchorElementPosition() const;
// Returns true if the request has two origins and should use the two origin
// prompt. Returns false otherwise.
bool ShouldUseTwoOriginPrompt() const;
// Called when the user has granted the requested permission.
// If |is_one_time| is true the permission will last until all tabs of
// |origin| are closed or navigated away from, and then the permission will
// automatically expire after 1 day.
void PermissionGranted(bool is_one_time);
// Called when the user has denied the requested permission.
void PermissionDenied();
// Called when the user has cancelled the permission request. This
// corresponds to a denial, but is segregated in case the context needs to
// be able to distinguish between an active refusal or an implicit refusal.
void Cancelled(bool is_final_decision = true);
// The UI this request was associated with was answered by the user.
// It is safe for the request to be deleted at this point -- it will receive
// no further message from the permission request system. This method will
// eventually be called on every request which is not unregistered.
// It is ok to call this method without actually resolving the request via
// PermissionGranted(), PermissionDenied() or Canceled(). However, it will not
// resolve the javascript promise from the requesting origin.
void RequestFinished();
// Used to record UMA for whether requests are associated with a user gesture.
// To keep things simple this metric is only recorded for the most popular
// request types.
PermissionRequestGestureType GetGestureType() const;
virtual const std::vector<std::string>& GetRequestedAudioCaptureDeviceIds()
const;
virtual const std::vector<std::string>& GetRequestedVideoCaptureDeviceIds()
const;
// Used on Android to determine what Android OS permissions are needed for
// this permission request.
ContentSettingsType GetContentSettingsType() const;
void set_requesting_frame_id(content::GlobalRenderFrameHostId id) {
data_->id.set_global_render_frame_host_id(id);
}
const content::GlobalRenderFrameHostId& get_requesting_frame_id() {
return data_->id.global_render_frame_host_id();
}
// Permission name text fragment which can be used in permission prompts to
// identify the permission being requested.
virtual std::u16string GetPermissionNameTextFragment() const;
bool uses_automatic_embargo() const { return uses_automatic_embargo_; }
std::optional<PermissionHatsTriggerHelper::PreviewParametersForHats>
get_preview_parameters() const;
void set_preview_parameters(
PermissionHatsTriggerHelper::PreviewParametersForHats preview_parmeters);
protected:
// Sets whether this request is permission element initiated, for testing
// subclasses only.
void SetEmbeddedPermissionElementInitiatedForTesting(
bool embedded_permission_element_initiated);
private:
// The PermissionRequestData associated with this request.
std::unique_ptr<PermissionRequestData> data_;
// Called once a decision is made about the permission.
PermissionDecidedCallback permission_decided_callback_;
// Called when the request is no longer in use so it can be deleted by the
// caller.
base::OnceClosure delete_callback_;
const bool uses_automatic_embargo_ = true;
std::optional<PermissionHatsTriggerHelper::PreviewParametersForHats>
preview_parameters_;
base::WeakPtrFactory<PermissionRequest> weak_factory_{this};
};
} // namespace permissions
#endif // COMPONENTS_PERMISSIONS_PERMISSION_REQUEST_H_