15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h"
11ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h"
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/sequenced_worker_pool.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_browsertest.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/requirements_checker.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_paths.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension_file_util.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/gpu_data_manager.h"
21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h"
2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "gpu/config/gpu_info.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/generated_resources.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_switches.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RequirementsCheckerBrowserTest : public ExtensionBrowserTest {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<const Extension> LoadExtensionFromDirName(
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::string& extension_dir_name) {
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath extension_path;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string load_error;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PathService::Get(chrome::DIR_TEST_DATA, &extension_path);
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extension_path = extension_path.AppendASCII("requirements_checker")
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   .AppendASCII(extension_dir_name);
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<const Extension> extension =
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        extension_file_util::LoadExtension(extension_path, Manifest::UNPACKED,
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           0, &load_error);
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(load_error.length() == 0u);
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return extension;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ValidateRequirementErrors(std::vector<std::string> expected_errors,
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 std::vector<std::string> actual_errors) {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(expected_errors, actual_errors);
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    requirement_errors_.swap(actual_errors);
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This should only be called once per test instance. Calling more than once
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // will result in stale information in the GPUDataManager which will throw off
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the RequirementsChecker.
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void BlackListGPUFeatures(const std::vector<std::string>& features) {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    static const std::string json_blacklist =
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "{\n"
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  \"name\": \"gpu blacklist\",\n"
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  \"version\": \"1.0\",\n"
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  \"entries\": [\n"
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "    {\n"
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "      \"id\": 1,\n"
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "      \"features\": [\"" + JoinString(features, "\", \"") + "\"]\n"
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "    }\n"
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  ]\n"
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "}";
6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    gpu::GPUInfo gpu_info;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::GpuDataManager::GetInstance()->InitializeForTesting(
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        json_blacklist, gpu_info);
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> requirement_errors_;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RequirementsChecker checker_;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(RequirementsCheckerBrowserTest, CheckEmptyExtension) {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<const Extension> extension(
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LoadExtensionFromDirName("no_requirements"));
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(extension.get());
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  checker_.Check(extension, base::Bind(
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &RequirementsCheckerBrowserTest::ValidateRequirementErrors,
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Unretained(this), std::vector<std::string>()));
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::BrowserThread::GetBlockingPool()->FlushForTesting();
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(RequirementsCheckerBrowserTest, CheckNpapiExtension) {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<const Extension> extension(
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LoadExtensionFromDirName("require_npapi"));
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(extension.get());
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> expected_errors;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // npapi plugins are dissalowd on CROMEOS.
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected_errors.push_back(l10n_util::GetStringUTF8(
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IDS_EXTENSION_NPAPI_NOT_SUPPORTED));
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // defined(OS_CHROMEOS)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  checker_.Check(extension, base::Bind(
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &RequirementsCheckerBrowserTest::ValidateRequirementErrors,
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Unretained(this), expected_errors));
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::BrowserThread::GetBlockingPool()->FlushForTesting();
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(RequirementsCheckerBrowserTest, DisallowCSS3D) {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<const Extension> extension(
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LoadExtensionFromDirName("require_3d"));
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(extension.get());
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Blacklist css3d
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> blacklisted_features;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blacklisted_features.push_back("accelerated_compositing");
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BlackListGPUFeatures(blacklisted_features);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::BrowserThread::GetBlockingPool()->FlushForTesting();
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> expected_errors;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected_errors.push_back(l10n_util::GetStringUTF8(
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IDS_EXTENSION_CSS3D_NOT_SUPPORTED));
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  checker_.Check(extension, base::Bind(
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &RequirementsCheckerBrowserTest::ValidateRequirementErrors,
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Unretained(this), expected_errors));
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::BrowserThread::GetBlockingPool()->FlushForTesting();
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(RequirementsCheckerBrowserTest, DisallowWebGL) {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<const Extension> extension(
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LoadExtensionFromDirName("require_3d"));
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(extension.get());
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Backlist webgl
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> blacklisted_features;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blacklisted_features.push_back("webgl");
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BlackListGPUFeatures(blacklisted_features);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::BrowserThread::GetBlockingPool()->FlushForTesting();
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> expected_errors;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected_errors.push_back(l10n_util::GetStringUTF8(
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IDS_EXTENSION_WEBGL_NOT_SUPPORTED));
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  checker_.Check(extension, base::Bind(
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &RequirementsCheckerBrowserTest::ValidateRequirementErrors,
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Unretained(this), expected_errors));
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::BrowserThread::GetBlockingPool()->FlushForTesting();
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(RequirementsCheckerBrowserTest, DisallowGPUFeatures) {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<const Extension> extension(
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LoadExtensionFromDirName("require_3d"));
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(extension.get());
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Backlist both webgl and css3d
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> blacklisted_features;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blacklisted_features.push_back("webgl");
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blacklisted_features.push_back("accelerated_compositing");
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BlackListGPUFeatures(blacklisted_features);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::BrowserThread::GetBlockingPool()->FlushForTesting();
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> expected_errors;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected_errors.push_back(l10n_util::GetStringUTF8(
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IDS_EXTENSION_WEBGL_NOT_SUPPORTED));
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected_errors.push_back(l10n_util::GetStringUTF8(
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IDS_EXTENSION_CSS3D_NOT_SUPPORTED));
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  checker_.Check(extension, base::Bind(
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &RequirementsCheckerBrowserTest::ValidateRequirementErrors,
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Unretained(this), expected_errors));
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::BrowserThread::GetBlockingPool()->FlushForTesting();
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(RequirementsCheckerBrowserTest, Check3DExtension) {
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<const Extension> extension(
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LoadExtensionFromDirName("require_3d"));
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(extension.get());
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
176a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  std::vector<std::string> expected_errors;
177a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
178a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!content::GpuDataManager::GetInstance()->GpuAccessAllowed(NULL)) {
179a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    expected_errors.push_back(l10n_util::GetStringUTF8(
180a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        IDS_EXTENSION_WEBGL_NOT_SUPPORTED));
181a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    expected_errors.push_back(l10n_util::GetStringUTF8(
182a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        IDS_EXTENSION_CSS3D_NOT_SUPPORTED));
183a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
184a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  checker_.Check(extension, base::Bind(
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &RequirementsCheckerBrowserTest::ValidateRequirementErrors,
187a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      base::Unretained(this), expected_errors));
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::BrowserThread::GetBlockingPool()->FlushForTesting();
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
191c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch}  // namespace extensions
192