InjectedBundle.cpp revision 2bde8e466a4451c7319e3a072d118917957d6554
1/*
2 * Copyright (C) 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 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "InjectedBundle.h"
28
29#include "ActivateFonts.h"
30#include "InjectedBundlePage.h"
31#include "StringFunctions.h"
32#include <WebKit2/WKBundle.h>
33#include <WebKit2/WKBundlePage.h>
34#include <WebKit2/WKBundlePagePrivate.h>
35#include <WebKit2/WKBundlePrivate.h>
36#include <WebKit2/WKRetainPtr.h>
37#include <WebKit2/WebKit2.h>
38#include <wtf/PassOwnPtr.h>
39#include <wtf/Vector.h>
40
41namespace WTR {
42
43InjectedBundle& InjectedBundle::shared()
44{
45    static InjectedBundle& shared = *new InjectedBundle;
46    return shared;
47}
48
49InjectedBundle::InjectedBundle()
50    : m_bundle(0)
51    , m_topLoadingFrame(0)
52    , m_state(Idle)
53    , m_dumpPixels(false)
54{
55}
56
57void InjectedBundle::didCreatePage(WKBundleRef bundle, WKBundlePageRef page, const void* clientInfo)
58{
59    static_cast<InjectedBundle*>(const_cast<void*>(clientInfo))->didCreatePage(page);
60}
61
62void InjectedBundle::willDestroyPage(WKBundleRef bundle, WKBundlePageRef page, const void* clientInfo)
63{
64    static_cast<InjectedBundle*>(const_cast<void*>(clientInfo))->willDestroyPage(page);
65}
66
67void InjectedBundle::didInitializePageGroup(WKBundleRef bundle, WKBundlePageGroupRef pageGroup, const void* clientInfo)
68{
69    static_cast<InjectedBundle*>(const_cast<void*>(clientInfo))->didInitializePageGroup(pageGroup);
70}
71
72void InjectedBundle::didReceiveMessage(WKBundleRef bundle, WKStringRef messageName, WKTypeRef messageBody, const void *clientInfo)
73{
74    static_cast<InjectedBundle*>(const_cast<void*>(clientInfo))->didReceiveMessage(messageName, messageBody);
75}
76
77void InjectedBundle::initialize(WKBundleRef bundle, WKTypeRef initializationUserData)
78{
79    m_bundle = bundle;
80
81    WKBundleClient client = {
82        0,
83        this,
84        didCreatePage,
85        willDestroyPage,
86        didInitializePageGroup,
87        didReceiveMessage
88    };
89    WKBundleSetClient(m_bundle, &client);
90
91    platformInitialize(initializationUserData);
92
93    activateFonts();
94    WKBundleActivateMacFontAscentHack(m_bundle);
95}
96
97void InjectedBundle::didCreatePage(WKBundlePageRef page)
98{
99    m_pages.append(adoptPtr(new InjectedBundlePage(page)));
100}
101
102void InjectedBundle::willDestroyPage(WKBundlePageRef page)
103{
104    size_t size = m_pages.size();
105    for (size_t i = 0; i < size; ++i) {
106        if (m_pages[i]->page() == page) {
107            m_pages.remove(i);
108            break;
109        }
110    }
111}
112
113void InjectedBundle::didInitializePageGroup(WKBundlePageGroupRef pageGroup)
114{
115    m_pageGroup = pageGroup;
116}
117
118InjectedBundlePage* InjectedBundle::page() const
119{
120    // It might be better to have the UI process send over a reference to the main
121    // page instead of just assuming it's the first one.
122    return m_pages[0].get();
123}
124
125void InjectedBundle::resetLocalSettings()
126{
127    setlocale(LC_ALL, "");
128}
129
130void InjectedBundle::didReceiveMessage(WKStringRef messageName, WKTypeRef messageBody)
131{
132    if (WKStringIsEqualToUTF8CString(messageName, "BeginTest")) {
133        ASSERT(messageBody);
134        ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID());
135        m_dumpPixels = WKBooleanGetValue(static_cast<WKBooleanRef>(messageBody));
136
137        WKRetainPtr<WKStringRef> ackMessageName(AdoptWK, WKStringCreateWithUTF8CString("Ack"));
138        WKRetainPtr<WKStringRef> ackMessageBody(AdoptWK, WKStringCreateWithUTF8CString("BeginTest"));
139        WKBundlePostMessage(m_bundle, ackMessageName.get(), ackMessageBody.get());
140
141        beginTesting();
142        return;
143    } else if (WKStringIsEqualToUTF8CString(messageName, "Reset")) {
144        m_state = Idle;
145        m_dumpPixels = false;
146
147        resetLocalSettings();
148
149        return;
150    }
151
152    WKRetainPtr<WKStringRef> errorMessageName(AdoptWK, WKStringCreateWithUTF8CString("Error"));
153    WKRetainPtr<WKStringRef> errorMessageBody(AdoptWK, WKStringCreateWithUTF8CString("Unknown"));
154    WKBundlePostMessage(m_bundle, errorMessageName.get(), errorMessageBody.get());
155}
156
157void InjectedBundle::beginTesting()
158{
159    m_state = Testing;
160
161    m_outputStream.str("");
162    m_pixelResult.clear();
163
164    m_layoutTestController = LayoutTestController::create();
165    m_gcController = GCController::create();
166    m_eventSendingController = EventSendingController::create();
167
168    WKBundleSetShouldTrackVisitedLinks(m_bundle, false);
169    WKBundleRemoveAllVisitedLinks(m_bundle);
170    WKBundleOverrideAllowUniversalAccessFromFileURLsForTestRunner(m_bundle, m_pageGroup, true);
171
172    WKBundleRemoveAllUserContent(m_bundle, m_pageGroup);
173
174    page()->reset();
175}
176
177void InjectedBundle::done()
178{
179    m_state = Stopping;
180
181    page()->stopLoading();
182    setTopLoadingFrame(0);
183
184    WKRetainPtr<WKStringRef> doneMessageName(AdoptWK, WKStringCreateWithUTF8CString("Done"));
185    WKRetainPtr<WKMutableDictionaryRef> doneMessageBody(AdoptWK, WKMutableDictionaryCreate());
186
187    WKRetainPtr<WKStringRef> textOutputKey(AdoptWK, WKStringCreateWithUTF8CString("TextOutput"));
188    WKRetainPtr<WKStringRef> textOutput(AdoptWK, WKStringCreateWithUTF8CString(m_outputStream.str().c_str()));
189    WKDictionaryAddItem(doneMessageBody.get(), textOutputKey.get(), textOutput.get());
190
191    WKRetainPtr<WKStringRef> pixelResultKey = adoptWK(WKStringCreateWithUTF8CString("PixelResult"));
192    WKDictionaryAddItem(doneMessageBody.get(), pixelResultKey.get(), m_pixelResult.get());
193
194    WKBundlePostMessage(m_bundle, doneMessageName.get(), doneMessageBody.get());
195
196    closeOtherPages();
197
198    m_state = Idle;
199}
200
201void InjectedBundle::closeOtherPages()
202{
203    Vector<WKBundlePageRef> pagesToClose;
204    size_t size = m_pages.size();
205    for (size_t i = 1; i < size; ++i)
206        pagesToClose.append(m_pages[i]->page());
207    size = pagesToClose.size();
208    for (size_t i = 0; i < size; ++i)
209        WKBundlePageClose(pagesToClose[i]);
210}
211
212void InjectedBundle::dumpBackForwardListsForAllPages()
213{
214    size_t size = m_pages.size();
215    for (size_t i = 0; i < size; ++i)
216        m_pages[i]->dumpBackForwardList();
217}
218
219} // namespace WTR
220