Convert another batch of String::lower callsites to something better, typically conve...
authordarin@apple.com <darin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 3 Feb 2016 22:08:57 +0000 (22:08 +0000)
committerdarin@apple.com <darin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 3 Feb 2016 22:08:57 +0000 (22:08 +0000)
https://bugs.webkit.org/show_bug.cgi?id=153789

Reviewed by Sam Weinig.

Source/WebCore:

* dom/DOMImplementation.cpp:
(WebCore::DOMImplementation::isXMLMIMEType): Use equalLettersIgnoringASCIICase
and the boolean argument to endsWith to ignore ASCII case.
(WebCore::DOMImplementation::isTextMIMEType): Ditto. Also simplified the logic
by removing an if statement.

* dom/Document.cpp:
(WebCore::isSeparator): Deleted. Moved to WindowFeatures.cpp.
(WebCore::processArguments): Ditto.
(WebCore::Document::processViewport): Call the processFeaturesString function
from WindowFeatures.h; the code here was originally just a pasted copy of that code!
(WebCore::Document::processFormatDetection): Ditto.

* html/HTMLCanvasElement.cpp:
(WebCore::HTMLCanvasElement::toEncodingMimeType): Remove now-unneeded
lowercasing of MIME type before calling isSupportedImageMIMETypeForEncoding,
since the MIME type registry now ignores ASCII case. Use convertToASCIILowercase
on the return value, to preserve behavior.
(WebCore::HTMLCanvasElement::toDataURL): Minor coding style tweaks.

* html/HTMLEmbedElement.cpp:
(WebCore::HTMLEmbedElement::parseAttribute): Use convertToASCIILowercase for
the service type here.

* html/HTMLImageElement.cpp:
(WebCore::HTMLImageElement::bestFitSourceFromPictureElement): Remove now-unneeded
lowercasing since MIME type registry now ignores ASCII case. And use
equalLettersIgnoringASCIICase for the case here.

* html/HTMLInputElement.cpp:
(WebCore::parseAcceptAttribute): Use convertToASCIILowercase for the type here.

* html/HTMLLinkElement.cpp:
(WebCore::HTMLLinkElement::parseAttribute): Use convertToASCIILowercase for the
media value here.

* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::canPlayType): Use convertToASCIILowercase for the
content type here.
(WebCore::HTMLMediaElement::selectNextSourceChild): Ditto.

* html/HTMLObjectElement.cpp:
(WebCore::HTMLObjectElement::parseAttribute): Use convertToASCIILowercase for
the service type here.

* html/HTMLTrackElement.cpp:
(WebCore::HTMLTrackElement::parseAttribute): Use convertToASCIILowercase for
the kind here.
(WebCore::HTMLTrackElement::ensureTrack): Ditto. Also use fastGetAttribute
since this is neither the style attribute nor an animatable SVG attribute.

* html/parser/HTMLTreeBuilder.cpp:
(WebCore::createCaseMap): Use convertToASCIILowercase for the local names here.

* inspector/DOMPatchSupport.cpp:
(WebCore::DOMPatchSupport::patchNode): Use containsIgnoringASCIICase instead
of combining lower with find == notFound here.
(WebCore::nodeName): Use convertToASCIILowercase here.

* inspector/InspectorOverlay.cpp:
(WebCore::buildObjectForElementData): Use convertToASCIILowercase for node
name here.

* inspector/InspectorPageAgent.cpp:
(WebCore::createXHRTextDecoder): Remove a now-unneeded call to lower since
DOMImplementation::isXMLMIMEType now ignores ASCII case.

* inspector/InspectorStyleSheet.cpp:
(WebCore::lowercasePropertyName): Use convertToASCIILowercase for property
names here. Also use startsWith rather than a hand-written alternative.
(WebCore::InspectorStyle::populateAllProperties): Use the return value of
the add function to avoid doing a double hash table lookp.
(WebCore::InspectorStyle::styleWithProperties): Use convertToASCIILowercase
to lowercase the property name.

* inspector/NetworkResourcesData.cpp:
(WebCore::createOtherResourceTextDecoder): Remove unneeded call to lower since
DOMImplement::isXMLMIMEType now ignores ASCII case.

* loader/CrossOriginAccessControl.cpp:
(WebCore::createAccessControlPreflightRequest): Use convertToASCIILowercase
to lowercase the access control request header field value.

* loader/cache/CachedScript.cpp:
(WebCore::CachedScript::mimeType): Use convertToASCIILowercase on the content type.

* page/CaptionUserPreferencesMediaAF.cpp:
(WebCore::languageIdentifier): Use convertToASCIILowercase on the language code.

* page/DOMWindow.cpp:
(WebCore::DOMWindow::open): Call parseWindowFeatures instead of using the
constructor for WindowFeatures.
(WebCore::DOMWindow::showModalDialog): Call parseDialogFeatures instead of
using the constructor for WindowFeatures.

* page/EventHandler.cpp:
(WebCore::findDropZone): Remove unneeded lowercasing and empty string checking,
and use the option SpaceSplitString already has to convert to lowercase.
(WebCore::EventHandler::handleAccessKey): Remove unneeded call to lower since
getElementByAccessKey now ignores case. Also tweaked coding style a bit.

* page/OriginAccessEntry.cpp:
(WebCore::OriginAccessEntry::OriginAccessEntry): Use convertToASCIILowercase
on the protocol and host.
(WebCore::OriginAccessEntry::matchesOrigin): Ditto.

* page/SecurityOrigin.cpp:
(WebCore::shouldTreatAsUniqueOrigin): Remove unneeded call to lower since
SchemeRegistry now ignores ASCII case.
(WebCore::SecurityOrigin::SecurityOrigin): Use convertToASCIILowercase on
the protocol and host.
(WebCore::SecurityOrigin::setDomainFromDOM): Use convertToASCIILowercase on
the domain.
(WebCore::SecurityOrigin::canDisplay): Remove call to lower since SchemeRegistry
now ignores ASCII case and because this now uses equalIgnoringASCIICase in
one place that used to use exact matching.

* page/WindowFeatures.cpp: Refactored so this is now some helper functions
plus a struct rather than a class.
(WebCore::isSeparator): Renamed this and removed special handling for NUL.
(WebCore::parseWindowFeatures): Moved the code that was formerly in the
WindowFeatures constructor in here. Refactored the parsing into the
processFeaturesString function, shared with the functions in Document that
do the same kind of parsing. Removed the code that converts the entire string
to lowercase before parsing.
(WebCore::processFeaturesString): Moved the improved version of this function
here from Document.cpp; more efficient because it doesn't allocate strings.
(WebCore::setWindowFeature): Changed to be a function private to this file
with internal linkage. Use equalLettersIgnoringASCIICase so we no longer
rely on converting the string to lowercase before parsing.
(WebCore::parseDialogFeatures): Similar refactoring, but also changed all
the default handling to use Optional<> instead of default values.
(WebCore::boolFeature): Changed to use option and to ignore ASCII case.
(WebCore::floatFeature): Ditto.
(WebCore::parseDialogFeaturesMap): Removed the calls to lower, which are
not needed any more.

* page/WindowFeatures.h: Added default values for all the data members,
and removed all the functions from the WindowFeatures struct. Added the two
functions for parsing window and dialog features. Also added the
processFeaturesString function so we can share it with Document.cpp.

* platform/SchemeRegistry.cpp:
(WebCore::SchemeRegistry::removeURLSchemeRegisteredAsLocal): Use
equalLettersIgnoringASCIICase to ignore ASCII case.

* platform/efl/MIMETypeRegistryEfl.cpp:
(WebCore::MIMETypeRegistry::getMIMETypeForExtension): Use a modern for loop,
and equalIgnoringASCIICase rather than calling lower.

* platform/graphics/MediaPlayer.cpp:
(WebCore::MediaPlayer::load): Use convertToASCIILowercase on MIME type and
key system.
(WebCore::MediaPlayer::generateKeyRequest): Ditto.
(WebCore::MediaPlayer::addKey): Ditto.
(WebCore::MediaPlayer::cancelKeyRequest): Ditto.

* platform/graphics/opengl/Extensions3DOpenGLCommon.cpp:
(WebCore::Extensions3DOpenGLCommon::Extensions3DOpenGLCommon): Use
convertToASCIILowercase on vendor string.

* platform/gtk/MIMETypeRegistryGtk.cpp:
(WebCore::MIMETypeRegistry::getMIMETypeForExtension): Use a modern for loop,
and equalIgnoringASCIICase rather than calling lower.

* platform/mac/PasteboardMac.mm:
(WebCore::cocoaTypeFromHTMLClipboardType): Use convertToASCIILowercase
on the type. Also did a bit of renaming and tweaking the logic.

Source/WTF:

* wtf/text/StringView.h:
(WTF::StringView::toInt): Added an overload without the out parameter.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@196080 268f45cc-cd09-0410-ab3c-d52691b4dbfc

