chromium/components/permissions/contexts/geolocation_permission_context_android.h

// Copyright 2012 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_CONTEXTS_GEOLOCATION_PERMISSION_CONTEXT_ANDROID_H_
#define COMPONENTS_PERMISSIONS_CONTEXTS_GEOLOCATION_PERMISSION_CONTEXT_ANDROID_H_

// The flow for geolocation permissions on Android needs to take into account
// the global geolocation settings so it differs from the desktop one. It
// works as follows.
// GeolocationPermissionContextAndroid::RequestPermission intercepts the flow
// and proceeds to check the system location.
// This will in fact check several possible settings
//     - The global system geolocation setting
//     - The Google location settings on pre KK devices
//     - An old internal Chrome setting on pre-JB MR1 devices
// With all that information it will decide if system location is enabled.
// If enabled, it proceeds with the per site flow via
// GeolocationPermissionContext (which will check per site permissions, create
// infobars, etc.).
//
// Otherwise the permission is already decided.
#include <memory>

#include "base/memory/weak_ptr.h"
#include "components/location/android/location_settings.h"
#include "components/location/android/location_settings_dialog_context.h"
#include "components/location/android/location_settings_dialog_outcome.h"
#include "components/permissions/contexts/geolocation_permission_context.h"
#include "components/permissions/permission_request_id.h"

namespace content {
class WebContents;
}

class GURL;
class PrefRegistrySimple;

namespace permissions {

class GeolocationPermissionContextAndroid
    : public GeolocationPermissionContext {
 public:
  // This enum is used in histograms, thus is append only. Do not re-order or
  // remove any entries, or add any except at the end.
  enum class LocationSettingsDialogBackOff {
    kNoBackOff,
    kOneWeek,
    kOneMonth,
    kThreeMonths,
    kCount,
  };

  static void RegisterProfilePrefs(PrefRegistrySimple* registry);

  GeolocationPermissionContextAndroid(
      content::BrowserContext* browser_context,
      std::unique_ptr<Delegate> delegate,
      bool is_regular_profile,
      std::unique_ptr<LocationSettings> settings_override_for_test = nullptr);

  GeolocationPermissionContextAndroid(
      const GeolocationPermissionContextAndroid&) = delete;
  GeolocationPermissionContextAndroid& operator=(
      const GeolocationPermissionContextAndroid&) = delete;

  ~GeolocationPermissionContextAndroid() override;

  static void AddDayOffsetForTesting(int days);

  // Overrides the LocationSettings object used to determine whether
  // system and Chrome-wide location permissions are enabled.
  void SetLocationSettingsForTesting(
      std::unique_ptr<LocationSettings> settings);

 private:
  // GeolocationPermissionContext:
  void RequestPermission(PermissionRequestData request_data,
                         BrowserPermissionCallback callback) override;
  void UserMadePermissionDecision(const PermissionRequestID& id,
                                  const GURL& requesting_origin,
                                  const GURL& embedding_origin,
                                  ContentSetting content_setting) override;
  void NotifyPermissionSet(const PermissionRequestID& id,
                           const GURL& requesting_origin,
                           const GURL& embedding_origin,
                           BrowserPermissionCallback callback,
                           bool persist,
                           ContentSetting content_setting,
                           bool is_one_time,
                           bool is_final_decision) override;
  content::PermissionResult UpdatePermissionStatusWithDeviceStatus(
      content::PermissionResult result,
      const GURL& requesting_origin,
      const GURL& embedding_origin) override;
  bool AlwaysIncludeDeviceStatus() const override;

  // Functions to handle back off for showing the Location Settings Dialog.
  std::string GetLocationSettingsBackOffLevelPref(bool is_default_search) const;
  std::string GetLocationSettingsNextShowPref(bool is_default_search) const;
  bool IsInLocationSettingsBackOff(bool is_default_search) const;
  void ResetLocationSettingsBackOff(bool is_default_search);
  void UpdateLocationSettingsBackOff(bool is_default_search);
  LocationSettingsDialogBackOff LocationSettingsBackOffLevel(
      bool is_default_search) const;

  // Returns whether location access is possible for the given origin. Ignores
  // Location Settings Dialog backoff, as the backoff is ignored if the user
  // will be prompted for permission.
  bool IsLocationAccessPossible(content::WebContents* web_contents,
                                const GURL& requesting_origin,
                                bool user_gesture);

  bool IsRequestingOriginDSE(const GURL& requesting_origin) const;

  void HandleUpdateAndroidPermissions(const PermissionRequestID& id,
                                      const GURL& requesting_frame_origin,
                                      const GURL& embedding_origin,
                                      BrowserPermissionCallback callback,
                                      bool permissions_updated);

  // Will return true if the location settings dialog will be shown for the
  // given origins. This is true if the location setting is off, the dialog can
  // be shown, any gesture requirements for the origin are met, and the dialog
  // is not being suppressed for backoff.
  bool CanShowLocationSettingsDialog(const GURL& requesting_origin,
                                     bool user_gesture,
                                     bool ignore_backoff) const;

  void OnLocationSettingsDialogShown(
      const GURL& requesting_origin,
      const GURL& embedding_origin,
      bool persist,
      ContentSetting content_setting,
      bool is_one_time,
      LocationSettingsDialogOutcome prompt_outcome);

  void FinishNotifyPermissionSet(const PermissionRequestID& id,
                                 const GURL& requesting_origin,
                                 const GURL& embedding_origin,
                                 BrowserPermissionCallback callback,
                                 bool persist,
                                 ContentSetting content_setting,
                                 bool is_one_time);

  std::unique_ptr<LocationSettings> location_settings_;

  PermissionRequestID location_settings_dialog_request_id_;
  BrowserPermissionCallback location_settings_dialog_callback_;

  // Must be the last member, to ensure that it will be destroyed first, which
  // will invalidate weak pointers.
  base::WeakPtrFactory<GeolocationPermissionContextAndroid> weak_factory_{this};
};

}  // namespace permissions

#endif  // COMPONENTS_PERMISSIONS_CONTEXTS_GEOLOCATION_PERMISSION_CONTEXT_ANDROID_H_