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