#include "base/command_line.h"
#include "base/file_util.h"
+#include "base/files/file_proxy.h"
#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram.h"
#include "base/path_service.h"
const bool kValidationCacheEnabledByDefault = true;
-enum ValidationCacheStatus {
- CACHE_MISS = 0,
- CACHE_HIT,
- CACHE_MAX
-};
-
// Keep the cache bounded to an arbitrary size. If it's too small, useful
// entries could be evicted when multiple .nexes are loaded at once. On the
// other hand, entries are not always claimed (and hence removed), so the size
irt_name.append(FILE_PATH_LITERAL("x86_32"));
#elif defined(ARCH_CPU_ARMEL)
- // TODO(mcgrathr): Eventually we'll need to distinguish arm32 vs thumb2.
- // That may need to be based on the actual nexe rather than a static
- // choice, which would require substantial refactoring.
irt_name.append(FILE_PATH_LITERAL("arm"));
#elif defined(ARCH_CPU_MIPSEL)
irt_name.append(FILE_PATH_LITERAL("mips32"));
}
void WriteCache(const base::FilePath& filename, const Pickle* pickle) {
- file_util::WriteFile(filename, static_cast<const char*>(pickle->data()),
+ base::WriteFile(filename, static_cast<const char*>(pickle->data()),
pickle->size());
}
callback);
}
-void LogCacheQuery(ValidationCacheStatus status) {
- UMA_HISTOGRAM_ENUMERATION("NaCl.ValidationCache.Query", status, CACHE_MAX);
+void LogCacheQuery(nacl::NaClBrowser::ValidationCacheStatus status) {
+ UMA_HISTOGRAM_ENUMERATION("NaCl.ValidationCache.Query", status,
+ nacl::NaClBrowser::CACHE_MAX);
}
-void LogCacheSet(ValidationCacheStatus status) {
+void LogCacheSet(nacl::NaClBrowser::ValidationCacheStatus status) {
// Bucket zero is reserved for future use.
- UMA_HISTOGRAM_ENUMERATION("NaCl.ValidationCache.Set", status, CACHE_MAX);
+ UMA_HISTOGRAM_ENUMERATION("NaCl.ValidationCache.Set", status,
+ nacl::NaClBrowser::CACHE_MAX);
}
// Crash throttling parameters.
namespace nacl {
-base::PlatformFile OpenNaClExecutableImpl(const base::FilePath& file_path) {
+base::File OpenNaClReadExecImpl(const base::FilePath& file_path,
+ bool is_executable) {
// Get a file descriptor. On Windows, we need 'GENERIC_EXECUTE' in order to
// memory map the executable.
// IMPORTANT: This file descriptor must not have write access - that could
// allow a NaCl inner sandbox escape.
- base::PlatformFile file;
- base::PlatformFileError error_code;
- file = base::CreatePlatformFile(
- file_path,
- (base::PLATFORM_FILE_OPEN |
- base::PLATFORM_FILE_READ |
- base::PLATFORM_FILE_EXECUTE), // Windows only flag.
- NULL,
- &error_code);
- if (error_code != base::PLATFORM_FILE_OK)
- return base::kInvalidPlatformFileValue;
+ uint32 flags = base::File::FLAG_OPEN | base::File::FLAG_READ;
+ if (is_executable)
+ flags |= base::File::FLAG_EXECUTE; // Windows only flag.
+ base::File file(file_path, flags);
+ if (!file.IsValid())
+ return file.Pass();
// Check that the file does not reference a directory. Returning a descriptor
// to an extension directory could allow an outer sandbox escape. openat(...)
// could be used to traverse into the file system.
- base::PlatformFileInfo file_info;
- if (!base::GetPlatformFileInfo(file, &file_info) || file_info.is_directory) {
- base::ClosePlatformFile(file);
- return base::kInvalidPlatformFileValue;
- }
- return file;
+ base::File::Info file_info;
+ if (!file.GetInfo(&file_info) || file_info.is_directory)
+ return base::File();
+
+ return file.Pass();
}
NaClBrowser::NaClBrowser()
: weak_factory_(this),
- irt_platform_file_(base::kInvalidPlatformFileValue),
irt_filepath_(),
irt_state_(NaClResourceUninitialized),
validation_cache_file_path_(),
}
NaClBrowser::~NaClBrowser() {
- if (irt_platform_file_ != base::kInvalidPlatformFileValue)
- base::ClosePlatformFile(irt_platform_file_);
}
void NaClBrowser::InitIrtFilePath() {
return ok_;
}
-base::PlatformFile NaClBrowser::IrtFile() const {
+const base::File& NaClBrowser::IrtFile() const {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
CHECK_EQ(irt_state_, NaClResourceReady);
- CHECK_NE(irt_platform_file_, base::kInvalidPlatformFileValue);
- return irt_platform_file_;
+ CHECK(irt_file_.IsValid());
+ return irt_file_;
}
void NaClBrowser::EnsureAllResourcesAvailable() {
if (IsOk() && irt_state_ == NaClResourceUninitialized) {
irt_state_ = NaClResourceRequested;
// TODO(ncbray) use blocking pool.
- if (!base::FileUtilProxy::CreateOrOpen(
- content::BrowserThread::GetMessageLoopProxyForThread(
- content::BrowserThread::FILE)
- .get(),
- irt_filepath_,
- base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ,
- base::Bind(&NaClBrowser::OnIrtOpened,
- weak_factory_.GetWeakPtr()))) {
+ scoped_ptr<base::FileProxy> file_proxy(new base::FileProxy(
+ content::BrowserThread::GetMessageLoopProxyForThread(
+ content::BrowserThread::FILE).get()));
+ base::FileProxy* proxy = file_proxy.get();
+ if (!proxy->CreateOrOpen(irt_filepath_,
+ base::File::FLAG_OPEN | base::File::FLAG_READ,
+ base::Bind(&NaClBrowser::OnIrtOpened,
+ weak_factory_.GetWeakPtr(),
+ Passed(&file_proxy)))) {
LOG(ERROR) << "Internal error, NaCl disabled.";
MarkAsFailed();
}
}
}
-void NaClBrowser::OnIrtOpened(base::File::Error error_code,
- base::PassPlatformFile file,
- bool created) {
+void NaClBrowser::OnIrtOpened(scoped_ptr<base::FileProxy> file_proxy,
+ base::File::Error error_code) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
DCHECK_EQ(irt_state_, NaClResourceRequested);
- DCHECK(!created);
- if (error_code == base::File::FILE_OK) {
- irt_platform_file_ = file.ReleaseValue();
+ if (file_proxy->IsValid()) {
+ irt_file_ = file_proxy->TakeFile();
} else {
LOG(ERROR) << "Failed to open NaCl IRT file \""
<< irt_filepath_.LossyDisplayName()
CheckWaiting();
}
-void NaClBrowser::FireGdbDebugStubPortOpened(int port) {
- content::BrowserThread::PostTask(
- content::BrowserThread::IO,
- FROM_HERE,
- base::Bind(debug_stub_port_listener_, port));
-}
-
-bool NaClBrowser::HasGdbDebugStubPortListener() {
- return !debug_stub_port_listener_.is_null();
+void NaClBrowser::SetProcessGdbDebugStubPort(int process_id, int port) {
+ gdb_debug_stub_port_map_[process_id] = port;
+ if (port != kGdbDebugStubPortUnknown &&
+ !debug_stub_port_listener_.is_null()) {
+ content::BrowserThread::PostTask(
+ content::BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(debug_stub_port_listener_, port));
+ }
}
void NaClBrowser::SetGdbDebugStubPortListener(
debug_stub_port_listener_.Reset();
}
+int NaClBrowser::GetProcessGdbDebugStubPort(int process_id) {
+ GdbDebugStubPortMap::iterator i = gdb_debug_stub_port_map_.find(process_id);
+ if (i != gdb_debug_stub_port_map_.end()) {
+ return i->second;
+ }
+ return kGdbDebugStubPortUnused;
+}
+
void NaClBrowser::InitValidationCacheFilePath() {
// Determine where the validation cache resides in the file system. It
// exists in Chrome's cache directory and is not tied to any specific
validation_cache_is_modified_ = false;
}
+void NaClBrowser::OnProcessEnd(int process_id) {
+ gdb_debug_stub_port_map_.erase(process_id);
+}
+
void NaClBrowser::OnProcessCrashed() {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
if (crash_times_.size() == kMaxCrashesPerInterval) {