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