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

Unified Diff: webkit/browser/appcache/appcache_url_request_job.cc

Issue 22314003: NavigationController prototype Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: NavController prototype - chrome side Created 7 years, 3 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 side-by-side diff with in-line comments
Download patch
Index: webkit/browser/appcache/appcache_url_request_job.cc
diff --git a/webkit/browser/appcache/appcache_url_request_job.cc b/webkit/browser/appcache/appcache_url_request_job.cc
index 077e09d8b99df3fc55de5c3edbeda80ebdf3602d..99915d860fdb9859549408d273fa080d2f3f19f7 100644
--- a/webkit/browser/appcache/appcache_url_request_job.cc
+++ b/webkit/browser/appcache/appcache_url_request_job.cc
@@ -12,6 +12,7 @@
#include "base/compiler_specific.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
#include "base/strings/stringprintf.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
@@ -26,9 +27,27 @@
#include "webkit/browser/appcache/appcache_histograms.h"
#include "webkit/browser/appcache/appcache_host.h"
#include "webkit/browser/appcache/appcache_service.h"
+#include "webkit/browser/blob/blob_reader.h"
+#include "webkit/browser/blob/blob_storage_controller.h"
namespace appcache {
+namespace {
+
+// Helper to make structs for synthesized responses
+net::HttpResponseInfo* MakeHttpResponseInfo(const std::string& raw_headers) {
+ net::HttpResponseInfo* info = new net::HttpResponseInfo;
+ info->request_time = base::Time::Now();
+ info->response_time = base::Time::Now();
+ info->was_cached = false;
+ info->headers = new net::HttpResponseHeaders(raw_headers);
+ std::string headers;
+ info->headers->GetNormalizedHeaders(&headers);
+ return info;
+}
+
+}
+
AppCacheURLRequestJob::AppCacheURLRequestJob(
net::URLRequest* request,
net::NetworkDelegate* network_delegate,
@@ -41,7 +60,8 @@ AppCacheURLRequestJob::AppCacheURLRequestJob(
delivery_type_(AWAITING_DELIVERY_ORDERS),
group_id_(0), cache_id_(kNoCacheId), is_fallback_(false),
cache_entry_not_found_(false),
- weak_factory_(this) {
+ weak_factory_(this),
+ is_main_resource_load_(false) {
DCHECK(storage_);
}
@@ -125,6 +145,11 @@ void AppCacheURLRequestJob::BeginDelivery() {
manifest_url_, group_id_, entry_.response_id(), this);
break;
+ case SYNTHESIZED_DELIVERY:
+ DCHECK(info_);
+ NotifyHeadersComplete();
+ break;
+
default:
NOTREACHED();
break;
@@ -134,11 +159,16 @@ void AppCacheURLRequestJob::BeginDelivery() {
void AppCacheURLRequestJob::BeginExecutableHandlerDelivery() {
DCHECK(CommandLine::ForCurrentProcess()->
HasSwitch(kEnableExecutableHandlers));
- if (!storage_->service()->handler_factory()) {
+ if (!storage_->service()->executable_handler_factory()) {
BeginErrorDelivery("missing handler factory");
return;
}
+ if (is_range_request()) {
+ BeginErrorDelivery("sorry, no support for range requests yet");
+ return;
+ }
+
request()->net_log().AddEvent(
net::NetLog::TYPE_APPCACHE_DELIVERING_EXECUTABLE_RESPONSE);
@@ -166,6 +196,14 @@ void AppCacheURLRequestJob::OnCacheLoaded(AppCache* cache, int64 cache_id) {
cache_ = cache;
group_ = cache->owning_group();
+ // Detect odd ball cases where we want to return the resource instead of
+ // executing the script. If it's an exact match for the resource, just return it.
+ if (cache_->GetEntry(request()->url())) {
+ entry_.clear_types(AppCacheEntry::EXECUTABLE);
+ delivery_type_ = APPCACHED_DELIVERY;
+ BeginDelivery();
+ return;
+ }
// If the handler is spun up, ask it to compute a response.
AppCacheExecutableHandler* handler =
cache->GetExecutableHandler(entry_.response_id());
@@ -202,11 +240,11 @@ void AppCacheURLRequestJob::OnExecutableSourceLoaded(int result) {
return;
}
- handler_source_buffer_->SetCapacity(result); // Free up some memory.
+ std::string raw_handler_source(handler_source_buffer_->data(), result);
+ handler_source_buffer_ = NULL; // Free up some memory.
AppCacheExecutableHandler* handler = cache_->GetOrCreateExecutableHandler(
- entry_.response_id(), handler_source_buffer_.get());
- handler_source_buffer_ = NULL; // not needed anymore
+ entry_.response_id(), raw_handler_source);
if (handler) {
InvokeExecutableHandler(handler);
return;
@@ -217,8 +255,21 @@ void AppCacheURLRequestJob::OnExecutableSourceLoaded(int result) {
void AppCacheURLRequestJob::InvokeExecutableHandler(
AppCacheExecutableHandler* handler) {
+ net::URLRequest* req = request();
+
+ AppCacheExecutableHandler::Request request;
+ request.url = req->url();
+ request.is_main_resource_load = is_main_resource_load_;
+ request.method = req->method();
+ request.referrer = req->referrer();
+ net::HttpRequestHeaders headers;
+ req->GetFullRequestHeaders(&headers);
+ net::HttpRequestHeaders::Iterator iter(headers);
+ while (iter.GetNext())
+ request.headers.insert(make_pair(iter.name(), iter.value()));
+
handler->HandleRequest(
- request(),
+ request,
base::Bind(&AppCacheURLRequestJob::OnExecutableResponseCallback,
weak_factory_.GetWeakPtr()));
}
@@ -226,26 +277,67 @@ void AppCacheURLRequestJob::InvokeExecutableHandler(
void AppCacheURLRequestJob::OnExecutableResponseCallback(
const AppCacheExecutableHandler::Response& response) {
DCHECK(!has_been_killed());
- if (response.use_network) {
+
+ // Support for .respondWithNetwork(id)
+ if (response.use_default) {
delivery_type_ = NETWORK_DELIVERY;
storage_ = NULL;
BeginDelivery();
return;
}
- if (!response.cached_resource_url.is_empty()) {
- AppCacheEntry* entry_ptr = cache_->GetEntry(response.cached_resource_url);
- if (entry_ptr && !entry_ptr->IsExecutable()) {
- entry_ = *entry_ptr;
- BeginDelivery();
- return;
+ // Support for .respondWith(blob) and .redirectTo(locataion);
+ if (response.status_code) {
+ // TODO(michaeln): synthesize a response with the response_code and
+ // the blob as the body.
+ webkit_blob::BlobStorageController* blob_storage =
+ storage_->service()->executable_handler_factory()->GetBlobStorageController();
+ fileapi::FileSystemContext* filesystem_context =
+ storage_->service()->executable_handler_factory()->GetFileSystemContext();
+
+ scoped_refptr<webkit_blob::BlobData> blob_data;
+ if (!response.blob_id.empty())
+ blob_data = blob_storage->GetBlobDataFromUrl(GURL(response.blob_id));
+
+ std::string raw_headers = base::StringPrintf(
+ "HTTP/1.0 %d %S", response.status_code, UTF16ToWide(response.status_text).data());
+ raw_headers.append(1, '\0');
+
+ // TODO(alecflett): content_type is totally messy because blob has
+ // a content type, as does the response body itself. Further, the
+ // response header may have additional information on it like
+ // 'text/html; charset=utf-8' - this code drastically simplifies
+ // by simply using the blob if they don't match.
+ string16 content_type;
+ for (std::map<string16, string16>::const_iterator iter = response.headers.begin();
+ iter != response.headers.end();
+ ++iter) {
+ if (LowerCaseEqualsASCII(iter->first, "content-type"))
+ content_type = iter->second;
+ else {
+ raw_headers.append(base::StringPrintf("%s: %s", UTF16ToUTF8(iter->first).data(), UTF16ToUTF8(iter->second).data()));
+ raw_headers.append(1, '\0');
+ }
}
- }
-
- if (!response.redirect_url.is_empty()) {
- // TODO(michaeln): playback a redirect
- // response_headers_(new HttpResponseHeaders(response_headers)),
- // fallthru for now to deliver an error
+ if (blob_data) {
+ if (content_type.empty())
+ content_type = UTF8ToUTF16(blob_data->content_type());
+ if (!EqualsASCII(content_type, blob_data->content_type()))
+ LOG(WARNING) << "Blob and header content types don't match, using " <<
+ content_type << ". (blob is " << blob_data->content_type() << " but header is " << content_type << ")";
+ raw_headers.append(base::StringPrintf(
+ "Content-Type: %s", UTF16ToUTF8(content_type).data()));
+
+ raw_headers.append(1, '\0');
+ // TODO: content-length header too
+ blob_reader_.reset(new webkit_blob::BlobReader(
+ blob_data.get(), filesystem_context));
+ }
+ raw_headers.append(2, '\0');
+ info_ = new AppCacheResponseInfo(
+ manifest_url_, MakeHttpResponseInfo(raw_headers), 0);
+ BeginSynthesizedDelivery();
+ return;
}
// Otherwise, return an error.
@@ -260,6 +352,12 @@ void AppCacheURLRequestJob::BeginErrorDelivery(const char* message) {
BeginDelivery();
}
+void AppCacheURLRequestJob::BeginSynthesizedDelivery() {
+ delivery_type_ = SYNTHESIZED_DELIVERY;
+ storage_ = NULL;
+ BeginDelivery();
+}
+
AppCacheURLRequestJob::~AppCacheURLRequestJob() {
if (storage_)
storage_->CancelDelegateCallbacks(this);
@@ -381,7 +479,8 @@ net::LoadState AppCacheURLRequestJob::GetLoadState() const {
return net::LOAD_STATE_IDLE;
if (!has_delivery_orders())
return net::LOAD_STATE_WAITING_FOR_APPCACHE;
- if (delivery_type_ != APPCACHED_DELIVERY)
+ if (delivery_type_ != APPCACHED_DELIVERY &&
+ delivery_type_ != SYNTHESIZED_DELIVERY)
return net::LOAD_STATE_IDLE;
if (!info_.get())
return net::LOAD_STATE_WAITING_FOR_APPCACHE;
@@ -416,9 +515,21 @@ int AppCacheURLRequestJob::GetResponseCode() const {
bool AppCacheURLRequestJob::ReadRawData(net::IOBuffer* buf, int buf_size,
int *bytes_read) {
- DCHECK(is_delivering_appcache_response());
+ DCHECK(is_delivering_appcache_response() ||
+ is_delivering_synthesized_response());
DCHECK_NE(buf_size, 0);
DCHECK(bytes_read);
+
+ // Branch to return a 'blob' response provided by an exe handler.
+ if (blob_reader_)
+ return ReadRawBlobData(buf, buf_size, bytes_read);
+
+ if (!reader_) {
+ // No raw data to read, an empty response body.
+ *bytes_read = 0;
+ return true;
+ }
+
DCHECK(!reader_->IsReadPending());
reader_->ReadData(
buf, buf_size, base::Bind(&AppCacheURLRequestJob::OnReadComplete,
@@ -427,6 +538,36 @@ bool AppCacheURLRequestJob::ReadRawData(net::IOBuffer* buf, int buf_size,
return false;
}
+bool AppCacheURLRequestJob::ReadRawBlobData(net::IOBuffer* buf, int buf_size,
+ int *bytes_read) {
+ DCHECK(is_delivering_synthesized_response());
+ DCHECK_NE(buf_size, 0);
+ DCHECK(bytes_read);
+
+ int rv = blob_reader_->Read(
+ buf, buf_size, base::Bind(&AppCacheURLRequestJob::OnReadBlobDataComplete,
+ base::Unretained(this)));
+ SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0));
+ if (rv != net::ERR_IO_PENDING) {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(&AppCacheURLRequestJob::OnReadBlobDataComplete,
+ weak_factory_.GetWeakPtr(), rv));
+ }
+ return false;
+}
+
+void AppCacheURLRequestJob::OnReadBlobDataComplete(int result) {
+ DCHECK(is_delivering_synthesized_response());
+ if (result == 0)
+ NotifyDone(net::URLRequestStatus());
+ else if (result < 0)
+ NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, result));
+ else
+ SetStatus(net::URLRequestStatus()); // Clear the IO_PENDING status
+ NotifyReadComplete(result);
+}
+
+
void AppCacheURLRequestJob::SetExtraRequestHeaders(
const net::HttpRequestHeaders& headers) {
std::string value;
« no previous file with comments | « webkit/browser/appcache/appcache_url_request_job.h ('k') | webkit/browser/appcache/view_appcache_internals_job.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698