blob: 438004ba87ab948b3ca26d5b98c2c0f722588162 [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.
#ifndef CHROME_BROWSER_DIPS_DIPS_UTILS_H_
#define CHROME_BROWSER_DIPS_DIPS_UTILS_H_
#include <ostream>
#include "base/files/file_path.h"
#include "base/strings/string_piece_forward.h"
#include "base/time/time.h"
#include "components/content_settings/browser/page_specific_content_settings.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_frame_host.h"
#include "services/network/public/mojom/cookie_access_observer.mojom.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
class ProfileSelections;
namespace base {
class TimeDelta;
}
namespace content {
class BrowserContext;
}
// A single cookie-accessing operation (either read or write). Not to be
// confused with SiteDataAccessType, which can also represent no access or both
// read+write.
using CookieOperation = network::mojom::CookieAccessDetails::Type;
inline CookieOperation ToCookieOperation(content_settings::AccessType type) {
switch (type) {
case content_settings::AccessType::kRead:
case content_settings::AccessType::kWrite:
case content_settings::AccessType::kUnknown:
return CookieOperation::kChange;
}
}
// The filename for the DIPS database.
const base::FilePath::CharType kDIPSFilename[] = FILE_PATH_LITERAL("DIPS");
// The FilePath for the ON-DISK DIPSDatabase associated with a BrowserContext,
// if one exists.
// NOTE: This returns the same value regardless of if there is actually a
// persisted DIPSDatabase for the BrowserContext or not.
base::FilePath GetDIPSFilePath(content::BrowserContext* context);
// The ProfileSelections used to dictate when the DIPSService should be created,
// if `dips::kFeature` is enabled, and when the DIPSCleanupService should be
// created, if `dips::kFeature` is NOT enabled.
ProfileSelections GetHumanProfileSelections();
// SiteDataAccessType:
// NOTE: We use this type as a bitfield, and will soon be logging it. Don't
// change the values or add additional members.
enum class SiteDataAccessType {
kUnknown = -1,
kNone = 0,
kRead = 1,
kWrite = 2,
kReadWrite = 3
};
inline SiteDataAccessType ToSiteDataAccessType(CookieOperation op) {
return (op == CookieOperation::kChange ? SiteDataAccessType::kWrite
: SiteDataAccessType::kRead);
}
base::StringPiece SiteDataAccessTypeToString(SiteDataAccessType type);
std::ostream& operator<<(std::ostream& os, SiteDataAccessType access_type);
constexpr SiteDataAccessType operator|(SiteDataAccessType lhs,
SiteDataAccessType rhs) {
return static_cast<SiteDataAccessType>(static_cast<int>(lhs) |
static_cast<int>(rhs));
}
// DIPSCookieMode:
enum class DIPSCookieMode {
kStandard,
kOffTheRecord,
kBlock3PC, // block third-party cookies
kOffTheRecord_Block3PC
};
DIPSCookieMode GetDIPSCookieMode(bool is_otr, bool block_third_party_cookies);
base::StringPiece GetHistogramSuffix(DIPSCookieMode mode);
const char* DIPSCookieModeToString(DIPSCookieMode mode);
std::ostream& operator<<(std::ostream& os, DIPSCookieMode mode);
// DIPSEventRemovalType:
// NOTE: We use this type as a bitfield don't change existing values other than
// kAll, which should be updated to include any new fields.
enum class DIPSEventRemovalType {
kNone = 0,
kHistory = 1 << 0,
kStorage = 1 << 1,
// kAll is intended to cover all the above fields.
kAll = kHistory | kStorage
};
constexpr DIPSEventRemovalType operator|(DIPSEventRemovalType lhs,
DIPSEventRemovalType rhs) {
return static_cast<DIPSEventRemovalType>(static_cast<int>(lhs) |
static_cast<int>(rhs));
}
constexpr DIPSEventRemovalType operator&(DIPSEventRemovalType lhs,
DIPSEventRemovalType rhs) {
return static_cast<DIPSEventRemovalType>(static_cast<int>(lhs) &
static_cast<int>(rhs));
}
constexpr DIPSEventRemovalType& operator|=(DIPSEventRemovalType& lhs,
DIPSEventRemovalType rhs) {
return lhs = lhs | rhs;
}
constexpr DIPSEventRemovalType& operator&=(DIPSEventRemovalType& lhs,
DIPSEventRemovalType rhs) {
return lhs = lhs & rhs;
}
// DIPSRedirectType:
enum class DIPSRedirectType { kClient, kServer };
base::StringPiece GetHistogramPiece(DIPSRedirectType type);
const char* DIPSRedirectTypeToString(DIPSRedirectType type);
std::ostream& operator<<(std::ostream& os, DIPSRedirectType type);
using TimestampRange = absl::optional<std::pair<base::Time, base::Time>>;
// Expand the range to include `time` if necessary. Returns true iff the range
// was modified.
bool UpdateTimestampRange(TimestampRange& range, base::Time time);
// Checks that `this` range is either null or falls within `other`.
bool IsNullOrWithin(const TimestampRange& inner, const TimestampRange& outer);
std::ostream& operator<<(std::ostream& os, TimestampRange type);
// StateValue:
struct StateValue {
TimestampRange site_storage_times;
TimestampRange user_interaction_times;
TimestampRange stateful_bounce_times;
TimestampRange bounce_times;
};
inline bool operator==(const StateValue& lhs, const StateValue& rhs) {
return std::tie(lhs.site_storage_times, lhs.user_interaction_times,
lhs.stateful_bounce_times, lhs.bounce_times) ==
std::tie(rhs.site_storage_times, rhs.user_interaction_times,
rhs.stateful_bounce_times, rhs.bounce_times);
}
enum class DIPSTriggeringAction { kNone, kStorage, kBounce, kStatefulBounce };
// Return the number of seconds in `td`, clamped to [0, 10].
// i.e. 11 linearly-sized buckets.
int64_t BucketizeBounceDelay(base::TimeDelta delta);
// Returns an opaque value representing the "privacy boundary" that the URL
// belongs to. Currently returns eTLD+1, but this is an implementation detail
// and may change.
std::string GetSiteForDIPS(const GURL& url);
// Returns `True` iff the `navigation_handle` represents a navigation happening
// in an iframe of the primary frame tree.
inline bool IsInPrimaryPageIFrame(
content::NavigationHandle* navigation_handle) {
return navigation_handle->GetParentFrame()
? navigation_handle->GetParentFrame()->GetPage().IsPrimary()
: false;
}
// Returns `True` iff both urls return a similar outcome off of
// `GetSiteForDIPS()`.
inline bool IsSameSiteForDIPS(const GURL& url1, const GURL& url2) {
return GetSiteForDIPS(url1) == GetSiteForDIPS(url2);
}
// Returns `True` iff the `navigation_handle` represents a navigation happening
// in any frame of the primary page.
// NOTE: This does not include fenced frames.
inline bool IsInPrimaryPage(content::NavigationHandle* navigation_handle) {
return navigation_handle->GetParentFrame()
? navigation_handle->GetParentFrame()->GetPage().IsPrimary()
: navigation_handle->IsInPrimaryMainFrame();
}
// Returns `True` iff the 'rfh' exists and represents a frame in the primary
// page.
inline bool IsInPrimaryPage(content::RenderFrameHost* rfh) {
return rfh && rfh->GetPage().IsPrimary();
}
// Returns the last committed or the to be committed url of the main frame of
// the page containing the `navigation_handle`.
inline GURL GetFirstPartyURL(content::NavigationHandle* navigation_handle) {
return navigation_handle->GetParentFrame()
? navigation_handle->GetParentFrame()
->GetMainFrame()
->GetLastCommittedURL()
: navigation_handle->GetURL();
}
// Returns an optional last committed url of the main frame of the page
// containing the `rfh`.
inline absl::optional<GURL> GetFirstPartyURL(content::RenderFrameHost* rfh) {
return rfh ? absl::optional<GURL>(rfh->GetMainFrame()->GetLastCommittedURL())
: absl::nullopt;
}
enum class DIPSRecordedEvent {
kStorage,
kInteraction,
kWebAuthnAssertion,
};
// RedirectCategory is basically the cross-product of SiteDataAccessType and a
// boolean value indicating site engagement. It's used in UMA enum histograms.
//
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class RedirectCategory {
kNoCookies_NoEngagement = 0,
kReadCookies_NoEngagement = 1,
kWriteCookies_NoEngagement = 2,
kReadWriteCookies_NoEngagement = 3,
kNoCookies_HasEngagement = 4,
kReadCookies_HasEngagement = 5,
kWriteCookies_HasEngagement = 6,
kReadWriteCookies_HasEngagement = 7,
kUnknownCookies_NoEngagement = 8,
kUnknownCookies_HasEngagement = 9,
kMaxValue = kUnknownCookies_HasEngagement,
};
// DIPSErrorCode is used in UMA enum histograms to monitor certain errors and
// verify that they are being fixed.
//
// When adding an error to this enum, update the DIPSErrorCode enum in
// tools/metrics/histograms/enums.xml as well.
//
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class DIPSErrorCode {
kRead_None = 0,
kRead_OpenEndedRange_NullStart = 1,
kRead_OpenEndedRange_NullEnd = 2,
kRead_BounceTimesIsntSupersetOfStatefulBounces = 3,
kMaxValue = kRead_BounceTimesIsntSupersetOfStatefulBounces,
};
// DIPSDeletionAction is used in UMA enum histograms to record the actual
// deletion action taken on DIPS-eligible (incidental) site.
//
// When adding an action to this enum, update the DIPSDeletionAction enum in
// tools/metrics/histograms/enums.xml as well.
//
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class DIPSDeletionAction {
kDisallowed = 0,
kExceptedAs1p = 1,
kExceptedAs3p = 2,
kEnforced = 3,
kIgnored = 4,
kMaxValue = kIgnored,
};
#endif // CHROME_BROWSER_DIPS_DIPS_UTILS_H_