chromiumembedded / cef

Chromium Embedded Framework (CEF). A simple framework for embedding Chromium-based browsers in other applications.
https://bitbucket.org/chromiumembedded/cef/
Other
3.31k stars 462 forks source link

Failure uploading large files to Dropbox #1761

Closed magreenblatt closed 8 years ago

magreenblatt commented 8 years ago

Original report by me.


What steps will reproduce the problem?

  1. Log into the Dropbox website.
  2. Use the website widget to upload a large file. For example, the 10MB file from http://speedtest.reliableservers.com/index.php

What is the expected output? What do you see instead?

The upload should succeed. Instead, it fails mysteriously in a Release build and hits NOTREACHED() in Debug build.

What version of the product are you using? On what operating system?

Tested with a 32-bit build of 2454 branch and newer on Windows 8.1 64-bit.

The failure seems related to the use of multiple chunked uploads.

Call stack (current master branch):

>   libcef.dll!base::debug::BreakDebugger() Line 21 C++
    libcef.dll!logging::LogMessage::~LogMessage() Line 604  C++
    libcef.dll!CefPostDataElementImpl::Set(const net::UploadElementReader & element_reader) Line 762    C++
    libcef.dll!CefPostDataImpl::Set(const net::UploadDataStream & data_stream) Line 547 C++
    libcef.dll!CefRequestImpl::Set(net::URLRequest * request) Line 244  C++
    libcef.dll!CefNetworkDelegate::OnBeforeURLRequest(net::URLRequest * request, const base::Callback<void __cdecl(int)> & callback, GURL * new_url) Line 244   C++
    libcef.dll!net::NetworkDelegate::NotifyBeforeURLRequest(net::URLRequest * request, const base::Callback<void __cdecl(int)> & callback, GURL * new_url) Line 26  C++
    libcef.dll!net::URLRequest::Start() Line 517    C++
    libcef.dll!content::ResourceLoader::StartRequestInternal() Line 486 C++
    libcef.dll!content::ResourceLoader::StartRequest() Line 171 C++
    libcef.dll!content::ResourceDispatcherHostImpl::StartLoading(content::ResourceRequestInfoImpl * info, const linked_ptr<content::ResourceLoader> & loader) Line 2208 C++
    libcef.dll!content::ResourceDispatcherHostImpl::BeginRequestInternal(scoped_ptr<net::URLRequest,base::DefaultDeleter<net::URLRequest> > request, scoped_ptr<content::ResourceHandler,base::DefaultDeleter<content::ResourceHandler> > handler) Line 2196    C++
    libcef.dll!content::ResourceDispatcherHostImpl::BeginRequest(int request_id, const ResourceHostMsg_Request & request_data, IPC::Message * sync_result, int route_id) Line 1398  C++
    libcef.dll!content::ResourceDispatcherHostImpl::OnRequestResource(int routing_id, int request_id, const ResourceHostMsg_Request & request_data) Line 1072   C++
    libcef.dll!base::DispatchToMethodImpl<content::ResourceDispatcherHostImpl,void (__thiscall content::ResourceDispatcherHostImpl::*)(int,int,ResourceHostMsg_Request const &),int,int,ResourceHostMsg_Request,0,1,2>(content::ResourceDispatcherHostImpl * obj, void (int, int, const ResourceHostMsg_Request &) * method, const base::Tuple<int,int,ResourceHostMsg_Request> & arg, base::IndexSequence<0,1,2> __formal) Line 254    C++
    libcef.dll!base::DispatchToMethod<content::ResourceDispatcherHostImpl,void (__thiscall content::ResourceDispatcherHostImpl::*)(int,int,ResourceHostMsg_Request const &),int,int,ResourceHostMsg_Request>(content::ResourceDispatcherHostImpl * obj, void (int, int, const ResourceHostMsg_Request &) * method, const base::Tuple<int,int,ResourceHostMsg_Request> & arg) Line 261   C++
    libcef.dll!ResourceHostMsg_RequestResource::Dispatch<content::ResourceDispatcherHostImpl,content::ResourceDispatcherHostImpl,void,void (__thiscall content::ResourceDispatcherHostImpl::*)(int,int,ResourceHostMsg_Request const &)>(const IPC::Message * msg, content::ResourceDispatcherHostImpl * obj, content::ResourceDispatcherHostImpl * sender, void * parameter, void (int, int, const ResourceHostMsg_Request &) * func) Line 373 C++
    libcef.dll!content::ResourceDispatcherHostImpl::OnMessageReceived(const IPC::Message & message, content::ResourceMessageFilter * filter) Line 1014  C++
    libcef.dll!content::ResourceMessageFilter::OnMessageReceived(const IPC::Message & message) Line 50  C++
    libcef.dll!content::BrowserMessageFilter::Internal::DispatchMessageW(const IPC::Message & message) Line 92  C++
    libcef.dll!content::BrowserMessageFilter::Internal::OnMessageReceived(const IPC::Message & message) Line 67 C++
    libcef.dll!IPC::`anonymous namespace'::TryFiltersImpl(std::vector<IPC::MessageFilter *,std::allocator<IPC::MessageFilter *> > & filters, const IPC::Message & message) Line 20  C++
    libcef.dll!IPC::MessageFilterRouter::TryFilters(const IPC::Message & message) Line 85   C++
    libcef.dll!IPC::ChannelProxy::Context::TryFilters(const IPC::Message & message) Line 73 C++
    libcef.dll!IPC::ChannelProxy::Context::OnMessageReceived(const IPC::Message & message) Line 90  C++
    libcef.dll!IPC::internal::ChannelReader::DispatchMessageW(IPC::Message * m) Line 75 C++
    libcef.dll!IPC::internal::ChannelReader::HandleExternalMessage(IPC::Message * external_message, const std::vector<IPC::BrokerableAttachment::AttachmentId,std::allocator<IPC::BrokerableAttachment::AttachmentId> > & attachment_ids) Line 204  C++
    libcef.dll!IPC::internal::ChannelReader::HandleTranslatedMessage(IPC::Message * translated_message, const std::vector<IPC::BrokerableAttachment::AttachmentId,std::allocator<IPC::BrokerableAttachment::AttachmentId> > & attachment_ids) Line 186  C++
    libcef.dll!IPC::internal::ChannelReader::TranslateInputData(const char * input_data, int input_data_len) Line 106   C++
    libcef.dll!IPC::internal::ChannelReader::AsyncReadComplete(int bytes_read) Line 49  C++
    libcef.dll!IPC::ChannelWin::OnIOCompleted(base::MessagePumpForIO::IOContext * context, unsigned long bytes_transfered, unsigned long error) Line 555    C++
    libcef.dll!base::MessagePumpForIO::WaitForIOCompletion(unsigned long timeout, base::MessagePumpForIO::IOHandler * filter) Line 560  C++
    libcef.dll!base::MessagePumpForIO::DoRunLoop() Line 500 C++
    libcef.dll!base::MessagePumpWin::RunWithDispatcher(base::MessagePump::Delegate * delegate, base::MessagePumpDispatcher * dispatcher) Line 50    C++
    libcef.dll!base::MessagePumpWin::Run(base::MessagePump::Delegate * delegate) Line 57    C++
    libcef.dll!base::MessageLoop::RunHandler() Line 439 C++
    libcef.dll!base::RunLoop::Run() Line 56 C++
    libcef.dll!base::MessageLoop::Run() Line 283    C++
    libcef.dll!base::Thread::Run(base::MessageLoop * message_loop) Line 200 C++
    libcef.dll!content::BrowserThreadImpl::IOThreadRun(base::MessageLoop * message_loop) Line 212   C++
    libcef.dll!content::BrowserThreadImpl::Run(base::MessageLoop * message_loop) Line 246   C++
    libcef.dll!base::Thread::ThreadMain() Line 251  C++
    libcef.dll!base::`anonymous namespace'::ThreadFunc(void * params) Line 82   C++
magreenblatt commented 8 years ago

The problem is that CefPostDataElementImpl cannot currently represent multi-part chunk data. In CefNetworkDelegate::OnBeforeURLRequest we convert the URLRequest data to a CefRequestImpl object and call OnBeforeResourceLoad. The CefBeforeResourceLoadCallbackImpl::RunNow implementation then re-populates the URLRequest from the CefRequestImpl and consequently the multi-part chunk data is lost causing the request to fail.

It would be nice if CefRequestImpl could represent multi-part data but that's really a side issue. We shouldn't be changing the URLRequest if the user has not changed the CefRequestImpl object. That means CefRequestImpl should track what has changed (what CefRequest API methods were called) and CefRequestImpl::Get should only update the changed portion of the URLRequest.

magreenblatt commented 8 years ago

Fixed in master revision c199539 (bb) and 2526 branch revision 61f7df0 (bb).

magreenblatt commented 8 years ago

Master revision 9bc8da1 (bb) and 2526 branch revision e7a02fe (bb) adds a CefPostData::HasExcludedElements method which returns true if the underlying POST data includes elements that are not represented.

magreenblatt commented 8 years ago