~ubuntu-branches/ubuntu/raring/qtwebkit-source/raring-proposed

« back to all changes in this revision

Viewing changes to Source/WebKit2/WebProcess/Downloads/soup/DownloadSoup.cpp

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2013-02-18 14:24:18 UTC
  • Revision ID: package-import@ubuntu.com-20130218142418-eon0jmjg3nj438uy
Tags: upstream-2.3
ImportĀ upstreamĀ versionĀ 2.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2010, 2011 Apple Inc. All rights reserved.
 
3
 * Copyright (C) 2010 Brent Fulgham <bfulgham@webkit.org>
 
4
 *
 
5
 * Redistribution and use in source and binary forms, with or without
 
6
 * modification, are permitted provided that the following conditions
 
7
 * are met:
 
8
 * 1. Redistributions of source code must retain the above copyright
 
9
 *    notice, this list of conditions and the following disclaimer.
 
10
 * 2. Redistributions in binary form must reproduce the above copyright
 
11
 *    notice, this list of conditions and the following disclaimer in the
 
12
 *    documentation and/or other materials provided with the distribution.
 
13
 *
 
14
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 
15
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 
16
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 
17
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 
18
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 
19
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 
20
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 
21
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 
22
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 
23
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 
24
 * THE POSSIBILITY OF SUCH DAMAGE.
 
25
 */
 
26
 
 
27
#include "config.h"
 
28
#include "Download.h"
 
29
 
 
30
#include "DataReference.h"
 
31
#include "DownloadSoupErrors.h"
 
32
#include <WebCore/NotImplemented.h>
 
33
#include <WebCore/ResourceHandleInternal.h>
 
34
#include <gio/gio.h>
 
35
#include <wtf/gobject/GOwnPtr.h>
 
36
#include <wtf/gobject/GRefPtr.h>
 
37
#include <wtf/text/CString.h>
 
38
 
 
39
#if PLATFORM(GTK)
 
40
#include <glib/gi18n-lib.h>
 
41
#endif
 
42
 
 
43
using namespace WebCore;
 
