blob: 8f4f57688ac82184fedeb860ddcb3aacdcfa3fb0 [file] [log] [blame]
/*
* Copyright (C) 2010 Apple Inc. 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. 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 UserMessageCoders_h
#define UserMessageCoders_h
#include "APIArray.h"
#include "APIData.h"
#include "APIError.h"
#include "APIGeometry.h"
#include "APINumber.h"
#include "APIString.h"
#include "APIURL.h"
#include "APIURLRequest.h"
#include "APIURLResponse.h"
#include "ArgumentDecoder.h"
#include "ArgumentEncoder.h"
#include "DataReference.h"
#include "ImmutableDictionary.h"
#include "ShareableBitmap.h"
#include "WebCertificateInfo.h"
#include "WebCoreArgumentCoders.h"
#include "WebImage.h"
#include "WebRenderLayer.h"
#include "WebRenderObject.h"
#include "WebSerializedScriptValue.h"
#include "WebUserContentURLPattern.h"
namespace WebKit {
// - Null -> Null
// - API::Array -> API::Array
// - Dictionary -> Dictionary
// - SerializedScriptValue -> SerializedScriptValue
// - API::String -> API::String
// - UserContentURLPattern -> UserContentURLPattern
// - WebCertificateInfo -> WebCertificateInfo
// - API::Data -> API::Data
// - API::Double -> API::Double
// - WebImage -> WebImage
// - WebRenderLayer -> WebRenderLayer
// - WebRenderObject -> WebRenderObject
// - API::UInt64 -> API::UInt64
// - API::URL -> API::URL
// - API::URLRequest -> API::URLRequest
// - API::URLResponse -> API::URLResponse
// - API::Error -> API::Error
template<typename Owner>
class UserMessageEncoder {
public:
bool baseEncode(IPC::ArgumentEncoder& encoder, const Owner& coder, API::Object::Type& type) const
{
if (!m_root) {
encoder << static_cast<uint32_t>(API::Object::Type::Null);
return true;
}
type = m_root->type();
encoder << static_cast<uint32_t>(type);
switch (type) {
case API::Object::Type::Array: {
API::Array* array = static_cast<API::Array*>(m_root);
encoder << static_cast<uint64_t>(array->size());
for (size_t i = 0; i < array->size(); ++i)
encoder << Owner(coder, array->at(i));
return true;
}
case API::Object::Type::Dictionary: {
ImmutableDictionary* dictionary = static_cast<ImmutableDictionary*>(m_root);
const ImmutableDictionary::MapType& map = dictionary->map();
encoder << static_cast<uint64_t>(map.size());
ImmutableDictionary::MapType::const_iterator it = map.begin();
ImmutableDictionary::MapType::const_iterator end = map.end();
for (; it != end; ++it) {
encoder << it->key;
encoder << Owner(coder, it->value.get());
}
return true;
}
case API::Object::Type::String: {
API::String* string = static_cast<API::String*>(m_root);
encoder << string->string();
return true;
}
case API::Object::Type::SerializedScriptValue: {
WebSerializedScriptValue* scriptValue = static_cast<WebSerializedScriptValue*>(m_root);
encoder << scriptValue->dataReference();
return true;
}
case API::Object::Type::Boolean: {
API::Boolean* booleanObject = static_cast<API::Boolean*>(m_root);
encoder << booleanObject->value();
return true;
}
case API::Object::Type::Double: {
API::Double* doubleObject = static_cast<API::Double*>(m_root);
encoder << doubleObject->value();
return true;
}
case API::Object::Type::UInt64: {
API::UInt64* uint64Object = static_cast<API::UInt64*>(m_root);
encoder << uint64Object->value();
return true;
}
case API::Object::Type::Point: {
API::Point* pointObject = static_cast<API::Point*>(m_root);
encoder << pointObject->point().x;
encoder << pointObject->point().y;
return true;
}
case API::Object::Type::Size: {
API::Size* sizeObject = static_cast<API::Size*>(m_root);
encoder << sizeObject->size().width;
encoder << sizeObject->size().height;
return true;
}
case API::Object::Type::Rect: {
API::Rect* rectObject = static_cast<API::Rect*>(m_root);
encoder << rectObject->rect().origin.x;
encoder << rectObject->rect().origin.y;
encoder << rectObject->rect().size.width;
encoder << rectObject->rect().size.height;
return true;
}
case API::Object::Type::RenderLayer: {
WebRenderLayer* renderLayer = static_cast<WebRenderLayer*>(m_root);
encoder << Owner(coder, renderLayer->renderer());
encoder << renderLayer->isReflection();
encoder << renderLayer->isClipping();
encoder << renderLayer->isClipped();
encoder << static_cast<uint32_t>(renderLayer->compositingLayerType());
encoder << renderLayer->absoluteBoundingBox();
encoder << Owner(coder, renderLayer->negativeZOrderList());
encoder << Owner(coder, renderLayer->normalFlowList());
encoder << Owner(coder, renderLayer->positiveZOrderList());
return true;
}
case API::Object::Type::RenderObject: {
WebRenderObject* renderObject = static_cast<WebRenderObject*>(m_root);
encoder << renderObject->name();
encoder << renderObject->elementTagName();
encoder << renderObject->elementID();
encoder << Owner(coder, renderObject->elementClassNames());
encoder << renderObject->absolutePosition();
encoder << renderObject->frameRect();
encoder << Owner(coder, renderObject->children());
return true;
}
case API::Object::Type::URL: {
API::URL* urlObject = static_cast<API::URL*>(m_root);
encoder << urlObject->string();
return true;
}
case API::Object::Type::URLRequest: {
API::URLRequest* urlRequestObject = static_cast<API::URLRequest*>(m_root);
encoder << urlRequestObject->resourceRequest();
return true;
}
case API::Object::Type::URLResponse: {
API::URLResponse* urlResponseObject = static_cast<API::URLResponse*>(m_root);
encoder << urlResponseObject->resourceResponse();
return true;
}
case API::Object::Type::UserContentURLPattern: {
WebUserContentURLPattern* urlPattern = static_cast<WebUserContentURLPattern*>(m_root);
encoder << urlPattern->patternString();
return true;
}
case API::Object::Type::Image: {
WebImage* image = static_cast<WebImage*>(m_root);
ShareableBitmap::Handle handle;
ASSERT(!image->bitmap() || image->bitmap()->isBackedBySharedMemory());
if (!image->bitmap() || !image->bitmap()->isBackedBySharedMemory() || !image->bitmap()->createHandle(handle)) {
// Initial false indicates no allocated bitmap or is not shareable.
encoder << false;
return true;
}
// Initial true indicates a bitmap was allocated and is shareable.
encoder << true;
encoder << handle;
return true;
}
case API::Object::Type::Data: {
API::Data* data = static_cast<API::Data*>(m_root);
encoder << data->dataReference();
return true;
}
case API::Object::Type::CertificateInfo: {
WebCertificateInfo* certificateInfo = static_cast<WebCertificateInfo*>(m_root);
encoder << certificateInfo->certificateInfo();
return true;
}
case API::Object::Type::Error: {
API::Error* errorObject = static_cast<API::Error*>(m_root);
encoder << errorObject->platformError();
return true;
}
default:
break;
}
return false;
}
protected:
UserMessageEncoder(API::Object* root)
: m_root(root)
{
}
API::Object* m_root;
};
// Handles
// - Null -> Null
// - API::Array -> API::Array
// - Dictionary -> Dictionary
// - SerializedScriptValue -> SerializedScriptValue
// - API::String -> API::String
// - UserContentURLPattern -> UserContentURLPattern
// - WebCertificateInfo -> WebCertificateInfo
// - API::Data -> API::Data
// - API::Double -> API::Double
// - WebImage -> WebImage
// - API::UInt64 -> API::UInt64
// - API::URL -> API::URL
// - API::URLRequest -> API::URLRequest
// - API::URLResponse -> API::URLResponse
// - API::Error -> API::Error
template<typename Owner>
class UserMessageDecoder {
public:
static bool baseDecode(IPC::ArgumentDecoder& decoder, Owner& coder, API::Object::Type& type)
{
uint32_t typeAsUInt32;
if (!decoder.decode(typeAsUInt32))
return false;
type = static_cast<API::Object::Type>(typeAsUInt32);
switch (type) {
case API::Object::Type::Array: {
uint64_t size;
if (!decoder.decode(size))
return false;
Vector<RefPtr<API::Object>> vector;
for (size_t i = 0; i < size; ++i) {
RefPtr<API::Object> element;
Owner messageCoder(coder, element);
if (!decoder.decode(messageCoder))
return false;
vector.append(element.release());
}
coder.m_root = API::Array::create(std::move(vector));
break;
}
case API::Object::Type::Dictionary: {
uint64_t size;
if (!decoder.decode(size))
return false;
ImmutableDictionary::MapType map;
for (size_t i = 0; i < size; ++i) {
String key;
if (!decoder.decode(key))
return false;
RefPtr<API::Object> element;
Owner messageCoder(coder, element);
if (!decoder.decode(messageCoder))
return false;
ImmutableDictionary::MapType::AddResult result = map.set(key, element.release());
if (!result.isNewEntry)
return false;
}
coder.m_root = ImmutableDictionary::create(std::move(map));
break;
}
case API::Object::Type::String: {
String string;
if (!decoder.decode(string))
return false;
coder.m_root = API::String::create(string);
break;
}
case API::Object::Type::SerializedScriptValue: {
IPC::DataReference dataReference;
if (!decoder.decode(dataReference))
return false;
Vector<uint8_t> vector = dataReference.vector();
coder.m_root = WebSerializedScriptValue::adopt(vector);
break;
}
case API::Object::Type::Double: {
double value;
if (!decoder.decode(value))
return false;
coder.m_root = API::Double::create(value);
break;
}
case API::Object::Type::UInt64: {
uint64_t value;
if (!decoder.decode(value))
return false;
coder.m_root = API::UInt64::create(value);
break;
}
case API::Object::Type::Boolean: {
bool value;
if (!decoder.decode(value))
return false;
coder.m_root = API::Boolean::create(value);
break;
}
case API::Object::Type::Size: {
double width;
double height;
if (!decoder.decode(width))
return false;
if (!decoder.decode(height))
return false;
coder.m_root = API::Size::create(WKSizeMake(width, height));
break;
}
case API::Object::Type::Point: {
double x;
double y;
if (!decoder.decode(x))
return false;
if (!decoder.decode(y))
return false;
coder.m_root = API::Point::create(WKPointMake(x, y));
break;
}
case API::Object::Type::Rect: {
double x;
double y;
double width;
double height;
if (!decoder.decode(x))
return false;
if (!decoder.decode(y))
return false;
if (!decoder.decode(width))
return false;
if (!decoder.decode(height))
return false;
coder.m_root = API::Rect::create(WKRectMake(x, y, width, height));
break;
}
case API::Object::Type::RenderLayer: {
RefPtr<API::Object> renderer;
bool isReflection;
bool isClipping;
bool isClipped;
uint32_t compositingLayerTypeAsUInt32;
WebCore::IntRect absoluteBoundingBox;
RefPtr<API::Object> negativeZOrderList;
RefPtr<API::Object> normalFlowList;
RefPtr<API::Object> positiveZOrderList;
Owner rendererCoder(coder, renderer);
if (!decoder.decode(rendererCoder))
return false;
if (renderer->type() != API::Object::Type::RenderObject)
return false;
if (!decoder.decode(isReflection))
return false;
if (!decoder.decode(isClipping))
return false;
if (!decoder.decode(isClipped))
return false;
if (!decoder.decode(compositingLayerTypeAsUInt32))
return false;
if (!decoder.decode(absoluteBoundingBox))
return false;
Owner negativeZOrderListCoder(coder, negativeZOrderList);
if (!decoder.decode(negativeZOrderListCoder))
return false;
Owner normalFlowListCoder(coder, normalFlowList);
if (!decoder.decode(normalFlowListCoder))
return false;
Owner positiveZOrderListCoder(coder, positiveZOrderList);
if (!decoder.decode(positiveZOrderListCoder))
return false;
coder.m_root = WebRenderLayer::create(static_pointer_cast<WebRenderObject>(renderer), isReflection, isClipping, isClipped, static_cast<WebRenderLayer::CompositingLayerType>(compositingLayerTypeAsUInt32),
absoluteBoundingBox, static_pointer_cast<API::Array>(negativeZOrderList), static_pointer_cast<API::Array>(normalFlowList),
static_pointer_cast<API::Array>(positiveZOrderList));
break;
}
case API::Object::Type::RenderObject: {
String name;
String elementTagName;
String elementID;
RefPtr<API::Object> elementClassNames;
WebCore::IntPoint absolutePosition;
WebCore::IntRect frameRect;
RefPtr<API::Object> children;
if (!decoder.decode(name))
return false;
if (!decoder.decode(elementTagName))
return false;
if (!decoder.decode(elementID))
return false;
Owner classNamesCoder(coder, elementClassNames);
if (!decoder.decode(classNamesCoder))
return false;
if (!decoder.decode(absolutePosition))
return false;
if (!decoder.decode(frameRect))
return false;
Owner messageCoder(coder, children);
if (!decoder.decode(messageCoder))
return false;
if (children && children->type() != API::Object::Type::Array)
return false;
coder.m_root = WebRenderObject::create(name, elementTagName, elementID, static_pointer_cast<API::Array>(elementClassNames), absolutePosition, frameRect, static_pointer_cast<API::Array>(children));
break;
}
case API::Object::Type::URL: {
String string;
if (!decoder.decode(string))
return false;
coder.m_root = API::URL::create(string);
break;
}
case API::Object::Type::URLRequest: {
WebCore::ResourceRequest request;
if (!decoder.decode(request))
return false;
coder.m_root = API::URLRequest::create(request);
break;
}
case API::Object::Type::URLResponse: {
WebCore::ResourceResponse response;
if (!decoder.decode(response))
return false;
coder.m_root = API::URLResponse::create(response);
break;
}
case API::Object::Type::UserContentURLPattern: {
String string;
if (!decoder.decode(string))
return false;
coder.m_root = WebUserContentURLPattern::create(string);
break;
}
case API::Object::Type::Image: {
bool didEncode = false;
if (!decoder.decode(didEncode))
return false;
if (!didEncode)
break;
ShareableBitmap::Handle handle;
if (!decoder.decode(handle))
return false;
coder.m_root = WebImage::create(ShareableBitmap::create(handle));
return true;
}
case API::Object::Type::Data: {
IPC::DataReference dataReference;
if (!decoder.decode(dataReference))
return false;
coder.m_root = API::Data::create(dataReference.data(), dataReference.size());
break;
}
case API::Object::Type::CertificateInfo: {
WebCore::CertificateInfo certificateInfo;
if (!decoder.decode(certificateInfo))
return false;
coder.m_root = WebCertificateInfo::create(certificateInfo);
break;
}
case API::Object::Type::Error: {
WebCore::ResourceError resourceError;
if (!decoder.decode(resourceError))
return false;
coder.m_root = API::Error::create(resourceError);
break;
}
default:
break;
}
return true;
}
protected:
UserMessageDecoder(RefPtr<API::Object>& root)
: m_root(root)
{
}
RefPtr<API::Object>& m_root;
};
} // namespace WebKit
#endif // UserMessageCoders_h