blob: eaa52341a4a336f9d93a3878dff2de8cfddc6f8e [file] [log] [blame]
michaelpga8ea0372017-04-06 20:41:351// Copyright 2017 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 "extensions/browser/requirements_checker.h"
6
7#include <memory>
8#include <vector>
9
michaelpga8ea0372017-04-06 20:41:3510#include "base/memory/ref_counted.h"
11#include "base/strings/string16.h"
12#include "base/strings/utf_string_conversions.h"
13#include "base/values.h"
14#include "content/public/browser/gpu_data_manager.h"
michaelpga8ea0372017-04-06 20:41:3515#include "extensions/browser/extension_system.h"
16#include "extensions/browser/extensions_test.h"
17#include "extensions/browser/preload_check.h"
18#include "extensions/browser/preload_check_test_util.h"
19#include "extensions/common/extension.h"
20#include "extensions/common/manifest.h"
21#include "testing/gmock/include/gmock/gmock.h"
22#include "testing/gtest/include/gtest/gtest.h"
23#include "ui/base/l10n/l10n_util.h"
24
25namespace extensions {
26
27namespace {
28
29// Whether this build supports the window.shape requirement.
30const bool kSupportsWindowShape =
31#if defined(USE_AURA)
32 true;
33#else
34 false;
35#endif
36
michaelpga8ea0372017-04-06 20:41:3537// Returns true if a WebGL check might not fail immediately.
38bool MightSupportWebGL() {
39 return content::GpuDataManager::GetInstance()->GpuAccessAllowed(nullptr);
40}
41
42const char kFeaturesKey[] = "requirements.3D.features";
43const char kFeatureWebGL[] = "webgl";
44const char kFeatureCSS3d[] = "css3d";
45
46} // namespace
47
48class RequirementsCheckerTest : public ExtensionsTest {
49 public:
Lukasz Anforowicz58d0dac2018-03-23 15:48:1050 RequirementsCheckerTest() {
Jeremy Roman16529d0e2017-08-24 18:13:4751 manifest_dict_ = std::make_unique<base::DictionaryValue>();
michaelpga8ea0372017-04-06 20:41:3552 }
53
54 ~RequirementsCheckerTest() override {}
55
56 void CreateExtension() {
57 manifest_dict_->SetString("name", "dummy name");
58 manifest_dict_->SetString("version", "1");
Devlin Cronin1fa235b62018-04-12 14:04:0759 manifest_dict_->SetInteger("manifest_version", 2);
michaelpga8ea0372017-04-06 20:41:3560
61 std::string error;
62 extension_ =
63 Extension::Create(base::FilePath(), Manifest::UNPACKED, *manifest_dict_,
64 Extension::NO_FLAGS, &error);
65 ASSERT_TRUE(extension_.get()) << error;
66 }
67
68 protected:
69 void StartChecker() {
Jeremy Roman16529d0e2017-08-24 18:13:4770 checker_ = std::make_unique<RequirementsChecker>(extension_);
michaelpga8ea0372017-04-06 20:41:3571 // TODO(michaelpg): This should normally not have to be async. Use Run()
72 // instead of RunUntilComplete() after crbug.com/708354 is addressed.
73 runner_.RunUntilComplete(checker_.get());
74 }
75
76 void RequireWindowShape() {
77 manifest_dict_->SetBoolean("requirements.window.shape", true);
78 }
79
michaelpga8ea0372017-04-06 20:41:3580 void RequireFeature(const char feature[]) {
81 if (!manifest_dict_->HasKey(kFeaturesKey))
Jeremy Roman16529d0e2017-08-24 18:13:4782 manifest_dict_->Set(kFeaturesKey, std::make_unique<base::ListValue>());
michaelpga8ea0372017-04-06 20:41:3583 base::ListValue* features_list = nullptr;
84 ASSERT_TRUE(manifest_dict_->GetList(kFeaturesKey, &features_list));
85 features_list->AppendString(feature);
86 }
87
88 std::unique_ptr<RequirementsChecker> checker_;
89 PreloadCheckRunner runner_;
90
91 private:
michaelpga8ea0372017-04-06 20:41:3592 scoped_refptr<Extension> extension_;
93 std::unique_ptr<base::DictionaryValue> manifest_dict_;
94};
95
96// Tests no requirements.
97TEST_F(RequirementsCheckerTest, RequirementsEmpty) {
98 CreateExtension();
99 StartChecker();
100 EXPECT_TRUE(runner_.called());
101 EXPECT_EQ(0u, runner_.errors().size());
102 EXPECT_TRUE(checker_->GetErrorMessage().empty());
103}
104
105// Tests fulfilled requirements.
106TEST_F(RequirementsCheckerTest, RequirementsSuccess) {
107 if (kSupportsWindowShape)
108 RequireWindowShape();
Karan Bhatiac8954af2017-12-01 23:39:07109
michaelpga8ea0372017-04-06 20:41:35110 RequireFeature(kFeatureCSS3d);
111
112 CreateExtension();
113 StartChecker();
114 EXPECT_TRUE(runner_.called());
115 EXPECT_EQ(0u, runner_.errors().size());
116 EXPECT_TRUE(checker_->GetErrorMessage().empty());
117}
118
119// Tests multiple requirements failing (on some builds).
120TEST_F(RequirementsCheckerTest, RequirementsFailMultiple) {
121 size_t expected_errors = 0u;
122 if (!kSupportsWindowShape) {
123 RequireWindowShape();
124 expected_errors++;
125 }
michaelpga8ea0372017-04-06 20:41:35126 if (!MightSupportWebGL()) {
127 RequireFeature(kFeatureWebGL);
128 expected_errors++;
129 }
130 // css3d should always succeed.
131 RequireFeature(kFeatureCSS3d);
132
133 CreateExtension();
134 StartChecker();
135 EXPECT_TRUE(runner_.called());
136 EXPECT_EQ(expected_errors, runner_.errors().size());
137 EXPECT_EQ(expected_errors == 0, checker_->GetErrorMessage().empty());
138}
139
140// Tests a requirement that might fail asynchronously.
141TEST_F(RequirementsCheckerTest, RequirementsFailWebGL) {
142 content::GpuDataManager::GetInstance()->BlacklistWebGLForTesting();
143 RequireFeature(kFeatureWebGL);
144 CreateExtension();
145 StartChecker();
146
147 // TODO(michaelpg): Check that the runner actually finishes, which requires
148 // waiting for the GPU check to succeed: crbug.com/706204.
michaelpga8ea0372017-04-06 20:41:35149 if (runner_.errors().size()) {
150 EXPECT_THAT(runner_.errors(), testing::UnorderedElementsAre(
151 PreloadCheck::WEBGL_NOT_SUPPORTED));
152 EXPECT_FALSE(checker_->GetErrorMessage().empty());
153 }
154}
155
156} // namespace extensions