44
 
 
45
namespace WebKit {
 
46
 
 
47
class DownloadClient : public ResourceHandleClient {
 
48
    WTF_MAKE_NONCOPYABLE(DownloadClient);
 
49
public:
 
50
    DownloadClient(Download* download)
 
51
        : m_download(download)
 
52
        , m_handleResponseLaterID(0)
 
53
    {
 
54
    }
 
55
 
 
56
    ~DownloadClient()
 
57
    {
 
58
        if (m_handleResponseLaterID)
 
59
            g_source_remove(m_handleResponseLaterID);
 
60
    }
 
61
 
 
62
    void downloadFailed(const ResourceError& error)
 
63
    {
 
64
        m_download->didFail(error, CoreIPC::DataReference());
 
65
    }
 
66
 
 
67
    void didReceiveResponse(ResourceHandle*, const ResourceResponse& response)
 
68
    {
 
69
        m_response = adoptGRef(response.toSoupMessage());
 
70
        m_download->didReceiveResponse(response);
 
71
 
 
72
        if (response.httpStatusCode() >= 400) {
 
73
            downloadFailed(platformDownloadNetworkError(response.httpStatusCode(), response.url().string(), response.httpStatusText()));
 
74
            return;
 
75
        }
 
76
 
 
77
        String suggestedFilename = response.suggestedFilename();
 
78
        if (suggestedFilename.isEmpty()) {
 
79
            KURL url = response.url();
 
80
            url.setQuery(String());
 
81
            url.removeFragmentIdentifier();
 
82
            suggestedFilename = decodeURLEscapeSequences(url.lastPathComponent());
 
83
        }
 
84
 
 
85
        bool overwrite;
 
86
        String destinationURI = m_download->decideDestinationWithSuggestedFilename(suggestedFilename, overwrite);
 
87
        if (destinationURI.isEmpty()) {
 
88
#if PLATFORM(GTK)
 
89
            GOwnPtr<char> buffer(g_strdup_printf(_("Cannot determine destination URI for download with suggested filename %s"), suggestedFilename.utf8().data()));
 
90
            String errorMessage = String::fromUTF8(buffer.get());
 
91
#else
 
92
            String errorMessage = makeString("Cannot determine destination URI for download with suggested filename ", suggestedFilename);
 
93
#endif
 
94
            downloadFailed(platformDownloadDestinationError(response, errorMessage));
 
95
            return;
 
96
        }
 
97
 
 
98
        GRefPtr<GFile> file = adoptGRef(g_file_new_for_uri(destinationURI.utf8().data()));
 
99
        GOwnPtr<GError> error;
 
100
        m_outputStream = adoptGRef(g_file_replace(file.get(), 0, TRUE, G_FILE_CREATE_NONE, 0, &error.outPtr()));
 
101
        if (!m_outputStream) {
 
102
            downloadFailed(platformDownloadDestinationError(response, error->message));
 
103
            return;
 
104
        }
 
105
 
 
106
        GRefPtr<GFileInfo> info = adoptGRef(g_file_info_new());
 
107
        g_file_info_set_attribute_string(info.get(), "metadata::download-uri", response.url().string().utf8().data());
 
108
        g_file_set_attributes_async(file.get(), info.get(), G_FILE_QUERY_INFO_NONE, G_PRIORITY_DEFAULT, 0, 0, 0);
 
109
 
 
110
        m_download->didCreateDestination(destinationURI);
 
111
    }
 
112
 
 
113
    void didReceiveData(ResourceHandle*, const char* data, int length, int /*encodedDataLength*/)
 
114
    {
 
115
        if (m_handleResponseLaterID) {
 
116
            g_source_remove(m_handleResponseLaterID);
 
117
            handleResponse();
 
118
        }
 
119
 
 
120
        gsize bytesWritten;
 
121
        GOwnPtr<GError> error;
 
122
        g_output_stream_write_all(G_OUTPUT_STREAM(m_outputStream.get()), data, length, &bytesWritten, 0, &error.outPtr());
 
123
        if (error) {
 
124
            downloadFailed(platformDownloadDestinationError(ResourceResponse(m_response.get()), error->message));
 
125
            return;
 
126
        }
 
127
        m_download->didReceiveData(bytesWritten);
 
128
    }
 
129
 
 
130
    void didFinishLoading(ResourceHandle*, double)
 
131
    {
 
132
        m_outputStream = 0;
 
133
        m_download->didFinish();
 
134
    }
 
135
 
 
136
    void didFail(ResourceHandle*, const ResourceError& error)
 
137
    {
 
138
        downloadFailed(platformDownloadNetworkError(error.errorCode(), error.failingURL(), error.localizedDescription()));
 
139
    }
 
140
 
 
141
    void wasBlocked(ResourceHandle*)
 
142
    {
 
143
        notImplemented();
 
144
    }
 
145
 
 
146
    void cannotShowURL(ResourceHandle*)
 
147
    {
 
148
        notImplemented();
 
149
    }
 
150
 
 
151
    void handleResponse()
 
152
    {
 
153
        m_handleResponseLaterID = 0;
 
154
        didReceiveResponse(0, m_delayedResponse);
 
155
    }
 
156
 
 
157
    static gboolean handleResponseLaterCallback(DownloadClient* downloadClient)
 
158
    {
 
159
        downloadClient->handleResponse();
 
160
        return FALSE;
 
161
    }
 
162
 
 
163
    void handleResponseLater(const ResourceResponse& response)
 
164
    {
 
165
        ASSERT(!m_response);
 
166
        ASSERT(!m_handleResponseLaterID);
 
167
 
 
168
        m_delayedResponse = response;
 
169
 
 
170
        // Call didReceiveResponse in an idle to make sure the download is added
 
171
        // to the DownloadManager downloads map.
 
172
        m_handleResponseLaterID = g_idle_add_full(G_PRIORITY_DEFAULT, reinterpret_cast<GSourceFunc>(handleResponseLaterCallback), this, 0);
 
173
    }
 
174
 
 
175
    Download* m_download;
 
176
    GRefPtr<GFileOutputStream> m_outputStream;
 
177
    GRefPtr<SoupMessage> m_response;
 
178
    ResourceResponse m_delayedResponse;
 
179
    unsigned m_handleResponseLaterID;
 
180
};
 
181
 
 
182
void Download::start(WebPage*)
 
183
{
 
184
    ASSERT(!m_downloadClient);
 
185
    ASSERT(!m_resourceHandle);
 
186
    m_downloadClient = adoptPtr(new DownloadClient(this));
 
187
    m_resourceHandle = ResourceHandle::create(0, m_request, m_downloadClient.get(), false, false);
 
188
    didStart();
 
189
}
 
190
 
 
191
void Download::startWithHandle(WebPage*, ResourceHandle* resourceHandle, const ResourceResponse& response)
 
192
{
 
193
    ASSERT(!m_downloadClient);
 
194
    ASSERT(!m_resourceHandle);
 
195
    m_downloadClient = adoptPtr(new DownloadClient(this));
 
196
    resourceHandle->setClient(m_downloadClient.get());
 
197
    m_resourceHandle = resourceHandle;
 
198
    didStart();
 
199
    static_cast<DownloadClient*>(m_downloadClient.get())->handleResponseLater(response);
 
200
}
 
201
 
 
202
void Download::cancel()
 
203
{
 
204
    if (!m_resourceHandle)
 
205
        return;
 
206
    m_resourceHandle->cancel();
 
207
    didCancel(CoreIPC::DataReference());
 
208
    m_resourceHandle = 0;
 
209
}
 
210
 
 
211
void Download::platformInvalidate()
 
212
{
 
213
    if (m_resourceHandle) {
 
214
        m_resourceHandle->setClient(0);
 
215
        m_resourceHandle->cancel();
 
216
        m_resourceHandle = 0;
 
217
    }
 
218
    m_downloadClient.release();
 
219
}
 
220
 
 
221
void Download::didDecideDestination(const String& /*destination*/, bool /*allowOverwrite*/)
 
222
{
 
223
    notImplemented();
 
224
}
 
225
 
 
226
void Download::platformDidFinish()
 
227
{
 
228
    m_resourceHandle = 0;
 
229
}
 
230
 
 
231
void Download::receivedCredential(const AuthenticationChallenge&, const Credential&)
 
232
{
 
233
    notImplemented();
 
234
}
 
235
 
 
236
void Download::receivedRequestToContinueWithoutCredential(const AuthenticationChallenge&)
 
237
{
 
238
    notImplemented();
 
239
}
 
240
 
 
241
void Download::receivedCancellation(const AuthenticationChallenge&)
 
242
{
 
243
    notImplemented();
 
244
}
 
245
 
 
246
void Download::continueWithoutCredential(const AuthenticationChallenge &)
 
247
{
 
248
    notImplemented();
 
249
}
 
250
 
 
251
void Download::useCredential(const AuthenticationChallenge&, const Credential&)
 
252
{
 
253
    notImplemented();
 
254
}
 
255
 
 
256
void Download::cancelAuthenticationChallenge(const AuthenticationChallenge&)
 
257
{
 
258
    notImplemented();
 
259
}
 
260
 
 
261
} // namespace WebKit