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