Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(24)

Side by Side Diff: components/nacl/browser/pnacl_host.cc

Issue 2207683002: Use a raw pointer instead of Singleton for PnaclHost and leak it. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@b6_sequenced_worker_pool_redirection
Patch Set: typo Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « components/nacl/browser/pnacl_host.h ('k') | components/nacl/browser/pnacl_host_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 <utility> 7 #include <utility>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/bind_helpers.h" 10 #include "base/bind_helpers.h"
11 #include "base/debug/leak_annotations.h"
11 #include "base/files/file_path.h" 12 #include "base/files/file_path.h"
12 #include "base/files/file_util.h" 13 #include "base/files/file_util.h"
13 #include "base/logging.h" 14 #include "base/logging.h"
14 #include "base/numerics/safe_math.h" 15 #include "base/numerics/safe_math.h"
15 #include "base/task_runner_util.h" 16 #include "base/task_runner_util.h"
16 #include "base/threading/sequenced_worker_pool.h" 17 #include "base/threading/sequenced_worker_pool.h"
17 #include "components/nacl/browser/nacl_browser.h" 18 #include "components/nacl/browser/nacl_browser.h"
18 #include "components/nacl/browser/pnacl_translation_cache.h" 19 #include "components/nacl/browser/pnacl_translation_cache.h"
19 #include "content/public/browser/browser_thread.h" 20 #include "content/public/browser/browser_thread.h"
20 #include "net/base/io_buffer.h" 21 #include "net/base/io_buffer.h"
(...skipping 12 matching lines...) Expand all
33 } 34 }
34 35
35 void CloseScopedFile(std::unique_ptr<base::File> auto_file_closer) {} 36 void CloseScopedFile(std::unique_ptr<base::File> auto_file_closer) {}
36 37
37 } // namespace 38 } // namespace
38 39
39 namespace pnacl { 40 namespace pnacl {
40 41
41 class FileProxy { 42 class FileProxy {
42 public: 43 public:
43 FileProxy(std::unique_ptr<base::File> file, 44 FileProxy(std::unique_ptr<base::File> file, PnaclHost* host);
44 base::WeakPtr<pnacl::PnaclHost> host);
45 int Write(scoped_refptr<net::DrainableIOBuffer> buffer); 45 int Write(scoped_refptr<net::DrainableIOBuffer> buffer);
46 void WriteDone(const PnaclHost::TranslationID& id, int result); 46 void WriteDone(const PnaclHost::TranslationID& id, int result);
47 47
48 private: 48 private:
49 std::unique_ptr<base::File> file_; 49 std::unique_ptr<base::File> file_;
50 base::WeakPtr<pnacl::PnaclHost> host_; 50 PnaclHost* host_;
51 }; 51 };
52 52
53 FileProxy::FileProxy(std::unique_ptr<base::File> file, 53 FileProxy::FileProxy(std::unique_ptr<base::File> file, PnaclHost* host)
54 base::WeakPtr<pnacl::PnaclHost> host)
55 : file_(std::move(file)), host_(host) {} 54 : file_(std::move(file)), host_(host) {}
56 55
57 int FileProxy::Write(scoped_refptr<net::DrainableIOBuffer> buffer) { 56 int FileProxy::Write(scoped_refptr<net::DrainableIOBuffer> buffer) {
58 int rv = file_->Write(0, buffer->data(), buffer->size()); 57 int rv = file_->Write(0, buffer->data(), buffer->size());
59 if (rv == -1) 58 if (rv == -1)
60 PLOG(ERROR) << "FileProxy::Write error"; 59 PLOG(ERROR) << "FileProxy::Write error";
61 return rv; 60 return rv;
62 } 61 }
63 62
64 void FileProxy::WriteDone(const PnaclHost::TranslationID& id, int result) { 63 void FileProxy::WriteDone(const PnaclHost::TranslationID& id, int result) {
65 if (host_) { 64 host_->OnBufferCopiedToTempFile(id, std::move(file_), result);
66 host_->OnBufferCopiedToTempFile(id, std::move(file_), result);
67 } else {
68 BrowserThread::PostBlockingPoolTask(
69 FROM_HERE,
70 base::Bind(CloseScopedFile, Passed(&file_)));
71 }
72 } 65 }
73 66
74 PnaclHost::PnaclHost() 67 PnaclHost::PnaclHost() = default;
75 : pending_backend_operations_(0),
76 cache_state_(CacheUninitialized),
77 weak_factory_(this) {}
78
79 PnaclHost::~PnaclHost() {
80 // When PnaclHost is destroyed, it's too late to post anything to the cache
81 // thread (it will hang shutdown). So just leak the cache backend.
82 pnacl::PnaclTranslationCache* cache = disk_cache_.release();
83 (void)cache;
84 }
85 68
86 PnaclHost* PnaclHost::GetInstance() { 69 PnaclHost* PnaclHost::GetInstance() {
87 return base::Singleton<PnaclHost>::get(); 70 static PnaclHost* instance = nullptr;
71 if (!instance) {
72 instance = new PnaclHost;
73 ANNOTATE_LEAKING_OBJECT_PTR(instance);
74 }
75 return instance;
88 } 76 }
89 77
90 PnaclHost::PendingTranslation::PendingTranslation() 78 PnaclHost::PendingTranslation::PendingTranslation()
91 : process_handle(base::kNullProcessHandle), 79 : process_handle(base::kNullProcessHandle),
92 render_view_id(0), 80 render_view_id(0),
93 nexe_fd(NULL), 81 nexe_fd(NULL),
94 got_nexe_fd(false), 82 got_nexe_fd(false),
95 got_cache_reply(false), 83 got_cache_reply(false),
96 got_cache_hit(false), 84 got_cache_hit(false),
97 is_incognito(false), 85 is_incognito(false),
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 } 137 }
150 138
151 void PnaclHost::Init() { 139 void PnaclHost::Init() {
152 // Extra check that we're on the real IO thread since this version of 140 // Extra check that we're on the real IO thread since this version of
153 // Init isn't used in unit tests. 141 // Init isn't used in unit tests.
154 DCHECK_CURRENTLY_ON(BrowserThread::IO); 142 DCHECK_CURRENTLY_ON(BrowserThread::IO);
155 DCHECK(thread_checker_.CalledOnValidThread()); 143 DCHECK(thread_checker_.CalledOnValidThread());
156 base::FilePath cache_path(GetCachePath()); 144 base::FilePath cache_path(GetCachePath());
157 if (cache_path.empty() || cache_state_ != CacheUninitialized) 145 if (cache_path.empty() || cache_state_ != CacheUninitialized)
158 return; 146 return;
159 disk_cache_.reset(new pnacl::PnaclTranslationCache()); 147 disk_cache_.reset(new PnaclTranslationCache());
160 cache_state_ = CacheInitializing; 148 cache_state_ = CacheInitializing;
161 int rv = disk_cache_->InitOnDisk( 149 int rv = disk_cache_->InitOnDisk(
162 cache_path, 150 cache_path,
163 base::Bind(&PnaclHost::OnCacheInitialized, weak_factory_.GetWeakPtr())); 151 base::Bind(&PnaclHost::OnCacheInitialized, base::Unretained(this)));
164 if (rv != net::ERR_IO_PENDING) 152 if (rv != net::ERR_IO_PENDING)
165 OnCacheInitialized(rv); 153 OnCacheInitialized(rv);
166 } 154 }
167 155
168 // Initialize for testing, optionally using the in-memory backend, and manually 156 // Initialize for testing, optionally using the in-memory backend, and manually
169 // setting the temporary file directory instead of using the system directory. 157 // setting the temporary file directory instead of using the system directory.
170 void PnaclHost::InitForTest(base::FilePath temp_dir, bool in_memory) { 158 void PnaclHost::InitForTest(base::FilePath temp_dir, bool in_memory) {
171 DCHECK(thread_checker_.CalledOnValidThread()); 159 DCHECK(thread_checker_.CalledOnValidThread());
172 disk_cache_.reset(new pnacl::PnaclTranslationCache()); 160 disk_cache_.reset(new PnaclTranslationCache());
173 cache_state_ = CacheInitializing; 161 cache_state_ = CacheInitializing;
174 temp_dir_ = temp_dir; 162 temp_dir_ = temp_dir;
175 int rv; 163 int rv;
176 if (in_memory) { 164 if (in_memory) {
177 rv = disk_cache_->InitInMemory( 165 rv = disk_cache_->InitInMemory(
178 base::Bind(&PnaclHost::OnCacheInitialized, weak_factory_.GetWeakPtr())); 166 base::Bind(&PnaclHost::OnCacheInitialized, base::Unretained(this)));
179 } else { 167 } else {
180 rv = disk_cache_->InitOnDisk( 168 rv = disk_cache_->InitOnDisk(
181 temp_dir, 169 temp_dir,
182 base::Bind(&PnaclHost::OnCacheInitialized, weak_factory_.GetWeakPtr())); 170 base::Bind(&PnaclHost::OnCacheInitialized, base::Unretained(this)));
183 } 171 }
184 if (rv != net::ERR_IO_PENDING) 172 if (rv != net::ERR_IO_PENDING)
185 OnCacheInitialized(rv); 173 OnCacheInitialized(rv);
186 } 174 }
187 175
188 ///////////////////////////////////////// Temp files 176 ///////////////////////////////////////// Temp files
189 177
190 // Create a temporary file on the blocking pool 178 // Create a temporary file on the blocking pool
191 // static 179 // static
192 void PnaclHost::DoCreateTemporaryFile(base::FilePath temp_dir, 180 void PnaclHost::DoCreateTemporaryFile(base::FilePath temp_dir,
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
235 const NexeFdCallback& cb) { 223 const NexeFdCallback& cb) {
236 DCHECK(thread_checker_.CalledOnValidThread()); 224 DCHECK(thread_checker_.CalledOnValidThread());
237 if (cache_state_ == CacheUninitialized) { 225 if (cache_state_ == CacheUninitialized) {
238 Init(); 226 Init();
239 } 227 }
240 if (cache_state_ != CacheReady) { 228 if (cache_state_ != CacheReady) {
241 // If the backend hasn't yet initialized, try the request again later. 229 // If the backend hasn't yet initialized, try the request again later.
242 BrowserThread::PostDelayedTask(BrowserThread::IO, 230 BrowserThread::PostDelayedTask(BrowserThread::IO,
243 FROM_HERE, 231 FROM_HERE,
244 base::Bind(&PnaclHost::GetNexeFd, 232 base::Bind(&PnaclHost::GetNexeFd,
245 weak_factory_.GetWeakPtr(), 233 base::Unretained(this),
246 render_process_id, 234 render_process_id,
247 render_view_id, 235 render_view_id,
248 pp_instance, 236 pp_instance,
249 is_incognito, 237 is_incognito,
250 cache_info, 238 cache_info,
251 cb), 239 cb),
252 base::TimeDelta::FromMilliseconds( 240 base::TimeDelta::FromMilliseconds(
253 kTranslationCacheInitializationDelayMs)); 241 kTranslationCacheInitializationDelayMs));
254 return; 242 return;
255 } 243 }
(...skipping 21 matching lines...) Expand all
277 pt.is_incognito = is_incognito; 265 pt.is_incognito = is_incognito;
278 pending_translations_[id] = pt; 266 pending_translations_[id] = pt;
279 SendCacheQueryAndTempFileRequest(cache_key, id); 267 SendCacheQueryAndTempFileRequest(cache_key, id);
280 } 268 }
281 269
282 // Dispatch the cache read request and the temp file creation request 270 // Dispatch the cache read request and the temp file creation request
283 // simultaneously; currently we need a temp file regardless of whether the 271 // simultaneously; currently we need a temp file regardless of whether the
284 // request hits. 272 // request hits.
285 void PnaclHost::SendCacheQueryAndTempFileRequest(const std::string& cache_key, 273 void PnaclHost::SendCacheQueryAndTempFileRequest(const std::string& cache_key,
286 const TranslationID& id) { 274 const TranslationID& id) {
275 DCHECK(thread_checker_.CalledOnValidThread());
287 pending_backend_operations_++; 276 pending_backend_operations_++;
288 disk_cache_->GetNexe( 277 disk_cache_->GetNexe(cache_key, base::Bind(&PnaclHost::OnCacheQueryReturn,
289 cache_key, 278 base::Unretained(this), id));
290 base::Bind(
291 &PnaclHost::OnCacheQueryReturn, weak_factory_.GetWeakPtr(), id));
292 279
293 CreateTemporaryFile( 280 CreateTemporaryFile(
294 base::Bind(&PnaclHost::OnTempFileReturn, weak_factory_.GetWeakPtr(), id)); 281 base::Bind(&PnaclHost::OnTempFileReturn, base::Unretained(this), id));
295 } 282 }
296 283
297 // Callback from the translation cache query. |id| is bound from 284 // Callback from the translation cache query. |id| is bound from
298 // SendCacheQueryAndTempFileRequest, |net_error| is a net::Error code (which for 285 // SendCacheQueryAndTempFileRequest, |net_error| is a net::Error code (which for
299 // our purposes means a hit if it's net::OK (i.e. 0). |buffer| is allocated 286 // our purposes means a hit if it's net::OK (i.e. 0). |buffer| is allocated
300 // by PnaclTranslationCache and now belongs to PnaclHost. 287 // by PnaclTranslationCache and now belongs to PnaclHost.
301 // (Bound callbacks must re-lookup the TranslationID because the translation 288 // (Bound callbacks must re-lookup the TranslationID because the translation
302 // could be cancelled before they get called). 289 // could be cancelled before they get called).
303 void PnaclHost::OnCacheQueryReturn( 290 void PnaclHost::OnCacheQueryReturn(
304 const TranslationID& id, 291 const TranslationID& id,
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
353 PendingTranslation* pt = &entry->second; 340 PendingTranslation* pt = &entry->second;
354 pt->got_nexe_fd = true; 341 pt->got_nexe_fd = true;
355 pt->nexe_fd = new base::File(std::move(file)); 342 pt->nexe_fd = new base::File(std::move(file));
356 CheckCacheQueryReady(entry); 343 CheckCacheQueryReady(entry);
357 } 344 }
358 345
359 // Check whether both the cache query and the temp file have returned, and check 346 // Check whether both the cache query and the temp file have returned, and check
360 // whether we actually got a hit or not. 347 // whether we actually got a hit or not.
361 void PnaclHost::CheckCacheQueryReady( 348 void PnaclHost::CheckCacheQueryReady(
362 const PendingTranslationMap::iterator& entry) { 349 const PendingTranslationMap::iterator& entry) {
350 DCHECK(thread_checker_.CalledOnValidThread());
363 PendingTranslation* pt = &entry->second; 351 PendingTranslation* pt = &entry->second;
364 if (!(pt->got_cache_reply && pt->got_nexe_fd)) 352 if (!(pt->got_cache_reply && pt->got_nexe_fd))
365 return; 353 return;
366 if (!pt->got_cache_hit) { 354 if (!pt->got_cache_hit) {
367 // Check if there is already a pending translation for this file. If there 355 // Check if there is already a pending translation for this file. If there
368 // is, we will wait for it to come back, to avoid redundant translations. 356 // is, we will wait for it to come back, to avoid redundant translations.
369 for (PendingTranslationMap::iterator it = pending_translations_.begin(); 357 for (PendingTranslationMap::iterator it = pending_translations_.begin();
370 it != pending_translations_.end(); 358 it != pending_translations_.end();
371 ++it) { 359 ++it) {
372 // Another translation matches if it's a request for the same file, 360 // Another translation matches if it's a request for the same file,
373 if (it->second.cache_key == entry->second.cache_key && 361 if (it->second.cache_key == entry->second.cache_key &&
374 // and it's not this translation, 362 // and it's not this translation,
375 it->first != entry->first && 363 it->first != entry->first &&
376 // and it can be stored in the cache, 364 // and it can be stored in the cache,
377 TranslationMayBeCached(it) && 365 TranslationMayBeCached(it) &&
378 // and it's already gotten past this check and returned the miss. 366 // and it's already gotten past this check and returned the miss.
379 it->second.got_cache_reply && 367 it->second.got_cache_reply &&
380 it->second.got_nexe_fd) { 368 it->second.got_nexe_fd) {
381 return; 369 return;
382 } 370 }
383 } 371 }
384 ReturnMiss(entry); 372 ReturnMiss(entry);
385 return; 373 return;
386 } 374 }
387 375
388 std::unique_ptr<base::File> file(pt->nexe_fd); 376 std::unique_ptr<base::File> file(pt->nexe_fd);
389 pt->nexe_fd = NULL; 377 pt->nexe_fd = NULL;
390 pt->got_nexe_fd = false; 378 pt->got_nexe_fd = false;
391 FileProxy* proxy(new FileProxy(std::move(file), weak_factory_.GetWeakPtr())); 379 FileProxy* proxy(new FileProxy(std::move(file), this));
392 380
393 if (!base::PostTaskAndReplyWithResult( 381 if (!base::PostTaskAndReplyWithResult(
394 BrowserThread::GetBlockingPool(), 382 BrowserThread::GetBlockingPool(),
395 FROM_HERE, 383 FROM_HERE,
396 base::Bind(&FileProxy::Write, base::Unretained(proxy), 384 base::Bind(&FileProxy::Write, base::Unretained(proxy),
397 pt->nexe_read_buffer), 385 pt->nexe_read_buffer),
398 base::Bind(&FileProxy::WriteDone, base::Owned(proxy), 386 base::Bind(&FileProxy::WriteDone, base::Owned(proxy),
399 entry->first))) { 387 entry->first))) {
400 pt->callback.Run(base::File(), false); 388 pt->callback.Run(base::File(), false);
401 } 389 }
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
461 // translations. 449 // translations.
462 if (!entry->second.got_nexe_fd || !entry->second.got_cache_reply || 450 if (!entry->second.got_nexe_fd || !entry->second.got_cache_reply ||
463 !success || !TranslationMayBeCached(entry)) { 451 !success || !TranslationMayBeCached(entry)) {
464 store_nexe = false; 452 store_nexe = false;
465 } else { 453 } else {
466 std::unique_ptr<base::File> file(entry->second.nexe_fd); 454 std::unique_ptr<base::File> file(entry->second.nexe_fd);
467 entry->second.nexe_fd = NULL; 455 entry->second.nexe_fd = NULL;
468 entry->second.got_nexe_fd = false; 456 entry->second.got_nexe_fd = false;
469 457
470 if (!base::PostTaskAndReplyWithResult( 458 if (!base::PostTaskAndReplyWithResult(
471 BrowserThread::GetBlockingPool(), 459 BrowserThread::GetBlockingPool(), FROM_HERE,
472 FROM_HERE, 460 base::Bind(&PnaclHost::CopyFileToBuffer, Passed(&file)),
473 base::Bind(&PnaclHost::CopyFileToBuffer, Passed(&file)), 461 base::Bind(&PnaclHost::StoreTranslatedNexe, base::Unretained(this),
474 base::Bind(&PnaclHost::StoreTranslatedNexe, 462 id))) {
475 weak_factory_.GetWeakPtr(),
476 id))) {
477 store_nexe = false; 463 store_nexe = false;
478 } 464 }
479 } 465 }
480 466
481 if (!store_nexe) { 467 if (!store_nexe) {
482 // If store_nexe is true, the fd will be closed by CopyFileToBuffer. 468 // If store_nexe is true, the fd will be closed by CopyFileToBuffer.
483 if (entry->second.got_nexe_fd) { 469 if (entry->second.got_nexe_fd) {
484 std::unique_ptr<base::File> file(entry->second.nexe_fd); 470 std::unique_ptr<base::File> file(entry->second.nexe_fd);
485 entry->second.nexe_fd = NULL; 471 entry->second.nexe_fd = NULL;
486 BrowserThread::PostBlockingPoolTask( 472 BrowserThread::PostBlockingPoolTask(
(...skipping 19 matching lines...) Expand all
506 LOG(ERROR) << "StoreTranslatedNexe: TranslationID " << id.first << "," 492 LOG(ERROR) << "StoreTranslatedNexe: TranslationID " << id.first << ","
507 << id.second << " not found."; 493 << id.second << " not found.";
508 return; 494 return;
509 } 495 }
510 496
511 if (buffer.get() == NULL) { 497 if (buffer.get() == NULL) {
512 LOG(ERROR) << "Error reading translated nexe"; 498 LOG(ERROR) << "Error reading translated nexe";
513 return; 499 return;
514 } 500 }
515 pending_backend_operations_++; 501 pending_backend_operations_++;
516 disk_cache_->StoreNexe(it->second.cache_key, 502 disk_cache_->StoreNexe(it->second.cache_key, buffer.get(),
517 buffer.get(),
518 base::Bind(&PnaclHost::OnTranslatedNexeStored, 503 base::Bind(&PnaclHost::OnTranslatedNexeStored,
519 weak_factory_.GetWeakPtr(), 504 base::Unretained(this), it->first));
520 it->first));
521 } 505 }
522 506
523 // After we know the nexe has been stored, we can clean up, and unblock any 507 // After we know the nexe has been stored, we can clean up, and unblock any
524 // outstanding requests for the same file. 508 // outstanding requests for the same file.
525 // (Bound callbacks must re-lookup the TranslationID because the translation 509 // (Bound callbacks must re-lookup the TranslationID because the translation
526 // could be cancelled before they get called). 510 // could be cancelled before they get called).
527 void PnaclHost::OnTranslatedNexeStored(const TranslationID& id, int net_error) { 511 void PnaclHost::OnTranslatedNexeStored(const TranslationID& id, int net_error) {
528 PendingTranslationMap::iterator entry(pending_translations_.find(id)); 512 PendingTranslationMap::iterator entry(pending_translations_.find(id));
529 pending_backend_operations_--; 513 pending_backend_operations_--;
530 if (entry == pending_translations_.end()) { 514 if (entry == pending_translations_.end()) {
531 // If the renderer closed while we were storing the nexe, we land here. 515 // If the renderer closed while we were storing the nexe, we land here.
532 // Make sure we try to de-init. 516 // Make sure we try to de-init.
533 DeInitIfSafe(); 517 DeInitIfSafe();
534 return; 518 return;
535 } 519 }
536 std::string key(entry->second.cache_key); 520 std::string key(entry->second.cache_key);
537 pending_translations_.erase(entry); 521 pending_translations_.erase(entry);
538 RequeryMatchingTranslations(key); 522 RequeryMatchingTranslations(key);
539 } 523 }
540 524
541 // Check if any pending translations match |key|. If so, re-issue the cache 525 // Check if any pending translations match |key|. If so, re-issue the cache
542 // query. In the overlapped miss case, we expect a hit this time, but a miss 526 // query. In the overlapped miss case, we expect a hit this time, but a miss
543 // is also possible in case of an error. 527 // is also possible in case of an error.
544 void PnaclHost::RequeryMatchingTranslations(const std::string& key) { 528 void PnaclHost::RequeryMatchingTranslations(const std::string& key) {
529 DCHECK(thread_checker_.CalledOnValidThread());
545 // Check for outstanding misses to this same file 530 // Check for outstanding misses to this same file
546 for (PendingTranslationMap::iterator it = pending_translations_.begin(); 531 for (PendingTranslationMap::iterator it = pending_translations_.begin();
547 it != pending_translations_.end(); 532 it != pending_translations_.end();
548 ++it) { 533 ++it) {
549 if (it->second.cache_key == key) { 534 if (it->second.cache_key == key) {
550 // Re-send the cache read request. This time we expect a hit, but if 535 // Re-send the cache read request. This time we expect a hit, but if
551 // something goes wrong, it will just handle it like a miss. 536 // something goes wrong, it will just handle it like a miss.
552 it->second.got_cache_reply = false; 537 it->second.got_cache_reply = false;
553 pending_backend_operations_++; 538 pending_backend_operations_++;
554 disk_cache_->GetNexe(key, 539 disk_cache_->GetNexe(key, base::Bind(&PnaclHost::OnCacheQueryReturn,
555 base::Bind(&PnaclHost::OnCacheQueryReturn, 540 base::Unretained(this), it->first));
556 weak_factory_.GetWeakPtr(),
557 it->first));
558 } 541 }
559 } 542 }
560 } 543 }
561 544
562 //////////////////// GetNexeFd hit path 545 //////////////////// GetNexeFd hit path
563 546
564 void PnaclHost::OnBufferCopiedToTempFile(const TranslationID& id, 547 void PnaclHost::OnBufferCopiedToTempFile(const TranslationID& id,
565 std::unique_ptr<base::File> file, 548 std::unique_ptr<base::File> file,
566 int file_error) { 549 int file_error) {
567 DCHECK(thread_checker_.CalledOnValidThread()); 550 DCHECK(thread_checker_.CalledOnValidThread());
568 PendingTranslationMap::iterator entry(pending_translations_.find(id)); 551 PendingTranslationMap::iterator entry(pending_translations_.find(id));
569 if (entry == pending_translations_.end()) { 552 if (entry == pending_translations_.end()) {
570 BrowserThread::PostBlockingPoolTask( 553 BrowserThread::PostBlockingPoolTask(
571 FROM_HERE, 554 FROM_HERE,
572 base::Bind(CloseScopedFile, Passed(&file))); 555 base::Bind(CloseScopedFile, Passed(&file)));
573 return; 556 return;
574 } 557 }
575 if (file_error == -1) { 558 if (file_error == -1) {
576 // Write error on the temp file. Request a new file and start over. 559 // Write error on the temp file. Request a new file and start over.
577 BrowserThread::PostBlockingPoolTask( 560 BrowserThread::PostBlockingPoolTask(
578 FROM_HERE, 561 FROM_HERE,
579 base::Bind(CloseScopedFile, Passed(&file))); 562 base::Bind(CloseScopedFile, Passed(&file)));
580 CreateTemporaryFile(base::Bind(&PnaclHost::OnTempFileReturn, 563 CreateTemporaryFile(base::Bind(&PnaclHost::OnTempFileReturn,
581 weak_factory_.GetWeakPtr(), 564 base::Unretained(this), entry->first));
582 entry->first));
583 return; 565 return;
584 } 566 }
585 entry->second.callback.Run(*file.get(), true); 567 entry->second.callback.Run(*file.get(), true);
586 BrowserThread::PostBlockingPoolTask( 568 BrowserThread::PostBlockingPoolTask(
587 FROM_HERE, 569 FROM_HERE,
588 base::Bind(CloseScopedFile, Passed(&file))); 570 base::Bind(CloseScopedFile, Passed(&file)));
589 pending_translations_.erase(entry); 571 pending_translations_.erase(entry);
590 } 572 }
591 573
592 /////////////////// 574 ///////////////////
(...skipping 14 matching lines...) Expand all
607 base::Bind(CloseScopedFile, Passed(&file))); 589 base::Bind(CloseScopedFile, Passed(&file)));
608 std::string key(to_erase->second.cache_key); 590 std::string key(to_erase->second.cache_key);
609 bool may_be_cached = TranslationMayBeCached(to_erase); 591 bool may_be_cached = TranslationMayBeCached(to_erase);
610 pending_translations_.erase(to_erase); 592 pending_translations_.erase(to_erase);
611 // No translations will be waiting for entries that will not be stored. 593 // No translations will be waiting for entries that will not be stored.
612 if (may_be_cached) 594 if (may_be_cached)
613 RequeryMatchingTranslations(key); 595 RequeryMatchingTranslations(key);
614 } 596 }
615 } 597 }
616 BrowserThread::PostTask( 598 BrowserThread::PostTask(
617 BrowserThread::IO, 599 BrowserThread::IO, FROM_HERE,
618 FROM_HERE, 600 base::Bind(&PnaclHost::DeInitIfSafe, base::Unretained(this)));
619 base::Bind(&PnaclHost::DeInitIfSafe, weak_factory_.GetWeakPtr()));
620 } 601 }
621 602
622 ////////////////// Cache data removal 603 ////////////////// Cache data removal
623 void PnaclHost::ClearTranslationCacheEntriesBetween( 604 void PnaclHost::ClearTranslationCacheEntriesBetween(
624 base::Time initial_time, 605 base::Time initial_time,
625 base::Time end_time, 606 base::Time end_time,
626 const base::Closure& callback) { 607 const base::Closure& callback) {
627 DCHECK(thread_checker_.CalledOnValidThread()); 608 DCHECK(thread_checker_.CalledOnValidThread());
628 if (cache_state_ == CacheUninitialized) { 609 if (cache_state_ == CacheUninitialized) {
629 Init(); 610 Init();
630 } 611 }
631 if (cache_state_ == CacheInitializing) { 612 if (cache_state_ == CacheInitializing) {
632 // If the backend hasn't yet initialized, try the request again later. 613 // If the backend hasn't yet initialized, try the request again later.
633 BrowserThread::PostDelayedTask( 614 BrowserThread::PostDelayedTask(
634 BrowserThread::IO, 615 BrowserThread::IO, FROM_HERE,
635 FROM_HERE,
636 base::Bind(&PnaclHost::ClearTranslationCacheEntriesBetween, 616 base::Bind(&PnaclHost::ClearTranslationCacheEntriesBetween,
637 weak_factory_.GetWeakPtr(), 617 base::Unretained(this), initial_time, end_time, callback),
638 initial_time,
639 end_time,
640 callback),
641 base::TimeDelta::FromMilliseconds( 618 base::TimeDelta::FromMilliseconds(
642 kTranslationCacheInitializationDelayMs)); 619 kTranslationCacheInitializationDelayMs));
643 return; 620 return;
644 } 621 }
645 pending_backend_operations_++; 622 pending_backend_operations_++;
646 int rv = disk_cache_->DoomEntriesBetween( 623 int rv = disk_cache_->DoomEntriesBetween(
647 initial_time, 624 initial_time, end_time, base::Bind(&PnaclHost::OnEntriesDoomed,
648 end_time, 625 base::Unretained(this), callback));
649 base::Bind(
650 &PnaclHost::OnEntriesDoomed, weak_factory_.GetWeakPtr(), callback));
651 if (rv != net::ERR_IO_PENDING) 626 if (rv != net::ERR_IO_PENDING)
652 OnEntriesDoomed(callback, rv); 627 OnEntriesDoomed(callback, rv);
653 } 628 }
654 629
655 void PnaclHost::OnEntriesDoomed(const base::Closure& callback, int net_error) { 630 void PnaclHost::OnEntriesDoomed(const base::Closure& callback, int net_error) {
656 DCHECK(thread_checker_.CalledOnValidThread()); 631 DCHECK(thread_checker_.CalledOnValidThread());
657 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, callback); 632 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, callback);
658 pending_backend_operations_--; 633 pending_backend_operations_--;
659 // When clearing the cache, the UI is blocked on all the cache-clearing 634 // When clearing the cache, the UI is blocked on all the cache-clearing
660 // operations, and freeing the backend actually blocks the IO thread. So 635 // operations, and freeing the backend actually blocks the IO thread. So
661 // instead of calling DeInitIfSafe directly, post it for later. 636 // instead of calling DeInitIfSafe directly, post it for later.
662 BrowserThread::PostTask( 637 BrowserThread::PostTask(
663 BrowserThread::IO, 638 BrowserThread::IO, FROM_HERE,
664 FROM_HERE, 639 base::Bind(&PnaclHost::DeInitIfSafe, base::Unretained(this)));
665 base::Bind(&PnaclHost::DeInitIfSafe, weak_factory_.GetWeakPtr()));
666 } 640 }
667 641
668 // Destroying the cache backend causes it to post tasks to the cache thread to 642 // Destroying the cache backend causes it to post tasks to the cache thread to
669 // flush to disk. Because PnaclHost is a singleton, it does not get destroyed 643 // flush to disk. PnaclHost is leaked on shutdown because registering it as a
670 // until all the browser threads have gone away and it's too late to post 644 // Singleton with AtExitManager would result in it not being destroyed until all
671 // anything (attempting to do so hangs shutdown). So we make sure to destroy it 645 // the browser threads have gone away and it's too late to post anything
672 // when we no longer have any outstanding operations that need it. These include 646 // (attempting to do so hangs shutdown) at that point anyways. So we make sure
673 // pending translations, cache clear requests, and requests to read or write 647 // to destroy it when we no longer have any outstanding operations that need it.
674 // translated nexes. We check when renderers close, when cache clear requests 648 // These include pending translations, cache clear requests, and requests to
675 // finish, and when backend operations complete. 649 // read or write translated nexes. We check when renderers close, when cache
650 // clear requests finish, and when backend operations complete.
676 651
677 // It is not safe to delete the backend while it is initializing, nor if it has 652 // It is not safe to delete the backend while it is initializing, nor if it has
678 // outstanding entry open requests; it is in theory safe to delete it with 653 // outstanding entry open requests; it is in theory safe to delete it with
679 // outstanding read/write requests, but because that distinction is hidden 654 // outstanding read/write requests, but because that distinction is hidden
680 // inside PnaclTranslationCache, we do not delete the backend if there are any 655 // inside PnaclTranslationCache, we do not delete the backend if there are any
681 // backend requests in flight. As a last resort in the destructor, we just leak 656 // backend requests in flight. As a last resort in the destructor, we just leak
682 // the backend to avoid hanging shutdown. 657 // the backend to avoid hanging shutdown.
683 void PnaclHost::DeInitIfSafe() { 658 void PnaclHost::DeInitIfSafe() {
684 DCHECK(pending_backend_operations_ >= 0); 659 DCHECK(pending_backend_operations_ >= 0);
685 if (pending_translations_.empty() && 660 if (pending_translations_.empty() &&
686 pending_backend_operations_ <= 0 && 661 pending_backend_operations_ <= 0 &&
687 cache_state_ == CacheReady) { 662 cache_state_ == CacheReady) {
688 cache_state_ = CacheUninitialized; 663 cache_state_ = CacheUninitialized;
689 disk_cache_.reset(); 664 disk_cache_.reset();
690 } 665 }
691 } 666 }
692 667
693 } // namespace pnacl 668 } // namespace pnacl
OLDNEW
« no previous file with comments | « components/nacl/browser/pnacl_host.h ('k') | components/nacl/browser/pnacl_host_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698