1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CONTENT_SHELL_RENDERER_TEST_RUNNER_WEB_TEST_PROXY_H_
6#define CONTENT_SHELL_RENDERER_TEST_RUNNER_WEB_TEST_PROXY_H_
7
8#include <deque>
9#include <map>
10#include <string>
11
12#include "base/basictypes.h"
13#include "base/callback.h"
14#include "base/memory/scoped_ptr.h"
15#include "content/shell/renderer/test_runner/web_task.h"
16#include "third_party/WebKit/public/platform/WebRect.h"
17#include "third_party/WebKit/public/platform/WebScreenInfo.h"
18#include "third_party/WebKit/public/platform/WebURLError.h"
19#include "third_party/WebKit/public/platform/WebURLRequest.h"
20#include "third_party/WebKit/public/web/WebAXEnums.h"
21#include "third_party/WebKit/public/web/WebDOMMessageEvent.h"
22#include "third_party/WebKit/public/web/WebDataSource.h"
23#include "third_party/WebKit/public/web/WebDragOperation.h"
24#include "third_party/WebKit/public/web/WebFrame.h"
25#include "third_party/WebKit/public/web/WebFrameClient.h"
26#include "third_party/WebKit/public/web/WebHistoryCommitType.h"
27#include "third_party/WebKit/public/web/WebIconURL.h"
28#include "third_party/WebKit/public/web/WebNavigationPolicy.h"
29#include "third_party/WebKit/public/web/WebNavigationType.h"
30#include "third_party/WebKit/public/web/WebSecurityOrigin.h"
31#include "third_party/WebKit/public/web/WebTextAffinity.h"
32#include "third_party/WebKit/public/web/WebTextDirection.h"
33
34class SkBitmap;
35class SkCanvas;
36
37namespace blink {
38class WebAXObject;
39class WebAudioDevice;
40class WebCachedURLRequest;
41class WebColorChooser;
42class WebColorChooserClient;
43class WebDataSource;
44class WebDragData;
45class WebFileChooserCompletion;
46class WebFrame;
47class WebImage;
48class WebLocalFrame;
49class WebMIDIAccessor;
50class WebMIDIAccessorClient;
51class WebMIDIClient;
52class WebMIDIClientMock;
53class WebNode;
54class WebNotificationPresenter;
55class WebPlugin;
56class WebPushClient;
57class WebRange;
58class WebSerializedScriptValue;
59class WebSpeechRecognizer;
60class WebSpellCheckClient;
61class WebString;
62class WebURL;
63class WebURLResponse;
64class WebUserMediaClient;
65class WebView;
66class WebWidget;
67struct WebColorSuggestion;
68struct WebConsoleMessage;
69struct WebContextMenuData;
70struct WebFileChooserParams;
71struct WebPluginParams;
72struct WebPoint;
73struct WebSize;
74struct WebWindowFeatures;
75typedef unsigned WebColor;
76}
77
78namespace content {
79
80class MockCredentialManagerClient;
81class MockScreenOrientationClient;
82class MockWebPushClient;
83class MockWebSpeechRecognizer;
84class MockWebUserMediaClient;
85class RenderFrame;
86class SpellCheckClient;
87class TestInterfaces;
88class WebTestDelegate;
89class WebTestInterfaces;
90
91// WebTestProxyBase is the "brain" of WebTestProxy in the sense that
92// WebTestProxy does the bridge between RenderViewImpl and WebTestProxyBase and
93// when it requires a behavior to be different from the usual, it will call
94// WebTestProxyBase that implements the expected behavior.
95// See WebTestProxy class comments for more information.
96class WebTestProxyBase {
97 public:
98  void SetInterfaces(WebTestInterfaces* interfaces);
99  void SetDelegate(WebTestDelegate* delegate);
100  void set_widget(blink::WebWidget* widget) { web_widget_ = widget; }
101
102  void Reset();
103
104  blink::WebSpellCheckClient* GetSpellCheckClient() const;
105  blink::WebColorChooser* CreateColorChooser(
106      blink::WebColorChooserClient* client,
107      const blink::WebColor& color,
108      const blink::WebVector<blink::WebColorSuggestion>& suggestions);
109  bool RunFileChooser(const blink::WebFileChooserParams& params,
110                      blink::WebFileChooserCompletion* completion);
111  void ShowValidationMessage(const base::string16& message,
112                             const base::string16& sub_message);
113  void HideValidationMessage();
114  void MoveValidationMessage(const blink::WebRect& anchor_in_root_view);
115
116  std::string CaptureTree(bool debug_render_tree);
117  void CapturePixelsForPrinting(
118      const base::Callback<void(const SkBitmap&)>& callback);
119  void CopyImageAtAndCapturePixels(
120      int x, int y, const base::Callback<void(const SkBitmap&)>& callback);
121  void CapturePixelsAsync(
122      const base::Callback<void(const SkBitmap&)>& callback);
123
124  void SetLogConsoleOutput(bool enabled);
125
126  void DidOpenChooser();
127  void DidCloseChooser();
128  bool IsChooserShown();
129
130  void DisplayAsyncThen(const base::Closure& callback);
131
132  void GetScreenOrientationForTesting(blink::WebScreenInfo&);
133  MockScreenOrientationClient* GetScreenOrientationClientMock();
134  blink::WebMIDIClientMock* GetMIDIClientMock();
135  MockWebSpeechRecognizer* GetSpeechRecognizerMock();
136  MockCredentialManagerClient* GetCredentialManagerClientMock();
137
138  WebTaskList* mutable_task_list() { return &task_list_; }
139
140  blink::WebView* GetWebView() const;
141
142  void PostSpellCheckEvent(const blink::WebString& event_name);
143
144  void SetAcceptLanguages(const std::string& accept_languages);
145
146  MockWebPushClient* GetPushClientMock();
147
148 protected:
149  WebTestProxyBase();
150  ~WebTestProxyBase();
151
152  void ScheduleAnimation();
153  void PostAccessibilityEvent(const blink::WebAXObject&, blink::WebAXEvent);
154  void StartDragging(blink::WebLocalFrame* frame,
155                     const blink::WebDragData& data,
156                     blink::WebDragOperationsMask mask,
157                     const blink::WebImage& image,
158                     const blink::WebPoint& point);
159  void DidChangeSelection(bool isEmptySelection);
160  void DidChangeContents();
161  void DidEndEditing();
162  bool CreateView(blink::WebLocalFrame* creator,
163                  const blink::WebURLRequest& request,
164                  const blink::WebWindowFeatures& features,
165                  const blink::WebString& frame_name,
166                  blink::WebNavigationPolicy policy,
167                  bool suppress_opener);
168  blink::WebPlugin* CreatePlugin(blink::WebLocalFrame* frame,
169                                 const blink::WebPluginParams& params);
170  void SetStatusText(const blink::WebString& text);
171  void DidStopLoading();
172  void ShowContextMenu(blink::WebLocalFrame* frame,
173                       const blink::WebContextMenuData& data);
174  blink::WebUserMediaClient* GetUserMediaClient();
175  void PrintPage(blink::WebLocalFrame* frame);
176  blink::WebNotificationPresenter* GetNotificationPresenter();
177  blink::WebMIDIClient* GetWebMIDIClient();
178  blink::WebSpeechRecognizer* GetSpeechRecognizer();
179  bool RequestPointerLock();
180  void RequestPointerUnlock();
181  bool IsPointerLocked();
182  void DidFocus();
183  void DidBlur();
184  void SetToolTipText(const blink::WebString& text,
185                      blink::WebTextDirection direction);
186  void DidAddMessageToConsole(const blink::WebConsoleMessage& text,
187                              const blink::WebString& source_name,
188                              unsigned source_line);
189  void LoadURLExternally(blink::WebLocalFrame* frame,
190                         const blink::WebURLRequest& request,
191                         blink::WebNavigationPolicy policy,
192                         const blink::WebString& suggested_name);
193  void DidStartProvisionalLoad(blink::WebLocalFrame*);
194  void DidReceiveServerRedirectForProvisionalLoad(blink::WebLocalFrame* frame);
195  bool DidFailProvisionalLoad(blink::WebLocalFrame* frame,
196                              const blink::WebURLError& error);
197  void DidCommitProvisionalLoad(blink::WebLocalFrame* frame,
198                                const blink::WebHistoryItem& history_item,
199                                blink::WebHistoryCommitType history_type);
200  void DidReceiveTitle(blink::WebLocalFrame* frame,
201                       const blink::WebString& title,
202                       blink::WebTextDirection text_direction);
203  void DidChangeIcon(blink::WebLocalFrame* frame,
204                     blink::WebIconURL::Type icon_type);
205  void DidFinishDocumentLoad(blink::WebLocalFrame* frame);
206  void DidHandleOnloadEvents(blink::WebLocalFrame* frame);
207  void DidFailLoad(blink::WebLocalFrame* frame,
208                   const blink::WebURLError& error);
209  void DidFinishLoad(blink::WebLocalFrame* frame);
210  void DidChangeLocationWithinPage(blink::WebLocalFrame* frame);
211  void DidDetectXSS(blink::WebLocalFrame* frame,
212                    const blink::WebURL& insecure_url,
213                    bool did_block_entire_page);
214  void DidDispatchPingLoader(blink::WebLocalFrame* frame,
215                             const blink::WebURL& url);
216  void WillRequestResource(blink::WebLocalFrame* frame,
217                           const blink::WebCachedURLRequest& url_request);
218  void WillSendRequest(blink::WebLocalFrame* frame,
219                       unsigned identifier,
220                       blink::WebURLRequest& request,
221                       const blink::WebURLResponse& redirect_response);
222  void DidReceiveResponse(blink::WebLocalFrame* frame,
223                          unsigned identifier,
224                          const blink::WebURLResponse& response);
225  void DidChangeResourcePriority(blink::WebLocalFrame* frame,
226                                 unsigned identifier,
227                                 const blink::WebURLRequest::Priority& priority,
228                                 int intra_priority_value);
229  void DidFinishResourceLoad(blink::WebLocalFrame* frame, unsigned identifier);
230  blink::WebNavigationPolicy DecidePolicyForNavigation(
231      const blink::WebFrameClient::NavigationPolicyInfo& info);
232  bool WillCheckAndDispatchMessageEvent(blink::WebLocalFrame* source_frame,
233                                        blink::WebFrame* target_frame,
234                                        blink::WebSecurityOrigin target,
235                                        blink::WebDOMMessageEvent event);
236  void ResetInputMethod();
237
238  blink::WebString acceptLanguages();
239  blink::WebPushClient* GetWebPushClient();
240
241 private:
242  template <class, typename, typename>
243  friend class WebFrameTestProxy;
244
245  enum CheckDoneReason {
246    LoadFinished,
247    MainResourceLoadFailed,
248    ResourceLoadCompleted
249  };
250  void CheckDone(blink::WebLocalFrame* frame, CheckDoneReason reason);
251  void AnimateNow();
252  void DrawSelectionRect(SkCanvas* canvas);
253  void DidCapturePixelsAsync(const base::Callback<void(const SkBitmap&)>& callback, const SkBitmap& bitmap);
254  void DidDisplayAsync(const base::Closure& callback, const SkBitmap& bitmap);
255
256  blink::WebWidget* web_widget() const { return web_widget_; }
257
258  TestInterfaces* test_interfaces_;
259  WebTestDelegate* delegate_;
260  blink::WebWidget* web_widget_;
261
262  WebTaskList task_list_;
263
264  scoped_ptr<SpellCheckClient> spellcheck_;
265  scoped_ptr<MockWebUserMediaClient> user_media_client_;
266
267  bool animate_scheduled_;
268  std::map<unsigned, std::string> resource_identifier_map_;
269
270  bool log_console_output_;
271  int chooser_count_;
272
273  scoped_ptr<MockCredentialManagerClient> credential_manager_client_;
274  scoped_ptr<blink::WebMIDIClientMock> midi_client_;
275  scoped_ptr<MockWebSpeechRecognizer> speech_recognizer_;
276  scoped_ptr<MockWebPushClient> push_client_;
277  scoped_ptr<MockScreenOrientationClient> screen_orientation_client_;
278
279  std::string accept_languages_;
280
281 private:
282  DISALLOW_COPY_AND_ASSIGN(WebTestProxyBase);
283};
284
285// WebTestProxy is used during LayoutTests and always instantiated, at time of
286// writing with Base=RenderViewImpl. It does not directly inherit from it for
287// layering purposes.
288// The intent of that class is to wrap RenderViewImpl for tests purposes in
289// order to reduce the amount of test specific code in the production code.
290// WebTestProxy is only doing the glue between RenderViewImpl and
291// WebTestProxyBase, that means that there is no logic living in this class
292// except deciding which base class should be called (could be both).
293//
294// Examples of usage:
295//  * when a fooClient has a mock implementation, WebTestProxy can override the
296//    fooClient() call and have WebTestProxyBase return the mock implementation.
297//  * when a value needs to be overridden by LayoutTests, WebTestProxy can
298//    override RenderViewImpl's getter and call a getter from WebTestProxyBase
299//    instead. In addition, WebTestProxyBase will have a public setter that
300//    could be called from the TestRunner.
301template <class Base, typename T>
302class WebTestProxy : public Base, public WebTestProxyBase {
303 public:
304  explicit WebTestProxy(T t) : Base(t) {}
305
306  virtual ~WebTestProxy() {}
307
308  // WebWidgetClient implementation.
309  virtual blink::WebScreenInfo screenInfo() {
310    blink::WebScreenInfo info = Base::screenInfo();
311    WebTestProxyBase::GetScreenOrientationForTesting(info);
312    return info;
313  }
314
315  // WebViewClient implementation.
316  virtual void scheduleAnimation() { WebTestProxyBase::ScheduleAnimation(); }
317  virtual void postAccessibilityEvent(const blink::WebAXObject& object,
318                                      blink::WebAXEvent event) {
319    WebTestProxyBase::PostAccessibilityEvent(object, event);
320    Base::postAccessibilityEvent(object, event);
321  }
322  virtual void startDragging(blink::WebLocalFrame* frame,
323                             const blink::WebDragData& data,
324                             blink::WebDragOperationsMask mask,
325                             const blink::WebImage& image,
326                             const blink::WebPoint& point) {
327    WebTestProxyBase::StartDragging(frame, data, mask, image, point);
328    // Don't forward this call to Base because we don't want to do a real
329    // drag-and-drop.
330  }
331  virtual void didChangeContents() {
332    WebTestProxyBase::DidChangeContents();
333    Base::didChangeContents();
334  }
335  virtual blink::WebView* createView(blink::WebLocalFrame* creator,
336                                     const blink::WebURLRequest& request,
337                                     const blink::WebWindowFeatures& features,
338                                     const blink::WebString& frame_name,
339                                     blink::WebNavigationPolicy policy,
340                                     bool suppress_opener) {
341    if (!WebTestProxyBase::CreateView(
342            creator, request, features, frame_name, policy, suppress_opener))
343      return 0;
344    return Base::createView(
345        creator, request, features, frame_name, policy, suppress_opener);
346  }
347  virtual void setStatusText(const blink::WebString& text) {
348    WebTestProxyBase::SetStatusText(text);
349    Base::setStatusText(text);
350  }
351  virtual void printPage(blink::WebLocalFrame* frame) {
352    WebTestProxyBase::PrintPage(frame);
353  }
354  virtual blink::WebSpeechRecognizer* speechRecognizer() {
355    return WebTestProxyBase::GetSpeechRecognizer();
356  }
357  virtual bool requestPointerLock() {
358    return WebTestProxyBase::RequestPointerLock();
359  }
360  virtual void requestPointerUnlock() {
361    WebTestProxyBase::RequestPointerUnlock();
362  }
363  virtual bool isPointerLocked() { return WebTestProxyBase::IsPointerLocked(); }
364  virtual void didFocus() {
365    WebTestProxyBase::DidFocus();
366    Base::didFocus();
367  }
368  virtual void didBlur() {
369    WebTestProxyBase::DidBlur();
370    Base::didBlur();
371  }
372  virtual void setToolTipText(const blink::WebString& text,
373                              blink::WebTextDirection hint) {
374    WebTestProxyBase::SetToolTipText(text, hint);
375    Base::setToolTipText(text, hint);
376  }
377  virtual void resetInputMethod() { WebTestProxyBase::ResetInputMethod(); }
378  virtual bool runFileChooser(const blink::WebFileChooserParams& params,
379                              blink::WebFileChooserCompletion* completion) {
380    return WebTestProxyBase::RunFileChooser(params, completion);
381  }
382  virtual void showValidationMessage(const blink::WebRect& anchor_in_root_view,
383                                     const blink::WebString& main_message,
384                                     blink::WebTextDirection main_message_hint,
385                                     const blink::WebString& sub_message,
386                                     blink::WebTextDirection sub_message_hint) {
387    base::string16 wrapped_main_text = main_message;
388    base::string16 wrapped_sub_text = sub_message;
389
390    Base::SetValidationMessageDirection(
391        &wrapped_main_text, main_message_hint, &wrapped_sub_text, sub_message_hint);
392
393    WebTestProxyBase::ShowValidationMessage(
394        wrapped_main_text, wrapped_sub_text);
395  }
396  virtual void postSpellCheckEvent(const blink::WebString& event_name) {
397    WebTestProxyBase::PostSpellCheckEvent(event_name);
398  }
399  virtual blink::WebString acceptLanguages() {
400    return WebTestProxyBase::acceptLanguages();
401  }
402  virtual blink::WebPushClient* webPushClient() {
403    return WebTestProxyBase::GetWebPushClient();
404  }
405
406 private:
407  DISALLOW_COPY_AND_ASSIGN(WebTestProxy);
408};
409
410}  // namespace content
411
412#endif  // CONTENT_SHELL_RENDERER_TEST_RUNNER_WEB_TEST_PROXY_H_
413