1 // Copyright 2019 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 CHROME_BROWSER_METRICS_UKM_BACKGROUND_RECORDER_SERVICE_H_
6 #define CHROME_BROWSER_METRICS_UKM_BACKGROUND_RECORDER_SERVICE_H_
7 
8 #include "base/callback_forward.h"
9 #include "base/macros.h"
10 #include "base/memory/singleton.h"
11 #include "base/memory/weak_ptr.h"
12 #include "base/optional.h"
13 #include "base/task/cancelable_task_tracker.h"
14 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
15 #include "components/keyed_service/core/keyed_service.h"
16 #include "services/metrics/public/cpp/ukm_source_id.h"
17 
18 class Profile;
19 class UkmBackgroundRecorderBrowserTest;
20 
21 namespace content {
22 class BrowserContext;
23 }  // namespace content
24 
25 namespace history {
26 class HistoryService;
27 struct VisibleVisitCountToHostResult;
28 }  // namespace history
29 
30 namespace url {
31 class Origin;
32 }  // namespace url
33 
34 namespace ukm {
35 
36 // Service for background features that want to record UKM events. This service
37 // relies on the HistoryService, so that it can check whether the URL of the
38 // event is present in the Browser's history, and accordingly decide whether to
39 // generate a new SourceId or not.
40 class UkmBackgroundRecorderService : public KeyedService {
41  public:
42   using GetBackgroundSourceIdCallback =
43       base::OnceCallback<void(base::Optional<ukm::SourceId>)>;
44 
45   // |profile| is needed to access the appropriate services |this| depends on.
46   explicit UkmBackgroundRecorderService(Profile* profile);
47   ~UkmBackgroundRecorderService() override;
48 
49   void Shutdown() override;
50 
51   // Checks whether events related to |origin| can be recorded with UKM, by
52   // checking if |origin| is present in the profile's history. This
53   // should be used with background features if there will not be an open
54   // window at the time of the recording. |callback| will be run with a valid
55   // source ID if recording is allowed, or a nullopt otherwise.
56   void GetBackgroundSourceIdIfAllowed(const url::Origin& origin,
57                                       GetBackgroundSourceIdCallback callback);
58 
59  private:
60   friend UkmBackgroundRecorderBrowserTest;
61 
62   // Callback for querying the history service. |did_determine| is whether the
63   // history service was able to complete the query, and |num_visits| is the
64   // number of visits for the provided |origin|.
65   void DidGetVisibleVisitCount(
66       const url::Origin& origin,
67       UkmBackgroundRecorderService::GetBackgroundSourceIdCallback callback,
68       history::VisibleVisitCountToHostResult result);
69 
70   history::HistoryService* history_service_;
71 
72   // Task tracker used for querying URLs in the history service.
73   base::CancelableTaskTracker task_tracker_;
74 
75   base::WeakPtrFactory<UkmBackgroundRecorderService> weak_ptr_factory_{this};
76 
77   DISALLOW_COPY_AND_ASSIGN(UkmBackgroundRecorderService);
78 };
79 
80 class UkmBackgroundRecorderFactory : public BrowserContextKeyedServiceFactory {
81  public:
82   static UkmBackgroundRecorderFactory* GetInstance();
83   static UkmBackgroundRecorderService* GetForProfile(Profile* profile);
84 
85  private:
86   friend struct base::DefaultSingletonTraits<UkmBackgroundRecorderFactory>;
87 
88   UkmBackgroundRecorderFactory();
89   ~UkmBackgroundRecorderFactory() override;
90 
91   KeyedService* BuildServiceInstanceFor(
92       content::BrowserContext* context) const override;
93 
94   content::BrowserContext* GetBrowserContextToUse(
95       content::BrowserContext* context) const override;
96 };
97 
98 }  // namespace ukm
99 
100 #endif  // CHROME_BROWSER_METRICS_UKM_BACKGROUND_RECORDER_SERVICE_H_
101