Home | History | Annotate | Download | only in extensions
      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