diff options
10 files changed, 265 insertions, 124 deletions
diff --git a/chrome/renderer/pepper/ppb_nacl_private_impl.cc b/chrome/renderer/pepper/ppb_nacl_private_impl.cc index fb4d5f9..3b4607d 100644 --- a/chrome/renderer/pepper/ppb_nacl_private_impl.cc +++ b/chrome/renderer/pepper/ppb_nacl_private_impl.cc @@ -13,6 +13,7 @@ #include "base/rand_util.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/render_messages.h" +#include "chrome/renderer/chrome_render_process_observer.h" #include "content/public/common/content_client.h" #include "content/public/common/content_switches.h" #include "content/public/common/sandbox_init.h" @@ -20,6 +21,7 @@ #include "content/public/renderer/render_view.h" #include "content/public/renderer/renderer_restrict_dispatch_group.h" #include "ipc/ipc_sync_message_filter.h" +#include "ppapi/c/pp_bool.h" #include "ppapi/c/private/pp_file_handle.h" #include "ppapi/c/private/ppb_nacl_private.h" #include "ppapi/native_client/src/trusted/plugin/nacl_entry_points.h" @@ -307,6 +309,10 @@ PP_FileHandle CreateTemporaryFile(PP_Instance instance) { return handle; } +PP_Bool IsOffTheRecord() { + return PP_FromBool(ChromeRenderProcessObserver::is_incognito_process()); +} + const PPB_NaCl_Private nacl_interface = { &LaunchSelLdr, &StartPpapiProxy, @@ -315,7 +321,8 @@ const PPB_NaCl_Private nacl_interface = { &EnableBackgroundSelLdrLaunch, &BrokerDuplicateHandle, &GetReadonlyPnaclFD, - &CreateTemporaryFile + &CreateTemporaryFile, + &IsOffTheRecord }; } // namespace diff --git a/ppapi/api/private/finish_writing_these/ppb_nacl_private.idl b/ppapi/api/private/finish_writing_these/ppb_nacl_private.idl index c490398..f1a23f7 100644 --- a/ppapi/api/private/finish_writing_these/ppb_nacl_private.idl +++ b/ppapi/api/private/finish_writing_these/ppb_nacl_private.idl @@ -8,20 +8,20 @@ #include "ppapi/c/private/pp_file_handle.h" /* PPB_NaCl_Private */ -interface PPB_NaCl_Private_0_7 { +interface PPB_NaCl_Private_0_8 { /* This function launches NaCl's sel_ldr process. On success, the function * returns true, otherwise it returns false. When it returns true, it will * write |socket_count| nacl::Handles to imc_handles. */ - bool LaunchSelLdr([in] PP_Instance instance, - [in] str_t alleged_url, - [in] int32_t socket_count, - [out] mem_t imc_handles); + PP_Bool LaunchSelLdr([in] PP_Instance instance, + [in] str_t alleged_url, + [in] int32_t socket_count, + [out] mem_t imc_handles); /* This function starts the PPAPI proxy so the nexe can communicate with the * browser's renderer process. */ - bool StartPpapiProxy([in] PP_Instance instance); + PP_Bool StartPpapiProxy([in] PP_Instance instance); /* On POSIX systems, this function returns the file descriptor of * /dev/urandom. On non-POSIX systems, this function returns 0. @@ -46,4 +46,8 @@ interface PPB_NaCl_Private_0_7 { * returns a posix handle to that temporary file. */ PP_FileHandle CreateTemporaryFile([in] PP_Instance instance); + + /* Return true if we are off the record. + */ + PP_Bool IsOffTheRecord([in] PP_Instance instance); }; diff --git a/ppapi/c/private/ppb_nacl_private.h b/ppapi/c/private/ppb_nacl_private.h index 8f58f2d..3bdd4ca 100644 --- a/ppapi/c/private/ppb_nacl_private.h +++ b/ppapi/c/private/ppb_nacl_private.h @@ -11,7 +11,7 @@ #include "ppapi/c/pp_stdint.h" #include "ppapi/c/private/pp_file_handle.h" -#define PPB_NACL_PRIVATE_INTERFACE "PPB_NaCl(Private);0.7" +#define PPB_NACL_PRIVATE_INTERFACE "PPB_NaCl(Private);0.8" struct PPB_NaCl_Private { // This function launches NaCl's sel_ldr process. On success, the function @@ -66,6 +66,9 @@ struct PPB_NaCl_Private { // the last handle is closed (or earlier on POSIX systems), and // returns a posix handle to that temporary file. PP_FileHandle (*CreateTemporaryFile)(PP_Instance instance); + + // Return true if we are off the record. + PP_Bool (*IsOffTheRecord)(); }; #endif // PPAPI_C_PRIVATE_PPB_NACL_PRIVATE_H_ diff --git a/ppapi/native_client/src/trusted/plugin/local_temp_file.h b/ppapi/native_client/src/trusted/plugin/local_temp_file.h index 3e3858d..51d2095 100644 --- a/ppapi/native_client/src/trusted/plugin/local_temp_file.h +++ b/ppapi/native_client/src/trusted/plugin/local_temp_file.h @@ -82,7 +82,7 @@ class LocalTempFile { const nacl::string identifier() const { return nacl::string(reinterpret_cast<const char*>(identifier_)); } - const pp::FileIO& write_file_io() const { return *write_io_; } + pp::FileIO* write_file_io() const { return write_io_.get(); } private: NACL_DISALLOW_COPY_AND_ASSIGN(LocalTempFile); diff --git a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc index 3f8d258..7b9c3b5 100644 --- a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc +++ b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc @@ -16,14 +16,15 @@ #include "native_client/src/trusted/plugin/pnacl_translate_thread.h" #include "native_client/src/trusted/plugin/service_runtime.h" #include "native_client/src/trusted/plugin/temporary_file.h" -#include "native_client/src/trusted/service_runtime/include/sys/stat.h" +#include "ppapi/c/pp_bool.h" #include "ppapi/c/pp_errors.h" #include "ppapi/c/ppb_file_io.h" #include "ppapi/cpp/file_io.h" namespace { const char kPnaclTempDir[] = "/.pnacl"; +const uint32_t kCopyBufSize = 512 << 10; } namespace plugin { @@ -182,8 +183,13 @@ PnaclCoordinator* PnaclCoordinator::BitcodeToNative( PnaclCoordinator* coordinator = new PnaclCoordinator(plugin, pexe_url, cache_identity, translate_notify_callback); - PLUGIN_PRINTF(("PnaclCoordinator::BitcodeToNative (manifest=%p)\n", - reinterpret_cast<const void*>(coordinator->manifest_.get()))); + coordinator->off_the_record_ = + plugin->nacl_interface()->IsOffTheRecord(); + PLUGIN_PRINTF(("PnaclCoordinator::BitcodeToNative (manifest=%p, " + "off_the_record=%b)\n", + reinterpret_cast<const void*>(coordinator->manifest_.get()), + coordinator->off_the_record_)); + // Load llc and ld. std::vector<nacl::string> resource_urls; resource_urls.push_back(PnaclUrls::GetLlcUrl()); @@ -234,7 +240,8 @@ PnaclCoordinator::PnaclCoordinator( manifest_(new ExtensionManifest(plugin->url_util())), pexe_url_(pexe_url), cache_identity_(cache_identity), - error_already_reported_(false) { + error_already_reported_(false), + off_the_record_(false) { PLUGIN_PRINTF(("PnaclCoordinator::PnaclCoordinator (this=%p, plugin=%p)\n", static_cast<void*>(this), static_cast<void*>(plugin))); callback_factory_.Initialize(this); @@ -294,51 +301,138 @@ void PnaclCoordinator::ReportPpapiError(int32_t pp_error) { void PnaclCoordinator::TranslateFinished(int32_t pp_error) { PLUGIN_PRINTF(("PnaclCoordinator::TranslateFinished (pp_error=%" NACL_PRId32")\n", pp_error)); - // Save the translate error code, and inspect after cleaning up junk files. - // Note: If there was a surfaway and the file objects were actually - // destroyed, then we are in trouble since the obj_file_, nexe_file_, - // etc. may have been destroyed. - // TODO(jvoung,sehr): Fix. - // If there was an error already set (e.g. pexe load failure) then we want - // to use the first one, (which might be something useful) rather than - // the one from the compiler, (which is always just PP_ERROR_FAILED) - if (translate_finish_error_ == PP_OK) translate_finish_error_ = pp_error; - - // Close the nexe temporary file. - if (nexe_file_ != NULL) { - pp::CompletionCallback cb = - callback_factory_.NewCallback(&PnaclCoordinator::NexeFileWasClosed); - nexe_file_->Close(cb); + // Bail out if there was an earlier error (e.g., pexe load failure). + if (translate_finish_error_ != PP_OK) { + ReportPpapiError(translate_finish_error_); + return; + } + // Bail out if there is an error from the translation thread. + if (pp_error != PP_OK) { + ReportPpapiError(pp_error); + return; + } + + // The nexe is written to the temp_nexe_file_. We must Reset() the file + // pointer to be able to read it again from the beginning. + temp_nexe_file_->Reset(); + + if (cache_identity_ != "" && cached_nexe_file_ != NULL) { + // We are using a cache, but had a cache miss, which is why we did the + // translation. Reset cached_nexe_file_ to have a random name, + // for scratch purposes, before renaming to the final cache_identity_. + cached_nexe_file_.reset(new LocalTempFile(plugin_, file_system_.get(), + nacl::string(kPnaclTempDir))); + pp::CompletionCallback cb = callback_factory_.NewCallback( + &PnaclCoordinator::CachedNexeOpenedForWrite); + cached_nexe_file_->OpenWrite(cb); + } else { + // For now, tolerate bitcode that is missing a cache identity, and + // tolerate the lack of caching in incognito mode. + PLUGIN_PRINTF(("PnaclCoordinator -- not caching.\n")); + NexeReadDidOpen(PP_OK); } } -void PnaclCoordinator::NexeFileWasClosed(int32_t pp_error) { - PLUGIN_PRINTF(("PnaclCoordinator::NexeFileWasClosed (pp_error=%" - NACL_PRId32")\n", pp_error)); +void PnaclCoordinator::CachedNexeOpenedForWrite(int32_t pp_error) { if (pp_error != PP_OK) { - ReportPpapiError(pp_error); + ReportPpapiError(pp_error, "Failed to open cache file for write."); return; } - // Now that cleanup of the obj file is done, check the old TranslateFinished - // error code to see if we should proceed normally or not. - if (translate_finish_error_ != PP_OK) { - pp::CompletionCallback cb = - callback_factory_.NewCallback(&PnaclCoordinator::NexeFileWasDeleted); - nexe_file_->Delete(cb); + + // Copy the contents from temp_nexe_file_ -> cached_nexe_file_, + // then rename the cached_nexe_file_ file to the cache id. + int64_t cur_offset = 0; + nacl::DescWrapper* read_wrapper = temp_nexe_file_->read_wrapper(); + char buf[kCopyBufSize]; + ssize_t num_read = read_wrapper->Read(buf, sizeof buf); + // Hit EOF or something. + if (num_read == 0) { + NexeWasCopiedToCache(PP_OK); return; } + if (num_read < 0) { + PLUGIN_PRINTF(("PnaclCoordinator::CachedNexeOpenedForWrite read failed " + "(error=%"NACL_PRId32")\n", num_read)); + NexeWasCopiedToCache(PP_ERROR_FAILED); + return; + } + pp::CompletionCallback cb = callback_factory_.NewCallback( + &PnaclCoordinator::DidCopyNexeToCachePartial, num_read, cur_offset); + cached_nexe_file_->write_file_io()->Write(cur_offset, buf, num_read, cb); +} - // Rename the nexe file to the cache id. - if (cache_identity_ != "") { - pp::CompletionCallback cb = - callback_factory_.NewCallback(&PnaclCoordinator::NexeFileWasRenamed); - nexe_file_->Rename(cache_identity_, cb); - } else { - // For now tolerate bitcode that is missing a cache identity. - PLUGIN_PRINTF(("PnaclCoordinator -- WARNING: missing cache identity," - " not caching.\n")); - NexeFileWasRenamed(PP_OK); +void PnaclCoordinator::DidCopyNexeToCachePartial(int32_t pp_error, + int32_t num_read_prev, + int64_t cur_offset) { + PLUGIN_PRINTF(("PnaclCoordinator::DidCopyNexeToCachePartial " + "(pp_error=%"NACL_PRId32", num_read_prev=%"NACL_PRId32"" + ", cur_offset=%"NACL_PRId64").\n", + pp_error, num_read_prev, cur_offset)); + // Assume we are done. + if (pp_error == PP_OK) { + NexeWasCopiedToCache(PP_OK); + return; + } + if (pp_error < PP_OK) { + PLUGIN_PRINTF(("PnaclCoordinator::DidCopyNexeToCachePartial failed (err=%" + NACL_PRId32")\n", pp_error)); + NexeWasCopiedToCache(pp_error); + return; } + + // Check if we wrote as much as we read. + nacl::DescWrapper* read_wrapper = temp_nexe_file_->read_wrapper(); + if (pp_error != num_read_prev) { + PLUGIN_PRINTF(("PnaclCoordinator::DidCopyNexeToCachePartial partial " + "write (bytes_written=%"NACL_PRId32" vs " + "read=%"NACL_PRId32")\n", pp_error, num_read_prev)); + CHECK(pp_error < num_read_prev); + // Seek back to re-read the bytes that were not written. + nacl_off64_t seek_result = + read_wrapper->Seek(pp_error - num_read_prev, SEEK_CUR); + if (seek_result < 0) { + PLUGIN_PRINTF(("PnaclCoordinator::DidCopyNexeToCachePartial seek failed " + "(err=%"NACL_PRId64")\n", seek_result)); + NexeWasCopiedToCache(PP_ERROR_FAILED); + return; + } + } + + int64_t next_offset = cur_offset + pp_error; + char buf[kCopyBufSize]; + ssize_t num_read = read_wrapper->Read(buf, sizeof buf); + PLUGIN_PRINTF(("PnaclCoordinator::DidCopyNexeToCachePartial read (bytes=%" + NACL_PRId32")\n", num_read)); + // Hit EOF or something. + if (num_read == 0) { + NexeWasCopiedToCache(PP_OK); + return; + } + if (num_read < 0) { + PLUGIN_PRINTF(("PnaclCoordinator::DidCopyNexeToCachePartial read failed " + "(error=%"NACL_PRId32")\n", num_read)); + NexeWasCopiedToCache(PP_ERROR_FAILED); + return; + } + pp::CompletionCallback cb = callback_factory_.NewCallback( + &PnaclCoordinator::DidCopyNexeToCachePartial, num_read, next_offset); + PLUGIN_PRINTF(("PnaclCoordinator::CopyNexeToCache Writing (bytes=%d, " + "buf=%p, file_io=%p)\n", num_read, buf, + cached_nexe_file_->write_file_io())); + cached_nexe_file_->write_file_io()->Write(next_offset, buf, num_read, cb); +} + +void PnaclCoordinator::NexeWasCopiedToCache(int32_t pp_error) { + if (pp_error != PP_OK) { + // TODO(jvoung): This should probably try to delete the cache file + // before returning... + ReportPpapiError(pp_error, "Failed to copy nexe to cache."); + return; + } + // Rename the cached_nexe_file_ file to the cache id, to finalize. + pp::CompletionCallback cb = + callback_factory_.NewCallback(&PnaclCoordinator::NexeFileWasRenamed); + cached_nexe_file_->Rename(cache_identity_, cb); } void PnaclCoordinator::NexeFileWasRenamed(int32_t pp_error) { @@ -350,11 +444,12 @@ void PnaclCoordinator::NexeFileWasRenamed(int32_t pp_error) { ReportPpapiError(pp_error, "Failed to place cached bitcode translation."); return; } - nexe_file_->FinishRename(); - // Open the nexe temporary file for reading. + + cached_nexe_file_->FinishRename(); + // Open the cache file for reading. pp::CompletionCallback cb = callback_factory_.NewCallback(&PnaclCoordinator::NexeReadDidOpen); - nexe_file_->OpenRead(cb); + cached_nexe_file_->OpenRead(cb); } void PnaclCoordinator::NexeReadDidOpen(int32_t pp_error) { @@ -364,18 +459,17 @@ void PnaclCoordinator::NexeReadDidOpen(int32_t pp_error) { ReportPpapiError(pp_error, "Failed to open translated nexe."); return; } - // Transfer ownership of the nexe wrapper to the coordinator. - translated_fd_.reset(nexe_file_->release_read_wrapper()); + + // Transfer ownership of cache/temp file's wrapper to the coordinator. + if (cached_nexe_file_ != NULL) { + translated_fd_.reset(cached_nexe_file_->release_read_wrapper()); + } else { + translated_fd_.reset(temp_nexe_file_->release_read_wrapper()); + } plugin_->EnqueueProgressEvent(Plugin::kProgressEventProgress); translate_notify_callback_.Run(pp_error); } -void PnaclCoordinator::NexeFileWasDeleted(int32_t pp_error) { - PLUGIN_PRINTF(("PnaclCoordinator::NexeFileWasDeleted (pp_error=%" - NACL_PRId32")\n", pp_error)); - ReportPpapiError(translate_finish_error_); -} - void PnaclCoordinator::ResourcesDidLoad(int32_t pp_error) { PLUGIN_PRINTF(("PnaclCoordinator::ResourcesDidLoad (pp_error=%" NACL_PRId32")\n", pp_error)); @@ -383,12 +477,17 @@ void PnaclCoordinator::ResourcesDidLoad(int32_t pp_error) { ReportPpapiError(pp_error, "resources failed to load."); return; } - // Open the local temporary file system to create the temporary files - // for the object and nexe. - pp::CompletionCallback cb = - callback_factory_.NewCallback(&PnaclCoordinator::FileSystemDidOpen); - if (!file_system_->Open(0, cb)) { - ReportNonPpapiError("failed to open file system."); + + if (!off_the_record_) { + // Open the local temporary FS to see if we get a hit in the cache. + pp::CompletionCallback cb = + callback_factory_.NewCallback(&PnaclCoordinator::FileSystemDidOpen); + if (!file_system_->Open(0, cb)) { + ReportNonPpapiError("failed to open file system."); + } + } else { + // We don't have a cache, so do the non-cached codepath. + CachedFileDidOpen(PP_ERROR_FAILED); } } @@ -399,8 +498,7 @@ void PnaclCoordinator::FileSystemDidOpen(int32_t pp_error) { ReportPpapiError(pp_error, "file system didn't open."); return; } - dir_ref_.reset(new pp::FileRef(*file_system_, - kPnaclTempDir)); + dir_ref_.reset(new pp::FileRef(*file_system_, kPnaclTempDir)); // Attempt to create the directory. pp::CompletionCallback cb = callback_factory_.NewCallback(&PnaclCoordinator::DirectoryWasCreated); @@ -416,12 +514,12 @@ void PnaclCoordinator::DirectoryWasCreated(int32_t pp_error) { return; } if (cache_identity_ != "") { - nexe_file_.reset(new LocalTempFile(plugin_, file_system_.get(), - nacl::string(kPnaclTempDir), - cache_identity_)); + cached_nexe_file_.reset(new LocalTempFile(plugin_, file_system_.get(), + nacl::string(kPnaclTempDir), + cache_identity_)); pp::CompletionCallback cb = callback_factory_.NewCallback(&PnaclCoordinator::CachedFileDidOpen); - nexe_file_->OpenRead(cb); + cached_nexe_file_->OpenRead(cb); } else { // For now, tolerate lack of cache identity... CachedFileDidOpen(PP_ERROR_FAILED); @@ -469,9 +567,9 @@ void PnaclCoordinator::BitcodeStreamDidFinish(int32_t pp_error) { PLUGIN_PRINTF(("PnaclCoordinator::BitcodeStreamDidFinish (pp_error=%" NACL_PRId32")\n", pp_error)); if (pp_error != PP_OK) { - // Defer reporting the error and obj_file/nexe_file cleanup until after - // the translation thread returns, because it may be accessing the - // coordinator's objects or writing to the files. + // Defer reporting the error and cleanup until after the translation + // thread returns, because it may be accessing the coordinator's + // objects or writing to the files. translate_finish_error_ = pp_error; error_info_.SetReport(ERROR_UNKNOWN, nacl::string("PnaclCoordinator: pexe load failed.")); @@ -501,11 +599,10 @@ void PnaclCoordinator::ObjectFileDidOpen(int32_t pp_error) { } // Create the nexe file for connecting ld and sel_ldr. // Start translation when done with this last step of setup! - nexe_file_.reset(new LocalTempFile(plugin_, file_system_.get(), - nacl::string(kPnaclTempDir))); + temp_nexe_file_.reset(new TempFile(plugin_)); pp::CompletionCallback cb = callback_factory_.NewCallback(&PnaclCoordinator::RunTranslate); - nexe_file_->OpenWrite(cb); + temp_nexe_file_->Open(cb); } void PnaclCoordinator::RunTranslate(int32_t pp_error) { @@ -521,7 +618,7 @@ void PnaclCoordinator::RunTranslate(int32_t pp_error) { manifest_.get(), ld_manifest_.get(), obj_file_.get(), - nexe_file_.get(), + temp_nexe_file_.get(), &error_info_, resources_.get(), plugin_); diff --git a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h index 3b3b828..944240e 100644 --- a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h +++ b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h @@ -62,17 +62,18 @@ class TempFile; // The coordinator proceeds through several states. They are // LOAD_TRANSLATOR_BINARIES // Complete when ResourcesDidLoad is invoked. -// OPEN_LOCAL_FILE_SYSTEM -// Complete when FileSystemDidOpen is invoked. -// CREATED_PNACL_TEMP_DIRECTORY -// Complete when DirectoryWasCreated is invoked. -// CACHED_FILE_OPEN -// Complete with success if cached version is available and jump to end. -// Otherwise, proceed with usual pipeline of translation. -// OPEN_TMP_WRITE_FOR_LLC_TO_LD_COMMUNICATION -// Complete when ObjectWriteDidOpen is invoked. -// OPEN_TMP_READ_FOR_LLC_TO_LD_COMMUNICATION -// Complete when ObjectReadDidOpen is invoked. +// +// If cache is enabled: +// OPEN_LOCAL_FILE_SYSTEM +// Complete when FileSystemDidOpen is invoked. +// CREATED_PNACL_TEMP_DIRECTORY +// Complete when DirectoryWasCreated is invoked. +// CACHED_FILE_OPEN +// Complete with success if cached version is available and jump to end. +// Otherwise, proceed with usual pipeline of translation. +// +// OPEN_TMP_FOR_LLC_TO_LD_COMMUNICATION +// Complete when ObjectFileDidOpen is invoked. // OPEN_TMP_FOR_LD_WRITING // Complete when NexeWriteDidOpen is invoked. // PREPARE_PEXE_FOR_STREAMING @@ -81,16 +82,17 @@ class TempFile; // Complete when RunTranslate returns. // TRANSLATION_COMPLETE // Complete when TranslateFinished is invoked. -// CLOSE_OBJECT_FILE -// Complete when ObjectFileWasClosed is invoked. -// DELETE_OBJECT_FILE -// Complete when ObjectFileWasDeleted is invoked. -// CLOSE_NEXE_FILE -// Complete when NexeFileWasClosed is invoked. -// RENAME_NEXE_FILE +// +// If cache is enabled: +// OPEN_CACHE_FOR_WRITE +// Complete when CachedNexeOpenedForWrite is invoked +// COPY_NEXE_TO_CACHE +// Complete when NexeWasCopiedToCache is invoked. +// RENAME_CACHE_FILE // Complete when NexeFileWasRenamed is invoked. +// // OPEN_NEXE_FOR_SEL_LDR -// Complete when NexeReadDidOpen is invoked. +// Complete when NexeReadDidOpen is invoked. class PnaclCoordinator: public CallbackSource<FileStreamData> { public: virtual ~PnaclCoordinator(); @@ -155,21 +157,27 @@ class PnaclCoordinator: public CallbackSource<FileStreamData> { void BitcodeStreamDidFinish(int32_t pp_error); // Invoked when the write descriptor for obj_file_ is created. void ObjectFileDidOpen(int32_t pp_error); - // Invoked when the descriptors for nexe_file_ have been closed. - void NexeFileWasClosed(int32_t pp_error); - // Invoked when the nexe_file_ temporary has been renamed to the nexe name. - void NexeFileWasRenamed(int32_t pp_error); - // Invoked when the read descriptor for nexe_file_ is created. - void NexeReadDidOpen(int32_t pp_error); - // Invoked if there was an error and we've cleaned up the nexe_file_ temp. - void NexeFileWasDeleted(int32_t pp_error); - // Once llc and ld nexes have been loaded and the two temporary files have // been created, this starts the translation. Translation starts two // subprocesses, one for llc and one for ld. void RunTranslate(int32_t pp_error); + // Invoked when translation is finished. void TranslateFinished(int32_t pp_error); + + // If the cache is enabled, open a cache file for write, then copy + // the nexe data from temp_nexe_file_ to> cached_nexe_file_. + // Once the copy is done, we commit it to the cache by renaming the + // cache file to the final name. + void CachedNexeOpenedForWrite(int32_t pp_error); + void DidCopyNexeToCachePartial(int32_t pp_error, int32_t num_read_prev, + int64_t cur_offset); + void NexeWasCopiedToCache(int32_t pp_error); + // Invoked when the nexe_file_ temporary has been renamed to the nexe name. + void NexeFileWasRenamed(int32_t pp_error); + // Invoked when the read descriptor for nexe_file_ is created. + void NexeReadDidOpen(int32_t pp_error); + // Keeps track of the pp_error upon entry to TranslateFinished, // for inspection after cleanup. int32_t translate_finish_error_; @@ -209,8 +217,12 @@ class PnaclCoordinator: public CallbackSource<FileStreamData> { nacl::string cache_identity_; // Object file, produced by the translator and consumed by the linker. nacl::scoped_ptr<TempFile> obj_file_; - // Translated nexe file, produced by the linker and consumed by sel_ldr. - nacl::scoped_ptr<LocalTempFile> nexe_file_; + // Translated nexe file, produced by the linker. + nacl::scoped_ptr<TempFile> temp_nexe_file_; + // Cached nexe file, consumed by sel_ldr. This will be NULL if we do + // not have a writeable cache file. That is currently the case when + // off_the_record_ is true. + nacl::scoped_ptr<LocalTempFile> cached_nexe_file_; // Downloader for streaming translation nacl::scoped_ptr<FileDownloader> streaming_downloader_; @@ -221,6 +233,9 @@ class PnaclCoordinator: public CallbackSource<FileStreamData> { // was already run/consumed. bool error_already_reported_; + // True if compilation is off_the_record. + bool off_the_record_; + // The helper thread used to do translations via SRPC. // Keep this last in declaration order to ensure the other variables // haven't been destroyed yet when its destructor runs. diff --git a/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.cc b/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.cc index 441345a..cd6c43a 100644 --- a/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.cc +++ b/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.cc @@ -33,7 +33,7 @@ void PnaclTranslateThread::RunTranslate( const Manifest* manifest, const Manifest* ld_manifest, TempFile* obj_file, - LocalTempFile* nexe_file, + TempFile* nexe_file, ErrorInfo* error_info, PnaclResources* resources, Plugin* plugin) { @@ -131,7 +131,7 @@ void PnaclTranslateThread::DoTranslate() { } // Run LLC. SrpcParams params; - nacl::DescWrapper* llc_out_file = obj_file_->get_wrapper(); + nacl::DescWrapper* llc_out_file = obj_file_->write_wrapper(); PluginReverseInterface* llc_reverse = llc_subprocess->service_runtime()->rev_interface(); llc_reverse->AddTempQuotaManagedFile(obj_file_->identifier()); @@ -233,12 +233,11 @@ bool PnaclTranslateThread::RunLdSubprocess(int is_shared_library, TranslateFailed("Link process could not reset object file"); return false; } - nacl::DescWrapper* ld_in_file = obj_file_->get_wrapper(); + nacl::DescWrapper* ld_in_file = obj_file_->read_wrapper(); nacl::DescWrapper* ld_out_file = nexe_file_->write_wrapper(); PluginReverseInterface* ld_reverse = ld_subprocess->service_runtime()->rev_interface(); - ld_reverse->AddQuotaManagedFile(nexe_file_->identifier(), - nexe_file_->write_file_io()); + ld_reverse->AddTempQuotaManagedFile(nexe_file_->identifier()); RegisterReverseInterface(ld_reverse); if (!ld_subprocess->InvokeSrpcMethod("RunWithDefaultCommandLine", "hhiss", diff --git a/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.h b/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.h index 76621e5..52f15a3 100644 --- a/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.h +++ b/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.h @@ -25,7 +25,6 @@ class DescWrapper; namespace plugin { -class LocalTempFile; class Manifest; class NaClSubprocess; class Plugin; @@ -43,7 +42,7 @@ class PnaclTranslateThread { const Manifest* manifest, const Manifest* ld_manifest, TempFile* obj_file, - LocalTempFile* nexe_file, + TempFile* nexe_file, ErrorInfo* error_info, PnaclResources* resources, Plugin* plugin); @@ -115,7 +114,7 @@ class PnaclTranslateThread { const Manifest* manifest_; const Manifest* ld_manifest_; TempFile* obj_file_; - LocalTempFile* nexe_file_; + TempFile* nexe_file_; ErrorInfo* coordinator_error_info_; PnaclResources* resources_; Plugin* plugin_; diff --git a/ppapi/native_client/src/trusted/plugin/temporary_file.cc b/ppapi/native_client/src/trusted/plugin/temporary_file.cc index 4cdd04d..7e84c47 100644 --- a/ppapi/native_client/src/trusted/plugin/temporary_file.cc +++ b/ppapi/native_client/src/trusted/plugin/temporary_file.cc @@ -69,16 +69,31 @@ void TempFile::Open(const pp::CompletionCallback& cb) { return; } + // dup the fd to make allow making a non-Quota-based wrapper. + // sel_ldr currently does not allow loading from Quota-backed descs, + // only plain host descs. It's probably good hygiene to separate the + // read wrapper from the write wrapper anyway. + int32_t read_fd = DUP(fd); + if (read_fd == NACL_NO_FILE_DESC) { + PLUGIN_PRINTF(("TempFile::Open DUP failed\n")); + core->CallOnMainThread(0, cb, PP_ERROR_FAILED); + return; + } + // The descriptor for a writeable file needs to have quota management. - wrapper_.reset( - plugin_->wrapper_factory()->MakeFileDescQuota(fd, O_RDWR, identifier_)); + write_wrapper_.reset( + plugin_->wrapper_factory()->MakeFileDescQuota(fd, O_RDWR, identifier_)); + read_wrapper_.reset( + plugin_->wrapper_factory()->MakeFileDesc(fd, O_RDONLY)); core->CallOnMainThread(0, cb, PP_OK); } bool TempFile::Reset() { PLUGIN_PRINTF(("TempFile::Reset\n")); - CHECK(wrapper_.get() != NULL); - nacl_off64_t newpos = wrapper_->Seek(0, SEEK_SET); + // Use the write_wrapper_ to reset the file pos. The read_wrapper_ is also + // backed by the same file, so it should also reset. + CHECK(write_wrapper_.get() != NULL); + nacl_off64_t newpos = write_wrapper_->Seek(0, SEEK_SET); return newpos >= 0; } diff --git a/ppapi/native_client/src/trusted/plugin/temporary_file.h b/ppapi/native_client/src/trusted/plugin/temporary_file.h index 298656d..0fe6d26 100644 --- a/ppapi/native_client/src/trusted/plugin/temporary_file.h +++ b/ppapi/native_client/src/trusted/plugin/temporary_file.h @@ -47,9 +47,10 @@ class TempFile { // Accessors. // The nacl::DescWrapper* for the writeable version of the file. - nacl::DescWrapper* get_wrapper() { return wrapper_.get(); } - nacl::DescWrapper* release_wrapper() { - return wrapper_.release(); + nacl::DescWrapper* write_wrapper() { return write_wrapper_.get(); } + nacl::DescWrapper* read_wrapper() { return read_wrapper_.get(); } + nacl::DescWrapper* release_read_wrapper() { + return read_wrapper_.release(); } // For quota management. @@ -61,7 +62,8 @@ class TempFile { NACL_DISALLOW_COPY_AND_ASSIGN(TempFile); Plugin* plugin_; - nacl::scoped_ptr<nacl::DescWrapper> wrapper_; + nacl::scoped_ptr<nacl::DescWrapper> read_wrapper_; + nacl::scoped_ptr<nacl::DescWrapper> write_wrapper_; // An identifier string used for quota request processing. The quota // interface needs a string that is unique per sel_ldr instance only, so |