File: extension_js_browser_test.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (166 lines) | stat: -rw-r--r-- 6,359 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
// 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/extension_js_browser_test.h"

#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>

#include "base/command_line.h"
#include "base/containers/contains.h"
#include "base/files/file_path.h"
#include "base/functional/callback.h"
#include "base/json/json_reader.h"
#include "base/strings/strcat.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/extensions/component_loader.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/test/base/ash/javascript_browser_test.h"
#include "chrome/test/base/test_switches.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_test_utils.h"
#include "extensions/browser/background_script_executor.h"
#include "extensions/browser/browsertest_util.h"
#include "extensions/browser/extension_host.h"
#include "extensions/browser/extension_host_test_helper.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_registry_observer.h"
#include "extensions/browser/extension_registry_test_helper.h"
#include "extensions/browser/process_manager.h"
#include "extensions/browser/service_worker/service_worker_host.h"
#include "extensions/browser/service_worker/service_worker_test_utils.h"
#include "extensions/common/extension.h"
#include "ui/base/ime/ash/extension_ime_util.h"

namespace {

const std::vector<std::string>& GetExtensionIdsToCollectCoverage() {
  static const std::vector<std::string> extensions_for_coverage = {
      extension_misc::kChromeVoxExtensionId,
      extension_misc::kSelectToSpeakExtensionId,
      extension_misc::kSwitchAccessExtensionId,
      extension_misc::kAccessibilityCommonExtensionId,
      extension_misc::kEnhancedNetworkTtsExtensionId,
      ash::extension_ime_util::kBrailleImeExtensionId,
  };
  return extensions_for_coverage;
}

}  // namespace

ExtensionJSBrowserTest::ExtensionJSBrowserTest() = default;

ExtensionJSBrowserTest::~ExtensionJSBrowserTest() = default;

void ExtensionJSBrowserTest::SetUpOnMainThread() {
  JavaScriptBrowserTest::SetUpOnMainThread();

  // Set up coverage collection.
  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
  if (command_line->HasSwitch(switches::kDevtoolsCodeCoverage)) {
    base::FilePath devtools_code_coverage_dir =
        command_line->GetSwitchValuePath(switches::kDevtoolsCodeCoverage);
    ShouldInspectDevToolsAgentHostCallback callback =
        base::BindRepeating([](content::DevToolsAgentHost* host) {
          const auto& ext_ids = GetExtensionIdsToCollectCoverage();
          for (const auto& ext_id : ext_ids) {
            if (base::Contains(host->GetURL().path(), ext_id) &&
                host->GetType() == "background_page") {
              return true;
            }
          }
          return false;
        });
    coverage_handler_ = std::make_unique<DevToolsAgentCoverageObserver>(
        devtools_code_coverage_dir, std::move(callback));
  }
}

void ExtensionJSBrowserTest::WaitForExtension(const char* extension_id,
                                              base::OnceClosure load_cb) {
  extension_id_ = extension_id;

  // ExtensionHosts only exist when there is an associated RenderFrame.
  // Initialize both an ExtensionHostTestHelper and a ServiceWorkerObserver
  // before running the load callback, to avoid missing the relevant event.
  extensions::ExtensionHostTestHelper host_helper(GetProfile(), extension_id);
  extensions::ExtensionRegistryTestHelper observer(extension_id, GetProfile());
  std::move(load_cb).Run();

  if (observer.WaitForManifestVersion() == 3) {
    observer.WaitForServiceWorkerStart();
    extension_host_browser_context_ = GetProfile();
    return;
  }

  extensions::ExtensionHost* extension_host =
      host_helper.WaitForHostCompletedFirstLoad();
  ASSERT_TRUE(extension_host);
  extension_host_browser_context_ = extension_host->browser_context();
}

bool ExtensionJSBrowserTest::RunJavascriptTestF(bool is_async,
                                                const std::string& test_fixture,
                                                const std::string& test_name) {
  if (!extension_host_browser_context_) {
    ADD_FAILURE() << "ExtensionHost failed to start";
    return false;
  }
  std::vector<std::u16string> scripts;

  base::Value::Dict test_runner_params;
  if (embedded_test_server()->Started()) {
    test_runner_params.Set("testServerBaseUrl",
                           embedded_test_server()->base_url().spec());
  }

  if (!libs_loaded_) {
    if (!BuildJavascriptLibraries(&scripts)) {
      ADD_FAILURE() << "Failed to build JavaScript libraries";
      return false;
    }
    libs_loaded_ = true;
  }

  scripts.push_back(base::UTF8ToUTF16(content::JsReplace(
      "const testRunnerParams = $1;", std::move(test_runner_params))));

  scripts.push_back(BuildRunTestJSCall(
      is_async, "RUN_TEST_F",
      base::Value::List().Append(test_fixture).Append(test_name)));

  std::u16string script_16 = base::JoinString(scripts, u"\n");
  std::string script = base::UTF16ToUTF8(script_16);

  auto result = extensions::BackgroundScriptExecutor::ExecuteScript(
      extension_host_browser_context_, extension_id_, script,
      extensions::BackgroundScriptExecutor::ResultCapture::kSendScriptResult);

  if (!result.is_string())
    return false;

  if (coverage_handler_ && coverage_handler_->CoverageEnabled()) {
    const std::string& full_test_name = base::StrCat({test_fixture, test_name});
    coverage_handler_->CollectCoverage(full_test_name);
  }

  std::string result_str = result.GetString();
  std::optional<base::Value> value_result = base::JSONReader::Read(result_str);
  const base::Value::Dict& dict_value = value_result->GetDict();

  bool test_result = dict_value.FindBool("result").value();
  const std::string* test_result_message = dict_value.FindString("message");
  CHECK(test_result_message);
  if (!test_result_message->empty()) {
    ADD_FAILURE() << *test_result_message;
  }
  return test_result;
}