1/*
2 * Copyright (C) 2009 Apple Inc. All Rights Reserved.
3 * Copyright (C) 2009, 2011 Google Inc. All Rights Reserved.
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 COMPUTER, INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 */
27
28#include "config.h"
29
30#if ENABLE(WORKERS)
31
32#include "WorkerScriptLoader.h"
33
34#include "CrossThreadTask.h"
35#include "ResourceRequest.h"
36#include "ScriptExecutionContext.h"
37#include "SecurityOrigin.h"
38#include "WorkerContext.h"
39#include "WorkerScriptLoaderClient.h"
40#include "WorkerThreadableLoader.h"
41#include <wtf/OwnPtr.h>
42#include <wtf/UnusedParam.h>
43
44namespace WebCore {
45
46WorkerScriptLoader::WorkerScriptLoader(ResourceRequestBase::TargetType targetType)
47    : m_client(0)
48    , m_failed(false)
49    , m_identifier(0)
50    , m_targetType(targetType)
51{
52}
53
54void WorkerScriptLoader::loadSynchronously(ScriptExecutionContext* scriptExecutionContext, const KURL& url, CrossOriginRequestPolicy crossOriginRequestPolicy)
55{
56    m_url = url;
57
58    OwnPtr<ResourceRequest> request(createResourceRequest());
59    if (!request)
60        return;
61
62    ASSERT(scriptExecutionContext->isWorkerContext());
63
64    ThreadableLoaderOptions options;
65    options.allowCredentials = true;
66    options.crossOriginRequestPolicy = crossOriginRequestPolicy;
67    options.sendLoadCallbacks = true;
68
69    WorkerThreadableLoader::loadResourceSynchronously(static_cast<WorkerContext*>(scriptExecutionContext), *request, *this, options);
70}
71
72void WorkerScriptLoader::loadAsynchronously(ScriptExecutionContext* scriptExecutionContext, const KURL& url, CrossOriginRequestPolicy crossOriginRequestPolicy, WorkerScriptLoaderClient* client)
73{
74    ASSERT(client);
75    m_client = client;
76    m_url = url;
77
78    OwnPtr<ResourceRequest> request(createResourceRequest());
79    if (!request)
80        return;
81
82    ThreadableLoaderOptions options;
83    options.allowCredentials = true;
84    options.crossOriginRequestPolicy = crossOriginRequestPolicy;
85    options.sendLoadCallbacks = true;
86
87    m_threadableLoader = ThreadableLoader::create(scriptExecutionContext, this, *request, options);
88}
89
90const KURL& WorkerScriptLoader::responseURL() const
91{
92    ASSERT(!failed());
93    return m_responseURL;
94}
95
96PassOwnPtr<ResourceRequest> WorkerScriptLoader::createResourceRequest()
97{
98    OwnPtr<ResourceRequest> request(new ResourceRequest(m_url));
99    request->setHTTPMethod("GET");
100    request->setTargetType(m_targetType);
101    return request.release();
102}
103
104void WorkerScriptLoader::didReceiveResponse(const ResourceResponse& response)
105{
106    if (response.httpStatusCode() / 100 != 2 && response.httpStatusCode()) {
107        m_failed = true;
108        return;
109    }
110    m_responseURL = response.url();
111    m_responseEncoding = response.textEncodingName();
112    if (m_client)
113        m_client->didReceiveResponse(response);
114}
115
116void WorkerScriptLoader::didReceiveData(const char* data, int len)
117{
118    if (m_failed)
119        return;
120
121    if (!m_decoder) {
122        if (!m_responseEncoding.isEmpty())
123            m_decoder = TextResourceDecoder::create("text/javascript", m_responseEncoding);
124        else
125            m_decoder = TextResourceDecoder::create("text/javascript", "UTF-8");
126    }
127
128    if (!len)
129        return;
130
131    if (len == -1)
132        len = strlen(data);
133
134    m_script += m_decoder->decode(data, len);
135}
136
137void WorkerScriptLoader::didFinishLoading(unsigned long identifier, double)
138{
139    if (m_failed)
140        return;
141
142    if (m_decoder)
143        m_script += m_decoder->flush();
144
145    m_identifier = identifier;
146    notifyFinished();
147}
148
149void WorkerScriptLoader::didFail(const ResourceError&)
150{
151    notifyError();
152}
153
154void WorkerScriptLoader::didFailRedirectCheck()
155{
156    notifyError();
157}
158
159void WorkerScriptLoader::didReceiveAuthenticationCancellation(const ResourceResponse&)
160{
161    notifyError();
162}
163
164void WorkerScriptLoader::notifyError()
165{
166    m_failed = true;
167    notifyFinished();
168}
169
170void WorkerScriptLoader::notifyFinished()
171{
172    if (m_client)
173        m_client->notifyFinished();
174}
175
176} // namespace WebCore
177
178#endif // ENABLE(WORKERS)
179