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