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