OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (C) 2012 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 "InjectedBundleTest.h" | |
28 #include <WebKit2/WKBundleDOMWindowExtension.h> | |
29 #include <WebKit2/WKBundleFrame.h> | |
30 #include <WebKit2/WKBundlePage.h> | |
31 #include <WebKit2/WKBundlePageGroup.h> | |
32 #include <WebKit2/WKBundlePrivate.h> | |
33 #include <WebKit2/WKBundleScriptWorld.h> | |
34 #include <WebKit2/WKRetainPtr.h> | |
35 #include <wtf/HashMap.h> | |
36 #include <assert.h> | |
37 | |
38 namespace TestWebKitAPI { | |
39 | |
40 static void didFinishLoadForFrameCallback(WKBundlePageRef, WKBundleFrameRef, WKT
ypeRef*, const void* clientInfo); | |
41 static void globalObjectIsAvailableForFrameCallback(WKBundlePageRef, WKBundleFra
meRef, WKBundleScriptWorldRef, const void* clientInfo); | |
42 static void willDisconnectDOMWindowExtensionFromGlobalObjectCallback(WKBundlePag
eRef, WKBundleDOMWindowExtensionRef, const void* clientInfo); | |
43 static void didReconnectDOMWindowExtensionToGlobalObjectCallback(WKBundlePageRef
, WKBundleDOMWindowExtensionRef, const void* clientInfo); | |
44 static void willDestroyGlobalObjectForDOMWindowExtensionCallback(WKBundlePageRef
, WKBundleDOMWindowExtensionRef, const void* clientInfo); | |
45 | |
46 enum ExtensionState { | |
47 Uncreated = 0, Connected, Disconnected, Destroyed, Removed | |
48 }; | |
49 | |
50 const char* states[5] = { | |
51 "Uncreated", | |
52 "Connected", | |
53 "Disconnected", | |
54 "Destroyed", | |
55 "Removed" | |
56 }; | |
57 | |
58 typedef struct { | |
59 const char* name; | |
60 ExtensionState state; | |
61 } ExtensionRecord; | |
62 | |
63 class DOMWindowExtensionNoCache : public InjectedBundleTest { | |
64 public: | |
65 DOMWindowExtensionNoCache(const std::string& identifier); | |
66 | |
67 virtual void initialize(WKBundleRef, WKTypeRef userData); | |
68 virtual void didCreatePage(WKBundleRef, WKBundlePageRef); | |
69 virtual void willDestroyPage(WKBundleRef, WKBundlePageRef); | |
70 | |
71 void globalObjectIsAvailableForFrame(WKBundleFrameRef, WKBundleScriptWorldRe
f); | |
72 void willDisconnectDOMWindowExtensionFromGlobalObject(WKBundleDOMWindowExten
sionRef); | |
73 void didReconnectDOMWindowExtensionToGlobalObject(WKBundleDOMWindowExtension
Ref); | |
74 void willDestroyGlobalObjectForDOMWindowExtension(WKBundleDOMWindowExtension
Ref); | |
75 | |
76 void frameLoadFinished(WKBundleFrameRef); | |
77 | |
78 private: | |
79 void updateExtensionStateRecord(WKBundleDOMWindowExtensionRef, ExtensionStat
e); | |
80 void sendExtensionStateMessage(); | |
81 void sendBundleMessage(const char*); | |
82 | |
83 WKBundleRef m_bundle; | |
84 ExtensionRecord m_extensionRecords[10]; | |
85 HashMap<WKBundleDOMWindowExtensionRef, int> m_extensionToRecordMap; | |
86 int m_numberMainFrameLoads; | |
87 }; | |
88 | |
89 static InjectedBundleTest::Register<DOMWindowExtensionNoCache> registrar("DOMWin
dowExtensionNoCache"); | |
90 | |
91 DOMWindowExtensionNoCache::DOMWindowExtensionNoCache(const std::string& identifi
er) | |
92 : InjectedBundleTest(identifier) | |
93 , m_numberMainFrameLoads(0) | |
94 { | |
95 m_extensionRecords[0].name = "First page, main frame, standard world"; | |
96 m_extensionRecords[1].name = "First page, main frame, non-standard world"; | |
97 m_extensionRecords[2].name = "First page, subframe, standard world"; | |
98 m_extensionRecords[3].name = "First page, subframe, non-standard world"; | |
99 m_extensionRecords[4].name = "Second page, main frame, standard world"; | |
100 m_extensionRecords[5].name = "Second page, main frame, non-standard world"; | |
101 m_extensionRecords[6].name = "First page, main frame, standard world"; | |
102 m_extensionRecords[7].name = "First page, main frame, non-standard world"; | |
103 m_extensionRecords[8].name = "First page, subframe, standard world"; | |
104 m_extensionRecords[9].name = "First page, subframe, non-standard world"; | |
105 | |
106 for (size_t i = 0; i < 10; ++i) | |
107 m_extensionRecords[i].state = Uncreated; | |
108 } | |
109 | |
110 void DOMWindowExtensionNoCache::frameLoadFinished(WKBundleFrameRef frame) | |
111 { | |
112 bool mainFrame = !WKBundleFrameGetParentFrame(frame); | |
113 if (mainFrame) | |
114 m_numberMainFrameLoads++; | |
115 | |
116 char body[16384]; | |
117 sprintf(body, "%s finished loading", mainFrame ? "Main frame" : "Subframe"); | |
118 | |
119 // Only consider load finished for the main frame | |
120 const char* name = mainFrame ? "DidFinishLoadForMainFrame" : "DidFinishLoadF
orFrame"; | |
121 | |
122 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString
(name)); | |
123 WKRetainPtr<WKStringRef> messageBody = adoptWK(WKStringCreateWithUTF8CString
(body)); | |
124 WKBundlePostMessage(m_bundle, messageName.get(), messageBody.get()); | |
125 | |
126 sendExtensionStateMessage(); | |
127 } | |
128 | |
129 void DOMWindowExtensionNoCache::sendExtensionStateMessage() | |
130 { | |
131 char body[16384]; | |
132 sprintf(body, "Extension states:\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %
s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s", | |
133 m_extensionRecords[0].name, states[m_extensionRecords[0].state], | |
134 m_extensionRecords[1].name, states[m_extensionRecords[1].state], | |
135 m_extensionRecords[2].name, states[m_extensionRecords[2].state], | |
136 m_extensionRecords[3].name, states[m_extensionRecords[3].state], | |
137 m_extensionRecords[4].name, states[m_extensionRecords[4].state], | |
138 m_extensionRecords[5].name, states[m_extensionRecords[5].state], | |
139 m_extensionRecords[6].name, states[m_extensionRecords[6].state], | |
140 m_extensionRecords[7].name, states[m_extensionRecords[7].state], | |
141 m_extensionRecords[8].name, states[m_extensionRecords[8].state], | |
142 m_extensionRecords[9].name, states[m_extensionRecords[9].state]); | |
143 | |
144 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString
("ExtensionStates")); | |
145 WKRetainPtr<WKStringRef> messageBody = adoptWK(WKStringCreateWithUTF8CString
(body)); | |
146 WKBundlePostMessage(m_bundle, messageName.get(), messageBody.get()); | |
147 } | |
148 | |
149 void DOMWindowExtensionNoCache::initialize(WKBundleRef bundle, WKTypeRef userDat
a) | |
150 { | |
151 assert(WKGetTypeID(userData) == WKBundlePageGroupGetTypeID()); | |
152 WKBundlePageGroupRef pageGroup = static_cast<WKBundlePageGroupRef>(userData)
; | |
153 | |
154 WKRetainPtr<WKStringRef> source(AdoptWK, WKStringCreateWithUTF8CString("aler
t('Unimportant alert');")); | |
155 WKBundleAddUserScript(bundle, pageGroup, WKBundleScriptWorldCreateWorld(), s
ource.get(), 0, 0, 0, kWKInjectAtDocumentStart, kWKInjectInAllFrames); | |
156 } | |
157 | |
158 void DOMWindowExtensionNoCache::didCreatePage(WKBundleRef bundle, WKBundlePageRe
f page) | |
159 { | |
160 m_bundle = bundle; | |
161 | |
162 WKBundlePageLoaderClient pageLoaderClient; | |
163 memset(&pageLoaderClient, 0, sizeof(pageLoaderClient)); | |
164 | |
165 pageLoaderClient.version = kWKBundlePageLoaderClientCurrentVersion; | |
166 pageLoaderClient.clientInfo = this; | |
167 pageLoaderClient.didFinishLoadForFrame = didFinishLoadForFrameCallback; | |
168 pageLoaderClient.globalObjectIsAvailableForFrame = globalObjectIsAvailableFo
rFrameCallback; | |
169 pageLoaderClient.willDisconnectDOMWindowExtensionFromGlobalObject = willDisc
onnectDOMWindowExtensionFromGlobalObjectCallback; | |
170 pageLoaderClient.didReconnectDOMWindowExtensionToGlobalObject = didReconnect
DOMWindowExtensionToGlobalObjectCallback; | |
171 pageLoaderClient.willDestroyGlobalObjectForDOMWindowExtension = willDestroyG
lobalObjectForDOMWindowExtensionCallback; | |
172 | |
173 WKBundlePageSetPageLoaderClient(page, &pageLoaderClient); | |
174 } | |
175 | |
176 void DOMWindowExtensionNoCache::willDestroyPage(WKBundleRef, WKBundlePageRef) | |
177 { | |
178 HashMap<WKBundleDOMWindowExtensionRef, int>::iterator it = m_extensionToReco
rdMap.begin(); | |
179 HashMap<WKBundleDOMWindowExtensionRef, int>::iterator end = m_extensionToRec
ordMap.end(); | |
180 for (; it != end; ++it) { | |
181 updateExtensionStateRecord(it->key, Removed); | |
182 WKRelease(it->key); | |
183 } | |
184 | |
185 m_extensionToRecordMap.clear(); | |
186 | |
187 sendExtensionStateMessage(); | |
188 sendBundleMessage("TestComplete"); | |
189 } | |
190 | |
191 void DOMWindowExtensionNoCache::updateExtensionStateRecord(WKBundleDOMWindowExte
nsionRef extension, ExtensionState state) | |
192 { | |
193 int index = m_extensionToRecordMap.get(extension); | |
194 m_extensionRecords[index].state = state; | |
195 } | |
196 | |
197 void DOMWindowExtensionNoCache::sendBundleMessage(const char* message) | |
198 { | |
199 WKRetainPtr<WKStringRef> wkMessage = adoptWK(WKStringCreateWithUTF8CString(m
essage)); | |
200 WKBundlePostMessage(m_bundle, wkMessage.get(), wkMessage.get()); | |
201 } | |
202 | |
203 void DOMWindowExtensionNoCache::globalObjectIsAvailableForFrame(WKBundleFrameRef
frame, WKBundleScriptWorldRef world) | |
204 { | |
205 WKBundleDOMWindowExtensionRef extension = WKBundleDOMWindowExtensionCreate(f
rame, world); | |
206 | |
207 int index; | |
208 bool standard; | |
209 standard = world == WKBundleScriptWorldNormalWorld(); | |
210 | |
211 bool mainFrame = !WKBundleFrameGetParentFrame(frame); | |
212 switch (m_numberMainFrameLoads) { | |
213 case 0: | |
214 index = mainFrame ? (standard ? 0 : 1) : (standard ? 2 : 3); | |
215 break; | |
216 case 1: | |
217 index = standard ? 4 : 5; | |
218 break; | |
219 case 2: | |
220 index = mainFrame ? (standard ? 6 : 7) : (standard ? 8 : 9); | |
221 break; | |
222 default: | |
223 ASSERT_NOT_REACHED(); | |
224 break; | |
225 } | |
226 | |
227 m_extensionToRecordMap.set(extension, index); | |
228 | |
229 updateExtensionStateRecord(extension, Connected); | |
230 sendBundleMessage("GlobalObjectIsAvailableForFrame called"); | |
231 } | |
232 | |
233 void DOMWindowExtensionNoCache::willDisconnectDOMWindowExtensionFromGlobalObject
(WKBundleDOMWindowExtensionRef extension) | |
234 { | |
235 // No items should be going into a 0-capacity page cache. | |
236 ASSERT_NOT_REACHED(); | |
237 } | |
238 | |
239 void DOMWindowExtensionNoCache::didReconnectDOMWindowExtensionToGlobalObject(WKB
undleDOMWindowExtensionRef) | |
240 { | |
241 // No items should be coming out of a 0-capacity page cache. | |
242 ASSERT_NOT_REACHED(); | |
243 } | |
244 | |
245 void DOMWindowExtensionNoCache::willDestroyGlobalObjectForDOMWindowExtension(WKB
undleDOMWindowExtensionRef extension) | |
246 { | |
247 sendBundleMessage("WillDestroyDOMWindowExtensionToGlobalObject called"); | |
248 updateExtensionStateRecord(extension, Destroyed); | |
249 m_extensionToRecordMap.remove(extension); | |
250 WKRelease(extension); | |
251 } | |
252 | |
253 static void didFinishLoadForFrameCallback(WKBundlePageRef, WKBundleFrameRef fram
e, WKTypeRef*, const void *clientInfo) | |
254 { | |
255 ((DOMWindowExtensionNoCache*)clientInfo)->frameLoadFinished(frame); | |
256 } | |
257 | |
258 static void globalObjectIsAvailableForFrameCallback(WKBundlePageRef, WKBundleFra
meRef frame, WKBundleScriptWorldRef world, const void* clientInfo) | |
259 { | |
260 ((DOMWindowExtensionNoCache*)clientInfo)->globalObjectIsAvailableForFrame(fr
ame, world); | |
261 } | |
262 | |
263 static void willDisconnectDOMWindowExtensionFromGlobalObjectCallback(WKBundlePag
eRef, WKBundleDOMWindowExtensionRef extension, const void* clientInfo) | |
264 { | |
265 ((DOMWindowExtensionNoCache*)clientInfo)->willDisconnectDOMWindowExtensionFr
omGlobalObject(extension); | |
266 } | |
267 | |
268 static void didReconnectDOMWindowExtensionToGlobalObjectCallback(WKBundlePageRef
, WKBundleDOMWindowExtensionRef extension, const void* clientInfo) | |
269 { | |
270 ((DOMWindowExtensionNoCache*)clientInfo)->didReconnectDOMWindowExtensionToGl
obalObject(extension); | |
271 } | |
272 | |
273 static void willDestroyGlobalObjectForDOMWindowExtensionCallback(WKBundlePageRef
, WKBundleDOMWindowExtensionRef extension , const void* clientInfo) | |
274 { | |
275 ((DOMWindowExtensionNoCache*)clientInfo)->willDestroyGlobalObjectForDOMWindo
wExtension(extension); | |
276 } | |
277 | |
278 } // namespace TestWebKitAPI | |
OLD | NEW |