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

Side by Side Diff: webkit/glue/resource_handle_win.cc

Issue 7419: Move many files that were suffixed Win.cpp to Chromium.cpp, and place them in... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 12 years, 2 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/glue/resource_handle_impl.cc ('k') | webkit/glue/webframe_impl.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 //
5 // This file replaces WebCore/platform/network/win/ResourceHandleWin.cpp with a
6 // platform-neutral implementation that simply defers almost entirely to
7 // ResouceLoaderBridge.
8 //
9 // This uses the same ResourceHandle.h header file that the rest of WebKit
10 // uses, allowing us to avoid complicated changes. Our specific things are
11 // added on ResourceHandleInternal. The ResourceHandle owns the
12 // ResourceHandleInternal and passes off almost all processing to it.
13 //
14 // The WebKit version of this code keeps the ResourceHandle AddRef'd when
15 // there are any callbacks. This prevents the callbacks from occuring into
16 // destroyed objects. However, our destructors should always stop callbacks
17 // from happening, making this (hopefully) unnecessary.
18 //
19 // We preserve this behavior for safety. A client could count on this behavior
20 // and fire off a request, release it, and wait for callbacks to get the data
21 // as long as it doesn't care about canceling the request. Although this is
22 // dumb, we support it. We use pending_ to indicate this extra AddRef, which
23 // is done in start() and released in OnCompletedRequest.
24
25 #include "config.h"
26
27 #pragma warning(push, 0)
28 #include "CString.h"
29 #include "Console.h"
30 #include "DocLoader.h"
31 #include "DOMWindow.h"
32 #include "FormData.h"
33 #include "FrameLoader.h"
34 #include "LogWin.h"
35 #include "Page.h"
36 #include "ResourceError.h"
37 #include "ResourceHandle.h"
38 #include "ResourceHandleClient.h"
39 #include "ResourceRequest.h"
40 #include "ResourceResponse.h"
41 #pragma warning(pop)
42
43 #undef LOG
44 #include "base/logging.h"
45 #include "base/message_loop.h"
46 #include "base/process_util.h"
47 #include "base/time.h"
48 #include "base/string_util.h"
49 #include "base/string_tokenizer.h"
50 #include "webkit/glue/feed_preview.h"
51 #include "webkit/glue/glue_util.h"
52 #include "webkit/glue/multipart_response_delegate.h"
53 #include "webkit/glue/resource_loader_bridge.h"
54 #include "webkit/glue/webframe_impl.h"
55 #include "net/base/data_url.h"
56 #include "net/base/net_errors.h"
57 #include "net/base/net_util.h"
58 #include "net/base/load_flags.h"
59
60 using webkit_glue::ResourceLoaderBridge;
61 using net::HttpResponseHeaders;
62
63 namespace {
64
65 // Extracts the information from a data: url.
66 bool GetInfoFromDataUrl(const GURL& url,
67 ResourceLoaderBridge::ResponseInfo* info,
68 std::string* data, URLRequestStatus* status) {
69 std::string mime_type;
70 std::string charset;
71 if (net::DataURL::Parse(url, &mime_type, &charset, data)) {
72 info->request_time = Time::Now();
73 info->response_time = Time::Now();
74 info->mime_type.swap(mime_type);
75 info->charset.swap(charset);
76 *status = URLRequestStatus(URLRequestStatus::SUCCESS, 0);
77 return true;
78 }
79
80 *status = URLRequestStatus(URLRequestStatus::FAILED, net::ERR_INVALID_URL);
81 return false;
82 }
83
84 } // namespace
85
86 namespace WebCore {
87
88 static void ExtractInfoFromHeaders(const HttpResponseHeaders* headers,
89 HTTPHeaderMap* header_map,
90 int* status_code,
91 String* status_text,
92 long long* expected_content_length) {
93 *status_code = headers->response_code();
94
95 // Set the status text
96 *status_text = webkit_glue::StdStringToString(headers->GetStatusText());
97
98 // Set the content length.
99 std::string length_val;
100 if (headers->EnumerateHeader(NULL, "content-length", &length_val))
101 *expected_content_length = StringToInt64(length_val);
102
103 // Build up the header map. Take care with duplicate headers.
104 void* iter = NULL;
105 std::string name, value;
106 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
107 String name_str = webkit_glue::StdStringToString(name);
108 String value_str = webkit_glue::StdStringToString(value);
109
110 pair<HTTPHeaderMap::iterator, bool> result =
111 header_map->add(name_str, value_str);
112 if (!result.second)
113 result.first->second += ", " + value_str;
114 }
115 }
116
117 static ResourceResponse MakeResourceResponse(
118 const KURL& kurl,
119 const ResourceLoaderBridge::ResponseInfo& info) {
120 int status_code = 0;
121 long long expected_content_length = info.content_length;
122 String status_text;
123 HTTPHeaderMap header_map;
124
125 // It's okay if there are no headers
126 if (info.headers)
127 ExtractInfoFromHeaders(info.headers,
128 &header_map,
129 &status_code,
130 &status_text,
131 &expected_content_length);
132
133 // TODO(darin): We should leverage HttpResponseHeaders for this, and this
134 // should be using the same code as ResourceDispatcherHost.
135 std::wstring suggested_filename;
136 if (info.headers) {
137 std::string disp_val;
138 if (info.headers->EnumerateHeader(NULL, "content-disposition", &disp_val)) {
139 suggested_filename = net::GetSuggestedFilename(
140 webkit_glue::KURLToGURL(kurl), disp_val, std::wstring());
141 }
142 }
143
144 ResourceResponse response(kurl,
145 webkit_glue::StdStringToString(info.mime_type),
146 expected_content_length,
147 webkit_glue::StdStringToString(info.charset),
148 webkit_glue::StdWStringToString(suggested_filename));
149
150 if (info.headers) {
151 Time time_val;
152 if (info.headers->GetLastModifiedValue(&time_val))
153 response.setLastModifiedDate(time_val.ToTimeT());
154
155 // Compute expiration date
156 TimeDelta freshness_lifetime =
157 info.headers->GetFreshnessLifetime(info.response_time);
158 if (freshness_lifetime != TimeDelta()) {
159 Time now = Time::Now();
160 TimeDelta current_age =
161 info.headers->GetCurrentAge(info.request_time, info.response_time,
162 now);
163 time_val = now + freshness_lifetime - current_age;
164
165 response.setExpirationDate(time_val.ToTimeT());
166 } else {
167 // WebKit uses 0 as a special expiration date that means never expire.
168 // 1 is a small enough value to let it always expire.
169 response.setExpirationDate(1);
170 }
171 }
172
173 response.setHTTPStatusCode(status_code);
174 response.setHTTPStatusText(status_text);
175 response.setSecurityInfo(webkit_glue::StdStringToCString(info.security_info));
176
177 // WebKit doesn't provide a way for us to set expected content length after
178 // calling the constructor, so we parse the headers first and then swap in
179 // our HTTP header map. Ideally we would like a setter for expected content
180 // length (perhaps by abstracting ResourceResponse interface into
181 // ResourceResponseBase) but that would require forking.
182 const_cast<HTTPHeaderMap*>(&response.httpHeaderFields())->swap(header_map);
183
184 return response;
185 }
186
187 class ResourceHandleInternal : public ResourceLoaderBridge::Peer {
188 public:
189 ResourceHandleInternal(ResourceHandle* job, const ResourceRequest& r,
190 ResourceHandleClient* c);
191 ~ResourceHandleInternal();
192
193 // If the response parameter is null, then an asynchronous load is started.
194 bool Start(ResourceLoaderBridge::SyncLoadResponse* response);
195
196 // Used to cancel an asynchronous load.
197 void Cancel();
198
199 // Used to suspend/resume an asynchronous load.
200 void SetDefersLoading(bool value);
201
202 // ResourceLoaderBridge::Peer implementation
203 virtual void OnReceivedRedirect(const GURL& new_url);
204 virtual void OnReceivedResponse(
205 const ResourceLoaderBridge::ResponseInfo& info,
206 bool content_filtered);
207 virtual void OnReceivedData(const char* data, int len);
208 virtual void OnCompletedRequest(const URLRequestStatus& status);
209 virtual std::string GetURLForDebugging();
210
211 // Handles a data: url internally instead of calling the bridge.
212 void HandleDataUrl();
213
214 // This is the bridge implemented by the embedder.
215 // The bridge is kept alive as long as the request is valid and we
216 // are ready for callbacks.
217 scoped_ptr<ResourceLoaderBridge> bridge_;
218
219 // The resource loader that owns us
220 ResourceHandle* job_;
221
222 // This is the object that receives various status messages (such as when the
223 // loader has received data). See definition for the exact messages that are
224 // sent to it.
225 ResourceHandleClient* client_;
226
227 ResourceRequest request_;
228
229 // Runnable Method Factory used to invoke later HandleDataUrl().
230 ScopedRunnableMethodFactory<ResourceHandleInternal> data_url_factory_;
231
232 int load_flags_;
233
234 private:
235 // Set to true when we're waiting for data from the bridge, also indicating
236 // we have addrefed our job.
237 bool pending_;
238
239 // Expected content length of the response
240 long long expected_content_length_;
241
242 // NULL unless we are handling a multipart/x-mixed-replace request
243 scoped_ptr<MultipartResponseDelegate> multipart_delegate_;
244
245 // NULL unless we are handling a feed:// request.
246 scoped_ptr<FeedClientProxy> feed_client_proxy_;
247 };
248
249 ResourceHandleInternal::ResourceHandleInternal(ResourceHandle* job,
250 const ResourceRequest& r,
251 ResourceHandleClient* c)
252 : job_(job),
253 client_(c),
254 request_(r),
255 MSVC_SUPPRESS_WARNING(4355) // can use this
256 data_url_factory_(this),
257 load_flags_(net::LOAD_NORMAL),
258 pending_(false),
259 expected_content_length_(-1),
260 multipart_delegate_(NULL) {
261 }
262
263 ResourceHandleInternal::~ResourceHandleInternal() {
264 DCHECK(!pending_);
265 }
266
267 void ResourceHandleInternal::HandleDataUrl() {
268 ResourceLoaderBridge::ResponseInfo info;
269 URLRequestStatus status;
270 std::string data;
271
272 if (GetInfoFromDataUrl(webkit_glue::KURLToGURL(request_.url()), &info, &data,
273 &status)) {
274 OnReceivedResponse(info, false);
275
276 if (data.size())
277 OnReceivedData(data.c_str(), data.size());
278 }
279
280 OnCompletedRequest(status);
281
282 // We are done using the object. ResourceHandle and ResourceHandleInternal
283 // might be destroyed now.
284 job_->deref();
285 }
286
287 bool ResourceHandleInternal::Start(
288 ResourceLoaderBridge::SyncLoadResponse* sync_load_response) {
289 DCHECK(!bridge_.get());
290
291 // The WebFrame is the Frame's FrameWinClient
292 WebFrameImpl* webframe =
293 request_.frame() ? WebFrameImpl::FromFrame(request_.frame()) : NULL;
294
295 CString method = request_.httpMethod().latin1();
296 GURL referrer(webkit_glue::StringToStdString(request_.httpReferrer()));
297
298 // Compute the URL of the load.
299 GURL url = webkit_glue::KURLToGURL(request_.url());
300 if (url.SchemeIs("feed:")) {
301 // Feed URLs are special, they actually mean "http".
302 url_canon::Replacements<char> replacements;
303 replacements.SetScheme("http", url_parse::Component(0, 4));
304 url = url.ReplaceComponents(replacements);
305
306 // Replace our client with a client that understands previewing feeds
307 // and forwards the feeds along to the original client.
308 feed_client_proxy_.reset(new FeedClientProxy(client_));
309 client_ = feed_client_proxy_.get();
310 }
311
312 // Inherit the policy URL from the request's frame. However, if the request
313 // is for a main frame, the current document's policyBaseURL is the old
314 // document, so we leave policyURL empty to indicate that the request is a
315 // first-party request.
316 GURL policy_url;
317 if (request_.resourceType() != ResourceType::MAIN_FRAME &&
318 request_.frame() && request_.frame()->document()) {
319 policy_url = GURL(webkit_glue::StringToStdString(
320 request_.frame()->document()->policyBaseURL()));
321 }
322
323 // Translate the table of request headers to a formatted string blob
324 String headerBuf;
325 const HTTPHeaderMap& headerMap = request_.httpHeaderFields();
326
327 // In some cases, WebCore doesn't add an Accept header, but not having the
328 // header confuses some web servers. See bug 808613.
329 // Note: headerMap uses case-insenstive keys, so this will find Accept as
330 // as well.
331 if (!headerMap.contains("accept"))
332 request_.addHTTPHeaderField("Accept", "*/*");
333
334 const String crlf("\r\n");
335 const String sep(": ");
336 for (HTTPHeaderMap::const_iterator it = headerMap.begin();
337 it != headerMap.end(); ++it) {
338 // Skip over referrer headers found in the header map because we already
339 // pulled it out as a separate parameter. We likewise prune the UA since
340 // that will be added back by the network layer.
341 if (equalIgnoringCase((*it).first, "referer") ||
342 equalIgnoringCase((*it).first, "user-agent"))
343 continue;
344 // WinInet dies if blank headers are set. TODO(darin): Is this still an
345 // issue now that we are using WinHTTP?
346 if ((*it).first.isEmpty()) {
347 webframe->frame()->domWindow()->console()->addMessage(
348 JSMessageSource,
349 ErrorMessageLevel,
350 "Refused to set blank header",
351 1,
352 String());
353 continue;
354 }
355 if (!headerBuf.isEmpty())
356 headerBuf.append(crlf);
357 headerBuf.append((*it).first + sep + (*it).second);
358 }
359
360 switch (request_.cachePolicy()) {
361 case ReloadIgnoringCacheData:
362 // Required by LayoutTests/http/tests/misc/refresh-headers.php
363 load_flags_ |= net::LOAD_VALIDATE_CACHE;
364 break;
365 case ReturnCacheDataElseLoad:
366 load_flags_ |= net::LOAD_PREFERRING_CACHE;
367 break;
368 case ReturnCacheDataDontLoad:
369 load_flags_ |= net::LOAD_ONLY_FROM_CACHE;
370 break;
371 case UseProtocolCachePolicy:
372 break;
373 }
374
375 // TODO(jcampan): in the non out-of-process plugin case the request does not
376 // have a origin_pid. Find a better place to set this.
377 int origin_pid = request_.originPid();
378 if (origin_pid == 0)
379 origin_pid = process_util::GetCurrentProcId();
380
381 bool mixed_content =
382 webkit_glue::KURLToGURL(request_.mainDocumentURL()).SchemeIsSecure() &&
383 !url.SchemeIsSecure();
384
385 if (url.SchemeIs("data")) {
386 if (sync_load_response) {
387 // This is a sync load. Do the work now.
388 sync_load_response->url = url;
389 std::string data;
390 GetInfoFromDataUrl(sync_load_response->url, sync_load_response,
391 &sync_load_response->data,
392 &sync_load_response->status);
393 } else {
394 pending_ = true;
395 job_->ref(); // to be released when we get a OnCompletedRequest.
396 job_->ref(); // to be released when HandleDataUrl is completed.
397 MessageLoop::current()->PostTask(FROM_HERE,
398 data_url_factory_.NewRunnableMethod(
399 &ResourceHandleInternal::HandleDataUrl));
400 }
401 return true;
402 }
403
404 // TODO(darin): is latin1 really correct here? It is if the strings are
405 // already ASCII (i.e., if they are already escaped properly).
406 // TODO(brettw) this should take parameter encoding into account when
407 // creating the GURLs.
408 bridge_.reset(ResourceLoaderBridge::Create(
409 webframe,
410 webkit_glue::CStringToStdString(method),
411 url,
412 policy_url,
413 referrer,
414 webkit_glue::CStringToStdString(headerBuf.latin1()),
415 load_flags_,
416 origin_pid,
417 request_.resourceType(),
418 mixed_content));
419 if (!bridge_.get())
420 return false;
421
422 if (request_.httpBody()) {
423 // GET and HEAD requests shouldn't have http bodies.
424 DCHECK(method != "GET" && method != "HEAD");
425 const Vector<FormDataElement>& elements = request_.httpBody()->elements();
426 size_t n = elements.size();
427 for (size_t i = 0; i < n; ++i) {
428 const FormDataElement& e = elements[static_cast<unsigned>(i)];
429 if (e.m_type == FormDataElement::data) {
430 if (e.m_data.size() > 0) {
431 // WebKit sometimes gives up empty data to append. These aren't
432 // necessary so we just optimize those out here.
433 bridge_->AppendDataToUpload(e.m_data.data(),
434 static_cast<int>(e.m_data.size()));
435 }
436 } else {
437 bridge_->AppendFileToUpload(
438 webkit_glue::StringToStdWString(e.m_filename));
439 }
440 }
441 }
442
443 if (sync_load_response) {
444 bridge_->SyncLoad(sync_load_response);
445 return true;
446 }
447
448 bool rv = bridge_->Start(this);
449 if (rv) {
450 pending_ = true;
451 job_->ref(); // to be released when we get a OnCompletedRequest.
452 } else {
453 bridge_.reset();
454 }
455
456 return rv;
457 }
458
459 void ResourceHandleInternal::Cancel() {
460 // The bridge will still send OnCompletedRequest, which will deref() us,
461 // so we don't do that here.
462 if (bridge_.get())
463 bridge_->Cancel();
464
465 // Ensure that we do not notify the multipart delegate anymore as it has
466 // its own pointer to the client.
467 multipart_delegate_.reset();
468
469 // Do not make any further calls to the client.
470 client_ = NULL;
471 }
472
473 void ResourceHandleInternal::SetDefersLoading(bool value) {
474 if (bridge_.get())
475 bridge_->SetDefersLoading(value);
476 }
477
478 // ResourceLoaderBridge::Peer impl --------------------------------------------
479
480 void ResourceHandleInternal::OnReceivedRedirect(const GURL& new_url) {
481 DCHECK(pending_);
482
483 KURL url = webkit_glue::GURLToKURL(new_url);
484
485 // TODO(darin): need a way to properly initialize a ResourceResponse
486 ResourceResponse response(request_.url(), String(), -1, String(), String());
487
488 ResourceRequest new_request(url);
489
490 // TODO(darin): we need to setup new_request to reflect the fact that we
491 // for example drop the httpBody when following a POST request that is
492 // redirected to a GET request.
493
494 if (client_)
495 client_->willSendRequest(job_, new_request, response);
496
497 //
498 // TODO(darin): since new_request is sent as a mutable reference, it is
499 // possible that willSendRequest may expect to be able to modify it.
500 //
501 // andresca on #webkit confirms that that is intentional, so we'll need
502 // to rework the ResourceLoaderBridge to give us control over what URL
503 // is really loaded (and with what headers) when a redirect is encountered.
504 //
505
506 request_ = new_request;
507 }
508
509 void ResourceHandleInternal::OnReceivedResponse(
510 const ResourceLoaderBridge::ResponseInfo& info,
511 bool content_filtered) {
512 DCHECK(pending_);
513
514 // TODO(darin): need a way to properly initialize a ResourceResponse
515 ResourceResponse response = MakeResourceResponse(request_.url(), info);
516 response.setIsContentFiltered(content_filtered);
517
518 expected_content_length_ = response.expectedContentLength();
519
520 if (client_)
521 client_->didReceiveResponse(job_, response);
522
523 // we may have been cancelled after didReceiveResponse, which would leave us
524 // without a client and therefore without much need to do multipart handling.
525
526 DCHECK(!multipart_delegate_.get());
527 if (client_ && info.headers && response.isMultipart()) {
528 std::string content_type;
529 info.headers->EnumerateHeader(NULL, "content-type", &content_type);
530
531 std::string boundary = net::GetHeaderParamValue(content_type, "boundary");
532 TrimString(boundary, " \"", &boundary);
533 // If there's no boundary, just handle the request normally. In the gecko
534 // code, nsMultiMixedConv::OnStartRequest throws an exception.
535 if (!boundary.empty()) {
536 multipart_delegate_.reset(new MultipartResponseDelegate(client_, job_,
537 response, boundary));
538 }
539 }
540
541 // TODO(darin): generate willCacheResponse callback. debug mac webkit to
542 // determine when it should be called.
543 }
544
545 void ResourceHandleInternal::OnReceivedData(const char* data, int data_len) {
546 DCHECK(pending_);
547
548 if (client_) {
549 // TODO(darin): figure out what to pass for lengthReceived. from reading
550 // the loader code, it looks like this is supposed to be the content-length
551 // value, but it seems really wacky to include that here! we have to debug
552 // webkit on mac to figure out what this should be.
553
554 // TODO(jackson): didReceiveData expects an int, but an expected content
555 // length is an int64, so we do our best to fit it inside an int. The only
556 // code that cares currently about this value is the Inspector, so beware
557 // that the Inspector's network panel might under-represent the size of
558 // some resources if they're larger than a gigabyte.
559 int lengthReceived = static_cast<int>(expected_content_length_);
560 if (lengthReceived != expected_content_length_) // overflow occurred
561 lengthReceived = -1;
562
563 if (!multipart_delegate_.get()) {
564 client_->didReceiveData(job_, data, data_len, lengthReceived);
565 } else {
566 // AddData will make the appropriate calls to client_->didReceiveData
567 // and client_->didReceiveResponse
568 multipart_delegate_->OnReceivedData(data, data_len);
569 }
570 }
571 }
572
573 void ResourceHandleInternal::OnCompletedRequest(
574 const URLRequestStatus& status) {
575 if (multipart_delegate_.get()) {
576 multipart_delegate_->OnCompletedRequest();
577 multipart_delegate_.reset(NULL);
578 }
579
580 pending_ = false;
581
582 if (client_) {
583 if (status.status() != URLRequestStatus::SUCCESS) {
584 int error_code;
585 if (status.status() == URLRequestStatus::HANDLED_EXTERNALLY) {
586 // By marking this request as aborted we insure that we don't navigate
587 // to an error page.
588 error_code = net::ERR_ABORTED;
589 } else {
590 error_code = status.os_error();
591 }
592 // TODO(tc): fill in these fields properly
593 ResourceError error(net::kErrorDomain,
594 error_code,
595 request_.url().string(),
596 String() /*localized description*/);
597 client_->didFail(job_, error);
598 } else {
599 client_->didFinishLoading(job_);
600 }
601 }
602
603 job_->deref(); // may destroy our owner and hence |this|
604 }
605
606 std::string ResourceHandleInternal::GetURLForDebugging() {
607 return webkit_glue::CStringToStdString(request_.url().string().latin1());
608 }
609
610 // ResourceHandle -------------------------------------------------------------
611
612 ResourceHandle::ResourceHandle(const ResourceRequest& request,
613 ResourceHandleClient* client,
614 bool defersLoading,
615 bool shouldContentSniff,
616 bool mightDownloadFromHandle)
617 MSVC_SUPPRESS_WARNING(4355) // it's okay to pass |this| here!
618 : d(new ResourceHandleInternal(this, request, client)) {
619 // TODO(darin): figure out what to do with the two bool params
620 }
621
622 PassRefPtr<ResourceHandle> ResourceHandle::create(const ResourceRequest& request ,
623 ResourceHandleClient* client,
624 Frame* deprecated,
625 bool defersLoading,
626 bool shouldContentSniff,
627 bool mightDownloadFromHandle) {
628 RefPtr<ResourceHandle> newHandle =
629 adoptRef(new ResourceHandle(request, client, defersLoading,
630 shouldContentSniff, mightDownloadFromHandle));
631
632 if (newHandle->start(NULL))
633 return newHandle.release();
634
635 return NULL;
636 }
637
638 const ResourceRequest& ResourceHandle::request() const {
639 return d->request_;
640 }
641
642 ResourceHandleClient* ResourceHandle::client() const {
643 return d->client_;
644 }
645
646 void ResourceHandle::setClient(ResourceHandleClient* client) {
647 d->client_ = client;
648 }
649
650 void ResourceHandle::setDefersLoading(bool value) {
651 d->SetDefersLoading(value);
652 }
653
654 bool ResourceHandle::start(Frame* deprecated) {
655 return d->Start(NULL);
656 }
657
658 void ResourceHandle::clearAuthentication() {
659 // TODO(darin): do something here. it looks like the ResourceLoader calls
660 // this method when it is canceled. i have no idea why it does this.
661 }
662
663 void ResourceHandle::cancel() {
664 d->Cancel();
665 }
666
667 ResourceHandle::~ResourceHandle() {
668 }
669
670 PassRefPtr<SharedBuffer> ResourceHandle::bufferedData() {
671 return NULL;
672 }
673
674 /*static*/ bool ResourceHandle::loadsBlocked() {
675 return false; // this seems to be related to sync XMLHttpRequest...
676 }
677
678 /*static*/ bool ResourceHandle::supportsBufferedData() {
679 return false; // the loader will buffer manually if it needs to
680 }
681
682 /*static*/ void ResourceHandle::loadResourceSynchronously(
683 const ResourceRequest& request, ResourceError& error,
684 ResourceResponse& response, Vector<char>& data, Frame*) {
685
686 RefPtr<ResourceHandle> handle =
687 new ResourceHandle(request, NULL, false, false, false);
688
689 ResourceLoaderBridge::SyncLoadResponse sync_load_response;
690 if (!handle->d->Start(&sync_load_response)) {
691 response =
692 ResourceResponse(request.url(), String(), 0, String(), String());
693 // TODO(darin): what should the error code really be?
694 error = ResourceError(net::kErrorDomain,
695 net::ERR_FAILED,
696 request.url().string(),
697 String() /* localized description */);
698 return;
699 }
700
701 KURL kurl = webkit_glue::GURLToKURL(sync_load_response.url);
702
703 // TODO(tc): For file loads, we may want to include a more descriptive
704 // status code or status text.
705 const URLRequestStatus::Status& status = sync_load_response.status.status();
706 if (status != URLRequestStatus::SUCCESS &&
707 status != URLRequestStatus::HANDLED_EXTERNALLY) {
708 response = ResourceResponse(kurl, String(), 0, String(), String());
709 error = ResourceError(net::kErrorDomain,
710 sync_load_response.status.os_error(),
711 kurl.string(),
712 String() /* localized description */);
713 return;
714 }
715
716 response = MakeResourceResponse(kurl, sync_load_response);
717
718 data.clear();
719 data.append(sync_load_response.data.data(),
720 sync_load_response.data.size());
721 }
722
723 // static
724 bool ResourceHandle::willLoadFromCache(ResourceRequest& request) {
725 //
726 // This method is used to determine if a POST request can be repeated from
727 // cache, but you cannot really know until you actually try to read from the
728 // cache. Even if we checked now, something else could come along and wipe
729 // out the cache entry by the time we fetch it.
730 //
731 // So, we always say yes here, which allows us to generate an ERR_CACHE_MISS
732 // if the request cannot be serviced from cache. We force the 'DontLoad'
733 // cache policy at this point to ensure that we never hit the network for
734 // this request.
735 //
736 DCHECK(request.httpMethod() == "POST");
737 request.setCachePolicy(ReturnCacheDataDontLoad);
738 return true;
739 }
740
741 } // namespace WebCore
742
OLDNEW
« no previous file with comments | « webkit/glue/resource_handle_impl.cc ('k') | webkit/glue/webframe_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698