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 "InjectedBundlePageFormClient.h" 28 29#include "APIArray.h" 30#include "ImmutableDictionary.h" 31#include "InjectedBundleNodeHandle.h" 32#include "WKAPICast.h" 33#include "WKBundleAPICast.h" 34#include <WebCore/HTMLFormElement.h> 35#include <WebCore/HTMLInputElement.h> 36#include <WebCore/HTMLTextAreaElement.h> 37 38using namespace WebCore; 39 40namespace WebKit { 41 42InjectedBundlePageFormClient::InjectedBundlePageFormClient(const WKBundlePageFormClientBase* client) 43{ 44 initialize(client); 45} 46 47void InjectedBundlePageFormClient::didFocusTextField(WebPage* page, HTMLInputElement* inputElement, WebFrame* frame) 48{ 49 if (!m_client.didFocusTextField) 50 return; 51 52 RefPtr<InjectedBundleNodeHandle> nodeHandle = InjectedBundleNodeHandle::getOrCreate(inputElement); 53 m_client.didFocusTextField(toAPI(page), toAPI(nodeHandle.get()), toAPI(frame), m_client.base.clientInfo); 54} 55 56void InjectedBundlePageFormClient::textFieldDidBeginEditing(WebPage* page, HTMLInputElement* inputElement, WebFrame* frame) 57{ 58 if (!m_client.textFieldDidBeginEditing) 59 return; 60 61 RefPtr<InjectedBundleNodeHandle> nodeHandle = InjectedBundleNodeHandle::getOrCreate(inputElement); 62 m_client.textFieldDidBeginEditing(toAPI(page), toAPI(nodeHandle.get()), toAPI(frame), m_client.base.clientInfo); 63} 64 65void InjectedBundlePageFormClient::textFieldDidEndEditing(WebPage* page, HTMLInputElement* inputElement, WebFrame* frame) 66{ 67 if (!m_client.textFieldDidEndEditing) 68 return; 69 70 RefPtr<InjectedBundleNodeHandle> nodeHandle = InjectedBundleNodeHandle::getOrCreate(inputElement); 71 m_client.textFieldDidEndEditing(toAPI(page), toAPI(nodeHandle.get()), toAPI(frame), m_client.base.clientInfo); 72} 73 74void InjectedBundlePageFormClient::textDidChangeInTextField(WebPage* page, HTMLInputElement* inputElement, WebFrame* frame, bool initiatedByUserTyping) 75{ 76 if (!m_client.textDidChangeInTextField) 77 return; 78 79 if (!initiatedByUserTyping) 80 return; 81 82 RefPtr<InjectedBundleNodeHandle> nodeHandle = InjectedBundleNodeHandle::getOrCreate(inputElement); 83 m_client.textDidChangeInTextField(toAPI(page), toAPI(nodeHandle.get()), toAPI(frame), m_client.base.clientInfo); 84} 85 86void InjectedBundlePageFormClient::textDidChangeInTextArea(WebPage* page, HTMLTextAreaElement* textAreaElement, WebFrame* frame) 87{ 88 if (!m_client.textDidChangeInTextArea) 89 return; 90 91 RefPtr<InjectedBundleNodeHandle> nodeHandle = InjectedBundleNodeHandle::getOrCreate(textAreaElement); 92 m_client.textDidChangeInTextArea(toAPI(page), toAPI(nodeHandle.get()), toAPI(frame), m_client.base.clientInfo); 93} 94 95static WKInputFieldActionType toWKInputFieldActionType(API::InjectedBundle::FormClient::InputFieldAction action) 96{ 97 switch (action) { 98 case API::InjectedBundle::FormClient::InputFieldAction::MoveUp: 99 return WKInputFieldActionTypeMoveUp; 100 case API::InjectedBundle::FormClient::InputFieldAction::MoveDown: 101 return WKInputFieldActionTypeMoveDown; 102 case API::InjectedBundle::FormClient::InputFieldAction::Cancel: 103 return WKInputFieldActionTypeCancel; 104 case API::InjectedBundle::FormClient::InputFieldAction::InsertTab: 105 return WKInputFieldActionTypeInsertTab; 106 case API::InjectedBundle::FormClient::InputFieldAction::InsertBacktab: 107 return WKInputFieldActionTypeInsertBacktab; 108 case API::InjectedBundle::FormClient::InputFieldAction::InsertNewline: 109 return WKInputFieldActionTypeInsertNewline; 110 case API::InjectedBundle::FormClient::InputFieldAction::InsertDelete: 111 return WKInputFieldActionTypeInsertDelete; 112 } 113 114 ASSERT_NOT_REACHED(); 115 return WKInputFieldActionTypeCancel; 116} 117 118bool InjectedBundlePageFormClient::shouldPerformActionInTextField(WebPage* page, HTMLInputElement* inputElement, API::InjectedBundle::FormClient::InputFieldAction actionType, WebFrame* frame) 119{ 120 if (!m_client.shouldPerformActionInTextField) 121 return false; 122 123 RefPtr<InjectedBundleNodeHandle> nodeHandle = InjectedBundleNodeHandle::getOrCreate(inputElement); 124 return m_client.shouldPerformActionInTextField(toAPI(page), toAPI(nodeHandle.get()), toWKInputFieldActionType(actionType), toAPI(frame), m_client.base.clientInfo); 125} 126 127void InjectedBundlePageFormClient::willSendSubmitEvent(WebPage* page, HTMLFormElement* formElement, WebFrame* frame, WebFrame* sourceFrame, const Vector<std::pair<String, String>>& values) 128{ 129 if (!m_client.willSendSubmitEvent) 130 return; 131 132 RefPtr<InjectedBundleNodeHandle> nodeHandle = InjectedBundleNodeHandle::getOrCreate(formElement); 133 134 ImmutableDictionary::MapType map; 135 for (size_t i = 0; i < values.size(); ++i) 136 map.set(values[i].first, API::String::create(values[i].second)); 137 auto textFieldsMap = ImmutableDictionary::create(WTF::move(map)); 138 139 m_client.willSendSubmitEvent(toAPI(page), toAPI(nodeHandle.get()), toAPI(frame), toAPI(sourceFrame), toAPI(textFieldsMap.get()), m_client.base.clientInfo); 140} 141 142void InjectedBundlePageFormClient::willSubmitForm(WebPage* page, HTMLFormElement* formElement, WebFrame* frame, WebFrame* sourceFrame, const Vector<std::pair<String, String>>& values, RefPtr<API::Object>& userData) 143{ 144 if (!m_client.willSubmitForm) 145 return; 146 147 RefPtr<InjectedBundleNodeHandle> nodeHandle = InjectedBundleNodeHandle::getOrCreate(formElement); 148 149 ImmutableDictionary::MapType map; 150 for (size_t i = 0; i < values.size(); ++i) 151 map.set(values[i].first, API::String::create(values[i].second)); 152 auto textFieldsMap = ImmutableDictionary::create(WTF::move(map)); 153 154 WKTypeRef userDataToPass = 0; 155 m_client.willSubmitForm(toAPI(page), toAPI(nodeHandle.get()), toAPI(frame), toAPI(sourceFrame), toAPI(textFieldsMap.get()), &userDataToPass, m_client.base.clientInfo); 156 userData = adoptRef(toImpl(userDataToPass)); 157} 158 159void InjectedBundlePageFormClient::didAssociateFormControls(WebPage* page, const Vector<RefPtr<WebCore::Element>>& elements) 160{ 161 if (!m_client.didAssociateFormControls) 162 return; 163 164 Vector<RefPtr<API::Object>> elementHandles; 165 elementHandles.reserveInitialCapacity(elements.size()); 166 167 for (const auto& element : elements) 168 elementHandles.uncheckedAppend(InjectedBundleNodeHandle::getOrCreate(element.get())); 169 170 m_client.didAssociateFormControls(toAPI(page), toAPI(API::Array::create(WTF::move(elementHandles)).get()), m_client.base.clientInfo); 171} 172 173bool InjectedBundlePageFormClient::shouldNotifyOnFormChanges(WebPage* page) 174{ 175 if (!m_client.shouldNotifyOnFormChanges) 176 return false; 177 178 return m_client.shouldNotifyOnFormChanges(toAPI(page), m_client.base.clientInfo); 179} 180 181} // namespace WebKit 182