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 "InjectedBundlePageEditorClient.h"
28
29#include "ImmutableArray.h"
30#include "InjectedBundleNodeHandle.h"
31#include "InjectedBundleRangeHandle.h"
32#include "WKAPICast.h"
33#include "WKBundleAPICast.h"
34#include "WKString.h"
35#include "WebData.h"
36#include <wtf/text/WTFString.h>
37
38using namespace WebCore;
39
40namespace WebKit {
41
42bool InjectedBundlePageEditorClient::shouldBeginEditing(WebPage* page, Range* range)
43{
44    if (m_client.shouldBeginEditing) {
45        RefPtr<InjectedBundleRangeHandle> rangeHandle = InjectedBundleRangeHandle::getOrCreate(range);
46        return m_client.shouldBeginEditing(toAPI(page), toAPI(rangeHandle.get()), m_client.clientInfo);
47    }
48    return true;
49}
50
51bool InjectedBundlePageEditorClient::shouldEndEditing(WebPage* page, Range* range)
52{
53    if (m_client.shouldEndEditing) {
54        RefPtr<InjectedBundleRangeHandle> rangeHandle = InjectedBundleRangeHandle::getOrCreate(range);
55        return m_client.shouldEndEditing(toAPI(page), toAPI(rangeHandle.get()), m_client.clientInfo);
56    }
57    return true;
58}
59
60bool InjectedBundlePageEditorClient::shouldInsertNode(WebPage* page, Node* node, Range* rangeToReplace, EditorInsertAction action)
61{
62    if (m_client.shouldInsertNode) {
63        RefPtr<InjectedBundleNodeHandle> nodeHandle = InjectedBundleNodeHandle::getOrCreate(node);
64        RefPtr<InjectedBundleRangeHandle> rangeToReplaceHandle = InjectedBundleRangeHandle::getOrCreate(rangeToReplace);
65        return m_client.shouldInsertNode(toAPI(page), toAPI(nodeHandle.get()), toAPI(rangeToReplaceHandle.get()), toAPI(action), m_client.clientInfo);
66    }
67    return true;
68}
69
70bool InjectedBundlePageEditorClient::shouldInsertText(WebPage* page, StringImpl* text, Range* rangeToReplace, EditorInsertAction action)
71{
72    if (m_client.shouldInsertText) {
73        RefPtr<InjectedBundleRangeHandle> rangeToReplaceHandle = InjectedBundleRangeHandle::getOrCreate(rangeToReplace);
74        return m_client.shouldInsertText(toAPI(page), toAPI(text), toAPI(rangeToReplaceHandle.get()), toAPI(action), m_client.clientInfo);
75    }
76    return true;
77}
78
79bool InjectedBundlePageEditorClient::shouldDeleteRange(WebPage* page, Range* range)
80{
81    if (m_client.shouldDeleteRange) {
82        RefPtr<InjectedBundleRangeHandle> rangeHandle = InjectedBundleRangeHandle::getOrCreate(range);
83        return m_client.shouldDeleteRange(toAPI(page), toAPI(rangeHandle.get()), m_client.clientInfo);
84    }
85    return true;
86}
87
88bool InjectedBundlePageEditorClient::shouldChangeSelectedRange(WebPage* page, Range* fromRange, Range* toRange, EAffinity affinity, bool stillSelecting)
89{
90    if (m_client.shouldChangeSelectedRange) {
91        RefPtr<InjectedBundleRangeHandle> fromRangeHandle = InjectedBundleRangeHandle::getOrCreate(fromRange);
92        RefPtr<InjectedBundleRangeHandle> toRangeHandle = InjectedBundleRangeHandle::getOrCreate(toRange);
93        return m_client.shouldChangeSelectedRange(toAPI(page), toAPI(fromRangeHandle.get()), toAPI(toRangeHandle.get()), toAPI(affinity), stillSelecting, m_client.clientInfo);
94    }
95    return true;
96}
97
98bool InjectedBundlePageEditorClient::shouldApplyStyle(WebPage* page, CSSStyleDeclaration* style, Range* range)
99{
100    if (m_client.shouldApplyStyle) {
101        RefPtr<InjectedBundleRangeHandle> rangeHandle = InjectedBundleRangeHandle::getOrCreate(range);
102        return m_client.shouldApplyStyle(toAPI(page), toAPI(style), toAPI(rangeHandle.get()), m_client.clientInfo);
103    }
104    return true;
105}
106
107void InjectedBundlePageEditorClient::didBeginEditing(WebPage* page, StringImpl* notificationName)
108{
109    if (m_client.didBeginEditing)
110        m_client.didBeginEditing(toAPI(page), toAPI(notificationName), m_client.clientInfo);
111}
112
113void InjectedBundlePageEditorClient::didEndEditing(WebPage* page, StringImpl* notificationName)
114{
115    if (m_client.didEndEditing)
116        m_client.didEndEditing(toAPI(page), toAPI(notificationName), m_client.clientInfo);
117}
118
119void InjectedBundlePageEditorClient::didChange(WebPage* page, StringImpl* notificationName)
120{
121    if (m_client.didChange)
122        m_client.didChange(toAPI(page), toAPI(notificationName), m_client.clientInfo);
123}
124
125void InjectedBundlePageEditorClient::didChangeSelection(WebPage* page, StringImpl* notificationName)
126{
127    if (m_client.didChangeSelection)
128        m_client.didChangeSelection(toAPI(page), toAPI(notificationName), m_client.clientInfo);
129}
130
131void InjectedBundlePageEditorClient::willWriteToPasteboard(WebPage* page, Range* range)
132{
133    if (m_client.willWriteToPasteboard) {
134        RefPtr<InjectedBundleRangeHandle> rangeHandle = InjectedBundleRangeHandle::getOrCreate(range);
135        m_client.willWriteToPasteboard(toAPI(page), toAPI(rangeHandle.get()), m_client.clientInfo);
136    }
137}
138
139void InjectedBundlePageEditorClient::getPasteboardDataForRange(WebPage* page, Range* range, Vector<String>& pasteboardTypes, Vector<RefPtr<SharedBuffer>>& pasteboardData)
140{
141    if (m_client.getPasteboardDataForRange) {
142        RefPtr<InjectedBundleRangeHandle> rangeHandle = InjectedBundleRangeHandle::getOrCreate(range);
143        WKArrayRef types = 0;
144        WKArrayRef data = 0;
145        m_client.getPasteboardDataForRange(toAPI(page), toAPI(rangeHandle.get()), &types, &data, m_client.clientInfo);
146        RefPtr<ImmutableArray> typesArray = adoptRef(toImpl(types));
147        RefPtr<ImmutableArray> dataArray = adoptRef(toImpl(data));
148
149        pasteboardTypes.clear();
150        pasteboardData.clear();
151
152        if (!typesArray || !dataArray)
153            return;
154
155        ASSERT(typesArray->size() == dataArray->size());
156
157        size_t size = typesArray->size();
158        for (size_t i = 0; i < size; ++i) {
159            WebString* type = typesArray->at<WebString>(i);
160            if (type)
161                pasteboardTypes.append(type->string());
162        }
163
164        size = dataArray->size();
165        for (size_t i = 0; i < size; ++i) {
166            WebData* item = dataArray->at<WebData>(i);
167            if (item) {
168                RefPtr<SharedBuffer> buffer = SharedBuffer::create(item->bytes(), item->size());
169                pasteboardData.append(buffer);
170            }
171        }
172    }
173}
174
175void InjectedBundlePageEditorClient::didWriteToPasteboard(WebPage* page)
176{
177    if (m_client.didWriteToPasteboard)
178        m_client.didWriteToPasteboard(toAPI(page), m_client.clientInfo);
179}
180
181} // namespace WebKit
182