1 /* 2 * Copyright (C) 2010 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 "InjectedBundle.h" 28 29 #include "ActivateFonts.h" 30 #include "InjectedBundlePage.h" 31 #include "StringFunctions.h" 32 #include <WebKit2/WKBundle.h> 33 #include <WebKit2/WKBundlePage.h> 34 #include <WebKit2/WKBundlePagePrivate.h> 35 #include <WebKit2/WKBundlePrivate.h> 36 #include <WebKit2/WKRetainPtr.h> 37 #include <WebKit2/WebKit2.h> 38 #include <wtf/PassOwnPtr.h> 39 #include <wtf/Vector.h> 40 41 namespace WTR { 42 43 InjectedBundle& InjectedBundle::shared() 44 { 45 static InjectedBundle& shared = *new InjectedBundle; 46 return shared; 47 } 48 49 InjectedBundle::InjectedBundle() 50 : m_bundle(0) 51 , m_topLoadingFrame(0) 52 , m_state(Idle) 53 , m_dumpPixels(false) 54 { 55 } 56 57 void InjectedBundle::didCreatePage(WKBundleRef bundle, WKBundlePageRef page, const void* clientInfo) 58 { 59 static_cast<InjectedBundle*>(const_cast<void*>(clientInfo))->didCreatePage(page); 60 } 61 62 void InjectedBundle::willDestroyPage(WKBundleRef bundle, WKBundlePageRef page, const void* clientInfo) 63 { 64 static_cast<InjectedBundle*>(const_cast<void*>(clientInfo))->willDestroyPage(page); 65 } 66 67 void InjectedBundle::didInitializePageGroup(WKBundleRef bundle, WKBundlePageGroupRef pageGroup, const void* clientInfo) 68 { 69 static_cast<InjectedBundle*>(const_cast<void*>(clientInfo))->didInitializePageGroup(pageGroup); 70 } 71 72 void InjectedBundle::didReceiveMessage(WKBundleRef bundle, WKStringRef messageName, WKTypeRef messageBody, const void *clientInfo) 73 { 74 static_cast<InjectedBundle*>(const_cast<void*>(clientInfo))->didReceiveMessage(messageName, messageBody); 75 } 76 77 void InjectedBundle::initialize(WKBundleRef bundle, WKTypeRef initializationUserData) 78 { 79 m_bundle = bundle; 80 81 WKBundleClient client = { 82 0, 83 this, 84 didCreatePage, 85 willDestroyPage, 86 didInitializePageGroup, 87 didReceiveMessage 88 }; 89 WKBundleSetClient(m_bundle, &client); 90 91 platformInitialize(initializationUserData); 92 93 activateFonts(); 94 WKBundleActivateMacFontAscentHack(m_bundle); 95 } 96 97 void InjectedBundle::didCreatePage(WKBundlePageRef page) 98 { 99 m_pages.append(adoptPtr(new InjectedBundlePage(page))); 100 } 101 102 void InjectedBundle::willDestroyPage(WKBundlePageRef page) 103 { 104 size_t size = m_pages.size(); 105 for (size_t i = 0; i < size; ++i) { 106 if (m_pages[i]->page() == page) { 107 m_pages.remove(i); 108 break; 109 } 110 } 111 } 112 113 void InjectedBundle::didInitializePageGroup(WKBundlePageGroupRef pageGroup) 114 { 115 m_pageGroup = pageGroup; 116 } 117 118 InjectedBundlePage* InjectedBundle::page() const 119 { 120 // It might be better to have the UI process send over a reference to the main 121 // page instead of just assuming it's the first one. 122 return m_pages[0].get(); 123 } 124 125 void InjectedBundle::resetLocalSettings() 126 { 127 setlocale(LC_ALL, ""); 128 } 129 130 void InjectedBundle::didReceiveMessage(WKStringRef messageName, WKTypeRef messageBody) 131 { 132 if (WKStringIsEqualToUTF8CString(messageName, "BeginTest")) { 133 ASSERT(messageBody); 134 ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID()); 135 m_dumpPixels = WKBooleanGetValue(static_cast<WKBooleanRef>(messageBody)); 136 137 WKRetainPtr<WKStringRef> ackMessageName(AdoptWK, WKStringCreateWithUTF8CString("Ack")); 138 WKRetainPtr<WKStringRef> ackMessageBody(AdoptWK, WKStringCreateWithUTF8CString("BeginTest")); 139 WKBundlePostMessage(m_bundle, ackMessageName.get(), ackMessageBody.get()); 140 141 beginTesting(); 142 return; 143 } else if (WKStringIsEqualToUTF8CString(messageName, "Reset")) { 144 m_state = Idle; 145 m_dumpPixels = false; 146 147 resetLocalSettings(); 148 149 return; 150 } 151 152 WKRetainPtr<WKStringRef> errorMessageName(AdoptWK, WKStringCreateWithUTF8CString("Error")); 153 WKRetainPtr<WKStringRef> errorMessageBody(AdoptWK, WKStringCreateWithUTF8CString("Unknown")); 154 WKBundlePostMessage(m_bundle, errorMessageName.get(), errorMessageBody.get()); 155 } 156 157 void InjectedBundle::beginTesting() 158 { 159 m_state = Testing; 160 161 m_outputStream.str(""); 162 m_pixelResult.clear(); 163 164 m_layoutTestController = LayoutTestController::create(); 165 m_gcController = GCController::create(); 166 m_eventSendingController = EventSendingController::create(); 167 168 WKBundleSetShouldTrackVisitedLinks(m_bundle, false); 169 WKBundleRemoveAllVisitedLinks(m_bundle); 170 WKBundleOverrideAllowUniversalAccessFromFileURLsForTestRunner(m_bundle, m_pageGroup, true); 171 172 WKBundleRemoveAllUserContent(m_bundle, m_pageGroup); 173 174 page()->reset(); 175 176 WKBundleClearAllDatabases(m_bundle); 177 } 178 179 void InjectedBundle::done() 180 { 181 m_state = Stopping; 182 183 page()->stopLoading(); 184 setTopLoadingFrame(0); 185 186 WKRetainPtr<WKStringRef> doneMessageName(AdoptWK, WKStringCreateWithUTF8CString("Done")); 187 WKRetainPtr<WKMutableDictionaryRef> doneMessageBody(AdoptWK, WKMutableDictionaryCreate()); 188 189 WKRetainPtr<WKStringRef> textOutputKey(AdoptWK, WKStringCreateWithUTF8CString("TextOutput")); 190 WKRetainPtr<WKStringRef> textOutput(AdoptWK, WKStringCreateWithUTF8CString(m_outputStream.str().c_str())); 191 WKDictionaryAddItem(doneMessageBody.get(), textOutputKey.get(), textOutput.get()); 192 193 WKRetainPtr<WKStringRef> pixelResultKey = adoptWK(WKStringCreateWithUTF8CString("PixelResult")); 194 WKDictionaryAddItem(doneMessageBody.get(), pixelResultKey.get(), m_pixelResult.get()); 195 196 WKBundlePostMessage(m_bundle, doneMessageName.get(), doneMessageBody.get()); 197 198 closeOtherPages(); 199 200 m_state = Idle; 201 } 202 203 void InjectedBundle::closeOtherPages() 204 { 205 Vector<WKBundlePageRef> pagesToClose; 206 size_t size = m_pages.size(); 207 for (size_t i = 1; i < size; ++i) 208 pagesToClose.append(m_pages[i]->page()); 209 size = pagesToClose.size(); 210 for (size_t i = 0; i < size; ++i) 211 WKBundlePageClose(pagesToClose[i]); 212 } 213 214 void InjectedBundle::dumpBackForwardListsForAllPages() 215 { 216 size_t size = m_pages.size(); 217 for (size_t i = 0; i < size; ++i) 218 m_pages[i]->dumpBackForwardList(); 219 } 220 221 } // namespace WTR 222