[email protected] | 78089f0 | 2012-07-19 06:11:28 | [diff] [blame] | 1 | // Copyright (c) 2012 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/public/test/browser_test_utils.h" |
| 6 | |
avi | 652869c | 2015-12-25 01:48:45 | [diff] [blame] | 7 | #include <stddef.h> |
Lei Zhang | 6cef326 | 2017-08-16 15:44:38 | [diff] [blame] | 8 | |
| 9 | #include <set> |
tzik | 1068f1be | 2016-06-03 07:25:20 | [diff] [blame] | 10 | #include <tuple> |
dcheng | f63a125 | 2015-12-26 20:43:13 | [diff] [blame] | 11 | #include <utility> |
avi | 652869c | 2015-12-25 01:48:45 | [diff] [blame] | 12 | |
[email protected] | e7e9c86 | 2014-08-21 22:00:38 | [diff] [blame] | 13 | #include "base/bind.h" |
nick | bfaea4ee | 2016-12-02 20:59:31 | [diff] [blame] | 14 | #include "base/bind_helpers.h" |
[email protected] | 6dbb699 | 2012-07-24 18:04:54 | [diff] [blame] | 15 | #include "base/command_line.h" |
lukasza | c7d6bd3 | 2017-07-11 00:19:31 | [diff] [blame] | 16 | #include "base/guid.h" |
[email protected] | 7d478cb | 2012-07-24 17:19:42 | [diff] [blame] | 17 | #include "base/json/json_reader.h" |
[email protected] | c3c10f2 | 2013-07-25 14:21:12 | [diff] [blame] | 18 | #include "base/process/kill.h" |
Ria Jiang | 79f58ed92 | 2018-04-10 03:30:52 | [diff] [blame] | 19 | #include "base/run_loop.h" |
ahest | 29276c3 | 2017-01-19 07:36:31 | [diff] [blame] | 20 | #include "base/stl_util.h" |
rob | c72f59f3 | 2016-10-14 09:35:16 | [diff] [blame] | 21 | #include "base/strings/pattern.h" |
[email protected] | 26dd01c | 2013-06-12 13:52:13 | [diff] [blame] | 22 | #include "base/strings/string_number_conversions.h" |
mgiuca | 77752c3 | 2015-02-05 07:31:18 | [diff] [blame] | 23 | #include "base/strings/string_piece.h" |
lukasza | c7d6bd3 | 2017-07-11 00:19:31 | [diff] [blame] | 24 | #include "base/strings/stringprintf.h" |
[email protected] | 74ebfb1 | 2013-06-07 20:48:00 | [diff] [blame] | 25 | #include "base/strings/utf_string_conversions.h" |
[email protected] | 88509ab | 2012-08-27 15:04:14 | [diff] [blame] | 26 | #include "base/synchronization/waitable_event.h" |
Eric Seckler | 8652dcd5 | 2018-09-20 10:42:28 | [diff] [blame] | 27 | #include "base/task/post_task.h" |
[email protected] | 6dbb699 | 2012-07-24 18:04:54 | [diff] [blame] | 28 | #include "base/test/test_timeouts.h" |
fdoray | 0c755de | 2016-10-19 15:28:44 | [diff] [blame] | 29 | #include "base/threading/thread_task_runner_handle.h" |
[email protected] | 2e27285 | 2013-01-03 23:42:11 | [diff] [blame] | 30 | #include "base/values.h" |
avi | 652869c | 2015-12-25 01:48:45 | [diff] [blame] | 31 | #include "build/build_config.h" |
Fady Samuel | dea5e8f | 2017-07-19 21:41:33 | [diff] [blame] | 32 | #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h" |
Fady Samuel | e478607 | 2017-07-24 20:03:38 | [diff] [blame] | 33 | #include "components/viz/service/surfaces/surface.h" |
| 34 | #include "components/viz/service/surfaces/surface_manager.h" |
dmazzoni | fdfa2e0 | 2016-03-30 01:15:43 | [diff] [blame] | 35 | #include "content/browser/accessibility/browser_accessibility.h" |
| 36 | #include "content/browser/accessibility/browser_accessibility_manager.h" |
wjmaclean | b65ea79 | 2016-07-07 22:17:07 | [diff] [blame] | 37 | #include "content/browser/browser_plugin/browser_plugin_guest.h" |
Chris Blume | 12a2646 | 2018-04-22 02:00:12 | [diff] [blame] | 38 | #include "content/browser/browser_plugin/browser_plugin_message_filter.h" |
wjmaclean | b65ea79 | 2016-07-07 22:17:07 | [diff] [blame] | 39 | #include "content/browser/compositor/surface_utils.h" |
Adithya Srinivasan | 0c72ff0 | 2018-08-13 19:47:29 | [diff] [blame] | 40 | #include "content/browser/fileapi/file_system_manager_impl.h" |
wjmaclean | b65ea79 | 2016-07-07 22:17:07 | [diff] [blame] | 41 | #include "content/browser/frame_host/cross_process_frame_connector.h" |
alexmos | af3efeb | 2016-04-12 07:17:39 | [diff] [blame] | 42 | #include "content/browser/frame_host/frame_tree_node.h" |
lfg | 1453e41 | 2017-04-11 00:48:50 | [diff] [blame] | 43 | #include "content/browser/frame_host/interstitial_page_impl.h" |
alexmos | af3efeb | 2016-04-12 07:17:39 | [diff] [blame] | 44 | #include "content/browser/frame_host/render_frame_host_impl.h" |
Xida Chen | 9658adb | 2018-08-17 18:38:30 | [diff] [blame] | 45 | #include "content/browser/frame_host/render_widget_host_view_guest.h" |
Chris Blume | 12a2646 | 2018-04-22 02:00:12 | [diff] [blame] | 46 | #include "content/browser/renderer_host/render_process_host_impl.h" |
[email protected] | c8befac4 | 2014-05-22 15:13:27 | [diff] [blame] | 47 | #include "content/browser/renderer_host/render_widget_host_impl.h" |
lfg | 1453e41 | 2017-04-11 00:48:50 | [diff] [blame] | 48 | #include "content/browser/renderer_host/render_widget_host_input_event_router.h" |
Ken Buchanan | daef006b | 2017-08-17 18:32:15 | [diff] [blame] | 49 | #include "content/browser/renderer_host/render_widget_host_view_child_frame.h" |
Evan Stade | f96e813 | 2018-10-18 18:55:38 | [diff] [blame] | 50 | #include "content/browser/screen_orientation/screen_orientation_provider.h" |
James Cook | 6929b87 | 2018-01-03 17:56:56 | [diff] [blame] | 51 | #include "content/browser/service_manager/service_manager_context.h" |
nick | 7bb1c5c7 | 2014-12-24 01:37:19 | [diff] [blame] | 52 | #include "content/browser/web_contents/web_contents_impl.h" |
[email protected] | fc2b46b | 2014-05-03 16:33:45 | [diff] [blame] | 53 | #include "content/browser/web_contents/web_contents_view.h" |
Chris Blume | 12a2646 | 2018-04-22 02:00:12 | [diff] [blame] | 54 | #include "content/common/browser_plugin/browser_plugin_messages.h" |
nick | bfaea4ee | 2016-12-02 20:59:31 | [diff] [blame] | 55 | #include "content/common/fileapi/webblob_messages.h" |
lfg | 1453e41 | 2017-04-11 00:48:50 | [diff] [blame] | 56 | #include "content/common/frame_messages.h" |
Fady Samuel | 799e7219 | 2018-04-25 21:16:57 | [diff] [blame] | 57 | #include "content/common/frame_visual_properties.h" |
[email protected] | c8befac4 | 2014-05-22 15:13:27 | [diff] [blame] | 58 | #include "content/common/input/synthetic_web_input_event_builders.h" |
dtapuska | 0bd451a | 2016-02-18 17:08:10 | [diff] [blame] | 59 | #include "content/common/input_messages.h" |
Albert J. Wong | 3c93c18 | 2018-09-27 17:29:43 | [diff] [blame] | 60 | #include "content/common/widget_messages.h" |
[email protected] | 88509ab | 2012-08-27 15:04:14 | [diff] [blame] | 61 | #include "content/public/browser/browser_context.h" |
dmazzoni | 5a0018c9 | 2016-07-18 21:45:35 | [diff] [blame] | 62 | #include "content/public/browser/browser_plugin_guest_manager.h" |
Eric Seckler | 8652dcd5 | 2018-09-20 10:42:28 | [diff] [blame] | 63 | #include "content/public/browser/browser_task_traits.h" |
dominicc | 4d8435d | 2016-07-22 03:43:34 | [diff] [blame] | 64 | #include "content/public/browser/browser_thread.h" |
Bo Liu | 2a48940 | 2018-04-24 23:41:27 | [diff] [blame] | 65 | #include "content/public/browser/child_process_termination_info.h" |
[email protected] | e7e9c86 | 2014-08-21 22:00:38 | [diff] [blame] | 66 | #include "content/public/browser/histogram_fetcher.h" |
lfg | 1453e41 | 2017-04-11 00:48:50 | [diff] [blame] | 67 | #include "content/public/browser/interstitial_page.h" |
alexmos | 0785dd76 | 2014-11-13 19:59:38 | [diff] [blame] | 68 | #include "content/public/browser/navigation_entry.h" |
csharrison | 4bd8a19 | 2016-08-02 18:03:15 | [diff] [blame] | 69 | #include "content/public/browser/navigation_handle.h" |
| 70 | #include "content/public/browser/navigation_throttle.h" |
Chong Zhang | c40a6ce5 | 2017-12-10 03:00:28 | [diff] [blame] | 71 | #include "content/public/browser/network_service_instance.h" |
[email protected] | b5e3497 | 2012-09-26 03:50:23 | [diff] [blame] | 72 | #include "content/public/browser/notification_service.h" |
[email protected] | 74ebfb1 | 2013-06-07 20:48:00 | [diff] [blame] | 73 | #include "content/public/browser/notification_types.h" |
[email protected] | ff4657ee | 2014-03-15 01:08:15 | [diff] [blame] | 74 | #include "content/public/browser/render_frame_host.h" |
[email protected] | e0f3e14 | 2012-07-26 03:31:34 | [diff] [blame] | 75 | #include "content/public/browser/render_process_host.h" |
[email protected] | 26151fd | 2012-07-20 23:38:57 | [diff] [blame] | 76 | #include "content/public/browser/render_view_host.h" |
jam | b84299e | 2016-04-12 16:58:59 | [diff] [blame] | 77 | #include "content/public/browser/storage_partition.h" |
[email protected] | 35daebe0 | 2012-07-20 05:40:59 | [diff] [blame] | 78 | #include "content/public/browser/web_contents.h" |
Chong Zhang | c40a6ce5 | 2017-12-10 03:00:28 | [diff] [blame] | 79 | #include "content/public/common/content_features.h" |
John Abd-El-Malek | 7c5c7e4c | 2018-01-11 21:36:16 | [diff] [blame] | 80 | #include "content/public/common/content_switches.h" |
Chong Zhang | c40a6ce5 | 2017-12-10 03:00:28 | [diff] [blame] | 81 | #include "content/public/common/service_names.mojom.h" |
Chris Blume | 12a2646 | 2018-04-22 02:00:12 | [diff] [blame] | 82 | #include "content/public/common/use_zoom_for_dsf_policy.h" |
Chong Zhang | c40a6ce5 | 2017-12-10 03:00:28 | [diff] [blame] | 83 | #include "content/public/test/simple_url_loader_test_helper.h" |
nick | bfaea4ee | 2016-12-02 20:59:31 | [diff] [blame] | 84 | #include "content/public/test/test_fileapi_operation_waiter.h" |
Luciano Pacheco | 034fd9d | 2018-09-19 01:18:40 | [diff] [blame] | 85 | #include "content/public/test/test_launcher.h" |
creis | 748a2c9 | 2015-12-15 18:09:30 | [diff] [blame] | 86 | #include "content/public/test/test_navigation_observer.h" |
[email protected] | 35daebe0 | 2012-07-20 05:40:59 | [diff] [blame] | 87 | #include "content/public/test/test_utils.h" |
dmazzoni | 25af842 | 2016-06-28 20:29:54 | [diff] [blame] | 88 | #include "content/test/accessibility_browser_test_utils.h" |
Charlie Reis | e2c2c49 | 2018-06-15 21:34:04 | [diff] [blame] | 89 | #include "content/test/did_commit_provisional_load_interceptor.h" |
nick | bfaea4ee | 2016-12-02 20:59:31 | [diff] [blame] | 90 | #include "ipc/ipc_security_test_util.h" |
[email protected] | d96cf75 | 2014-04-09 04:05:28 | [diff] [blame] | 91 | #include "net/base/filename_util.h" |
Randy Smith | e23356c2 | 2017-11-14 01:41:50 | [diff] [blame] | 92 | #include "net/base/io_buffer.h" |
| 93 | #include "net/cookies/canonical_cookie.h" |
dbeam | 49dab44 | 2016-08-20 00:49:52 | [diff] [blame] | 94 | #include "net/filter/gzip_header.h" |
xunjieli | 6cc8b84b | 2016-11-08 15:23:39 | [diff] [blame] | 95 | #include "net/filter/gzip_source_stream.h" |
| 96 | #include "net/filter/mock_source_stream.h" |
nasko | b00afd8 | 2014-10-03 05:48:59 | [diff] [blame] | 97 | #include "net/test/embedded_test_server/embedded_test_server.h" |
| 98 | #include "net/test/embedded_test_server/http_request.h" |
| 99 | #include "net/test/embedded_test_server/http_response.h" |
[email protected] | 6dbb699 | 2012-07-24 18:04:54 | [diff] [blame] | 100 | #include "net/test/python_utils.h" |
Chong Zhang | c40a6ce5 | 2017-12-10 03:00:28 | [diff] [blame] | 101 | #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" |
| 102 | #include "net/url_request/url_request_context.h" |
| 103 | #include "net/url_request/url_request_context_getter.h" |
Yutaka Hirano | d8789f9 | 2018-01-30 09:59:51 | [diff] [blame] | 104 | #include "services/network/public/cpp/features.h" |
John Abd-El-Malek | bdafede | 2018-02-06 15:10:36 | [diff] [blame] | 105 | #include "services/network/public/cpp/simple_url_loader.h" |
Ken Rockot | 54311e6 | 2018-02-10 19:01:52 | [diff] [blame] | 106 | #include "services/network/public/mojom/cookie_manager.mojom.h" |
| 107 | #include "services/network/public/mojom/network_service.mojom.h" |
| 108 | #include "services/network/public/mojom/network_service_test.mojom.h" |
Chong Zhang | c40a6ce5 | 2017-12-10 03:00:28 | [diff] [blame] | 109 | #include "services/service_manager/public/cpp/connector.h" |
nick | bfaea4ee | 2016-12-02 20:59:31 | [diff] [blame] | 110 | #include "storage/browser/fileapi/file_system_context.h" |
[email protected] | 35daebe0 | 2012-07-20 05:40:59 | [diff] [blame] | 111 | #include "testing/gtest/include/gtest/gtest.h" |
Adithya Srinivasan | 0c72ff0 | 2018-08-13 19:47:29 | [diff] [blame] | 112 | #include "third_party/blink/public/mojom/filesystem/file_system.mojom.h" |
dominicc | 4d8435d | 2016-07-22 03:43:34 | [diff] [blame] | 113 | #include "ui/base/clipboard/clipboard.h" |
| 114 | #include "ui/base/clipboard/scoped_clipboard_writer.h" |
[email protected] | c2791c1a | 2013-08-22 07:18:35 | [diff] [blame] | 115 | #include "ui/base/resource/resource_bundle.h" |
dominicc | 4d8435d | 2016-07-22 03:43:34 | [diff] [blame] | 116 | #include "ui/base/test/test_clipboard.h" |
[email protected] | 6b614747 | 2014-06-27 17:37:07 | [diff] [blame] | 117 | #include "ui/compositor/test/draw_waiter_for_test.h" |
dtapuska | 899ac22 | 2017-01-03 18:09:16 | [diff] [blame] | 118 | #include "ui/events/base_event_utils.h" |
lanwei | db8214afd | 2014-10-27 17:58:42 | [diff] [blame] | 119 | #include "ui/events/gesture_detection/gesture_configuration.h" |
kpschoedel | 103db44 | 2015-05-15 19:13:57 | [diff] [blame] | 120 | #include "ui/events/keycodes/dom/dom_code.h" |
kpschoedel | 3b0960a | 2015-05-11 17:52:11 | [diff] [blame] | 121 | #include "ui/events/keycodes/dom/keycode_converter.h" |
mfomitchev | 3ba450ad | 2017-04-03 18:20:40 | [diff] [blame] | 122 | #include "ui/latency/latency_info.h" |
tfarina | 272c8d7 | 2014-09-07 05:48:46 | [diff] [blame] | 123 | #include "ui/resources/grit/webui_resources.h" |
[email protected] | 35daebe0 | 2012-07-20 05:40:59 | [diff] [blame] | 124 | |
[email protected] | 6b614747 | 2014-06-27 17:37:07 | [diff] [blame] | 125 | #if defined(USE_AURA) |
mcnee | 19fd249 | 2017-06-01 14:42:43 | [diff] [blame] | 126 | #include "content/browser/renderer_host/overscroll_controller.h" |
wjmaclean | e31234f | 2015-12-14 17:20:45 | [diff] [blame] | 127 | #include "content/browser/renderer_host/render_widget_host_view_aura.h" |
[email protected] | 6b614747 | 2014-06-27 17:37:07 | [diff] [blame] | 128 | #include "ui/aura/test/window_event_dispatcher_test_api.h" |
| 129 | #include "ui/aura/window.h" |
| 130 | #include "ui/aura/window_event_dispatcher.h" |
| 131 | #include "ui/aura/window_tree_host.h" |
wjmaclean | e31234f | 2015-12-14 17:20:45 | [diff] [blame] | 132 | #include "ui/events/event.h" |
[email protected] | 6b614747 | 2014-06-27 17:37:07 | [diff] [blame] | 133 | #endif // USE_AURA |
| 134 | |
[email protected] | 78089f0 | 2012-07-19 06:11:28 | [diff] [blame] | 135 | namespace content { |
[email protected] | 7d478cb | 2012-07-24 17:19:42 | [diff] [blame] | 136 | namespace { |
[email protected] | 26151fd | 2012-07-20 23:38:57 | [diff] [blame] | 137 | |
meacer | b47bc878 | 2014-10-07 03:40:01 | [diff] [blame] | 138 | class InterstitialObserver : public content::WebContentsObserver { |
| 139 | public: |
| 140 | InterstitialObserver(content::WebContents* web_contents, |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 141 | base::OnceClosure attach_callback, |
| 142 | base::OnceClosure detach_callback) |
meacer | b47bc878 | 2014-10-07 03:40:01 | [diff] [blame] | 143 | : WebContentsObserver(web_contents), |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 144 | attach_callback_(std::move(attach_callback)), |
| 145 | detach_callback_(std::move(detach_callback)) {} |
dcheng | e933b3e | 2014-10-21 11:44:09 | [diff] [blame] | 146 | ~InterstitialObserver() override {} |
meacer | b47bc878 | 2014-10-07 03:40:01 | [diff] [blame] | 147 | |
| 148 | // WebContentsObserver methods: |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 149 | void DidAttachInterstitialPage() override { |
| 150 | std::move(attach_callback_).Run(); |
| 151 | } |
| 152 | void DidDetachInterstitialPage() override { |
| 153 | std::move(detach_callback_).Run(); |
| 154 | } |
meacer | b47bc878 | 2014-10-07 03:40:01 | [diff] [blame] | 155 | |
| 156 | private: |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 157 | base::OnceClosure attach_callback_; |
| 158 | base::OnceClosure detach_callback_; |
meacer | b47bc878 | 2014-10-07 03:40:01 | [diff] [blame] | 159 | |
| 160 | DISALLOW_COPY_AND_ASSIGN(InterstitialObserver); |
| 161 | }; |
| 162 | |
[email protected] | 7d478cb | 2012-07-24 17:19:42 | [diff] [blame] | 163 | // Specifying a prototype so that we can add the WARN_UNUSED_RESULT attribute. |
dcheng | 6003e0b | 2016-04-09 18:42:34 | [diff] [blame] | 164 | bool ExecuteScriptHelper(RenderFrameHost* render_frame_host, |
Nick Carter | b7e7131 | 2018-08-03 23:36:13 | [diff] [blame] | 165 | const std::string& script, |
vasilii | b50cee4c9 | 2017-03-31 11:53:14 | [diff] [blame] | 166 | bool user_gesture, |
Nick Carter | b7e7131 | 2018-08-03 23:36:13 | [diff] [blame] | 167 | int world_id, |
dcheng | 6003e0b | 2016-04-09 18:42:34 | [diff] [blame] | 168 | std::unique_ptr<base::Value>* result) |
| 169 | WARN_UNUSED_RESULT; |
[email protected] | 7d478cb | 2012-07-24 17:19:42 | [diff] [blame] | 170 | |
lukasza | fe9cc5e | 2017-07-19 20:18:41 | [diff] [blame] | 171 | // Executes the passed |script| in the frame specified by |render_frame_host|. |
| 172 | // If |result| is not NULL, stores the value that the evaluation of the script |
| 173 | // in |result|. Returns true on success. |
[email protected] | ff4657ee | 2014-03-15 01:08:15 | [diff] [blame] | 174 | bool ExecuteScriptHelper(RenderFrameHost* render_frame_host, |
lukasza | fe9cc5e | 2017-07-19 20:18:41 | [diff] [blame] | 175 | const std::string& script, |
vasilii | b50cee4c9 | 2017-03-31 11:53:14 | [diff] [blame] | 176 | bool user_gesture, |
Nick Carter | b7e7131 | 2018-08-03 23:36:13 | [diff] [blame] | 177 | int world_id, |
dcheng | 6003e0b | 2016-04-09 18:42:34 | [diff] [blame] | 178 | std::unique_ptr<base::Value>* result) { |
lukasza | f1cf692 | 2016-11-03 00:21:43 | [diff] [blame] | 179 | // TODO(lukasza): Only get messages from the specific |render_frame_host|. |
| 180 | DOMMessageQueue dom_message_queue( |
| 181 | WebContents::FromRenderFrameHost(render_frame_host)); |
Nick Carter | b7e7131 | 2018-08-03 23:36:13 | [diff] [blame] | 182 | base::string16 script16 = base::UTF8ToUTF16(script); |
| 183 | if (world_id == ISOLATED_WORLD_ID_GLOBAL) { |
| 184 | if (user_gesture) |
| 185 | render_frame_host->ExecuteJavaScriptWithUserGestureForTests(script16); |
| 186 | else |
| 187 | render_frame_host->ExecuteJavaScriptForTests(script16); |
vasilii | b50cee4c9 | 2017-03-31 11:53:14 | [diff] [blame] | 188 | } else { |
Nick Carter | b7e7131 | 2018-08-03 23:36:13 | [diff] [blame] | 189 | // Note that |user_gesture| here is ignored. We allow a value of |true| |
| 190 | // because it's the default, but in blink, the execution will occur with |
| 191 | // no user gesture. |
| 192 | render_frame_host->ExecuteJavaScriptInIsolatedWorld( |
| 193 | script16, RenderFrameHost::JavaScriptResultCallback(), world_id); |
vasilii | b50cee4c9 | 2017-03-31 11:53:14 | [diff] [blame] | 194 | } |
[email protected] | ff4657ee | 2014-03-15 01:08:15 | [diff] [blame] | 195 | std::string json; |
lukasza | f1cf692 | 2016-11-03 00:21:43 | [diff] [blame] | 196 | if (!dom_message_queue.WaitForMessage(&json)) { |
| 197 | DLOG(ERROR) << "Cannot communicate with DOMMessageQueue."; |
[email protected] | ff4657ee | 2014-03-15 01:08:15 | [diff] [blame] | 198 | return false; |
| 199 | } |
| 200 | |
| 201 | // Nothing more to do for callers that ignore the returned JS value. |
| 202 | if (!result) |
| 203 | return true; |
| 204 | |
| 205 | base::JSONReader reader(base::JSON_ALLOW_TRAILING_COMMAS); |
estade | 69505de | 2015-05-20 22:46:58 | [diff] [blame] | 206 | *result = reader.ReadToValue(json); |
| 207 | if (!*result) { |
[email protected] | ff4657ee | 2014-03-15 01:08:15 | [diff] [blame] | 208 | DLOG(ERROR) << reader.GetErrorMessage(); |
| 209 | return false; |
| 210 | } |
| 211 | |
| 212 | return true; |
| 213 | } |
| 214 | |
lukasza | c7d6bd3 | 2017-07-11 00:19:31 | [diff] [blame] | 215 | bool ExecuteScriptWithUserGestureControl(RenderFrameHost* frame, |
| 216 | const std::string& script, |
| 217 | bool user_gesture) { |
| 218 | // TODO(lukasza): ExecuteScript should just call |
| 219 | // ExecuteJavaScriptWithUserGestureForTests and avoid modifying the original |
| 220 | // script (and at that point we should merge it with and remove |
| 221 | // ExecuteScriptAsync). This is difficult to change, because many tests |
| 222 | // depend on the message loop pumping done by ExecuteScriptHelper below (this |
| 223 | // is fragile - these tests should wait on a more specific thing instead). |
| 224 | |
Nick Carter | b7e7131 | 2018-08-03 23:36:13 | [diff] [blame] | 225 | // TODO(nick): This function can't be replaced with a call to ExecJs(), since |
| 226 | // ExecJs calls eval() which might be blocked by the page's CSP. |
lukasza | c7d6bd3 | 2017-07-11 00:19:31 | [diff] [blame] | 227 | std::string expected_response = "ExecuteScript-" + base::GenerateGUID(); |
| 228 | std::string new_script = base::StringPrintf( |
| 229 | R"( %s; // Original script. |
| 230 | window.domAutomationController.send('%s'); )", |
| 231 | script.c_str(), expected_response.c_str()); |
| 232 | |
| 233 | std::unique_ptr<base::Value> value; |
Nick Carter | b7e7131 | 2018-08-03 23:36:13 | [diff] [blame] | 234 | if (!ExecuteScriptHelper(frame, new_script, user_gesture, |
| 235 | ISOLATED_WORLD_ID_GLOBAL, &value) || |
lukasza | c7d6bd3 | 2017-07-11 00:19:31 | [diff] [blame] | 236 | !value.get()) { |
| 237 | return false; |
| 238 | } |
| 239 | |
jdoerrie | 76cee9c | 2017-10-06 22:42:42 | [diff] [blame] | 240 | DCHECK_EQ(base::Value::Type::STRING, value->type()); |
lukasza | c7d6bd3 | 2017-07-11 00:19:31 | [diff] [blame] | 241 | std::string actual_response; |
| 242 | if (value->GetAsString(&actual_response)) |
| 243 | DCHECK_EQ(expected_response, actual_response); |
| 244 | |
| 245 | return true; |
| 246 | } |
| 247 | |
[email protected] | 180ef24 | 2013-11-07 06:50:46 | [diff] [blame] | 248 | void BuildSimpleWebKeyEvent(blink::WebInputEvent::Type type, |
dtapuska | 8b1bdc8 | 2016-06-07 21:39:48 | [diff] [blame] | 249 | ui::DomKey key, |
| 250 | ui::DomCode code, |
[email protected] | 6dc5a33 | 2013-09-11 01:02:10 | [diff] [blame] | 251 | ui::KeyboardCode key_code, |
[email protected] | 26151fd | 2012-07-20 23:38:57 | [diff] [blame] | 252 | NativeWebKeyboardEvent* event) { |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 253 | event->dom_key = key; |
| 254 | event->dom_code = static_cast<int>(code); |
| 255 | event->native_key_code = ui::KeycodeConverter::DomCodeToNativeKeycode(code); |
| 256 | event->windows_key_code = key_code; |
| 257 | event->is_system_key = false; |
[email protected] | 26151fd | 2012-07-20 23:38:57 | [diff] [blame] | 258 | event->skip_in_browser = true; |
| 259 | |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 260 | if (type == blink::WebInputEvent::kChar || |
| 261 | type == blink::WebInputEvent::kRawKeyDown) { |
Vasilii Sukhanov | 886f65d | 2018-05-15 08:15:29 | [diff] [blame] | 262 | // |key| is the only parameter that contains information about the case of |
| 263 | // the character. Use it to be able to generate lower case input. |
| 264 | if (key.IsCharacter()) { |
| 265 | event->text[0] = key.ToCharacter(); |
| 266 | event->unmodified_text[0] = key.ToCharacter(); |
| 267 | } else { |
| 268 | event->text[0] = key_code; |
| 269 | event->unmodified_text[0] = key_code; |
| 270 | } |
[email protected] | 26151fd | 2012-07-20 23:38:57 | [diff] [blame] | 271 | } |
[email protected] | ec8e0595 | 2013-09-19 21:45:40 | [diff] [blame] | 272 | } |
[email protected] | 26151fd | 2012-07-20 23:38:57 | [diff] [blame] | 273 | |
[email protected] | ec8e0595 | 2013-09-19 21:45:40 | [diff] [blame] | 274 | void InjectRawKeyEvent(WebContents* web_contents, |
[email protected] | 180ef24 | 2013-11-07 06:50:46 | [diff] [blame] | 275 | blink::WebInputEvent::Type type, |
dtapuska | 8b1bdc8 | 2016-06-07 21:39:48 | [diff] [blame] | 276 | ui::DomKey key, |
| 277 | ui::DomCode code, |
[email protected] | ec8e0595 | 2013-09-19 21:45:40 | [diff] [blame] | 278 | ui::KeyboardCode key_code, |
[email protected] | ec8e0595 | 2013-09-19 21:45:40 | [diff] [blame] | 279 | int modifiers) { |
dtapuska | 899ac22 | 2017-01-03 18:09:16 | [diff] [blame] | 280 | NativeWebKeyboardEvent event(type, modifiers, base::TimeTicks::Now()); |
| 281 | BuildSimpleWebKeyEvent(type, key, code, key_code, &event); |
alexmos | c4cbacb | 2015-11-21 01:29:22 | [diff] [blame] | 282 | WebContentsImpl* web_contents_impl = |
| 283 | static_cast<WebContentsImpl*>(web_contents); |
| 284 | RenderWidgetHostImpl* main_frame_rwh = |
| 285 | web_contents_impl->GetMainFrame()->GetRenderWidgetHost(); |
| 286 | web_contents_impl->GetFocusedRenderWidgetHost(main_frame_rwh) |
alexmos | c4d183e | 2015-11-06 00:46:52 | [diff] [blame] | 287 | ->ForwardKeyboardEvent(event); |
[email protected] | 26151fd | 2012-07-20 23:38:57 | [diff] [blame] | 288 | } |
| 289 | |
Lei Zhang | 6cef326 | 2017-08-16 15:44:38 | [diff] [blame] | 290 | int SimulateModifierKeysDown(WebContents* web_contents, |
| 291 | bool control, |
| 292 | bool shift, |
| 293 | bool alt, |
| 294 | bool command) { |
| 295 | int modifiers = 0; |
| 296 | |
| 297 | // The order of these key down events shouldn't matter for our simulation. |
| 298 | // For our simulation we can use either the left keys or the right keys. |
| 299 | if (control) { |
| 300 | modifiers |= blink::WebInputEvent::kControlKey; |
| 301 | InjectRawKeyEvent(web_contents, blink::WebInputEvent::kRawKeyDown, |
| 302 | ui::DomKey::CONTROL, ui::DomCode::CONTROL_LEFT, |
| 303 | ui::VKEY_CONTROL, modifiers); |
| 304 | } |
| 305 | if (shift) { |
| 306 | modifiers |= blink::WebInputEvent::kShiftKey; |
| 307 | InjectRawKeyEvent(web_contents, blink::WebInputEvent::kRawKeyDown, |
| 308 | ui::DomKey::SHIFT, ui::DomCode::SHIFT_LEFT, |
| 309 | ui::VKEY_SHIFT, modifiers); |
| 310 | } |
| 311 | if (alt) { |
| 312 | modifiers |= blink::WebInputEvent::kAltKey; |
| 313 | InjectRawKeyEvent(web_contents, blink::WebInputEvent::kRawKeyDown, |
| 314 | ui::DomKey::ALT, ui::DomCode::ALT_LEFT, ui::VKEY_MENU, |
| 315 | modifiers); |
| 316 | } |
| 317 | if (command) { |
| 318 | modifiers |= blink::WebInputEvent::kMetaKey; |
| 319 | InjectRawKeyEvent(web_contents, blink::WebInputEvent::kRawKeyDown, |
| 320 | ui::DomKey::META, ui::DomCode::META_LEFT, |
| 321 | ui::VKEY_COMMAND, modifiers); |
| 322 | } |
| 323 | return modifiers; |
| 324 | } |
| 325 | |
| 326 | int SimulateModifierKeysUp(WebContents* web_contents, |
| 327 | bool control, |
| 328 | bool shift, |
| 329 | bool alt, |
| 330 | bool command, |
| 331 | int modifiers) { |
| 332 | // The order of these key releases shouldn't matter for our simulation. |
| 333 | if (control) { |
| 334 | modifiers &= ~blink::WebInputEvent::kControlKey; |
| 335 | InjectRawKeyEvent(web_contents, blink::WebInputEvent::kKeyUp, |
| 336 | ui::DomKey::CONTROL, ui::DomCode::CONTROL_LEFT, |
| 337 | ui::VKEY_CONTROL, modifiers); |
| 338 | } |
| 339 | |
| 340 | if (shift) { |
| 341 | modifiers &= ~blink::WebInputEvent::kShiftKey; |
| 342 | InjectRawKeyEvent(web_contents, blink::WebInputEvent::kKeyUp, |
| 343 | ui::DomKey::SHIFT, ui::DomCode::SHIFT_LEFT, |
| 344 | ui::VKEY_SHIFT, modifiers); |
| 345 | } |
| 346 | |
| 347 | if (alt) { |
| 348 | modifiers &= ~blink::WebInputEvent::kAltKey; |
| 349 | InjectRawKeyEvent(web_contents, blink::WebInputEvent::kKeyUp, |
| 350 | ui::DomKey::ALT, ui::DomCode::ALT_LEFT, ui::VKEY_MENU, |
| 351 | modifiers); |
| 352 | } |
| 353 | |
| 354 | if (command) { |
| 355 | modifiers &= ~blink::WebInputEvent::kMetaKey; |
| 356 | InjectRawKeyEvent(web_contents, blink::WebInputEvent::kKeyUp, |
| 357 | ui::DomKey::META, ui::DomCode::META_LEFT, |
| 358 | ui::VKEY_COMMAND, modifiers); |
| 359 | } |
| 360 | return modifiers; |
| 361 | } |
| 362 | |
| 363 | void SimulateKeyEvent(WebContents* web_contents, |
| 364 | ui::DomKey key, |
| 365 | ui::DomCode code, |
| 366 | ui::KeyboardCode key_code, |
| 367 | bool send_char, |
| 368 | int modifiers) { |
| 369 | InjectRawKeyEvent(web_contents, blink::WebInputEvent::kRawKeyDown, key, code, |
| 370 | key_code, modifiers); |
| 371 | if (send_char) { |
| 372 | InjectRawKeyEvent(web_contents, blink::WebInputEvent::kChar, key, code, |
| 373 | key_code, modifiers); |
| 374 | } |
| 375 | InjectRawKeyEvent(web_contents, blink::WebInputEvent::kKeyUp, key, code, |
| 376 | key_code, modifiers); |
| 377 | } |
| 378 | |
| 379 | void SimulateKeyPressImpl(WebContents* web_contents, |
| 380 | ui::DomKey key, |
| 381 | ui::DomCode code, |
| 382 | ui::KeyboardCode key_code, |
| 383 | bool control, |
| 384 | bool shift, |
| 385 | bool alt, |
| 386 | bool command, |
| 387 | bool send_char) { |
| 388 | int modifiers = |
| 389 | SimulateModifierKeysDown(web_contents, control, shift, alt, command); |
| 390 | SimulateKeyEvent(web_contents, key, code, key_code, send_char, modifiers); |
| 391 | modifiers = SimulateModifierKeysUp(web_contents, control, shift, alt, command, |
| 392 | modifiers); |
| 393 | ASSERT_EQ(modifiers, 0); |
| 394 | } |
| 395 | |
dcheng | 6003e0b | 2016-04-09 18:42:34 | [diff] [blame] | 396 | std::unique_ptr<net::test_server::HttpResponse> |
martijn | 2037cd7 | 2016-11-10 20:11:32 | [diff] [blame] | 397 | CrossSiteRedirectResponseHandler(const net::EmbeddedTestServer* test_server, |
dcheng | 6003e0b | 2016-04-09 18:42:34 | [diff] [blame] | 398 | const net::test_server::HttpRequest& request) { |
lukasza | 2ad8fef | 2016-05-24 23:00:43 | [diff] [blame] | 399 | net::HttpStatusCode http_status_code; |
nasko | b00afd8 | 2014-10-03 05:48:59 | [diff] [blame] | 400 | |
lukasza | 2ad8fef | 2016-05-24 23:00:43 | [diff] [blame] | 401 | // Inspect the prefix and extract the remainder of the url into |params|. |
| 402 | size_t length_of_chosen_prefix; |
| 403 | std::string prefix_302("/cross-site/"); |
| 404 | std::string prefix_307("/cross-site-307/"); |
| 405 | if (base::StartsWith(request.relative_url, prefix_302, |
| 406 | base::CompareCase::SENSITIVE)) { |
| 407 | http_status_code = net::HTTP_MOVED_PERMANENTLY; |
| 408 | length_of_chosen_prefix = prefix_302.length(); |
| 409 | } else if (base::StartsWith(request.relative_url, prefix_307, |
| 410 | base::CompareCase::SENSITIVE)) { |
| 411 | http_status_code = net::HTTP_TEMPORARY_REDIRECT; |
| 412 | length_of_chosen_prefix = prefix_307.length(); |
| 413 | } else { |
| 414 | // Unrecognized prefix - let somebody else handle this request. |
| 415 | return std::unique_ptr<net::test_server::HttpResponse>(); |
| 416 | } |
| 417 | std::string params = request.relative_url.substr(length_of_chosen_prefix); |
nasko | b00afd8 | 2014-10-03 05:48:59 | [diff] [blame] | 418 | |
| 419 | // A hostname to redirect to must be included in the URL, therefore at least |
| 420 | // one '/' character is expected. |
| 421 | size_t slash = params.find('/'); |
| 422 | if (slash == std::string::npos) |
dcheng | 6003e0b | 2016-04-09 18:42:34 | [diff] [blame] | 423 | return std::unique_ptr<net::test_server::HttpResponse>(); |
nasko | b00afd8 | 2014-10-03 05:48:59 | [diff] [blame] | 424 | |
| 425 | // Replace the host of the URL with the one passed in the URL. |
nasko | b00afd8 | 2014-10-03 05:48:59 | [diff] [blame] | 426 | GURL::Replacements replace_host; |
mgiuca | 77752c3 | 2015-02-05 07:31:18 | [diff] [blame] | 427 | replace_host.SetHostStr(base::StringPiece(params).substr(0, slash)); |
martijn | 2037cd7 | 2016-11-10 20:11:32 | [diff] [blame] | 428 | GURL redirect_server = |
| 429 | test_server->base_url().ReplaceComponents(replace_host); |
nasko | b00afd8 | 2014-10-03 05:48:59 | [diff] [blame] | 430 | |
| 431 | // Append the real part of the path to the new URL. |
| 432 | std::string path = params.substr(slash + 1); |
| 433 | GURL redirect_target(redirect_server.Resolve(path)); |
| 434 | DCHECK(redirect_target.is_valid()); |
| 435 | |
dcheng | 6003e0b | 2016-04-09 18:42:34 | [diff] [blame] | 436 | std::unique_ptr<net::test_server::BasicHttpResponse> http_response( |
nasko | b00afd8 | 2014-10-03 05:48:59 | [diff] [blame] | 437 | new net::test_server::BasicHttpResponse); |
lukasza | 2ad8fef | 2016-05-24 23:00:43 | [diff] [blame] | 438 | http_response->set_code(http_status_code); |
nasko | b00afd8 | 2014-10-03 05:48:59 | [diff] [blame] | 439 | http_response->AddCustomHeader("Location", redirect_target.spec()); |
dcheng | f63a125 | 2015-12-26 20:43:13 | [diff] [blame] | 440 | return std::move(http_response); |
nasko | b00afd8 | 2014-10-03 05:48:59 | [diff] [blame] | 441 | } |
| 442 | |
csharrison | 4bd8a19 | 2016-08-02 18:03:15 | [diff] [blame] | 443 | // Helper class used by the TestNavigationManager to pause navigations. |
| 444 | // Note: the throttle should be added to the *end* of the list of throttles, |
| 445 | // so all NavigationThrottles that should be attached observe the |
| 446 | // WillStartRequest callback. RegisterThrottleForTesting has this behavior. |
| 447 | class TestNavigationManagerThrottle : public NavigationThrottle { |
| 448 | public: |
| 449 | TestNavigationManagerThrottle(NavigationHandle* handle, |
clamy | d69748c | 2016-10-07 22:09:44 | [diff] [blame] | 450 | base::Closure on_will_start_request_closure, |
| 451 | base::Closure on_will_process_response_closure) |
csharrison | 4bd8a19 | 2016-08-02 18:03:15 | [diff] [blame] | 452 | : NavigationThrottle(handle), |
clamy | d69748c | 2016-10-07 22:09:44 | [diff] [blame] | 453 | on_will_start_request_closure_(on_will_start_request_closure), |
| 454 | on_will_process_response_closure_(on_will_process_response_closure) {} |
csharrison | 4bd8a19 | 2016-08-02 18:03:15 | [diff] [blame] | 455 | ~TestNavigationManagerThrottle() override {} |
| 456 | |
nasko | d818557 | 2017-04-24 17:17:17 | [diff] [blame] | 457 | const char* GetNameForLogging() override { |
| 458 | return "TestNavigationManagerThrottle"; |
| 459 | } |
| 460 | |
csharrison | 4bd8a19 | 2016-08-02 18:03:15 | [diff] [blame] | 461 | private: |
| 462 | // NavigationThrottle: |
| 463 | NavigationThrottle::ThrottleCheckResult WillStartRequest() override { |
Eric Seckler | 8652dcd5 | 2018-09-20 10:42:28 | [diff] [blame] | 464 | base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, |
| 465 | on_will_start_request_closure_); |
csharrison | 4bd8a19 | 2016-08-02 18:03:15 | [diff] [blame] | 466 | return NavigationThrottle::DEFER; |
| 467 | } |
| 468 | |
clamy | d69748c | 2016-10-07 22:09:44 | [diff] [blame] | 469 | NavigationThrottle::ThrottleCheckResult WillProcessResponse() override { |
Eric Seckler | 8652dcd5 | 2018-09-20 10:42:28 | [diff] [blame] | 470 | base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, |
| 471 | on_will_process_response_closure_); |
clamy | d69748c | 2016-10-07 22:09:44 | [diff] [blame] | 472 | return NavigationThrottle::DEFER; |
| 473 | } |
| 474 | |
csharrison | 4bd8a19 | 2016-08-02 18:03:15 | [diff] [blame] | 475 | base::Closure on_will_start_request_closure_; |
clamy | d69748c | 2016-10-07 22:09:44 | [diff] [blame] | 476 | base::Closure on_will_process_response_closure_; |
csharrison | 4bd8a19 | 2016-08-02 18:03:15 | [diff] [blame] | 477 | }; |
| 478 | |
dbeam | 49dab44 | 2016-08-20 00:49:52 | [diff] [blame] | 479 | bool HasGzipHeader(const base::RefCountedMemory& maybe_gzipped) { |
| 480 | net::GZipHeader header; |
| 481 | net::GZipHeader::Status header_status = net::GZipHeader::INCOMPLETE_HEADER; |
| 482 | const char* header_end = nullptr; |
| 483 | while (header_status == net::GZipHeader::INCOMPLETE_HEADER) { |
| 484 | header_status = header.ReadMore(maybe_gzipped.front_as<char>(), |
| 485 | maybe_gzipped.size(), |
| 486 | &header_end); |
| 487 | } |
| 488 | return header_status == net::GZipHeader::COMPLETE_HEADER; |
| 489 | } |
| 490 | |
| 491 | void AppendGzippedResource(const base::RefCountedMemory& encoded, |
| 492 | std::string* to_append) { |
xunjieli | 6cc8b84b | 2016-11-08 15:23:39 | [diff] [blame] | 493 | std::unique_ptr<net::MockSourceStream> source_stream( |
| 494 | new net::MockSourceStream()); |
| 495 | source_stream->AddReadResult(encoded.front_as<char>(), encoded.size(), |
| 496 | net::OK, net::MockSourceStream::SYNC); |
| 497 | // Add an EOF. |
| 498 | source_stream->AddReadResult(encoded.front_as<char>() + encoded.size(), 0, |
| 499 | net::OK, net::MockSourceStream::SYNC); |
| 500 | std::unique_ptr<net::GzipSourceStream> filter = net::GzipSourceStream::Create( |
| 501 | std::move(source_stream), net::SourceStream::TYPE_GZIP); |
| 502 | scoped_refptr<net::IOBufferWithSize> dest_buffer = |
Victor Costan | 63c8b3d | 2018-09-01 01:34:10 | [diff] [blame] | 503 | base::MakeRefCounted<net::IOBufferWithSize>(4096); |
xunjieli | 6cc8b84b | 2016-11-08 15:23:39 | [diff] [blame] | 504 | net::CompletionCallback callback; |
| 505 | while (true) { |
| 506 | int rv = filter->Read(dest_buffer.get(), dest_buffer->size(), callback); |
| 507 | ASSERT_LE(0, rv); |
| 508 | if (rv <= 0) |
| 509 | break; |
| 510 | to_append->append(dest_buffer->data(), rv); |
| 511 | } |
dbeam | 49dab44 | 2016-08-20 00:49:52 | [diff] [blame] | 512 | } |
| 513 | |
lunalu | 2ddb05a8 | 2016-09-19 19:22:07 | [diff] [blame] | 514 | // Queries for video input devices on the current system using the getSources |
| 515 | // API. |
| 516 | // |
| 517 | // This does not guarantee that a getUserMedia with video will succeed, as the |
| 518 | // camera could be busy for instance. |
| 519 | // |
| 520 | // Returns has-video-input-device to the test if there is a webcam available, |
| 521 | // no-video-input-devices otherwise. |
lukasza | c7d6bd3 | 2017-07-11 00:19:31 | [diff] [blame] | 522 | const char kHasVideoInputDeviceOnSystem[] = R"( |
| 523 | (function() { |
| 524 | navigator.mediaDevices.enumerateDevices() |
| 525 | .then(function(devices) { |
| 526 | if (devices.some((device) => device.kind == 'videoinput')) { |
| 527 | window.domAutomationController.send('has-video-input-device'); |
| 528 | } else { |
| 529 | window.domAutomationController.send('no-video-input-devices'); |
| 530 | } |
| 531 | }); |
| 532 | })() |
| 533 | )"; |
lunalu | 2ddb05a8 | 2016-09-19 19:22:07 | [diff] [blame] | 534 | |
| 535 | const char kHasVideoInputDevice[] = "has-video-input-device"; |
| 536 | |
Charlie Reis | e2c2c49 | 2018-06-15 21:34:04 | [diff] [blame] | 537 | // Interceptor that replaces params.url with |new_url| and params.origin with |
| 538 | // |new_origin| for any commits to |target_url|. |
| 539 | class CommitOriginInterceptor : public DidCommitProvisionalLoadInterceptor { |
| 540 | public: |
| 541 | CommitOriginInterceptor(WebContents* web_contents, |
| 542 | const GURL& target_url, |
| 543 | const GURL& new_url, |
| 544 | const url::Origin& new_origin) |
| 545 | : DidCommitProvisionalLoadInterceptor(web_contents), |
| 546 | target_url_(target_url), |
| 547 | new_url_(new_url), |
| 548 | new_origin_(new_origin) {} |
| 549 | ~CommitOriginInterceptor() override = default; |
| 550 | |
| 551 | // WebContentsObserver: |
| 552 | void WebContentsDestroyed() override { delete this; } |
| 553 | |
| 554 | protected: |
clamy | d3bfdb0 | 2018-07-12 13:52:18 | [diff] [blame] | 555 | bool WillDispatchDidCommitProvisionalLoad( |
Charlie Reis | e2c2c49 | 2018-06-15 21:34:04 | [diff] [blame] | 556 | RenderFrameHost* render_frame_host, |
| 557 | ::FrameHostMsg_DidCommitProvisionalLoad_Params* params, |
| 558 | service_manager::mojom::InterfaceProviderRequest* |
| 559 | interface_provider_request) override { |
| 560 | if (params->url == target_url_) { |
| 561 | params->url = new_url_; |
| 562 | params->origin = new_origin_; |
| 563 | } |
clamy | d3bfdb0 | 2018-07-12 13:52:18 | [diff] [blame] | 564 | return true; |
Charlie Reis | e2c2c49 | 2018-06-15 21:34:04 | [diff] [blame] | 565 | } |
| 566 | |
| 567 | private: |
| 568 | GURL target_url_; |
| 569 | GURL new_url_; |
| 570 | url::Origin new_origin_; |
| 571 | |
| 572 | DISALLOW_COPY_AND_ASSIGN(CommitOriginInterceptor); |
| 573 | }; |
| 574 | |
[email protected] | 7d478cb | 2012-07-24 17:19:42 | [diff] [blame] | 575 | } // namespace |
| 576 | |
Lukasz Anforowicz | 637e7d6d | 2018-10-06 05:44:12 | [diff] [blame] | 577 | bool NavigateToURL(WebContents* web_contents, const GURL& url) { |
| 578 | NavigateToURLBlockUntilNavigationsComplete(web_contents, url, 1); |
| 579 | if (!IsLastCommittedEntryOfPageType(web_contents, PAGE_TYPE_NORMAL)) { |
| 580 | // TODO(crbug.com/882545) remove the following debug information: |
| 581 | { |
| 582 | NavigationEntry* last_entry = |
| 583 | web_contents->GetController().GetLastCommittedEntry(); |
| 584 | if (!last_entry) { |
| 585 | DLOG(WARNING) << "No last committed entry"; |
| 586 | } else { |
| 587 | DLOG(WARNING) << "Last committed entry is of type " |
| 588 | << last_entry->GetPageType(); |
| 589 | } |
| 590 | } |
| 591 | return false; |
| 592 | } |
| 593 | |
| 594 | // TODO(crbug.com/882545) revert this to the return statement below. |
| 595 | bool same_url = web_contents->GetLastCommittedURL() == url; |
| 596 | if (!same_url) { |
| 597 | DLOG(WARNING) << "Expected URL " << url << " but observed " |
| 598 | << web_contents->GetLastCommittedURL(); |
| 599 | } |
| 600 | return same_url; |
| 601 | // return web_contents->GetLastCommittedURL() == url; |
| 602 | } |
| 603 | |
alexmos | 75648bb3 | 2015-01-07 21:06:28 | [diff] [blame] | 604 | bool NavigateIframeToURL(WebContents* web_contents, |
| 605 | std::string iframe_id, |
| 606 | const GURL& url) { |
alexmos | 75648bb3 | 2015-01-07 21:06:28 | [diff] [blame] | 607 | std::string script = base::StringPrintf( |
| 608 | "setTimeout(\"" |
| 609 | "var iframes = document.getElementById('%s');iframes.src='%s';" |
| 610 | "\",0)", |
| 611 | iframe_id.c_str(), url.spec().c_str()); |
creis | 748a2c9 | 2015-12-15 18:09:30 | [diff] [blame] | 612 | TestNavigationObserver load_observer(web_contents); |
alexmos | 75648bb3 | 2015-01-07 21:06:28 | [diff] [blame] | 613 | bool result = ExecuteScript(web_contents, script); |
| 614 | load_observer.Wait(); |
| 615 | return result; |
| 616 | } |
[email protected] | 71d504f | 2012-07-25 17:15:28 | [diff] [blame] | 617 | |
Lukasz Anforowicz | 637e7d6d | 2018-10-06 05:44:12 | [diff] [blame] | 618 | void NavigateToURLBlockUntilNavigationsComplete(WebContents* web_contents, |
| 619 | const GURL& url, |
| 620 | int number_of_navigations) { |
| 621 | // Prepare for the navigation. |
| 622 | WaitForLoadStop(web_contents); |
| 623 | TestNavigationObserver same_tab_observer(web_contents, number_of_navigations); |
| 624 | |
| 625 | // This mimics behavior of Shell::LoadURL... |
| 626 | NavigationController::LoadURLParams params(url); |
| 627 | params.transition_type = ui::PageTransitionFromInt( |
| 628 | ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR); |
| 629 | web_contents->GetController().LoadURLWithParams(params); |
| 630 | web_contents->Focus(); |
| 631 | |
| 632 | // Wait until the expected number of navigations finish. |
| 633 | same_tab_observer.Wait(); |
| 634 | // TODO(crbug.com/882545) Delete this if statement once the problem has been |
| 635 | // identified. |
| 636 | if (!same_tab_observer.last_navigation_succeeded()) { |
| 637 | DLOG(WARNING) << "Last navigation to " << url << " failed with net error " |
| 638 | << same_tab_observer.last_net_error_code(); |
| 639 | } |
| 640 | } |
| 641 | |
[email protected] | c42de73 | 2013-02-16 06:26:31 | [diff] [blame] | 642 | GURL GetFileUrlWithQuery(const base::FilePath& path, |
[email protected] | 71d504f | 2012-07-25 17:15:28 | [diff] [blame] | 643 | const std::string& query_string) { |
| 644 | GURL url = net::FilePathToFileURL(path); |
| 645 | if (!query_string.empty()) { |
| 646 | GURL::Replacements replacements; |
| 647 | replacements.SetQueryStr(query_string); |
| 648 | return url.ReplaceComponents(replacements); |
| 649 | } |
| 650 | return url; |
| 651 | } |
| 652 | |
Xida Chen | ec19b70 | 2018-08-15 01:57:14 | [diff] [blame] | 653 | void ResetTouchAction(RenderWidgetHost* host) { |
| 654 | static_cast<InputRouterImpl*>( |
| 655 | static_cast<RenderWidgetHostImpl*>(host)->input_router()) |
Xida Chen | 0f7980b | 2018-10-12 12:40:53 | [diff] [blame] | 656 | ->ForceResetTouchActionForTest(); |
Xida Chen | ec19b70 | 2018-08-15 01:57:14 | [diff] [blame] | 657 | } |
| 658 | |
| 659 | void ResendGestureScrollUpdateToEmbedder(WebContents* guest_web_contents, |
| 660 | const blink::WebInputEvent& event) { |
Ehsan Karamad | fa983e8 | 2018-11-13 01:26:42 | [diff] [blame] | 661 | auto* guest_web_contents_impl = |
| 662 | static_cast<WebContentsImpl*>(guest_web_contents); |
| 663 | DCHECK(guest_web_contents_impl->GetBrowserPluginGuest()); |
| 664 | guest_web_contents_impl->GetBrowserPluginGuest()->ResendEventToEmbedder( |
| 665 | event); |
Xida Chen | ec19b70 | 2018-08-15 01:57:14 | [diff] [blame] | 666 | } |
| 667 | |
Xida Chen | 9658adb | 2018-08-17 18:38:30 | [diff] [blame] | 668 | void MaybeSendSyntheticTapGesture(WebContents* guest_web_contents) { |
| 669 | content::RenderWidgetHostViewGuest* rwhv = |
| 670 | static_cast<content::RenderWidgetHostViewGuest*>( |
| 671 | guest_web_contents->GetRenderWidgetHostView()); |
| 672 | DCHECK(rwhv); |
| 673 | rwhv->MaybeSendSyntheticTapGestureForTest(blink::WebFloatPoint(1, 1), |
| 674 | blink::WebFloatPoint(1, 1)); |
| 675 | } |
| 676 | |
alexmos | 0785dd76 | 2014-11-13 19:59:38 | [diff] [blame] | 677 | void WaitForLoadStopWithoutSuccessCheck(WebContents* web_contents) { |
[email protected] | 6ddc6e3f2 | 2012-07-26 01:15:35 | [diff] [blame] | 678 | // In many cases, the load may have finished before we get here. Only wait if |
| 679 | // the tab still has a pending navigation. |
[email protected] | 6b614747 | 2014-06-27 17:37:07 | [diff] [blame] | 680 | if (web_contents->IsLoading()) { |
| 681 | WindowedNotificationObserver load_stop_observer( |
| 682 | NOTIFICATION_LOAD_STOP, |
| 683 | Source<NavigationController>(&web_contents->GetController())); |
| 684 | load_stop_observer.Wait(); |
| 685 | } |
[email protected] | 6ddc6e3f2 | 2012-07-26 01:15:35 | [diff] [blame] | 686 | } |
| 687 | |
alexmos | 0785dd76 | 2014-11-13 19:59:38 | [diff] [blame] | 688 | bool WaitForLoadStop(WebContents* web_contents) { |
Gennady Sushko | 1fbd57fa | 2017-10-25 20:28:17 | [diff] [blame] | 689 | WebContentsDestroyedObserver observer(web_contents); |
alexmos | 0785dd76 | 2014-11-13 19:59:38 | [diff] [blame] | 690 | WaitForLoadStopWithoutSuccessCheck(web_contents); |
Gennady Sushko | 1fbd57fa | 2017-10-25 20:28:17 | [diff] [blame] | 691 | if (observer.IsDestroyed()) { |
| 692 | LOG(ERROR) << "WebContents was destroyed during waiting for load stop."; |
| 693 | return false; |
| 694 | } |
alexmos | 0785dd76 | 2014-11-13 19:59:38 | [diff] [blame] | 695 | return IsLastCommittedEntryOfPageType(web_contents, PAGE_TYPE_NORMAL); |
| 696 | } |
| 697 | |
avi | 336125f7 | 2017-05-06 22:25:40 | [diff] [blame] | 698 | void PrepContentsForBeforeUnloadTest(WebContents* web_contents) { |
| 699 | for (auto* frame : web_contents->GetAllFrames()) { |
| 700 | // JavaScript onbeforeunload dialogs are ignored unless the frame received a |
| 701 | // user gesture. Make sure the frames have user gestures. |
| 702 | frame->ExecuteJavaScriptWithUserGestureForTests(base::string16()); |
| 703 | |
| 704 | // Disable the hang monitor, otherwise there will be a race between the |
| 705 | // beforeunload dialog and the beforeunload hang timer. |
| 706 | frame->DisableBeforeUnloadHangMonitorForTesting(); |
| 707 | } |
| 708 | } |
| 709 | |
alexmos | 0785dd76 | 2014-11-13 19:59:38 | [diff] [blame] | 710 | bool IsLastCommittedEntryOfPageType(WebContents* web_contents, |
| 711 | content::PageType page_type) { |
| 712 | NavigationEntry* last_entry = |
| 713 | web_contents->GetController().GetLastCommittedEntry(); |
| 714 | if (!last_entry) |
| 715 | return false; |
| 716 | return last_entry->GetPageType() == page_type; |
| 717 | } |
| 718 | |
Charlie Reis | 7614790 | 2018-04-26 01:21:07 | [diff] [blame] | 719 | void OverrideLastCommittedOrigin(RenderFrameHost* render_frame_host, |
| 720 | const url::Origin& origin) { |
| 721 | static_cast<RenderFrameHostImpl*>(render_frame_host) |
| 722 | ->SetLastCommittedOriginForTesting(origin); |
| 723 | } |
| 724 | |
[email protected] | e0f3e14 | 2012-07-26 03:31:34 | [diff] [blame] | 725 | void CrashTab(WebContents* web_contents) { |
Lukasz Anforowicz | f14b545 | 2017-10-02 20:10:34 | [diff] [blame] | 726 | RenderProcessHost* rph = web_contents->GetMainFrame()->GetProcess(); |
[email protected] | 8ffad4e | 2014-01-02 23:18:26 | [diff] [blame] | 727 | RenderProcessHostWatcher watcher( |
| 728 | rph, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); |
Wez | 0abfbf51 | 2018-03-03 01:54:45 | [diff] [blame] | 729 | rph->Shutdown(0); |
[email protected] | 8ffad4e | 2014-01-02 23:18:26 | [diff] [blame] | 730 | watcher.Wait(); |
[email protected] | e0f3e14 | 2012-07-26 03:31:34 | [diff] [blame] | 731 | } |
[email protected] | 6ddc6e3f2 | 2012-07-26 01:15:35 | [diff] [blame] | 732 | |
Charlie Reis | e2c2c49 | 2018-06-15 21:34:04 | [diff] [blame] | 733 | void PwnCommitIPC(WebContents* web_contents, |
| 734 | const GURL& target_url, |
| 735 | const GURL& new_url, |
| 736 | const url::Origin& new_origin) { |
| 737 | // This will be cleaned up when |web_contents| is destroyed. |
| 738 | new CommitOriginInterceptor(web_contents, target_url, new_url, new_origin); |
| 739 | } |
| 740 | |
creis | 0f90533 | 2017-05-01 17:07:30 | [diff] [blame] | 741 | void SimulateUnresponsiveRenderer(WebContents* web_contents, |
| 742 | RenderWidgetHost* widget) { |
| 743 | static_cast<WebContentsImpl*>(web_contents) |
Lukasz Anforowicz | 52b9372 | 2018-06-20 16:11:39 | [diff] [blame] | 744 | ->RendererUnresponsive(RenderWidgetHostImpl::From(widget), |
| 745 | base::DoNothing::Repeatedly()); |
creis | 0f90533 | 2017-05-01 17:07:30 | [diff] [blame] | 746 | } |
| 747 | |
[email protected] | 6b614747 | 2014-06-27 17:37:07 | [diff] [blame] | 748 | #if defined(USE_AURA) |
| 749 | bool IsResizeComplete(aura::test::WindowEventDispatcherTestApi* dispatcher_test, |
| 750 | RenderWidgetHostImpl* widget_host) { |
Saman Sami | ac97cd0 | 2018-01-19 19:04:10 | [diff] [blame] | 751 | dispatcher_test->WaitUntilPointerMovesDispatched(); |
Fady Samuel | 0b91182 | 2018-04-25 13:22:16 | [diff] [blame] | 752 | widget_host->SynchronizeVisualProperties(); |
Fady Samuel | 44e5e78d | 2018-05-08 05:46:04 | [diff] [blame] | 753 | return !widget_host->visual_properties_ack_pending_for_testing(); |
[email protected] | 6b614747 | 2014-06-27 17:37:07 | [diff] [blame] | 754 | } |
| 755 | |
| 756 | void WaitForResizeComplete(WebContents* web_contents) { |
| 757 | aura::Window* content = web_contents->GetContentNativeView(); |
| 758 | if (!content) |
| 759 | return; |
| 760 | |
| 761 | aura::WindowTreeHost* window_host = content->GetHost(); |
| 762 | aura::WindowEventDispatcher* dispatcher = window_host->dispatcher(); |
| 763 | aura::test::WindowEventDispatcherTestApi dispatcher_test(dispatcher); |
avi | f9ab5d94 | 2015-10-15 14:05:44 | [diff] [blame] | 764 | RenderWidgetHostImpl* widget_host = RenderWidgetHostImpl::From( |
| 765 | web_contents->GetRenderViewHost()->GetWidget()); |
[email protected] | 6b614747 | 2014-06-27 17:37:07 | [diff] [blame] | 766 | if (!IsResizeComplete(&dispatcher_test, widget_host)) { |
| 767 | WindowedNotificationObserver resize_observer( |
Fady Samuel | 44e5e78d | 2018-05-08 05:46:04 | [diff] [blame] | 768 | NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_VISUAL_PROPERTIES, |
[email protected] | 6b614747 | 2014-06-27 17:37:07 | [diff] [blame] | 769 | base::Bind(IsResizeComplete, &dispatcher_test, widget_host)); |
| 770 | resize_observer.Wait(); |
| 771 | } |
| 772 | } |
jaekyun | 23d007d | 2015-03-11 02:24:56 | [diff] [blame] | 773 | #elif defined(OS_ANDROID) |
| 774 | bool IsResizeComplete(RenderWidgetHostImpl* widget_host) { |
Fady Samuel | 44e5e78d | 2018-05-08 05:46:04 | [diff] [blame] | 775 | return !widget_host->visual_properties_ack_pending_for_testing(); |
jaekyun | 23d007d | 2015-03-11 02:24:56 | [diff] [blame] | 776 | } |
| 777 | |
| 778 | void WaitForResizeComplete(WebContents* web_contents) { |
avi | f9ab5d94 | 2015-10-15 14:05:44 | [diff] [blame] | 779 | RenderWidgetHostImpl* widget_host = RenderWidgetHostImpl::From( |
| 780 | web_contents->GetRenderViewHost()->GetWidget()); |
jaekyun | 23d007d | 2015-03-11 02:24:56 | [diff] [blame] | 781 | if (!IsResizeComplete(widget_host)) { |
| 782 | WindowedNotificationObserver resize_observer( |
Fady Samuel | 44e5e78d | 2018-05-08 05:46:04 | [diff] [blame] | 783 | NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_VISUAL_PROPERTIES, |
jaekyun | 23d007d | 2015-03-11 02:24:56 | [diff] [blame] | 784 | base::Bind(IsResizeComplete, widget_host)); |
| 785 | resize_observer.Wait(); |
| 786 | } |
| 787 | } |
| 788 | #endif |
[email protected] | 6b614747 | 2014-06-27 17:37:07 | [diff] [blame] | 789 | |
[email protected] | 0f061d9 | 2012-10-24 17:30:25 | [diff] [blame] | 790 | void SimulateMouseClick(WebContents* web_contents, |
| 791 | int modifiers, |
[email protected] | 180ef24 | 2013-11-07 06:50:46 | [diff] [blame] | 792 | blink::WebMouseEvent::Button button) { |
[email protected] | fc2b46b | 2014-05-03 16:33:45 | [diff] [blame] | 793 | int x = web_contents->GetContainerBounds().width() / 2; |
| 794 | int y = web_contents->GetContainerBounds().height() / 2; |
[email protected] | 861f978 | 2013-03-05 03:29:54 | [diff] [blame] | 795 | SimulateMouseClickAt(web_contents, modifiers, button, gfx::Point(x, y)); |
| 796 | } |
| 797 | |
| 798 | void SimulateMouseClickAt(WebContents* web_contents, |
| 799 | int modifiers, |
[email protected] | 180ef24 | 2013-11-07 06:50:46 | [diff] [blame] | 800 | blink::WebMouseEvent::Button button, |
[email protected] | 861f978 | 2013-03-05 03:29:54 | [diff] [blame] | 801 | const gfx::Point& point) { |
Daniel Cheng | 224569ee | 2018-04-25 05:45:06 | [diff] [blame] | 802 | blink::WebMouseEvent mouse_event(blink::WebInputEvent::kMouseDown, modifiers, |
| 803 | ui::EventTimeForNow()); |
[email protected] | 0f061d9 | 2012-10-24 17:30:25 | [diff] [blame] | 804 | mouse_event.button = button; |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 805 | mouse_event.SetPositionInWidget(point.x(), point.y()); |
mustaq | c51f3aab | 2017-04-05 15:43:11 | [diff] [blame] | 806 | // Mac needs positionInScreen for events to plugins. |
[email protected] | fc2b46b | 2014-05-03 16:33:45 | [diff] [blame] | 807 | gfx::Rect offset = web_contents->GetContainerBounds(); |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 808 | mouse_event.SetPositionInScreen(point.x() + offset.x(), |
mustaq | c51f3aab | 2017-04-05 15:43:11 | [diff] [blame] | 809 | point.y() + offset.y()); |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 810 | mouse_event.click_count = 1; |
avi | f9ab5d94 | 2015-10-15 14:05:44 | [diff] [blame] | 811 | web_contents->GetRenderViewHost()->GetWidget()->ForwardMouseEvent( |
| 812 | mouse_event); |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 813 | mouse_event.SetType(blink::WebInputEvent::kMouseUp); |
avi | f9ab5d94 | 2015-10-15 14:05:44 | [diff] [blame] | 814 | web_contents->GetRenderViewHost()->GetWidget()->ForwardMouseEvent( |
| 815 | mouse_event); |
[email protected] | 7d478cb | 2012-07-24 17:19:42 | [diff] [blame] | 816 | } |
| 817 | |
W. James MacLean | 82b029b | 2017-10-23 15:05:43 | [diff] [blame] | 818 | void SimulateRoutedMouseClickAt(WebContents* web_contents, |
| 819 | int modifiers, |
| 820 | blink::WebMouseEvent::Button button, |
| 821 | const gfx::Point& point) { |
| 822 | content::WebContentsImpl* web_contents_impl = |
| 823 | static_cast<content::WebContentsImpl*>(web_contents); |
| 824 | content::RenderWidgetHostViewBase* rwhvb = |
| 825 | static_cast<content::RenderWidgetHostViewBase*>( |
| 826 | web_contents->GetRenderWidgetHostView()); |
Daniel Cheng | 224569ee | 2018-04-25 05:45:06 | [diff] [blame] | 827 | blink::WebMouseEvent mouse_event(blink::WebInputEvent::kMouseDown, modifiers, |
| 828 | ui::EventTimeForNow()); |
W. James MacLean | 82b029b | 2017-10-23 15:05:43 | [diff] [blame] | 829 | mouse_event.button = button; |
| 830 | mouse_event.SetPositionInWidget(point.x(), point.y()); |
| 831 | // Mac needs positionInScreen for events to plugins. |
| 832 | gfx::Rect offset = web_contents->GetContainerBounds(); |
| 833 | mouse_event.SetPositionInScreen(point.x() + offset.x(), |
| 834 | point.y() + offset.y()); |
| 835 | mouse_event.click_count = 1; |
| 836 | web_contents_impl->GetInputEventRouter()->RouteMouseEvent(rwhvb, &mouse_event, |
| 837 | ui::LatencyInfo()); |
| 838 | mouse_event.SetType(blink::WebInputEvent::kMouseUp); |
| 839 | web_contents_impl->GetInputEventRouter()->RouteMouseEvent(rwhvb, &mouse_event, |
| 840 | ui::LatencyInfo()); |
| 841 | } |
| 842 | |
Ken Buchanan | d1d30d1 | 2018-10-04 22:48:04 | [diff] [blame] | 843 | void SendMouseDownToWidget(RenderWidgetHost* target, |
| 844 | int modifiers, |
| 845 | blink::WebMouseEvent::Button button) { |
| 846 | auto* view = static_cast<content::RenderWidgetHostImpl*>(target)->GetView(); |
| 847 | |
| 848 | blink::WebMouseEvent mouse_event(blink::WebInputEvent::kMouseDown, modifiers, |
| 849 | ui::EventTimeForNow()); |
| 850 | mouse_event.button = button; |
| 851 | int x = view->GetViewBounds().width() / 2; |
| 852 | int y = view->GetViewBounds().height() / 2; |
| 853 | mouse_event.SetPositionInWidget(x, y); |
| 854 | mouse_event.click_count = 1; |
| 855 | target->ForwardMouseEvent(mouse_event); |
| 856 | } |
| 857 | |
[email protected] | 7d478cb | 2012-07-24 17:19:42 | [diff] [blame] | 858 | void SimulateMouseEvent(WebContents* web_contents, |
[email protected] | 180ef24 | 2013-11-07 06:50:46 | [diff] [blame] | 859 | blink::WebInputEvent::Type type, |
[email protected] | 7d478cb | 2012-07-24 17:19:42 | [diff] [blame] | 860 | const gfx::Point& point) { |
Daniel Cheng | 224569ee | 2018-04-25 05:45:06 | [diff] [blame] | 861 | blink::WebMouseEvent mouse_event(type, blink::WebInputEvent::kNoModifiers, |
| 862 | ui::EventTimeForNow()); |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 863 | mouse_event.SetPositionInWidget(point.x(), point.y()); |
avi | f9ab5d94 | 2015-10-15 14:05:44 | [diff] [blame] | 864 | web_contents->GetRenderViewHost()->GetWidget()->ForwardMouseEvent( |
| 865 | mouse_event); |
[email protected] | 7d478cb | 2012-07-24 17:19:42 | [diff] [blame] | 866 | } |
| 867 | |
W. James MacLean | 4263cfc | 2018-05-10 15:57:52 | [diff] [blame] | 868 | void SimulateRoutedMouseEvent(WebContents* web_contents, |
| 869 | blink::WebInputEvent::Type type, |
| 870 | const gfx::Point& point) { |
| 871 | content::WebContentsImpl* web_contents_impl = |
| 872 | static_cast<content::WebContentsImpl*>(web_contents); |
| 873 | content::RenderWidgetHostViewBase* rwhvb = |
| 874 | static_cast<content::RenderWidgetHostViewBase*>( |
| 875 | web_contents->GetRenderWidgetHostView()); |
| 876 | blink::WebMouseEvent mouse_event(type, 0, ui::EventTimeForNow()); |
| 877 | mouse_event.SetPositionInWidget(point.x(), point.y()); |
| 878 | // Mac needs positionInScreen for events to plugins. |
| 879 | gfx::Rect offset = web_contents->GetContainerBounds(); |
| 880 | mouse_event.SetPositionInScreen(point.x() + offset.x(), |
| 881 | point.y() + offset.y()); |
| 882 | |
| 883 | web_contents_impl->GetInputEventRouter()->RouteMouseEvent(rwhvb, &mouse_event, |
| 884 | ui::LatencyInfo()); |
| 885 | } |
| 886 | |
wjmaclean | 73b15a2 | 2015-09-25 15:56:40 | [diff] [blame] | 887 | void SimulateMouseWheelEvent(WebContents* web_contents, |
| 888 | const gfx::Point& point, |
sahel | e2b952b | 2017-09-13 18:28:49 | [diff] [blame] | 889 | const gfx::Vector2d& delta, |
| 890 | const blink::WebMouseWheelEvent::Phase phase) { |
Daniel Cheng | 224569ee | 2018-04-25 05:45:06 | [diff] [blame] | 891 | blink::WebMouseWheelEvent wheel_event(blink::WebInputEvent::kMouseWheel, |
| 892 | blink::WebInputEvent::kNoModifiers, |
| 893 | ui::EventTimeForNow()); |
dtapuska | 899ac22 | 2017-01-03 18:09:16 | [diff] [blame] | 894 | |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 895 | wheel_event.SetPositionInWidget(point.x(), point.y()); |
| 896 | wheel_event.delta_x = delta.x(); |
| 897 | wheel_event.delta_y = delta.y(); |
sahel | e2b952b | 2017-09-13 18:28:49 | [diff] [blame] | 898 | wheel_event.phase = phase; |
avi | f9ab5d94 | 2015-10-15 14:05:44 | [diff] [blame] | 899 | RenderWidgetHostImpl* widget_host = RenderWidgetHostImpl::From( |
| 900 | web_contents->GetRenderViewHost()->GetWidget()); |
wjmaclean | 73b15a2 | 2015-09-25 15:56:40 | [diff] [blame] | 901 | widget_host->ForwardWheelEvent(wheel_event); |
| 902 | } |
| 903 | |
Kevin McNee | bc61eb6 | 2017-11-13 20:39:14 | [diff] [blame] | 904 | #if !defined(OS_MACOSX) |
| 905 | void SimulateMouseWheelCtrlZoomEvent(WebContents* web_contents, |
| 906 | const gfx::Point& point, |
| 907 | bool zoom_in, |
| 908 | blink::WebMouseWheelEvent::Phase phase) { |
Daniel Cheng | 224569ee | 2018-04-25 05:45:06 | [diff] [blame] | 909 | blink::WebMouseWheelEvent wheel_event(blink::WebInputEvent::kMouseWheel, |
| 910 | blink::WebInputEvent::kControlKey, |
| 911 | ui::EventTimeForNow()); |
Kevin McNee | bc61eb6 | 2017-11-13 20:39:14 | [diff] [blame] | 912 | |
| 913 | wheel_event.SetPositionInWidget(point.x(), point.y()); |
| 914 | wheel_event.delta_y = |
| 915 | (zoom_in ? 1.0 : -1.0) * ui::MouseWheelEvent::kWheelDelta; |
| 916 | wheel_event.wheel_ticks_y = (zoom_in ? 1.0 : -1.0); |
| 917 | wheel_event.has_precise_scrolling_deltas = false; |
| 918 | wheel_event.phase = phase; |
| 919 | RenderWidgetHostImpl* widget_host = RenderWidgetHostImpl::From( |
| 920 | web_contents->GetRenderViewHost()->GetWidget()); |
| 921 | widget_host->ForwardWheelEvent(wheel_event); |
| 922 | } |
| 923 | #endif // !defined(OS_MACOSX) |
| 924 | |
| 925 | void SimulateGesturePinchSequence(WebContents* web_contents, |
| 926 | const gfx::Point& point, |
| 927 | float scale, |
| 928 | blink::WebGestureDevice source_device) { |
| 929 | RenderWidgetHostImpl* widget_host = RenderWidgetHostImpl::From( |
| 930 | web_contents->GetRenderViewHost()->GetWidget()); |
| 931 | |
Daniel Cheng | 224569ee | 2018-04-25 05:45:06 | [diff] [blame] | 932 | blink::WebGestureEvent pinch_begin(blink::WebInputEvent::kGesturePinchBegin, |
| 933 | blink::WebInputEvent::kNoModifiers, |
| 934 | ui::EventTimeForNow(), source_device); |
Ella Ge | 1116059d | 2018-03-21 02:06:13 | [diff] [blame] | 935 | pinch_begin.SetPositionInWidget(gfx::PointF(point)); |
| 936 | pinch_begin.SetPositionInScreen(gfx::PointF(point)); |
Kevin McNee | 297980d | 2018-06-04 21:32:14 | [diff] [blame] | 937 | pinch_begin.SetNeedsWheelEvent(source_device == |
| 938 | blink::kWebGestureDeviceTouchpad); |
Kevin McNee | bc61eb6 | 2017-11-13 20:39:14 | [diff] [blame] | 939 | widget_host->ForwardGestureEvent(pinch_begin); |
| 940 | |
| 941 | blink::WebGestureEvent pinch_update(pinch_begin); |
| 942 | pinch_update.SetType(blink::WebInputEvent::kGesturePinchUpdate); |
| 943 | pinch_update.data.pinch_update.scale = scale; |
Kevin McNee | 297980d | 2018-06-04 21:32:14 | [diff] [blame] | 944 | pinch_update.SetNeedsWheelEvent(source_device == |
| 945 | blink::kWebGestureDeviceTouchpad); |
Kevin McNee | bc61eb6 | 2017-11-13 20:39:14 | [diff] [blame] | 946 | widget_host->ForwardGestureEvent(pinch_update); |
| 947 | |
| 948 | blink::WebGestureEvent pinch_end(pinch_begin); |
Kevin McNee | 297980d | 2018-06-04 21:32:14 | [diff] [blame] | 949 | pinch_end.SetType(blink::WebInputEvent::kGesturePinchEnd); |
| 950 | pinch_end.SetNeedsWheelEvent(source_device == |
| 951 | blink::kWebGestureDeviceTouchpad); |
Kevin McNee | bc61eb6 | 2017-11-13 20:39:14 | [diff] [blame] | 952 | widget_host->ForwardGestureEvent(pinch_end); |
| 953 | } |
| 954 | |
wjmaclean | 73b15a2 | 2015-09-25 15:56:40 | [diff] [blame] | 955 | void SimulateGestureScrollSequence(WebContents* web_contents, |
| 956 | const gfx::Point& point, |
| 957 | const gfx::Vector2dF& delta) { |
avi | f9ab5d94 | 2015-10-15 14:05:44 | [diff] [blame] | 958 | RenderWidgetHostImpl* widget_host = RenderWidgetHostImpl::From( |
| 959 | web_contents->GetRenderViewHost()->GetWidget()); |
wjmaclean | 73b15a2 | 2015-09-25 15:56:40 | [diff] [blame] | 960 | |
dtapuska | 899ac22 | 2017-01-03 18:09:16 | [diff] [blame] | 961 | blink::WebGestureEvent scroll_begin( |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 962 | blink::WebGestureEvent::kGestureScrollBegin, |
Daniel Cheng | 224569ee | 2018-04-25 05:45:06 | [diff] [blame] | 963 | blink::WebInputEvent::kNoModifiers, ui::EventTimeForNow(), |
Ella Ge | 1116059d | 2018-03-21 02:06:13 | [diff] [blame] | 964 | blink::kWebGestureDeviceTouchpad); |
| 965 | scroll_begin.SetPositionInWidget(gfx::PointF(point)); |
Sahel Sharify | dbafed5 | 2017-08-03 16:59:12 | [diff] [blame] | 966 | scroll_begin.data.scroll_begin.delta_x_hint = delta.x(); |
| 967 | scroll_begin.data.scroll_begin.delta_y_hint = delta.y(); |
wjmaclean | 73b15a2 | 2015-09-25 15:56:40 | [diff] [blame] | 968 | widget_host->ForwardGestureEvent(scroll_begin); |
| 969 | |
dtapuska | 899ac22 | 2017-01-03 18:09:16 | [diff] [blame] | 970 | blink::WebGestureEvent scroll_update( |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 971 | blink::WebGestureEvent::kGestureScrollUpdate, |
Daniel Cheng | 224569ee | 2018-04-25 05:45:06 | [diff] [blame] | 972 | blink::WebInputEvent::kNoModifiers, ui::EventTimeForNow(), |
Ella Ge | 1116059d | 2018-03-21 02:06:13 | [diff] [blame] | 973 | blink::kWebGestureDeviceTouchpad); |
| 974 | scroll_update.SetPositionInWidget(gfx::PointF(point)); |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 975 | scroll_update.data.scroll_update.delta_x = delta.x(); |
| 976 | scroll_update.data.scroll_update.delta_y = delta.y(); |
| 977 | scroll_update.data.scroll_update.velocity_x = 0; |
| 978 | scroll_update.data.scroll_update.velocity_y = 0; |
wjmaclean | 73b15a2 | 2015-09-25 15:56:40 | [diff] [blame] | 979 | widget_host->ForwardGestureEvent(scroll_update); |
| 980 | |
Daniel Cheng | 224569ee | 2018-04-25 05:45:06 | [diff] [blame] | 981 | blink::WebGestureEvent scroll_end(blink::WebGestureEvent::kGestureScrollEnd, |
| 982 | blink::WebInputEvent::kNoModifiers, |
| 983 | ui::EventTimeForNow(), |
| 984 | blink::kWebGestureDeviceTouchpad); |
Ella Ge | 1116059d | 2018-03-21 02:06:13 | [diff] [blame] | 985 | scroll_end.SetPositionInWidget(gfx::PointF(point)); |
wjmaclean | 73b15a2 | 2015-09-25 15:56:40 | [diff] [blame] | 986 | widget_host->ForwardGestureEvent(scroll_end); |
| 987 | } |
| 988 | |
khmel | d926940 | 2016-06-04 03:59:34 | [diff] [blame] | 989 | void SimulateGestureFlingSequence(WebContents* web_contents, |
| 990 | const gfx::Point& point, |
| 991 | const gfx::Vector2dF& velocity) { |
| 992 | RenderWidgetHostImpl* widget_host = RenderWidgetHostImpl::From( |
| 993 | web_contents->GetRenderViewHost()->GetWidget()); |
| 994 | |
dtapuska | 899ac22 | 2017-01-03 18:09:16 | [diff] [blame] | 995 | blink::WebGestureEvent scroll_begin( |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 996 | blink::WebGestureEvent::kGestureScrollBegin, |
Daniel Cheng | 224569ee | 2018-04-25 05:45:06 | [diff] [blame] | 997 | blink::WebInputEvent::kNoModifiers, ui::EventTimeForNow(), |
Ella Ge | 1116059d | 2018-03-21 02:06:13 | [diff] [blame] | 998 | blink::kWebGestureDeviceTouchpad); |
| 999 | scroll_begin.SetPositionInWidget(gfx::PointF(point)); |
khmel | d926940 | 2016-06-04 03:59:34 | [diff] [blame] | 1000 | widget_host->ForwardGestureEvent(scroll_begin); |
| 1001 | |
Daniel Cheng | 224569ee | 2018-04-25 05:45:06 | [diff] [blame] | 1002 | blink::WebGestureEvent scroll_end(blink::WebGestureEvent::kGestureScrollEnd, |
| 1003 | blink::WebInputEvent::kNoModifiers, |
| 1004 | ui::EventTimeForNow(), |
| 1005 | blink::kWebGestureDeviceTouchpad); |
Ella Ge | 1116059d | 2018-03-21 02:06:13 | [diff] [blame] | 1006 | scroll_end.SetPositionInWidget(gfx::PointF(point)); |
khmel | d926940 | 2016-06-04 03:59:34 | [diff] [blame] | 1007 | widget_host->ForwardGestureEvent(scroll_end); |
| 1008 | |
Daniel Cheng | 224569ee | 2018-04-25 05:45:06 | [diff] [blame] | 1009 | blink::WebGestureEvent fling_start(blink::WebGestureEvent::kGestureFlingStart, |
| 1010 | blink::WebInputEvent::kNoModifiers, |
| 1011 | ui::EventTimeForNow(), |
| 1012 | blink::kWebGestureDeviceTouchpad); |
Ella Ge | 1116059d | 2018-03-21 02:06:13 | [diff] [blame] | 1013 | fling_start.SetPositionInWidget(gfx::PointF(point)); |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 1014 | fling_start.data.fling_start.target_viewport = false; |
| 1015 | fling_start.data.fling_start.velocity_x = velocity.x(); |
| 1016 | fling_start.data.fling_start.velocity_y = velocity.y(); |
khmel | d926940 | 2016-06-04 03:59:34 | [diff] [blame] | 1017 | widget_host->ForwardGestureEvent(fling_start); |
| 1018 | } |
| 1019 | |
Kevin McNee | 08bf6de6 | 2017-11-08 15:24:48 | [diff] [blame] | 1020 | void SimulateGestureEvent(WebContents* web_contents, |
| 1021 | const blink::WebGestureEvent& gesture_event, |
| 1022 | const ui::LatencyInfo& latency) { |
| 1023 | RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>( |
| 1024 | web_contents->GetRenderWidgetHostView()); |
| 1025 | view->ProcessGestureEvent(gesture_event, latency); |
| 1026 | } |
| 1027 | |
Xida Chen | 2eec314f | 2018-06-07 11:42:42 | [diff] [blame] | 1028 | void SimulateTouchGestureAt(WebContents* web_contents, |
| 1029 | const gfx::Point& point, |
| 1030 | blink::WebInputEvent::Type type) { |
| 1031 | blink::WebGestureEvent gesture(type, 0, ui::EventTimeForNow(), |
| 1032 | blink::kWebGestureDeviceTouchscreen); |
| 1033 | gesture.SetPositionInWidget(gfx::PointF(point)); |
avi | f9ab5d94 | 2015-10-15 14:05:44 | [diff] [blame] | 1034 | RenderWidgetHostImpl* widget_host = RenderWidgetHostImpl::From( |
| 1035 | web_contents->GetRenderViewHost()->GetWidget()); |
Xida Chen | 2eec314f | 2018-06-07 11:42:42 | [diff] [blame] | 1036 | widget_host->ForwardGestureEvent(gesture); |
| 1037 | } |
| 1038 | |
| 1039 | void SimulateTapDownAt(WebContents* web_contents, const gfx::Point& point) { |
| 1040 | SimulateTouchGestureAt(web_contents, point, |
| 1041 | blink::WebGestureEvent::kGestureTapDown); |
| 1042 | } |
| 1043 | |
| 1044 | void SimulateTapAt(WebContents* web_contents, const gfx::Point& point) { |
| 1045 | SimulateTouchGestureAt(web_contents, point, |
| 1046 | blink::WebGestureEvent::kGestureTap); |
myid.shin | 8143cbe | 2015-03-18 17:26:10 | [diff] [blame] | 1047 | } |
| 1048 | |
| 1049 | void SimulateTapWithModifiersAt(WebContents* web_contents, |
| 1050 | unsigned modifiers, |
| 1051 | const gfx::Point& point) { |
Ella Ge | 1116059d | 2018-03-21 02:06:13 | [diff] [blame] | 1052 | blink::WebGestureEvent tap(blink::WebGestureEvent::kGestureTap, modifiers, |
Daniel Cheng | 224569ee | 2018-04-25 05:45:06 | [diff] [blame] | 1053 | ui::EventTimeForNow(), |
Ella Ge | 1116059d | 2018-03-21 02:06:13 | [diff] [blame] | 1054 | blink::kWebGestureDeviceTouchpad); |
| 1055 | tap.SetPositionInWidget(gfx::PointF(point)); |
avi | f9ab5d94 | 2015-10-15 14:05:44 | [diff] [blame] | 1056 | RenderWidgetHostImpl* widget_host = RenderWidgetHostImpl::From( |
| 1057 | web_contents->GetRenderViewHost()->GetWidget()); |
[email protected] | 709c57e | 2014-08-08 06:46:34 | [diff] [blame] | 1058 | widget_host->ForwardGestureEvent(tap); |
[email protected] | c8befac4 | 2014-05-22 15:13:27 | [diff] [blame] | 1059 | } |
| 1060 | |
wjmaclean | e31234f | 2015-12-14 17:20:45 | [diff] [blame] | 1061 | #if defined(USE_AURA) |
wjmaclean | 6aefc3a | 2015-06-22 21:58:29 | [diff] [blame] | 1062 | void SimulateTouchPressAt(WebContents* web_contents, const gfx::Point& point) { |
lanwei | 6472567 | 2017-03-16 20:56:05 | [diff] [blame] | 1063 | ui::TouchEvent touch( |
| 1064 | ui::ET_TOUCH_PRESSED, point, base::TimeTicks(), |
| 1065 | ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0)); |
wjmaclean | e31234f | 2015-12-14 17:20:45 | [diff] [blame] | 1066 | static_cast<RenderWidgetHostViewAura*>( |
| 1067 | web_contents->GetRenderWidgetHostView()) |
| 1068 | ->OnTouchEvent(&touch); |
wjmaclean | 6aefc3a | 2015-06-22 21:58:29 | [diff] [blame] | 1069 | } |
Pedro Amaral | 55cc4c00 | 2017-12-20 21:33:48 | [diff] [blame] | 1070 | |
Ella Ge | aa4f1763 | 2018-04-04 00:05:58 | [diff] [blame] | 1071 | void SimulateLongTapAt(WebContents* web_contents, const gfx::Point& point) { |
Pedro Amaral | 55cc4c00 | 2017-12-20 21:33:48 | [diff] [blame] | 1072 | RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>( |
| 1073 | web_contents->GetRenderWidgetHostView()); |
| 1074 | |
| 1075 | ui::TouchEvent touch_start( |
| 1076 | ui::ET_TOUCH_PRESSED, point, base::TimeTicks(), |
| 1077 | ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0)); |
| 1078 | rwhva->OnTouchEvent(&touch_start); |
| 1079 | |
| 1080 | ui::GestureEventDetails tap_down_details(ui::ET_GESTURE_TAP_DOWN); |
| 1081 | tap_down_details.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHSCREEN); |
| 1082 | ui::GestureEvent tap_down(point.x(), point.y(), 0, ui::EventTimeForNow(), |
| 1083 | tap_down_details, touch_start.unique_event_id()); |
| 1084 | rwhva->OnGestureEvent(&tap_down); |
| 1085 | |
| 1086 | ui::GestureEventDetails long_press_details(ui::ET_GESTURE_LONG_PRESS); |
| 1087 | long_press_details.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHSCREEN); |
| 1088 | ui::GestureEvent long_press(point.x(), point.y(), 0, ui::EventTimeForNow(), |
| 1089 | long_press_details, |
| 1090 | touch_start.unique_event_id()); |
| 1091 | rwhva->OnGestureEvent(&long_press); |
| 1092 | |
| 1093 | ui::TouchEvent touch_end( |
| 1094 | ui::ET_TOUCH_RELEASED, point, base::TimeTicks(), |
| 1095 | ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0)); |
| 1096 | rwhva->OnTouchEvent(&touch_end); |
Ella Ge | aa4f1763 | 2018-04-04 00:05:58 | [diff] [blame] | 1097 | |
| 1098 | ui::GestureEventDetails long_tap_details(ui::ET_GESTURE_LONG_TAP); |
| 1099 | long_tap_details.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHSCREEN); |
| 1100 | ui::GestureEvent long_tap(point.x(), point.y(), 0, ui::EventTimeForNow(), |
| 1101 | long_tap_details, touch_end.unique_event_id()); |
| 1102 | rwhva->OnGestureEvent(&long_tap); |
Pedro Amaral | 55cc4c00 | 2017-12-20 21:33:48 | [diff] [blame] | 1103 | } |
wjmaclean | e31234f | 2015-12-14 17:20:45 | [diff] [blame] | 1104 | #endif |
wjmaclean | 6aefc3a | 2015-06-22 21:58:29 | [diff] [blame] | 1105 | |
[email protected] | 26151fd | 2012-07-20 23:38:57 | [diff] [blame] | 1106 | void SimulateKeyPress(WebContents* web_contents, |
dtapuska | 8b1bdc8 | 2016-06-07 21:39:48 | [diff] [blame] | 1107 | ui::DomKey key, |
| 1108 | ui::DomCode code, |
[email protected] | 6dc5a33 | 2013-09-11 01:02:10 | [diff] [blame] | 1109 | ui::KeyboardCode key_code, |
[email protected] | 26151fd | 2012-07-20 23:38:57 | [diff] [blame] | 1110 | bool control, |
| 1111 | bool shift, |
| 1112 | bool alt, |
| 1113 | bool command) { |
Lei Zhang | 6cef326 | 2017-08-16 15:44:38 | [diff] [blame] | 1114 | SimulateKeyPressImpl(web_contents, key, code, key_code, control, shift, alt, |
| 1115 | command, /*send_char=*/true); |
| 1116 | } |
[email protected] | ec8e0595 | 2013-09-19 21:45:40 | [diff] [blame] | 1117 | |
Lei Zhang | 6cef326 | 2017-08-16 15:44:38 | [diff] [blame] | 1118 | void SimulateKeyPressWithoutChar(WebContents* web_contents, |
| 1119 | ui::DomKey key, |
| 1120 | ui::DomCode code, |
| 1121 | ui::KeyboardCode key_code, |
| 1122 | bool control, |
| 1123 | bool shift, |
| 1124 | bool alt, |
| 1125 | bool command) { |
| 1126 | SimulateKeyPressImpl(web_contents, key, code, key_code, control, shift, alt, |
| 1127 | command, /*send_char=*/false); |
| 1128 | } |
[email protected] | ec8e0595 | 2013-09-19 21:45:40 | [diff] [blame] | 1129 | |
Lei Zhang | 6cef326 | 2017-08-16 15:44:38 | [diff] [blame] | 1130 | ScopedSimulateModifierKeyPress::ScopedSimulateModifierKeyPress( |
| 1131 | WebContents* web_contents, |
| 1132 | bool control, |
| 1133 | bool shift, |
| 1134 | bool alt, |
| 1135 | bool command) |
| 1136 | : web_contents_(web_contents), |
| 1137 | modifiers_(0), |
| 1138 | control_(control), |
| 1139 | shift_(shift), |
| 1140 | alt_(alt), |
| 1141 | command_(command) { |
| 1142 | modifiers_ = |
| 1143 | SimulateModifierKeysDown(web_contents_, control_, shift_, alt_, command_); |
| 1144 | } |
[email protected] | ec8e0595 | 2013-09-19 21:45:40 | [diff] [blame] | 1145 | |
Lei Zhang | 6cef326 | 2017-08-16 15:44:38 | [diff] [blame] | 1146 | ScopedSimulateModifierKeyPress::~ScopedSimulateModifierKeyPress() { |
| 1147 | modifiers_ = SimulateModifierKeysUp(web_contents_, control_, shift_, alt_, |
| 1148 | command_, modifiers_); |
| 1149 | DCHECK_EQ(0, modifiers_); |
| 1150 | } |
[email protected] | ec8e0595 | 2013-09-19 21:45:40 | [diff] [blame] | 1151 | |
Lei Zhang | 6cef326 | 2017-08-16 15:44:38 | [diff] [blame] | 1152 | void ScopedSimulateModifierKeyPress::MouseClickAt( |
| 1153 | int additional_modifiers, |
| 1154 | blink::WebMouseEvent::Button button, |
| 1155 | const gfx::Point& point) { |
| 1156 | SimulateMouseClickAt(web_contents_, modifiers_ | additional_modifiers, button, |
| 1157 | point); |
| 1158 | } |
[email protected] | ec8e0595 | 2013-09-19 21:45:40 | [diff] [blame] | 1159 | |
Lei Zhang | 6cef326 | 2017-08-16 15:44:38 | [diff] [blame] | 1160 | void ScopedSimulateModifierKeyPress::KeyPress(ui::DomKey key, |
| 1161 | ui::DomCode code, |
| 1162 | ui::KeyboardCode key_code) { |
| 1163 | SimulateKeyEvent(web_contents_, key, code, key_code, /*send_char=*/true, |
| 1164 | modifiers_); |
| 1165 | } |
[email protected] | 26151fd | 2012-07-20 23:38:57 | [diff] [blame] | 1166 | |
Lei Zhang | 6cef326 | 2017-08-16 15:44:38 | [diff] [blame] | 1167 | void ScopedSimulateModifierKeyPress::KeyPressWithoutChar( |
| 1168 | ui::DomKey key, |
| 1169 | ui::DomCode code, |
| 1170 | ui::KeyboardCode key_code) { |
| 1171 | SimulateKeyEvent(web_contents_, key, code, key_code, /*send_char=*/false, |
| 1172 | modifiers_); |
[email protected] | 26151fd | 2012-07-20 23:38:57 | [diff] [blame] | 1173 | } |
| 1174 | |
lunalu | 2ddb05a8 | 2016-09-19 19:22:07 | [diff] [blame] | 1175 | bool IsWebcamAvailableOnSystem(WebContents* web_contents) { |
| 1176 | std::string result; |
| 1177 | EXPECT_TRUE(content::ExecuteScriptAndExtractString( |
| 1178 | web_contents, kHasVideoInputDeviceOnSystem, &result)); |
| 1179 | return result == kHasVideoInputDevice; |
| 1180 | } |
| 1181 | |
nick | adef4a5 | 2016-06-09 18:45:54 | [diff] [blame] | 1182 | RenderFrameHost* ConvertToRenderFrameHost(WebContents* web_contents) { |
| 1183 | return web_contents->GetMainFrame(); |
[email protected] | ff4657ee | 2014-03-15 01:08:15 | [diff] [blame] | 1184 | } |
| 1185 | |
nick | adef4a5 | 2016-06-09 18:45:54 | [diff] [blame] | 1186 | RenderFrameHost* ConvertToRenderFrameHost(RenderFrameHost* render_frame_host) { |
| 1187 | return render_frame_host; |
[email protected] | ff4657ee | 2014-03-15 01:08:15 | [diff] [blame] | 1188 | } |
| 1189 | |
alexmos | 4cf2aa3 | 2015-07-15 23:40:43 | [diff] [blame] | 1190 | bool ExecuteScript(const ToRenderFrameHost& adapter, |
[email protected] | b6987e0 | 2013-01-04 18:30:43 | [diff] [blame] | 1191 | const std::string& script) { |
lukasza | c7d6bd3 | 2017-07-11 00:19:31 | [diff] [blame] | 1192 | return ExecuteScriptWithUserGestureControl(adapter.render_frame_host(), |
| 1193 | script, true); |
vasilii | b50cee4c9 | 2017-03-31 11:53:14 | [diff] [blame] | 1194 | } |
| 1195 | |
| 1196 | bool ExecuteScriptWithoutUserGesture(const ToRenderFrameHost& adapter, |
| 1197 | const std::string& script) { |
lukasza | c7d6bd3 | 2017-07-11 00:19:31 | [diff] [blame] | 1198 | return ExecuteScriptWithUserGestureControl(adapter.render_frame_host(), |
| 1199 | script, false); |
| 1200 | } |
| 1201 | |
| 1202 | void ExecuteScriptAsync(const ToRenderFrameHost& adapter, |
| 1203 | const std::string& script) { |
| 1204 | adapter.render_frame_host()->ExecuteJavaScriptWithUserGestureForTests( |
| 1205 | base::UTF8ToUTF16(script)); |
[email protected] | b6987e0 | 2013-01-04 18:30:43 | [diff] [blame] | 1206 | } |
| 1207 | |
wjmaclean | 6495190 | 2016-04-29 20:59:12 | [diff] [blame] | 1208 | bool ExecuteScriptAndExtractDouble(const ToRenderFrameHost& adapter, |
| 1209 | const std::string& script, double* result) { |
| 1210 | DCHECK(result); |
| 1211 | std::unique_ptr<base::Value> value; |
Nick Carter | b7e7131 | 2018-08-03 23:36:13 | [diff] [blame] | 1212 | return ExecuteScriptHelper(adapter.render_frame_host(), script, true, |
| 1213 | ISOLATED_WORLD_ID_GLOBAL, &value) && |
| 1214 | value && value->GetAsDouble(result); |
wjmaclean | 6495190 | 2016-04-29 20:59:12 | [diff] [blame] | 1215 | } |
| 1216 | |
alexmos | 4cf2aa3 | 2015-07-15 23:40:43 | [diff] [blame] | 1217 | bool ExecuteScriptAndExtractInt(const ToRenderFrameHost& adapter, |
[email protected] | b6987e0 | 2013-01-04 18:30:43 | [diff] [blame] | 1218 | const std::string& script, int* result) { |
[email protected] | ff4657ee | 2014-03-15 01:08:15 | [diff] [blame] | 1219 | DCHECK(result); |
dcheng | 6003e0b | 2016-04-09 18:42:34 | [diff] [blame] | 1220 | std::unique_ptr<base::Value> value; |
Nick Carter | b7e7131 | 2018-08-03 23:36:13 | [diff] [blame] | 1221 | return ExecuteScriptHelper(adapter.render_frame_host(), script, true, |
| 1222 | ISOLATED_WORLD_ID_GLOBAL, &value) && |
| 1223 | value && value->GetAsInteger(result); |
[email protected] | b6987e0 | 2013-01-04 18:30:43 | [diff] [blame] | 1224 | } |
| 1225 | |
alexmos | 4cf2aa3 | 2015-07-15 23:40:43 | [diff] [blame] | 1226 | bool ExecuteScriptAndExtractBool(const ToRenderFrameHost& adapter, |
[email protected] | b6987e0 | 2013-01-04 18:30:43 | [diff] [blame] | 1227 | const std::string& script, bool* result) { |
[email protected] | ff4657ee | 2014-03-15 01:08:15 | [diff] [blame] | 1228 | DCHECK(result); |
dcheng | 6003e0b | 2016-04-09 18:42:34 | [diff] [blame] | 1229 | std::unique_ptr<base::Value> value; |
Nick Carter | b7e7131 | 2018-08-03 23:36:13 | [diff] [blame] | 1230 | return ExecuteScriptHelper(adapter.render_frame_host(), script, true, |
| 1231 | ISOLATED_WORLD_ID_GLOBAL, &value) && |
| 1232 | value && value->GetAsBoolean(result); |
mdjones | 28f3694 | 2015-09-24 00:48:22 | [diff] [blame] | 1233 | } |
| 1234 | |
alexmos | 4cf2aa3 | 2015-07-15 23:40:43 | [diff] [blame] | 1235 | bool ExecuteScriptAndExtractString(const ToRenderFrameHost& adapter, |
[email protected] | b6987e0 | 2013-01-04 18:30:43 | [diff] [blame] | 1236 | const std::string& script, |
| 1237 | std::string* result) { |
[email protected] | ff4657ee | 2014-03-15 01:08:15 | [diff] [blame] | 1238 | DCHECK(result); |
dcheng | 6003e0b | 2016-04-09 18:42:34 | [diff] [blame] | 1239 | std::unique_ptr<base::Value> value; |
Nick Carter | b7e7131 | 2018-08-03 23:36:13 | [diff] [blame] | 1240 | return ExecuteScriptHelper(adapter.render_frame_host(), script, true, |
| 1241 | ISOLATED_WORLD_ID_GLOBAL, &value) && |
| 1242 | value && value->GetAsString(result); |
[email protected] | b6987e0 | 2013-01-04 18:30:43 | [diff] [blame] | 1243 | } |
| 1244 | |
vasilii | b50cee4c9 | 2017-03-31 11:53:14 | [diff] [blame] | 1245 | bool ExecuteScriptWithoutUserGestureAndExtractDouble( |
| 1246 | const ToRenderFrameHost& adapter, |
| 1247 | const std::string& script, |
| 1248 | double* result) { |
| 1249 | DCHECK(result); |
| 1250 | std::unique_ptr<base::Value> value; |
| 1251 | return ExecuteScriptHelper(adapter.render_frame_host(), script, false, |
Nick Carter | b7e7131 | 2018-08-03 23:36:13 | [diff] [blame] | 1252 | ISOLATED_WORLD_ID_GLOBAL, &value) && |
vasilii | b50cee4c9 | 2017-03-31 11:53:14 | [diff] [blame] | 1253 | value && value->GetAsDouble(result); |
| 1254 | } |
| 1255 | |
| 1256 | bool ExecuteScriptWithoutUserGestureAndExtractInt( |
| 1257 | const ToRenderFrameHost& adapter, |
| 1258 | const std::string& script, |
| 1259 | int* result) { |
| 1260 | DCHECK(result); |
| 1261 | std::unique_ptr<base::Value> value; |
| 1262 | return ExecuteScriptHelper(adapter.render_frame_host(), script, false, |
Nick Carter | b7e7131 | 2018-08-03 23:36:13 | [diff] [blame] | 1263 | ISOLATED_WORLD_ID_GLOBAL, &value) && |
vasilii | b50cee4c9 | 2017-03-31 11:53:14 | [diff] [blame] | 1264 | value && value->GetAsInteger(result); |
| 1265 | } |
| 1266 | |
| 1267 | bool ExecuteScriptWithoutUserGestureAndExtractBool( |
| 1268 | const ToRenderFrameHost& adapter, |
| 1269 | const std::string& script, |
| 1270 | bool* result) { |
| 1271 | DCHECK(result); |
| 1272 | std::unique_ptr<base::Value> value; |
| 1273 | return ExecuteScriptHelper(adapter.render_frame_host(), script, false, |
Nick Carter | b7e7131 | 2018-08-03 23:36:13 | [diff] [blame] | 1274 | ISOLATED_WORLD_ID_GLOBAL, &value) && |
vasilii | b50cee4c9 | 2017-03-31 11:53:14 | [diff] [blame] | 1275 | value && value->GetAsBoolean(result); |
| 1276 | } |
| 1277 | |
| 1278 | bool ExecuteScriptWithoutUserGestureAndExtractString( |
| 1279 | const ToRenderFrameHost& adapter, |
| 1280 | const std::string& script, |
| 1281 | std::string* result) { |
| 1282 | DCHECK(result); |
| 1283 | std::unique_ptr<base::Value> value; |
| 1284 | return ExecuteScriptHelper(adapter.render_frame_host(), script, false, |
Nick Carter | b7e7131 | 2018-08-03 23:36:13 | [diff] [blame] | 1285 | ISOLATED_WORLD_ID_GLOBAL, &value) && |
vasilii | b50cee4c9 | 2017-03-31 11:53:14 | [diff] [blame] | 1286 | value && value->GetAsString(result); |
| 1287 | } |
| 1288 | |
Nick Carter | b7e7131 | 2018-08-03 23:36:13 | [diff] [blame] | 1289 | // EvalJsResult methods. |
| 1290 | EvalJsResult::EvalJsResult(base::Value value, const std::string& error) |
| 1291 | : value(error.empty() ? std::move(value) : base::Value()), error(error) {} |
| 1292 | |
| 1293 | EvalJsResult::EvalJsResult(const EvalJsResult& other) |
| 1294 | : value(other.value.Clone()), error(other.error) {} |
| 1295 | |
| 1296 | const std::string& EvalJsResult::ExtractString() const { |
| 1297 | CHECK(error.empty()) |
| 1298 | << "Can't ExtractString() because the script encountered a problem: " |
| 1299 | << error; |
| 1300 | CHECK(value.is_string()) << "Can't ExtractString() because script result: " |
| 1301 | << value << "is not a string."; |
| 1302 | return value.GetString(); |
| 1303 | } |
| 1304 | |
| 1305 | int EvalJsResult::ExtractInt() const { |
| 1306 | CHECK(error.empty()) |
| 1307 | << "Can't ExtractInt() because the script encountered a problem: " |
| 1308 | << error; |
| 1309 | CHECK(value.is_int()) << "Can't ExtractInt() because script result: " << value |
| 1310 | << "is not an int."; |
| 1311 | return value.GetInt(); |
| 1312 | } |
| 1313 | |
| 1314 | bool EvalJsResult::ExtractBool() const { |
| 1315 | CHECK(error.empty()) |
| 1316 | << "Can't ExtractBool() because the script encountered a problem: " |
| 1317 | << error; |
| 1318 | CHECK(value.is_bool()) << "Can't ExtractBool() because script result: " |
| 1319 | << value << "is not a bool."; |
| 1320 | return value.GetBool(); |
| 1321 | } |
| 1322 | |
| 1323 | double EvalJsResult::ExtractDouble() const { |
| 1324 | CHECK(error.empty()) |
| 1325 | << "Can't ExtractDouble() because the script encountered a problem: " |
| 1326 | << error; |
| 1327 | CHECK(value.is_double() || value.is_int()) |
| 1328 | << "Can't ExtractDouble() because script result: " << value |
| 1329 | << "is not a double or int."; |
| 1330 | return value.GetDouble(); |
| 1331 | } |
| 1332 | |
| 1333 | base::ListValue EvalJsResult::ExtractList() const { |
| 1334 | CHECK(error.empty()) |
| 1335 | << "Can't ExtractList() because the script encountered a problem: " |
| 1336 | << error; |
| 1337 | CHECK(value.is_list()) << "Can't ExtractList() because script result: " |
| 1338 | << value << "is not a list."; |
| 1339 | return base::ListValue(value.GetList()); |
| 1340 | } |
| 1341 | |
| 1342 | void PrintTo(const EvalJsResult& bar, ::std::ostream* os) { |
| 1343 | if (!bar.error.empty()) { |
| 1344 | *os << bar.error; |
| 1345 | } else { |
| 1346 | *os << bar.value; |
| 1347 | } |
| 1348 | } |
| 1349 | |
| 1350 | namespace { |
| 1351 | |
| 1352 | // Parse a JS stack trace out of |js_error|, detect frames that match |
| 1353 | // |source_name|, and interleave the appropriate lines of source code from |
| 1354 | // |source| into the error report. This is meant to be useful for scripts that |
| 1355 | // are passed to ExecuteScript functions, and hence dynamically generated. |
| 1356 | // |
| 1357 | // An adjustment of |column_adjustment_for_line_one| characters is subtracted |
| 1358 | // when mapping positions from line 1 of |source|. This is to offset the effect |
| 1359 | // of boilerplate added by the script runner. |
| 1360 | // |
| 1361 | // TODO(nick): Elide snippets to 80 chars, since it is common for sources to not |
| 1362 | // include newlines. |
| 1363 | std::string AnnotateAndAdjustJsStackTraces(const std::string& js_error, |
| 1364 | std::string source_name, |
| 1365 | const std::string& source, |
| 1366 | int column_adjustment_for_line_one) { |
| 1367 | // Escape wildcards in |source_name| for use in MatchPattern. |
| 1368 | base::ReplaceChars(source_name, "\\", "\\\\", &source_name); |
| 1369 | base::ReplaceChars(source_name, "*", "\\*", &source_name); |
| 1370 | base::ReplaceChars(source_name, "?", "\\?", &source_name); |
| 1371 | |
| 1372 | // This vector maps line numbers to the corresponding text in |source|. |
| 1373 | const std::vector<base::StringPiece> source_lines = base::SplitStringPiece( |
| 1374 | source, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); |
| 1375 | |
| 1376 | // |source_frame_pattern| should match any line that looks like a stack frame |
| 1377 | // from a source file named |source_name|. |
| 1378 | const std::string source_frame_pattern = |
| 1379 | base::StringPrintf(" at * (%s:*:*)", source_name.c_str()); |
| 1380 | |
| 1381 | // This is the amount of indentation that is applied to the lines of inserted |
| 1382 | // annotations. |
| 1383 | const std::string indent(8, ' '); |
| 1384 | const base::StringPiece elision_mark = ""; |
| 1385 | |
| 1386 | // Loop over each line of |js_error|, and append each to |annotated_error| -- |
| 1387 | // possibly rewriting to include extra context. |
| 1388 | std::ostringstream annotated_error; |
| 1389 | for (const base::StringPiece& error_line : base::SplitStringPiece( |
| 1390 | js_error, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL)) { |
| 1391 | // Does this look like a stack frame whose URL source matches |source_name|? |
| 1392 | if (base::MatchPattern(error_line, source_frame_pattern)) { |
| 1393 | // When a match occurs, annotate the stack trace with the corresponding |
| 1394 | // line from |source|, along with a ^^^ underneath, indicating the column |
| 1395 | // position. |
| 1396 | std::vector<base::StringPiece> error_line_parts = base::SplitStringPiece( |
| 1397 | error_line, ":", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); |
Lukasz Anforowicz | 637e7d6d | 2018-10-06 05:44:12 | [diff] [blame] | 1398 | CHECK_GE(error_line_parts.size(), 2u); |
Nick Carter | b7e7131 | 2018-08-03 23:36:13 | [diff] [blame] | 1399 | |
| 1400 | int column_number = 0; |
| 1401 | base::StringToInt(error_line_parts.back(), &column_number); |
| 1402 | error_line_parts.pop_back(); |
| 1403 | int line_number = 0; |
| 1404 | base::StringToInt(error_line_parts.back(), &line_number); |
| 1405 | error_line_parts.pop_back(); |
| 1406 | |
| 1407 | // Protect against out-of-range matches. |
| 1408 | if ((line_number > 0) && (column_number > 0) && |
| 1409 | static_cast<size_t>(line_number) <= source_lines.size()) { |
| 1410 | // Apply adjustment requested by caller to columns on the first line. |
| 1411 | // This allows us to add preamble boilerplate to the script, but still |
| 1412 | // locate errors correctly. |
| 1413 | if (line_number == 1 && column_number > column_adjustment_for_line_one) |
| 1414 | column_number -= column_adjustment_for_line_one; |
| 1415 | |
| 1416 | // Some source lines are huge. Elide |source_line| so that it doesn't |
| 1417 | // occupy more than one actual line. |
| 1418 | std::string source_line = source_lines[line_number - 1].as_string(); |
| 1419 | |
| 1420 | int max_column_number = 60 - indent.length(); |
| 1421 | if (column_number > max_column_number) { |
| 1422 | source_line = source_line.substr(column_number - max_column_number); |
| 1423 | column_number = max_column_number; |
| 1424 | source_line.replace(0, elision_mark.length(), elision_mark.data(), |
| 1425 | elision_mark.length()); |
| 1426 | } |
| 1427 | |
| 1428 | size_t max_length = 80 - indent.length(); |
| 1429 | if (source_line.length() > max_length) { |
| 1430 | source_line = |
| 1431 | source_line.substr(0, max_length - elision_mark.length()); |
| 1432 | elision_mark.AppendToString(&source_line); |
| 1433 | } |
| 1434 | |
| 1435 | annotated_error << base::JoinString(error_line_parts, ":") << ":" |
| 1436 | << line_number << ":" << column_number << "):\n" |
| 1437 | << indent << source_line << '\n' |
| 1438 | << indent << std::string(column_number - 1, ' ') |
| 1439 | << "^^^^^\n"; |
| 1440 | continue; |
| 1441 | } |
| 1442 | } |
| 1443 | // This line was not rewritten -- just append it as-is. |
| 1444 | annotated_error << error_line << "\n"; |
| 1445 | } |
| 1446 | return annotated_error.str(); |
| 1447 | } |
| 1448 | |
| 1449 | } // namespace |
| 1450 | |
| 1451 | testing::AssertionResult ExecJs(const ToRenderFrameHost& execution_target, |
| 1452 | const std::string& script, |
| 1453 | int options, |
| 1454 | int world_id) { |
| 1455 | CHECK(!(options & EXECUTE_SCRIPT_USE_MANUAL_REPLY)) |
| 1456 | << "USE_MANUAL_REPLY does not make sense with ExecJs."; |
| 1457 | |
| 1458 | // ExecJs() doesn't care about the result, so disable promise resolution. |
| 1459 | // Instead of using ExecJs() to wait for an async event, callers may use |
| 1460 | // EvalJs() with a sentinel result value like "success". |
| 1461 | options |= EXECUTE_SCRIPT_NO_RESOLVE_PROMISES; |
| 1462 | |
| 1463 | // TODO(nick): Do we care enough about folks shooting themselves in the foot |
| 1464 | // here with e.g. ASSERT_TRUE(ExecJs("window == window.top")) -- when they |
| 1465 | // mean EvalJs -- to fail a CHECK() when eval_result.value.is_bool()? |
| 1466 | EvalJsResult eval_result = |
| 1467 | EvalJs(execution_target, script, options, world_id); |
| 1468 | |
| 1469 | // NOTE: |eval_result.value| is intentionally ignored by ExecJs(). |
| 1470 | if (!eval_result.error.empty()) |
| 1471 | return testing::AssertionFailure() << eval_result.error; |
| 1472 | return testing::AssertionSuccess(); |
| 1473 | } |
| 1474 | |
| 1475 | EvalJsResult EvalJs(const ToRenderFrameHost& execution_target, |
| 1476 | const std::string& script, |
| 1477 | int options, |
| 1478 | int world_id) { |
| 1479 | // The sourceURL= parameter provides a string that replaces <anonymous> in |
| 1480 | // stack traces, if an Error is thrown. 'std::string' is meant to communicate |
| 1481 | // that this is a dynamic argument originating from C++ code. |
| 1482 | const char* kSourceURL = "__const_std::string&_script__"; |
| 1483 | std::string modified_script = |
| 1484 | base::StringPrintf("%s;\n//# sourceURL=%s", script.c_str(), kSourceURL); |
| 1485 | |
| 1486 | // An extra eval() indirection is used here to catch syntax errors and return |
| 1487 | // them as assertion failures. This eval() operation deliberately occurs in |
| 1488 | // the global scope, so 'var' declarations in |script| will persist for later |
| 1489 | // script executions. (As an aside: global/local scope for eval depends on |
| 1490 | // whether 'eval' is called directly or indirectly; 'window.eval()' is |
| 1491 | // indirect). |
| 1492 | // |
| 1493 | // The call to eval() itself is inside a .then() handler so that syntax errors |
| 1494 | // result in Promise rejection. Calling eval() either throws (in the event of |
| 1495 | // a SyntaxError) or returns the script's completion value. |
| 1496 | // |
| 1497 | // The result of eval() (i.e., the statement completion value of |script|) is |
| 1498 | // wrapped in an array and passed to a second .then() handler. If eval() |
| 1499 | // returned a Promise and the |resolve_promises| option is set, this handler |
| 1500 | // calls Promise.all to reply after the returned Promise resolves. |
| 1501 | // |
| 1502 | // If |script| evaluated successfully, the third.then() handler maps the |
| 1503 | // resolved |result| of eval() to a |reply| that is a one-element list |
| 1504 | // containing the value (this element can be any JSON-serializable type). If |
| 1505 | // the manual reply option is being used, no reply is emitted after successful |
| 1506 | // execution -- the script is expected to call send() itself. The call to |
| 1507 | // Promise.reject() squelches this reply, and the final .then() handler is not |
| 1508 | // called. |
| 1509 | // |
| 1510 | // If an uncaught error was thrown, or eval() returns a Promise that is |
| 1511 | // rejected, the third .then() handler maps the |error| to a |reply| that is |
| 1512 | // a string value. |
| 1513 | // |
| 1514 | // The fourth and final .then() handler passes the |reply| (whether |
| 1515 | // successful or unsuccessful) to domAutomationController.send(), so that it's |
| 1516 | // transmitted back here in browser process C++ land. A GUID token is also |
| 1517 | // included, that protects against |script| directly calling |
| 1518 | // domAutomationController.send() itself, which is disallowed in EvalJs. |
| 1519 | bool use_automatic_reply = !(options & EXECUTE_SCRIPT_USE_MANUAL_REPLY); |
| 1520 | bool resolve_promises = !(options & EXECUTE_SCRIPT_NO_RESOLVE_PROMISES); |
| 1521 | |
| 1522 | std::string token = "EvalJs-" + base::GenerateGUID(); |
| 1523 | std::string runner_script = JsReplace( |
| 1524 | R"(Promise.resolve($1) |
| 1525 | .then(script => [window.eval(script)]) |
| 1526 | .then((result) => $2 ? Promise.all(result) : result ) |
| 1527 | .then((result) => $3 ? result : Promise.reject(), |
| 1528 | (error) => 'a JavaScript error:' + |
| 1529 | (error && error.stack ? '\n' + error.stack |
| 1530 | : ' "' + error + '"')) |
| 1531 | .then((reply) => window.domAutomationController.send([$4, reply])); |
| 1532 | //# sourceURL=EvalJs-runner.js)", |
| 1533 | modified_script, resolve_promises, use_automatic_reply, token); |
| 1534 | |
| 1535 | bool user_gesture = !(options & EXECUTE_SCRIPT_NO_USER_GESTURE); |
| 1536 | std::ostringstream error_stream; |
| 1537 | std::unique_ptr<base::Value> response; |
| 1538 | if (!execution_target.render_frame_host()->IsRenderFrameLive()) { |
| 1539 | error_stream << "Error: EvalJs won't work on an already-crashed frame."; |
| 1540 | } else if (!ExecuteScriptHelper(execution_target.render_frame_host(), |
| 1541 | runner_script, user_gesture, world_id, |
| 1542 | &response)) { |
| 1543 | error_stream << "Internal Error: ExecuteScriptHelper failed"; |
| 1544 | } else if (!response) { |
| 1545 | error_stream << "Internal Error: no value"; |
| 1546 | } else { |
| 1547 | bool is_reply_from_runner_script = |
| 1548 | response->is_list() && response->GetList().size() == 2 && |
| 1549 | response->GetList()[0].is_string() && |
| 1550 | response->GetList()[0].GetString() == token; |
| 1551 | |
| 1552 | bool is_error = |
| 1553 | is_reply_from_runner_script && response->GetList()[1].is_string(); |
| 1554 | bool is_automatic_success_reply = |
| 1555 | is_reply_from_runner_script && response->GetList()[1].is_list() && |
| 1556 | response->GetList()[1].GetList().size() == 1; |
| 1557 | |
| 1558 | if (is_error) { |
| 1559 | // This is a response generated by the error handler in our runner |
| 1560 | // script. This occurs when the script throws an exception, or when |
| 1561 | // eval throws a SyntaxError. |
| 1562 | // |
| 1563 | // Parse the stack trace here, and interleave lines of source code from |
| 1564 | // |script| to aid debugging. |
| 1565 | std::string error_text = response->GetList()[1].GetString(); |
| 1566 | |
| 1567 | if (base::StartsWith(error_text, |
| 1568 | "a JavaScript error:\nEvalError: Refused", |
| 1569 | base::CompareCase::SENSITIVE)) { |
| 1570 | error_text = |
| 1571 | "EvalJs encountered an EvalError, because eval() is blocked by the " |
| 1572 | "document's CSP on this page. To test content that is protected by " |
| 1573 | "CSP, consider using EvalJs with an isolated world. Details: " + |
| 1574 | error_text; |
| 1575 | } |
| 1576 | |
| 1577 | CHECK(!error_text.empty()); |
| 1578 | error_stream << AnnotateAndAdjustJsStackTraces(error_text, kSourceURL, |
| 1579 | script, 0); |
| 1580 | } else if (!use_automatic_reply) { |
| 1581 | // When |script| itself calls domAutomationController.send() on success, |
| 1582 | // |response| could be anything; so there's no more checking we can do: |
| 1583 | // return |response| as success, with an empty error. |
| 1584 | return EvalJsResult(std::move(*response), std::string()); |
| 1585 | } else if (is_automatic_success_reply) { |
| 1586 | // Got a response from the runner script that indicates success (of the |
| 1587 | // form [token, [completion_value]]. Return the completion value, with an |
| 1588 | // empty error. |
| 1589 | return EvalJsResult(std::move(response->GetList()[1].GetList()[0]), |
| 1590 | std::string()); |
| 1591 | } else { |
| 1592 | // The response was not well-formed (it failed the token match), so it's |
| 1593 | // not from our runner script. Fail with an explanation of the raw |
| 1594 | // message. This allows us to reject other calls |
| 1595 | // domAutomationController.send(). |
| 1596 | error_stream |
| 1597 | << "Internal Error: expected a 2-element list of the form " |
| 1598 | << "['" << token << "', [result]]; but got instead: " << *response |
| 1599 | << " ... This is potentially because a script tried to call " |
| 1600 | "domAutomationController.send itself -- that is only allowed " |
| 1601 | "when using EvalJsWithManualReply(). When using EvalJs(), result " |
| 1602 | "values are just the result of calling eval() on the script -- " |
| 1603 | "the completion value is the value of the last executed " |
| 1604 | "statement. When using ExecJs(), there is no result value."; |
| 1605 | } |
| 1606 | } |
| 1607 | |
| 1608 | // Something went wrong. Return an empty value and a non-empty error. |
| 1609 | return EvalJsResult(base::Value(), error_stream.str()); |
| 1610 | } |
| 1611 | |
| 1612 | EvalJsResult EvalJsWithManualReply(const ToRenderFrameHost& execution_target, |
| 1613 | const std::string& script, |
| 1614 | int options, |
| 1615 | int world_id) { |
| 1616 | return EvalJs(execution_target, script, |
| 1617 | options | EXECUTE_SCRIPT_USE_MANUAL_REPLY, world_id); |
| 1618 | } |
| 1619 | |
[email protected] | 67048bd | 2014-03-18 07:32:35 | [diff] [blame] | 1620 | namespace { |
| 1621 | void AddToSetIfFrameMatchesPredicate( |
| 1622 | std::set<RenderFrameHost*>* frame_set, |
| 1623 | const base::Callback<bool(RenderFrameHost*)>& predicate, |
| 1624 | RenderFrameHost* host) { |
| 1625 | if (predicate.Run(host)) |
| 1626 | frame_set->insert(host); |
| 1627 | } |
| 1628 | } |
| 1629 | |
| 1630 | RenderFrameHost* FrameMatchingPredicate( |
| 1631 | WebContents* web_contents, |
| 1632 | const base::Callback<bool(RenderFrameHost*)>& predicate) { |
| 1633 | std::set<RenderFrameHost*> frame_set; |
Lei Zhang | ebcc630 | 2018-01-12 19:46:45 | [diff] [blame] | 1634 | web_contents->ForEachFrame(base::BindRepeating( |
| 1635 | &AddToSetIfFrameMatchesPredicate, &frame_set, predicate)); |
lukasza | 424c045 | 2017-05-03 16:08:24 | [diff] [blame] | 1636 | EXPECT_EQ(1U, frame_set.size()); |
| 1637 | return frame_set.size() == 1 ? *frame_set.begin() : nullptr; |
[email protected] | 67048bd | 2014-03-18 07:32:35 | [diff] [blame] | 1638 | } |
| 1639 | |
| 1640 | bool FrameMatchesName(const std::string& name, RenderFrameHost* frame) { |
| 1641 | return frame->GetFrameName() == name; |
| 1642 | } |
| 1643 | |
[email protected] | 18fb469 | 2014-03-20 00:47:17 | [diff] [blame] | 1644 | bool FrameIsChildOfMainFrame(RenderFrameHost* frame) { |
| 1645 | return frame->GetParent() && !frame->GetParent()->GetParent(); |
| 1646 | } |
| 1647 | |
[email protected] | 2f7a399 | 2014-03-20 22:53:24 | [diff] [blame] | 1648 | bool FrameHasSourceUrl(const GURL& url, RenderFrameHost* frame) { |
| 1649 | return frame->GetLastCommittedURL() == url; |
| 1650 | } |
| 1651 | |
alexmos | af3efeb | 2016-04-12 07:17:39 | [diff] [blame] | 1652 | RenderFrameHost* ChildFrameAt(RenderFrameHost* frame, size_t index) { |
| 1653 | RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(frame); |
| 1654 | if (index >= rfh->frame_tree_node()->child_count()) |
| 1655 | return nullptr; |
| 1656 | return rfh->frame_tree_node()->child_at(index)->current_frame_host(); |
| 1657 | } |
| 1658 | |
[email protected] | ff4657ee | 2014-03-15 01:08:15 | [diff] [blame] | 1659 | bool ExecuteWebUIResourceTest(WebContents* web_contents, |
| 1660 | const std::vector<int>& js_resource_ids) { |
[email protected] | c2791c1a | 2013-08-22 07:18:35 | [diff] [blame] | 1661 | // Inject WebUI test runner script first prior to other scripts required to |
| 1662 | // run the test as scripts may depend on it being declared. |
| 1663 | std::vector<int> ids; |
| 1664 | ids.push_back(IDR_WEBUI_JS_WEBUI_RESOURCE_TEST); |
| 1665 | ids.insert(ids.end(), js_resource_ids.begin(), js_resource_ids.end()); |
| 1666 | |
| 1667 | std::string script; |
Lei Zhang | 0fe3176e | 2017-11-01 05:30:08 | [diff] [blame] | 1668 | for (int id : ids) { |
dbeam | 49dab44 | 2016-08-20 00:49:52 | [diff] [blame] | 1669 | scoped_refptr<base::RefCountedMemory> bytes = |
Lei Zhang | 0fe3176e | 2017-11-01 05:30:08 | [diff] [blame] | 1670 | ui::ResourceBundle::GetSharedInstance().LoadDataResourceBytes(id); |
dbeam | 49dab44 | 2016-08-20 00:49:52 | [diff] [blame] | 1671 | |
| 1672 | if (HasGzipHeader(*bytes)) |
| 1673 | AppendGzippedResource(*bytes, &script); |
| 1674 | else |
| 1675 | script.append(bytes->front_as<char>(), bytes->size()); |
| 1676 | |
[email protected] | c2791c1a | 2013-08-22 07:18:35 | [diff] [blame] | 1677 | script.append("\n"); |
| 1678 | } |
lukasza | c7d6bd3 | 2017-07-11 00:19:31 | [diff] [blame] | 1679 | ExecuteScriptAsync(web_contents, script); |
[email protected] | c2791c1a | 2013-08-22 07:18:35 | [diff] [blame] | 1680 | |
[email protected] | 67048bd | 2014-03-18 07:32:35 | [diff] [blame] | 1681 | DOMMessageQueue message_queue; |
Luciano Pacheco | 034fd9d | 2018-09-19 01:18:40 | [diff] [blame] | 1682 | |
| 1683 | bool should_wait_flag = |
| 1684 | base::CommandLine::ForCurrentProcess()->HasSwitch(kWaitForDebuggerWebUI); |
| 1685 | |
Christopher Lam | 4d3266c1 | 2018-12-17 01:49:44 | [diff] [blame] | 1686 | if (should_wait_flag) { |
Luciano Pacheco | 034fd9d | 2018-09-19 01:18:40 | [diff] [blame] | 1687 | ExecuteScriptAsync( |
| 1688 | web_contents, |
| 1689 | "window.waitUser = true; " |
| 1690 | "window.go = function() { window.waitUser = false }; " |
| 1691 | "console.log('Waiting for debugger...'); " |
| 1692 | "console.log('Run: go() in the JS console when you are ready.');"); |
| 1693 | } |
| 1694 | |
lukasza | c7d6bd3 | 2017-07-11 00:19:31 | [diff] [blame] | 1695 | ExecuteScriptAsync(web_contents, "runTests()"); |
[email protected] | c2791c1a | 2013-08-22 07:18:35 | [diff] [blame] | 1696 | |
| 1697 | std::string message; |
| 1698 | do { |
| 1699 | if (!message_queue.WaitForMessage(&message)) |
| 1700 | return false; |
| 1701 | } while (message.compare("\"PENDING\"") == 0); |
| 1702 | |
| 1703 | return message.compare("\"SUCCESS\"") == 0; |
| 1704 | } |
| 1705 | |
[email protected] | 88509ab | 2012-08-27 15:04:14 | [diff] [blame] | 1706 | std::string GetCookies(BrowserContext* browser_context, const GURL& url) { |
| 1707 | std::string cookies; |
Randy Smith | e23356c2 | 2017-11-14 01:41:50 | [diff] [blame] | 1708 | base::RunLoop run_loop; |
| 1709 | network::mojom::CookieManagerPtr cookie_manager; |
| 1710 | BrowserContext::GetDefaultStoragePartition(browser_context) |
| 1711 | ->GetNetworkContext() |
| 1712 | ->GetCookieManager(mojo::MakeRequest(&cookie_manager)); |
| 1713 | cookie_manager->GetCookieList( |
| 1714 | url, net::CookieOptions(), |
Joshua Bell | 1d432be | 2018-06-27 19:59:48 | [diff] [blame] | 1715 | base::BindOnce( |
| 1716 | [](std::string* cookies_out, base::RunLoop* run_loop, |
| 1717 | const std::vector<net::CanonicalCookie>& cookies) { |
| 1718 | *cookies_out = net::CanonicalCookie::BuildCookieLine(cookies); |
| 1719 | run_loop->Quit(); |
| 1720 | }, |
| 1721 | &cookies, &run_loop)); |
| 1722 | run_loop.Run(); |
| 1723 | return cookies; |
| 1724 | } |
| 1725 | |
| 1726 | std::vector<net::CanonicalCookie> GetCanonicalCookies( |
| 1727 | BrowserContext* browser_context, |
| 1728 | const GURL& url) { |
| 1729 | std::vector<net::CanonicalCookie> cookies; |
| 1730 | base::RunLoop run_loop; |
| 1731 | network::mojom::CookieManagerPtr cookie_manager; |
| 1732 | BrowserContext::GetDefaultStoragePartition(browser_context) |
| 1733 | ->GetNetworkContext() |
| 1734 | ->GetCookieManager(mojo::MakeRequest(&cookie_manager)); |
| 1735 | cookie_manager->GetCookieList( |
| 1736 | url, net::CookieOptions(), |
| 1737 | base::BindOnce( |
| 1738 | [](base::RunLoop* run_loop, |
| 1739 | std::vector<net::CanonicalCookie>* cookies_out, |
| 1740 | const std::vector<net::CanonicalCookie>& cookies) { |
| 1741 | *cookies_out = cookies; |
| 1742 | run_loop->Quit(); |
| 1743 | }, |
| 1744 | &run_loop, &cookies)); |
Randy Smith | e23356c2 | 2017-11-14 01:41:50 | [diff] [blame] | 1745 | run_loop.Run(); |
[email protected] | 88509ab | 2012-08-27 15:04:14 | [diff] [blame] | 1746 | return cookies; |
| 1747 | } |
| 1748 | |
[email protected] | b561aab | 2012-08-27 20:17:49 | [diff] [blame] | 1749 | bool SetCookie(BrowserContext* browser_context, |
| 1750 | const GURL& url, |
| 1751 | const std::string& value) { |
| 1752 | bool result = false; |
Randy Smith | e23356c2 | 2017-11-14 01:41:50 | [diff] [blame] | 1753 | base::RunLoop run_loop; |
| 1754 | network::mojom::CookieManagerPtr cookie_manager; |
| 1755 | BrowserContext::GetDefaultStoragePartition(browser_context) |
| 1756 | ->GetNetworkContext() |
| 1757 | ->GetCookieManager(mojo::MakeRequest(&cookie_manager)); |
| 1758 | std::unique_ptr<net::CanonicalCookie> cc(net::CanonicalCookie::Create( |
| 1759 | url, value, base::Time::Now(), net::CookieOptions())); |
| 1760 | DCHECK(cc.get()); |
[email protected] | b561aab | 2012-08-27 20:17:49 | [diff] [blame] | 1761 | |
Randy Smith | e23356c2 | 2017-11-14 01:41:50 | [diff] [blame] | 1762 | cookie_manager->SetCanonicalCookie( |
| 1763 | *cc.get(), true /* secure_source */, true /* modify_http_only */, |
Joshua Bell | 1d432be | 2018-06-27 19:59:48 | [diff] [blame] | 1764 | base::BindOnce( |
| 1765 | [](bool* result, base::RunLoop* run_loop, bool success) { |
| 1766 | *result = success; |
| 1767 | run_loop->Quit(); |
| 1768 | }, |
| 1769 | &result, &run_loop)); |
Randy Smith | e23356c2 | 2017-11-14 01:41:50 | [diff] [blame] | 1770 | run_loop.Run(); |
[email protected] | b561aab | 2012-08-27 20:17:49 | [diff] [blame] | 1771 | return result; |
| 1772 | } |
| 1773 | |
[email protected] | e7e9c86 | 2014-08-21 22:00:38 | [diff] [blame] | 1774 | void FetchHistogramsFromChildProcesses() { |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 1775 | base::RunLoop run_loop; |
[email protected] | e7e9c86 | 2014-08-21 22:00:38 | [diff] [blame] | 1776 | |
| 1777 | FetchHistogramsAsynchronously( |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 1778 | base::ThreadTaskRunnerHandle::Get(), run_loop.QuitClosure(), |
[email protected] | e7e9c86 | 2014-08-21 22:00:38 | [diff] [blame] | 1779 | // If this call times out, it means that a child process is not |
| 1780 | // responding, which is something we should not ignore. The timeout is |
| 1781 | // set to be longer than the normal browser test timeout so that it will |
| 1782 | // be prempted by the normal timeout. |
| 1783 | TestTimeouts::action_max_timeout()); |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 1784 | run_loop.Run(); |
[email protected] | e7e9c86 | 2014-08-21 22:00:38 | [diff] [blame] | 1785 | } |
| 1786 | |
svaldez | c3a9a17 | 2015-11-03 22:01:33 | [diff] [blame] | 1787 | void SetupCrossSiteRedirector(net::EmbeddedTestServer* embedded_test_server) { |
martijn | 2037cd7 | 2016-11-10 20:11:32 | [diff] [blame] | 1788 | embedded_test_server->RegisterRequestHandler( |
| 1789 | base::Bind(&CrossSiteRedirectResponseHandler, embedded_test_server)); |
nasko | b00afd8 | 2014-10-03 05:48:59 | [diff] [blame] | 1790 | } |
| 1791 | |
meacer | b47bc878 | 2014-10-07 03:40:01 | [diff] [blame] | 1792 | void WaitForInterstitialAttach(content::WebContents* web_contents) { |
| 1793 | if (web_contents->ShowingInterstitialPage()) |
| 1794 | return; |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 1795 | base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed); |
| 1796 | InterstitialObserver observer(web_contents, run_loop.QuitClosure(), |
| 1797 | base::OnceClosure()); |
| 1798 | run_loop.Run(); |
meacer | b47bc878 | 2014-10-07 03:40:01 | [diff] [blame] | 1799 | } |
| 1800 | |
| 1801 | void WaitForInterstitialDetach(content::WebContents* web_contents) { |
David Benjamin | 5f4ec14 | 2018-12-19 16:44:24 | [diff] [blame] | 1802 | RunTaskAndWaitForInterstitialDetach(web_contents, base::OnceClosure()); |
meacer | b47bc878 | 2014-10-07 03:40:01 | [diff] [blame] | 1803 | } |
| 1804 | |
| 1805 | void RunTaskAndWaitForInterstitialDetach(content::WebContents* web_contents, |
David Benjamin | 5f4ec14 | 2018-12-19 16:44:24 | [diff] [blame] | 1806 | base::OnceClosure task) { |
meacer | b47bc878 | 2014-10-07 03:40:01 | [diff] [blame] | 1807 | if (!web_contents || !web_contents->ShowingInterstitialPage()) |
| 1808 | return; |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 1809 | base::RunLoop run_loop; |
| 1810 | InterstitialObserver observer(web_contents, base::OnceClosure(), |
| 1811 | run_loop.QuitClosure()); |
meacer | b47bc878 | 2014-10-07 03:40:01 | [diff] [blame] | 1812 | if (!task.is_null()) |
David Benjamin | 5f4ec14 | 2018-12-19 16:44:24 | [diff] [blame] | 1813 | std::move(task).Run(); |
meacer | b47bc878 | 2014-10-07 03:40:01 | [diff] [blame] | 1814 | // At this point, web_contents may have been deleted. |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 1815 | run_loop.Run(); |
meacer | b47bc878 | 2014-10-07 03:40:01 | [diff] [blame] | 1816 | } |
| 1817 | |
meacer | 8543a23 | 2015-01-23 19:58:45 | [diff] [blame] | 1818 | bool WaitForRenderFrameReady(RenderFrameHost* rfh) { |
| 1819 | if (!rfh) |
| 1820 | return false; |
Nick Carter | b7e7131 | 2018-08-03 23:36:13 | [diff] [blame] | 1821 | // TODO(nick): This can't switch to EvalJs yet, because of hardcoded |
| 1822 | // dependencies on 'pageLoadComplete' in some interstitial implementations. |
meacer | 8543a23 | 2015-01-23 19:58:45 | [diff] [blame] | 1823 | std::string result; |
Nick Carter | b7e7131 | 2018-08-03 23:36:13 | [diff] [blame] | 1824 | EXPECT_TRUE(ExecuteScriptAndExtractString( |
| 1825 | rfh, |
| 1826 | "(async function() {" |
| 1827 | " if (document.readyState != 'complete') {" |
| 1828 | " await new Promise((resolve) =>" |
| 1829 | " document.addEventListener('readystatechange', event => {" |
| 1830 | " if (document.readyState == 'complete') {" |
| 1831 | " resolve();" |
| 1832 | " }" |
| 1833 | " }));" |
| 1834 | " }" |
| 1835 | "})().then(() => {" |
| 1836 | " window.domAutomationController.send('pageLoadComplete');" |
| 1837 | "});", |
| 1838 | &result)); |
| 1839 | EXPECT_EQ("pageLoadComplete", result); |
| 1840 | return "pageLoadComplete" == result; |
meacer | 8543a23 | 2015-01-23 19:58:45 | [diff] [blame] | 1841 | } |
| 1842 | |
dmazzoni | fdfa2e0 | 2016-03-30 01:15:43 | [diff] [blame] | 1843 | void EnableAccessibilityForWebContents(WebContents* web_contents) { |
| 1844 | WebContentsImpl* web_contents_impl = |
| 1845 | static_cast<WebContentsImpl*>(web_contents); |
Doug Turner | 63f3c7b | 2017-07-29 05:10:01 | [diff] [blame] | 1846 | web_contents_impl->SetAccessibilityMode(ui::kAXModeComplete); |
dmazzoni | fdfa2e0 | 2016-03-30 01:15:43 | [diff] [blame] | 1847 | } |
| 1848 | |
| 1849 | void WaitForAccessibilityFocusChange() { |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 1850 | base::RunLoop run_loop; |
dmazzoni | fdfa2e0 | 2016-03-30 01:15:43 | [diff] [blame] | 1851 | BrowserAccessibilityManager::SetFocusChangeCallbackForTesting( |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 1852 | run_loop.QuitClosure()); |
| 1853 | run_loop.Run(); |
dmazzoni | fdfa2e0 | 2016-03-30 01:15:43 | [diff] [blame] | 1854 | } |
| 1855 | |
| 1856 | ui::AXNodeData GetFocusedAccessibilityNodeInfo(WebContents* web_contents) { |
| 1857 | WebContentsImpl* web_contents_impl = |
| 1858 | static_cast<WebContentsImpl*>(web_contents); |
| 1859 | BrowserAccessibilityManager* manager = |
| 1860 | web_contents_impl->GetRootBrowserAccessibilityManager(); |
| 1861 | if (!manager) |
| 1862 | return ui::AXNodeData(); |
| 1863 | BrowserAccessibility* focused_node = manager->GetFocus(); |
| 1864 | return focused_node->GetData(); |
| 1865 | } |
| 1866 | |
dmazzoni | 25af842 | 2016-06-28 20:29:54 | [diff] [blame] | 1867 | bool AccessibilityTreeContainsNodeWithName(BrowserAccessibility* node, |
| 1868 | const std::string& name) { |
Dominic Mazzoni | dcef1b73 | 2018-01-26 17:57:04 | [diff] [blame] | 1869 | if (node->GetStringAttribute(ax::mojom::StringAttribute::kName) == name) |
dmazzoni | 25af842 | 2016-06-28 20:29:54 | [diff] [blame] | 1870 | return true; |
| 1871 | for (unsigned i = 0; i < node->PlatformChildCount(); i++) { |
| 1872 | if (AccessibilityTreeContainsNodeWithName(node->PlatformGetChild(i), name)) |
| 1873 | return true; |
| 1874 | } |
| 1875 | return false; |
| 1876 | } |
| 1877 | |
dmazzoni | 5a0018c9 | 2016-07-18 21:45:35 | [diff] [blame] | 1878 | bool ListenToGuestWebContents( |
| 1879 | AccessibilityNotificationWaiter* accessibility_waiter, |
| 1880 | WebContents* web_contents) { |
| 1881 | accessibility_waiter->ListenToAdditionalFrame( |
| 1882 | static_cast<RenderFrameHostImpl*>(web_contents->GetMainFrame())); |
| 1883 | return true; |
| 1884 | } |
| 1885 | |
dmazzoni | 25af842 | 2016-06-28 20:29:54 | [diff] [blame] | 1886 | void WaitForAccessibilityTreeToContainNodeWithName(WebContents* web_contents, |
| 1887 | const std::string& name) { |
| 1888 | WebContentsImpl* web_contents_impl = static_cast<WebContentsImpl*>( |
| 1889 | web_contents); |
| 1890 | RenderFrameHostImpl* main_frame = static_cast<RenderFrameHostImpl*>( |
| 1891 | web_contents_impl->GetMainFrame()); |
| 1892 | BrowserAccessibilityManager* main_frame_manager = |
| 1893 | main_frame->browser_accessibility_manager(); |
| 1894 | FrameTree* frame_tree = web_contents_impl->GetFrameTree(); |
dmazzoni | 5a0018c9 | 2016-07-18 21:45:35 | [diff] [blame] | 1895 | while (!main_frame_manager || !AccessibilityTreeContainsNodeWithName( |
dmazzoni | 25af842 | 2016-06-28 20:29:54 | [diff] [blame] | 1896 | main_frame_manager->GetRoot(), name)) { |
Dominic Mazzoni | dcef1b73 | 2018-01-26 17:57:04 | [diff] [blame] | 1897 | AccessibilityNotificationWaiter accessibility_waiter( |
| 1898 | main_frame, ax::mojom::Event::kNone); |
dmazzoni | 5a0018c9 | 2016-07-18 21:45:35 | [diff] [blame] | 1899 | for (FrameTreeNode* node : frame_tree->Nodes()) { |
dmazzoni | 25af842 | 2016-06-28 20:29:54 | [diff] [blame] | 1900 | accessibility_waiter.ListenToAdditionalFrame( |
| 1901 | node->current_frame_host()); |
dmazzoni | 5a0018c9 | 2016-07-18 21:45:35 | [diff] [blame] | 1902 | } |
| 1903 | |
| 1904 | content::BrowserPluginGuestManager* guest_manager = |
| 1905 | web_contents_impl->GetBrowserContext()->GetGuestManager(); |
| 1906 | if (guest_manager) { |
| 1907 | guest_manager->ForEachGuest(web_contents_impl, |
Mark Pilgrim | d8412173 | 2018-03-22 14:12:12 | [diff] [blame] | 1908 | base::BindRepeating(&ListenToGuestWebContents, |
| 1909 | &accessibility_waiter)); |
dmazzoni | 5a0018c9 | 2016-07-18 21:45:35 | [diff] [blame] | 1910 | } |
dmazzoni | 25af842 | 2016-06-28 20:29:54 | [diff] [blame] | 1911 | |
| 1912 | accessibility_waiter.WaitForNotification(); |
dmazzoni | 5a0018c9 | 2016-07-18 21:45:35 | [diff] [blame] | 1913 | main_frame_manager = main_frame->browser_accessibility_manager(); |
dmazzoni | 25af842 | 2016-06-28 20:29:54 | [diff] [blame] | 1914 | } |
| 1915 | } |
| 1916 | |
| 1917 | ui::AXTreeUpdate GetAccessibilityTreeSnapshot(WebContents* web_contents) { |
| 1918 | WebContentsImpl* web_contents_impl = |
| 1919 | static_cast<WebContentsImpl*>(web_contents); |
| 1920 | BrowserAccessibilityManager* manager = |
| 1921 | web_contents_impl->GetRootBrowserAccessibilityManager(); |
| 1922 | if (!manager) |
| 1923 | return ui::AXTreeUpdate(); |
| 1924 | return manager->SnapshotAXTreeForTesting(); |
| 1925 | } |
| 1926 | |
wjmaclean | b65ea79 | 2016-07-07 22:17:07 | [diff] [blame] | 1927 | bool IsWebContentsBrowserPluginFocused(content::WebContents* web_contents) { |
| 1928 | WebContentsImpl* web_contents_impl = |
| 1929 | static_cast<WebContentsImpl*>(web_contents); |
| 1930 | BrowserPluginGuest* browser_plugin_guest = |
| 1931 | web_contents_impl->GetBrowserPluginGuest(); |
| 1932 | return browser_plugin_guest ? browser_plugin_guest->focused() : false; |
| 1933 | } |
| 1934 | |
lfg | e2176fb | 2017-03-26 00:45:47 | [diff] [blame] | 1935 | RenderWidgetHost* GetMouseLockWidget(WebContents* web_contents) { |
| 1936 | return static_cast<WebContentsImpl*>(web_contents)->GetMouseLockWidget(); |
| 1937 | } |
| 1938 | |
Joe Downing | a7235f9 | 2018-05-30 22:40:52 | [diff] [blame] | 1939 | RenderWidgetHost* GetKeyboardLockWidget(WebContents* web_contents) { |
| 1940 | return static_cast<WebContentsImpl*>(web_contents)->GetKeyboardLockWidget(); |
| 1941 | } |
| 1942 | |
Ken Buchanan | d1d30d1 | 2018-10-04 22:48:04 | [diff] [blame] | 1943 | RenderWidgetHost* GetMouseCaptureWidget(WebContents* web_contents) { |
| 1944 | return static_cast<WebContentsImpl*>(web_contents) |
| 1945 | ->GetInputEventRouter() |
| 1946 | ->GetMouseCaptureWidgetForTests(); |
| 1947 | } |
| 1948 | |
Joe Downing | 89926824 | 2018-06-01 05:52:24 | [diff] [blame] | 1949 | bool RequestKeyboardLock(WebContents* web_contents, |
| 1950 | base::Optional<base::flat_set<ui::DomCode>> codes) { |
| 1951 | DCHECK(!codes.has_value() || !codes.value().empty()); |
| 1952 | WebContentsImpl* web_contents_impl = |
| 1953 | static_cast<WebContentsImpl*>(web_contents); |
| 1954 | RenderWidgetHostImpl* render_widget_host_impl = |
| 1955 | web_contents_impl->GetMainFrame()->GetRenderWidgetHost(); |
| 1956 | return render_widget_host_impl->RequestKeyboardLock(std::move(codes)); |
| 1957 | } |
| 1958 | |
| 1959 | void CancelKeyboardLock(WebContents* web_contents) { |
| 1960 | WebContentsImpl* web_contents_impl = |
| 1961 | static_cast<WebContentsImpl*>(web_contents); |
| 1962 | RenderWidgetHostImpl* render_widget_host_impl = |
| 1963 | web_contents_impl->GetMainFrame()->GetRenderWidgetHost(); |
| 1964 | render_widget_host_impl->CancelKeyboardLock(); |
| 1965 | } |
| 1966 | |
lfg | 1453e41 | 2017-04-11 00:48:50 | [diff] [blame] | 1967 | bool IsInnerInterstitialPageConnected(InterstitialPage* interstitial_page) { |
| 1968 | InterstitialPageImpl* impl = |
| 1969 | static_cast<InterstitialPageImpl*>(interstitial_page); |
| 1970 | |
| 1971 | RenderWidgetHostViewBase* rwhvb = |
| 1972 | static_cast<RenderWidgetHostViewBase*>(impl->GetView()); |
| 1973 | EXPECT_TRUE(rwhvb->IsRenderWidgetHostViewChildFrame()); |
| 1974 | RenderWidgetHostViewChildFrame* rwhvcf = |
| 1975 | static_cast<RenderWidgetHostViewChildFrame*>(rwhvb); |
| 1976 | |
| 1977 | CrossProcessFrameConnector* frame_connector = |
Ken Buchanan | daef006b | 2017-08-17 18:32:15 | [diff] [blame] | 1978 | static_cast<CrossProcessFrameConnector*>( |
| 1979 | rwhvcf->FrameConnectorForTesting()); |
lfg | 1453e41 | 2017-04-11 00:48:50 | [diff] [blame] | 1980 | |
| 1981 | WebContentsImpl* inner_web_contents = |
| 1982 | static_cast<WebContentsImpl*>(impl->GetWebContents()); |
| 1983 | FrameTreeNode* outer_node = FrameTreeNode::GloballyFindByID( |
| 1984 | inner_web_contents->GetOuterDelegateFrameTreeNodeId()); |
| 1985 | |
| 1986 | return outer_node->current_frame_host()->GetView() == |
| 1987 | frame_connector->GetParentRenderWidgetHostView(); |
| 1988 | } |
| 1989 | |
Evan Stade | f96e813 | 2018-10-18 18:55:38 | [diff] [blame] | 1990 | ScreenOrientationDelegate* GetScreenOrientationDelegate() { |
| 1991 | return ScreenOrientationProvider::GetDelegateForTesting(); |
| 1992 | } |
| 1993 | |
lfg | 1453e41 | 2017-04-11 00:48:50 | [diff] [blame] | 1994 | std::vector<RenderWidgetHostView*> GetInputEventRouterRenderWidgetHostViews( |
| 1995 | WebContents* web_contents) { |
| 1996 | return static_cast<WebContentsImpl*>(web_contents) |
| 1997 | ->GetInputEventRouter() |
| 1998 | ->GetRenderWidgetHostViewsForTests(); |
| 1999 | } |
| 2000 | |
| 2001 | RenderWidgetHost* GetFocusedRenderWidgetHost(WebContents* web_contents) { |
| 2002 | WebContentsImpl* web_contents_impl = |
| 2003 | static_cast<WebContentsImpl*>(web_contents); |
| 2004 | return web_contents_impl->GetFocusedRenderWidgetHost( |
| 2005 | web_contents_impl->GetMainFrame()->GetRenderWidgetHost()); |
| 2006 | } |
| 2007 | |
Lucas Furukawa Gadani | abbfa34 | 2017-08-29 19:37:57 | [diff] [blame] | 2008 | WebContents* GetFocusedWebContents(WebContents* web_contents) { |
| 2009 | WebContentsImpl* web_contents_impl = |
| 2010 | static_cast<WebContentsImpl*>(web_contents); |
| 2011 | return web_contents_impl->GetFocusedWebContents(); |
| 2012 | } |
| 2013 | |
lfg | 1453e41 | 2017-04-11 00:48:50 | [diff] [blame] | 2014 | void RouteMouseEvent(WebContents* web_contents, blink::WebMouseEvent* event) { |
| 2015 | WebContentsImpl* web_contents_impl = |
| 2016 | static_cast<WebContentsImpl*>(web_contents); |
| 2017 | web_contents_impl->GetInputEventRouter()->RouteMouseEvent( |
| 2018 | static_cast<RenderWidgetHostViewBase*>( |
| 2019 | web_contents_impl->GetMainFrame()->GetView()), |
| 2020 | event, ui::LatencyInfo()); |
| 2021 | } |
| 2022 | |
wjmaclean | b65ea79 | 2016-07-07 22:17:07 | [diff] [blame] | 2023 | #if defined(USE_AURA) |
| 2024 | void SendRoutedTouchTapSequence(content::WebContents* web_contents, |
| 2025 | gfx::Point point) { |
| 2026 | RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>( |
| 2027 | web_contents->GetRenderWidgetHostView()); |
lanwei | 6472567 | 2017-03-16 20:56:05 | [diff] [blame] | 2028 | ui::TouchEvent touch_start( |
| 2029 | ui::ET_TOUCH_PRESSED, point, base::TimeTicks::Now(), |
| 2030 | ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0)); |
wjmaclean | b65ea79 | 2016-07-07 22:17:07 | [diff] [blame] | 2031 | rwhva->OnTouchEvent(&touch_start); |
lanwei | 6472567 | 2017-03-16 20:56:05 | [diff] [blame] | 2032 | ui::TouchEvent touch_end( |
| 2033 | ui::ET_TOUCH_RELEASED, point, base::TimeTicks::Now(), |
| 2034 | ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0)); |
wjmaclean | b65ea79 | 2016-07-07 22:17:07 | [diff] [blame] | 2035 | rwhva->OnTouchEvent(&touch_end); |
| 2036 | } |
| 2037 | |
| 2038 | void SendRoutedGestureTapSequence(content::WebContents* web_contents, |
| 2039 | gfx::Point point) { |
| 2040 | RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>( |
| 2041 | web_contents->GetRenderWidgetHostView()); |
| 2042 | ui::GestureEventDetails gesture_tap_down_details(ui::ET_GESTURE_TAP_DOWN); |
Xida Chen | 2eec314f | 2018-06-07 11:42:42 | [diff] [blame] | 2043 | gesture_tap_down_details.set_is_source_touch_event_set_non_blocking(true); |
wjmaclean | b65ea79 | 2016-07-07 22:17:07 | [diff] [blame] | 2044 | gesture_tap_down_details.set_device_type( |
| 2045 | ui::GestureDeviceType::DEVICE_TOUCHSCREEN); |
| 2046 | ui::GestureEvent gesture_tap_down(point.x(), point.y(), 0, |
| 2047 | base::TimeTicks::Now(), |
| 2048 | gesture_tap_down_details); |
| 2049 | rwhva->OnGestureEvent(&gesture_tap_down); |
| 2050 | ui::GestureEventDetails gesture_tap_details(ui::ET_GESTURE_TAP); |
Xida Chen | 2eec314f | 2018-06-07 11:42:42 | [diff] [blame] | 2051 | gesture_tap_details.set_is_source_touch_event_set_non_blocking(true); |
wjmaclean | b65ea79 | 2016-07-07 22:17:07 | [diff] [blame] | 2052 | gesture_tap_details.set_device_type( |
| 2053 | ui::GestureDeviceType::DEVICE_TOUCHSCREEN); |
| 2054 | gesture_tap_details.set_tap_count(1); |
| 2055 | ui::GestureEvent gesture_tap(point.x(), point.y(), 0, base::TimeTicks::Now(), |
| 2056 | gesture_tap_details); |
| 2057 | rwhva->OnGestureEvent(&gesture_tap); |
| 2058 | } |
| 2059 | |
kenrb | 66c4629 | 2017-04-03 18:47:36 | [diff] [blame] | 2060 | #endif |
| 2061 | |
wjmaclean | b65ea79 | 2016-07-07 22:17:07 | [diff] [blame] | 2062 | namespace { |
| 2063 | |
jonross | 068adbc | 2018-05-30 18:04:47 | [diff] [blame] | 2064 | RenderFrameMetadataProvider* RenderFrameMetadataProviderFromFrameTreeNode( |
| 2065 | FrameTreeNode* node) { |
| 2066 | DCHECK(node); |
| 2067 | DCHECK(node->current_frame_host()); |
| 2068 | DCHECK(node->current_frame_host()->GetRenderWidgetHost()); |
| 2069 | return node->current_frame_host() |
| 2070 | ->GetRenderWidgetHost() |
| 2071 | ->render_frame_metadata_provider(); |
| 2072 | } |
| 2073 | |
jonross | 36545cf | 2018-02-23 19:50:35 | [diff] [blame] | 2074 | RenderFrameMetadataProvider* RenderFrameMetadataProviderFromWebContents( |
| 2075 | WebContents* web_contents) { |
Eric Seckler | 4f0eb9fa | 2018-03-01 11:23:21 | [diff] [blame] | 2076 | DCHECK(web_contents); |
| 2077 | DCHECK(web_contents->GetRenderViewHost()); |
| 2078 | DCHECK( |
| 2079 | RenderWidgetHostImpl::From(web_contents->GetRenderViewHost()->GetWidget()) |
| 2080 | ->render_frame_metadata_provider()); |
jonross | 36545cf | 2018-02-23 19:50:35 | [diff] [blame] | 2081 | return RenderWidgetHostImpl::From( |
| 2082 | web_contents->GetRenderViewHost()->GetWidget()) |
| 2083 | ->render_frame_metadata_provider(); |
| 2084 | } |
| 2085 | |
wjmaclean | b65ea79 | 2016-07-07 22:17:07 | [diff] [blame] | 2086 | } // namespace |
| 2087 | |
[email protected] | 35daebe0 | 2012-07-20 05:40:59 | [diff] [blame] | 2088 | TitleWatcher::TitleWatcher(WebContents* web_contents, |
[email protected] | fcf75d4 | 2013-12-03 20:11:26 | [diff] [blame] | 2089 | const base::string16& expected_title) |
ahest | 29276c3 | 2017-01-19 07:36:31 | [diff] [blame] | 2090 | : WebContentsObserver(web_contents) { |
[email protected] | 35daebe0 | 2012-07-20 05:40:59 | [diff] [blame] | 2091 | expected_titles_.push_back(expected_title); |
[email protected] | 35daebe0 | 2012-07-20 05:40:59 | [diff] [blame] | 2092 | } |
| 2093 | |
[email protected] | fcf75d4 | 2013-12-03 20:11:26 | [diff] [blame] | 2094 | void TitleWatcher::AlsoWaitForTitle(const base::string16& expected_title) { |
[email protected] | 35daebe0 | 2012-07-20 05:40:59 | [diff] [blame] | 2095 | expected_titles_.push_back(expected_title); |
| 2096 | } |
| 2097 | |
| 2098 | TitleWatcher::~TitleWatcher() { |
| 2099 | } |
| 2100 | |
[email protected] | fcf75d4 | 2013-12-03 20:11:26 | [diff] [blame] | 2101 | const base::string16& TitleWatcher::WaitAndGetTitle() { |
[email protected] | b17eb8e4 | 2014-02-07 01:20:37 | [diff] [blame] | 2102 | TestTitle(); |
ahest | 29276c3 | 2017-01-19 07:36:31 | [diff] [blame] | 2103 | run_loop_.Run(); |
[email protected] | 35daebe0 | 2012-07-20 05:40:59 | [diff] [blame] | 2104 | return observed_title_; |
| 2105 | } |
| 2106 | |
fdegans | 6ce28f5 | 2015-03-19 12:52:22 | [diff] [blame] | 2107 | void TitleWatcher::DidStopLoading() { |
[email protected] | 6679890 | 2013-10-01 18:40:16 | [diff] [blame] | 2108 | // When navigating through the history, the restored NavigationEntry's title |
| 2109 | // will be used. If the entry ends up having the same title after we return |
| 2110 | // to it, as will usually be the case, then WebContentsObserver::TitleSet |
| 2111 | // will then be suppressed, since the NavigationEntry's title hasn't changed. |
| 2112 | TestTitle(); |
| 2113 | } |
[email protected] | 35daebe0 | 2012-07-20 05:40:59 | [diff] [blame] | 2114 | |
Avi Drissman | 9300221 | 2017-09-27 03:20:52 | [diff] [blame] | 2115 | void TitleWatcher::TitleWasSet(NavigationEntry* entry) { |
[email protected] | 6679890 | 2013-10-01 18:40:16 | [diff] [blame] | 2116 | TestTitle(); |
| 2117 | } |
| 2118 | |
| 2119 | void TitleWatcher::TestTitle() { |
ahest | 29276c3 | 2017-01-19 07:36:31 | [diff] [blame] | 2120 | const base::string16& current_title = web_contents()->GetTitle(); |
| 2121 | if (base::ContainsValue(expected_titles_, current_title)) { |
| 2122 | observed_title_ = current_title; |
| 2123 | run_loop_.Quit(); |
| 2124 | } |
[email protected] | 35daebe0 | 2012-07-20 05:40:59 | [diff] [blame] | 2125 | } |
| 2126 | |
[email protected] | 8ffad4e | 2014-01-02 23:18:26 | [diff] [blame] | 2127 | RenderProcessHostWatcher::RenderProcessHostWatcher( |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 2128 | RenderProcessHost* render_process_host, |
| 2129 | WatchType type) |
[email protected] | 8ffad4e | 2014-01-02 23:18:26 | [diff] [blame] | 2130 | : render_process_host_(render_process_host), |
| 2131 | type_(type), |
alexmos | 3c8c8a1 | 2015-04-13 20:51:39 | [diff] [blame] | 2132 | did_exit_normally_(true), |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 2133 | quit_closure_(run_loop_.QuitClosure()) { |
[email protected] | 8ffad4e | 2014-01-02 23:18:26 | [diff] [blame] | 2134 | render_process_host_->AddObserver(this); |
| 2135 | } |
| 2136 | |
Lukasz Anforowicz | f14b545 | 2017-10-02 20:10:34 | [diff] [blame] | 2137 | RenderProcessHostWatcher::RenderProcessHostWatcher(WebContents* web_contents, |
| 2138 | WatchType type) |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 2139 | : RenderProcessHostWatcher(web_contents->GetMainFrame()->GetProcess(), |
| 2140 | type) {} |
[email protected] | 8ffad4e | 2014-01-02 23:18:26 | [diff] [blame] | 2141 | |
| 2142 | RenderProcessHostWatcher::~RenderProcessHostWatcher() { |
| 2143 | if (render_process_host_) |
| 2144 | render_process_host_->RemoveObserver(this); |
| 2145 | } |
| 2146 | |
| 2147 | void RenderProcessHostWatcher::Wait() { |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 2148 | run_loop_.Run(); |
[email protected] | 8ffad4e | 2014-01-02 23:18:26 | [diff] [blame] | 2149 | } |
| 2150 | |
| 2151 | void RenderProcessHostWatcher::RenderProcessExited( |
| 2152 | RenderProcessHost* host, |
Bo Liu | 2a48940 | 2018-04-24 23:41:27 | [diff] [blame] | 2153 | const ChildProcessTerminationInfo& info) { |
| 2154 | did_exit_normally_ = |
| 2155 | info.status == base::TERMINATION_STATUS_NORMAL_TERMINATION; |
[email protected] | 8ffad4e | 2014-01-02 23:18:26 | [diff] [blame] | 2156 | if (type_ == WATCH_FOR_PROCESS_EXIT) |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 2157 | std::move(quit_closure_).Run(); |
[email protected] | 8ffad4e | 2014-01-02 23:18:26 | [diff] [blame] | 2158 | } |
| 2159 | |
| 2160 | void RenderProcessHostWatcher::RenderProcessHostDestroyed( |
| 2161 | RenderProcessHost* host) { |
Ivan Kotenkov | 2c0d2bb3 | 2017-11-01 15:41:28 | [diff] [blame] | 2162 | render_process_host_ = nullptr; |
[email protected] | 8ffad4e | 2014-01-02 23:18:26 | [diff] [blame] | 2163 | if (type_ == WATCH_FOR_HOST_DESTRUCTION) |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 2164 | std::move(quit_closure_).Run(); |
[email protected] | 8ffad4e | 2014-01-02 23:18:26 | [diff] [blame] | 2165 | } |
| 2166 | |
[email protected] | 25ebc37b | 2014-03-24 21:34:48 | [diff] [blame] | 2167 | DOMMessageQueue::DOMMessageQueue() { |
[email protected] | b5e3497 | 2012-09-26 03:50:23 | [diff] [blame] | 2168 | registrar_.Add(this, NOTIFICATION_DOM_OPERATION_RESPONSE, |
| 2169 | NotificationService::AllSources()); |
| 2170 | } |
| 2171 | |
lukasza | f1cf692 | 2016-11-03 00:21:43 | [diff] [blame] | 2172 | DOMMessageQueue::DOMMessageQueue(WebContents* web_contents) |
| 2173 | : WebContentsObserver(web_contents) { |
| 2174 | registrar_.Add(this, NOTIFICATION_DOM_OPERATION_RESPONSE, |
| 2175 | Source<WebContents>(web_contents)); |
| 2176 | } |
| 2177 | |
[email protected] | b5e3497 | 2012-09-26 03:50:23 | [diff] [blame] | 2178 | DOMMessageQueue::~DOMMessageQueue() {} |
| 2179 | |
| 2180 | void DOMMessageQueue::Observe(int type, |
| 2181 | const NotificationSource& source, |
| 2182 | const NotificationDetails& details) { |
avi | 60bd490 | 2015-09-23 20:39:24 | [diff] [blame] | 2183 | Details<std::string> dom_op_result(details); |
| 2184 | message_queue_.push(*dom_op_result.ptr()); |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 2185 | if (quit_closure_) |
| 2186 | std::move(quit_closure_).Run(); |
[email protected] | b5e3497 | 2012-09-26 03:50:23 | [diff] [blame] | 2187 | } |
| 2188 | |
lukasza | f1cf692 | 2016-11-03 00:21:43 | [diff] [blame] | 2189 | void DOMMessageQueue::RenderProcessGone(base::TerminationStatus status) { |
vasilii | b50cee4c9 | 2017-03-31 11:53:14 | [diff] [blame] | 2190 | VLOG(0) << "DOMMessageQueue::RenderProcessGone " << status; |
lukasza | f1cf692 | 2016-11-03 00:21:43 | [diff] [blame] | 2191 | switch (status) { |
| 2192 | case base::TERMINATION_STATUS_NORMAL_TERMINATION: |
| 2193 | case base::TERMINATION_STATUS_STILL_RUNNING: |
| 2194 | break; |
| 2195 | default: |
lukasza | c7d6bd3 | 2017-07-11 00:19:31 | [diff] [blame] | 2196 | renderer_crashed_ = true; |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 2197 | if (quit_closure_) |
| 2198 | std::move(quit_closure_).Run(); |
lukasza | f1cf692 | 2016-11-03 00:21:43 | [diff] [blame] | 2199 | break; |
| 2200 | } |
| 2201 | } |
| 2202 | |
[email protected] | b5e3497 | 2012-09-26 03:50:23 | [diff] [blame] | 2203 | void DOMMessageQueue::ClearQueue() { |
Brett Wilson | cc8623d | 2017-09-12 03:28:10 | [diff] [blame] | 2204 | message_queue_ = base::queue<std::string>(); |
[email protected] | b5e3497 | 2012-09-26 03:50:23 | [diff] [blame] | 2205 | } |
| 2206 | |
| 2207 | bool DOMMessageQueue::WaitForMessage(std::string* message) { |
[email protected] | 25ebc37b | 2014-03-24 21:34:48 | [diff] [blame] | 2208 | DCHECK(message); |
lukasza | c7d6bd3 | 2017-07-11 00:19:31 | [diff] [blame] | 2209 | if (!renderer_crashed_ && message_queue_.empty()) { |
[email protected] | b5e3497 | 2012-09-26 03:50:23 | [diff] [blame] | 2210 | // This will be quit when a new message comes in. |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 2211 | base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed); |
| 2212 | quit_closure_ = run_loop.QuitClosure(); |
| 2213 | run_loop.Run(); |
[email protected] | b5e3497 | 2012-09-26 03:50:23 | [diff] [blame] | 2214 | } |
lukasza | d4d9b103 | 2016-12-10 03:38:12 | [diff] [blame] | 2215 | return PopMessage(message); |
| 2216 | } |
| 2217 | |
| 2218 | bool DOMMessageQueue::PopMessage(std::string* message) { |
| 2219 | DCHECK(message); |
lukasza | c7d6bd3 | 2017-07-11 00:19:31 | [diff] [blame] | 2220 | if (renderer_crashed_ || message_queue_.empty()) |
[email protected] | b5e3497 | 2012-09-26 03:50:23 | [diff] [blame] | 2221 | return false; |
[email protected] | 25ebc37b | 2014-03-24 21:34:48 | [diff] [blame] | 2222 | *message = message_queue_.front(); |
[email protected] | eb6a392 | 2013-06-21 22:03:52 | [diff] [blame] | 2223 | message_queue_.pop(); |
[email protected] | b5e3497 | 2012-09-26 03:50:23 | [diff] [blame] | 2224 | return true; |
| 2225 | } |
| 2226 | |
nick | 7bb1c5c7 | 2014-12-24 01:37:19 | [diff] [blame] | 2227 | class WebContentsAddedObserver::RenderViewCreatedObserver |
| 2228 | : public WebContentsObserver { |
| 2229 | public: |
| 2230 | explicit RenderViewCreatedObserver(WebContents* web_contents) |
| 2231 | : WebContentsObserver(web_contents), |
| 2232 | render_view_created_called_(false), |
| 2233 | main_frame_created_called_(false) {} |
| 2234 | |
| 2235 | // WebContentsObserver: |
| 2236 | void RenderViewCreated(RenderViewHost* rvh) override { |
| 2237 | render_view_created_called_ = true; |
| 2238 | } |
| 2239 | |
| 2240 | void RenderFrameCreated(RenderFrameHost* rfh) override { |
| 2241 | if (rfh == web_contents()->GetMainFrame()) |
| 2242 | main_frame_created_called_ = true; |
| 2243 | } |
| 2244 | |
| 2245 | bool render_view_created_called_; |
| 2246 | bool main_frame_created_called_; |
| 2247 | }; |
| 2248 | |
| 2249 | WebContentsAddedObserver::WebContentsAddedObserver() |
| 2250 | : web_contents_created_callback_( |
| 2251 | base::Bind(&WebContentsAddedObserver::WebContentsCreated, |
| 2252 | base::Unretained(this))), |
Ivan Kotenkov | 2c0d2bb3 | 2017-11-01 15:41:28 | [diff] [blame] | 2253 | web_contents_(nullptr) { |
benwells | 5e7260d | 2017-03-20 23:36:33 | [diff] [blame] | 2254 | WebContentsImpl::FriendWrapper::AddCreatedCallbackForTesting( |
nick | 7bb1c5c7 | 2014-12-24 01:37:19 | [diff] [blame] | 2255 | web_contents_created_callback_); |
| 2256 | } |
| 2257 | |
| 2258 | WebContentsAddedObserver::~WebContentsAddedObserver() { |
benwells | 5e7260d | 2017-03-20 23:36:33 | [diff] [blame] | 2259 | WebContentsImpl::FriendWrapper::RemoveCreatedCallbackForTesting( |
nick | 7bb1c5c7 | 2014-12-24 01:37:19 | [diff] [blame] | 2260 | web_contents_created_callback_); |
| 2261 | } |
| 2262 | |
| 2263 | void WebContentsAddedObserver::WebContentsCreated(WebContents* web_contents) { |
| 2264 | DCHECK(!web_contents_); |
| 2265 | web_contents_ = web_contents; |
| 2266 | child_observer_.reset(new RenderViewCreatedObserver(web_contents)); |
| 2267 | |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 2268 | if (quit_closure_) |
| 2269 | std::move(quit_closure_).Run(); |
nick | 7bb1c5c7 | 2014-12-24 01:37:19 | [diff] [blame] | 2270 | } |
| 2271 | |
| 2272 | WebContents* WebContentsAddedObserver::GetWebContents() { |
| 2273 | if (web_contents_) |
| 2274 | return web_contents_; |
| 2275 | |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 2276 | base::RunLoop run_loop; |
| 2277 | quit_closure_ = run_loop.QuitClosure(); |
| 2278 | run_loop.Run(); |
nick | 7bb1c5c7 | 2014-12-24 01:37:19 | [diff] [blame] | 2279 | return web_contents_; |
| 2280 | } |
| 2281 | |
| 2282 | bool WebContentsAddedObserver::RenderViewCreatedCalled() { |
| 2283 | if (child_observer_) { |
| 2284 | return child_observer_->render_view_created_called_ && |
| 2285 | child_observer_->main_frame_created_called_; |
| 2286 | } |
| 2287 | return false; |
| 2288 | } |
| 2289 | |
Gennady Sushko | 1fbd57fa | 2017-10-25 20:28:17 | [diff] [blame] | 2290 | WebContentsDestroyedObserver::WebContentsDestroyedObserver( |
| 2291 | WebContents* web_contents) |
| 2292 | : WebContentsObserver(web_contents) { |
| 2293 | DCHECK(web_contents); |
| 2294 | } |
| 2295 | |
| 2296 | WebContentsDestroyedObserver::~WebContentsDestroyedObserver() {} |
| 2297 | |
| 2298 | void WebContentsDestroyedObserver::WebContentsDestroyed() { |
| 2299 | destroyed_ = true; |
| 2300 | } |
| 2301 | |
wjmaclean | 6aefc3a | 2015-06-22 21:58:29 | [diff] [blame] | 2302 | bool RequestFrame(WebContents* web_contents) { |
| 2303 | DCHECK(web_contents); |
avi | f9ab5d94 | 2015-10-15 14:05:44 | [diff] [blame] | 2304 | return RenderWidgetHostImpl::From( |
| 2305 | web_contents->GetRenderViewHost()->GetWidget()) |
Fady Samuel | 3798e6d5 | 2018-05-02 17:06:25 | [diff] [blame] | 2306 | ->RequestRepaintForTesting(); |
wjmaclean | 6aefc3a | 2015-06-22 21:58:29 | [diff] [blame] | 2307 | } |
| 2308 | |
jonross | a2ff4f8 | 2018-02-16 17:27:46 | [diff] [blame] | 2309 | RenderFrameSubmissionObserver::RenderFrameSubmissionObserver( |
| 2310 | RenderFrameMetadataProvider* render_frame_metadata_provider) |
| 2311 | : render_frame_metadata_provider_(render_frame_metadata_provider) { |
| 2312 | render_frame_metadata_provider_->AddObserver(this); |
| 2313 | render_frame_metadata_provider_->ReportAllFrameSubmissionsForTesting(true); |
| 2314 | } |
| 2315 | |
jonross | 36545cf | 2018-02-23 19:50:35 | [diff] [blame] | 2316 | RenderFrameSubmissionObserver::RenderFrameSubmissionObserver( |
jonross | 068adbc | 2018-05-30 18:04:47 | [diff] [blame] | 2317 | FrameTreeNode* node) |
| 2318 | : RenderFrameSubmissionObserver( |
| 2319 | RenderFrameMetadataProviderFromFrameTreeNode(node)) {} |
| 2320 | |
| 2321 | RenderFrameSubmissionObserver::RenderFrameSubmissionObserver( |
jonross | 36545cf | 2018-02-23 19:50:35 | [diff] [blame] | 2322 | WebContents* web_contents) |
| 2323 | : RenderFrameSubmissionObserver( |
| 2324 | RenderFrameMetadataProviderFromWebContents(web_contents)) {} |
| 2325 | |
jonross | a2ff4f8 | 2018-02-16 17:27:46 | [diff] [blame] | 2326 | RenderFrameSubmissionObserver::~RenderFrameSubmissionObserver() { |
| 2327 | render_frame_metadata_provider_->RemoveObserver(this); |
| 2328 | render_frame_metadata_provider_->ReportAllFrameSubmissionsForTesting(false); |
| 2329 | } |
| 2330 | |
jonross | 36545cf | 2018-02-23 19:50:35 | [diff] [blame] | 2331 | void RenderFrameSubmissionObserver::WaitForAnyFrameSubmission() { |
| 2332 | break_on_any_frame_ = true; |
| 2333 | Wait(); |
| 2334 | break_on_any_frame_ = false; |
| 2335 | } |
| 2336 | |
| 2337 | void RenderFrameSubmissionObserver::WaitForMetadataChange() { |
| 2338 | Wait(); |
| 2339 | } |
| 2340 | |
W. James MacLean | 2a90bff | 2018-11-05 20:52:47 | [diff] [blame] | 2341 | void RenderFrameSubmissionObserver::WaitForPageScaleFactor( |
| 2342 | float expected_page_scale_factor, |
| 2343 | const float tolerance) { |
| 2344 | while (std::abs(render_frame_metadata_provider_->LastRenderFrameMetadata() |
| 2345 | .page_scale_factor - |
| 2346 | expected_page_scale_factor) < tolerance) { |
| 2347 | WaitForMetadataChange(); |
| 2348 | } |
| 2349 | } |
| 2350 | |
| 2351 | void RenderFrameSubmissionObserver::WaitForExternalPageScaleFactor( |
| 2352 | float expected_external_page_scale_factor, |
| 2353 | const float tolerance) { |
| 2354 | while (std::abs(render_frame_metadata_provider_->LastRenderFrameMetadata() |
| 2355 | .external_page_scale_factor - |
| 2356 | expected_external_page_scale_factor) < tolerance) { |
| 2357 | WaitForMetadataChange(); |
| 2358 | } |
| 2359 | } |
| 2360 | |
jonross | 082707af4 | 2018-03-23 14:14:30 | [diff] [blame] | 2361 | void RenderFrameSubmissionObserver::WaitForScrollOffset( |
| 2362 | const gfx::Vector2dF& expected_offset) { |
| 2363 | while (render_frame_metadata_provider_->LastRenderFrameMetadata() |
| 2364 | .root_scroll_offset != expected_offset) { |
| 2365 | WaitForMetadataChange(); |
| 2366 | } |
| 2367 | } |
| 2368 | |
yiyix | 5989c74 | 2018-04-06 19:13:16 | [diff] [blame] | 2369 | void RenderFrameSubmissionObserver::WaitForScrollOffsetAtTop( |
| 2370 | bool expected_scroll_offset_at_top) { |
| 2371 | while (render_frame_metadata_provider_->LastRenderFrameMetadata() |
| 2372 | .is_scroll_offset_at_top != expected_scroll_offset_at_top) { |
| 2373 | WaitForMetadataChange(); |
| 2374 | } |
| 2375 | } |
| 2376 | |
jonross | 36545cf | 2018-02-23 19:50:35 | [diff] [blame] | 2377 | const cc::RenderFrameMetadata& |
| 2378 | RenderFrameSubmissionObserver::LastRenderFrameMetadata() const { |
| 2379 | return render_frame_metadata_provider_->LastRenderFrameMetadata(); |
jonross | a2ff4f8 | 2018-02-16 17:27:46 | [diff] [blame] | 2380 | } |
| 2381 | |
| 2382 | void RenderFrameSubmissionObserver::Quit() { |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 2383 | if (quit_closure_) |
| 2384 | std::move(quit_closure_).Run(); |
jonross | a2ff4f8 | 2018-02-16 17:27:46 | [diff] [blame] | 2385 | } |
| 2386 | |
jonross | 36545cf | 2018-02-23 19:50:35 | [diff] [blame] | 2387 | void RenderFrameSubmissionObserver::Wait() { |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 2388 | base::RunLoop run_loop; |
| 2389 | quit_closure_ = run_loop.QuitClosure(); |
| 2390 | run_loop.Run(); |
jonross | 36545cf | 2018-02-23 19:50:35 | [diff] [blame] | 2391 | } |
| 2392 | |
Fady Samuel | 365f293 | 2018-06-24 14:14:50 | [diff] [blame] | 2393 | void RenderFrameSubmissionObserver:: |
| 2394 | OnRenderFrameMetadataChangedBeforeActivation( |
| 2395 | const cc::RenderFrameMetadata& metadata) {} |
| 2396 | |
| 2397 | void RenderFrameSubmissionObserver:: |
| 2398 | OnRenderFrameMetadataChangedAfterActivation() { |
jonross | 36545cf | 2018-02-23 19:50:35 | [diff] [blame] | 2399 | Quit(); |
| 2400 | } |
jonross | a2ff4f8 | 2018-02-16 17:27:46 | [diff] [blame] | 2401 | |
| 2402 | void RenderFrameSubmissionObserver::OnRenderFrameSubmission() { |
Eric Seckler | 4f0eb9fa | 2018-03-01 11:23:21 | [diff] [blame] | 2403 | render_frame_count_++; |
jonross | 36545cf | 2018-02-23 19:50:35 | [diff] [blame] | 2404 | if (break_on_any_frame_) |
| 2405 | Quit(); |
jonross | a2ff4f8 | 2018-02-16 17:27:46 | [diff] [blame] | 2406 | } |
| 2407 | |
Fady Samuel | ca9ecb7 | 2018-05-05 05:59:27 | [diff] [blame] | 2408 | void RenderFrameSubmissionObserver::OnLocalSurfaceIdChanged( |
| 2409 | const cc::RenderFrameMetadata& metadata) {} |
| 2410 | |
lfg | 43e08e6 | 2016-02-03 18:51:37 | [diff] [blame] | 2411 | MainThreadFrameObserver::MainThreadFrameObserver( |
| 2412 | RenderWidgetHost* render_widget_host) |
| 2413 | : render_widget_host_(render_widget_host), |
| 2414 | routing_id_(render_widget_host_->GetProcess()->GetNextRoutingID()) { |
| 2415 | // TODO(lfg): We should look into adding a way to observe RenderWidgetHost |
| 2416 | // messages similarly to what WebContentsObserver can do with RFH and RVW. |
| 2417 | render_widget_host_->GetProcess()->AddRoute(routing_id_, this); |
| 2418 | } |
| 2419 | |
| 2420 | MainThreadFrameObserver::~MainThreadFrameObserver() { |
| 2421 | render_widget_host_->GetProcess()->RemoveRoute(routing_id_); |
| 2422 | } |
| 2423 | |
| 2424 | void MainThreadFrameObserver::Wait() { |
| 2425 | DCHECK_CURRENTLY_ON(BrowserThread::UI); |
Albert J. Wong | 3c93c18 | 2018-09-27 17:29:43 | [diff] [blame] | 2426 | render_widget_host_->Send(new WidgetMsg_WaitForNextFrameForTests( |
lfg | 43e08e6 | 2016-02-03 18:51:37 | [diff] [blame] | 2427 | render_widget_host_->GetRoutingID(), routing_id_)); |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 2428 | base::RunLoop run_loop; |
| 2429 | quit_closure_ = run_loop.QuitClosure(); |
| 2430 | run_loop.Run(); |
lfg | 43e08e6 | 2016-02-03 18:51:37 | [diff] [blame] | 2431 | } |
| 2432 | |
| 2433 | void MainThreadFrameObserver::Quit() { |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 2434 | if (quit_closure_) |
| 2435 | std::move(quit_closure_).Run(); |
lfg | 43e08e6 | 2016-02-03 18:51:37 | [diff] [blame] | 2436 | } |
| 2437 | |
| 2438 | bool MainThreadFrameObserver::OnMessageReceived(const IPC::Message& msg) { |
Albert J. Wong | 3c93c18 | 2018-09-27 17:29:43 | [diff] [blame] | 2439 | if (msg.type() == WidgetHostMsg_WaitForNextFrameForTests_ACK::ID && |
lfg | 43e08e6 | 2016-02-03 18:51:37 | [diff] [blame] | 2440 | msg.routing_id() == routing_id_) { |
Eric Seckler | 8652dcd5 | 2018-09-20 10:42:28 | [diff] [blame] | 2441 | base::PostTaskWithTraits( |
| 2442 | FROM_HERE, {BrowserThread::UI}, |
tzik | 87419051 | 2017-08-18 01:40:20 | [diff] [blame] | 2443 | base::BindOnce(&MainThreadFrameObserver::Quit, base::Unretained(this))); |
lfg | 43e08e6 | 2016-02-03 18:51:37 | [diff] [blame] | 2444 | } |
| 2445 | return true; |
| 2446 | } |
| 2447 | |
dtapuska | 0bd451a | 2016-02-18 17:08:10 | [diff] [blame] | 2448 | InputMsgWatcher::InputMsgWatcher(RenderWidgetHost* render_widget_host, |
| 2449 | blink::WebInputEvent::Type type) |
Dave Tapuska | b1b6faa | 2017-10-23 21:54:23 | [diff] [blame] | 2450 | : render_widget_host_(render_widget_host), |
dtapuska | 0bd451a | 2016-02-18 17:08:10 | [diff] [blame] | 2451 | wait_for_type_(type), |
dtapuska | 120e997 | 2016-11-07 20:13:39 | [diff] [blame] | 2452 | ack_result_(INPUT_EVENT_ACK_STATE_UNKNOWN), |
Dave Tapuska | b1b6faa | 2017-10-23 21:54:23 | [diff] [blame] | 2453 | ack_source_(InputEventAckSource::UNKNOWN) { |
| 2454 | render_widget_host->AddInputEventObserver(this); |
dtapuska | 0bd451a | 2016-02-18 17:08:10 | [diff] [blame] | 2455 | } |
| 2456 | |
Dave Tapuska | b1b6faa | 2017-10-23 21:54:23 | [diff] [blame] | 2457 | InputMsgWatcher::~InputMsgWatcher() { |
| 2458 | render_widget_host_->RemoveInputEventObserver(this); |
| 2459 | } |
dtapuska | 0bd451a | 2016-02-18 17:08:10 | [diff] [blame] | 2460 | |
Dave Tapuska | b1b6faa | 2017-10-23 21:54:23 | [diff] [blame] | 2461 | void InputMsgWatcher::OnInputEventAck(InputEventAckSource ack_source, |
| 2462 | InputEventAckState ack_state, |
| 2463 | const blink::WebInputEvent& event) { |
| 2464 | if (event.GetType() == wait_for_type_) { |
dtapuska | 0bd451a | 2016-02-18 17:08:10 | [diff] [blame] | 2465 | ack_result_ = ack_state; |
dtapuska | 120e997 | 2016-11-07 20:13:39 | [diff] [blame] | 2466 | ack_source_ = ack_source; |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 2467 | if (quit_closure_) |
| 2468 | std::move(quit_closure_).Run(); |
dtapuska | 0bd451a | 2016-02-18 17:08:10 | [diff] [blame] | 2469 | } |
| 2470 | } |
| 2471 | |
samuong | 8db7601 | 2017-01-20 06:36:08 | [diff] [blame] | 2472 | bool InputMsgWatcher::HasReceivedAck() const { |
| 2473 | return ack_result_ != INPUT_EVENT_ACK_STATE_UNKNOWN; |
| 2474 | } |
| 2475 | |
Dave Tapuska | b1b6faa | 2017-10-23 21:54:23 | [diff] [blame] | 2476 | InputEventAckState InputMsgWatcher::WaitForAck() { |
dtapuska | 0bd451a | 2016-02-18 17:08:10 | [diff] [blame] | 2477 | DCHECK_CURRENTLY_ON(BrowserThread::UI); |
dtapuska | 0bd451a | 2016-02-18 17:08:10 | [diff] [blame] | 2478 | base::RunLoop run_loop; |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 2479 | quit_closure_ = run_loop.QuitClosure(); |
dtapuska | 0bd451a | 2016-02-18 17:08:10 | [diff] [blame] | 2480 | run_loop.Run(); |
| 2481 | return ack_result_; |
| 2482 | } |
| 2483 | |
Dave Tapuska | 27e3e7c | 2017-10-25 13:14:55 | [diff] [blame] | 2484 | InputEventAckState InputMsgWatcher::GetAckStateWaitIfNecessary() { |
| 2485 | if (HasReceivedAck()) |
| 2486 | return ack_result_; |
| 2487 | return WaitForAck(); |
| 2488 | } |
| 2489 | |
Kevin McNee | cbb8687a | 2017-11-14 19:10:59 | [diff] [blame] | 2490 | InputEventAckWaiter::InputEventAckWaiter(RenderWidgetHost* render_widget_host, |
| 2491 | InputEventAckPredicate predicate) |
| 2492 | : render_widget_host_(render_widget_host), |
| 2493 | predicate_(predicate), |
| 2494 | event_received_(false) { |
| 2495 | render_widget_host_->AddInputEventObserver(this); |
| 2496 | } |
| 2497 | |
| 2498 | namespace { |
| 2499 | InputEventAckWaiter::InputEventAckPredicate EventAckHasType( |
| 2500 | blink::WebInputEvent::Type type) { |
| 2501 | return base::BindRepeating( |
| 2502 | [](blink::WebInputEvent::Type expected_type, InputEventAckSource source, |
| 2503 | InputEventAckState state, const blink::WebInputEvent& event) { |
| 2504 | return event.GetType() == expected_type; |
| 2505 | }, |
| 2506 | type); |
| 2507 | } |
| 2508 | } // namespace |
| 2509 | |
| 2510 | InputEventAckWaiter::InputEventAckWaiter(RenderWidgetHost* render_widget_host, |
| 2511 | blink::WebInputEvent::Type type) |
| 2512 | : InputEventAckWaiter(render_widget_host, EventAckHasType(type)) {} |
| 2513 | |
| 2514 | InputEventAckWaiter::~InputEventAckWaiter() { |
| 2515 | render_widget_host_->RemoveInputEventObserver(this); |
| 2516 | } |
| 2517 | |
| 2518 | void InputEventAckWaiter::Wait() { |
| 2519 | if (!event_received_) { |
| 2520 | base::RunLoop run_loop; |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 2521 | quit_closure_ = run_loop.QuitClosure(); |
Kevin McNee | cbb8687a | 2017-11-14 19:10:59 | [diff] [blame] | 2522 | run_loop.Run(); |
| 2523 | } |
| 2524 | } |
| 2525 | |
| 2526 | void InputEventAckWaiter::Reset() { |
| 2527 | event_received_ = false; |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 2528 | quit_closure_ = base::OnceClosure(); |
Kevin McNee | cbb8687a | 2017-11-14 19:10:59 | [diff] [blame] | 2529 | } |
| 2530 | |
| 2531 | void InputEventAckWaiter::OnInputEventAck(InputEventAckSource source, |
| 2532 | InputEventAckState state, |
| 2533 | const blink::WebInputEvent& event) { |
| 2534 | if (predicate_.Run(source, state, event)) { |
| 2535 | event_received_ = true; |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 2536 | if (quit_closure_) |
| 2537 | std::move(quit_closure_).Run(); |
Kevin McNee | cbb8687a | 2017-11-14 19:10:59 | [diff] [blame] | 2538 | } |
| 2539 | } |
| 2540 | |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 2541 | // TODO(dcheng): Make the test clipboard on different threads share the |
| 2542 | // same backing store. crbug.com/629765 |
| 2543 | // TODO(slangley): crbug.com/775830 - Cleanup BrowserTestClipboardScope now that |
| 2544 | // there is no need to thread hop for Windows. |
| 2545 | BrowserTestClipboardScope::BrowserTestClipboardScope() { |
dominicc | 4d8435d | 2016-07-22 03:43:34 | [diff] [blame] | 2546 | ui::TestClipboard::CreateForCurrentThread(); |
| 2547 | } |
| 2548 | |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 2549 | BrowserTestClipboardScope::~BrowserTestClipboardScope() { |
dominicc | 4d8435d | 2016-07-22 03:43:34 | [diff] [blame] | 2550 | ui::Clipboard::DestroyClipboardForCurrentThread(); |
| 2551 | } |
| 2552 | |
dominicc | 4d8435d | 2016-07-22 03:43:34 | [diff] [blame] | 2553 | void BrowserTestClipboardScope::SetRtf(const std::string& rtf) { |
dominicc | 4d8435d | 2016-07-22 03:43:34 | [diff] [blame] | 2554 | ui::ScopedClipboardWriter clipboard_writer(ui::CLIPBOARD_TYPE_COPY_PASTE); |
| 2555 | clipboard_writer.WriteRTF(rtf); |
| 2556 | } |
| 2557 | |
| 2558 | void BrowserTestClipboardScope::SetText(const std::string& text) { |
dominicc | 4d8435d | 2016-07-22 03:43:34 | [diff] [blame] | 2559 | ui::ScopedClipboardWriter clipboard_writer(ui::CLIPBOARD_TYPE_COPY_PASTE); |
| 2560 | clipboard_writer.WriteText(base::ASCIIToUTF16(text)); |
| 2561 | } |
| 2562 | |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 2563 | void BrowserTestClipboardScope::GetText(std::string* result) { |
| 2564 | ui::Clipboard::GetForCurrentThread()->ReadAsciiText( |
| 2565 | ui::CLIPBOARD_TYPE_COPY_PASTE, result); |
| 2566 | } |
| 2567 | |
avallee | 0206f78 | 2016-07-28 18:55:33 | [diff] [blame] | 2568 | class FrameFocusedObserver::FrameTreeNodeObserverImpl |
| 2569 | : public FrameTreeNode::Observer { |
| 2570 | public: |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 2571 | explicit FrameTreeNodeObserverImpl(FrameTreeNode* owner) : owner_(owner) { |
avallee | 0206f78 | 2016-07-28 18:55:33 | [diff] [blame] | 2572 | owner->AddObserver(this); |
| 2573 | } |
| 2574 | ~FrameTreeNodeObserverImpl() override { owner_->RemoveObserver(this); } |
| 2575 | |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 2576 | void Run() { run_loop_.Run(); } |
avallee | 0206f78 | 2016-07-28 18:55:33 | [diff] [blame] | 2577 | |
| 2578 | void OnFrameTreeNodeFocused(FrameTreeNode* node) override { |
| 2579 | if (node == owner_) |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 2580 | run_loop_.Quit(); |
avallee | 0206f78 | 2016-07-28 18:55:33 | [diff] [blame] | 2581 | } |
| 2582 | |
| 2583 | private: |
| 2584 | FrameTreeNode* owner_; |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 2585 | base::RunLoop run_loop_; |
avallee | 0206f78 | 2016-07-28 18:55:33 | [diff] [blame] | 2586 | }; |
| 2587 | |
| 2588 | FrameFocusedObserver::FrameFocusedObserver(RenderFrameHost* owner_host) |
| 2589 | : impl_(new FrameTreeNodeObserverImpl( |
| 2590 | static_cast<RenderFrameHostImpl*>(owner_host)->frame_tree_node())) {} |
| 2591 | |
| 2592 | FrameFocusedObserver::~FrameFocusedObserver() {} |
| 2593 | |
| 2594 | void FrameFocusedObserver::Wait() { |
| 2595 | impl_->Run(); |
| 2596 | } |
| 2597 | |
Ria Jiang | 79f58ed92 | 2018-04-10 03:30:52 | [diff] [blame] | 2598 | class FrameDeletedObserver::FrameTreeNodeObserverImpl |
| 2599 | : public FrameTreeNode::Observer { |
| 2600 | public: |
| 2601 | explicit FrameTreeNodeObserverImpl(FrameTreeNode* owner) : owner_(owner) { |
| 2602 | owner->AddObserver(this); |
| 2603 | } |
| 2604 | ~FrameTreeNodeObserverImpl() override = default; |
| 2605 | |
| 2606 | void Run() { run_loop_.Run(); } |
| 2607 | |
| 2608 | private: |
| 2609 | // FrameTreeNode::Observer |
| 2610 | void OnFrameTreeNodeDestroyed(FrameTreeNode* node) override { |
| 2611 | if (node == owner_) |
| 2612 | run_loop_.Quit(); |
| 2613 | } |
| 2614 | |
| 2615 | FrameTreeNode* owner_; |
| 2616 | base::RunLoop run_loop_; |
| 2617 | }; |
| 2618 | |
| 2619 | FrameDeletedObserver::FrameDeletedObserver(RenderFrameHost* owner_host) |
| 2620 | : impl_(new FrameTreeNodeObserverImpl( |
| 2621 | static_cast<RenderFrameHostImpl*>(owner_host)->frame_tree_node())) {} |
| 2622 | |
| 2623 | FrameDeletedObserver::~FrameDeletedObserver() = default; |
| 2624 | |
| 2625 | void FrameDeletedObserver::Wait() { |
| 2626 | impl_->Run(); |
| 2627 | } |
| 2628 | |
csharrison | 4bd8a19 | 2016-08-02 18:03:15 | [diff] [blame] | 2629 | TestNavigationManager::TestNavigationManager(WebContents* web_contents, |
| 2630 | const GURL& url) |
| 2631 | : WebContentsObserver(web_contents), |
| 2632 | url_(url), |
csharrison | 4bd8a19 | 2016-08-02 18:03:15 | [diff] [blame] | 2633 | handle_(nullptr), |
clamy | 19f0d49 | 2016-10-13 16:53:28 | [diff] [blame] | 2634 | navigation_paused_(false), |
| 2635 | current_state_(NavigationState::INITIAL), |
| 2636 | desired_state_(NavigationState::STARTED), |
csharrison | 4bd8a19 | 2016-08-02 18:03:15 | [diff] [blame] | 2637 | weak_factory_(this) {} |
| 2638 | |
| 2639 | TestNavigationManager::~TestNavigationManager() { |
clamy | 19f0d49 | 2016-10-13 16:53:28 | [diff] [blame] | 2640 | if (navigation_paused_) |
Charles Harrison | 4f2bf1a | 2017-07-18 20:21:21 | [diff] [blame] | 2641 | handle_->CallResumeForTesting(); |
csharrison | 4bd8a19 | 2016-08-02 18:03:15 | [diff] [blame] | 2642 | } |
| 2643 | |
clamy | 19f0d49 | 2016-10-13 16:53:28 | [diff] [blame] | 2644 | bool TestNavigationManager::WaitForRequestStart() { |
| 2645 | // This is the default desired state. In PlzNavigate, a browser-initiated |
| 2646 | // navigation can reach this state synchronously, so the TestNavigationManager |
| 2647 | // is set to always pause navigations at WillStartRequest. This ensures the |
| 2648 | // user can always call WaitForWillStartRequest. |
| 2649 | DCHECK(desired_state_ == NavigationState::STARTED); |
| 2650 | return WaitForDesiredState(); |
csharrison | 4bd8a19 | 2016-08-02 18:03:15 | [diff] [blame] | 2651 | } |
| 2652 | |
arthursonzogni | 85a0423 | 2017-09-28 18:14:19 | [diff] [blame] | 2653 | void TestNavigationManager::ResumeNavigation() { |
| 2654 | DCHECK(current_state_ == NavigationState::STARTED || |
| 2655 | current_state_ == NavigationState::RESPONSE); |
| 2656 | DCHECK_EQ(current_state_, desired_state_); |
| 2657 | DCHECK(navigation_paused_); |
| 2658 | navigation_paused_ = false; |
| 2659 | handle_->CallResumeForTesting(); |
| 2660 | } |
| 2661 | |
arthursonzogni | 3a4ca9f | 2017-12-07 17:58:34 | [diff] [blame] | 2662 | NavigationHandle* TestNavigationManager::GetNavigationHandle() { |
| 2663 | return handle_; |
| 2664 | } |
| 2665 | |
clamy | 19f0d49 | 2016-10-13 16:53:28 | [diff] [blame] | 2666 | bool TestNavigationManager::WaitForResponse() { |
| 2667 | desired_state_ = NavigationState::RESPONSE; |
| 2668 | return WaitForDesiredState(); |
clamy | d69748c | 2016-10-07 22:09:44 | [diff] [blame] | 2669 | } |
| 2670 | |
csharrison | 4bd8a19 | 2016-08-02 18:03:15 | [diff] [blame] | 2671 | void TestNavigationManager::WaitForNavigationFinished() { |
clamy | 19f0d49 | 2016-10-13 16:53:28 | [diff] [blame] | 2672 | desired_state_ = NavigationState::FINISHED; |
| 2673 | WaitForDesiredState(); |
csharrison | 4bd8a19 | 2016-08-02 18:03:15 | [diff] [blame] | 2674 | } |
| 2675 | |
| 2676 | void TestNavigationManager::DidStartNavigation(NavigationHandle* handle) { |
| 2677 | if (!ShouldMonitorNavigation(handle)) |
| 2678 | return; |
| 2679 | |
| 2680 | handle_ = handle; |
| 2681 | std::unique_ptr<NavigationThrottle> throttle( |
| 2682 | new TestNavigationManagerThrottle( |
| 2683 | handle_, base::Bind(&TestNavigationManager::OnWillStartRequest, |
clamy | d69748c | 2016-10-07 22:09:44 | [diff] [blame] | 2684 | weak_factory_.GetWeakPtr()), |
| 2685 | base::Bind(&TestNavigationManager::OnWillProcessResponse, |
| 2686 | weak_factory_.GetWeakPtr()))); |
csharrison | 4bd8a19 | 2016-08-02 18:03:15 | [diff] [blame] | 2687 | handle_->RegisterThrottleForTesting(std::move(throttle)); |
| 2688 | } |
| 2689 | |
| 2690 | void TestNavigationManager::DidFinishNavigation(NavigationHandle* handle) { |
| 2691 | if (handle != handle_) |
| 2692 | return; |
clamy | b99ec53 | 2018-03-01 15:00:48 | [diff] [blame] | 2693 | was_successful_ = handle->HasCommitted() && !handle->IsErrorPage(); |
clamy | 19f0d49 | 2016-10-13 16:53:28 | [diff] [blame] | 2694 | current_state_ = NavigationState::FINISHED; |
| 2695 | navigation_paused_ = false; |
csharrison | 4bd8a19 | 2016-08-02 18:03:15 | [diff] [blame] | 2696 | handle_ = nullptr; |
clamy | 19f0d49 | 2016-10-13 16:53:28 | [diff] [blame] | 2697 | OnNavigationStateChanged(); |
csharrison | 4bd8a19 | 2016-08-02 18:03:15 | [diff] [blame] | 2698 | } |
| 2699 | |
| 2700 | void TestNavigationManager::OnWillStartRequest() { |
clamy | 19f0d49 | 2016-10-13 16:53:28 | [diff] [blame] | 2701 | current_state_ = NavigationState::STARTED; |
| 2702 | navigation_paused_ = true; |
| 2703 | OnNavigationStateChanged(); |
clamy | d69748c | 2016-10-07 22:09:44 | [diff] [blame] | 2704 | } |
| 2705 | |
| 2706 | void TestNavigationManager::OnWillProcessResponse() { |
clamy | 19f0d49 | 2016-10-13 16:53:28 | [diff] [blame] | 2707 | current_state_ = NavigationState::RESPONSE; |
| 2708 | navigation_paused_ = true; |
| 2709 | OnNavigationStateChanged(); |
csharrison | 4bd8a19 | 2016-08-02 18:03:15 | [diff] [blame] | 2710 | } |
| 2711 | |
Charles Harrison | 4f2bf1a | 2017-07-18 20:21:21 | [diff] [blame] | 2712 | // TODO(csharrison): Remove CallResumeForTesting method calls in favor of doing |
| 2713 | // it through the throttle. |
clamy | 19f0d49 | 2016-10-13 16:53:28 | [diff] [blame] | 2714 | bool TestNavigationManager::WaitForDesiredState() { |
| 2715 | // If the desired state has laready been reached, just return. |
| 2716 | if (current_state_ == desired_state_) |
| 2717 | return true; |
| 2718 | |
| 2719 | // Resume the navigation if it was paused. |
| 2720 | if (navigation_paused_) |
Charles Harrison | 4f2bf1a | 2017-07-18 20:21:21 | [diff] [blame] | 2721 | handle_->CallResumeForTesting(); |
clamy | 19f0d49 | 2016-10-13 16:53:28 | [diff] [blame] | 2722 | |
| 2723 | // Wait for the desired state if needed. |
| 2724 | if (current_state_ < desired_state_) { |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 2725 | DCHECK(!quit_closure_); |
| 2726 | base::RunLoop run_loop; |
| 2727 | quit_closure_ = run_loop.QuitClosure(); |
| 2728 | run_loop.Run(); |
clamy | 19f0d49 | 2016-10-13 16:53:28 | [diff] [blame] | 2729 | } |
| 2730 | |
| 2731 | // Return false if the navigation did not reach the state specified by the |
| 2732 | // user. |
| 2733 | return current_state_ == desired_state_; |
| 2734 | } |
| 2735 | |
| 2736 | void TestNavigationManager::OnNavigationStateChanged() { |
| 2737 | // If the state the user was waiting for has been reached, exit the message |
| 2738 | // loop. |
| 2739 | if (current_state_ >= desired_state_) { |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 2740 | if (quit_closure_) |
| 2741 | std::move(quit_closure_).Run(); |
csharrison | 4bd8a19 | 2016-08-02 18:03:15 | [diff] [blame] | 2742 | return; |
clamy | d69748c | 2016-10-07 22:09:44 | [diff] [blame] | 2743 | } |
clamy | 19f0d49 | 2016-10-13 16:53:28 | [diff] [blame] | 2744 | |
| 2745 | // Otherwise, the navigation should be resumed if it was previously paused. |
| 2746 | if (navigation_paused_) |
Charles Harrison | 4f2bf1a | 2017-07-18 20:21:21 | [diff] [blame] | 2747 | handle_->CallResumeForTesting(); |
csharrison | 4bd8a19 | 2016-08-02 18:03:15 | [diff] [blame] | 2748 | } |
| 2749 | |
| 2750 | bool TestNavigationManager::ShouldMonitorNavigation(NavigationHandle* handle) { |
| 2751 | if (handle_ || handle->GetURL() != url_) |
| 2752 | return false; |
clamy | 19f0d49 | 2016-10-13 16:53:28 | [diff] [blame] | 2753 | if (current_state_ != NavigationState::INITIAL) |
csharrison | 4bd8a19 | 2016-08-02 18:03:15 | [diff] [blame] | 2754 | return false; |
| 2755 | return true; |
| 2756 | } |
| 2757 | |
nasko | 7058e5de | 2017-04-18 23:05:30 | [diff] [blame] | 2758 | NavigationHandleCommitObserver::NavigationHandleCommitObserver( |
| 2759 | content::WebContents* web_contents, |
| 2760 | const GURL& url) |
| 2761 | : content::WebContentsObserver(web_contents), |
| 2762 | url_(url), |
| 2763 | has_committed_(false), |
| 2764 | was_same_document_(false), |
| 2765 | was_renderer_initiated_(false) {} |
| 2766 | |
| 2767 | void NavigationHandleCommitObserver::DidFinishNavigation( |
| 2768 | content::NavigationHandle* handle) { |
| 2769 | if (handle->GetURL() != url_) |
| 2770 | return; |
| 2771 | has_committed_ = true; |
| 2772 | was_same_document_ = handle->IsSameDocument(); |
| 2773 | was_renderer_initiated_ = handle->IsRendererInitiated(); |
| 2774 | } |
| 2775 | |
rob | c72f59f3 | 2016-10-14 09:35:16 | [diff] [blame] | 2776 | ConsoleObserverDelegate::ConsoleObserverDelegate(WebContents* web_contents, |
| 2777 | const std::string& filter) |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 2778 | : web_contents_(web_contents), filter_(filter) {} |
rob | c72f59f3 | 2016-10-14 09:35:16 | [diff] [blame] | 2779 | |
| 2780 | ConsoleObserverDelegate::~ConsoleObserverDelegate() {} |
| 2781 | |
| 2782 | void ConsoleObserverDelegate::Wait() { |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 2783 | run_loop_.Run(); |
rob | c72f59f3 | 2016-10-14 09:35:16 | [diff] [blame] | 2784 | } |
| 2785 | |
avi | a90ae4e | 2016-11-11 20:49:33 | [diff] [blame] | 2786 | bool ConsoleObserverDelegate::DidAddMessageToConsole( |
rob | c72f59f3 | 2016-10-14 09:35:16 | [diff] [blame] | 2787 | WebContents* source, |
| 2788 | int32_t level, |
| 2789 | const base::string16& message, |
| 2790 | int32_t line_no, |
| 2791 | const base::string16& source_id) { |
| 2792 | DCHECK(source == web_contents_); |
| 2793 | |
| 2794 | std::string ascii_message = base::UTF16ToASCII(message); |
| 2795 | if (base::MatchPattern(ascii_message, filter_)) { |
| 2796 | message_ = ascii_message; |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 2797 | run_loop_.Quit(); |
rob | c72f59f3 | 2016-10-14 09:35:16 | [diff] [blame] | 2798 | } |
| 2799 | return false; |
| 2800 | } |
| 2801 | |
nick | bfaea4ee | 2016-12-02 20:59:31 | [diff] [blame] | 2802 | // static |
nick | bfaea4ee | 2016-12-02 20:59:31 | [diff] [blame] | 2803 | void PwnMessageHelper::RegisterBlobURL(RenderProcessHost* process, |
| 2804 | GURL url, |
| 2805 | std::string uuid) { |
| 2806 | IPC::IpcSecurityTestUtil::PwnMessageReceived( |
| 2807 | process->GetChannel(), BlobHostMsg_RegisterPublicURL(url, uuid)); |
| 2808 | } |
| 2809 | |
Adithya Srinivasan | 0c72ff0 | 2018-08-13 19:47:29 | [diff] [blame] | 2810 | namespace { |
| 2811 | blink::mojom::FileSystemManagerPtr GetFileSystemManager( |
| 2812 | RenderProcessHost* rph) { |
| 2813 | FileSystemManagerImpl* file_system = static_cast<RenderProcessHostImpl*>(rph) |
| 2814 | ->GetFileSystemManagerForTesting(); |
| 2815 | blink::mojom::FileSystemManagerPtr file_system_manager_ptr; |
Eric Seckler | 8652dcd5 | 2018-09-20 10:42:28 | [diff] [blame] | 2816 | base::PostTaskWithTraits( |
| 2817 | FROM_HERE, {BrowserThread::IO}, |
Adithya Srinivasan | 0c72ff0 | 2018-08-13 19:47:29 | [diff] [blame] | 2818 | base::BindOnce(&FileSystemManagerImpl::BindRequest, |
| 2819 | base::Unretained(file_system), |
| 2820 | mojo::MakeRequest(&file_system_manager_ptr))); |
| 2821 | return file_system_manager_ptr; |
| 2822 | } |
| 2823 | } // namespace |
| 2824 | |
nick | bfaea4ee | 2016-12-02 20:59:31 | [diff] [blame] | 2825 | // static |
| 2826 | void PwnMessageHelper::FileSystemCreate(RenderProcessHost* process, |
| 2827 | int request_id, |
| 2828 | GURL path, |
| 2829 | bool exclusive, |
| 2830 | bool is_directory, |
| 2831 | bool recursive) { |
Adithya Srinivasan | 0c72ff0 | 2018-08-13 19:47:29 | [diff] [blame] | 2832 | TestFileapiOperationWaiter waiter; |
| 2833 | blink::mojom::FileSystemManagerPtr file_system_manager_ptr = |
| 2834 | GetFileSystemManager(process); |
| 2835 | file_system_manager_ptr->Create( |
| 2836 | path, exclusive, is_directory, recursive, |
| 2837 | base::BindOnce(&TestFileapiOperationWaiter::DidCreate, |
| 2838 | base::Unretained(&waiter))); |
| 2839 | waiter.WaitForOperationToFinish(); |
nick | bfaea4ee | 2016-12-02 20:59:31 | [diff] [blame] | 2840 | } |
| 2841 | |
| 2842 | // static |
| 2843 | void PwnMessageHelper::FileSystemWrite(RenderProcessHost* process, |
| 2844 | int request_id, |
| 2845 | GURL file_path, |
| 2846 | std::string blob_uuid, |
| 2847 | int64_t position) { |
Adithya Srinivasan | 0c72ff0 | 2018-08-13 19:47:29 | [diff] [blame] | 2848 | TestFileapiOperationWaiter waiter; |
| 2849 | blink::mojom::FileSystemManagerPtr file_system_manager_ptr = |
| 2850 | GetFileSystemManager(process); |
| 2851 | blink::mojom::FileSystemOperationListenerPtr listener_ptr; |
| 2852 | mojo::Binding<blink::mojom::FileSystemOperationListener> binding( |
| 2853 | &waiter, mojo::MakeRequest(&listener_ptr)); |
| 2854 | blink::mojom::FileSystemCancellableOperationPtr op_ptr; |
nick | bfaea4ee | 2016-12-02 20:59:31 | [diff] [blame] | 2855 | |
Adithya Srinivasan | 0c72ff0 | 2018-08-13 19:47:29 | [diff] [blame] | 2856 | file_system_manager_ptr->Write(file_path, blob_uuid, position, |
| 2857 | mojo::MakeRequest(&op_ptr), |
| 2858 | std::move(listener_ptr)); |
| 2859 | waiter.WaitForOperationToFinish(); |
nick | bfaea4ee | 2016-12-02 20:59:31 | [diff] [blame] | 2860 | } |
| 2861 | |
lfg | e2176fb | 2017-03-26 00:45:47 | [diff] [blame] | 2862 | void PwnMessageHelper::LockMouse(RenderProcessHost* process, |
| 2863 | int routing_id, |
| 2864 | bool user_gesture, |
lfg | e2176fb | 2017-03-26 00:45:47 | [diff] [blame] | 2865 | bool privileged) { |
| 2866 | IPC::IpcSecurityTestUtil::PwnMessageReceived( |
| 2867 | process->GetChannel(), |
Albert J. Wong | 3c93c18 | 2018-09-27 17:29:43 | [diff] [blame] | 2868 | WidgetHostMsg_LockMouse(routing_id, user_gesture, privileged)); |
lfg | e2176fb | 2017-03-26 00:45:47 | [diff] [blame] | 2869 | } |
| 2870 | |
mcnee | 19fd249 | 2017-06-01 14:42:43 | [diff] [blame] | 2871 | #if defined(USE_AURA) |
| 2872 | namespace { |
| 2873 | class MockOverscrollControllerImpl : public OverscrollController, |
| 2874 | public MockOverscrollController { |
| 2875 | public: |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 2876 | MockOverscrollControllerImpl() : content_scrolling_(false) {} |
mcnee | 19fd249 | 2017-06-01 14:42:43 | [diff] [blame] | 2877 | ~MockOverscrollControllerImpl() override {} |
| 2878 | |
| 2879 | // OverscrollController: |
| 2880 | void ReceivedEventACK(const blink::WebInputEvent& event, |
| 2881 | bool processed) override { |
| 2882 | // Since we're only mocking this one method of OverscrollController and its |
| 2883 | // other methods are non-virtual, we'll delegate to it so that it doesn't |
| 2884 | // get into an inconsistent state. |
| 2885 | OverscrollController::ReceivedEventACK(event, processed); |
| 2886 | |
| 2887 | if (event.GetType() == blink::WebInputEvent::kGestureScrollUpdate && |
| 2888 | processed) { |
| 2889 | content_scrolling_ = true; |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 2890 | if (quit_closure_) |
| 2891 | std::move(quit_closure_).Run(); |
mcnee | 19fd249 | 2017-06-01 14:42:43 | [diff] [blame] | 2892 | } |
| 2893 | } |
| 2894 | |
| 2895 | // MockOverscrollController: |
| 2896 | void WaitForConsumedScroll() override { |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 2897 | if (!content_scrolling_) { |
| 2898 | base::RunLoop run_loop; |
| 2899 | quit_closure_ = run_loop.QuitClosure(); |
| 2900 | run_loop.Run(); |
| 2901 | } |
mcnee | 19fd249 | 2017-06-01 14:42:43 | [diff] [blame] | 2902 | } |
| 2903 | |
| 2904 | private: |
| 2905 | bool content_scrolling_; |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 2906 | base::OnceClosure quit_closure_; |
mcnee | 19fd249 | 2017-06-01 14:42:43 | [diff] [blame] | 2907 | |
| 2908 | DISALLOW_COPY_AND_ASSIGN(MockOverscrollControllerImpl); |
| 2909 | }; |
| 2910 | } // namespace |
| 2911 | |
| 2912 | // static |
| 2913 | MockOverscrollController* MockOverscrollController::Create( |
| 2914 | RenderWidgetHostView* rwhv) { |
| 2915 | std::unique_ptr<MockOverscrollControllerImpl> mock = |
Jeremy Roman | 04f27c37 | 2017-10-27 15:20:55 | [diff] [blame] | 2916 | std::make_unique<MockOverscrollControllerImpl>(); |
mcnee | 19fd249 | 2017-06-01 14:42:43 | [diff] [blame] | 2917 | MockOverscrollController* raw_mock = mock.get(); |
| 2918 | |
| 2919 | RenderWidgetHostViewAura* rwhva = |
| 2920 | static_cast<RenderWidgetHostViewAura*>(rwhv); |
| 2921 | rwhva->SetOverscrollControllerForTesting(std::move(mock)); |
| 2922 | |
| 2923 | return raw_mock; |
| 2924 | } |
| 2925 | |
| 2926 | #endif // defined(USE_AURA) |
| 2927 | |
W. James MacLean | 82b029b | 2017-10-23 15:05:43 | [diff] [blame] | 2928 | ContextMenuFilter::ContextMenuFilter() |
| 2929 | : content::BrowserMessageFilter(FrameMsgStart), |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 2930 | run_loop_(new base::RunLoop), |
| 2931 | quit_closure_(run_loop_->QuitClosure()) {} |
W. James MacLean | 82b029b | 2017-10-23 15:05:43 | [diff] [blame] | 2932 | |
| 2933 | bool ContextMenuFilter::OnMessageReceived(const IPC::Message& message) { |
| 2934 | DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 2935 | if (message.type() == FrameHostMsg_ContextMenu::ID) { |
| 2936 | FrameHostMsg_ContextMenu::Param params; |
| 2937 | FrameHostMsg_ContextMenu::Read(&message, ¶ms); |
| 2938 | content::ContextMenuParams menu_params = std::get<0>(params); |
Eric Seckler | 8652dcd5 | 2018-09-20 10:42:28 | [diff] [blame] | 2939 | base::PostTaskWithTraits( |
| 2940 | FROM_HERE, {content::BrowserThread::UI}, |
W. James MacLean | 82b029b | 2017-10-23 15:05:43 | [diff] [blame] | 2941 | base::BindOnce(&ContextMenuFilter::OnContextMenu, this, menu_params)); |
| 2942 | } |
| 2943 | return false; |
| 2944 | } |
| 2945 | |
| 2946 | void ContextMenuFilter::Wait() { |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 2947 | DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 2948 | run_loop_->Run(); |
| 2949 | run_loop_ = nullptr; |
W. James MacLean | 82b029b | 2017-10-23 15:05:43 | [diff] [blame] | 2950 | } |
| 2951 | |
| 2952 | ContextMenuFilter::~ContextMenuFilter() {} |
| 2953 | |
| 2954 | void ContextMenuFilter::OnContextMenu( |
| 2955 | const content::ContextMenuParams& params) { |
| 2956 | DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
W. James MacLean | 82b029b | 2017-10-23 15:05:43 | [diff] [blame] | 2957 | last_params_ = params; |
Wez | f2311d7 | 2018-06-02 02:02:18 | [diff] [blame] | 2958 | std::move(quit_closure_).Run(); |
W. James MacLean | 82b029b | 2017-10-23 15:05:43 | [diff] [blame] | 2959 | } |
| 2960 | |
W. James MacLean | a21ff3d | 2017-10-28 13:04:24 | [diff] [blame] | 2961 | WebContents* GetEmbedderForGuest(content::WebContents* guest) { |
| 2962 | CHECK(guest); |
| 2963 | return static_cast<content::WebContentsImpl*>(guest)->GetOuterWebContents(); |
| 2964 | } |
| 2965 | |
John Abd-El-Malek | 7c5c7e4c | 2018-01-11 21:36:16 | [diff] [blame] | 2966 | bool IsNetworkServiceRunningInProcess() { |
Yutaka Hirano | d8789f9 | 2018-01-30 09:59:51 | [diff] [blame] | 2967 | return base::FeatureList::IsEnabled(network::features::kNetworkService) && |
John Abd-El-Malek | 7c5c7e4c | 2018-01-11 21:36:16 | [diff] [blame] | 2968 | (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 2969 | switches::kSingleProcess) || |
| 2970 | base::FeatureList::IsEnabled(features::kNetworkServiceInProcess)); |
| 2971 | } |
| 2972 | |
John Abd-El-Malek | 53670dd | 2018-01-18 22:07:21 | [diff] [blame] | 2973 | int LoadBasicRequest(network::mojom::NetworkContext* network_context, |
John Abd-El-Malek | deec008 | 2017-12-20 20:47:47 | [diff] [blame] | 2974 | const GURL& url, |
| 2975 | int process_id, |
Chong Zhang | fdbb7e9d | 2018-08-24 23:40:54 | [diff] [blame] | 2976 | int render_frame_id, |
| 2977 | int load_flags) { |
John Abd-El-Malek | b165dc5 | 2018-01-18 17:12:18 | [diff] [blame] | 2978 | network::mojom::URLLoaderFactoryPtr url_loader_factory; |
Lukasz Anforowicz | 0b05f08 | 2018-05-18 23:04:00 | [diff] [blame] | 2979 | network::mojom::URLLoaderFactoryParamsPtr url_loader_factory_params = |
| 2980 | network::mojom::URLLoaderFactoryParams::New(); |
| 2981 | url_loader_factory_params->process_id = process_id; |
| 2982 | url_loader_factory_params->is_corb_enabled = false; |
John Abd-El-Malek | deec008 | 2017-12-20 20:47:47 | [diff] [blame] | 2983 | network_context->CreateURLLoaderFactory(MakeRequest(&url_loader_factory), |
Lukasz Anforowicz | 0b05f08 | 2018-05-18 23:04:00 | [diff] [blame] | 2984 | std::move(url_loader_factory_params)); |
Chong Zhang | c40a6ce5 | 2017-12-10 03:00:28 | [diff] [blame] | 2985 | // |url_loader_factory| will receive error notification asynchronously if |
| 2986 | // |network_context| has already encountered error. However it's still false |
| 2987 | // at this point. |
| 2988 | EXPECT_FALSE(url_loader_factory.encountered_error()); |
| 2989 | |
John Abd-El-Malek | 1df6179 | 2018-01-12 20:40:45 | [diff] [blame] | 2990 | auto request = std::make_unique<network::ResourceRequest>(); |
Chong Zhang | c40a6ce5 | 2017-12-10 03:00:28 | [diff] [blame] | 2991 | request->url = url; |
John Abd-El-Malek | deec008 | 2017-12-20 20:47:47 | [diff] [blame] | 2992 | request->render_frame_id = render_frame_id; |
Chong Zhang | fdbb7e9d | 2018-08-24 23:40:54 | [diff] [blame] | 2993 | request->load_flags = load_flags; |
Chong Zhang | c40a6ce5 | 2017-12-10 03:00:28 | [diff] [blame] | 2994 | |
| 2995 | content::SimpleURLLoaderTestHelper simple_loader_helper; |
John Abd-El-Malek | bdafede | 2018-02-06 15:10:36 | [diff] [blame] | 2996 | std::unique_ptr<network::SimpleURLLoader> simple_loader = |
| 2997 | network::SimpleURLLoader::Create(std::move(request), |
Chong Zhang | c40a6ce5 | 2017-12-10 03:00:28 | [diff] [blame] | 2998 | TRAFFIC_ANNOTATION_FOR_TESTS); |
| 2999 | |
| 3000 | simple_loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie( |
| 3001 | url_loader_factory.get(), simple_loader_helper.GetCallback()); |
| 3002 | simple_loader_helper.WaitForCallback(); |
| 3003 | |
| 3004 | return simple_loader->NetError(); |
| 3005 | } |
| 3006 | |
John Abd-El-Malek | cc0b2a6 | 2018-03-20 19:32:50 | [diff] [blame] | 3007 | void EnsureCookiesFlushed(BrowserContext* browser_context) { |
| 3008 | BrowserContext::ForEachStoragePartition( |
| 3009 | browser_context, base::BindRepeating([](StoragePartition* partition) { |
| 3010 | base::RunLoop run_loop; |
| 3011 | partition->GetCookieManagerForBrowserProcess()->FlushCookieStore( |
| 3012 | run_loop.QuitClosure()); |
| 3013 | run_loop.Run(); |
| 3014 | })); |
| 3015 | } |
| 3016 | |
Jay Civelli | fd2d7f91 | 2018-01-26 21:51:39 | [diff] [blame] | 3017 | bool HasValidProcessForProcessGroup(const std::string& process_group_name) { |
| 3018 | return ServiceManagerContext::HasValidProcessForProcessGroup( |
| 3019 | process_group_name); |
James Cook | 6929b87 | 2018-01-03 17:56:56 | [diff] [blame] | 3020 | } |
| 3021 | |
Chris Blume | 12a2646 | 2018-04-22 02:00:12 | [diff] [blame] | 3022 | bool TestChildOrGuestAutoresize(bool is_guest, |
| 3023 | RenderProcessHost* embedder_rph, |
| 3024 | RenderWidgetHost* guest_rwh) { |
| 3025 | RenderProcessHostImpl* embedder_rph_impl = |
| 3026 | static_cast<RenderProcessHostImpl*>(embedder_rph); |
| 3027 | RenderWidgetHostImpl* guest_rwh_impl = |
| 3028 | static_cast<RenderWidgetHostImpl*>(guest_rwh); |
| 3029 | |
Fady Samuel | 799e7219 | 2018-04-25 21:16:57 | [diff] [blame] | 3030 | scoped_refptr<SynchronizeVisualPropertiesMessageFilter> filter( |
| 3031 | new SynchronizeVisualPropertiesMessageFilter()); |
Chris Blume | 12a2646 | 2018-04-22 02:00:12 | [diff] [blame] | 3032 | |
| 3033 | // Register the message filter for the guest or child. For guest, we must use |
| 3034 | // a special hook, as there are already message filters installed which will |
| 3035 | // supercede us. |
| 3036 | if (is_guest) { |
| 3037 | embedder_rph_impl->SetBrowserPluginMessageFilterSubFilterForTesting( |
| 3038 | filter.get()); |
| 3039 | } else { |
| 3040 | embedder_rph_impl->AddFilter(filter.get()); |
| 3041 | } |
| 3042 | |
Fady Samuel | 84d8a1f7 | 2018-11-08 00:26:17 | [diff] [blame] | 3043 | viz::LocalSurfaceId current_id = guest_rwh_impl->GetView() |
| 3044 | ->GetLocalSurfaceIdAllocation() |
| 3045 | .local_surface_id(); |
Eric Karl | 2a4b17a | 2018-04-22 11:00:29 | [diff] [blame] | 3046 | // The guest may not yet be fully attached / initted. If not, |current_id| |
| 3047 | // will be invalid, and we should wait for an ID before proceeding. |
| 3048 | if (!current_id.is_valid()) |
| 3049 | current_id = filter->WaitForSurfaceId(); |
| 3050 | |
Chris Blume | 12a2646 | 2018-04-22 02:00:12 | [diff] [blame] | 3051 | // Enable auto-resize. |
Eric Karl | 7fdf2af | 2018-04-24 21:21:30 | [diff] [blame] | 3052 | gfx::Size min_size(10, 10); |
| 3053 | gfx::Size max_size(100, 100); |
| 3054 | guest_rwh_impl->SetAutoResize(true, min_size, max_size); |
| 3055 | guest_rwh_impl->GetView()->EnableAutoResize(min_size, max_size); |
| 3056 | |
| 3057 | // Enabling auto resize generates a surface ID, wait for it. |
| 3058 | current_id = filter->WaitForSurfaceId(); |
Chris Blume | 12a2646 | 2018-04-22 02:00:12 | [diff] [blame] | 3059 | |
| 3060 | // Fake an auto-resize update. |
Fady Samuel | eeab7395 | 2018-05-08 03:00:00 | [diff] [blame] | 3061 | viz::LocalSurfaceId local_surface_id(current_id.parent_sequence_number(), |
| 3062 | current_id.child_sequence_number() + 1, |
| 3063 | current_id.embed_token()); |
Fady Samuel | e392fd5 | 2018-05-11 17:16:43 | [diff] [blame] | 3064 | cc::RenderFrameMetadata metadata; |
| 3065 | metadata.viewport_size_in_pixels = gfx::Size(75, 75); |
Fady Samuel | b655f45 | 2018-11-06 00:48:34 | [diff] [blame] | 3066 | metadata.local_surface_id_allocation = |
| 3067 | viz::LocalSurfaceIdAllocation(local_surface_id, base::TimeTicks::Now()); |
Fady Samuel | e392fd5 | 2018-05-11 17:16:43 | [diff] [blame] | 3068 | guest_rwh_impl->DidUpdateVisualProperties(metadata); |
Eric Karl | 7fdf2af | 2018-04-24 21:21:30 | [diff] [blame] | 3069 | |
| 3070 | // This won't generate a response, as we short-circuit auto-resizes, so cause |
| 3071 | // an additional update by disabling auto-resize. |
Fady Samuel | eeab7395 | 2018-05-08 03:00:00 | [diff] [blame] | 3072 | guest_rwh_impl->GetView()->DisableAutoResize(gfx::Size(75, 75)); |
Eric Karl | 7fdf2af | 2018-04-24 21:21:30 | [diff] [blame] | 3073 | |
Chris Blume | 12a2646 | 2018-04-22 02:00:12 | [diff] [blame] | 3074 | // Get the first delivered surface id and ensure it has the surface id which |
| 3075 | // we expect. |
Eric Karl | 7fdf2af | 2018-04-24 21:21:30 | [diff] [blame] | 3076 | return filter->WaitForSurfaceId() == |
| 3077 | viz::LocalSurfaceId(current_id.parent_sequence_number() + 1, |
| 3078 | current_id.child_sequence_number() + 1, |
| 3079 | current_id.embed_token()); |
Chris Blume | 12a2646 | 2018-04-22 02:00:12 | [diff] [blame] | 3080 | } |
| 3081 | |
Fady Samuel | 799e7219 | 2018-04-25 21:16:57 | [diff] [blame] | 3082 | const uint32_t |
| 3083 | SynchronizeVisualPropertiesMessageFilter::kMessageClassesToFilter[2] = { |
| 3084 | FrameMsgStart, BrowserPluginMsgStart}; |
Chris Blume | 12a2646 | 2018-04-22 02:00:12 | [diff] [blame] | 3085 | |
Fady Samuel | 799e7219 | 2018-04-25 21:16:57 | [diff] [blame] | 3086 | SynchronizeVisualPropertiesMessageFilter:: |
| 3087 | SynchronizeVisualPropertiesMessageFilter() |
Chris Blume | 12a2646 | 2018-04-22 02:00:12 | [diff] [blame] | 3088 | : content::BrowserMessageFilter(kMessageClassesToFilter, |
Avi Drissman | 9d3ded9 | 2018-12-25 20:50:21 | [diff] [blame^] | 3089 | base::size(kMessageClassesToFilter)), |
Chris Blume | 12a2646 | 2018-04-22 02:00:12 | [diff] [blame] | 3090 | screen_space_rect_run_loop_(std::make_unique<base::RunLoop>()), |
| 3091 | screen_space_rect_received_(false) {} |
| 3092 | |
Fady Samuel | 799e7219 | 2018-04-25 21:16:57 | [diff] [blame] | 3093 | void SynchronizeVisualPropertiesMessageFilter::WaitForRect() { |
Chris Blume | 12a2646 | 2018-04-22 02:00:12 | [diff] [blame] | 3094 | screen_space_rect_run_loop_->Run(); |
| 3095 | } |
| 3096 | |
Fady Samuel | 799e7219 | 2018-04-25 21:16:57 | [diff] [blame] | 3097 | void SynchronizeVisualPropertiesMessageFilter::ResetRectRunLoop() { |
Chris Blume | 12a2646 | 2018-04-22 02:00:12 | [diff] [blame] | 3098 | last_rect_ = gfx::Rect(); |
| 3099 | screen_space_rect_run_loop_.reset(new base::RunLoop); |
| 3100 | screen_space_rect_received_ = false; |
| 3101 | } |
| 3102 | |
Fady Samuel | 799e7219 | 2018-04-25 21:16:57 | [diff] [blame] | 3103 | viz::FrameSinkId SynchronizeVisualPropertiesMessageFilter::GetOrWaitForId() { |
Chris Blume | 12a2646 | 2018-04-22 02:00:12 | [diff] [blame] | 3104 | // No-op if already quit. |
| 3105 | frame_sink_id_run_loop_.Run(); |
| 3106 | return frame_sink_id_; |
| 3107 | } |
| 3108 | |
Fady Samuel | 799e7219 | 2018-04-25 21:16:57 | [diff] [blame] | 3109 | viz::LocalSurfaceId |
| 3110 | SynchronizeVisualPropertiesMessageFilter::WaitForSurfaceId() { |
Chris Blume | 12a2646 | 2018-04-22 02:00:12 | [diff] [blame] | 3111 | surface_id_run_loop_.reset(new base::RunLoop); |
| 3112 | surface_id_run_loop_->Run(); |
| 3113 | return last_surface_id_; |
| 3114 | } |
| 3115 | |
Fady Samuel | 799e7219 | 2018-04-25 21:16:57 | [diff] [blame] | 3116 | SynchronizeVisualPropertiesMessageFilter:: |
| 3117 | ~SynchronizeVisualPropertiesMessageFilter() {} |
Chris Blume | 12a2646 | 2018-04-22 02:00:12 | [diff] [blame] | 3118 | |
Fady Samuel | 799e7219 | 2018-04-25 21:16:57 | [diff] [blame] | 3119 | void SynchronizeVisualPropertiesMessageFilter:: |
| 3120 | OnSynchronizeFrameHostVisualProperties( |
Fady Samuel | b6b52ea | 2018-11-08 20:34:49 | [diff] [blame] | 3121 | const viz::FrameSinkId& frame_sink_id, |
| 3122 | const FrameVisualProperties& visual_properties) { |
| 3123 | OnSynchronizeVisualProperties(frame_sink_id, visual_properties); |
Chris Blume | 12a2646 | 2018-04-22 02:00:12 | [diff] [blame] | 3124 | } |
| 3125 | |
Fady Samuel | 799e7219 | 2018-04-25 21:16:57 | [diff] [blame] | 3126 | void SynchronizeVisualPropertiesMessageFilter:: |
| 3127 | OnSynchronizeBrowserPluginVisualProperties( |
| 3128 | int browser_plugin_guest_instance_id, |
Fady Samuel | b6b52ea | 2018-11-08 20:34:49 | [diff] [blame] | 3129 | FrameVisualProperties visual_properties) { |
| 3130 | OnSynchronizeVisualProperties(viz::FrameSinkId(), visual_properties); |
Chris Blume | 12a2646 | 2018-04-22 02:00:12 | [diff] [blame] | 3131 | } |
| 3132 | |
Fady Samuel | 799e7219 | 2018-04-25 21:16:57 | [diff] [blame] | 3133 | void SynchronizeVisualPropertiesMessageFilter::OnSynchronizeVisualProperties( |
Chris Blume | 12a2646 | 2018-04-22 02:00:12 | [diff] [blame] | 3134 | const viz::FrameSinkId& frame_sink_id, |
Fady Samuel | b6b52ea | 2018-11-08 20:34:49 | [diff] [blame] | 3135 | const FrameVisualProperties& visual_properties) { |
| 3136 | gfx::Rect screen_space_rect_in_dip = visual_properties.screen_space_rect; |
Chris Blume | 12a2646 | 2018-04-22 02:00:12 | [diff] [blame] | 3137 | if (IsUseZoomForDSFEnabled()) { |
| 3138 | screen_space_rect_in_dip = |
| 3139 | gfx::Rect(gfx::ScaleToFlooredPoint( |
Fady Samuel | b6b52ea | 2018-11-08 20:34:49 | [diff] [blame] | 3140 | visual_properties.screen_space_rect.origin(), |
| 3141 | 1.f / visual_properties.screen_info.device_scale_factor), |
Chris Blume | 12a2646 | 2018-04-22 02:00:12 | [diff] [blame] | 3142 | gfx::ScaleToCeiledSize( |
Fady Samuel | b6b52ea | 2018-11-08 20:34:49 | [diff] [blame] | 3143 | visual_properties.screen_space_rect.size(), |
| 3144 | 1.f / visual_properties.screen_info.device_scale_factor)); |
Chris Blume | 12a2646 | 2018-04-22 02:00:12 | [diff] [blame] | 3145 | } |
| 3146 | // Track each rect updates. |
Eric Seckler | 8652dcd5 | 2018-09-20 10:42:28 | [diff] [blame] | 3147 | base::PostTaskWithTraits( |
| 3148 | FROM_HERE, {content::BrowserThread::UI}, |
Fady Samuel | 799e7219 | 2018-04-25 21:16:57 | [diff] [blame] | 3149 | base::BindOnce( |
| 3150 | &SynchronizeVisualPropertiesMessageFilter::OnUpdatedFrameRectOnUI, |
| 3151 | this, screen_space_rect_in_dip)); |
Chris Blume | 12a2646 | 2018-04-22 02:00:12 | [diff] [blame] | 3152 | |
| 3153 | // Track each surface id update. |
Eric Seckler | 8652dcd5 | 2018-09-20 10:42:28 | [diff] [blame] | 3154 | base::PostTaskWithTraits( |
| 3155 | FROM_HERE, {content::BrowserThread::UI}, |
Fady Samuel | 799e7219 | 2018-04-25 21:16:57 | [diff] [blame] | 3156 | base::BindOnce( |
| 3157 | &SynchronizeVisualPropertiesMessageFilter::OnUpdatedSurfaceIdOnUI, |
Fady Samuel | b6b52ea | 2018-11-08 20:34:49 | [diff] [blame] | 3158 | this, |
| 3159 | visual_properties.local_surface_id_allocation.local_surface_id())); |
Chris Blume | 12a2646 | 2018-04-22 02:00:12 | [diff] [blame] | 3160 | |
| 3161 | // Record the received value. We cannot check the current state of the child |
| 3162 | // frame, as it can only be processed on the UI thread, and we cannot block |
| 3163 | // here. |
| 3164 | frame_sink_id_ = frame_sink_id; |
| 3165 | |
| 3166 | // There can be several updates before a valid viz::FrameSinkId is ready. Do |
| 3167 | // not quit |run_loop_| until after we receive a valid one. |
| 3168 | if (!frame_sink_id_.is_valid()) |
| 3169 | return; |
| 3170 | |
| 3171 | // We can't nest on the IO thread. So tests will wait on the UI thread, so |
| 3172 | // post there to exit the nesting. |
Eric Seckler | 8652dcd5 | 2018-09-20 10:42:28 | [diff] [blame] | 3173 | base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::UI}) |
Chris Blume | 12a2646 | 2018-04-22 02:00:12 | [diff] [blame] | 3174 | ->PostTask(FROM_HERE, |
Fady Samuel | 799e7219 | 2018-04-25 21:16:57 | [diff] [blame] | 3175 | base::BindOnce(&SynchronizeVisualPropertiesMessageFilter:: |
| 3176 | OnUpdatedFrameSinkIdOnUI, |
| 3177 | this)); |
Chris Blume | 12a2646 | 2018-04-22 02:00:12 | [diff] [blame] | 3178 | } |
| 3179 | |
Fady Samuel | 799e7219 | 2018-04-25 21:16:57 | [diff] [blame] | 3180 | void SynchronizeVisualPropertiesMessageFilter::OnUpdatedFrameRectOnUI( |
Chris Blume | 12a2646 | 2018-04-22 02:00:12 | [diff] [blame] | 3181 | const gfx::Rect& rect) { |
| 3182 | last_rect_ = rect; |
| 3183 | if (!screen_space_rect_received_) { |
| 3184 | screen_space_rect_received_ = true; |
| 3185 | // Tests looking at the rect currently expect all received input to finish |
| 3186 | // processing before the test continutes. |
| 3187 | screen_space_rect_run_loop_->QuitWhenIdle(); |
| 3188 | } |
| 3189 | } |
| 3190 | |
Fady Samuel | 799e7219 | 2018-04-25 21:16:57 | [diff] [blame] | 3191 | void SynchronizeVisualPropertiesMessageFilter::OnUpdatedFrameSinkIdOnUI() { |
Chris Blume | 12a2646 | 2018-04-22 02:00:12 | [diff] [blame] | 3192 | frame_sink_id_run_loop_.Quit(); |
| 3193 | } |
| 3194 | |
Fady Samuel | 799e7219 | 2018-04-25 21:16:57 | [diff] [blame] | 3195 | void SynchronizeVisualPropertiesMessageFilter::OnUpdatedSurfaceIdOnUI( |
Chris Blume | 12a2646 | 2018-04-22 02:00:12 | [diff] [blame] | 3196 | viz::LocalSurfaceId surface_id) { |
| 3197 | last_surface_id_ = surface_id; |
| 3198 | if (surface_id_run_loop_) { |
| 3199 | surface_id_run_loop_->QuitWhenIdle(); |
| 3200 | } |
| 3201 | } |
| 3202 | |
Fady Samuel | 799e7219 | 2018-04-25 21:16:57 | [diff] [blame] | 3203 | bool SynchronizeVisualPropertiesMessageFilter::OnMessageReceived( |
Chris Blume | 12a2646 | 2018-04-22 02:00:12 | [diff] [blame] | 3204 | const IPC::Message& message) { |
Fady Samuel | 799e7219 | 2018-04-25 21:16:57 | [diff] [blame] | 3205 | IPC_BEGIN_MESSAGE_MAP(SynchronizeVisualPropertiesMessageFilter, message) |
| 3206 | IPC_MESSAGE_HANDLER(FrameHostMsg_SynchronizeVisualProperties, |
| 3207 | OnSynchronizeFrameHostVisualProperties) |
| 3208 | IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SynchronizeVisualProperties, |
| 3209 | OnSynchronizeBrowserPluginVisualProperties) |
Chris Blume | 12a2646 | 2018-04-22 02:00:12 | [diff] [blame] | 3210 | IPC_END_MESSAGE_MAP() |
| 3211 | |
| 3212 | // We do not consume the message, so that we can verify the effects of it |
| 3213 | // being processed. |
| 3214 | return false; |
| 3215 | } |
| 3216 | |
[email protected] | 78089f0 | 2012-07-19 06:11:28 | [diff] [blame] | 3217 | } // namespace content |