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 | |
47 enum ExtensionState { | |
48 Uncreated = 0, Connected, Disconnected, Destroyed, Removed | |
49 }; | |
50 | |
51 const char* stateNames[5] = { | |
52 "Uncreated", | |
53 "Connected", | |
54 "Disconnected", | |
55 "Destroyed", | |
56 "Removed" | |
57 }; | |
58 | |
59 typedef struct { | |
60 const char* name; | |
61 ExtensionState state; | |
62 } ExtensionRecord; | |
63 | |
64 class DOMWindowExtensionBasic : public InjectedBundleTest { | |
65 public: | |
66 DOMWindowExtensionBasic(const std::string& identifier); | |
67 | |
68 virtual void initialize(WKBundleRef, WKTypeRef userData); | |
69 virtual void didCreatePage(WKBundleRef, WKBundlePageRef); | |
70 virtual void willDestroyPage(WKBundleRef, WKBundlePageRef); | |
71 | |
72 void globalObjectIsAvailableForFrame(WKBundleFrameRef, WKBundleScriptWorldRe
f); | |
73 void willDisconnectDOMWindowExtensionFromGlobalObject(WKBundleDOMWindowExten
sionRef); | |
74 void didReconnectDOMWindowExtensionToGlobalObject(WKBundleDOMWindowExtension
Ref); | |
75 void willDestroyGlobalObjectForDOMWindowExtension(WKBundleDOMWindowExtension
Ref); | |
76 | |
77 void frameLoadFinished(WKBundleFrameRef); | |
78 | |
79 private: | |
80 void updateExtensionStateRecord(WKBundleDOMWindowExtensionRef, ExtensionStat
e); | |
81 void sendExtensionStateMessage(); | |
82 void sendBundleMessage(const char*); | |
83 | |
84 WKBundleRef m_bundle; | |
85 ExtensionRecord m_extensionRecords[6]; | |
86 HashMap<WKBundleDOMWindowExtensionRef, int> m_extensionToRecordMap; | |
87 bool m_finishedOneMainFrameLoad; | |
88 }; | |
89 | |
90 static InjectedBundleTest::Register<DOMWindowExtensionBasic> registrar("DOMWindo
wExtensionBasic"); | |
91 | |
92 DOMWindowExtensionBasic::DOMWindowExtensionBasic(const std::string& identifier) | |
93 : InjectedBundleTest(identifier) | |
94 , m_finishedOneMainFrameLoad(false) | |
95 { | |
96 m_extensionRecords[0].name = "First page, main frame, standard world"; | |
97 m_extensionRecords[1].name = "First page, main frame, non-standard world"; | |
98 m_extensionRecords[2].name = "First page, subframe, standard world"; | |
99 m_extensionRecords[3].name = "First page, subframe, non-standard world"; | |
100 m_extensionRecords[4].name = "Second page, main frame, standard world"; | |
101 m_extensionRecords[5].name = "Second page, main frame, non-standard world"; | |
102 | |
103 for (size_t i = 0; i < 6; ++i) | |
104 m_extensionRecords[i].state = Uncreated; | |
105 } | |
106 | |
107 void DOMWindowExtensionBasic::frameLoadFinished(WKBundleFrameRef frame) | |
108 { | |
109 bool mainFrame = !WKBundleFrameGetParentFrame(frame); | |
110 if (mainFrame) | |
111 m_finishedOneMainFrameLoad = true; | |
112 | |
113 char body[16384]; | |
114 sprintf(body, "%s finished loading", mainFrame ? "Main frame" : "Subframe"); | |
115 | |
116 // Only consider load finished for the main frame | |
117 const char* name = mainFrame ? "DidFinishLoadForMainFrame" : "DidFinishLoadF
orFrame"; | |
118 | |
119 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString
(name)); | |
120 WKRetainPtr<WKStringRef> messageBody = adoptWK(WKStringCreateWithUTF8CString
(body)); | |
121 WKBundlePostMessage(m_bundle, messageName.get(), messageBody.get()); | |
122 | |
123 sendExtensionStateMessage(); | |
124 } | |
125 | |
126 void DOMWindowExtensionBasic::sendExtensionStateMessage() | |
127 { | |
128 char body[16384]; | |
129 sprintf(body, "Extension states:\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %
s\n%s - %s", | |
130 m_extensionRecords[0].name, stateNames[m_extensionRecords[0].state], | |
131 m_extensionRecords[1].name, stateNames[m_extensionRecords[1].state], | |
132 m_extensionRecords[2].name, stateNames[m_extensionRecords[2].state], | |
133 m_extensionRecords[3].name, stateNames[m_extensionRecords[3].state], | |
134 m_extensionRecords[4].name, stateNames[m_extensionRecords[4].state], | |
135 m_extensionRecords[5].name, stateNames[m_extensionRecords[5].state]); | |
136 | |
137 WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString
("ExtensionStates")); | |
138 WKRetainPtr<WKStringRef> messageBody = adoptWK(WKStringCreateWithUTF8CString
(body)); | |
139 WKBundlePostMessage(m_bundle, messageName.get(), messageBody.get()); | |
140 } | |
141 | |
142 void DOMWindowExtensionBasic::initialize(WKBundleRef bundle, WKTypeRef userData) | |
143 { | |
144 assert(WKGetTypeID(userData) == WKBundlePageGroupGetTypeID()); | |
145 WKBundlePageGroupRef pageGroup = static_cast<WKBundlePageGroupRef>(userData)
; | |
146 | |
147 WKRetainPtr<WKStringRef> source(AdoptWK, WKStringCreateWithUTF8CString("aler
t('Unimportant alert');")); | |
148 WKBundleAddUserScript(bundle, pageGroup, WKBundleScriptWorldCreateWorld(), s
ource.get(), 0, 0, 0, kWKInjectAtDocumentStart, kWKInjectInAllFrames); | |
149 } | |
150 | |
151 void DOMWindowExtensionBasic::didCreatePage(WKBundleRef bundle, WKBundlePageRef
page) | |
152 { | |
153 m_bundle = bundle; | |
154 | |
155 WKBundlePageLoaderClient pageLoaderClient; | |
156 memset(&pageLoaderClient, 0, sizeof(pageLoaderClient)); | |
157 | |
158 pageLoaderClient.version = 1; | |
159 pageLoaderClient.clientInfo = this; | |
160 pageLoaderClient.didFinishLoadForFrame = didFinishLoadForFrameCallback; | |
161 pageLoaderClient.globalObjectIsAvailableForFrame = globalObjectIsAvailableFo
rFrameCallback; | |
162 pageLoaderClient.willDisconnectDOMWindowExtensionFromGlobalObject = willDisc
onnectDOMWindowExtensionFromGlobalObjectCallback; | |
163 pageLoaderClient.didReconnectDOMWindowExtensionToGlobalObject = didReconnect
DOMWindowExtensionToGlobalObjectCallback; | |
164 pageLoaderClient.willDestroyGlobalObjectForDOMWindowExtension = willDestroyG
lobalObjectForDOMWindowExtensionCallback; | |
165 | |
166 WKBundlePageSetPageLoaderClient(page, &pageLoaderClient); | |
167 } | |
168 | |
169 void DOMWindowExtensionBasic::willDestroyPage(WKBundleRef, WKBundlePageRef) | |
170 { | |
171 HashMap<WKBundleDOMWindowExtensionRef, int>::iterator it = m_extensionToReco
rdMap.begin(); | |
172 HashMap<WKBundleDOMWindowExtensionRef, int>::iterator end = m_extensionToRec
ordMap.end(); | |
173 for (; it != end; ++it) { | |
174 updateExtensionStateRecord(it->key, Removed); | |
175 WKRelease(it->key); | |
176 } | |
177 | |
178 m_extensionToRecordMap.clear(); | |
179 | |
180 sendExtensionStateMessage(); | |
181 sendBundleMessage("TestComplete"); | |
182 } | |
183 | |
184 void DOMWindowExtensionBasic::updateExtensionStateRecord(WKBundleDOMWindowExtens
ionRef extension, ExtensionState state) | |
185 { | |
186 int index = m_extensionToRecordMap.get(extension); | |
187 m_extensionRecords[index].state = state; | |
188 } | |
189 | |
190 void DOMWindowExtensionBasic::sendBundleMessage(const char* message) | |
191 { | |
192 WKRetainPtr<WKStringRef> wkMessage = adoptWK(WKStringCreateWithUTF8CString(m
essage)); | |
193 WKBundlePostMessage(m_bundle, wkMessage.get(), wkMessage.get()); | |
194 } | |
195 | |
196 void DOMWindowExtensionBasic::globalObjectIsAvailableForFrame(WKBundleFrameRef f
rame, WKBundleScriptWorldRef world) | |
197 { | |
198 WKBundleDOMWindowExtensionRef extension = WKBundleDOMWindowExtensionCreate(f
rame, world); | |
199 | |
200 int index; | |
201 bool standard; | |
202 standard = world == WKBundleScriptWorldNormalWorld(); | |
203 | |
204 if (WKBundleFrameGetParentFrame(frame)) | |
205 index = standard ? 2 : 3; | |
206 else | |
207 index = m_finishedOneMainFrameLoad ? (standard ? 4 : 5) : (standard ? 0
: 1); | |
208 | |
209 m_extensionToRecordMap.set(extension, index); | |
210 | |
211 updateExtensionStateRecord(extension, Connected); | |
212 sendBundleMessage("GlobalObjectIsAvailableForFrame called"); | |
213 } | |
214 | |
215 void DOMWindowExtensionBasic::willDisconnectDOMWindowExtensionFromGlobalObject(W
KBundleDOMWindowExtensionRef extension) | |
216 { | |
217 updateExtensionStateRecord(extension, Disconnected); | |
218 sendBundleMessage("WillDisconnectDOMWindowExtensionFromGlobalObject called")
; | |
219 } | |
220 | |
221 void DOMWindowExtensionBasic::didReconnectDOMWindowExtensionToGlobalObject(WKBun
dleDOMWindowExtensionRef extension) | |
222 { | |
223 updateExtensionStateRecord(extension, Connected); | |
224 sendBundleMessage("DidReconnectDOMWindowExtensionToGlobalObject called"); | |
225 } | |
226 | |
227 void DOMWindowExtensionBasic::willDestroyGlobalObjectForDOMWindowExtension(WKBun
dleDOMWindowExtensionRef) | |
228 { | |
229 // All of the items are candidates for the page cache and should not be evic
ted from the page | |
230 // cache before the test completes. | |
231 ASSERT_NOT_REACHED(); | |
232 } | |
233 | |
234 static void didFinishLoadForFrameCallback(WKBundlePageRef, WKBundleFrameRef fram
e, WKTypeRef*, const void *clientInfo) | |
235 { | |
236 ((DOMWindowExtensionBasic*)clientInfo)->frameLoadFinished(frame); | |
237 } | |
238 | |
239 static void globalObjectIsAvailableForFrameCallback(WKBundlePageRef, WKBundleFra
meRef frame, WKBundleScriptWorldRef world, const void* clientInfo) | |
240 { | |
241 ((DOMWindowExtensionBasic*)clientInfo)->globalObjectIsAvailableForFrame(fram
e, world); | |
242 } | |
243 | |
244 static void willDisconnectDOMWindowExtensionFromGlobalObjectCallback(WKBundlePag
eRef, WKBundleDOMWindowExtensionRef extension, const void* clientInfo) | |
245 { | |
246 ((DOMWindowExtensionBasic*)clientInfo)->willDisconnectDOMWindowExtensionFrom
GlobalObject(extension); | |
247 } | |
248 | |
249 static void didReconnectDOMWindowExtensionToGlobalObjectCallback(WKBundlePageRef
, WKBundleDOMWindowExtensionRef extension, const void* clientInfo) | |
250 { | |
251 ((DOMWindowExtensionBasic*)clientInfo)->didReconnectDOMWindowExtensionToGlob
alObject(extension); | |
252 } | |
253 | |
254 static void willDestroyGlobalObjectForDOMWindowExtensionCallback(WKBundlePageRef
, WKBundleDOMWindowExtensionRef extension , const void* clientInfo) | |
255 { | |
256 ((DOMWindowExtensionBasic*)clientInfo)->willDestroyGlobalObjectForDOMWindowE
xtension(extension); | |
257 } | |
258 | |
259 } // namespace TestWebKitAPI | |
OLD | NEW |