Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(148)

Side by Side Diff: components/offline_pages/offline_page_model.h

Issue 2011763005: Splits the OfflinePageModel into and interface and and implementation class. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix to take ExpirePages defn out of model i/f as StorageManager defines it currently Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « components/offline_pages/BUILD.gn ('k') | components/offline_pages/offline_page_model.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef COMPONENTS_OFFLINE_PAGES_OFFLINE_PAGE_MODEL_H_ 5 #ifndef COMPONENTS_OFFLINE_PAGES_OFFLINE_PAGE_MODEL_H_
6 #define COMPONENTS_OFFLINE_PAGES_OFFLINE_PAGE_MODEL_H_ 6 #define COMPONENTS_OFFLINE_PAGES_OFFLINE_PAGE_MODEL_H_
7 7
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include <map>
11 #include <memory> 10 #include <memory>
12 #include <set> 11 #include <set>
12 #include <string>
13 #include <vector> 13 #include <vector>
14 14
15 #include "base/callback.h"
16 #include "base/files/file_path.h"
17 #include "base/gtest_prod_util.h"
18 #include "base/macros.h"
19 #include "base/memory/ref_counted.h"
20 #include "base/memory/scoped_vector.h"
21 #include "base/memory/weak_ptr.h"
22 #include "base/observer_list.h"
23 #include "base/optional.h"
24 #include "base/supports_user_data.h" 15 #include "base/supports_user_data.h"
25 #include "components/keyed_service/core/keyed_service.h"
26 #include "components/offline_pages/offline_page_archiver.h" 16 #include "components/offline_pages/offline_page_archiver.h"
27 #include "components/offline_pages/offline_page_metadata_store.h"
28 #include "components/offline_pages/offline_page_storage_manager.h" 17 #include "components/offline_pages/offline_page_storage_manager.h"
29 #include "components/offline_pages/offline_page_types.h" 18 #include "components/offline_pages/offline_page_types.h"
30 19
31 class GURL; 20 class GURL;
32 namespace base { 21 namespace base {
33 class SequencedTaskRunner;
34 class Time; 22 class Time;
35 class TimeDelta;
36 class TimeTicks;
37 } // namespace base 23 } // namespace base
38 24
39 namespace offline_pages { 25 namespace offline_pages {
40 26
41 static const char* const kBookmarkNamespace = "bookmark"; 27 static const char* const kBookmarkNamespace = "bookmark";
42 static const int64_t kInvalidOfflineId = 0; 28 static const int64_t kInvalidOfflineId = 0;
43 29
44 struct ClientId; 30 struct ClientId;
45 struct OfflinePageItem; 31 struct OfflinePageItem;
46 32
47 class ArchiveManager;
48 class ClientPolicyController;
49 class OfflinePageMetadataStore;
50 class OfflinePageStorageManager;
51
52 // Service for saving pages offline, storing the offline copy and metadata, and 33 // Service for saving pages offline, storing the offline copy and metadata, and
53 // retrieving them upon request. 34 // retrieving them upon request.
54 // 35 //
55 // Example usage: 36 // Example usage:
56 // class ArchiverImpl : public OfflinePageArchiver { 37 // class ArchiverImpl : public OfflinePageArchiver {
57 // // This is a class that knows how to create archiver 38 // // This is a class that knows how to create archiver
58 // void CreateArchiver(...) override; 39 // void CreateArchiver(...) override;
59 // ... 40 // ...
60 // } 41 // }
61 // 42 //
62 // // In code using the OfflinePagesModel to save a page: 43 // // In code using the OfflinePagesModel to save a page:
63 // std::unique_ptr<ArchiverImpl> archiver(new ArchiverImpl()); 44 // std::unique_ptr<ArchiverImpl> archiver(new ArchiverImpl());
64 // // Callback is of type SavePageCallback. 45 // // Callback is of type SavePageCallback.
65 // model->SavePage(url, std::move(archiver), callback); 46 // model->SavePage(url, std::move(archiver), callback);
66 // 47 //
67 // TODO(fgorski): Things to describe: 48 // TODO(fgorski): Things to describe:
68 // * how to cancel requests and what to expect 49 // * how to cancel requests and what to expect
69 class OfflinePageModel : public KeyedService, 50 class OfflinePageModel : public base::SupportsUserData,
70 public base::SupportsUserData,
71 public OfflinePageStorageManager::Client { 51 public OfflinePageStorageManager::Client {
72 public: 52 public:
73 // Observer of the OfflinePageModel. 53 // Observer of the OfflinePageModel.
74 class Observer { 54 class Observer {
75 public: 55 public:
76 // Invoked when the model has finished loading. 56 // Invoked when the model has finished loading.
77 virtual void OfflinePageModelLoaded(OfflinePageModel* model) = 0; 57 virtual void OfflinePageModelLoaded(OfflinePageModel* model) = 0;
78 58
79 // Invoked when the model is being updated, due to adding, removing or 59 // Invoked when the model is being updated, due to adding, removing or
80 // updating an offline page. 60 // updating an offline page.
81 virtual void OfflinePageModelChanged(OfflinePageModel* model) = 0; 61 virtual void OfflinePageModelChanged(OfflinePageModel* model) = 0;
82 62
83 // Invoked when an offline copy related to |offline_id| was deleted. 63 // Invoked when an offline copy related to |offline_id| was deleted.
84 // In can be invoked as a result of |CheckForExternalFileDeletion|, if a 64 // In can be invoked as a result of |CheckForExternalFileDeletion|, if a
85 // deleted page is detected. 65 // deleted page is detected.
86 virtual void OfflinePageDeleted(int64_t offline_id, 66 virtual void OfflinePageDeleted(int64_t offline_id,
87 const ClientId& client_id) = 0; 67 const ClientId& client_id) = 0;
88 68
89 protected: 69 protected:
90 virtual ~Observer() {} 70 virtual ~Observer() = default;
91 }; 71 };
92 72
93 using CheckPagesExistOfflineResult = 73 using CheckPagesExistOfflineResult =
94 offline_pages::CheckPagesExistOfflineResult; 74 offline_pages::CheckPagesExistOfflineResult;
95 using MultipleOfflinePageItemResult = 75 using MultipleOfflinePageItemResult =
96 offline_pages::MultipleOfflinePageItemResult; 76 offline_pages::MultipleOfflinePageItemResult;
97 using SingleOfflinePageItemResult = 77 using SingleOfflinePageItemResult =
98 offline_pages::SingleOfflinePageItemResult; 78 offline_pages::SingleOfflinePageItemResult;
99
100 //using DeletePageCallback = offline_pages::DeletePageCallback;
101 using DeletePageResult = offline_pages::DeletePageResult; 79 using DeletePageResult = offline_pages::DeletePageResult;
102 using SavePageResult = offline_pages::SavePageResult; 80 using SavePageResult = offline_pages::SavePageResult;
103 81
104 // Generates a new offline id
105 static int64_t GenerateOfflineId();
106
107 // Returns true if an offline copy can be saved for the given URL. 82 // Returns true if an offline copy can be saved for the given URL.
83 // TODO(dougarnett): Consider renaming and moving to Utils.
108 static bool CanSavePage(const GURL& url); 84 static bool CanSavePage(const GURL& url);
109 85
110 static base::TimeDelta GetFinalDeletionDelayForTesting(); 86 OfflinePageModel();
111
112 // All blocking calls/disk access will happen on the provided |task_runner|.
113 OfflinePageModel(std::unique_ptr<OfflinePageMetadataStore> store,
114 const base::FilePath& archives_dir,
115 const scoped_refptr<base::SequencedTaskRunner>& task_runner);
116 ~OfflinePageModel() override; 87 ~OfflinePageModel() override;
117 88
118 void AddObserver(Observer* observer); 89 virtual void AddObserver(Observer* observer) = 0;
119 void RemoveObserver(Observer* observer); 90 virtual void RemoveObserver(Observer* observer) = 0;
120 91
121 // Attempts to save a page addressed by |url| offline. Requires that the model 92 // Attempts to save a page addressed by |url| offline. Requires that the model
122 // is loaded. Generates a new offline id and returns it. 93 // is loaded. Generates a new offline id and returns it.
123 void SavePage(const GURL& url, 94 virtual void SavePage(const GURL& url,
124 const ClientId& client_id, 95 const ClientId& client_id,
125 std::unique_ptr<OfflinePageArchiver> archiver, 96 std::unique_ptr<OfflinePageArchiver> archiver,
126 const SavePageCallback& callback); 97 const SavePageCallback& callback) = 0;
127 98
128 // Marks that the offline page related to the passed |offline_id| has been 99 // Marks that the offline page related to the passed |offline_id| has been
129 // accessed. Its access info, including last access time and access count, 100 // accessed. Its access info, including last access time and access count,
130 // will be updated. Requires that the model is loaded. 101 // will be updated. Requires that the model is loaded.
131 void MarkPageAccessed(int64_t offline_id); 102 virtual void MarkPageAccessed(int64_t offline_id) = 0;
132 103
133 // Deletes an offline page related to the passed |offline_id|. 104 // TODO(romax): Pull this interface up from OfflinePageStorageManager::Client
134 void DeletePageByOfflineId(int64_t offline_id, 105 // void DeletePagesByOfflineId(const std::vector<int64_t>& offline_ids,
135 const DeletePageCallback& callback); 106 // const DeletePageCallback& callback);
136
137 // Deletes offline pages related to the passed |offline_ids|.
138 void DeletePagesByOfflineId(const std::vector<int64_t>& offline_ids,
139 const DeletePageCallback& callback) override;
140 107
141 // Wipes out all the data by deleting all saved files and clearing the store. 108 // Wipes out all the data by deleting all saved files and clearing the store.
142 void ClearAll(const base::Closure& callback); 109 virtual void ClearAll(const base::Closure& callback) = 0;
143 110
144 // Deletes offline pages matching the URL predicate. 111 // Deletes offline pages matching the URL predicate.
145 void DeletePagesByURLPredicate(const UrlPredicate& predicate, 112 virtual void DeletePagesByURLPredicate(
146 const DeletePageCallback& callback); 113 const UrlPredicate& predicate,
114 const DeletePageCallback& callback) = 0;
147 115
148 // Returns true via callback if there are offline pages in the given 116 // Returns true via callback if there are offline pages in the given
149 // |name_space|. 117 // |name_space|.
150 void HasPages(const std::string& name_space, 118 virtual void HasPages(const std::string& name_space,
151 const HasPagesCallback& callback); 119 const HasPagesCallback& callback) = 0;
152 120
153 // Returns via callback all GURLs in |urls| that are equal to the online URL 121 // Returns via callback all GURLs in |urls| that are equal to the online URL
154 // of any offline page. 122 // of any offline page.
155 void CheckPagesExistOffline(const std::set<GURL>& urls, 123 virtual void CheckPagesExistOffline(
156 const CheckPagesExistOfflineCallback& callback); 124 const std::set<GURL>& urls,
157 125 const CheckPagesExistOfflineCallback& callback) = 0;
158 // Gets all available offline pages.
159 void GetAllPages(const MultipleOfflinePageItemCallback& callback) override;
160 126
161 // Gets all offline ids where the offline page has the matching client id. 127 // Gets all offline ids where the offline page has the matching client id.
162 void GetOfflineIdsForClientId(const ClientId& client_id, 128 virtual void GetOfflineIdsForClientId(
163 const MultipleOfflineIdCallback& callback); 129 const ClientId& client_id,
130 const MultipleOfflineIdCallback& callback) = 0;
164 131
165 // Gets all offline ids where the offline page has the matching client id. 132 // Gets all offline ids where the offline page has the matching client id.
166 // Requires that the model is loaded. May not return matching IDs depending 133 // Requires that the model is loaded. May not return matching IDs depending
167 // on the internal state of the model. 134 // on the internal state of the model.
168 // 135 //
169 // This function is deprecated. Use |GetOfflineIdsForClientId| instead. 136 // This function is deprecated. Use |GetOfflineIdsForClientId| instead.
170 const std::vector<int64_t> MaybeGetOfflineIdsForClientId( 137 virtual const std::vector<int64_t> MaybeGetOfflineIdsForClientId(
171 const ClientId& client_id) const; 138 const ClientId& client_id) const = 0;
172 139
173 // Returns zero or one offline pages associated with a specified |offline_id|. 140 // Returns zero or one offline pages associated with a specified |offline_id|.
174 void GetPageByOfflineId(int64_t offline_id, 141 virtual void GetPageByOfflineId(
175 const SingleOfflinePageItemCallback& callback); 142 int64_t offline_id,
143 const SingleOfflinePageItemCallback& callback) = 0;
176 144
177 // Returns an offline page associated with a specified |offline_id|. nullptr 145 // Returns an offline page associated with a specified |offline_id|. nullptr
178 // is returned if not found. 146 // is returned if not found.
179 const OfflinePageItem* MaybeGetPageByOfflineId(int64_t offline_id) const; 147 virtual const OfflinePageItem* MaybeGetPageByOfflineId(
148 int64_t offline_id) const = 0;
180 149
181 // Returns the offline page that is stored under |offline_url|, if any. 150 // Returns the offline page that is stored under |offline_url|, if any.
182 void GetPageByOfflineURL(const GURL& offline_url, 151 virtual void GetPageByOfflineURL(
183 const SingleOfflinePageItemCallback& callback); 152 const GURL& offline_url,
153 const SingleOfflinePageItemCallback& callback) = 0;
184 154
185 // Returns an offline page that is stored as |offline_url|. A nullptr is 155 // Returns an offline page that is stored as |offline_url|. A nullptr is
186 // returned if not found. 156 // returned if not found.
187 // 157 //
188 // This function is deprecated, and may return |nullptr| even if a page 158 // This function is deprecated, and may return |nullptr| even if a page
189 // exists, depending on the implementation details of OfflinePageModel. 159 // exists, depending on the implementation details of OfflinePageModel.
190 // Use |GetPageByOfflineURL| instead. 160 // Use |GetPageByOfflineURL| instead.
191 const OfflinePageItem* MaybeGetPageByOfflineURL( 161 virtual const OfflinePageItem* MaybeGetPageByOfflineURL(
192 const GURL& offline_url) const; 162 const GURL& offline_url) const = 0;
193 163
194 // Returns the offline pages that are stored under |online_url|. 164 // Returns the offline pages that are stored under |online_url|.
195 void GetPagesByOnlineURL(const GURL& online_url, 165 virtual void GetPagesByOnlineURL(
196 const MultipleOfflinePageItemCallback& callback); 166 const GURL& online_url,
167 const MultipleOfflinePageItemCallback& callback) = 0;
197 168
198 // Returns via callback an offline page saved for |online_url|, if any. The 169 // Returns via callback an offline page saved for |online_url|, if any. The
199 // best page is chosen based on creation date; a more recently created offline 170 // best page is chosen based on creation date; a more recently created offline
200 // page will be preferred over an older one. This API function does not 171 // page will be preferred over an older one. This API function does not
201 // respect namespaces, as it is used to choose which page is rendered in a 172 // respect namespaces, as it is used to choose which page is rendered in a
202 // tab. Today all namespaces are treated equally for the purposes of this 173 // tab. Today all namespaces are treated equally for the purposes of this
203 // selection. 174 // selection.
204 void GetBestPageForOnlineURL(const GURL& online_url, 175 virtual void GetBestPageForOnlineURL(
205 const SingleOfflinePageItemCallback callback); 176 const GURL& online_url,
177 const SingleOfflinePageItemCallback callback) = 0;
206 178
207 // Returns an offline page saved for |online_url|. A nullptr is returned if 179 // Returns an offline page saved for |online_url|. A nullptr is returned if
208 // not found. See |GetBestPageForOnlineURL| for selection criteria. 180 // not found. See |GetBestPageForOnlineURL| for selection criteria.
209 const OfflinePageItem* MaybeGetBestPageForOnlineURL( 181 virtual const OfflinePageItem* MaybeGetBestPageForOnlineURL(
210 const GURL& online_url) const; 182 const GURL& online_url) const = 0;
211 183
212 // Checks that all of the offline pages have corresponding offline copies. 184 // Checks that all of the offline pages have corresponding offline copies.
213 // If a page is discovered to be missing an offline copy, its offline page 185 // If a page is discovered to be missing an offline copy, its offline page
214 // metadata will be removed and |OfflinePageDeleted| will be sent to model 186 // metadata will be removed and |OfflinePageDeleted| will be sent to model
215 // observers. 187 // observers.
216 void CheckForExternalFileDeletion(); 188 virtual void CheckForExternalFileDeletion() = 0;
217
218 // Marks pages as expired and removes their respective files from the archive
219 // directory.
220 void ExpirePages(const std::vector<int64_t>& offline_ids,
221 const base::Time& expiration_time,
222 const base::Callback<void(bool)>& callback) override;
223 189
224 // Returns the policy controller. 190 // Returns the policy controller.
225 ClientPolicyController* GetPolicyController(); 191 virtual ClientPolicyController* GetPolicyController() = 0;
226 192
227 // Methods for testing only: 193 // TODO(dougarnett): Remove this and its uses.
228 OfflinePageMetadataStore* GetStoreForTesting(); 194 virtual bool is_loaded() const = 0;
229
230 OfflinePageStorageManager* GetStorageManager();
231
232 bool is_loaded() const;
233
234 protected:
235 // Adding a protected constructor for testing-only purposes in
236 // offline_page_storage_manager_unittest.cc
237 OfflinePageModel();
238
239 private:
240 FRIEND_TEST_ALL_PREFIXES(OfflinePageModelTest, MarkPageForDeletion);
241
242 typedef ScopedVector<OfflinePageArchiver> PendingArchivers;
243
244 // Callback for ensuring archive directory is created.
245 void OnEnsureArchivesDirCreatedDone(const base::TimeTicks& start_time);
246
247 void GetAllPagesAfterLoadDone(
248 const MultipleOfflinePageItemCallback& callback);
249 void CheckPagesExistOfflineAfterLoadDone(
250 const std::set<GURL>& urls,
251 const CheckPagesExistOfflineCallback& callback);
252 void GetOfflineIdsForClientIdWhenLoadDone(
253 const ClientId& client_id,
254 const MultipleOfflineIdCallback& callback) const;
255 void GetPageByOfflineIdWhenLoadDone(
256 int64_t offline_id,
257 const SingleOfflinePageItemCallback& callback) const;
258 void GetPagesByOnlineURLWhenLoadDone(
259 const GURL& offline_url,
260 const MultipleOfflinePageItemCallback& callback) const;
261 void GetPageByOfflineURLWhenLoadDone(
262 const GURL& offline_url,
263 const SingleOfflinePageItemCallback& callback) const;
264 void GetBestPageForOnlineURLWhenLoadDone(
265 const GURL& online_url,
266 const SingleOfflinePageItemCallback& callback) const;
267
268 // Callback for checking whether we have offline pages.
269 void HasPagesAfterLoadDone(const std::string& name_space,
270 const HasPagesCallback& callback) const;
271
272 // Callback for loading pages from the offline page metadata store.
273 void OnLoadDone(const base::TimeTicks& start_time,
274 OfflinePageMetadataStore::LoadStatus load_status,
275 const std::vector<OfflinePageItem>& offline_pages);
276
277 // Steps for saving a page offline.
278 void OnCreateArchiveDone(const GURL& requested_url,
279 int64_t offline_id,
280 const ClientId& client_id,
281 const base::Time& start_time,
282 const SavePageCallback& callback,
283 OfflinePageArchiver* archiver,
284 OfflinePageArchiver::ArchiverResult result,
285 const GURL& url,
286 const base::FilePath& file_path,
287 int64_t file_size);
288 void OnAddOfflinePageDone(OfflinePageArchiver* archiver,
289 const SavePageCallback& callback,
290 const OfflinePageItem& offline_page,
291 bool success);
292 void InformSavePageDone(const SavePageCallback& callback,
293 SavePageResult result,
294 const ClientId& client_id,
295 int64_t offline_id);
296 void DeletePendingArchiver(OfflinePageArchiver* archiver);
297
298 // Steps for deleting files and data for an offline page.
299 void OnDeleteArchiveFilesDone(const std::vector<int64_t>& offline_ids,
300 const DeletePageCallback& callback,
301 bool success);
302 void OnRemoveOfflinePagesDone(const std::vector<int64_t>& offline_ids,
303 const DeletePageCallback& callback,
304 bool success);
305 void InformDeletePageDone(const DeletePageCallback& callback,
306 DeletePageResult result);
307
308 void OnMarkPageAccesseDone(const OfflinePageItem& offline_page_item,
309 bool success);
310
311 // Callbacks for checking if offline pages are missing archive files.
312 void ScanForMissingArchiveFiles(
313 const std::set<base::FilePath>& archive_paths);
314 void OnRemoveOfflinePagesMissingArchiveFileDone(
315 const std::vector<std::pair<int64_t, ClientId>>& offline_client_id_pairs,
316 DeletePageResult result);
317
318 // Steps for clearing all.
319 void OnRemoveAllFilesDoneForClearAll(const base::Closure& callback,
320 DeletePageResult result);
321 void OnResetStoreDoneForClearAll(const base::Closure& callback, bool success);
322 void OnReloadStoreDoneForClearAll(
323 const base::Closure& callback,
324 OfflinePageMetadataStore::LoadStatus load_status,
325 const std::vector<OfflinePageItem>& offline_pages);
326
327 void CacheLoadedData(const std::vector<OfflinePageItem>& offline_pages);
328
329 // Actually does the work of deleting, requires the model is loaded.
330 void DoDeletePagesByOfflineId(const std::vector<int64_t>& offline_ids,
331 const DeletePageCallback& callback);
332
333 // Similar to DoDeletePagesByOfflineId, does actual work of deleting, and
334 // requires that the model is loaded.
335 void DoDeletePagesByURLPredicate(const UrlPredicate& predicate,
336 const DeletePageCallback& callback);
337
338 // Callback completing page expiration.
339 void OnExpirePageDone(int64_t offline_id,
340 const base::Time& expiration_time,
341 bool success);
342
343 // Clears expired pages if there are any.
344 void ClearStorageIfNeeded(
345 const OfflinePageStorageManager::ClearStorageCallback& callback);
346
347 // Callback completing storage clearing.
348 void OnStorageCleared(size_t expired_page_count,
349 OfflinePageStorageManager::ClearStorageResult result);
350
351 void RunWhenLoaded(const base::Closure& job);
352
353 // Persistent store for offline page metadata.
354 std::unique_ptr<OfflinePageMetadataStore> store_;
355
356 // Location where all of the archive files will be stored.
357 base::FilePath archives_dir_;
358
359 // The observers.
360 base::ObserverList<Observer> observers_;
361
362 bool is_loaded_;
363
364 // In memory copy of the offline page metadata, keyed by bookmark IDs.
365 std::map<int64_t, OfflinePageItem> offline_pages_;
366
367 // Pending archivers owned by this model.
368 PendingArchivers pending_archivers_;
369
370 // Delayed tasks that should be invoked after the loading is done.
371 std::vector<base::Closure> delayed_tasks_;
372
373 // Controller of the client policies.
374 std::unique_ptr<ClientPolicyController> policy_controller_;
375
376 // Manager for the storage consumed by archives and responsible for
377 // automatic page clearing.
378 std::unique_ptr<OfflinePageStorageManager> storage_manager_;
379
380 // Manager for the offline archive files and directory.
381 std::unique_ptr<ArchiveManager> archive_manager_;
382
383 base::WeakPtrFactory<OfflinePageModel> weak_ptr_factory_;
384
385 DISALLOW_COPY_AND_ASSIGN(OfflinePageModel);
386 }; 195 };
387 196
388 } // namespace offline_pages 197 } // namespace offline_pages
389 198
390 #endif // COMPONENTS_OFFLINE_PAGES_OFFLINE_PAGE_MODEL_H_ 199 #endif // COMPONENTS_OFFLINE_PAGES_OFFLINE_PAGE_MODEL_H_
OLDNEW
« no previous file with comments | « components/offline_pages/BUILD.gn ('k') | components/offline_pages/offline_page_model.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698