OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (C) 2012 Google Inc. All rights reserved. | |
3 * | |
4 * Redistribution and use in source and binary forms, with or without | |
5 * modification, are permitted provided that the following conditions are | |
6 * met: | |
7 * | |
8 * * Redistributions of source code must retain the above copyright | |
9 * notice, this list of conditions and the following disclaimer. | |
10 * * Redistributions in binary form must reproduce the above | |
11 * copyright notice, this list of conditions and the following disclaimer | |
12 * in the documentation and/or other materials provided with the | |
13 * distribution. | |
14 * * Neither the name of Google Inc. nor the names of its | |
15 * contributors may be used to endorse or promote products derived from | |
16 * this software without specific prior written permission. | |
17 * | |
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
29 */ | |
30 | |
31 #include "config.h" | |
32 #include "TestShell.h" | |
33 | |
34 #include "DRTDevToolsAgent.h" | |
35 #include "DRTDevToolsClient.h" | |
36 #include "MockPlatform.h" | |
37 #include "MockWebPrerenderingSupport.h" | |
38 #include "WebArrayBufferView.h" | |
39 #include "WebDataSource.h" | |
40 #include "WebDocument.h" | |
41 #include "WebElement.h" | |
42 #include "WebFrame.h" | |
43 #include "WebHistoryItem.h" | |
44 #include "WebTestingSupport.h" | |
45 #include "WebSettings.h" | |
46 #include "WebTestProxy.h" | |
47 #include "WebTestRunner.h" | |
48 #include "WebView.h" | |
49 #include "WebViewHost.h" | |
50 #include "skia/ext/platform_canvas.h" | |
51 #include "webkit/support/webkit_support.h" | |
52 #include "webkit/support/webkit_support_gfx.h" | |
53 #include "public/platform/Platform.h" | |
54 #include "public/platform/WebCompositorSupport.h" | |
55 #include "public/platform/WebPoint.h" | |
56 #include "public/platform/WebSize.h" | |
57 #include "public/platform/WebString.h" | |
58 #include "public/platform/WebThread.h" | |
59 #include "public/platform/WebURLRequest.h" | |
60 #include "public/platform/WebURLResponse.h" | |
61 #include <algorithm> | |
62 #include <cctype> | |
63 #include <vector> | |
64 #include <wtf/MD5.h> | |
65 #include <wtf/OwnArrayPtr.h> | |
66 | |
67 | |
68 using namespace WebKit; | |
69 using namespace WebTestRunner; | |
70 using namespace std; | |
71 | |
72 // Content area size for newly created windows. | |
73 static const int testWindowWidth = 800; | |
74 static const int testWindowHeight = 600; | |
75 | |
76 // The W3C SVG layout tests use a different size than the other layout tests. | |
77 static const int SVGTestWindowWidth = 480; | |
78 static const int SVGTestWindowHeight = 360; | |
79 | |
80 static const char layoutTestsPattern[] = "/LayoutTests/"; | |
81 static const string::size_type layoutTestsPatternSize = sizeof(layoutTestsPatter
n) - 1; | |
82 static const char fileUrlPattern[] = "file:/"; | |
83 static const char fileTestPrefix[] = "(file test):"; | |
84 static const char dataUrlPattern[] = "data:"; | |
85 static const string::size_type dataUrlPatternSize = sizeof(dataUrlPattern) - 1; | |
86 | |
87 // FIXME: Move this to a common place so that it can be shared with | |
88 // WebCore::TransparencyWin::makeLayerOpaque(). | |
89 static void makeCanvasOpaque(SkCanvas* canvas) | |
90 { | |
91 const SkBitmap& bitmap = canvas->getTopDevice()->accessBitmap(true); | |
92 ASSERT(bitmap.config() == SkBitmap::kARGB_8888_Config); | |
93 | |
94 SkAutoLockPixels lock(bitmap); | |
95 for (int y = 0; y < bitmap.height(); y++) { | |
96 uint32_t* row = bitmap.getAddr32(0, y); | |
97 for (int x = 0; x < bitmap.width(); x++) | |
98 row[x] |= 0xFF000000; // Set alpha bits to 1. | |
99 } | |
100 } | |
101 | |
102 TestShell::TestShell() | |
103 : m_testIsPending(false) | |
104 , m_testIsPreparing(false) | |
105 , m_focusedWidget(0) | |
106 , m_devTools(0) | |
107 , m_dumpPixelsForCurrentTest(false) | |
108 , m_allowExternalPages(false) | |
109 , m_acceleratedCompositingForVideoEnabled(false) | |
110 , m_acceleratedCompositingForFixedPositionEnabled(false) | |
111 , m_acceleratedCompositingForOverflowScrollEnabled(false) | |
112 , m_acceleratedCompositingForTransitionEnabled(false) | |
113 , m_softwareCompositingEnabled(false) | |
114 , m_threadedCompositingEnabled(false) | |
115 , m_forceCompositingMode(false) | |
116 , m_threadedHTMLParser(true) | |
117 , m_accelerated2dCanvasEnabled(false) | |
118 , m_perTilePaintingEnabled(false) | |
119 , m_deferredImageDecodingEnabled(false) | |
120 , m_stressOpt(false) | |
121 , m_stressDeopt(false) | |
122 , m_dumpWhenFinished(true) | |
123 , m_isDisplayingModalDialog(false) | |
124 { | |
125 // 30 second is the same as the value in Mac DRT. | |
126 // If we use a value smaller than the timeout value of | |
127 // (new-)run-webkit-tests, (new-)run-webkit-tests misunderstands that a | |
128 // timed-out DRT process was crashed. | |
129 m_timeout = 30 * 1000; | |
130 } | |
131 | |
132 void TestShell::initialize(MockPlatform* platformSupport) | |
133 { | |
134 m_testInterfaces = adoptPtr(new WebTestInterfaces()); | |
135 platformSupport->setInterfaces(m_testInterfaces.get()); | |
136 m_devToolsTestInterfaces = adoptPtr(new WebTestInterfaces()); | |
137 m_prerenderingSupport = adoptPtr(new MockWebPrerenderingSupport()); | |
138 #if !defined(USE_DEFAULT_RENDER_THEME) && (OS(WINDOWS) || OS(DARWIN)) | |
139 // Set theme engine. | |
140 webkit_support::SetThemeEngine(m_testInterfaces->themeEngine()); | |
141 #endif | |
142 | |
143 if (m_threadedCompositingEnabled) | |
144 m_webCompositorThread = adoptPtr(WebKit::Platform::current()->createThre
ad("Compositor")); | |
145 webkit_support::SetThreadedCompositorEnabled(m_threadedCompositingEnabled); | |
146 | |
147 createMainWindow(); | |
148 } | |
149 | |
150 void TestShell::createMainWindow() | |
151 { | |
152 m_drtDevToolsAgent = adoptPtr(new DRTDevToolsAgent); | |
153 m_webViewHost = adoptPtr(createNewWindow(WebURL(), m_drtDevToolsAgent.get(),
m_testInterfaces.get())); | |
154 m_webView = m_webViewHost->webView(); | |
155 m_testInterfaces->setDelegate(m_webViewHost.get()); | |
156 m_testInterfaces->setWebView(m_webView, m_webViewHost->proxy()); | |
157 m_drtDevToolsAgent->setWebView(m_webView); | |
158 } | |
159 | |
160 TestShell::~TestShell() | |
161 { | |
162 if (m_webViewHost) | |
163 m_webViewHost->shutdown(); | |
164 m_testInterfaces->setDelegate(0); | |
165 m_testInterfaces->setWebView(0, 0); | |
166 m_devToolsTestInterfaces->setDelegate(0); | |
167 m_devToolsTestInterfaces->setWebView(0, 0); | |
168 m_drtDevToolsAgent->setWebView(0); | |
169 } | |
170 | |
171 void TestShell::createDRTDevToolsClient(DRTDevToolsAgent* agent) | |
172 { | |
173 m_drtDevToolsClient = adoptPtr(new DRTDevToolsClient(agent, m_devTools->webV
iew())); | |
174 } | |
175 | |
176 void TestShell::showDevTools() | |
177 { | |
178 if (!m_devTools) { | |
179 WebURL url = webkit_support::GetDevToolsPathAsURL(); | |
180 if (!url.isValid()) { | |
181 ASSERT(false); | |
182 return; | |
183 } | |
184 m_devTools = createNewWindow(url, 0, m_devToolsTestInterfaces.get()); | |
185 m_devTools->webView()->settings()->setMemoryInfoEnabled(true); | |
186 m_devTools->proxy()->setLogConsoleOutput(false); | |
187 m_devToolsTestInterfaces->setDelegate(m_devTools); | |
188 m_devToolsTestInterfaces->setWebView(m_devTools->webView(), m_devTools->
proxy()); | |
189 ASSERT(m_devTools); | |
190 createDRTDevToolsClient(m_drtDevToolsAgent.get()); | |
191 } | |
192 m_devTools->show(WebKit::WebNavigationPolicyNewWindow); | |
193 } | |
194 | |
195 void TestShell::closeDevTools() | |
196 { | |
197 if (m_devTools) { | |
198 m_devTools->webView()->settings()->setMemoryInfoEnabled(false); | |
199 m_drtDevToolsAgent->reset(); | |
200 m_drtDevToolsClient.clear(); | |
201 m_devToolsTestInterfaces->setDelegate(0); | |
202 m_devToolsTestInterfaces->setWebView(0, 0); | |
203 closeWindow(m_devTools); | |
204 m_devTools = 0; | |
205 } | |
206 } | |
207 | |
208 void TestShell::resetWebSettings(WebView& webView) | |
209 { | |
210 m_prefs.reset(); | |
211 m_prefs.acceleratedCompositingEnabled = true; | |
212 m_prefs.acceleratedCompositingForVideoEnabled = m_acceleratedCompositingForV
ideoEnabled; | |
213 m_prefs.acceleratedCompositingForFixedPositionEnabled = m_acceleratedComposi
tingForFixedPositionEnabled; | |
214 m_prefs.acceleratedCompositingForOverflowScrollEnabled = m_acceleratedCompos
itingForOverflowScrollEnabled; | |
215 m_prefs.acceleratedCompositingForTransitionEnabled = m_acceleratedCompositin
gForTransitionEnabled; | |
216 m_prefs.forceCompositingMode = m_forceCompositingMode; | |
217 m_prefs.accelerated2dCanvasEnabled = m_accelerated2dCanvasEnabled; | |
218 m_prefs.perTilePaintingEnabled = m_perTilePaintingEnabled; | |
219 m_prefs.deferredImageDecodingEnabled = m_deferredImageDecodingEnabled; | |
220 m_prefs.threadedHTMLParser = m_threadedHTMLParser; | |
221 m_prefs.applyTo(&webView); | |
222 } | |
223 | |
224 void TestShell::runFileTest(const TestParams& params, bool shouldDumpPixels) | |
225 { | |
226 ASSERT(params.testUrl.isValid()); | |
227 m_dumpPixelsForCurrentTest = shouldDumpPixels; | |
228 m_testIsPreparing = true; | |
229 m_testInterfaces->setTestIsRunning(true); | |
230 m_params = params; | |
231 string testUrl = m_params.testUrl.spec(); | |
232 m_testInterfaces->configureForTestWithURL(m_params.testUrl, shouldDumpPixels
); | |
233 | |
234 if (testUrl.find("compositing/") != string::npos || testUrl.find("compositin
g\\") != string::npos) { | |
235 if (!m_softwareCompositingEnabled) | |
236 m_prefs.accelerated2dCanvasEnabled = true; | |
237 m_prefs.acceleratedCompositingForVideoEnabled = true; | |
238 m_prefs.mockScrollbarsEnabled = true; | |
239 m_prefs.applyTo(m_webView); | |
240 } | |
241 | |
242 if (m_dumpWhenFinished) | |
243 m_printer.handleTestHeader(testUrl.c_str()); | |
244 loadURL(m_params.testUrl); | |
245 | |
246 if (m_devTools) | |
247 this->setFocus(m_devTools->webView(), true); | |
248 | |
249 m_testIsPreparing = false; | |
250 waitTestFinished(); | |
251 } | |
252 | |
253 static inline bool isSVGTestURL(const WebURL& url) | |
254 { | |
255 return url.isValid() && string(url.spec()).find("W3C-SVG-1.1") != string::np
os; | |
256 } | |
257 | |
258 void TestShell::resizeWindowForTest(WebViewHost* window, const WebURL& url) | |
259 { | |
260 int width, height; | |
261 if (isSVGTestURL(url)) { | |
262 width = SVGTestWindowWidth; | |
263 height = SVGTestWindowHeight; | |
264 } else { | |
265 width = testWindowWidth; | |
266 height = testWindowHeight; | |
267 } | |
268 window->setWindowRect(WebRect(WebViewHost::screenUnavailableBorder, WebViewH
ost::screenUnavailableBorder, width + virtualWindowBorder * 2, height + virtualW
indowBorder * 2)); | |
269 } | |
270 | |
271 void TestShell::resetTestController() | |
272 { | |
273 resetWebSettings(*webView()); | |
274 m_testInterfaces->resetAll(); | |
275 m_devToolsTestInterfaces->resetAll(); | |
276 m_webViewHost->reset(); | |
277 m_drtDevToolsAgent->reset(); | |
278 if (m_drtDevToolsClient) | |
279 m_drtDevToolsClient->reset(); | |
280 webView()->setPageScaleFactor(1, WebPoint(0, 0)); | |
281 webView()->enableFixedLayoutMode(false); | |
282 webView()->setFixedLayoutSize(WebSize(0, 0)); | |
283 webView()->mainFrame()->clearOpener(); | |
284 WebTestingSupport::resetInternalsObject(webView()->mainFrame()); | |
285 } | |
286 | |
287 void TestShell::loadURL(const WebURL& url) | |
288 { | |
289 m_webViewHost->loadURLForFrame(url, string()); | |
290 } | |
291 | |
292 void TestShell::reload() | |
293 { | |
294 m_webViewHost->navigationController()->reload(); | |
295 } | |
296 | |
297 void TestShell::goToOffset(int offset) | |
298 { | |
299 m_webViewHost->navigationController()->goToOffset(offset); | |
300 } | |
301 | |
302 int TestShell::navigationEntryCount() const | |
303 { | |
304 return m_webViewHost->navigationController()->entryCount(); | |
305 } | |
306 | |
307 void TestShell::callJSGC() | |
308 { | |
309 m_webView->mainFrame()->collectGarbage(); | |
310 } | |
311 | |
312 void TestShell::setFocus(WebWidget* widget, bool enable) | |
313 { | |
314 // Simulate the effects of InteractiveSetFocus(), which includes calling | |
315 // both setFocus() and setIsActive(). | |
316 if (enable) { | |
317 if (m_focusedWidget != widget) { | |
318 if (m_focusedWidget) | |
319 m_focusedWidget->setFocus(false); | |
320 webView()->setIsActive(enable); | |
321 widget->setFocus(enable); | |
322 m_focusedWidget = widget; | |
323 } | |
324 } else { | |
325 if (m_focusedWidget == widget) { | |
326 widget->setFocus(enable); | |
327 webView()->setIsActive(enable); | |
328 m_focusedWidget = 0; | |
329 } | |
330 } | |
331 } | |
332 | |
333 void TestShell::testFinished(WebViewHost* host) | |
334 { | |
335 if (host == m_devTools) | |
336 return; | |
337 | |
338 if (!m_testIsPending) | |
339 return; | |
340 m_testIsPending = false; | |
341 m_testInterfaces->setTestIsRunning(false); | |
342 if (m_dumpWhenFinished) | |
343 dump(); | |
344 webkit_support::QuitMessageLoop(); | |
345 } | |
346 | |
347 void TestShell::testTimedOut() | |
348 { | |
349 m_printer.handleTimedOut(); | |
350 testFinished(webViewHost()); | |
351 } | |
352 | |
353 void TestShell::dump() | |
354 { | |
355 // Dump the requested representation. | |
356 WebFrame* frame = m_webView->mainFrame(); | |
357 if (!frame) | |
358 return; | |
359 bool shouldDumpAsAudio = m_testInterfaces->testRunner()->shouldDumpAsAudio()
; | |
360 bool shouldGeneratePixelResults = m_testInterfaces->testRunner()->shouldGene
ratePixelResults(); | |
361 bool dumpedAnything = false; | |
362 | |
363 if (shouldDumpAsAudio) { | |
364 const WebKit::WebArrayBufferView* webArrayBufferView = m_testInterfaces-
>testRunner()->audioData(); | |
365 m_printer.handleAudio(webArrayBufferView->baseAddress(), webArrayBufferV
iew->byteLength()); | |
366 m_printer.handleAudioFooter(); | |
367 m_printer.handleTestFooter(true); | |
368 | |
369 fflush(stdout); | |
370 fflush(stderr); | |
371 return; | |
372 } | |
373 | |
374 if (m_params.dumpTree) { | |
375 dumpedAnything = true; | |
376 m_printer.handleTextHeader(); | |
377 string dataUtf8 = m_webViewHost->proxy()->captureTree(m_params.debugRend
erTree); | |
378 if (fwrite(dataUtf8.c_str(), 1, dataUtf8.size(), stdout) != dataUtf8.siz
e()) | |
379 FATAL("Short write to stdout, disk full?\n"); | |
380 } | |
381 if (dumpedAnything && m_params.printSeparators) | |
382 m_printer.handleTextFooter(); | |
383 | |
384 if (m_dumpPixelsForCurrentTest && shouldGeneratePixelResults) { | |
385 // Image output: we write the image data to the file given on the | |
386 // command line (for the dump pixels argument), and the MD5 sum to | |
387 // stdout. | |
388 dumpedAnything = true; | |
389 dumpImage(m_webViewHost->proxy()->capturePixels()); | |
390 } | |
391 m_printer.handleTestFooter(dumpedAnything); | |
392 fflush(stdout); | |
393 fflush(stderr); | |
394 } | |
395 | |
396 void TestShell::dumpImage(SkCanvas* canvas) const | |
397 { | |
398 // Fix the alpha. The expected PNGs on Mac have an alpha channel, so we want | |
399 // to keep it. On Windows, the alpha channel is wrong since text/form contro
l | |
400 // drawing may have erased it in a few places. So on Windows we force it to | |
401 // opaque and also don't write the alpha channel for the reference. Linux | |
402 // doesn't have the wrong alpha like Windows, but we match Windows. | |
403 #if OS(DARWIN) | |
404 bool discardTransparency = false; | |
405 #else | |
406 bool discardTransparency = true; | |
407 makeCanvasOpaque(canvas); | |
408 #endif | |
409 | |
410 const SkBitmap& sourceBitmap = canvas->getTopDevice()->accessBitmap(false); | |
411 SkAutoLockPixels sourceBitmapLock(sourceBitmap); | |
412 | |
413 // Compute MD5 sum. | |
414 MD5 digester; | |
415 Vector<uint8_t, 16> digestValue; | |
416 #if OS(ANDROID) | |
417 // On Android, pixel layout is RGBA (see third_party/skia/include/core/SkCol
orPriv.h); | |
418 // however, other Chrome platforms use BGRA (see skia/config/SkUserConfig.h)
. | |
419 // To match the checksum of other Chrome platforms, we need to reorder the l
ayout of pixels. | |
420 // NOTE: The following code assumes we use SkBitmap::kARGB_8888_Config, | |
421 // which has been checked in device.makeOpaque() (see above). | |
422 const uint8_t* rawPixels = reinterpret_cast<const uint8_t*>(sourceBitmap.get
Pixels()); | |
423 size_t bitmapSize = sourceBitmap.getSize(); | |
424 OwnArrayPtr<uint8_t> reorderedPixels = adoptArrayPtr(new uint8_t[bitmapSize]
); | |
425 for (size_t i = 0; i < bitmapSize; i += 4) { | |
426 reorderedPixels[i] = rawPixels[i + 2]; // R | |
427 reorderedPixels[i + 1] = rawPixels[i + 1]; // G | |
428 reorderedPixels[i + 2] = rawPixels[i]; // B | |
429 reorderedPixels[i + 3] = rawPixels[i + 3]; // A | |
430 } | |
431 digester.addBytes(reorderedPixels.get(), bitmapSize); | |
432 reorderedPixels.clear(); | |
433 #else | |
434 digester.addBytes(reinterpret_cast<const uint8_t*>(sourceBitmap.getPixels())
, sourceBitmap.getSize()); | |
435 #endif | |
436 digester.checksum(digestValue); | |
437 string md5hash; | |
438 md5hash.reserve(16 * 2); | |
439 for (unsigned i = 0; i < 16; ++i) { | |
440 char hex[3]; | |
441 // Use "x", not "X". The string must be lowercased. | |
442 sprintf(hex, "%02x", digestValue[i]); | |
443 md5hash.append(hex); | |
444 } | |
445 | |
446 // Only encode and dump the png if the hashes don't match. Encoding the | |
447 // image is really expensive. | |
448 if (md5hash.compare(m_params.pixelHash)) { | |
449 std::vector<unsigned char> png; | |
450 #if OS(ANDROID) | |
451 webkit_support::EncodeRGBAPNGWithChecksum(reinterpret_cast<const unsigne
d char*>(sourceBitmap.getPixels()), sourceBitmap.width(), | |
452 sourceBitmap.height(), static_cast<int>(sourceBitmap.rowBytes()), di
scardTransparency, md5hash, &png); | |
453 #else | |
454 webkit_support::EncodeBGRAPNGWithChecksum(reinterpret_cast<const unsigne
d char*>(sourceBitmap.getPixels()), sourceBitmap.width(), | |
455 sourceBitmap.height(), static_cast<int>(sourceBitmap.rowBytes()), di
scardTransparency, md5hash, &png); | |
456 #endif | |
457 | |
458 m_printer.handleImage(md5hash.c_str(), m_params.pixelHash.c_str(), &png[
0], png.size()); | |
459 } else | |
460 m_printer.handleImage(md5hash.c_str(), m_params.pixelHash.c_str(), 0, 0)
; | |
461 } | |
462 | |
463 void TestShell::bindJSObjectsToWindow(WebFrame* frame) | |
464 { | |
465 WebTestingSupport::injectInternalsObject(frame); | |
466 if (m_devTools && m_devTools->webView() == frame->view()) | |
467 m_devToolsTestInterfaces->bindTo(frame); | |
468 else | |
469 m_testInterfaces->bindTo(frame); | |
470 } | |
471 | |
472 WebViewHost* TestShell::createNewWindow(const WebKit::WebURL& url) | |
473 { | |
474 return createNewWindow(url, 0, m_testInterfaces.get()); | |
475 } | |
476 | |
477 WebViewHost* TestShell::createNewWindow(const WebKit::WebURL& url, DRTDevToolsAg
ent* devToolsAgent, WebTestInterfaces *testInterfaces) | |
478 { | |
479 WebTestProxy<WebViewHost, TestShell*>* host = new WebTestProxy<WebViewHost,
TestShell*>(this); | |
480 host->setInterfaces(testInterfaces); | |
481 if (m_webViewHost) | |
482 host->setDelegate(m_webViewHost.get()); | |
483 else | |
484 host->setDelegate(host); | |
485 host->setProxy(host); | |
486 WebView* view = WebView::create(host); | |
487 view->setPermissionClient(testInterfaces->testRunner()->webPermissions()); | |
488 view->setDevToolsAgentClient(devToolsAgent); | |
489 host->setWebWidget(view); | |
490 m_prefs.applyTo(view); | |
491 view->initializeMainFrame(host); | |
492 m_windowList.append(host); | |
493 host->loadURLForFrame(url, string()); | |
494 return host; | |
495 } | |
496 | |
497 void TestShell::closeWindow(WebViewHost* window) | |
498 { | |
499 size_t i = m_windowList.find(window); | |
500 if (i == notFound) { | |
501 ASSERT_NOT_REACHED(); | |
502 return; | |
503 } | |
504 m_windowList.remove(i); | |
505 WebWidget* focusedWidget = m_focusedWidget; | |
506 if (window->webWidget() == m_focusedWidget) | |
507 focusedWidget = 0; | |
508 | |
509 window->shutdown(); | |
510 delete window; | |
511 // We set the focused widget after deleting the web view host because it | |
512 // can change the focus. | |
513 m_focusedWidget = focusedWidget; | |
514 if (m_focusedWidget) { | |
515 webView()->setIsActive(true); | |
516 m_focusedWidget->setFocus(true); | |
517 } | |
518 } | |
519 | |
520 void TestShell::closeRemainingWindows() | |
521 { | |
522 // Just close devTools window manually because we have custom deinitializati
on code for it. | |
523 closeDevTools(); | |
524 | |
525 // Iterate through the window list and close everything except the main | |
526 // window. We don't want to delete elements as we're iterating, so we copy | |
527 // to a temp vector first. | |
528 Vector<WebViewHost*> windowsToDelete; | |
529 for (unsigned i = 0; i < m_windowList.size(); ++i) { | |
530 if (m_windowList[i] != webViewHost()) | |
531 windowsToDelete.append(m_windowList[i]); | |
532 } | |
533 ASSERT(windowsToDelete.size() + 1 == m_windowList.size()); | |
534 for (unsigned i = 0; i < windowsToDelete.size(); ++i) | |
535 closeWindow(windowsToDelete[i]); | |
536 ASSERT(m_windowList.size() == 1); | |
537 } | |
538 | |
539 int TestShell::windowCount() | |
540 { | |
541 return m_windowList.size(); | |
542 } | |
543 | |
544 void TestShell::captureHistoryForWindow(size_t windowIndex, WebVector<WebHistory
Item>* history, size_t* currentEntryIndex) | |
545 { | |
546 ASSERT(history); | |
547 ASSERT(currentEntryIndex); | |
548 if (windowIndex >= m_windowList.size()) | |
549 return; | |
550 TestNavigationController& navigationController = *m_windowList[windowIndex]-
>navigationController(); | |
551 size_t entryCount = navigationController.entryCount(); | |
552 WebVector<WebHistoryItem> result(entryCount); | |
553 *currentEntryIndex = navigationController.lastCommittedEntryIndex(); | |
554 for (size_t index = 0; index < entryCount; ++index) { | |
555 WebHistoryItem historyItem = navigationController.entryAtIndex(index)->c
ontentState(); | |
556 if (historyItem.isNull()) { | |
557 historyItem.initialize(); | |
558 historyItem.setURLString(navigationController.entryAtIndex(index)->U
RL().spec().utf16()); | |
559 } | |
560 result[index] = historyItem; | |
561 } | |
562 history->swap(result); | |
563 } | |
OLD | NEW |