1/* 2 * Copyright (C) 2012 Igalia S.L. 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2,1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Library General Public License for more details. 13 * 14 * You should have received a copy of the GNU Library General Public License 15 * along with this library; see the file COPYING.LIB. If not, write to 16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 * Boston, MA 02110-1301, USA. 18 */ 19 20#include "config.h" 21#include "WebKitWebExtension.h" 22 23#include "APIString.h" 24#include "ImmutableDictionary.h" 25#include "WKBundleAPICast.h" 26#include "WKBundlePage.h" 27#include "WebKitPrivate.h" 28#include "WebKitWebExtensionPrivate.h" 29#include "WebKitWebPagePrivate.h" 30#include <WebCore/DNS.h> 31#include <wtf/HashMap.h> 32#include <wtf/gobject/GRefPtr.h> 33 34using namespace WebKit; 35 36enum { 37 PAGE_CREATED, 38 39 LAST_SIGNAL 40}; 41 42typedef HashMap<WebPage*, GRefPtr<WebKitWebPage> > WebPageMap; 43 44struct _WebKitWebExtensionPrivate { 45 WebPageMap pages; 46}; 47 48static guint signals[LAST_SIGNAL] = { 0, }; 49 50WEBKIT_DEFINE_TYPE(WebKitWebExtension, webkit_web_extension, G_TYPE_OBJECT) 51 52static void webkit_web_extension_class_init(WebKitWebExtensionClass* klass) 53{ 54 /** 55 * WebKitWebExtension::page-created: 56 * @extension: the #WebKitWebExtension on which the signal is emitted 57 * @web_page: the #WebKitWebPage created 58 * 59 * This signal is emitted when a new #WebKitWebPage is created in 60 * the Web Process. 61 */ 62 signals[PAGE_CREATED] = g_signal_new( 63 "page-created", 64 G_TYPE_FROM_CLASS(klass), 65 G_SIGNAL_RUN_LAST, 66 0, 0, 0, 67 g_cclosure_marshal_VOID__OBJECT, 68 G_TYPE_NONE, 1, 69 WEBKIT_TYPE_WEB_PAGE); 70} 71 72static void webkitWebExtensionPageCreated(WebKitWebExtension* extension, WebPage* page) 73{ 74 GRefPtr<WebKitWebPage> webPage = adoptGRef(webkitWebPageCreate(page)); 75 extension->priv->pages.add(page, webPage); 76 g_signal_emit(extension, signals[PAGE_CREATED], 0, webPage.get()); 77} 78 79static void webkitWebExtensionPageDestroy(WebKitWebExtension* extension, WebPage* page) 80{ 81 extension->priv->pages.remove(page); 82} 83 84static void webkitWebExtensionDidReceiveMessage(WebKitWebExtension*, const String& messageName, ImmutableDictionary& message) 85{ 86 if (messageName == String::fromUTF8("PrefetchDNS")) { 87 API::String* hostname = static_cast<API::String*>(message.get(String::fromUTF8("Hostname"))); 88 WebCore::prefetchDNS(hostname->string()); 89 } else 90 ASSERT_NOT_REACHED(); 91} 92 93static void didCreatePage(WKBundleRef, WKBundlePageRef page, const void* clientInfo) 94{ 95 webkitWebExtensionPageCreated(WEBKIT_WEB_EXTENSION(clientInfo), toImpl(page)); 96} 97 98static void willDestroyPage(WKBundleRef, WKBundlePageRef page, const void* clientInfo) 99{ 100 webkitWebExtensionPageDestroy(WEBKIT_WEB_EXTENSION(clientInfo), toImpl(page)); 101} 102 103static void didReceiveMessage(WKBundleRef, WKStringRef name, WKTypeRef messageBody, const void* clientInfo) 104{ 105 ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID()); 106 webkitWebExtensionDidReceiveMessage(WEBKIT_WEB_EXTENSION(clientInfo), toImpl(name)->string(), *toImpl(static_cast<WKDictionaryRef>(messageBody))); 107} 108 109static void didReceiveMessageToPage(WKBundleRef, WKBundlePageRef page, WKStringRef name, WKTypeRef messageBody, const void* clientInfo) 110{ 111 ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID()); 112 if (WebKitWebPage* webPage = WEBKIT_WEB_EXTENSION(clientInfo)->priv->pages.get(toImpl(page)).get()) 113 webkitWebPageDidReceiveMessage(webPage, toImpl(name)->string(), *toImpl(static_cast<WKDictionaryRef>(messageBody))); 114} 115 116WebKitWebExtension* webkitWebExtensionCreate(InjectedBundle* bundle) 117{ 118 WebKitWebExtension* extension = WEBKIT_WEB_EXTENSION(g_object_new(WEBKIT_TYPE_WEB_EXTENSION, NULL)); 119 120 WKBundleClientV1 wkBundleClient = { 121 { 122 1, // version 123 extension, // clientInfo 124 }, 125 didCreatePage, 126 willDestroyPage, 127 0, // didInitializePageGroup 128 didReceiveMessage, 129 didReceiveMessageToPage 130 }; 131 WKBundleSetClient(toAPI(bundle), &wkBundleClient.base); 132 133 return extension; 134} 135 136/** 137 * webkit_web_extension_get_page: 138 * @extension: a #WebKitWebExtension 139 * @page_id: the identifier of the #WebKitWebPage to get 140 * 141 * Get the web page of the given @page_id. 142 * 143 * Returns: (transfer none): the #WebKitWebPage for the given @page_id, or %NULL if the 144 * identifier doesn't correspond to an exsiting web page. 145 */ 146WebKitWebPage* webkit_web_extension_get_page(WebKitWebExtension* extension, guint64 pageID) 147{ 148 g_return_val_if_fail(WEBKIT_IS_WEB_EXTENSION(extension), 0); 149 150 WebKitWebExtensionPrivate* priv = extension->priv; 151 WebPageMap::const_iterator end = priv->pages.end(); 152 for (WebPageMap::const_iterator it = priv->pages.begin(); it != end; ++it) 153 if (it->key->pageID() == pageID) 154 return it->value.get(); 155 156 return 0; 157} 158