1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef COMPONENTS_PREVIEWS_CORE_PREVIEWS_BLOCK_LIST_H_
6 #define COMPONENTS_PREVIEWS_CORE_PREVIEWS_BLOCK_LIST_H_
7 
8 #include <stdint.h>
9 
10 #include <map>
11 #include <memory>
12 #include <string>
13 #include <vector>
14 
15 #include "base/callback.h"
16 #include "base/macros.h"
17 #include "base/optional.h"
18 #include "base/time/time.h"
19 #include "components/blocklist/opt_out_blocklist/opt_out_blocklist.h"
20 #include "components/blocklist/opt_out_blocklist/opt_out_blocklist_delegate.h"
21 #include "components/blocklist/opt_out_blocklist/opt_out_store.h"
22 #include "components/previews/core/previews_experiments.h"
23 
24 class GURL;
25 
26 namespace base {
27 class Clock;
28 }
29 
30 namespace previews {
31 
32 // Must remain synchronized with |PreviewsEligibilityReason| in
33 // //tools/metrics/histograms/enums.xml.
34 enum class PreviewsEligibilityReason {
35   // The preview navigation was allowed.
36   ALLOWED = 0,
37   // The block list was not initialized.
38   BLOCKLIST_UNAVAILABLE = 1,
39   // The block list has not loaded from disk yet.
40   BLOCKLIST_DATA_NOT_LOADED = 2,
41   // The user has opted out of a preview recently.
42   USER_RECENTLY_OPTED_OUT = 3,
43   // The user has opted out of previews often, and is no longer shown previews
44   // on any host.
45   USER_BLOCKLISTED = 4,
46   // The user has opted out of previews on a specific host often, and was not
47   // not shown a previews on that host.
48   HOST_BLOCKLISTED = 5,
49   // The network quality estimate is not available.
50   NETWORK_QUALITY_UNAVAILABLE = 6,
51   // The network was fast enough to not warrant previews.
52   NETWORK_NOT_SLOW = 7,
53   // If the page was reloaded, the user should not be shown a stale preview.
54   RELOAD_DISALLOWED = 8,
55   // DEPRECATED: The host is explicitly blocklisted by the server, so the user
56   // was not shown
57   // a preview.
58   // Replaced by NOT_ALLOWED_BY_OPTIMIZATION_GUIDE.
59   DEPRECATED_HOST_BLOCKLISTED_BY_SERVER = 9,
60   // DEPRECATED: The host is not allowlisted by the server for a preview
61   // decision that uses
62   // server optimization hints.
63   // Replaced by NOT_ALLOWED_BY_OPTIMIZATION_GUIDE.
64   DEPRECATED_HOST_NOT_ALLOWLISTED_BY_SERVER = 10,
65   // The preview is allowed but without an expected check of server optimization
66   // hints because they are not enabled (features::kOptimizationHints).
67   ALLOWED_WITHOUT_OPTIMIZATION_HINTS = 11,
68   // The preview type chosen as the committed preview.
69   COMMITTED = 12,
70   // Previews blocked by a Cache-Control:no-transform directive.
71   CACHE_CONTROL_NO_TRANSFORM = 13,
72   // The network is faster than the max slow page triggering threshold for the
73   // session. No longer used as of M80.
74   DEPRECATED_NETWORK_NOT_SLOW_FOR_SESSION = 14,
75   // Device is offline.
76   DEVICE_OFFLINE = 15,
77   // URL contained Basic Authentication, i.e.: a username or password.
78   URL_HAS_BASIC_AUTH = 16,
79   // Optimization hints needed to be checked for this preview type, but were not
80   // available. Common on first navigations.
81   OPTIMIZATION_HINTS_NOT_AVAILABLE = 17,
82   // The navigation URL has a media suffix which is excluded from previews.
83   EXCLUDED_BY_MEDIA_SUFFIX = 18,
84   // The Optimization Guide was checked for this preview type and the
85   // optimization guide did not allow this preview type.
86   NOT_ALLOWED_BY_OPTIMIZATION_GUIDE = 19,
87   // The preview was not performed due to a coinflip experiment holdback.
88   COINFLIP_HOLDBACK = 20,
89   // A redirect loop was detected.
90   REDIRECT_LOOP_DETECTED = 21,
91   // URL matched the deny list.
92   DENY_LIST_MATCHED = 22,
93   // The page load was not predicted to be painful.
94   PAGE_LOAD_PREDICTION_NOT_PAINFUL = 23,
95   LAST,
96 };
97 
98 // Manages the state of block listed domains for the previews experiment. Loads
99 // the stored block list from |opt_out_store| and manages an in memory block
100 // list on the IO thread. Updates to the block list are stored in memory and
101 // pushed to the store. Asynchronous modifications are stored in a queue and
102 // executed in order. Reading from the block list is always synchronous, and if
103 // the block list is not currently loaded (e.g., at startup, after clearing
104 // browsing history), domains are reported as block listed. The list stores no
105 // more than previews::params::MaxInMemoryHostsInBlockList hosts in-memory,
106 // which defaults to 100.
107 class PreviewsBlockList : public blocklist::OptOutBlocklist {
108  public:
109   PreviewsBlockList(
110       std::unique_ptr<blocklist::OptOutStore> opt_out_store,
111       base::Clock* clock,
112       blocklist::OptOutBlocklistDelegate* blocklist_delegate,
113       blocklist::BlocklistData::AllowedTypesAndVersions allowed_types);
114   ~PreviewsBlockList() override;
115 
116   // Asynchronously adds a new navigation to to the in-memory block list and
117   // backing store. |opt_out| is whether the user opted out of the preview or
118   // navigated away from the page without opting out. |type| is only passed to
119   // the backing store. If the in memory map has reached the max number of hosts
120   // allowed, and |url| is a new host, a host will be evicted based on recency
121   // of the hosts most recent opt out. It returns the time used for recording
122   // the moment when the navigation is added for logging.
123   base::Time AddPreviewNavigation(const GURL& url,
124                                   bool opt_out,
125                                   PreviewsType type);
126 
127   // Synchronously determines if |host_name| should be allowed to show previews.
128   // Returns the reason the blocklist disallowed the preview, or
129   // PreviewsEligibilityReason::ALLOWED if the preview is allowed. Record
130   // checked reasons in |passed_reasons|. Virtualized in testing.
131   virtual PreviewsEligibilityReason IsLoadedAndAllowed(
132       const GURL& url,
133       PreviewsType type,
134       std::vector<PreviewsEligibilityReason>* passed_reasons) const;
135 
136  protected:
137   // blocklist::OptOutBlocklist (virtual for testing):
138   bool ShouldUseSessionPolicy(base::TimeDelta* duration,
139                               size_t* history,
140                               int* threshold) const override;
141   bool ShouldUsePersistentPolicy(base::TimeDelta* duration,
142                                  size_t* history,
143                                  int* threshold) const override;
144   bool ShouldUseHostPolicy(base::TimeDelta* duration,
145                            size_t* history,
146                            int* threshold,
147                            size_t* max_hosts) const override;
148   bool ShouldUseTypePolicy(base::TimeDelta* duration,
149                            size_t* history,
150                            int* threshold) const override;
151   blocklist::BlocklistData::AllowedTypesAndVersions GetAllowedTypes()
152       const override;
153 
154  private:
155   const blocklist::BlocklistData::AllowedTypesAndVersions allowed_types_;
156 
157   DISALLOW_COPY_AND_ASSIGN(PreviewsBlockList);
158 };
159 
160 }  // namespace previews
161 
162 #endif  // COMPONENTS_PREVIEWS_CORE_PREVIEWS_BLOCK_LIST_H_
163