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 Library General Public 6 * License as published by the Free Software Foundation; either 7 * version 2 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 "WebGtkExtensionManager.h" 22 23#include "InjectedBundle.h" 24#include "WKBundleAPICast.h" 25#include "WKDictionary.h" 26#include "WKString.h" 27#include "WKType.h" 28#include "WebKitWebExtensionPrivate.h" 29#include <WebCore/FileSystem.h> 30#include <memory> 31#include <wtf/text/CString.h> 32 33namespace WebKit { 34 35WebGtkExtensionManager& WebGtkExtensionManager::shared() 36{ 37 static NeverDestroyed<WebGtkExtensionManager> extensionManager; 38 return extensionManager; 39} 40 41WebGtkExtensionManager::WebGtkExtensionManager() 42{ 43} 44 45void WebGtkExtensionManager::scanModules(const String& webExtensionsDirectory, Vector<String>& modules) 46{ 47 Vector<String> modulePaths = WebCore::listDirectory(webExtensionsDirectory, String("*.so")); 48 for (size_t i = 0; i < modulePaths.size(); ++i) { 49 if (WebCore::fileExists(modulePaths[i])) 50 modules.append(modulePaths[i]); 51 } 52} 53 54static void parseUserData(WKTypeRef userData, String& webExtensionsDirectory, GRefPtr<GVariant>& initializationUserData) 55{ 56 ASSERT(userData); 57 ASSERT(WKGetTypeID(userData) == WKStringGetTypeID()); 58 59 CString userDataString = toImpl(static_cast<WKStringRef>(userData))->string().utf8(); 60 GRefPtr<GVariant> variant = g_variant_parse(nullptr, userDataString.data(), 61 userDataString.data() + userDataString.length(), nullptr, nullptr); 62 63 ASSERT(variant); 64 ASSERT(g_variant_check_format_string(variant.get(), "(m&smv)", FALSE)); 65 66 const char* directory = nullptr; 67 GVariant* data = nullptr; 68 g_variant_get(variant.get(), "(m&smv)", &directory, &data); 69 70 webExtensionsDirectory = WebCore::filenameToString(directory); 71 initializationUserData = adoptGRef(data); 72} 73 74bool WebGtkExtensionManager::initializeWebExtension(Module* extensionModule, GVariant* userData) 75{ 76 WebKitWebExtensionInitializeWithUserDataFunction initializeWithUserDataFunction = 77 extensionModule->functionPointer<WebKitWebExtensionInitializeWithUserDataFunction>("webkit_web_extension_initialize_with_user_data"); 78 if (initializeWithUserDataFunction) { 79 initializeWithUserDataFunction(m_extension.get(), userData); 80 return true; 81 } 82 83 WebKitWebExtensionInitializeFunction initializeFunction = 84 extensionModule->functionPointer<WebKitWebExtensionInitializeFunction>("webkit_web_extension_initialize"); 85 if (initializeFunction) { 86 initializeFunction(m_extension.get()); 87 return true; 88 } 89 90 return false; 91} 92 93void WebGtkExtensionManager::initialize(WKBundleRef bundle, WKTypeRef userDataString) 94{ 95 m_extension = adoptGRef(webkitWebExtensionCreate(toImpl(bundle))); 96 97 String webExtensionsDirectory; 98 GRefPtr<GVariant> userData; 99 parseUserData(userDataString, webExtensionsDirectory, userData); 100 101 if (webExtensionsDirectory.isNull()) 102 return; 103 104 Vector<String> modulePaths; 105 scanModules(webExtensionsDirectory, modulePaths); 106 107 for (size_t i = 0; i < modulePaths.size(); ++i) { 108 auto module = std::make_unique<Module>(modulePaths[i]); 109 if (!module->load()) 110 continue; 111 if (initializeWebExtension(module.get(), userData.get())) 112 m_extensionModules.append(module.release()); 113 } 114} 115 116} // namespace WebKit 117