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_download_job.h"
28
29#include "WKAPICast.h"
30#include "WKRetainPtr.h"
31#include "WKURLRequest.h"
32#include "ewk_download_job_private.h"
33#include "ewk_url_response_private.h"
34#include <Ecore.h>
35
36using namespace WebKit;
37
38EwkDownloadJob::EwkDownloadJob(WKDownloadRef download, EwkView* viewImpl)
39    : m_download(download)
40    , m_viewImpl(viewImpl)
41    , m_state(EWK_DOWNLOAD_JOB_STATE_NOT_STARTED)
42    , m_startTime(-1)
43    , m_endTime(-1)
44    , m_downloaded(0)
45{ }
46
47/**
48 * @internal
49 * Queries the identifier for this download
50 */
51uint64_t EwkDownloadJob::id() const
52{
53    return WKDownloadGetID(m_download.get());
54}
55
56/**
57 * @internal
58 * Returns the view this download is attached to.
59 * The view is needed to send notification signals.
60 */
61EwkView* EwkDownloadJob::view() const
62{
63    return m_viewImpl;
64}
65
66Ewk_Download_Job_State ewk_download_job_state_get(const Ewk_Download_Job* download)
67{
68    EWK_OBJ_GET_IMPL_OR_RETURN(const EwkDownloadJob, download, impl, EWK_DOWNLOAD_JOB_STATE_UNKNOWN);
69
70    return impl->state();
71}
72
73Ewk_Download_Job_State EwkDownloadJob::state() const
74{
75    return m_state;
76}
77
78Ewk_Url_Request* ewk_download_job_request_get(const Ewk_Download_Job* download)
79{
80    EWK_OBJ_GET_IMPL_OR_RETURN(const EwkDownloadJob, download, impl, 0);
81
82    return impl->request();
83}
84
85EwkUrlRequest* EwkDownloadJob::request() const
86{
87    if (!m_request) {
88        WKRetainPtr<WKURLRequestRef> wkURLRequest(AdoptWK, WKDownloadCopyRequest(m_download.get()));
89        m_request = EwkUrlRequest::create(wkURLRequest.get());
90    }
91
92    return m_request.get();
93}
94
95Ewk_Url_Response* ewk_download_job_response_get(const Ewk_Download_Job* download)
96{
97    EWK_OBJ_GET_IMPL_OR_RETURN(const EwkDownloadJob, download, impl, 0);
98
99    return impl->response();
100}
101
102EwkUrlResponse* EwkDownloadJob::response() const
103{
104    return m_response.get();
105}
106
107const char* ewk_download_job_destination_get(const Ewk_Download_Job* download)
108{
109    EWK_OBJ_GET_IMPL_OR_RETURN(const EwkDownloadJob, download, impl, 0);
110
111    return impl->destination();
112}
113
114const char* EwkDownloadJob::destination() const
115{
116    return m_destination;
117}
118
119Eina_Bool ewk_download_job_destination_set(Ewk_Download_Job* download, const char* destination)
120{
121    EWK_OBJ_GET_IMPL_OR_RETURN(EwkDownloadJob, download, impl, false);
122    EINA_SAFETY_ON_NULL_RETURN_VAL(destination, false);
123
124    impl->setDestination(destination);
125
126    return true;
127}
128
129void EwkDownloadJob::setDestination(const char* destination)
130{
131    m_destination = destination;
132}
133
134const char* ewk_download_job_suggested_filename_get(const Ewk_Download_Job* download)
135{
136    EWK_OBJ_GET_IMPL_OR_RETURN(const EwkDownloadJob, download, impl, 0);
137
138    return impl->suggestedFileName();
139}
140
141const char* EwkDownloadJob::suggestedFileName() const
142{
143    return m_suggestedFilename;
144}
145
146Eina_Bool ewk_download_job_cancel(Ewk_Download_Job* download)
147{
148    EWK_OBJ_GET_IMPL_OR_RETURN(EwkDownloadJob, download, impl, false);
149
150    return impl->cancel();
151}
152
153bool EwkDownloadJob::cancel()
154{
155    if (m_state != EWK_DOWNLOAD_JOB_STATE_DOWNLOADING)
156        return false;
157
158    m_state = EWK_DOWNLOAD_JOB_STATE_CANCELLING;
159    WKDownloadCancel(m_download.get());
160
161    return true;
162}
163
164double ewk_download_job_estimated_progress_get(const Ewk_Download_Job* download)
165{
166    EWK_OBJ_GET_IMPL_OR_RETURN(const EwkDownloadJob, download, impl, 0);
167
168    return impl->estimatedProgress();
169}
170
171double EwkDownloadJob::estimatedProgress() const
172{
173    if (!m_response)
174        return 0;
175
176    const unsigned long contentLength = m_response->contentLength();
177    if (!contentLength)
178        return 0;
179
180    return static_cast<double>(m_downloaded) / contentLength;
181}
182
183double ewk_download_job_elapsed_time_get(const Ewk_Download_Job* download)
184{
185    EWK_OBJ_GET_IMPL_OR_RETURN(const EwkDownloadJob, download, impl, 0);
186
187    return impl->elapsedTime();
188}
189
190double EwkDownloadJob::elapsedTime() const
191{
192    // Download has not started yet.
193    if (m_startTime < 0)
194        return 0;
195
196    // Download had ended, return the time elapsed between the
197    // download start and the end event.
198    if (m_endTime >= 0)
199        return m_endTime - m_startTime;
200
201    // Download is still going.
202    return ecore_time_get() - m_startTime;
203}
204
205/**
206 * @internal
207 * Sets the URL @a response for this @a download.
208 */
209void EwkDownloadJob::setResponse(PassRefPtr<EwkUrlResponse> response)
210{
211    ASSERT(response);
212
213    m_response = response;
214}
215
216/**
217 * @internal
218 * Sets the suggested file name for this @a download.
219 */
220void EwkDownloadJob::setSuggestedFileName(const char* suggestedFilename)
221{
222    m_suggestedFilename = suggestedFilename;
223}
224
225/**
226 * @internal
227 * Report a given amount of data was received.
228 */
229void EwkDownloadJob::incrementReceivedData(uint64_t length)
230{
231    m_downloaded += length;
232}
233
234/**
235 * @internal
236 * Sets the state of the download.
237 */
238void EwkDownloadJob::setState(Ewk_Download_Job_State state)
239{
240    m_state = state;
241
242    switch (state) {
243    case EWK_DOWNLOAD_JOB_STATE_DOWNLOADING:
244        m_startTime = ecore_time_get();
245        break;
246    case EWK_DOWNLOAD_JOB_STATE_FAILED:
247    case EWK_DOWNLOAD_JOB_STATE_CANCELLED:
248    case EWK_DOWNLOAD_JOB_STATE_FINISHED:
249        m_endTime = ecore_time_get();
250        break;
251    default:
252        break;
253    }
254}
255