910e62b5创建于 1月15日历史提交
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/test/base/ash/javascript_browser_test.h"

#include <optional>

#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_restrictions.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/test/base/ash/js_test_api.h"
#include "components/privacy_sandbox/privacy_sandbox_features.h"
#include "content/public/browser/web_ui.h"
#include "net/base/filename_util.h"

void JavaScriptBrowserTest::AddLibrary(const base::FilePath& library_path) {
  user_libraries_.push_back(library_path);
}

JavaScriptBrowserTest::JavaScriptBrowserTest() = default;

JavaScriptBrowserTest::~JavaScriptBrowserTest() = default;

void JavaScriptBrowserTest::SetUpOnMainThread() {
  JsTestApiConfig config;
  library_search_paths_.push_back(config.search_path);
  DCHECK(user_libraries_.empty());
  user_libraries_ = config.default_libraries;

  // This generated test directory needs to exist for tests using the js2gtest
  // GN template.
  base::FilePath gen_test_data_directory;
  ASSERT_TRUE(base::PathService::Get(chrome::DIR_GEN_TEST_DATA,
                                     &gen_test_data_directory));
  library_search_paths_.push_back(gen_test_data_directory);

  base::FilePath source_root_directory;
  ASSERT_TRUE(base::PathService::Get(base::DIR_SRC_TEST_DATA_ROOT,
                                     &source_root_directory));
  library_search_paths_.push_back(source_root_directory);
}

bool JavaScriptBrowserTest::BuildJavascriptLibraries(
    std::vector<std::u16string>* libraries) {
  base::ScopedAllowBlockingForTesting allow_blocking;
  if (!libraries) {
    LOG(ERROR) << "BuildJavascriptLibraries called with null libraries pointer";
    return false;
  }

  // Path processing logic.
  auto resolve_mapped_or_absolute_path =
      [&](const base::FilePath& path) -> std::optional<base::FilePath> {
    const auto components = path.GetComponents();
    if (components.front() == FILE_PATH_LITERAL("ROOT_GEN_DIR")) {
      base::FilePath exe_dir;
      if (!base::PathService::Get(base::DIR_EXE, &exe_dir)) {
        LOG(ERROR) << "Failed to get base::DIR_EXE for ROOT_GEN_DIR: "
                   << path.value();
        return std::nullopt;
      }
      base::FilePath abs_path = exe_dir.AppendASCII("gen");
      for (size_t i = 1; i < components.size(); ++i) {
        abs_path = abs_path.Append(components[i]);
      }
      return abs_path.NormalizePathSeparators();
    }
    return path.IsAbsolute() ? std::optional<base::FilePath>(path)
                             : std::nullopt;
  };

  for (const auto& library_path : user_libraries_) {
    std::string library_content;
    base::FilePath library_absolute_path;
    bool found = false;
    // Resolve mapped paths or absolute paths.
    if (auto resolved_path = resolve_mapped_or_absolute_path(library_path)) {
      if (base::ReadFileToString(*resolved_path, &library_content)) {
        library_absolute_path = *resolved_path;
        found = true;
      } else {
        LOG(ERROR) << "Failed to read resolved library file: "
                   << resolved_path->value();
      }
    } else {
      // Handling relative paths.
      for (const auto& search_path : library_search_paths_) {
        base::FilePath candidate =
            base::MakeAbsoluteFilePath(search_path.Append(library_path));
        if (base::ReadFileToString(candidate, &library_content)) {
          library_absolute_path = candidate;
          found = true;
          break;
        }
      }
    }

    if (!found) {
      LOG(ERROR) << "Failed to load JS library: " << library_path.value();
      return false;
    }

    // This magic code puts filenames in stack traces.
    std::string source_url =
        "//# sourceURL=" +
        net::FilePathToFileURL(library_absolute_path).spec() + "\n";

    library_content.reserve(library_content.size() + source_url.size() + 3);
    library_content += ";\n";
    library_content += source_url;

    libraries->push_back(base::UTF8ToUTF16(library_content));
  }
  return true;
}

std::u16string JavaScriptBrowserTest::BuildRunTestJSCall(
    bool is_async,
    const std::string& function_name,
    base::Value::List test_func_args) {
  auto arguments = base::Value::List()
                       .Append(is_async)
                       .Append(function_name)
                       .Append(std::move(test_func_args));
  return content::WebUI::GetJavascriptCall(std::string("runTest"), arguments);
}

Profile* JavaScriptBrowserTest::GetProfile() const {
  return browser()->profile();
}