initial import
[vuplus_webkit] / Tools / WebKitTestRunner / InjectedBundle / InjectedBundle.cpp
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
41 namespace WTR {
42
43 InjectedBundle& InjectedBundle::shared()
44 {
45     static InjectedBundle& shared = *new InjectedBundle;
46     return shared;
47 }
48
49 InjectedBundle::InjectedBundle()
50     : m_bundle(0)
51     , m_topLoadingFrame(0)
52     , m_state(Idle)
53     , m_dumpPixels(false)
54 {
55 }
56
57 void InjectedBundle::didCreatePage(WKBundleRef bundle, WKBundlePageRef page, const void* clientInfo)
58 {
59     static_cast<InjectedBundle*>(const_cast<void*>(clientInfo))->didCreatePage(page);
60 }
61
62 void InjectedBundle::willDestroyPage(WKBundleRef bundle, WKBundlePageRef page, const void* clientInfo)
63 {
64     static_cast<InjectedBundle*>(const_cast<void*>(clientInfo))->willDestroyPage(page);
65 }
66
67 void InjectedBundle::didInitializePageGroup(WKBundleRef bundle, WKBundlePageGroupRef pageGroup, const void* clientInfo)
68 {
69     static_cast<InjectedBundle*>(const_cast<void*>(clientInfo))->didInitializePageGroup(pageGroup);
70 }
71
72 void 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
77 void InjectedBundle::initialize(WKBundleRef bundle, WKTypeRef initializationUserData)
78 {
79     m_bundle = bundle;
80
81     WKBundleClient client = {
82         kWKBundleClientCurrentVersion,
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
97 void InjectedBundle::didCreatePage(WKBundlePageRef page)
98 {
99     m_pages.append(adoptPtr(new InjectedBundlePage(page)));
100 }
101
102 void 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
113 void InjectedBundle::didInitializePageGroup(WKBundlePageGroupRef pageGroup)
114 {
115     m_pageGroup = pageGroup;
116 }
117
118 InjectedBundlePage* 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
125 void InjectedBundle::resetLocalSettings()
126 {
127     setlocale(LC_ALL, "");
128 }
129
130 void 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         ASSERT(messageBody);
145         ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
146         WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
147
148         WKRetainPtr<WKStringRef> shouldGCKey(AdoptWK, WKStringCreateWithUTF8CString("ShouldGC"));
149         bool shouldGC = WKBooleanGetValue(static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, shouldGCKey.get())));
150
151         if (shouldGC)
152             WKBundleGarbageCollectJavaScriptObjects(m_bundle);
153
154         m_state = Idle;
155         m_dumpPixels = false;
156
157         resetLocalSettings();
158
159         return;
160     }
161
162     WKRetainPtr<WKStringRef> errorMessageName(AdoptWK, WKStringCreateWithUTF8CString("Error"));
163     WKRetainPtr<WKStringRef> errorMessageBody(AdoptWK, WKStringCreateWithUTF8CString("Unknown"));
164     WKBundlePostMessage(m_bundle, errorMessageName.get(), errorMessageBody.get());
165 }
166
167 void InjectedBundle::beginTesting()
168 {
169     m_state = Testing;
170
171     m_outputStream.str("");
172     m_pixelResult.clear();
173
174     m_layoutTestController = LayoutTestController::create();
175     m_gcController = GCController::create();
176     m_eventSendingController = EventSendingController::create();
177
178     WKBundleSetShouldTrackVisitedLinks(m_bundle, false);
179     WKBundleRemoveAllVisitedLinks(m_bundle);
180     WKBundleSetAllowUniversalAccessFromFileURLs(m_bundle, m_pageGroup, true);
181     WKBundleSetJavaScriptCanAccessClipboard(m_bundle, m_pageGroup, true);
182     WKBundleSetPrivateBrowsingEnabled(m_bundle, m_pageGroup, false);
183     WKBundleSwitchNetworkLoaderToNewTestingSession(m_bundle);
184     WKBundleSetAuthorAndUserStylesEnabled(m_bundle, m_pageGroup, true);
185     WKBundleSetFrameFlatteningEnabled(m_bundle, m_pageGroup, false);
186
187     WKBundleRemoveAllUserContent(m_bundle, m_pageGroup);
188
189     page()->reset();
190
191     WKBundleClearAllDatabases(m_bundle);
192     WKBundleResetOriginAccessWhitelists(m_bundle);
193 }
194
195 void InjectedBundle::done()
196 {
197     m_state = Stopping;
198
199     page()->stopLoading();
200     setTopLoadingFrame(0);
201
202     WKRetainPtr<WKStringRef> doneMessageName(AdoptWK, WKStringCreateWithUTF8CString("Done"));
203     WKRetainPtr<WKMutableDictionaryRef> doneMessageBody(AdoptWK, WKMutableDictionaryCreate());
204
205     WKRetainPtr<WKStringRef> textOutputKey(AdoptWK, WKStringCreateWithUTF8CString("TextOutput"));
206     WKRetainPtr<WKStringRef> textOutput(AdoptWK, WKStringCreateWithUTF8CString(m_outputStream.str().c_str()));
207     WKDictionaryAddItem(doneMessageBody.get(), textOutputKey.get(), textOutput.get());
208     
209     WKRetainPtr<WKStringRef> pixelResultKey = adoptWK(WKStringCreateWithUTF8CString("PixelResult"));
210     WKDictionaryAddItem(doneMessageBody.get(), pixelResultKey.get(), m_pixelResult.get());
211
212     WKBundlePostMessage(m_bundle, doneMessageName.get(), doneMessageBody.get());
213
214     closeOtherPages();
215     
216     m_state = Idle;
217 }
218
219 void InjectedBundle::closeOtherPages()
220 {
221     Vector<WKBundlePageRef> pagesToClose;
222     size_t size = m_pages.size();
223     for (size_t i = 1; i < size; ++i)
224         pagesToClose.append(m_pages[i]->page());
225     size = pagesToClose.size();
226     for (size_t i = 0; i < size; ++i)
227         WKBundlePageClose(pagesToClose[i]);
228 }
229
230 void InjectedBundle::dumpBackForwardListsForAllPages()
231 {
232     size_t size = m_pages.size();
233     for (size_t i = 0; i < size; ++i)
234         m_pages[i]->dumpBackForwardList();
235 }
236     
237 void InjectedBundle::postNewBeforeUnloadReturnValue(bool value)
238 {
239     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("BeforeUnloadReturnValue"));
240     WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value));
241     WKBundlePostMessage(m_bundle, messageName.get(), messageBody.get());
242 }
243
244 } // namespace WTR