| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/chrome_plugin_host.h" | 5 #include "chrome/browser/chrome_plugin_host.h" |
| 6 | 6 |
| 7 #include <set> | 7 #include <set> |
| 8 | 8 |
| 9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 47 #include "third_party/skia/include/core/SkBitmap.h" | 47 #include "third_party/skia/include/core/SkBitmap.h" |
| 48 | 48 |
| 49 | 49 |
| 50 using base::TimeDelta; | 50 using base::TimeDelta; |
| 51 | 51 |
| 52 // This class manages the interception of network requests. It queries the | 52 // This class manages the interception of network requests. It queries the |
| 53 // plugin on every request, and creates an intercept job if the plugin can | 53 // plugin on every request, and creates an intercept job if the plugin can |
| 54 // intercept the request. | 54 // intercept the request. |
| 55 // NOTE: All methods must be called on the IO thread. | 55 // NOTE: All methods must be called on the IO thread. |
| 56 class PluginRequestInterceptor | 56 class PluginRequestInterceptor |
| 57 : public PluginHelper, public URLRequest::Interceptor { | 57 : public PluginHelper, public net::URLRequest::Interceptor { |
| 58 public: | 58 public: |
| 59 static URLRequestJob* UninterceptedProtocolHandler( | 59 static URLRequestJob* UninterceptedProtocolHandler( |
| 60 URLRequest* request, const std::string& scheme) { | 60 net::URLRequest* request, const std::string& scheme) { |
| 61 // This will get called if a plugin failed to intercept a request for a | 61 // This will get called if a plugin failed to intercept a request for a |
| 62 // protocol it has registered. In that case, we return NULL and the request | 62 // protocol it has registered. In that case, we return NULL and the request |
| 63 // will result in an error. | 63 // will result in an error. |
| 64 return new URLRequestErrorJob(request, net::ERR_FILE_NOT_FOUND); | 64 return new URLRequestErrorJob(request, net::ERR_FILE_NOT_FOUND); |
| 65 } | 65 } |
| 66 | 66 |
| 67 explicit PluginRequestInterceptor(ChromePluginLib* plugin) | 67 explicit PluginRequestInterceptor(ChromePluginLib* plugin) |
| 68 : PluginHelper(plugin) { | 68 : PluginHelper(plugin) { |
| 69 URLRequest::RegisterRequestInterceptor(this); | 69 net::URLRequest::RegisterRequestInterceptor(this); |
| 70 } | 70 } |
| 71 | 71 |
| 72 virtual ~PluginRequestInterceptor() { | 72 virtual ~PluginRequestInterceptor() { |
| 73 URLRequest::UnregisterRequestInterceptor(this); | 73 net::URLRequest::UnregisterRequestInterceptor(this); |
| 74 | 74 |
| 75 // Unregister our protocols. | 75 // Unregister our protocols. |
| 76 for (HandledProtocolList::iterator it = registered_protocols_.begin(); | 76 for (HandledProtocolList::iterator it = registered_protocols_.begin(); |
| 77 it != registered_protocols_.end(); ++it) { | 77 it != registered_protocols_.end(); ++it) { |
| 78 URLRequest::ProtocolFactory* factory = | 78 net::URLRequest::ProtocolFactory* factory = |
| 79 URLRequest::RegisterProtocolFactory(*it, NULL); | 79 net::URLRequest::RegisterProtocolFactory(*it, NULL); |
| 80 DCHECK(factory == UninterceptedProtocolHandler); | 80 DCHECK(factory == UninterceptedProtocolHandler); |
| 81 } | 81 } |
| 82 } | 82 } |
| 83 | 83 |
| 84 void RegisterProtocol(const std::string& scheme) { | 84 void RegisterProtocol(const std::string& scheme) { |
| 85 DCHECK(CalledOnValidThread()); | 85 DCHECK(CalledOnValidThread()); |
| 86 | 86 |
| 87 std::string lower_scheme = StringToLowerASCII(scheme); | 87 std::string lower_scheme = StringToLowerASCII(scheme); |
| 88 handled_protocols_.insert(lower_scheme); | 88 handled_protocols_.insert(lower_scheme); |
| 89 | 89 |
| 90 // Only add a protocol factory if the URLRequest doesn't already handle | 90 // Only add a protocol factory if the net::URLRequest doesn't already handle |
| 91 // it. If we fail to intercept, the request will be treated as an error. | 91 // it. If we fail to intercept, the request will be treated as an error. |
| 92 if (!URLRequest::IsHandledProtocol(lower_scheme)) { | 92 if (!net::URLRequest::IsHandledProtocol(lower_scheme)) { |
| 93 registered_protocols_.insert(lower_scheme); | 93 registered_protocols_.insert(lower_scheme); |
| 94 URLRequest::RegisterProtocolFactory(lower_scheme, | 94 net::URLRequest::RegisterProtocolFactory(lower_scheme, |
| 95 &UninterceptedProtocolHandler); | 95 &UninterceptedProtocolHandler); |
| 96 } | 96 } |
| 97 } | 97 } |
| 98 | 98 |
| 99 // URLRequest::Interceptor | 99 // net::URLRequest::Interceptor |
| 100 virtual URLRequestJob* MaybeIntercept(URLRequest* request) { | 100 virtual URLRequestJob* MaybeIntercept(net::URLRequest* request) { |
| 101 // TODO(darin): This DCHECK fails in the unit tests because our interceptor | 101 // TODO(darin): This DCHECK fails in the unit tests because our interceptor |
| 102 // is being persisted across unit tests. As a result, each time we get | 102 // is being persisted across unit tests. As a result, each time we get |
| 103 // poked on a different thread, but never from more than one thread at a | 103 // poked on a different thread, but never from more than one thread at a |
| 104 // time. We need a way to have the URLRequestJobManager get reset between | 104 // time. We need a way to have the URLRequestJobManager get reset between |
| 105 // unit tests. | 105 // unit tests. |
| 106 // DCHECK(CalledOnValidThread()); | 106 // DCHECK(CalledOnValidThread()); |
| 107 | 107 |
| 108 if (!IsHandledProtocol(request->url().scheme())) | 108 if (!IsHandledProtocol(request->url().scheme())) |
| 109 return NULL; | 109 return NULL; |
| 110 | 110 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 136 void LogInterceptMissTime(const TimeDelta& time) { | 136 void LogInterceptMissTime(const TimeDelta& time) { |
| 137 UMA_HISTOGRAM_TIMES("Gears.InterceptMiss", time); | 137 UMA_HISTOGRAM_TIMES("Gears.InterceptMiss", time); |
| 138 } | 138 } |
| 139 | 139 |
| 140 typedef std::set<std::string> HandledProtocolList; | 140 typedef std::set<std::string> HandledProtocolList; |
| 141 HandledProtocolList handled_protocols_; | 141 HandledProtocolList handled_protocols_; |
| 142 HandledProtocolList registered_protocols_; | 142 HandledProtocolList registered_protocols_; |
| 143 }; | 143 }; |
| 144 | 144 |
| 145 // This class manages a network request made by the plugin, also acting as | 145 // This class manages a network request made by the plugin, also acting as |
| 146 // the URLRequest delegate. | 146 // the net::URLRequest delegate. |
| 147 // NOTE: All methods must be called on the IO thread. | 147 // NOTE: All methods must be called on the IO thread. |
| 148 class PluginRequestHandler : public PluginHelper, public URLRequest::Delegate { | 148 class PluginRequestHandler : public PluginHelper, |
| 149 public net::URLRequest::Delegate { |
| 149 public: | 150 public: |
| 150 static PluginRequestHandler* FromCPRequest(CPRequest* request) { | 151 static PluginRequestHandler* FromCPRequest(CPRequest* request) { |
| 151 return ScopableCPRequest::GetData<PluginRequestHandler*>(request); | 152 return ScopableCPRequest::GetData<PluginRequestHandler*>(request); |
| 152 } | 153 } |
| 153 | 154 |
| 154 PluginRequestHandler(ChromePluginLib* plugin, ScopableCPRequest* cprequest) | 155 PluginRequestHandler(ChromePluginLib* plugin, ScopableCPRequest* cprequest) |
| 155 : PluginHelper(plugin), cprequest_(cprequest), user_buffer_(NULL) { | 156 : PluginHelper(plugin), cprequest_(cprequest), user_buffer_(NULL) { |
| 156 cprequest_->data = this; // see FromCPRequest(). | 157 cprequest_->data = this; // see FromCPRequest(). |
| 157 | 158 |
| 158 URLRequestContext* context = CPBrowsingContextManager::Instance()-> | 159 URLRequestContext* context = CPBrowsingContextManager::Instance()-> |
| 159 ToURLRequestContext(cprequest_->context); | 160 ToURLRequestContext(cprequest_->context); |
| 160 // TODO(mpcomplete): remove fallback case when Gears support is prevalent. | 161 // TODO(mpcomplete): remove fallback case when Gears support is prevalent. |
| 161 if (!context) | 162 if (!context) |
| 162 context = Profile::GetDefaultRequestContext()->GetURLRequestContext(); | 163 context = Profile::GetDefaultRequestContext()->GetURLRequestContext(); |
| 163 | 164 |
| 164 GURL gurl(cprequest_->url); | 165 GURL gurl(cprequest_->url); |
| 165 request_.reset(new URLRequest(gurl, this)); | 166 request_.reset(new net::URLRequest(gurl, this)); |
| 166 request_->set_context(context); | 167 request_->set_context(context); |
| 167 request_->set_method(cprequest_->method); | 168 request_->set_method(cprequest_->method); |
| 168 request_->set_load_flags(PluginResponseUtils::CPLoadFlagsToNetFlags(0)); | 169 request_->set_load_flags(PluginResponseUtils::CPLoadFlagsToNetFlags(0)); |
| 169 } | 170 } |
| 170 | 171 |
| 171 URLRequest* request() { return request_.get(); } | 172 net::URLRequest* request() { return request_.get(); } |
| 172 | 173 |
| 173 // Wraper of URLRequest::Read() | 174 // Wraper of net::URLRequest::Read() |
| 174 bool Read(char* dest, int dest_size, int *bytes_read) { | 175 bool Read(char* dest, int dest_size, int *bytes_read) { |
| 175 CHECK(!my_buffer_.get()); | 176 CHECK(!my_buffer_.get()); |
| 176 // We'll use our own buffer until the read actually completes. | 177 // We'll use our own buffer until the read actually completes. |
| 177 user_buffer_ = dest; | 178 user_buffer_ = dest; |
| 178 my_buffer_ = new net::IOBuffer(dest_size); | 179 my_buffer_ = new net::IOBuffer(dest_size); |
| 179 | 180 |
| 180 if (request_->Read(my_buffer_, dest_size, bytes_read)) { | 181 if (request_->Read(my_buffer_, dest_size, bytes_read)) { |
| 181 memcpy(dest, my_buffer_->data(), *bytes_read); | 182 memcpy(dest, my_buffer_->data(), *bytes_read); |
| 182 my_buffer_ = NULL; | 183 my_buffer_ = NULL; |
| 183 return true; | 184 return true; |
| 184 } | 185 } |
| 185 | 186 |
| 186 if (!request_->status().is_io_pending()) | 187 if (!request_->status().is_io_pending()) |
| 187 my_buffer_ = NULL; | 188 my_buffer_ = NULL; |
| 188 | 189 |
| 189 return false; | 190 return false; |
| 190 } | 191 } |
| 191 | 192 |
| 192 // URLRequest::Delegate | 193 // net::URLRequest::Delegate |
| 193 virtual void OnReceivedRedirect(URLRequest* request, const GURL& new_url, | 194 virtual void OnReceivedRedirect(net::URLRequest* request, const GURL& new_url, |
| 194 bool* defer_redirect) { | 195 bool* defer_redirect) { |
| 195 plugin_->functions().response_funcs->received_redirect( | 196 plugin_->functions().response_funcs->received_redirect( |
| 196 cprequest_.get(), new_url.spec().c_str()); | 197 cprequest_.get(), new_url.spec().c_str()); |
| 197 } | 198 } |
| 198 | 199 |
| 199 virtual void OnResponseStarted(URLRequest* request) { | 200 virtual void OnResponseStarted(net::URLRequest* request) { |
| 200 // TODO(mpcomplete): better error codes | 201 // TODO(mpcomplete): better error codes |
| 201 CPError result = | 202 CPError result = |
| 202 request_->status().is_success() ? CPERR_SUCCESS : CPERR_FAILURE; | 203 request_->status().is_success() ? CPERR_SUCCESS : CPERR_FAILURE; |
| 203 plugin_->functions().response_funcs->start_completed( | 204 plugin_->functions().response_funcs->start_completed( |
| 204 cprequest_.get(), result); | 205 cprequest_.get(), result); |
| 205 } | 206 } |
| 206 | 207 |
| 207 virtual void OnReadCompleted(URLRequest* request, int bytes_read) { | 208 virtual void OnReadCompleted(net::URLRequest* request, int bytes_read) { |
| 208 CHECK(my_buffer_.get()); | 209 CHECK(my_buffer_.get()); |
| 209 CHECK(user_buffer_); | 210 CHECK(user_buffer_); |
| 210 if (bytes_read > 0) { | 211 if (bytes_read > 0) { |
| 211 memcpy(user_buffer_, my_buffer_->data(), bytes_read); | 212 memcpy(user_buffer_, my_buffer_->data(), bytes_read); |
| 212 } else if (bytes_read < 0) { | 213 } else if (bytes_read < 0) { |
| 213 // TODO(mpcomplete): better error codes | 214 // TODO(mpcomplete): better error codes |
| 214 bytes_read = CPERR_FAILURE; | 215 bytes_read = CPERR_FAILURE; |
| 215 } | 216 } |
| 216 my_buffer_ = NULL; | 217 my_buffer_ = NULL; |
| 217 plugin_->functions().response_funcs->read_completed( | 218 plugin_->functions().response_funcs->read_completed( |
| 218 cprequest_.get(), bytes_read); | 219 cprequest_.get(), bytes_read); |
| 219 } | 220 } |
| 220 | 221 |
| 221 private: | 222 private: |
| 222 scoped_ptr<ScopableCPRequest> cprequest_; | 223 scoped_ptr<ScopableCPRequest> cprequest_; |
| 223 scoped_ptr<URLRequest> request_; | 224 scoped_ptr<net::URLRequest> request_; |
| 224 scoped_refptr<net::IOBuffer> my_buffer_; | 225 scoped_refptr<net::IOBuffer> my_buffer_; |
| 225 char* user_buffer_; | 226 char* user_buffer_; |
| 226 }; | 227 }; |
| 227 | 228 |
| 228 // This class manages plugins that want to handle UI commands. Right now, we | 229 // This class manages plugins that want to handle UI commands. Right now, we |
| 229 // only allow 1 plugin to do this, so there's only ever 1 instance of this | 230 // only allow 1 plugin to do this, so there's only ever 1 instance of this |
| 230 // class at once. | 231 // class at once. |
| 231 // NOTE: All methods must be called on the IO thread. | 232 // NOTE: All methods must be called on the IO thread. |
| 232 class PluginCommandHandler : public PluginHelper { | 233 class PluginCommandHandler : public PluginHelper { |
| 233 public: | 234 public: |
| (...skipping 590 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 824 CPBrowsingContext context) { | 825 CPBrowsingContext context) { |
| 825 // Sadly if we try and pass context through, we seem to break cl's little | 826 // Sadly if we try and pass context through, we seem to break cl's little |
| 826 // brain trying to compile the Tuple3 ctor. This cast works. | 827 // brain trying to compile the Tuple3 ctor. This cast works. |
| 827 int32 context_as_int32 = static_cast<int32>(context); | 828 int32 context_as_int32 = static_cast<int32>(context); |
| 828 // Plugins can only be accessed on the IO thread. | 829 // Plugins can only be accessed on the IO thread. |
| 829 BrowserThread::PostTask( | 830 BrowserThread::PostTask( |
| 830 BrowserThread::IO, FROM_HERE, | 831 BrowserThread::IO, FROM_HERE, |
| 831 NewRunnableFunction(PluginCommandHandler::HandleCommand, | 832 NewRunnableFunction(PluginCommandHandler::HandleCommand, |
| 832 command, data, context_as_int32)); | 833 command, data, context_as_int32)); |
| 833 } | 834 } |
| OLD | NEW |