mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-02-02 12:17:15 +01:00
Add a new CefBrowserHost::StartDownload method for starting a download that can then be handled via CefDownloadHandler (issue #883).
git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@1100 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
parent
d65179c135
commit
7f3d1ccf78
1
cef.gyp
1
cef.gyp
@ -247,6 +247,7 @@
|
||||
'tests/unittests/dialog_unittest.cc',
|
||||
'tests/unittests/display_unittest.cc',
|
||||
'tests/unittests/dom_unittest.cc',
|
||||
'tests/unittests/download_unittest.cc',
|
||||
'tests/unittests/geolocation_unittest.cc',
|
||||
'tests/unittests/jsdialog_unittest.cc',
|
||||
'tests/unittests/navigation_unittest.cc',
|
||||
|
@ -298,6 +298,12 @@ typedef struct _cef_browser_host_t {
|
||||
const cef_string_t* default_file_name, cef_string_list_t accept_types,
|
||||
struct _cef_run_file_dialog_callback_t* callback);
|
||||
|
||||
///
|
||||
// Download the file at |url| using cef_download_handler_t.
|
||||
///
|
||||
void (CEF_CALLBACK *start_download)(struct _cef_browser_host_t* self,
|
||||
const cef_string_t* url);
|
||||
|
||||
///
|
||||
// Returns true (1) if window rendering is disabled.
|
||||
///
|
||||
|
@ -339,6 +339,12 @@ class CefBrowserHost : public virtual CefBase {
|
||||
const std::vector<CefString>& accept_types,
|
||||
CefRefPtr<CefRunFileDialogCallback> callback) =0;
|
||||
|
||||
///
|
||||
// Download the file at |url| using CefDownloadHandler.
|
||||
///
|
||||
/*--cef()--*/
|
||||
virtual void StartDownload(const CefString& url) =0;
|
||||
|
||||
///
|
||||
// Returns true if window rendering is disabled.
|
||||
///
|
||||
|
@ -29,6 +29,8 @@
|
||||
#include "base/bind_helpers.h"
|
||||
#include "content/browser/renderer_host/render_view_host_impl.h"
|
||||
#include "content/browser/web_contents/web_contents_impl.h"
|
||||
#include "content/public/browser/download_manager.h"
|
||||
#include "content/public/browser/download_url_parameters.h"
|
||||
#include "content/public/browser/native_web_keyboard_event.h"
|
||||
#include "content/public/browser/navigation_controller.h"
|
||||
#include "content/public/browser/navigation_entry.h"
|
||||
@ -555,6 +557,35 @@ void CefBrowserHostImpl::RunFileDialog(
|
||||
base::Bind(&CefRunFileDialogCallbackWrapper::Callback, wrapper));
|
||||
}
|
||||
|
||||
void CefBrowserHostImpl::StartDownload(const CefString& url) {
|
||||
if (!CEF_CURRENTLY_ON_UIT()) {
|
||||
CEF_POST_TASK(CEF_UIT,
|
||||
base::Bind(&CefBrowserHostImpl::StartDownload, this, url));
|
||||
return;
|
||||
}
|
||||
|
||||
GURL gurl = GURL(url.ToString());
|
||||
if (gurl.is_empty() || !gurl.is_valid())
|
||||
return;
|
||||
|
||||
if (!web_contents())
|
||||
return;
|
||||
|
||||
CefBrowserContext* context = _Context->browser_context();
|
||||
if (!context)
|
||||
return;
|
||||
|
||||
scoped_refptr<content::DownloadManager> manager =
|
||||
content::BrowserContext::GetDownloadManager(context);
|
||||
if (!manager)
|
||||
return;
|
||||
|
||||
scoped_ptr<content::DownloadUrlParameters> params;
|
||||
params.reset(
|
||||
content::DownloadUrlParameters::FromWebContents(web_contents(), gurl));
|
||||
manager->DownloadUrl(params.Pass());
|
||||
}
|
||||
|
||||
bool CefBrowserHostImpl::IsWindowRenderingDisabled() {
|
||||
return IsWindowRenderingDisabled(window_info_);
|
||||
}
|
||||
|
@ -124,6 +124,7 @@ class CefBrowserHostImpl : public CefBrowserHost,
|
||||
const CefString& default_file_name,
|
||||
const std::vector<CefString>& accept_types,
|
||||
CefRefPtr<CefRunFileDialogCallback> callback) OVERRIDE;
|
||||
virtual void StartDownload(const CefString& url) OVERRIDE;
|
||||
virtual bool IsWindowRenderingDisabled() OVERRIDE;
|
||||
virtual void WasResized() OVERRIDE;
|
||||
virtual void Invalidate(const CefRect& dirtyRect,
|
||||
|
@ -262,6 +262,23 @@ void CEF_CALLBACK browser_host_run_file_dialog(struct _cef_browser_host_t* self,
|
||||
CefRunFileDialogCallbackCToCpp::Wrap(callback));
|
||||
}
|
||||
|
||||
void CEF_CALLBACK browser_host_start_download(struct _cef_browser_host_t* self,
|
||||
const cef_string_t* url) {
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
DCHECK(self);
|
||||
if (!self)
|
||||
return;
|
||||
// Verify param: url; type: string_byref_const
|
||||
DCHECK(url);
|
||||
if (!url)
|
||||
return;
|
||||
|
||||
// Execute
|
||||
CefBrowserHostCppToC::Get(self)->StartDownload(
|
||||
CefString(url));
|
||||
}
|
||||
|
||||
int CEF_CALLBACK browser_host_is_window_rendering_disabled(
|
||||
struct _cef_browser_host_t* self) {
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
@ -449,6 +466,7 @@ CefBrowserHostCppToC::CefBrowserHostCppToC(CefBrowserHost* cls)
|
||||
struct_.struct_.get_zoom_level = browser_host_get_zoom_level;
|
||||
struct_.struct_.set_zoom_level = browser_host_set_zoom_level;
|
||||
struct_.struct_.run_file_dialog = browser_host_run_file_dialog;
|
||||
struct_.struct_.start_download = browser_host_start_download;
|
||||
struct_.struct_.is_window_rendering_disabled =
|
||||
browser_host_is_window_rendering_disabled;
|
||||
struct_.struct_.was_resized = browser_host_was_resized;
|
||||
|
@ -215,6 +215,22 @@ void CefBrowserHostCToCpp::RunFileDialog(FileDialogMode mode,
|
||||
cef_string_list_free(accept_typesList);
|
||||
}
|
||||
|
||||
void CefBrowserHostCToCpp::StartDownload(const CefString& url) {
|
||||
if (CEF_MEMBER_MISSING(struct_, start_download))
|
||||
return;
|
||||
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
// Verify param: url; type: string_byref_const
|
||||
DCHECK(!url.empty());
|
||||
if (url.empty())
|
||||
return;
|
||||
|
||||
// Execute
|
||||
struct_->start_download(struct_,
|
||||
url.GetStruct());
|
||||
}
|
||||
|
||||
bool CefBrowserHostCToCpp::IsWindowRenderingDisabled() {
|
||||
if (CEF_MEMBER_MISSING(struct_, is_window_rendering_disabled))
|
||||
return false;
|
||||
|
@ -51,6 +51,7 @@ class CefBrowserHostCToCpp
|
||||
const CefString& default_file_name,
|
||||
const std::vector<CefString>& accept_types,
|
||||
CefRefPtr<CefRunFileDialogCallback> callback) OVERRIDE;
|
||||
virtual void StartDownload(const CefString& url) OVERRIDE;
|
||||
virtual bool IsWindowRenderingDisabled() OVERRIDE;
|
||||
virtual void WasResized() OVERRIDE;
|
||||
virtual void Invalidate(const CefRect& dirtyRect,
|
||||
|
265
tests/unittests/download_unittest.cc
Normal file
265
tests/unittests/download_unittest.cc
Normal file
@ -0,0 +1,265 @@
|
||||
// Copyright (c) 2013 The Chromium Embedded Framework 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 "include/cef_scheme.h"
|
||||
#include "base/file_util.h"
|
||||
#include "base/files/scoped_temp_dir.h"
|
||||
#include "tests/unittests/test_handler.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
namespace {
|
||||
|
||||
const char kTestDomain[] = "test-download";
|
||||
const char kTestEntryUrl[] = "http://test-download/test.html";
|
||||
const char kTestDownloadUrl[] = "http://test-download/download.txt";
|
||||
const char kTestFileName[] = "download_test.txt";
|
||||
const char kTestContentDisposition[] =
|
||||
"attachment; filename=\"download_test.txt\"";
|
||||
const char kTestMimeType[] = "text/plain";
|
||||
const char kTestContent[] = "Download test text";
|
||||
|
||||
class DownloadSchemeHandler : public CefResourceHandler {
|
||||
public:
|
||||
explicit DownloadSchemeHandler(TrackCallback* got_download_request)
|
||||
: got_download_request_(got_download_request),
|
||||
offset_(0) {}
|
||||
|
||||
virtual bool ProcessRequest(CefRefPtr<CefRequest> request,
|
||||
CefRefPtr<CefCallback> callback)
|
||||
OVERRIDE {
|
||||
std::string url = request->GetURL();
|
||||
if (url == kTestEntryUrl) {
|
||||
content_ = "<html><body>Download Test</body></html>";
|
||||
mime_type_ = "text/html";
|
||||
} else if (url == kTestDownloadUrl) {
|
||||
got_download_request_->yes();
|
||||
content_ = kTestContent;
|
||||
mime_type_ = kTestMimeType;
|
||||
content_disposition_ = kTestContentDisposition;
|
||||
} else {
|
||||
EXPECT_TRUE(false); // Not reached.
|
||||
return false;
|
||||
}
|
||||
|
||||
callback->Continue();
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void GetResponseHeaders(CefRefPtr<CefResponse> response,
|
||||
int64& response_length,
|
||||
CefString& redirectUrl) OVERRIDE {
|
||||
response_length = content_.size();
|
||||
|
||||
response->SetStatus(200);
|
||||
response->SetMimeType(mime_type_);
|
||||
|
||||
if (!content_disposition_.empty()) {
|
||||
CefResponse::HeaderMap headerMap;
|
||||
response->GetHeaderMap(headerMap);
|
||||
headerMap.insert(
|
||||
std::make_pair("Content-Disposition", content_disposition_));
|
||||
response->SetHeaderMap(headerMap);
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool ReadResponse(void* data_out,
|
||||
int bytes_to_read,
|
||||
int& bytes_read,
|
||||
CefRefPtr<CefCallback> callback)
|
||||
OVERRIDE {
|
||||
bool has_data = false;
|
||||
bytes_read = 0;
|
||||
|
||||
size_t size = content_.size();
|
||||
if (offset_ < size) {
|
||||
int transfer_size =
|
||||
std::min(bytes_to_read, static_cast<int>(size - offset_));
|
||||
memcpy(data_out, content_.c_str() + offset_, transfer_size);
|
||||
offset_ += transfer_size;
|
||||
|
||||
bytes_read = transfer_size;
|
||||
has_data = true;
|
||||
}
|
||||
|
||||
return has_data;
|
||||
}
|
||||
|
||||
virtual void Cancel() OVERRIDE {
|
||||
}
|
||||
|
||||
private:
|
||||
TrackCallback* got_download_request_;
|
||||
std::string content_;
|
||||
std::string mime_type_;
|
||||
std::string content_disposition_;
|
||||
size_t offset_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(SchemeHandler);
|
||||
};
|
||||
|
||||
class DownloadSchemeHandlerFactory : public CefSchemeHandlerFactory {
|
||||
public:
|
||||
explicit DownloadSchemeHandlerFactory(TrackCallback* got_download_request)
|
||||
: got_download_request_(got_download_request) {}
|
||||
|
||||
virtual CefRefPtr<CefResourceHandler> Create(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
const CefString& scheme_name,
|
||||
CefRefPtr<CefRequest> request) OVERRIDE {
|
||||
return new DownloadSchemeHandler(got_download_request_);
|
||||
}
|
||||
|
||||
private:
|
||||
TrackCallback* got_download_request_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(SchemeHandlerFactory);
|
||||
};
|
||||
|
||||
class DownloadTestHandler : public TestHandler {
|
||||
public:
|
||||
DownloadTestHandler() {}
|
||||
|
||||
virtual void RunTest() OVERRIDE {
|
||||
CefRegisterSchemeHandlerFactory("http", kTestDomain,
|
||||
new DownloadSchemeHandlerFactory(&got_download_request_));
|
||||
|
||||
// Create a new temporary directory.
|
||||
EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
|
||||
test_path_ = temp_dir_.path().AppendASCII(kTestFileName);
|
||||
|
||||
// Create the browser
|
||||
CreateBrowser(kTestEntryUrl);
|
||||
}
|
||||
|
||||
virtual void OnLoadEnd(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
int httpStatusCode) OVERRIDE {
|
||||
EXPECT_STREQ(kTestEntryUrl, frame->GetURL().ToString().c_str());
|
||||
|
||||
// Begin the download.
|
||||
browser->GetHost()->StartDownload(kTestDownloadUrl);
|
||||
}
|
||||
|
||||
virtual void OnBeforeDownload(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefDownloadItem> download_item,
|
||||
const CefString& suggested_name,
|
||||
CefRefPtr<CefBeforeDownloadCallback> callback) OVERRIDE {
|
||||
EXPECT_TRUE(CefCurrentlyOn(TID_UI));
|
||||
EXPECT_FALSE(got_on_before_download_);
|
||||
EXPECT_FALSE(got_on_download_updated_);
|
||||
|
||||
got_on_before_download_.yes();
|
||||
|
||||
EXPECT_TRUE(browser->IsSame(GetBrowser()));
|
||||
EXPECT_STREQ(kTestFileName, suggested_name.ToString().c_str());
|
||||
EXPECT_TRUE(download_item.get());
|
||||
EXPECT_TRUE(callback.get());
|
||||
|
||||
download_id_ = download_item->GetId();
|
||||
EXPECT_LT(0, download_id_);
|
||||
|
||||
EXPECT_TRUE(download_item->IsValid());
|
||||
EXPECT_TRUE(download_item->IsInProgress());
|
||||
EXPECT_FALSE(download_item->IsComplete());
|
||||
EXPECT_FALSE(download_item->IsCanceled());
|
||||
EXPECT_EQ(0LL, download_item->GetCurrentSpeed());
|
||||
EXPECT_EQ(0, download_item->GetPercentComplete());
|
||||
EXPECT_EQ(static_cast<int64>(sizeof(kTestContent)-1),
|
||||
download_item->GetTotalBytes());
|
||||
EXPECT_EQ(0LL, download_item->GetReceivedBytes());
|
||||
EXPECT_EQ(0L, download_item->GetFullPath().length());
|
||||
EXPECT_STREQ(kTestDownloadUrl, download_item->GetURL().ToString().c_str());
|
||||
EXPECT_EQ(0L, download_item->GetSuggestedFileName().length());
|
||||
EXPECT_STREQ(kTestContentDisposition,
|
||||
download_item->GetContentDisposition().ToString().c_str());
|
||||
EXPECT_STREQ(kTestMimeType, download_item->GetMimeType().ToString().c_str());
|
||||
|
||||
callback->Continue(test_path_.value(), false);
|
||||
}
|
||||
|
||||
virtual void OnDownloadUpdated(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefDownloadItem> download_item,
|
||||
CefRefPtr<CefDownloadItemCallback> callback) OVERRIDE {
|
||||
EXPECT_TRUE(CefCurrentlyOn(TID_UI));
|
||||
EXPECT_TRUE(got_on_before_download_);
|
||||
|
||||
got_on_download_updated_.yes();
|
||||
|
||||
EXPECT_TRUE(browser->IsSame(GetBrowser()));
|
||||
EXPECT_TRUE(download_item.get());
|
||||
EXPECT_TRUE(callback.get());
|
||||
|
||||
EXPECT_EQ(download_id_, download_item->GetId());
|
||||
|
||||
EXPECT_TRUE(download_item->IsValid());
|
||||
EXPECT_FALSE(download_item->IsCanceled());
|
||||
EXPECT_LT(0LL, download_item->GetCurrentSpeed());
|
||||
EXPECT_LT(0, download_item->GetPercentComplete());
|
||||
EXPECT_EQ(static_cast<int64>(sizeof(kTestContent)-1),
|
||||
download_item->GetTotalBytes());
|
||||
EXPECT_STREQ(kTestDownloadUrl, download_item->GetURL().ToString().c_str());
|
||||
EXPECT_STREQ(kTestContentDisposition,
|
||||
download_item->GetContentDisposition().ToString().c_str());
|
||||
EXPECT_STREQ(kTestMimeType,
|
||||
download_item->GetMimeType().ToString().c_str());
|
||||
|
||||
std::string full_path = download_item->GetFullPath();
|
||||
if (!full_path.empty()) {
|
||||
got_full_path_.yes();
|
||||
EXPECT_STREQ(CefString(test_path_.value()).ToString().c_str(),
|
||||
full_path.c_str());
|
||||
}
|
||||
|
||||
if (download_item->IsComplete()) {
|
||||
EXPECT_FALSE(download_item->IsInProgress());
|
||||
EXPECT_EQ(100, download_item->GetPercentComplete());
|
||||
EXPECT_EQ(static_cast<int64>(sizeof(kTestContent)-1),
|
||||
download_item->GetReceivedBytes());
|
||||
|
||||
DestroyTest();
|
||||
} else {
|
||||
EXPECT_TRUE(download_item->IsInProgress());
|
||||
EXPECT_LT(0LL, download_item->GetReceivedBytes());
|
||||
}
|
||||
}
|
||||
|
||||
virtual void DestroyTest() OVERRIDE {
|
||||
CefRegisterSchemeHandlerFactory("http", kTestDomain, NULL);
|
||||
|
||||
EXPECT_TRUE(got_download_request_);
|
||||
EXPECT_TRUE(got_on_before_download_);
|
||||
EXPECT_TRUE(got_on_download_updated_);
|
||||
EXPECT_TRUE(got_full_path_);
|
||||
|
||||
// Verify the file contents.
|
||||
std::string contents;
|
||||
EXPECT_TRUE(file_util::ReadFileToString(test_path_, &contents));
|
||||
EXPECT_STREQ(kTestContent, contents.c_str());
|
||||
|
||||
EXPECT_TRUE(temp_dir_.Delete());
|
||||
|
||||
TestHandler::DestroyTest();
|
||||
}
|
||||
|
||||
private:
|
||||
base::ScopedTempDir temp_dir_;
|
||||
FilePath test_path_;
|
||||
int download_id_;
|
||||
|
||||
TrackCallback got_download_request_;
|
||||
TrackCallback got_on_before_download_;
|
||||
TrackCallback got_on_download_updated_;
|
||||
TrackCallback got_full_path_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
// Verify that downloads work.
|
||||
TEST(DownloadTest, Download) {
|
||||
CefRefPtr<DownloadTestHandler> handler = new DownloadTestHandler();
|
||||
handler->ExecuteTest();
|
||||
}
|
@ -33,6 +33,7 @@ class TrackCallback {
|
||||
class TestHandler : public CefClient,
|
||||
public CefDialogHandler,
|
||||
public CefDisplayHandler,
|
||||
public CefDownloadHandler,
|
||||
public CefGeolocationHandler,
|
||||
public CefJSDialogHandler,
|
||||
public CefLifeSpanHandler,
|
||||
@ -52,6 +53,9 @@ class TestHandler : public CefClient,
|
||||
virtual CefRefPtr<CefDisplayHandler> GetDisplayHandler() OVERRIDE {
|
||||
return this;
|
||||
}
|
||||
virtual CefRefPtr<CefDownloadHandler> GetDownloadHandler() OVERRIDE {
|
||||
return this;
|
||||
}
|
||||
virtual CefRefPtr<CefGeolocationHandler> GetGeolocationHandler() OVERRIDE {
|
||||
return this;
|
||||
}
|
||||
@ -68,6 +72,13 @@ class TestHandler : public CefClient,
|
||||
return this;
|
||||
}
|
||||
|
||||
// CefDownloadHandler methods
|
||||
virtual void OnBeforeDownload(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefDownloadItem> download_item,
|
||||
const CefString& suggested_name,
|
||||
CefRefPtr<CefBeforeDownloadCallback> callback) OVERRIDE {}
|
||||
|
||||
// CefLifeSpanHandler methods
|
||||
virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
|
||||
virtual void OnBeforeClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
|
||||
|
Loading…
x
Reference in New Issue
Block a user