Support file uploads in CefURLRequests originating from the browser process (issue #1013).

git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@1525 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
Marshall Greenblatt 2013-11-25 17:31:59 +00:00
parent ec8b64e88a
commit 43d2ca32fa
4 changed files with 82 additions and 13 deletions

View File

@ -101,7 +101,14 @@ typedef struct _cef_urlrequest_t {
/// ///
// Create a new URL request. Only GET, POST, HEAD, DELETE and PUT request // Create a new URL request. Only GET, POST, HEAD, DELETE and PUT request
// functions are supported. The |request| object will be marked as read-only // functions are supported. Multiple post data elements are not supported and
// elements of type PDE_TYPE_FILE are only supported for requests originating
// from the browser process. Requests originating from the render process will
// receive the same handling as requests originating from Web content -- if the
// response contains Content-Disposition or Mime-Type header values that would
// not normally be rendered then the response may receive special handling
// inside the browser (for example, via the file download code path instead of
// the URL request code path). The |request| object will be marked as read-only
// after calling this function. // after calling this function.
/// ///
CEF_EXPORT cef_urlrequest_t* cef_urlrequest_create( CEF_EXPORT cef_urlrequest_t* cef_urlrequest_create(

View File

@ -60,8 +60,15 @@ class CefURLRequest : public virtual CefBase {
/// ///
// Create a new URL request. Only GET, POST, HEAD, DELETE and PUT request // Create a new URL request. Only GET, POST, HEAD, DELETE and PUT request
// methods are supported. The |request| object will be marked as read-only // methods are supported. Multiple post data elements are not supported and
// after calling this method. // elements of type PDE_TYPE_FILE are only supported for requests originating
// from the browser process. Requests originating from the render process will
// receive the same handling as requests originating from Web content -- if
// the response contains Content-Disposition or Mime-Type header values that
// would not normally be rendered then the response may receive special
// handling inside the browser (for example, via the file download code path
// instead of the URL request code path). The |request| object will be marked
// as read-only after calling this method.
/// ///
/*--cef()--*/ /*--cef()--*/
static CefRefPtr<CefURLRequest> Create( static CefRefPtr<CefURLRequest> Create(

View File

@ -221,20 +221,34 @@ class CefBrowserURLRequest::Context
if (post_data.get()) { if (post_data.get()) {
CefPostData::ElementVector elements; CefPostData::ElementVector elements;
post_data->GetElements(elements); post_data->GetElements(elements);
if (elements.size() == 1 && elements[0]->GetType() == PDE_TYPE_BYTES) { if (elements.size() == 1) {
CefPostDataElementImpl* impl =
static_cast<CefPostDataElementImpl*>(elements[0].get());
// Default to URL encoding if not specified. // Default to URL encoding if not specified.
if (content_type.empty()) if (content_type.empty())
content_type = "application/x-www-form-urlencoded"; content_type = "application/x-www-form-urlencoded";
upload_data_size = impl->GetBytesCount(); CefPostDataElementImpl* impl =
fetcher_->SetUploadData(content_type, static_cast<CefPostDataElementImpl*>(elements[0].get());
std::string(static_cast<char*>(impl->GetBytes()),
upload_data_size)); switch (elements[0]->GetType())
} else { case PDE_TYPE_BYTES: {
NOTIMPLEMENTED() << "multi-part form data is not supported"; upload_data_size = impl->GetBytesCount();
fetcher_->SetUploadData(content_type,
std::string(static_cast<char*>(impl->GetBytes()),
upload_data_size));
break;
case PDE_TYPE_FILE:
fetcher_->SetUploadFilePath(
content_type,
base::FilePath(impl->GetFile()),
0, kuint64max,
content::BrowserThread::GetMessageLoopProxyForThread(
content::BrowserThread::FILE).get());
break;
case PDE_TYPE_EMPTY:
break;
}
} else if (elements.size() > 1) {
NOTIMPLEMENTED() << " multi-part form data is not supported";
} }
} }

View File

@ -2,6 +2,7 @@
// reserved. Use of this source code is governed by a BSD-style license that // reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file. // can be found in the LICENSE file.
#include <fstream>
#include <map> #include <map>
#include <sstream> #include <sstream>
@ -14,6 +15,7 @@
#include "base/bind.h" #include "base/bind.h"
#include "base/callback.h" #include "base/callback.h"
#include "base/files/scoped_temp_dir.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
@ -45,6 +47,7 @@ enum RequestTestMode {
REQTEST_GET_ALLOWCOOKIES, REQTEST_GET_ALLOWCOOKIES,
REQTEST_GET_REDIRECT, REQTEST_GET_REDIRECT,
REQTEST_POST, REQTEST_POST,
REQTEST_POST_FILE,
REQTEST_POST_WITHPROGRESS, REQTEST_POST_WITHPROGRESS,
REQTEST_HEAD, REQTEST_HEAD,
}; };
@ -108,6 +111,15 @@ void SetUploadData(CefRefPtr<CefRequest> request,
request->SetPostData(postData); request->SetPostData(postData);
} }
void SetUploadFile(CefRefPtr<CefRequest> request,
const base::FilePath& file) {
CefRefPtr<CefPostData> postData = CefPostData::Create();
CefRefPtr<CefPostDataElement> element = CefPostDataElement::Create();
element->SetToFile(file.value());
postData->AddElement(element);
request->SetPostData(postData);
}
void GetUploadData(CefRefPtr<CefRequest> request, void GetUploadData(CefRefPtr<CefRequest> request,
std::string& data) { std::string& data) {
CefRefPtr<CefPostData> postData = request->GetPostData(); CefRefPtr<CefPostData> postData = request->GetPostData();
@ -532,6 +544,7 @@ class RequestTestRunner {
GenericRunTest); GenericRunTest);
REGISTER_TEST(REQTEST_GET_REDIRECT, SetupGetRedirectTest, GenericRunTest); REGISTER_TEST(REQTEST_GET_REDIRECT, SetupGetRedirectTest, GenericRunTest);
REGISTER_TEST(REQTEST_POST, SetupPostTest, GenericRunTest); REGISTER_TEST(REQTEST_POST, SetupPostTest, GenericRunTest);
REGISTER_TEST(REQTEST_POST_FILE, SetupPostFileTest, GenericRunTest);
REGISTER_TEST(REQTEST_POST_WITHPROGRESS, SetupPostWithProgressTest, REGISTER_TEST(REQTEST_POST_WITHPROGRESS, SetupPostWithProgressTest,
GenericRunTest); GenericRunTest);
REGISTER_TEST(REQTEST_HEAD, SetupHeadTest, GenericRunTest); REGISTER_TEST(REQTEST_HEAD, SetupHeadTest, GenericRunTest);
@ -630,6 +643,28 @@ class RequestTestRunner {
settings_.response_data = "POST TEST SUCCESS"; settings_.response_data = "POST TEST SUCCESS";
} }
void SetupPostFileTest() {
settings_.request = CefRequest::Create();
settings_.request->SetURL(MakeSchemeURL("PostFileTest.html"));
settings_.request->SetMethod("POST");
EXPECT_TRUE(post_file_tmpdir_.CreateUniqueTempDir());
base::FilePath path =
post_file_tmpdir_.path().Append(FILE_PATH_LITERAL("example.txt"));
std::ofstream myfile;
myfile.open(path.value());
myfile << "HELLO FRIEND!";
myfile.close();
SetUploadFile(settings_.request, path);
settings_.response = CefResponse::Create();
settings_.response->SetMimeType("text/html");
settings_.response->SetStatus(200);
settings_.response->SetStatusText("OK");
settings_.response_data = "POST TEST SUCCESS";
}
void SetupPostWithProgressTest() { void SetupPostWithProgressTest() {
// Start with the normal post test. // Start with the normal post test.
SetupPostTest(); SetupPostTest();
@ -755,6 +790,9 @@ class RequestTestRunner {
scheme_factory_ = NULL; scheme_factory_ = NULL;
} }
if (post_file_tmpdir_.IsValid())
EXPECT_TRUE(post_file_tmpdir_.Delete());
delegate_->DestroyTest(settings_); delegate_->DestroyTest(settings_);
} }
@ -800,6 +838,8 @@ class RequestTestRunner {
std::string scheme_name_; std::string scheme_name_;
CefRefPtr<RequestSchemeHandlerFactory> scheme_factory_; CefRefPtr<RequestSchemeHandlerFactory> scheme_factory_;
base::ScopedTempDir post_file_tmpdir_;
public: public:
RequestRunSettings settings_; RequestRunSettings settings_;
}; };
@ -1044,6 +1084,7 @@ REQ_TEST(BrowserGETNoData, REQTEST_GET_NODATA, true);
REQ_TEST(BrowserGETAllowCookies, REQTEST_GET_ALLOWCOOKIES, true); REQ_TEST(BrowserGETAllowCookies, REQTEST_GET_ALLOWCOOKIES, true);
REQ_TEST(BrowserGETRedirect, REQTEST_GET_REDIRECT, true); REQ_TEST(BrowserGETRedirect, REQTEST_GET_REDIRECT, true);
REQ_TEST(BrowserPOST, REQTEST_POST, true); REQ_TEST(BrowserPOST, REQTEST_POST, true);
REQ_TEST(BrowserPOSTFile, REQTEST_POST_FILE, true);
REQ_TEST(BrowserPOSTWithProgress, REQTEST_POST_WITHPROGRESS, true); REQ_TEST(BrowserPOSTWithProgress, REQTEST_POST_WITHPROGRESS, true);
REQ_TEST(BrowserHEAD, REQTEST_HEAD, true); REQ_TEST(BrowserHEAD, REQTEST_HEAD, true);