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 41namespace WTR { 42 43InjectedBundle& InjectedBundle::shared() 44{ 45 static InjectedBundle& shared = *new InjectedBundle; 46 return shared; 47} 48 49InjectedBundle::InjectedBundle() 50 : m_bundle(0) 51 , m_topLoadingFrame(0) 52 , m_state(Idle) 53 , m_dumpPixels(false) 54{ 55} 56 57void InjectedBundle::didCreatePage(WKBundleRef bundle, WKBundlePageRef page, const void* clientInfo) 58{ 59 static_cast<InjectedBundle*>(const_cast<void*>(clientInfo))->didCreatePage(page); 60} 61 62void InjectedBundle::willDestroyPage(WKBundleRef bundle, WKBundlePageRef page, const void* clientInfo) 63{ 64 static_cast<InjectedBundle*>(const_cast<void*>(clientInfo))->willDestroyPage(page); 65} 66 67void InjectedBundle::didInitializePageGroup(WKBundleRef bundle, WKBundlePageGroupRef pageGroup, const void* clientInfo) 68{ 69 static_cast<InjectedBundle*>(const_cast<void*>(clientInfo))->didInitializePageGroup(pageGroup); 70} 71 72void 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 77void 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 97void InjectedBundle::didCreatePage(WKBundlePageRef page) 98{ 99 m_pages.append(adoptPtr(new InjectedBundlePage(page))); 100} 101 102void 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 113void InjectedBundle::didInitializePageGroup(WKBundlePageGroupRef pageGroup) 114{ 115 m_pageGroup = pageGroup; 116} 117 118InjectedBundlePage* 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 125void InjectedBundle::resetLocalSettings() 126{ 127 setlocale(LC_ALL, ""); 128} 129 130void 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 157void 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 179void 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 203void 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 214void 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