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

Side by Side Diff: content/browser/gpu/gpu_data_manager_impl.cc

Issue 11378008: Raise an infobar and deny access to WebGL if a GPU reset was detected while a web page containing W… (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Work around build failure on Mac OS with 10.6 SDK. Created 8 years, 1 month 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "content/browser/gpu/gpu_data_manager_impl.h" 5 #include "content/browser/gpu/gpu_data_manager_impl.h"
6 6
7 #if defined(OS_MACOSX) 7 #if defined(OS_MACOSX)
8 #include <ApplicationServices/ApplicationServices.h> 8 #include <ApplicationServices/ApplicationServices.h>
9 #endif // OS_MACOSX 9 #endif // OS_MACOSX
10 10
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
62 void* gpu_data_manager) { 62 void* gpu_data_manager) {
63 if (flags & kCGDisplayAddFlag) { 63 if (flags & kCGDisplayAddFlag) {
64 GpuDataManagerImpl* manager = 64 GpuDataManagerImpl* manager =
65 reinterpret_cast<GpuDataManagerImpl*>(gpu_data_manager); 65 reinterpret_cast<GpuDataManagerImpl*>(gpu_data_manager);
66 DCHECK(manager); 66 DCHECK(manager);
67 manager->HandleGpuSwitch(); 67 manager->HandleGpuSwitch();
68 } 68 }
69 } 69 }
70 #endif // OS_MACOSX 70 #endif // OS_MACOSX
71 71
72 // Block all domains' use of 3D APIs for this many milliseconds if
73 // approaching a threshold where system stability might be compromised.
74 const int64 kBlockAllDomainsMs = 10000;
75 const int kNumResetsWithinDuration = 1;
76
72 } // namespace anonymous 77 } // namespace anonymous
73 78
74 // static 79 // static
75 GpuDataManager* GpuDataManager::GetInstance() { 80 GpuDataManager* GpuDataManager::GetInstance() {
76 return GpuDataManagerImpl::GetInstance(); 81 return GpuDataManagerImpl::GetInstance();
77 } 82 }
78 83
79 // static 84 // static
80 GpuDataManagerImpl* GpuDataManagerImpl::GetInstance() { 85 GpuDataManagerImpl* GpuDataManagerImpl::GetInstance() {
81 return Singleton<GpuDataManagerImpl>::get(); 86 return Singleton<GpuDataManagerImpl>::get();
82 } 87 }
83 88
84 GpuDataManagerImpl::GpuDataManagerImpl() 89 GpuDataManagerImpl::GpuDataManagerImpl()
85 : complete_gpu_info_already_requested_(false), 90 : complete_gpu_info_already_requested_(false),
86 blacklisted_features_(GPU_FEATURE_TYPE_UNKNOWN), 91 blacklisted_features_(GPU_FEATURE_TYPE_UNKNOWN),
87 preliminary_blacklisted_features_(GPU_FEATURE_TYPE_UNKNOWN), 92 preliminary_blacklisted_features_(GPU_FEATURE_TYPE_UNKNOWN),
88 gpu_switching_(GPU_SWITCHING_OPTION_AUTOMATIC), 93 gpu_switching_(GPU_SWITCHING_OPTION_AUTOMATIC),
89 observer_list_(new GpuDataManagerObserverList), 94 observer_list_(new GpuDataManagerObserverList),
90 software_rendering_(false), 95 software_rendering_(false),
91 card_blacklisted_(false), 96 card_blacklisted_(false),
92 update_histograms_(true), 97 update_histograms_(true),
93 window_count_(0) { 98 window_count_(0),
99 domain_blocking_enabled_(true) {
94 CommandLine* command_line = CommandLine::ForCurrentProcess(); 100 CommandLine* command_line = CommandLine::ForCurrentProcess();
95 if (command_line->HasSwitch(switches::kDisableAcceleratedCompositing)) { 101 if (command_line->HasSwitch(switches::kDisableAcceleratedCompositing)) {
96 command_line->AppendSwitch(switches::kDisableAccelerated2dCanvas); 102 command_line->AppendSwitch(switches::kDisableAccelerated2dCanvas);
97 command_line->AppendSwitch(switches::kDisableAcceleratedLayers); 103 command_line->AppendSwitch(switches::kDisableAcceleratedLayers);
98 } 104 }
99 if (command_line->HasSwitch(switches::kDisableGpu)) 105 if (command_line->HasSwitch(switches::kDisableGpu))
100 BlacklistCard(); 106 BlacklistCard();
101 if (command_line->HasSwitch(switches::kGpuSwitching)) { 107 if (command_line->HasSwitch(switches::kGpuSwitching)) {
102 std::string option_string = command_line->GetSwitchValueASCII( 108 std::string option_string = command_line->GetSwitchValueASCII(
103 switches::kGpuSwitching); 109 switches::kGpuSwitching);
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after
335 GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, 341 GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
336 CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH, 342 CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH,
337 new GpuMsg_SetVideoMemoryWindowCount(count)); 343 new GpuMsg_SetVideoMemoryWindowCount(count));
338 } 344 }
339 345
340 uint32 GpuDataManagerImpl::GetWindowCount() const { 346 uint32 GpuDataManagerImpl::GetWindowCount() const {
341 base::AutoLock auto_lock(gpu_info_lock_); 347 base::AutoLock auto_lock(gpu_info_lock_);
342 return window_count_; 348 return window_count_;
343 } 349 }
344 350
351 void GpuDataManagerImpl::UnblockDomainFrom3DAPIs(const GURL& url) {
352 // This method must do two things:
353 //
354 // 1. If the specific domain is blocked, then unblock it.
355 //
356 // 2. Reset our notion of how many GPU resets have occurred recently.
357 // This is necessary even if the specific domain was blocked.
358 // Otherwise, if we call Are3DAPIsBlocked with the same domain right
359 // after unblocking it, it will probably still be blocked because of
360 // the recent GPU reset caused by that domain.
361 //
362 // These policies could be refined, but at a certain point the behavior
363 // will become difficult to explain.
364 std::string domain = GetDomainFromURL(url);
365
366 base::AutoLock auto_lock(gpu_info_lock_);
367 blocked_domains_.erase(domain);
368 timestamps_of_gpu_resets_.clear();
369 }
370
371 void GpuDataManagerImpl::DisableDomainBlockingFor3DAPIsForTesting() {
372 domain_blocking_enabled_ = false;
373 }
374
345 void GpuDataManagerImpl::AppendRendererCommandLine( 375 void GpuDataManagerImpl::AppendRendererCommandLine(
346 CommandLine* command_line) const { 376 CommandLine* command_line) const {
347 DCHECK(command_line); 377 DCHECK(command_line);
348 378
349 uint32 flags = GetBlacklistedFeatures(); 379 uint32 flags = GetBlacklistedFeatures();
350 if ((flags & GPU_FEATURE_TYPE_WEBGL)) { 380 if ((flags & GPU_FEATURE_TYPE_WEBGL)) {
351 #if !defined(OS_ANDROID) 381 #if !defined(OS_ANDROID)
352 if (!command_line->HasSwitch(switches::kDisableExperimentalWebGL)) 382 if (!command_line->HasSwitch(switches::kDisableExperimentalWebGL))
353 command_line->AppendSwitch(switches::kDisableExperimentalWebGL); 383 command_line->AppendSwitch(switches::kDisableExperimentalWebGL);
354 #endif 384 #endif
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
464 if (command_line->HasSwitch(switches::kDisableImageTransportSurface)) 494 if (command_line->HasSwitch(switches::kDisableImageTransportSurface))
465 return false; 495 return false;
466 uint32 flags = GetBlacklistedFeatures(); 496 uint32 flags = GetBlacklistedFeatures();
467 if (flags & GPU_FEATURE_TYPE_TEXTURE_SHARING) 497 if (flags & GPU_FEATURE_TYPE_TEXTURE_SHARING)
468 return false; 498 return false;
469 499
470 return true; 500 return true;
471 } 501 }
472 #endif 502 #endif
473 503
504 void GpuDataManagerImpl::BlockDomainFrom3DAPIs(
505 const GURL& url, DomainGuilt guilt) {
506 BlockDomainFrom3DAPIsAtTime(url, guilt, base::Time::Now());
507 }
508
509 GpuDataManagerImpl::DomainBlockStatus
510 GpuDataManagerImpl::Are3DAPIsBlocked(const GURL& url) const {
511 return Are3DAPIsBlockedAtTime(url, base::Time::Now());
512 }
513
474 void GpuDataManagerImpl::AppendPluginCommandLine( 514 void GpuDataManagerImpl::AppendPluginCommandLine(
475 CommandLine* command_line) const { 515 CommandLine* command_line) const {
476 DCHECK(command_line); 516 DCHECK(command_line);
477 517
478 #if defined(OS_MACOSX) 518 #if defined(OS_MACOSX)
479 uint32 flags = GetBlacklistedFeatures(); 519 uint32 flags = GetBlacklistedFeatures();
480 // TODO(jbauman): Add proper blacklist support for core animation plugins so 520 // TODO(jbauman): Add proper blacklist support for core animation plugins so
481 // special-casing this video card won't be necessary. See 521 // special-casing this video card won't be necessary. See
482 // http://crbug.com/134015 522 // http://crbug.com/134015
483 if ((flags & GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING) || 523 if ((flags & GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING) ||
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
565 605
566 void GpuDataManagerImpl::BlacklistCard() { 606 void GpuDataManagerImpl::BlacklistCard() {
567 card_blacklisted_ = true; 607 card_blacklisted_ = true;
568 608
569 blacklisted_features_ = GPU_FEATURE_TYPE_ALL; 609 blacklisted_features_ = GPU_FEATURE_TYPE_ALL;
570 610
571 EnableSoftwareRenderingIfNecessary(); 611 EnableSoftwareRenderingIfNecessary();
572 NotifyGpuInfoUpdate(); 612 NotifyGpuInfoUpdate();
573 } 613 }
574 614
615 std::string GpuDataManagerImpl::GetDomainFromURL(const GURL& url) const {
616 // For the moment, we just use the host, or its IP address, as the
617 // entry in the set, rather than trying to figure out the top-level
618 // domain. This does mean that a.foo.com and b.foo.com will be
619 // treated independently in the blocking of a given domain, but it
620 // would require a third-party library to reliably figure out the
621 // top-level domain from a URL.
622 if (!url.has_host()) {
623 return std::string();
624 }
625
626 return url.host();
627 }
628
629 void GpuDataManagerImpl::BlockDomainFrom3DAPIsAtTime(
630 const GURL& url, DomainGuilt guilt, base::Time at_time) {
631 if (!domain_blocking_enabled_)
632 return;
633
634 std::string domain = GetDomainFromURL(url);
635
636 base::AutoLock auto_lock(gpu_info_lock_);
637 DomainBlockEntry& entry = blocked_domains_[domain];
638 entry.last_guilt = guilt;
639 timestamps_of_gpu_resets_.push_back(at_time);
640 }
641
642 GpuDataManagerImpl::DomainBlockStatus
643 GpuDataManagerImpl::Are3DAPIsBlockedAtTime(
644 const GURL& url, base::Time at_time) const {
645 if (!domain_blocking_enabled_)
646 return DOMAIN_BLOCK_STATUS_NOT_BLOCKED;
647
648 // Note: adjusting the policies in this code will almost certainly
649 // require adjusting the associated unit tests.
650 std::string domain = GetDomainFromURL(url);
651
652 base::AutoLock auto_lock(gpu_info_lock_);
653 {
654 DomainBlockMap::const_iterator iter = blocked_domains_.find(domain);
655 if (iter != blocked_domains_.end()) {
656 // Err on the side of caution, and assume that if a particular
657 // domain shows up in the block map, it's there for a good
658 // reason and don't let its presence there automatically expire.
659 return DOMAIN_BLOCK_STATUS_BLOCKED;
660 }
661 }
662
663 // Look at the timestamps of the recent GPU resets to see if there are
664 // enough within the threshold which would cause us to blacklist all
665 // domains. This doesn't need to be overly precise -- if time goes
666 // backward due to a system clock adjustment, that's fine.
667 //
668 // TODO(kbr): make this pay attention to the TDR thresholds in the
669 // Windows registry, but make sure it continues to be testable.
670 std::list<base::Time>::iterator iter = timestamps_of_gpu_resets_.begin();
671 int num_resets_within_timeframe = 0;
672 while (iter != timestamps_of_gpu_resets_.end()) {
673 base::Time time = *iter;
674 base::TimeDelta delta_t = at_time - time;
675
676 // If this entry has "expired", just remove it.
677 if (delta_t.InMilliseconds() > kBlockAllDomainsMs) {
678 iter = timestamps_of_gpu_resets_.erase(iter);
679 continue;
680 }
681
682 ++num_resets_within_timeframe;
683 ++iter;
684 }
685
686 if (num_resets_within_timeframe >= kNumResetsWithinDuration) {
687 return DOMAIN_BLOCK_STATUS_ALL_DOMAINS_BLOCKED;
688 }
689
690 return DOMAIN_BLOCK_STATUS_NOT_BLOCKED;
691 }
692
693 int64 GpuDataManagerImpl::GetBlockAllDomainsDurationInMs() const {
694 return kBlockAllDomainsMs;
695 }
696
575 } // namespace content 697 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/gpu/gpu_data_manager_impl.h ('k') | content/browser/gpu/gpu_data_manager_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698