Commit 979b48da authored by jvoung@google.com's avatar jvoung@google.com

Retry "Add an interface for PNaCl to check if the session is incognito..."

(previously 149749).

Again, we use the interface to use the cache when available, or to
load from a temporary file in incognito, when the cache is not available.

Differences from previous try:
* double-fd-close bug.
* compiler warnings that show up in scons build.

BUG= http://code.google.com/p/nativeclient/issues/detail?id=2683

Review URL: https://chromiumcodereview.appspot.com/10834173

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@150093 0039d316-1c4b-4281-b951-d872f2087c98
parent 81e513a9
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "base/rand_util.h" #include "base/rand_util.h"
#include "chrome/common/chrome_switches.h" #include "chrome/common/chrome_switches.h"
#include "chrome/common/render_messages.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_client.h"
#include "content/public/common/content_switches.h" #include "content/public/common/content_switches.h"
#include "content/public/common/sandbox_init.h" #include "content/public/common/sandbox_init.h"
...@@ -20,6 +21,7 @@ ...@@ -20,6 +21,7 @@
#include "content/public/renderer/render_view.h" #include "content/public/renderer/render_view.h"
#include "content/public/renderer/renderer_restrict_dispatch_group.h" #include "content/public/renderer/renderer_restrict_dispatch_group.h"
#include "ipc/ipc_sync_message_filter.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/pp_file_handle.h"
#include "ppapi/c/private/ppb_nacl_private.h" #include "ppapi/c/private/ppb_nacl_private.h"
#include "ppapi/native_client/src/trusted/plugin/nacl_entry_points.h" #include "ppapi/native_client/src/trusted/plugin/nacl_entry_points.h"
...@@ -307,6 +309,10 @@ PP_FileHandle CreateTemporaryFile(PP_Instance instance) { ...@@ -307,6 +309,10 @@ PP_FileHandle CreateTemporaryFile(PP_Instance instance) {
return handle; return handle;
} }
PP_Bool IsOffTheRecord() {
return PP_FromBool(ChromeRenderProcessObserver::is_incognito_process());
}
const PPB_NaCl_Private nacl_interface = { const PPB_NaCl_Private nacl_interface = {
&LaunchSelLdr, &LaunchSelLdr,
&StartPpapiProxy, &StartPpapiProxy,
...@@ -315,7 +321,8 @@ const PPB_NaCl_Private nacl_interface = { ...@@ -315,7 +321,8 @@ const PPB_NaCl_Private nacl_interface = {
&EnableBackgroundSelLdrLaunch, &EnableBackgroundSelLdrLaunch,
&BrokerDuplicateHandle, &BrokerDuplicateHandle,
&GetReadonlyPnaclFD, &GetReadonlyPnaclFD,
&CreateTemporaryFile &CreateTemporaryFile,
&IsOffTheRecord
}; };
} // namespace } // namespace
......
...@@ -8,20 +8,20 @@ ...@@ -8,20 +8,20 @@
#include "ppapi/c/private/pp_file_handle.h" #include "ppapi/c/private/pp_file_handle.h"
/* PPB_NaCl_Private */ /* 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 /* This function launches NaCl's sel_ldr process. On success, the function
* returns true, otherwise it returns false. When it returns true, it will * returns true, otherwise it returns false. When it returns true, it will
* write |socket_count| nacl::Handles to imc_handles. * write |socket_count| nacl::Handles to imc_handles.
*/ */
bool LaunchSelLdr([in] PP_Instance instance, PP_Bool LaunchSelLdr([in] PP_Instance instance,
[in] str_t alleged_url, [in] str_t alleged_url,
[in] int32_t socket_count, [in] int32_t socket_count,
[out] mem_t imc_handles); [out] mem_t imc_handles);
/* This function starts the PPAPI proxy so the nexe can communicate with the /* This function starts the PPAPI proxy so the nexe can communicate with the
* browser's renderer process. * 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 /* On POSIX systems, this function returns the file descriptor of
* /dev/urandom. On non-POSIX systems, this function returns 0. * /dev/urandom. On non-POSIX systems, this function returns 0.
...@@ -46,4 +46,8 @@ interface PPB_NaCl_Private_0_7 { ...@@ -46,4 +46,8 @@ interface PPB_NaCl_Private_0_7 {
* returns a posix handle to that temporary file. * returns a posix handle to that temporary file.
*/ */
PP_FileHandle CreateTemporaryFile([in] PP_Instance instance); PP_FileHandle CreateTemporaryFile([in] PP_Instance instance);
/* Return true if we are off the record.
*/
PP_Bool IsOffTheRecord([in] PP_Instance instance);
}; };
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
#include "ppapi/c/pp_stdint.h" #include "ppapi/c/pp_stdint.h"
#include "ppapi/c/private/pp_file_handle.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 { struct PPB_NaCl_Private {
// This function launches NaCl's sel_ldr process. On success, the function // This function launches NaCl's sel_ldr process. On success, the function
...@@ -66,6 +66,9 @@ struct PPB_NaCl_Private { ...@@ -66,6 +66,9 @@ struct PPB_NaCl_Private {
// the last handle is closed (or earlier on POSIX systems), and // the last handle is closed (or earlier on POSIX systems), and
// returns a posix handle to that temporary file. // returns a posix handle to that temporary file.
PP_FileHandle (*CreateTemporaryFile)(PP_Instance instance); 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_ #endif // PPAPI_C_PRIVATE_PPB_NACL_PRIVATE_H_
...@@ -82,7 +82,7 @@ class LocalTempFile { ...@@ -82,7 +82,7 @@ class LocalTempFile {
const nacl::string identifier() const { const nacl::string identifier() const {
return nacl::string(reinterpret_cast<const char*>(identifier_)); 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: private:
NACL_DISALLOW_COPY_AND_ASSIGN(LocalTempFile); NACL_DISALLOW_COPY_AND_ASSIGN(LocalTempFile);
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "native_client/src/include/checked_cast.h"
#include "native_client/src/include/portability_io.h" #include "native_client/src/include/portability_io.h"
#include "native_client/src/shared/platform/nacl_check.h" #include "native_client/src/shared/platform/nacl_check.h"
#include "native_client/src/trusted/plugin/local_temp_file.h" #include "native_client/src/trusted/plugin/local_temp_file.h"
...@@ -16,14 +17,15 @@ ...@@ -16,14 +17,15 @@
#include "native_client/src/trusted/plugin/pnacl_translate_thread.h" #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/service_runtime.h"
#include "native_client/src/trusted/plugin/temporary_file.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/pp_errors.h"
#include "ppapi/c/ppb_file_io.h" #include "ppapi/c/ppb_file_io.h"
#include "ppapi/cpp/file_io.h" #include "ppapi/cpp/file_io.h"
namespace { namespace {
const char kPnaclTempDir[] = "/.pnacl"; const char kPnaclTempDir[] = "/.pnacl";
const uint32_t kCopyBufSize = 512 << 10;
} }
namespace plugin { namespace plugin {
...@@ -182,8 +184,13 @@ PnaclCoordinator* PnaclCoordinator::BitcodeToNative( ...@@ -182,8 +184,13 @@ PnaclCoordinator* PnaclCoordinator::BitcodeToNative(
PnaclCoordinator* coordinator = PnaclCoordinator* coordinator =
new PnaclCoordinator(plugin, pexe_url, new PnaclCoordinator(plugin, pexe_url,
cache_identity, translate_notify_callback); cache_identity, translate_notify_callback);
PLUGIN_PRINTF(("PnaclCoordinator::BitcodeToNative (manifest=%p)\n", coordinator->off_the_record_ =
reinterpret_cast<const void*>(coordinator->manifest_.get()))); 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. // Load llc and ld.
std::vector<nacl::string> resource_urls; std::vector<nacl::string> resource_urls;
resource_urls.push_back(PnaclUrls::GetLlcUrl()); resource_urls.push_back(PnaclUrls::GetLlcUrl());
...@@ -234,7 +241,8 @@ PnaclCoordinator::PnaclCoordinator( ...@@ -234,7 +241,8 @@ PnaclCoordinator::PnaclCoordinator(
manifest_(new ExtensionManifest(plugin->url_util())), manifest_(new ExtensionManifest(plugin->url_util())),
pexe_url_(pexe_url), pexe_url_(pexe_url),
cache_identity_(cache_identity), 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", PLUGIN_PRINTF(("PnaclCoordinator::PnaclCoordinator (this=%p, plugin=%p)\n",
static_cast<void*>(this), static_cast<void*>(plugin))); static_cast<void*>(this), static_cast<void*>(plugin)));
callback_factory_.Initialize(this); callback_factory_.Initialize(this);
...@@ -294,51 +302,140 @@ void PnaclCoordinator::ReportPpapiError(int32_t pp_error) { ...@@ -294,51 +302,140 @@ void PnaclCoordinator::ReportPpapiError(int32_t pp_error) {
void PnaclCoordinator::TranslateFinished(int32_t pp_error) { void PnaclCoordinator::TranslateFinished(int32_t pp_error) {
PLUGIN_PRINTF(("PnaclCoordinator::TranslateFinished (pp_error=%" PLUGIN_PRINTF(("PnaclCoordinator::TranslateFinished (pp_error=%"
NACL_PRId32")\n", pp_error)); NACL_PRId32")\n", pp_error));
// Save the translate error code, and inspect after cleaning up junk files. // Bail out if there was an earlier error (e.g., pexe load failure).
// Note: If there was a surfaway and the file objects were actually if (translate_finish_error_ != PP_OK) {
// destroyed, then we are in trouble since the obj_file_, nexe_file_, ReportPpapiError(translate_finish_error_);
// etc. may have been destroyed. return;
// TODO(jvoung,sehr): Fix. }
// If there was an error already set (e.g. pexe load failure) then we want // Bail out if there is an error from the translation thread.
// to use the first one, (which might be something useful) rather than if (pp_error != PP_OK) {
// the one from the compiler, (which is always just PP_ERROR_FAILED) ReportPpapiError(pp_error);
if (translate_finish_error_ == PP_OK) translate_finish_error_ = pp_error; return;
}
// Close the nexe temporary file.
if (nexe_file_ != NULL) { // The nexe is written to the temp_nexe_file_. We must Reset() the file
pp::CompletionCallback cb = // pointer to be able to read it again from the beginning.
callback_factory_.NewCallback(&PnaclCoordinator::NexeFileWasClosed); temp_nexe_file_->Reset();
nexe_file_->Close(cb);
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) { void PnaclCoordinator::CachedNexeOpenedForWrite(int32_t pp_error) {
PLUGIN_PRINTF(("PnaclCoordinator::NexeFileWasClosed (pp_error=%"
NACL_PRId32")\n", pp_error));
if (pp_error != PP_OK) { if (pp_error != PP_OK) {
ReportPpapiError(pp_error); ReportPpapiError(pp_error, "Failed to open cache file for write.");
return; 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. // Copy the contents from temp_nexe_file_ -> cached_nexe_file_,
if (translate_finish_error_ != PP_OK) { // then rename the cached_nexe_file_ file to the cache id.
pp::CompletionCallback cb = int64_t cur_offset = 0;
callback_factory_.NewCallback(&PnaclCoordinator::NexeFileWasDeleted); nacl::DescWrapper* read_wrapper = temp_nexe_file_->read_wrapper();
nexe_file_->Delete(cb); char buf[kCopyBufSize];
int32_t num_read =
nacl::assert_cast<int32_t>(read_wrapper->Read(buf, sizeof buf));
// Hit EOF or something.
if (num_read == 0) {
NexeWasCopiedToCache(PP_OK);
return; 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. void PnaclCoordinator::DidCopyNexeToCachePartial(int32_t pp_error,
if (cache_identity_ != "") { int32_t num_read_prev,
pp::CompletionCallback cb = int64_t cur_offset) {
callback_factory_.NewCallback(&PnaclCoordinator::NexeFileWasRenamed); PLUGIN_PRINTF(("PnaclCoordinator::DidCopyNexeToCachePartial "
nexe_file_->Rename(cache_identity_, cb); "(pp_error=%"NACL_PRId32", num_read_prev=%"NACL_PRId32""
} else { ", cur_offset=%"NACL_PRId64").\n",
// For now tolerate bitcode that is missing a cache identity. pp_error, num_read_prev, cur_offset));
PLUGIN_PRINTF(("PnaclCoordinator -- WARNING: missing cache identity," // Assume we are done.
" not caching.\n")); if (pp_error == PP_OK) {
NexeFileWasRenamed(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];
int32_t num_read =
nacl::assert_cast<int32_t>(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=%"NACL_PRId32", 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) { void PnaclCoordinator::NexeFileWasRenamed(int32_t pp_error) {
...@@ -350,11 +447,12 @@ void PnaclCoordinator::NexeFileWasRenamed(int32_t pp_error) { ...@@ -350,11 +447,12 @@ void PnaclCoordinator::NexeFileWasRenamed(int32_t pp_error) {
ReportPpapiError(pp_error, "Failed to place cached bitcode translation."); ReportPpapiError(pp_error, "Failed to place cached bitcode translation.");
return; return;
} }
nexe_file_->FinishRename();
// Open the nexe temporary file for reading. cached_nexe_file_->FinishRename();
// Open the cache file for reading.
pp::CompletionCallback cb = pp::CompletionCallback cb =
callback_factory_.NewCallback(&PnaclCoordinator::NexeReadDidOpen); callback_factory_.NewCallback(&PnaclCoordinator::NexeReadDidOpen);
nexe_file_->OpenRead(cb); cached_nexe_file_->OpenRead(cb);
} }
void PnaclCoordinator::NexeReadDidOpen(int32_t pp_error) { void PnaclCoordinator::NexeReadDidOpen(int32_t pp_error) {
...@@ -364,18 +462,17 @@ void PnaclCoordinator::NexeReadDidOpen(int32_t pp_error) { ...@@ -364,18 +462,17 @@ void PnaclCoordinator::NexeReadDidOpen(int32_t pp_error) {
ReportPpapiError(pp_error, "Failed to open translated nexe."); ReportPpapiError(pp_error, "Failed to open translated nexe.");
return; 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); plugin_->EnqueueProgressEvent(Plugin::kProgressEventProgress);
translate_notify_callback_.Run(pp_error); 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) { void PnaclCoordinator::ResourcesDidLoad(int32_t pp_error) {
PLUGIN_PRINTF(("PnaclCoordinator::ResourcesDidLoad (pp_error=%" PLUGIN_PRINTF(("PnaclCoordinator::ResourcesDidLoad (pp_error=%"
NACL_PRId32")\n", pp_error)); NACL_PRId32")\n", pp_error));
...@@ -383,12 +480,17 @@ void PnaclCoordinator::ResourcesDidLoad(int32_t pp_error) { ...@@ -383,12 +480,17 @@ void PnaclCoordinator::ResourcesDidLoad(int32_t pp_error) {
ReportPpapiError(pp_error, "resources failed to load."); ReportPpapiError(pp_error, "resources failed to load.");
return; return;
} }
// Open the local temporary file system to create the temporary files
// for the object and nexe. if (!off_the_record_) {
pp::CompletionCallback cb = // Open the local temporary FS to see if we get a hit in the cache.
callback_factory_.NewCallback(&PnaclCoordinator::FileSystemDidOpen); pp::CompletionCallback cb =
if (!file_system_->Open(0, cb)) { callback_factory_.NewCallback(&PnaclCoordinator::FileSystemDidOpen);
ReportNonPpapiError("failed to open file system."); 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 +501,7 @@ void PnaclCoordinator::FileSystemDidOpen(int32_t pp_error) { ...@@ -399,8 +501,7 @@ void PnaclCoordinator::FileSystemDidOpen(int32_t pp_error) {
ReportPpapiError(pp_error, "file system didn't open."); ReportPpapiError(pp_error, "file system didn't open.");
return; return;
} }
dir_ref_.reset(new pp::FileRef(*file_system_, dir_ref_.reset(new pp::FileRef(*file_system_, kPnaclTempDir));
kPnaclTempDir));
// Attempt to create the directory. // Attempt to create the directory.
pp::CompletionCallback cb = pp::CompletionCallback cb =
callback_factory_.NewCallback(&PnaclCoordinator::DirectoryWasCreated); callback_factory_.NewCallback(&PnaclCoordinator::DirectoryWasCreated);
...@@ -416,12 +517,12 @@ void PnaclCoordinator::DirectoryWasCreated(int32_t pp_error) { ...@@ -416,12 +517,12 @@ void PnaclCoordinator::DirectoryWasCreated(int32_t pp_error) {
return; return;
} }
if (cache_identity_ != "") { if (cache_identity_ != "") {
nexe_file_.reset(new LocalTempFile(plugin_, file_system_.get(), cached_nexe_file_.reset(new LocalTempFile(plugin_, file_system_.get(),
nacl::string(kPnaclTempDir), nacl::string(kPnaclTempDir),
cache_identity_)); cache_identity_));
pp::CompletionCallback cb = pp::CompletionCallback cb =
callback_factory_.NewCallback(&PnaclCoordinator::CachedFileDidOpen); callback_factory_.NewCallback(&PnaclCoordinator::CachedFileDidOpen);
nexe_file_->OpenRead(cb); cached_nexe_file_->OpenRead(cb);
} else { } else {
// For now, tolerate lack of cache identity... // For now, tolerate lack of cache identity...
CachedFileDidOpen(PP_ERROR_FAILED); CachedFileDidOpen(PP_ERROR_FAILED);
...@@ -467,9 +568,9 @@ void PnaclCoordinator::BitcodeStreamDidFinish(int32_t pp_error) { ...@@ -467,9 +568,9 @@ void PnaclCoordinator::BitcodeStreamDidFinish(int32_t pp_error) {
PLUGIN_PRINTF(("PnaclCoordinator::BitcodeStreamDidFinish (pp_error=%" PLUGIN_PRINTF(("PnaclCoordinator::BitcodeStreamDidFinish (pp_error=%"
NACL_PRId32")\n", pp_error)); NACL_PRId32")\n", pp_error));
if (pp_error != PP_OK) { if (pp_error != PP_OK) {
// Defer reporting the error and obj_file/nexe_file cleanup until after // Defer reporting the error and cleanup until after the translation
// the translation thread returns, because it may be accessing the // thread returns, because it may be accessing the coordinator's
// coordinator's objects or writing to the files. // objects or writing to the files.
translate_finish_error_ = pp_error; translate_finish_error_ = pp_error;
error_info_.SetReport(ERROR_UNKNOWN, error_info_.SetReport(ERROR_UNKNOWN,
nacl::string("PnaclCoordinator: pexe load failed.")); nacl::string("PnaclCoordinator: pexe load failed."));
...@@ -499,11 +600,10 @@ void PnaclCoordinator::ObjectFileDidOpen(int32_t pp_error) { ...@@ -499,11 +600,10 @@ void PnaclCoordinator::ObjectFileDidOpen(int32_t pp_error) {
} }
// Create the nexe file for connecting ld and sel_ldr. // Create the nexe file for connecting ld and sel_ldr.
// Start translation when done with this last step of setup! // Start translation when done with this last step of setup!
nexe_file_.reset(new LocalTempFile(plugin_, file_system_.get(), temp_nexe_file_.reset(new TempFile(plugin_));
nacl::string(kPnaclTempDir)));
pp::CompletionCallback cb = pp::CompletionCallback cb =
callback_factory_.NewCallback(&PnaclCoordinator::RunTranslate); callback_factory_.NewCallback(&PnaclCoordinator::RunTranslate);
nexe_file_->OpenWrite(cb); temp_nexe_file_->Open(cb);
} }
void PnaclCoordinator::RunTranslate(int32_t pp_error) { void PnaclCoordinator::RunTranslate(int32_t pp_error) {
...@@ -519,7 +619,7 @@ void PnaclCoordinator::RunTranslate(int32_t pp_error) { ...@@ -519,7 +619,7 @@ void PnaclCoordinator::RunTranslate(int32_t pp_error) {
manifest_.get(), manifest_.get(),
ld_manifest_.get(), ld_manifest_.get(),
obj_file_.get(), obj_file_.get(),
nexe_file_.get(), temp_nexe_file_.get(),
&error_info_, &error_info_,
resources_.get(), resources_.get(),
plugin_); plugin_);
......
...@@ -62,17 +62,18 @@ class TempFile; ...@@ -62,17 +62,18 @@ class TempFile;
// The coordinator proceeds through several states. They are // The coordinator proceeds through several states. They are
// LOAD_TRANSLATOR_BINARIES // LOAD_TRANSLATOR_BINARIES
// Complete when ResourcesDidLoad is invoked. // Complete when ResourcesDidLoad is invoked.
// OPEN_LOCAL_FILE_SYSTEM //
// Complete when FileSystemDidOpen is invoked. // If cache is enabled:
// CREATED_PNACL_TEMP_DIRECTORY // OPEN_LOCAL_FILE_SYSTEM
// Complete when DirectoryWasCreated is invoked. // Complete when FileSystemDidOpen is invoked.
// CACHED_FILE_OPEN // CREATED_PNACL_TEMP_DIRECTORY
// Complete with success if cached version is available and jump to end. // Complete when DirectoryWasCreated is invoked.
// Otherwise, proceed with usual pipeline of translation. // CACHED_FILE_OPEN
// OPEN_TMP_WRITE_FOR_LLC_TO_LD_COMMUNICATION // Complete with success if cached version is available and jump to end.
// Complete when ObjectWriteDidOpen is invoked. // Otherwise, proceed with usual pipeline of translation.
// OPEN_TMP_READ_FOR_LLC_TO_LD_COMMUNICATION //
// Complete when ObjectReadDidOpen is invoked. // OPEN_TMP_FOR_LLC_TO_LD_COMMUNICATION
// Complete when ObjectFileDidOpen is invoked.
// OPEN_TMP_FOR_LD_WRITING // OPEN_TMP_FOR_LD_WRITING
// Complete when NexeWriteDidOpen is invoked. // Complete when NexeWriteDidOpen is invoked.
// PREPARE_PEXE_FOR_STREAMING // PREPARE_PEXE_FOR_STREAMING
...@@ -81,16 +82,17 @@ class TempFile; ...@@ -81,16 +82,17 @@ class TempFile;
// Complete when RunTranslate returns. // Complete when RunTranslate returns.
// TRANSLATION_COMPLETE // TRANSLATION_COMPLETE
// Complete when TranslateFinished is invoked. // Complete when TranslateFinished is invoked.
// CLOSE_OBJECT_FILE //
// Complete when ObjectFileWasClosed is invoked. // If cache is enabled:
// DELETE_OBJECT_FILE // OPEN_CACHE_FOR_WRITE
// Complete when ObjectFileWasDeleted is invoked. // Complete when CachedNexeOpenedForWrite is invoked
// CLOSE_NEXE_FILE // COPY_NEXE_TO_CACHE
// Complete when NexeFileWasClosed is invoked. // Complete when NexeWasCopiedToCache is invoked.
// RENAME_NEXE_FILE // RENAME_CACHE_FILE
// Complete when NexeFileWasRenamed is invoked. // Complete when NexeFileWasRenamed is invoked.
//
// OPEN_NEXE_FOR_SEL_LDR // OPEN_NEXE_FOR_SEL_LDR
// Complete when NexeReadDidOpen is invoked. // Complete when NexeReadDidOpen is invoked.
class PnaclCoordinator: public CallbackSource<FileStreamData> { class PnaclCoordinator: public CallbackSource<FileStreamData> {
public: public:
virtual ~PnaclCoordinator(); virtual ~PnaclCoordinator();
...@@ -155,21 +157,27 @@ class PnaclCoordinator: public CallbackSource<FileStreamData> { ...@@ -155,21 +157,27 @@ class PnaclCoordinator: public CallbackSource<FileStreamData> {
void BitcodeStreamDidFinish(int32_t pp_error); void BitcodeStreamDidFinish(int32_t pp_error);
// Invoked when the write descriptor for obj_file_ is created. // Invoked when the write descriptor for obj_file_ is created.
void ObjectFileDidOpen(int32_t pp_error); 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 // Once llc and ld nexes have been loaded and the two temporary files have
// been created, this starts the translation. Translation starts two // been created, this starts the translation. Translation starts two
// subprocesses, one for llc and one for ld. // subprocesses, one for llc and one for ld.
void RunTranslate(int32_t pp_error); void RunTranslate(int32_t pp_error);
// Invoked when translation is finished.
void TranslateFinished(int32_t pp_error); 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, // Keeps track of the pp_error upon entry to TranslateFinished,
// for inspection after cleanup. // for inspection after cleanup.
int32_t translate_finish_error_; int32_t translate_finish_error_;
...@@ -209,8 +217,12 @@ class PnaclCoordinator: public CallbackSource<FileStreamData> { ...@@ -209,8 +217,12 @@ class PnaclCoordinator: public CallbackSource<FileStreamData> {
nacl::string cache_identity_; nacl::string cache_identity_;
// Object file, produced by the translator and consumed by the linker. // Object file, produced by the translator and consumed by the linker.
nacl::scoped_ptr<TempFile> obj_file_; nacl::scoped_ptr<TempFile> obj_file_;
// Translated nexe file, produced by the linker and consumed by sel_ldr. // Translated nexe file, produced by the linker.
nacl::scoped_ptr<LocalTempFile> nexe_file_; 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 // Downloader for streaming translation
nacl::scoped_ptr<FileDownloader> streaming_downloader_; nacl::scoped_ptr<FileDownloader> streaming_downloader_;
...@@ -221,6 +233,9 @@ class PnaclCoordinator: public CallbackSource<FileStreamData> { ...@@ -221,6 +233,9 @@ class PnaclCoordinator: public CallbackSource<FileStreamData> {
// was already run/consumed. // was already run/consumed.
bool error_already_reported_; bool error_already_reported_;
// True if compilation is off_the_record.
bool off_the_record_;
// The helper thread used to do translations via SRPC. // The helper thread used to do translations via SRPC.
// Keep this last in declaration order to ensure the other variables // Keep this last in declaration order to ensure the other variables
// haven't been destroyed yet when its destructor runs. // haven't been destroyed yet when its destructor runs.
......
...@@ -33,7 +33,7 @@ void PnaclTranslateThread::RunTranslate( ...@@ -33,7 +33,7 @@ void PnaclTranslateThread::RunTranslate(
const Manifest* manifest, const Manifest* manifest,
const Manifest* ld_manifest, const Manifest* ld_manifest,
TempFile* obj_file, TempFile* obj_file,
LocalTempFile* nexe_file, TempFile* nexe_file,
ErrorInfo* error_info, ErrorInfo* error_info,
PnaclResources* resources, PnaclResources* resources,
Plugin* plugin) { Plugin* plugin) {
...@@ -123,7 +123,7 @@ void WINAPI PnaclTranslateThread::DoTranslateThread(void* arg) { ...@@ -123,7 +123,7 @@ void WINAPI PnaclTranslateThread::DoTranslateThread(void* arg) {
void PnaclTranslateThread::DoTranslate() { void PnaclTranslateThread::DoTranslate() {
ErrorInfo error_info; ErrorInfo error_info;
SrpcParams params; SrpcParams params;
nacl::DescWrapper* llc_out_file = obj_file_->get_wrapper(); nacl::DescWrapper* llc_out_file = obj_file_->write_wrapper();
{ {
nacl::MutexLocker ml(&subprocess_mu_); nacl::MutexLocker ml(&subprocess_mu_);
...@@ -233,7 +233,7 @@ bool PnaclTranslateThread::RunLdSubprocess(int is_shared_library, ...@@ -233,7 +233,7 @@ bool PnaclTranslateThread::RunLdSubprocess(int is_shared_library,
TranslateFailed("Link process could not reset object file"); TranslateFailed("Link process could not reset object file");
return false; 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(); nacl::DescWrapper* ld_out_file = nexe_file_->write_wrapper();
{ {
...@@ -249,8 +249,7 @@ bool PnaclTranslateThread::RunLdSubprocess(int is_shared_library, ...@@ -249,8 +249,7 @@ bool PnaclTranslateThread::RunLdSubprocess(int is_shared_library,
ld_subprocess_active_ = true; ld_subprocess_active_ = true;
PluginReverseInterface* ld_reverse = PluginReverseInterface* ld_reverse =
ld_subprocess_->service_runtime()->rev_interface(); ld_subprocess_->service_runtime()->rev_interface();
ld_reverse->AddQuotaManagedFile(nexe_file_->identifier(), ld_reverse->AddTempQuotaManagedFile(nexe_file_->identifier());
nexe_file_->write_file_io());
} }
// Run LD. // Run LD.
if (!ld_subprocess_->InvokeSrpcMethod("RunWithDefaultCommandLine", if (!ld_subprocess_->InvokeSrpcMethod("RunWithDefaultCommandLine",
......
...@@ -25,7 +25,6 @@ class DescWrapper; ...@@ -25,7 +25,6 @@ class DescWrapper;
namespace plugin { namespace plugin {
class LocalTempFile;
class Manifest; class Manifest;
class NaClSubprocess; class NaClSubprocess;
class Plugin; class Plugin;
...@@ -43,7 +42,7 @@ class PnaclTranslateThread { ...@@ -43,7 +42,7 @@ class PnaclTranslateThread {
const Manifest* manifest, const Manifest* manifest,
const Manifest* ld_manifest, const Manifest* ld_manifest,
TempFile* obj_file, TempFile* obj_file,
LocalTempFile* nexe_file, TempFile* nexe_file,
ErrorInfo* error_info, ErrorInfo* error_info,
PnaclResources* resources, PnaclResources* resources,
Plugin* plugin); Plugin* plugin);
...@@ -108,7 +107,7 @@ class PnaclTranslateThread { ...@@ -108,7 +107,7 @@ class PnaclTranslateThread {
const Manifest* manifest_; const Manifest* manifest_;
const Manifest* ld_manifest_; const Manifest* ld_manifest_;
TempFile* obj_file_; TempFile* obj_file_;
LocalTempFile* nexe_file_; TempFile* nexe_file_;
ErrorInfo* coordinator_error_info_; ErrorInfo* coordinator_error_info_;
PnaclResources* resources_; PnaclResources* resources_;
Plugin* plugin_; Plugin* plugin_;
......
...@@ -69,16 +69,31 @@ void TempFile::Open(const pp::CompletionCallback& cb) { ...@@ -69,16 +69,31 @@ void TempFile::Open(const pp::CompletionCallback& cb) {
return; 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. // The descriptor for a writeable file needs to have quota management.
wrapper_.reset( write_wrapper_.reset(
plugin_->wrapper_factory()->MakeFileDescQuota(fd, O_RDWR, identifier_)); plugin_->wrapper_factory()->MakeFileDescQuota(fd, O_RDWR, identifier_));
read_wrapper_.reset(
plugin_->wrapper_factory()->MakeFileDesc(read_fd, O_RDONLY));
core->CallOnMainThread(0, cb, PP_OK); core->CallOnMainThread(0, cb, PP_OK);
} }
bool TempFile::Reset() { bool TempFile::Reset() {
PLUGIN_PRINTF(("TempFile::Reset\n")); PLUGIN_PRINTF(("TempFile::Reset\n"));
CHECK(wrapper_.get() != NULL); // Use the write_wrapper_ to reset the file pos. The read_wrapper_ is also
nacl_off64_t newpos = wrapper_->Seek(0, SEEK_SET); // 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; return newpos >= 0;
} }
......
...@@ -47,9 +47,10 @@ class TempFile { ...@@ -47,9 +47,10 @@ class TempFile {
// Accessors. // Accessors.
// The nacl::DescWrapper* for the writeable version of the file. // The nacl::DescWrapper* for the writeable version of the file.
nacl::DescWrapper* get_wrapper() { return wrapper_.get(); } nacl::DescWrapper* write_wrapper() { return write_wrapper_.get(); }
nacl::DescWrapper* release_wrapper() { nacl::DescWrapper* read_wrapper() { return read_wrapper_.get(); }
return wrapper_.release(); nacl::DescWrapper* release_read_wrapper() {
return read_wrapper_.release();
} }
// For quota management. // For quota management.
...@@ -61,7 +62,8 @@ class TempFile { ...@@ -61,7 +62,8 @@ class TempFile {
NACL_DISALLOW_COPY_AND_ASSIGN(TempFile); NACL_DISALLOW_COPY_AND_ASSIGN(TempFile);
Plugin* plugin_; 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 // An identifier string used for quota request processing. The quota
// interface needs a string that is unique per sel_ldr instance only, so // interface needs a string that is unique per sel_ldr instance only, so
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment