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