| 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 |