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 <vector>
6
7#include "base/bind.h"
8#include "base/command_line.h"
9#include "base/files/file_path.h"
10#include "base/memory/ref_counted.h"
11#include "base/message_loop/message_loop.h"
12#include "base/path_service.h"
13#include "base/strings/string_util.h"
14#include "base/threading/sequenced_worker_pool.h"
15#include "chrome/browser/extensions/extension_browsertest.h"
16#include "chrome/browser/extensions/requirements_checker.h"
17#include "chrome/common/chrome_paths.h"
18#include "chrome/common/extensions/extension.h"
19#include "chrome/common/extensions/extension_file_util.h"
20#include "content/public/browser/browser_thread.h"
21#include "content/public/browser/gpu_data_manager.h"
22#include "gpu/config/gpu_info.h"
23#include "grit/generated_resources.h"
24#include "ui/base/l10n/l10n_util.h"
25#include "ui/gl/gl_switches.h"
26
27namespace extensions {
28
29class RequirementsCheckerBrowserTest : public ExtensionBrowserTest {
30 public:
31  scoped_refptr<const Extension> LoadExtensionFromDirName(
32      const std::string& extension_dir_name) {
33    base::FilePath extension_path;
34    std::string load_error;
35    PathService::Get(chrome::DIR_TEST_DATA, &extension_path);
36    extension_path = extension_path.AppendASCII("requirements_checker")
37                                   .AppendASCII(extension_dir_name);
38    scoped_refptr<const Extension> extension =
39        extension_file_util::LoadExtension(extension_path, Manifest::UNPACKED,
40                                           0, &load_error);
41    CHECK(load_error.length() == 0u);
42    return extension;
43  }
44
45  void ValidateRequirementErrors(std::vector<std::string> expected_errors,
46                                 std::vector<std::string> actual_errors) {
47    ASSERT_EQ(expected_errors, actual_errors);
48    requirement_errors_.swap(actual_errors);
49  }
50
51  // This should only be called once per test instance. Calling more than once
52  // will result in stale information in the GPUDataManager which will throw off
53  // the RequirementsChecker.
54  void BlackListGPUFeatures(const std::vector<std::string>& features) {
55    static const std::string json_blacklist =
56      "{\n"
57      "  \"name\": \"gpu blacklist\",\n"
58      "  \"version\": \"1.0\",\n"
59      "  \"entries\": [\n"
60      "    {\n"
61      "      \"id\": 1,\n"
62      "      \"features\": [\"" + JoinString(features, "\", \"") + "\"]\n"
63      "    }\n"
64      "  ]\n"
65      "}";
66    gpu::GPUInfo gpu_info;
67    content::GpuDataManager::GetInstance()->InitializeForTesting(
68        json_blacklist, gpu_info);
69  }
70
71 protected:
72  std::vector<std::string> requirement_errors_;
73  RequirementsChecker checker_;
74};
75
76IN_PROC_BROWSER_TEST_F(RequirementsCheckerBrowserTest, CheckEmptyExtension) {
77  scoped_refptr<const Extension> extension(
78      LoadExtensionFromDirName("no_requirements"));
79  ASSERT_TRUE(extension.get());
80  checker_.Check(extension, base::Bind(
81      &RequirementsCheckerBrowserTest::ValidateRequirementErrors,
82      base::Unretained(this), std::vector<std::string>()));
83  content::BrowserThread::GetBlockingPool()->FlushForTesting();
84}
85
86IN_PROC_BROWSER_TEST_F(RequirementsCheckerBrowserTest, CheckNpapiExtension) {
87  scoped_refptr<const Extension> extension(
88      LoadExtensionFromDirName("require_npapi"));
89  ASSERT_TRUE(extension.get());
90
91  std::vector<std::string> expected_errors;
92  // npapi plugins are dissalowd on CROMEOS.
93#if defined(OS_CHROMEOS)
94  expected_errors.push_back(l10n_util::GetStringUTF8(
95      IDS_EXTENSION_NPAPI_NOT_SUPPORTED));
96#endif  // defined(OS_CHROMEOS)
97
98  checker_.Check(extension, base::Bind(
99      &RequirementsCheckerBrowserTest::ValidateRequirementErrors,
100      base::Unretained(this), expected_errors));
101  content::BrowserThread::GetBlockingPool()->FlushForTesting();
102}
103
104IN_PROC_BROWSER_TEST_F(RequirementsCheckerBrowserTest, DisallowCSS3D) {
105  scoped_refptr<const Extension> extension(
106      LoadExtensionFromDirName("require_3d"));
107  ASSERT_TRUE(extension.get());
108
109
110  // Blacklist css3d
111  std::vector<std::string> blacklisted_features;
112  blacklisted_features.push_back("accelerated_compositing");
113  BlackListGPUFeatures(blacklisted_features);
114  content::BrowserThread::GetBlockingPool()->FlushForTesting();
115
116  std::vector<std::string> expected_errors;
117  expected_errors.push_back(l10n_util::GetStringUTF8(
118      IDS_EXTENSION_CSS3D_NOT_SUPPORTED));
119
120  checker_.Check(extension, base::Bind(
121      &RequirementsCheckerBrowserTest::ValidateRequirementErrors,
122      base::Unretained(this), expected_errors));
123  content::BrowserThread::GetBlockingPool()->FlushForTesting();
124}
125
126IN_PROC_BROWSER_TEST_F(RequirementsCheckerBrowserTest, DisallowWebGL) {
127  scoped_refptr<const Extension> extension(
128      LoadExtensionFromDirName("require_3d"));
129  ASSERT_TRUE(extension.get());
130
131  // Backlist webgl
132  std::vector<std::string> blacklisted_features;
133  blacklisted_features.push_back("webgl");
134  BlackListGPUFeatures(blacklisted_features);
135  content::BrowserThread::GetBlockingPool()->FlushForTesting();
136
137  std::vector<std::string> expected_errors;
138  expected_errors.push_back(l10n_util::GetStringUTF8(
139      IDS_EXTENSION_WEBGL_NOT_SUPPORTED));
140
141  checker_.Check(extension, base::Bind(
142      &RequirementsCheckerBrowserTest::ValidateRequirementErrors,
143      base::Unretained(this), expected_errors));
144  content::BrowserThread::GetBlockingPool()->FlushForTesting();
145}
146
147IN_PROC_BROWSER_TEST_F(RequirementsCheckerBrowserTest, DisallowGPUFeatures) {
148  scoped_refptr<const Extension> extension(
149      LoadExtensionFromDirName("require_3d"));
150  ASSERT_TRUE(extension.get());
151
152  // Backlist both webgl and css3d
153  std::vector<std::string> blacklisted_features;
154  blacklisted_features.push_back("webgl");
155  blacklisted_features.push_back("accelerated_compositing");
156  BlackListGPUFeatures(blacklisted_features);
157  content::BrowserThread::GetBlockingPool()->FlushForTesting();
158
159  std::vector<std::string> expected_errors;
160  expected_errors.push_back(l10n_util::GetStringUTF8(
161      IDS_EXTENSION_WEBGL_NOT_SUPPORTED));
162  expected_errors.push_back(l10n_util::GetStringUTF8(
163      IDS_EXTENSION_CSS3D_NOT_SUPPORTED));
164
165  checker_.Check(extension, base::Bind(
166      &RequirementsCheckerBrowserTest::ValidateRequirementErrors,
167      base::Unretained(this), expected_errors));
168  content::BrowserThread::GetBlockingPool()->FlushForTesting();
169}
170
171IN_PROC_BROWSER_TEST_F(RequirementsCheckerBrowserTest, Check3DExtension) {
172  scoped_refptr<const Extension> extension(
173      LoadExtensionFromDirName("require_3d"));
174  ASSERT_TRUE(extension.get());
175
176  checker_.Check(extension, base::Bind(
177      &RequirementsCheckerBrowserTest::ValidateRequirementErrors,
178      base::Unretained(this), std::vector<std::string>()));
179  content::BrowserThread::GetBlockingPool()->FlushForTesting();
180}
181
182}  // namespace extensions
183