summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorboliu@chromium.org <boliu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-12-05 06:05:31 +0000
committerboliu@chromium.org <boliu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-12-05 06:05:31 +0000
commitc347c436757c3e37179854861107e1de9ee510a3 (patch)
tree9baca4c051d9f66355927066f4ceeb1cf8eceaba
parentc8a26f18938cc35ab25e9992c2b61326804af346 (diff)
downloadchromium_src-c347c436757c3e37179854861107e1de9ee510a3.zip
chromium_src-c347c436757c3e37179854861107e1de9ee510a3.tar.gz
chromium_src-c347c436757c3e37179854861107e1de9ee510a3.tar.bz2
(Re)implement Android WebView downloads
Current plan for Android WebView downloads is to only support existing DownloadListener API. This is a very simple API that cancels all Chromium side downloads and passes the request information to the listener. This independence from Chrome on Android's more sophisticated implementation (support Http POST downloads etc) will allow the Chrome impelmentation to be refactored more cleanly. BUG= Android only change. Ran through Android trybots. NOTRY=true Review URL: https://chromiumcodereview.appspot.com/11418301 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@171180 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--android_webview/android_webview.gyp6
-rw-r--r--android_webview/browser/aw_browser_context.cc5
-rw-r--r--android_webview/browser/aw_browser_context.h6
-rw-r--r--android_webview/browser/aw_content_browser_client.cc6
-rw-r--r--android_webview/browser/aw_contents_io_thread_client.h11
-rw-r--r--android_webview/browser/aw_download_manager_delegate.cc43
-rw-r--r--android_webview/browser/aw_download_manager_delegate.h36
-rw-r--r--android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc37
-rw-r--r--android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.h9
-rw-r--r--android_webview/java/src/org/chromium/android_webview/AwContents.java47
-rw-r--r--android_webview/java/src/org/chromium/android_webview/AwContentsClient.java7
-rw-r--r--android_webview/java/src/org/chromium/android_webview/AwContentsIoThreadClient.java7
-rw-r--r--android_webview/javatests/src/org/chromium/android_webview/test/AndroidWebViewTestBase.java2
-rw-r--r--android_webview/javatests/src/org/chromium/android_webview/test/AwContentsTest.java46
-rw-r--r--android_webview/javatests/src/org/chromium/android_webview/test/NullContentsClient.java8
-rw-r--r--android_webview/javatests/src/org/chromium/android_webview/test/TestAwContentsClient.java19
-rw-r--r--android_webview/native/aw_contents_io_thread_client_impl.cc30
-rw-r--r--android_webview/native/aw_contents_io_thread_client_impl.h5
18 files changed, 318 insertions, 12 deletions
diff --git a/android_webview/android_webview.gyp b/android_webview/android_webview.gyp
index 086523a..b49863a 100644
--- a/android_webview/android_webview.gyp
+++ b/android_webview/android_webview.gyp
@@ -57,6 +57,8 @@
'browser/aw_contents_io_thread_client.h',
'browser/aw_cookie_access_policy.cc',
'browser/aw_cookie_access_policy.h',
+ 'browser/aw_download_manager_delegate.cc',
+ 'browser/aw_download_manager_delegate.h',
'browser/aw_http_auth_handler_base.cc',
'browser/aw_http_auth_handler_base.h',
'browser/aw_login_delegate.cc',
@@ -78,11 +80,11 @@
'browser/net/aw_url_request_context_getter.h',
'browser/net/aw_url_request_job_factory.cc',
'browser/net/aw_url_request_job_factory.h',
+ 'browser/net_disk_cache_remover.cc',
+ 'browser/net_disk_cache_remover.h',
'browser/net/init_native_callback.h',
'browser/net/input_stream_reader.cc',
'browser/net/input_stream_reader.h',
- 'browser/net_disk_cache_remover.cc',
- 'browser/net_disk_cache_remover.h',
'browser/renderer_host/aw_render_view_host_ext.cc',
'browser/renderer_host/aw_render_view_host_ext.h',
'browser/renderer_host/aw_resource_dispatcher_host_delegate.cc',
diff --git a/android_webview/browser/aw_browser_context.cc b/android_webview/browser/aw_browser_context.cc
index cfdb350..c476fe8 100644
--- a/android_webview/browser/aw_browser_context.cc
+++ b/android_webview/browser/aw_browser_context.cc
@@ -70,10 +70,7 @@ content::ResourceContext* AwBrowserContext::GetResourceContext() {
content::DownloadManagerDelegate*
AwBrowserContext::GetDownloadManagerDelegate() {
- // TODO(boliu): Implement intercepting downloads for DownloadListener and
- // maybe put a NOTREACHED if it is indeed never needed.
- NOTIMPLEMENTED();
- return NULL;
+ return &download_manager_delegate_;
}
content::GeolocationPermissionContext*
diff --git a/android_webview/browser/aw_browser_context.h b/android_webview/browser/aw_browser_context.h
index edbafa0..d184cde 100644
--- a/android_webview/browser/aw_browser_context.h
+++ b/android_webview/browser/aw_browser_context.h
@@ -5,10 +5,10 @@
#ifndef ANDROID_WEBVIEW_BROWSER_AW_BROWSER_CONTEXT_H_
#define ANDROID_WEBVIEW_BROWSER_AW_BROWSER_CONTEXT_H_
-#include "content/public/browser/browser_context.h"
-
+#include "android_webview/browser/aw_download_manager_delegate.h"
#include "base/file_path.h"
#include "base/memory/ref_counted.h"
+#include "content/public/browser/browser_context.h"
namespace android_webview {
@@ -52,6 +52,8 @@ class AwBrowserContext : public content::BrowserContext {
scoped_refptr<AwURLRequestContextGetter> url_request_context_getter_;
+ AwDownloadManagerDelegate download_manager_delegate_;
+
DISALLOW_COPY_AND_ASSIGN(AwBrowserContext);
};
diff --git a/android_webview/browser/aw_content_browser_client.cc b/android_webview/browser/aw_content_browser_client.cc
index 62f92ec..e897a79 100644
--- a/android_webview/browser/aw_content_browser_client.cc
+++ b/android_webview/browser/aw_content_browser_client.cc
@@ -302,7 +302,11 @@ void AwContentBrowserClient::ClearCookies(content::RenderViewHost* rvh) {
}
FilePath AwContentBrowserClient::GetDefaultDownloadDirectory() {
- NOTREACHED() << "Android WebView does not use chromium downloads";
+ // Android WebView does not currently use the Chromium downloads system.
+ // Download requests are cancelled immedately when recognized; see
+ // AwResourceDispatcherHost::CreateResourceHandlerForDownload. However the
+ // download system still tries to start up and calls this before recognizing
+ // the request has been cancelled.
return FilePath();
}
diff --git a/android_webview/browser/aw_contents_io_thread_client.h b/android_webview/browser/aw_contents_io_thread_client.h
index fad8a1a..9edab2d 100644
--- a/android_webview/browser/aw_contents_io_thread_client.h
+++ b/android_webview/browser/aw_contents_io_thread_client.h
@@ -5,6 +5,8 @@
#ifndef ANDROID_WEBVIEW_BROWSER_AW_CONTENTS_IO_THREAD_CLIENT_H_
#define ANDROID_WEBVIEW_BROWSER_AW_CONTENTS_IO_THREAD_CLIENT_H_
+#include <string>
+
#include "base/memory/scoped_ptr.h"
class GURL;
@@ -72,6 +74,15 @@ class AwContentsIoThreadClient {
// Retrieve the BlockNetworkLoads setting value of this AwContents.
// This method is called on the IO thread only.
virtual bool ShouldBlockNetworkLoads() const = 0;
+
+ // Called when ResourceDispathcerHost detects a download request.
+ // The download is already cancelled when this is called, since
+ // relevant for DownloadListener is already extracted.
+ virtual void NewDownload(const GURL& url,
+ const std::string& user_agent,
+ const std::string& content_disposition,
+ const std::string& mime_type,
+ int64 content_length) = 0;
};
} // namespace android_webview
diff --git a/android_webview/browser/aw_download_manager_delegate.cc b/android_webview/browser/aw_download_manager_delegate.cc
new file mode 100644
index 0000000..9eca137
--- /dev/null
+++ b/android_webview/browser/aw_download_manager_delegate.cc
@@ -0,0 +1,43 @@
+// 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 "android_webview/browser/aw_download_manager_delegate.h"
+
+#include "base/file_path.h"
+#include "content/public/browser/download_danger_type.h"
+#include "content/public/browser/download_item.h"
+
+
+namespace android_webview {
+
+AwDownloadManagerDelegate::~AwDownloadManagerDelegate() {}
+
+bool AwDownloadManagerDelegate::DetermineDownloadTarget(
+ content::DownloadItem* item,
+ const content::DownloadTargetCallback& callback) {
+ // Note this cancel is independent of the URLRequest cancel in
+ // AwResourceDispatcherHostDelegate::DownloadStarting. The request
+ // could have already finished by the time DownloadStarting is called.
+ callback.Run(FilePath() /* Empty file path for cancel */,
+ content::DownloadItem::TARGET_DISPOSITION_OVERWRITE,
+ content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
+ FilePath());
+ return true;
+}
+
+bool AwDownloadManagerDelegate::ShouldCompleteDownload(
+ content::DownloadItem* item,
+ const base::Closure& complete_callback) {
+ NOTREACHED();
+ return true;
+}
+
+bool AwDownloadManagerDelegate::ShouldOpenDownload(
+ content::DownloadItem* item,
+ const content::DownloadOpenDelayedCallback& callback) {
+ NOTREACHED();
+ return true;
+}
+
+} // namespace android_webview
diff --git a/android_webview/browser/aw_download_manager_delegate.h b/android_webview/browser/aw_download_manager_delegate.h
new file mode 100644
index 0000000..3ddddc7
--- /dev/null
+++ b/android_webview/browser/aw_download_manager_delegate.h
@@ -0,0 +1,36 @@
+// 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.
+
+#ifndef ANDROID_WEBVIEW_BROWSER_AW_DOWNLOAD_MANAGER_DELEGATE_H_
+#define ANDROID_WEBVIEW_BROWSER_AW_DOWNLOAD_MANAGER_DELEGATE_H_
+
+#include "content/public/browser/download_manager_delegate.h"
+
+namespace content {
+class DownloadItem;
+} // namespace content
+
+namespace android_webview {
+
+// Android WebView does not use Chromium downloads, so implement methods here to
+// unconditionally cancel the download.
+class AwDownloadManagerDelegate : public content::DownloadManagerDelegate {
+ public:
+ virtual ~AwDownloadManagerDelegate();
+
+ // content::DownloadManagerDelegate implementation.
+ virtual bool DetermineDownloadTarget(
+ content::DownloadItem* item,
+ const content::DownloadTargetCallback& callback) OVERRIDE;
+ virtual bool ShouldCompleteDownload(
+ content::DownloadItem* item,
+ const base::Closure& complete_callback) OVERRIDE;
+ virtual bool ShouldOpenDownload(
+ content::DownloadItem* item,
+ const content::DownloadOpenDelayedCallback& callback) OVERRIDE;
+};
+
+} // anemspace android_webview
+
+#endif // ANDROID_WEBVIEW_BROWSER_AW_DOWNLOAD_MANAGER_DELEGATE_H_
diff --git a/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc b/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc
index fcabd97..db605c3 100644
--- a/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc
+++ b/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc
@@ -4,6 +4,8 @@
#include "android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.h"
+#include <string>
+
#include "android_webview/browser/aw_contents_io_thread_client.h"
#include "android_webview/browser/aw_login_delegate.h"
#include "android_webview/common/url_constants.h"
@@ -228,6 +230,41 @@ void AwResourceDispatcherHostDelegate::RequestBeginning(
}
}
+void AwResourceDispatcherHostDelegate::DownloadStarting(
+ net::URLRequest* request,
+ content::ResourceContext* resource_context,
+ int child_id,
+ int route_id,
+ int request_id,
+ bool is_content_initiated,
+ ScopedVector<content::ResourceThrottle>* throttles) {
+ GURL url(request->url());
+ std::string user_agent;
+ std::string content_disposition;
+ std::string mime_type;
+ int64 content_length = request->GetExpectedContentSize();
+
+ request->GetResponseHeaderByName("content-disposition", &content_disposition);
+ request->extra_request_headers().GetHeader(
+ net::HttpRequestHeaders::kUserAgent, &user_agent);
+ request->GetResponseHeaderByName("mime-type", &mime_type);
+
+ request->Cancel();
+
+ scoped_ptr<AwContentsIoThreadClient> io_client =
+ AwContentsIoThreadClient::FromID(child_id, route_id);
+
+ // POST request cannot be repeated in general, so prevent client from
+ // retrying the same request, even if it is with a GET.
+ if ("GET" == request->method() && io_client) {
+ io_client->NewDownload(url,
+ user_agent,
+ content_disposition,
+ mime_type,
+ content_length);
+ }
+}
+
bool AwResourceDispatcherHostDelegate::AcceptAuthRequest(
net::URLRequest* request,
net::AuthChallengeInfo* auth_info) {
diff --git a/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.h b/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.h
index 48ab0a5..3a80a37 100644
--- a/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.h
+++ b/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.h
@@ -34,6 +34,15 @@ class AwResourceDispatcherHostDelegate
bool is_continuation_of_transferred_request,
ScopedVector<content::ResourceThrottle>* throttles) OVERRIDE;
+ virtual void DownloadStarting(
+ net::URLRequest* request,
+ content::ResourceContext* resource_context,
+ int child_id,
+ int route_id,
+ int request_id,
+ bool is_content_initiated,
+ ScopedVector<content::ResourceThrottle>* throttles) OVERRIDE;
+
virtual bool AcceptAuthRequest(net::URLRequest* request,
net::AuthChallengeInfo* auth_info) OVERRIDE;
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContents.java b/android_webview/java/src/org/chromium/android_webview/AwContents.java
index 4eb823d..19f3f52 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwContents.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java
@@ -101,6 +101,26 @@ public class AwContents {
private CleanupReference mCleanupReference;
+ private static class DownloadInfo {
+ final String mUrl;
+ final String mUserAgent;
+ final String mContentDisposition;
+ final String mMimeType;
+ final long mContentLength;
+
+ DownloadInfo(String url,
+ String userAgent,
+ String contentDisposition,
+ String mimeType,
+ long contentLength) {
+ mUrl = url;
+ mUserAgent = userAgent;
+ mContentDisposition = contentDisposition;
+ mMimeType = mimeType;
+ mContentLength = contentLength;
+ }
+ }
+
// This class is responsible for calling certain client callbacks on the UI thread. Most
// callbacks do no go through here, but get forwarded to AwContentsClient directly.
// The messages processed here may originate from the IO or UI thread.
@@ -108,6 +128,7 @@ public class AwContents {
private class ClientCallbackHandler extends Handler {
public static final int MSG_ON_LOAD_RESOURCE = 1;
public static final int MSG_ON_PAGE_STARTED = 2;
+ public static final int MSG_ON_DOWNLOAD_START = 3;
@Override
public void handleMessage(Message msg) {
@@ -122,6 +143,15 @@ public class AwContents {
AwContents.this.mContentsClient.onPageStarted(url);
break;
}
+ case MSG_ON_DOWNLOAD_START: {
+ DownloadInfo info = (DownloadInfo)msg.obj;
+ AwContents.this.mContentsClient.onDownloadStart(info.mUrl,
+ info.mUserAgent,
+ info.mContentDisposition,
+ info.mMimeType,
+ info.mContentLength);
+ break;
+ }
default:
throw new IllegalStateException(
"IoThreadClientHandler: unhandled message " + msg.what);
@@ -164,6 +194,23 @@ public class AwContents {
public boolean shouldBlockNetworkLoads() {
return AwContents.this.mSettings.getBlockNetworkLoads();
}
+
+ @Override
+ public void onDownloadStart(String url,
+ String userAgent,
+ String contentDisposition,
+ String mimeType,
+ long contentLength) {
+ DownloadInfo info = new DownloadInfo(url,
+ userAgent,
+ contentDisposition,
+ mimeType,
+ contentLength);
+ mClientCallbackHandler.sendMessage(
+ mClientCallbackHandler.obtainMessage(
+ ClientCallbackHandler.MSG_ON_DOWNLOAD_START,
+ info));
+ }
}
private class InterceptNavigationDelegateImpl implements InterceptNavigationDelegate {
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContentsClient.java b/android_webview/java/src/org/chromium/android_webview/AwContentsClient.java
index 3da0d6f..b5f153b 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwContentsClient.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwContentsClient.java
@@ -203,10 +203,15 @@ public abstract class AwContentsClient extends ContentViewClient {
public abstract void onFormResubmission(Message dontResend, Message resend);
+ // TODO(boliu): Make this abstract.
+ public void onDownloadStart(String url, String userAgent, String contentDisposition,
+ String mimeType, long contentLength) {
+ }
+
protected abstract void handleJsAlert(String url, String message, JsResultReceiver receiver);
protected abstract void handleJsBeforeUnload(String url, String message,
- JsResultReceiver receiver);
+ JsResultReceiver receiver);
protected abstract void handleJsConfirm(String url, String message, JsResultReceiver receiver);
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContentsIoThreadClient.java b/android_webview/java/src/org/chromium/android_webview/AwContentsIoThreadClient.java
index 284f0fc..bdbc1b2 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwContentsIoThreadClient.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwContentsIoThreadClient.java
@@ -29,4 +29,11 @@ public interface AwContentsIoThreadClient {
@CalledByNative
public boolean shouldBlockNetworkLoads();
+
+ @CalledByNative
+ public void onDownloadStart(String url,
+ String userAgent,
+ String contentDisposition,
+ String mimeType,
+ long contentLength);
}
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AndroidWebViewTestBase.java b/android_webview/javatests/src/org/chromium/android_webview/test/AndroidWebViewTestBase.java
index cd9802e..a4388a3 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AndroidWebViewTestBase.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AndroidWebViewTestBase.java
@@ -282,7 +282,7 @@ public class AndroidWebViewTestBase
@Override
public boolean isSatisfied() {
try {
- return runTestOnUiThreadAndGetResult(callable);
+ return runTestOnUiThreadAndGetResult(callable);
} catch (Throwable e) {
return false;
}
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsTest.java
index 0955ccc..a120279a 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsTest.java
@@ -26,9 +26,10 @@ import org.chromium.net.test.util.TestWebServer;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.Callable;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
import java.util.List;
/**
@@ -212,4 +213,47 @@ public class AwContentsTest extends AndroidWebViewTestBase {
if (webServer != null) webServer.shutdown();
}
}
+
+ public void testDownload() throws Throwable {
+ AwTestContainerView testView = createAwTestContainerViewOnMainSync(mContentsClient);
+ AwContents awContents = testView.getAwContents();
+
+ // TODO(boliu): This is to work around disk cache corruption bug on
+ // unclean shutdown (crbug.com/154805).
+ clearCacheOnUiThread(awContents, true);
+
+ final String data = "download data";
+ final String contentDisposition = "attachment;filename=\"download.txt\"";
+ final String mimeType = "text/plain";
+
+ List<Pair<String, String>> downloadHeaders = new ArrayList<Pair<String, String>>();
+ downloadHeaders.add(Pair.create("Content-Disposition", contentDisposition));
+ downloadHeaders.add(Pair.create("Mime-Type", mimeType));
+ downloadHeaders.add(Pair.create("Content-Length", Integer.toString(data.length())));
+
+ TestWebServer webServer = null;
+ try {
+ webServer = new TestWebServer(false);
+ final String pageUrl = webServer.setResponse(
+ "/download.txt", data, downloadHeaders);
+ loadUrlSync(awContents, mContentsClient.getOnPageFinishedHelper(), pageUrl);
+
+ assertTrue(pollOnUiThread(new Callable<Boolean>() {
+ @Override
+ public Boolean call() {
+ // Assert failures are treated as return false.
+ assertEquals(pageUrl, mContentsClient.mLastDownloadUrl);
+ assertEquals(contentDisposition,
+ mContentsClient.mLastDownloadContentDisposition);
+ assertEquals(mimeType,
+ mContentsClient.mLastDownloadMimeType);
+ assertEquals(data.length(),
+ mContentsClient.mLastDownloadContentLength);
+ return true;
+ }
+ }));
+ } finally {
+ if (webServer != null) webServer.shutdown();
+ }
+ }
}
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/NullContentsClient.java b/android_webview/javatests/src/org/chromium/android_webview/test/NullContentsClient.java
index 5a44943..51d3bd1 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/NullContentsClient.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/NullContentsClient.java
@@ -92,6 +92,14 @@ class NullContentsClient extends AwContentsClient {
}
@Override
+ public void onDownloadStart(String url,
+ String userAgent,
+ String contentDisposition,
+ String mimeType,
+ long contentLength) {
+ }
+
+ @Override
public boolean onCreateWindow(boolean isDialog, boolean isUserGesture) {
return false;
}
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/TestAwContentsClient.java b/android_webview/javatests/src/org/chromium/android_webview/test/TestAwContentsClient.java
index 1ba193e..8905034 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/TestAwContentsClient.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/TestAwContentsClient.java
@@ -130,4 +130,23 @@ class TestAwContentsClient extends NullContentsClient {
return mSourceId;
}
}
+
+ String mLastDownloadUrl;
+ String mLastDownloadUserAgent;
+ String mLastDownloadContentDisposition;
+ String mLastDownloadMimeType;
+ long mLastDownloadContentLength;
+
+ @Override
+ public void onDownloadStart(String url,
+ String userAgent,
+ String contentDisposition,
+ String mimeType,
+ long contentLength) {
+ mLastDownloadUrl = url;
+ mLastDownloadUserAgent = userAgent;
+ mLastDownloadContentDisposition = contentDisposition;
+ mLastDownloadMimeType = mimeType;
+ mLastDownloadContentLength = contentLength;
+ }
}
diff --git a/android_webview/native/aw_contents_io_thread_client_impl.cc b/android_webview/native/aw_contents_io_thread_client_impl.cc
index 75a8615..682bcaf 100644
--- a/android_webview/native/aw_contents_io_thread_client_impl.cc
+++ b/android_webview/native/aw_contents_io_thread_client_impl.cc
@@ -238,6 +238,36 @@ bool AwContentsIoThreadClientImpl::ShouldBlockNetworkLoads() const {
env, java_object_.obj());
}
+void AwContentsIoThreadClientImpl::NewDownload(
+ const GURL& url,
+ const std::string& user_agent,
+ const std::string& content_disposition,
+ const std::string& mime_type,
+ int64 content_length) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (java_object_.is_null())
+ return;
+
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jstring> jstring_url =
+ ConvertUTF8ToJavaString(env, url.spec());
+ ScopedJavaLocalRef<jstring> jstring_user_agent =
+ ConvertUTF8ToJavaString(env, user_agent);
+ ScopedJavaLocalRef<jstring> jstring_content_disposition =
+ ConvertUTF8ToJavaString(env, content_disposition);
+ ScopedJavaLocalRef<jstring> jstring_mime_type =
+ ConvertUTF8ToJavaString(env, mime_type);
+
+ Java_AwContentsIoThreadClient_onDownloadStart(
+ env,
+ java_object_.obj(),
+ jstring_url.obj(),
+ jstring_user_agent.obj(),
+ jstring_content_disposition.obj(),
+ jstring_mime_type.obj(),
+ content_length);
+}
+
bool RegisterAwContentsIoThreadClientImpl(JNIEnv* env) {
return RegisterNativesImpl(env);
}
diff --git a/android_webview/native/aw_contents_io_thread_client_impl.h b/android_webview/native/aw_contents_io_thread_client_impl.h
index 92fce24..861851b 100644
--- a/android_webview/native/aw_contents_io_thread_client_impl.h
+++ b/android_webview/native/aw_contents_io_thread_client_impl.h
@@ -43,6 +43,11 @@ class AwContentsIoThreadClientImpl : public AwContentsIoThreadClient {
virtual bool ShouldBlockContentUrls() const OVERRIDE;
virtual bool ShouldBlockFileUrls() const OVERRIDE;
virtual bool ShouldBlockNetworkLoads() const OVERRIDE;
+ virtual void NewDownload(const GURL& url,
+ const std::string& user_agent,
+ const std::string& content_disposition,
+ const std::string& mime_type,
+ int64 content_length) OVERRIDE;
private:
base::android::ScopedJavaGlobalRef<jobject> java_object_;