Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "components/nacl/browser/pnacl_host.h" | 5 #include "components/nacl/browser/pnacl_host.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
| 9 #include "base/file_util.h" | 9 #include "base/file_util.h" |
| 10 #include "base/files/file_path.h" | 10 #include "base/files/file_path.h" |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/task_runner_util.h" | 12 #include "base/task_runner_util.h" |
| 13 #include "base/threading/sequenced_worker_pool.h" | 13 #include "base/threading/sequenced_worker_pool.h" |
| 14 #include "components/nacl/browser/nacl_browser.h" | 14 #include "components/nacl/browser/nacl_browser.h" |
| 15 #include "components/nacl/browser/pnacl_translation_cache.h" | 15 #include "components/nacl/browser/pnacl_translation_cache.h" |
| 16 #include "content/public/browser/browser_thread.h" | 16 #include "content/public/browser/browser_thread.h" |
| 17 #include "net/base/io_buffer.h" | 17 #include "net/base/io_buffer.h" |
| 18 #include "net/base/net_errors.h" | 18 #include "net/base/net_errors.h" |
| 19 | 19 |
| 20 using content::BrowserThread; | 20 using content::BrowserThread; |
| 21 | 21 |
| 22 namespace { | 22 namespace { |
|
Mark Seaborn
2014/02/14 19:00:08
Nit: add empty line after this so that the start a
rvargas (doing something else)
2014/02/14 19:37:15
oops. done.
| |
| 23 static const base::FilePath::CharType kTranslationCacheDirectoryName[] = | 23 static const base::FilePath::CharType kTranslationCacheDirectoryName[] = |
| 24 FILE_PATH_LITERAL("PnaclTranslationCache"); | 24 FILE_PATH_LITERAL("PnaclTranslationCache"); |
| 25 // Delay to wait for initialization of the cache backend | 25 // Delay to wait for initialization of the cache backend |
| 26 static const int kTranslationCacheInitializationDelayMs = 20; | 26 static const int kTranslationCacheInitializationDelayMs = 20; |
| 27 | |
| 28 void CloseBaseFile(base::File file) { | |
| 29 // Not really needed because the file will go out of scope here. | |
| 30 file.Close(); | |
| 31 } | |
| 32 | |
| 27 } | 33 } |
| 28 | 34 |
| 29 namespace pnacl { | 35 namespace pnacl { |
| 30 | 36 |
| 31 PnaclHost::PnaclHost() | 37 PnaclHost::PnaclHost() |
| 32 : pending_backend_operations_(0), | 38 : pending_backend_operations_(0), |
| 33 cache_state_(CacheUninitialized), | 39 cache_state_(CacheUninitialized), |
| 34 weak_factory_(this) {} | 40 weak_factory_(this) {} |
| 35 | 41 |
| 36 PnaclHost::~PnaclHost() { | 42 PnaclHost::~PnaclHost() { |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 134 | 140 |
| 135 ///////////////////////////////////////// Temp files | 141 ///////////////////////////////////////// Temp files |
| 136 | 142 |
| 137 // Create a temporary file on the blocking pool | 143 // Create a temporary file on the blocking pool |
| 138 // static | 144 // static |
| 139 void PnaclHost::DoCreateTemporaryFile(base::FilePath temp_dir, | 145 void PnaclHost::DoCreateTemporaryFile(base::FilePath temp_dir, |
| 140 TempFileCallback cb) { | 146 TempFileCallback cb) { |
| 141 DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); | 147 DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); |
| 142 | 148 |
| 143 base::FilePath file_path; | 149 base::FilePath file_path; |
| 144 base::PlatformFile file_handle(base::kInvalidPlatformFileValue); | 150 base::File file; |
| 145 bool rv = temp_dir.empty() | 151 bool rv = temp_dir.empty() |
| 146 ? base::CreateTemporaryFile(&file_path) | 152 ? base::CreateTemporaryFile(&file_path) |
| 147 : base::CreateTemporaryFileInDir(temp_dir, &file_path); | 153 : base::CreateTemporaryFileInDir(temp_dir, &file_path); |
| 148 if (!rv) { | 154 if (!rv) { |
| 149 PLOG(ERROR) << "Temp file creation failed."; | 155 PLOG(ERROR) << "Temp file creation failed."; |
| 150 } else { | 156 } else { |
| 151 base::PlatformFileError error; | 157 file.Initialize( |
| 152 file_handle = base::CreatePlatformFile( | |
| 153 file_path, | 158 file_path, |
| 154 base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_READ | | 159 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_READ | |
| 155 base::PLATFORM_FILE_WRITE | base::PLATFORM_FILE_TEMPORARY | | 160 base::File::FLAG_WRITE | base::File::FLAG_TEMPORARY | |
| 156 base::PLATFORM_FILE_DELETE_ON_CLOSE, | 161 base::File::FLAG_DELETE_ON_CLOSE); |
| 157 NULL, | |
| 158 &error); | |
| 159 | 162 |
| 160 if (error != base::PLATFORM_FILE_OK) { | 163 if (!file.IsValid()) |
| 161 PLOG(ERROR) << "Temp file open failed: " << error; | 164 PLOG(ERROR) << "Temp file open failed: " << file.error_details(); |
| 162 file_handle = base::kInvalidPlatformFileValue; | |
| 163 } | |
| 164 } | 165 } |
| 165 BrowserThread::PostTask( | 166 BrowserThread::PostTask( |
| 166 BrowserThread::IO, FROM_HERE, base::Bind(cb, file_handle)); | 167 BrowserThread::IO, FROM_HERE, base::Bind(cb, Passed(file.Pass()))); |
| 167 } | 168 } |
| 168 | 169 |
| 169 void PnaclHost::CreateTemporaryFile(TempFileCallback cb) { | 170 void PnaclHost::CreateTemporaryFile(TempFileCallback cb) { |
| 170 if (!BrowserThread::PostBlockingPoolSequencedTask( | 171 if (!BrowserThread::PostBlockingPoolSequencedTask( |
| 171 "PnaclHostCreateTempFile", | 172 "PnaclHostCreateTempFile", |
| 172 FROM_HERE, | 173 FROM_HERE, |
| 173 base::Bind(&PnaclHost::DoCreateTemporaryFile, temp_dir_, cb))) { | 174 base::Bind(&PnaclHost::DoCreateTemporaryFile, temp_dir_, cb))) { |
| 174 DCHECK(thread_checker_.CalledOnValidThread()); | 175 DCHECK(thread_checker_.CalledOnValidThread()); |
| 175 cb.Run(base::kInvalidPlatformFileValue); | 176 cb.Run(base::File()); |
| 176 } | 177 } |
| 177 } | 178 } |
| 178 | 179 |
| 179 ///////////////////////////////////////// GetNexeFd implementation | 180 ///////////////////////////////////////// GetNexeFd implementation |
| 180 ////////////////////// Common steps | 181 ////////////////////// Common steps |
| 181 | 182 |
| 182 void PnaclHost::GetNexeFd(int render_process_id, | 183 void PnaclHost::GetNexeFd(int render_process_id, |
| 183 int render_view_id, | 184 int render_view_id, |
| 184 int pp_instance, | 185 int pp_instance, |
| 185 bool is_incognito, | 186 bool is_incognito, |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 266 } | 267 } |
| 267 PendingTranslation* pt = &entry->second; | 268 PendingTranslation* pt = &entry->second; |
| 268 pt->got_cache_reply = true; | 269 pt->got_cache_reply = true; |
| 269 pt->got_cache_hit = (net_error == net::OK); | 270 pt->got_cache_hit = (net_error == net::OK); |
| 270 if (pt->got_cache_hit) | 271 if (pt->got_cache_hit) |
| 271 pt->nexe_read_buffer = buffer; | 272 pt->nexe_read_buffer = buffer; |
| 272 CheckCacheQueryReady(entry); | 273 CheckCacheQueryReady(entry); |
| 273 } | 274 } |
| 274 | 275 |
| 275 // Callback from temp file creation. |id| is bound from | 276 // Callback from temp file creation. |id| is bound from |
| 276 // SendCacheQueryAndTempFileRequest, and fd is the created file descriptor. | 277 // SendCacheQueryAndTempFileRequest, and |file| is the created file. |
| 277 // If there was an error, fd is kInvalidPlatformFileValue. | 278 // If there was an error, fd is kInvalidPlatformFileValue. |
| 278 // (Bound callbacks must re-lookup the TranslationID because the translation | 279 // (Bound callbacks must re-lookup the TranslationID because the translation |
| 279 // could be cancelled before they get called). | 280 // could be cancelled before they get called). |
| 280 void PnaclHost::OnTempFileReturn(const TranslationID& id, | 281 void PnaclHost::OnTempFileReturn(const TranslationID& id, |
| 281 base::PlatformFile fd) { | 282 base::File file) { |
| 282 DCHECK(thread_checker_.CalledOnValidThread()); | 283 DCHECK(thread_checker_.CalledOnValidThread()); |
| 283 PendingTranslationMap::iterator entry(pending_translations_.find(id)); | 284 PendingTranslationMap::iterator entry(pending_translations_.find(id)); |
| 284 if (entry == pending_translations_.end()) { | 285 if (entry == pending_translations_.end()) { |
| 285 // The renderer may have signaled an error or closed while the temp | 286 // The renderer may have signaled an error or closed while the temp |
| 286 // file was being created. | 287 // file was being created. |
| 287 LOG(ERROR) << "OnTempFileReturn: id not found"; | 288 LOG(ERROR) << "OnTempFileReturn: id not found"; |
| 288 BrowserThread::PostBlockingPoolTask( | 289 BrowserThread::PostBlockingPoolTask( |
| 289 FROM_HERE, base::Bind(base::IgnoreResult(base::ClosePlatformFile), fd)); | 290 FROM_HERE, base::Bind(CloseBaseFile, Passed(file.Pass()))); |
| 290 return; | 291 return; |
| 291 } | 292 } |
| 292 if (fd == base::kInvalidPlatformFileValue) { | 293 if (!file.IsValid()) { |
| 293 // This translation will fail, but we need to retry any translation | 294 // This translation will fail, but we need to retry any translation |
| 294 // waiting for its result. | 295 // waiting for its result. |
| 295 LOG(ERROR) << "OnTempFileReturn: temp file creation failed"; | 296 LOG(ERROR) << "OnTempFileReturn: temp file creation failed"; |
| 296 std::string key(entry->second.cache_key); | 297 std::string key(entry->second.cache_key); |
| 297 entry->second.callback.Run(fd, false); | 298 entry->second.callback.Run(base::kInvalidPlatformFileValue, false); |
| 298 bool may_be_cached = TranslationMayBeCached(entry); | 299 bool may_be_cached = TranslationMayBeCached(entry); |
| 299 pending_translations_.erase(entry); | 300 pending_translations_.erase(entry); |
| 300 // No translations will be waiting for entries that will not be stored. | 301 // No translations will be waiting for entries that will not be stored. |
| 301 if (may_be_cached) | 302 if (may_be_cached) |
| 302 RequeryMatchingTranslations(key); | 303 RequeryMatchingTranslations(key); |
| 303 return; | 304 return; |
| 304 } | 305 } |
| 305 PendingTranslation* pt = &entry->second; | 306 PendingTranslation* pt = &entry->second; |
| 306 pt->got_nexe_fd = true; | 307 pt->got_nexe_fd = true; |
| 307 pt->nexe_fd = fd; | 308 pt->nexe_fd = file.TakePlatformFile(); |
| 308 CheckCacheQueryReady(entry); | 309 CheckCacheQueryReady(entry); |
| 309 } | 310 } |
| 310 | 311 |
| 311 // Check whether both the cache query and the temp file have returned, and check | 312 // Check whether both the cache query and the temp file have returned, and check |
| 312 // whether we actually got a hit or not. | 313 // whether we actually got a hit or not. |
| 313 void PnaclHost::CheckCacheQueryReady( | 314 void PnaclHost::CheckCacheQueryReady( |
| 314 const PendingTranslationMap::iterator& entry) { | 315 const PendingTranslationMap::iterator& entry) { |
| 315 PendingTranslation* pt = &entry->second; | 316 PendingTranslation* pt = &entry->second; |
| 316 if (!(pt->got_cache_reply && pt->got_nexe_fd)) | 317 if (!(pt->got_cache_reply && pt->got_nexe_fd)) |
| 317 return; | 318 return; |
| (...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 634 DCHECK(pending_backend_operations_ >= 0); | 635 DCHECK(pending_backend_operations_ >= 0); |
| 635 if (pending_translations_.empty() && | 636 if (pending_translations_.empty() && |
| 636 pending_backend_operations_ <= 0 && | 637 pending_backend_operations_ <= 0 && |
| 637 cache_state_ == CacheReady) { | 638 cache_state_ == CacheReady) { |
| 638 cache_state_ = CacheUninitialized; | 639 cache_state_ = CacheUninitialized; |
| 639 disk_cache_.reset(); | 640 disk_cache_.reset(); |
| 640 } | 641 } |
| 641 } | 642 } |
| 642 | 643 |
| 643 } // namespace pnacl | 644 } // namespace pnacl |
| OLD | NEW |