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