UNPKG

5.15 kBJavaScriptView Raw
1/**
2 * Copyright (c) Facebook, Inc. and its affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 *
7 * @format
8 */
9
10'use strict';
11
12const Blob = require('Blob');
13
14const {BlobModule} = require('NativeModules');
15
16let BLOB_URL_PREFIX = null;
17
18if (BlobModule && typeof BlobModule.BLOB_URI_SCHEME === 'string') {
19 BLOB_URL_PREFIX = BlobModule.BLOB_URI_SCHEME + ':';
20 if (typeof BlobModule.BLOB_URI_HOST === 'string') {
21 BLOB_URL_PREFIX += `//${BlobModule.BLOB_URI_HOST}/`;
22 }
23}
24
25/**
26 * To allow Blobs be accessed via `content://` URIs,
27 * you need to register `BlobProvider` as a ContentProvider in your app's `AndroidManifest.xml`:
28 *
29 * ```xml
30 * <manifest>
31 * <application>
32 * <provider
33 * android:name="com.facebook.react.modules.blob.BlobProvider"
34 * android:authorities="@string/blob_provider_authority"
35 * android:exported="false"
36 * />
37 * </application>
38 * </manifest>
39 * ```
40 * And then define the `blob_provider_authority` string in `res/values/strings.xml`.
41 * Use a dotted name that's entirely unique to your app:
42 *
43 * ```xml
44 * <resources>
45 * <string name="blob_provider_authority">your.app.package.blobs</string>
46 * </resources>
47 * ```
48 */
49
50// Small subset from whatwg-url: https://github.com/jsdom/whatwg-url/tree/master/lib
51// The reference code bloat comes from Unicode issues with URLs, so those won't work here.
52export class URLSearchParams {
53 _searchParams = [];
54
55 constructor(params: any) {
56 if (typeof params === 'object') {
57 Object.keys(params).forEach(key => this.append(key, params[key]));
58 }
59 }
60
61 append(key: string, value: string) {
62 this._searchParams.push([key, value]);
63 }
64
65 delete(name) {
66 throw new Error('not implemented');
67 }
68
69 get(name) {
70 throw new Error('not implemented');
71 }
72
73 getAll(name) {
74 throw new Error('not implemented');
75 }
76
77 has(name) {
78 throw new Error('not implemented');
79 }
80
81 set(name, value) {
82 throw new Error('not implemented');
83 }
84
85 sort() {
86 throw new Error('not implemented');
87 }
88
89 [Symbol.iterator]() {
90 return this._searchParams[Symbol.iterator]();
91 }
92
93 toString() {
94 if (this._searchParams.length === 0) {
95 return '';
96 }
97 const last = this._searchParams.length - 1;
98 return this._searchParams.reduce((acc, curr, index) => {
99 return acc + curr.join('=') + (index === last ? '' : '&');
100 }, '');
101 }
102}
103
104function validateBaseUrl(url: string) {
105 // from this MIT-licensed gist: https://gist.github.com/dperini/729294
106 return /^(?:(?:(?:https?|ftp):)?\/\/)(?:(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:[/?#]\S*)?$/i.test(
107 url,
108 );
109}
110
111export class URL {
112 _searchParamsInstance = null;
113
114 static createObjectURL(blob: Blob) {
115 if (BLOB_URL_PREFIX === null) {
116 throw new Error('Cannot create URL for blob!');
117 }
118 return `${BLOB_URL_PREFIX}${blob.data.blobId}?offset=${
119 blob.data.offset
120 }&size=${blob.size}`;
121 }
122
123 static revokeObjectURL(url: string) {
124 // Do nothing.
125 }
126
127 constructor(url: string, base: string) {
128 let baseUrl = null;
129 if (base) {
130 if (typeof base === 'string') {
131 baseUrl = base;
132 if (!validateBaseUrl(baseUrl)) {
133 throw new TypeError(`Invalid base URL: ${baseUrl}`);
134 }
135 } else if (typeof base === 'object') {
136 baseUrl = base.toString();
137 }
138 if (baseUrl.endsWith('/') && url.startsWith('/')) {
139 baseUrl = baseUrl.slice(0, baseUrl.length - 1);
140 }
141 if (baseUrl.endsWith(url)) {
142 url = '';
143 }
144 this._url = `${baseUrl}${url}`;
145 } else {
146 this._url = url;
147 if (!this._url.endsWith('/')) {
148 this._url += '/';
149 }
150 }
151 }
152
153 get hash() {
154 throw new Error('not implemented');
155 }
156
157 get host() {
158 throw new Error('not implemented');
159 }
160
161 get hostname() {
162 throw new Error('not implemented');
163 }
164
165 get href(): string {
166 return this.toString();
167 }
168
169 get origin() {
170 throw new Error('not implemented');
171 }
172
173 get password() {
174 throw new Error('not implemented');
175 }
176
177 get pathname() {
178 throw new Error('not implemented');
179 }
180
181 get port() {
182 throw new Error('not implemented');
183 }
184
185 get protocol() {
186 throw new Error('not implemented');
187 }
188
189 get search() {
190 throw new Error('not implemented');
191 }
192
193 get searchParams(): URLSearchParams {
194 if (this._searchParamsInstance == null) {
195 this._searchParamsInstance = new URLSearchParams();
196 }
197 return this._searchParamsInstance;
198 }
199
200 toJSON(): string {
201 return this.toString();
202 }
203
204 toString(): string {
205 if (this._searchParamsInstance === null) {
206 return this._url;
207 }
208 const separator = this._url.indexOf('?') > -1 ? '&' : '?';
209 return this._url + separator + this._searchParamsInstance.toString();
210 }
211
212 get username() {
213 throw new Error('not implemented');
214 }
215}