Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/url/URLMainThread.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "URLMainThread.h"
8
9
#include "mozilla/dom/BindingUtils.h"
10
#include "mozilla/dom/Blob.h"
11
#include "mozilla/dom/BlobURLProtocolHandler.h"
12
#include "mozilla/Unused.h"
13
#include "nsContentUtils.h"
14
#include "nsIURL.h"
15
#include "nsIURIMutator.h"
16
#include "nsNetUtil.h"
17
18
namespace mozilla {
19
namespace dom {
20
21
/* static */ already_AddRefed<URLMainThread>
22
URLMainThread::Constructor(const GlobalObject& aGlobal, const nsAString& aURL,
23
                           const Optional<nsAString>& aBase, ErrorResult& aRv)
24
0
{
25
0
  if (aBase.WasPassed()) {
26
0
    return Constructor(aGlobal.GetAsSupports(), aURL, aBase.Value(), aRv);
27
0
  }
28
0
29
0
  return Constructor(aGlobal.GetAsSupports(), aURL, nullptr, aRv);
30
0
}
31
32
/* static */ already_AddRefed<URLMainThread>
33
URLMainThread::Constructor(nsISupports* aParent, const nsAString& aURL,
34
                           const nsAString& aBase, ErrorResult& aRv)
35
0
{
36
0
  MOZ_ASSERT(NS_IsMainThread());
37
0
38
0
  nsCOMPtr<nsIURI> baseUri;
39
0
  nsresult rv = NS_NewURI(getter_AddRefs(baseUri), aBase, nullptr, nullptr,
40
0
                          nsContentUtils::GetIOService());
41
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
42
0
    aRv.ThrowTypeError<MSG_INVALID_URL>(aBase);
43
0
    return nullptr;
44
0
  }
45
0
46
0
  return Constructor(aParent, aURL, baseUri, aRv);
47
0
}
48
49
/* static */ already_AddRefed<URLMainThread>
50
URLMainThread::Constructor(nsISupports* aParent, const nsAString& aURL,
51
                           nsIURI* aBase, ErrorResult& aRv)
52
0
{
53
0
  MOZ_ASSERT(NS_IsMainThread());
54
0
55
0
  nsCOMPtr<nsIURI> uri;
56
0
  nsresult rv = NS_NewURI(getter_AddRefs(uri), aURL, nullptr, aBase,
57
0
                          nsContentUtils::GetIOService());
58
0
  if (NS_FAILED(rv)) {
59
0
    // No need to warn in this case. It's common to use the URL constructor
60
0
    // to determine if a URL is valid and an exception will be propagated.
61
0
    aRv.ThrowTypeError<MSG_INVALID_URL>(aURL);
62
0
    return nullptr;
63
0
  }
64
0
65
0
  RefPtr<URLMainThread> url = new URLMainThread(aParent);
66
0
  url->SetURI(uri.forget());
67
0
  return url.forget();
68
0
}
69
70
/* static */ void
71
URLMainThread::CreateObjectURL(const GlobalObject& aGlobal, Blob& aBlob,
72
                               nsAString& aResult, ErrorResult& aRv)
73
0
{
74
0
  MOZ_ASSERT(NS_IsMainThread());
75
0
76
0
  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
77
0
  if (NS_WARN_IF(!global)) {
78
0
    aRv.Throw(NS_ERROR_FAILURE);
79
0
    return;
80
0
  }
81
0
82
0
  nsCOMPtr<nsIPrincipal> principal =
83
0
    nsContentUtils::ObjectPrincipal(aGlobal.Get());
84
0
85
0
  nsAutoCString url;
86
0
  aRv = BlobURLProtocolHandler::AddDataEntry(aBlob.Impl(), principal, url);
87
0
  if (NS_WARN_IF(aRv.Failed())) {
88
0
    return;
89
0
  }
90
0
91
0
  global->RegisterHostObjectURI(url);
92
0
  CopyASCIItoUTF16(url, aResult);
93
0
}
94
95
/* static */ void
96
URLMainThread::CreateObjectURL(const GlobalObject& aGlobal,
97
                               MediaSource& aSource,
98
                               nsAString& aResult, ErrorResult& aRv)
99
0
{
100
0
  MOZ_ASSERT(NS_IsMainThread());
101
0
102
0
  nsCOMPtr<nsIPrincipal> principal =
103
0
    nsContentUtils::ObjectPrincipal(aGlobal.Get());
104
0
105
0
  nsAutoCString url;
106
0
  aRv = BlobURLProtocolHandler::AddDataEntry(&aSource, principal, url);
107
0
  if (NS_WARN_IF(aRv.Failed())) {
108
0
    return;
109
0
  }
110
0
111
0
  nsCOMPtr<nsIRunnable> revocation =
112
0
    NS_NewRunnableFunction("dom::URLMainThread::CreateObjectURL", [url] {
113
0
      BlobURLProtocolHandler::RemoveDataEntry(url);
114
0
    });
115
0
116
0
  nsContentUtils::RunInStableState(revocation.forget());
117
0
118
0
  CopyASCIItoUTF16(url, aResult);
119
0
}
120
121
/* static */ void
122
URLMainThread::RevokeObjectURL(const GlobalObject& aGlobal,
123
                               const nsAString& aURL, ErrorResult& aRv)
124
0
{
125
0
  MOZ_ASSERT(NS_IsMainThread());
126
0
  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
127
0
  if (!global) {
128
0
    aRv.Throw(NS_ERROR_FAILURE);
129
0
    return;
130
0
  }
131
0
132
0
  nsIPrincipal* principal = nsContentUtils::ObjectPrincipal(aGlobal.Get());
133
0
134
0
  NS_LossyConvertUTF16toASCII asciiurl(aURL);
135
0
136
0
  nsIPrincipal* urlPrincipal =
137
0
    BlobURLProtocolHandler::GetDataEntryPrincipal(asciiurl);
138
0
139
0
  if (urlPrincipal && principal->Subsumes(urlPrincipal)) {
140
0
    global->UnregisterHostObjectURI(asciiurl);
141
0
    BlobURLProtocolHandler::RemoveDataEntry(asciiurl);
142
0
  }
143
0
}
144
145
URLMainThread::URLMainThread(nsISupports* aParent)
146
  : URL(aParent)
147
0
{
148
0
  MOZ_ASSERT(NS_IsMainThread());
149
0
}
150
151
URLMainThread::~URLMainThread()
152
0
{
153
0
  MOZ_ASSERT(NS_IsMainThread());
154
0
}
155
156
/* static */ bool
157
URLMainThread::IsValidURL(const GlobalObject& aGlobal, const nsAString& aURL,
158
                          ErrorResult& aRv)
159
0
{
160
0
  MOZ_ASSERT(NS_IsMainThread());
161
0
  NS_LossyConvertUTF16toASCII asciiurl(aURL);
162
0
  return BlobURLProtocolHandler::HasDataEntry(asciiurl);
163
0
}
164
165
void
166
URLMainThread::SetHref(const nsAString& aHref, ErrorResult& aRv)
167
0
{
168
0
  NS_ConvertUTF16toUTF8 href(aHref);
169
0
170
0
  nsresult rv;
171
0
  nsCOMPtr<nsIIOService> ioService(do_GetService(NS_IOSERVICE_CONTRACTID, &rv));
172
0
  if (NS_FAILED(rv)) {
173
0
    aRv.Throw(rv);
174
0
    return;
175
0
  }
176
0
177
0
  nsCOMPtr<nsIURI> uri;
178
0
  rv = ioService->NewURI(href, nullptr, nullptr, getter_AddRefs(uri));
179
0
  if (NS_FAILED(rv)) {
180
0
    aRv.ThrowTypeError<MSG_INVALID_URL>(aHref);
181
0
    return;
182
0
  }
183
0
184
0
  SetURI(uri.forget());
185
0
  UpdateURLSearchParams();
186
0
}
187
188
void
189
URLMainThread::GetOrigin(nsAString& aOrigin, ErrorResult& aRv) const
190
0
{
191
0
  nsContentUtils::GetUTFOrigin(GetURI(), aOrigin);
192
0
}
193
194
void
195
URLMainThread::SetProtocol(const nsAString& aProtocol, ErrorResult& aRv)
196
0
{
197
0
  nsAString::const_iterator start, end;
198
0
  aProtocol.BeginReading(start);
199
0
  aProtocol.EndReading(end);
200
0
  nsAString::const_iterator iter(start);
201
0
202
0
  FindCharInReadable(':', iter, end);
203
0
204
0
  // Changing the protocol of a URL, changes the "nature" of the URI
205
0
  // implementation. In order to do this properly, we have to serialize the
206
0
  // existing URL and reparse it in a new object.
207
0
  nsCOMPtr<nsIURI> clone;
208
0
  nsresult rv = NS_MutateURI(GetURI())
209
0
                  .SetScheme(NS_ConvertUTF16toUTF8(Substring(start, iter)))
210
0
                  .Finalize(clone);
211
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
212
0
    return;
213
0
  }
214
0
215
0
  nsAutoCString href;
216
0
  rv = clone->GetSpec(href);
217
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
218
0
    return;
219
0
  }
220
0
221
0
  nsCOMPtr<nsIURI> uri;
222
0
  rv = NS_NewURI(getter_AddRefs(uri), href);
223
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
224
0
    return;
225
0
  }
226
0
227
0
  SetURI(uri.forget());
228
0
}
229
230
} // namespace dom
231
} // namespace mozilla