Index: components/nacl/renderer/ppb_nacl_private_impl.cc |
diff --git a/components/nacl/renderer/ppb_nacl_private_impl.cc b/components/nacl/renderer/ppb_nacl_private_impl.cc |
index aa66f086445acbd0eaac724083ce45e8c2bf2693..9ada43de3774f1284e3f421254621d9c99c50297 100644 |
--- a/components/nacl/renderer/ppb_nacl_private_impl.cc |
+++ b/components/nacl/renderer/ppb_nacl_private_impl.cc |
@@ -17,6 +17,8 @@ |
#include "base/lazy_instance.h" |
#include "base/logging.h" |
#include "base/rand_util.h" |
+#include "base/strings/string_split.h" |
+#include "base/strings/string_util.h" |
#include "components/nacl/common/nacl_host_messages.h" |
#include "components/nacl/common/nacl_messages.h" |
#include "components/nacl/common/nacl_nonsfi_util.h" |
@@ -52,6 +54,7 @@ |
#include "ppapi/shared_impl/var_tracker.h" |
#include "ppapi/thunk/enter.h" |
#include "third_party/WebKit/public/platform/WebURLLoader.h" |
+#include "third_party/WebKit/public/platform/WebURLResponse.h" |
#include "third_party/WebKit/public/web/WebDocument.h" |
#include "third_party/WebKit/public/web/WebElement.h" |
#include "third_party/WebKit/public/web/WebLocalFrame.h" |
@@ -587,80 +590,40 @@ PP_Bool PPIsNonSFIModeEnabled() { |
return PP_FromBool(IsNonSFIModeEnabled()); |
} |
-void GetNexeFdContinuation(scoped_refptr<ppapi::TrackedCallback> callback, |
- PP_Bool* out_is_hit, |
- PP_FileHandle* out_handle, |
- int32_t pp_error, |
- bool is_hit, |
- PP_FileHandle handle) { |
- if (pp_error == PP_OK) { |
- *out_is_hit = PP_FromBool(is_hit); |
- *out_handle = handle; |
- } |
- callback->PostRun(pp_error); |
-} |
- |
-int32_t GetNexeFd(PP_Instance instance, |
- const char* pexe_url, |
- uint32_t abi_version, |
- uint32_t opt_level, |
- const char* http_headers_param, |
- const char* extra_flags, |
- PP_Bool* is_hit, |
- PP_FileHandle* handle, |
- struct PP_CompletionCallback callback) { |
- ppapi::thunk::EnterInstance enter(instance, callback); |
- if (enter.failed()) |
- return enter.retval(); |
- if (!pexe_url || !is_hit || !handle) |
- return enter.SetResult(PP_ERROR_BADARGUMENT); |
- if (!InitializePnaclResourceHost()) |
- return enter.SetResult(PP_ERROR_FAILED); |
- |
- std::string http_headers(http_headers_param); |
- net::HttpUtil::HeadersIterator iter( |
- http_headers.begin(), http_headers.end(), "\r\n"); |
- |
- std::string last_modified; |
- std::string etag; |
- bool has_no_store_header = false; |
- while (iter.GetNext()) { |
- if (StringToLowerASCII(iter.name()) == "last-modified") |
- last_modified = iter.values(); |
- if (StringToLowerASCII(iter.name()) == "etag") |
- etag = iter.values(); |
- if (StringToLowerASCII(iter.name()) == "cache-control") { |
- net::HttpUtil::ValuesIterator values_iter( |
- iter.values_begin(), iter.values_end(), ','); |
- while (values_iter.GetNext()) { |
- if (StringToLowerASCII(values_iter.value()) == "no-store") |
- has_no_store_header = true; |
- } |
- } |
+void GetNexeFd(PP_Instance instance, |
+ const std::string& pexe_url, |
+ uint32_t opt_level, |
+ const base::Time& last_modified_time, |
+ const std::string& etag, |
+ bool has_no_store_header, |
+ base::Callback<void(int32_t, bool, PP_FileHandle)> callback) { |
+ if (!InitializePnaclResourceHost()) { |
+ ppapi::PpapiGlobals::Get()->GetMainThreadMessageLoop()->PostTask( |
+ FROM_HERE, |
+ base::Bind(callback, |
+ static_cast<int32_t>(PP_ERROR_FAILED), |
+ false, |
+ PP_kInvalidFileHandle)); |
+ return; |
} |
- base::Time last_modified_time; |
- // If FromString fails, it doesn't touch last_modified_time and we just send |
- // the default-constructed null value. |
- base::Time::FromString(last_modified.c_str(), &last_modified_time); |
- |
PnaclCacheInfo cache_info; |
cache_info.pexe_url = GURL(pexe_url); |
- cache_info.abi_version = abi_version; |
+ // TODO(dschuff): Get this value from the pnacl json file after it |
+ // rolls in from NaCl. |
+ cache_info.abi_version = 1; |
cache_info.opt_level = opt_level; |
cache_info.last_modified = last_modified_time; |
cache_info.etag = etag; |
cache_info.has_no_store_header = has_no_store_header; |
cache_info.sandbox_isa = GetSandboxArch(); |
- cache_info.extra_flags = std::string(extra_flags); |
+ cache_info.extra_flags = GetCpuFeatures(); |
g_pnacl_resource_host.Get()->RequestNexeFd( |
GetRoutingID(instance), |
instance, |
cache_info, |
- base::Bind(&GetNexeFdContinuation, enter.callback(), is_hit, handle)); |
- |
- return enter.SetResult(PP_OK_COMPLETIONPENDING); |
+ callback); |
} |
void ReportTranslationFinished(PP_Instance instance, |
@@ -1563,6 +1526,160 @@ void SetPNaClStartTime(PP_Instance instance) { |
load_manager->set_pnacl_start_time(base::Time::Now()); |
} |
+class PexeDownloader : public blink::WebURLLoaderClient { |
+ public: |
+ PexeDownloader(PP_Instance instance, |
+ scoped_ptr<blink::WebURLLoader> url_loader, |
+ const std::string& pexe_url, |
+ int32_t pexe_opt_level, |
+ const PPP_PexeStreamHandler* stream_handler, |
+ void* stream_handler_user_data) |
+ : instance_(instance), |
+ url_loader_(url_loader.Pass()), |
+ pexe_url_(pexe_url), |
+ pexe_opt_level_(pexe_opt_level), |
+ stream_handler_(stream_handler), |
+ stream_handler_user_data_(stream_handler_user_data), |
+ success_(false), |
+ expected_content_length_(-1), |
+ weak_factory_(this) { } |
+ |
+ void Load(const blink::WebURLRequest& request) { |
+ url_loader_->loadAsynchronously(request, this); |
+ } |
+ |
+ private: |
+ virtual void didReceiveResponse(blink::WebURLLoader* loader, |
+ const blink::WebURLResponse& response) { |
+ success_ = (response.httpStatusCode() == 200); |
+ if (!success_) |
+ return; |
+ |
+ expected_content_length_ = response.expectedContentLength(); |
+ |
+ // Defer loading after receiving headers. This is because we may already |
+ // have a cached translated nexe, so check for that now. |
+ url_loader_->setDefersLoading(true); |
+ |
+ std::string etag = response.httpHeaderField("etag").utf8(); |
+ std::string last_modified = |
+ response.httpHeaderField("last-modified").utf8(); |
+ base::Time last_modified_time; |
+ base::Time::FromString(last_modified.c_str(), &last_modified_time); |
+ |
+ bool has_no_store_header = false; |
+ std::string cache_control = |
+ response.httpHeaderField("cache-control").utf8(); |
+ |
+ std::vector<std::string> values; |
+ base::SplitString(cache_control, ',', &values); |
+ for (std::vector<std::string>::const_iterator it = values.begin(); |
+ it != values.end(); |
+ ++it) { |
+ if (StringToLowerASCII(*it) == "no-store") |
+ has_no_store_header = true; |
+ } |
+ |
+ GetNexeFd(instance_, |
+ pexe_url_, |
+ pexe_opt_level_, |
+ last_modified_time, |
+ etag, |
+ has_no_store_header, |
+ base::Bind(&PexeDownloader::didGetNexeFd, |
+ weak_factory_.GetWeakPtr())); |
+ } |
+ |
+ virtual void didGetNexeFd(int32_t pp_error, |
+ bool cache_hit, |
+ PP_FileHandle file_handle) { |
+ if (cache_hit) { |
+ stream_handler_->DidCacheHit(stream_handler_user_data_, file_handle); |
+ |
+ // We delete the PexeDownloader at this point since we successfully got a |
+ // cached, translated nexe. |
+ delete this; |
+ return; |
+ } |
+ stream_handler_->DidCacheMiss(stream_handler_user_data_, |
+ expected_content_length_); |
+ |
+ // No translated nexe was found in the cache, so we should download the |
+ // file to start streaming it. |
+ url_loader_->setDefersLoading(false); |
+ } |
+ |
+ virtual void didReceiveData(blink::WebURLLoader* loader, |
+ const char* data, |
+ int data_length, |
+ int encoded_data_length) { |
+ // Stream the data we received to the stream callback. |
+ stream_handler_->DidStreamData(stream_handler_user_data_, |
+ data, |
+ data_length); |
+ } |
+ |
+ virtual void didFinishLoading(blink::WebURLLoader* loader, |
+ double finish_time, |
+ int64_t total_encoded_data_length) { |
+ int32_t result = success_ ? PP_OK : PP_ERROR_FAILED; |
+ stream_handler_->DidFinishStream(stream_handler_user_data_, result); |
+ delete this; |
+ } |
+ |
+ virtual void didFail(blink::WebURLLoader* loader, |
+ const blink::WebURLError& error) { |
+ success_ = false; |
+ } |
+ |
+ PP_Instance instance_; |
+ scoped_ptr<blink::WebURLLoader> url_loader_; |
+ std::string pexe_url_; |
+ int32_t pexe_opt_level_; |
+ const PPP_PexeStreamHandler* stream_handler_; |
+ void* stream_handler_user_data_; |
+ bool success_; |
+ int64_t expected_content_length_; |
+ base::WeakPtrFactory<PexeDownloader> weak_factory_; |
+}; |
+ |
+void StreamPexe(PP_Instance instance, |
+ const char* pexe_url, |
+ int32_t opt_level, |
+ const PPP_PexeStreamHandler* handler, |
+ void* handler_user_data) { |
+ content::PepperPluginInstance* plugin_instance = |
+ content::PepperPluginInstance::Get(instance); |
+ if (!plugin_instance) { |
+ base::MessageLoop::current()->PostTask( |
+ FROM_HERE, |
+ base::Bind(handler->DidFinishStream, |
+ handler_user_data, |
+ static_cast<int32_t>(PP_ERROR_FAILED))); |
+ return; |
+ } |
+ |
+ GURL gurl(pexe_url); |
+ const blink::WebDocument& document = |
+ plugin_instance->GetContainer()->element().document(); |
+ scoped_ptr<blink::WebURLLoader> url_loader( |
+ CreateWebURLLoader(document, gurl)); |
+ PexeDownloader* downloader = new PexeDownloader(instance, |
+ url_loader.Pass(), |
+ pexe_url, |
+ opt_level, |
+ handler, |
+ handler_user_data); |
+ |
+ blink::WebURLRequest url_request = CreateWebURLRequest(document, gurl); |
+ // Mark the request as requesting a PNaCl bitcode file, |
+ // so that component updater can detect this user action. |
+ url_request.addHTTPHeaderField( |
+ blink::WebString::fromUTF8("Accept"), |
+ blink::WebString::fromUTF8("application/x-pnacl, */*")); |
+ downloader->Load(url_request); |
+} |
+ |
const PPB_NaCl_Private nacl_interface = { |
&LaunchSelLdr, |
&StartPpapiProxy, |
@@ -1573,7 +1690,6 @@ const PPB_NaCl_Private nacl_interface = { |
&CreateTemporaryFile, |
&GetNumberOfProcessors, |
&PPIsNonSFIModeEnabled, |
- &GetNexeFd, |
&ReportTranslationFinished, |
&DispatchEvent, |
&ReportLoadSuccess, |
@@ -1603,7 +1719,8 @@ const PPB_NaCl_Private nacl_interface = { |
&ReportSelLdrStatus, |
&LogTranslateTime, |
&OpenManifestEntry, |
- &SetPNaClStartTime |
+ &SetPNaClStartTime, |
+ &StreamPexe |
}; |
} // namespace |