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);
48
Uncreated = 0, Connected, Disconnected, Destroyed, Removed
51
const char* stateNames[5] = {
64
class DOMWindowExtensionBasic : public InjectedBundleTest {
66
DOMWindowExtensionBasic(const std::string& identifier);
68
virtual void initialize(WKBundleRef, WKTypeRef userData);
69
virtual void didCreatePage(WKBundleRef, WKBundlePageRef);
70
virtual void willDestroyPage(WKBundleRef, WKBundlePageRef);
72
void globalObjectIsAvailableForFrame(WKBundleFrameRef, WKBundleScriptWorldRef);
73
void willDisconnectDOMWindowExtensionFromGlobalObject(WKBundleDOMWindowExtensionRef);
74
void didReconnectDOMWindowExtensionToGlobalObject(WKBundleDOMWindowExtensionRef);
75
void willDestroyGlobalObjectForDOMWindowExtension(WKBundleDOMWindowExtensionRef);
77
void frameLoadFinished(WKBundleFrameRef);
80
void updateExtensionStateRecord(WKBundleDOMWindowExtensionRef, ExtensionState);
81
void sendExtensionStateMessage();
82
void sendBundleMessage(const char*);
85
ExtensionRecord m_extensionRecords[6];
86
HashMap<WKBundleDOMWindowExtensionRef, int> m_extensionToRecordMap;
87
bool m_finishedOneMainFrameLoad;
90
static InjectedBundleTest::Register<DOMWindowExtensionBasic> registrar("DOMWindowExtensionBasic");
92
DOMWindowExtensionBasic::DOMWindowExtensionBasic(const std::string& identifier)
93
: InjectedBundleTest(identifier)
94
, m_finishedOneMainFrameLoad(false)
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";
103
for (size_t i = 0; i < 6; ++i)
104
m_extensionRecords[i].state = Uncreated;
107
void DOMWindowExtensionBasic::frameLoadFinished(WKBundleFrameRef frame)
109
bool mainFrame = !WKBundleFrameGetParentFrame(frame);
111
m_finishedOneMainFrameLoad = true;
114
sprintf(body, "%s finished loading", mainFrame ? "Main frame" : "Subframe");
116
// Only consider load finished for the main frame
117
const char* name = mainFrame ? "DidFinishLoadForMainFrame" : "DidFinishLoadForFrame";
119
WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString(name));
120
WKRetainPtr<WKStringRef> messageBody = adoptWK(WKStringCreateWithUTF8CString(body));
121
WKBundlePostMessage(m_bundle, messageName.get(), messageBody.get());
123
sendExtensionStateMessage();
126
void DOMWindowExtensionBasic::sendExtensionStateMessage()
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]);
137
WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("ExtensionStates"));
138
WKRetainPtr<WKStringRef> messageBody = adoptWK(WKStringCreateWithUTF8CString(body));
139
WKBundlePostMessage(m_bundle, messageName.get(), messageBody.get());
142
void DOMWindowExtensionBasic::initialize(WKBundleRef bundle, WKTypeRef userData)
144
assert(WKGetTypeID(userData) == WKBundlePageGroupGetTypeID());
145
WKBundlePageGroupRef pageGroup = static_cast<WKBundlePageGroupRef>(userData);
147
WKRetainPtr<WKStringRef> source(AdoptWK, WKStringCreateWithUTF8CString("alert('Unimportant alert');"));
148
WKBundleAddUserScript(bundle, pageGroup, WKBundleScriptWorldCreateWorld(), source.get(), 0, 0, 0, kWKInjectAtDocumentStart, kWKInjectInAllFrames);
151
void DOMWindowExtensionBasic::didCreatePage(WKBundleRef bundle, WKBundlePageRef page)
155
WKBundlePageLoaderClient pageLoaderClient;
156
memset(&pageLoaderClient, 0, sizeof(pageLoaderClient));
158
pageLoaderClient.version = 1;
159
pageLoaderClient.clientInfo = this;
160
pageLoaderClient.didFinishLoadForFrame = didFinishLoadForFrameCallback;
161
pageLoaderClient.globalObjectIsAvailableForFrame = globalObjectIsAvailableForFrameCallback;
162
pageLoaderClient.willDisconnectDOMWindowExtensionFromGlobalObject = willDisconnectDOMWindowExtensionFromGlobalObjectCallback;
163
pageLoaderClient.didReconnectDOMWindowExtensionToGlobalObject = didReconnectDOMWindowExtensionToGlobalObjectCallback;
164
pageLoaderClient.willDestroyGlobalObjectForDOMWindowExtension = willDestroyGlobalObjectForDOMWindowExtensionCallback;
166
WKBundlePageSetPageLoaderClient(page, &pageLoaderClient);
169
void DOMWindowExtensionBasic::willDestroyPage(WKBundleRef, WKBundlePageRef)
171
HashMap<WKBundleDOMWindowExtensionRef, int>::iterator it = m_extensionToRecordMap.begin();
172
HashMap<WKBundleDOMWindowExtensionRef, int>::iterator end = m_extensionToRecordMap.end();
173
for (; it != end; ++it) {
174
updateExtensionStateRecord(it->key, Removed);
178
m_extensionToRecordMap.clear();
180
sendExtensionStateMessage();
181
sendBundleMessage("TestComplete");
184
void DOMWindowExtensionBasic::updateExtensionStateRecord(WKBundleDOMWindowExtensionRef extension, ExtensionState state)
186
int index = m_extensionToRecordMap.get(extension);
187
m_extensionRecords[index].state = state;
190
void DOMWindowExtensionBasic::sendBundleMessage(const char* message)
192
WKRetainPtr<WKStringRef> wkMessage = adoptWK(WKStringCreateWithUTF8CString(message));
193
WKBundlePostMessage(m_bundle, wkMessage.get(), wkMessage.get());
196
void DOMWindowExtensionBasic::globalObjectIsAvailableForFrame(WKBundleFrameRef frame, WKBundleScriptWorldRef world)
198
WKBundleDOMWindowExtensionRef extension = WKBundleDOMWindowExtensionCreate(frame, world);
202
standard = world == WKBundleScriptWorldNormalWorld();
204
if (WKBundleFrameGetParentFrame(frame))
205
index = standard ? 2 : 3;
207
index = m_finishedOneMainFrameLoad ? (standard ? 4 : 5) : (standard ? 0 : 1);
209
m_extensionToRecordMap.set(extension, index);
211
updateExtensionStateRecord(extension, Connected);
212
sendBundleMessage("GlobalObjectIsAvailableForFrame called");
215
void DOMWindowExtensionBasic::willDisconnectDOMWindowExtensionFromGlobalObject(WKBundleDOMWindowExtensionRef extension)
217
updateExtensionStateRecord(extension, Disconnected);
218
sendBundleMessage("WillDisconnectDOMWindowExtensionFromGlobalObject called");
221
void DOMWindowExtensionBasic::didReconnectDOMWindowExtensionToGlobalObject(WKBundleDOMWindowExtensionRef extension)
223
updateExtensionStateRecord(extension, Connected);
224
sendBundleMessage("DidReconnectDOMWindowExtensionToGlobalObject called");
227
void DOMWindowExtensionBasic::willDestroyGlobalObjectForDOMWindowExtension(WKBundleDOMWindowExtensionRef)
229
// All of the items are candidates for the page cache and should not be evicted from the page
230
// cache before the test completes.
231
ASSERT_NOT_REACHED();
234
static void didFinishLoadForFrameCallback(WKBundlePageRef, WKBundleFrameRef frame, WKTypeRef*, const void *clientInfo)
236
((DOMWindowExtensionBasic*)clientInfo)->frameLoadFinished(frame);
239
static void globalObjectIsAvailableForFrameCallback(WKBundlePageRef, WKBundleFrameRef frame, WKBundleScriptWorldRef world, const void* clientInfo)
241
((DOMWindowExtensionBasic*)clientInfo)->globalObjectIsAvailableForFrame(frame, world);
244
static void willDisconnectDOMWindowExtensionFromGlobalObjectCallback(WKBundlePageRef, WKBundleDOMWindowExtensionRef extension, const void* clientInfo)
246
((DOMWindowExtensionBasic*)clientInfo)->willDisconnectDOMWindowExtensionFromGlobalObject(extension);
249
static void didReconnectDOMWindowExtensionToGlobalObjectCallback(WKBundlePageRef, WKBundleDOMWindowExtensionRef extension, const void* clientInfo)
251
((DOMWindowExtensionBasic*)clientInfo)->didReconnectDOMWindowExtensionToGlobalObject(extension);
254
static void willDestroyGlobalObjectForDOMWindowExtensionCallback(WKBundlePageRef, WKBundleDOMWindowExtensionRef extension , const void* clientInfo)
256
((DOMWindowExtensionBasic*)clientInfo)->willDestroyGlobalObjectForDOMWindowExtension(extension);
259
} // namespace TestWebKitAPI