• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/shell/renderer/webkit_test_runner.h"
6 
7 #include <algorithm>
8 #include <clocale>
9 #include <cmath>
10 
11 #include "base/base64.h"
12 #include "base/command_line.h"
13 #include "base/debug/debugger.h"
14 #include "base/files/file_path.h"
15 #include "base/md5.h"
16 #include "base/memory/scoped_ptr.h"
17 #include "base/message_loop/message_loop.h"
18 #include "base/strings/string_util.h"
19 #include "base/strings/stringprintf.h"
20 #include "base/strings/sys_string_conversions.h"
21 #include "base/strings/utf_string_conversions.h"
22 #include "base/time/time.h"
23 #include "content/public/common/content_switches.h"
24 #include "content/public/common/url_constants.h"
25 #include "content/public/renderer/history_item_serialization.h"
26 #include "content/public/renderer/render_view.h"
27 #include "content/public/renderer/render_view_visitor.h"
28 #include "content/public/test/layouttest_support.h"
29 #include "content/shell/common/shell_messages.h"
30 #include "content/shell/common/webkit_test_helpers.h"
31 #include "content/shell/renderer/shell_render_process_observer.h"
32 #include "net/base/net_errors.h"
33 #include "net/base/net_util.h"
34 #include "skia/ext/platform_canvas.h"
35 #include "third_party/WebKit/public/platform/Platform.h"
36 #include "third_party/WebKit/public/platform/WebCString.h"
37 #include "third_party/WebKit/public/platform/WebPoint.h"
38 #include "third_party/WebKit/public/platform/WebRect.h"
39 #include "third_party/WebKit/public/platform/WebSize.h"
40 #include "third_party/WebKit/public/platform/WebString.h"
41 #include "third_party/WebKit/public/platform/WebURL.h"
42 #include "third_party/WebKit/public/platform/WebURLError.h"
43 #include "third_party/WebKit/public/platform/WebURLRequest.h"
44 #include "third_party/WebKit/public/platform/WebURLResponse.h"
45 #include "third_party/WebKit/public/testing/WebTask.h"
46 #include "third_party/WebKit/public/testing/WebTestInterfaces.h"
47 #include "third_party/WebKit/public/testing/WebTestProxy.h"
48 #include "third_party/WebKit/public/testing/WebTestRunner.h"
49 #include "third_party/WebKit/public/web/WebArrayBufferView.h"
50 #include "third_party/WebKit/public/web/WebContextMenuData.h"
51 #include "third_party/WebKit/public/web/WebDataSource.h"
52 #include "third_party/WebKit/public/web/WebDevToolsAgent.h"
53 #include "third_party/WebKit/public/web/WebDocument.h"
54 #include "third_party/WebKit/public/web/WebElement.h"
55 #include "third_party/WebKit/public/web/WebFrame.h"
56 #include "third_party/WebKit/public/web/WebHistoryItem.h"
57 #include "third_party/WebKit/public/web/WebKit.h"
58 #include "third_party/WebKit/public/web/WebScriptSource.h"
59 #include "third_party/WebKit/public/web/WebTestingSupport.h"
60 #include "third_party/WebKit/public/web/WebView.h"
61 #include "ui/gfx/rect.h"
62 #include "webkit/common/webpreferences.h"
63 
64 using blink::Platform;
65 using blink::WebArrayBufferView;
66 using blink::WebContextMenuData;
67 using blink::WebDevToolsAgent;
68 using blink::WebDeviceMotionData;
69 using blink::WebDeviceOrientationData;
70 using blink::WebElement;
71 using blink::WebFrame;
72 using blink::WebGamepads;
73 using blink::WebHistoryItem;
74 using blink::WebPoint;
75 using blink::WebRect;
76 using blink::WebScriptSource;
77 using blink::WebSize;
78 using blink::WebString;
79 using blink::WebURL;
80 using blink::WebURLError;
81 using blink::WebURLRequest;
82 using blink::WebTestingSupport;
83 using blink::WebVector;
84 using blink::WebView;
85 using WebTestRunner::WebTask;
86 using WebTestRunner::WebTestInterfaces;
87 using WebTestRunner::WebTestProxyBase;
88 
89 namespace content {
90 
91 namespace {
92 
InvokeTaskHelper(void * context)93 void InvokeTaskHelper(void* context) {
94   WebTask* task = reinterpret_cast<WebTask*>(context);
95   task->run();
96   delete task;
97 }
98 
99 #if !defined(OS_MACOSX)
MakeBitmapOpaque(SkBitmap * bitmap)100 void MakeBitmapOpaque(SkBitmap* bitmap) {
101   SkAutoLockPixels lock(*bitmap);
102   DCHECK_EQ(bitmap->config(), SkBitmap::kARGB_8888_Config);
103   for (int y = 0; y < bitmap->height(); ++y) {
104     uint32_t* row = bitmap->getAddr32(0, y);
105     for (int x = 0; x < bitmap->width(); ++x)
106       row[x] |= 0xFF000000;  // Set alpha bits to 1.
107   }
108 }
109 #endif
110 
CopyCanvasToBitmap(SkCanvas * canvas,SkBitmap * snapshot)111 void CopyCanvasToBitmap(SkCanvas* canvas,  SkBitmap* snapshot) {
112   SkBaseDevice* device = skia::GetTopDevice(*canvas);
113   const SkBitmap& bitmap = device->accessBitmap(false);
114   const bool success = bitmap.copyTo(snapshot, SkBitmap::kARGB_8888_Config);
115   DCHECK(success);
116 
117 #if !defined(OS_MACOSX)
118   // Only the expected PNGs for Mac have a valid alpha channel.
119   if (!CommandLine::ForCurrentProcess()->HasSwitch(
120       switches::kEnableOverlayFullscreenVideo))
121     MakeBitmapOpaque(snapshot);
122 #endif
123 }
124 
125 class SyncNavigationStateVisitor : public RenderViewVisitor {
126  public:
SyncNavigationStateVisitor()127   SyncNavigationStateVisitor() {}
~SyncNavigationStateVisitor()128   virtual ~SyncNavigationStateVisitor() {}
129 
Visit(RenderView * render_view)130   virtual bool Visit(RenderView* render_view) OVERRIDE {
131     SyncNavigationState(render_view);
132     return true;
133   }
134  private:
135   DISALLOW_COPY_AND_ASSIGN(SyncNavigationStateVisitor);
136 };
137 
138 class ProxyToRenderViewVisitor : public RenderViewVisitor {
139  public:
ProxyToRenderViewVisitor(WebTestProxyBase * proxy)140   explicit ProxyToRenderViewVisitor(WebTestProxyBase* proxy)
141       : proxy_(proxy),
142         render_view_(NULL) {
143   }
~ProxyToRenderViewVisitor()144   virtual ~ProxyToRenderViewVisitor() {}
145 
render_view() const146   RenderView* render_view() const { return render_view_; }
147 
Visit(RenderView * render_view)148   virtual bool Visit(RenderView* render_view) OVERRIDE {
149     WebKitTestRunner* test_runner = WebKitTestRunner::Get(render_view);
150     if (!test_runner) {
151       NOTREACHED();
152       return true;
153     }
154     if (test_runner->proxy() == proxy_) {
155       render_view_ = render_view;
156       return false;
157     }
158     return true;
159   }
160 
161  private:
162   WebTestProxyBase* proxy_;
163   RenderView* render_view_;
164 
165   DISALLOW_COPY_AND_ASSIGN(ProxyToRenderViewVisitor);
166 };
167 
168 class NavigateAwayVisitor : public RenderViewVisitor {
169  public:
NavigateAwayVisitor(RenderView * main_render_view)170   explicit NavigateAwayVisitor(RenderView* main_render_view)
171       : main_render_view_(main_render_view) {}
~NavigateAwayVisitor()172   virtual ~NavigateAwayVisitor() {}
173 
Visit(RenderView * render_view)174   virtual bool Visit(RenderView* render_view) OVERRIDE {
175     if (render_view == main_render_view_)
176       return true;
177     render_view->GetWebView()->mainFrame()->loadRequest(
178         WebURLRequest(GURL(kAboutBlankURL)));
179     return true;
180   }
181 
182  private:
183   RenderView* main_render_view_;
184 
185   DISALLOW_COPY_AND_ASSIGN(NavigateAwayVisitor);
186 };
187 
188 class UseSynchronousResizeModeVisitor : public RenderViewVisitor {
189  public:
UseSynchronousResizeModeVisitor(bool enable)190   explicit UseSynchronousResizeModeVisitor(bool enable) : enable_(enable) {}
~UseSynchronousResizeModeVisitor()191   virtual ~UseSynchronousResizeModeVisitor() {}
192 
Visit(RenderView * render_view)193   virtual bool Visit(RenderView* render_view) OVERRIDE {
194     UseSynchronousResizeMode(render_view, enable_);
195     return true;
196   }
197 
198  private:
199   bool enable_;
200 };
201 
202 }  // namespace
203 
WebKitTestRunner(RenderView * render_view)204 WebKitTestRunner::WebKitTestRunner(RenderView* render_view)
205     : RenderViewObserver(render_view),
206       RenderViewObserverTracker<WebKitTestRunner>(render_view),
207       proxy_(NULL),
208       focused_view_(NULL),
209       is_main_window_(false),
210       focus_on_next_commit_(false) {
211   UseMockMediaStreams(render_view);
212 }
213 
~WebKitTestRunner()214 WebKitTestRunner::~WebKitTestRunner() {
215 }
216 
217 // WebTestDelegate  -----------------------------------------------------------
218 
clearEditCommand()219 void WebKitTestRunner::clearEditCommand() {
220   render_view()->ClearEditCommands();
221 }
222 
setEditCommand(const std::string & name,const std::string & value)223 void WebKitTestRunner::setEditCommand(const std::string& name,
224                                       const std::string& value) {
225   render_view()->SetEditCommandForNextKeyEvent(name, value);
226 }
227 
setGamepadData(const WebGamepads & gamepads)228 void WebKitTestRunner::setGamepadData(const WebGamepads& gamepads) {
229   SetMockGamepads(gamepads);
230 }
231 
setDeviceMotionData(const WebDeviceMotionData & data)232 void WebKitTestRunner::setDeviceMotionData(const WebDeviceMotionData& data) {
233   SetMockDeviceMotionData(data);
234 }
235 
setDeviceOrientationData(const WebDeviceOrientationData & data)236 void WebKitTestRunner::setDeviceOrientationData(
237     const WebDeviceOrientationData& data) {
238   SetMockDeviceOrientationData(data);
239 }
240 
printMessage(const std::string & message)241 void WebKitTestRunner::printMessage(const std::string& message) {
242   Send(new ShellViewHostMsg_PrintMessage(routing_id(), message));
243 }
244 
postTask(WebTask * task)245 void WebKitTestRunner::postTask(WebTask* task) {
246   Platform::current()->callOnMainThread(InvokeTaskHelper, task);
247 }
248 
postDelayedTask(WebTask * task,long long ms)249 void WebKitTestRunner::postDelayedTask(WebTask* task, long long ms) {
250   base::MessageLoop::current()->PostDelayedTask(
251       FROM_HERE,
252       base::Bind(&WebTask::run, base::Owned(task)),
253       base::TimeDelta::FromMilliseconds(ms));
254 }
255 
registerIsolatedFileSystem(const blink::WebVector<blink::WebString> & absolute_filenames)256 WebString WebKitTestRunner::registerIsolatedFileSystem(
257     const blink::WebVector<blink::WebString>& absolute_filenames) {
258   std::vector<base::FilePath> files;
259   for (size_t i = 0; i < absolute_filenames.size(); ++i)
260     files.push_back(base::FilePath::FromUTF16Unsafe(absolute_filenames[i]));
261   std::string filesystem_id;
262   Send(new ShellViewHostMsg_RegisterIsolatedFileSystem(
263       routing_id(), files, &filesystem_id));
264   return WebString::fromUTF8(filesystem_id);
265 }
266 
getCurrentTimeInMillisecond()267 long long WebKitTestRunner::getCurrentTimeInMillisecond() {
268   return base::TimeDelta(base::Time::Now() -
269                          base::Time::UnixEpoch()).ToInternalValue() /
270          base::Time::kMicrosecondsPerMillisecond;
271 }
272 
getAbsoluteWebStringFromUTF8Path(const std::string & utf8_path)273 WebString WebKitTestRunner::getAbsoluteWebStringFromUTF8Path(
274     const std::string& utf8_path) {
275   base::FilePath path = base::FilePath::FromUTF8Unsafe(utf8_path);
276   if (!path.IsAbsolute()) {
277     GURL base_url =
278         net::FilePathToFileURL(test_config_.current_working_directory.Append(
279             FILE_PATH_LITERAL("foo")));
280     net::FileURLToFilePath(base_url.Resolve(utf8_path), &path);
281   }
282   return path.AsUTF16Unsafe();
283 }
284 
localFileToDataURL(const WebURL & file_url)285 WebURL WebKitTestRunner::localFileToDataURL(const WebURL& file_url) {
286   base::FilePath local_path;
287   if (!net::FileURLToFilePath(file_url, &local_path))
288     return WebURL();
289 
290   std::string contents;
291   Send(new ShellViewHostMsg_ReadFileToString(
292         routing_id(), local_path, &contents));
293 
294   std::string contents_base64;
295   base::Base64Encode(contents, &contents_base64);
296 
297   const char data_url_prefix[] = "data:text/css:charset=utf-8;base64,";
298   return WebURL(GURL(data_url_prefix + contents_base64));
299 }
300 
rewriteLayoutTestsURL(const std::string & utf8_url)301 WebURL WebKitTestRunner::rewriteLayoutTestsURL(const std::string& utf8_url) {
302   const char kPrefix[] = "file:///tmp/LayoutTests/";
303   const int kPrefixLen = arraysize(kPrefix) - 1;
304 
305   if (utf8_url.compare(0, kPrefixLen, kPrefix, kPrefixLen))
306     return WebURL(GURL(utf8_url));
307 
308   base::FilePath replace_path =
309       ShellRenderProcessObserver::GetInstance()->webkit_source_dir().Append(
310           FILE_PATH_LITERAL("LayoutTests/"));
311 #if defined(OS_WIN)
312   std::string utf8_path = WideToUTF8(replace_path.value());
313 #else
314   std::string utf8_path =
315       WideToUTF8(base::SysNativeMBToWide(replace_path.value()));
316 #endif
317   std::string new_url =
318       std::string("file://") + utf8_path + utf8_url.substr(kPrefixLen);
319   return WebURL(GURL(new_url));
320 }
321 
preferences()322 WebTestRunner::WebPreferences* WebKitTestRunner::preferences() {
323   return &prefs_;
324 }
325 
applyPreferences()326 void WebKitTestRunner::applyPreferences() {
327   WebPreferences prefs = render_view()->GetWebkitPreferences();
328   ExportLayoutTestSpecificPreferences(prefs_, &prefs);
329   render_view()->SetWebkitPreferences(prefs);
330   Send(new ShellViewHostMsg_OverridePreferences(routing_id(), prefs));
331 }
332 
makeURLErrorDescription(const WebURLError & error)333 std::string WebKitTestRunner::makeURLErrorDescription(
334     const WebURLError& error) {
335   std::string domain = error.domain.utf8();
336   int code = error.reason;
337 
338   if (domain == net::kErrorDomain) {
339     domain = "NSURLErrorDomain";
340     switch (error.reason) {
341     case net::ERR_ABORTED:
342       code = -999;  // NSURLErrorCancelled
343       break;
344     case net::ERR_UNSAFE_PORT:
345       // Our unsafe port checking happens at the network stack level, but we
346       // make this translation here to match the behavior of stock WebKit.
347       domain = "WebKitErrorDomain";
348       code = 103;
349       break;
350     case net::ERR_ADDRESS_INVALID:
351     case net::ERR_ADDRESS_UNREACHABLE:
352     case net::ERR_NETWORK_ACCESS_DENIED:
353       code = -1004;  // NSURLErrorCannotConnectToHost
354       break;
355     }
356   } else {
357     DLOG(WARNING) << "Unknown error domain";
358   }
359 
360   return base::StringPrintf("<NSError domain %s, code %d, failing URL \"%s\">",
361       domain.c_str(), code, error.unreachableURL.spec().data());
362 }
363 
useUnfortunateSynchronousResizeMode(bool enable)364 void WebKitTestRunner::useUnfortunateSynchronousResizeMode(bool enable) {
365   UseSynchronousResizeModeVisitor visitor(enable);
366   RenderView::ForEach(&visitor);
367 }
368 
enableAutoResizeMode(const WebSize & min_size,const WebSize & max_size)369 void WebKitTestRunner::enableAutoResizeMode(const WebSize& min_size,
370                                             const WebSize& max_size) {
371   EnableAutoResizeMode(render_view(), min_size, max_size);
372 }
373 
disableAutoResizeMode(const WebSize & new_size)374 void WebKitTestRunner::disableAutoResizeMode(const WebSize& new_size) {
375   DisableAutoResizeMode(render_view(), new_size);
376   if (!new_size.isEmpty())
377     ForceResizeRenderView(render_view(), new_size);
378 }
379 
showDevTools()380 void WebKitTestRunner::showDevTools() {
381   Send(new ShellViewHostMsg_ShowDevTools(routing_id()));
382 }
383 
closeDevTools()384 void WebKitTestRunner::closeDevTools() {
385   Send(new ShellViewHostMsg_CloseDevTools(routing_id()));
386   WebDevToolsAgent* agent = render_view()->GetWebView()->devToolsAgent();
387   if (agent)
388     agent->detach();
389 }
390 
evaluateInWebInspector(long call_id,const std::string & script)391 void WebKitTestRunner::evaluateInWebInspector(long call_id,
392                                               const std::string& script) {
393   WebDevToolsAgent* agent = render_view()->GetWebView()->devToolsAgent();
394   if (agent)
395     agent->evaluateInWebInspector(call_id, WebString::fromUTF8(script));
396 }
397 
clearAllDatabases()398 void WebKitTestRunner::clearAllDatabases() {
399   Send(new ShellViewHostMsg_ClearAllDatabases(routing_id()));
400 }
401 
setDatabaseQuota(int quota)402 void WebKitTestRunner::setDatabaseQuota(int quota) {
403   Send(new ShellViewHostMsg_SetDatabaseQuota(routing_id(), quota));
404 }
405 
setDeviceScaleFactor(float factor)406 void WebKitTestRunner::setDeviceScaleFactor(float factor) {
407   SetDeviceScaleFactor(render_view(), factor);
408 }
409 
setFocus(WebTestProxyBase * proxy,bool focus)410 void WebKitTestRunner::setFocus(WebTestProxyBase* proxy, bool focus) {
411   ProxyToRenderViewVisitor visitor(proxy);
412   RenderView::ForEach(&visitor);
413   if (!visitor.render_view()) {
414     NOTREACHED();
415     return;
416   }
417 
418   // Check whether the focused view was closed meanwhile.
419   if (!WebKitTestRunner::Get(focused_view_))
420     focused_view_ = NULL;
421 
422   if (focus) {
423     if (focused_view_ != visitor.render_view()) {
424       if (focused_view_)
425         SetFocusAndActivate(focused_view_, false);
426       SetFocusAndActivate(visitor.render_view(), true);
427       focused_view_ = visitor.render_view();
428     }
429   } else {
430     if (focused_view_ == visitor.render_view()) {
431       SetFocusAndActivate(visitor.render_view(), false);
432       focused_view_ = NULL;
433     }
434   }
435 }
436 
setAcceptAllCookies(bool accept)437 void WebKitTestRunner::setAcceptAllCookies(bool accept) {
438   Send(new ShellViewHostMsg_AcceptAllCookies(routing_id(), accept));
439 }
440 
pathToLocalResource(const std::string & resource)441 std::string WebKitTestRunner::pathToLocalResource(const std::string& resource) {
442 #if defined(OS_WIN)
443   if (resource.find("/tmp/") == 0) {
444     // We want a temp file.
445     GURL base_url = net::FilePathToFileURL(test_config_.temp_path);
446     return base_url.Resolve(resource.substr(strlen("/tmp/"))).spec();
447   }
448 #endif
449 
450   // Some layout tests use file://// which we resolve as a UNC path. Normalize
451   // them to just file:///.
452   std::string result = resource;
453   while (StringToLowerASCII(result).find("file:////") == 0) {
454     result = result.substr(0, strlen("file:///")) +
455              result.substr(strlen("file:////"));
456   }
457   return rewriteLayoutTestsURL(result).spec();
458 }
459 
setLocale(const std::string & locale)460 void WebKitTestRunner::setLocale(const std::string& locale) {
461   setlocale(LC_ALL, locale.c_str());
462 }
463 
testFinished()464 void WebKitTestRunner::testFinished() {
465   if (!is_main_window_) {
466     Send(new ShellViewHostMsg_TestFinishedInSecondaryWindow(routing_id()));
467     return;
468   }
469   WebTestInterfaces* interfaces =
470       ShellRenderProcessObserver::GetInstance()->test_interfaces();
471   interfaces->setTestIsRunning(false);
472   if (interfaces->testRunner()->shouldDumpBackForwardList()) {
473     SyncNavigationStateVisitor visitor;
474     RenderView::ForEach(&visitor);
475     Send(new ShellViewHostMsg_CaptureSessionHistory(routing_id()));
476   } else {
477     CaptureDump();
478   }
479 }
480 
closeRemainingWindows()481 void WebKitTestRunner::closeRemainingWindows() {
482   NavigateAwayVisitor visitor(render_view());
483   RenderView::ForEach(&visitor);
484   Send(new ShellViewHostMsg_CloseRemainingWindows(routing_id()));
485 }
486 
deleteAllCookies()487 void WebKitTestRunner::deleteAllCookies() {
488   Send(new ShellViewHostMsg_DeleteAllCookies(routing_id()));
489 }
490 
navigationEntryCount()491 int WebKitTestRunner::navigationEntryCount() {
492   return GetLocalSessionHistoryLength(render_view());
493 }
494 
goToOffset(int offset)495 void WebKitTestRunner::goToOffset(int offset) {
496   Send(new ShellViewHostMsg_GoToOffset(routing_id(), offset));
497 }
498 
reload()499 void WebKitTestRunner::reload() {
500   Send(new ShellViewHostMsg_Reload(routing_id()));
501 }
502 
loadURLForFrame(const WebURL & url,const std::string & frame_name)503 void WebKitTestRunner::loadURLForFrame(const WebURL& url,
504                              const std::string& frame_name) {
505   Send(new ShellViewHostMsg_LoadURLForFrame(
506       routing_id(), url, frame_name));
507 }
508 
allowExternalPages()509 bool WebKitTestRunner::allowExternalPages() {
510   return test_config_.allow_external_pages;
511 }
512 
captureHistoryForWindow(WebTestProxyBase * proxy,WebVector<blink::WebHistoryItem> * history,size_t * currentEntryIndex)513 void WebKitTestRunner::captureHistoryForWindow(
514     WebTestProxyBase* proxy,
515     WebVector<blink::WebHistoryItem>* history,
516     size_t* currentEntryIndex) {
517   size_t pos = 0;
518   std::vector<int>::iterator id;
519   for (id = routing_ids_.begin(); id != routing_ids_.end(); ++id, ++pos) {
520     RenderView* render_view = RenderView::FromRoutingID(*id);
521     if (!render_view) {
522       NOTREACHED();
523       continue;
524     }
525     if (WebKitTestRunner::Get(render_view)->proxy() == proxy)
526       break;
527   }
528 
529   if (id == routing_ids_.end()) {
530     NOTREACHED();
531     return;
532   }
533   size_t num_entries = session_histories_[pos].size();
534   *currentEntryIndex = current_entry_indexes_[pos];
535   WebVector<WebHistoryItem> result(num_entries);
536   for (size_t entry = 0; entry < num_entries; ++entry) {
537     result[entry] =
538         PageStateToHistoryItem(session_histories_[pos][entry]);
539   }
540   history->swap(result);
541 }
542 
543 // RenderViewObserver  --------------------------------------------------------
544 
DidClearWindowObject(WebFrame * frame)545 void WebKitTestRunner::DidClearWindowObject(WebFrame* frame) {
546   WebTestingSupport::injectInternalsObject(frame);
547   ShellRenderProcessObserver::GetInstance()->test_interfaces()->bindTo(frame);
548 }
549 
OnMessageReceived(const IPC::Message & message)550 bool WebKitTestRunner::OnMessageReceived(const IPC::Message& message) {
551   bool handled = true;
552   IPC_BEGIN_MESSAGE_MAP(WebKitTestRunner, message)
553     IPC_MESSAGE_HANDLER(ShellViewMsg_SetTestConfiguration,
554                         OnSetTestConfiguration)
555     IPC_MESSAGE_HANDLER(ShellViewMsg_SessionHistory, OnSessionHistory)
556     IPC_MESSAGE_HANDLER(ShellViewMsg_Reset, OnReset)
557     IPC_MESSAGE_HANDLER(ShellViewMsg_NotifyDone, OnNotifyDone)
558     IPC_MESSAGE_UNHANDLED(handled = false)
559   IPC_END_MESSAGE_MAP()
560 
561   return handled;
562 }
563 
Navigate(const GURL & url)564 void WebKitTestRunner::Navigate(const GURL& url) {
565   focus_on_next_commit_ = true;
566   if (!is_main_window_ &&
567       ShellRenderProcessObserver::GetInstance()->main_test_runner() == this) {
568     WebTestInterfaces* interfaces =
569         ShellRenderProcessObserver::GetInstance()->test_interfaces();
570     interfaces->setTestIsRunning(true);
571     interfaces->configureForTestWithURL(GURL(), false);
572     ForceResizeRenderView(render_view(), WebSize(800, 600));
573   }
574 }
575 
DidCommitProvisionalLoad(WebFrame * frame,bool is_new_navigation)576 void WebKitTestRunner::DidCommitProvisionalLoad(WebFrame* frame,
577                                                 bool is_new_navigation) {
578   if (!focus_on_next_commit_)
579     return;
580   focus_on_next_commit_ = false;
581   render_view()->GetWebView()->setFocusedFrame(frame);
582 }
583 
DidFailProvisionalLoad(WebFrame * frame,const WebURLError & error)584 void WebKitTestRunner::DidFailProvisionalLoad(WebFrame* frame,
585                                               const WebURLError& error) {
586   focus_on_next_commit_ = false;
587 }
588 
589 // Public methods - -----------------------------------------------------------
590 
Reset()591 void WebKitTestRunner::Reset() {
592   // The proxy_ is always non-NULL, it is set right after construction.
593   proxy_->setWidget(render_view()->GetWebView());
594   proxy_->reset();
595   prefs_.reset();
596   routing_ids_.clear();
597   session_histories_.clear();
598   current_entry_indexes_.clear();
599 
600   render_view()->ClearEditCommands();
601   render_view()->GetWebView()->mainFrame()->setName(WebString());
602   render_view()->GetWebView()->mainFrame()->clearOpener();
603   render_view()->GetWebView()->setPageScaleFactorLimits(-1, -1);
604   render_view()->GetWebView()->setPageScaleFactor(1, WebPoint(0, 0));
605 
606   // Resetting the internals object also overrides the WebPreferences, so we
607   // have to sync them to WebKit again.
608   WebTestingSupport::resetInternalsObject(
609       render_view()->GetWebView()->mainFrame());
610   render_view()->SetWebkitPreferences(render_view()->GetWebkitPreferences());
611 }
612 
613 // Private methods  -----------------------------------------------------------
614 
CaptureDump()615 void WebKitTestRunner::CaptureDump() {
616   WebTestInterfaces* interfaces =
617       ShellRenderProcessObserver::GetInstance()->test_interfaces();
618 
619   if (interfaces->testRunner()->shouldDumpAsAudio()) {
620     const WebArrayBufferView* audio_data =
621         interfaces->testRunner()->audioData();
622     std::vector<unsigned char> vector_data(
623         static_cast<const unsigned char*>(audio_data->baseAddress()),
624         static_cast<const unsigned char*>(audio_data->baseAddress()) +
625             audio_data->byteLength());
626     Send(new ShellViewHostMsg_AudioDump(routing_id(), vector_data));
627   } else {
628     Send(new ShellViewHostMsg_TextDump(routing_id(),
629                                        proxy()->captureTree(false)));
630 
631     if (test_config_.enable_pixel_dumping &&
632         interfaces->testRunner()->shouldGeneratePixelResults()) {
633       SkBitmap snapshot;
634       CopyCanvasToBitmap(proxy()->capturePixels(), &snapshot);
635 
636       SkAutoLockPixels snapshot_lock(snapshot);
637       base::MD5Digest digest;
638       base::MD5Sum(snapshot.getPixels(), snapshot.getSize(), &digest);
639       std::string actual_pixel_hash = base::MD5DigestToBase16(digest);
640 
641       if (actual_pixel_hash == test_config_.expected_pixel_hash) {
642         SkBitmap empty_image;
643         Send(new ShellViewHostMsg_ImageDump(
644             routing_id(), actual_pixel_hash, empty_image));
645       } else {
646         Send(new ShellViewHostMsg_ImageDump(
647             routing_id(), actual_pixel_hash, snapshot));
648       }
649     }
650   }
651 
652   render_view()->GetWebView()->mainFrame()->stopLoading();
653 
654   base::MessageLoop::current()->PostTask(
655       FROM_HERE,
656       base::Bind(base::IgnoreResult(&WebKitTestRunner::Send),
657                  base::Unretained(this),
658                  new ShellViewHostMsg_TestFinished(routing_id())));
659 }
660 
OnSetTestConfiguration(const ShellTestConfiguration & params)661 void WebKitTestRunner::OnSetTestConfiguration(
662     const ShellTestConfiguration& params) {
663   test_config_ = params;
664   is_main_window_ = true;
665 
666   ForceResizeRenderView(
667       render_view(),
668       WebSize(params.initial_size.width(), params.initial_size.height()));
669   setFocus(proxy_, true);
670 
671   WebTestInterfaces* interfaces =
672       ShellRenderProcessObserver::GetInstance()->test_interfaces();
673   interfaces->setTestIsRunning(true);
674   interfaces->configureForTestWithURL(params.test_url,
675                                       params.enable_pixel_dumping);
676 }
677 
OnSessionHistory(const std::vector<int> & routing_ids,const std::vector<std::vector<PageState>> & session_histories,const std::vector<unsigned> & current_entry_indexes)678 void WebKitTestRunner::OnSessionHistory(
679     const std::vector<int>& routing_ids,
680     const std::vector<std::vector<PageState> >& session_histories,
681     const std::vector<unsigned>& current_entry_indexes) {
682   routing_ids_ = routing_ids;
683   session_histories_ = session_histories;
684   current_entry_indexes_ = current_entry_indexes;
685   CaptureDump();
686 }
687 
OnReset()688 void WebKitTestRunner::OnReset() {
689   ShellRenderProcessObserver::GetInstance()->test_interfaces()->resetAll();
690   Reset();
691   // Navigating to about:blank will make sure that no new loads are initiated
692   // by the renderer.
693   render_view()->GetWebView()->mainFrame()->loadRequest(
694       WebURLRequest(GURL(kAboutBlankURL)));
695   Send(new ShellViewHostMsg_ResetDone(routing_id()));
696 }
697 
OnNotifyDone()698 void WebKitTestRunner::OnNotifyDone() {
699   render_view()->GetWebView()->mainFrame()->executeScript(
700       WebScriptSource(WebString::fromUTF8("testRunner.notifyDone();")));
701 }
702 
703 }  // namespace content
704