Index: chrome_frame/npapi_url_request.cc |
=================================================================== |
--- chrome_frame/npapi_url_request.cc (revision 37418) |
+++ chrome_frame/npapi_url_request.cc (working copy) |
@@ -33,6 +33,39 @@ |
#include "chrome_frame/np_browser_functions.h" |
#include "net/base/net_errors.h" |
+class NPAPIUrlRequest : public PluginUrlRequest { |
+ public: |
+ explicit NPAPIUrlRequest(NPP instance); |
+ ~NPAPIUrlRequest(); |
+ |
+ virtual bool Start(); |
+ virtual void Stop(); |
+ virtual bool Read(int bytes_to_read); |
+ |
+ // Called from NPAPI |
+ bool OnStreamCreated(const char* mime_type, NPStream* stream); |
+ NPError OnStreamDestroyed(NPReason reason); |
+ int OnWriteReady(); |
+ int OnWrite(void* buffer, int len); |
+ |
+ // Thread unsafe implementation of ref counting, since |
+ // this will be called on the plugin UI thread only. |
+ virtual unsigned long API_CALL AddRef(); |
+ virtual unsigned long API_CALL Release(); |
+ |
+ private: |
+ PluginUrlRequestDelegate* delegate_; |
+ unsigned long ref_count_; |
+ NPP instance_; |
+ NPStream* stream_; |
+ size_t pending_read_size_; |
+ URLRequestStatus status_; |
+ |
+ PlatformThreadId thread_; |
+ static int instance_count_; |
+ DISALLOW_COPY_AND_ASSIGN(NPAPIUrlRequest); |
+}; |
+ |
int NPAPIUrlRequest::instance_count_ = 0; |
NPAPIUrlRequest::NPAPIUrlRequest(NPP instance) |
@@ -62,9 +95,7 @@ |
NOTREACHED() << "PluginUrlRequest only supports 'GET'/'POST'"; |
} |
- if (NPERR_NO_ERROR == result) { |
- request_handler()->AddRequest(this); |
- } else { |
+ if (NPERR_NO_ERROR != result) { |
int os_error = net::ERR_FAILED; |
switch (result) { |
case NPERR_INVALID_URL: |
@@ -74,7 +105,8 @@ |
break; |
} |
- OnResponseEnd(URLRequestStatus(URLRequestStatus::FAILED, os_error)); |
+ delegate_->OnResponseEnd(id(), |
+ URLRequestStatus(URLRequestStatus::FAILED, os_error)); |
return false; |
} |
@@ -88,10 +120,6 @@ |
npapi::DestroyStream(instance_, stream_, NPRES_USER_BREAK); |
stream_ = NULL; |
} |
- |
- request_handler()->RemoveRequest(this); |
- if (!status_.is_io_pending()) |
- OnResponseEnd(status_); |
} |
bool NPAPIUrlRequest::Read(int bytes_to_read) { |
@@ -105,13 +133,13 @@ |
// TODO(iyengar) |
// Add support for passing persistent cookies and information about any URL |
// redirects to Chrome. |
- OnResponseStarted(mime_type, stream->headers, stream->end, |
+ delegate_->OnResponseStarted(id(), mime_type, stream->headers, stream->end, |
base::Time::FromTimeT(stream->lastmodified), std::string(), |
std::string(), 0); |
return true; |
} |
-void NPAPIUrlRequest::OnStreamDestroyed(NPReason reason) { |
+NPError NPAPIUrlRequest::OnStreamDestroyed(NPReason reason) { |
URLRequestStatus::Status status = URLRequestStatus::FAILED; |
switch (reason) { |
case NPRES_DONE: |
@@ -128,6 +156,9 @@ |
status_.set_os_error(net::ERR_CONNECTION_CLOSED); |
break; |
} |
+ |
+ delegate_->OnResponseEnd(id(), status_); |
+ return NPERR_NO_ERROR; |
} |
int NPAPIUrlRequest::OnWriteReady() { |
@@ -136,7 +167,7 @@ |
int NPAPIUrlRequest::OnWrite(void* buffer, int len) { |
pending_read_size_ = 0; |
- OnReadComplete(buffer, len); |
+ delegate_->OnReadComplete(id(), buffer, len); |
return len; |
} |
@@ -155,3 +186,123 @@ |
return ret; |
} |
+NPAPIUrlRequestManager::NPAPIUrlRequestManager() : instance_(NULL) { |
+} |
+ |
+NPAPIUrlRequestManager::~NPAPIUrlRequestManager() { |
+ StopAll(); |
+} |
+ |
+// PluginUrlRequestManager implementation |
+bool NPAPIUrlRequestManager::IsThreadSafe() { |
+ return false; |
+} |
+ |
+void NPAPIUrlRequestManager::StartRequest(int request_id, |
+ const IPC::AutomationURLRequest& request_info) { |
+ scoped_refptr<NPAPIUrlRequest> new_request(new NPAPIUrlRequest(instance_)); |
+ DCHECK(new_request); |
+ if (new_request->Initialize(this, request_id, request_info.url, |
+ request_info.method, request_info.referrer, |
+ request_info.extra_request_headers, request_info.upload_data.get(), |
+ enable_frame_busting_)) { |
+ // Add to map. |
+ DCHECK(NULL == request_map_[request_id].get()); |
+ request_map_[request_id] = new_request; |
+ if (new_request->Start()) { |
+ // Keep additional reference on request for NPSTREAM |
+ // This will be released in NPP_UrlNotify |
+ new_request->AddRef(); |
+ } |
+ } |
+} |
+ |
+void NPAPIUrlRequestManager::ReadRequest(int request_id, int bytes_to_read) { |
+ scoped_refptr<NPAPIUrlRequest> request = request_map_[request_id]; |
+ DCHECK(request.get()); |
+ if (request) |
+ request->Read(bytes_to_read); |
+} |
+ |
+void NPAPIUrlRequestManager::EndRequest(int request_id) { |
+ scoped_refptr<NPAPIUrlRequest> request = request_map_[request_id]; |
+ if (request) |
+ request->Stop(); |
+} |
+ |
+void NPAPIUrlRequestManager::StopAll() { |
+ for (RequestMap::iterator index = request_map_.begin(); |
+ index != request_map_.end(); |
+ ++index) { |
+ scoped_refptr<NPAPIUrlRequest> request = (*index).second; |
+ request->Stop(); |
+ } |
+} |
+ |
+// PluginRequestDelegate implementation. |
+// Callbacks from NPAPIUrlRequest. Simply forward to the delegate. |
+void NPAPIUrlRequestManager::OnResponseStarted(int request_id, |
+ const char* mime_type, const char* headers, int size, |
+ base::Time last_modified, const std::string& peristent_cookies, |
+ const std::string& redirect_url, int redirect_status) { |
+ delegate_->OnResponseStarted(request_id, mime_type, headers, size, |
+ last_modified, peristent_cookies, redirect_url, redirect_status); |
+} |
+ |
+void NPAPIUrlRequestManager::OnReadComplete(int request_id, const void* buffer, |
+ int len) { |
+ delegate_->OnReadComplete(request_id, buffer, len); |
+} |
+ |
+void NPAPIUrlRequestManager::OnResponseEnd(int request_id, |
+ const URLRequestStatus& status) { |
+ // Delete from map. |
+ RequestMap::iterator it = request_map_.find(request_id); |
+ DCHECK(request_map_.end() != it); |
+ scoped_refptr<NPAPIUrlRequest> request = (*it).second; |
+ request_map_.erase(it); |
+ |
+ // Inform delegate unless canceled. |
+ if (status.status() != URLRequestStatus::CANCELED) |
+ delegate_->OnResponseEnd(request_id, status); |
+} |
+ |
+// Notifications from browser. Find the NPAPIUrlRequest and forward to it. |
+bool NPAPIUrlRequestManager::NewStream(NPMIMEType type, NPStream* stream, |
+ NPBool seekable, uint16* stream_type) { |
+ NPAPIUrlRequest* request = RequestFromNotifyData(stream->notifyData); |
+ DCHECK(request_map_.find(request->id()) != request_map_.end()); |
+ // We need to return the requested stream mode if we are returning a success |
+ // code. If we don't do this it causes Opera to blow up. |
+ *stream_type = NP_NORMAL; |
+ return request->OnStreamCreated(type, stream); |
+} |
+ |
+int32 NPAPIUrlRequestManager::WriteReady(NPStream* stream) { |
+ NPAPIUrlRequest* request = RequestFromNotifyData(stream->notifyData); |
+ DCHECK(request_map_.find(request->id()) != request_map_.end()); |
+ return request->OnWriteReady(); |
+} |
+ |
+int32 NPAPIUrlRequestManager::Write(NPStream* stream, int32 offset, |
+ int32 len, void* buffer) { |
+ NPAPIUrlRequest* request = RequestFromNotifyData(stream->notifyData); |
+ DCHECK(request_map_.find(request->id()) != request_map_.end()); |
+ return request->OnWrite(buffer, len); |
+} |
+ |
+NPError NPAPIUrlRequestManager::DestroyStream(NPStream* stream, |
+ NPReason reason) { |
+ NPAPIUrlRequest* request = RequestFromNotifyData(stream->notifyData); |
+ DCHECK(request_map_.find(request->id()) != request_map_.end()); |
+ return request->OnStreamDestroyed(reason); |
+} |
+ |
+void NPAPIUrlRequestManager::UrlNotify(const char* url, NPReason reason, |
+ void* notify_data) { |
+ NPAPIUrlRequest* request = RequestFromNotifyData(notify_data); |
+ if (request) { |
+ request->Stop(); |
+ request->Release(); |
+ } |
+} |