1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2001 Dirk Mueller (mueller@kde.org)
5 * (C) 2006 Alexey Proskuryakov (ap@webkit.org)
6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012 Apple Inc. All
7 * rights reserved.
8 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved.
9 * (http://www.torchmobile.com/)
10 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
11 * Copyright (C) 2013 Google Inc. All rights reserved.
12 *
13 * This library is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU Library General Public
15 * License as published by the Free Software Foundation; either
16 * version 2 of the License, or (at your option) any later version.
17 *
18 * This library is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * Library General Public License for more details.
22 *
23 * You should have received a copy of the GNU Library General Public License
24 * along with this library; see the file COPYING.LIB. If not, write to
25 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
26 * Boston, MA 02110-1301, USA.
27 *
28 */
29
30 #include "third_party/blink/renderer/core/dom/document_init.h"
31
32 #include "services/metrics/public/cpp/ukm_source_id.h"
33 #include "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom-blink.h"
34 #include "third_party/blink/renderer/core/dom/document.h"
35 #include "third_party/blink/renderer/core/dom/dom_implementation.h"
36 #include "third_party/blink/renderer/core/dom/sink_document.h"
37 #include "third_party/blink/renderer/core/dom/xml_document.h"
38 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
39 #include "third_party/blink/renderer/core/frame/local_frame.h"
40 #include "third_party/blink/renderer/core/frame/settings.h"
41 #include "third_party/blink/renderer/core/html/custom/v0_custom_element_registration_context.h"
42 #include "third_party/blink/renderer/core/html/html_document.h"
43 #include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
44 #include "third_party/blink/renderer/core/html/html_view_source_document.h"
45 #include "third_party/blink/renderer/core/html/image_document.h"
46 #include "third_party/blink/renderer/core/html/imports/html_imports_controller.h"
47 #include "third_party/blink/renderer/core/html/media/html_media_element.h"
48 #include "third_party/blink/renderer/core/html/media/media_document.h"
49 #include "third_party/blink/renderer/core/html/plugin_document.h"
50 #include "third_party/blink/renderer/core/html/text_document.h"
51 #include "third_party/blink/renderer/core/loader/document_loader.h"
52 #include "third_party/blink/renderer/core/page/chrome_client.h"
53 #include "third_party/blink/renderer/core/page/page.h"
54 #include "third_party/blink/renderer/core/page/plugin_data.h"
55 #include "third_party/blink/renderer/platform/network/mime/content_type.h"
56 #include "third_party/blink/renderer/platform/network/mime/mime_type_registry.h"
57 #include "third_party/blink/renderer/platform/network/network_utils.h"
58
59 namespace blink {
60
61 // static
Create()62 DocumentInit DocumentInit::Create() {
63 return DocumentInit();
64 }
65
66 DocumentInit::DocumentInit(const DocumentInit&) = default;
67
68 DocumentInit::~DocumentInit() = default;
69
ForTest()70 DocumentInit& DocumentInit::ForTest() {
71 DCHECK(!execution_context_);
72 DCHECK(!window_);
73 #if DCHECK_IS_ON()
74 DCHECK(!for_test_);
75 for_test_ = true;
76 #endif
77 return *this;
78 }
79
WithImportsController(HTMLImportsController * controller)80 DocumentInit& DocumentInit::WithImportsController(
81 HTMLImportsController* controller) {
82 imports_controller_ = controller;
83 return *this;
84 }
85
ShouldSetURL() const86 bool DocumentInit::ShouldSetURL() const {
87 return (window_ && !window_->GetFrame()->IsMainFrame()) || !url_.IsEmpty();
88 }
89
IsSrcdocDocument() const90 bool DocumentInit::IsSrcdocDocument() const {
91 return window_ && !window_->GetFrame()->IsMainFrame() && is_srcdoc_document_;
92 }
93
WithWindow(LocalDOMWindow * window,Document * owner_document)94 DocumentInit& DocumentInit::WithWindow(LocalDOMWindow* window,
95 Document* owner_document) {
96 DCHECK(!window_);
97 DCHECK(!execution_context_);
98 DCHECK(!imports_controller_);
99 #if DCHECK_IS_ON()
100 DCHECK(!for_test_);
101 #endif
102 DCHECK(window);
103 window_ = window;
104 execution_context_ = window;
105 owner_document_ = owner_document;
106 return *this;
107 }
108
ForInitialEmptyDocument(bool empty)109 DocumentInit& DocumentInit::ForInitialEmptyDocument(bool empty) {
110 is_initial_empty_document_ = empty;
111 return *this;
112 }
113
114 // static
ComputeDocumentType(LocalFrame * frame,const KURL & url,const String & mime_type,bool * is_for_external_handler)115 DocumentInit::Type DocumentInit::ComputeDocumentType(
116 LocalFrame* frame,
117 const KURL& url,
118 const String& mime_type,
119 bool* is_for_external_handler) {
120 if (frame && frame->InViewSourceMode())
121 return Type::kViewSource;
122
123 // Plugins cannot take HTML and XHTML from us, and we don't even need to
124 // initialize the plugin database for those.
125 if (mime_type == "text/html")
126 return Type::kHTML;
127
128 if (mime_type == "application/xhtml+xml")
129 return Type::kXHTML;
130
131 // multipart/x-mixed-replace is only supported for images.
132 if (MIMETypeRegistry::IsSupportedImageResourceMIMEType(mime_type) ||
133 mime_type == "multipart/x-mixed-replace") {
134 return Type::kImage;
135 }
136
137 if (HTMLMediaElement::GetSupportsType(ContentType(mime_type)))
138 return Type::kMedia;
139
140 if (frame && frame->GetPage() &&
141 frame->Loader().AllowPlugins(kNotAboutToInstantiatePlugin)) {
142 PluginData* plugin_data = GetPluginData(frame, url);
143
144 // Everything else except text/plain can be overridden by plugins.
145 // Disallowing plugins to use text/plain prevents plugins from hijacking a
146 // fundamental type that the browser is expected to handle, and also serves
147 // as an optimization to prevent loading the plugin database in the common
148 // case.
149 if (mime_type != "text/plain" && plugin_data &&
150 plugin_data->SupportsMimeType(mime_type)) {
151 // Plugins handled by MimeHandlerView do not create a PluginDocument. They
152 // are rendered inside cross-process frames and the notion of a PluginView
153 // (which is associated with PluginDocument) is irrelevant here.
154 if (plugin_data->IsExternalPluginMimeType(mime_type)) {
155 if (is_for_external_handler)
156 *is_for_external_handler = true;
157 return Type::kHTML;
158 }
159
160 return Type::kPlugin;
161 }
162 }
163
164 if (MIMETypeRegistry::IsSupportedJavaScriptMIMEType(mime_type) ||
165 MIMETypeRegistry::IsJSONMimeType(mime_type) ||
166 MIMETypeRegistry::IsPlainTextMIMEType(mime_type)) {
167 return Type::kText;
168 }
169
170 if (mime_type == "image/svg+xml")
171 return Type::kSVG;
172
173 if (MIMETypeRegistry::IsXMLMIMEType(mime_type))
174 return Type::kXML;
175
176 return Type::kHTML;
177 }
178
179 // static
GetPluginData(LocalFrame * frame,const KURL & url)180 PluginData* DocumentInit::GetPluginData(LocalFrame* frame, const KURL& url) {
181 // If the document is being created for the main frame,
182 // frame()->tree().top()->securityContext() returns nullptr.
183 // For that reason, the origin must be retrieved directly from |url|.
184 if (frame->IsMainFrame())
185 return frame->GetPage()->GetPluginData(SecurityOrigin::Create(url).get());
186
187 const SecurityOrigin* main_frame_origin =
188 frame->Tree().Top().GetSecurityContext()->GetSecurityOrigin();
189 return frame->GetPage()->GetPluginData(main_frame_origin);
190 }
191
WithTypeFrom(const String & mime_type)192 DocumentInit& DocumentInit::WithTypeFrom(const String& mime_type) {
193 mime_type_ = mime_type;
194 type_ = ComputeDocumentType(window_ ? window_->GetFrame() : nullptr, Url(),
195 mime_type_, &is_for_external_handler_);
196 return *this;
197 }
198
WithExecutionContext(ExecutionContext * execution_context)199 DocumentInit& DocumentInit::WithExecutionContext(
200 ExecutionContext* execution_context) {
201 DCHECK(!execution_context_);
202 DCHECK(!window_);
203 #if DCHECK_IS_ON()
204 DCHECK(!for_test_);
205 #endif
206 execution_context_ = execution_context;
207 return *this;
208 }
209
WithURL(const KURL & url)210 DocumentInit& DocumentInit::WithURL(const KURL& url) {
211 DCHECK(url_.IsNull());
212 url_ = url;
213 return *this;
214 }
215
GetCookieUrl() const216 const KURL& DocumentInit::GetCookieUrl() const {
217 return owner_document_ ? owner_document_->CookieURL() : url_;
218 }
219
WithSrcdocDocument(bool is_srcdoc_document)220 DocumentInit& DocumentInit::WithSrcdocDocument(bool is_srcdoc_document) {
221 is_srcdoc_document_ = is_srcdoc_document;
222 return *this;
223 }
224
225
WithRegistrationContext(V0CustomElementRegistrationContext * registration_context)226 DocumentInit& DocumentInit::WithRegistrationContext(
227 V0CustomElementRegistrationContext* registration_context) {
228 DCHECK(!create_new_registration_context_);
229 DCHECK(!registration_context_);
230 registration_context_ = registration_context;
231 return *this;
232 }
233
WithNewRegistrationContext()234 DocumentInit& DocumentInit::WithNewRegistrationContext() {
235 DCHECK(!create_new_registration_context_);
236 DCHECK(!registration_context_);
237 create_new_registration_context_ = true;
238 return *this;
239 }
240
RegistrationContext(Document * document) const241 V0CustomElementRegistrationContext* DocumentInit::RegistrationContext(
242 Document* document) const {
243 if (!IsA<HTMLDocument>(document) && !document->IsXHTMLDocument())
244 return nullptr;
245
246 if (create_new_registration_context_)
247 return MakeGarbageCollected<V0CustomElementRegistrationContext>();
248
249 return registration_context_;
250 }
251
WithWebBundleClaimedUrl(const KURL & web_bundle_claimed_url)252 DocumentInit& DocumentInit::WithWebBundleClaimedUrl(
253 const KURL& web_bundle_claimed_url) {
254 web_bundle_claimed_url_ = web_bundle_claimed_url;
255 return *this;
256 }
257
WithUkmSourceId(ukm::SourceId ukm_source_id)258 DocumentInit& DocumentInit::WithUkmSourceId(ukm::SourceId ukm_source_id) {
259 ukm_source_id_ = ukm_source_id;
260 return *this;
261 }
262
CreateDocument() const263 Document* DocumentInit::CreateDocument() const {
264 #if DCHECK_IS_ON()
265 DCHECK(execution_context_ || for_test_);
266 #endif
267 switch (type_) {
268 case Type::kHTML:
269 return MakeGarbageCollected<HTMLDocument>(*this);
270 case Type::kXHTML:
271 return XMLDocument::CreateXHTML(*this);
272 case Type::kImage:
273 return MakeGarbageCollected<ImageDocument>(*this);
274 case Type::kPlugin: {
275 DCHECK(window_);
276 if (window_->IsSandboxed(
277 network::mojom::blink::WebSandboxFlags::kPlugins)) {
278 return MakeGarbageCollected<SinkDocument>(*this);
279 }
280 return MakeGarbageCollected<PluginDocument>(*this);
281 }
282 case Type::kMedia:
283 return MakeGarbageCollected<MediaDocument>(*this);
284 case Type::kSVG:
285 return XMLDocument::CreateSVG(*this);
286 case Type::kXML:
287 return MakeGarbageCollected<XMLDocument>(*this);
288 case Type::kViewSource:
289 return MakeGarbageCollected<HTMLViewSourceDocument>(*this);
290 case Type::kText:
291 return MakeGarbageCollected<TextDocument>(*this);
292 case Type::kUnspecified:
293 FALLTHROUGH;
294 default:
295 break;
296 }
297 NOTREACHED();
298 return nullptr;
299 }
300
301 } // namespace blink
302