InjectedBundle.cpp revision 2fc2651226baac27029e38c9d6ef883fa32084db
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 "InjectedBundle.h"
27
28#include "ActivateFonts.h"
29#include "InjectedBundlePage.h"
30#include "StringFunctions.h"
31#include <WebKit2/WKBundle.h>
32#include <WebKit2/WKBundlePage.h>
33#include <WebKit2/WKBundlePagePrivate.h>
34#include <WebKit2/WKBundlePrivate.h>
35#include <WebKit2/WKRetainPtr.h>
36#include <WebKit2/WebKit2.h>
37#include <wtf/PassOwnPtr.h>
38#include <wtf/Vector.h>
39
40namespace WTR {
41
42InjectedBundle& InjectedBundle::shared()
43{
44    static InjectedBundle& shared = *new InjectedBundle;
45    return shared;
46}
47
48InjectedBundle::InjectedBundle()
49    : m_bundle(0)
50    , m_topLoadingFrame(0)
51    , m_state(Idle)
52{
53}
54
55void InjectedBundle::didCreatePage(WKBundleRef bundle, WKBundlePageRef page, const void* clientInfo)
56{
57    static_cast<InjectedBundle*>(const_cast<void*>(clientInfo))->didCreatePage(page);
58}
59
60void InjectedBundle::willDestroyPage(WKBundleRef bundle, WKBundlePageRef page, const void* clientInfo)
61{
62    static_cast<InjectedBundle*>(const_cast<void*>(clientInfo))->willDestroyPage(page);
63}
64
65void InjectedBundle::didInitializePageGroup(WKBundleRef bundle, WKBundlePageGroupRef pageGroup, const void* clientInfo)
66{
67    static_cast<InjectedBundle*>(const_cast<void*>(clientInfo))->didInitializePageGroup(pageGroup);
68}
69
70void InjectedBundle::didReceiveMessage(WKBundleRef bundle, WKStringRef messageName, WKTypeRef messageBody, const void *clientInfo)
71{
72    static_cast<InjectedBundle*>(const_cast<void*>(clientInfo))->didReceiveMessage(messageName, messageBody);
73}
74
75void InjectedBundle::initialize(WKBundleRef bundle)
76{
77    m_bundle = bundle;
78
79    WKBundleClient client = {
80        0,
81        this,
82        didCreatePage,
83        willDestroyPage,
84        didInitializePageGroup,
85        didReceiveMessage
86    };
87    WKBundleSetClient(m_bundle, &client);
88
89    activateFonts();
90    WKBundleActivateMacFontAscentHack(m_bundle);
91}
92
93void InjectedBundle::didCreatePage(WKBundlePageRef page)
94{
95    m_pages.append(adoptPtr(new InjectedBundlePage(page)));
96}
97
98void InjectedBundle::willDestroyPage(WKBundlePageRef page)
99{
100    size_t size = m_pages.size();
101    for (size_t i = 0; i < size; ++i) {
102        if (m_pages[i]->page() == page) {
103            m_pages.remove(i);
104            break;
105        }
106    }
107}
108
109void InjectedBundle::didInitializePageGroup(WKBundlePageGroupRef pageGroup)
110{
111    m_pageGroup = pageGroup;
112}
113
114InjectedBundlePage* InjectedBundle::page() const
115{
116    // It might be better to have the UI process send over a reference to the main
117    // page instead of just assuming it's the first one.
118    return m_pages[0].get();
119}
120
121void InjectedBundle::resetLocalSettings()
122{
123    setlocale(LC_ALL, "");
124}
125
126void InjectedBundle::didReceiveMessage(WKStringRef messageName, WKTypeRef messageBody)
127{
128    if (WKStringIsEqualToUTF8CString(messageName, "BeginTest")) {
129        ASSERT(!messageBody);
130
131        WKRetainPtr<WKStringRef> ackMessageName(AdoptWK, WKStringCreateWithUTF8CString("Ack"));
132        WKRetainPtr<WKStringRef> ackMessageBody(AdoptWK, WKStringCreateWithUTF8CString("BeginTest"));
133        WKBundlePostMessage(m_bundle, ackMessageName.get(), ackMessageBody.get());
134
135        beginTesting();
136        return;
137    } else if (WKStringIsEqualToUTF8CString(messageName, "Reset")) {
138        m_state = Idle;
139
140        resetLocalSettings();
141
142        return;
143    }
144
145    WKRetainPtr<WKStringRef> errorMessageName(AdoptWK, WKStringCreateWithUTF8CString("Error"));
146    WKRetainPtr<WKStringRef> errorMessageBody(AdoptWK, WKStringCreateWithUTF8CString("Unknown"));
147    WKBundlePostMessage(m_bundle, errorMessageName.get(), errorMessageBody.get());
148}
149
150void InjectedBundle::beginTesting()
151{
152    m_state = Testing;
153
154    m_outputStream.str("");
155
156    m_layoutTestController = LayoutTestController::create();
157    m_gcController = GCController::create();
158    m_eventSendingController = EventSendingController::create();
159
160    WKBundleSetShouldTrackVisitedLinks(m_bundle, false);
161    WKBundleRemoveAllVisitedLinks(m_bundle);
162
163    WKBundleRemoveAllUserContent(m_bundle, m_pageGroup);
164
165    page()->reset();
166}
167
168void InjectedBundle::done()
169{
170    m_state = Stopping;
171
172    page()->stopLoading();
173    setTopLoadingFrame(0);
174
175    WKRetainPtr<WKStringRef> doneMessageName(AdoptWK, WKStringCreateWithUTF8CString("Done"));
176    WKRetainPtr<WKStringRef> doneMessageBody(AdoptWK, WKStringCreateWithUTF8CString(m_outputStream.str().c_str()));
177
178    WKBundlePostMessage(m_bundle, doneMessageName.get(), doneMessageBody.get());
179
180    closeOtherPages();
181
182    m_state = Idle;
183}
184
185void InjectedBundle::closeOtherPages()
186{
187    Vector<WKBundlePageRef> pagesToClose;
188    size_t size = m_pages.size();
189    for (size_t i = 1; i < size; ++i)
190        pagesToClose.append(m_pages[i]->page());
191    size = pagesToClose.size();
192    for (size_t i = 0; i < size; ++i)
193        WKBundlePageClose(pagesToClose[i]);
194}
195
196void InjectedBundle::dumpBackForwardListsForAllPages()
197{
198    size_t size = m_pages.size();
199    for (size_t i = 0; i < size; ++i)
200        m_pages[i]->dumpBackForwardList();
201}
202
203} // namespace WTR
204