| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/public/test/browser_test_utils.h" | 5 #include "content/public/test/browser_test_utils.h" |
| 6 | 6 |
| 7 #include "base/json/json_reader.h" |
| 8 #include "base/utf_string_conversions.h" |
| 9 #include "content/public/browser/dom_operation_notification_details.h" |
| 7 #include "content/public/browser/notification_types.h" | 10 #include "content/public/browser/notification_types.h" |
| 8 #include "content/public/browser/render_view_host.h" | 11 #include "content/public/browser/render_view_host.h" |
| 9 #include "content/public/browser/web_contents.h" | 12 #include "content/public/browser/web_contents.h" |
| 13 #include "content/public/browser/web_contents_observer.h" |
| 10 #include "content/public/browser/web_contents_view.h" | 14 #include "content/public/browser/web_contents_view.h" |
| 11 #include "content/public/test/test_utils.h" | 15 #include "content/public/test/test_utils.h" |
| 12 #include "testing/gtest/include/gtest/gtest.h" | 16 #include "testing/gtest/include/gtest/gtest.h" |
| 13 | 17 |
| 14 namespace content { | 18 namespace content { |
| 15 | 19 |
| 16 void SimulateMouseClick(WebContents* web_contents) { | 20 namespace { |
| 17 int x = web_contents->GetView()->GetContainerSize().width() / 2; | |
| 18 int y = web_contents->GetView()->GetContainerSize().height() / 2; | |
| 19 WebKit::WebMouseEvent mouse_event; | |
| 20 mouse_event.type = WebKit::WebInputEvent::MouseDown; | |
| 21 mouse_event.button = WebKit::WebMouseEvent::ButtonLeft; | |
| 22 mouse_event.x = x; | |
| 23 mouse_event.y = y; | |
| 24 // Mac needs globalX/globalY for events to plugins. | |
| 25 gfx::Rect offset; | |
| 26 web_contents->GetView()->GetContainerBounds(&offset); | |
| 27 mouse_event.globalX = x + offset.x(); | |
| 28 mouse_event.globalY = y + offset.y(); | |
| 29 mouse_event.clickCount = 1; | |
| 30 web_contents->GetRenderViewHost()->ForwardMouseEvent(mouse_event); | |
| 31 mouse_event.type = WebKit::WebInputEvent::MouseUp; | |
| 32 web_contents->GetRenderViewHost()->ForwardMouseEvent(mouse_event); | |
| 33 } | |
| 34 | 21 |
| 35 void SimulateMouseEvent(WebContents* web_contents, | 22 class DOMOperationObserver : public NotificationObserver, |
| 36 WebKit::WebInputEvent::Type type, | 23 public WebContentsObserver { |
| 37 const gfx::Point& point) { | 24 public: |
| 38 WebKit::WebMouseEvent mouse_event; | 25 explicit DOMOperationObserver(RenderViewHost* render_view_host) |
| 39 mouse_event.type = type; | 26 : WebContentsObserver(WebContents::FromRenderViewHost(render_view_host)), |
| 40 mouse_event.x = point.x(); | 27 did_respond_(false) { |
| 41 mouse_event.y = point.y(); | 28 registrar_.Add(this, NOTIFICATION_DOM_OPERATION_RESPONSE, |
| 42 web_contents->GetRenderViewHost()->ForwardMouseEvent(mouse_event); | 29 Source<RenderViewHost>(render_view_host)); |
| 30 message_loop_runner_ = new MessageLoopRunner; |
| 31 } |
| 32 |
| 33 virtual void Observe(int type, |
| 34 const NotificationSource& source, |
| 35 const NotificationDetails& details) OVERRIDE { |
| 36 DCHECK(type == NOTIFICATION_DOM_OPERATION_RESPONSE); |
| 37 Details<DomOperationNotificationDetails> dom_op_details(details); |
| 38 response_ = dom_op_details->json; |
| 39 did_respond_ = true; |
| 40 message_loop_runner_->Quit(); |
| 41 } |
| 42 |
| 43 // Overridden from WebContentsObserver: |
| 44 virtual void RenderViewGone(base::TerminationStatus status) OVERRIDE { |
| 45 message_loop_runner_->Quit(); |
| 46 } |
| 47 |
| 48 bool WaitAndGetResponse(std::string* response) WARN_UNUSED_RESULT { |
| 49 message_loop_runner_->Run(); |
| 50 *response = response_; |
| 51 return did_respond_; |
| 52 } |
| 53 |
| 54 private: |
| 55 NotificationRegistrar registrar_; |
| 56 std::string response_; |
| 57 bool did_respond_; |
| 58 scoped_refptr<MessageLoopRunner> message_loop_runner_; |
| 59 |
| 60 DISALLOW_COPY_AND_ASSIGN(DOMOperationObserver); |
| 61 }; |
| 62 |
| 63 // Specifying a prototype so that we can add the WARN_UNUSED_RESULT attribute. |
| 64 bool ExecuteJavaScriptHelper(RenderViewHost* render_view_host, |
| 65 const std::wstring& frame_xpath, |
| 66 const std::wstring& original_script, |
| 67 scoped_ptr<Value>* result) WARN_UNUSED_RESULT; |
| 68 |
| 69 // Executes the passed |original_script| in the frame pointed to by |
| 70 // |frame_xpath|. If |result| is not NULL, stores the value that the evaluation |
| 71 // of the script in |result|. Returns true on success. |
| 72 bool ExecuteJavaScriptHelper(RenderViewHost* render_view_host, |
| 73 const std::wstring& frame_xpath, |
| 74 const std::wstring& original_script, |
| 75 scoped_ptr<Value>* result) { |
| 76 // TODO(jcampan): we should make the domAutomationController not require an |
| 77 // automation id. |
| 78 std::wstring script = L"window.domAutomationController.setAutomationId(0);" + |
| 79 original_script; |
| 80 DOMOperationObserver dom_op_observer(render_view_host); |
| 81 render_view_host->ExecuteJavascriptInWebFrame(WideToUTF16Hack(frame_xpath), |
| 82 WideToUTF16Hack(script)); |
| 83 std::string json; |
| 84 if (!dom_op_observer.WaitAndGetResponse(&json)) { |
| 85 DLOG(ERROR) << "Cannot communicate with DOMOperationObserver."; |
| 86 return false; |
| 87 } |
| 88 |
| 89 // Nothing more to do for callers that ignore the returned JS value. |
| 90 if (!result) |
| 91 return true; |
| 92 |
| 93 base::JSONReader reader(base::JSON_ALLOW_TRAILING_COMMAS); |
| 94 result->reset(reader.ReadToValue(json)); |
| 95 if (!result->get()) { |
| 96 DLOG(ERROR) << reader.GetErrorMessage(); |
| 97 return false; |
| 98 } |
| 99 |
| 100 return true; |
| 43 } | 101 } |
| 44 | 102 |
| 45 void BuildSimpleWebKeyEvent(WebKit::WebInputEvent::Type type, | 103 void BuildSimpleWebKeyEvent(WebKit::WebInputEvent::Type type, |
| 46 ui::KeyboardCode key, | 104 ui::KeyboardCode key, |
| 47 bool control, | 105 bool control, |
| 48 bool shift, | 106 bool shift, |
| 49 bool alt, | 107 bool alt, |
| 50 bool command, | 108 bool command, |
| 51 NativeWebKeyboardEvent* event) { | 109 NativeWebKeyboardEvent* event) { |
| 52 event->nativeKeyCode = 0; | 110 event->nativeKeyCode = 0; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 70 if (shift) | 128 if (shift) |
| 71 event->modifiers |= WebKit::WebInputEvent::ShiftKey; | 129 event->modifiers |= WebKit::WebInputEvent::ShiftKey; |
| 72 | 130 |
| 73 if (alt) | 131 if (alt) |
| 74 event->modifiers |= WebKit::WebInputEvent::AltKey; | 132 event->modifiers |= WebKit::WebInputEvent::AltKey; |
| 75 | 133 |
| 76 if (command) | 134 if (command) |
| 77 event->modifiers |= WebKit::WebInputEvent::MetaKey; | 135 event->modifiers |= WebKit::WebInputEvent::MetaKey; |
| 78 } | 136 } |
| 79 | 137 |
| 138 } // namespace |
| 139 |
| 140 void SimulateMouseClick(WebContents* web_contents) { |
| 141 int x = web_contents->GetView()->GetContainerSize().width() / 2; |
| 142 int y = web_contents->GetView()->GetContainerSize().height() / 2; |
| 143 WebKit::WebMouseEvent mouse_event; |
| 144 mouse_event.type = WebKit::WebInputEvent::MouseDown; |
| 145 mouse_event.button = WebKit::WebMouseEvent::ButtonLeft; |
| 146 mouse_event.x = x; |
| 147 mouse_event.y = y; |
| 148 // Mac needs globalX/globalY for events to plugins. |
| 149 gfx::Rect offset; |
| 150 web_contents->GetView()->GetContainerBounds(&offset); |
| 151 mouse_event.globalX = x + offset.x(); |
| 152 mouse_event.globalY = y + offset.y(); |
| 153 mouse_event.clickCount = 1; |
| 154 web_contents->GetRenderViewHost()->ForwardMouseEvent(mouse_event); |
| 155 mouse_event.type = WebKit::WebInputEvent::MouseUp; |
| 156 web_contents->GetRenderViewHost()->ForwardMouseEvent(mouse_event); |
| 157 } |
| 158 |
| 159 void SimulateMouseEvent(WebContents* web_contents, |
| 160 WebKit::WebInputEvent::Type type, |
| 161 const gfx::Point& point) { |
| 162 WebKit::WebMouseEvent mouse_event; |
| 163 mouse_event.type = type; |
| 164 mouse_event.x = point.x(); |
| 165 mouse_event.y = point.y(); |
| 166 web_contents->GetRenderViewHost()->ForwardMouseEvent(mouse_event); |
| 167 } |
| 168 |
| 80 void SimulateKeyPress(WebContents* web_contents, | 169 void SimulateKeyPress(WebContents* web_contents, |
| 81 ui::KeyboardCode key, | 170 ui::KeyboardCode key, |
| 82 bool control, | 171 bool control, |
| 83 bool shift, | 172 bool shift, |
| 84 bool alt, | 173 bool alt, |
| 85 bool command) { | 174 bool command) { |
| 86 NativeWebKeyboardEvent event_down; | 175 NativeWebKeyboardEvent event_down; |
| 87 BuildSimpleWebKeyEvent( | 176 BuildSimpleWebKeyEvent( |
| 88 WebKit::WebInputEvent::RawKeyDown, key, control, shift, alt, command, | 177 WebKit::WebInputEvent::RawKeyDown, key, control, shift, alt, command, |
| 89 &event_down); | 178 &event_down); |
| 90 web_contents->GetRenderViewHost()->ForwardKeyboardEvent(event_down); | 179 web_contents->GetRenderViewHost()->ForwardKeyboardEvent(event_down); |
| 91 | 180 |
| 92 NativeWebKeyboardEvent char_event; | 181 NativeWebKeyboardEvent char_event; |
| 93 BuildSimpleWebKeyEvent( | 182 BuildSimpleWebKeyEvent( |
| 94 WebKit::WebInputEvent::Char, key, control, shift, alt, command, | 183 WebKit::WebInputEvent::Char, key, control, shift, alt, command, |
| 95 &char_event); | 184 &char_event); |
| 96 web_contents->GetRenderViewHost()->ForwardKeyboardEvent(char_event); | 185 web_contents->GetRenderViewHost()->ForwardKeyboardEvent(char_event); |
| 97 | 186 |
| 98 NativeWebKeyboardEvent event_up; | 187 NativeWebKeyboardEvent event_up; |
| 99 BuildSimpleWebKeyEvent( | 188 BuildSimpleWebKeyEvent( |
| 100 WebKit::WebInputEvent::KeyUp, key, control, shift, alt, command, | 189 WebKit::WebInputEvent::KeyUp, key, control, shift, alt, command, |
| 101 &event_up); | 190 &event_up); |
| 102 web_contents->GetRenderViewHost()->ForwardKeyboardEvent(event_up); | 191 web_contents->GetRenderViewHost()->ForwardKeyboardEvent(event_up); |
| 103 } | 192 } |
| 104 | 193 |
| 194 bool ExecuteJavaScript(RenderViewHost* render_view_host, |
| 195 const std::wstring& frame_xpath, |
| 196 const std::wstring& original_script) { |
| 197 std::wstring script = |
| 198 original_script + L";window.domAutomationController.send(0);"; |
| 199 return ExecuteJavaScriptHelper(render_view_host, frame_xpath, script, NULL); |
| 200 } |
| 201 |
| 202 bool ExecuteJavaScriptAndExtractInt(RenderViewHost* render_view_host, |
| 203 const std::wstring& frame_xpath, |
| 204 const std::wstring& script, |
| 205 int* result) { |
| 206 DCHECK(result); |
| 207 scoped_ptr<Value> value; |
| 208 if (!ExecuteJavaScriptHelper(render_view_host, frame_xpath, script, &value) || |
| 209 !value.get()) |
| 210 return false; |
| 211 |
| 212 return value->GetAsInteger(result); |
| 213 } |
| 214 |
| 215 bool ExecuteJavaScriptAndExtractBool(RenderViewHost* render_view_host, |
| 216 const std::wstring& frame_xpath, |
| 217 const std::wstring& script, |
| 218 bool* result) { |
| 219 DCHECK(result); |
| 220 scoped_ptr<Value> value; |
| 221 if (!ExecuteJavaScriptHelper(render_view_host, frame_xpath, script, &value) || |
| 222 !value.get()) |
| 223 return false; |
| 224 |
| 225 return value->GetAsBoolean(result); |
| 226 } |
| 227 |
| 228 bool ExecuteJavaScriptAndExtractString(RenderViewHost* render_view_host, |
| 229 const std::wstring& frame_xpath, |
| 230 const std::wstring& script, |
| 231 std::string* result) { |
| 232 DCHECK(result); |
| 233 scoped_ptr<Value> value; |
| 234 if (!ExecuteJavaScriptHelper(render_view_host, frame_xpath, script, &value) || |
| 235 !value.get()) |
| 236 return false; |
| 237 |
| 238 return value->GetAsString(result); |
| 239 } |
| 240 |
| 105 TitleWatcher::TitleWatcher(WebContents* web_contents, | 241 TitleWatcher::TitleWatcher(WebContents* web_contents, |
| 106 const string16& expected_title) | 242 const string16& expected_title) |
| 107 : web_contents_(web_contents), | 243 : web_contents_(web_contents), |
| 108 expected_title_observed_(false), | 244 expected_title_observed_(false), |
| 109 quit_loop_on_observation_(false) { | 245 quit_loop_on_observation_(false) { |
| 110 EXPECT_TRUE(web_contents != NULL); | 246 EXPECT_TRUE(web_contents != NULL); |
| 111 expected_titles_.push_back(expected_title); | 247 expected_titles_.push_back(expected_title); |
| 112 notification_registrar_.Add(this, | 248 notification_registrar_.Add(this, |
| 113 NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED, | 249 NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED, |
| 114 Source<WebContents>(web_contents)); | 250 Source<WebContents>(web_contents)); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 163 observed_title_ = *it; | 299 observed_title_ = *it; |
| 164 expected_title_observed_ = true; | 300 expected_title_observed_ = true; |
| 165 if (quit_loop_on_observation_) { | 301 if (quit_loop_on_observation_) { |
| 166 // Only call Quit once, on first Observe: | 302 // Only call Quit once, on first Observe: |
| 167 quit_loop_on_observation_ = false; | 303 quit_loop_on_observation_ = false; |
| 168 message_loop_runner_->Quit(); | 304 message_loop_runner_->Quit(); |
| 169 } | 305 } |
| 170 } | 306 } |
| 171 | 307 |
| 172 } // namespace content | 308 } // namespace content |
| OLD | NEW |