123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "content/browser/appcache/view_appcache_internals_job.h"
6868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/base64.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/format_macros.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/i18n/time_formatting.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/weak_ptr.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
175e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h"
185e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/stringprintf.h"
19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
20116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/browser/appcache/appcache.h"
21116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/browser/appcache/appcache_group.h"
22116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/browser/appcache/appcache_policy.h"
23116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/browser/appcache/appcache_response.h"
24116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/browser/appcache/appcache_service_impl.h"
25116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/browser/appcache/appcache_storage.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/escape.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/io_buffer.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_response_headers.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_simple_job.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/view_cache_helper.h"
3323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
3423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)namespace content {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kErrorMessage[] = "Error in retrieving Application Caches.";
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kEmptyAppCachesMessage[] = "No available Application Caches.";
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kManifestNotFoundMessage[] = "Manifest not found.";
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kManifest[] = "Manifest: ";
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kSize[] = "Size: ";
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kCreationTime[] = "Creation Time: ";
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kLastAccessTime[] = "Last Access Time: ";
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kLastUpdateTime[] = "Last Update Time: ";
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kFormattedDisabledAppCacheMsg[] =
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "<b><i><font color=\"FF0000\">"
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "This Application Cache is disabled by policy.</font></i></b><br/>";
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kRemoveCacheLabel[] = "Remove";
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kViewCacheLabel[] = "View Entries";
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kRemoveCacheCommand[] = "remove-cache";
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kViewCacheCommand[] = "view-cache";
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kViewEntryCommand[] = "view-entry";
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EmitPageStart(std::string* out) {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append(
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "<!DOCTYPE HTML>\n"
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "<html><title>AppCache Internals</title>\n"
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "<meta http-equiv=\"Content-Security-Policy\""
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  content=\"object-src 'none'; script-src 'none'\">\n"
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "<style>\n"
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "body { font-family: sans-serif; font-size: 0.8em; }\n"
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "tt, code, pre { font-family: WebKitHack, monospace; }\n"
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "form { display: inline; }\n"
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ".subsection_body { margin: 10px 0 10px 2em; }\n"
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ".subsection_title { font-weight: bold; }\n"
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "</style>\n"
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "</head><body>\n");
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EmitPageEnd(std::string* out) {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append("</body></html>\n");
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EmitListItem(const std::string& label,
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  const std::string& data,
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  std::string* out) {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append("<li>");
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append(net::EscapeForHTML(label));
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append(net::EscapeForHTML(data));
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append("</li>\n");
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EmitAnchor(const std::string& url, const std::string& text,
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                std::string* out) {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append("<a href=\"");
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append(net::EscapeForHTML(url));
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append("\">");
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append(net::EscapeForHTML(text));
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append("</a>");
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EmitCommandAnchor(const char* label,
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const GURL& base_url,
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const char* command,
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const char* param,
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       std::string* out) {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string query(command);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  query.push_back('=');
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  query.append(param);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL::Replacements replacements;
1015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  replacements.SetQuery(query.data(), url::Component(0, query.length()));
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL command_url = base_url.ReplaceComponents(replacements);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EmitAnchor(command_url.spec(), label, out);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EmitAppCacheInfo(const GURL& base_url,
10746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                      AppCacheServiceImpl* service,
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      const AppCacheInfo* info,
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      std::string* out) {
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string manifest_url_base64;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Base64Encode(info->manifest_url.spec(), &manifest_url_base64);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append("\n<p>");
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append(kManifest);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EmitAnchor(info->manifest_url.spec(), info->manifest_url.spec(), out);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append("<br/>\n");
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!service->appcache_policy()->CanLoadAppCache(
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          info->manifest_url, info->manifest_url)) {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out->append(kFormattedDisabledAppCacheMsg);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append("\n<br/>\n");
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EmitCommandAnchor(kRemoveCacheLabel, base_url,
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    kRemoveCacheCommand, manifest_url_base64.c_str(), out);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append("&nbsp;&nbsp;");
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EmitCommandAnchor(kViewCacheLabel, base_url,
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    kViewCacheCommand, manifest_url_base64.c_str(), out);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append("\n<br/>\n");
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append("<ul>");
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EmitListItem(
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kSize,
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::UTF16ToUTF8(FormatBytesUnlocalized(info->size)),
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      out);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EmitListItem(
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kCreationTime,
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::UTF16ToUTF8(TimeFormatFriendlyDateAndTime(info->creation_time)),
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      out);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EmitListItem(
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kLastUpdateTime,
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::UTF16ToUTF8(TimeFormatFriendlyDateAndTime(info->last_update_time)),
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      out);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EmitListItem(
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kLastAccessTime,
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::UTF16ToUTF8(TimeFormatFriendlyDateAndTime(info->last_access_time)),
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      out);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append("</ul></p></br>\n");
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EmitAppCacheInfoVector(
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& base_url,
15046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    AppCacheServiceImpl* service,
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const AppCacheInfoVector& appcaches,
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string* out) {
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::vector<AppCacheInfo>::const_iterator info =
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           appcaches.begin();
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       info != appcaches.end(); ++info) {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EmitAppCacheInfo(base_url, service, &(*info), out);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EmitTableData(const std::string& data, bool align_right, bool bold,
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   std::string* out) {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (align_right)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out->append("<td align='right'>");
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out->append("<td>");
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (bold)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out->append("<b>");
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append(data);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (bold)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out->append("</b>");
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append("</td>");
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string FormFlagsString(const AppCacheResourceInfo& info) {
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string str;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (info.is_manifest)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    str.append("Manifest, ");
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (info.is_master)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    str.append("Master, ");
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (info.is_intercept)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    str.append("Intercept, ");
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (info.is_fallback)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    str.append("Fallback, ");
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (info.is_explicit)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    str.append("Explicit, ");
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (info.is_foreign)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    str.append("Foreign, ");
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return str;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string FormViewEntryAnchor(const GURL& base_url,
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const GURL& manifest_url, const GURL& entry_url,
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                int64 response_id,
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                int64 group_id) {
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string manifest_url_base64;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string entry_url_base64;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string response_id_string;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string group_id_string;
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Base64Encode(manifest_url.spec(), &manifest_url_base64);
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Base64Encode(entry_url.spec(), &entry_url_base64);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response_id_string = base::Int64ToString(response_id);
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  group_id_string = base::Int64ToString(group_id);
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string query(kViewEntryCommand);
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  query.push_back('=');
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  query.append(manifest_url_base64);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  query.push_back('|');
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  query.append(entry_url_base64);
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  query.push_back('|');
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  query.append(response_id_string);
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  query.push_back('|');
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  query.append(group_id_string);
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL::Replacements replacements;
2155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  replacements.SetQuery(query.data(), url::Component(0, query.length()));
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL view_entry_url = base_url.ReplaceComponents(replacements);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string anchor;
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EmitAnchor(view_entry_url.spec(), entry_url.spec(), &anchor);
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return anchor;
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EmitAppCacheResourceInfoVector(
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& base_url,
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& manifest_url,
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const AppCacheResourceInfoVector& resource_infos,
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 group_id,
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string* out) {
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append("<table border='0'>\n");
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append("<tr>");
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EmitTableData("Flags", false, true, out);
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EmitTableData("URL", false, true, out);
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EmitTableData("Size (headers and data)", true, true, out);
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append("</tr>\n");
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (AppCacheResourceInfoVector::const_iterator
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          iter = resource_infos.begin();
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != resource_infos.end(); ++iter) {
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out->append("<tr>");
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EmitTableData(FormFlagsString(*iter), false, false, out);
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EmitTableData(FormViewEntryAnchor(base_url, manifest_url,
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      iter->url, iter->response_id,
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      group_id),
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  false, false, out);
2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EmitTableData(base::UTF16ToUTF8(FormatBytesUnlocalized(iter->size)),
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  true, false, out);
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out->append("</tr>\n");
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append("</table>\n");
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EmitResponseHeaders(net::HttpResponseHeaders* headers, std::string* out) {
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append("<hr><pre>");
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append(net::EscapeForHTML(headers->GetStatusLine()));
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->push_back('\n');
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* iter = NULL;
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string name, value;
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out->append(net::EscapeForHTML(name));
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out->append(": ");
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out->append(net::EscapeForHTML(value));
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out->push_back('\n');
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append("</pre>");
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EmitHexDump(const char *buf, size_t buf_len, size_t total_len,
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 std::string* out) {
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append("<hr><pre>");
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StringAppendF(out, "Showing %d of %d bytes\n\n",
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      static_cast<int>(buf_len), static_cast<int>(total_len));
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::ViewCacheHelper::HexDump(buf, buf_len, out);
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (buf_len < total_len)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out->append("\nNote: data is truncated...");
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append("</pre>");
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GURL DecodeBase64URL(const std::string& base64) {
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Base64Decode(base64, &url);
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GURL(url);
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ParseQuery(const std::string& query,
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                std::string* command, std::string* value) {
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t position = query.find("=");
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (position == std::string::npos)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *command = query.substr(0, position);
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *value = query.substr(position + 1);
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !command->empty() && !value->empty();
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SortByManifestUrl(const AppCacheInfo& lhs,
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const AppCacheInfo& rhs) {
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return lhs.manifest_url.spec() < rhs.manifest_url.spec();
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SortByResourceUrl(const AppCacheResourceInfo& lhs,
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const AppCacheResourceInfo& rhs) {
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return lhs.url.spec() < rhs.url.spec();
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GURL ClearQuery(const GURL& url) {
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL::Replacements replacements;
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  replacements.ClearQuery();
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return url.ReplaceComponents(replacements);
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Simple base class for the job subclasses defined here.
3111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)class BaseInternalsJob : public net::URLRequestSimpleJob,
31246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                         public AppCacheServiceImpl::Observer {
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BaseInternalsJob(net::URLRequest* request,
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   net::NetworkDelegate* network_delegate,
31646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                   AppCacheServiceImpl* service)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : URLRequestSimpleJob(request, network_delegate),
3181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        appcache_service_(service),
3191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        appcache_storage_(service->storage()) {
3201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    appcache_service_->AddObserver(this);
3211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
3221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  virtual ~BaseInternalsJob() {
3241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    appcache_service_->RemoveObserver(this);
3251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
3261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  virtual void OnServiceReinitialized(
3281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      AppCacheStorageReference* old_storage_ref) OVERRIDE {
3291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (old_storage_ref->storage() == appcache_storage_)
3301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      disabled_storage_reference_ = old_storage_ref;
3311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  AppCacheServiceImpl* appcache_service_;
3341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  AppCacheStorage* appcache_storage_;
3351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  scoped_refptr<AppCacheStorageReference> disabled_storage_reference_;
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Job that lists all appcaches in the system.
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MainPageJob : public BaseInternalsJob {
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MainPageJob(net::URLRequest* request,
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              net::NetworkDelegate* network_delegate,
34346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)              AppCacheServiceImpl* service)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : BaseInternalsJob(request, network_delegate, service),
345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        weak_factory_(this) {
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Start() OVERRIDE {
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(request_);
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    info_collection_ = new AppCacheInfoCollection;
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    appcache_service_->GetAllAppCacheInfo(
352868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        info_collection_.get(),
353868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        base::Bind(&MainPageJob::OnGotInfoComplete,
354868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                   weak_factory_.GetWeakPtr()));
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Produces a page containing the listing
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int GetData(std::string* mime_type,
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      std::string* charset,
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      std::string* out,
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      const net::CompletionCallback& callback) const OVERRIDE {
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mime_type->assign("text/html");
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    charset->assign("UTF-8");
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out->clear();
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EmitPageStart(out);
367868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!info_collection_.get()) {
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      out->append(kErrorMessage);
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (info_collection_->infos_by_origin.empty()) {
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      out->append(kEmptyAppCachesMessage);
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      typedef std::map<GURL, AppCacheInfoVector> InfoByOrigin;
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AppCacheInfoVector appcaches;
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (InfoByOrigin::const_iterator origin =
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               info_collection_->infos_by_origin.begin();
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           origin != info_collection_->infos_by_origin.end(); ++origin) {
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        appcaches.insert(appcaches.end(),
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         origin->second.begin(), origin->second.end());
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::sort(appcaches.begin(), appcaches.end(), SortByManifestUrl);
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GURL base_url = ClearQuery(request_->url());
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EmitAppCacheInfoVector(base_url, appcache_service_, appcaches, out);
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EmitPageEnd(out);
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::OK;
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~MainPageJob() {}
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnGotInfoComplete(int rv) {
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != net::OK)
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      info_collection_ = NULL;
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StartAsync();
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<AppCacheInfoCollection> info_collection_;
3994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  base::WeakPtrFactory<MainPageJob> weak_factory_;
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(MainPageJob);
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Job that redirects back to the main appcache internals page.
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RedirectToMainPageJob : public BaseInternalsJob {
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RedirectToMainPageJob(net::URLRequest* request,
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        net::NetworkDelegate* network_delegate,
40846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                        AppCacheServiceImpl* service)
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : BaseInternalsJob(request, network_delegate, service) {}
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int GetData(std::string* mime_type,
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      std::string* charset,
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      std::string* data,
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      const net::CompletionCallback& callback) const OVERRIDE {
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::OK;  // IsRedirectResponse induces a redirect.
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool IsRedirectResponse(GURL* location,
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  int* http_status_code) OVERRIDE {
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *location = ClearQuery(request_->url());
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *http_status_code = 307;
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~RedirectToMainPageJob() {}
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Job that removes an appcache and then redirects back to the main page.
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RemoveAppCacheJob : public RedirectToMainPageJob {
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RemoveAppCacheJob(
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::URLRequest* request,
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetworkDelegate* network_delegate,
43546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      AppCacheServiceImpl* service,
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const GURL& manifest_url)
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : RedirectToMainPageJob(request, network_delegate, service),
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        manifest_url_(manifest_url),
439c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        weak_factory_(this) {
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Start() OVERRIDE {
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(request_);
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    appcache_service_->DeleteAppCacheGroup(
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        manifest_url_,base::Bind(&RemoveAppCacheJob::OnDeleteAppCacheComplete,
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 weak_factory_.GetWeakPtr()));
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~RemoveAppCacheJob() {}
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnDeleteAppCacheComplete(int rv) {
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StartAsync();  // Causes the base class to redirect.
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL manifest_url_;
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WeakPtrFactory<RemoveAppCacheJob> weak_factory_;
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Job shows the details of a particular manifest url.
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ViewAppCacheJob : public BaseInternalsJob,
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        public AppCacheStorage::Delegate {
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ViewAppCacheJob(
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::URLRequest* request,
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetworkDelegate* network_delegate,
46946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      AppCacheServiceImpl* service,
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const GURL& manifest_url)
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : BaseInternalsJob(request, network_delegate, service),
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        manifest_url_(manifest_url) {}
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Start() OVERRIDE {
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(request_);
4761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    appcache_storage_->LoadOrCreateGroup(manifest_url_, this);
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Produces a page containing the entries listing.
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int GetData(std::string* mime_type,
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      std::string* charset,
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      std::string* out,
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      const net::CompletionCallback& callback) const OVERRIDE {
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mime_type->assign("text/html");
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    charset->assign("UTF-8");
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out->clear();
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EmitPageStart(out);
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (appcache_info_.manifest_url.is_empty()) {
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      out->append(kManifestNotFoundMessage);
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GURL base_url = ClearQuery(request_->url());
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EmitAppCacheInfo(base_url, appcache_service_, &appcache_info_, out);
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EmitAppCacheResourceInfoVector(base_url,
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     manifest_url_,
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     resource_infos_,
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     appcache_info_.group_id,
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     out);
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EmitPageEnd(out);
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::OK;
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~ViewAppCacheJob() {
5051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    appcache_storage_->CancelDelegateCallbacks(this);
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // AppCacheStorage::Delegate override
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnGroupLoaded(
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AppCacheGroup* group, const GURL& manifest_url) OVERRIDE {
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(manifest_url_, manifest_url);
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (group && group->newest_complete_cache()) {
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      appcache_info_.manifest_url = manifest_url;
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      appcache_info_.group_id = group->group_id();
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      appcache_info_.size = group->newest_complete_cache()->cache_size();
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      appcache_info_.creation_time = group->creation_time();
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      appcache_info_.last_update_time =
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          group->newest_complete_cache()->update_time();
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      appcache_info_.last_access_time = base::Time::Now();
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      group->newest_complete_cache()->ToResourceInfoVector(&resource_infos_);
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::sort(resource_infos_.begin(), resource_infos_.end(),
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                SortByResourceUrl);
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StartAsync();
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL manifest_url_;
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppCacheInfo appcache_info_;
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppCacheResourceInfoVector resource_infos_;
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ViewAppCacheJob);
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Job that shows the details of a particular cached resource.
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ViewEntryJob : public BaseInternalsJob,
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     public AppCacheStorage::Delegate {
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ViewEntryJob(
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::URLRequest* request,
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetworkDelegate* network_delegate,
54046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      AppCacheServiceImpl* service,
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const GURL& manifest_url,
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const GURL& entry_url,
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int64 response_id, int64 group_id)
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : BaseInternalsJob(request, network_delegate, service),
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        manifest_url_(manifest_url), entry_url_(entry_url),
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        response_id_(response_id), group_id_(group_id), amount_read_(0) {
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Start() OVERRIDE {
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(request_);
5511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    appcache_storage_->LoadResponseInfo(
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        manifest_url_, group_id_, response_id_, this);
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Produces a page containing the response headers and data.
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int GetData(std::string* mime_type,
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      std::string* charset,
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      std::string* out,
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      const net::CompletionCallback& callback) const OVERRIDE {
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mime_type->assign("text/html");
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    charset->assign("UTF-8");
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out->clear();
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EmitPageStart(out);
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EmitAnchor(entry_url_.spec(), entry_url_.spec(), out);
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out->append("<br/>\n");
566868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (response_info_.get()) {
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (response_info_->http_response_info())
568868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        EmitResponseHeaders(response_info_->http_response_info()->headers.get(),
569868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            out);
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        out->append("Failed to read response headers.<br>");
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
573868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (response_data_.get()) {
574868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        EmitHexDump(response_data_->data(),
575868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                    amount_read_,
576868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                    response_info_->response_data_size(),
577868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                    out);
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        out->append("Failed to read response data.<br>");
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      out->append("Failed to read response headers and data.<br>");
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EmitPageEnd(out);
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::OK;
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~ViewEntryJob() {
5901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    appcache_storage_->CancelDelegateCallbacks(this);
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnResponseInfoLoaded(
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AppCacheResponseInfo* response_info, int64 response_id) OVERRIDE {
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!response_info) {
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      StartAsync();
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    response_info_ = response_info;
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Read the response data, truncating if its too large.
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int64 kLimit = 100 * 1000;
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 amount_to_read =
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::min(kLimit, response_info->response_data_size());
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    response_data_ = new net::IOBuffer(amount_to_read);
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    reader_.reset(appcache_storage_->CreateResponseReader(
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        manifest_url_, group_id_, response_id_));
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reader_->ReadData(
610868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        response_data_.get(),
611868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        amount_to_read,
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&ViewEntryJob::OnReadComplete, base::Unretained(this)));
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnReadComplete(int result) {
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reader_.reset();
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    amount_read_ = result;
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (result < 0)
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      response_data_ = NULL;
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StartAsync();
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL manifest_url_;
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL entry_url_;
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 response_id_;
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 group_id_;
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<AppCacheResponseInfo> response_info_;
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<net::IOBuffer> response_data_;
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int amount_read_;
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<AppCacheResponseReader> reader_;
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)net::URLRequestJob* ViewAppCacheInternalsJobFactory::CreateJobForRequest(
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::URLRequest* request,
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::NetworkDelegate* network_delegate,
63846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    AppCacheServiceImpl* service) {
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!request->url().has_query())
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return new MainPageJob(request, network_delegate, service);
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string command;
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string param;
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ParseQuery(request->url().query(), &command, &param);
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (command == kRemoveCacheCommand)
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return new RemoveAppCacheJob(request, network_delegate, service,
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 DecodeBase64URL(param));
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (command == kViewCacheCommand)
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return new ViewAppCacheJob(request, network_delegate, service,
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               DecodeBase64URL(param));
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> tokens;
655116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  int64 response_id = 0;
656116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  int64 group_id = 0;
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (command == kViewEntryCommand && Tokenize(param, "|", &tokens) == 4u &&
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::StringToInt64(tokens[2], &response_id) &&
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::StringToInt64(tokens[3], &group_id)) {
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return new ViewEntryJob(request, network_delegate, service,
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            DecodeBase64URL(tokens[0]),  // manifest url
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            DecodeBase64URL(tokens[1]),  // entry url
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            response_id, group_id);
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new RedirectToMainPageJob(request, network_delegate, service);
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
66923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}  // namespace content
670