requirements_checker_unittest.cc 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. // 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. #include "extensions/browser/requirements_checker.h"
  5. #include <memory>
  6. #include <string>
  7. #include <vector>
  8. #include "base/memory/ref_counted.h"
  9. #include "base/strings/utf_string_conversions.h"
  10. #include "base/values.h"
  11. #include "content/public/browser/gpu_data_manager.h"
  12. #include "extensions/browser/extension_system.h"
  13. #include "extensions/browser/extensions_test.h"
  14. #include "extensions/browser/preload_check.h"
  15. #include "extensions/browser/preload_check_test_util.h"
  16. #include "extensions/common/extension.h"
  17. #include "extensions/common/manifest.h"
  18. #include "testing/gmock/include/gmock/gmock.h"
  19. #include "testing/gtest/include/gtest/gtest.h"
  20. #include "ui/base/l10n/l10n_util.h"
  21. namespace extensions {
  22. namespace {
  23. // Whether this build supports the window.shape requirement.
  24. const bool kSupportsWindowShape =
  25. #if defined(USE_AURA)
  26. true;
  27. #else
  28. false;
  29. #endif
  30. // Returns true if a WebGL check might not fail immediately.
  31. bool MightSupportWebGL() {
  32. return content::GpuDataManager::GetInstance()->GpuAccessAllowed(nullptr);
  33. }
  34. const char kFeaturesKey[] = "requirements.3D.features";
  35. const char kFeatureWebGL[] = "webgl";
  36. const char kFeatureCSS3d[] = "css3d";
  37. } // namespace
  38. class RequirementsCheckerTest : public ExtensionsTest {
  39. public:
  40. RequirementsCheckerTest() {
  41. manifest_dict_ = std::make_unique<base::DictionaryValue>();
  42. }
  43. ~RequirementsCheckerTest() override {}
  44. void CreateExtension() {
  45. manifest_dict_->SetStringKey("name", "dummy name");
  46. manifest_dict_->SetStringKey("version", "1");
  47. manifest_dict_->SetIntKey("manifest_version", 2);
  48. std::string error;
  49. extension_ =
  50. Extension::Create(base::FilePath(), mojom::ManifestLocation::kUnpacked,
  51. *manifest_dict_, Extension::NO_FLAGS, &error);
  52. ASSERT_TRUE(extension_.get()) << error;
  53. }
  54. protected:
  55. void StartChecker() {
  56. checker_ = std::make_unique<RequirementsChecker>(extension_);
  57. // TODO(michaelpg): This should normally not have to be async. Use Run()
  58. // instead of RunUntilComplete() after crbug.com/708354 is addressed.
  59. runner_.RunUntilComplete(checker_.get());
  60. }
  61. void RequireWindowShape() {
  62. manifest_dict_->SetBoolPath("requirements.window.shape", true);
  63. }
  64. void RequireFeature(const char feature[]) {
  65. if (!manifest_dict_->FindKey(kFeaturesKey))
  66. manifest_dict_->Set(kFeaturesKey, std::make_unique<base::ListValue>());
  67. base::ListValue* features_list = nullptr;
  68. ASSERT_TRUE(manifest_dict_->GetList(kFeaturesKey, &features_list));
  69. features_list->Append(feature);
  70. }
  71. std::unique_ptr<RequirementsChecker> checker_;
  72. PreloadCheckRunner runner_;
  73. private:
  74. scoped_refptr<Extension> extension_;
  75. std::unique_ptr<base::DictionaryValue> manifest_dict_;
  76. };
  77. // Tests no requirements.
  78. TEST_F(RequirementsCheckerTest, RequirementsEmpty) {
  79. CreateExtension();
  80. StartChecker();
  81. EXPECT_TRUE(runner_.called());
  82. EXPECT_EQ(0u, runner_.errors().size());
  83. EXPECT_TRUE(checker_->GetErrorMessage().empty());
  84. }
  85. // Tests fulfilled requirements.
  86. TEST_F(RequirementsCheckerTest, RequirementsSuccess) {
  87. if (kSupportsWindowShape)
  88. RequireWindowShape();
  89. RequireFeature(kFeatureCSS3d);
  90. CreateExtension();
  91. StartChecker();
  92. EXPECT_TRUE(runner_.called());
  93. EXPECT_EQ(0u, runner_.errors().size());
  94. EXPECT_TRUE(checker_->GetErrorMessage().empty());
  95. }
  96. // Tests multiple requirements failing (on some builds).
  97. TEST_F(RequirementsCheckerTest, RequirementsFailMultiple) {
  98. size_t expected_errors = 0u;
  99. if (!kSupportsWindowShape) {
  100. RequireWindowShape();
  101. expected_errors++;
  102. }
  103. if (!MightSupportWebGL()) {
  104. RequireFeature(kFeatureWebGL);
  105. expected_errors++;
  106. }
  107. // css3d should always succeed.
  108. RequireFeature(kFeatureCSS3d);
  109. CreateExtension();
  110. StartChecker();
  111. EXPECT_TRUE(runner_.called());
  112. EXPECT_EQ(expected_errors, runner_.errors().size());
  113. EXPECT_EQ(expected_errors == 0, checker_->GetErrorMessage().empty());
  114. }
  115. // Tests a requirement that might fail asynchronously.
  116. TEST_F(RequirementsCheckerTest, RequirementsFailWebGL) {
  117. content::GpuDataManager::GetInstance()->BlocklistWebGLForTesting();
  118. RequireFeature(kFeatureWebGL);
  119. CreateExtension();
  120. StartChecker();
  121. // TODO(michaelpg): Check that the runner actually finishes, which requires
  122. // waiting for the GPU check to succeed: crbug.com/706204.
  123. if (runner_.errors().size()) {
  124. EXPECT_THAT(runner_.errors(), testing::UnorderedElementsAre(
  125. PreloadCheck::Error::kWebglNotSupported));
  126. EXPECT_FALSE(checker_->GetErrorMessage().empty());
  127. }
  128. }
  129. } // namespace extensions