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 3 // found in the LICENSE file. 4 5 #include "chrome/browser/extensions/requirements_checker.h" 6 7 #include "base/bind.h" 8 #include "base/strings/utf_string_conversions.h" 9 #include "chrome/browser/gpu/gpu_feature_checker.h" 10 #include "chrome/common/extensions/extension_manifest_constants.h" 11 #include "chrome/common/extensions/extension.h" 12 #include "chrome/common/extensions/manifest.h" 13 #include "chrome/common/extensions/manifest_handlers/requirements_handler.h" 14 #include "content/public/browser/browser_thread.h" 15 #include "gpu/config/gpu_feature_type.h" 16 #include "grit/generated_resources.h" 17 #include "ui/base/l10n/l10n_util.h" 18 19 #if defined(OS_WIN) 20 #include "base/win/metro.h" 21 #endif // defined(OS_WIN) 22 23 namespace extensions { 24 25 RequirementsChecker::RequirementsChecker() 26 : pending_requirement_checks_(0) { 27 } 28 29 RequirementsChecker::~RequirementsChecker() { 30 } 31 32 void RequirementsChecker::Check(scoped_refptr<const Extension> extension, 33 base::Callback<void(std::vector<std::string> errors)> callback) { 34 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 35 36 callback_ = callback; 37 const RequirementsInfo& requirements = 38 RequirementsInfo::GetRequirements(extension.get()); 39 40 if (requirements.npapi) { 41 #if defined(OS_CHROMEOS) 42 errors_.push_back( 43 l10n_util::GetStringUTF8(IDS_EXTENSION_NPAPI_NOT_SUPPORTED)); 44 #endif // defined(OS_CHROMEOS) 45 #if defined(OS_WIN) 46 if (base::win::IsMetroProcess()) { 47 errors_.push_back( 48 l10n_util::GetStringUTF8(IDS_EXTENSION_NPAPI_NOT_SUPPORTED)); 49 } 50 #endif // defined(OS_WIN) 51 } 52 53 if (requirements.webgl) { 54 ++pending_requirement_checks_; 55 webgl_checker_ = new GPUFeatureChecker( 56 gpu::GPU_FEATURE_TYPE_WEBGL, 57 base::Bind(&RequirementsChecker::SetWebGLAvailability, 58 AsWeakPtr())); 59 } 60 61 if (requirements.css3d) { 62 ++pending_requirement_checks_; 63 css3d_checker_ = new GPUFeatureChecker( 64 gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING, 65 base::Bind(&RequirementsChecker::SetCSS3DAvailability, 66 AsWeakPtr())); 67 } 68 69 if (pending_requirement_checks_ == 0) { 70 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, 71 base::Bind(callback_, errors_)); 72 // Reset the callback so any ref-counted bound parameters will get released. 73 callback_.Reset(); 74 return; 75 } 76 // Running the GPU checkers down here removes any race condition that arises 77 // from the use of pending_requirement_checks_. 78 if (webgl_checker_.get()) 79 webgl_checker_->CheckGPUFeatureAvailability(); 80 if (css3d_checker_.get()) 81 css3d_checker_->CheckGPUFeatureAvailability(); 82 } 83 84 void RequirementsChecker::SetWebGLAvailability(bool available) { 85 if (!available) { 86 errors_.push_back( 87 l10n_util::GetStringUTF8(IDS_EXTENSION_WEBGL_NOT_SUPPORTED)); 88 } 89 MaybeRunCallback(); 90 } 91 92 void RequirementsChecker::SetCSS3DAvailability(bool available) { 93 if (!available) { 94 errors_.push_back( 95 l10n_util::GetStringUTF8(IDS_EXTENSION_CSS3D_NOT_SUPPORTED)); 96 } 97 MaybeRunCallback(); 98 } 99 100 void RequirementsChecker::MaybeRunCallback() { 101 if (--pending_requirement_checks_ == 0) { 102 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, 103 base::Bind(callback_, errors_)); 104 // Reset the callback so any ref-counted bound parameters will get released. 105 callback_.Reset(); 106 errors_.clear(); 107 } 108 } 109 110 } // namespace extensions 111