File: recent_tab_helper.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (180 lines) | stat: -rw-r--r-- 7,776 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
// Copyright 2016 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_OFFLINE_PAGES_RECENT_TAB_HELPER_H_
#define CHROME_BROWSER_OFFLINE_PAGES_RECENT_TAB_HELPER_H_

#include <memory>
#include <vector>

#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "components/offline_pages/core/offline_page_model.h"
#include "components/offline_pages/core/snapshot_controller.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h"

namespace content {
class NavigationHandle;
}

namespace offline_pages {

// Attaches to every WebContent shown in a tab. Waits until the WebContent is
// loaded to proper degree and then makes a snapshot of the page. Removes the
// oldest snapshot in the 'ring buffer'. As a result, there is always up to N
// snapshots of recent pages on the device.
class RecentTabHelper
    : public content::WebContentsObserver,
      public content::WebContentsUserData<RecentTabHelper>,
      public SnapshotController::Client {
 public:
  RecentTabHelper(const RecentTabHelper&) = delete;
  RecentTabHelper& operator=(const RecentTabHelper&) = delete;

  ~RecentTabHelper() override;

  // content::WebContentsObserver
  void DidFinishNavigation(
      content::NavigationHandle* navigation_handle) override;
  void PrimaryMainDocumentElementAvailable() override;
  void DocumentOnLoadCompletedInPrimaryMainFrame() override;
  void WebContentsDestroyed() override;
  void OnVisibilityChanged(content::Visibility visibility) override;

  // Notifies that the tab of the associated WebContents will (most probably) be
  // closed. This call is expected to always happen before the one to WasHidden.
  void WillCloseTab();

  // SnapshotController::Client
  void StartSnapshot() override;

  // Delegate that is used by RecentTabHelper to get external dependencies.
  // Default implementation lives in .cc file, while tests provide an override.
  class Delegate {
   public:
    virtual ~Delegate() = default;
    virtual std::unique_ptr<OfflinePageArchiver> CreatePageArchiver(
        content::WebContents* web_contents) = 0;
    // There is no expectations that tab_id is always present.
    virtual bool GetTabId(content::WebContents* web_contents, int* tab_id) = 0;
    virtual bool IsLowEndDevice() = 0;
    virtual bool IsCustomTab(content::WebContents* web_contents) = 0;
  };
  void SetDelegate(std::unique_ptr<RecentTabHelper::Delegate> delegate);

  // Creates a request to download the current page with a properly filled
  // |client_id| and valid |request_id| issued by RequestCoordinator from a
  // suspended request. This method might be called multiple times for the same
  // page at any point after its navigation commits. There are some important
  // points about how requests are handled:
  // a) While there is an ongoing request, new requests are ignored (no
  //    overlapping snapshots).
  // b) The page has to be sufficiently loaded to be considerer of minimum
  //    quality for the request to be started immediately.
  // c) Any calls made before the page is considered to have minimal quality
  //    will be scheduled to be executed once that happens. The scheduled
  //    request is considered "ongoing" for a) purposes.
  // d) If the save operation is successful the dormant request with
  //    RequestCoordinator is canceled; otherwise it is resumed. This logic is
  //    robust to crashes.
  // e) At the moment the page reaches high quality, if there was a successful
  //    snapshot saved at a lower quality then a new snapshot is automatically
  //    requested to replace it.
  // Note #1: Page quality is determined by SnapshotController and is based on
  // its assessment of "how much loaded" it is.
  // Note #2: Currently this method only accepts download requests from the
  // downloads namespace.
  void ObserveAndDownloadCurrentPage(const ClientId& client_id,
                                     int64_t request_id,
                                     const std::string& origin);

 private:
  FRIEND_TEST_ALL_PREFIXES(RecentTabHelperFencedFrameTest,
                           FencedFrameDoesNotChangePageQuality);

  struct SnapshotProgressInfo;

  explicit RecentTabHelper(content::WebContents* web_contents);
  friend class content::WebContentsUserData<RecentTabHelper>;

  void WebContentsWasHidden();
  void WebContentsWasShown();

  bool EnsureInitialized();
  void ContinueSnapshotWithIdsToPurge(SnapshotProgressInfo* snapshot_info,
                                      const std::vector<int64_t>& page_ids);
  void ContinueSnapshotAfterPurge(SnapshotProgressInfo* snapshot_info,
                                  OfflinePageModel::DeletePageResult result);
  void SavePageCallback(SnapshotProgressInfo* snapshot_info,
                        OfflinePageModel::SavePageResult result,
                        int64_t offline_id);
  void ReportSnapshotCompleted(SnapshotProgressInfo* snapshot_info,
                               bool success);
  void ReportDownloadStatusToRequestCoordinator(
      SnapshotProgressInfo* snapshot_info,
      bool cancel_background_request);
  ClientId GetRecentPagesClientId() const;
  void SaveSnapshotForDownloads(bool replace_latest);
  void CancelInFlightSnapshots();

  // Page model is a service, no ownership. Can be null - for example, in
  // case when tab is in incognito profile.
  raw_ptr<OfflinePageModel> page_model_ = nullptr;

  // If false, never make snapshots off the attached WebContents.
  // Not page-specific.
  bool snapshots_enabled_ = false;

  // Snapshot progress information for an ongoing snapshot requested by
  // downloads. Null if there's no ongoing request.
  std::unique_ptr<SnapshotProgressInfo> downloads_ongoing_snapshot_info_;

  // This is set to true if the ongoing snapshot for downloads is waiting on the
  // page to reach a minimal quality level to start.
  bool downloads_snapshot_on_hold_ = false;

  // Snapshot information for the last successful snapshot requested by
  // downloads. Null if no successful one has ever completed for the current
  // page.
  std::unique_ptr<SnapshotProgressInfo> downloads_latest_saved_snapshot_info_;

  // Snapshot progress information for a last_n triggered request. Null if
  // last_n is not currently capturing the current page. It is cleared upon non
  // ignored navigations.
  std::unique_ptr<SnapshotProgressInfo> last_n_ongoing_snapshot_info_;

  // Snapshot information for the last successful snapshot requested by
  // last_n for the currently loaded page. Null if no successful one has ever
  // completed for the current page. It is cleared when the referenced snapshot
  // is about to be deleted.
  std::unique_ptr<SnapshotProgressInfo> last_n_latest_saved_snapshot_info_;

  // If empty, the tab does not have AndroidId and can not capture pages.
  std::string tab_id_;

  // Monitors page loads and starts snapshots when a download request exist. It
  // is also used as an initialization flag for EnsureInitialized() to be run
  // only once.
  std::unique_ptr<SnapshotController> snapshot_controller_;

  std::unique_ptr<Delegate> delegate_;

  // Set at each navigation to control if last_n should save snapshots of the
  // current page being loaded.
  bool last_n_listen_to_tab_hidden_ = false;

  // Set to true when the tab containing the associated WebContents is in the
  // process of being closed.
  bool tab_is_closing_ = false;

  base::WeakPtrFactory<RecentTabHelper> weak_ptr_factory_{this};

  WEB_CONTENTS_USER_DATA_KEY_DECL();
};

}  // namespace offline_pages

#endif  // CHROME_BROWSER_OFFLINE_PAGES_RECENT_TAB_HELPER_H_