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 |