view_appcache_internals_job.cc revision 5c02ac1a9c1b504631c0a3d2b6e737b5d738bae1
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"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/escape.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/io_buffer.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_response_headers.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_simple_job.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/view_cache_helper.h"
27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "webkit/browser/appcache/appcache.h"
28868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "webkit/browser/appcache/appcache_group.h"
29868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "webkit/browser/appcache/appcache_policy.h"
30868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "webkit/browser/appcache/appcache_response.h"
31868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "webkit/browser/appcache/appcache_service.h"
32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "webkit/browser/appcache/appcache_storage.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)using appcache::AppCacheGroup;
3523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)using appcache::AppCacheInfo;
3623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)using appcache::AppCacheInfoCollection;
3723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)using appcache::AppCacheInfoVector;
3823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)using appcache::AppCacheService;
3923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)using appcache::AppCacheStorage;
4023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)using appcache::AppCacheStorageReference;
4123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)using appcache::AppCacheResourceInfo;
4223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)using appcache::AppCacheResourceInfoVector;
4323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)using appcache::AppCacheResponseInfo;
4423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)using appcache::AppCacheResponseReader;
4523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
4623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)namespace content {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kErrorMessage[] = "Error in retrieving Application Caches.";
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kEmptyAppCachesMessage[] = "No available Application Caches.";
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kManifestNotFoundMessage[] = "Manifest not found.";
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kManifest[] = "Manifest: ";
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kSize[] = "Size: ";
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kCreationTime[] = "Creation Time: ";
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kLastAccessTime[] = "Last Access Time: ";
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kLastUpdateTime[] = "Last Update Time: ";
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kFormattedDisabledAppCacheMsg[] =
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "<b><i><font color=\"FF0000\">"
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "This Application Cache is disabled by policy.</font></i></b><br/>";
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kRemoveCacheLabel[] = "Remove";
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kViewCacheLabel[] = "View Entries";
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kRemoveCacheCommand[] = "remove-cache";
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kViewCacheCommand[] = "view-cache";
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kViewEntryCommand[] = "view-entry";
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EmitPageStart(std::string* out) {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append(
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "<!DOCTYPE HTML>\n"
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "<html><title>AppCache Internals</title>\n"
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "<meta http-equiv=\"Content-Security-Policy\""
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  content=\"object-src 'none'; script-src 'none'\">\n"
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "<style>\n"
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "body { font-family: sans-serif; font-size: 0.8em; }\n"
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "tt, code, pre { font-family: WebKitHack, monospace; }\n"
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "form { display: inline; }\n"
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ".subsection_body { margin: 10px 0 10px 2em; }\n"
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ".subsection_title { font-weight: bold; }\n"
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "</style>\n"
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "</head><body>\n");
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EmitPageEnd(std::string* out) {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append("</body></html>\n");
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EmitListItem(const std::string& label,
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  const std::string& data,
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  std::string* out) {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append("<li>");
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append(net::EscapeForHTML(label));
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append(net::EscapeForHTML(data));
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append("</li>\n");
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EmitAnchor(const std::string& url, const std::string& text,
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                std::string* out) {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append("<a href=\"");
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append(net::EscapeForHTML(url));
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append("\">");
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append(net::EscapeForHTML(text));
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append("</a>");
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EmitCommandAnchor(const char* label,
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const GURL& base_url,
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const char* command,
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const char* param,
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       std::string* out) {
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string query(command);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  query.push_back('=');
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  query.append(param);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL::Replacements replacements;
1135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  replacements.SetQuery(query.data(), url::Component(0, query.length()));
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL command_url = base_url.ReplaceComponents(replacements);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EmitAnchor(command_url.spec(), label, out);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EmitAppCacheInfo(const GURL& base_url,
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      AppCacheService* service,
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      const AppCacheInfo* info,
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      std::string* out) {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string manifest_url_base64;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Base64Encode(info->manifest_url.spec(), &manifest_url_base64);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append("\n<p>");
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append(kManifest);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EmitAnchor(info->manifest_url.spec(), info->manifest_url.spec(), out);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append("<br/>\n");
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!service->appcache_policy()->CanLoadAppCache(
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          info->manifest_url, info->manifest_url)) {
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out->append(kFormattedDisabledAppCacheMsg);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append("\n<br/>\n");
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EmitCommandAnchor(kRemoveCacheLabel, base_url,
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    kRemoveCacheCommand, manifest_url_base64.c_str(), out);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append("&nbsp;&nbsp;");
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EmitCommandAnchor(kViewCacheLabel, base_url,
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    kViewCacheCommand, manifest_url_base64.c_str(), out);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append("\n<br/>\n");
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append("<ul>");
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EmitListItem(
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kSize,
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::UTF16ToUTF8(FormatBytesUnlocalized(info->size)),
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      out);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EmitListItem(
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kCreationTime,
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::UTF16ToUTF8(TimeFormatFriendlyDateAndTime(info->creation_time)),
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      out);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EmitListItem(
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kLastUpdateTime,
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::UTF16ToUTF8(TimeFormatFriendlyDateAndTime(info->last_update_time)),
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      out);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EmitListItem(
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kLastAccessTime,
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::UTF16ToUTF8(TimeFormatFriendlyDateAndTime(info->last_access_time)),
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      out);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append("</ul></p></br>\n");
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EmitAppCacheInfoVector(
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& base_url,
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AppCacheService* service,
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const AppCacheInfoVector& appcaches,
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string* out) {
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::vector<AppCacheInfo>::const_iterator info =
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           appcaches.begin();
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       info != appcaches.end(); ++info) {
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EmitAppCacheInfo(base_url, service, &(*info), out);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EmitTableData(const std::string& data, bool align_right, bool bold,
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   std::string* out) {
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (align_right)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out->append("<td align='right'>");
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out->append("<td>");
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (bold)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out->append("<b>");
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append(data);
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (bold)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out->append("</b>");
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append("</td>");
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string FormFlagsString(const AppCacheResourceInfo& info) {
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string str;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (info.is_manifest)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    str.append("Manifest, ");
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (info.is_master)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    str.append("Master, ");
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (info.is_intercept)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    str.append("Intercept, ");
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (info.is_fallback)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    str.append("Fallback, ");
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (info.is_explicit)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    str.append("Explicit, ");
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (info.is_foreign)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    str.append("Foreign, ");
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return str;
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string FormViewEntryAnchor(const GURL& base_url,
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const GURL& manifest_url, const GURL& entry_url,
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                int64 response_id,
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                int64 group_id) {
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string manifest_url_base64;
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string entry_url_base64;
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string response_id_string;
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string group_id_string;
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Base64Encode(manifest_url.spec(), &manifest_url_base64);
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Base64Encode(entry_url.spec(), &entry_url_base64);
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response_id_string = base::Int64ToString(response_id);
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  group_id_string = base::Int64ToString(group_id);
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string query(kViewEntryCommand);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  query.push_back('=');
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  query.append(manifest_url_base64);
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  query.push_back('|');
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  query.append(entry_url_base64);
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  query.push_back('|');
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  query.append(response_id_string);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  query.push_back('|');
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  query.append(group_id_string);
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL::Replacements replacements;
2275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  replacements.SetQuery(query.data(), url::Component(0, query.length()));
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL view_entry_url = base_url.ReplaceComponents(replacements);
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string anchor;
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EmitAnchor(view_entry_url.spec(), entry_url.spec(), &anchor);
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return anchor;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EmitAppCacheResourceInfoVector(
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& base_url,
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& manifest_url,
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const AppCacheResourceInfoVector& resource_infos,
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 group_id,
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string* out) {
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append("<table border='0'>\n");
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append("<tr>");
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EmitTableData("Flags", false, true, out);
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EmitTableData("URL", false, true, out);
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EmitTableData("Size (headers and data)", true, true, out);
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append("</tr>\n");
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (AppCacheResourceInfoVector::const_iterator
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          iter = resource_infos.begin();
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != resource_infos.end(); ++iter) {
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out->append("<tr>");
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EmitTableData(FormFlagsString(*iter), false, false, out);
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EmitTableData(FormViewEntryAnchor(base_url, manifest_url,
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      iter->url, iter->response_id,
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      group_id),
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  false, false, out);
2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EmitTableData(base::UTF16ToUTF8(FormatBytesUnlocalized(iter->size)),
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  true, false, out);
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out->append("</tr>\n");
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append("</table>\n");
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EmitResponseHeaders(net::HttpResponseHeaders* headers, std::string* out) {
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append("<hr><pre>");
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append(net::EscapeForHTML(headers->GetStatusLine()));
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->push_back('\n');
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* iter = NULL;
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string name, value;
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out->append(net::EscapeForHTML(name));
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out->append(": ");
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out->append(net::EscapeForHTML(value));
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out->push_back('\n');
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append("</pre>");
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EmitHexDump(const char *buf, size_t buf_len, size_t total_len,
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 std::string* out) {
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append("<hr><pre>");
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StringAppendF(out, "Showing %d of %d bytes\n\n",
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      static_cast<int>(buf_len), static_cast<int>(total_len));
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::ViewCacheHelper::HexDump(buf, buf_len, out);
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (buf_len < total_len)
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out->append("\nNote: data is truncated...");
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->append("</pre>");
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GURL DecodeBase64URL(const std::string& base64) {
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Base64Decode(base64, &url);
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GURL(url);
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ParseQuery(const std::string& query,
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                std::string* command, std::string* value) {
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t position = query.find("=");
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (position == std::string::npos)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *command = query.substr(0, position);
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *value = query.substr(position + 1);
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !command->empty() && !value->empty();
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SortByManifestUrl(const AppCacheInfo& lhs,
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const AppCacheInfo& rhs) {
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return lhs.manifest_url.spec() < rhs.manifest_url.spec();
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SortByResourceUrl(const AppCacheResourceInfo& lhs,
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const AppCacheResourceInfo& rhs) {
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return lhs.url.spec() < rhs.url.spec();
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GURL ClearQuery(const GURL& url) {
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL::Replacements replacements;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  replacements.ClearQuery();
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return url.ReplaceComponents(replacements);
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Simple base class for the job subclasses defined here.
3231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)class BaseInternalsJob : public net::URLRequestSimpleJob,
3241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                         public AppCacheService::Observer {
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BaseInternalsJob(net::URLRequest* request,
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   net::NetworkDelegate* network_delegate,
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   AppCacheService* service)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : URLRequestSimpleJob(request, network_delegate),
3301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        appcache_service_(service),
3311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        appcache_storage_(service->storage()) {
3321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    appcache_service_->AddObserver(this);
3331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
3341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  virtual ~BaseInternalsJob() {
3361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    appcache_service_->RemoveObserver(this);
3371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
3381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  virtual void OnServiceReinitialized(
3401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      AppCacheStorageReference* old_storage_ref) OVERRIDE {
3411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (old_storage_ref->storage() == appcache_storage_)
3421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      disabled_storage_reference_ = old_storage_ref;
3431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppCacheService* appcache_service_;
3461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  AppCacheStorage* appcache_storage_;
3471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  scoped_refptr<AppCacheStorageReference> disabled_storage_reference_;
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Job that lists all appcaches in the system.
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MainPageJob : public BaseInternalsJob {
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MainPageJob(net::URLRequest* request,
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              net::NetworkDelegate* network_delegate,
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              AppCacheService* service)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : BaseInternalsJob(request, network_delegate, service),
357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        weak_factory_(this) {
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Start() OVERRIDE {
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(request_);
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    info_collection_ = new AppCacheInfoCollection;
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    appcache_service_->GetAllAppCacheInfo(
364868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        info_collection_.get(),
365868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        base::Bind(&MainPageJob::OnGotInfoComplete,
366868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                   weak_factory_.GetWeakPtr()));
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Produces a page containing the listing
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int GetData(std::string* mime_type,
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      std::string* charset,
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      std::string* out,
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      const net::CompletionCallback& callback) const OVERRIDE {
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mime_type->assign("text/html");
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    charset->assign("UTF-8");
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out->clear();
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EmitPageStart(out);
379868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!info_collection_.get()) {
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      out->append(kErrorMessage);
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (info_collection_->infos_by_origin.empty()) {
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      out->append(kEmptyAppCachesMessage);
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      typedef std::map<GURL, AppCacheInfoVector> InfoByOrigin;
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AppCacheInfoVector appcaches;
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (InfoByOrigin::const_iterator origin =
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               info_collection_->infos_by_origin.begin();
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           origin != info_collection_->infos_by_origin.end(); ++origin) {
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        appcaches.insert(appcaches.end(),
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         origin->second.begin(), origin->second.end());
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::sort(appcaches.begin(), appcaches.end(), SortByManifestUrl);
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GURL base_url = ClearQuery(request_->url());
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EmitAppCacheInfoVector(base_url, appcache_service_, appcaches, out);
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EmitPageEnd(out);
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::OK;
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~MainPageJob() {}
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnGotInfoComplete(int rv) {
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != net::OK)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      info_collection_ = NULL;
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StartAsync();
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<AppCacheInfoCollection> info_collection_;
4114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  base::WeakPtrFactory<MainPageJob> weak_factory_;
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(MainPageJob);
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Job that redirects back to the main appcache internals page.
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RedirectToMainPageJob : public BaseInternalsJob {
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RedirectToMainPageJob(net::URLRequest* request,
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        net::NetworkDelegate* network_delegate,
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        AppCacheService* service)
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : BaseInternalsJob(request, network_delegate, service) {}
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int GetData(std::string* mime_type,
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      std::string* charset,
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      std::string* data,
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      const net::CompletionCallback& callback) const OVERRIDE {
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::OK;  // IsRedirectResponse induces a redirect.
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool IsRedirectResponse(GURL* location,
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  int* http_status_code) OVERRIDE {
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *location = ClearQuery(request_->url());
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *http_status_code = 307;
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~RedirectToMainPageJob() {}
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Job that removes an appcache and then redirects back to the main page.
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RemoveAppCacheJob : public RedirectToMainPageJob {
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RemoveAppCacheJob(
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::URLRequest* request,
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetworkDelegate* network_delegate,
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AppCacheService* service,
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const GURL& manifest_url)
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : RedirectToMainPageJob(request, network_delegate, service),
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        manifest_url_(manifest_url),
451c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        weak_factory_(this) {
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Start() OVERRIDE {
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(request_);
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    appcache_service_->DeleteAppCacheGroup(
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        manifest_url_,base::Bind(&RemoveAppCacheJob::OnDeleteAppCacheComplete,
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 weak_factory_.GetWeakPtr()));
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~RemoveAppCacheJob() {}
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnDeleteAppCacheComplete(int rv) {
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StartAsync();  // Causes the base class to redirect.
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL manifest_url_;
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WeakPtrFactory<RemoveAppCacheJob> weak_factory_;
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Job shows the details of a particular manifest url.
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ViewAppCacheJob : public BaseInternalsJob,
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        public AppCacheStorage::Delegate {
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ViewAppCacheJob(
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::URLRequest* request,
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetworkDelegate* network_delegate,
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AppCacheService* service,
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const GURL& manifest_url)
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : BaseInternalsJob(request, network_delegate, service),
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        manifest_url_(manifest_url) {}
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Start() OVERRIDE {
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(request_);
4881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    appcache_storage_->LoadOrCreateGroup(manifest_url_, this);
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Produces a page containing the entries listing.
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int GetData(std::string* mime_type,
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      std::string* charset,
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      std::string* out,
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      const net::CompletionCallback& callback) const OVERRIDE {
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mime_type->assign("text/html");
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    charset->assign("UTF-8");
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out->clear();
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EmitPageStart(out);
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (appcache_info_.manifest_url.is_empty()) {
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      out->append(kManifestNotFoundMessage);
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GURL base_url = ClearQuery(request_->url());
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EmitAppCacheInfo(base_url, appcache_service_, &appcache_info_, out);
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EmitAppCacheResourceInfoVector(base_url,
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     manifest_url_,
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     resource_infos_,
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     appcache_info_.group_id,
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     out);
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EmitPageEnd(out);
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::OK;
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~ViewAppCacheJob() {
5171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    appcache_storage_->CancelDelegateCallbacks(this);
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // AppCacheStorage::Delegate override
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnGroupLoaded(
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AppCacheGroup* group, const GURL& manifest_url) OVERRIDE {
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(manifest_url_, manifest_url);
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (group && group->newest_complete_cache()) {
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      appcache_info_.manifest_url = manifest_url;
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      appcache_info_.group_id = group->group_id();
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      appcache_info_.size = group->newest_complete_cache()->cache_size();
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      appcache_info_.creation_time = group->creation_time();
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      appcache_info_.last_update_time =
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          group->newest_complete_cache()->update_time();
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      appcache_info_.last_access_time = base::Time::Now();
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      group->newest_complete_cache()->ToResourceInfoVector(&resource_infos_);
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::sort(resource_infos_.begin(), resource_infos_.end(),
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                SortByResourceUrl);
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StartAsync();
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL manifest_url_;
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppCacheInfo appcache_info_;
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppCacheResourceInfoVector resource_infos_;
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ViewAppCacheJob);
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Job that shows the details of a particular cached resource.
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ViewEntryJob : public BaseInternalsJob,
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     public AppCacheStorage::Delegate {
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ViewEntryJob(
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::URLRequest* request,
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetworkDelegate* network_delegate,
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AppCacheService* service,
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const GURL& manifest_url,
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const GURL& entry_url,
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int64 response_id, int64 group_id)
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : BaseInternalsJob(request, network_delegate, service),
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        manifest_url_(manifest_url), entry_url_(entry_url),
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        response_id_(response_id), group_id_(group_id), amount_read_(0) {
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Start() OVERRIDE {
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(request_);
5631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    appcache_storage_->LoadResponseInfo(
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        manifest_url_, group_id_, response_id_, this);
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Produces a page containing the response headers and data.
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int GetData(std::string* mime_type,
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      std::string* charset,
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      std::string* out,
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      const net::CompletionCallback& callback) const OVERRIDE {
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mime_type->assign("text/html");
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    charset->assign("UTF-8");
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out->clear();
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EmitPageStart(out);
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EmitAnchor(entry_url_.spec(), entry_url_.spec(), out);
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out->append("<br/>\n");
578868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (response_info_.get()) {
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (response_info_->http_response_info())
580868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        EmitResponseHeaders(response_info_->http_response_info()->headers.get(),
581868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            out);
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        out->append("Failed to read response headers.<br>");
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (response_data_.get()) {
586868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        EmitHexDump(response_data_->data(),
587868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                    amount_read_,
588868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                    response_info_->response_data_size(),
589868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                    out);
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        out->append("Failed to read response data.<br>");
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      out->append("Failed to read response headers and data.<br>");
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EmitPageEnd(out);
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::OK;
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~ViewEntryJob() {
6021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    appcache_storage_->CancelDelegateCallbacks(this);
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnResponseInfoLoaded(
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AppCacheResponseInfo* response_info, int64 response_id) OVERRIDE {
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!response_info) {
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      StartAsync();
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    response_info_ = response_info;
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Read the response data, truncating if its too large.
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int64 kLimit = 100 * 1000;
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 amount_to_read =
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::min(kLimit, response_info->response_data_size());
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    response_data_ = new net::IOBuffer(amount_to_read);
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    reader_.reset(appcache_storage_->CreateResponseReader(
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        manifest_url_, group_id_, response_id_));
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reader_->ReadData(
622868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        response_data_.get(),
623868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        amount_to_read,
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&ViewEntryJob::OnReadComplete, base::Unretained(this)));
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnReadComplete(int result) {
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reader_.reset();
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    amount_read_ = result;
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (result < 0)
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      response_data_ = NULL;
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StartAsync();
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL manifest_url_;
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL entry_url_;
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 response_id_;
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 group_id_;
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<AppCacheResponseInfo> response_info_;
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<net::IOBuffer> response_data_;
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int amount_read_;
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<AppCacheResponseReader> reader_;
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)net::URLRequestJob* ViewAppCacheInternalsJobFactory::CreateJobForRequest(
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::URLRequest* request,
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::NetworkDelegate* network_delegate,
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AppCacheService* service) {
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!request->url().has_query())
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return new MainPageJob(request, network_delegate, service);
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string command;
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string param;
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ParseQuery(request->url().query(), &command, &param);
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (command == kRemoveCacheCommand)
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return new RemoveAppCacheJob(request, network_delegate, service,
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 DecodeBase64URL(param));
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (command == kViewCacheCommand)
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return new ViewAppCacheJob(request, network_delegate, service,
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               DecodeBase64URL(param));
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> tokens;
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 response_id;
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 group_id;
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (command == kViewEntryCommand && Tokenize(param, "|", &tokens) == 4u &&
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::StringToInt64(tokens[2], &response_id) &&
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::StringToInt64(tokens[3], &group_id)) {
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return new ViewEntryJob(request, network_delegate, service,
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            DecodeBase64URL(tokens[0]),  // manifest url
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            DecodeBase64URL(tokens[1]),  // entry url
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            response_id, group_id);
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new RedirectToMainPageJob(request, network_delegate, service);
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
68123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}  // namespace content
682