| /* |
| * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
| * (C) 1999 Antti Koivisto (koivisto@kde.org) |
| * (C) 2001 Dirk Mueller (mueller@kde.org) |
| * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. |
| * Copyright (C) 2006 Samuel Weinig (sam@webkit.org) |
| * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. |
| * (http://www.torchmobile.com/) |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Library General Public |
| * License as published by the Free Software Foundation; either |
| * version 2 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Library General Public License for more details. |
| * |
| * You should have received a copy of the GNU Library General Public License |
| * along with this library; see the file COPYING.LIB. If not, write to |
| * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
| * Boston, MA 02110-1301, USA. |
| */ |
| |
| #include "third_party/blink/renderer/core/dom/dom_implementation.h" |
| |
| #include "third_party/blink/renderer/core/css/css_style_sheet.h" |
| #include "third_party/blink/renderer/core/css/media_list.h" |
| #include "third_party/blink/renderer/core/css/style_sheet_contents.h" |
| #include "third_party/blink/renderer/core/dom/context_features.h" |
| #include "third_party/blink/renderer/core/dom/document_init.h" |
| #include "third_party/blink/renderer/core/dom/document_type.h" |
| #include "third_party/blink/renderer/core/dom/element.h" |
| #include "third_party/blink/renderer/core/dom/text.h" |
| #include "third_party/blink/renderer/core/dom/xml_document.h" |
| #include "third_party/blink/renderer/core/frame/local_frame.h" |
| #include "third_party/blink/renderer/core/frame/use_counter.h" |
| #include "third_party/blink/renderer/core/html/custom/v0_custom_element_registration_context.h" |
| #include "third_party/blink/renderer/core/html/html_document.h" |
| #include "third_party/blink/renderer/core/html/html_head_element.h" |
| #include "third_party/blink/renderer/core/html/html_title_element.h" |
| #include "third_party/blink/renderer/core/html/html_view_source_document.h" |
| #include "third_party/blink/renderer/core/html/image_document.h" |
| #include "third_party/blink/renderer/core/html/media/html_media_element.h" |
| #include "third_party/blink/renderer/core/html/media/media_document.h" |
| #include "third_party/blink/renderer/core/html/plugin_document.h" |
| #include "third_party/blink/renderer/core/html/text_document.h" |
| #include "third_party/blink/renderer/core/html_names.h" |
| #include "third_party/blink/renderer/core/loader/frame_loader.h" |
| #include "third_party/blink/renderer/core/page/page.h" |
| #include "third_party/blink/renderer/core/svg_names.h" |
| #include "third_party/blink/renderer/platform/bindings/exception_state.h" |
| #include "third_party/blink/renderer/platform/graphics/image.h" |
| #include "third_party/blink/renderer/platform/network/mime/content_type.h" |
| #include "third_party/blink/renderer/platform/network/mime/mime_type_registry.h" |
| #include "third_party/blink/renderer/platform/plugins/plugin_data.h" |
| #include "third_party/blink/renderer/platform/weborigin/security_origin.h" |
| #include "third_party/blink/renderer/platform/wtf/std_lib_extras.h" |
| |
| namespace blink { |
| |
| DOMImplementation::DOMImplementation(Document& document) |
| : document_(document) {} |
| |
| DocumentType* DOMImplementation::createDocumentType( |
| const AtomicString& qualified_name, |
| const String& public_id, |
| const String& system_id, |
| ExceptionState& exception_state) { |
| AtomicString prefix, local_name; |
| if (!Document::ParseQualifiedName(qualified_name, prefix, local_name, |
| exception_state)) |
| return nullptr; |
| |
| return DocumentType::Create(document_, qualified_name, public_id, system_id); |
| } |
| |
| XMLDocument* DOMImplementation::createDocument( |
| const AtomicString& namespace_uri, |
| const AtomicString& qualified_name, |
| DocumentType* doctype, |
| ExceptionState& exception_state) { |
| XMLDocument* doc = nullptr; |
| DocumentInit init = |
| DocumentInit::Create().WithContextDocument(document_->ContextDocument()); |
| if (namespace_uri == svg_names::kNamespaceURI) { |
| doc = XMLDocument::CreateSVG(init); |
| } else if (namespace_uri == html_names::xhtmlNamespaceURI) { |
| doc = XMLDocument::CreateXHTML( |
| init.WithRegistrationContext(document_->RegistrationContext())); |
| } else { |
| doc = XMLDocument::Create(init); |
| } |
| |
| doc->SetSecurityOrigin(document_->GetMutableSecurityOrigin()); |
| doc->SetContextFeatures(document_->GetContextFeatures()); |
| |
| Node* document_element = nullptr; |
| if (!qualified_name.IsEmpty()) { |
| document_element = |
| doc->createElementNS(namespace_uri, qualified_name, exception_state); |
| if (exception_state.HadException()) |
| return nullptr; |
| } |
| |
| if (doctype) |
| doc->AppendChild(doctype); |
| if (document_element) |
| doc->AppendChild(document_element); |
| |
| return doc; |
| } |
| |
| bool DOMImplementation::IsXMLMIMEType(const String& mime_type) { |
| if (EqualIgnoringASCIICase(mime_type, "text/xml") || |
| EqualIgnoringASCIICase(mime_type, "application/xml") || |
| EqualIgnoringASCIICase(mime_type, "text/xsl")) |
| return true; |
| |
| // Per RFCs 3023 and 2045, an XML MIME type is of the form: |
| // ^[0-9a-zA-Z_\\-+~!$\\^{}|.%'`#&*]+/[0-9a-zA-Z_\\-+~!$\\^{}|.%'`#&*]+\+xml$ |
| |
| int length = mime_type.length(); |
| if (length < 7) |
| return false; |
| |
| if (mime_type[0] == '/' || mime_type[length - 5] == '/' || |
| !mime_type.EndsWithIgnoringASCIICase("+xml")) |
| return false; |
| |
| bool has_slash = false; |
| for (int i = 0; i < length - 4; ++i) { |
| UChar ch = mime_type[i]; |
| if (ch >= '0' && ch <= '9') |
| continue; |
| if (ch >= 'a' && ch <= 'z') |
| continue; |
| if (ch >= 'A' && ch <= 'Z') |
| continue; |
| switch (ch) { |
| case '_': |
| case '-': |
| case '+': |
| case '~': |
| case '!': |
| case '$': |
| case '^': |
| case '{': |
| case '}': |
| case '|': |
| case '.': |
| case '%': |
| case '\'': |
| case '`': |
| case '#': |
| case '&': |
| case '*': |
| continue; |
| case '/': |
| if (has_slash) |
| return false; |
| has_slash = true; |
| continue; |
| default: |
| return false; |
| } |
| } |
| |
| return true; |
| } |
| |
| bool DOMImplementation::IsJSONMIMEType(const String& mime_type) { |
| if (mime_type.StartsWithIgnoringASCIICase("application/json")) |
| return true; |
| if (mime_type.StartsWithIgnoringASCIICase("application/")) { |
| size_t subtype = mime_type.FindIgnoringASCIICase("+json", 12); |
| if (subtype != kNotFound) { |
| // Just check that a parameter wasn't matched. |
| size_t parameter_marker = mime_type.Find(";"); |
| if (parameter_marker == kNotFound) { |
| unsigned end_subtype = static_cast<unsigned>(subtype) + 5; |
| return end_subtype == mime_type.length() || |
| IsASCIISpace(mime_type[end_subtype]); |
| } |
| return parameter_marker > subtype; |
| } |
| } |
| return false; |
| } |
| |
| static bool IsTextPlainType(const String& mime_type) { |
| return mime_type.StartsWithIgnoringASCIICase("text/") && |
| !(EqualIgnoringASCIICase(mime_type, "text/html") || |
| EqualIgnoringASCIICase(mime_type, "text/xml") || |
| EqualIgnoringASCIICase(mime_type, "text/xsl")); |
| } |
| |
| bool DOMImplementation::IsTextMIMEType(const String& mime_type) { |
| return MIMETypeRegistry::IsSupportedJavaScriptMIMEType(mime_type) || |
| IsJSONMIMEType(mime_type) || IsTextPlainType(mime_type); |
| } |
| |
| Document* DOMImplementation::createHTMLDocument(const String& title) { |
| DocumentInit init = |
| DocumentInit::Create() |
| .WithContextDocument(document_->ContextDocument()) |
| .WithRegistrationContext(document_->RegistrationContext()); |
| HTMLDocument* d = HTMLDocument::Create(init); |
| d->open(); |
| d->write("<!doctype html><html><head></head><body></body></html>"); |
| if (!title.IsNull()) { |
| HTMLHeadElement* head_element = d->head(); |
| DCHECK(head_element); |
| HTMLTitleElement* title_element = HTMLTitleElement::Create(*d); |
| head_element->AppendChild(title_element); |
| title_element->AppendChild(d->createTextNode(title), ASSERT_NO_EXCEPTION); |
| } |
| d->SetSecurityOrigin(document_->GetMutableSecurityOrigin()); |
| d->SetContextFeatures(document_->GetContextFeatures()); |
| return d; |
| } |
| |
| Document* DOMImplementation::createDocument(const String& type, |
| const DocumentInit& init, |
| bool in_view_source_mode) { |
| if (in_view_source_mode) |
| return HTMLViewSourceDocument::Create(init, type); |
| |
| // Plugins cannot take HTML and XHTML from us, and we don't even need to |
| // initialize the plugin database for those. |
| if (type == "text/html") |
| return HTMLDocument::Create(init); |
| if (type == "application/xhtml+xml") |
| return XMLDocument::CreateXHTML(init); |
| |
| PluginData* plugin_data = nullptr; |
| if (init.GetFrame() && init.GetFrame()->GetPage() && |
| init.GetFrame()->Loader().AllowPlugins(kNotAboutToInstantiatePlugin)) { |
| // If the document is being created for the main frame, |
| // init.frame()->tree().top()->securityContext() returns nullptr. |
| // For that reason, the origin must be retrieved directly from init.url(). |
| if (init.GetFrame()->IsMainFrame()) { |
| scoped_refptr<const SecurityOrigin> origin = |
| SecurityOrigin::Create(init.Url()); |
| plugin_data = init.GetFrame()->GetPage()->GetPluginData(origin.get()); |
| } else { |
| plugin_data = |
| init.GetFrame()->GetPage()->GetPluginData(init.GetFrame() |
| ->Tree() |
| .Top() |
| .GetSecurityContext() |
| ->GetSecurityOrigin()); |
| } |
| } |
| |
| // PDF is one image type for which a plugin can override built-in support. |
| // We do not want QuickTime to take over all image types, obviously. |
| if ((type == "application/pdf" || type == "text/pdf") && plugin_data && |
| plugin_data->SupportsMimeType(type)) { |
| return RuntimeEnabledFeatures::MimeHandlerViewInCrossProcessFrameEnabled() |
| ? HTMLDocument::Create(init) |
| : PluginDocument::Create( |
| init, plugin_data->PluginBackgroundColorForMimeType(type)); |
| } |
| // multipart/x-mixed-replace is only supported for images. |
| if (MIMETypeRegistry::IsSupportedImageResourceMIMEType(type) || |
| type == "multipart/x-mixed-replace") { |
| return ImageDocument::Create(init); |
| } |
| |
| // Check to see if the type can be played by our media player, if so create a |
| // MediaDocument |
| if (HTMLMediaElement::GetSupportsType(ContentType(type))) |
| return MediaDocument::Create(init); |
| |
| // Everything else except text/plain can be overridden by plugins. In |
| // particular, Adobe SVG Viewer should be used for SVG, if installed. |
| // Disallowing plugins to use text/plain prevents plugins from hijacking a |
| // fundamental type that the browser is expected to handle, and also serves as |
| // an optimization to prevent loading the plugin database in the common case. |
| if (type != "text/plain" && plugin_data && |
| plugin_data->SupportsMimeType(type)) { |
| return PluginDocument::Create( |
| init, plugin_data->PluginBackgroundColorForMimeType(type)); |
| } |
| if (IsTextMIMEType(type)) |
| return TextDocument::Create(init); |
| if (type == "image/svg+xml") |
| return XMLDocument::CreateSVG(init); |
| if (IsXMLMIMEType(type)) |
| return XMLDocument::Create(init); |
| |
| return HTMLDocument::Create(init); |
| } |
| |
| void DOMImplementation::Trace(Visitor* visitor) { |
| visitor->Trace(document_); |
| ScriptWrappable::Trace(visitor); |
| } |
| |
| } // namespace blink |