1 // Copyright 2014 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 "content/web_test/renderer/test_runner.h"
6
7 #include <stddef.h>
8
9 #include <algorithm>
10 #include <clocale>
11 #include <limits>
12 #include <utility>
13
14 #include "base/bind.h"
15 #include "base/command_line.h"
16 #include "base/logging.h"
17 #include "base/macros.h"
18 #include "base/stl_util.h"
19 #include "base/strings/nullable_string16.h"
20 #include "base/strings/stringprintf.h"
21 #include "base/strings/utf_string_conversions.h"
22 #include "build/build_config.h"
23 #include "cc/paint/paint_canvas.h"
24 #include "content/public/common/isolated_world_ids.h"
25 #include "content/public/common/use_zoom_for_dsf_policy.h"
26 #include "content/renderer/render_thread_impl.h"
27 #include "content/web_test/common/web_test_constants.h"
28 #include "content/web_test/common/web_test_string_util.h"
29 #include "content/web_test/renderer/app_banner_service.h"
30 #include "content/web_test/renderer/blink_test_helpers.h"
31 #include "content/web_test/renderer/fake_subresource_filter.h"
32 #include "content/web_test/renderer/pixel_dump.h"
33 #include "content/web_test/renderer/spell_check_client.h"
34 #include "content/web_test/renderer/test_preferences.h"
35 #include "content/web_test/renderer/web_frame_test_proxy.h"
36 #include "content/web_test/renderer/web_view_test_proxy.h"
37 #include "content/web_test/renderer/web_widget_test_proxy.h"
38 #include "gin/arguments.h"
39 #include "gin/array_buffer.h"
40 #include "gin/handle.h"
41 #include "gin/object_template_builder.h"
42 #include "gin/wrappable.h"
43 #include "mojo/public/mojom/base/text_direction.mojom-forward.h"
44 #include "services/network/public/mojom/cors.mojom.h"
45 #include "third_party/blink/public/common/page/page_zoom.h"
46 #include "third_party/blink/public/common/permissions/permission_utils.h"
47 #include "third_party/blink/public/common/web_preferences/web_preferences.h"
48 #include "third_party/blink/public/mojom/app_banner/app_banner.mojom.h"
49 #include "third_party/blink/public/mojom/clipboard/clipboard.mojom.h"
50 #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
51 #include "third_party/blink/public/platform/web_cache.h"
52 #include "third_party/blink/public/platform/web_data.h"
53 #include "third_party/blink/public/platform/web_isolated_world_ids.h"
54 #include "third_party/blink/public/platform/web_isolated_world_info.h"
55 #include "third_party/blink/public/platform/web_string.h"
56 #include "third_party/blink/public/platform/web_url_response.h"
57 #include "third_party/blink/public/web/blink.h"
58 #include "third_party/blink/public/web/web_array_buffer.h"
59 #include "third_party/blink/public/web/web_array_buffer_converter.h"
60 #include "third_party/blink/public/web/web_document.h"
61 #include "third_party/blink/public/web/web_document_loader.h"
62 #include "third_party/blink/public/web/web_frame.h"
63 #include "third_party/blink/public/web/web_frame_widget.h"
64 #include "third_party/blink/public/web/web_input_element.h"
65 #include "third_party/blink/public/web/web_local_frame.h"
66 #include "third_party/blink/public/web/web_manifest_manager.h"
67 #include "third_party/blink/public/web/web_render_theme.h"
68 #include "third_party/blink/public/web/web_script_source.h"
69 #include "third_party/blink/public/web/web_security_policy.h"
70 #include "third_party/blink/public/web/web_serialized_script_value.h"
71 #include "third_party/blink/public/web/web_testing_support.h"
72 #include "third_party/blink/public/web/web_view.h"
73 #include "third_party/skia/include/core/SkBitmap.h"
74 #include "third_party/skia/include/core/SkCanvas.h"
75 #include "ui/gfx/color_space.h"
76 #include "ui/gfx/geometry/rect.h"
77 #include "ui/gfx/geometry/rect_f.h"
78 #include "ui/gfx/geometry/size.h"
79 #include "ui/gfx/skia_util.h"
80 #include "ui/gfx/test/icc_profiles.h"
81
82 #if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_FUCHSIA)
83 #include "third_party/blink/public/platform/web_font_render_style.h"
84 #endif
85
86 namespace content {
87
88 namespace {
89
90 // A V8 callback with bound arguments, and the ability to pass additional
91 // arguments at time of calling Run().
92 using BoundV8Callback =
93 base::OnceCallback<void(const std::vector<v8::Local<v8::Value>>&)>;
94 // Returns an empty set of args for running the BoundV8Callback.
NoV8Args()95 std::vector<v8::Local<v8::Value>> NoV8Args() {
96 return {};
97 }
98
99 // Returns 3 arguments, width, height, and an array of pixel values. Takes a
100 // v8::Context::Scope just to prove one exists in the caller.
ConvertBitmapToV8(const v8::Context::Scope & context_scope,const SkBitmap & bitmap)101 std::vector<v8::Local<v8::Value>> ConvertBitmapToV8(
102 const v8::Context::Scope& context_scope,
103 const SkBitmap& bitmap) {
104 v8::Isolate* isolate = blink::MainThreadIsolate();
105
106 std::vector<v8::Local<v8::Value>> args;
107 // Note that the bitmap size can be 0 if there's no pixels.
108 args.push_back(v8::Number::New(isolate, bitmap.info().width()));
109 args.push_back(v8::Number::New(isolate, bitmap.info().height()));
110 if (bitmap.isNull()) {
111 // The 3rd argument will be undefined (an empty argument is not valid and
112 // would crash).
113 return args;
114 }
115
116 // Always produce pixels in RGBA order, regardless of the platform default.
117 SkImageInfo info = bitmap.info().makeColorType(kRGBA_8888_SkColorType);
118 size_t row_bytes = info.minRowBytes();
119
120 blink::WebArrayBuffer buffer =
121 blink::WebArrayBuffer::Create(info.computeByteSize(row_bytes), 1);
122 bool read = bitmap.readPixels(info, buffer.Data(), row_bytes, 0, 0);
123 CHECK(read);
124
125 args.push_back(blink::WebArrayBufferConverter::ToV8Value(
126 &buffer, isolate->GetCurrentContext()->Global(), isolate));
127 return args;
128 }
129
ConvertAndSet(gin::Arguments * args,int * set_param)130 void ConvertAndSet(gin::Arguments* args, int* set_param) {
131 v8::Local<v8::Value> value = args->PeekNext();
132 v8::Maybe<int> result = value->Int32Value(args->GetHolderCreationContext());
133
134 if (result.IsNothing()) {
135 // Skip so the error is thrown for the correct argument as PeekNext doesn't
136 // update the current argument pointer.
137 args->Skip();
138 args->ThrowError();
139 return;
140 }
141
142 *set_param = result.ToChecked();
143 }
144
ConvertAndSet(gin::Arguments * args,bool * set_param)145 void ConvertAndSet(gin::Arguments* args, bool* set_param) {
146 v8::Local<v8::Value> value = args->PeekNext();
147 *set_param = value->BooleanValue(args->isolate());
148 }
149
ConvertAndSet(gin::Arguments * args,blink::WebString * set_param)150 void ConvertAndSet(gin::Arguments* args, blink::WebString* set_param) {
151 v8::Local<v8::Value> value = args->PeekNext();
152 v8::MaybeLocal<v8::String> result =
153 value->ToString(args->GetHolderCreationContext());
154
155 if (result.IsEmpty()) {
156 // Skip so the error is thrown for the correct argument as PeekNext doesn't
157 // update the current argument pointer.
158 args->Skip();
159 args->ThrowError();
160 return;
161 }
162
163 *set_param = web_test_string_util::V8StringToWebString(
164 args->isolate(), result.ToLocalChecked());
165 }
166
167 } // namespace
168
169 class TestRunnerBindings : public gin::Wrappable<TestRunnerBindings> {
170 public:
171 static gin::WrapperInfo kWrapperInfo;
172
173 static void Install(TestRunner* test_runner,
174 WebFrameTestProxy* frame,
175 SpellCheckClient* spell_check,
176 bool is_wpt_reftest,
177 bool is_main_test_window);
178
179 // Wraps the V8 function in a base::OnceCallback that binds in the given V8
180 // arguments. The callback will do nothing when Run() if the
181 // TestRunnerBindings has been destroyed, so it is safe to PostTask(). At the
182 // time of Run(), further arguments can be passed to the V8 function.
183 BoundV8Callback WrapV8Callback(
184 v8::Local<v8::Function> v8_callback,
185 std::vector<v8::Local<v8::Value>> args_to_bind = {});
186 // Same as WrapV8Callback but Run() takes no arguments, so only bound
187 // arguments can be passed to the V8 function.
188 base::OnceClosure WrapV8Closure(
189 v8::Local<v8::Function> v8_callback,
190 std::vector<v8::Local<v8::Value>> args_to_bind = {});
191 // Calls WrapV8Callback() and then posts the resulting callback to the frame's
192 // task runner.
193 void PostV8Callback(v8::Local<v8::Function> v8_callback,
194 std::vector<v8::Local<v8::Value>> args = {});
195
GetWebFrame()196 blink::WebLocalFrame* GetWebFrame() { return frame_->GetWebFrame(); }
197
198 private:
199 explicit TestRunnerBindings(TestRunner* test_runner,
200 WebFrameTestProxy* frame,
201 SpellCheckClient* spell_check);
202 ~TestRunnerBindings() override;
203
204 // gin::Wrappable overrides.
205 gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
206 v8::Isolate* isolate) override;
207
208 void AddOriginAccessAllowListEntry(const std::string& source_origin,
209 const std::string& destination_protocol,
210 const std::string& destination_host,
211 bool allow_destination_subdomains);
212 void AddWebPageOverlay();
213 void AllowPointerLock();
214 void SetHighlightAds();
215 void CapturePrintingPixelsThen(v8::Local<v8::Function> callback);
216 void CheckForLeakedWindows();
217 void ClearAllDatabases();
218 void ClearTrustTokenState(v8::Local<v8::Function> callback);
219 void CopyImageThen(int x, int y, v8::Local<v8::Function> callback);
220 void DisableMockScreenOrientation();
221 void DispatchBeforeInstallPromptEvent(
222 const std::vector<std::string>& event_platforms,
223 v8::Local<v8::Function> callback);
224 void DropPointerLock();
225 void DumpAsMarkup();
226 void DumpAsText();
227 void DumpAsTextWithPixelResults();
228 void DumpAsLayout();
229 void DumpAsLayoutWithPixelResults();
230 void DumpChildFrames();
231 void DumpBackForwardList();
232 void DumpCreateView();
233 void DumpDragImage();
234 void DumpEditingCallbacks();
235 void DumpFrameLoadCallbacks();
236 void DumpIconChanges();
237 void DumpNavigationPolicy();
238 void DumpPermissionClientCallbacks();
239 void DumpPingLoaderCallbacks();
240 void DumpSelectionRect();
241 void DumpTitleChanges();
242 void DumpUserGestureInFrameLoadCallbacks();
243 void EvaluateScriptInIsolatedWorld(int world_id, const std::string& script);
244 void ExecCommand(gin::Arguments* args);
245 void TriggerTestInspectorIssue(gin::Arguments* args);
246 void FocusDevtoolsSecondaryWindow();
247 void ForceNextDrawingBufferCreationToFail();
248 void ForceNextWebGLContextCreationToFail();
249 void GetBluetoothManualChooserEvents(v8::Local<v8::Function> callback);
250 void GetManifestThen(v8::Local<v8::Function> callback);
251 base::FilePath::StringType GetWritableDirectory();
252 void InsertStyleSheet(const std::string& source_code);
253 void UpdateAllLifecyclePhasesAndComposite();
254 void UpdateAllLifecyclePhasesAndCompositeThen(
255 v8::Local<v8::Function> callback);
256 void SetAnimationRequiresRaster(bool do_raster);
257 void LogToStderr(const std::string& output);
258 void NotImplemented(const gin::Arguments& args);
259 void NotifyDone();
260 void OverridePreference(gin::Arguments* args);
261 void QueueBackNavigation(int how_far_back);
262 void QueueForwardNavigation(int how_far_forward);
263 void QueueLoad(gin::Arguments* args);
264 void QueueLoadingScript(const std::string& script);
265 void QueueNonLoadingScript(const std::string& script);
266 void QueueReload();
267 void RemoveSpellCheckResolvedCallback();
268 void RemoveWebPageOverlay();
269 void ResolveBeforeInstallPromptPromise(const std::string& platform);
270 void RunIdleTasks(v8::Local<v8::Function> callback);
271 void SendBluetoothManualChooserEvent(const std::string& event,
272 const std::string& argument);
273 void SetAcceptLanguages(const std::string& accept_languages);
274 void SetAllowFileAccessFromFileURLs(bool allow);
275 void SetAllowRunningOfInsecureContent(bool allowed);
276 void SetBlockThirdPartyCookies(bool block);
277 void SetAudioData(const gin::ArrayBufferView& view);
278 void SetBackingScaleFactor(double value, v8::Local<v8::Function> callback);
279 void SetBluetoothFakeAdapter(const std::string& adapter_name,
280 v8::Local<v8::Function> callback);
281 void SetBluetoothManualChooser(bool enable);
282 void SetCanOpenWindows();
283 void SetColorProfile(const std::string& name,
284 v8::Local<v8::Function> callback);
285 void SetCustomPolicyDelegate(gin::Arguments* args);
286 void SetCustomTextOutput(const std::string& output);
287 void SetDatabaseQuota(int quota);
288 void SetDisallowedSubresourcePathSuffixes(std::vector<std::string> suffixes,
289 bool block_subresources);
290 void SetDomainRelaxationForbiddenForURLScheme(bool forbidden,
291 const std::string& scheme);
292 void SetDumpConsoleMessages(bool value);
293 void SetDumpJavaScriptDialogs(bool value);
294 void SetEffectiveConnectionType(const std::string& connection_type);
295 void SetFilePathForMockFileDialog(const base::FilePath::StringType& path);
296 void SetMockSpellCheckerEnabled(bool enabled);
297 void SetImagesAllowed(bool allowed);
298 void SetIsolatedWorldInfo(int world_id,
299 v8::Local<v8::Value> security_origin,
300 v8::Local<v8::Value> content_security_policy);
301 void SetJavaScriptCanAccessClipboard(bool can_access);
302 void SetMockScreenOrientation(const std::string& orientation);
303 void SetPOSIXLocale(const std::string& locale);
304 void SetMainWindowHidden(bool hidden);
305 void SetPermission(const std::string& name,
306 const std::string& value,
307 const std::string& origin,
308 const std::string& embedding_origin);
309 void SetPluginsAllowed(bool allowed);
310 void SetPluginsEnabled(bool enabled);
311 void SetPointerLockWillFail();
312 void SetPointerLockWillRespondAsynchronously();
313 void SetPopupBlockingEnabled(bool block_popups);
314 void SetPrinting();
315 void SetPrintingForFrame(const std::string& frame_name);
316 void SetScriptsAllowed(bool allowed);
317 void SetShouldGeneratePixelResults(bool);
318 void SetShouldStayOnPageAfterHandlingBeforeUnload(bool value);
319 void SetSpellCheckResolvedCallback(v8::Local<v8::Function> callback);
320 void SetStorageAllowed(bool allowed);
321 void SetTabKeyCyclesThroughElements(bool tab_key_cycles_through_elements);
322 void SetTextDirection(const std::string& direction_name);
323 void SetTextSubpixelPositioning(bool value);
324 void SetTrustTokenKeyCommitments(const std::string& raw_commitments,
325 v8::Local<v8::Function> callback);
326 void SetWillSendRequestClearHeader(const std::string& header);
327 void SetWillSendRequestClearReferrer();
328 void SimulateBrowserWindowFocus(bool value);
329 void NavigateSecondaryWindow(const std::string& url);
330 void InspectSecondaryWindow();
331 void SimulateWebNotificationClick(gin::Arguments* args);
332 void SimulateWebNotificationClose(const std::string& title, bool by_user);
333 void SimulateWebContentIndexDelete(const std::string& id);
334 void UseUnfortunateSynchronousResizeMode();
335 void WaitForPolicyDelegate();
336 void WaitUntilDone();
337 void WaitUntilExternalURLLoad();
338 void DisableAutoResizeMode(int new_width, int new_height);
339 void EnableAutoResizeMode(int min_width,
340 int min_height,
341 int max_width,
342 int max_height);
343 v8::Local<v8::Value> EvaluateScriptInIsolatedWorldAndReturnValue(
344 int world_id,
345 const std::string& script);
346 bool FindString(const std::string& search_text,
347 const std::vector<std::string>& options_array);
348
349 bool IsCommandEnabled(const std::string& command);
350 std::string PathToLocalResource(const std::string& path);
351 std::string PlatformName();
352 std::string SelectionAsMarkup();
353 void TextZoomIn();
354 void TextZoomOut();
355 void ZoomPageIn();
356 void ZoomPageOut();
357 void SetPageZoomFactor(double factor);
358 std::string TooltipText();
359
360 int WebHistoryItemCount();
361 int WindowCount();
362
363 void InvokeV8Callback(v8::UniquePersistent<v8::Function> callback,
364 std::vector<v8::UniquePersistent<v8::Value>> bound_args,
365 const std::vector<v8::Local<v8::Value>>& runtime_args);
366
367 // Hears about the RenderFrame in |frame_| being destroyed. The
368 // TestRunningBindings should not do anything thereafter.
OnFrameDestroyed()369 void OnFrameDestroyed() {
370 invalid_ = true;
371 }
372
373 // Becomes true when the underlying frame is destroyed. Then the class should
374 // stop doing anything.
375 bool invalid_ = false;
376
377 TestRunner* runner_;
378 WebFrameTestProxy* const frame_;
379 SpellCheckClient* const spell_check_;
380 TestPreferences prefs_;
381 std::unique_ptr<AppBannerService> app_banner_service_;
382
383 base::WeakPtrFactory<TestRunnerBindings> weak_ptr_factory_{this};
384
385 DISALLOW_COPY_AND_ASSIGN(TestRunnerBindings);
386 };
387
388 gin::WrapperInfo TestRunnerBindings::kWrapperInfo = {gin::kEmbedderNativeGin};
389
390 // static
Install(TestRunner * test_runner,WebFrameTestProxy * frame,SpellCheckClient * spell_check,bool is_wpt_test,bool is_main_test_window)391 void TestRunnerBindings::Install(TestRunner* test_runner,
392 WebFrameTestProxy* frame,
393 SpellCheckClient* spell_check,
394 bool is_wpt_test,
395 bool is_main_test_window) {
396 v8::Isolate* isolate = blink::MainThreadIsolate();
397 v8::HandleScope handle_scope(isolate);
398 blink::WebLocalFrame* web_frame = frame->GetWebFrame();
399 v8::Local<v8::Context> context = web_frame->MainWorldScriptContext();
400 CHECK(!context.IsEmpty());
401
402 v8::Context::Scope context_scope(context);
403
404 TestRunnerBindings* wrapped =
405 new TestRunnerBindings(test_runner, frame, spell_check);
406 gin::Handle<TestRunnerBindings> bindings =
407 gin::CreateHandle(isolate, wrapped);
408 CHECK(!bindings.IsEmpty());
409 v8::Local<v8::Object> global = context->Global();
410 v8::Local<v8::Value> v8_bindings = bindings.ToV8();
411
412 global->Set(context, gin::StringToV8(isolate, "testRunner"), v8_bindings)
413 .Check();
414
415 // Inject some JavaScript to the top-level frame of a reftest in the
416 // web-platform-tests suite to have the same reftest screenshot timing as
417 // upstream WPT:
418 //
419 // 1. For normal reftest, we would like to take screenshots after web fonts
420 // are loaded, i.e. replicate the behavior of this injected script:
421 // https://github.com/web-platform-tests/wpt/blob/master/tools/wptrunner/wptrunner/executors/reftest-wait_webdriver.js
422 // 2. For reftests with a 'reftest-wait' or crash tests with a 'test-wait'
423 // class on the root element, reference comparison is delayed (and a
424 // TestRendered event emitted in its place) until that class attribute is
425 // removed. To support this feature, we use a mutation observer.
426 // https://web-platform-tests.org/writing-tests/reftests.html#controlling-when-comparison-occurs
427 // https://web-platform-tests.org/writing-tests/crashtest.html
428 //
429 // Note that this method may be called multiple times on a frame, so we put
430 // the code behind a flag. The flag is safe to be installed on testRunner
431 // because WPT reftests never access this object.
432 if (is_wpt_test && is_main_test_window && !web_frame->Parent() &&
433 !web_frame->Opener()) {
434 web_frame->ExecuteScript(blink::WebString(
435 R"(if (!window.testRunner._wpt_reftest_setup) {
436 window.testRunner._wpt_reftest_setup = true;
437
438 window.addEventListener('load', function() {
439 if (window.assert_equals) // In case of a testharness test.
440 return;
441 window.testRunner.waitUntilDone();
442 const target = document.documentElement;
443 if (target != null &&
444 (target.classList.contains('reftest-wait') ||
445 target.classList.contains('test-wait'))) {
446 const observer = new MutationObserver(function(mutations) {
447 mutations.forEach(function(mutation) {
448 if (!target.classList.contains('reftest-wait') &&
449 !target.classList.contains('test-wait')) {
450 window.testRunner.notifyDone();
451 }
452 });
453 });
454 const config = {attributes: true};
455 observer.observe(target, config);
456
457 var event = new Event('TestRendered', {bubbles: true});
458 target.dispatchEvent(event);
459 } else {
460 document.fonts.ready.then(() => window.testRunner.notifyDone());
461 }
462 });
463 })"));
464 }
465 }
466
TestRunnerBindings(TestRunner * runner,WebFrameTestProxy * frame,SpellCheckClient * spell_check)467 TestRunnerBindings::TestRunnerBindings(TestRunner* runner,
468 WebFrameTestProxy* frame,
469 SpellCheckClient* spell_check)
470 : runner_(runner), frame_(frame), spell_check_(spell_check) {}
471
472 TestRunnerBindings::~TestRunnerBindings() = default;
473
GetObjectTemplateBuilder(v8::Isolate * isolate)474 gin::ObjectTemplateBuilder TestRunnerBindings::GetObjectTemplateBuilder(
475 v8::Isolate* isolate) {
476 return gin::Wrappable<TestRunnerBindings>::GetObjectTemplateBuilder(isolate)
477 .SetMethod("abortModal", &TestRunnerBindings::NotImplemented)
478 .SetMethod("addDisallowedURL", &TestRunnerBindings::NotImplemented)
479 .SetMethod("addOriginAccessAllowListEntry",
480 &TestRunnerBindings::AddOriginAccessAllowListEntry)
481 // Permits the adding of only one opaque overlay. May only be called from
482 // inside the main frame.
483 .SetMethod("addWebPageOverlay", &TestRunnerBindings::AddWebPageOverlay)
484 .SetMethod("capturePrintingPixelsThen",
485 &TestRunnerBindings::CapturePrintingPixelsThen)
486 // If the test will be closing its windows explicitly, and wants to look
487 // for leaks due to those windows closing incorrectly, it can specify this
488 // to avoid having them closed at the end of the test before the leak
489 // checker.
490 .SetMethod("checkForLeakedWindows",
491 &TestRunnerBindings::CheckForLeakedWindows)
492 // Clears WebSQL databases.
493 .SetMethod("clearAllDatabases", &TestRunnerBindings::ClearAllDatabases)
494 .SetMethod("clearBackForwardList", &TestRunnerBindings::NotImplemented)
495 // Clears persistent Trust Tokens state in the browser. See
496 // https://github.com/wicg/trust-token-api.
497 .SetMethod("clearTrustTokenState",
498 &TestRunnerBindings::ClearTrustTokenState)
499 .SetMethod("copyImageThen", &TestRunnerBindings::CopyImageThen)
500 // While holding a pointer lock, this breaks the lock. Or if
501 // setPointerLockWillRespondAsynchronously() was called, and a lock is
502 // pending it rejects the lock request.
503 .SetMethod("dropPointerLock", &TestRunnerBindings::DropPointerLock)
504 // When setPointerLockWillRespondAsynchronously() was called, this is used
505 // to respond to the async pointer request.
506 .SetMethod("allowPointerLock", &TestRunnerBindings::AllowPointerLock)
507 // Causes the next pointer lock request to fail in the renderer.
508 .SetMethod("setPointerLockWillFail",
509 &TestRunnerBindings::SetPointerLockWillFail)
510 // Causes the next pointer lock request to delay until the test calls
511 // either allowPointerLock() or dropPointerLock().
512 .SetMethod("setPointerLockWillRespondAsynchronously",
513 &TestRunnerBindings::SetPointerLockWillRespondAsynchronously)
514 .SetMethod("disableAutoResizeMode",
515 &TestRunnerBindings::DisableAutoResizeMode)
516 .SetMethod("disableMockScreenOrientation",
517 &TestRunnerBindings::DisableMockScreenOrientation)
518 // Sets up a mock DocumentSubresourceFilter to disallow subsequent
519 // subresource loads within the current document with the given path
520 // |suffixes|. The filter is created and injected even if |suffixes| is
521 // empty. If |suffixes| contains the empty string, all subresource loads
522 // will be disallowed. If |block_subresources| is false, matching
523 // resources will not be blocked but instead marked as matching a
524 // disallowed resource.
525 .SetMethod("setDisallowedSubresourcePathSuffixes",
526 &TestRunnerBindings::SetDisallowedSubresourcePathSuffixes)
527 // Causes the beforeinstallprompt event to be sent to the renderer.
528 .SetMethod("dispatchBeforeInstallPromptEvent",
529 &TestRunnerBindings::DispatchBeforeInstallPromptEvent)
530 .SetMethod("dumpAsMarkup", &TestRunnerBindings::DumpAsMarkup)
531 .SetMethod("dumpAsText", &TestRunnerBindings::DumpAsText)
532 .SetMethod("dumpAsTextWithPixelResults",
533 &TestRunnerBindings::DumpAsTextWithPixelResults)
534 .SetMethod("dumpAsLayout", &TestRunnerBindings::DumpAsLayout)
535 .SetMethod("dumpAsLayoutWithPixelResults",
536 &TestRunnerBindings::DumpAsLayoutWithPixelResults)
537 .SetMethod("dumpBackForwardList",
538 &TestRunnerBindings::DumpBackForwardList)
539 .SetMethod("dumpChildFrames", &TestRunnerBindings::DumpChildFrames)
540 .SetMethod("dumpCreateView", &TestRunnerBindings::DumpCreateView)
541 .SetMethod("dumpDatabaseCallbacks", &TestRunnerBindings::NotImplemented)
542 .SetMethod("dumpDragImage", &TestRunnerBindings::DumpDragImage)
543 .SetMethod("dumpEditingCallbacks",
544 &TestRunnerBindings::DumpEditingCallbacks)
545 .SetMethod("dumpFrameLoadCallbacks",
546 &TestRunnerBindings::DumpFrameLoadCallbacks)
547 .SetMethod("dumpIconChanges", &TestRunnerBindings::DumpIconChanges)
548 .SetMethod("dumpNavigationPolicy",
549 &TestRunnerBindings::DumpNavigationPolicy)
550 .SetMethod("dumpPermissionClientCallbacks",
551 &TestRunnerBindings::DumpPermissionClientCallbacks)
552 .SetMethod("dumpPingLoaderCallbacks",
553 &TestRunnerBindings::DumpPingLoaderCallbacks)
554 .SetMethod("dumpSelectionRect", &TestRunnerBindings::DumpSelectionRect)
555 .SetMethod("dumpTitleChanges", &TestRunnerBindings::DumpTitleChanges)
556 .SetMethod("dumpUserGestureInFrameLoadCallbacks",
557 &TestRunnerBindings::DumpUserGestureInFrameLoadCallbacks)
558 .SetMethod("enableAutoResizeMode",
559 &TestRunnerBindings::EnableAutoResizeMode)
560 .SetMethod("evaluateScriptInIsolatedWorld",
561 &TestRunnerBindings::EvaluateScriptInIsolatedWorld)
562 .SetMethod(
563 "evaluateScriptInIsolatedWorldAndReturnValue",
564 &TestRunnerBindings::EvaluateScriptInIsolatedWorldAndReturnValue)
565 // Executes an internal command (superset of document.execCommand()
566 // commands) on the frame's document.
567 .SetMethod("execCommand", &TestRunnerBindings::ExecCommand)
568 // Trigger an inspector issue for the frame.
569 .SetMethod("triggerTestInspectorIssue",
570 &TestRunnerBindings::TriggerTestInspectorIssue)
571 .SetMethod("findString", &TestRunnerBindings::FindString)
572 // Moves focus and active state to the secondary devtools window, which
573 // exists only in devtools JS tests.
574 .SetMethod("focusDevtoolsSecondaryWindow",
575 &TestRunnerBindings::FocusDevtoolsSecondaryWindow)
576 // Sets a flag causing the next call to WebGLRenderingContext::Create() to
577 // fail.
578 .SetMethod("forceNextDrawingBufferCreationToFail",
579 &TestRunnerBindings::ForceNextDrawingBufferCreationToFail)
580 // Sets a flag causing the next call to DrawingBuffer::Create() to fail.
581 .SetMethod("forceNextWebGLContextCreationToFail",
582 &TestRunnerBindings::ForceNextWebGLContextCreationToFail)
583
584 // The Bluetooth functions are specified at
585 // https://webbluetoothcg.github.io/web-bluetooth/tests/.
586 //
587 // Returns the events recorded since the last call to this function.
588 .SetMethod("getBluetoothManualChooserEvents",
589 &TestRunnerBindings::GetBluetoothManualChooserEvents)
590 .SetMethod("getManifestThen", &TestRunnerBindings::GetManifestThen)
591 // Returns the absolute path to a directory this test can write data in.
592 // This returns the path to a fresh empty directory every time this method
593 // is called. Additionally when this method is called any previously
594 // created directories will be deleted.
595 .SetMethod("getWritableDirectory",
596 &TestRunnerBindings::GetWritableDirectory)
597 .SetMethod("insertStyleSheet", &TestRunnerBindings::InsertStyleSheet)
598 // Checks if an internal editing command is currently available for the
599 // frame's document.
600 .SetMethod("isCommandEnabled", &TestRunnerBindings::IsCommandEnabled)
601 .SetMethod("keepWebHistory", &TestRunnerBindings::NotImplemented)
602 .SetMethod("updateAllLifecyclePhasesAndComposite",
603 &TestRunnerBindings::UpdateAllLifecyclePhasesAndComposite)
604 // Note, the reply callback is executed synchronously. Wrap in
605 // setTimeout() to run asynchronously.
606 .SetMethod("updateAllLifecyclePhasesAndCompositeThen",
607 &TestRunnerBindings::UpdateAllLifecyclePhasesAndCompositeThen)
608 .SetMethod("setAnimationRequiresRaster",
609 &TestRunnerBindings::SetAnimationRequiresRaster)
610 .SetMethod("logToStderr", &TestRunnerBindings::LogToStderr)
611 .SetMethod("notifyDone", &TestRunnerBindings::NotifyDone)
612 .SetMethod("overridePreference", &TestRunnerBindings::OverridePreference)
613 .SetMethod("pathToLocalResource",
614 &TestRunnerBindings::PathToLocalResource)
615 .SetProperty("platformName", &TestRunnerBindings::PlatformName)
616 .SetMethod("queueBackNavigation",
617 &TestRunnerBindings::QueueBackNavigation)
618 .SetMethod("queueForwardNavigation",
619 &TestRunnerBindings::QueueForwardNavigation)
620 .SetMethod("queueLoad", &TestRunnerBindings::QueueLoad)
621 .SetMethod("queueLoadingScript", &TestRunnerBindings::QueueLoadingScript)
622 .SetMethod("queueNonLoadingScript",
623 &TestRunnerBindings::QueueNonLoadingScript)
624 .SetMethod("queueReload", &TestRunnerBindings::QueueReload)
625 .SetMethod("removeSpellCheckResolvedCallback",
626 &TestRunnerBindings::RemoveSpellCheckResolvedCallback)
627 // Removes an overlay added by addWebPageOverlay(). May only be called
628 // from inside the main frame.
629 .SetMethod("removeWebPageOverlay",
630 &TestRunnerBindings::RemoveWebPageOverlay)
631 .SetMethod("resolveBeforeInstallPromptPromise",
632 &TestRunnerBindings::ResolveBeforeInstallPromptPromise)
633 // Immediately run all pending idle tasks, including all pending
634 // requestIdleCallback calls. Invoke the callback when all
635 // idle tasks are complete.
636 .SetMethod("runIdleTasks", &TestRunnerBindings::RunIdleTasks)
637 .SetMethod("selectionAsMarkup", &TestRunnerBindings::SelectionAsMarkup)
638
639 // The Bluetooth functions are specified at
640 // https://webbluetoothcg.github.io/web-bluetooth/tests/.
641
642 // Calls the BluetoothChooser::EventHandler with the arguments here. Valid
643 // event strings are:
644 // * "cancel" - simulates the user canceling the chooser.
645 // * "select" - simulates the user selecting a device whose device ID is
646 // in the 2nd parameter.
647 .SetMethod("sendBluetoothManualChooserEvent",
648 &TestRunnerBindings::SendBluetoothManualChooserEvent)
649 .SetMethod("setAcceptLanguages", &TestRunnerBindings::SetAcceptLanguages)
650 .SetMethod("setAllowFileAccessFromFileURLs",
651 &TestRunnerBindings::SetAllowFileAccessFromFileURLs)
652 .SetMethod("setAllowRunningOfInsecureContent",
653 &TestRunnerBindings::SetAllowRunningOfInsecureContent)
654 // Controls whether all cookies should be accepted or writing cookies in a
655 // third-party context is blocked:
656 // - Allows all cookies when |block| is false
657 // - Blocks only third-party cookies when |block| is true
658 .SetMethod("setBlockThirdPartyCookies",
659 &TestRunnerBindings::SetBlockThirdPartyCookies)
660 .SetMethod("setAudioData", &TestRunnerBindings::SetAudioData)
661 .SetMethod("setBackingScaleFactor",
662 &TestRunnerBindings::SetBackingScaleFactor)
663 // Set the bluetooth adapter while running a web test.
664 .SetMethod("setBluetoothFakeAdapter",
665 &TestRunnerBindings::SetBluetoothFakeAdapter)
666 // If |enable| is true, makes the Bluetooth chooser record its input and
667 // wait for instructions from the test program on how to proceed.
668 // Otherwise falls back to the browser's default chooser.
669 .SetMethod("setBluetoothManualChooser",
670 &TestRunnerBindings::SetBluetoothManualChooser)
671 .SetMethod("setCallCloseOnWebViews", &TestRunnerBindings::NotImplemented)
672 .SetMethod("setCanOpenWindows", &TestRunnerBindings::SetCanOpenWindows)
673 .SetMethod("setColorProfile", &TestRunnerBindings::SetColorProfile)
674 .SetMethod("setCustomPolicyDelegate",
675 &TestRunnerBindings::SetCustomPolicyDelegate)
676 .SetMethod("setCustomTextOutput",
677 &TestRunnerBindings::SetCustomTextOutput)
678 // Setting quota to kDefaultDatabaseQuota will reset it to the default
679 // value.
680 .SetMethod("setDatabaseQuota", &TestRunnerBindings::SetDatabaseQuota)
681 .SetMethod("setDomainRelaxationForbiddenForURLScheme",
682 &TestRunnerBindings::SetDomainRelaxationForbiddenForURLScheme)
683 .SetMethod("setDumpConsoleMessages",
684 &TestRunnerBindings::SetDumpConsoleMessages)
685 .SetMethod("setDumpJavaScriptDialogs",
686 &TestRunnerBindings::SetDumpJavaScriptDialogs)
687 .SetMethod("setEffectiveConnectionType",
688 &TestRunnerBindings::SetEffectiveConnectionType)
689 // Sets the path that should be returned when the test shows a file
690 // dialog.
691 .SetMethod("setFilePathForMockFileDialog",
692 &TestRunnerBindings::SetFilePathForMockFileDialog)
693 .SetMethod("setHighlightAds", &TestRunnerBindings::SetHighlightAds)
694 .SetMethod("setMockSpellCheckerEnabled",
695 &TestRunnerBindings::SetMockSpellCheckerEnabled)
696 .SetMethod("setIconDatabaseEnabled", &TestRunnerBindings::NotImplemented)
697 .SetMethod("setImagesAllowed", &TestRunnerBindings::SetImagesAllowed)
698 .SetMethod("setIsolatedWorldInfo",
699 &TestRunnerBindings::SetIsolatedWorldInfo)
700 .SetMethod("setJavaScriptCanAccessClipboard",
701 &TestRunnerBindings::SetJavaScriptCanAccessClipboard)
702 .SetMethod("setMainFrameIsFirstResponder",
703 &TestRunnerBindings::NotImplemented)
704 .SetMethod("setMockScreenOrientation",
705 &TestRunnerBindings::SetMockScreenOrientation)
706 // Calls setlocale(LC_ALL, ...) for a specified locale.
707 .SetMethod("setPOSIXLocale", &TestRunnerBindings::SetPOSIXLocale)
708 // Hide or show the main window. Watch for the |document.visibilityState|
709 // to change in order to wait for the side effects of calling this.
710 .SetMethod("setMainWindowHidden",
711 &TestRunnerBindings::SetMainWindowHidden)
712 // Sets the permission's |name| to |value| for a given {origin, embedder}
713 // tuple. Sends a message to the WebTestPermissionManager in order for it
714 // to update its database.
715 .SetMethod("setPermission", &TestRunnerBindings::SetPermission)
716 .SetMethod("setPluginsAllowed", &TestRunnerBindings::SetPluginsAllowed)
717 .SetMethod("setPluginsEnabled", &TestRunnerBindings::SetPluginsEnabled)
718 .SetMethod("setPopupBlockingEnabled",
719 &TestRunnerBindings::SetPopupBlockingEnabled)
720 .SetMethod("setPrinting", &TestRunnerBindings::SetPrinting)
721 .SetMethod("setPrintingForFrame",
722 &TestRunnerBindings::SetPrintingForFrame)
723 .SetMethod("setScriptsAllowed", &TestRunnerBindings::SetScriptsAllowed)
724 .SetMethod("setScrollbarPolicy", &TestRunnerBindings::NotImplemented)
725 .SetMethod("setShouldGeneratePixelResults",
726 &TestRunnerBindings::SetShouldGeneratePixelResults)
727 .SetMethod(
728 "setShouldStayOnPageAfterHandlingBeforeUnload",
729 &TestRunnerBindings::SetShouldStayOnPageAfterHandlingBeforeUnload)
730 .SetMethod("setSpellCheckResolvedCallback",
731 &TestRunnerBindings::SetSpellCheckResolvedCallback)
732 .SetMethod("setStorageAllowed", &TestRunnerBindings::SetStorageAllowed)
733 // Method that controls whether pressing Tab key cycles through page
734 // elements or inserts a '\t' char in text area
735 .SetMethod("setTabKeyCyclesThroughElements",
736 &TestRunnerBindings::SetTabKeyCyclesThroughElements)
737 // Changes the direction of text for the frame's focused element.
738 .SetMethod("setTextDirection", &TestRunnerBindings::SetTextDirection)
739 .SetMethod("setTextSubpixelPositioning",
740 &TestRunnerBindings::SetTextSubpixelPositioning)
741 // Sets the network service-global Trust Tokens key commitments.
742 // Takes a |raw_commitments| string that should be JSON-encoded according
743 // to the format expected by NetworkService::SetTrustTokenKeyCommitments.
744 .SetMethod("setTrustTokenKeyCommitments",
745 &TestRunnerBindings::SetTrustTokenKeyCommitments)
746 .SetMethod("setUseDashboardCompatibilityMode",
747 &TestRunnerBindings::NotImplemented)
748 .SetMethod("setWillSendRequestClearHeader",
749 &TestRunnerBindings::SetWillSendRequestClearHeader)
750 .SetMethod("setWillSendRequestClearReferrer",
751 &TestRunnerBindings::SetWillSendRequestClearReferrer)
752 .SetMethod("setWindowFocus",
753 &TestRunnerBindings::SimulateBrowserWindowFocus)
754 // Simulates a click on a Web Notification.
755 .SetMethod("simulateWebNotificationClick",
756 &TestRunnerBindings::SimulateWebNotificationClick)
757 // Simulates closing a Web Notification.
758 .SetMethod("simulateWebNotificationClose",
759 &TestRunnerBindings::SimulateWebNotificationClose)
760 // Simulates a user deleting a content index entry.
761 .SetMethod("simulateWebContentIndexDelete",
762 &TestRunnerBindings::SimulateWebContentIndexDelete)
763 .SetMethod("textZoomIn", &TestRunnerBindings::TextZoomIn)
764 .SetMethod("textZoomOut", &TestRunnerBindings::TextZoomOut)
765 .SetMethod("zoomPageIn", &TestRunnerBindings::ZoomPageIn)
766 .SetMethod("zoomPageOut", &TestRunnerBindings::ZoomPageOut)
767 .SetMethod("setPageZoomFactor", &TestRunnerBindings::SetPageZoomFactor)
768 .SetProperty("tooltipText", &TestRunnerBindings::TooltipText)
769 .SetMethod("useUnfortunateSynchronousResizeMode",
770 &TestRunnerBindings::UseUnfortunateSynchronousResizeMode)
771 .SetMethod("waitForPolicyDelegate",
772 &TestRunnerBindings::WaitForPolicyDelegate)
773 .SetMethod("waitUntilDone", &TestRunnerBindings::WaitUntilDone)
774 .SetMethod("waitUntilExternalURLLoad",
775 &TestRunnerBindings::WaitUntilExternalURLLoad)
776
777 // webHistoryItemCount is used by tests in web_tests\http\tests\history
778 .SetProperty("webHistoryItemCount",
779 &TestRunnerBindings::WebHistoryItemCount)
780 .SetMethod("windowCount", &TestRunnerBindings::WindowCount);
781 }
782
WrapV8Callback(v8::Local<v8::Function> v8_callback,std::vector<v8::Local<v8::Value>> args_to_bind)783 BoundV8Callback TestRunnerBindings::WrapV8Callback(
784 v8::Local<v8::Function> v8_callback,
785 std::vector<v8::Local<v8::Value>> args_to_bind) {
786 auto persistent_callback = v8::UniquePersistent<v8::Function>(
787 blink::MainThreadIsolate(), std::move(v8_callback));
788
789 std::vector<v8::UniquePersistent<v8::Value>> persistent_args;
790 persistent_args.reserve(args_to_bind.size());
791 for (auto& arg : args_to_bind)
792 persistent_args.emplace_back(blink::MainThreadIsolate(), std::move(arg));
793
794 return base::BindOnce(
795 &TestRunnerBindings::InvokeV8Callback, weak_ptr_factory_.GetWeakPtr(),
796 std::move(persistent_callback), std::move(persistent_args));
797 }
798
WrapV8Closure(v8::Local<v8::Function> v8_callback,std::vector<v8::Local<v8::Value>> args_to_bind)799 base::OnceClosure TestRunnerBindings::WrapV8Closure(
800 v8::Local<v8::Function> v8_callback,
801 std::vector<v8::Local<v8::Value>> args_to_bind) {
802 return base::BindOnce(
803 WrapV8Callback(std::move(v8_callback), std::move(args_to_bind)),
804 NoV8Args());
805 }
806
PostV8Callback(v8::Local<v8::Function> v8_callback,std::vector<v8::Local<v8::Value>> args)807 void TestRunnerBindings::PostV8Callback(
808 v8::Local<v8::Function> v8_callback,
809 std::vector<v8::Local<v8::Value>> args) {
810 const auto& task_runner =
811 GetWebFrame()->GetTaskRunner(blink::TaskType::kInternalTest);
812 task_runner->PostTask(FROM_HERE,
813 WrapV8Closure(std::move(v8_callback), std::move(args)));
814 }
815
InvokeV8Callback(v8::UniquePersistent<v8::Function> callback,std::vector<v8::UniquePersistent<v8::Value>> bound_args,const std::vector<v8::Local<v8::Value>> & runtime_args)816 void TestRunnerBindings::InvokeV8Callback(
817 v8::UniquePersistent<v8::Function> callback,
818 std::vector<v8::UniquePersistent<v8::Value>> bound_args,
819 const std::vector<v8::Local<v8::Value>>& runtime_args) {
820 v8::Isolate* isolate = blink::MainThreadIsolate();
821 v8::HandleScope handle_scope(isolate);
822
823 v8::Local<v8::Context> context = GetWebFrame()->MainWorldScriptContext();
824 CHECK(!context.IsEmpty());
825 v8::Context::Scope context_scope(context);
826
827 std::vector<v8::Local<v8::Value>> local_args;
828 for (auto& arg : bound_args)
829 local_args.push_back(v8::Local<v8::Value>::New(isolate, std::move(arg)));
830 for (const auto& arg : runtime_args)
831 local_args.push_back(arg);
832
833 GetWebFrame()->CallFunctionEvenIfScriptDisabled(
834 v8::Local<v8::Function>::New(isolate, std::move(callback)),
835 context->Global(), local_args.size(), local_args.data());
836 }
837
LogToStderr(const std::string & output)838 void TestRunnerBindings::LogToStderr(const std::string& output) {
839 if (invalid_)
840 return;
841 TRACE_EVENT1("shell", "TestRunner::LogToStderr", "output", output);
842 LOG(ERROR) << output;
843 }
844
NotifyDone()845 void TestRunnerBindings::NotifyDone() {
846 if (invalid_)
847 return;
848 runner_->NotifyDone();
849 }
850
WaitUntilDone()851 void TestRunnerBindings::WaitUntilDone() {
852 if (invalid_)
853 return;
854 runner_->WaitUntilDone();
855 }
856
QueueBackNavigation(int how_far_back)857 void TestRunnerBindings::QueueBackNavigation(int how_far_back) {
858 if (invalid_)
859 return;
860 runner_->QueueBackNavigation(how_far_back);
861 }
862
QueueForwardNavigation(int how_far_forward)863 void TestRunnerBindings::QueueForwardNavigation(int how_far_forward) {
864 if (invalid_)
865 return;
866 runner_->QueueForwardNavigation(how_far_forward);
867 }
868
QueueReload()869 void TestRunnerBindings::QueueReload() {
870 if (invalid_)
871 return;
872 runner_->QueueReload();
873 }
874
QueueLoadingScript(const std::string & script)875 void TestRunnerBindings::QueueLoadingScript(const std::string& script) {
876 if (invalid_)
877 return;
878 runner_->QueueLoadingScript(script);
879 }
880
QueueNonLoadingScript(const std::string & script)881 void TestRunnerBindings::QueueNonLoadingScript(const std::string& script) {
882 if (invalid_)
883 return;
884 runner_->QueueNonLoadingScript(script);
885 }
886
QueueLoad(gin::Arguments * args)887 void TestRunnerBindings::QueueLoad(gin::Arguments* args) {
888 if (invalid_)
889 return;
890 std::string url;
891 std::string target;
892 args->GetNext(&url);
893 args->GetNext(&target);
894 runner_->QueueLoad(GURL(GetWebFrame()->GetDocument().Url()), url, target);
895 }
896
SetCustomPolicyDelegate(gin::Arguments * args)897 void TestRunnerBindings::SetCustomPolicyDelegate(gin::Arguments* args) {
898 if (invalid_)
899 return;
900 runner_->SetCustomPolicyDelegate(args);
901 }
902
WaitForPolicyDelegate()903 void TestRunnerBindings::WaitForPolicyDelegate() {
904 if (invalid_)
905 return;
906 runner_->WaitForPolicyDelegate();
907 }
908
WindowCount()909 int TestRunnerBindings::WindowCount() {
910 if (invalid_)
911 return 0;
912 return runner_->InProcessWindowCount();
913 }
914
SetTabKeyCyclesThroughElements(bool tab_key_cycles_through_elements)915 void TestRunnerBindings::SetTabKeyCyclesThroughElements(
916 bool tab_key_cycles_through_elements) {
917 if (invalid_)
918 return;
919 blink::WebView* web_view = GetWebFrame()->View();
920 web_view->SetTabKeyCyclesThroughElements(tab_key_cycles_through_elements);
921 }
922
ExecCommand(gin::Arguments * args)923 void TestRunnerBindings::ExecCommand(gin::Arguments* args) {
924 if (invalid_)
925 return;
926
927 std::string command;
928 args->GetNext(&command);
929
930 std::string value;
931 if (args->Length() >= 3) {
932 // Ignore the second parameter (which is userInterface)
933 // since this command emulates a manual action.
934 args->Skip();
935 args->GetNext(&value);
936 }
937
938 // Note: webkit's version does not return the boolean, so neither do we.
939 GetWebFrame()->ExecuteCommand(blink::WebString::FromUTF8(command),
940 blink::WebString::FromUTF8(value));
941 }
942
TriggerTestInspectorIssue(gin::Arguments * args)943 void TestRunnerBindings::TriggerTestInspectorIssue(gin::Arguments* args) {
944 if (invalid_)
945 return;
946 GetWebFrame()->AddInspectorIssue(
947 blink::mojom::InspectorIssueCode::kSameSiteCookieIssue);
948 }
949
IsCommandEnabled(const std::string & command)950 bool TestRunnerBindings::IsCommandEnabled(const std::string& command) {
951 if (invalid_)
952 return false;
953 return GetWebFrame()->IsCommandEnabled(blink::WebString::FromUTF8(command));
954 }
955
SetDomainRelaxationForbiddenForURLScheme(bool forbidden,const std::string & scheme)956 void TestRunnerBindings::SetDomainRelaxationForbiddenForURLScheme(
957 bool forbidden,
958 const std::string& scheme) {
959 if (invalid_)
960 return;
961 blink::SetDomainRelaxationForbiddenForTest(
962 forbidden, blink::WebString::FromUTF8(scheme));
963 }
964
SetDumpConsoleMessages(bool enabled)965 void TestRunnerBindings::SetDumpConsoleMessages(bool enabled) {
966 if (invalid_)
967 return;
968 runner_->SetDumpConsoleMessages(enabled);
969 }
970
SetDumpJavaScriptDialogs(bool enabled)971 void TestRunnerBindings::SetDumpJavaScriptDialogs(bool enabled) {
972 if (invalid_)
973 return;
974 runner_->SetDumpJavaScriptDialogs(enabled);
975 }
976
SetEffectiveConnectionType(const std::string & connection_type)977 void TestRunnerBindings::SetEffectiveConnectionType(
978 const std::string& connection_type) {
979 if (invalid_)
980 return;
981
982 blink::WebEffectiveConnectionType web_type =
983 blink::WebEffectiveConnectionType::kTypeUnknown;
984 if (connection_type == "TypeUnknown")
985 web_type = blink::WebEffectiveConnectionType::kTypeUnknown;
986 else if (connection_type == "TypeOffline")
987 web_type = blink::WebEffectiveConnectionType::kTypeOffline;
988 else if (connection_type == "TypeSlow2G")
989 web_type = blink::WebEffectiveConnectionType::kTypeSlow2G;
990 else if (connection_type == "Type2G")
991 web_type = blink::WebEffectiveConnectionType::kType2G;
992 else if (connection_type == "Type3G")
993 web_type = blink::WebEffectiveConnectionType::kType3G;
994 else if (connection_type == "Type4G")
995 web_type = blink::WebEffectiveConnectionType::kType4G;
996 else
997 NOTREACHED();
998
999 if (runner_)
1000 runner_->SetEffectiveConnectionType(web_type);
1001 }
1002
GetWritableDirectory()1003 base::FilePath::StringType TestRunnerBindings::GetWritableDirectory() {
1004 if (invalid_)
1005 return {};
1006 base::FilePath result;
1007 runner_->GetWebTestControlHostRemote()->GetWritableDirectory(&result);
1008 return result.value();
1009 }
1010
SetFilePathForMockFileDialog(const base::FilePath::StringType & path)1011 void TestRunnerBindings::SetFilePathForMockFileDialog(
1012 const base::FilePath::StringType& path) {
1013 if (invalid_)
1014 return;
1015 runner_->GetWebTestControlHostRemote()->SetFilePathForMockFileDialog(
1016 base::FilePath(path));
1017 }
1018
SetMockSpellCheckerEnabled(bool enabled)1019 void TestRunnerBindings::SetMockSpellCheckerEnabled(bool enabled) {
1020 if (invalid_)
1021 return;
1022 spell_check_->SetEnabled(enabled);
1023 }
1024
SetSpellCheckResolvedCallback(v8::Local<v8::Function> callback)1025 void TestRunnerBindings::SetSpellCheckResolvedCallback(
1026 v8::Local<v8::Function> callback) {
1027 if (invalid_)
1028 return;
1029 spell_check_->SetSpellCheckResolvedCallback(callback);
1030 }
1031
RemoveSpellCheckResolvedCallback()1032 void TestRunnerBindings::RemoveSpellCheckResolvedCallback() {
1033 if (invalid_)
1034 return;
1035 spell_check_->RemoveSpellCheckResolvedCallback();
1036 }
1037
1038 v8::Local<v8::Value>
EvaluateScriptInIsolatedWorldAndReturnValue(int world_id,const std::string & script)1039 TestRunnerBindings::EvaluateScriptInIsolatedWorldAndReturnValue(
1040 int world_id,
1041 const std::string& script) {
1042 if (invalid_ || world_id <= 0 || world_id >= (1 << 29))
1043 return {};
1044
1045 blink::WebScriptSource source = blink::WebString::FromUTF8(script);
1046 return GetWebFrame()->ExecuteScriptInIsolatedWorldAndReturnValue(world_id,
1047 source);
1048 }
1049
EvaluateScriptInIsolatedWorld(int world_id,const std::string & script)1050 void TestRunnerBindings::EvaluateScriptInIsolatedWorld(
1051 int world_id,
1052 const std::string& script) {
1053 if (invalid_ || world_id <= 0 || world_id >= (1 << 29))
1054 return;
1055
1056 blink::WebScriptSource source = blink::WebString::FromUTF8(script);
1057 GetWebFrame()->ExecuteScriptInIsolatedWorld(world_id, source);
1058 }
1059
SetIsolatedWorldInfo(int world_id,v8::Local<v8::Value> security_origin,v8::Local<v8::Value> content_security_policy)1060 void TestRunnerBindings::SetIsolatedWorldInfo(
1061 int world_id,
1062 v8::Local<v8::Value> security_origin,
1063 v8::Local<v8::Value> content_security_policy) {
1064 if (invalid_)
1065 return;
1066
1067 if (world_id <= content::ISOLATED_WORLD_ID_GLOBAL ||
1068 world_id >= blink::IsolatedWorldId::kEmbedderWorldIdLimit) {
1069 return;
1070 }
1071
1072 if (!security_origin->IsString() && !security_origin->IsNull())
1073 return;
1074
1075 if (!content_security_policy->IsString() &&
1076 !content_security_policy->IsNull()) {
1077 return;
1078 }
1079
1080 // If |content_security_policy| is specified, |security_origin| must also be
1081 // specified.
1082 if (content_security_policy->IsString() && security_origin->IsNull())
1083 return;
1084
1085 blink::WebIsolatedWorldInfo info;
1086 if (security_origin->IsString()) {
1087 info.security_origin = blink::WebSecurityOrigin::CreateFromString(
1088 web_test_string_util::V8StringToWebString(
1089 blink::MainThreadIsolate(), security_origin.As<v8::String>()));
1090 }
1091
1092 if (content_security_policy->IsString()) {
1093 info.content_security_policy = web_test_string_util::V8StringToWebString(
1094 blink::MainThreadIsolate(), content_security_policy.As<v8::String>());
1095 }
1096
1097 // Clear the document->isolated world CSP mapping.
1098 GetWebFrame()->ClearIsolatedWorldCSPForTesting(world_id);
1099
1100 blink::SetIsolatedWorldInfo(world_id, info);
1101 }
1102
AddOriginAccessAllowListEntry(const std::string & source_origin,const std::string & destination_protocol,const std::string & destination_host,bool allow_destination_subdomains)1103 void TestRunnerBindings::AddOriginAccessAllowListEntry(
1104 const std::string& source_origin,
1105 const std::string& destination_protocol,
1106 const std::string& destination_host,
1107 bool allow_destination_subdomains) {
1108 if (invalid_)
1109 return;
1110
1111 // Non-standard schemes should be added to the scheme registeries to use
1112 // for the origin access whitelisting.
1113 GURL url(source_origin);
1114 DCHECK(url.is_valid());
1115 DCHECK(url.has_scheme());
1116 DCHECK(url.has_host());
1117
1118 runner_->AddOriginAccessAllowListEntry(source_origin, destination_protocol,
1119 destination_host,
1120 allow_destination_subdomains);
1121 }
1122
InsertStyleSheet(const std::string & source_code)1123 void TestRunnerBindings::InsertStyleSheet(const std::string& source_code) {
1124 if (invalid_)
1125 return;
1126 GetWebFrame()->GetDocument().InsertStyleSheet(
1127 blink::WebString::FromUTF8(source_code));
1128 }
1129
FindString(const std::string & search_text,const std::vector<std::string> & options_array)1130 bool TestRunnerBindings::FindString(
1131 const std::string& search_text,
1132 const std::vector<std::string>& options_array) {
1133 if (invalid_)
1134 return false;
1135
1136 bool match_case = true;
1137 bool forward = true;
1138 bool new_session = false;
1139 bool wrap_around = false;
1140 bool async = false;
1141 for (const auto& option : options_array) {
1142 if (option == "CaseInsensitive")
1143 match_case = false;
1144 else if (option == "Backwards")
1145 forward = false;
1146 else if (option == "StartInSelection")
1147 new_session = true;
1148 else if (option == "WrapAround")
1149 wrap_around = true;
1150 else if (option == "Async")
1151 async = true;
1152 }
1153
1154 const bool find_result = GetWebFrame()->FindForTesting(
1155 0, blink::WebString::FromUTF8(search_text), match_case, forward,
1156 new_session, false /* force */, wrap_around, async);
1157 return find_result;
1158 }
1159
SelectionAsMarkup()1160 std::string TestRunnerBindings::SelectionAsMarkup() {
1161 if (invalid_)
1162 return {};
1163 return GetWebFrame()->SelectionAsMarkup().Utf8();
1164 }
1165
SetTextSubpixelPositioning(bool value)1166 void TestRunnerBindings::SetTextSubpixelPositioning(bool value) {
1167 if (invalid_)
1168 return;
1169 runner_->SetTextSubpixelPositioning(value);
1170 }
1171
SetTrustTokenKeyCommitments(const std::string & raw_commitments,v8::Local<v8::Function> v8_callback)1172 void TestRunnerBindings::SetTrustTokenKeyCommitments(
1173 const std::string& raw_commitments,
1174 v8::Local<v8::Function> v8_callback) {
1175 if (invalid_)
1176 return;
1177
1178 runner_->GetWebTestControlHostRemote()->SetTrustTokenKeyCommitments(
1179 raw_commitments, WrapV8Closure(std::move(v8_callback)));
1180 }
1181
SetMainWindowHidden(bool hidden)1182 void TestRunnerBindings::SetMainWindowHidden(bool hidden) {
1183 if (invalid_)
1184 return;
1185 runner_->GetWebTestControlHostRemote()->SetMainWindowHidden(hidden);
1186 }
1187
SetTextDirection(const std::string & direction_name)1188 void TestRunnerBindings::SetTextDirection(const std::string& direction_name) {
1189 if (invalid_)
1190 return;
1191
1192 // Map a direction name to a base::i18n::TextDirection value.
1193 base::i18n::TextDirection direction;
1194 if (direction_name == "auto")
1195 direction = base::i18n::TextDirection::UNKNOWN_DIRECTION;
1196 else if (direction_name == "rtl")
1197 direction = base::i18n::TextDirection::RIGHT_TO_LEFT;
1198 else if (direction_name == "ltr")
1199 direction = base::i18n::TextDirection::LEFT_TO_RIGHT;
1200 else
1201 return;
1202
1203 GetWebFrame()->SetTextDirectionForTesting(direction);
1204 }
1205
UseUnfortunateSynchronousResizeMode()1206 void TestRunnerBindings::UseUnfortunateSynchronousResizeMode() {
1207 if (invalid_)
1208 return;
1209 runner_->UseUnfortunateSynchronousResizeMode();
1210 }
1211
EnableAutoResizeMode(int min_width,int min_height,int max_width,int max_height)1212 void TestRunnerBindings::EnableAutoResizeMode(int min_width,
1213 int min_height,
1214 int max_width,
1215 int max_height) {
1216 if (invalid_)
1217 return;
1218 // Early out instead of CHECK() to avoid poking the fuzzer bear.
1219 if (!frame_->IsMainFrame())
1220 return;
1221 if (max_width <= 0 || max_height <= 0)
1222 return;
1223
1224 blink::WebView* web_view = GetWebFrame()->View();
1225
1226 gfx::Size min_size(min_width, min_height);
1227 gfx::Size max_size(max_width, max_height);
1228 web_view->EnableAutoResizeForTesting(min_size, max_size);
1229 }
1230
DisableAutoResizeMode(int new_width,int new_height)1231 void TestRunnerBindings::DisableAutoResizeMode(int new_width, int new_height) {
1232 if (invalid_)
1233 return;
1234 // Early out instead of CHECK() to avoid poking the fuzzer bear.
1235 if (!frame_->IsMainFrame())
1236 return;
1237 if (new_width <= 0 || new_height <= 0)
1238 return;
1239
1240 RenderWidget* widget = frame_->GetLocalRootRenderWidget();
1241
1242 gfx::Size new_size(new_width, new_height);
1243 blink::WebView* web_view = GetWebFrame()->View();
1244 web_view->DisableAutoResizeForTesting(new_size);
1245
1246 gfx::Rect window_rect(widget->GetWebWidget()->WindowRect().origin(),
1247 new_size);
1248 web_view->SetWindowRectSynchronouslyForTesting(window_rect);
1249 }
1250
SetMockScreenOrientation(const std::string & orientation)1251 void TestRunnerBindings::SetMockScreenOrientation(
1252 const std::string& orientation) {
1253 if (invalid_)
1254 return;
1255 runner_->SetMockScreenOrientation(frame_->GetWebViewTestProxy(), orientation);
1256 }
1257
DisableMockScreenOrientation()1258 void TestRunnerBindings::DisableMockScreenOrientation() {
1259 if (invalid_)
1260 return;
1261 runner_->DisableMockScreenOrientation(frame_->GetWebViewTestProxy());
1262 }
1263
SetDisallowedSubresourcePathSuffixes(std::vector<std::string> suffixes,bool block_subresources)1264 void TestRunnerBindings::SetDisallowedSubresourcePathSuffixes(
1265 std::vector<std::string> suffixes,
1266 bool block_subresources) {
1267 if (invalid_)
1268 return;
1269 GetWebFrame()->GetDocumentLoader()->SetSubresourceFilter(
1270 new FakeSubresourceFilter(std::move(suffixes), block_subresources));
1271 }
1272
SetPopupBlockingEnabled(bool block_popups)1273 void TestRunnerBindings::SetPopupBlockingEnabled(bool block_popups) {
1274 if (invalid_)
1275 return;
1276 runner_->GetWebTestControlHostRemote()->SetPopupBlockingEnabled(block_popups);
1277 }
1278
SetJavaScriptCanAccessClipboard(bool can_access)1279 void TestRunnerBindings::SetJavaScriptCanAccessClipboard(bool can_access) {
1280 if (invalid_)
1281 return;
1282
1283 // WebPreferences aren't propagated between frame tree fragments, so only
1284 // allow this in the main frame.
1285 // Early out instead of CHECK() to avoid poking the fuzzer bear.
1286 if (!frame_->IsMainFrame())
1287 return;
1288
1289 prefs_.java_script_can_access_clipboard = can_access;
1290 runner_->OnTestPreferencesChanged(prefs_, frame_);
1291 }
1292
SetAllowFileAccessFromFileURLs(bool allow)1293 void TestRunnerBindings::SetAllowFileAccessFromFileURLs(bool allow) {
1294 if (invalid_)
1295 return;
1296
1297 // WebPreferences aren't propagated between frame tree fragments, so only
1298 // allow this in the main frame.
1299 // Early out instead of CHECK() to avoid poking the fuzzer bear.
1300 if (!frame_->IsMainFrame())
1301 return;
1302
1303 prefs_.allow_file_access_from_file_urls = allow;
1304 runner_->OnTestPreferencesChanged(prefs_, frame_);
1305 }
1306
OverridePreference(gin::Arguments * args)1307 void TestRunnerBindings::OverridePreference(gin::Arguments* args) {
1308 if (invalid_)
1309 return;
1310
1311 if (args->Length() != 2) {
1312 args->ThrowTypeError("overridePreference expects 2 arguments");
1313 return;
1314 }
1315
1316 std::string key;
1317 if (!args->GetNext(&key)) {
1318 args->ThrowError();
1319 return;
1320 }
1321
1322 if (key == "WebKitDefaultFontSize") {
1323 ConvertAndSet(args, &prefs_.default_font_size);
1324 } else if (key == "WebKitMinimumFontSize") {
1325 ConvertAndSet(args, &prefs_.minimum_font_size);
1326 } else if (key == "WebKitDefaultTextEncodingName") {
1327 ConvertAndSet(args, &prefs_.default_text_encoding_name);
1328 } else if (key == "WebKitJavaScriptEnabled") {
1329 ConvertAndSet(args, &prefs_.java_script_enabled);
1330 } else if (key == "WebKitSupportsMultipleWindows") {
1331 ConvertAndSet(args, &prefs_.supports_multiple_windows);
1332 } else if (key == "WebKitDisplayImagesKey") {
1333 ConvertAndSet(args, &prefs_.loads_images_automatically);
1334 } else if (key == "WebKitPluginsEnabled") {
1335 ConvertAndSet(args, &prefs_.plugins_enabled);
1336 } else if (key == "WebKitTabToLinksPreferenceKey") {
1337 ConvertAndSet(args, &prefs_.tabs_to_links);
1338 } else if (key == "WebKitCSSGridLayoutEnabled") {
1339 ConvertAndSet(args, &prefs_.experimental_css_grid_layout_enabled);
1340 } else if (key == "WebKitHyperlinkAuditingEnabled") {
1341 ConvertAndSet(args, &prefs_.hyperlink_auditing_enabled);
1342 } else if (key == "WebKitEnableCaretBrowsing") {
1343 ConvertAndSet(args, &prefs_.caret_browsing_enabled);
1344 } else if (key == "WebKitAllowRunningInsecureContent") {
1345 ConvertAndSet(args, &prefs_.allow_running_of_insecure_content);
1346 } else if (key == "WebKitDisableReadingFromCanvas") {
1347 ConvertAndSet(args, &prefs_.disable_reading_from_canvas);
1348 } else if (key == "WebKitStrictMixedContentChecking") {
1349 ConvertAndSet(args, &prefs_.strict_mixed_content_checking);
1350 } else if (key == "WebKitStrictPowerfulFeatureRestrictions") {
1351 ConvertAndSet(args, &prefs_.strict_powerful_feature_restrictions);
1352 } else if (key == "WebKitShouldRespectImageOrientation") {
1353 ConvertAndSet(args, &prefs_.should_respect_image_orientation);
1354 } else if (key == "WebKitWebSecurityEnabled") {
1355 ConvertAndSet(args, &prefs_.web_security_enabled);
1356 } else if (key == "WebKitSpatialNavigationEnabled") {
1357 ConvertAndSet(args, &prefs_.spatial_navigation_enabled);
1358 } else {
1359 args->ThrowTypeError("Invalid name for preference: " + key);
1360 }
1361
1362 runner_->OnTestPreferencesChanged(prefs_, frame_);
1363 }
1364
SetAcceptLanguages(const std::string & accept_languages)1365 void TestRunnerBindings::SetAcceptLanguages(
1366 const std::string& accept_languages) {
1367 if (invalid_)
1368 return;
1369 runner_->SetAcceptLanguages(accept_languages);
1370 }
1371
SetPluginsEnabled(bool enabled)1372 void TestRunnerBindings::SetPluginsEnabled(bool enabled) {
1373 if (invalid_)
1374 return;
1375
1376 // WebPreferences aren't propagated between frame tree fragments, so only
1377 // allow this in the main frame.
1378 // Early out instead of CHECK() to avoid poking the fuzzer bear.
1379 if (!frame_->IsMainFrame())
1380 return;
1381
1382 prefs_.plugins_enabled = enabled;
1383 runner_->OnTestPreferencesChanged(prefs_, frame_);
1384 }
1385
DumpEditingCallbacks()1386 void TestRunnerBindings::DumpEditingCallbacks() {
1387 if (invalid_)
1388 return;
1389 runner_->DumpEditingCallbacks();
1390 }
1391
DumpAsMarkup()1392 void TestRunnerBindings::DumpAsMarkup() {
1393 if (invalid_)
1394 return;
1395 runner_->DumpAsMarkup();
1396 }
1397
DumpAsText()1398 void TestRunnerBindings::DumpAsText() {
1399 if (invalid_)
1400 return;
1401 runner_->DumpAsText();
1402 }
1403
DumpAsTextWithPixelResults()1404 void TestRunnerBindings::DumpAsTextWithPixelResults() {
1405 if (invalid_)
1406 return;
1407 runner_->DumpAsTextWithPixelResults();
1408 }
1409
DumpAsLayout()1410 void TestRunnerBindings::DumpAsLayout() {
1411 if (invalid_)
1412 return;
1413 runner_->DumpAsLayout();
1414 }
1415
DumpAsLayoutWithPixelResults()1416 void TestRunnerBindings::DumpAsLayoutWithPixelResults() {
1417 if (invalid_)
1418 return;
1419 runner_->DumpAsLayoutWithPixelResults();
1420 }
1421
DumpChildFrames()1422 void TestRunnerBindings::DumpChildFrames() {
1423 if (invalid_)
1424 return;
1425 runner_->DumpChildFrames();
1426 }
1427
DumpIconChanges()1428 void TestRunnerBindings::DumpIconChanges() {
1429 if (invalid_)
1430 return;
1431 runner_->DumpIconChanges();
1432 }
1433
SetAudioData(const gin::ArrayBufferView & view)1434 void TestRunnerBindings::SetAudioData(const gin::ArrayBufferView& view) {
1435 if (invalid_)
1436 return;
1437 runner_->SetAudioData(view);
1438 }
1439
DumpFrameLoadCallbacks()1440 void TestRunnerBindings::DumpFrameLoadCallbacks() {
1441 if (invalid_)
1442 return;
1443 runner_->DumpFrameLoadCallbacks();
1444 }
1445
DumpPingLoaderCallbacks()1446 void TestRunnerBindings::DumpPingLoaderCallbacks() {
1447 if (invalid_)
1448 return;
1449 runner_->DumpPingLoaderCallbacks();
1450 }
1451
DumpUserGestureInFrameLoadCallbacks()1452 void TestRunnerBindings::DumpUserGestureInFrameLoadCallbacks() {
1453 if (invalid_)
1454 return;
1455 runner_->DumpUserGestureInFrameLoadCallbacks();
1456 }
1457
DumpTitleChanges()1458 void TestRunnerBindings::DumpTitleChanges() {
1459 if (invalid_)
1460 return;
1461 runner_->DumpTitleChanges();
1462 }
1463
DumpCreateView()1464 void TestRunnerBindings::DumpCreateView() {
1465 if (invalid_)
1466 return;
1467 runner_->DumpCreateView();
1468 }
1469
SetCanOpenWindows()1470 void TestRunnerBindings::SetCanOpenWindows() {
1471 if (invalid_)
1472 return;
1473 runner_->SetCanOpenWindows();
1474 }
1475
SetImagesAllowed(bool allowed)1476 void TestRunnerBindings::SetImagesAllowed(bool allowed) {
1477 if (invalid_)
1478 return;
1479 runner_->SetImagesAllowed(allowed);
1480 }
1481
SetScriptsAllowed(bool allowed)1482 void TestRunnerBindings::SetScriptsAllowed(bool allowed) {
1483 if (invalid_)
1484 return;
1485 runner_->SetScriptsAllowed(allowed);
1486 }
1487
SetStorageAllowed(bool allowed)1488 void TestRunnerBindings::SetStorageAllowed(bool allowed) {
1489 if (invalid_)
1490 return;
1491 runner_->SetStorageAllowed(allowed);
1492 }
1493
SetPluginsAllowed(bool allowed)1494 void TestRunnerBindings::SetPluginsAllowed(bool allowed) {
1495 if (invalid_)
1496 return;
1497 // This only modifies the local process, and is used to verify behaviour based
1498 // on settings, but does not test propagation of settings across renderers.
1499 blink::WebView* web_view = GetWebFrame()->View();
1500 web_view->GetSettings()->SetPluginsEnabled(allowed);
1501 }
1502
SetAllowRunningOfInsecureContent(bool allowed)1503 void TestRunnerBindings::SetAllowRunningOfInsecureContent(bool allowed) {
1504 if (invalid_)
1505 return;
1506 runner_->SetAllowRunningOfInsecureContent(allowed);
1507 }
1508
DumpPermissionClientCallbacks()1509 void TestRunnerBindings::DumpPermissionClientCallbacks() {
1510 if (invalid_)
1511 return;
1512 runner_->DumpPermissionClientCallbacks();
1513 }
1514
DumpBackForwardList()1515 void TestRunnerBindings::DumpBackForwardList() {
1516 if (invalid_)
1517 return;
1518 runner_->DumpBackForwardList();
1519 }
1520
DumpSelectionRect()1521 void TestRunnerBindings::DumpSelectionRect() {
1522 if (invalid_)
1523 return;
1524 runner_->DumpSelectionRect();
1525 }
1526
SetPrinting()1527 void TestRunnerBindings::SetPrinting() {
1528 if (invalid_)
1529 return;
1530 runner_->SetPrinting();
1531 }
1532
SetPrintingForFrame(const std::string & frame_name)1533 void TestRunnerBindings::SetPrintingForFrame(const std::string& frame_name) {
1534 if (invalid_)
1535 return;
1536 runner_->SetPrintingForFrame(frame_name);
1537 }
1538
ClearTrustTokenState(v8::Local<v8::Function> v8_callback)1539 void TestRunnerBindings::ClearTrustTokenState(
1540 v8::Local<v8::Function> v8_callback) {
1541 if (invalid_)
1542 return;
1543 runner_->GetWebTestControlHostRemote()->ClearTrustTokenState(
1544 WrapV8Closure(std::move(v8_callback)));
1545 }
1546
SetShouldGeneratePixelResults(bool value)1547 void TestRunnerBindings::SetShouldGeneratePixelResults(bool value) {
1548 if (invalid_)
1549 return;
1550 runner_->SetShouldGeneratePixelResults(value);
1551 }
1552
SetShouldStayOnPageAfterHandlingBeforeUnload(bool value)1553 void TestRunnerBindings::SetShouldStayOnPageAfterHandlingBeforeUnload(
1554 bool value) {
1555 if (invalid_)
1556 return;
1557 runner_->SetShouldStayOnPageAfterHandlingBeforeUnload(value);
1558 }
1559
SetWillSendRequestClearHeader(const std::string & header)1560 void TestRunnerBindings::SetWillSendRequestClearHeader(
1561 const std::string& header) {
1562 if (invalid_)
1563 return;
1564 runner_->SetWillSendRequestClearHeader(header);
1565 }
1566
SetWillSendRequestClearReferrer()1567 void TestRunnerBindings::SetWillSendRequestClearReferrer() {
1568 if (invalid_)
1569 return;
1570 runner_->SetWillSendRequestClearReferrer();
1571 }
1572
WaitUntilExternalURLLoad()1573 void TestRunnerBindings::WaitUntilExternalURLLoad() {
1574 if (invalid_)
1575 return;
1576 runner_->WaitUntilExternalURLLoad();
1577 }
1578
DumpDragImage()1579 void TestRunnerBindings::DumpDragImage() {
1580 if (invalid_)
1581 return;
1582 runner_->DumpDragImage();
1583 }
1584
DumpNavigationPolicy()1585 void TestRunnerBindings::DumpNavigationPolicy() {
1586 if (invalid_)
1587 return;
1588 runner_->DumpNavigationPolicy();
1589 }
1590
ClearAllDatabases()1591 void TestRunnerBindings::ClearAllDatabases() {
1592 if (invalid_)
1593 return;
1594 runner_->GetWebTestControlHostRemote()->ClearAllDatabases();
1595 }
1596
SetDatabaseQuota(int quota)1597 void TestRunnerBindings::SetDatabaseQuota(int quota) {
1598 if (invalid_)
1599 return;
1600 runner_->GetWebTestControlHostRemote()->SetDatabaseQuota(quota);
1601 }
1602
SetBlockThirdPartyCookies(bool block)1603 void TestRunnerBindings::SetBlockThirdPartyCookies(bool block) {
1604 if (invalid_)
1605 return;
1606 runner_->GetWebTestControlHostRemote()->BlockThirdPartyCookies(block);
1607 }
1608
SimulateBrowserWindowFocus(bool value)1609 void TestRunnerBindings::SimulateBrowserWindowFocus(bool value) {
1610 if (invalid_)
1611 return;
1612 // This simulates the browser focusing or unfocusing the window,
1613 // but does so only for this renderer process. Other frame tree
1614 // fragments in other processes do not hear about the change. To
1615 // do so the focus change would need to go through window.focus()
1616 // and then watch for the focus event or do a round trip to the
1617 // browser.
1618 // TODO(danakj): This does not appear to do the same thing as the
1619 // browser does, because actually moving focus causes different test
1620 // results in tests such as editing/selection/4975120.html with the
1621 // inner frame not getting its caret back.
1622 // Early out instead of CHECK() to avoid poking the fuzzer bear.
1623 if (!frame_->IsMainFrame())
1624 return;
1625 runner_->FocusWindow(frame_, value);
1626 }
1627
PathToLocalResource(const std::string & path)1628 std::string TestRunnerBindings::PathToLocalResource(const std::string& path) {
1629 if (invalid_)
1630 return {};
1631 return RewriteFileURLToLocalResource(path).GetString().Utf8();
1632 }
1633
SetBackingScaleFactor(double value,v8::Local<v8::Function> v8_callback)1634 void TestRunnerBindings::SetBackingScaleFactor(
1635 double value,
1636 v8::Local<v8::Function> v8_callback) {
1637 if (invalid_)
1638 return;
1639
1640 // Limit backing scale factor to something low - 15x. Without
1641 // this limit, arbitrarily large values can be used, which can lead to
1642 // crashes and other problems. Examples of problems:
1643 // gfx::Size::GetCheckedArea crashes with a size which overflows int;
1644 // GLES2DecoderImpl::TexStorageImpl fails with "dimensions out of range"; GL
1645 // ERROR :GL_OUT_OF_MEMORY. See https://crbug.com/899482 or
1646 // https://crbug.com/900271
1647 double limited_value = fmin(15, value);
1648
1649 frame_->GetLocalRootWebFrameWidget()->SetDeviceScaleFactorForTesting(
1650 limited_value);
1651
1652 v8::Isolate* isolate = blink::MainThreadIsolate();
1653 v8::HandleScope handle_scope(isolate);
1654
1655 WrapV8Callback(std::move(v8_callback))
1656 .Run({
1657 // TODO(oshima): remove this callback argument when all platforms are
1658 // migrated to use-zoom-for-dsf by default.
1659 v8::Boolean::New(isolate, IsUseZoomForDSFEnabled()),
1660 });
1661 }
1662
SetColorProfile(const std::string & name,v8::Local<v8::Function> v8_callback)1663 void TestRunnerBindings::SetColorProfile(const std::string& name,
1664 v8::Local<v8::Function> v8_callback) {
1665 if (invalid_)
1666 return;
1667
1668 gfx::ColorSpace color_space;
1669 if (name == "genericRGB") {
1670 color_space = gfx::ICCProfileForTestingGenericRGB().GetColorSpace();
1671 } else if (name == "sRGB") {
1672 color_space = gfx::ColorSpace::CreateSRGB();
1673 } else if (name == "colorSpin") {
1674 color_space = gfx::ICCProfileForTestingColorSpin().GetColorSpace();
1675 } else if (name == "adobeRGB") {
1676 color_space = gfx::ICCProfileForTestingAdobeRGB().GetColorSpace();
1677 }
1678 GetWebFrame()->View()->SetDeviceColorSpaceForTesting(color_space);
1679
1680 WrapV8Closure(std::move(v8_callback)).Run();
1681 }
1682
SetBluetoothFakeAdapter(const std::string & adapter_name,v8::Local<v8::Function> v8_callback)1683 void TestRunnerBindings::SetBluetoothFakeAdapter(
1684 const std::string& adapter_name,
1685 v8::Local<v8::Function> v8_callback) {
1686 if (invalid_)
1687 return;
1688 runner_->GetBluetoothFakeAdapterSetter().Set(
1689 adapter_name, WrapV8Closure(std::move(v8_callback)));
1690 }
1691
SetBluetoothManualChooser(bool enable)1692 void TestRunnerBindings::SetBluetoothManualChooser(bool enable) {
1693 if (invalid_)
1694 return;
1695 runner_->GetWebTestControlHostRemote()->SetBluetoothManualChooser(enable);
1696 }
1697
GetBluetoothManualChooserEventsReply(base::WeakPtr<TestRunnerBindings> test_runner,blink::WebLocalFrame * frame,BoundV8Callback callback,const std::vector<std::string> & events)1698 static void GetBluetoothManualChooserEventsReply(
1699 base::WeakPtr<TestRunnerBindings> test_runner,
1700 blink::WebLocalFrame* frame,
1701 BoundV8Callback callback,
1702 const std::vector<std::string>& events) {
1703 if (!test_runner) // This guards the validity of the |frame|.
1704 return;
1705
1706 v8::Isolate* isolate = blink::MainThreadIsolate();
1707 v8::HandleScope handle_scope(isolate);
1708
1709 // gin::TryConvertToV8() requires a v8::Context.
1710 v8::Local<v8::Context> context = frame->MainWorldScriptContext();
1711 CHECK(!context.IsEmpty());
1712 v8::Context::Scope context_scope(context);
1713
1714 v8::Local<v8::Value> arg;
1715 bool converted = gin::TryConvertToV8(isolate, events, &arg);
1716 CHECK(converted);
1717
1718 std::move(callback).Run({
1719 arg,
1720 });
1721 }
1722
GetBluetoothManualChooserEvents(v8::Local<v8::Function> callback)1723 void TestRunnerBindings::GetBluetoothManualChooserEvents(
1724 v8::Local<v8::Function> callback) {
1725 if (invalid_)
1726 return;
1727 runner_->GetWebTestControlHostRemote()->GetBluetoothManualChooserEvents(
1728 base::BindOnce(&GetBluetoothManualChooserEventsReply,
1729 weak_ptr_factory_.GetWeakPtr(), GetWebFrame(),
1730 WrapV8Callback(std::move(callback))));
1731 }
1732
SendBluetoothManualChooserEvent(const std::string & event,const std::string & argument)1733 void TestRunnerBindings::SendBluetoothManualChooserEvent(
1734 const std::string& event,
1735 const std::string& argument) {
1736 if (invalid_)
1737 return;
1738 runner_->GetWebTestControlHostRemote()->SendBluetoothManualChooserEvent(
1739 event, argument);
1740 }
1741
SetPOSIXLocale(const std::string & locale)1742 void TestRunnerBindings::SetPOSIXLocale(const std::string& locale) {
1743 if (invalid_)
1744 return;
1745 setlocale(LC_ALL, locale.c_str());
1746 // Number to string conversions require C locale, regardless of what
1747 // all the other subsystems are set to.
1748 setlocale(LC_NUMERIC, "C");
1749 }
1750
SimulateWebNotificationClick(gin::Arguments * args)1751 void TestRunnerBindings::SimulateWebNotificationClick(gin::Arguments* args) {
1752 if (invalid_)
1753 return;
1754
1755 DCHECK_GE(args->Length(), 1);
1756
1757 std::string title;
1758 int action_index = std::numeric_limits<int32_t>::min();
1759 base::Optional<base::string16> reply;
1760
1761 if (!args->GetNext(&title)) {
1762 args->ThrowError();
1763 return;
1764 }
1765
1766 // Optional |action_index| argument.
1767 if (args->Length() >= 2) {
1768 if (!args->GetNext(&action_index)) {
1769 args->ThrowError();
1770 return;
1771 }
1772 }
1773
1774 // Optional |reply| argument.
1775 if (args->Length() >= 3) {
1776 std::string reply_string;
1777 if (!args->GetNext(&reply_string)) {
1778 args->ThrowError();
1779 return;
1780 }
1781
1782 reply = base::UTF8ToUTF16(reply_string);
1783 }
1784
1785 runner_->GetWebTestControlHostRemote()->SimulateWebNotificationClick(
1786 title, action_index, reply);
1787 }
1788
SimulateWebNotificationClose(const std::string & title,bool by_user)1789 void TestRunnerBindings::SimulateWebNotificationClose(const std::string& title,
1790 bool by_user) {
1791 if (invalid_)
1792 return;
1793 runner_->GetWebTestControlHostRemote()->SimulateWebNotificationClose(title,
1794 by_user);
1795 }
1796
SimulateWebContentIndexDelete(const std::string & id)1797 void TestRunnerBindings::SimulateWebContentIndexDelete(const std::string& id) {
1798 if (invalid_)
1799 return;
1800 runner_->GetWebTestControlHostRemote()->SimulateWebContentIndexDelete(id);
1801 }
1802
SetHighlightAds()1803 void TestRunnerBindings::SetHighlightAds() {
1804 if (invalid_)
1805 return;
1806 blink::WebView* web_view = GetWebFrame()->View();
1807 web_view->GetSettings()->SetHighlightAds(true);
1808 }
1809
AddWebPageOverlay()1810 void TestRunnerBindings::AddWebPageOverlay() {
1811 if (invalid_)
1812 return;
1813 // Early out instead of CHECK() to avoid poking the fuzzer bear.
1814 if (!frame_->IsMainFrame())
1815 return;
1816 frame_->GetLocalRootWebFrameWidget()->SetMainFrameOverlayColor(SK_ColorCYAN);
1817 }
1818
RemoveWebPageOverlay()1819 void TestRunnerBindings::RemoveWebPageOverlay() {
1820 if (invalid_)
1821 return;
1822 // Early out instead of CHECK() to avoid poking the fuzzer bear.
1823 if (!frame_->IsMainFrame())
1824 return;
1825 frame_->GetLocalRootWebFrameWidget()->SetMainFrameOverlayColor(
1826 SK_ColorTRANSPARENT);
1827 }
1828
UpdateAllLifecyclePhasesAndComposite()1829 void TestRunnerBindings::UpdateAllLifecyclePhasesAndComposite() {
1830 if (invalid_)
1831 return;
1832 static_cast<WebWidgetTestProxy*>(frame_->GetLocalRootRenderWidget())
1833 ->UpdateAllLifecyclePhasesAndComposite(base::DoNothing());
1834 }
1835
UpdateAllLifecyclePhasesAndCompositeThen(v8::Local<v8::Function> v8_callback)1836 void TestRunnerBindings::UpdateAllLifecyclePhasesAndCompositeThen(
1837 v8::Local<v8::Function> v8_callback) {
1838 if (invalid_)
1839 return;
1840 static_cast<WebWidgetTestProxy*>(frame_->GetLocalRootRenderWidget())
1841 ->UpdateAllLifecyclePhasesAndComposite(
1842 WrapV8Closure(std::move(v8_callback)));
1843 }
1844
SetAnimationRequiresRaster(bool do_raster)1845 void TestRunnerBindings::SetAnimationRequiresRaster(bool do_raster) {
1846 if (invalid_)
1847 return;
1848 runner_->SetAnimationRequiresRaster(do_raster);
1849 }
1850
GetManifestReply(BoundV8Callback callback,const blink::WebURL & manifest_url,const blink::Manifest & manifest)1851 static void GetManifestReply(BoundV8Callback callback,
1852 const blink::WebURL& manifest_url,
1853 const blink::Manifest& manifest) {
1854 std::move(callback).Run(NoV8Args());
1855 }
1856
GetManifestThen(v8::Local<v8::Function> v8_callback)1857 void TestRunnerBindings::GetManifestThen(v8::Local<v8::Function> v8_callback) {
1858 if (invalid_)
1859 return;
1860 blink::WebManifestManager::RequestManifestForTesting(
1861 GetWebFrame(),
1862 base::BindOnce(GetManifestReply, WrapV8Callback(std::move(v8_callback))));
1863 }
1864
CapturePrintingPixelsThen(v8::Local<v8::Function> v8_callback)1865 void TestRunnerBindings::CapturePrintingPixelsThen(
1866 v8::Local<v8::Function> v8_callback) {
1867 if (invalid_)
1868 return;
1869 SkBitmap bitmap = PrintFrameToBitmap(GetWebFrame());
1870
1871 v8::Isolate* isolate = blink::MainThreadIsolate();
1872 v8::HandleScope handle_scope(isolate);
1873
1874 // ConvertBitmapToV8() requires a v8::Context.
1875 v8::Local<v8::Context> context = GetWebFrame()->MainWorldScriptContext();
1876 CHECK(!context.IsEmpty());
1877 v8::Context::Scope context_scope(context);
1878
1879 WrapV8Callback(std::move(v8_callback))
1880 .Run({
1881 ConvertBitmapToV8(context_scope, bitmap),
1882 });
1883 }
1884
CheckForLeakedWindows()1885 void TestRunnerBindings::CheckForLeakedWindows() {
1886 if (invalid_)
1887 return;
1888 runner_->GetWebTestControlHostRemote()->CheckForLeakedWindows();
1889 }
1890
CopyImageThen(int x,int y,v8::Local<v8::Function> v8_callback)1891 void TestRunnerBindings::CopyImageThen(int x,
1892 int y,
1893 v8::Local<v8::Function> v8_callback) {
1894 mojo::Remote<blink::mojom::ClipboardHost> remote_clipboard;
1895 frame_->GetBrowserInterfaceBroker()->GetInterface(
1896 remote_clipboard.BindNewPipeAndPassReceiver());
1897
1898 uint64_t sequence_number_before = 0;
1899 remote_clipboard->GetSequenceNumber(ui::ClipboardBuffer::kCopyPaste,
1900 &sequence_number_before);
1901 GetWebFrame()->CopyImageAtForTesting(gfx::Point(x, y));
1902 uint64_t sequence_number_after = 0;
1903 while (sequence_number_before == sequence_number_after) {
1904 remote_clipboard->GetSequenceNumber(ui::ClipboardBuffer::kCopyPaste,
1905 &sequence_number_after);
1906 }
1907
1908 SkBitmap bitmap;
1909 remote_clipboard->ReadImage(ui::ClipboardBuffer::kCopyPaste, &bitmap);
1910
1911 v8::Isolate* isolate = blink::MainThreadIsolate();
1912 v8::HandleScope handle_scope(isolate);
1913
1914 v8::Local<v8::Context> context = GetWebFrame()->MainWorldScriptContext();
1915 CHECK(!context.IsEmpty());
1916 v8::Context::Scope context_scope(context);
1917
1918 WrapV8Callback(std::move(v8_callback))
1919 .Run(ConvertBitmapToV8(context_scope, std::move(bitmap)));
1920 }
1921
DropPointerLock()1922 void TestRunnerBindings::DropPointerLock() {
1923 if (invalid_)
1924 return;
1925 runner_->GetWebTestControlHostRemote()->DropPointerLock();
1926 }
1927
SetPointerLockWillFail()1928 void TestRunnerBindings::SetPointerLockWillFail() {
1929 if (invalid_)
1930 return;
1931 runner_->GetWebTestControlHostRemote()->SetPointerLockWillFail();
1932 }
1933
SetPointerLockWillRespondAsynchronously()1934 void TestRunnerBindings::SetPointerLockWillRespondAsynchronously() {
1935 if (invalid_)
1936 return;
1937 runner_->GetWebTestControlHostRemote()
1938 ->SetPointerLockWillRespondAsynchronously();
1939 }
1940
AllowPointerLock()1941 void TestRunnerBindings::AllowPointerLock() {
1942 if (invalid_)
1943 return;
1944 runner_->GetWebTestControlHostRemote()->AllowPointerLock();
1945 }
1946
SetCustomTextOutput(const std::string & output)1947 void TestRunnerBindings::SetCustomTextOutput(const std::string& output) {
1948 if (invalid_)
1949 return;
1950 runner_->SetCustomTextOutput(output);
1951 }
1952
SetPermission(const std::string & name,const std::string & value,const std::string & origin,const std::string & embedding_origin)1953 void TestRunnerBindings::SetPermission(const std::string& name,
1954 const std::string& value,
1955 const std::string& origin,
1956 const std::string& embedding_origin) {
1957 if (invalid_)
1958 return;
1959 runner_->GetWebTestControlHostRemote()->SetPermission(
1960 name, blink::ToPermissionStatus(value), GURL(origin),
1961 GURL(embedding_origin));
1962 }
1963
DispatchBeforeInstallPromptEventReply(BoundV8Callback callback,bool cancelled)1964 static void DispatchBeforeInstallPromptEventReply(BoundV8Callback callback,
1965 bool cancelled) {
1966 v8::Isolate* isolate = blink::MainThreadIsolate();
1967 v8::HandleScope handle_scope(isolate);
1968 std::move(callback).Run({
1969 v8::Boolean::New(isolate, cancelled),
1970 });
1971 }
1972
DispatchBeforeInstallPromptEvent(const std::vector<std::string> & event_platforms,v8::Local<v8::Function> v8_callback)1973 void TestRunnerBindings::DispatchBeforeInstallPromptEvent(
1974 const std::vector<std::string>& event_platforms,
1975 v8::Local<v8::Function> v8_callback) {
1976 if (invalid_)
1977 return;
1978 app_banner_service_ = std::make_unique<AppBannerService>();
1979 frame_->BindLocalInterface(blink::mojom::AppBannerController::Name_,
1980 app_banner_service_->controller()
1981 .BindNewPipeAndPassReceiver()
1982 .PassPipe());
1983
1984 app_banner_service_->SendBannerPromptRequest(
1985 event_platforms, base::BindOnce(&DispatchBeforeInstallPromptEventReply,
1986 WrapV8Callback(std::move(v8_callback))));
1987 }
1988
ResolveBeforeInstallPromptPromise(const std::string & platform)1989 void TestRunnerBindings::ResolveBeforeInstallPromptPromise(
1990 const std::string& platform) {
1991 if (invalid_)
1992 return;
1993 if (app_banner_service_) {
1994 app_banner_service_->ResolvePromise(platform);
1995 app_banner_service_.reset();
1996 }
1997 }
1998
RunIdleTasks(v8::Local<v8::Function> v8_callback)1999 void TestRunnerBindings::RunIdleTasks(v8::Local<v8::Function> v8_callback) {
2000 if (invalid_)
2001 return;
2002 blink::scheduler::WebThreadScheduler* scheduler =
2003 content::RenderThreadImpl::current()->GetWebMainThreadScheduler();
2004 blink::scheduler::RunIdleTasksForTesting(
2005 scheduler, WrapV8Closure(std::move(v8_callback)));
2006 }
2007
PlatformName()2008 std::string TestRunnerBindings::PlatformName() {
2009 if (invalid_)
2010 return {};
2011 return runner_->platform_name_;
2012 }
2013
TextZoomIn()2014 void TestRunnerBindings::TextZoomIn() {
2015 if (invalid_)
2016 return;
2017
2018 // This may only be run from the main frame, as the user modifies this at the
2019 // top level.
2020 // Early out instead of CHECK() to avoid poking the fuzzer bear.
2021 if (!frame_->IsMainFrame())
2022 return;
2023
2024 // TODO(danakj): This should be an async call through the browser process, but
2025 // note this is an AndroidWebView feature which is not part of the content (or
2026 // content_shell) APIs.
2027 blink::WebFrameWidget* widget = frame_->GetLocalRootWebFrameWidget();
2028 widget->SetTextZoomFactor(widget->TextZoomFactor() * 1.2f);
2029 }
2030
TextZoomOut()2031 void TestRunnerBindings::TextZoomOut() {
2032 if (invalid_)
2033 return;
2034
2035 // This may only be run from the main frame, as the user modifies this at the
2036 // top level.
2037 // Early out instead of CHECK() to avoid poking the fuzzer bear.
2038 if (!frame_->IsMainFrame())
2039 return;
2040
2041 // TODO(danakj): This should be an async call through the browser process, but
2042 // note this is an AndroidWebView feature which is not part of the content (or
2043 // content_shell) APIs.
2044 blink::WebFrameWidget* widget = frame_->GetLocalRootWebFrameWidget();
2045 widget->SetTextZoomFactor(widget->TextZoomFactor() / 1.2f);
2046 }
2047
ZoomPageIn()2048 void TestRunnerBindings::ZoomPageIn() {
2049 if (invalid_)
2050 return;
2051
2052 // This may only be run from the main frame, as the user modifies this at the
2053 // top level.
2054 // Early out instead of CHECK() to avoid poking the fuzzer bear.
2055 if (!frame_->IsMainFrame())
2056 return;
2057
2058 blink::WebView* web_view = GetWebFrame()->View();
2059 // TODO(danakj): This should be an async call through the browser process.
2060 // JS can wait for `matchMedia("screen and (min-resolution: 2dppx)").matches`
2061 // for the operation to complete, if it can tell which number to use in
2062 // min-resolution.
2063 frame_->GetLocalRootWebFrameWidget()->SetZoomLevelForTesting(
2064 web_view->ZoomLevel() + 1);
2065 }
2066
ZoomPageOut()2067 void TestRunnerBindings::ZoomPageOut() {
2068 if (invalid_)
2069 return;
2070
2071 // This may only be run from the main frame, as the user modifies this at the
2072 // top level.
2073 // Early out instead of CHECK() to avoid poking the fuzzer bear.
2074 if (!frame_->IsMainFrame())
2075 return;
2076
2077 blink::WebView* web_view = GetWebFrame()->View();
2078 // TODO(danakj): This should be an async call through the browser process.
2079 // JS can wait for `matchMedia("screen and (min-resolution: 2dppx)").matches`
2080 // for the operation to complete, if it can tell which number to use in
2081 // min-resolution.
2082 frame_->GetLocalRootWebFrameWidget()->SetZoomLevelForTesting(
2083 web_view->ZoomLevel() - 1);
2084 }
2085
SetPageZoomFactor(double zoom_factor)2086 void TestRunnerBindings::SetPageZoomFactor(double zoom_factor) {
2087 if (invalid_)
2088 return;
2089
2090 // This may only be run from the main frame, as the user modifies this at the
2091 // top level.
2092 // Early out instead of CHECK() to avoid poking the fuzzer bear.
2093 if (!frame_->IsMainFrame())
2094 return;
2095
2096 // TODO(danakj): This should be an async call through the browser process.
2097 // JS can wait for `matchMedia("screen and (min-resolution: 2dppx)").matches`
2098 // for the operation to complete, if it can tell which number to use in
2099 // min-resolution.
2100 frame_->GetLocalRootWebFrameWidget()->SetZoomLevelForTesting(
2101 blink::PageZoomFactorToZoomLevel(zoom_factor));
2102 }
2103
TooltipText()2104 std::string TestRunnerBindings::TooltipText() {
2105 if (invalid_)
2106 return {};
2107
2108 blink::WebString tooltip_text = frame_->GetLocalRootRenderWidget()
2109 ->GetWebWidget()
2110 ->GetLastToolTipTextForTesting();
2111 return tooltip_text.Utf8();
2112 }
2113
WebHistoryItemCount()2114 int TestRunnerBindings::WebHistoryItemCount() {
2115 if (invalid_)
2116 return 0;
2117 return frame_->render_view()->GetLocalSessionHistoryLengthForTesting();
2118 }
2119
ForceNextWebGLContextCreationToFail()2120 void TestRunnerBindings::ForceNextWebGLContextCreationToFail() {
2121 if (invalid_)
2122 return;
2123 blink::ForceNextWebGLContextCreationToFailForTest();
2124 }
2125
FocusDevtoolsSecondaryWindow()2126 void TestRunnerBindings::FocusDevtoolsSecondaryWindow() {
2127 if (invalid_)
2128 return;
2129 runner_->GetWebTestControlHostRemote()->FocusDevtoolsSecondaryWindow();
2130 }
2131
ForceNextDrawingBufferCreationToFail()2132 void TestRunnerBindings::ForceNextDrawingBufferCreationToFail() {
2133 if (invalid_)
2134 return;
2135 blink::ForceNextDrawingBufferCreationToFailForTest();
2136 }
2137
NotImplemented(const gin::Arguments & args)2138 void TestRunnerBindings::NotImplemented(const gin::Arguments& args) {}
2139
WorkQueue(TestRunner * controller)2140 TestRunner::WorkQueue::WorkQueue(TestRunner* controller)
2141 : controller_(controller) {}
2142
Reset()2143 void TestRunner::WorkQueue::Reset() {
2144 // Set values in a TrackedDictionary |states_| to avoid accessing missing
2145 // values.
2146 set_frozen(false);
2147 set_has_items(false);
2148 states_.ResetChangeTracking();
2149 set_loading(true);
2150 }
2151
AddWork(mojom::WorkItemPtr work_item)2152 void TestRunner::WorkQueue::AddWork(mojom::WorkItemPtr work_item) {
2153 if (is_frozen())
2154 return;
2155 controller_->GetWebTestControlHostRemote()->WorkItemAdded(
2156 std::move(work_item));
2157 set_has_items(true);
2158 OnStatesChanged();
2159 }
2160
RequestWork()2161 void TestRunner::WorkQueue::RequestWork() {
2162 controller_->GetWebTestControlHostRemote()->RequestWorkItem();
2163 }
2164
ProcessWorkItem(mojom::WorkItemPtr work_item)2165 void TestRunner::WorkQueue::ProcessWorkItem(mojom::WorkItemPtr work_item) {
2166 // Watch for loading finishing inside ProcessWorkItemInternal().
2167 set_loading(true);
2168 bool started_load = ProcessWorkItemInternal(std::move(work_item));
2169 if (started_load) {
2170 // If a load started, and didn't complete inside of
2171 // ProcessWorkItemInternal(), then mark the load as running.
2172 if (loading_)
2173 controller_->frame_will_start_load_ = true;
2174
2175 // Wait for an ongoing load to complete before requesting the next WorkItem.
2176 return;
2177 }
2178 RequestWork();
2179 }
2180
ProcessWorkItemInternal(mojom::WorkItemPtr work_item)2181 bool TestRunner::WorkQueue::ProcessWorkItemInternal(
2182 mojom::WorkItemPtr work_item) {
2183 switch (work_item->which()) {
2184 case mojom::WorkItem::Tag::BACK_FORWARD: {
2185 mojom::WorkItemBackForwardPtr& item_back_forward =
2186 work_item->get_back_forward();
2187 controller_->GoToOffset(item_back_forward->distance);
2188 return true; // TODO(danakj): Did it really start a navigation?
2189 }
2190 case mojom::WorkItem::Tag::LOADING_SCRIPT: {
2191 mojom::WorkItemLoadingScriptPtr& item_loading_script =
2192 work_item->get_loading_script();
2193 WebFrameTestProxy* main_frame =
2194 controller_->FindInProcessMainWindowMainFrame();
2195 DCHECK(main_frame);
2196 main_frame->GetWebFrame()->ExecuteScript(blink::WebScriptSource(
2197 blink::WebString::FromUTF8(item_loading_script->script)));
2198 return true; // TODO(danakj): Did it really start a navigation?
2199 }
2200 case mojom::WorkItem::Tag::NON_LOADING_SCRIPT: {
2201 mojom::WorkItemNonLoadingScriptPtr& item_non_loading_script =
2202 work_item->get_non_loading_script();
2203 WebFrameTestProxy* main_frame =
2204 controller_->FindInProcessMainWindowMainFrame();
2205 DCHECK(main_frame);
2206 main_frame->GetWebFrame()->ExecuteScript(blink::WebScriptSource(
2207 blink::WebString::FromUTF8(item_non_loading_script->script)));
2208 return false;
2209 }
2210 case mojom::WorkItem::Tag::LOAD: {
2211 mojom::WorkItemLoadPtr& item_load = work_item->get_load();
2212 controller_->LoadURLForFrame(GURL(item_load->url), item_load->target);
2213 return true; // TODO(danakj): Did it really start a navigation?
2214 }
2215 case mojom::WorkItem::Tag::RELOAD:
2216 controller_->Reload();
2217 return true;
2218 }
2219 NOTREACHED();
2220 return false;
2221 }
2222
ReplicateStates(const base::DictionaryValue & values)2223 void TestRunner::WorkQueue::ReplicateStates(
2224 const base::DictionaryValue& values) {
2225 states_.ApplyUntrackedChanges(values);
2226 if (!has_items())
2227 controller_->FinishTestIfReady();
2228 }
2229
OnStatesChanged()2230 void TestRunner::WorkQueue::OnStatesChanged() {
2231 if (states_.changed_values().empty())
2232 return;
2233
2234 controller_->GetWebTestControlHostRemote()->WorkQueueStatesChanged(
2235 states_.changed_values().Clone());
2236 states_.ResetChangeTracking();
2237 }
2238
TestRunner()2239 TestRunner::TestRunner()
2240 : work_queue_(this),
2241 test_content_settings_client_(this, &web_test_runtime_flags_) {
2242 // NOTE: please don't put feature specific enable flags here,
2243 // instead add them to runtime_enabled_features.json5.
2244 //
2245 // Stores state to be restored after each test.
2246 blink::WebTestingSupport::SaveRuntimeFeatures();
2247
2248 Reset();
2249 }
2250
2251 TestRunner::~TestRunner() = default;
2252
Install(WebFrameTestProxy * frame,SpellCheckClient * spell_check)2253 void TestRunner::Install(WebFrameTestProxy* frame,
2254 SpellCheckClient* spell_check) {
2255 bool is_main_test_window = frame->GetWebViewTestProxy()->is_main_window();
2256 TestRunnerBindings::Install(this, frame, spell_check,
2257 IsWebPlatformTestsMode(), is_main_test_window);
2258 fake_screen_orientation_impl_.OverrideAssociatedInterfaceProviderForFrame(
2259 frame->GetWebFrame());
2260 gamepad_controller_.Install(frame);
2261 frame->GetWebViewTestProxy()
2262 ->GetWebView()
2263 ->SetScreenOrientationOverrideForTesting(
2264 fake_screen_orientation_impl_.CurrentOrientationType());
2265 }
2266
Reset()2267 void TestRunner::Reset() {
2268 loading_frames_.clear();
2269 web_test_runtime_flags_.Reset();
2270 fake_screen_orientation_impl_.ResetData();
2271 gamepad_controller_.Reset();
2272 drag_image_.reset();
2273
2274 blink::WebTestingSupport::ResetRuntimeFeatures();
2275 blink::WebCache::Clear();
2276 blink::WebSecurityPolicy::ClearOriginAccessList();
2277 #if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_FUCHSIA)
2278 blink::WebFontRenderStyle::SetSubpixelPositioning(false);
2279 #endif
2280 blink::ResetDomainRelaxationForTest();
2281
2282 setlocale(LC_ALL, "");
2283 setlocale(LC_NUMERIC, "C");
2284
2285 dump_as_audio_ = false;
2286 dump_back_forward_list_ = false;
2287 test_repaint_ = false;
2288 sweep_horizontally_ = false;
2289 animation_requires_raster_ = false;
2290 main_frame_loaded_ = false;
2291 frame_will_start_load_ = false;
2292 did_notify_done_ = false;
2293
2294 http_headers_to_clear_.clear();
2295 clear_referrer_ = false;
2296
2297 platform_name_ = "chromium";
2298
2299 weak_factory_.InvalidateWeakPtrs();
2300 work_queue_.Reset();
2301 }
2302
ResetWebView(WebViewTestProxy * web_view_test_proxy)2303 void TestRunner::ResetWebView(WebViewTestProxy* web_view_test_proxy) {
2304 blink::WebView* web_view = web_view_test_proxy->GetWebView();
2305
2306 web_view->SetTabKeyCyclesThroughElements(true);
2307 web_view->GetSettings()->SetHighlightAds(false);
2308 web_view->DisableAutoResizeForTesting(gfx::Size());
2309 web_view->SetScreenOrientationOverrideForTesting(
2310 fake_screen_orientation_impl_.CurrentOrientationType());
2311 web_view->UseSynchronousResizeModeForTesting(false);
2312 }
2313
ResetWebWidget(WebWidgetTestProxy * web_widget_test_proxy)2314 void TestRunner::ResetWebWidget(WebWidgetTestProxy* web_widget_test_proxy) {
2315 blink::WebFrameWidget* web_widget =
2316 web_widget_test_proxy->GetWebFrameWidget();
2317
2318 web_widget->SetDeviceScaleFactorForTesting(0);
2319 web_widget->ReleaseMouseLockAndPointerCaptureForTesting();
2320
2321 // These things are only modified/valid for the main frame's widget.
2322 if (web_widget_test_proxy->delegate()) {
2323 web_widget->ResetZoomLevelForTesting();
2324
2325 web_widget->SetMainFrameOverlayColor(SK_ColorTRANSPARENT);
2326 web_widget->SetTextZoomFactor(1);
2327 }
2328 }
2329
SetTestIsRunning(bool running)2330 void TestRunner::SetTestIsRunning(bool running) {
2331 test_is_running_ = running;
2332 }
2333
ShouldDumpSelectionRect() const2334 bool TestRunner::ShouldDumpSelectionRect() const {
2335 return web_test_runtime_flags_.dump_selection_rect();
2336 }
2337
ShouldDumpEditingCallbacks() const2338 bool TestRunner::ShouldDumpEditingCallbacks() const {
2339 return web_test_runtime_flags_.dump_editting_callbacks();
2340 }
2341
SetShouldDumpAsLayout(bool value)2342 void TestRunner::SetShouldDumpAsLayout(bool value) {
2343 web_test_runtime_flags_.set_dump_as_layout(value);
2344 OnWebTestRuntimeFlagsChanged();
2345 }
2346
ShouldDumpAsCustomText() const2347 bool TestRunner::ShouldDumpAsCustomText() const {
2348 return web_test_runtime_flags_.has_custom_text_output();
2349 }
2350
CustomDumpText() const2351 std::string TestRunner::CustomDumpText() const {
2352 return web_test_runtime_flags_.custom_text_output();
2353 }
2354
SetCustomTextOutput(const std::string & text)2355 void TestRunner::SetCustomTextOutput(const std::string& text) {
2356 web_test_runtime_flags_.set_custom_text_output(text);
2357 web_test_runtime_flags_.set_has_custom_text_output(true);
2358 OnWebTestRuntimeFlagsChanged();
2359 }
2360
ShouldGeneratePixelResults()2361 bool TestRunner::ShouldGeneratePixelResults() {
2362 return web_test_runtime_flags_.generate_pixel_results();
2363 }
2364
ShouldGenerateTextResults()2365 TextResultType TestRunner::ShouldGenerateTextResults() {
2366 if (web_test_runtime_flags_.dump_as_text()) {
2367 return TextResultType::kText;
2368 } else if (web_test_runtime_flags_.dump_as_markup()) {
2369 DCHECK(!web_test_runtime_flags_.is_printing());
2370 return TextResultType::kMarkup;
2371 } else if (web_test_runtime_flags_.dump_as_layout()) {
2372 if (web_test_runtime_flags_.is_printing())
2373 return TextResultType::kLayoutAsPrinting;
2374 return TextResultType::kLayout;
2375 }
2376 return TextResultType::kEmpty;
2377 }
2378
ShouldStayOnPageAfterHandlingBeforeUnload() const2379 bool TestRunner::ShouldStayOnPageAfterHandlingBeforeUnload() const {
2380 return web_test_runtime_flags_.stay_on_page_after_handling_before_unload();
2381 }
2382
SetShouldGeneratePixelResults(bool value)2383 void TestRunner::SetShouldGeneratePixelResults(bool value) {
2384 web_test_runtime_flags_.set_generate_pixel_results(value);
2385 OnWebTestRuntimeFlagsChanged();
2386 }
2387
ShouldDumpAsAudio() const2388 bool TestRunner::ShouldDumpAsAudio() const {
2389 return dump_as_audio_;
2390 }
2391
GetAudioData() const2392 const std::vector<uint8_t>& TestRunner::GetAudioData() const {
2393 return audio_data_;
2394 }
2395
IsRecursiveLayoutDumpRequested()2396 bool TestRunner::IsRecursiveLayoutDumpRequested() {
2397 return web_test_runtime_flags_.dump_child_frames();
2398 }
2399
CanDumpPixelsFromRenderer() const2400 bool TestRunner::CanDumpPixelsFromRenderer() const {
2401 return web_test_runtime_flags_.dump_drag_image() ||
2402 web_test_runtime_flags_.is_printing();
2403 }
2404
DumpPixelsInRenderer(content::RenderView * render_view)2405 SkBitmap TestRunner::DumpPixelsInRenderer(content::RenderView* render_view) {
2406 auto* view_proxy = static_cast<WebViewTestProxy*>(render_view);
2407 DCHECK(view_proxy->GetWebView()->MainFrame());
2408 DCHECK(CanDumpPixelsFromRenderer());
2409
2410 if (web_test_runtime_flags_.dump_drag_image()) {
2411 if (!drag_image_.isNull())
2412 return drag_image_;
2413
2414 // This means the test called dumpDragImage but did not initiate a drag.
2415 // Return a blank image so that the test fails.
2416 SkBitmap bitmap;
2417 bitmap.allocN32Pixels(1, 1);
2418 bitmap.eraseColor(0);
2419 return bitmap;
2420 }
2421
2422 blink::WebLocalFrame* frame =
2423 view_proxy->GetWebView()->MainFrame()->ToWebLocalFrame();
2424 blink::WebLocalFrame* target_frame = frame;
2425 std::string frame_name = web_test_runtime_flags_.printing_frame();
2426 if (!frame_name.empty()) {
2427 blink::WebFrame* frame_to_print =
2428 frame->FindFrameByName(blink::WebString::FromUTF8(frame_name));
2429 if (frame_to_print && frame_to_print->IsWebLocalFrame())
2430 target_frame = frame_to_print->ToWebLocalFrame();
2431 }
2432 return PrintFrameToBitmap(target_frame);
2433 }
2434
ReplicateWebTestRuntimeFlagsChanges(const base::DictionaryValue & changed_values)2435 void TestRunner::ReplicateWebTestRuntimeFlagsChanges(
2436 const base::DictionaryValue& changed_values) {
2437 if (!test_is_running_)
2438 return;
2439
2440 web_test_runtime_flags_.tracked_dictionary().ApplyUntrackedChanges(
2441 changed_values);
2442 }
2443
HasCustomTextDump(std::string * custom_text_dump) const2444 bool TestRunner::HasCustomTextDump(std::string* custom_text_dump) const {
2445 if (ShouldDumpAsCustomText()) {
2446 *custom_text_dump = CustomDumpText();
2447 return true;
2448 }
2449
2450 return false;
2451 }
2452
ShouldDumpFrameLoadCallbacks() const2453 bool TestRunner::ShouldDumpFrameLoadCallbacks() const {
2454 return test_is_running_ &&
2455 web_test_runtime_flags_.dump_frame_load_callbacks();
2456 }
2457
SetShouldDumpFrameLoadCallbacks(bool value)2458 void TestRunner::SetShouldDumpFrameLoadCallbacks(bool value) {
2459 web_test_runtime_flags_.set_dump_frame_load_callbacks(value);
2460 OnWebTestRuntimeFlagsChanged();
2461 }
2462
ShouldDumpPingLoaderCallbacks() const2463 bool TestRunner::ShouldDumpPingLoaderCallbacks() const {
2464 return test_is_running_ &&
2465 web_test_runtime_flags_.dump_ping_loader_callbacks();
2466 }
2467
ShouldDumpUserGestureInFrameLoadCallbacks() const2468 bool TestRunner::ShouldDumpUserGestureInFrameLoadCallbacks() const {
2469 return test_is_running_ &&
2470 web_test_runtime_flags_.dump_user_gesture_in_frame_load_callbacks();
2471 }
2472
ShouldDumpTitleChanges() const2473 bool TestRunner::ShouldDumpTitleChanges() const {
2474 return web_test_runtime_flags_.dump_title_changes();
2475 }
2476
ShouldDumpIconChanges() const2477 bool TestRunner::ShouldDumpIconChanges() const {
2478 return web_test_runtime_flags_.dump_icon_changes();
2479 }
2480
ShouldDumpCreateView() const2481 bool TestRunner::ShouldDumpCreateView() const {
2482 return web_test_runtime_flags_.dump_create_view();
2483 }
2484
CanOpenWindows() const2485 bool TestRunner::CanOpenWindows() const {
2486 return web_test_runtime_flags_.can_open_windows();
2487 }
2488
GetWebContentSettings()2489 blink::WebContentSettingsClient* TestRunner::GetWebContentSettings() {
2490 return &test_content_settings_client_;
2491 }
2492
ShouldDumpBackForwardList() const2493 bool TestRunner::ShouldDumpBackForwardList() const {
2494 return dump_back_forward_list_;
2495 }
2496
ShouldWaitUntilExternalURLLoad() const2497 bool TestRunner::ShouldWaitUntilExternalURLLoad() const {
2498 return web_test_runtime_flags_.wait_until_external_url_load();
2499 }
2500
HttpHeadersToClear() const2501 const std::set<std::string>* TestRunner::HttpHeadersToClear() const {
2502 return &http_headers_to_clear_;
2503 }
2504
ClearReferrer() const2505 bool TestRunner::ClearReferrer() const {
2506 return clear_referrer_;
2507 }
2508
AddLoadingFrame(blink::WebFrame * frame)2509 void TestRunner::AddLoadingFrame(blink::WebFrame* frame) {
2510 // Don't track loading the about:blank between tests
2511 if (!test_is_running_)
2512 return;
2513
2514 if (loading_frames_.empty()) {
2515 // Don't do anything if another renderer process is already tracking the
2516 // loading frames.
2517 if (web_test_runtime_flags_.have_loading_frame())
2518 return;
2519 web_test_runtime_flags_.set_have_loading_frame(true);
2520 OnWebTestRuntimeFlagsChanged();
2521 }
2522
2523 loading_frames_.push_back(frame);
2524 frame_will_start_load_ = false;
2525 }
2526
RemoveLoadingFrame(blink::WebFrame * frame)2527 void TestRunner::RemoveLoadingFrame(blink::WebFrame* frame) {
2528 // We don't track frames that were started between tests.
2529 if (!base::Contains(loading_frames_, frame))
2530 return;
2531
2532 // We had a DCHECK checking
2533 // web_test_runtime_flags_.have_loading_frame() here, but that led to
2534 // flakiness due to inconsistent state management across renderers.
2535 // See https://crbug.com/1100223 for details.
2536
2537 base::Erase(loading_frames_, frame);
2538 if (!loading_frames_.empty())
2539 return;
2540
2541 web_test_runtime_flags_.set_have_loading_frame(false);
2542
2543 // Loads in between tests should not propel us into thinking that we're now
2544 // inside the test. |main_frame_loaded_| set below is used to signal that the
2545 // test has definitely started executing.
2546 if (!test_is_running_)
2547 return;
2548
2549 main_frame_loaded_ = true;
2550 OnWebTestRuntimeFlagsChanged();
2551
2552 // No more new work after the first complete load.
2553 work_queue_.set_frozen(true);
2554 work_queue_.OnStatesChanged();
2555
2556 // Inform the work queue that any load it started is done, in case it is
2557 // still inside ProcessWorkItem().
2558 work_queue_.set_loading(false);
2559
2560 // testRunner.waitUntilDone() will pause the work queue if it is being used by
2561 // the test, until testRunner.notifyDone() is called. However this can only be
2562 // done once.
2563 if (!web_test_runtime_flags_.wait_until_done() || did_notify_done_)
2564 work_queue_.RequestWork();
2565 }
2566
OnFrameDeactivated(WebFrameTestProxy * frame)2567 void TestRunner::OnFrameDeactivated(WebFrameTestProxy* frame) {
2568 if (!test_is_running_)
2569 return;
2570
2571 DCHECK(frame->IsMainFrame());
2572 RemoveMainFrame(frame);
2573 RemoveRenderView(frame->GetWebViewTestProxy());
2574
2575 if (frame->GetWebFrame()->IsLoading())
2576 RemoveLoadingFrame(frame->GetWebFrame());
2577 }
2578
OnFrameReactivated(WebFrameTestProxy * frame)2579 void TestRunner::OnFrameReactivated(WebFrameTestProxy* frame) {
2580 if (!test_is_running_)
2581 return;
2582
2583 DCHECK(frame->IsMainFrame());
2584
2585 if (frame->GetWebFrame()->IsLoading()) {
2586 AddLoadingFrame(frame->GetWebFrame());
2587 }
2588
2589 // A WorkQueueItem that navigates reports that it will start a load, but when
2590 // a frame comes from the back/forward cache, it is already loaded so
2591 // AddLoadingFrame() will not occur. This informs the system that the load is
2592 // complete, or will in fact not start so that the TestRunner does not wait
2593 // for this frame to end the test. At this point the frame has already had a
2594 // chance to run script and insert further WorkQueueItems or other state that
2595 // would delay ending the test, if it wished to.
2596 frame_will_start_load_ = false;
2597
2598 AddMainFrame(frame);
2599 WebViewTestProxy* view_proxy = frame->GetWebViewTestProxy();
2600 AddRenderView(view_proxy);
2601 if (view_proxy->is_main_window()) {
2602 work_queue_.RequestWork();
2603 }
2604 }
2605
FinishTestIfReady()2606 void TestRunner::FinishTestIfReady() {
2607 if (!test_is_running_)
2608 return;
2609
2610 // We don't end the test before the main frame has had a chance to load. This
2611 // is used to ensure the main frame has had a chance to start loading. If the
2612 // test calls testRunner.notifyDone() then we also know it has begun loading.
2613 if (!main_frame_loaded_ && !did_notify_done_)
2614 return;
2615
2616 // While loading any frames, we do not end the test.
2617 // The |frame_will_start_load_| bool is used for when the work queue has
2618 // started a load, but it is not in |loading_frames_| yet as there is some
2619 // time between them. We also have to check |loading_frames_| for once the
2620 // loading is started, and because the test may start a load in other ways
2621 // besides the work queue.
2622 if (frame_will_start_load_ || !loading_frames_.empty())
2623 return;
2624
2625 // If there are tasks in the queue still, we must wait for them before
2626 // finishing the test.
2627 if (work_queue_.has_items())
2628 return;
2629
2630 // If waiting for testRunner.notifyDone() then we can not end the test.
2631 if (web_test_runtime_flags_.wait_until_done() && !did_notify_done_)
2632 return;
2633
2634 FinishTest();
2635 }
2636
TestFinishedFromSecondaryRenderer()2637 void TestRunner::TestFinishedFromSecondaryRenderer() {
2638 NotifyDone();
2639 }
2640
ResetRendererAfterWebTest(base::OnceClosure done_callback)2641 void TestRunner::ResetRendererAfterWebTest(base::OnceClosure done_callback) {
2642 // Instead of resetting for the next test here, delay until after the
2643 // navigation to about:blank, which is heard about in in
2644 // `DidCommitNavigationInMainFrame()`. This ensures we reset settings that are
2645 // set between now and the load of about:blank, and that no new changes or
2646 // loads can be started by the renderer.
2647 waiting_for_reset_navigation_to_about_blank_ = std::move(done_callback);
2648
2649 // TODO(danakj): Move this navigation to the browser.
2650 blink::WebURLRequest request{GURL(url::kAboutBlankURL)};
2651 request.SetMode(network::mojom::RequestMode::kNavigate);
2652 request.SetRedirectMode(network::mojom::RedirectMode::kManual);
2653 request.SetRequestContext(blink::mojom::RequestContextType::INTERNAL);
2654 request.SetRequestorOrigin(blink::WebSecurityOrigin::CreateUniqueOpaque());
2655
2656 WebFrameTestProxy* main_frame = FindInProcessMainWindowMainFrame();
2657 DCHECK(main_frame);
2658 main_frame->GetWebFrame()->StartNavigation(request);
2659 }
2660
DidCommitNavigationInMainFrame(WebFrameTestProxy * main_frame)2661 void TestRunner::DidCommitNavigationInMainFrame(WebFrameTestProxy* main_frame) {
2662 // This method is just meant to catch the about:blank navigation started in
2663 // ResetRendererAfterWebTest().
2664 if (!waiting_for_reset_navigation_to_about_blank_)
2665 return;
2666
2667 // This would mean some other navigation was already happening when the test
2668 // ended, the about:blank should still be coming.
2669 GURL url = main_frame->GetWebFrame()->GetDocumentLoader()->GetUrl();
2670 if (!url.IsAboutBlank())
2671 return;
2672
2673 // Perform the reset now that the main frame is on about:blank.
2674 main_frame->Reset();
2675 Reset();
2676
2677 // Ack to the browser.
2678 std::move(waiting_for_reset_navigation_to_about_blank_).Run();
2679 }
2680
AddMainFrame(WebFrameTestProxy * frame)2681 void TestRunner::AddMainFrame(WebFrameTestProxy* frame) {
2682 main_frames_.insert(frame);
2683 }
2684
RemoveMainFrame(WebFrameTestProxy * frame)2685 void TestRunner::RemoveMainFrame(WebFrameTestProxy* frame) {
2686 main_frames_.erase(frame);
2687 }
2688
AddRenderView(WebViewTestProxy * view)2689 void TestRunner::AddRenderView(WebViewTestProxy* view) {
2690 render_views_.insert(view);
2691 }
2692
RemoveRenderView(WebViewTestProxy * view)2693 void TestRunner::RemoveRenderView(WebViewTestProxy* view) {
2694 render_views_.erase(view);
2695 }
2696
PolicyDelegateDone()2697 void TestRunner::PolicyDelegateDone() {
2698 DCHECK(web_test_runtime_flags_.wait_until_done());
2699 FinishTest();
2700 }
2701
PolicyDelegateEnabled() const2702 bool TestRunner::PolicyDelegateEnabled() const {
2703 return web_test_runtime_flags_.policy_delegate_enabled();
2704 }
2705
PolicyDelegateIsPermissive() const2706 bool TestRunner::PolicyDelegateIsPermissive() const {
2707 return web_test_runtime_flags_.policy_delegate_is_permissive();
2708 }
2709
PolicyDelegateShouldNotifyDone() const2710 bool TestRunner::PolicyDelegateShouldNotifyDone() const {
2711 return web_test_runtime_flags_.policy_delegate_should_notify_done();
2712 }
2713
SetDragImage(const SkBitmap & drag_image)2714 void TestRunner::SetDragImage(const SkBitmap& drag_image) {
2715 if (web_test_runtime_flags_.dump_drag_image()) {
2716 if (drag_image_.isNull())
2717 drag_image_ = drag_image;
2718 }
2719 }
2720
ShouldDumpNavigationPolicy() const2721 bool TestRunner::ShouldDumpNavigationPolicy() const {
2722 return web_test_runtime_flags_.dump_navigation_policy();
2723 }
2724
FindInProcessMainWindowMainFrame()2725 WebFrameTestProxy* TestRunner::FindInProcessMainWindowMainFrame() {
2726 for (WebFrameTestProxy* main_frame : main_frames_) {
2727 WebViewTestProxy* view = main_frame->GetWebViewTestProxy();
2728 DCHECK_EQ(view->GetMainRenderFrame(), main_frame);
2729 if (view->is_main_window())
2730 return main_frame;
2731 }
2732 return nullptr;
2733 }
2734
WaitUntilDone()2735 void TestRunner::WaitUntilDone() {
2736 web_test_runtime_flags_.set_wait_until_done(true);
2737 OnWebTestRuntimeFlagsChanged();
2738 }
2739
NotifyDone()2740 void TestRunner::NotifyDone() {
2741 if (!web_test_runtime_flags_.wait_until_done())
2742 return;
2743 if (did_notify_done_)
2744 return;
2745
2746 // Mark that the test has asked the test to end when the rest of our stopping
2747 // conditions are met. Then check if we can end the test.
2748 did_notify_done_ = true;
2749 FinishTestIfReady();
2750 }
2751
QueueBackNavigation(int how_far_back)2752 void TestRunner::QueueBackNavigation(int how_far_back) {
2753 work_queue_.AddWork(mojom::WorkItem::NewBackForward(
2754 mojom::WorkItemBackForward::New(-how_far_back)));
2755 }
2756
QueueForwardNavigation(int how_far_forward)2757 void TestRunner::QueueForwardNavigation(int how_far_forward) {
2758 work_queue_.AddWork(mojom::WorkItem::NewBackForward(
2759 mojom::WorkItemBackForward::New(how_far_forward)));
2760 }
2761
QueueReload()2762 void TestRunner::QueueReload() {
2763 work_queue_.AddWork(mojom::WorkItem::NewReload(mojom::WorkItemReload::New()));
2764 }
2765
QueueLoadingScript(const std::string & script)2766 void TestRunner::QueueLoadingScript(const std::string& script) {
2767 work_queue_.AddWork(mojom::WorkItem::NewLoadingScript(
2768 mojom::WorkItemLoadingScript::New(script)));
2769 }
2770
QueueNonLoadingScript(const std::string & script)2771 void TestRunner::QueueNonLoadingScript(const std::string& script) {
2772 work_queue_.AddWork(mojom::WorkItem::NewNonLoadingScript(
2773 mojom::WorkItemNonLoadingScript::New(script)));
2774 }
2775
QueueLoad(const GURL & current_url,const std::string & relative_url,const std::string & target)2776 void TestRunner::QueueLoad(const GURL& current_url,
2777 const std::string& relative_url,
2778 const std::string& target) {
2779 GURL full_url = current_url.Resolve(relative_url);
2780 work_queue_.AddWork(mojom::WorkItem::NewLoad(
2781 mojom::WorkItemLoad::New(full_url.spec(), target)));
2782 }
2783
ProcessWorkItem(mojom::WorkItemPtr work_item)2784 void TestRunner::ProcessWorkItem(mojom::WorkItemPtr work_item) {
2785 work_queue_.ProcessWorkItem(std::move(work_item));
2786 }
2787
ReplicateWorkQueueStates(const base::DictionaryValue & values)2788 void TestRunner::ReplicateWorkQueueStates(const base::DictionaryValue& values) {
2789 if (!test_is_running_)
2790 return;
2791 work_queue_.ReplicateStates(values);
2792 }
2793
OnTestPreferencesChanged(const TestPreferences & test_prefs,RenderFrame * frame)2794 void TestRunner::OnTestPreferencesChanged(const TestPreferences& test_prefs,
2795 RenderFrame* frame) {
2796 RenderView* render_view = frame->GetRenderView();
2797 blink::web_pref::WebPreferences web_prefs =
2798 render_view->GetBlinkPreferences();
2799
2800 // Turns the TestPreferences into WebPreferences.
2801 ExportWebTestSpecificPreferences(test_prefs, &web_prefs);
2802
2803 render_view->SetBlinkPreferences(web_prefs);
2804
2805 GetWebTestControlHostRemote()->OverridePreferences(web_prefs);
2806 }
2807
SetCustomPolicyDelegate(gin::Arguments * args)2808 void TestRunner::SetCustomPolicyDelegate(gin::Arguments* args) {
2809 bool value;
2810 args->GetNext(&value);
2811 web_test_runtime_flags_.set_policy_delegate_enabled(value);
2812
2813 if (!args->PeekNext().IsEmpty() && args->PeekNext()->IsBoolean()) {
2814 args->GetNext(&value);
2815 web_test_runtime_flags_.set_policy_delegate_is_permissive(value);
2816 }
2817
2818 OnWebTestRuntimeFlagsChanged();
2819 }
2820
WaitForPolicyDelegate()2821 void TestRunner::WaitForPolicyDelegate() {
2822 web_test_runtime_flags_.set_policy_delegate_enabled(true);
2823 web_test_runtime_flags_.set_policy_delegate_should_notify_done(true);
2824 web_test_runtime_flags_.set_wait_until_done(true);
2825 OnWebTestRuntimeFlagsChanged();
2826 }
2827
InProcessWindowCount()2828 int TestRunner::InProcessWindowCount() {
2829 return main_frames_.size();
2830 }
2831
AddOriginAccessAllowListEntry(const std::string & source_origin,const std::string & destination_protocol,const std::string & destination_host,bool allow_destination_subdomains)2832 void TestRunner::AddOriginAccessAllowListEntry(
2833 const std::string& source_origin,
2834 const std::string& destination_protocol,
2835 const std::string& destination_host,
2836 bool allow_destination_subdomains) {
2837 blink::WebURL url((GURL(source_origin)));
2838 if (!url.IsValid())
2839 return;
2840
2841 blink::WebSecurityPolicy::AddOriginAccessAllowListEntry(
2842 url, blink::WebString::FromUTF8(destination_protocol),
2843 blink::WebString::FromUTF8(destination_host), /*destination_port=*/0,
2844 allow_destination_subdomains
2845 ? network::mojom::CorsDomainMatchMode::kAllowSubdomains
2846 : network::mojom::CorsDomainMatchMode::kDisallowSubdomains,
2847 network::mojom::CorsPortMatchMode::kAllowAnyPort,
2848 network::mojom::CorsOriginAccessMatchPriority::kDefaultPriority);
2849 }
2850
SetTextSubpixelPositioning(bool value)2851 void TestRunner::SetTextSubpixelPositioning(bool value) {
2852 #if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_FUCHSIA)
2853 // Since FontConfig doesn't provide a variable to control subpixel
2854 // positioning, we'll fall back to setting it globally for all fonts.
2855 blink::WebFontRenderStyle::SetSubpixelPositioning(value);
2856 #endif
2857 }
2858
UseUnfortunateSynchronousResizeMode()2859 void TestRunner::UseUnfortunateSynchronousResizeMode() {
2860 // Sets the resize mode on the view of each open window.
2861 for (WebViewTestProxy* view : render_views_) {
2862 view->GetWebView()->UseSynchronousResizeModeForTesting(true);
2863 }
2864 }
2865
SetMockScreenOrientation(WebViewTestProxy * view_proxy,const std::string & orientation_str)2866 void TestRunner::SetMockScreenOrientation(WebViewTestProxy* view_proxy,
2867 const std::string& orientation_str) {
2868 blink::mojom::ScreenOrientation orientation;
2869
2870 if (orientation_str == "portrait-primary") {
2871 orientation = blink::mojom::ScreenOrientation::kPortraitPrimary;
2872 } else if (orientation_str == "portrait-secondary") {
2873 orientation = blink::mojom::ScreenOrientation::kPortraitSecondary;
2874 } else if (orientation_str == "landscape-primary") {
2875 orientation = blink::mojom::ScreenOrientation::kLandscapePrimary;
2876 } else {
2877 DCHECK_EQ("landscape-secondary", orientation_str);
2878 orientation = blink::mojom::ScreenOrientation::kLandscapeSecondary;
2879 }
2880
2881 bool changed = fake_screen_orientation_impl_.UpdateDeviceOrientation(
2882 view_proxy, orientation);
2883 if (changed)
2884 GetWebTestControlHostRemote()->SetScreenOrientationChanged();
2885 }
2886
DisableMockScreenOrientation(WebViewTestProxy * view_proxy)2887 void TestRunner::DisableMockScreenOrientation(WebViewTestProxy* view_proxy) {
2888 fake_screen_orientation_impl_.SetDisabled(view_proxy, true);
2889 }
2890
GetAcceptLanguages() const2891 std::string TestRunner::GetAcceptLanguages() const {
2892 return web_test_runtime_flags_.accept_languages();
2893 }
2894
SetAcceptLanguages(const std::string & accept_languages)2895 void TestRunner::SetAcceptLanguages(const std::string& accept_languages) {
2896 if (accept_languages == GetAcceptLanguages())
2897 return;
2898
2899 // TODO(danakj): IPC to WebTestControlHost, and have it change the
2900 // WebContentsImpl::GetMutableRendererPrefs(). Then have the browser sync that
2901 // to the window's RenderViews, instead of using WebTestRuntimeFlags for this.
2902 // Then also get rid of |render_views_|.
2903 web_test_runtime_flags_.set_accept_languages(accept_languages);
2904 OnWebTestRuntimeFlagsChanged();
2905
2906 for (WebViewTestProxy* view : render_views_)
2907 view->GetWebView()->AcceptLanguagesChanged();
2908 }
2909
DumpEditingCallbacks()2910 void TestRunner::DumpEditingCallbacks() {
2911 web_test_runtime_flags_.set_dump_editting_callbacks(true);
2912 OnWebTestRuntimeFlagsChanged();
2913 }
2914
DumpAsMarkup()2915 void TestRunner::DumpAsMarkup() {
2916 web_test_runtime_flags_.set_dump_as_markup(true);
2917 web_test_runtime_flags_.set_generate_pixel_results(false);
2918 OnWebTestRuntimeFlagsChanged();
2919 }
2920
DumpAsText()2921 void TestRunner::DumpAsText() {
2922 web_test_runtime_flags_.set_dump_as_text(true);
2923 web_test_runtime_flags_.set_generate_pixel_results(false);
2924 OnWebTestRuntimeFlagsChanged();
2925 }
2926
DumpAsTextWithPixelResults()2927 void TestRunner::DumpAsTextWithPixelResults() {
2928 web_test_runtime_flags_.set_dump_as_text(true);
2929 web_test_runtime_flags_.set_generate_pixel_results(true);
2930 OnWebTestRuntimeFlagsChanged();
2931 }
2932
DumpAsLayout()2933 void TestRunner::DumpAsLayout() {
2934 web_test_runtime_flags_.set_dump_as_layout(true);
2935 web_test_runtime_flags_.set_generate_pixel_results(false);
2936 OnWebTestRuntimeFlagsChanged();
2937 }
2938
DumpAsLayoutWithPixelResults()2939 void TestRunner::DumpAsLayoutWithPixelResults() {
2940 web_test_runtime_flags_.set_dump_as_layout(true);
2941 web_test_runtime_flags_.set_generate_pixel_results(true);
2942 OnWebTestRuntimeFlagsChanged();
2943 }
2944
DumpChildFrames()2945 void TestRunner::DumpChildFrames() {
2946 web_test_runtime_flags_.set_dump_child_frames(true);
2947 OnWebTestRuntimeFlagsChanged();
2948 }
2949
DumpIconChanges()2950 void TestRunner::DumpIconChanges() {
2951 web_test_runtime_flags_.set_dump_icon_changes(true);
2952 OnWebTestRuntimeFlagsChanged();
2953 }
2954
SetAudioData(const gin::ArrayBufferView & view)2955 void TestRunner::SetAudioData(const gin::ArrayBufferView& view) {
2956 uint8_t* bytes = static_cast<uint8_t*>(view.bytes());
2957 audio_data_.resize(view.num_bytes());
2958 std::copy(bytes, bytes + view.num_bytes(), audio_data_.begin());
2959 dump_as_audio_ = true;
2960 }
2961
DumpFrameLoadCallbacks()2962 void TestRunner::DumpFrameLoadCallbacks() {
2963 web_test_runtime_flags_.set_dump_frame_load_callbacks(true);
2964 OnWebTestRuntimeFlagsChanged();
2965 }
2966
DumpPingLoaderCallbacks()2967 void TestRunner::DumpPingLoaderCallbacks() {
2968 web_test_runtime_flags_.set_dump_ping_loader_callbacks(true);
2969 OnWebTestRuntimeFlagsChanged();
2970 }
2971
DumpUserGestureInFrameLoadCallbacks()2972 void TestRunner::DumpUserGestureInFrameLoadCallbacks() {
2973 web_test_runtime_flags_.set_dump_user_gesture_in_frame_load_callbacks(true);
2974 OnWebTestRuntimeFlagsChanged();
2975 }
2976
DumpTitleChanges()2977 void TestRunner::DumpTitleChanges() {
2978 web_test_runtime_flags_.set_dump_title_changes(true);
2979 OnWebTestRuntimeFlagsChanged();
2980 }
2981
DumpCreateView()2982 void TestRunner::DumpCreateView() {
2983 web_test_runtime_flags_.set_dump_create_view(true);
2984 OnWebTestRuntimeFlagsChanged();
2985 }
2986
SetCanOpenWindows()2987 void TestRunner::SetCanOpenWindows() {
2988 web_test_runtime_flags_.set_can_open_windows(true);
2989 OnWebTestRuntimeFlagsChanged();
2990 }
2991
SetImagesAllowed(bool allowed)2992 void TestRunner::SetImagesAllowed(bool allowed) {
2993 web_test_runtime_flags_.set_images_allowed(allowed);
2994 OnWebTestRuntimeFlagsChanged();
2995 }
2996
SetScriptsAllowed(bool allowed)2997 void TestRunner::SetScriptsAllowed(bool allowed) {
2998 web_test_runtime_flags_.set_scripts_allowed(allowed);
2999 OnWebTestRuntimeFlagsChanged();
3000 }
3001
SetStorageAllowed(bool allowed)3002 void TestRunner::SetStorageAllowed(bool allowed) {
3003 web_test_runtime_flags_.set_storage_allowed(allowed);
3004 OnWebTestRuntimeFlagsChanged();
3005 }
3006
SetAllowRunningOfInsecureContent(bool allowed)3007 void TestRunner::SetAllowRunningOfInsecureContent(bool allowed) {
3008 web_test_runtime_flags_.set_running_insecure_content_allowed(allowed);
3009 OnWebTestRuntimeFlagsChanged();
3010 }
3011
DumpPermissionClientCallbacks()3012 void TestRunner::DumpPermissionClientCallbacks() {
3013 web_test_runtime_flags_.set_dump_web_content_settings_client_callbacks(true);
3014 OnWebTestRuntimeFlagsChanged();
3015 }
3016
DumpBackForwardList()3017 void TestRunner::DumpBackForwardList() {
3018 dump_back_forward_list_ = true;
3019 }
3020
DumpSelectionRect()3021 void TestRunner::DumpSelectionRect() {
3022 web_test_runtime_flags_.set_dump_selection_rect(true);
3023 OnWebTestRuntimeFlagsChanged();
3024 }
3025
SetPrinting()3026 void TestRunner::SetPrinting() {
3027 SetPrintingForFrame("");
3028 }
3029
SetPrintingForFrame(const std::string & frame_name)3030 void TestRunner::SetPrintingForFrame(const std::string& frame_name) {
3031 web_test_runtime_flags_.set_printing_frame(frame_name);
3032 web_test_runtime_flags_.set_is_printing(true);
3033 OnWebTestRuntimeFlagsChanged();
3034 }
3035
SetShouldStayOnPageAfterHandlingBeforeUnload(bool value)3036 void TestRunner::SetShouldStayOnPageAfterHandlingBeforeUnload(bool value) {
3037 web_test_runtime_flags_.set_stay_on_page_after_handling_before_unload(value);
3038 OnWebTestRuntimeFlagsChanged();
3039 }
3040
SetWillSendRequestClearHeader(const std::string & header)3041 void TestRunner::SetWillSendRequestClearHeader(const std::string& header) {
3042 if (!header.empty())
3043 http_headers_to_clear_.insert(header);
3044 }
3045
SetWillSendRequestClearReferrer()3046 void TestRunner::SetWillSendRequestClearReferrer() {
3047 clear_referrer_ = true;
3048 }
3049
WaitUntilExternalURLLoad()3050 void TestRunner::WaitUntilExternalURLLoad() {
3051 web_test_runtime_flags_.set_wait_until_external_url_load(true);
3052 web_test_runtime_flags_.set_wait_until_done(true);
3053 OnWebTestRuntimeFlagsChanged();
3054 }
3055
DumpDragImage()3056 void TestRunner::DumpDragImage() {
3057 web_test_runtime_flags_.set_dump_drag_image(true);
3058 DumpAsTextWithPixelResults();
3059 OnWebTestRuntimeFlagsChanged();
3060 }
3061
DumpNavigationPolicy()3062 void TestRunner::DumpNavigationPolicy() {
3063 web_test_runtime_flags_.set_dump_navigation_policy(true);
3064 OnWebTestRuntimeFlagsChanged();
3065 }
3066
SetDumpConsoleMessages(bool value)3067 void TestRunner::SetDumpConsoleMessages(bool value) {
3068 web_test_runtime_flags_.set_dump_console_messages(value);
3069 OnWebTestRuntimeFlagsChanged();
3070 }
3071
SetIsWebPlatformTestsMode()3072 void TestRunner::SetIsWebPlatformTestsMode() {
3073 web_test_runtime_flags_.set_is_web_platform_tests_mode(true);
3074 OnWebTestRuntimeFlagsChanged();
3075 }
3076
IsWebPlatformTestsMode() const3077 bool TestRunner::IsWebPlatformTestsMode() const {
3078 return web_test_runtime_flags_.is_web_platform_tests_mode();
3079 }
3080
SetDumpJavaScriptDialogs(bool value)3081 void TestRunner::SetDumpJavaScriptDialogs(bool value) {
3082 web_test_runtime_flags_.set_dump_javascript_dialogs(value);
3083 OnWebTestRuntimeFlagsChanged();
3084 }
3085
SetEffectiveConnectionType(blink::WebEffectiveConnectionType connection_type)3086 void TestRunner::SetEffectiveConnectionType(
3087 blink::WebEffectiveConnectionType connection_type) {
3088 effective_connection_type_ = connection_type;
3089 }
3090
ShouldDumpConsoleMessages() const3091 bool TestRunner::ShouldDumpConsoleMessages() const {
3092 // Once TestFinished() is entered, we don't want additional log lines to
3093 // be printed while we collect the renderer-side test results, so we check
3094 // |test_is_running_| here as well.
3095 return test_is_running_ && web_test_runtime_flags_.dump_console_messages();
3096 }
3097
GoToOffset(int offset)3098 void TestRunner::GoToOffset(int offset) {
3099 GetWebTestControlHostRemote()->GoToOffset(offset);
3100 }
3101
Reload()3102 void TestRunner::Reload() {
3103 GetWebTestControlHostRemote()->Reload();
3104 }
3105
LoadURLForFrame(const GURL & url,const std::string & frame_name)3106 void TestRunner::LoadURLForFrame(const GURL& url,
3107 const std::string& frame_name) {
3108 GetWebTestControlHostRemote()->LoadURLForFrame(url, frame_name);
3109 }
3110
PrintMessage(const std::string & message)3111 void TestRunner::PrintMessage(const std::string& message) {
3112 GetWebTestControlHostRemote()->PrintMessage(message);
3113 }
3114
PrintMessageToStderr(const std::string & message)3115 void TestRunner::PrintMessageToStderr(const std::string& message) {
3116 GetWebTestControlHostRemote()->PrintMessageToStderr(message);
3117 }
3118
RegisterIsolatedFileSystem(const std::vector<base::FilePath> & file_paths)3119 blink::WebString TestRunner::RegisterIsolatedFileSystem(
3120 const std::vector<base::FilePath>& file_paths) {
3121 std::string filesystem_id;
3122 GetWebTestControlHostRemote()->RegisterIsolatedFileSystem(file_paths,
3123 &filesystem_id);
3124 return blink::WebString::FromUTF8(filesystem_id);
3125 }
3126
FocusWindow(RenderFrame * main_frame,bool focus)3127 void TestRunner::FocusWindow(RenderFrame* main_frame, bool focus) {
3128 // Early out instead of CHECK() to avoid poking the fuzzer bear.
3129 if (!main_frame->IsMainFrame())
3130 return;
3131
3132 auto* frame_proxy = static_cast<WebFrameTestProxy*>(main_frame);
3133 RenderWidget* widget = frame_proxy->GetLocalRootRenderWidget();
3134
3135 // Web tests get multiple windows in one renderer by doing same-site
3136 // window.open() calls (or about:blank). They want to be able to move focus
3137 // between those windows synchronously in the renderer, which is what we
3138 // do here. We only allow it to focus main frames however, for simplicitly.
3139
3140 if (!focus) {
3141 // This path simulates losing focus on the window, without moving it to
3142 // another window.
3143 if (widget->GetWebWidget()->HasFocus()) {
3144 auto* view_proxy = frame_proxy->GetWebViewTestProxy();
3145 // TODO(dtapuska): We should call the exact IPC the browser
3146 // calls. ie. WebFrameWidgetBase::SetActive but that isn't
3147 // exposed outside of blink.
3148 view_proxy->GetWebView()->SetIsActive(false);
3149 widget->GetWebWidget()->SetFocus(false);
3150 }
3151 return;
3152 }
3153
3154 // Find the currently focused window, and remove its focus.
3155 for (WebFrameTestProxy* other_main_frame : main_frames_) {
3156 if (other_main_frame != main_frame) {
3157 RenderWidget* other_widget = other_main_frame->GetLocalRootRenderWidget();
3158 if (other_widget->GetWebWidget()->HasFocus()) {
3159 auto* other_view_proxy = other_main_frame->GetWebViewTestProxy();
3160 // TODO(dtapuska): We should call the exact IPC the browser
3161 // calls. ie. WebFrameWidgetBase::SetActive but that isn't
3162 // exposed outside of blink.
3163 other_view_proxy->GetWebView()->SetIsActive(false);
3164 other_widget->GetWebWidget()->SetFocus(false);
3165 }
3166 }
3167 }
3168
3169 if (!widget->GetWebWidget()->HasFocus()) {
3170 widget->GetWebWidget()->SetFocus(true);
3171 }
3172 }
3173
SetAnimationRequiresRaster(bool do_raster)3174 void TestRunner::SetAnimationRequiresRaster(bool do_raster) {
3175 animation_requires_raster_ = do_raster;
3176 }
3177
OnWebTestRuntimeFlagsChanged()3178 void TestRunner::OnWebTestRuntimeFlagsChanged() {
3179 // Ignore changes that happen before we got the initial, accumulated
3180 // web flag changes in SetTestConfiguration().
3181 if (!test_is_running_)
3182 return;
3183 if (web_test_runtime_flags_.tracked_dictionary().changed_values().empty())
3184 return;
3185
3186 GetWebTestControlHostRemote()->WebTestRuntimeFlagsChanged(
3187 web_test_runtime_flags_.tracked_dictionary().changed_values().Clone());
3188
3189 web_test_runtime_flags_.tracked_dictionary().ResetChangeTracking();
3190 }
3191
FinishTest()3192 void TestRunner::FinishTest() {
3193 WebFrameTestProxy* main_frame = FindInProcessMainWindowMainFrame();
3194
3195 // When there are no more frames loading, and the test hasn't asked to wait
3196 // for NotifyDone(), then we normally conclude the test. However if this
3197 // TestRunner is attached to a swapped out frame tree - that is, the main
3198 // frame is in another frame tree - then finishing here would be premature
3199 // for the main frame where the test is running. If |did_notify_done_| is
3200 // true then we *were* waiting for NotifyDone() and it has already happened,
3201 // so we want to proceed as if the NotifyDone() is happening now.
3202 //
3203 // Ideally, the main frame would wait for loading frames in its frame tree
3204 // as well as any secondary renderers, but it does not know about secondary
3205 // renderers. So in this case the test should finish when frames finish
3206 // loading in the primary renderer, and we don't finish the test from a
3207 // secondary renderer unless it is asked for explicitly via NotifyDone.
3208 //
3209 // This will bounce through the browser to the renderer process hosting the
3210 // main window's main frame. There it will come back to this method, but hit
3211 // the other path.
3212 if (!main_frame) {
3213 if (did_notify_done_)
3214 GetWebTestControlHostRemote()->TestFinishedInSecondaryRenderer();
3215 return;
3216 }
3217
3218 // Avoid a situation where TestFinished is called twice, because
3219 // of a racey test where multiple renderers call notifyDone(), or a test that
3220 // calls notifyDone() more than once.
3221 if (!test_is_running_)
3222 return;
3223 test_is_running_ = false;
3224
3225 // Now we know that we're in the main frame, we should generate dump results.
3226 // Clean out the lifecycle if needed before capturing the web tree
3227 // dump and pixels from the compositor.
3228 auto* web_frame = main_frame->GetWebFrame();
3229 web_frame->FrameWidget()->UpdateAllLifecyclePhases(
3230 blink::DocumentUpdateReason::kTest);
3231
3232 const mojom::WebTestRunTestConfiguration& test_config =
3233 main_frame->GetWebViewTestProxy()->test_config();
3234
3235 // Initialize a new dump results object which we will populate in the calls
3236 // below.
3237 auto dump_result = mojom::WebTestRendererDumpResult::New();
3238
3239 bool browser_should_dump_back_forward_list = ShouldDumpBackForwardList();
3240 bool browser_should_dump_pixels = false;
3241
3242 if (ShouldDumpAsAudio()) {
3243 TRACE_EVENT0("shell", "TestRunner::CaptureLocalAudioDump");
3244 dump_result->audio = GetAudioData();
3245 } else {
3246 TextResultType text_result_type = ShouldGenerateTextResults();
3247 bool pixel_result = ShouldGeneratePixelResults();
3248
3249 std::string spec = GURL(test_config.test_url).spec();
3250 size_t path_start = spec.rfind("web_tests/");
3251 if (path_start != std::string::npos)
3252 spec = spec.substr(path_start);
3253
3254 std::string mime_type =
3255 web_frame->GetDocumentLoader()->GetResponse().MimeType().Utf8();
3256
3257 // In a text/plain document, and in a dumpAsText/ subdirectory, we generate
3258 // text results no matter what the test may previously have requested.
3259 if (mime_type == "text/plain" ||
3260 spec.find("/dumpAsText/") != std::string::npos) {
3261 text_result_type = TextResultType::kText;
3262 pixel_result = false;
3263 }
3264
3265 // If possible we grab the layout dump locally because a round trip through
3266 // the browser would give javascript a chance to run and change the layout.
3267 // We only go to the browser if we can not do it locally, because we want to
3268 // dump more than just the local main frame. Those tests must be written to
3269 // not modify layout after signalling the test is finished.
3270 //
3271 // The CustomTextDump always takes precedence if it's been specified by the
3272 // test.
3273 std::string custom_text_dump;
3274 if (HasCustomTextDump(&custom_text_dump)) {
3275 dump_result->layout = custom_text_dump + "\n";
3276 } else if (!IsRecursiveLayoutDumpRequested()) {
3277 TRACE_EVENT0("shell", "TestRunner::CaptureLocalLayoutDump");
3278 dump_result->layout = DumpLayoutAsString(web_frame, text_result_type);
3279 }
3280
3281 if (pixel_result) {
3282 if (CanDumpPixelsFromRenderer()) {
3283 TRACE_EVENT0("shell", "TestRunner::CaptureLocalPixelsDump");
3284 SkBitmap actual =
3285 DumpPixelsInRenderer(main_frame->GetWebViewTestProxy());
3286 DCHECK_GT(actual.info().width(), 0);
3287 DCHECK_GT(actual.info().height(), 0);
3288
3289 base::MD5Digest digest;
3290 base::MD5Sum(actual.getPixels(), actual.computeByteSize(), &digest);
3291 dump_result->actual_pixel_hash = base::MD5DigestToBase16(digest);
3292
3293 if (dump_result->actual_pixel_hash != test_config.expected_pixel_hash)
3294 dump_result->pixels = std::move(actual);
3295 } else {
3296 browser_should_dump_pixels = true;
3297 if (ShouldDumpSelectionRect()) {
3298 TRACE_EVENT0("shell", "TestRunner::CaptureLocalSelectionRect");
3299 dump_result->selection_rect =
3300 web_frame->GetSelectionBoundsRectForTesting();
3301 }
3302 }
3303 }
3304 }
3305
3306 // Informs the browser that the test is done, passing along any test results
3307 // that have been generated locally. The browser may collect further results
3308 // from this and other renderer processes before moving on to the next test.
3309 GetWebTestControlHostRemote()->InitiateCaptureDump(
3310 std::move(dump_result), browser_should_dump_back_forward_list,
3311 browser_should_dump_pixels);
3312 }
3313
3314 mojo::AssociatedRemote<mojom::WebTestControlHost>&
GetWebTestControlHostRemote()3315 TestRunner::GetWebTestControlHostRemote() {
3316 if (!web_test_control_host_remote_) {
3317 RenderThread::Get()->GetChannel()->GetRemoteAssociatedInterface(
3318 &web_test_control_host_remote_);
3319 web_test_control_host_remote_.set_disconnect_handler(
3320 base::BindOnce(&TestRunner::HandleWebTestControlHostDisconnected,
3321 base::Unretained(this)));
3322 }
3323 return web_test_control_host_remote_;
3324 }
3325
HandleWebTestControlHostDisconnected()3326 void TestRunner::HandleWebTestControlHostDisconnected() {
3327 web_test_control_host_remote_.reset();
3328 }
3329
3330 mojom::WebTestBluetoothFakeAdapterSetter&
GetBluetoothFakeAdapterSetter()3331 TestRunner::GetBluetoothFakeAdapterSetter() {
3332 if (!bluetooth_fake_adapter_setter_) {
3333 RenderThread::Get()->BindHostReceiver(
3334 bluetooth_fake_adapter_setter_.BindNewPipeAndPassReceiver());
3335 bluetooth_fake_adapter_setter_.set_disconnect_handler(base::BindOnce(
3336 &TestRunner::HandleBluetoothFakeAdapterSetterDisconnected,
3337 base::Unretained(this)));
3338 }
3339 return *bluetooth_fake_adapter_setter_;
3340 }
3341
HandleBluetoothFakeAdapterSetterDisconnected()3342 void TestRunner::HandleBluetoothFakeAdapterSetterDisconnected() {
3343 bluetooth_fake_adapter_setter_.reset();
3344 }
3345
3346 } // namespace content
3347