diff options
Diffstat (limited to 'Source/WebCore/platform/glib')
-rw-r--r-- | Source/WebCore/platform/glib/BatteryProviderUPower.cpp | 137 | ||||
-rw-r--r-- | Source/WebCore/platform/glib/BatteryProviderUPower.h | 53 | ||||
-rw-r--r-- | Source/WebCore/platform/glib/EventLoopGlib.cpp (renamed from Source/WebCore/platform/glib/BatteryProviderUPowerClient.h) | 26 | ||||
-rw-r--r-- | Source/WebCore/platform/glib/FileSystemGlib.cpp | 425 | ||||
-rw-r--r-- | Source/WebCore/platform/glib/KeyedDecoderGlib.cpp | 173 | ||||
-rw-r--r-- | Source/WebCore/platform/glib/KeyedDecoderGlib.h | 71 | ||||
-rw-r--r-- | Source/WebCore/platform/glib/KeyedEncoderGlib.cpp | 138 | ||||
-rw-r--r-- | Source/WebCore/platform/glib/KeyedEncoderGlib.h | 67 | ||||
-rw-r--r-- | Source/WebCore/platform/glib/MainThreadSharedTimerGLib.cpp | 57 | ||||
-rw-r--r-- | Source/WebCore/platform/glib/SharedBufferGlib.cpp | 50 |
10 files changed, 989 insertions, 208 deletions
diff --git a/Source/WebCore/platform/glib/BatteryProviderUPower.cpp b/Source/WebCore/platform/glib/BatteryProviderUPower.cpp deleted file mode 100644 index efc8000ed..000000000 --- a/Source/WebCore/platform/glib/BatteryProviderUPower.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (C) 2013 Igalia S.L. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" -#include "BatteryProviderUPower.h" - -#if ENABLE(BATTERY_STATUS) - -#include "BatteryProviderUPowerClient.h" -#include <cmath> -#include <limits> -#include <wtf/gobject/GUniquePtr.h> - -using namespace WebCore; - -static void powerDeviceAlterationCallback(UpClient* upowerClient, UpDevice* upowerDevice, BatteryProviderUPower* provider) -{ - UpDeviceKind deviceKind; - g_object_get(upowerDevice, "kind", &deviceKind, nullptr); - if (deviceKind != UP_DEVICE_KIND_BATTERY) - return; - - provider->updateBatteryStatus(); -} - -BatteryProviderUPower::BatteryProviderUPower(BatteryProviderUPowerClient* client) - : m_client(client) - , m_isUpdating(false) -{ - ASSERT(m_client); -} - -void BatteryProviderUPower::startUpdating() -{ - ASSERT(!m_upowerClient); - m_upowerClient = adoptGRef(up_client_new()); - - GUniqueOutPtr<GError> error; - if (!up_client_enumerate_devices_sync(m_upowerClient.get(), 0, &error.outPtr())) { - m_client->updateBatteryStatus(NotAvailable); - return; - } - - g_signal_connect(m_upowerClient.get(), "device-changed", G_CALLBACK(powerDeviceAlterationCallback), this); - g_signal_connect(m_upowerClient.get(), "device-added", G_CALLBACK(powerDeviceAlterationCallback), this); - g_signal_connect(m_upowerClient.get(), "device-removed", G_CALLBACK(powerDeviceAlterationCallback), this); - - m_isUpdating = true; - updateBatteryStatus(); -} - -void BatteryProviderUPower::stopUpdating() -{ - m_upowerClient.clear(); - m_isUpdating = false; -} - -void BatteryProviderUPower::updateBatteryStatus() -{ - if (!m_isUpdating) - return; - - GPtrArray* devices = up_client_get_devices(m_upowerClient.get()); - if (!devices) { - m_client->updateBatteryStatus(NotAvailable); - return; - } - - unsigned numOfBatteryDevices = 0; - double combinedEnergyCapacityCurrent = 0, combinedEnergyCapacityFull = 0, combinedEnergyRate = 0; - - for (unsigned i = 0; i < devices->len; i++) { - UpDevice* device = static_cast<UpDevice*>(g_ptr_array_index(devices, i)); - UpDeviceKind deviceKind; - UpDeviceState deviceState; - bool isPresent; - double energyCapacityCurrent = 0, energyCapacityEmpty = 0, energyCapacityFull = 0, energyRate = 0; - - g_object_get(device, - "energy", &energyCapacityCurrent, - "energy-empty", &energyCapacityEmpty, - "energy-full", &energyCapacityFull, - "energy-rate", &energyRate, - "is-present", &isPresent, - "kind", &deviceKind, - "state", &deviceState, - nullptr); - - if (deviceKind != UP_DEVICE_KIND_BATTERY || !isPresent) - continue; - - numOfBatteryDevices++; - combinedEnergyCapacityCurrent += energyCapacityCurrent - energyCapacityEmpty; - combinedEnergyCapacityFull += energyCapacityFull; - // Added energy rate should be signed according to the charging/discharging state. - combinedEnergyRate += deviceState == UP_DEVICE_STATE_DISCHARGING ? -energyRate : energyRate; - } - - g_ptr_array_unref(devices); - - if (!numOfBatteryDevices) { - m_client->updateBatteryStatus(NotAvailable); - return; - } - - double level = 0; - if (combinedEnergyCapacityFull > 0) - level = combinedEnergyCapacityCurrent / combinedEnergyCapacityFull; - - if (combinedEnergyRate >= 0) { - double chargingTime = std::numeric_limits<double>::infinity(); - if (combinedEnergyRate) - chargingTime = 3600 * (combinedEnergyCapacityFull - combinedEnergyCapacityCurrent) / combinedEnergyRate; - m_client->updateBatteryStatus(Charging, chargingTime, level); - } else { - double dischargingTime = 3600 * combinedEnergyCapacityCurrent / std::abs(combinedEnergyRate); - m_client->updateBatteryStatus(Discharging, dischargingTime, level); - } -} - -#endif // ENABLE(BATTERY_STATUS) diff --git a/Source/WebCore/platform/glib/BatteryProviderUPower.h b/Source/WebCore/platform/glib/BatteryProviderUPower.h deleted file mode 100644 index d1609bb65..000000000 --- a/Source/WebCore/platform/glib/BatteryProviderUPower.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2013 Igalia S.L. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef BatteryProviderUPower_h -#define BatteryProviderUPower_h - -#if ENABLE(BATTERY_STATUS) - -#include <libupower-glib/upower.h> -#include <wtf/gobject/GRefPtr.h> - -namespace WebCore { - -class BatteryProviderUPowerClient; - -class BatteryProviderUPower { -public: - BatteryProviderUPower(BatteryProviderUPowerClient*); - - void startUpdating(); - void stopUpdating(); - - void updateBatteryStatus(); - -private: - BatteryProviderUPowerClient* m_client; - - GRefPtr<UpClient> m_upowerClient; - - bool m_isUpdating; -}; - -} - -#endif // ENABLE(BATTERY_STATUS) - -#endif // BatteryProviderUPower_h diff --git a/Source/WebCore/platform/glib/BatteryProviderUPowerClient.h b/Source/WebCore/platform/glib/EventLoopGlib.cpp index 6ea81f2e6..4ef7b5cb7 100644 --- a/Source/WebCore/platform/glib/BatteryProviderUPowerClient.h +++ b/Source/WebCore/platform/glib/EventLoopGlib.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Igalia S.L. + * Copyright (C) 2008 Nuanti Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -17,26 +17,16 @@ * Boston, MA 02110-1301, USA. */ -#ifndef BatteryProviderUPowerClient_h -#define BatteryProviderUPowerClient_h +#include "config.h" +#include "EventLoop.h" -#if ENABLE(BATTERY_STATUS) +#include <glib.h> namespace WebCore { -enum BatteryProviderUPowerStatus { - NotAvailable = 0, - Charging, - Discharging, -}; - -class BatteryProviderUPowerClient { -public: - virtual void updateBatteryStatus(BatteryProviderUPowerStatus, double secondsRemaining = 0, double batteryLevel = 0) = 0; -}; - +void EventLoop::cycle() +{ + g_main_context_iteration(NULL, FALSE); } -#endif // ENABLE(BATTERY_STATUS) - -#endif // BatteryProviderUPowerClient_h +} // namespace WebCore diff --git a/Source/WebCore/platform/glib/FileSystemGlib.cpp b/Source/WebCore/platform/glib/FileSystemGlib.cpp new file mode 100644 index 000000000..6fa3ea771 --- /dev/null +++ b/Source/WebCore/platform/glib/FileSystemGlib.cpp @@ -0,0 +1,425 @@ +/* + * Copyright (C) 2007, 2009 Holger Hans Peter Freyther + * Copyright (C) 2008 Collabora, Ltd. + * Copyright (C) 2008 Apple Inc. All rights reserved. + * Portions Copyright (c) 2010 Motorola Mobility, Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "FileSystem.h" + +#include "FileMetadata.h" +#include "NotImplemented.h" +#include "UUID.h" +#include <gio/gio.h> +#include <glib.h> +#include <glib/gstdio.h> +#include <wtf/glib/GLibUtilities.h> +#include <wtf/glib/GRefPtr.h> +#include <wtf/glib/GUniquePtr.h> +#include <wtf/text/CString.h> +#include <wtf/text/WTFString.h> + +namespace WebCore { + +/* On linux file names are just raw bytes, so also strings that cannot be encoded in any way + * are valid file names. This mean that we cannot just store a file name as-is in a String + * but we have to escape it. + * On Windows the GLib file name encoding is always UTF-8 so we can optimize this case. */ +String stringFromFileSystemRepresentation(const char* fileSystemRepresentation) +{ + if (!fileSystemRepresentation) + return String(); + +#if OS(WINDOWS) + return String::fromUTF8(fileSystemRepresentation); +#else + GUniquePtr<gchar> escapedString(g_uri_escape_string(fileSystemRepresentation, "/:", FALSE)); + return escapedString.get(); +#endif +} + +static GUniquePtr<char> unescapedFilename(const String& path) +{ + if (path.isEmpty()) + return nullptr; +#if OS(WINDOWS) + return GUniquePtr<char>(g_strdup(path.utf8().data())); +#else + return GUniquePtr<char>(g_uri_unescape_string(path.utf8().data(), nullptr)); +#endif +} + +CString fileSystemRepresentation(const String& path) +{ +#if OS(WINDOWS) + return path.utf8(); +#else + GUniquePtr<gchar> filename = unescapedFilename(path); + return filename.get(); +#endif +} + +// Converts a string to something suitable to be displayed to the user. +String filenameForDisplay(const String& string) +{ +#if OS(WINDOWS) + return string; +#else + GUniquePtr<gchar> filename = unescapedFilename(string); + if (!filename) + return string; + + GUniquePtr<gchar> display(g_filename_to_utf8(filename.get(), -1, nullptr, nullptr, nullptr)); + if (!display) + return string; + + return String::fromUTF8(display.get()); +#endif +} + +bool fileExists(const String& path) +{ + GUniquePtr<gchar> filename = unescapedFilename(path); + return filename ? g_file_test(filename.get(), G_FILE_TEST_EXISTS) : false; +} + +bool deleteFile(const String& path) +{ + GUniquePtr<gchar> filename = unescapedFilename(path); + return filename ? g_remove(filename.get()) != -1 : false; +} + +bool deleteEmptyDirectory(const String& path) +{ + GUniquePtr<gchar> filename = unescapedFilename(path); + return filename ? g_rmdir(filename.get()) != -1 : false; +} + +static bool getFileStat(const String& path, GStatBuf* statBuffer) +{ + GUniquePtr<gchar> filename = unescapedFilename(path); + if (!filename) + return false; + + return g_stat(filename.get(), statBuffer) != -1; +} + +bool getFileSize(const String& path, long long& resultSize) +{ + GStatBuf statResult; + if (!getFileStat(path, &statResult)) + return false; + + resultSize = statResult.st_size; + return true; +} + +bool getFileSize(PlatformFileHandle, long long&) +{ + notImplemented(); + return false; +} + +bool getFileCreationTime(const String&, time_t&) +{ + // FIXME: Is there a way to retrieve file creation time with Gtk on platforms that support it? + return false; +} + +bool getFileModificationTime(const String& path, time_t& modifiedTime) +{ + GStatBuf statResult; + if (!getFileStat(path, &statResult)) + return false; + + modifiedTime = statResult.st_mtime; + return true; +} + +bool getFileMetadata(const String& path, FileMetadata& metadata) +{ + GStatBuf statResult; + if (!getFileStat(path, &statResult)) + return false; + + metadata.modificationTime = statResult.st_mtime; + metadata.length = statResult.st_size; + metadata.type = S_ISDIR(statResult.st_mode) ? FileMetadata::TypeDirectory : FileMetadata::TypeFile; + return true; +} + +String pathByAppendingComponent(const String& path, const String& component) +{ + if (path.endsWith(G_DIR_SEPARATOR_S)) + return path + component; + return path + G_DIR_SEPARATOR_S + component; +} + +bool makeAllDirectories(const String& path) +{ + GUniquePtr<gchar> filename = unescapedFilename(path); + return filename ? g_mkdir_with_parents(filename.get(), S_IRWXU) != -1 : false; +} + +String homeDirectoryPath() +{ + return stringFromFileSystemRepresentation(g_get_home_dir()); +} + +String pathGetFileName(const String& pathName) +{ + GUniquePtr<gchar> tmpFilename = unescapedFilename(pathName); + if (!tmpFilename) + return pathName; + + GUniquePtr<gchar> baseName(g_path_get_basename(tmpFilename.get())); + return String::fromUTF8(baseName.get()); +} + +CString applicationDirectoryPath() +{ + CString path = getCurrentExecutablePath(); + if (!path.isNull()) + return path; + + // If the above fails, check the PATH env variable. + GUniquePtr<char> currentExePath(g_find_program_in_path(g_get_prgname())); + if (!currentExePath.get()) + return CString(); + + GUniquePtr<char> dirname(g_path_get_dirname(currentExePath.get())); + return dirname.get(); +} + +CString sharedResourcesPath() +{ + static CString cachedPath; + if (!cachedPath.isNull()) + return cachedPath; + +#if OS(WINDOWS) + HMODULE hmodule = 0; + GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, reinterpret_cast<char*>(sharedResourcesPath), &hmodule); + + GUniquePtr<gchar> runtimeDir(g_win32_get_package_installation_directory_of_module(hmodule)); + GUniquePtr<gchar> dataPath(g_build_filename(runtimeDir.get(), "share", "webkitgtk-" WEBKITGTK_API_VERSION_STRING, NULL)); +#else + GUniquePtr<gchar> dataPath(g_build_filename(DATA_DIR, "webkitgtk-" WEBKITGTK_API_VERSION_STRING, NULL)); +#endif + + cachedPath = dataPath.get(); + return cachedPath; +} + +bool getVolumeFreeSpace(const String& path, uint64_t& freeSpace) +{ + GUniquePtr<gchar> filename = unescapedFilename(path); + if (!filename) + return false; + + GRefPtr<GFile> file = adoptGRef(g_file_new_for_path(filename.get())); + GRefPtr<GFileInfo> fileInfo = adoptGRef(g_file_query_filesystem_info(file.get(), G_FILE_ATTRIBUTE_FILESYSTEM_FREE, 0, 0)); + if (!fileInfo) + return false; + + freeSpace = g_file_info_get_attribute_uint64(fileInfo.get(), G_FILE_ATTRIBUTE_FILESYSTEM_FREE); + return !!freeSpace; +} + +String directoryName(const String& path) +{ + GUniquePtr<gchar> filename = unescapedFilename(path); + if (!filename) + return String(); + + GUniquePtr<char> dirname(g_path_get_dirname(filename.get())); + return String::fromUTF8(dirname.get()); +} + +Vector<String> listDirectory(const String& path, const String& filter) +{ + Vector<String> entries; + + GUniquePtr<gchar> filename = unescapedFilename(path); + if (!filename) + return entries; + + GUniquePtr<GDir> dir(g_dir_open(filename.get(), 0, nullptr)); + if (!dir) + return entries; + + GUniquePtr<GPatternSpec> pspec(g_pattern_spec_new((filter.utf8()).data())); + while (const char* name = g_dir_read_name(dir.get())) { + if (!g_pattern_match_string(pspec.get(), name)) + continue; + + GUniquePtr<gchar> entry(g_build_filename(filename.get(), name, nullptr)); + entries.append(stringFromFileSystemRepresentation(entry.get())); + } + + return entries; +} + +String openTemporaryFile(const String& prefix, PlatformFileHandle& handle) +{ + GUniquePtr<gchar> filename(g_strdup_printf("%s%s", prefix.utf8().data(), createCanonicalUUIDString().utf8().data())); + GUniquePtr<gchar> tempPath(g_build_filename(g_get_tmp_dir(), filename.get(), NULL)); + GRefPtr<GFile> file = adoptGRef(g_file_new_for_path(tempPath.get())); + + handle = g_file_create_readwrite(file.get(), G_FILE_CREATE_NONE, 0, 0); + if (!isHandleValid(handle)) + return String(); + return String::fromUTF8(tempPath.get()); +} + +PlatformFileHandle openFile(const String& path, FileOpenMode mode) +{ + GUniquePtr<gchar> filename = unescapedFilename(path); + if (!filename) + return invalidPlatformFileHandle; + + GRefPtr<GFile> file = adoptGRef(g_file_new_for_path(filename.get())); + GFileIOStream* ioStream = 0; + if (mode == OpenForRead) + ioStream = g_file_open_readwrite(file.get(), 0, 0); + else if (mode == OpenForWrite) { + if (g_file_test(filename.get(), static_cast<GFileTest>(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))) + ioStream = g_file_open_readwrite(file.get(), 0, 0); + else + ioStream = g_file_create_readwrite(file.get(), G_FILE_CREATE_NONE, 0, 0); + } + + return ioStream; +} + +void closeFile(PlatformFileHandle& handle) +{ + if (!isHandleValid(handle)) + return; + + g_io_stream_close(G_IO_STREAM(handle), 0, 0); + g_object_unref(handle); + handle = invalidPlatformFileHandle; +} + +long long seekFile(PlatformFileHandle handle, long long offset, FileSeekOrigin origin) +{ + GSeekType seekType = G_SEEK_SET; + switch (origin) { + case SeekFromBeginning: + seekType = G_SEEK_SET; + break; + case SeekFromCurrent: + seekType = G_SEEK_CUR; + break; + case SeekFromEnd: + seekType = G_SEEK_END; + break; + default: + ASSERT_NOT_REACHED(); + } + + if (!g_seekable_seek(G_SEEKABLE(g_io_stream_get_input_stream(G_IO_STREAM(handle))), + offset, seekType, 0, 0)) + { + return -1; + } + return g_seekable_tell(G_SEEKABLE(g_io_stream_get_input_stream(G_IO_STREAM(handle)))); +} + +int writeToFile(PlatformFileHandle handle, const char* data, int length) +{ + gsize bytesWritten; + g_output_stream_write_all(g_io_stream_get_output_stream(G_IO_STREAM(handle)), + data, length, &bytesWritten, 0, 0); + return bytesWritten; +} + +int readFromFile(PlatformFileHandle handle, char* data, int length) +{ + GUniqueOutPtr<GError> error; + do { + gssize bytesRead = g_input_stream_read(g_io_stream_get_input_stream(G_IO_STREAM(handle)), + data, length, 0, &error.outPtr()); + if (bytesRead >= 0) + return bytesRead; + } while (error && error->code == G_FILE_ERROR_INTR); + return -1; +} + +bool moveFile(const String& oldPath, const String& newPath) +{ + GUniquePtr<gchar> oldFilename = unescapedFilename(oldPath); + if (!oldFilename) + return false; + + GUniquePtr<gchar> newFilename = unescapedFilename(newPath); + if (!newFilename) + return false; + + return g_rename(oldFilename.get(), newFilename.get()) != -1; +} + +bool unloadModule(PlatformModule module) +{ +#if OS(WINDOWS) + return ::FreeLibrary(module); +#else + return g_module_close(module); +#endif +} + +bool hardLinkOrCopyFile(const String& source, const String& destination) +{ +#if OS(WINDOWS) + return !!::CopyFile(source.charactersWithNullTermination().data(), destination.charactersWithNullTermination().data(), TRUE); +#else + GUniquePtr<gchar> sourceFilename = unescapedFilename(source); + if (!sourceFilename) + return false; + + GUniquePtr<gchar> destinationFilename = unescapedFilename(destination); + if (!destinationFilename) + return false; + + if (!link(sourceFilename.get(), destinationFilename.get())) + return true; + + // Hard link failed. Perform a copy instead. + GRefPtr<GFile> sourceFile = adoptGRef(g_file_new_for_path(sourceFilename.get())); + GRefPtr<GFile> destinationFile = adoptGRef(g_file_new_for_path(destinationFilename.get())); + return g_file_copy(sourceFile.get(), destinationFile.get(), G_FILE_COPY_NONE, nullptr, nullptr, nullptr, nullptr); +#endif +} + +std::optional<int32_t> getFileDeviceId(const CString& fsFile) +{ + GUniquePtr<gchar> filename = unescapedFilename(fsFile.data()); + if (!filename) + return std::nullopt; + + GRefPtr<GFile> file = adoptGRef(g_file_new_for_path(filename.get())); + GRefPtr<GFileInfo> fileInfo = adoptGRef(g_file_query_filesystem_info(file.get(), G_FILE_ATTRIBUTE_UNIX_DEVICE, nullptr, nullptr)); + if (!fileInfo) + return std::nullopt; + + return g_file_info_get_attribute_uint32(fileInfo.get(), G_FILE_ATTRIBUTE_UNIX_DEVICE); +} + +} diff --git a/Source/WebCore/platform/glib/KeyedDecoderGlib.cpp b/Source/WebCore/platform/glib/KeyedDecoderGlib.cpp new file mode 100644 index 000000000..551090e02 --- /dev/null +++ b/Source/WebCore/platform/glib/KeyedDecoderGlib.cpp @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2015 Igalia S.L. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "KeyedDecoderGlib.h" + +#include <wtf/text/CString.h> + +namespace WebCore { + +std::unique_ptr<KeyedDecoder> KeyedDecoder::decoder(const uint8_t* data, size_t size) +{ + return std::make_unique<KeyedDecoderGlib>(data, size); +} + +KeyedDecoderGlib::KeyedDecoderGlib(const uint8_t* data, size_t size) +{ + GRefPtr<GBytes> bytes = adoptGRef(g_bytes_new(data, size)); + GRefPtr<GVariant> variant = g_variant_new_from_bytes(G_VARIANT_TYPE("a{sv}"), bytes.get(), TRUE); + m_dictionaryStack.append(dictionaryFromGVariant(variant.get())); +} + +KeyedDecoderGlib::~KeyedDecoderGlib() +{ + ASSERT(m_dictionaryStack.size() == 1); + ASSERT(m_arrayStack.isEmpty()); + ASSERT(m_arrayIndexStack.isEmpty()); +} + +HashMap<String, GRefPtr<GVariant>> KeyedDecoderGlib::dictionaryFromGVariant(GVariant* variant) +{ + HashMap<String, GRefPtr<GVariant>> dictionary; + GVariantIter iter; + g_variant_iter_init(&iter, variant); + const char* key; + GVariant* value; + while (g_variant_iter_loop(&iter, "{&sv}", &key, &value)) + dictionary.set(String::fromUTF8(key), value); + return dictionary; +} + +bool KeyedDecoderGlib::decodeBytes(const String& key, const uint8_t*& bytes, size_t& size) +{ + GRefPtr<GVariant> value = m_dictionaryStack.last().get(key); + if (!value) + return false; + + size = g_variant_get_size(value.get()); + bytes = static_cast<const uint8_t*>(g_variant_get_data(value.get())); + return true; +} + +template<typename T, typename F> +bool KeyedDecoderGlib::decodeSimpleValue(const String& key, T& result, F getFunction) +{ + GRefPtr<GVariant> value = m_dictionaryStack.last().get(key); + if (!value) + return false; + + result = getFunction(value.get()); + return true; +} + +bool KeyedDecoderGlib::decodeBool(const String& key, bool& result) +{ + return decodeSimpleValue(key, result, g_variant_get_boolean); +} + +bool KeyedDecoderGlib::decodeUInt32(const String& key, uint32_t& result) +{ + return decodeSimpleValue(key, result, g_variant_get_uint32); +} + +bool KeyedDecoderGlib::decodeInt32(const String& key, int32_t& result) +{ + return decodeSimpleValue(key, result, g_variant_get_int32); +} + +bool KeyedDecoderGlib::decodeInt64(const String& key, int64_t& result) +{ + return decodeSimpleValue(key, result, g_variant_get_int64); +} + +bool KeyedDecoderGlib::decodeFloat(const String& key, float& result) +{ + return decodeSimpleValue(key, result, g_variant_get_double); +} + +bool KeyedDecoderGlib::decodeDouble(const String& key, double& result) +{ + return decodeSimpleValue(key, result, g_variant_get_double); +} + +bool KeyedDecoderGlib::decodeString(const String& key, String& result) +{ + GRefPtr<GVariant> value = m_dictionaryStack.last().get(key); + if (!value) + return false; + + result = String::fromUTF8(g_variant_get_string(value.get(), nullptr)); + return true; +} + +bool KeyedDecoderGlib::beginObject(const String& key) +{ + GRefPtr<GVariant> value = m_dictionaryStack.last().get(key); + if (!value) + return false; + + m_dictionaryStack.append(dictionaryFromGVariant(value.get())); + return true; +} + +void KeyedDecoderGlib::endObject() +{ + m_dictionaryStack.removeLast(); +} + +bool KeyedDecoderGlib::beginArray(const String& key) +{ + GRefPtr<GVariant> value = m_dictionaryStack.last().get(key); + if (!value) + return false; + + m_arrayStack.append(value.get()); + m_arrayIndexStack.append(0); + return true; +} + +bool KeyedDecoderGlib::beginArrayElement() +{ + if (m_arrayIndexStack.last() >= g_variant_n_children(m_arrayStack.last())) + return false; + + GRefPtr<GVariant> variant = adoptGRef(g_variant_get_child_value(m_arrayStack.last(), m_arrayIndexStack.last()++)); + m_dictionaryStack.append(dictionaryFromGVariant(variant.get())); + return true; +} + +void KeyedDecoderGlib::endArrayElement() +{ + m_dictionaryStack.removeLast(); +} + +void KeyedDecoderGlib::endArray() +{ + m_arrayStack.removeLast(); + m_arrayIndexStack.removeLast(); +} + +} // namespace WebCore diff --git a/Source/WebCore/platform/glib/KeyedDecoderGlib.h b/Source/WebCore/platform/glib/KeyedDecoderGlib.h new file mode 100644 index 000000000..aee3692ca --- /dev/null +++ b/Source/WebCore/platform/glib/KeyedDecoderGlib.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2015 Igaia S.L. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef KeyedDecoderGlib_h +#define KeyedDecoderGlib_h + +#include "KeyedCoding.h" +#include <glib.h> +#include <wtf/HashMap.h> +#include <wtf/glib/GRefPtr.h> +#include <wtf/text/StringHash.h> +#include <wtf/text/WTFString.h> + +namespace WebCore { + +class KeyedDecoderGlib final : public KeyedDecoder { +public: + KeyedDecoderGlib(const uint8_t* data, size_t); + ~KeyedDecoderGlib() override; + +private: + bool decodeBytes(const String& key, const uint8_t*&, size_t&) override; + bool decodeBool(const String& key, bool&) override; + bool decodeUInt32(const String& key, uint32_t&) override; + bool decodeInt32(const String& key, int32_t&) override; + bool decodeInt64(const String& key, int64_t&) override; + bool decodeFloat(const String& key, float&) override; + bool decodeDouble(const String& key, double&) override; + bool decodeString(const String& key, String&) override; + + bool beginObject(const String& key) override; + void endObject() override; + + bool beginArray(const String& key) override; + bool beginArrayElement() override; + void endArrayElement() override; + void endArray() override; + + template<typename T, typename F> bool decodeSimpleValue(const String& key, T& result, F getFunction); + HashMap<String, GRefPtr<GVariant>> dictionaryFromGVariant(GVariant*); + + Vector<HashMap<String, GRefPtr<GVariant>>> m_dictionaryStack; + Vector<GVariant*, 16> m_arrayStack; + Vector<unsigned> m_arrayIndexStack; +}; + +} // namespace WebCore + +#endif // KeyedDecoderGlib_h diff --git a/Source/WebCore/platform/glib/KeyedEncoderGlib.cpp b/Source/WebCore/platform/glib/KeyedEncoderGlib.cpp new file mode 100644 index 000000000..81cbed53d --- /dev/null +++ b/Source/WebCore/platform/glib/KeyedEncoderGlib.cpp @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2015 Igalia S.L. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "KeyedEncoderGlib.h" + +#include "SharedBuffer.h" +#include <wtf/text/CString.h> + +namespace WebCore { + +std::unique_ptr<KeyedEncoder> KeyedEncoder::encoder() +{ + return std::make_unique<KeyedEncoderGlib>(); +} + +KeyedEncoderGlib::KeyedEncoderGlib() +{ + g_variant_builder_init(&m_variantBuilder, G_VARIANT_TYPE("a{sv}")); + m_variantBuilderStack.append(&m_variantBuilder); +} + +KeyedEncoderGlib::~KeyedEncoderGlib() +{ + ASSERT(m_variantBuilderStack.size() == 1); + ASSERT(m_variantBuilderStack.last() == &m_variantBuilder); + ASSERT(m_arrayStack.isEmpty()); + ASSERT(m_objectStack.isEmpty()); +} + +void KeyedEncoderGlib::encodeBytes(const String& key, const uint8_t* bytes, size_t size) +{ + GRefPtr<GBytes> gBytes = adoptGRef(g_bytes_new_static(bytes, size)); + g_variant_builder_add(m_variantBuilderStack.last(), "{sv}", key.utf8().data(), g_variant_new_from_bytes(G_VARIANT_TYPE("ay"), gBytes.get(), TRUE)); +} + +void KeyedEncoderGlib::encodeBool(const String& key, bool value) +{ + g_variant_builder_add(m_variantBuilderStack.last(), "{sv}", key.utf8().data(), g_variant_new_boolean(value)); +} + +void KeyedEncoderGlib::encodeUInt32(const String& key, uint32_t value) +{ + g_variant_builder_add(m_variantBuilderStack.last(), "{sv}", key.utf8().data(), g_variant_new_uint32(value)); +} + +void KeyedEncoderGlib::encodeInt32(const String& key, int32_t value) +{ + g_variant_builder_add(m_variantBuilderStack.last(), "{sv}", key.utf8().data(), g_variant_new_int32(value)); +} + +void KeyedEncoderGlib::encodeInt64(const String& key, int64_t value) +{ + g_variant_builder_add(m_variantBuilderStack.last(), "{sv}", key.utf8().data(), g_variant_new_int64(value)); +} + +void KeyedEncoderGlib::encodeFloat(const String& key, float value) +{ + encodeDouble(key, value); +} + +void KeyedEncoderGlib::encodeDouble(const String& key, double value) +{ + g_variant_builder_add(m_variantBuilderStack.last(), "{sv}", key.utf8().data(), g_variant_new_double(value)); +} + +void KeyedEncoderGlib::encodeString(const String& key, const String& value) +{ + g_variant_builder_add(m_variantBuilderStack.last(), "{sv}", key.utf8().data(), g_variant_new_string(value.utf8().data())); +} + +void KeyedEncoderGlib::beginObject(const String& key) +{ + GRefPtr<GVariantBuilder> builder = adoptGRef(g_variant_builder_new(G_VARIANT_TYPE("aa{sv}"))); + m_objectStack.append(std::make_pair(key, builder)); + m_variantBuilderStack.append(builder.get()); +} + +void KeyedEncoderGlib::endObject() +{ + GVariantBuilder* builder = m_variantBuilderStack.takeLast(); + g_variant_builder_add(m_variantBuilderStack.last(), "{sv}", m_objectStack.last().first.utf8().data(), g_variant_builder_end(builder)); + m_objectStack.removeLast(); +} + +void KeyedEncoderGlib::beginArray(const String& key) +{ + m_arrayStack.append(std::make_pair(key, adoptGRef(g_variant_builder_new(G_VARIANT_TYPE("aa{sv}"))))); +} + +void KeyedEncoderGlib::beginArrayElement() +{ + m_variantBuilderStack.append(g_variant_builder_new(G_VARIANT_TYPE("a{sv}"))); +} + +void KeyedEncoderGlib::endArrayElement() +{ + GRefPtr<GVariantBuilder> variantBuilder = adoptGRef(m_variantBuilderStack.takeLast()); + g_variant_builder_add_value(m_arrayStack.last().second.get(), g_variant_builder_end(variantBuilder.get())); +} + +void KeyedEncoderGlib::endArray() +{ + g_variant_builder_add(m_variantBuilderStack.last(), "{sv}", m_arrayStack.last().first.utf8().data(), g_variant_builder_end(m_arrayStack.last().second.get())); + m_arrayStack.removeLast(); +} + +RefPtr<SharedBuffer> KeyedEncoderGlib::finishEncoding() +{ + g_assert(m_variantBuilderStack.last() == &m_variantBuilder); + GRefPtr<GVariant> variant = g_variant_builder_end(&m_variantBuilder); + GRefPtr<GBytes> data = g_variant_get_data_as_bytes(variant.get()); + return SharedBuffer::create(static_cast<const unsigned char*>(g_bytes_get_data(data.get(), nullptr)), static_cast<unsigned>(g_bytes_get_size(data.get()))); +} + +} // namespace WebCore diff --git a/Source/WebCore/platform/glib/KeyedEncoderGlib.h b/Source/WebCore/platform/glib/KeyedEncoderGlib.h new file mode 100644 index 000000000..f91b4ddb3 --- /dev/null +++ b/Source/WebCore/platform/glib/KeyedEncoderGlib.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2015 Igalia S.L. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "KeyedCoding.h" +#include <glib.h> +#include <wtf/Vector.h> +#include <wtf/glib/GRefPtr.h> +#include <wtf/text/WTFString.h> + +namespace WebCore { + +class KeyedEncoderGlib final : public KeyedEncoder { +public: + KeyedEncoderGlib(); + ~KeyedEncoderGlib(); + +private: + RefPtr<WebCore::SharedBuffer> finishEncoding() final; + + void encodeBytes(const String& key, const uint8_t*, size_t) final; + void encodeBool(const String& key, bool) final; + void encodeUInt32(const String& key, uint32_t) final; + void encodeInt32(const String& key, int32_t) final; + void encodeInt64(const String& key, int64_t) final; + void encodeFloat(const String& key, float) final; + void encodeDouble(const String& key, double) final; + void encodeString(const String& key, const String&) final; + + void beginObject(const String& key) final; + void endObject() final; + + void beginArray(const String& key) final; + void beginArrayElement() final; + void endArrayElement() final; + void endArray() final; + + GVariantBuilder m_variantBuilder; + Vector<GVariantBuilder*, 16> m_variantBuilderStack; + Vector<std::pair<String, GRefPtr<GVariantBuilder>>, 16> m_arrayStack; + Vector<std::pair<String, GRefPtr<GVariantBuilder>>, 16> m_objectStack; +}; + +} // namespace WebCore diff --git a/Source/WebCore/platform/glib/MainThreadSharedTimerGLib.cpp b/Source/WebCore/platform/glib/MainThreadSharedTimerGLib.cpp new file mode 100644 index 000000000..284f8b17e --- /dev/null +++ b/Source/WebCore/platform/glib/MainThreadSharedTimerGLib.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2006-2016 Apple Inc. All rights reserved. + * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "MainThreadSharedTimer.h" + +#include <glib.h> + +namespace WebCore { + +MainThreadSharedTimer::MainThreadSharedTimer() + : m_timer(RunLoop::main(), this, &MainThreadSharedTimer::fired) +{ + // This is GDK_PRIORITY_REDRAW, but we don't want to depend on GDK here just to use a constant. + m_timer.setPriority(G_PRIORITY_HIGH_IDLE + 20); +} + +void MainThreadSharedTimer::setFireInterval(Seconds interval) +{ + ASSERT(m_firedFunction); + m_timer.startOneShot(interval.value()); +} + +void MainThreadSharedTimer::stop() +{ + m_timer.stop(); +} + +void MainThreadSharedTimer::invalidate() +{ +} + +} // namespace WebCore diff --git a/Source/WebCore/platform/glib/SharedBufferGlib.cpp b/Source/WebCore/platform/glib/SharedBufferGlib.cpp new file mode 100644 index 000000000..e1522f6fa --- /dev/null +++ b/Source/WebCore/platform/glib/SharedBufferGlib.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2008 Collabora Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "SharedBuffer.h" + +#include "FileSystem.h" +#include <wtf/glib/GUniquePtr.h> +#include <wtf/text/CString.h> + +#include <glib.h> + + +namespace WebCore { + +RefPtr<SharedBuffer> SharedBuffer::createFromReadingFile(const String& filePath) +{ + if (filePath.isEmpty()) + return 0; + + CString filename = fileSystemRepresentation(filePath); + GUniqueOutPtr<gchar> contents; + gsize size; + GUniqueOutPtr<GError> error; + if (!g_file_get_contents(filename.data(), &contents.outPtr(), &size, &error.outPtr())) { + LOG_ERROR("Failed to fully read contents of file %s - %s", filenameForDisplay(filePath).utf8().data(), error->message); + return 0; + } + + RefPtr<SharedBuffer> result = SharedBuffer::create(contents.get(), size); + + return result.release(); +} + +} // namespace WebCore |