2
* Copyright (C) 2012 Apple Inc. All rights reserved.
4
* Redistribution and use in source and binary forms, with or without
5
* modification, are permitted provided that the following conditions
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.
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.
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>
38
namespace TestWebKitAPI {
40
static void didFinishLoadForFrameCallback(WKBundlePageRef, WKBundleFrameRef, WKTypeRef*, const void* clientInfo);
41
static void globalObjectIsAvailableForFrameCallback(WKBundlePageRef, WKBundleFrameRef, WKBundleScriptWorldRef, const void* clientInfo);
42
static void willDisconnectDOMWindowExtensionFromGlobalObjectCallback(WKBundlePageRef, WKBundleDOMWindowExtensionRef, const void* clientInfo);
43
static void didReconnectDOMWindowExtensionToGlobalObjectCallback(WKBundlePageRef, WKBundleDOMWindowExtensionRef, const void* clientInfo);
44
static void willDestroyGlobalObjectForDOMWindowExtensionCallback(WKBundlePageRef, WKBundleDOMWindowExtensionRef, const void* clientInfo);
47
Uncreated = 0, Connected, Disconnected, Destroyed, Removed
50
const char* states[5] = {
63
class DOMWindowExtensionNoCache : public InjectedBundleTest {
65
DOMWindowExtensionNoCache(const std::string& identifier);
67
virtual void initialize(WKBundleRef, WKTypeRef userData);
68
virtual void didCreatePage(WKBundleRef, WKBundlePageRef);
69
virtual void willDestroyPage(WKBundleRef, WKBundlePageRef);
71
void globalObjectIsAvailableForFrame(WKBundleFrameRef, WKBundleScriptWorldRef);
72
void willDisconnectDOMWindowExtensionFromGlobalObject(WKBundleDOMWindowExtensionRef);
73
void didReconnectDOMWindowExtensionToGlobalObject(WKBundleDOMWindowExtensionRef);
74
void willDestroyGlobalObjectForDOMWindowExtension(WKBundleDOMWindowExtensionRef);
76
void frameLoadFinished(WKBundleFrameRef);
79
void updateExtensionStateRecord(WKBundleDOMWindowExtensionRef, ExtensionState);
80
void sendExtensionStateMessage();
81
void sendBundleMessage(const char*);
84
ExtensionRecord m_extensionRecords[10];
85
HashMap<WKBundleDOMWindowExtensionRef, int> m_extensionToRecordMap;
86
int m_numberMainFrameLoads;
89
static InjectedBundleTest::Register<DOMWindowExtensionNoCache> registrar("DOMWindowExtensionNoCache");
91
DOMWindowExtensionNoCache::DOMWindowExtensionNoCache(const std::string& identifier)
92
: InjectedBundleTest(identifier)
93
, m_numberMainFrameLoads(0)
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";
106
for (size_t i = 0; i < 10; ++i)
107
m_extensionRecords[i].state = Uncreated;
110
void DOMWindowExtensionNoCache::frameLoadFinished(WKBundleFrameRef frame)
112
bool mainFrame = !WKBundleFrameGetParentFrame(frame);
114
m_numberMainFrameLoads++;
117
sprintf(body, "%s finished loading", mainFrame ? "Main frame" : "Subframe");
119
// Only consider load finished for the main frame
120
const char* name = mainFrame ? "DidFinishLoadForMainFrame" : "DidFinishLoadForFrame";
122
WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString(name));
123
WKRetainPtr<WKStringRef> messageBody = adoptWK(WKStringCreateWithUTF8CString(body));
124
WKBundlePostMessage(m_bundle, messageName.get(), messageBody.get());
126
sendExtensionStateMessage();
129
void DOMWindowExtensionNoCache::sendExtensionStateMessage()
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]);
144
WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("ExtensionStates"));
145
WKRetainPtr<WKStringRef> messageBody = adoptWK(WKStringCreateWithUTF8CString(body));
146
WKBundlePostMessage(m_bundle, messageName.get(), messageBody.get());
149
void DOMWindowExtensionNoCache::initialize(WKBundleRef bundle, WKTypeRef userData)
151
assert(WKGetTypeID(userData) == WKBundlePageGroupGetTypeID());
152
WKBundlePageGroupRef pageGroup = static_cast<WKBundlePageGroupRef>(userData);
154
WKRetainPtr<WKStringRef> source(AdoptWK, WKStringCreateWithUTF8CString("alert('Unimportant alert');"));
155
WKBundleAddUserScript(bundle, pageGroup, WKBundleScriptWorldCreateWorld(), source.get(), 0, 0, 0, kWKInjectAtDocumentStart, kWKInjectInAllFrames);
158
void DOMWindowExtensionNoCache::didCreatePage(WKBundleRef bundle, WKBundlePageRef page)
162
WKBundlePageLoaderClient pageLoaderClient;
163
memset(&pageLoaderClient, 0, sizeof(pageLoaderClient));
165
pageLoaderClient.version = kWKBundlePageLoaderClientCurrentVersion;
166
pageLoaderClient.clientInfo = this;
167
pageLoaderClient.didFinishLoadForFrame = didFinishLoadForFrameCallback;
168
pageLoaderClient.globalObjectIsAvailableForFrame = globalObjectIsAvailableForFrameCallback;
169
pageLoaderClient.willDisconnectDOMWindowExtensionFromGlobalObject = willDisconnectDOMWindowExtensionFromGlobalObjectCallback;
170
pageLoaderClient.didReconnectDOMWindowExtensionToGlobalObject = didReconnectDOMWindowExtensionToGlobalObjectCallback;
171
pageLoaderClient.willDestroyGlobalObjectForDOMWindowExtension = willDestroyGlobalObjectForDOMWindowExtensionCallback;
173
WKBundlePageSetPageLoaderClient(page, &pageLoaderClient);
176
void DOMWindowExtensionNoCache::willDestroyPage(WKBundleRef, WKBundlePageRef)
178
HashMap<WKBundleDOMWindowExtensionRef, int>::iterator it = m_extensionToRecordMap.begin();
179
HashMap<WKBundleDOMWindowExtensionRef, int>::iterator end = m_extensionToRecordMap.end();
180
for (; it != end; ++it) {
181
updateExtensionStateRecord(it->key, Removed);
185
m_extensionToRecordMap.clear();
187
sendExtensionStateMessage();
188
sendBundleMessage("TestComplete");
191
void DOMWindowExtensionNoCache::updateExtensionStateRecord(WKBundleDOMWindowExtensionRef extension, ExtensionState state)
193
int index = m_extensionToRecordMap.get(extension);
194
m_extensionRecords[index].state = state;
197
void DOMWindowExtensionNoCache::sendBundleMessage(const char* message)
199
WKRetainPtr<WKStringRef> wkMessage = adoptWK(WKStringCreateWithUTF8CString(message));
200
WKBundlePostMessage(m_bundle, wkMessage.get(), wkMessage.get());
203
void DOMWindowExtensionNoCache::globalObjectIsAvailableForFrame(WKBundleFrameRef frame, WKBundleScriptWorldRef world)
205
WKBundleDOMWindowExtensionRef extension = WKBundleDOMWindowExtensionCreate(frame, world);
209
standard = world == WKBundleScriptWorldNormalWorld();
211
bool mainFrame = !WKBundleFrameGetParentFrame(frame);
212
switch (m_numberMainFrameLoads) {
214
index = mainFrame ? (standard ? 0 : 1) : (standard ? 2 : 3);
217
index = standard ? 4 : 5;
220
index = mainFrame ? (standard ? 6 : 7) : (standard ? 8 : 9);
223
ASSERT_NOT_REACHED();
227
m_extensionToRecordMap.set(extension, index);
229
updateExtensionStateRecord(extension, Connected);
230
sendBundleMessage("GlobalObjectIsAvailableForFrame called");
233
void DOMWindowExtensionNoCache::willDisconnectDOMWindowExtensionFromGlobalObject(WKBundleDOMWindowExtensionRef extension)
235
// No items should be going into a 0-capacity page cache.
236
ASSERT_NOT_REACHED();
239
void DOMWindowExtensionNoCache::didReconnectDOMWindowExtensionToGlobalObject(WKBundleDOMWindowExtensionRef)
241
// No items should be coming out of a 0-capacity page cache.
242
ASSERT_NOT_REACHED();
245
void DOMWindowExtensionNoCache::willDestroyGlobalObjectForDOMWindowExtension(WKBundleDOMWindowExtensionRef extension)
247
sendBundleMessage("WillDestroyDOMWindowExtensionToGlobalObject called");
248
updateExtensionStateRecord(extension, Destroyed);
249
m_extensionToRecordMap.remove(extension);
250
WKRelease(extension);
253
static void didFinishLoadForFrameCallback(WKBundlePageRef, WKBundleFrameRef frame, WKTypeRef*, const void *clientInfo)
255
((DOMWindowExtensionNoCache*)clientInfo)->frameLoadFinished(frame);
258
static void globalObjectIsAvailableForFrameCallback(WKBundlePageRef, WKBundleFrameRef frame, WKBundleScriptWorldRef world, const void* clientInfo)
260
((DOMWindowExtensionNoCache*)clientInfo)->globalObjectIsAvailableForFrame(frame, world);
263
static void willDisconnectDOMWindowExtensionFromGlobalObjectCallback(WKBundlePageRef, WKBundleDOMWindowExtensionRef extension, const void* clientInfo)
265
((DOMWindowExtensionNoCache*)clientInfo)->willDisconnectDOMWindowExtensionFromGlobalObject(extension);
268
static void didReconnectDOMWindowExtensionToGlobalObjectCallback(WKBundlePageRef, WKBundleDOMWindowExtensionRef extension, const void* clientInfo)
270
((DOMWindowExtensionNoCache*)clientInfo)->didReconnectDOMWindowExtensionToGlobalObject(extension);
273
static void willDestroyGlobalObjectForDOMWindowExtensionCallback(WKBundlePageRef, WKBundleDOMWindowExtensionRef extension , const void* clientInfo)
275
((DOMWindowExtensionNoCache*)clientInfo)->willDestroyGlobalObjectForDOMWindowExtension(extension);
278
} // namespace TestWebKitAPI