LayoutTestController.cpp revision 2bde8e466a4451c7319e3a072d118917957d6554
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
262bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "config.h"
27ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block#include "LayoutTestController.h"
28967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch
29e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke#include "InjectedBundle.h"
30e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke#include "InjectedBundlePage.h"
31967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch#include "JSLayoutTestController.h"
32dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch#include "StringFunctions.h"
33e14391e94c850b8bd03680c23b38978db68687a8John Reck#include <WebKit2/WKBundleBackForwardList.h>
34e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke#include <WebKit2/WKBundleFrame.h>
350617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen#include <WebKit2/WKBundleFramePrivate.h>
362fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include <WebKit2/WKBundleInspector.h>
370617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen#include <WebKit2/WKBundlePagePrivate.h>
385ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen#include <WebKit2/WKBundleScriptWorld.h>
39dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch#include <WebKit2/WKBundlePrivate.h>
40e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke#include <WebKit2/WKRetainPtr.h>
41e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke#include <WebKit2/WebKit2.h>
42ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch#include <wtf/HashMap.h>
43ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block
44ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Blocknamespace WTR {
45ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block
460617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen// This is lower than DumpRenderTree's timeout, to make it easier to work through the failures
470617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen// Eventually it should be changed to match.
4868513a70bcd92384395513322f1b801e7bf9c729Steve Blockconst double LayoutTestController::waitToDumpWatchdogTimerInterval = 6;
490617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen
500617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsenstatic JSValueRef propertyValue(JSContextRef context, JSObjectRef object, const char* propertyName)
510617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen{
520617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    if (!object)
530617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen        return 0;
540617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    JSRetainPtr<JSStringRef> propertyNameString(Adopt, JSStringCreateWithUTF8CString(propertyName));
550617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    JSValueRef exception;
560617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    return JSObjectGetProperty(context, object, propertyNameString.get(), &exception);
570617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen}
580617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen
590617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsenstatic JSObjectRef propertyObject(JSContextRef context, JSObjectRef object, const char* propertyName)
600617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen{
610617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    JSValueRef value = propertyValue(context, object, propertyName);
620617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    if (!value || !JSValueIsObject(context, value))
630617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen        return 0;
640617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    return const_cast<JSObjectRef>(value);
650617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen}
660617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen
670617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsenstatic JSObjectRef getElementById(WKBundleFrameRef frame, JSStringRef elementId)
68ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block{
690617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    JSContextRef context = WKBundleFrameGetJavaScriptContext(frame);
700617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    JSObjectRef document = propertyObject(context, JSContextGetGlobalObject(context), "document");
710617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    if (!document)
720617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen        return 0;
730617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    JSValueRef getElementById = propertyObject(context, document, "getElementById");
740617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    if (!getElementById || !JSValueIsObject(context, getElementById))
750617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen        return 0;
760617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    JSValueRef elementIdValue = JSValueMakeString(context, elementId);
770617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    JSValueRef exception;
780617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    JSValueRef element = JSObjectCallAsFunction(context, const_cast<JSObjectRef>(getElementById), document, 1, &elementIdValue, &exception);
790617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    if (!element || !JSValueIsObject(context, element))
800617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen        return 0;
810617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    return const_cast<JSObjectRef>(element);
82ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block}
83ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block
840617145a89917ae7735fe1c9538688ab9a577df5Kristian MonsenPassRefPtr<LayoutTestController> LayoutTestController::create()
850617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen{
860617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    return adoptRef(new LayoutTestController);
870617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen}
880617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen
890617145a89917ae7735fe1c9538688ab9a577df5Kristian MonsenLayoutTestController::LayoutTestController()
900617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    : m_whatToDump(RenderTree)
910617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    , m_shouldDumpAllFrameScrollPositions(false)
92e14391e94c850b8bd03680c23b38978db68687a8John Reck    , m_shouldDumpBackForwardListsForAllWindows(false)
930617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    , m_shouldAllowEditing(true)
94db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    , m_shouldCloseExtraWindows(false)
950617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    , m_dumpEditingCallbacks(false)
96967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch    , m_dumpStatusCallbacks(false)
97dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    , m_dumpTitleChanges(false)
9881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    , m_dumpPixels(true)
99e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    , m_waitToDump(false)
100967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch    , m_testRepaint(false)
101967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch    , m_testRepaintSweepHorizontally(false)
1022fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    , m_willSendRequestReturnsNull(false)
103ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block{
10468513a70bcd92384395513322f1b801e7bf9c729Steve Block    platformInitialize();
105ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block}
106ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block
107ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve BlockLayoutTestController::~LayoutTestController()
108ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block{
109ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block}
110ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block
111967717af5423377c967781471ee106e2bb4e11c8Ben MurdochJSClassRef LayoutTestController::wrapperClass()
112967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch{
113967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch    return JSLayoutTestController::layoutTestControllerClass();
114967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch}
115e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
116967717af5423377c967781471ee106e2bb4e11c8Ben Murdochvoid LayoutTestController::display()
117967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch{
118967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch    // FIXME: actually implement, once we want pixel tests
119967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch}
120e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
12181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochvoid LayoutTestController::dumpAsText()
12281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{
12381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    m_whatToDump = MainFrameText;
12481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    m_dumpPixels = false;
12581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch}
12681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
127967717af5423377c967781471ee106e2bb4e11c8Ben Murdochvoid LayoutTestController::waitUntilDone()
128e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke{
129e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    m_waitToDump = true;
13068513a70bcd92384395513322f1b801e7bf9c729Steve Block    initializeWaitToDumpWatchdogTimerIfNeeded();
131e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke}
132e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
133e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarkevoid LayoutTestController::waitToDumpWatchdogTimerFired()
134e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke{
13568513a70bcd92384395513322f1b801e7bf9c729Steve Block    invalidateWaitToDumpWatchdogTimer();
136e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    const char* message = "FAIL: Timed out waiting for notifyDone to be called\n";
137e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    InjectedBundle::shared().os() << message << "\n";
138e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    InjectedBundle::shared().done();
139e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke}
140e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
141e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarkevoid LayoutTestController::notifyDone()
142e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke{
143cad810f21b803229eb11403f9209855525a25d57Steve Block    if (!InjectedBundle::shared().isTestRunning())
144cad810f21b803229eb11403f9209855525a25d57Steve Block        return;
145cad810f21b803229eb11403f9209855525a25d57Steve Block
146ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    if (m_waitToDump && !InjectedBundle::shared().topLoadingFrame())
147e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke        InjectedBundle::shared().page()->dump();
148ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
149e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    m_waitToDump = false;
150e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke}
151e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
152e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarkeunsigned LayoutTestController::numberOfActiveAnimations() const
153e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke{
1540617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    // FIXME: Is it OK this works only for the main frame?
1550617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    // FIXME: If this is needed only for the main frame, then why is the function on WKBundleFrame instead of WKBundlePage?
156e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page());
157e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    return WKBundleFrameGetNumberOfActiveAnimations(mainFrame);
158e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke}
159e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
160e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarkebool LayoutTestController::pauseAnimationAtTimeOnElementWithId(JSStringRef animationName, double time, JSStringRef elementId)
161e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke{
1620617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    // FIXME: Is it OK this works only for the main frame?
1630617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    // FIXME: If this is needed only for the main frame, then why is the function on WKBundleFrame instead of WKBundlePage?
1640617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page());
1650617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    return WKBundleFramePauseAnimationOnElementWithId(mainFrame, toWK(animationName).get(), toWK(elementId).get(), time);
1660617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen}
167e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
16828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhuvoid LayoutTestController::suspendAnimations()
16928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu{
17028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page());
17128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    WKBundleFrameSuspendAnimations(mainFrame);
17228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu}
17328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
17428040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhuvoid LayoutTestController::resumeAnimations()
17528040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu{
17628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page());
17728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    WKBundleFrameResumeAnimations(mainFrame);
17828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu}
17928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
180e14391e94c850b8bd03680c23b38978db68687a8John ReckJSRetainPtr<JSStringRef> LayoutTestController::layerTreeAsText() const
181e14391e94c850b8bd03680c23b38978db68687a8John Reck{
182e14391e94c850b8bd03680c23b38978db68687a8John Reck    WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page());
183e14391e94c850b8bd03680c23b38978db68687a8John Reck    WKRetainPtr<WKStringRef> text(AdoptWK, WKBundleFrameCopyLayerTreeAsText(mainFrame));
184e14391e94c850b8bd03680c23b38978db68687a8John Reck    return toJS(text);
185e14391e94c850b8bd03680c23b38978db68687a8John Reck}
186e14391e94c850b8bd03680c23b38978db68687a8John Reck
1875ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenvoid LayoutTestController::addUserScript(JSStringRef source, bool runAtStart, bool allFrames)
1885ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen{
1895ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    WKRetainPtr<WKStringRef> sourceWK = toWK(source);
1905ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    WKRetainPtr<WKBundleScriptWorldRef> scriptWorld(AdoptWK, WKBundleScriptWorldCreateWorld());
1915ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
192f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    WKBundleAddUserScript(InjectedBundle::shared().bundle(), InjectedBundle::shared().pageGroup(), scriptWorld.get(), sourceWK.get(), 0, 0, 0,
1935ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        (runAtStart ? kWKInjectAtDocumentStart : kWKInjectAtDocumentEnd),
1945ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        (allFrames ? kWKInjectInAllFrames : kWKInjectInTopFrameOnly));
1955ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen}
1965ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1975ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenvoid LayoutTestController::addUserStyleSheet(JSStringRef source, bool allFrames)
1985ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen{
1995ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    WKRetainPtr<WKStringRef> sourceWK = toWK(source);
2005ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    WKRetainPtr<WKBundleScriptWorldRef> scriptWorld(AdoptWK, WKBundleScriptWorldCreateWorld());
2015ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
202f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    WKBundleAddUserStyleSheet(InjectedBundle::shared().bundle(), InjectedBundle::shared().pageGroup(), scriptWorld.get(), sourceWK.get(), 0, 0, 0,
2035ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        (allFrames ? kWKInjectInAllFrames : kWKInjectInTopFrameOnly));
2045ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen}
2055ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
2060617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsenvoid LayoutTestController::keepWebHistory()
2070617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen{
208dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    WKBundleSetShouldTrackVisitedLinks(InjectedBundle::shared().bundle(), true);
2090617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen}
2100617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen
2110617145a89917ae7735fe1c9538688ab9a577df5Kristian MonsenJSValueRef LayoutTestController::computedStyleIncludingVisitedInfo(JSValueRef element)
2120617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen{
2130617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    // FIXME: Is it OK this works only for the main frame?
214e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page());
2150617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
2160617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    if (!JSValueIsObject(context, element))
2170617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen        return JSValueMakeUndefined(context);
2180617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    JSValueRef value = WKBundleFrameGetComputedStyleIncludingVisitedInfo(mainFrame, const_cast<JSObjectRef>(element));
2190617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    if (!value)
2200617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen        return JSValueMakeUndefined(context);
2210617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    return value;
2220617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen}
2230617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen
2240617145a89917ae7735fe1c9538688ab9a577df5Kristian MonsenJSRetainPtr<JSStringRef> LayoutTestController::counterValueForElementById(JSStringRef elementId)
2250617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen{
2260617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page());
2270617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    JSObjectRef element = getElementById(mainFrame, elementId);
2280617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    if (!element)
2290617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen        return 0;
2300617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    WKRetainPtr<WKStringRef> value(AdoptWK, WKBundleFrameCopyCounterValue(mainFrame, const_cast<JSObjectRef>(element)));
2310617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    return toJS(value);
2320617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen}
2330617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen
2340617145a89917ae7735fe1c9538688ab9a577df5Kristian MonsenJSRetainPtr<JSStringRef> LayoutTestController::markerTextForListItem(JSValueRef element)
2350617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen{
2360617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page());
2370617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
2380617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    if (!element || !JSValueIsObject(context, element))
2390617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen        return 0;
2400617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    WKRetainPtr<WKStringRef> text(AdoptWK, WKBundleFrameCopyMarkerText(mainFrame, const_cast<JSObjectRef>(element)));
2410617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    if (WKStringIsEmpty(text.get()))
2420617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen        return 0;
2430617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    return toJS(text);
2440617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen}
2450617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen
2460617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsenvoid LayoutTestController::execCommand(JSStringRef name, JSStringRef argument)
2470617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen{
2480617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    WKBundlePageExecuteEditingCommand(InjectedBundle::shared().page()->page(), toWK(name).get(), toWK(argument).get());
2490617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen}
2500617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen
251f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochbool LayoutTestController::findString(JSStringRef target, JSValueRef optionsArrayAsValue)
252f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
253f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    WKFindOptions options = 0;
254f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
255f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page());
256f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
257f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    JSRetainPtr<JSStringRef> lengthPropertyName(Adopt, JSStringCreateWithUTF8CString("length"));
258f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    JSObjectRef optionsArray = JSValueToObject(context, optionsArrayAsValue, 0);
259f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    JSValueRef lengthValue = JSObjectGetProperty(context, optionsArray, lengthPropertyName.get(), 0);
260f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (!JSValueIsNumber(context, lengthValue))
261f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        return false;
262f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
263f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    size_t length = static_cast<size_t>(JSValueToNumber(context, lengthValue, 0));
264f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    for (size_t i = 0; i < length; ++i) {
265f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        JSValueRef value = JSObjectGetPropertyAtIndex(context, optionsArray, i, 0);
266f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        if (!JSValueIsString(context, value))
267f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            continue;
268f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
269f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        JSRetainPtr<JSStringRef> optionName(Adopt, JSValueToStringCopy(context, value, 0));
270f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
271f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        if (JSStringIsEqualToUTF8CString(optionName.get(), "CaseInsensitive"))
272f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            options |= kWKFindOptionsCaseInsensitive;
273f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        else if (JSStringIsEqualToUTF8CString(optionName.get(), "AtWordStarts"))
274f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            options |= kWKFindOptionsAtWordStarts;
275f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        else if (JSStringIsEqualToUTF8CString(optionName.get(), "TreatMedialCapitalAsWordStart"))
276f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            options |= kWKFindOptionsTreatMedialCapitalAsWordStart;
277f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        else if (JSStringIsEqualToUTF8CString(optionName.get(), "Backwards"))
278f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            options |= kWKFindOptionsBackwards;
279f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        else if (JSStringIsEqualToUTF8CString(optionName.get(), "WrapAround"))
280f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            options |= kWKFindOptionsWrapAround;
281f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        else if (JSStringIsEqualToUTF8CString(optionName.get(), "StartInSelection")) {
282f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            // FIXME: No kWKFindOptionsStartInSelection.
283f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        }
284f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    }
285f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
286f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    return WKBundlePageFindString(InjectedBundle::shared().page()->page(), toWK(target).get(), options);
287f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
288f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
2890617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsenbool LayoutTestController::isCommandEnabled(JSStringRef name)
2900617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen{
2910617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    return WKBundlePageIsEditingCommandEnabled(InjectedBundle::shared().page()->page(), toWK(name).get());
292e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke}
293e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
294db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Blockvoid LayoutTestController::setCanOpenWindows(bool)
295db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block{
296db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    // It's not clear if or why any tests require opening windows be forbidden.
297db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    // For now, just ignore this setting, and if we find later it's needed we can add it.
298db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block}
299db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block
3005ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenvoid LayoutTestController::setXSSAuditorEnabled(bool enabled)
3015ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen{
302f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    WKBundleOverrideXSSAuditorEnabledForTestRunner(InjectedBundle::shared().bundle(), InjectedBundle::shared().pageGroup(), true);
3035ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen}
3045ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
3052bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid LayoutTestController::setAllowUniversalAccessFromFileURLs(bool enabled)
3062bde8e466a4451c7319e3a072d118917957d6554Steve Block{
3072bde8e466a4451c7319e3a072d118917957d6554Steve Block    WKBundleOverrideAllowUniversalAccessFromFileURLsForTestRunner(InjectedBundle::shared().bundle(), InjectedBundle::shared().pageGroup(), enabled);
3082bde8e466a4451c7319e3a072d118917957d6554Steve Block}
3092bde8e466a4451c7319e3a072d118917957d6554Steve Block
310db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Blockunsigned LayoutTestController::windowCount()
311db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block{
312db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    return InjectedBundle::shared().pageCount();
313db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block}
314db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block
315e14391e94c850b8bd03680c23b38978db68687a8John Reckvoid LayoutTestController::clearBackForwardList()
316e14391e94c850b8bd03680c23b38978db68687a8John Reck{
317e14391e94c850b8bd03680c23b38978db68687a8John Reck    WKBundleBackForwardListClear(WKBundlePageGetBackForwardList(InjectedBundle::shared().page()->page()));
318e14391e94c850b8bd03680c23b38978db68687a8John Reck}
319e14391e94c850b8bd03680c23b38978db68687a8John Reck
320ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block// Object Creation
321ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block
322ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Blockvoid LayoutTestController::makeWindowObject(JSContextRef context, JSObjectRef windowObject, JSValueRef* exception)
323ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block{
3240617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    setProperty(context, windowObject, "layoutTestController", this, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, exception);
325ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block}
326ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block
3272fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockvoid LayoutTestController::showWebInspector()
3282fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
3292fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    WKBundleInspectorShow(WKBundlePageGetInspector(InjectedBundle::shared().page()->page()));
3302fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
3312fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
3322fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockvoid LayoutTestController::closeWebInspector()
3332fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
3342fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    WKBundleInspectorClose(WKBundlePageGetInspector(InjectedBundle::shared().page()->page()));
3352fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
3362fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
3372fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockvoid LayoutTestController::evaluateInWebInspector(long callID, JSStringRef script)
3382fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
3392fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    WKRetainPtr<WKStringRef> scriptWK = toWK(script);
3402fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    WKBundleInspectorEvaluateScriptForTest(WKBundlePageGetInspector(InjectedBundle::shared().page()->page()), callID, scriptWK.get());
3412fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
3422fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
3432fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockvoid LayoutTestController::setTimelineProfilingEnabled(bool enabled)
3442fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
3452fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    WKBundleInspectorSetPageProfilingEnabled(WKBundlePageGetInspector(InjectedBundle::shared().page()->page()), enabled);
3462fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
3472fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
348ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdochtypedef WTF::HashMap<unsigned, WKRetainPtr<WKBundleScriptWorldRef> > WorldMap;
349ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdochstatic WorldMap& worldMap()
350ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch{
351ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    static WorldMap& map = *new WorldMap;
352ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    return map;
353ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch}
354ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
355ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdochunsigned LayoutTestController::worldIDForWorld(WKBundleScriptWorldRef world)
356ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch{
357ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    WorldMap::const_iterator end = worldMap().end();
358ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    for (WorldMap::const_iterator it = worldMap().begin(); it != end; ++it) {
359ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        if (it->second == world)
360ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch            return it->first;
361ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    }
362ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
363ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    return 0;
364ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch}
365ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
366ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdochvoid LayoutTestController::evaluateScriptInIsolatedWorld(JSContextRef context, unsigned worldID, JSStringRef script)
367ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch{
368ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    // A worldID of 0 always corresponds to a new world. Any other worldID corresponds to a world
369ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    // that is created once and cached forever.
370ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    WKRetainPtr<WKBundleScriptWorldRef> world;
371ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    if (!worldID)
372ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        world.adopt(WKBundleScriptWorldCreateWorld());
373ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    else {
374ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        WKRetainPtr<WKBundleScriptWorldRef>& worldSlot = worldMap().add(worldID, 0).first->second;
375ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        if (!worldSlot)
376ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch            worldSlot.adopt(WKBundleScriptWorldCreateWorld());
377ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        world = worldSlot;
378ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    }
379ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
380ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    WKBundleFrameRef frame = WKBundleFrameForJavaScriptContext(context);
381ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    if (!frame)
382ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        frame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page());
383ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
384ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    JSGlobalContextRef jsContext = WKBundleFrameGetJavaScriptContextForWorld(frame, world.get());
385ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    JSEvaluateScript(jsContext, script, 0, 0, 0, 0);
386ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch}
387ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
3882fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockvoid LayoutTestController::setPOSIXLocale(JSStringRef locale)
3892fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
3902fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    char localeBuf[32];
3912fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    JSStringGetUTF8CString(locale, localeBuf, sizeof(localeBuf));
3922fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    setlocale(LC_ALL, localeBuf);
3932fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
3942fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
395ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block} // namespace WTR
396