1 /*
2 * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple 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
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14 * its contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include "config.h"
30 #include "LayoutTestController.h"
31
32 #include "DumpRenderTree.h"
33 #include "EditingDelegate.h"
34 #include "PolicyDelegate.h"
35 #include "WorkQueue.h"
36 #include "WorkQueueItem.h"
37 #include <CoreFoundation/CoreFoundation.h>
38 #include <JavaScriptCore/Assertions.h>
39 #include <JavaScriptCore/JSRetainPtr.h>
40 #include <JavaScriptCore/JSStringRefBSTR.h>
41 #include <JavaScriptCore/JavaScriptCore.h>
42 #include <WebCore/COMPtr.h>
43 #include <WebKit/WebKit.h>
44 #include <WebKit/WebKitCOMAPI.h>
45 #include <comutil.h>
46 #include <shlwapi.h>
47 #include <shlguid.h>
48 #include <shobjidl.h>
49 #include <string>
50 #include <wtf/Platform.h>
51 #include <wtf/RetainPtr.h>
52 #include <wtf/Vector.h>
53
54 using std::string;
55 using std::wstring;
56
57 static bool resolveCygwinPath(const wstring& cygwinPath, wstring& windowsPath);
58
~LayoutTestController()59 LayoutTestController::~LayoutTestController()
60 {
61 COMPtr<IWebView> webView;
62 if (FAILED(frame->webView(&webView)))
63 return;
64
65 // reset webview-related states back to default values in preparation for next test
66
67 COMPtr<IWebViewPrivate> viewPrivate;
68 if (SUCCEEDED(webView->QueryInterface(&viewPrivate)))
69 viewPrivate->setTabKeyCyclesThroughElements(TRUE);
70
71 COMPtr<IWebViewEditing> viewEditing;
72 if (FAILED(webView->QueryInterface(&viewEditing)))
73 return;
74 COMPtr<IWebEditingDelegate> delegate;
75 if (FAILED(viewEditing->editingDelegate(&delegate)))
76 return;
77 COMPtr<EditingDelegate> editingDelegate(Query, viewEditing.get());
78 if (editingDelegate)
79 editingDelegate->setAcceptsEditing(TRUE);
80 }
81
addDisallowedURL(JSStringRef url)82 void LayoutTestController::addDisallowedURL(JSStringRef url)
83 {
84 // FIXME: Implement!
85 }
86
clearBackForwardList()87 void LayoutTestController::clearBackForwardList()
88 {
89 COMPtr<IWebView> webView;
90 if (FAILED(frame->webView(&webView)))
91 return;
92
93 COMPtr<IWebBackForwardList> backForwardList;
94 if (FAILED(webView->backForwardList(&backForwardList)))
95 return;
96
97 COMPtr<IWebHistoryItem> item;
98 if (FAILED(backForwardList->currentItem(&item)))
99 return;
100
101 // We clear the history by setting the back/forward list's capacity to 0
102 // then restoring it back and adding back the current item.
103 int capacity;
104 if (FAILED(backForwardList->capacity(&capacity)))
105 return;
106
107 backForwardList->setCapacity(0);
108 backForwardList->setCapacity(capacity);
109 backForwardList->addItem(item.get());
110 backForwardList->goToItem(item.get());
111 }
112
callShouldCloseOnWebView()113 bool LayoutTestController::callShouldCloseOnWebView()
114 {
115 COMPtr<IWebView> webView;
116 if (FAILED(frame->webView(&webView)))
117 return false;
118
119 COMPtr<IWebViewPrivate> viewPrivate;
120 if (FAILED(webView->QueryInterface(&viewPrivate)))
121 return false;
122
123 BOOL result;
124 viewPrivate->shouldClose(&result);
125 return result;
126 }
127
copyDecodedHostName(JSStringRef name)128 JSStringRef LayoutTestController::copyDecodedHostName(JSStringRef name)
129 {
130 // FIXME: Implement!
131 return 0;
132 }
133
copyEncodedHostName(JSStringRef name)134 JSStringRef LayoutTestController::copyEncodedHostName(JSStringRef name)
135 {
136 // FIXME: Implement!
137 return 0;
138 }
139
disableImageLoading()140 void LayoutTestController::disableImageLoading()
141 {
142 COMPtr<IWebView> webView;
143 if (FAILED(frame->webView(&webView)))
144 return;
145
146 COMPtr<IWebPreferences> preferences;
147 if (FAILED(webView->preferences(&preferences)))
148 return;
149
150 preferences->setLoadsImagesAutomatically(FALSE);
151 }
152
dispatchPendingLoadRequests()153 void LayoutTestController::dispatchPendingLoadRequests()
154 {
155 // FIXME: Implement for testing fix for 6727495
156 }
157
display()158 void LayoutTestController::display()
159 {
160 displayWebView();
161 }
162
keepWebHistory()163 void LayoutTestController::keepWebHistory()
164 {
165 COMPtr<IWebHistory> history;
166 if (FAILED(WebKitCreateInstance(CLSID_WebHistory, 0, __uuidof(history), reinterpret_cast<void**>(&history))))
167 return;
168
169 COMPtr<IWebHistory> sharedHistory;
170 if (FAILED(WebKitCreateInstance(CLSID_WebHistory, 0, __uuidof(sharedHistory), reinterpret_cast<void**>(&sharedHistory))))
171 return;
172
173 history->setOptionalSharedHistory(sharedHistory.get());
174 }
175
computedStyleIncludingVisitedInfo(JSContextRef context,JSValueRef value)176 JSValueRef LayoutTestController::computedStyleIncludingVisitedInfo(JSContextRef context, JSValueRef value)
177 {
178 // FIXME: Implement this.
179 return JSValueMakeUndefined(context);
180 }
181
nodesFromRect(JSContextRef context,JSValueRef value,int x,int y,unsigned top,unsigned right,unsigned bottom,unsigned left,bool ignoreClipping)182 JSValueRef LayoutTestController::nodesFromRect(JSContextRef context, JSValueRef value, int x, int y, unsigned top, unsigned right, unsigned bottom, unsigned left, bool ignoreClipping)
183 {
184 // FIXME: Implement this.
185 return JSValueMakeUndefined(context);
186 }
187
layerTreeAsText() const188 JSRetainPtr<JSStringRef> LayoutTestController::layerTreeAsText() const
189 {
190 COMPtr<IWebFramePrivate> framePrivate(Query, frame);
191 if (!framePrivate)
192 return false;
193
194 BSTR textBSTR = 0;
195 HRESULT hr = framePrivate->layerTreeAsText(&textBSTR);
196
197 wstring text(textBSTR, SysStringLen(textBSTR));
198 SysFreeString(textBSTR);
199 JSRetainPtr<JSStringRef> textValueJS(Adopt, JSStringCreateWithCharacters(text.data(), text.length()));
200 return textValueJS;
201 }
202
markerTextForListItem(JSContextRef context,JSValueRef nodeObject) const203 JSRetainPtr<JSStringRef> LayoutTestController::markerTextForListItem(JSContextRef context, JSValueRef nodeObject) const
204 {
205 COMPtr<IWebView> webView;
206 if (FAILED(frame->webView(&webView)))
207 return 0;
208
209 COMPtr<IWebViewPrivate> webViewPrivate(Query, webView);
210 if (!webViewPrivate)
211 return 0;
212
213 COMPtr<IDOMElement> element;
214 if (FAILED(webViewPrivate->elementFromJS(context, nodeObject, &element)))
215 return 0;
216
217 COMPtr<IDOMElementPrivate> elementPrivate(Query, element);
218 if (!elementPrivate)
219 return 0;
220
221 BSTR textBSTR = 0;
222 if (FAILED(elementPrivate->markerTextForListItem(&textBSTR)))
223 return 0;
224
225 JSRetainPtr<JSStringRef> markerText(Adopt, JSStringCreateWithBSTR(textBSTR));
226 SysFreeString(textBSTR);
227 return markerText;
228 }
229
waitForPolicyDelegate()230 void LayoutTestController::waitForPolicyDelegate()
231 {
232 COMPtr<IWebView> webView;
233 if (FAILED(frame->webView(&webView)))
234 return;
235
236 setWaitToDump(true);
237 policyDelegate->setControllerToNotifyDone(this);
238 webView->setPolicyDelegate(policyDelegate);
239 }
240
webHistoryItemCount()241 size_t LayoutTestController::webHistoryItemCount()
242 {
243 COMPtr<IWebHistory> history;
244 if (FAILED(WebKitCreateInstance(CLSID_WebHistory, 0, __uuidof(history), reinterpret_cast<void**>(&history))))
245 return 0;
246
247 COMPtr<IWebHistory> sharedHistory;
248 if (FAILED(history->optionalSharedHistory(&sharedHistory)) || !sharedHistory)
249 return 0;
250
251 COMPtr<IWebHistoryPrivate> sharedHistoryPrivate;
252 if (FAILED(sharedHistory->QueryInterface(&sharedHistoryPrivate)))
253 return 0;
254
255 int count;
256 if (FAILED(sharedHistoryPrivate->allItems(&count, 0)))
257 return 0;
258
259 return count;
260 }
261
workerThreadCount() const262 unsigned LayoutTestController::workerThreadCount() const
263 {
264 COMPtr<IWebWorkersPrivate> workers;
265 if (FAILED(WebKitCreateInstance(CLSID_WebWorkersPrivate, 0, __uuidof(workers), reinterpret_cast<void**>(&workers))))
266 return 0;
267 unsigned count;
268 if (FAILED(workers->workerThreadCount(&count)))
269 return 0;
270 return count;
271 }
272
notifyDone()273 void LayoutTestController::notifyDone()
274 {
275 // Same as on mac. This can be shared.
276 if (m_waitToDump && !topLoadingFrame && !WorkQueue::shared()->count())
277 dump();
278 m_waitToDump = false;
279 }
280
pathToLocalResource(JSContextRef context,JSStringRef url)281 JSStringRef LayoutTestController::pathToLocalResource(JSContextRef context, JSStringRef url)
282 {
283 wstring input(JSStringGetCharactersPtr(url), JSStringGetLength(url));
284
285 wstring localPath;
286 if (!resolveCygwinPath(input, localPath)) {
287 printf("ERROR: Failed to resolve Cygwin path %S\n", input.c_str());
288 return 0;
289 }
290
291 return JSStringCreateWithCharacters(localPath.c_str(), localPath.length());
292 }
293
jsStringRefToWString(JSStringRef jsStr)294 static wstring jsStringRefToWString(JSStringRef jsStr)
295 {
296 size_t length = JSStringGetLength(jsStr);
297 Vector<WCHAR> buffer(length + 1);
298 memcpy(buffer.data(), JSStringGetCharactersPtr(jsStr), length * sizeof(WCHAR));
299 buffer[length] = '\0';
300
301 return buffer.data();
302 }
303
queueLoad(JSStringRef url,JSStringRef target)304 void LayoutTestController::queueLoad(JSStringRef url, JSStringRef target)
305 {
306 COMPtr<IWebDataSource> dataSource;
307 if (FAILED(frame->dataSource(&dataSource)))
308 return;
309
310 COMPtr<IWebURLResponse> response;
311 if (FAILED(dataSource->response(&response)) || !response)
312 return;
313
314 BSTR responseURLBSTR;
315 if (FAILED(response->URL(&responseURLBSTR)))
316 return;
317 wstring responseURL(responseURLBSTR, SysStringLen(responseURLBSTR));
318 SysFreeString(responseURLBSTR);
319
320 // FIXME: We should do real relative URL resolution here.
321 int lastSlash = responseURL.rfind('/');
322 if (lastSlash != -1)
323 responseURL = responseURL.substr(0, lastSlash);
324
325 wstring wURL = jsStringRefToWString(url);
326 wstring wAbsoluteURL = responseURL + TEXT("/") + wURL;
327 JSRetainPtr<JSStringRef> jsAbsoluteURL(Adopt, JSStringCreateWithCharacters(wAbsoluteURL.data(), wAbsoluteURL.length()));
328
329 WorkQueue::shared()->queue(new LoadItem(jsAbsoluteURL.get(), target));
330 }
331
setAcceptsEditing(bool acceptsEditing)332 void LayoutTestController::setAcceptsEditing(bool acceptsEditing)
333 {
334 COMPtr<IWebView> webView;
335 if (FAILED(frame->webView(&webView)))
336 return;
337
338 COMPtr<IWebViewEditing> viewEditing;
339 if (FAILED(webView->QueryInterface(&viewEditing)))
340 return;
341
342 COMPtr<IWebEditingDelegate> delegate;
343 if (FAILED(viewEditing->editingDelegate(&delegate)))
344 return;
345
346 EditingDelegate* editingDelegate = (EditingDelegate*)(IWebEditingDelegate*)delegate.get();
347 editingDelegate->setAcceptsEditing(acceptsEditing);
348 }
349
setAlwaysAcceptCookies(bool alwaysAcceptCookies)350 void LayoutTestController::setAlwaysAcceptCookies(bool alwaysAcceptCookies)
351 {
352 if (alwaysAcceptCookies == m_alwaysAcceptCookies)
353 return;
354
355 if (!::setAlwaysAcceptCookies(alwaysAcceptCookies))
356 return;
357 m_alwaysAcceptCookies = alwaysAcceptCookies;
358 }
359
setAuthorAndUserStylesEnabled(bool flag)360 void LayoutTestController::setAuthorAndUserStylesEnabled(bool flag)
361 {
362 COMPtr<IWebView> webView;
363 if (FAILED(frame->webView(&webView)))
364 return;
365
366 COMPtr<IWebPreferences> preferences;
367 if (FAILED(webView->preferences(&preferences)))
368 return;
369
370 COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences);
371 if (!prefsPrivate)
372 return;
373
374 prefsPrivate->setAuthorAndUserStylesEnabled(flag);
375 }
376
setAutofilled(JSContextRef context,JSValueRef nodeObject,bool autofilled)377 void LayoutTestController::setAutofilled(JSContextRef context, JSValueRef nodeObject, bool autofilled)
378 {
379 COMPtr<IWebView> webView;
380 if (FAILED(frame->webView(&webView)))
381 return;
382
383 COMPtr<IWebViewPrivate> webViewPrivate(Query, webView);
384 if (!webViewPrivate)
385 return;
386
387 COMPtr<IDOMElement> element;
388 if (FAILED(webViewPrivate->elementFromJS(context, nodeObject, &element)))
389 return;
390
391 COMPtr<IFormsAutoFillTransition> autofillElement(Query, element);
392 if (!autofillElement)
393 return;
394
395 autofillElement->setAutofilled(autofilled);
396 }
397
setCustomPolicyDelegate(bool setDelegate,bool permissive)398 void LayoutTestController::setCustomPolicyDelegate(bool setDelegate, bool permissive)
399 {
400 COMPtr<IWebView> webView;
401 if (FAILED(frame->webView(&webView)))
402 return;
403
404 if (setDelegate) {
405 policyDelegate->setPermissive(permissive);
406 webView->setPolicyDelegate(policyDelegate);
407 } else
408 webView->setPolicyDelegate(0);
409 }
410
setMockDeviceOrientation(bool canProvideAlpha,double alpha,bool canProvideBeta,double beta,bool canProvideGamma,double gamma)411 void LayoutTestController::setMockDeviceOrientation(bool canProvideAlpha, double alpha, bool canProvideBeta, double beta, bool canProvideGamma, double gamma)
412 {
413 // FIXME: Implement for DeviceOrientation layout tests.
414 // See https://bugs.webkit.org/show_bug.cgi?id=30335.
415 }
416
setMockGeolocationPosition(double latitude,double longitude,double accuracy)417 void LayoutTestController::setMockGeolocationPosition(double latitude, double longitude, double accuracy)
418 {
419 // FIXME: Implement for Geolocation layout tests.
420 // See https://bugs.webkit.org/show_bug.cgi?id=28264.
421 }
422
setMockGeolocationError(int code,JSStringRef message)423 void LayoutTestController::setMockGeolocationError(int code, JSStringRef message)
424 {
425 // FIXME: Implement for Geolocation layout tests.
426 // See https://bugs.webkit.org/show_bug.cgi?id=28264.
427 }
428
setGeolocationPermission(bool allow)429 void LayoutTestController::setGeolocationPermission(bool allow)
430 {
431 // FIXME: Implement for Geolocation layout tests.
432 setGeolocationPermissionCommon(allow);
433 }
434
numberOfPendingGeolocationPermissionRequests()435 int LayoutTestController::numberOfPendingGeolocationPermissionRequests()
436 {
437 // FIXME: Implement for Geolocation layout tests.
438 return -1;
439 }
440
addMockSpeechInputResult(JSStringRef result,double confidence,JSStringRef language)441 void LayoutTestController::addMockSpeechInputResult(JSStringRef result, double confidence, JSStringRef language)
442 {
443 // FIXME: Implement for speech input layout tests.
444 // See https://bugs.webkit.org/show_bug.cgi?id=39485.
445 }
446
setIconDatabaseEnabled(bool iconDatabaseEnabled)447 void LayoutTestController::setIconDatabaseEnabled(bool iconDatabaseEnabled)
448 {
449 // See also <rdar://problem/6480108>
450 COMPtr<IWebIconDatabase> iconDatabase;
451 COMPtr<IWebIconDatabase> tmpIconDatabase;
452 if (FAILED(WebKitCreateInstance(CLSID_WebIconDatabase, 0, IID_IWebIconDatabase, (void**)&tmpIconDatabase)))
453 return;
454 if (FAILED(tmpIconDatabase->sharedIconDatabase(&iconDatabase)))
455 return;
456
457 iconDatabase->setEnabled(iconDatabaseEnabled);
458 }
459
setMainFrameIsFirstResponder(bool flag)460 void LayoutTestController::setMainFrameIsFirstResponder(bool flag)
461 {
462 // FIXME: Implement!
463 }
464
setPrivateBrowsingEnabled(bool privateBrowsingEnabled)465 void LayoutTestController::setPrivateBrowsingEnabled(bool privateBrowsingEnabled)
466 {
467 COMPtr<IWebView> webView;
468 if (FAILED(frame->webView(&webView)))
469 return;
470
471 COMPtr<IWebPreferences> preferences;
472 if (FAILED(webView->preferences(&preferences)))
473 return;
474
475 preferences->setPrivateBrowsingEnabled(privateBrowsingEnabled);
476 }
477
setXSSAuditorEnabled(bool enabled)478 void LayoutTestController::setXSSAuditorEnabled(bool enabled)
479 {
480 COMPtr<IWebView> webView;
481 if (FAILED(frame->webView(&webView)))
482 return;
483
484 COMPtr<IWebPreferences> preferences;
485 if (FAILED(webView->preferences(&preferences)))
486 return;
487
488 COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences);
489 if (!prefsPrivate)
490 return;
491
492 prefsPrivate->setXSSAuditorEnabled(enabled);
493 }
494
setFrameFlatteningEnabled(bool enabled)495 void LayoutTestController::setFrameFlatteningEnabled(bool enabled)
496 {
497 COMPtr<IWebView> webView;
498 if (FAILED(frame->webView(&webView)))
499 return;
500
501 COMPtr<IWebPreferences> preferences;
502 if (FAILED(webView->preferences(&preferences)))
503 return;
504
505 COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences);
506 if (!prefsPrivate)
507 return;
508
509 prefsPrivate->setFrameFlatteningEnabled(enabled);
510 }
511
setSpatialNavigationEnabled(bool enabled)512 void LayoutTestController::setSpatialNavigationEnabled(bool enabled)
513 {
514 // FIXME: Implement for SpatialNavigation layout tests.
515 }
516
setAllowUniversalAccessFromFileURLs(bool enabled)517 void LayoutTestController::setAllowUniversalAccessFromFileURLs(bool enabled)
518 {
519 COMPtr<IWebView> webView;
520 if (FAILED(frame->webView(&webView)))
521 return;
522
523 COMPtr<IWebPreferences> preferences;
524 if (FAILED(webView->preferences(&preferences)))
525 return;
526
527 COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences);
528 if (!prefsPrivate)
529 return;
530
531 prefsPrivate->setAllowUniversalAccessFromFileURLs(enabled);
532 }
533
setAllowFileAccessFromFileURLs(bool enabled)534 void LayoutTestController::setAllowFileAccessFromFileURLs(bool enabled)
535 {
536 COMPtr<IWebView> webView;
537 if (FAILED(frame->webView(&webView)))
538 return;
539
540 COMPtr<IWebPreferences> preferences;
541 if (FAILED(webView->preferences(&preferences)))
542 return;
543
544 COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences);
545 if (!prefsPrivate)
546 return;
547
548 prefsPrivate->setAllowFileAccessFromFileURLs(enabled);
549 }
550
setPopupBlockingEnabled(bool enabled)551 void LayoutTestController::setPopupBlockingEnabled(bool enabled)
552 {
553 COMPtr<IWebView> webView;
554 if (FAILED(frame->webView(&webView)))
555 return;
556
557 COMPtr<IWebPreferences> preferences;
558 if (FAILED(webView->preferences(&preferences)))
559 return;
560
561 preferences->setJavaScriptCanOpenWindowsAutomatically(!enabled);
562 }
563
setPluginsEnabled(bool flag)564 void LayoutTestController::setPluginsEnabled(bool flag)
565 {
566 // FIXME: Implement
567 }
568
setJavaScriptCanAccessClipboard(bool enabled)569 void LayoutTestController::setJavaScriptCanAccessClipboard(bool enabled)
570 {
571 COMPtr<IWebView> webView;
572 if (FAILED(frame->webView(&webView)))
573 return;
574
575 COMPtr<IWebPreferences> preferences;
576 if (FAILED(webView->preferences(&preferences)))
577 return;
578
579 COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences);
580 if (!prefsPrivate)
581 return;
582
583 prefsPrivate->setJavaScriptCanAccessClipboard(enabled);
584 }
585
setTabKeyCyclesThroughElements(bool shouldCycle)586 void LayoutTestController::setTabKeyCyclesThroughElements(bool shouldCycle)
587 {
588 COMPtr<IWebView> webView;
589 if (FAILED(frame->webView(&webView)))
590 return;
591
592 COMPtr<IWebViewPrivate> viewPrivate;
593 if (FAILED(webView->QueryInterface(&viewPrivate)))
594 return;
595
596 viewPrivate->setTabKeyCyclesThroughElements(shouldCycle ? TRUE : FALSE);
597 }
598
setTimelineProfilingEnabled(bool flag)599 void LayoutTestController::setTimelineProfilingEnabled(bool flag)
600 {
601 COMPtr<IWebView> webView;
602 if (FAILED(frame->webView(&webView)))
603 return;
604
605 COMPtr<IWebViewPrivate> viewPrivate;
606 if (FAILED(webView->QueryInterface(&viewPrivate)))
607 return;
608
609 COMPtr<IWebInspector> inspector;
610 if (FAILED(viewPrivate->inspector(&inspector)))
611 return;
612
613 inspector->setTimelineProfilingEnabled(flag);
614 }
615
setUseDashboardCompatibilityMode(bool flag)616 void LayoutTestController::setUseDashboardCompatibilityMode(bool flag)
617 {
618 // FIXME: Implement!
619 }
620
setUserStyleSheetEnabled(bool flag)621 void LayoutTestController::setUserStyleSheetEnabled(bool flag)
622 {
623 COMPtr<IWebView> webView;
624 if (FAILED(frame->webView(&webView)))
625 return;
626
627 COMPtr<IWebPreferences> preferences;
628 if (FAILED(webView->preferences(&preferences)))
629 return;
630
631 preferences->setUserStyleSheetEnabled(flag);
632 }
633
appendComponentToPath(wstring & path,const wstring & component)634 bool appendComponentToPath(wstring& path, const wstring& component)
635 {
636 WCHAR buffer[MAX_PATH];
637
638 if (path.size() + 1 > MAX_PATH)
639 return false;
640
641 memcpy(buffer, path.data(), path.size() * sizeof(WCHAR));
642 buffer[path.size()] = '\0';
643
644 if (!PathAppendW(buffer, component.c_str()))
645 return false;
646
647 path = wstring(buffer);
648 return true;
649 }
650
followShortcuts(wstring & path)651 static bool followShortcuts(wstring& path)
652 {
653 if (PathFileExists(path.c_str()))
654 return true;
655
656 // Do we have a shortcut?
657 wstring linkPath = path;
658 linkPath.append(TEXT(".lnk"));
659 if (!PathFileExists(linkPath.c_str()))
660 return true;
661
662 // We have a shortcut, find its target.
663 COMPtr<IShellLink> shortcut(Create, CLSID_ShellLink);
664 if (!shortcut)
665 return false;
666 COMPtr<IPersistFile> persistFile(Query, shortcut);
667 if (!shortcut)
668 return false;
669 if (FAILED(persistFile->Load(linkPath.c_str(), STGM_READ)))
670 return false;
671 if (FAILED(shortcut->Resolve(0, 0)))
672 return false;
673 WCHAR targetPath[MAX_PATH];
674 DWORD targetPathLen = _countof(targetPath);
675 if (FAILED(shortcut->GetPath(targetPath, targetPathLen, 0, 0)))
676 return false;
677 if (!PathFileExists(targetPath))
678 return false;
679 // Use the target path as the result path instead.
680 path = wstring(targetPath);
681
682 return true;
683 }
684
resolveCygwinPath(const wstring & cygwinPath,wstring & windowsPath)685 static bool resolveCygwinPath(const wstring& cygwinPath, wstring& windowsPath)
686 {
687 wstring fileProtocol = L"file://";
688 bool isFileProtocol = cygwinPath.find(fileProtocol) != string::npos;
689 if (cygwinPath[isFileProtocol ? 7 : 0] != '/') // ensure path is absolute
690 return false;
691
692 // Get the Root path.
693 WCHAR rootPath[MAX_PATH];
694 DWORD rootPathSize = _countof(rootPath);
695 DWORD keyType;
696 DWORD result = ::SHGetValueW(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Cygnus Solutions\\Cygwin\\mounts v2\\/"), TEXT("native"), &keyType, &rootPath, &rootPathSize);
697
698 if (result != ERROR_SUCCESS || keyType != REG_SZ) {
699 // Cygwin 1.7 doesn't store Cygwin's root as a mount point anymore, because mount points are now stored in /etc/fstab.
700 // However, /etc/fstab doesn't contain any information about where / is located as a Windows path, so we need to use Cygwin's
701 // new registry key that has the root.
702 result = ::SHGetValueW(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Cygwin\\setup"), TEXT("rootdir"), &keyType, &rootPath, &rootPathSize);
703 if (result != ERROR_SUCCESS || keyType != REG_SZ)
704 return false;
705 }
706
707 windowsPath = wstring(rootPath, rootPathSize);
708
709 int oldPos = isFileProtocol ? 8 : 1;
710 while (1) {
711 int newPos = cygwinPath.find('/', oldPos);
712
713 if (newPos == -1) {
714 wstring pathComponent = cygwinPath.substr(oldPos);
715
716 if (!appendComponentToPath(windowsPath, pathComponent))
717 return false;
718
719 if (!followShortcuts(windowsPath))
720 return false;
721
722 break;
723 }
724
725 wstring pathComponent = cygwinPath.substr(oldPos, newPos - oldPos);
726 if (!appendComponentToPath(windowsPath, pathComponent))
727 return false;
728
729 if (!followShortcuts(windowsPath))
730 return false;
731
732 oldPos = newPos + 1;
733 }
734
735 if (isFileProtocol)
736 windowsPath = fileProtocol + windowsPath;
737
738 return true;
739 }
740
setUserStyleSheetLocation(JSStringRef jsURL)741 void LayoutTestController::setUserStyleSheetLocation(JSStringRef jsURL)
742 {
743 COMPtr<IWebView> webView;
744 if (FAILED(frame->webView(&webView)))
745 return;
746
747 COMPtr<IWebPreferences> preferences;
748 if (FAILED(webView->preferences(&preferences)))
749 return;
750
751 RetainPtr<CFStringRef> urlString(AdoptCF, JSStringCopyCFString(0, jsURL));
752 RetainPtr<CFURLRef> url(AdoptCF, CFURLCreateWithString(0, urlString.get(), 0));
753 if (!url)
754 return;
755
756 // Now copy the file system path, POSIX style.
757 RetainPtr<CFStringRef> pathCF(AdoptCF, CFURLCopyFileSystemPath(url.get(), kCFURLPOSIXPathStyle));
758 if (!pathCF)
759 return;
760
761 wstring path = cfStringRefToWString(pathCF.get());
762
763 wstring resultPath;
764 if (!resolveCygwinPath(path, resultPath))
765 return;
766
767 // The path has been resolved, now convert it back to a CFURL.
768 int result = WideCharToMultiByte(CP_UTF8, 0, resultPath.c_str(), resultPath.size() + 1, 0, 0, 0, 0);
769 Vector<char> utf8Vector(result);
770 result = WideCharToMultiByte(CP_UTF8, 0, resultPath.c_str(), resultPath.size() + 1, utf8Vector.data(), result, 0, 0);
771 if (!result)
772 return;
773
774 url = CFURLCreateFromFileSystemRepresentation(0, (const UInt8*)utf8Vector.data(), utf8Vector.size() - 1, false);
775 if (!url)
776 return;
777
778 resultPath = cfStringRefToWString(CFURLGetString(url.get()));
779
780 BSTR resultPathBSTR = SysAllocStringLen(resultPath.data(), resultPath.size());
781 preferences->setUserStyleSheetLocation(resultPathBSTR);
782 SysFreeString(resultPathBSTR);
783 }
784
setValueForUser(JSContextRef context,JSValueRef element,JSStringRef value)785 void LayoutTestController::setValueForUser(JSContextRef context, JSValueRef element, JSStringRef value)
786 {
787 // FIXME: implement
788 }
789
setViewModeMediaFeature(JSStringRef mode)790 void LayoutTestController::setViewModeMediaFeature(JSStringRef mode)
791 {
792 // FIXME: implement
793 }
794
setPersistentUserStyleSheetLocation(JSStringRef jsURL)795 void LayoutTestController::setPersistentUserStyleSheetLocation(JSStringRef jsURL)
796 {
797 RetainPtr<CFStringRef> urlString(AdoptCF, JSStringCopyCFString(0, jsURL));
798 ::setPersistentUserStyleSheetLocation(urlString.get());
799 }
800
clearPersistentUserStyleSheet()801 void LayoutTestController::clearPersistentUserStyleSheet()
802 {
803 ::setPersistentUserStyleSheetLocation(0);
804 }
805
setWindowIsKey(bool flag)806 void LayoutTestController::setWindowIsKey(bool flag)
807 {
808 COMPtr<IWebView> webView;
809 if (FAILED(frame->webView(&webView)))
810 return;
811
812 COMPtr<IWebViewPrivate> viewPrivate;
813 if (FAILED(webView->QueryInterface(&viewPrivate)))
814 return;
815
816 HWND webViewWindow;
817 if (FAILED(viewPrivate->viewWindow((OLE_HANDLE*)&webViewWindow)))
818 return;
819
820 ::SendMessage(webViewWindow, flag ? WM_SETFOCUS : WM_KILLFOCUS, (WPARAM)::GetDesktopWindow(), 0);
821 }
822
setSmartInsertDeleteEnabled(bool flag)823 void LayoutTestController::setSmartInsertDeleteEnabled(bool flag)
824 {
825 COMPtr<IWebView> webView;
826 if (FAILED(frame->webView(&webView)))
827 return;
828
829 COMPtr<IWebViewEditing> viewEditing;
830 if (FAILED(webView->QueryInterface(&viewEditing)))
831 return;
832
833 viewEditing->setSmartInsertDeleteEnabled(flag ? TRUE : FALSE);
834 }
835
setJavaScriptProfilingEnabled(bool flag)836 void LayoutTestController::setJavaScriptProfilingEnabled(bool flag)
837 {
838 COMPtr<IWebView> webView;
839 if (FAILED(frame->webView(&webView)))
840 return;
841
842 COMPtr<IWebViewPrivate> viewPrivate;
843 if (FAILED(webView->QueryInterface(&viewPrivate)))
844 return;
845
846 COMPtr<IWebInspector> inspector;
847 if (FAILED(viewPrivate->inspector(&inspector)))
848 return;
849
850 setDeveloperExtrasEnabled(flag);
851 inspector->setJavaScriptProfilingEnabled(flag);
852 }
853
setSelectTrailingWhitespaceEnabled(bool flag)854 void LayoutTestController::setSelectTrailingWhitespaceEnabled(bool flag)
855 {
856 COMPtr<IWebView> webView;
857 if (FAILED(frame->webView(&webView)))
858 return;
859
860 COMPtr<IWebViewEditing> viewEditing;
861 if (FAILED(webView->QueryInterface(&viewEditing)))
862 return;
863
864 viewEditing->setSelectTrailingWhitespaceEnabled(flag ? TRUE : FALSE);
865 }
866
867 static const CFTimeInterval waitToDumpWatchdogInterval = 30.0;
868
waitUntilDoneWatchdogFired(HWND,UINT,UINT_PTR,DWORD)869 static void CALLBACK waitUntilDoneWatchdogFired(HWND, UINT, UINT_PTR, DWORD)
870 {
871 gLayoutTestController->waitToDumpWatchdogTimerFired();
872 }
873
setWaitToDump(bool waitUntilDone)874 void LayoutTestController::setWaitToDump(bool waitUntilDone)
875 {
876 m_waitToDump = waitUntilDone;
877 if (m_waitToDump && !waitToDumpWatchdog)
878 waitToDumpWatchdog = SetTimer(0, 0, waitToDumpWatchdogInterval * 1000, waitUntilDoneWatchdogFired);
879 }
880
windowCount()881 int LayoutTestController::windowCount()
882 {
883 return openWindows().size();
884 }
885
elementDoesAutoCompleteForElementWithId(JSStringRef id)886 bool LayoutTestController::elementDoesAutoCompleteForElementWithId(JSStringRef id)
887 {
888 COMPtr<IDOMDocument> document;
889 if (FAILED(frame->DOMDocument(&document)))
890 return false;
891
892 wstring idWstring = jsStringRefToWString(id);
893 BSTR idBSTR = SysAllocStringLen((OLECHAR*)idWstring.c_str(), idWstring.length());
894 COMPtr<IDOMElement> element;
895 HRESULT result = document->getElementById(idBSTR, &element);
896 SysFreeString(idBSTR);
897
898 if (FAILED(result))
899 return false;
900
901 COMPtr<IWebFramePrivate> framePrivate(Query, frame);
902 if (!framePrivate)
903 return false;
904
905 BOOL autoCompletes;
906 if (FAILED(framePrivate->elementDoesAutoComplete(element.get(), &autoCompletes)))
907 return false;
908
909 return autoCompletes;
910 }
911
execCommand(JSStringRef name,JSStringRef value)912 void LayoutTestController::execCommand(JSStringRef name, JSStringRef value)
913 {
914 wstring wName = jsStringRefToWString(name);
915 wstring wValue = jsStringRefToWString(value);
916
917 COMPtr<IWebView> webView;
918 if (FAILED(frame->webView(&webView)))
919 return;
920
921 COMPtr<IWebViewPrivate> viewPrivate;
922 if (FAILED(webView->QueryInterface(&viewPrivate)))
923 return;
924
925 BSTR nameBSTR = SysAllocStringLen((OLECHAR*)wName.c_str(), wName.length());
926 BSTR valueBSTR = SysAllocStringLen((OLECHAR*)wValue.c_str(), wValue.length());
927 viewPrivate->executeCoreCommandByName(nameBSTR, valueBSTR);
928
929 SysFreeString(nameBSTR);
930 SysFreeString(valueBSTR);
931 }
932
findString(JSContextRef,JSStringRef,JSObjectRef)933 bool LayoutTestController::findString(JSContextRef /* context */, JSStringRef /* target */, JSObjectRef /* optionsArray */)
934 {
935 // FIXME: Implement
936 return false;
937 }
938
setCacheModel(int)939 void LayoutTestController::setCacheModel(int)
940 {
941 // FIXME: Implement
942 }
943
isCommandEnabled(JSStringRef)944 bool LayoutTestController::isCommandEnabled(JSStringRef /*name*/)
945 {
946 printf("ERROR: LayoutTestController::isCommandEnabled() not implemented\n");
947 return false;
948 }
949
clearAllApplicationCaches()950 void LayoutTestController::clearAllApplicationCaches()
951 {
952 // FIXME: Implement to support application cache quotas.
953 }
954
clearApplicationCacheForOrigin(JSStringRef origin)955 void LayoutTestController::clearApplicationCacheForOrigin(JSStringRef origin)
956 {
957 // FIXME: Implement to support deleting all application cache for an origin.
958 }
959
setApplicationCacheOriginQuota(unsigned long long quota)960 void LayoutTestController::setApplicationCacheOriginQuota(unsigned long long quota)
961 {
962 // FIXME: Implement to support application cache quotas.
963 }
964
originsWithApplicationCache(JSContextRef context)965 JSValueRef LayoutTestController::originsWithApplicationCache(JSContextRef context)
966 {
967 // FIXME: Implement to get origins that have application caches.
968 return JSValueMakeUndefined(context);
969 }
970
clearAllDatabases()971 void LayoutTestController::clearAllDatabases()
972 {
973 COMPtr<IWebDatabaseManager> databaseManager;
974 COMPtr<IWebDatabaseManager> tmpDatabaseManager;
975 if (FAILED(WebKitCreateInstance(CLSID_WebDatabaseManager, 0, IID_IWebDatabaseManager, (void**)&tmpDatabaseManager)))
976 return;
977 if (FAILED(tmpDatabaseManager->sharedWebDatabaseManager(&databaseManager)))
978 return;
979
980 databaseManager->deleteAllDatabases();
981 }
982
overridePreference(JSStringRef key,JSStringRef value)983 void LayoutTestController::overridePreference(JSStringRef key, JSStringRef value)
984 {
985 COMPtr<IWebView> webView;
986 if (FAILED(frame->webView(&webView)))
987 return;
988
989 COMPtr<IWebPreferences> preferences;
990 if (FAILED(webView->preferences(&preferences)))
991 return;
992
993 COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences);
994 if (!prefsPrivate)
995 return;
996
997 BSTR keyBSTR = JSStringCopyBSTR(key);
998 BSTR valueBSTR = JSStringCopyBSTR(value);
999 prefsPrivate->setPreferenceForTest(keyBSTR, valueBSTR);
1000 SysFreeString(keyBSTR);
1001 SysFreeString(valueBSTR);
1002 }
1003
setDatabaseQuota(unsigned long long quota)1004 void LayoutTestController::setDatabaseQuota(unsigned long long quota)
1005 {
1006 COMPtr<IWebDatabaseManager> databaseManager;
1007 COMPtr<IWebDatabaseManager> tmpDatabaseManager;
1008
1009 if (FAILED(WebKitCreateInstance(CLSID_WebDatabaseManager, 0, IID_IWebDatabaseManager, (void**)&tmpDatabaseManager)))
1010 return;
1011 if (FAILED(tmpDatabaseManager->sharedWebDatabaseManager(&databaseManager)))
1012 return;
1013
1014 databaseManager->setQuota(TEXT("file:///"), quota);
1015 }
1016
setDomainRelaxationForbiddenForURLScheme(bool forbidden,JSStringRef scheme)1017 void LayoutTestController::setDomainRelaxationForbiddenForURLScheme(bool forbidden, JSStringRef scheme)
1018 {
1019 COMPtr<IWebViewPrivate> webView;
1020 if (FAILED(WebKitCreateInstance(__uuidof(WebView), 0, __uuidof(webView), reinterpret_cast<void**>(&webView))))
1021 return;
1022
1023 BSTR schemeBSTR = JSStringCopyBSTR(scheme);
1024 webView->setDomainRelaxationForbiddenForURLScheme(forbidden, schemeBSTR);
1025 SysFreeString(schemeBSTR);
1026 }
1027
setAppCacheMaximumSize(unsigned long long size)1028 void LayoutTestController::setAppCacheMaximumSize(unsigned long long size)
1029 {
1030 printf("ERROR: LayoutTestController::setAppCacheMaximumSize() not implemented\n");
1031 }
1032
pauseAnimationAtTimeOnElementWithId(JSStringRef animationName,double time,JSStringRef elementId)1033 bool LayoutTestController::pauseAnimationAtTimeOnElementWithId(JSStringRef animationName, double time, JSStringRef elementId)
1034 {
1035 COMPtr<IDOMDocument> document;
1036 if (FAILED(frame->DOMDocument(&document)))
1037 return false;
1038
1039 BSTR idBSTR = JSStringCopyBSTR(elementId);
1040 COMPtr<IDOMElement> element;
1041 HRESULT hr = document->getElementById(idBSTR, &element);
1042 SysFreeString(idBSTR);
1043 if (FAILED(hr))
1044 return false;
1045
1046 COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1047 if (!framePrivate)
1048 return false;
1049
1050 BSTR nameBSTR = JSStringCopyBSTR(animationName);
1051 BOOL wasRunning = FALSE;
1052 hr = framePrivate->pauseAnimation(nameBSTR, element.get(), time, &wasRunning);
1053 SysFreeString(nameBSTR);
1054
1055 return SUCCEEDED(hr) && wasRunning;
1056 }
1057
pauseTransitionAtTimeOnElementWithId(JSStringRef propertyName,double time,JSStringRef elementId)1058 bool LayoutTestController::pauseTransitionAtTimeOnElementWithId(JSStringRef propertyName, double time, JSStringRef elementId)
1059 {
1060 COMPtr<IDOMDocument> document;
1061 if (FAILED(frame->DOMDocument(&document)))
1062 return false;
1063
1064 BSTR idBSTR = JSStringCopyBSTR(elementId);
1065 COMPtr<IDOMElement> element;
1066 HRESULT hr = document->getElementById(idBSTR, &element);
1067 SysFreeString(idBSTR);
1068 if (FAILED(hr))
1069 return false;
1070
1071 COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1072 if (!framePrivate)
1073 return false;
1074
1075 BSTR nameBSTR = JSStringCopyBSTR(propertyName);
1076 BOOL wasRunning = FALSE;
1077 hr = framePrivate->pauseTransition(nameBSTR, element.get(), time, &wasRunning);
1078 SysFreeString(nameBSTR);
1079
1080 return SUCCEEDED(hr) && wasRunning;
1081 }
1082
sampleSVGAnimationForElementAtTime(JSStringRef animationId,double time,JSStringRef elementId)1083 bool LayoutTestController::sampleSVGAnimationForElementAtTime(JSStringRef animationId, double time, JSStringRef elementId)
1084 {
1085 COMPtr<IDOMDocument> document;
1086 if (FAILED(frame->DOMDocument(&document)))
1087 return false;
1088
1089 BSTR idBSTR = JSStringCopyBSTR(animationId);
1090 COMPtr<IDOMElement> element;
1091 HRESULT hr = document->getElementById(idBSTR, &element);
1092 SysFreeString(idBSTR);
1093 if (FAILED(hr))
1094 return false;
1095
1096 COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1097 if (!framePrivate)
1098 return false;
1099
1100 BSTR elementIdBSTR = JSStringCopyBSTR(elementId);
1101 BOOL wasRunning = FALSE;
1102 hr = framePrivate->pauseSVGAnimation(elementIdBSTR, element.get(), time, &wasRunning);
1103 SysFreeString(elementIdBSTR);
1104
1105 return SUCCEEDED(hr) && wasRunning;
1106 }
1107
numberOfActiveAnimations() const1108 unsigned LayoutTestController::numberOfActiveAnimations() const
1109 {
1110 COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1111 if (!framePrivate)
1112 return 0;
1113
1114 UINT number = 0;
1115 if (FAILED(framePrivate->numberOfActiveAnimations(&number)))
1116 return 0;
1117
1118 return number;
1119 }
1120
suspendAnimations() const1121 void LayoutTestController::suspendAnimations() const
1122 {
1123 COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1124 if (!framePrivate)
1125 return;
1126
1127 framePrivate->suspendAnimations();
1128 }
1129
resumeAnimations() const1130 void LayoutTestController::resumeAnimations() const
1131 {
1132 COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1133 if (!framePrivate)
1134 return;
1135
1136 framePrivate->resumeAnimations();
1137 }
1138
bstrT(JSStringRef jsString)1139 static _bstr_t bstrT(JSStringRef jsString)
1140 {
1141 // The false parameter tells the _bstr_t constructor to adopt the BSTR we pass it.
1142 return _bstr_t(JSStringCopyBSTR(jsString), false);
1143 }
1144
addOriginAccessWhitelistEntry(JSStringRef sourceOrigin,JSStringRef destinationProtocol,JSStringRef destinationHost,bool allowDestinationSubdomains)1145 void LayoutTestController::addOriginAccessWhitelistEntry(JSStringRef sourceOrigin, JSStringRef destinationProtocol, JSStringRef destinationHost, bool allowDestinationSubdomains)
1146 {
1147 COMPtr<IWebViewPrivate> webView;
1148 if (FAILED(WebKitCreateInstance(__uuidof(WebView), 0, __uuidof(webView), reinterpret_cast<void**>(&webView))))
1149 return;
1150
1151 webView->addOriginAccessWhitelistEntry(bstrT(sourceOrigin).GetBSTR(), bstrT(destinationProtocol).GetBSTR(), bstrT(destinationHost).GetBSTR(), allowDestinationSubdomains);
1152 }
1153
removeOriginAccessWhitelistEntry(JSStringRef sourceOrigin,JSStringRef destinationProtocol,JSStringRef destinationHost,bool allowDestinationSubdomains)1154 void LayoutTestController::removeOriginAccessWhitelistEntry(JSStringRef sourceOrigin, JSStringRef destinationProtocol, JSStringRef destinationHost, bool allowDestinationSubdomains)
1155 {
1156 COMPtr<IWebViewPrivate> webView;
1157 if (FAILED(WebKitCreateInstance(__uuidof(WebView), 0, __uuidof(webView), reinterpret_cast<void**>(&webView))))
1158 return;
1159
1160 webView->removeOriginAccessWhitelistEntry(bstrT(sourceOrigin).GetBSTR(), bstrT(destinationProtocol).GetBSTR(), bstrT(destinationHost).GetBSTR(), allowDestinationSubdomains);
1161 }
1162
setScrollbarPolicy(JSStringRef orientation,JSStringRef policy)1163 void LayoutTestController::setScrollbarPolicy(JSStringRef orientation, JSStringRef policy)
1164 {
1165 // FIXME: implement
1166 }
1167
addUserScript(JSStringRef source,bool runAtStart,bool allFrames)1168 void LayoutTestController::addUserScript(JSStringRef source, bool runAtStart, bool allFrames)
1169 {
1170 COMPtr<IWebViewPrivate> webView;
1171 if (FAILED(WebKitCreateInstance(__uuidof(WebView), 0, __uuidof(webView), reinterpret_cast<void**>(&webView))))
1172 return;
1173
1174 COMPtr<IWebScriptWorld> world;
1175 if (FAILED(WebKitCreateInstance(__uuidof(WebScriptWorld), 0, __uuidof(world), reinterpret_cast<void**>(&world))))
1176 return;
1177
1178 webView->addUserScriptToGroup(_bstr_t(L"org.webkit.DumpRenderTree").GetBSTR(), world.get(), bstrT(source).GetBSTR(), 0, 0, 0, 0, 0, runAtStart ? WebInjectAtDocumentStart : WebInjectAtDocumentEnd);
1179 }
1180
1181
addUserStyleSheet(JSStringRef source,bool allFrames)1182 void LayoutTestController::addUserStyleSheet(JSStringRef source, bool allFrames)
1183 {
1184 COMPtr<IWebViewPrivate> webView;
1185 if (FAILED(WebKitCreateInstance(__uuidof(WebView), 0, __uuidof(webView), reinterpret_cast<void**>(&webView))))
1186 return;
1187
1188 COMPtr<IWebScriptWorld> world;
1189 if (FAILED(WebKitCreateInstance(__uuidof(WebScriptWorld), 0, __uuidof(world), reinterpret_cast<void**>(&world))))
1190 return;
1191
1192 webView->addUserStyleSheetToGroup(_bstr_t(L"org.webkit.DumpRenderTree").GetBSTR(), world.get(), bstrT(source).GetBSTR(), 0, 0, 0, 0, 0);
1193 }
1194
setDeveloperExtrasEnabled(bool enabled)1195 void LayoutTestController::setDeveloperExtrasEnabled(bool enabled)
1196 {
1197 COMPtr<IWebView> webView;
1198 if (FAILED(frame->webView(&webView)))
1199 return;
1200
1201 COMPtr<IWebPreferences> preferences;
1202 if (FAILED(webView->preferences(&preferences)))
1203 return;
1204
1205 COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences);
1206 if (!prefsPrivate)
1207 return;
1208
1209 prefsPrivate->setDeveloperExtrasEnabled(enabled);
1210 }
1211
setAsynchronousSpellCheckingEnabled(bool)1212 void LayoutTestController::setAsynchronousSpellCheckingEnabled(bool)
1213 {
1214 // FIXME: Implement this.
1215 }
1216
showWebInspector()1217 void LayoutTestController::showWebInspector()
1218 {
1219 COMPtr<IWebView> webView;
1220 if (FAILED(frame->webView(&webView)))
1221 return;
1222
1223 COMPtr<IWebViewPrivate> viewPrivate(Query, webView);
1224 if (!viewPrivate)
1225 return;
1226
1227 COMPtr<IWebInspector> inspector;
1228 if (SUCCEEDED(viewPrivate->inspector(&inspector)))
1229 inspector->show();
1230 }
1231
closeWebInspector()1232 void LayoutTestController::closeWebInspector()
1233 {
1234 COMPtr<IWebView> webView;
1235 if (FAILED(frame->webView(&webView)))
1236 return;
1237
1238 COMPtr<IWebViewPrivate> viewPrivate(Query, webView);
1239 if (!viewPrivate)
1240 return;
1241
1242 COMPtr<IWebInspector> inspector;
1243 if (FAILED(viewPrivate->inspector(&inspector)))
1244 return;
1245
1246 inspector->close();
1247 }
1248
evaluateInWebInspector(long callId,JSStringRef script)1249 void LayoutTestController::evaluateInWebInspector(long callId, JSStringRef script)
1250 {
1251 COMPtr<IWebView> webView;
1252 if (FAILED(frame->webView(&webView)))
1253 return;
1254
1255 COMPtr<IWebViewPrivate> viewPrivate(Query, webView);
1256 if (!viewPrivate)
1257 return;
1258
1259 COMPtr<IWebInspector> inspector;
1260 if (FAILED(viewPrivate->inspector(&inspector)))
1261 return;
1262
1263 COMPtr<IWebInspectorPrivate> inspectorPrivate(Query, inspector);
1264 if (!inspectorPrivate)
1265 return;
1266
1267 inspectorPrivate->evaluateInFrontend(callId, bstrT(script).GetBSTR());
1268 }
1269
1270 typedef HashMap<unsigned, COMPtr<IWebScriptWorld> > WorldMap;
worldMap()1271 static WorldMap& worldMap()
1272 {
1273 static WorldMap& map = *new WorldMap;
1274 return map;
1275 }
1276
worldIDForWorld(IWebScriptWorld * world)1277 unsigned worldIDForWorld(IWebScriptWorld* world)
1278 {
1279 WorldMap::const_iterator end = worldMap().end();
1280 for (WorldMap::const_iterator it = worldMap().begin(); it != end; ++it) {
1281 if (it->second == world)
1282 return it->first;
1283 }
1284
1285 return 0;
1286 }
1287
evaluateScriptInIsolatedWorld(unsigned worldID,JSObjectRef globalObject,JSStringRef script)1288 void LayoutTestController::evaluateScriptInIsolatedWorld(unsigned worldID, JSObjectRef globalObject, JSStringRef script)
1289 {
1290 COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1291 if (!framePrivate)
1292 return;
1293
1294 // A worldID of 0 always corresponds to a new world. Any other worldID corresponds to a world
1295 // that is created once and cached forever.
1296 COMPtr<IWebScriptWorld> world;
1297 if (!worldID) {
1298 if (FAILED(WebKitCreateInstance(__uuidof(WebScriptWorld), 0, __uuidof(world), reinterpret_cast<void**>(&world))))
1299 return;
1300 } else {
1301 COMPtr<IWebScriptWorld>& worldSlot = worldMap().add(worldID, 0).first->second;
1302 if (!worldSlot && FAILED(WebKitCreateInstance(__uuidof(WebScriptWorld), 0, __uuidof(worldSlot), reinterpret_cast<void**>(&worldSlot))))
1303 return;
1304 world = worldSlot;
1305 }
1306
1307 BSTR result;
1308 if (FAILED(framePrivate->stringByEvaluatingJavaScriptInScriptWorld(world.get(), globalObject, bstrT(script).GetBSTR(), &result)))
1309 return;
1310 SysFreeString(result);
1311 }
1312
removeAllVisitedLinks()1313 void LayoutTestController::removeAllVisitedLinks()
1314 {
1315 COMPtr<IWebHistory> history;
1316 if (FAILED(WebKitCreateInstance(CLSID_WebHistory, 0, __uuidof(history), reinterpret_cast<void**>(&history))))
1317 return;
1318
1319 COMPtr<IWebHistory> sharedHistory;
1320 if (FAILED(history->optionalSharedHistory(&sharedHistory)) || !sharedHistory)
1321 return;
1322
1323 COMPtr<IWebHistoryPrivate> sharedHistoryPrivate;
1324 if (FAILED(sharedHistory->QueryInterface(&sharedHistoryPrivate)))
1325 return;
1326
1327 sharedHistoryPrivate->removeAllVisitedLinks();
1328 }
1329
counterValueForElementById(JSStringRef id)1330 JSRetainPtr<JSStringRef> LayoutTestController::counterValueForElementById(JSStringRef id)
1331 {
1332 COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1333 if (!framePrivate)
1334 return 0;
1335
1336 wstring idWstring = jsStringRefToWString(id);
1337 BSTR idBSTR = SysAllocStringLen((OLECHAR*)idWstring.c_str(), idWstring.length());
1338 BSTR counterValueBSTR;
1339 if (FAILED(framePrivate->counterValueForElementById(idBSTR, &counterValueBSTR)))
1340 return 0;
1341
1342 wstring counterValue(counterValueBSTR, SysStringLen(counterValueBSTR));
1343 SysFreeString(idBSTR);
1344 SysFreeString(counterValueBSTR);
1345 JSRetainPtr<JSStringRef> counterValueJS(Adopt, JSStringCreateWithCharacters(counterValue.data(), counterValue.length()));
1346 return counterValueJS;
1347 }
1348
pageNumberForElementById(JSStringRef id,float pageWidthInPixels,float pageHeightInPixels)1349 int LayoutTestController::pageNumberForElementById(JSStringRef id, float pageWidthInPixels, float pageHeightInPixels)
1350 {
1351 COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1352 if (!framePrivate)
1353 return 0;
1354
1355 wstring idWstring = jsStringRefToWString(id);
1356 BSTR idBSTR = SysAllocStringLen((OLECHAR*)idWstring.c_str(), idWstring.length());
1357 int pageNumber = -1;
1358 if (FAILED(framePrivate->pageNumberForElementById(idBSTR, pageWidthInPixels, pageHeightInPixels, &pageNumber)))
1359 pageNumber = -1;
1360 SysFreeString(idBSTR);
1361 return pageNumber;
1362 }
1363
numberOfPages(float pageWidthInPixels,float pageHeightInPixels)1364 int LayoutTestController::numberOfPages(float pageWidthInPixels, float pageHeightInPixels)
1365 {
1366 COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1367 if (!framePrivate)
1368 return 0;
1369
1370 int pageNumber = -1;
1371 if (FAILED(framePrivate->numberOfPages(pageWidthInPixels, pageHeightInPixels, &pageNumber)))
1372 pageNumber = -1;
1373 return pageNumber;
1374 }
1375
pageProperty(const char * propertyName,int pageNumber) const1376 JSRetainPtr<JSStringRef> LayoutTestController::pageProperty(const char* propertyName, int pageNumber) const
1377 {
1378 // FIXME: Implement this.
1379 return JSRetainPtr<JSStringRef>();
1380 }
1381
apiTestNewWindowDataLoadBaseURL(JSStringRef utf8Data,JSStringRef baseURL)1382 void LayoutTestController::apiTestNewWindowDataLoadBaseURL(JSStringRef utf8Data, JSStringRef baseURL)
1383 {
1384
1385 }
1386
isPageBoxVisible(int pageNumber) const1387 bool LayoutTestController::isPageBoxVisible(int pageNumber) const
1388 {
1389 // FIXME: implement
1390 return false;
1391 }
1392
pageSizeAndMarginsInPixels(int pageNumber,int width,int height,int marginTop,int marginRight,int marginBottom,int marginLeft) const1393 JSRetainPtr<JSStringRef> LayoutTestController::pageSizeAndMarginsInPixels(int pageNumber, int width, int height, int marginTop, int marginRight, int marginBottom, int marginLeft) const
1394 {
1395 // FIXME: implement
1396 return JSRetainPtr<JSStringRef>();
1397 }
1398
apiTestGoToCurrentBackForwardItem()1399 void LayoutTestController::apiTestGoToCurrentBackForwardItem()
1400 {
1401 COMPtr<IWebView> webView;
1402 if (FAILED(frame->webView(&webView)))
1403 return;
1404
1405 COMPtr<IWebBackForwardList> backForwardList;
1406 if (FAILED(webView->backForwardList(&backForwardList)))
1407 return;
1408
1409 COMPtr<IWebHistoryItem> item;
1410 if (FAILED(backForwardList->currentItem(&item)))
1411 return;
1412
1413 BOOL success;
1414 webView->goToBackForwardItem(item.get(), &success);
1415 }
1416
setWebViewEditable(bool)1417 void LayoutTestController::setWebViewEditable(bool)
1418 {
1419 }
1420
authenticateSession(JSStringRef,JSStringRef,JSStringRef)1421 void LayoutTestController::authenticateSession(JSStringRef, JSStringRef, JSStringRef)
1422 {
1423 }
1424
setEditingBehavior(const char * editingBehavior)1425 void LayoutTestController::setEditingBehavior(const char* editingBehavior)
1426 {
1427 COMPtr<IWebView> webView;
1428 if (FAILED(frame->webView(&webView)))
1429 return;
1430
1431 COMPtr<IWebPreferences> preferences;
1432 if (FAILED(webView->preferences(&preferences)))
1433 return;
1434
1435 string behaviorString(editingBehavior);
1436 if (behaviorString == "mac")
1437 preferences->setEditingBehavior(WebKitEditingMacBehavior);
1438 else if (behaviorString == "win")
1439 preferences->setEditingBehavior(WebKitEditingWinBehavior);
1440 else if (behaviorString == "unix")
1441 preferences->setEditingBehavior(WebKitEditingUnixBehavior);
1442 }
1443
shadowRoot(JSContextRef context,JSValueRef jsElement)1444 JSValueRef LayoutTestController::shadowRoot(JSContextRef context, JSValueRef jsElement)
1445 {
1446 // FIXME: Implement this.
1447 return JSValueMakeUndefined(context);
1448 }
1449
abortModal()1450 void LayoutTestController::abortModal()
1451 {
1452 }
1453
hasSpellingMarker(int from,int length)1454 bool LayoutTestController::hasSpellingMarker(int from, int length)
1455 {
1456 COMPtr<IWebFramePrivate> framePrivate(Query, frame);
1457 if (!framePrivate)
1458 return false;
1459 BOOL ret = FALSE;
1460 if (FAILED(framePrivate->hasSpellingMarker(from, length, &ret)))
1461 return false;
1462 return ret;
1463 }
1464
hasGrammarMarker(int from,int length)1465 bool LayoutTestController::hasGrammarMarker(int from, int length)
1466 {
1467 // FIXME: Implement this.
1468 return false;
1469 }
1470
dumpConfigurationForViewport(int,int,int,int,int)1471 void LayoutTestController::dumpConfigurationForViewport(int /*deviceDPI*/, int /*deviceWidth*/, int /*deviceHeight*/, int /*availableWidth*/, int /*availableHeight*/)
1472 {
1473 // FIXME: Implement this.
1474 }
1475
setSerializeHTTPLoads(bool)1476 void LayoutTestController::setSerializeHTTPLoads(bool)
1477 {
1478 // FIXME: Implement.
1479 }
1480
syncLocalStorage()1481 void LayoutTestController::syncLocalStorage()
1482 {
1483 // FIXME: Implement.
1484 }
1485
observeStorageTrackerNotifications(unsigned number)1486 void LayoutTestController::observeStorageTrackerNotifications(unsigned number)
1487 {
1488 // FIXME: Implement.
1489 }
1490
deleteAllLocalStorage()1491 void LayoutTestController::deleteAllLocalStorage()
1492 {
1493 // FIXME: Implement.
1494 }
1495
originsWithLocalStorage(JSContextRef context)1496 JSValueRef LayoutTestController::originsWithLocalStorage(JSContextRef context)
1497 {
1498 // FIXME: Implement.
1499 return JSValueMakeUndefined(context);
1500 }
1501
deleteLocalStorageForOrigin(JSStringRef URL)1502 void LayoutTestController::deleteLocalStorageForOrigin(JSStringRef URL)
1503 {
1504 // FIXME: Implement.
1505 }
1506
setMinimumTimerInterval(double minimumTimerInterval)1507 void LayoutTestController::setMinimumTimerInterval(double minimumTimerInterval)
1508 {
1509 COMPtr<IWebView> webView;
1510 if (FAILED(frame->webView(&webView)))
1511 return;
1512
1513 COMPtr<IWebViewPrivate> viewPrivate(Query, webView);
1514 if (!viewPrivate)
1515 return;
1516
1517 viewPrivate->setMinimumTimerInterval(minimumTimerInterval);
1518 }
1519
1520
1521