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

Unified Diff: chrome/browser/android/android_stream_reader_url_request_job.cc

Issue 10832034: Upstreaming AndroidProtocolAdapter. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 8 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/android/android_stream_reader_url_request_job.h ('k') | chrome/chrome_browser.gypi » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/android/android_stream_reader_url_request_job.cc
diff --git a/chrome/browser/android/android_stream_reader_url_request_job.cc b/chrome/browser/android/android_stream_reader_url_request_job.cc
new file mode 100644
index 0000000000000000000000000000000000000000..1c67b6922730f411ed49f9d93af5a5321a78df75
--- /dev/null
+++ b/chrome/browser/android/android_stream_reader_url_request_job.cc
@@ -0,0 +1,228 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/android/android_stream_reader_url_request_job.h"
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_string.h"
+#include "net/base/io_buffer.h"
+#include "net/base/mime_util.h"
+#include "net/base/net_errors.h"
+#include "net/base/net_util.h"
+#include "net/http/http_util.h"
+#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_context.h"
+#include "net/url_request/url_request_error_job.h"
+#include "net/url_request/url_request_file_job.h"
+#include "net/url_request/url_request_job_manager.h"
+// Disable "Warnings treated as errors" for input_stream_jni as it's a Java
+// system class and we have to generate C++ hooks for all methods in the class
+// even if they're unused.
+#pragma GCC diagnostic ignored "-Wunused-function"
+#include "jni/InputStream_jni.h"
+
+using base::android::AttachCurrentThread;
+using base::android::ClearException;
+using base::android::ConvertUTF8ToJavaString;
+using base::android::ScopedJavaGlobalRef;
+using base::android::ScopedJavaLocalRef;
+using JNI_InputStream::Java_InputStream_available;
+using JNI_InputStream::Java_InputStream_skip;
+using JNI_InputStream::Java_InputStream_read;
+
+
+namespace {
+
+// Maximum number of bytes to be read in a single read.
+const int kBufferSize = 4096;
+
+} // namespace
+
+AndroidStreamReaderURLRequestJob::AndroidStreamReaderURLRequestJob(
+ net::URLRequest* request,
+ scoped_ptr<Delegate> delegate)
+ : URLRequestJob(request, request->context()->network_delegate()),
+ delegate_(delegate.Pass()) {
+ DCHECK(delegate_.get());
+}
+
+AndroidStreamReaderURLRequestJob::~AndroidStreamReaderURLRequestJob() {
+}
+
+bool AndroidStreamReaderURLRequestJob::InitJNIBindings(JNIEnv* env) {
+ return JNI_InputStream::RegisterNativesImpl(env);
+}
+
+void AndroidStreamReaderURLRequestJob::Start() {
+ JNIEnv* env = AttachCurrentThread();
+ DCHECK(env);
+
+ stream_.Reset(env, delegate_->OpenInputStream(env, request()).obj());
+ if (!stream_.obj()) {
+ NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED,
+ net::ERR_FAILED));
+ return;
+ }
+
+ if (VerifyRequestedRange(env) && SkipToRequestedRange(env))
+ NotifyHeadersComplete();
+}
+
+bool AndroidStreamReaderURLRequestJob::VerifyRequestedRange(JNIEnv* env) {
+ int32_t size = Java_InputStream_available(env, stream_.obj());
+ if (ClearException(env)) {
+ NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED,
+ net::ERR_FAILED));
+ return false;
+ }
+
+ if (size <= 0)
+ return true;
+
+ // Check that the requested range was valid.
+ if (!byte_range_.ComputeBounds(size)) {
+ NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED,
+ net::ERR_REQUEST_RANGE_NOT_SATISFIABLE));
+ return false;
+ }
+
+ size = byte_range_.last_byte_position() -
+ byte_range_.first_byte_position() + 1;
+ DCHECK_GE(size, 0);
+ set_expected_content_size(size);
+
+ return true;
+}
+
+bool AndroidStreamReaderURLRequestJob::SkipToRequestedRange(JNIEnv* env) {
+ // Skip to the start of the requested data. This has to be done in a loop
+ // because the underlying InputStream is not guaranteed to skip the requested
+ // number of bytes.
+ if (byte_range_.first_byte_position() != 0) {
+ int64_t skipped, bytes_to_skip = byte_range_.first_byte_position();
+ do {
+ skipped = Java_InputStream_skip(env, stream_.obj(), bytes_to_skip);
+ if (ClearException(env)) {
+ NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED,
+ net::ERR_FAILED));
+ return false;
+ }
+ if (skipped <= 0) {
+ NotifyDone(
+ net::URLRequestStatus(net::URLRequestStatus::FAILED,
+ net::ERR_REQUEST_RANGE_NOT_SATISFIABLE));
+ return false;
+ }
+ } while ((bytes_to_skip -= skipped) > 0);
+ }
+ return true;
+}
+
+bool AndroidStreamReaderURLRequestJob::ReadRawData(net::IOBuffer* dest,
+ int dest_size,
+ int *bytes_read) {
+ DCHECK_NE(dest_size, 0);
+ DCHECK(bytes_read);
+ DCHECK(stream_.obj());
+
+ JNIEnv* env = AttachCurrentThread();
+ DCHECK(env);
+
+ if (!buffer_.obj()) {
+ // Allocate transfer buffer.
+ buffer_.Reset(env, env->NewByteArray(kBufferSize));
+ if (ClearException(env)) {
+ NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED,
+ net::ERR_FAILED));
+ return false;
+ }
+ }
+
+ jbyteArray buffer = buffer_.obj();
+ *bytes_read = 0;
+ if (!dest_size)
+ return true;
+
+ // Read data in multiples of the buffer size.
+ while (dest_size > 0) {
+ int read_size = std::min(dest_size, kBufferSize);
+ // TODO(skyostil): Make this non-blocking
+ int32_t byte_count =
+ Java_InputStream_read(env, stream_.obj(), buffer, 0, read_size);
+ if (byte_count <= 0) {
+ // net::URLRequestJob will call NotifyDone for us after the end of the
+ // file is reached.
+ break;
+ }
+
+ if (ClearException(env)) {
+ NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED,
+ net::ERR_FAILED));
+ return false;
+ }
+
+#ifndef NDEBUG
+ int32_t buffer_length = env->GetArrayLength(buffer);
+ DCHECK_GE(read_size, byte_count);
+ DCHECK_GE(buffer_length, byte_count);
+#endif // NDEBUG
+
+ // Copy the data over to the provided C++ side buffer.
+ DCHECK_GE(dest_size, byte_count);
+ env->GetByteArrayRegion(buffer, 0, byte_count,
+ reinterpret_cast<jbyte*>(dest->data() + *bytes_read));
+
+ if (ClearException(env)) {
+ NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED,
+ net::ERR_FAILED));
+ return false;
+ }
+
+ *bytes_read += byte_count;
+ dest_size -= byte_count;
+ }
+ return true;
+}
+
+bool AndroidStreamReaderURLRequestJob::GetMimeType(
+ std::string* mime_type) const {
+ JNIEnv* env = AttachCurrentThread();
+ DCHECK(env);
+
+ return delegate_->GetMimeType(env,
+ request(),
+ stream_.obj(),
+ mime_type);
+}
+
+bool AndroidStreamReaderURLRequestJob::GetCharset(
+ std::string* charset) {
+ JNIEnv* env = AttachCurrentThread();
+ DCHECK(env);
+
+ return delegate_->GetCharset(env,
+ request(),
+ stream_.obj(),
+ charset);
+}
+
+void AndroidStreamReaderURLRequestJob::SetExtraRequestHeaders(
+ const net::HttpRequestHeaders& headers) {
+ std::string range_header;
+ if (headers.GetHeader(net::HttpRequestHeaders::kRange, &range_header)) {
+ // We only care about "Range" header here.
+ std::vector<net::HttpByteRange> ranges;
+ if (net::HttpUtil::ParseRangeHeader(range_header, &ranges)) {
+ if (ranges.size() == 1) {
+ byte_range_ = ranges[0];
+ } else {
+ // We don't support multiple range requests in one single URL request,
+ // because we need to do multipart encoding here.
+ NotifyDone(net::URLRequestStatus(
+ net::URLRequestStatus::FAILED,
+ net::ERR_REQUEST_RANGE_NOT_SATISFIABLE));
+ }
+ }
+ }
+}
« no previous file with comments | « chrome/browser/android/android_stream_reader_url_request_job.h ('k') | chrome/chrome_browser.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698