1/*
2 * Copyright (C) 2012 Intel Corporation. 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 "ewk_file_chooser_request.h"
28
29#include "WKArray.h"
30#include "WKOpenPanelParameters.h"
31#include "WKOpenPanelResultListener.h"
32#include "WKSharedAPICast.h"
33#include "WKString.h"
34#include "WKURL.h"
35#include "ewk_file_chooser_request_private.h"
36#include <wtf/StdLibExtras.h>
37#include <wtf/text/CString.h>
38
39using namespace WebKit;
40
41EwkFileChooserRequest::EwkFileChooserRequest(WKOpenPanelParametersRef parameters, WKOpenPanelResultListenerRef listener)
42    : m_parameters(parameters)
43    , m_listener(listener)
44    , m_wasRequestHandled(false)
45{
46    ASSERT(parameters);
47    ASSERT(listener);
48}
49
50EwkFileChooserRequest::~EwkFileChooserRequest()
51{
52    if (!m_wasRequestHandled)
53        WKOpenPanelResultListenerCancel(m_listener.get());
54}
55
56bool EwkFileChooserRequest::allowMultipleFiles() const
57{
58    return WKOpenPanelParametersGetAllowsMultipleFiles(m_parameters.get());
59}
60
61WKRetainPtr<WKArrayRef> EwkFileChooserRequest::acceptedMIMETypes() const
62{
63    return adoptWK(WKOpenPanelParametersCopyAcceptedMIMETypes(m_parameters.get()));
64}
65
66void EwkFileChooserRequest::cancel()
67{
68    m_wasRequestHandled = true;
69
70    return WKOpenPanelResultListenerCancel(m_listener.get());
71}
72
73void EwkFileChooserRequest::chooseFiles(WKArrayRef fileURLs)
74{
75    m_wasRequestHandled = true;
76    WKOpenPanelResultListenerChooseFiles(m_listener.get(), fileURLs);
77}
78
79Eina_Bool ewk_file_chooser_request_allow_multiple_files_get(const Ewk_File_Chooser_Request* request)
80{
81    EWK_OBJ_GET_IMPL_OR_RETURN(const EwkFileChooserRequest, request, impl, false);
82
83    return impl->allowMultipleFiles();
84}
85
86Eina_List* ewk_file_chooser_request_accepted_mimetypes_get(const Ewk_File_Chooser_Request* request)
87{
88    EWK_OBJ_GET_IMPL_OR_RETURN(const EwkFileChooserRequest, request, impl, nullptr);
89
90    Eina_List* mimeTypeList = 0;
91    WKRetainPtr<WKArrayRef> mimeTypes = impl->acceptedMIMETypes();
92
93    const size_t size = WKArrayGetSize(mimeTypes.get());
94    for (size_t i = 0; i < size; ++i) {
95        WKRetainPtr<WKStringRef> mimeType = static_cast<WKStringRef>(WKArrayGetItemAtIndex(mimeTypes.get(), i));
96        if (!mimeType || WKStringIsEmpty(mimeType.get()))
97            continue;
98        mimeTypeList = eina_list_append(mimeTypeList, eina_stringshare_add(toWTFString(mimeType.get()).utf8().data()));
99    }
100
101    return mimeTypeList;
102}
103
104Eina_Bool ewk_file_chooser_request_cancel(Ewk_File_Chooser_Request* request)
105{
106    EWK_OBJ_GET_IMPL_OR_RETURN(EwkFileChooserRequest, request, impl, false);
107    EINA_SAFETY_ON_TRUE_RETURN_VAL(impl->wasHandled(), false);
108
109    impl->cancel();
110
111    return true;
112}
113
114Eina_Bool ewk_file_chooser_request_files_choose(Ewk_File_Chooser_Request* request, const Eina_List* chosenFiles)
115{
116    EWK_OBJ_GET_IMPL_OR_RETURN(EwkFileChooserRequest, request, impl, false);
117    EINA_SAFETY_ON_NULL_RETURN_VAL(chosenFiles, false);
118    EINA_SAFETY_ON_TRUE_RETURN_VAL(impl->wasHandled(), false);
119
120    const unsigned urlCount = eina_list_count(chosenFiles);
121    EINA_SAFETY_ON_FALSE_RETURN_VAL(urlCount == 1 || (urlCount > 1 && impl->allowMultipleFiles()), false);
122
123    auto filesURLs = std::make_unique<WKTypeRef[]>(urlCount);
124
125    for (unsigned i = 0; i < urlCount; ++i) {
126        const char* url = static_cast<char*>(eina_list_nth(chosenFiles, i));
127        EINA_SAFETY_ON_NULL_RETURN_VAL(url, false);
128        String fileURL = ASCIILiteral("file://") + String::fromUTF8(url);
129        filesURLs[i] = toCopiedURLAPI(fileURL);
130    }
131
132    WKRetainPtr<WKArrayRef> wkFileURLs(AdoptWK, WKArrayCreateAdoptingValues(filesURLs.get(), urlCount));
133    impl->chooseFiles(wkFileURLs.get());
134
135    return true;
136}
137
138Eina_Bool ewk_file_chooser_request_file_choose(Ewk_File_Chooser_Request* request, const char* chosenFile)
139{
140    EWK_OBJ_GET_IMPL_OR_RETURN(EwkFileChooserRequest, request, impl, false);
141    EINA_SAFETY_ON_NULL_RETURN_VAL(chosenFile, false);
142    EINA_SAFETY_ON_TRUE_RETURN_VAL(impl->wasHandled(), false);
143
144    String fileURL = ASCIILiteral("file://") + String::fromUTF8(chosenFile);
145    WKRetainPtr<WKURLRef> wkURL(AdoptWK, toCopiedURLAPI(fileURL));
146
147    WKTypeRef wkURLPtr = wkURL.get();
148    WKRetainPtr<WKArrayRef> wkFileURLs(AdoptWK, WKArrayCreate(&wkURLPtr, 1));
149    impl->chooseFiles(wkFileURLs.get());
150
151    return true;
152}
153