LayoutTestController.cpp revision ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddb
1ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block/*
2ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block * Copyright (C) 2010 Apple Inc. All rights reserved.
3ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block *
4ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block * Redistribution and use in source and binary forms, with or without
5ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block * modification, are permitted provided that the following conditions
6ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block * are met:
7ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block * 1. Redistributions of source code must retain the above copyright
8ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block *    notice, this list of conditions and the following disclaimer.
9ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block * 2. Redistributions in binary form must reproduce the above copyright
10ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block *    notice, this list of conditions and the following disclaimer in the
11ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block *    documentation and/or other materials provided with the distribution.
12ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block *
13ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block * THE POSSIBILITY OF SUCH DAMAGE.
24ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block */
25ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block
26ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block#include "LayoutTestController.h"
27967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch
28e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke#include "InjectedBundle.h"
29e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke#include "InjectedBundlePage.h"
30967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch#include "JSLayoutTestController.h"
31dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch#include "StringFunctions.h"
32e14391e94c850b8bd03680c23b38978db68687a8John Reck#include <WebKit2/WKBundleBackForwardList.h>
33e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke#include <WebKit2/WKBundleFrame.h>
340617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen#include <WebKit2/WKBundleFramePrivate.h>
350617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen#include <WebKit2/WKBundlePagePrivate.h>
365ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen#include <WebKit2/WKBundleScriptWorld.h>
37dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch#include <WebKit2/WKBundlePrivate.h>
38e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke#include <WebKit2/WKRetainPtr.h>
39e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke#include <WebKit2/WebKit2.h>
40ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch#include <wtf/HashMap.h>
41ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block
42ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Blocknamespace WTR {
43ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block
440617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen// This is lower than DumpRenderTree's timeout, to make it easier to work through the failures
450617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen// Eventually it should be changed to match.
4668513a70bcd92384395513322f1b801e7bf9c729Steve Blockconst double LayoutTestController::waitToDumpWatchdogTimerInterval = 6;
470617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen
480617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsenstatic JSValueRef propertyValue(JSContextRef context, JSObjectRef object, const char* propertyName)
490617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen{
500617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    if (!object)
510617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen        return 0;
520617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    JSRetainPtr<JSStringRef> propertyNameString(Adopt, JSStringCreateWithUTF8CString(propertyName));
530617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    JSValueRef exception;
540617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    return JSObjectGetProperty(context, object, propertyNameString.get(), &exception);
550617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen}
560617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen
570617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsenstatic JSObjectRef propertyObject(JSContextRef context, JSObjectRef object, const char* propertyName)
580617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen{
590617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    JSValueRef value = propertyValue(context, object, propertyName);
600617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    if (!value || !JSValueIsObject(context, value))
610617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen        return 0;
620617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    return const_cast<JSObjectRef>(value);
630617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen}
640617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen
650617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsenstatic JSObjectRef getElementById(WKBundleFrameRef frame, JSStringRef elementId)
66ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block{
670617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    JSContextRef context = WKBundleFrameGetJavaScriptContext(frame);
680617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    JSObjectRef document = propertyObject(context, JSContextGetGlobalObject(context), "document");
690617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    if (!document)
700617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen        return 0;
710617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    JSValueRef getElementById = propertyObject(context, document, "getElementById");
720617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    if (!getElementById || !JSValueIsObject(context, getElementById))
730617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen        return 0;
740617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    JSValueRef elementIdValue = JSValueMakeString(context, elementId);
750617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    JSValueRef exception;
760617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    JSValueRef element = JSObjectCallAsFunction(context, const_cast<JSObjectRef>(getElementById), document, 1, &elementIdValue, &exception);
770617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    if (!element || !JSValueIsObject(context, element))
780617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen        return 0;
790617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    return const_cast<JSObjectRef>(element);
80ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block}
81ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block
820617145a89917ae7735fe1c9538688ab9a577df5Kristian MonsenPassRefPtr<LayoutTestController> LayoutTestController::create()
830617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen{
840617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    return adoptRef(new LayoutTestController);
850617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen}
860617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen
870617145a89917ae7735fe1c9538688ab9a577df5Kristian MonsenLayoutTestController::LayoutTestController()
880617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    : m_whatToDump(RenderTree)
890617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    , m_shouldDumpAllFrameScrollPositions(false)
90e14391e94c850b8bd03680c23b38978db68687a8John Reck    , m_shouldDumpBackForwardListsForAllWindows(false)
910617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    , m_shouldAllowEditing(true)
92db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    , m_shouldCloseExtraWindows(false)
930617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    , m_dumpEditingCallbacks(false)
94967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch    , m_dumpStatusCallbacks(false)
95dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    , m_dumpTitleChanges(false)
96e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    , m_waitToDump(false)
97967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch    , m_testRepaint(false)
98967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch    , m_testRepaintSweepHorizontally(false)
99ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block{
10068513a70bcd92384395513322f1b801e7bf9c729Steve Block    platformInitialize();
101ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block}
102ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block
103ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve BlockLayoutTestController::~LayoutTestController()
104ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block{
105ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block}
106ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block
107967717af5423377c967781471ee106e2bb4e11c8Ben MurdochJSClassRef LayoutTestController::wrapperClass()
108967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch{
109967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch    return JSLayoutTestController::layoutTestControllerClass();
110967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch}
111e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
112967717af5423377c967781471ee106e2bb4e11c8Ben Murdochvoid LayoutTestController::display()
113967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch{
114967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch    // FIXME: actually implement, once we want pixel tests
115967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch}
116e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
117967717af5423377c967781471ee106e2bb4e11c8Ben Murdochvoid LayoutTestController::waitUntilDone()
118e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke{
119e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    m_waitToDump = true;
12068513a70bcd92384395513322f1b801e7bf9c729Steve Block    initializeWaitToDumpWatchdogTimerIfNeeded();
121e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke}
122e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
123e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarkevoid LayoutTestController::waitToDumpWatchdogTimerFired()
124e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke{
12568513a70bcd92384395513322f1b801e7bf9c729Steve Block    invalidateWaitToDumpWatchdogTimer();
126e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    const char* message = "FAIL: Timed out waiting for notifyDone to be called\n";
127e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    InjectedBundle::shared().os() << message << "\n";
128e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    InjectedBundle::shared().done();
129e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke}
130e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
131e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarkevoid LayoutTestController::notifyDone()
132e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke{
133cad810f21b803229eb11403f9209855525a25d57Steve Block    if (!InjectedBundle::shared().isTestRunning())
134cad810f21b803229eb11403f9209855525a25d57Steve Block        return;
135cad810f21b803229eb11403f9209855525a25d57Steve Block
136ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    if (m_waitToDump && !InjectedBundle::shared().topLoadingFrame())
137e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke        InjectedBundle::shared().page()->dump();
138ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
139e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    m_waitToDump = false;
140e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke}
141e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
142e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarkeunsigned LayoutTestController::numberOfActiveAnimations() const
143e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke{
1440617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    // FIXME: Is it OK this works only for the main frame?
1450617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    // FIXME: If this is needed only for the main frame, then why is the function on WKBundleFrame instead of WKBundlePage?
146e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page());
147e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    return WKBundleFrameGetNumberOfActiveAnimations(mainFrame);
148e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke}
149e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
150e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarkebool LayoutTestController::pauseAnimationAtTimeOnElementWithId(JSStringRef animationName, double time, JSStringRef elementId)
151e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke{
1520617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    // FIXME: Is it OK this works only for the main frame?
1530617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    // FIXME: If this is needed only for the main frame, then why is the function on WKBundleFrame instead of WKBundlePage?
1540617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page());
1550617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    return WKBundleFramePauseAnimationOnElementWithId(mainFrame, toWK(animationName).get(), toWK(elementId).get(), time);
1560617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen}
157e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
15828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhuvoid LayoutTestController::suspendAnimations()
15928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu{
16028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page());
16128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    WKBundleFrameSuspendAnimations(mainFrame);
16228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu}
16328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
16428040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhuvoid LayoutTestController::resumeAnimations()
16528040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu{
16628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page());
16728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    WKBundleFrameResumeAnimations(mainFrame);
16828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu}
16928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
170e14391e94c850b8bd03680c23b38978db68687a8John ReckJSRetainPtr<JSStringRef> LayoutTestController::layerTreeAsText() const
171e14391e94c850b8bd03680c23b38978db68687a8John Reck{
172e14391e94c850b8bd03680c23b38978db68687a8John Reck    WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page());
173e14391e94c850b8bd03680c23b38978db68687a8John Reck    WKRetainPtr<WKStringRef> text(AdoptWK, WKBundleFrameCopyLayerTreeAsText(mainFrame));
174e14391e94c850b8bd03680c23b38978db68687a8John Reck    return toJS(text);
175e14391e94c850b8bd03680c23b38978db68687a8John Reck}
176e14391e94c850b8bd03680c23b38978db68687a8John Reck
1775ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenvoid LayoutTestController::addUserScript(JSStringRef source, bool runAtStart, bool allFrames)
1785ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen{
1795ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    WKRetainPtr<WKStringRef> sourceWK = toWK(source);
1805ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    WKRetainPtr<WKBundleScriptWorldRef> scriptWorld(AdoptWK, WKBundleScriptWorldCreateWorld());
1815ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
182f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    WKBundleAddUserScript(InjectedBundle::shared().bundle(), InjectedBundle::shared().pageGroup(), scriptWorld.get(), sourceWK.get(), 0, 0, 0,
1835ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        (runAtStart ? kWKInjectAtDocumentStart : kWKInjectAtDocumentEnd),
1845ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        (allFrames ? kWKInjectInAllFrames : kWKInjectInTopFrameOnly));
1855ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen}
1865ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1875ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenvoid LayoutTestController::addUserStyleSheet(JSStringRef source, bool allFrames)
1885ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen{
1895ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    WKRetainPtr<WKStringRef> sourceWK = toWK(source);
1905ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    WKRetainPtr<WKBundleScriptWorldRef> scriptWorld(AdoptWK, WKBundleScriptWorldCreateWorld());
1915ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
192f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    WKBundleAddUserStyleSheet(InjectedBundle::shared().bundle(), InjectedBundle::shared().pageGroup(), scriptWorld.get(), sourceWK.get(), 0, 0, 0,
1935ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        (allFrames ? kWKInjectInAllFrames : kWKInjectInTopFrameOnly));
1945ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen}
1955ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1960617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsenvoid LayoutTestController::keepWebHistory()
1970617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen{
198dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    WKBundleSetShouldTrackVisitedLinks(InjectedBundle::shared().bundle(), true);
1990617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen}
2000617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen
2010617145a89917ae7735fe1c9538688ab9a577df5Kristian MonsenJSValueRef LayoutTestController::computedStyleIncludingVisitedInfo(JSValueRef element)
2020617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen{
2030617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    // FIXME: Is it OK this works only for the main frame?
204e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page());
2050617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
2060617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    if (!JSValueIsObject(context, element))
2070617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen        return JSValueMakeUndefined(context);
2080617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    JSValueRef value = WKBundleFrameGetComputedStyleIncludingVisitedInfo(mainFrame, const_cast<JSObjectRef>(element));
2090617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    if (!value)
2100617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen        return JSValueMakeUndefined(context);
2110617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    return value;
2120617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen}
2130617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen
2140617145a89917ae7735fe1c9538688ab9a577df5Kristian MonsenJSRetainPtr<JSStringRef> LayoutTestController::counterValueForElementById(JSStringRef elementId)
2150617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen{
2160617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page());
2170617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    JSObjectRef element = getElementById(mainFrame, elementId);
2180617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    if (!element)
2190617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen        return 0;
2200617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    WKRetainPtr<WKStringRef> value(AdoptWK, WKBundleFrameCopyCounterValue(mainFrame, const_cast<JSObjectRef>(element)));
2210617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    return toJS(value);
2220617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen}
2230617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen
2240617145a89917ae7735fe1c9538688ab9a577df5Kristian MonsenJSRetainPtr<JSStringRef> LayoutTestController::markerTextForListItem(JSValueRef element)
2250617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen{
2260617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page());
2270617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
2280617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    if (!element || !JSValueIsObject(context, element))
2290617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen        return 0;
2300617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    WKRetainPtr<WKStringRef> text(AdoptWK, WKBundleFrameCopyMarkerText(mainFrame, const_cast<JSObjectRef>(element)));
2310617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    if (WKStringIsEmpty(text.get()))
2320617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen        return 0;
2330617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    return toJS(text);
2340617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen}
2350617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen
2360617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsenvoid LayoutTestController::execCommand(JSStringRef name, JSStringRef argument)
2370617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen{
2380617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    WKBundlePageExecuteEditingCommand(InjectedBundle::shared().page()->page(), toWK(name).get(), toWK(argument).get());
2390617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen}
2400617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen
241f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochbool LayoutTestController::findString(JSStringRef target, JSValueRef optionsArrayAsValue)
242f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
243f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    WKFindOptions options = 0;
244f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
245f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page());
246f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
247f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    JSRetainPtr<JSStringRef> lengthPropertyName(Adopt, JSStringCreateWithUTF8CString("length"));
248f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    JSObjectRef optionsArray = JSValueToObject(context, optionsArrayAsValue, 0);
249f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    JSValueRef lengthValue = JSObjectGetProperty(context, optionsArray, lengthPropertyName.get(), 0);
250f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (!JSValueIsNumber(context, lengthValue))
251f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        return false;
252f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
253f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    size_t length = static_cast<size_t>(JSValueToNumber(context, lengthValue, 0));
254f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    for (size_t i = 0; i < length; ++i) {
255f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        JSValueRef value = JSObjectGetPropertyAtIndex(context, optionsArray, i, 0);
256f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        if (!JSValueIsString(context, value))
257f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            continue;
258f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
259f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        JSRetainPtr<JSStringRef> optionName(Adopt, JSValueToStringCopy(context, value, 0));
260f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
261f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        if (JSStringIsEqualToUTF8CString(optionName.get(), "CaseInsensitive"))
262f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            options |= kWKFindOptionsCaseInsensitive;
263f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        else if (JSStringIsEqualToUTF8CString(optionName.get(), "AtWordStarts"))
264f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            options |= kWKFindOptionsAtWordStarts;
265f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        else if (JSStringIsEqualToUTF8CString(optionName.get(), "TreatMedialCapitalAsWordStart"))
266f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            options |= kWKFindOptionsTreatMedialCapitalAsWordStart;
267f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        else if (JSStringIsEqualToUTF8CString(optionName.get(), "Backwards"))
268f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            options |= kWKFindOptionsBackwards;
269f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        else if (JSStringIsEqualToUTF8CString(optionName.get(), "WrapAround"))
270f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            options |= kWKFindOptionsWrapAround;
271f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        else if (JSStringIsEqualToUTF8CString(optionName.get(), "StartInSelection")) {
272f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            // FIXME: No kWKFindOptionsStartInSelection.
273f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        }
274f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    }
275f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
276f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    return WKBundlePageFindString(InjectedBundle::shared().page()->page(), toWK(target).get(), options);
277f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
278f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
2790617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsenbool LayoutTestController::isCommandEnabled(JSStringRef name)
2800617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen{
2810617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    return WKBundlePageIsEditingCommandEnabled(InjectedBundle::shared().page()->page(), toWK(name).get());
282e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke}
283e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
284db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Blockvoid LayoutTestController::setCanOpenWindows(bool)
285db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block{
286db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    // It's not clear if or why any tests require opening windows be forbidden.
287db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    // For now, just ignore this setting, and if we find later it's needed we can add it.
288db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block}
289db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block
2905ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenvoid LayoutTestController::setXSSAuditorEnabled(bool enabled)
2915ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen{
292f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    WKBundleOverrideXSSAuditorEnabledForTestRunner(InjectedBundle::shared().bundle(), InjectedBundle::shared().pageGroup(), true);
2935ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen}
2945ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
295db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Blockunsigned LayoutTestController::windowCount()
296db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block{
297db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    return InjectedBundle::shared().pageCount();
298db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block}
299db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block
300e14391e94c850b8bd03680c23b38978db68687a8John Reckvoid LayoutTestController::clearBackForwardList()
301e14391e94c850b8bd03680c23b38978db68687a8John Reck{
302e14391e94c850b8bd03680c23b38978db68687a8John Reck    WKBundleBackForwardListClear(WKBundlePageGetBackForwardList(InjectedBundle::shared().page()->page()));
303e14391e94c850b8bd03680c23b38978db68687a8John Reck}
304e14391e94c850b8bd03680c23b38978db68687a8John Reck
305ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block// Object Creation
306ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block
307ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Blockvoid LayoutTestController::makeWindowObject(JSContextRef context, JSObjectRef windowObject, JSValueRef* exception)
308ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block{
3090617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    setProperty(context, windowObject, "layoutTestController", this, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, exception);
310ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block}
311ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block
312ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdochtypedef WTF::HashMap<unsigned, WKRetainPtr<WKBundleScriptWorldRef> > WorldMap;
313ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdochstatic WorldMap& worldMap()
314ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch{
315ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    static WorldMap& map = *new WorldMap;
316ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    return map;
317ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch}
318ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
319ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdochunsigned LayoutTestController::worldIDForWorld(WKBundleScriptWorldRef world)
320ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch{
321ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    WorldMap::const_iterator end = worldMap().end();
322ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    for (WorldMap::const_iterator it = worldMap().begin(); it != end; ++it) {
323ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        if (it->second == world)
324ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch            return it->first;
325ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    }
326ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
327ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    return 0;
328ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch}
329ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
330ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdochvoid LayoutTestController::evaluateScriptInIsolatedWorld(JSContextRef context, unsigned worldID, JSStringRef script)
331ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch{
332ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    // A worldID of 0 always corresponds to a new world. Any other worldID corresponds to a world
333ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    // that is created once and cached forever.
334ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    WKRetainPtr<WKBundleScriptWorldRef> world;
335ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    if (!worldID)
336ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        world.adopt(WKBundleScriptWorldCreateWorld());
337ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    else {
338ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        WKRetainPtr<WKBundleScriptWorldRef>& worldSlot = worldMap().add(worldID, 0).first->second;
339ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        if (!worldSlot)
340ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch            worldSlot.adopt(WKBundleScriptWorldCreateWorld());
341ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        world = worldSlot;
342ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    }
343ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
344ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    WKBundleFrameRef frame = WKBundleFrameForJavaScriptContext(context);
345ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    if (!frame)
346ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        frame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page());
347ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
348ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    JSGlobalContextRef jsContext = WKBundleFrameGetJavaScriptContextForWorld(frame, world.get());
349ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    JSEvaluateScript(jsContext, script, 0, 0, 0, 0);
350ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch}
351ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
352ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block} // namespace WTR
353