34 files changed:
Source/WTF/ChangeLog
Source/WTF/wtf/text/StringView.h
Source/WebCore/ChangeLog
Source/WebCore/dom/DOMImplementation.cpp
Source/WebCore/dom/Document.cpp
Source/WebCore/html/HTMLCanvasElement.cpp
Source/WebCore/html/HTMLEmbedElement.cpp
Source/WebCore/html/HTMLImageElement.cpp
Source/WebCore/html/HTMLInputElement.cpp
Source/WebCore/html/HTMLLinkElement.cpp
Source/WebCore/html/HTMLMediaElement.cpp
Source/WebCore/html/HTMLObjectElement.cpp
Source/WebCore/html/HTMLTrackElement.cpp
Source/WebCore/html/parser/HTMLTreeBuilder.cpp
Source/WebCore/inspector/DOMPatchSupport.cpp
Source/WebCore/inspector/InspectorOverlay.cpp
Source/WebCore/inspector/InspectorPageAgent.cpp
Source/WebCore/inspector/InspectorStyleSheet.cpp
Source/WebCore/inspector/NetworkResourcesData.cpp
Source/WebCore/loader/CrossOriginAccessControl.cpp
Source/WebCore/loader/cache/CachedScript.cpp
Source/WebCore/page/CaptionUserPreferencesMediaAF.cpp
Source/WebCore/page/DOMWindow.cpp
Source/WebCore/page/EventHandler.cpp
Source/WebCore/page/OriginAccessEntry.cpp
Source/WebCore/page/SecurityOrigin.cpp
Source/WebCore/page/WindowFeatures.cpp
Source/WebCore/page/WindowFeatures.h
Source/WebCore/platform/SchemeRegistry.cpp
Source/WebCore/platform/efl/MIMETypeRegistryEfl.cpp
Source/WebCore/platform/graphics/MediaPlayer.cpp
Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLCommon.cpp
Source/WebCore/platform/gtk/MIMETypeRegistryGtk.cpp
Source/WebCore/platform/mac/PasteboardMac.mm

index 149547c..9097613 100644 (file)
@@ -1,3 +1,13 @@
+2016-02-03  Darin Adler  <darin@apple.com>
+
+        Convert another batch of String::lower callsites to something better, typically convertToASCIILowercase
+        https://bugs.webkit.org/show_bug.cgi?id=153789
+
+        Reviewed by Sam Weinig.
+
+        * wtf/text/StringView.h:
+        (WTF::StringView::toInt): Added an overload without the out parameter.
+
 2016-02-03  Michael Catanzaro  <mcatanzaro@igalia.com>
 
         [GTK][EFL] Switch FTL to B3
index d24c0ab..6dd9398 100644 (file)
@@ -125,6 +125,7 @@ public:
     WTF_EXPORT_STRING_API bool endsWith(const StringView&) const;
     WTF_EXPORT_STRING_API bool endsWithIgnoringASCIICase(const StringView&) const;
 
+    int toInt() const;
     int toInt(bool& isValid) const;
     int toIntStrict(bool& isValid) const;
     float toFloat(bool& isValid) const;
@@ -455,6 +456,12 @@ inline float StringView::toFloat(bool& isValid) const
     return charactersToFloat(characters16(), length(), &isValid);
 }
 
+inline int StringView::toInt() const
+{
+    bool isValid;
+    return toInt(isValid);
+}
+
 inline int StringView::toInt(bool& isValid) const
 {
     if (is8Bit())
index d3d9863..2c0b998 100644 (file)
@@ -1,3 +1,179 @@
+2016-02-03  Darin Adler  <darin@apple.com>
+
+        Convert another batch of String::lower callsites to something better, typically convertToASCIILowercase
+        https://bugs.webkit.org/show_bug.cgi?id=153789
+
+        Reviewed by Sam Weinig.
+
+        * dom/DOMImplementation.cpp:
+        (WebCore::DOMImplementation::isXMLMIMEType): Use equalLettersIgnoringASCIICase
+        and the boolean argument to endsWith to ignore ASCII case.
+        (WebCore::DOMImplementation::isTextMIMEType): Ditto. Also simplified the logic
+        by removing an if statement.
+
+        * dom/Document.cpp:
+        (WebCore::isSeparator): Deleted. Moved to WindowFeatures.cpp.
+        (WebCore::processArguments): Ditto.
+        (WebCore::Document::processViewport): Call the processFeaturesString function
+        from WindowFeatures.h; the code here was originally just a pasted copy of that code!
+        (WebCore::Document::processFormatDetection): Ditto.
+
+        * html/HTMLCanvasElement.cpp:
+        (WebCore::HTMLCanvasElement::toEncodingMimeType): Remove now-unneeded
+        lowercasing of MIME type before calling isSupportedImageMIMETypeForEncoding,
+        since the MIME type registry now ignores ASCII case. Use convertToASCIILowercase
+        on the return value, to preserve behavior.
+        (WebCore::HTMLCanvasElement::toDataURL): Minor coding style tweaks.
+
+        * html/HTMLEmbedElement.cpp:
+        (WebCore::HTMLEmbedElement::parseAttribute): Use convertToASCIILowercase for
+        the service type here.
+
+        * html/HTMLImageElement.cpp:
+        (WebCore::HTMLImageElement::bestFitSourceFromPictureElement): Remove now-unneeded
+        lowercasing since MIME type registry now ignores ASCII case. And use
+        equalLettersIgnoringASCIICase for the case here.
+
+        * html/HTMLInputElement.cpp:
+        (WebCore::parseAcceptAttribute): Use convertToASCIILowercase for the type here.
+
+        * html/HTMLLinkElement.cpp:
+        (WebCore::HTMLLinkElement::parseAttribute): Use convertToASCIILowercase for the
+        media value here.
+
+        * html/HTMLMediaElement.cpp:
+        (WebCore::HTMLMediaElement::canPlayType): Use convertToASCIILowercase for the
+        content type here.
+        (WebCore::HTMLMediaElement::selectNextSourceChild): Ditto.
+
+        * html/HTMLObjectElement.cpp:
+        (WebCore::HTMLObjectElement::parseAttribute): Use convertToASCIILowercase for
+        the service type here.
+
+        * html/HTMLTrackElement.cpp:
+        (WebCore::HTMLTrackElement::parseAttribute): Use convertToASCIILowercase for
+        the kind here.
+        (WebCore::HTMLTrackElement::ensureTrack): Ditto. Also use fastGetAttribute
+        since this is neither the style attribute nor an animatable SVG attribute.
+
+        * html/parser/HTMLTreeBuilder.cpp:
+        (WebCore::createCaseMap): Use convertToASCIILowercase for the local names here.
+
+        * inspector/DOMPatchSupport.cpp:
+        (WebCore::DOMPatchSupport::patchNode): Use containsIgnoringASCIICase instead
+        of combining lower with find == notFound here.
+        (WebCore::nodeName): Use convertToASCIILowercase here.
+
+        * inspector/InspectorOverlay.cpp:
+        (WebCore::buildObjectForElementData): Use convertToASCIILowercase for node
+        name here.
+
+        * inspector/InspectorPageAgent.cpp:
+        (WebCore::createXHRTextDecoder): Remove a now-unneeded call to lower since
+        DOMImplementation::isXMLMIMEType now ignores ASCII case.
+
+        * inspector/InspectorStyleSheet.cpp:
+        (WebCore::lowercasePropertyName): Use convertToASCIILowercase for property
+        names here. Also use startsWith rather than a hand-written alternative.
+        (WebCore::InspectorStyle::populateAllProperties): Use the return value of
+        the add function to avoid doing a double hash table lookp.
+        (WebCore::InspectorStyle::styleWithProperties): Use convertToASCIILowercase
+        to lowercase the property name.
+
+        * inspector/NetworkResourcesData.cpp:
+        (WebCore::createOtherResourceTextDecoder): Remove unneeded call to lower since
+        DOMImplement::isXMLMIMEType now ignores ASCII case.
+
+        * loader/CrossOriginAccessControl.cpp:
+        (WebCore::createAccessControlPreflightRequest): Use convertToASCIILowercase
+        to lowercase the access control request header field value.
+
+        * loader/cache/CachedScript.cpp:
+        (WebCore::CachedScript::mimeType): Use convertToASCIILowercase on the content type.
+
+        * page/CaptionUserPreferencesMediaAF.cpp:
+        (WebCore::languageIdentifier): Use convertToASCIILowercase on the language code.
+
+        * page/DOMWindow.cpp:
+        (WebCore::DOMWindow::open): Call parseWindowFeatures instead of using the
+        constructor for WindowFeatures.
+        (WebCore::DOMWindow::showModalDialog): Call parseDialogFeatures instead of
+        using the constructor for WindowFeatures.
+
+        * page/EventHandler.cpp:
+        (WebCore::findDropZone): Remove unneeded lowercasing and empty string checking,
+        and use the option SpaceSplitString already has to convert to lowercase.
+        (WebCore::EventHandler::handleAccessKey): Remove unneeded call to lower since
+        getElementByAccessKey now ignores case. Also tweaked coding style a bit.
+
+        * page/OriginAccessEntry.cpp:
+        (WebCore::OriginAccessEntry::OriginAccessEntry): Use convertToASCIILowercase
+        on the protocol and host.
+        (WebCore::OriginAccessEntry::matchesOrigin): Ditto.
+
+        * page/SecurityOrigin.cpp:
+        (WebCore::shouldTreatAsUniqueOrigin): Remove unneeded call to lower since
+        SchemeRegistry now ignores ASCII case.
+        (WebCore::SecurityOrigin::SecurityOrigin): Use convertToASCIILowercase on
+        the protocol and host.
+        (WebCore::SecurityOrigin::setDomainFromDOM): Use convertToASCIILowercase on
+        the domain.
+        (WebCore::SecurityOrigin::canDisplay): Remove call to lower since SchemeRegistry
+        now ignores ASCII case and because this now uses equalIgnoringASCIICase in
+        one place that used to use exact matching.
+
+        * page/WindowFeatures.cpp: Refactored so this is now some helper functions
+        plus a struct rather than a class.
+        (WebCore::isSeparator): Renamed this and removed special handling for NUL.
+        (WebCore::parseWindowFeatures): Moved the code that was formerly in the
+        WindowFeatures constructor in here. Refactored the parsing into the
+        processFeaturesString function, shared with the functions in Document that
+        do the same kind of parsing. Removed the code that converts the entire string
+        to lowercase before parsing.
+        (WebCore::processFeaturesString): Moved the improved version of this function
+        here from Document.cpp; more efficient because it doesn't allocate strings.
+        (WebCore::setWindowFeature): Changed to be a function private to this file
+        with internal linkage. Use equalLettersIgnoringASCIICase so we no longer
+        rely on converting the string to lowercase before parsing.
+        (WebCore::parseDialogFeatures): Similar refactoring, but also changed all
+        the default handling to use Optional<> instead of default values.
+        (WebCore::boolFeature): Changed to use option and to ignore ASCII case.
+        (WebCore::floatFeature): Ditto.
+        (WebCore::parseDialogFeaturesMap): Removed the calls to lower, which are
+        not needed any more.
+
+        * page/WindowFeatures.h: Added default values for all the data members,
+        and removed all the functions from the WindowFeatures struct. Added the two
+        functions for parsing window and dialog features. Also added the
+        processFeaturesString function so we can share it with Document.cpp.
+
+        * platform/SchemeRegistry.cpp:
+        (WebCore::SchemeRegistry::removeURLSchemeRegisteredAsLocal): Use
+        equalLettersIgnoringASCIICase to ignore ASCII case.
+
+        * platform/efl/MIMETypeRegistryEfl.cpp:
+        (WebCore::MIMETypeRegistry::getMIMETypeForExtension): Use a modern for loop,
+        and equalIgnoringASCIICase rather than calling lower.
+
+        * platform/graphics/MediaPlayer.cpp:
+        (WebCore::MediaPlayer::load): Use convertToASCIILowercase on MIME type and
+        key system.
+        (WebCore::MediaPlayer::generateKeyRequest): Ditto.
+        (WebCore::MediaPlayer::addKey): Ditto.
+        (WebCore::MediaPlayer::cancelKeyRequest): Ditto.
+
+        * platform/graphics/opengl/Extensions3DOpenGLCommon.cpp:
+        (WebCore::Extensions3DOpenGLCommon::Extensions3DOpenGLCommon): Use
+        convertToASCIILowercase on vendor string.
+
+        * platform/gtk/MIMETypeRegistryGtk.cpp:
+        (WebCore::MIMETypeRegistry::getMIMETypeForExtension): Use a modern for loop,
+        and equalIgnoringASCIICase rather than calling lower.
+
+        * platform/mac/PasteboardMac.mm:
+        (WebCore::cocoaTypeFromHTMLClipboardType): Use convertToASCIILowercase
+        on the type. Also did a bit of renaming and tweaking the logic.
+
 2016-02-03  Dave Hyatt  <hyatt@apple.com>
 
         Implement hanging-punctuation property parsing.
index ae0e70b..bc6a782 100644 (file)
@@ -268,10 +268,12 @@ static inline bool isValidXMLMIMETypeChar(UChar c)
 
 bool DOMImplementation::isXMLMIMEType(const String& mimeType)
 {
-    if (mimeType == "text/xml" || mimeType == "application/xml" || mimeType == "text/xsl")
+    // FIXME: Can we move this logic to MIMETypeRegistry and have this just be a single function call?
+
+    if (equalLettersIgnoringASCIICase(mimeType, "text/xml") || equalLettersIgnoringASCIICase(mimeType, "application/xml") || equalLettersIgnoringASCIICase(mimeType, "text/xsl"))
         return true;
 
-    if (!mimeType.endsWith("+xml"))
+    if (!mimeType.endsWith("+xml", false))
         return false;
 
     size_t slashPosition = mimeType.find('/');
@@ -291,13 +293,14 @@ bool DOMImplementation::isXMLMIMEType(const String& mimeType)
 
 bool DOMImplementation::isTextMIMEType(const String& mimeType)
 {
-    if (MIMETypeRegistry::isSupportedJavaScriptMIMEType(mimeType)
-        || mimeType == "application/json" // Render JSON as text/plain.
-        || (mimeType.startsWith("text/") && mimeType != "text/html"
-            && mimeType != "text/xml" && mimeType != "text/xsl"))
-        return true;
-
-    return false;
+    // FIXME: Can we move this logic to MIMETypeRegistry and have this just be a single function call?
+
+    return MIMETypeRegistry::isSupportedJavaScriptMIMEType(mimeType)
+        || equalLettersIgnoringASCIICase(mimeType, "application/json") // Render JSON as text/plain.
+        || (mimeType.startsWith("text/", false)
+            && !equalLettersIgnoringASCIICase(mimeType, "text/html")
+            && !equalLettersIgnoringASCIICase(mimeType, "text/xml")
+            && !equalLettersIgnoringASCIICase(mimeType, "text/xsl"));
 }
 
 Ref<HTMLDocument> DOMImplementation::createHTMLDocument(const String& title)
index 5c5a529..3a9095f 100644 (file)
 #include "TreeWalker.h"
 #include "VisitedLinkState.h"
 #include "WheelEvent.h"
+#include "WindowFeatures.h"
 #include "XMLDocument.h"
 #include "XMLDocumentParser.h"
 #include "XMLNSNames.h"
@@ -3278,43 +3279,6 @@ void Document::processHttpEquiv(const String& equiv, const String& content)
     }
 }
 
