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

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

Issue 2630443003: Add thread checks to NaClBrowser, and make it leaky (Closed)
Patch Set: Move SetDelegate(nullptr) to ClearAndDeleteDelegateForTest() Created 3 years, 11 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
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/nacl_browser.h" 5 #include "components/nacl/browser/nacl_browser.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include "base/command_line.h" 9 #include "base/command_line.h"
10 #include "base/files/file_proxy.h" 10 #include "base/files/file_proxy.h"
11 #include "base/files/file_util.h" 11 #include "base/files/file_util.h"
12 #include "base/lazy_instance.h"
12 #include "base/location.h" 13 #include "base/location.h"
13 #include "base/metrics/histogram_macros.h" 14 #include "base/metrics/histogram_macros.h"
14 #include "base/path_service.h" 15 #include "base/path_service.h"
15 #include "base/pickle.h" 16 #include "base/pickle.h"
16 #include "base/rand_util.h" 17 #include "base/rand_util.h"
17 #include "base/single_thread_task_runner.h" 18 #include "base/single_thread_task_runner.h"
18 #include "base/threading/thread_task_runner_handle.h" 19 #include "base/threading/thread_task_runner_handle.h"
19 #include "base/time/time.h" 20 #include "base/time/time.h"
20 #include "build/build_config.h" 21 #include "build/build_config.h"
21 #include "content/public/browser/browser_thread.h" 22 #include "content/public/browser/browser_thread.h"
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
111 void LogCacheSet(nacl::NaClBrowser::ValidationCacheStatus status) { 112 void LogCacheSet(nacl::NaClBrowser::ValidationCacheStatus status) {
112 // Bucket zero is reserved for future use. 113 // Bucket zero is reserved for future use.
113 UMA_HISTOGRAM_ENUMERATION("NaCl.ValidationCache.Set", status, 114 UMA_HISTOGRAM_ENUMERATION("NaCl.ValidationCache.Set", status,
114 nacl::NaClBrowser::CACHE_MAX); 115 nacl::NaClBrowser::CACHE_MAX);
115 } 116 }
116 117
117 // Crash throttling parameters. 118 // Crash throttling parameters.
118 const size_t kMaxCrashesPerInterval = 3; 119 const size_t kMaxCrashesPerInterval = 3;
119 const int64_t kCrashesIntervalInSeconds = 120; 120 const int64_t kCrashesIntervalInSeconds = 120;
120 121
122 // Holds the NaClBrowserDelegate, which is leaked on shutdown.
123 NaClBrowserDelegate* g_browser_delegate = nullptr;
124
121 } // namespace 125 } // namespace
122 126
123 namespace nacl { 127 namespace nacl {
124 128
125 base::File OpenNaClReadExecImpl(const base::FilePath& file_path, 129 base::File OpenNaClReadExecImpl(const base::FilePath& file_path,
126 bool is_executable) { 130 bool is_executable) {
127 // Get a file descriptor. On Windows, we need 'GENERIC_EXECUTE' in order to 131 // Get a file descriptor. On Windows, we need 'GENERIC_EXECUTE' in order to
128 // memory map the executable. 132 // memory map the executable.
129 // IMPORTANT: This file descriptor must not have write access - that could 133 // IMPORTANT: This file descriptor must not have write access - that could
130 // allow a NaCl inner sandbox escape. 134 // allow a NaCl inner sandbox escape.
(...skipping 15 matching lines...) Expand all
146 } 150 }
147 151
148 NaClBrowser::NaClBrowser() 152 NaClBrowser::NaClBrowser()
149 : irt_filepath_(), 153 : irt_filepath_(),
150 irt_state_(NaClResourceUninitialized), 154 irt_state_(NaClResourceUninitialized),
151 validation_cache_file_path_(), 155 validation_cache_file_path_(),
152 validation_cache_is_enabled_(false), 156 validation_cache_is_enabled_(false),
153 validation_cache_is_modified_(false), 157 validation_cache_is_modified_(false),
154 validation_cache_state_(NaClResourceUninitialized), 158 validation_cache_state_(NaClResourceUninitialized),
155 path_cache_(kFilePathCacheSize), 159 path_cache_(kFilePathCacheSize),
156 ok_(true), 160 has_failed_(false) {
157 weak_factory_(this) {
158 #if !defined(OS_ANDROID) 161 #if !defined(OS_ANDROID)
159 validation_cache_is_enabled_ = 162 validation_cache_is_enabled_ =
160 CheckEnvVar("NACL_VALIDATION_CACHE", 163 CheckEnvVar("NACL_VALIDATION_CACHE",
161 kValidationCacheEnabledByDefault); 164 kValidationCacheEnabledByDefault);
162 #endif 165 #endif
166 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
163 } 167 }
164 168
165 void NaClBrowser::SetDelegate(NaClBrowserDelegate* delegate) { 169 void NaClBrowser::SetDelegate(std::unique_ptr<NaClBrowserDelegate> delegate) {
166 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); 170 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
Wez 2017/01/14 01:53:11 bradnelson: Turns out that this breaks several tes
167 nacl_browser->browser_delegate_.reset(delegate); 171 DCHECK(delegate);
172 DCHECK(!g_browser_delegate);
173 g_browser_delegate = delegate.release();
168 } 174 }
169 175
170 NaClBrowserDelegate* NaClBrowser::GetDelegate() { 176 NaClBrowserDelegate* NaClBrowser::GetDelegate() {
171 // The delegate is not owned by the IO thread. This accessor method can be 177 // NaClBrowser calls this on the IO thread, not the UI thread.
172 // called from other threads. 178 DCHECK(g_browser_delegate);
173 DCHECK(GetInstance()->browser_delegate_.get() != NULL); 179 return g_browser_delegate;
174 return GetInstance()->browser_delegate_.get(); 180 }
181
182 void NaClBrowser::ClearAndDeleteDelegateForTest() {
183 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
184 DCHECK(g_browser_delegate);
185 delete g_browser_delegate;
186 g_browser_delegate = nullptr;
175 } 187 }
176 188
177 void NaClBrowser::EarlyStartup() { 189 void NaClBrowser::EarlyStartup() {
178 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 190 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
179 InitIrtFilePath(); 191 InitIrtFilePath();
180 InitValidationCacheFilePath(); 192 InitValidationCacheFilePath();
181 } 193 }
182 194
183 NaClBrowser::~NaClBrowser() { 195 NaClBrowser::~NaClBrowser() {
196 NOTREACHED();
184 } 197 }
185 198
186 void NaClBrowser::InitIrtFilePath() { 199 void NaClBrowser::InitIrtFilePath() {
187 // Allow the IRT library to be overridden via an environment 200 // Allow the IRT library to be overridden via an environment
188 // variable. This allows the NaCl/Chromium integration bot to 201 // variable. This allows the NaCl/Chromium integration bot to
189 // specify a newly-built IRT rather than using a prebuilt one 202 // specify a newly-built IRT rather than using a prebuilt one
190 // downloaded via Chromium's DEPS file. We use the same environment 203 // downloaded via Chromium's DEPS file. We use the same environment
191 // variable that the standalone NaCl PPAPI plugin accepts. 204 // variable that the standalone NaCl PPAPI plugin accepts.
192 const char* irt_path_var = getenv("NACL_IRT_LIBRARY"); 205 const char* irt_path_var = getenv("NACL_IRT_LIBRARY");
193 if (irt_path_var != NULL) { 206 if (irt_path_var != NULL) {
194 base::FilePath::StringType path_string( 207 base::FilePath::StringType path_string(
195 irt_path_var, const_cast<const char*>(strchr(irt_path_var, '\0'))); 208 irt_path_var, const_cast<const char*>(strchr(irt_path_var, '\0')));
196 irt_filepath_ = base::FilePath(path_string); 209 irt_filepath_ = base::FilePath(path_string);
197 } else { 210 } else {
198 base::FilePath plugin_dir; 211 base::FilePath plugin_dir;
199 if (!browser_delegate_->GetPluginDirectory(&plugin_dir)) { 212 if (!GetDelegate()->GetPluginDirectory(&plugin_dir)) {
200 DLOG(ERROR) << "Failed to locate the plugins directory, NaCl disabled."; 213 DLOG(ERROR) << "Failed to locate the plugins directory, NaCl disabled.";
201 MarkAsFailed(); 214 MarkAsFailed();
202 return; 215 return;
203 } 216 }
204 irt_filepath_ = plugin_dir.Append(NaClIrtName()); 217 irt_filepath_ = plugin_dir.Append(NaClIrtName());
205 } 218 }
206 } 219 }
207 220
208 #if defined(OS_WIN) 221 #if defined(OS_WIN)
209 bool NaClBrowser::GetNaCl64ExePath(base::FilePath* exe_path) { 222 bool NaClBrowser::GetNaCl64ExePath(base::FilePath* exe_path) {
223 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
210 base::FilePath module_path; 224 base::FilePath module_path;
211 if (!PathService::Get(base::FILE_MODULE, &module_path)) { 225 if (!PathService::Get(base::FILE_MODULE, &module_path)) {
212 LOG(ERROR) << "NaCl process launch failed: could not resolve module"; 226 LOG(ERROR) << "NaCl process launch failed: could not resolve module";
213 return false; 227 return false;
214 } 228 }
215 *exe_path = module_path.DirName().Append(L"nacl64"); 229 *exe_path = module_path.DirName().Append(L"nacl64");
216 return true; 230 return true;
217 } 231 }
218 #endif 232 #endif
219 233
220 NaClBrowser* NaClBrowser::GetInstance() { 234 NaClBrowser* NaClBrowser::GetInstance() {
221 return base::Singleton<NaClBrowser>::get(); 235 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
236 static NaClBrowser* g_instance = nullptr;
237 if (!g_instance)
238 g_instance = new NaClBrowser();
239 return g_instance;
222 } 240 }
223 241
224 bool NaClBrowser::IsReady() const { 242 bool NaClBrowser::IsReady() const {
243 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
225 return (IsOk() && 244 return (IsOk() &&
226 irt_state_ == NaClResourceReady && 245 irt_state_ == NaClResourceReady &&
227 validation_cache_state_ == NaClResourceReady); 246 validation_cache_state_ == NaClResourceReady);
228 } 247 }
229 248
230 bool NaClBrowser::IsOk() const { 249 bool NaClBrowser::IsOk() const {
231 return ok_; 250 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
251 return !has_failed_;
232 } 252 }
233 253
234 const base::File& NaClBrowser::IrtFile() const { 254 const base::File& NaClBrowser::IrtFile() const {
235 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 255 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
236 CHECK_EQ(irt_state_, NaClResourceReady); 256 CHECK_EQ(irt_state_, NaClResourceReady);
237 CHECK(irt_file_.IsValid()); 257 CHECK(irt_file_.IsValid());
238 return irt_file_; 258 return irt_file_;
239 } 259 }
240 260
241 void NaClBrowser::EnsureAllResourcesAvailable() { 261 void NaClBrowser::EnsureAllResourcesAvailable() {
242 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 262 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
243 EnsureIrtAvailable(); 263 EnsureIrtAvailable();
244 EnsureValidationCacheAvailable(); 264 EnsureValidationCacheAvailable();
245 } 265 }
246 266
247 // Load the IRT async. 267 // Load the IRT async.
248 void NaClBrowser::EnsureIrtAvailable() { 268 void NaClBrowser::EnsureIrtAvailable() {
249 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 269 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
250 if (IsOk() && irt_state_ == NaClResourceUninitialized) { 270 if (IsOk() && irt_state_ == NaClResourceUninitialized) {
251 irt_state_ = NaClResourceRequested; 271 irt_state_ = NaClResourceRequested;
252 // TODO(ncbray) use blocking pool. 272 // TODO(ncbray) use blocking pool.
253 std::unique_ptr<base::FileProxy> file_proxy( 273 std::unique_ptr<base::FileProxy> file_proxy(
254 new base::FileProxy(content::BrowserThread::GetTaskRunnerForThread( 274 new base::FileProxy(content::BrowserThread::GetTaskRunnerForThread(
255 content::BrowserThread::FILE) 275 content::BrowserThread::FILE)
256 .get())); 276 .get()));
257 base::FileProxy* proxy = file_proxy.get(); 277 base::FileProxy* proxy = file_proxy.get();
258 if (!proxy->CreateOrOpen(irt_filepath_, 278 if (!proxy->CreateOrOpen(
259 base::File::FLAG_OPEN | base::File::FLAG_READ, 279 irt_filepath_, base::File::FLAG_OPEN | base::File::FLAG_READ,
260 base::Bind(&NaClBrowser::OnIrtOpened, 280 base::Bind(&NaClBrowser::OnIrtOpened, base::Unretained(this),
261 weak_factory_.GetWeakPtr(), 281 base::Passed(&file_proxy)))) {
262 Passed(&file_proxy)))) {
263 LOG(ERROR) << "Internal error, NaCl disabled."; 282 LOG(ERROR) << "Internal error, NaCl disabled.";
264 MarkAsFailed(); 283 MarkAsFailed();
265 } 284 }
266 } 285 }
267 } 286 }
268 287
269 void NaClBrowser::OnIrtOpened(std::unique_ptr<base::FileProxy> file_proxy, 288 void NaClBrowser::OnIrtOpened(std::unique_ptr<base::FileProxy> file_proxy,
270 base::File::Error error_code) { 289 base::File::Error error_code) {
271 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 290 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
272 DCHECK_EQ(irt_state_, NaClResourceRequested); 291 DCHECK_EQ(irt_state_, NaClResourceRequested);
273 if (file_proxy->IsValid()) { 292 if (file_proxy->IsValid()) {
274 irt_file_ = file_proxy->TakeFile(); 293 irt_file_ = file_proxy->TakeFile();
275 } else { 294 } else {
276 LOG(ERROR) << "Failed to open NaCl IRT file \"" 295 LOG(ERROR) << "Failed to open NaCl IRT file \""
277 << irt_filepath_.LossyDisplayName() 296 << irt_filepath_.LossyDisplayName()
278 << "\": " << error_code; 297 << "\": " << error_code;
279 MarkAsFailed(); 298 MarkAsFailed();
280 } 299 }
281 irt_state_ = NaClResourceReady; 300 irt_state_ = NaClResourceReady;
282 CheckWaiting(); 301 CheckWaiting();
283 } 302 }
284 303
285 void NaClBrowser::SetProcessGdbDebugStubPort(int process_id, int port) { 304 void NaClBrowser::SetProcessGdbDebugStubPort(int process_id, int port) {
305 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
286 gdb_debug_stub_port_map_[process_id] = port; 306 gdb_debug_stub_port_map_[process_id] = port;
287 if (port != kGdbDebugStubPortUnknown && 307 if (port != kGdbDebugStubPortUnknown &&
288 !debug_stub_port_listener_.is_null()) { 308 !debug_stub_port_listener_.is_null()) {
289 content::BrowserThread::PostTask( 309 content::BrowserThread::PostTask(
290 content::BrowserThread::IO, 310 content::BrowserThread::IO,
291 FROM_HERE, 311 FROM_HERE,
292 base::Bind(debug_stub_port_listener_, port)); 312 base::Bind(debug_stub_port_listener_, port));
293 } 313 }
294 } 314 }
295 315
296 void NaClBrowser::SetGdbDebugStubPortListener( 316 void NaClBrowser::SetGdbDebugStubPortListenerForTest(
297 base::Callback<void(int)> listener) { 317 base::Callback<void(int)> listener) {
318 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
298 debug_stub_port_listener_ = listener; 319 debug_stub_port_listener_ = listener;
299 } 320 }
300 321
301 void NaClBrowser::ClearGdbDebugStubPortListener() { 322 void NaClBrowser::ClearGdbDebugStubPortListenerForTest() {
323 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
302 debug_stub_port_listener_.Reset(); 324 debug_stub_port_listener_.Reset();
303 } 325 }
304 326
305 int NaClBrowser::GetProcessGdbDebugStubPort(int process_id) { 327 int NaClBrowser::GetProcessGdbDebugStubPort(int process_id) {
328 // Called from TaskManager TaskGroup impl, on CrBrowserMain.
329 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
306 GdbDebugStubPortMap::iterator i = gdb_debug_stub_port_map_.find(process_id); 330 GdbDebugStubPortMap::iterator i = gdb_debug_stub_port_map_.find(process_id);
307 if (i != gdb_debug_stub_port_map_.end()) { 331 if (i != gdb_debug_stub_port_map_.end()) {
308 return i->second; 332 return i->second;
309 } 333 }
310 return kGdbDebugStubPortUnused; 334 return kGdbDebugStubPortUnused;
311 } 335 }
312 336
313 void NaClBrowser::InitValidationCacheFilePath() { 337 void NaClBrowser::InitValidationCacheFilePath() {
338 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
314 // Determine where the validation cache resides in the file system. It 339 // Determine where the validation cache resides in the file system. It
315 // exists in Chrome's cache directory and is not tied to any specific 340 // exists in Chrome's cache directory and is not tied to any specific
316 // profile. 341 // profile.
317 // Start by finding the user data directory. 342 // Start by finding the user data directory.
318 base::FilePath user_data_dir; 343 base::FilePath user_data_dir;
319 if (!browser_delegate_->GetUserDirectory(&user_data_dir)) { 344 if (!GetDelegate()->GetUserDirectory(&user_data_dir)) {
320 RunWithoutValidationCache(); 345 RunWithoutValidationCache();
321 return; 346 return;
322 } 347 }
323 // The cache directory may or may not be the user data directory. 348 // The cache directory may or may not be the user data directory.
324 base::FilePath cache_file_path; 349 base::FilePath cache_file_path;
325 browser_delegate_->GetCacheDirectory(&cache_file_path); 350 GetDelegate()->GetCacheDirectory(&cache_file_path);
326 // Append the base file name to the cache directory. 351 // Append the base file name to the cache directory.
327 352
328 validation_cache_file_path_ = 353 validation_cache_file_path_ =
329 cache_file_path.Append(kValidationCacheFileName); 354 cache_file_path.Append(kValidationCacheFileName);
330 } 355 }
331 356
332 void NaClBrowser::EnsureValidationCacheAvailable() { 357 void NaClBrowser::EnsureValidationCacheAvailable() {
333 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 358 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
334 if (IsOk() && validation_cache_state_ == NaClResourceUninitialized) { 359 if (IsOk() && validation_cache_state_ == NaClResourceUninitialized) {
335 if (ValidationCacheIsEnabled()) { 360 if (ValidationCacheIsEnabled()) {
336 validation_cache_state_ = NaClResourceRequested; 361 validation_cache_state_ = NaClResourceRequested;
337 362
338 // Structure for carrying data between the callbacks. 363 // Structure for carrying data between the callbacks.
339 std::string* data = new std::string(); 364 std::string* data = new std::string();
340 // We can get away not giving this a sequence ID because this is the first 365 // We can get away not giving this a sequence ID because this is the first
341 // task and further file access will not occur until after we get a 366 // task and further file access will not occur until after we get a
342 // response. 367 // response.
343 if (!content::BrowserThread::PostBlockingPoolTaskAndReply( 368 if (!content::BrowserThread::PostBlockingPoolTaskAndReply(
344 FROM_HERE, 369 FROM_HERE,
345 base::Bind(ReadCache, validation_cache_file_path_, data), 370 base::Bind(ReadCache, validation_cache_file_path_, data),
346 base::Bind(&NaClBrowser::OnValidationCacheLoaded, 371 base::Bind(&NaClBrowser::OnValidationCacheLoaded,
347 weak_factory_.GetWeakPtr(), 372 base::Unretained(this), base::Owned(data)))) {
348 base::Owned(data)))) {
349 RunWithoutValidationCache(); 373 RunWithoutValidationCache();
350 } 374 }
351 } else { 375 } else {
352 RunWithoutValidationCache(); 376 RunWithoutValidationCache();
353 } 377 }
354 } 378 }
355 } 379 }
356 380
357 void NaClBrowser::OnValidationCacheLoaded(const std::string *data) { 381 void NaClBrowser::OnValidationCacheLoaded(const std::string *data) {
358 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 382 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
359 // Did the cache get cleared before the load completed? If so, ignore the 383 // Did the cache get cleared before the load completed? If so, ignore the
360 // incoming data. 384 // incoming data.
361 if (validation_cache_state_ == NaClResourceReady) 385 if (validation_cache_state_ == NaClResourceReady)
362 return; 386 return;
363 387
364 if (data->size() == 0) { 388 if (data->size() == 0) {
365 // No file found. 389 // No file found.
366 validation_cache_.Reset(); 390 validation_cache_.Reset();
367 } else { 391 } else {
368 base::Pickle pickle(data->data(), data->size()); 392 base::Pickle pickle(data->data(), data->size());
369 validation_cache_.Deserialize(&pickle); 393 validation_cache_.Deserialize(&pickle);
370 } 394 }
371 validation_cache_state_ = NaClResourceReady; 395 validation_cache_state_ = NaClResourceReady;
372 CheckWaiting(); 396 CheckWaiting();
373 } 397 }
374 398
375 void NaClBrowser::RunWithoutValidationCache() { 399 void NaClBrowser::RunWithoutValidationCache() {
400 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
376 // Be paranoid. 401 // Be paranoid.
377 validation_cache_.Reset(); 402 validation_cache_.Reset();
378 validation_cache_is_enabled_ = false; 403 validation_cache_is_enabled_ = false;
379 validation_cache_state_ = NaClResourceReady; 404 validation_cache_state_ = NaClResourceReady;
380 CheckWaiting(); 405 CheckWaiting();
381 } 406 }
382 407
383 void NaClBrowser::CheckWaiting() { 408 void NaClBrowser::CheckWaiting() {
384 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 409 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
385 if (!IsOk() || IsReady()) { 410 if (!IsOk() || IsReady()) {
386 // Queue the waiting tasks into the message loop. This helps avoid 411 // Queue the waiting tasks into the message loop. This helps avoid
387 // re-entrancy problems that could occur if the closure was invoked 412 // re-entrancy problems that could occur if the closure was invoked
388 // directly. For example, this could result in use-after-free of the 413 // directly. For example, this could result in use-after-free of the
389 // process host. 414 // process host.
390 for (std::vector<base::Closure>::iterator iter = waiting_.begin(); 415 for (std::vector<base::Closure>::iterator iter = waiting_.begin();
391 iter != waiting_.end(); ++iter) { 416 iter != waiting_.end(); ++iter) {
392 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, *iter); 417 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, *iter);
393 } 418 }
394 waiting_.clear(); 419 waiting_.clear();
395 } 420 }
396 } 421 }
397 422
398 void NaClBrowser::MarkAsFailed() { 423 void NaClBrowser::MarkAsFailed() {
399 ok_ = false; 424 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
425 has_failed_ = true;
400 CheckWaiting(); 426 CheckWaiting();
401 } 427 }
402 428
403 void NaClBrowser::WaitForResources(const base::Closure& reply) { 429 void NaClBrowser::WaitForResources(const base::Closure& reply) {
430 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
404 waiting_.push_back(reply); 431 waiting_.push_back(reply);
405 EnsureAllResourcesAvailable(); 432 EnsureAllResourcesAvailable();
406 CheckWaiting(); 433 CheckWaiting();
407 } 434 }
408 435
409 const base::FilePath& NaClBrowser::GetIrtFilePath() { 436 const base::FilePath& NaClBrowser::GetIrtFilePath() {
437 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
410 return irt_filepath_; 438 return irt_filepath_;
411 } 439 }
412 440
413 void NaClBrowser::PutFilePath(const base::FilePath& path, 441 void NaClBrowser::PutFilePath(const base::FilePath& path,
414 uint64_t* file_token_lo, 442 uint64_t* file_token_lo,
415 uint64_t* file_token_hi) { 443 uint64_t* file_token_hi) {
416 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 444 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
417 while (true) { 445 while (true) {
418 uint64_t file_token[2] = {base::RandUint64(), base::RandUint64()}; 446 uint64_t file_token[2] = {base::RandUint64(), base::RandUint64()};
419 // A zero file_token indicates there is no file_token, if we get zero, ask 447 // A zero file_token indicates there is no file_token, if we get zero, ask
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
512 540
513 // If the cache is cleared before it is loaded from the filesystem, act as if 541 // If the cache is cleared before it is loaded from the filesystem, act as if
514 // we just loaded an empty cache. 542 // we just loaded an empty cache.
515 if (validation_cache_state_ != NaClResourceReady) { 543 if (validation_cache_state_ != NaClResourceReady) {
516 validation_cache_state_ = NaClResourceReady; 544 validation_cache_state_ = NaClResourceReady;
517 CheckWaiting(); 545 CheckWaiting();
518 } 546 }
519 } 547 }
520 548
521 void NaClBrowser::MarkValidationCacheAsModified() { 549 void NaClBrowser::MarkValidationCacheAsModified() {
550 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
522 if (!validation_cache_is_modified_) { 551 if (!validation_cache_is_modified_) {
523 // Wait before persisting to disk. This can coalesce multiple cache 552 // Wait before persisting to disk. This can coalesce multiple cache
524 // modifications info a single disk write. 553 // modifications info a single disk write.
525 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( 554 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
526 FROM_HERE, base::Bind(&NaClBrowser::PersistValidationCache, 555 FROM_HERE, base::Bind(&NaClBrowser::PersistValidationCache,
527 weak_factory_.GetWeakPtr()), 556 base::Unretained(this)),
528 base::TimeDelta::FromMilliseconds(kValidationCacheCoalescingTimeMS)); 557 base::TimeDelta::FromMilliseconds(kValidationCacheCoalescingTimeMS));
529 validation_cache_is_modified_ = true; 558 validation_cache_is_modified_ = true;
530 } 559 }
531 } 560 }
532 561
533 void NaClBrowser::PersistValidationCache() { 562 void NaClBrowser::PersistValidationCache() {
534 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 563 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
535 // validation_cache_is_modified_ may be false if the cache was cleared while 564 // validation_cache_is_modified_ may be false if the cache was cleared while
536 // this delayed task was pending. 565 // this delayed task was pending.
537 // validation_cache_file_path_ may be empty if something went wrong during 566 // validation_cache_file_path_ may be empty if something went wrong during
538 // initialization. 567 // initialization.
539 if (validation_cache_is_modified_ && !validation_cache_file_path_.empty()) { 568 if (validation_cache_is_modified_ && !validation_cache_file_path_.empty()) {
540 base::Pickle* pickle = new base::Pickle(); 569 base::Pickle* pickle = new base::Pickle();
541 validation_cache_.Serialize(pickle); 570 validation_cache_.Serialize(pickle);
542 571
543 // Pass the serialized data to another thread to write to disk. File IO is 572 // Pass the serialized data to another thread to write to disk. File IO is
544 // not allowed on the IO thread (which is the thread this method runs on) 573 // not allowed on the IO thread (which is the thread this method runs on)
545 // because it can degrade the responsiveness of the browser. 574 // because it can degrade the responsiveness of the browser.
546 // The task is sequenced so that multiple writes happen in order. 575 // The task is sequenced so that multiple writes happen in order.
547 content::BrowserThread::PostBlockingPoolSequencedTask( 576 content::BrowserThread::PostBlockingPoolSequencedTask(
548 kValidationCacheSequenceName, 577 kValidationCacheSequenceName,
549 FROM_HERE, 578 FROM_HERE,
550 base::Bind(WriteCache, validation_cache_file_path_, 579 base::Bind(WriteCache, validation_cache_file_path_,
551 base::Owned(pickle))); 580 base::Owned(pickle)));
552 } 581 }
553 validation_cache_is_modified_ = false; 582 validation_cache_is_modified_ = false;
554 } 583 }
555 584
556 void NaClBrowser::OnProcessEnd(int process_id) { 585 void NaClBrowser::OnProcessEnd(int process_id) {
586 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
557 gdb_debug_stub_port_map_.erase(process_id); 587 gdb_debug_stub_port_map_.erase(process_id);
558 } 588 }
559 589
560 void NaClBrowser::OnProcessCrashed() { 590 void NaClBrowser::OnProcessCrashed() {
561 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 591 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
562 if (crash_times_.size() == kMaxCrashesPerInterval) { 592 if (crash_times_.size() == kMaxCrashesPerInterval) {
563 crash_times_.pop_front(); 593 crash_times_.pop_front();
564 } 594 }
565 base::Time time = base::Time::Now(); 595 base::Time time = base::Time::Now();
566 crash_times_.push_back(time); 596 crash_times_.push_back(time);
567 } 597 }
568 598
569 bool NaClBrowser::IsThrottled() { 599 bool NaClBrowser::IsThrottled() {
570 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 600 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
571 if (crash_times_.size() != kMaxCrashesPerInterval) { 601 if (crash_times_.size() != kMaxCrashesPerInterval) {
572 return false; 602 return false;
573 } 603 }
574 base::TimeDelta delta = base::Time::Now() - crash_times_.front(); 604 base::TimeDelta delta = base::Time::Now() - crash_times_.front();
575 return delta.InSeconds() <= kCrashesIntervalInSeconds; 605 return delta.InSeconds() <= kCrashesIntervalInSeconds;
576 } 606 }
577 607
578 } // namespace nacl 608 } // namespace nacl
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698