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
23namespace extensions {
24
25RequirementsChecker::RequirementsChecker()
26    : pending_requirement_checks_(0) {
27}
28
29RequirementsChecker::~RequirementsChecker() {
30}
31
32void 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
84void 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
92void 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
100void 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