-static bool isSeparator(UChar character)
-{
-    return character == ' ' || character == '\t' || character == '\n' || character == '\r' || character == '=' || character == ',';
-}
-
-static void processArguments(StringView features, std::function<void(StringView type, StringView value)> callback)
-{
-    unsigned length = features.length();
-    for (unsigned i = 0; i < length; ) {
-        // skip to first non-separator
-        while (i < length && isSeparator(features[i]))
-            ++i;
-        unsigned keyBegin = i;
-
-        // skip to first separator
-        while (i < length && !isSeparator(features[i]))
-            i++;
-        unsigned keyEnd = i;
-
-        // skip to first '=', but don't skip past a ','
-        while (i < length && features[i] != '=' && features[i] != ',')
-            ++i;
-
-        // skip to first non-separator, but don't skip past a ','
-        while (i < length && isSeparator(features[i]) && features[i] != ',')
-            ++i;
-        unsigned valueBegin = i;
-
-        // skip to first separator
-        while (i < length && !isSeparator(features[i]))
-            ++i;
-        unsigned valueEnd = i;
-
-        callback(features.substring(keyBegin, keyEnd - keyBegin), features.substring(valueBegin, valueEnd - valueBegin));
-    }
-}
-
 void Document::processViewport(const String& features, ViewportArguments::Type origin)
 {
     ASSERT(!features.isNull());
@@ -3324,7 +3288,7 @@ void Document::processViewport(const String& features, ViewportArguments::Type o
 
     m_viewportArguments = ViewportArguments(origin);
 
-    processArguments(features, [this](StringView key, StringView value) {
+    processFeaturesString(features, [this](StringView key, StringView value) {
         setViewportFeature(m_viewportArguments, *this, key, value);
     });
 
@@ -3349,7 +3313,7 @@ void Document::updateViewportArguments()
 void Document::processFormatDetection(const String& features)
 {
     // FIXME: Find a better place for this function.
-    processArguments(features, [this](StringView key, StringView value) {
+    processFeaturesString(features, [this](StringView key, StringView value) {
         if (equalLettersIgnoringASCIICase(key, "telephone") && equalLettersIgnoringASCIICase(value, "no"))
             setIsTelephoneNumberParsingAllowed(false);
     });
index 7b35699..a9a57d4 100644 (file)
@@ -480,13 +480,9 @@ void HTMLCanvasElement::setSurfaceSize(const IntSize& size)
 
 String HTMLCanvasElement::toEncodingMimeType(const String& mimeType)
 {
-    String lowercaseMimeType = mimeType.lower();
-
-    // FIXME: Make isSupportedImageMIMETypeForEncoding threadsafe (to allow this method to be used on a worker thread).
-    if (mimeType.isNull() || !MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(lowercaseMimeType))
-        lowercaseMimeType = "image/png";
-
-    return lowercaseMimeType;
+    if (!MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType))
+        return ASCIILiteral("image/png");
+    return mimeType.convertToASCIILowercase();
 }
 
 String HTMLCanvasElement::toDataURL(const String& mimeType, const double* quality, ExceptionCode& ec)
@@ -499,19 +495,17 @@ String HTMLCanvasElement::toDataURL(const String& mimeType, const double* qualit
     if (m_size.isEmpty() || !buffer())
         return ASCIILiteral("data:,");
 
-    String encodingMimeType = toEncodingMimeType(mimeType);
+    String encodingMIMEType = toEncodingMimeType(mimeType);
 
 #if USE(CG)
     // Try to get ImageData first, as that may avoid lossy conversions.
-    RefPtr<ImageData> imageData = getImageData();
-
-    if (imageData)
-        return ImageDataToDataURL(*imageData, encodingMimeType, quality);
+    if (auto imageData = getImageData())
+        return ImageDataToDataURL(*imageData, encodingMIMEType, quality);
 #endif
 
     makeRenderingResultsAvailable();
 
-    return buffer()->toDataURL(encodingMimeType, quality);
+    return buffer()->toDataURL(encodingMIMEType, quality);
 }
 
 RefPtr<ImageData> HTMLCanvasElement::getImageData()
index 53ecf0a..0936649 100644 (file)
@@ -101,7 +101,7 @@ void HTMLEmbedElement::collectStyleForPresentationAttribute(const QualifiedName&
 void HTMLEmbedElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
 {
     if (name == typeAttr) {
-        m_serviceType = value.string().left(value.find(';')).lower();
+        m_serviceType = value.string().left(value.find(';')).convertToASCIILowercase();
         // FIXME: The only difference between this and HTMLObjectElement's corresponding
         // code is that HTMLObjectElement does setNeedsWidgetUpdate(true). Consider moving
         // this up to the HTMLPlugInImageElement to be shared.
index 800891b..8de9563 100644 (file)
@@ -162,8 +162,7 @@ ImageCandidate HTMLImageElement::bestFitSourceFromPictureElement()
             if (indexOfSemicolon >= 0)
                 type.truncate(indexOfSemicolon);
             type = stripLeadingAndTrailingHTMLSpaces(type);
-            type = type.lower();
-            if (!type.isEmpty() && !MIMETypeRegistry::isSupportedImageMIMEType(type) && type != "image/svg+xml")
+            if (!type.isEmpty() && !MIMETypeRegistry::isSupportedImageMIMEType(type) && !equalLettersIgnoringASCIICase(type, "image/svg+xml"))
                 continue;
         }
         MediaQueryEvaluator evaluator(document().printing() ? "print" : "screen", document().frame(), document().documentElement() ? document().documentElement()->computedStyle() : nullptr);
index 3c02e39..acdba84 100644 (file)
@@ -1229,7 +1229,7 @@ static Vector<String> parseAcceptAttribute(const String& acceptString, bool (*pr
             continue;
         if (!predicate(trimmedType))
             continue;
-        types.append(trimmedType.lower());
+        types.append(trimmedType.convertToASCIILowercase());
     }
 
     return types;
index 1c49ea3..18ee435 100644 (file)
@@ -164,7 +164,7 @@ void HTMLLinkElement::parseAttribute(const QualifiedName& name, const AtomicStri
         return;
     }
     if (name == mediaAttr) {
-        m_media = value.string().lower();
+        m_media = value.string().convertToASCIILowercase();
         process();
         if (m_sheet && !isDisabled())
             document().styleResolverChanged(DeferRecalcStyle);
index 4a829e0..2660fed 100644 (file)
@@ -920,7 +920,7 @@ String HTMLMediaElement::canPlayType(const String& mimeType, const String& keySy
 {
     MediaEngineSupportParameters parameters;
     ContentType contentType(mimeType);
-    parameters.type = contentType.type().lower();
+    parameters.type = contentType.type().convertToASCIILowercase();
     parameters.codecs = contentType.parameter(ASCIILiteral("codecs"));
     parameters.url = url;
 #if ENABLE(ENCRYPTED_MEDIA)
@@ -4176,7 +4176,7 @@ URL HTMLMediaElement::selectNextSourceChild(ContentType* contentType, String* ke
 #endif
             MediaEngineSupportParameters parameters;
             ContentType contentType(type);
-            parameters.type = contentType.type().lower();
+            parameters.type = contentType.type().convertToASCIILowercase();
             parameters.codecs = contentType.parameter(ASCIILiteral("codecs"));
             parameters.url = mediaURL;
 #if ENABLE(ENCRYPTED_MEDIA)
index 8b28310..b16928f 100644 (file)
@@ -112,7 +112,7 @@ void HTMLObjectElement::parseAttribute(const QualifiedName& name, const AtomicSt
     if (name == formAttr)
         formAttributeChanged();
     else if (name == typeAttr) {
-        m_serviceType = value.string().left(value.find(';')).lower();
+        m_serviceType = value.string().left(value.find(';')).convertToASCIILowercase();
         invalidateRenderer = !fastHasAttribute(classidAttr);
         setNeedsWidgetUpdate(true);
     } else if (name == dataAttr) {
index b3eb3b8..fa77be7 100644 (file)
@@ -102,7 +102,7 @@ void HTMLTrackElement::parseAttribute(const QualifiedName& name, const AtomicStr
         // 4.8.10.12.3 Sourcing out-of-band text tracks
         // As the kind, label, and srclang attributes are set, changed, or removed, the text track must update accordingly...
         } else if (name == kindAttr)
-            track()->setKind(value.lower());
+            track()->setKind(value.convertToASCIILowercase());
         else if (name == labelAttr)
             track()->setLabel(value);
         else if (name == srclangAttr)
@@ -157,8 +157,8 @@ void HTMLTrackElement::setIsDefault(bool isDefault)
 LoadableTextTrack& HTMLTrackElement::ensureTrack()
 {
     if (!m_track) {
-        // The kind attribute is an enumerated attribute, limited only to know values. It defaults to 'subtitles' if missing or invalid.
-        String kind = getAttribute(kindAttr).lower();
+        // The kind attribute is an enumerated attribute, limited only to known values. It defaults to 'subtitles' if missing or invalid.
+        String kind = fastGetAttribute(kindAttr).convertToASCIILowercase();
         if (!TextTrack::isValidKindKeyword(kind))
             kind = TextTrack::subtitlesKeyword();
         m_track = LoadableTextTrack::create(this, kind, label(), srclang());
index a21cc2d..dda0de8 100644 (file)
@@ -511,7 +511,7 @@ template <typename TableQualifiedName> static HashMap<AtomicString, QualifiedNam
     for (unsigned i = 0; i < length; ++i) {
         const QualifiedName& name = *names[i];
         const AtomicString& localName = name.localName();
-        AtomicString loweredLocalName = localName.lower();
+        AtomicString loweredLocalName = localName.convertToASCIILowercase();
         if (loweredLocalName != localName)
             map.add(loweredLocalName, name);
     }
index b69238c..9ffa00b 100644 (file)
@@ -136,14 +136,13 @@ Node* DOMPatchSupport::patchNode(Node& node, const String& markup, ExceptionCode
         oldList.append(createDigest(child, nullptr));
 
     // Compose the new list.
-    String markupCopy = markup.lower();
     Vector<std::unique_ptr<Digest>> newList;
     for (Node* child = parentNode->firstChild(); child != &node; child = child->nextSibling())
         newList.append(createDigest(child, nullptr));
     for (Node* child = fragment->firstChild(); child; child = child->nextSibling()) {
-        if (child->hasTagName(headTag) && !child->firstChild() && markupCopy.find("</head>") == notFound)
+        if (child->hasTagName(headTag) && !child->firstChild() && !markup.containsIgnoringASCIICase("</head>"))
             continue; // HTML5 parser inserts empty <head> tag whenever it parses <body>
-        if (child->hasTagName(bodyTag) && !child->firstChild() && markupCopy.find("</body>") == notFound)
+        if (child->hasTagName(bodyTag) && !child->firstChild() && !markup.containsIgnoringASCIICase("</body>"))
             continue; // HTML5 parser inserts empty <body> tag whenever it parses </head>
         newList.append(createDigest(child, &m_unusedNodesMap));
     }
@@ -496,11 +495,12 @@ void DOMPatchSupport::markNodeAsUsed(Digest* digest)
 }
 
 #ifdef DEBUG_DOM_PATCH_SUPPORT
+
 static String nodeName(Node* node)
 {
     if (node->document().isXHTMLDocument())
          return node->nodeName();
-    return node->nodeName().lower();
+    return node->nodeName().convertToASCIILowercase();
 }
 
 void DOMPatchSupport::dumpMap(const ResultMap& map, const String& name)
@@ -509,6 +509,7 @@ void DOMPatchSupport::dumpMap(const ResultMap& map, const String& name)
     for (size_t i = 0; i < map.size(); ++i)
         fprintf(stderr, "%s[%lu]: %s (%p) - [%lu]\n", name.utf8().data(), i, map[i].first ? nodeName(map[i].first->m_node).utf8().data() : "", map[i].first, map[i].second);
 }
+
 #endif
 
 } // namespace WebCore
index 10cc024..8e98933 100644 (file)
@@ -709,7 +709,7 @@ static RefPtr<Inspector::Protocol::OverlayTypes::ElementData> buildObjectForElem
     Element& element = *effectiveElement;
     bool isXHTML = element.document().isXHTMLDocument();
     auto elementData = Inspector::Protocol::OverlayTypes::ElementData::create()
-        .setTagName(isXHTML ? element.nodeName() : element.nodeName().lower())
+        .setTagName(isXHTML ? element.nodeName() : element.nodeName().convertToASCIILowercase())
         .setIdValue(element.getIdAttribute())
         .release();
 
index fda77e4..80ae7f2 100644 (file)
@@ -123,7 +123,7 @@ static RefPtr<TextResourceDecoder> createXHRTextDecoder(const String& mimeType,
     RefPtr<TextResourceDecoder> decoder;
     if (!textEncodingName.isEmpty())
         decoder = TextResourceDecoder::create("text/plain", textEncodingName);
-    else if (DOMImplementation::isXMLMIMEType(mimeType.lower())) {
+    else if (DOMImplementation::isXMLMIMEType(mimeType)) {
         decoder = TextResourceDecoder::create("application/xml");
         decoder->useLenientXMLDecoding();
     } else if (equalLettersIgnoringASCIICase(mimeType, "text/html"))
index 065035d..c310921 100644 (file)
@@ -350,9 +350,9 @@ bool InspectorStyle::getText(String* result) const
 static String lowercasePropertyName(const String& name)
 {
     // Custom properties are case-sensitive.
-    if (name.length() > 2 && name.characterAt(0) == '-' && name.characterAt(1) == '-')
+    if (name.startsWith("--"))
         return name;
-    return name.lower();
+    return name.convertToASCIILowercase();
 }
 
 bool InspectorStyle::populateAllProperties(Vector<InspectorStyleProperty>* result) const
@@ -375,11 +375,8 @@ bool InspectorStyle::populateAllProperties(Vector<InspectorStyleProperty>* resul
 
     for (int i = 0, size = m_style->length(); i < size; ++i) {
         String name = m_style->item(i);
-        String lowerName = lowercasePropertyName(name);
-        if (sourcePropertyNames.contains(lowerName))
-            continue;
-        sourcePropertyNames.add(lowerName);
-        result->append(InspectorStyleProperty(CSSPropertySourceData(name, m_style->getPropertyValue(name), !m_style->getPropertyPriority(name).isEmpty(), true, SourceRange()), false, false));
+        if (sourcePropertyNames.add(lowercasePropertyName(name)))
+            result->append(InspectorStyleProperty(CSSPropertySourceData(name, m_style->getPropertyValue(name), !m_style->getPropertyPriority(name).isEmpty(), true, SourceRange()), false, false));
     }
 
     return true;
@@ -413,7 +410,7 @@ Ref<Inspector::Protocol::CSS::CSSStyle> InspectorStyle::styleWithProperties() co
         status = it->disabled ? Inspector::Protocol::CSS::CSSPropertyStatus::Disabled : Inspector::Protocol::CSS::CSSPropertyStatus::Active;
 
         RefPtr<Inspector::Protocol::CSS::CSSProperty> property = Inspector::Protocol::CSS::CSSProperty::create()
-            .setName(name.lower())
+            .setName(name.convertToASCIILowercase())
             .setValue(propertyEntry.value)
             .release();
 
index dbd431a..39d3535 100644 (file)
@@ -141,7 +141,7 @@ static RefPtr<TextResourceDecoder> createOtherResourceTextDecoder(const String&
     RefPtr<TextResourceDecoder> decoder;
     if (!textEncodingName.isEmpty())
         decoder = TextResourceDecoder::create("text/plain", textEncodingName);
-    else if (DOMImplementation::isXMLMIMEType(mimeType.lower())) {
+    else if (DOMImplementation::isXMLMIMEType(mimeType)) {
         decoder = TextResourceDecoder::create("application/xml");
         decoder->useLenientXMLDecoding();
     } else if (equalLettersIgnoringASCIICase(mimeType, "text/html"))
index 17a0b0b..01a4d6f 100644 (file)
@@ -127,7 +127,7 @@ ResourceRequest createAccessControlPreflightRequest(const ResourceRequest& reque
             headerBuffer.append(headerField.key);
         }
 
-        preflightRequest.setHTTPHeaderField(HTTPHeaderName::AccessControlRequestHeaders, headerBuffer.toString().lower());
+        preflightRequest.setHTTPHeaderField(HTTPHeaderName::AccessControlRequestHeaders, headerBuffer.toString().convertToASCIILowercase());
     }
 
     return preflightRequest;
index 594fb33..edcecf8 100644 (file)
@@ -66,7 +66,7 @@ String CachedScript::encoding() const
 
 String CachedScript::mimeType() const
 {
-    return extractMIMETypeFromMediaType(m_response.httpHeaderField(HTTPHeaderName::ContentType)).lower();
+    return extractMIMETypeFromMediaType(m_response.httpHeaderField(HTTPHeaderName::ContentType)).convertToASCIILowercase();
 }
 
 StringView CachedScript::script()
index 42ae170..5006dca 100644 (file)
@@ -593,7 +593,7 @@ static String languageIdentifier(const String& languageCode)
     if (languageCode.isEmpty())
         return languageCode;
 
-    String lowercaseLanguageCode = languageCode.lower();
+    String lowercaseLanguageCode = languageCode.convertToASCIILowercase();
 
     // Need 2U here to disambiguate String::operator[] from operator(NSString*, int)[] in a production build.
     if (lowercaseLanguageCode.length() >= 3 && (lowercaseLanguageCode[2U] == '_' || lowercaseLanguageCode[2U] == '-'))
index 8e33a77..dac54d7 100644 (file)
@@ -2217,8 +2217,7 @@ PassRefPtr<DOMWindow> DOMWindow::open(const String& urlString, const AtomicStrin
         return targetFrame->document()->domWindow();
     }
 
-    WindowFeatures windowFeatures(windowFeaturesString);
-    RefPtr<Frame> result = createWindow(urlString, frameName, windowFeatures, activeWindow, *firstFrame, *m_frame);
+    RefPtr<Frame> result = createWindow(urlString, frameName, parseWindowFeatures(windowFeaturesString), activeWindow, *firstFrame, *m_frame);
     return result ? result->document()->domWindow() : nullptr;
 }
 
@@ -2245,8 +2244,7 @@ void DOMWindow::showModalDialog(const String& urlString, const String& dialogFea
     if (!canShowModalDialogNow(m_frame) || !firstWindow.allowPopUp())
         return;
 
-    WindowFeatures windowFeatures(dialogFeaturesString, screenAvailableRect(m_frame->view()));
-    RefPtr<Frame> dialogFrame = createWindow(urlString, emptyAtom, windowFeatures, activeWindow, *firstFrame, *m_frame, WTFMove(prepareDialogFunction));
+    RefPtr<Frame> dialogFrame = createWindow(urlString, emptyAtom, parseDialogFeatures(dialogFeaturesString, screenAvailableRect(m_frame->view())), activeWindow, *firstFrame, *m_frame, WTFMove(prepareDialogFunction));
     if (!dialogFrame)
         return;
     dialogFrame->page()->chrome().runModal();
index a24890c..3fca597 100644 (file)
@@ -2166,27 +2166,16 @@ static bool findDropZone(Node* target, DataTransfer* dataTransfer)
     ASSERT(target);
     Element* element = is<Element>(*target) ? downcast<Element>(target) : target->parentElement();
     for (; element; element = element->parentElement()) {
+        SpaceSplitString keywords(element->fastGetAttribute(webkitdropzoneAttr), true);
         bool matched = false;
-        String dropZoneStr = element->fastGetAttribute(webkitdropzoneAttr);
-
-        if (dropZoneStr.isEmpty())
-            continue;
-        
-        dropZoneStr = dropZoneStr.lower();
-        
-        SpaceSplitString keywords(dropZoneStr, false);
-        if (keywords.isEmpty())
-            continue;
-        
         DragOperation dragOperation = DragOperationNone;
-        for (unsigned int i = 0; i < keywords.size(); i++) {
+        for (unsigned i = 0, size = keywords.size(); i < size; ++i) {
             DragOperation op = convertDropZoneOperationToDragOperation(keywords[i]);
             if (op != DragOperationNone) {
                 if (dragOperation == DragOperationNone)
                     dragOperation = op;
             } else
                 matched = matched || hasDropZoneType(*dataTransfer, keywords[i].string());
-
             if (matched && dragOperation != DragOperationNone)
                 break;
         }
@@ -2913,20 +2902,19 @@ void EventHandler::hoverTimerFired()
     }
 }
 
-bool EventHandler::handleAccessKey(const PlatformKeyboardEvent& evt)
+bool EventHandler::handleAccessKey(const PlatformKeyboardEvent& event)
 {
     // FIXME: Ignoring the state of Shift key is what neither IE nor Firefox do.
     // IE matches lower and upper case access keys regardless of Shift key state - but if both upper and
     // lower case variants are present in a document, the correct element is matched based on Shift key state.
     // Firefox only matches an access key if Shift is not pressed, and does that case-insensitively.
     ASSERT(!(accessKeyModifiers() & PlatformEvent::ShiftKey));
-    if ((evt.modifiers() & ~PlatformEvent::ShiftKey) != accessKeyModifiers())
+    if ((event.modifiers() & ~PlatformEvent::ShiftKey) != accessKeyModifiers())
         return false;
-    String key = evt.unmodifiedText();
-    Element* elem = m_frame.document()->getElementByAccessKey(key.lower());
-    if (!elem)
+    Element* element = m_frame.document()->getElementByAccessKey(event.unmodifiedText());
+    if (!element)
         return false;
-    elem->accessKeyAction(false);
+    element->accessKeyAction(false);
     return true;
 }
 
index 7ff67cc..8c123ae 100644 (file)
@@ -36,8 +36,8 @@
 namespace WebCore {
     
 OriginAccessEntry::OriginAccessEntry(const String& protocol, const String& host, SubdomainSetting subdomainSetting)
-    : m_protocol(protocol.lower())
-    , m_host(host.lower())
+    : m_protocol(protocol.convertToASCIILowercase())
+    , m_host(host.convertToASCIILowercase())
     , m_subdomainSettings(subdomainSetting)
 {
     ASSERT(subdomainSetting == AllowSubdomains || subdomainSetting == DisallowSubdomains);
@@ -48,8 +48,8 @@ OriginAccessEntry::OriginAccessEntry(const String& protocol, const String& host,
 
 bool OriginAccessEntry::matchesOrigin(const SecurityOrigin& origin) const
 {
-    ASSERT(origin.host() == origin.host().lower());
-    ASSERT(origin.protocol() == origin.protocol().lower());
+    ASSERT(origin.host() == origin.host().convertToASCIILowercase());
+    ASSERT(origin.protocol() == origin.protocol().convertToASCIILowercase());
 
     if (m_protocol != origin.protocol())
         return false;
index 8fe7e60..fba6fc1 100644 (file)
@@ -97,11 +97,7 @@ static bool shouldTreatAsUniqueOrigin(const URL& url)
     if (schemeRequiresHost(innerURL) && innerURL.host().isEmpty())
         return true;
 
-    // SchemeRegistry needs a lower case protocol because it uses HashMaps
-    // that assume the scheme has already been canonicalized.
-    String protocol = innerURL.protocol().lower();
-
-    if (SchemeRegistry::shouldTreatURLSchemeAsNoAccess(protocol))
+    if (SchemeRegistry::shouldTreatURLSchemeAsNoAccess(innerURL.protocol()))
         return true;
 
     // This is the common case.
@@ -109,8 +105,8 @@ static bool shouldTreatAsUniqueOrigin(const URL& url)
 }
 
 SecurityOrigin::SecurityOrigin(const URL& url)
-    : m_protocol(url.protocol().isNull() ? emptyString() : url.protocol().lower())
-    , m_host(url.host().isNull() ? emptyString() : url.host().lower())
+    : m_protocol(url.protocol().isNull() ? emptyString() : url.protocol().convertToASCIILowercase())
+    , m_host(url.host().isNull() ? emptyString() : url.host().convertToASCIILowercase())
     , m_port(url.port())
     , m_isUnique(false)
     , m_universalAccess(false)
@@ -203,7 +199,7 @@ Ref<SecurityOrigin> SecurityOrigin::isolatedCopy() const
 void SecurityOrigin::setDomainFromDOM(const String& newDomain)
 {
     m_domainWasSetInDOM = true;
-    m_domain = newDomain.lower();
+    m_domain = newDomain.convertToASCIILowercase();
 }
 
 bool SecurityOrigin::isSecure(const URL& url)
@@ -354,16 +350,16 @@ bool SecurityOrigin::canDisplay(const URL& url) const
     if (m_universalAccess)
         return true;
 
-    String protocol = url.protocol().lower();
-
     if (isFeedWithNestedProtocolInHTTPFamily(url))
         return true;
 
+    String protocol = url.protocol();
+
     if (SchemeRegistry::canDisplayOnlyIfCanRequest(protocol))
         return canRequest(url);
 
     if (SchemeRegistry::shouldTreatURLSchemeAsDisplayIsolated(protocol))
-        return m_protocol == protocol || SecurityPolicy::isAccessToURLWhiteListed(this, url);
+        return equalIgnoringASCIICase(m_protocol, protocol) || SecurityPolicy::isAccessToURLWhiteListed(this, url);
 
     if (SecurityPolicy::restrictAccessToLocal() && SchemeRegistry::shouldTreatURLSchemeAsLocal(protocol))
         return canLoadLocalResources() || SecurityPolicy::isAccessToURLWhiteListed(this, url);
index c0dd86c..7c76ae1 100644 (file)
 
 #include "FloatRect.h"
 #include <wtf/Assertions.h>
+#include <wtf/HashMap.h>
 #include <wtf/MathExtras.h>
 #include <wtf/text/StringHash.h>
 
 namespace WebCore {
 
-// Though isspace() considers \t and \v to be whitespace, Win IE doesn't when parsing window features.
-static bool isWindowFeaturesSeparator(UChar c)
+typedef HashMap<String, String, ASCIICaseInsensitiveHash> DialogFeaturesMap;
+
+static void setWindowFeature(WindowFeatures&, StringView key, StringView value);
+
+static DialogFeaturesMap parseDialogFeaturesMap(const String&);
+static Optional<bool> boolFeature(const DialogFeaturesMap&, const char* key);
+static Optional<float> floatFeature(const DialogFeaturesMap&, const char* key, float min, float max);
+
+static bool isSeparator(UChar character)
 {
-    return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '=' || c == ',' || c == '\0';
+    return character == ' ' || character == '\t' || character == '\n' || character == '\r' || character == '=' || character == ',';
 }
 
-WindowFeatures::WindowFeatures(const String& features)
-    : resizable(true)
-    , fullscreen(false)
-    , dialog(false)
+WindowFeatures parseWindowFeatures(StringView featuresString)
 {
-    /*
-     The IE rule is: all features except for channelmode and fullscreen default to YES, but
-     if the user specifies a feature string, all features default to NO. (There is no public
-     standard that applies to this method.)
-
-     <http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/open_0.asp>
-     We always allow a window to be resized, which is consistent with Firefox.
-     */
-
-    if (features.isEmpty()) {
-        menuBarVisible = true;
-        statusBarVisible = true;
-        toolBarVisible = true;
-        locationBarVisible = true;
-        scrollbarsVisible = true;
-        return;
-    }
+    // The IE rule is: all features except for channelmode and fullscreen default to YES, but
+    // if the user specifies a feature string, all features default to NO. (There is no public
+    // standard that applies to this method.)
+    //
+    // <http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/open_0.asp>
+    // We always allow a window to be resized, which is consistent with Firefox.
+
+    WindowFeatures features;
+
+    if (featuresString.isEmpty())
+        return features;
 
-    menuBarVisible = false;
-    statusBarVisible = false;
-    toolBarVisible = false;
-    locationBarVisible = false;
-    scrollbarsVisible = false;
+    features.menuBarVisible = false;
+    features.statusBarVisible = false;
+    features.toolBarVisible = false;
+    features.locationBarVisible = false;
+    features.scrollbarsVisible = false;
 
-    // Tread lightly in this code -- it was specifically designed to mimic Win IE's parsing behavior.
-    unsigned keyBegin, keyEnd;
-    unsigned valueBegin, valueEnd;
+    processFeaturesString(featuresString, [&features](StringView key, StringView value) {
+        setWindowFeature(features, key, value);
+    });
 
-    String buffer = features.lower();
-    unsigned length = buffer.length();
+    return features;
+}
+
+void processFeaturesString(StringView features, std::function<void(StringView type, StringView value)> callback)
+{
+    unsigned length = features.length();
     for (unsigned i = 0; i < length; ) {
-        // skip to first non-separator, but don't skip past the end of the string
-        while (isWindowFeaturesSeparator(buffer[i])) {
-            if (i >= length)
-                break;
-            i++;
-        }
-        keyBegin = i;
+        // skip to first non-separator
+        while (i < length && isSeparator(features[i]))
+            ++i;
+        unsigned keyBegin = i;
 
         // skip to first separator
-        while (!isWindowFeaturesSeparator(buffer[i]))
+        while (i < length && !isSeparator(features[i]))
             i++;
-        keyEnd = i;
+        unsigned keyEnd = i;
 
-        // skip to first '=', but don't skip past a ',' or the end of the string
-        while (buffer[i] != '=') {
-            if (buffer[i] == ',' || i >= length)
-                break;
-            i++;
-        }
+        // skip to first '=', but don't skip past a ','
+        while (i < length && features[i] != '=' && features[i] != ',')
+            ++i;
 
-        // skip to first non-separator, but don't skip past a ',' or the end of the string
-        while (isWindowFeaturesSeparator(buffer[i])) {
-            if (buffer[i] == ',' || i >= length)
-                break;
-            i++;
-        }
-        valueBegin = i;
+        // skip to first non-separator, but don't skip past a ','
+        while (i < length && isSeparator(features[i]) && features[i] != ',')
+            ++i;
+        unsigned valueBegin = i;
 
         // skip to first separator
-        while (!isWindowFeaturesSeparator(buffer[i]))
-            i++;
-        valueEnd = i;
-
-        ASSERT_WITH_SECURITY_IMPLICATION(i <= length);
+        while (i < length && !isSeparator(features[i]))
+            ++i;
+        unsigned valueEnd = i;
 
-        String keyString(buffer.substring(keyBegin, keyEnd - keyBegin));
-        String valueString(buffer.substring(valueBegin, valueEnd - valueBegin));
-        setWindowFeature(keyString, valueString);
+        callback(features.substring(keyBegin, keyEnd - keyBegin), features.substring(valueBegin, valueEnd - valueBegin));
     }
 }
 
-void WindowFeatures::setWindowFeature(const String& keyString, const String& valueString)
+static void setWindowFeature(WindowFeatures& features, StringView key, StringView value)
 {
-    int value;
-
     // Listing a key with no value is shorthand for key=yes
-    if (valueString.isEmpty() || valueString == "yes")
-        value = 1;
+    int numericValue;
+    if (value.isEmpty() || equalLettersIgnoringASCIICase(value, "yes"))
+        numericValue = 1;
     else
-        value = valueString.toInt();
+        numericValue = value.toInt();
 
-    // We treat keyString of "resizable" here as an additional feature rather than setting resizeable to true.
+    // We treat key of "resizable" here as an additional feature rather than setting resizeable to true.
     // This is consistent with Firefox, but could also be handled at another level.
 
-    if (keyString == "left" || keyString == "screenx")
-        x = value;
-    else if (keyString == "top" || keyString == "screeny")
-        y = value;
-    else if (keyString == "width" || keyString == "innerwidth")
-        width = value;
-    else if (keyString == "height" || keyString == "innerheight")
-        height = value;
-    else if (keyString == "menubar")
-        menuBarVisible = value;
-    else if (keyString == "toolbar")
-        toolBarVisible = value;
-    else if (keyString == "location")
-        locationBarVisible = value;
-    else if (keyString == "status")
-        statusBarVisible = value;
-    else if (keyString == "fullscreen")
-        fullscreen = value;
-    else if (keyString == "scrollbars")
-        scrollbarsVisible = value;
-    else if (value == 1)
-        additionalFeatures.append(keyString);
+    if (equalLettersIgnoringASCIICase(key, "left") || equalLettersIgnoringASCIICase(key, "screenx"))
+        features.x = numericValue;
+    else if (equalLettersIgnoringASCIICase(key, "top") || equalLettersIgnoringASCIICase(key, "screeny"))
+        features.y = numericValue;
+    else if (equalLettersIgnoringASCIICase(key, "width") || equalLettersIgnoringASCIICase(key, "innerwidth"))
+        features.width = numericValue;
+    else if (equalLettersIgnoringASCIICase(key, "height") || equalLettersIgnoringASCIICase(key, "innerheight"))
+        features.height = numericValue;
+    else if (equalLettersIgnoringASCIICase(key, "menubar"))
+        features.menuBarVisible = numericValue;
+    else if (equalLettersIgnoringASCIICase(key, "toolbar"))
+        features.toolBarVisible = numericValue;
+    else if (equalLettersIgnoringASCIICase(key, "location"))
+        features.locationBarVisible = numericValue;
+    else if (equalLettersIgnoringASCIICase(key, "status"))
+        features.statusBarVisible = numericValue;
+    else if (equalLettersIgnoringASCIICase(key, "fullscreen"))
+        features.fullscreen = numericValue;
+    else if (equalLettersIgnoringASCIICase(key, "scrollbars"))
+        features.scrollbarsVisible = numericValue;
+    else if (numericValue == 1)
+        features.additionalFeatures.append(key.toString());
 }
 
-WindowFeatures::WindowFeatures(const String& dialogFeaturesString, const FloatRect& screenAvailableRect)
-    : menuBarVisible(false)
-    , toolBarVisible(false)
-    , locationBarVisible(false)
-    , fullscreen(false)
-    , dialog(true)
+WindowFeatures parseDialogFeatures(const String& dialogFeaturesString, const FloatRect& screenAvailableRect)
 {
-    auto features = parseDialogFeatures(dialogFeaturesString);
-
-    const bool trusted = false;
+    auto featuresMap = parseDialogFeaturesMap(dialogFeaturesString);
 
     // The following features from Microsoft's documentation are not implemented:
     // - default font settings
@@ -169,52 +151,61 @@ WindowFeatures::WindowFeatures(const String& dialogFeaturesString, const FloatRe
     // - help: boolFeature(features, "help", true), makes help icon appear in dialog (what does it do on Windows?)
     // - unadorned: trusted && boolFeature(features, "unadorned");
 
-    width = floatFeature(features, "dialogwidth", 100, screenAvailableRect.width(), 620); // default here came from frame size of dialog in MacIE
-    height = floatFeature(features, "dialogheight", 100, screenAvailableRect.height(), 450); // default here came from frame size of dialog in MacIE
+    WindowFeatures features;
+
+    features.menuBarVisible = false;
+    features.toolBarVisible = false;
+    features.locationBarVisible = false;
+    features.dialog = true;
 
-    auto dialogLeft = floatFeature(features, "dialogleft", screenAvailableRect.x(), screenAvailableRect.maxX() - *width, -1);
-    if (dialogLeft > 0)
-        x = dialogLeft;
+    float width = floatFeature(featuresMap, "dialogwidth", 100, screenAvailableRect.width()).valueOr(620); // default here came from frame size of dialog in MacIE
+    float height = floatFeature(featuresMap, "dialogheight", 100, screenAvailableRect.height()).valueOr(450); // default here came from frame size of dialog in MacIE
 
-    auto dialogTop = floatFeature(features, "dialogtop", screenAvailableRect.y(), screenAvailableRect.maxY() - *height, -1);
-    if (dialogTop > 0)
-        y = dialogTop;
+    features.width = width;
+    features.height = height;
 
-    if (boolFeature(features, "center", true)) {
-        if (!x)
-            x = screenAvailableRect.x() + (screenAvailableRect.width() - *width) / 2;
+    features.x = floatFeature(featuresMap, "dialogleft", screenAvailableRect.x(), screenAvailableRect.maxX() - width);
+    features.y = floatFeature(featuresMap, "dialogtop", screenAvailableRect.y(), screenAvailableRect.maxY() - height);
 
-        if (!y)
-            y = screenAvailableRect.y() + (screenAvailableRect.height() - *height) / 2;
+    if (boolFeature(featuresMap, "center").valueOr(true)) {
+        if (!features.x)
+            features.x = screenAvailableRect.x() + (screenAvailableRect.width() - width) / 2;
+        if (!features.y)
+            features.y = screenAvailableRect.y() + (screenAvailableRect.height() - height) / 2;
     }
 
-    resizable = boolFeature(features, "resizable");
-    scrollbarsVisible = boolFeature(features, "scroll", true);
-    statusBarVisible = boolFeature(features, "status", !trusted);
+    features.resizable = boolFeature(featuresMap, "resizable").valueOr(false);
+    features.scrollbarsVisible = boolFeature(featuresMap, "scroll").valueOr(true);
+    features.statusBarVisible = boolFeature(featuresMap, "status").valueOr(false);
+
+    return features;
 }
 
-bool WindowFeatures::boolFeature(const HashMap<String, String>& features, const char* key, bool defaultValue)
+static Optional<bool> boolFeature(const DialogFeaturesMap& features, const char* key)
 {
     auto it = features.find(key);
     if (it == features.end())
-        return defaultValue;
+        return Nullopt;
 
-    const String& value = it->value;
-    return value.isNull() || value == "1" || value == "yes" || value == "on";
+    auto& value = it->value;
+    return value.isNull()
+        || value == "1"
+        || equalLettersIgnoringASCIICase(value, "yes")
+        || equalLettersIgnoringASCIICase(value, "on");
 }
 
-float WindowFeatures::floatFeature(const HashMap<String, String>& features, const char* key, float min, float max, float defaultValue)
+static Optional<float> floatFeature(const DialogFeaturesMap& features, const char* key, float min, float max)
 {
     auto it = features.find(key);
     if (it == features.end())
-        return defaultValue;
+        return Nullopt;
 
     // FIXME: The toDouble function does not offer a way to tell "0q" from string with no digits in it: Both
     // return the number 0 and false for ok. But "0q" should yield the minimum rather than the default.
     bool ok;
     double parsedNumber = it->value.toDouble(&ok);
     if ((!parsedNumber && !ok) || std::isnan(parsedNumber))
-        return defaultValue;
+        return Nullopt;
     if (parsedNumber < min || max <= min)
         return min;
     if (parsedNumber > max)
@@ -224,9 +215,12 @@ float WindowFeatures::floatFeature(const HashMap<String, String>& features, cons
     return static_cast<int>(parsedNumber);
 }
 
-HashMap<String, String> WindowFeatures::parseDialogFeatures(const String& string)
+static DialogFeaturesMap parseDialogFeaturesMap(const String& string)
 {
-    HashMap<String, String> features;
+    // FIXME: Not clear why we take such a different approach to parsing dialog features
+    // as opposed to window features (using a map, different parsing quirks).
+
+    DialogFeaturesMap features;
 
     Vector<String> vector;
     string.split(';', vector);
@@ -239,12 +233,12 @@ HashMap<String, String> WindowFeatures::parseDialogFeatures(const String& string
         if (separatorPosition == notFound)
             separatorPosition = colonPosition;
 
-        String key = featureString.left(separatorPosition).stripWhiteSpace().lower();
+        String key = featureString.left(separatorPosition).stripWhiteSpace();
 
         // Null string for value indicates key without value.
         String value;
         if (separatorPosition != notFound) {
-            value = featureString.substring(separatorPosition + 1).stripWhiteSpace().lower();
+            value = featureString.substring(separatorPosition + 1).stripWhiteSpace();
             value = value.left(value.find(' '));
         }
 
index 87f6a8b..0cb6d9f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003, 2007, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2007, 2010, 2016 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #ifndef WindowFeatures_h
 #define WindowFeatures_h
 
-#include <wtf/Forward.h>
-#include <wtf/HashMap.h>
+#include <functional>
 #include <wtf/Optional.h>
 #include <wtf/Vector.h>
-#include <wtf/text/StringHash.h>
+#include <wtf/text/WTFString.h>
 
 namespace WebCore {
 
 class FloatRect;
 
 struct WindowFeatures {
-    WindowFeatures()
-        : menuBarVisible(true)
-        , statusBarVisible(true)
-        , toolBarVisible(true)
-        , locationBarVisible(true)
-        , scrollbarsVisible(true)
-        , resizable(true)
-        , fullscreen(false)
-        , dialog(false)
-    {
-    }
-    explicit WindowFeatures(const String& windowFeaturesString);
-    WindowFeatures(const String& dialogFeaturesString, const FloatRect& screenAvailableRect);
-
     Optional<float> x;
     Optional<float> y;
     Optional<float> width;
     Optional<float> height;
 
-    bool menuBarVisible;
-    bool statusBarVisible;
-    bool toolBarVisible;
-    bool locationBarVisible;
-    bool scrollbarsVisible;
-    bool resizable;
+    bool menuBarVisible { true };
+    bool statusBarVisible { true };
+    bool toolBarVisible { true };
+    bool locationBarVisible { true };
+    bool scrollbarsVisible { true };
+    bool resizable { true };
 
-    bool fullscreen;
-    bool dialog;
+    bool fullscreen { false };
+    bool dialog { false };
 
     Vector<String> additionalFeatures;
-
-private:
-    static HashMap<String, String> parseDialogFeatures(const String&);
-    static bool boolFeature(const HashMap<String, String>&, const char* key, bool defaultValue = false);
-    static float floatFeature(const HashMap<String, String>&, const char* key, float min, float max, float defaultValue);
-    void setWindowFeature(const String& keyString, const String& valueString);
 };
 
+WindowFeatures parseWindowFeatures(StringView windowFeaturesString);
+WindowFeatures parseDialogFeatures(const String& dialogFeaturesString, const FloatRect& screenAvailableRect);
+
+void processFeaturesString(StringView features, std::function<void(StringView type, StringView value)> callback);
+
 } // namespace WebCore
 
 #endif // WindowFeatures_h
index ef3473b..e5f73b2 100644 (file)
@@ -126,10 +126,10 @@ void SchemeRegistry::registerURLSchemeAsLocal(const String& scheme)
 
 void SchemeRegistry::removeURLSchemeRegisteredAsLocal(const String& scheme)
 {
-    if (scheme == "file")
+    if (equalLettersIgnoringASCIICase(scheme, "file"))
         return;
 #if PLATFORM(COCOA)
-    if (scheme == "applewebdata")
+    if (equalLettersIgnoringASCIICase(scheme, "applewebdata"))
         return;
 #endif
     localURLSchemes().remove(scheme);
index 33642b0..7c8ee95 100644 (file)
 #include "config.h"
 #include "MIMETypeRegistry.h"
 
-#include "NotImplemented.h"
-#include <wtf/Assertions.h>
-#include <wtf/MainThread.h>
-
 namespace WebCore {
 
 struct ExtensionMap {
@@ -74,21 +70,14 @@ static const ExtensionMap extensionMap[] = {
     { "xhtml", "application/xhtml+xml" },
     { "wml", "text/vnd.wap.wml" },
     { "wmlc", "application/vnd.wap.wmlc" },
-    { 0, 0 }
 };
 
-String MIMETypeRegistry::getMIMETypeForExtension(const String &ext)
+String MIMETypeRegistry::getMIMETypeForExtension(const String& extension)
 {
-    ASSERT(isMainThread());
-
-    String s = ext.lower();
-    const ExtensionMap *e = extensionMap;
-    while (e->extension) {
-        if (s == e->extension)
-            return e->mimeType;
-        ++e;
+    for (auto& entry : extensionMap) {
+        if (equalIgnoringASCIICase(extension, entry.extension))
+            return entry.mimeType;
     }
-
     return String();
 }
 
index ab82e48..8ddfb2b 100644 (file)
@@ -324,10 +324,10 @@ bool MediaPlayer::load(const URL& url, const ContentType& contentType, const Str
 {
     ASSERT(!m_reloadTimer.isActive());
 
-    m_contentMIMEType = contentType.type().lower();
+    m_contentMIMEType = contentType.type().convertToASCIILowercase();
     m_contentTypeCodecs = contentType.parameter(codecs());
     m_url = url;
-    m_keySystem = keySystem.lower();
+    m_keySystem = keySystem.convertToASCIILowercase();
     m_contentMIMETypeWasInferredFromExtension = false;
 
 #if ENABLE(MEDIA_SOURCE)
@@ -366,7 +366,7 @@ bool MediaPlayer::load(const URL& url, const ContentType& contentType, MediaSour
     ASSERT(mediaSource);
 
     m_mediaSource = mediaSource;
-    m_contentMIMEType = contentType.type().lower();
+    m_contentMIMEType = contentType.type().convertToASCIILowercase();
     m_contentTypeCodecs = contentType.parameter(codecs());
     m_url = url;
     m_keySystem = "";
@@ -517,17 +517,17 @@ void MediaPlayer::setShouldBufferData(bool shouldBuffer)
 #if ENABLE(ENCRYPTED_MEDIA)
 MediaPlayer::MediaKeyException MediaPlayer::generateKeyRequest(const String& keySystem, const unsigned char* initData, unsigned initDataLength)
 {
-    return m_private->generateKeyRequest(keySystem.lower(), initData, initDataLength);
+    return m_private->generateKeyRequest(keySystem.convertToASCIILowercase(), initData, initDataLength);
 }
 
 MediaPlayer::MediaKeyException MediaPlayer::addKey(const String& keySystem, const unsigned char* key, unsigned keyLength, const unsigned char* initData, unsigned initDataLength, const String& sessionId)
 {
-    return m_private->addKey(keySystem.lower(), key, keyLength, initData, initDataLength, sessionId);
+    return m_private->addKey(keySystem.convertToASCIILowercase(), key, keyLength, initData, initDataLength, sessionId);
 }
 
 MediaPlayer::MediaKeyException MediaPlayer::cancelKeyRequest(const String& keySystem, const String& sessionId)
 {
-    return m_private->cancelKeyRequest(keySystem.lower(), sessionId);
+    return m_private->cancelKeyRequest(keySystem.convertToASCIILowercase(), sessionId);
 }
 #endif
 
index 4c2cd98..dba8571 100644 (file)
@@ -65,7 +65,7 @@ Extensions3DOpenGLCommon::Extensions3DOpenGLCommon(GraphicsContext3D* context)
     m_renderer = String(reinterpret_cast<const char*>(::glGetString(GL_RENDERER)));
 
     Vector<String> vendorComponents;
-    m_vendor.lower().split(' ', vendorComponents);
+    m_vendor.convertToASCIILowercase().split(' ', vendorComponents);
     if (vendorComponents.contains("nvidia"))
         m_isNVIDIA = true;
     if (vendorComponents.contains("ati") || vendorComponents.contains("amd"))
index 0d9c188..9a41da3 100644 (file)
@@ -28,9 +28,6 @@
 #include "config.h"
 #include "MIMETypeRegistry.h"
 
-#include <wtf/Assertions.h>
-#include <wtf/MainThread.h>
-
 namespace WebCore {
 
 struct ExtensionMap {
@@ -61,21 +58,14 @@ static const ExtensionMap extensionMap [] = {
     { "xhtml", "application/xhtml+xml" },
     { "wml", "text/vnd.wap.wml" },
     { "wmlc", "application/vnd.wap.wmlc" },
-    { 0, 0 }
 };
 
-String MIMETypeRegistry::getMIMETypeForExtension(const String &ext)
+String MIMETypeRegistry::getMIMETypeForExtension(const String& extension)
 {
-    ASSERT(isMainThread());
-
-    String s = ext.lower();
-    const ExtensionMap *e = extensionMap;
-    while (e->extension) {
-        if (s == e->extension)
-            return e->mimeType;
-        ++e;
+    for (auto& entry : extensionMap) {
+        if (equalIgnoringASCIICase(extension, entry.extension))
+            return entry.mimeType;
     }
-
     return String();
 }
 
index 2ed51c6..c013246 100644 (file)
@@ -417,34 +417,32 @@ bool Pasteboard::hasData()
 static String cocoaTypeFromHTMLClipboardType(const String& type)
 {
     // http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html#dom-datatransfer-setdata
-    String qType = type.lower();
-
-    if (qType == "text")
-        qType = ASCIILiteral("text/plain");
-    if (qType == "url")
-        qType = ASCIILiteral("text/uri-list");
-
-    // Ignore any trailing charset - JS strings are Unicode, which encapsulates the charset issue
-    if (qType == "text/plain" || qType.startsWith("text/plain;"))
-        return String(NSStringPboardType);
-    if (qType == "text/uri-list")
-        // special case because UTI doesn't work with Cocoa's URL type
-        return String(NSURLPboardType); // note special case in getData to read NSFilenamesType
-
-    // Blacklist types that might contain subframe information
-    if (qType == "text/rtf" || qType == "public.rtf" || qType == "com.apple.traditional-mac-plain-text")
+    String lowercasedType = type.convertToASCIILowercase();
+
+    if (lowercasedType == "text")
+        lowercasedType = ASCIILiteral("text/plain");
+    if (lowercasedType == "url")
+        lowercasedType = ASCIILiteral("text/uri-list");
+
+    // Ignore any trailing charset - strings are already UTF-16, and the charset issue has already been dealt with.
+    if (lowercasedType == "text/plain" || lowercasedType.startsWith("text/plain;"))
+        return NSStringPboardType;
+    if (lowercasedType == "text/uri-list") {
+        // Special case because UTI doesn't work with Cocoa's URL type.
+        return NSURLPboardType;
+    }
+
+    // Blacklist types that might contain subframe information.
+    if (lowercasedType == "text/rtf" || lowercasedType == "public.rtf" || lowercasedType == "com.apple.traditional-mac-plain-text")
         return String();
 
-    // Try UTI now
-    String mimeType = qType;
-    if (RetainPtr<CFStringRef> utiType = adoptCF(UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, mimeType.createCFString().get(), NULL))) {
-        RetainPtr<CFStringRef> pbType = adoptCF(UTTypeCopyPreferredTagWithClass(utiType.get(), kUTTagClassNSPboardType));
-        if (pbType)
+    if (auto utiType = adoptCF(UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, lowercasedType.createCFString().get(), NULL))) {
+        if (auto pbType = adoptCF(UTTypeCopyPreferredTagWithClass(utiType.get(), kUTTagClassNSPboardType)))
             return pbType.get();
     }
 
     // No mapping, just pass the whole string though
-    return qType;
+    return lowercasedType;
 }
 
 void Pasteboard::clear(const String& type)