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

Side by Side Diff: webkit/appcache/view_appcache_internals_job.cc

Issue 7326023: about://appcache-internals enhancements (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « webkit/appcache/view_appcache_internals_job.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <algorithm> 5 #include <algorithm>
6 #include <string>
6 7
7 #include "webkit/appcache/view_appcache_internals_job.h" 8 #include "webkit/appcache/view_appcache_internals_job.h"
8 9
9 #include "base/base64.h" 10 #include "base/base64.h"
11 #include "base/format_macros.h"
12 #include "base/i18n/time_formatting.h"
10 #include "base/logging.h" 13 #include "base/logging.h"
11 #include "base/format_macros.h" 14 #include "base/string_number_conversions.h"
15 #include "base/string_util.h"
12 #include "base/stringprintf.h" 16 #include "base/stringprintf.h"
13 #include "base/utf_string_conversions.h" 17 #include "base/utf_string_conversions.h"
14 #include "base/i18n/time_formatting.h"
15 #include "base/string_util.h"
16 #include "net/base/escape.h" 18 #include "net/base/escape.h"
19 #include "net/base/io_buffer.h"
20 #include "net/http/http_response_headers.h"
17 #include "net/url_request/url_request.h" 21 #include "net/url_request/url_request.h"
22 #include "net/url_request/url_request_simple_job.h"
23 #include "net/url_request/view_cache_helper.h"
24 #include "webkit/appcache/appcache.h"
25 #include "webkit/appcache/appcache_group.h"
18 #include "webkit/appcache/appcache_policy.h" 26 #include "webkit/appcache/appcache_policy.h"
27 #include "webkit/appcache/appcache_response.h"
19 #include "webkit/appcache/appcache_service.h" 28 #include "webkit/appcache/appcache_service.h"
20 29
30 namespace appcache {
21 namespace { 31 namespace {
22 32
23 const char kErrorMessage[] = "Error in retrieving Application Caches."; 33 const char kErrorMessage[] = "Error in retrieving Application Caches.";
24 const char kEmptyAppCachesMessage[] = "No available Application Caches."; 34 const char kEmptyAppCachesMessage[] = "No available Application Caches.";
25 const char kRemoveAppCache[] = "Remove this AppCache"; 35 const char kManifestNotFoundMessage[] = "Manifest not found.";
26 const char kManifest[] = "Manifest: "; 36 const char kManifest[] = "Manifest: ";
27 const char kSize[] = "Size: "; 37 const char kSize[] = "Size: ";
28 const char kCreationTime[] = "Creation Time: "; 38 const char kCreationTime[] = "Creation Time: ";
29 const char kLastAccessTime[] = "Last Access Time: "; 39 const char kLastAccessTime[] = "Last Access Time: ";
30 const char kLastUpdateTime[] = "Last Update Time: "; 40 const char kLastUpdateTime[] = "Last Update Time: ";
31 const char kFormattedDisabledAppCacheMsg[] = 41 const char kFormattedDisabledAppCacheMsg[] =
32 "<b><i><font color=\"FF0000\">" 42 "<b><i><font color=\"FF0000\">"
33 "This Application Cache is disabled by policy.</font></i></b><br/>"; 43 "This Application Cache is disabled by policy.</font></i></b><br/>";
34 44 const char kRemoveCacheLabel[] = "Remove";
35 void StartHTML(std::string* out) { 45 const char kViewCacheLabel[] = "View Entries";
46 const char kRemoveCacheCommand[] = "remove-cache";
47 const char kViewCacheCommand[] = "view-cache";
48 const char kViewEntryCommand[] = "view-entry";
49
50 void EmitPageStart(std::string* out) {
36 DCHECK(out); 51 DCHECK(out);
37 out->append( 52 out->append(
38 "<!DOCTYPE HTML>" 53 "<!DOCTYPE HTML>\n"
39 "<html><title>AppCache Internals</title>" 54 "<html><title>AppCache Internals</title>\n"
40 "<style>" 55 "<style>\n"
41 "body { font-family: sans-serif; font-size: 0.8em; }\n" 56 "body { font-family: sans-serif; font-size: 0.8em; }\n"
42 "tt, code, pre { font-family: WebKitHack, monospace; }\n" 57 "tt, code, pre { font-family: WebKitHack, monospace; }\n"
43 ".subsection_body { margin: 10px 0 10px 2em; }\n" 58 ".subsection_body { margin: 10px 0 10px 2em; }\n"
44 ".subsection_title { font-weight: bold; }\n" 59 ".subsection_title { font-weight: bold; }\n"
45 "</style>" 60 "</style>\n"
46 "<script>\n" 61 "<script>\n"
47 // Unfortunately we can't do XHR from chrome://appcache-internals 62 "function PerformCommand(command, param) {\n"
48 // because the chrome:// protocol restricts access. 63 " location = location.pathname + '?' + command + '=' + param;\n"
49 //
50 // So instead, we will send commands by doing a form
51 // submission (which as a side effect will reload the page).
52 "function RemoveCommand(command) {\n"
53 " document.getElementById('cmd').value = command;\n"
54 " document.getElementById('cmdsender').submit();\n"
55 "}\n" 64 "}\n"
56 "</script>\n" 65 "</script>\n"
57 "</head><body>" 66 "</head><body>\n");
58 "<form action='' method=GET id=cmdsender>" 67 }
59 "<input type='hidden' id=cmd name='remove'>" 68
60 "</form>"); 69 void EmitPageEnd(std::string* out) {
61 }
62
63 void EndHTML(std::string* out) {
64 DCHECK(out); 70 DCHECK(out);
65 out->append("</body></html>"); 71 out->append("</body></html>\n");
66 } 72 }
67 73
68 // Appends an input button to |data| with text |title| that sends the command 74 // Appends an input button to |out| with text |label| that sends
69 // string |command| back to the browser, and then refreshes the page. 75 // |command| and |param| back to the browser and navigates the frame
70 void DrawCommandButton(const std::string& title, 76 // to the resulting page.
77 void EmitCommandButton(const std::string& label,
71 const std::string& command, 78 const std::string& command,
72 std::string* data) { 79 const std::string& param,
73 base::StringAppendF(data, "<input type=\"button\" value=\"%s\" " 80 std::string* out) {
74 "onclick=\"RemoveCommand('%s')\" />", 81 base::StringAppendF(out, "<input type=\"button\" value=\"%s\" "
75 title.c_str(), 82 "onclick=\"PerformCommand('%s', '%s')\" />\n",
76 command.c_str()); 83 label.c_str(), command.c_str(), param.c_str());
77 } 84 }
78 85
79 void AddLiTag(const std::string& element_title, 86 void EmitListItem(const std::string& label, const std::string& data,
80 const std::string& element_data, std::string* out) { 87 std::string* out) {
81 DCHECK(out); 88 DCHECK(out);
82 out->append("<li>"); 89 out->append("<li>");
83 out->append(element_title); 90 out->append(label);
84 out->append(element_data); 91 out->append(data);
85 out->append("</li>"); 92 out->append("</li>\n");
86 } 93 }
87 94
88 void WrapInHREF(const std::string& in, std::string* out) { 95 void EmitAnchor(const std::string& url, const std::string& text,
96 std::string* out) {
89 out->append("<a href="); 97 out->append("<a href=");
90 out->append(in); 98 out->append(url);
91 out->append(">"); 99 out->append(">");
92 out->append(in); 100 out->append(text);
93 out->append("</a><br/>"); 101 out->append("</a><br/>");
94 } 102 }
95 103
96 void AddHTMLFromAppCacheToOutput( 104 void EmitAppCacheInfo(AppCacheService* service,
97 const appcache::AppCacheService& appcache_service, 105 const AppCacheInfo* info,
98 const appcache::AppCacheInfoVector& appcaches, std::string* out) { 106 std::string* out) {
99 for (std::vector<appcache::AppCacheInfo>::const_iterator info = 107 std::string manifest_url_base64;
108 base::Base64Encode(info->manifest_url.spec(), &manifest_url_base64);
109
110 out->append("\n<p>");
111 out->append(kManifest);
112 EmitAnchor(info->manifest_url.spec(), info->manifest_url.spec(), out);
113 if (!service->appcache_policy()->CanLoadAppCache(
114 info->manifest_url)) {
115 out->append(kFormattedDisabledAppCacheMsg);
116 }
117 out->append("\n<br/>\n");
118 EmitCommandButton(kRemoveCacheLabel, kRemoveCacheCommand,
119 manifest_url_base64, out);
120 EmitCommandButton(kViewCacheLabel, kViewCacheCommand,
121 manifest_url_base64, out);
122 out->append("<ul>");
123 EmitListItem(
124 kSize,
125 UTF16ToUTF8(FormatBytesUnlocalized(info->size)),
126 out);
127 EmitListItem(
128 kCreationTime,
129 UTF16ToUTF8(TimeFormatFriendlyDateAndTime(info->creation_time)),
130 out);
131 EmitListItem(
132 kLastUpdateTime,
133 UTF16ToUTF8(TimeFormatFriendlyDateAndTime(info->last_update_time)),
134 out);
135 EmitListItem(
136 kLastAccessTime,
137 UTF16ToUTF8(TimeFormatFriendlyDateAndTime(info->last_access_time)),
138 out);
139 out->append("</ul></p></br>\n");
140 }
141
142 void EmitAppCacheInfoVector(
143 AppCacheService* service,
144 const AppCacheInfoVector& appcaches,
145 std::string* out) {
146 for (std::vector<AppCacheInfo>::const_iterator info =
100 appcaches.begin(); 147 appcaches.begin();
101 info != appcaches.end(); ++info) { 148 info != appcaches.end(); ++info) {
102 std::string manifest_url_base64; 149 EmitAppCacheInfo(service, &(*info), out);
103 base::Base64Encode(info->manifest_url.spec(), &manifest_url_base64); 150 }
104 151 }
105 out->append("<p>"); 152
106 std::string anchored_manifest; 153 void EmitTableData(const std::string& data, bool align_right, bool bold,
107 WrapInHREF(info->manifest_url.spec(), &anchored_manifest); 154 std::string* out) {
108 out->append(kManifest); 155 if (align_right)
109 out->append(anchored_manifest); 156 out->append("<td align='right'>");
110 if (!appcache_service.appcache_policy()->CanLoadAppCache( 157 else
111 info->manifest_url)) { 158 out->append("<td>");
112 out->append(kFormattedDisabledAppCacheMsg); 159 if (bold)
160 out->append("<b>");
161 out->append(data);
162 if (bold)
163 out->append("</b>");
164 out->append("</td>");
165 }
166
167 std::string FormFlagsString(const AppCacheResourceInfo& info) {
168 std::string str;
169 if (info.is_manifest)
170 str.append("Manifest, ");
171 if (info.is_master)
172 str.append("Master, ");
173 if (info.is_fallback)
174 str.append("Fallback, ");
175 if (info.is_explicit)
176 str.append("Explicit, ");
177 if (info.is_foreign)
178 str.append("Foreign, ");
179 return str;
180 }
181
182 std::string FormViewEntryAnchor(const GURL& base_url,
183 const GURL& manifest_url, const GURL& entry_url,
184 int64 response_id) {
185 std::string manifest_url_base64;
186 std::string entry_url_base64;
187 std::string response_id_string;
188 base::Base64Encode(manifest_url.spec(), &manifest_url_base64);
189 base::Base64Encode(entry_url.spec(), &entry_url_base64);
190 response_id_string = base::Int64ToString(response_id);
191
192 std::string query(kViewEntryCommand);
193 query.push_back('=');
194 query.append(manifest_url_base64);
195 query.push_back('|');
196 query.append(entry_url_base64);
197 query.push_back('|');
198 query.append(response_id_string);
199
200 GURL::Replacements replacements;
201 replacements.SetQuery(query.data(),
202 url_parse::Component(0, query.length()));
203 GURL view_entry_url = base_url.ReplaceComponents(replacements);
204
205 std::string anchor;
206 EmitAnchor(view_entry_url.spec(), entry_url.spec(), &anchor);
207 return anchor;
208 }
209
210 void EmitAppCacheResourceInfoVector(
211 const GURL& base_url,
212 const GURL& manifest_url,
213 const AppCacheResourceInfoVector& resource_infos,
214 std::string* out) {
215 out->append("<table border='0'>\n");
216 out->append("<tr>");
217 EmitTableData("Flags", false, true, out);
218 EmitTableData("URL", false, true, out);
219 EmitTableData("Size (headers and data)", true, true, out);
220 out->append("</tr>\n");
221 for (AppCacheResourceInfoVector::const_iterator
222 iter = resource_infos.begin();
223 iter != resource_infos.end(); ++iter) {
224 out->append("<tr>");
225 EmitTableData(FormFlagsString(*iter), false, false, out);
226 EmitTableData(FormViewEntryAnchor(base_url, manifest_url,
227 iter->url, iter->response_id),
228 false, false, out);
229 EmitTableData(UTF16ToUTF8(FormatBytesUnlocalized(iter->size)),
230 true, false, out);
231 out->append("</tr>\n");
232 }
233 out->append("</table>\n");
234 }
235
236 void EmitResponseHeaders(net::HttpResponseHeaders* headers, std::string* out) {
237 out->append("<hr><pre>");
238 out->append(EscapeForHTML(headers->GetStatusLine()));
239 out->push_back('\n');
240
241 void* iter = NULL;
242 std::string name, value;
243 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
244 out->append(EscapeForHTML(name));
245 out->append(": ");
246 out->append(EscapeForHTML(value));
247 out->push_back('\n');
248 }
249 out->append("</pre>");
250 }
251
252 void EmitHexDump(const char *buf, size_t buf_len, size_t total_len,
253 std::string* out) {
254 out->append("<hr><pre>");
255 base::StringAppendF(out, "Showing %d of %d bytes\n\n",
256 static_cast<int>(buf_len), static_cast<int>(total_len));
257 net::ViewCacheHelper::HexDump(buf, buf_len, out);
258 if (buf_len < total_len)
259 out->append("\nNote: data is truncated...");
260 out->append("</pre>");
261 }
262
263 GURL DecodeBase64URL(const std::string base64) {
264 std::string url;
265 base::Base64Decode(base64, &url);
266 return GURL(url);
267 }
268
269 bool ParseQuery(const std::string& query,
270 std::string* command, std::string* value) {
271 size_t position = query.find("=");
272 if (position == std::string::npos)
273 return false;
274 *command = query.substr(0, position);
275 *value = query.substr(position + 1);
276 return !command->empty() && !value->empty();
277 }
278
279 bool SortByManifestUrl(const AppCacheInfo& lhs,
280 const AppCacheInfo& rhs) {
281 return lhs.manifest_url.spec() < rhs.manifest_url.spec();
282 }
283
284 bool SortByResourceUrl(const AppCacheResourceInfo& lhs,
285 const AppCacheResourceInfo& rhs) {
286 return lhs.url.spec() < rhs.url.spec();
287 }
288
289 GURL ClearQuery(const GURL& url) {
290 GURL::Replacements replacements;
291 replacements.ClearQuery();
292 return url.ReplaceComponents(replacements);
293 }
294
295 // Simple base class for the job subclasses defined here.
296 class BaseInternalsJob : public net::URLRequestSimpleJob {
297 protected:
298 BaseInternalsJob(net::URLRequest* request, AppCacheService* service)
299 : URLRequestSimpleJob(request), appcache_service_(service) {}
300
301 AppCacheService* appcache_service_;
302 };
303
304 // Job that lists all appcaches in the system.
305 class MainPageJob : public BaseInternalsJob {
306 public:
307 MainPageJob(net::URLRequest* request, AppCacheService* service)
308 : BaseInternalsJob(request, service) {}
309
310 virtual void Start() {
311 DCHECK(request_);
312 info_collection_ = new AppCacheInfoCollection;
313 gotinfo_complete_callback_ =
314 new net::CancelableCompletionCallback<MainPageJob>(
315 this, &MainPageJob::OnGotInfoComplete);
316 appcache_service_->GetAllAppCacheInfo(
317 info_collection_, gotinfo_complete_callback_);
318 }
319
320 // Produces a page containing the listing
321 virtual bool GetData(std::string* mime_type,
322 std::string* charset,
323 std::string* out) const {
324 mime_type->assign("text/html");
325 charset->assign("UTF-8");
326
327 out->clear();
328 EmitPageStart(out);
329 if (!info_collection_.get()) {
330 out->append(kErrorMessage);
331 } else if (info_collection_->infos_by_origin.empty()) {
332 out->append(kEmptyAppCachesMessage);
333 } else {
334 typedef std::map<GURL, AppCacheInfoVector> InfoByOrigin;
335 AppCacheInfoVector appcaches;
336 for (InfoByOrigin::const_iterator origin =
337 info_collection_->infos_by_origin.begin();
338 origin != info_collection_->infos_by_origin.end(); ++origin) {
339 appcaches.insert(appcaches.end(),
340 origin->second.begin(), origin->second.end());
341 }
342 std::sort(appcaches.begin(), appcaches.end(), SortByManifestUrl);
343 EmitAppCacheInfoVector(appcache_service_, appcaches, out);
113 } 344 }
114 out->append("<br/>"); 345 EmitPageEnd(out);
115 DrawCommandButton(kRemoveAppCache, manifest_url_base64, out); 346 return true;
116 out->append("<ul>"); 347 }
117 348
118 AddLiTag(kSize, 349 private:
119 UTF16ToUTF8(FormatBytesUnlocalized(info->size)), 350 virtual ~MainPageJob() {
120 out); 351 if (gotinfo_complete_callback_)
121 AddLiTag(kCreationTime, 352 gotinfo_complete_callback_.release()->Cancel();
122 UTF16ToUTF8(TimeFormatFriendlyDateAndTime(info->creation_time)), 353 }
123 out); 354
124 AddLiTag(kLastAccessTime, 355 void OnGotInfoComplete(int rv) {
125 UTF16ToUTF8(TimeFormatFriendlyDateAndTime(info->last_access_time)), 356 gotinfo_complete_callback_ = NULL;
126 out); 357 if (rv != net::OK)
127 AddLiTag(kLastUpdateTime, 358 info_collection_ = NULL;
128 UTF16ToUTF8(TimeFormatFriendlyDateAndTime(info->last_update_time)), 359 StartAsync();
129 out); 360 }
130 361
131 out->append("</ul></p></br>"); 362 scoped_refptr<net::CancelableCompletionCallback<MainPageJob> >
132 } 363 gotinfo_complete_callback_;
133 } 364 scoped_refptr<AppCacheInfoCollection> info_collection_;
134 365 DISALLOW_COPY_AND_ASSIGN(MainPageJob);
135 std::string GetAppCacheManifestToRemove(const std::string& query) { 366 };
136 if (!StartsWithASCII(query, "remove=", true)) { 367
137 // Not a recognized format. 368 // Job that redirects back to the main appcache internals page.
138 return std::string(); 369 class RedirectToMainPageJob : public BaseInternalsJob {
139 }
140 std::string manifest_url_base64 = UnescapeURLComponent(
141 query.substr(strlen("remove=")),
142 UnescapeRule::NORMAL | UnescapeRule::URL_SPECIAL_CHARS);
143 std::string manifest_url;
144 base::Base64Decode(manifest_url_base64, &manifest_url);
145 return manifest_url;
146 }
147
148 struct ManifestURLComparator {
149 public: 370 public:
150 bool operator() ( 371 RedirectToMainPageJob(net::URLRequest* request, AppCacheService* service)
151 const appcache::AppCacheInfo& lhs, 372 : BaseInternalsJob(request, service) {}
152 const appcache::AppCacheInfo& rhs) const { 373
153 return (lhs.manifest_url.spec() < rhs.manifest_url.spec()); 374 virtual bool GetData(std::string* mime_type,
154 } 375 std::string* charset,
155 } manifest_url_comparator; 376 std::string* data) const {
156 377 return true; // IsRedirectResponse induces a redirect.
157 } // namespace 378 }
158 379
159 namespace appcache { 380 virtual bool IsRedirectResponse(GURL* location, int* http_status_code) {
160 381 *location = ClearQuery(request_->url());
161 ViewAppCacheInternalsJob::ViewAppCacheInternalsJob(
162 net::URLRequest* request,
163 AppCacheService* service)
164 : net::URLRequestSimpleJob(request),
165 appcache_service_(service) {
166 }
167
168 ViewAppCacheInternalsJob::~ViewAppCacheInternalsJob() {
169 // Cancel callback if job is destroyed before callback is called.
170 if (appcache_done_callback_)
171 appcache_done_callback_.release()->Cancel();
172 }
173
174 void ViewAppCacheInternalsJob::GetAppCacheInfoAsync() {
175 info_collection_ = new AppCacheInfoCollection;
176 appcache_done_callback_ =
177 new net::CancelableCompletionCallback<ViewAppCacheInternalsJob>(
178 this, &ViewAppCacheInternalsJob::AppCacheDone);
179 appcache_service_->GetAllAppCacheInfo(
180 info_collection_, appcache_done_callback_);
181 }
182
183 void ViewAppCacheInternalsJob::RemoveAppCacheInfoAsync(
184 const std::string& manifest_url_spec) {
185 appcache_done_callback_ =
186 new net::CancelableCompletionCallback<ViewAppCacheInternalsJob>(
187 this, &ViewAppCacheInternalsJob::AppCacheDone);
188
189 GURL manifest(manifest_url_spec);
190 appcache_service_->DeleteAppCacheGroup(
191 manifest, appcache_done_callback_);
192 }
193
194 void ViewAppCacheInternalsJob::Start() {
195 if (!request_)
196 return;
197
198 // Handle any remove appcache request, then redirect back to
199 // the same URL stripped of query parameters. The redirect happens as part
200 // of IsRedirectResponse().
201 if (request_->url().has_query()) {
202 std::string remove_appcache_manifest(
203 GetAppCacheManifestToRemove(request_->url().query()));
204
205 // Empty manifests are dealt with by the deleter.
206 RemoveAppCacheInfoAsync(remove_appcache_manifest);
207 } else {
208 GetAppCacheInfoAsync();
209 }
210 }
211
212 bool ViewAppCacheInternalsJob::IsRedirectResponse(
213 GURL* location, int* http_status_code) {
214 if (request_->url().has_query()) {
215 // Strip the query parameters.
216 GURL::Replacements replacements;
217 replacements.ClearQuery();
218 *location = request_->url().ReplaceComponents(replacements);
219 *http_status_code = 307; 382 *http_status_code = 307;
220 return true; 383 return true;
221 } 384 }
222 return false; 385 };
223 } 386
224 387 // Job that removes an appcache and then redirects back to the main page.
225 void ViewAppCacheInternalsJob::GenerateHTMLAppCacheInfo( 388 class RemoveAppCacheJob : public RedirectToMainPageJob {
226 std::string* out) const { 389 public:
227 typedef std::map<GURL, AppCacheInfoVector> InfoByOrigin; 390 RemoveAppCacheJob(
228 AppCacheInfoVector appcaches; 391 net::URLRequest* request, AppCacheService* service,
229 for (InfoByOrigin::const_iterator origin = 392 const GURL& manifest_url)
230 info_collection_->infos_by_origin.begin(); 393 : RedirectToMainPageJob(request, service),
231 origin != info_collection_->infos_by_origin.end(); ++origin) { 394 manifest_url_(manifest_url) {}
232 for (AppCacheInfoVector::const_iterator info = 395
233 origin->second.begin(); info != origin->second.end(); ++info) 396 virtual void Start() {
234 appcaches.push_back(*info); 397 DCHECK(request_);
235 } 398 delete_appcache_callback_ =
236 399 new net::CancelableCompletionCallback<RemoveAppCacheJob>(
237 std::sort(appcaches.begin(), appcaches.end(), manifest_url_comparator); 400 this, &RemoveAppCacheJob::OnDeleteAppCacheComplete);
238 401 appcache_service_->DeleteAppCacheGroup(
239 AddHTMLFromAppCacheToOutput(*appcache_service_, appcaches, out); 402 manifest_url_, delete_appcache_callback_);
240 } 403 }
241 404
242 void ViewAppCacheInternalsJob::AppCacheDone(int rv) { 405 private:
243 appcache_done_callback_ = NULL; 406 virtual ~RemoveAppCacheJob() {
244 if (rv != net::OK) 407 if (delete_appcache_callback_)
245 info_collection_ = NULL; 408 delete_appcache_callback_.release()->Cancel();
246 StartAsync(); 409 }
247 } 410
248 411 void OnDeleteAppCacheComplete(int rv) {
249 bool ViewAppCacheInternalsJob::GetData(std::string* mime_type, 412 delete_appcache_callback_ = NULL;
250 std::string* charset, 413 StartAsync(); // Causes the base class to redirect.
251 std::string* data) const { 414 }
252 mime_type->assign("text/html"); 415
253 charset->assign("UTF-8"); 416 GURL manifest_url_;
254 417 scoped_refptr<net::CancelableCompletionCallback<RemoveAppCacheJob> >
255 data->clear(); 418 delete_appcache_callback_;
256 StartHTML(data); 419 };
257 if (!info_collection_.get()) 420
258 data->append(kErrorMessage); 421
259 else if (info_collection_->infos_by_origin.empty()) 422 // Job shows the details of a particular manifest url.
260 data->append(kEmptyAppCachesMessage); 423 class ViewAppCacheJob : public BaseInternalsJob,
261 else 424 public AppCacheStorage::Delegate {
262 GenerateHTMLAppCacheInfo(data); 425 public:
263 EndHTML(data); 426 ViewAppCacheJob(
264 return true; 427 net::URLRequest* request, AppCacheService* service,
428 const GURL manifest_url)
429 : BaseInternalsJob(request, service),
430 manifest_url_(manifest_url) {}
431
432 virtual void Start() {
433 DCHECK(request_);
434 appcache_service_->storage()->LoadOrCreateGroup(manifest_url_, this);
435 }
436
437 // Produces a page containing the entries listing.
438 virtual bool GetData(std::string* mime_type,
439 std::string* charset,
440 std::string* out) const {
441 mime_type->assign("text/html");
442 charset->assign("UTF-8");
443 out->clear();
444 EmitPageStart(out);
445 if (appcache_info_.manifest_url.is_empty()) {
446 out->append(kManifestNotFoundMessage);
447 } else {
448 EmitAppCacheInfo(appcache_service_, &appcache_info_, out);
449 EmitAppCacheResourceInfoVector(ClearQuery(request_->url()),
450 manifest_url_,
451 resource_infos_, out);
452 }
453 EmitPageEnd(out);
454 return true;
455 }
456
457 private:
458 virtual ~ViewAppCacheJob() {
459 appcache_service_->storage()->CancelDelegateCallbacks(this);
460 }
461
462 // AppCacheStorage::Delegate override
463 virtual void OnGroupLoaded(
464 AppCacheGroup* group, const GURL& manifest_url) OVERRIDE {
465 DCHECK_EQ(manifest_url_, manifest_url);
466 if (group && group->newest_complete_cache()) {
467 appcache_info_.manifest_url = manifest_url;
468 appcache_info_.size = group->newest_complete_cache()->cache_size();
469 appcache_info_.creation_time = group->creation_time();
470 appcache_info_.last_update_time =
471 group->newest_complete_cache()->update_time();
472 appcache_info_.last_access_time = base::Time::Now();
473 group->newest_complete_cache()->ToResourceInfoVector(&resource_infos_);
474 std::sort(resource_infos_.begin(), resource_infos_.end(),
475 SortByResourceUrl);
476 }
477 StartAsync();
478 }
479
480 GURL manifest_url_;
481 AppCacheInfo appcache_info_;
482 AppCacheResourceInfoVector resource_infos_;
483 DISALLOW_COPY_AND_ASSIGN(ViewAppCacheJob);
484 };
485
486 // Job that shows the details of a particular cached resource.
487 class ViewEntryJob : public BaseInternalsJob,
488 public AppCacheStorage::Delegate {
489 public:
490 ViewEntryJob(
491 net::URLRequest* request, AppCacheService* service,
492 const GURL& manifest_url, const GURL& entry_url,
493 int64 response_id)
494 : BaseInternalsJob(request, service),
495 manifest_url_(manifest_url), entry_url_(entry_url),
496 response_id_(response_id), amount_read_(0),
497 ALLOW_THIS_IN_INITIALIZER_LIST(read_callback_(
498 this, &ViewEntryJob::OnReadComplete)) {}
499
500 virtual void Start() {
501 DCHECK(request_);
502 appcache_service_->storage()->LoadResponseInfo(
503 manifest_url_, response_id_, this);
504 }
505
506 // Produces a page containing the response headers and data.
507 virtual bool GetData(std::string* mime_type,
508 std::string* charset,
509 std::string* out) const {
510 mime_type->assign("text/html");
511 charset->assign("UTF-8");
512 out->clear();
513 EmitPageStart(out);
514 EmitAnchor(entry_url_.spec(), entry_url_.spec(), out);
515 if (response_info_) {
516 if (response_info_->http_response_info())
517 EmitResponseHeaders(response_info_->http_response_info()->headers, out);
518 else
519 out->append("Failed to read response headers.<br>");
520
521 if (response_data_) {
522 EmitHexDump(response_data_->data(), amount_read_,
523 response_info_->response_data_size(), out);
524 } else {
525 out->append("Failed to read response data.<br>");
526 }
527 } else {
528 out->append("Failed to read response headers and data.<br>");
529 }
530 EmitPageEnd(out);
531 return true;
532 }
533
534 private:
535 virtual ~ViewEntryJob() {
536 appcache_service_->storage()->CancelDelegateCallbacks(this);
537 }
538
539 virtual void OnResponseInfoLoaded(
540 AppCacheResponseInfo* response_info, int64 response_id) OVERRIDE {
541 if (!response_info) {
542 StartAsync();
543 return;
544 }
545 response_info_ = response_info;
546
547 // Read the response data, truncating if its too large.
548 const int64 kLimit = 100 * 1000;
549 int64 amount_to_read =
550 std::min(kLimit, response_info->response_data_size());
551 response_data_ = new net::IOBuffer(amount_to_read);
552
553 reader_.reset(appcache_service_->storage()->CreateResponseReader(
554 manifest_url_, response_id_));
555 reader_->ReadData(
556 response_data_, amount_to_read, &read_callback_);
557 }
558
559 void OnReadComplete(int result) {
560 reader_.reset();
561 amount_read_ = result;
562 if (result < 0)
563 response_data_ = NULL;
564 StartAsync();
565 }
566
567 GURL manifest_url_;
568 GURL entry_url_;
569 int64 response_id_;
570 scoped_refptr<AppCacheResponseInfo> response_info_;
571 scoped_refptr<net::IOBuffer> response_data_;
572 int amount_read_;
573 scoped_ptr<AppCacheResponseReader> reader_;
574 net::CompletionCallbackImpl<ViewEntryJob> read_callback_;
575 };
576
577 } // namespace
578
579 net::URLRequestJob* ViewAppCacheInternalsJobFactory::CreateJobForRequest(
580 net::URLRequest* request, AppCacheService* service) {
581 if (!request->url().has_query())
582 return new MainPageJob(request, service);
583
584 std::string command;
585 std::string param;
586 ParseQuery(request->url().query(), &command, &param);
587
588 if (command == kRemoveCacheCommand)
589 return new RemoveAppCacheJob(request, service,
590 DecodeBase64URL(param));
591
592 if (command == kViewCacheCommand)
593 return new ViewAppCacheJob(request, service,
594 DecodeBase64URL(param));
595
596 std::vector<std::string> tokens;
597 int64 response_id;
598 if (command == kViewEntryCommand &&
599 Tokenize(param, "|", &tokens) == 3u &&
600 base::StringToInt64(tokens[2], &response_id)) {
601 return new ViewEntryJob(request, service,
602 DecodeBase64URL(tokens[0]), // manifest url
603 DecodeBase64URL(tokens[1]), // entry url
604 response_id);
605 }
606
607 return new RedirectToMainPageJob(request, service);
265 } 608 }
266 609
267 } // namespace appcache 610 } // namespace appcache
OLDNEW
« no previous file with comments | « webkit/appcache/view_appcache_internals_job.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698