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 #include "chrome/browser/ui/webui/offline/offline_internals_ui_message_handler.h"
6
7 #include <stdint.h>
8 #include <stdlib.h>
9
10 #include <algorithm>
11 #include <utility>
12
13 #include "base/bind.h"
14 #include "base/guid.h"
15 #include "base/json/json_writer.h"
16 #include "base/strings/string_number_conversions.h"
17 #include "base/strings/string_split.h"
18 #include "base/strings/string_util.h"
19 #include "base/strings/stringprintf.h"
20 #include "base/strings/utf_string_conversions.h"
21 #include "base/values.h"
22 #include "build/build_config.h"
23 #include "chrome/browser/offline_pages/offline_page_model_factory.h"
24 #include "chrome/browser/offline_pages/prefetch/prefetch_service_factory.h"
25 #include "chrome/browser/offline_pages/prefetch/prefetched_pages_notifier.h"
26 #include "chrome/browser/offline_pages/request_coordinator_factory.h"
27 #include "chrome/browser/profiles/profile.h"
28 #include "chrome/browser/profiles/profile_key.h"
29 #include "chrome/common/channel_info.h"
30 #include "chrome/common/chrome_content_client.h"
31 #include "components/offline_pages/core/client_namespace_constants.h"
32 #include "components/offline_pages/core/offline_page_feature.h"
33 #include "components/offline_pages/core/prefetch/generate_page_bundle_request.h"
34 #include "components/offline_pages/core/prefetch/get_operation_request.h"
35 #include "components/offline_pages/core/prefetch/prefetch_background_task_handler.h"
36 #include "components/offline_pages/core/prefetch/prefetch_dispatcher.h"
37 #include "components/offline_pages/core/prefetch/prefetch_downloader.h"
38 #include "components/offline_pages/core/prefetch/prefetch_prefs.h"
39 #include "components/offline_pages/core/prefetch/prefetch_service.h"
40 #include "components/offline_pages/core/prefetch/prefetch_types.h"
41 #include "content/public/browser/web_ui.h"
42 #include "net/base/network_change_notifier.h"
43
44 namespace offline_internals {
45
46 namespace {
47
GetStringFromDeletePageResult(offline_pages::DeletePageResult value)48 std::string GetStringFromDeletePageResult(
49 offline_pages::DeletePageResult value) {
50 switch (value) {
51 case offline_pages::DeletePageResult::SUCCESS:
52 return "Success";
53 case offline_pages::DeletePageResult::CANCELLED:
54 return "Cancelled";
55 case offline_pages::DeletePageResult::STORE_FAILURE:
56 return "Store failure";
57 case offline_pages::DeletePageResult::DEVICE_FAILURE:
58 return "Device failure";
59 case offline_pages::DeletePageResult::DEPRECATED_NOT_FOUND:
60 return "Not found";
61 }
62 NOTREACHED();
63 return "Unknown";
64 }
65
GetStringFromDeleteRequestResults(const offline_pages::MultipleItemStatuses & results)66 std::string GetStringFromDeleteRequestResults(
67 const offline_pages::MultipleItemStatuses& results) {
68 // If any requests failed, return "failure", else "success".
69 for (const auto& result : results) {
70 if (result.second == offline_pages::ItemActionStatus::STORE_ERROR)
71 return "Store failure, could not delete one or more requests";
72 }
73
74 return "Success";
75 }
76
GetStringFromSavePageStatus()77 std::string GetStringFromSavePageStatus() {
78 return "Available";
79 }
80
81 } // namespace
82
OfflineInternalsUIMessageHandler()83 OfflineInternalsUIMessageHandler::OfflineInternalsUIMessageHandler()
84 : offline_page_model_(nullptr),
85 request_coordinator_(nullptr),
86 prefetch_service_(nullptr) {}
87
~OfflineInternalsUIMessageHandler()88 OfflineInternalsUIMessageHandler::~OfflineInternalsUIMessageHandler() {}
89
HandleDeleteSelectedPages(const base::ListValue * args)90 void OfflineInternalsUIMessageHandler::HandleDeleteSelectedPages(
91 const base::ListValue* args) {
92 std::string callback_id;
93 CHECK(args->GetString(0, &callback_id));
94
95 const base::ListValue* offline_ids_from_arg;
96 args->GetList(1, &offline_ids_from_arg);
97
98 std::vector<int64_t> offline_ids;
99 for (size_t i = 0; i < offline_ids_from_arg->GetSize(); i++) {
100 std::string value;
101 offline_ids_from_arg->GetString(i, &value);
102 int64_t int_value;
103 base::StringToInt64(value, &int_value);
104 offline_ids.push_back(int_value);
105 }
106
107 offline_pages::PageCriteria criteria;
108 criteria.offline_ids = std::move(offline_ids);
109 offline_page_model_->DeletePagesWithCriteria(
110 criteria,
111 base::Bind(&OfflineInternalsUIMessageHandler::HandleDeletedPagesCallback,
112 weak_ptr_factory_.GetWeakPtr(), callback_id));
113 }
114
HandleDeleteSelectedRequests(const base::ListValue * args)115 void OfflineInternalsUIMessageHandler::HandleDeleteSelectedRequests(
116 const base::ListValue* args) {
117 std::string callback_id;
118 CHECK(args->GetString(0, &callback_id));
119
120 std::vector<int64_t> offline_ids;
121 const base::ListValue* offline_ids_from_arg = nullptr;
122 args->GetList(1, &offline_ids_from_arg);
123
124 for (size_t i = 0; i < offline_ids_from_arg->GetSize(); i++) {
125 std::string value;
126 offline_ids_from_arg->GetString(i, &value);
127 int64_t int_value;
128 base::StringToInt64(value, &int_value);
129 offline_ids.push_back(int_value);
130 }
131
132 // Call RequestCoordinator to delete them
133 if (request_coordinator_) {
134 request_coordinator_->RemoveRequests(
135 offline_ids,
136 base::Bind(
137 &OfflineInternalsUIMessageHandler::HandleDeletedRequestsCallback,
138 weak_ptr_factory_.GetWeakPtr(), callback_id));
139 }
140 }
141
HandleDeletedPagesCallback(std::string callback_id,offline_pages::DeletePageResult result)142 void OfflineInternalsUIMessageHandler::HandleDeletedPagesCallback(
143 std::string callback_id,
144 offline_pages::DeletePageResult result) {
145 ResolveJavascriptCallback(base::Value(callback_id),
146 base::Value(GetStringFromDeletePageResult(result)));
147 }
148
HandleDeletedRequestsCallback(std::string callback_id,const offline_pages::MultipleItemStatuses & results)149 void OfflineInternalsUIMessageHandler::HandleDeletedRequestsCallback(
150 std::string callback_id,
151 const offline_pages::MultipleItemStatuses& results) {
152 ResolveJavascriptCallback(
153 base::Value(callback_id),
154 base::Value(GetStringFromDeleteRequestResults(results)));
155 }
156
HandleStoredPagesCallback(std::string callback_id,const offline_pages::MultipleOfflinePageItemResult & pages)157 void OfflineInternalsUIMessageHandler::HandleStoredPagesCallback(
158 std::string callback_id,
159 const offline_pages::MultipleOfflinePageItemResult& pages) {
160 std::vector<base::Value> results;
161 for (const auto& page : pages) {
162 base::Value offline_page(base::Value::Type::DICTIONARY);
163 offline_page.SetStringKey("onlineUrl", page.url.spec());
164 offline_page.SetStringKey("namespace", page.client_id.name_space);
165 offline_page.SetDoubleKey("size", page.file_size);
166 offline_page.SetStringKey("id", std::to_string(page.offline_id));
167 offline_page.SetStringKey("filePath", page.file_path.MaybeAsASCII());
168 offline_page.SetDoubleKey("creationTime", page.creation_time.ToJsTime());
169 offline_page.SetDoubleKey("lastAccessTime",
170 page.last_access_time.ToJsTime());
171 offline_page.SetIntKey("accessCount", page.access_count);
172 offline_page.SetStringKey("originalUrl",
173 page.original_url_if_different.spec());
174 offline_page.SetStringKey("requestOrigin", page.request_origin);
175 results.push_back(std::move(offline_page));
176 }
177 // Sort by creation order.
178 std::sort(results.begin(), results.end(), [](const auto& a, const auto& b) {
179 return a.FindKey({"creationTime"})->GetDouble() <
180 b.FindKey({"creationTime"})->GetDouble();
181 });
182
183 ResolveJavascriptCallback(base::Value(callback_id),
184 base::Value(std::move(results)));
185 }
186
HandleRequestQueueCallback(std::string callback_id,std::vector<std::unique_ptr<offline_pages::SavePageRequest>> requests)187 void OfflineInternalsUIMessageHandler::HandleRequestQueueCallback(
188 std::string callback_id,
189 std::vector<std::unique_ptr<offline_pages::SavePageRequest>> requests) {
190 base::ListValue save_page_requests;
191 for (const auto& request : requests) {
192 auto save_page_request = std::make_unique<base::DictionaryValue>();
193 save_page_request->SetString("onlineUrl", request->url().spec());
194 save_page_request->SetDouble("creationTime",
195 request->creation_time().ToJsTime());
196 save_page_request->SetString("status", GetStringFromSavePageStatus());
197 save_page_request->SetString("namespace", request->client_id().name_space);
198 save_page_request->SetDouble("lastAttemptTime",
199 request->last_attempt_time().ToJsTime());
200 save_page_request->SetString("id", std::to_string(request->request_id()));
201 save_page_request->SetString("originalUrl", request->original_url().spec());
202 save_page_request->SetString("requestOrigin", request->request_origin());
203 save_page_requests.Append(std::move(save_page_request));
204 }
205 ResolveJavascriptCallback(base::Value(callback_id), save_page_requests);
206 }
207
HandleGetRequestQueue(const base::ListValue * args)208 void OfflineInternalsUIMessageHandler::HandleGetRequestQueue(
209 const base::ListValue* args) {
210 AllowJavascript();
211 std::string callback_id;
212 CHECK(args->GetString(0, &callback_id));
213
214 if (request_coordinator_) {
215 request_coordinator_->GetAllRequests(base::BindOnce(
216 &OfflineInternalsUIMessageHandler::HandleRequestQueueCallback,
217 weak_ptr_factory_.GetWeakPtr(), callback_id));
218 } else {
219 base::ListValue results;
220 ResolveJavascriptCallback(base::Value(callback_id), results);
221 }
222 }
223
HandleGetStoredPages(const base::ListValue * args)224 void OfflineInternalsUIMessageHandler::HandleGetStoredPages(
225 const base::ListValue* args) {
226 AllowJavascript();
227 std::string callback_id;
228 CHECK(args->GetString(0, &callback_id));
229
230 if (offline_page_model_) {
231 offline_page_model_->GetAllPages(
232 base::Bind(&OfflineInternalsUIMessageHandler::HandleStoredPagesCallback,
233 weak_ptr_factory_.GetWeakPtr(), callback_id));
234 } else {
235 base::ListValue results;
236 ResolveJavascriptCallback(base::Value(callback_id), results);
237 }
238 }
239
HandleSetRecordPageModel(const base::ListValue * args)240 void OfflineInternalsUIMessageHandler::HandleSetRecordPageModel(
241 const base::ListValue* args) {
242 AllowJavascript();
243 bool should_record;
244 CHECK(args->GetBoolean(0, &should_record));
245 if (offline_page_model_)
246 offline_page_model_->GetLogger()->SetIsLogging(should_record);
247 }
248
HandleGetNetworkStatus(const base::ListValue * args)249 void OfflineInternalsUIMessageHandler::HandleGetNetworkStatus(
250 const base::ListValue* args) {
251 AllowJavascript();
252 const base::Value* callback_id;
253 CHECK(args->Get(0, &callback_id));
254
255 ResolveJavascriptCallback(
256 *callback_id,
257 base::Value(net::NetworkChangeNotifier::IsOffline() ? "Offline"
258 : "Online"));
259 }
260
HandleScheduleNwake(const base::ListValue * args)261 void OfflineInternalsUIMessageHandler::HandleScheduleNwake(
262 const base::ListValue* args) {
263 AllowJavascript();
264 const base::Value* callback_id;
265 CHECK(args->Get(0, &callback_id));
266
267 if (prefetch_service_) {
268 prefetch_service_->ForceRefreshSuggestions();
269 prefetch_service_->GetPrefetchBackgroundTaskHandler()
270 ->EnsureTaskScheduled();
271 ResolveJavascriptCallback(*callback_id, base::Value("Scheduled."));
272 } else {
273 RejectJavascriptCallback(*callback_id,
274 base::Value("No prefetch service available."));
275 }
276 }
277
HandleCancelNwake(const base::ListValue * args)278 void OfflineInternalsUIMessageHandler::HandleCancelNwake(
279 const base::ListValue* args) {
280 AllowJavascript();
281 const base::Value* callback_id;
282 CHECK(args->Get(0, &callback_id));
283
284 if (prefetch_service_) {
285 prefetch_service_->GetPrefetchBackgroundTaskHandler()
286 ->CancelBackgroundTask();
287 ResolveJavascriptCallback(*callback_id, base::Value("Cancelled."));
288 } else {
289 RejectJavascriptCallback(*callback_id,
290 base::Value("No prefetch service available."));
291 }
292 }
293
HandleShowPrefetchNotification(const base::ListValue * args)294 void OfflineInternalsUIMessageHandler::HandleShowPrefetchNotification(
295 const base::ListValue* args) {
296 AllowJavascript();
297 const base::Value* callback_id;
298 CHECK(args->Get(0, &callback_id));
299
300 offline_pages::ShowPrefetchedContentNotification(
301 GURL("https://www.example.com"));
302 ResolveJavascriptCallback(*callback_id, base::Value("Scheduled."));
303 }
304
HandleGeneratePageBundle(const base::ListValue * args)305 void OfflineInternalsUIMessageHandler::HandleGeneratePageBundle(
306 const base::ListValue* args) {
307 AllowJavascript();
308 std::string callback_id;
309 CHECK(args->GetString(0, &callback_id));
310
311 if (!prefetch_service_) {
312 RejectJavascriptCallback(base::Value(callback_id),
313 base::Value("No prefetch service available."));
314 return;
315 }
316
317 std::string data;
318 CHECK(args->GetString(1, &data));
319 std::vector<std::string> page_urls = base::SplitStringUsingSubstr(
320 data, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
321 std::vector<offline_pages::PrefetchURL> prefetch_urls;
322 for (auto& page_url : page_urls) {
323 // Creates a dummy prefetch URL with a bogus ID, and using the URL as the
324 // page title.
325 GURL url(page_url);
326 if (url.is_valid()) {
327 prefetch_urls.push_back(offline_pages::PrefetchURL(
328 "offline-internals", url, base::UTF8ToUTF16(page_url)));
329 }
330 }
331
332 prefetch_service_->GetPrefetchDispatcher()->AddCandidatePrefetchURLs(
333 offline_pages::kSuggestedArticlesNamespace, prefetch_urls);
334 // Note: Static casts are needed here so that both Windows and Android can
335 // compile these printf formats.
336 std::string message =
337 base::StringPrintf("Added %zu candidate URLs.", prefetch_urls.size());
338 if (prefetch_urls.size() < page_urls.size()) {
339 size_t invalid_urls_count = page_urls.size() - prefetch_urls.size();
340 message.append(
341 base::StringPrintf(" Ignored %zu invalid URLs.", invalid_urls_count));
342 }
343 message.append("\n");
344
345 // Construct a JSON array containing all the URLs. To guard against malicious
346 // URLs that might contain special characters, we create a ListValue and then
347 // serialize it into JSON, instead of doing direct string manipulation.
348 base::ListValue urls;
349 for (const auto& prefetch_url : prefetch_urls) {
350 urls.Append(prefetch_url.url.spec());
351 }
352 std::string json;
353 base::JSONWriter::Write(urls, &json);
354 message.append(json);
355 ResolveJavascriptCallback(base::Value(callback_id), base::Value(message));
356 }
357
HandleGetOperation(const base::ListValue * args)358 void OfflineInternalsUIMessageHandler::HandleGetOperation(
359 const base::ListValue* args) {
360 AllowJavascript();
361 std::string callback_id;
362 CHECK(args->GetString(0, &callback_id));
363
364 if (!prefetch_service_) {
365 RejectJavascriptCallback(base::Value(callback_id),
366 base::Value("No prefetch service available."));
367 return;
368 }
369
370 std::string name;
371 CHECK(args->GetString(1, &name));
372 base::TrimWhitespaceASCII(name, base::TRIM_ALL, &name);
373
374 prefetch_service_->GetPrefetchDispatcher()
375 ->GCMOperationCompletedMessageReceived(name);
376 base::Value message("GetOperation will be attempted for any matching pages.");
377 ResolveJavascriptCallback(base::Value(callback_id), message);
378 }
379
HandleDownloadArchive(const base::ListValue * args)380 void OfflineInternalsUIMessageHandler::HandleDownloadArchive(
381 const base::ListValue* args) {
382 AllowJavascript();
383 std::string name;
384 CHECK(args->GetString(0, &name));
385 base::TrimWhitespaceASCII(name, base::TRIM_ALL, &name);
386
387 if (prefetch_service_) {
388 prefetch_service_->GetPrefetchDownloader()->StartDownload(
389 base::GenerateGUID(), name, std::string());
390 }
391 }
392
HandleSetRecordRequestQueue(const base::ListValue * args)393 void OfflineInternalsUIMessageHandler::HandleSetRecordRequestQueue(
394 const base::ListValue* args) {
395 AllowJavascript();
396 bool should_record;
397 CHECK(args->GetBoolean(0, &should_record));
398 if (request_coordinator_)
399 request_coordinator_->GetLogger()->SetIsLogging(should_record);
400 }
401
HandleSetRecordPrefetchService(const base::ListValue * args)402 void OfflineInternalsUIMessageHandler::HandleSetRecordPrefetchService(
403 const base::ListValue* args) {
404 AllowJavascript();
405 bool should_record;
406 CHECK(args->GetBoolean(0, &should_record));
407 if (prefetch_service_)
408 prefetch_service_->GetLogger()->SetIsLogging(should_record);
409 }
410
HandleSetLimitlessPrefetchingEnabled(const base::ListValue * args)411 void OfflineInternalsUIMessageHandler::HandleSetLimitlessPrefetchingEnabled(
412 const base::ListValue* args) {
413 AllowJavascript();
414 PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs();
415 DCHECK(!args->GetList().empty());
416 bool enabled = args->GetList()[0].GetBool();
417 offline_pages::prefetch_prefs::SetLimitlessPrefetchingEnabled(prefs, enabled);
418 }
419
HandleGetLimitlessPrefetchingEnabled(const base::ListValue * args)420 void OfflineInternalsUIMessageHandler::HandleGetLimitlessPrefetchingEnabled(
421 const base::ListValue* args) {
422 AllowJavascript();
423 const base::Value* callback_id;
424 bool got_callback_id = args->Get(0, &callback_id);
425 DCHECK(got_callback_id);
426
427 PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs();
428 bool enabled =
429 offline_pages::prefetch_prefs::IsLimitlessPrefetchingEnabled(prefs);
430
431 ResolveJavascriptCallback(*callback_id, base::Value(enabled));
432 }
433
HandleSetPrefetchTestingHeader(const base::ListValue * args)434 void OfflineInternalsUIMessageHandler::HandleSetPrefetchTestingHeader(
435 const base::ListValue* args) {
436 AllowJavascript();
437 PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs();
438
439 if (args->GetList().size() != 1) {
440 DLOG(ERROR) << "Expected 1 argument to setPrefetchTesting header but got "
441 << args->GetList().size();
442 return;
443 }
444 if (!args->GetList()[0].is_string()) {
445 DLOG(ERROR) << "Expected argument to be string but got "
446 << base::Value::GetTypeName(args->GetList()[0].type());
447 return;
448 }
449
450 offline_pages::prefetch_prefs::SetPrefetchTestingHeader(
451 prefs, args->GetList()[0].GetString());
452
453 if (prefetch_service_)
454 prefetch_service_->SetEnabledByServer(prefs, true);
455 }
456
HandleGetPrefetchTestingHeader(const base::ListValue * args)457 void OfflineInternalsUIMessageHandler::HandleGetPrefetchTestingHeader(
458 const base::ListValue* args) {
459 AllowJavascript();
460 if (args->GetList().size() != 1) {
461 DLOG(ERROR) << "Expected 1 argument to getPrefetchTestingHeader but got "
462 << args->GetList().size();
463 return;
464 }
465 if (!args->GetList()[0].is_string()) {
466 DLOG(ERROR) << "Expected callback_id to be a string but got "
467 << base::Value::GetTypeName(args->GetList()[0].type());
468 return;
469 }
470
471 PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs();
472 ResolveJavascriptCallback(
473 args->GetList()[0],
474 base::Value(offline_pages::prefetch_prefs::GetPrefetchTestingHeader(prefs)
475
476 ));
477 }
478
HandleGetLoggingState(const base::ListValue * args)479 void OfflineInternalsUIMessageHandler::HandleGetLoggingState(
480 const base::ListValue* args) {
481 AllowJavascript();
482 const base::Value* callback_id;
483 CHECK(args->Get(0, &callback_id));
484
485 base::DictionaryValue result;
486 result.SetBoolean("modelIsLogging",
487 offline_page_model_
488 ? offline_page_model_->GetLogger()->GetIsLogging()
489 : false);
490 result.SetBoolean("queueIsLogging",
491 request_coordinator_
492 ? request_coordinator_->GetLogger()->GetIsLogging()
493 : false);
494 bool prefetch_logging = false;
495 if (prefetch_service_) {
496 prefetch_logging = prefetch_service_->GetLogger()->GetIsLogging();
497 }
498 result.SetBoolean("prefetchIsLogging", prefetch_logging);
499 ResolveJavascriptCallback(*callback_id, result);
500 }
501
HandleGetEventLogs(const base::ListValue * args)502 void OfflineInternalsUIMessageHandler::HandleGetEventLogs(
503 const base::ListValue* args) {
504 AllowJavascript();
505 const base::Value* callback_id;
506 CHECK(args->Get(0, &callback_id));
507
508 std::vector<std::string> logs;
509 if (offline_page_model_)
510 offline_page_model_->GetLogger()->GetLogs(&logs);
511 if (request_coordinator_)
512 request_coordinator_->GetLogger()->GetLogs(&logs);
513 if (prefetch_service_)
514 prefetch_service_->GetLogger()->GetLogs(&logs);
515 std::sort(logs.begin(), logs.end());
516
517 base::ListValue result;
518 result.AppendStrings(logs);
519
520 ResolveJavascriptCallback(*callback_id, result);
521 }
522
HandleAddToRequestQueue(const base::ListValue * args)523 void OfflineInternalsUIMessageHandler::HandleAddToRequestQueue(
524 const base::ListValue* args) {
525 std::string callback_id;
526 CHECK(args->GetString(0, &callback_id));
527
528 if (request_coordinator_) {
529 std::string url;
530 CHECK(args->GetString(1, &url));
531
532 // To be visible in Downloads UI, these items need a well-formed GUID
533 // and AsyncNamespace in their ClientId.
534 std::ostringstream id_stream;
535 id_stream << base::GenerateGUID();
536
537 offline_pages::RequestCoordinator::SavePageLaterParams params;
538 params.url = GURL(url);
539 params.client_id = offline_pages::ClientId(offline_pages::kAsyncNamespace,
540 id_stream.str());
541 request_coordinator_->SavePageLater(
542 params,
543 base::Bind(
544 &OfflineInternalsUIMessageHandler::HandleSavePageLaterCallback,
545 weak_ptr_factory_.GetWeakPtr(), callback_id));
546 } else {
547 ResolveJavascriptCallback(base::Value(callback_id), base::Value(false));
548 }
549 }
550
HandleSavePageLaterCallback(std::string callback_id,offline_pages::AddRequestResult result)551 void OfflineInternalsUIMessageHandler::HandleSavePageLaterCallback(
552 std::string callback_id,
553 offline_pages::AddRequestResult result) {
554 ResolveJavascriptCallback(
555 base::Value(callback_id),
556 base::Value(result == offline_pages::AddRequestResult::SUCCESS));
557 }
558
RegisterMessages()559 void OfflineInternalsUIMessageHandler::RegisterMessages() {
560 web_ui()->RegisterMessageCallback(
561 "deleteSelectedPages",
562 base::BindRepeating(
563 &OfflineInternalsUIMessageHandler::HandleDeleteSelectedPages,
564 base::Unretained(this)));
565 web_ui()->RegisterMessageCallback(
566 "deleteSelectedRequests",
567 base::BindRepeating(
568 &OfflineInternalsUIMessageHandler::HandleDeleteSelectedRequests,
569 base::Unretained(this)));
570 web_ui()->RegisterMessageCallback(
571 "getRequestQueue",
572 base::BindRepeating(
573 &OfflineInternalsUIMessageHandler::HandleGetRequestQueue,
574 base::Unretained(this)));
575 web_ui()->RegisterMessageCallback(
576 "getStoredPages",
577 base::BindRepeating(
578 &OfflineInternalsUIMessageHandler::HandleGetStoredPages,
579 base::Unretained(this)));
580 web_ui()->RegisterMessageCallback(
581 "getEventLogs",
582 base::BindRepeating(&OfflineInternalsUIMessageHandler::HandleGetEventLogs,
583 base::Unretained(this)));
584 web_ui()->RegisterMessageCallback(
585 "setRecordRequestQueue",
586 base::BindRepeating(
587 &OfflineInternalsUIMessageHandler::HandleSetRecordRequestQueue,
588 base::Unretained(this)));
589 web_ui()->RegisterMessageCallback(
590 "setRecordPageModel",
591 base::BindRepeating(
592 &OfflineInternalsUIMessageHandler::HandleSetRecordPageModel,
593 base::Unretained(this)));
594 web_ui()->RegisterMessageCallback(
595 "setRecordPrefetchService",
596 base::BindRepeating(
597 &OfflineInternalsUIMessageHandler::HandleSetRecordPrefetchService,
598 base::Unretained(this)));
599 web_ui()->RegisterMessageCallback(
600 "setLimitlessPrefetchingEnabled",
601 base::BindRepeating(&OfflineInternalsUIMessageHandler::
602 HandleSetLimitlessPrefetchingEnabled,
603 base::Unretained(this)));
604 web_ui()->RegisterMessageCallback(
605 "getLimitlessPrefetchingEnabled",
606 base::BindRepeating(&OfflineInternalsUIMessageHandler::
607 HandleGetLimitlessPrefetchingEnabled,
608 base::Unretained(this)));
609 web_ui()->RegisterMessageCallback(
610 "setPrefetchTestingHeader",
611 base::BindRepeating(
612 &OfflineInternalsUIMessageHandler::HandleSetPrefetchTestingHeader,
613 base::Unretained(this)));
614 web_ui()->RegisterMessageCallback(
615 "getPrefetchTestingHeader",
616 base::BindRepeating(
617 &OfflineInternalsUIMessageHandler::HandleGetPrefetchTestingHeader,
618 base::Unretained(this)));
619 web_ui()->RegisterMessageCallback(
620 "getLoggingState",
621 base::BindRepeating(
622 &OfflineInternalsUIMessageHandler::HandleGetLoggingState,
623 base::Unretained(this)));
624 web_ui()->RegisterMessageCallback(
625 "addToRequestQueue",
626 base::BindRepeating(
627 &OfflineInternalsUIMessageHandler::HandleAddToRequestQueue,
628 base::Unretained(this)));
629 web_ui()->RegisterMessageCallback(
630 "getNetworkStatus",
631 base::BindRepeating(
632 &OfflineInternalsUIMessageHandler::HandleGetNetworkStatus,
633 base::Unretained(this)));
634 web_ui()->RegisterMessageCallback(
635 "scheduleNwake",
636 base::BindRepeating(
637 &OfflineInternalsUIMessageHandler::HandleScheduleNwake,
638 base::Unretained(this)));
639 web_ui()->RegisterMessageCallback(
640 "cancelNwake",
641 base::BindRepeating(&OfflineInternalsUIMessageHandler::HandleCancelNwake,
642 base::Unretained(this)));
643 web_ui()->RegisterMessageCallback(
644 "showPrefetchNotification",
645 base::BindRepeating(
646 &OfflineInternalsUIMessageHandler::HandleShowPrefetchNotification,
647 base::Unretained(this)));
648 web_ui()->RegisterMessageCallback(
649 "generatePageBundle",
650 base::BindRepeating(
651 &OfflineInternalsUIMessageHandler::HandleGeneratePageBundle,
652 base::Unretained(this)));
653 web_ui()->RegisterMessageCallback(
654 "getOperation",
655 base::BindRepeating(&OfflineInternalsUIMessageHandler::HandleGetOperation,
656 base::Unretained(this)));
657 web_ui()->RegisterMessageCallback(
658 "downloadArchive",
659 base::BindRepeating(
660 &OfflineInternalsUIMessageHandler::HandleDownloadArchive,
661 base::Unretained(this)));
662
663 // Get the offline page model associated with this web ui.
664 Profile* profile = Profile::FromWebUI(web_ui());
665 offline_page_model_ =
666 offline_pages::OfflinePageModelFactory::GetForBrowserContext(profile);
667 request_coordinator_ =
668 offline_pages::RequestCoordinatorFactory::GetForBrowserContext(profile);
669 prefetch_service_ = offline_pages::PrefetchServiceFactory::GetForKey(
670 profile->GetProfileKey());
671 }
672
OnJavascriptDisallowed()673 void OfflineInternalsUIMessageHandler::OnJavascriptDisallowed() {
674 weak_ptr_factory_.InvalidateWeakPtrs();
675 }
676
677 } // namespace offline_internals
678