Commit 5d1c0e78 authored by hyatt@apple.com's avatar hyatt@apple.com

https://bugs.webkit.org/show_bug.cgi?id=29892

Add support for whitelist patterns to control conditional injection of user scripts and
user stylesheets.

Reviewed by Jon Honeycutt.

No new tests. Not testable until WebKit portion is added in followup patch.

* GNUmakefile.am:
* WebCore.gypi:
* WebCore.pro:
* WebCore.vcproj/WebCore.vcproj:
* WebCore.xcodeproj/project.pbxproj:
* dom/Document.cpp:
(WebCore::Document::pageGroupUserSheets):
* page/Frame.cpp:
(WebCore::Frame::injectUserScriptsForWorld):
* page/UserContentURLPattern.cpp: Added.
(WebCore::UserContentURLPattern::matchesPatterns):
(WebCore::UserContentURLPattern::parse):
(WebCore::UserContentURLPattern::matches):
(WebCore::UserContentURLPattern::matchesHost):
(WebCore::MatchTester::MatchTester):
(WebCore::MatchTester::testStringFinished):
(WebCore::MatchTester::patternStringFinished):
(WebCore::MatchTester::eatWildcard):
(WebCore::MatchTester::eatSameChars):
(WebCore::MatchTester::test):
(WebCore::UserContentURLPattern::matchesPath):
* page/UserContentURLPattern.h: Added.
(WebCore::UserContentURLPattern::UserContentURLPattern):
(WebCore::UserContentURLPattern::scheme):
(WebCore::UserContentURLPattern::host):
(WebCore::UserContentURLPattern::path):
(WebCore::UserContentURLPattern::matchSubdomains):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@48912 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 59ac2d39
2009-09-29 Dave Hyatt <hyatt@apple.com>
Reviewed by Jon Honeycutt.
https://bugs.webkit.org/show_bug.cgi?id=29892
Add support for whitelist patterns to control conditional injection of user scripts and
user stylesheets.
No new tests. Not testable until WebKit portion is added in followup patch.
* GNUmakefile.am:
* WebCore.gypi:
* WebCore.pro:
* WebCore.vcproj/WebCore.vcproj:
* WebCore.xcodeproj/project.pbxproj:
* dom/Document.cpp:
(WebCore::Document::pageGroupUserSheets):
* page/Frame.cpp:
(WebCore::Frame::injectUserScriptsForWorld):
* page/UserContentURLPattern.cpp: Added.
(WebCore::UserContentURLPattern::matchesPatterns):
(WebCore::UserContentURLPattern::parse):
(WebCore::UserContentURLPattern::matches):
(WebCore::UserContentURLPattern::matchesHost):
(WebCore::MatchTester::MatchTester):
(WebCore::MatchTester::testStringFinished):
(WebCore::MatchTester::patternStringFinished):
(WebCore::MatchTester::eatWildcard):
(WebCore::MatchTester::eatSameChars):
(WebCore::MatchTester::test):
(WebCore::UserContentURLPattern::matchesPath):
* page/UserContentURLPattern.h: Added.
(WebCore::UserContentURLPattern::UserContentURLPattern):
(WebCore::UserContentURLPattern::scheme):
(WebCore::UserContentURLPattern::host):
(WebCore::UserContentURLPattern::path):
(WebCore::UserContentURLPattern::matchSubdomains):
2009-09-29 Enrica Casucci <enrica@apple.com>
Reviewed by Adele Peterson.
......@@ -1349,6 +1349,8 @@ webcore_sources += \
WebCore/page/SecurityOriginHash.h \
WebCore/page/Settings.cpp \
WebCore/page/Settings.h \
WebCore/page/UserContentURLPattern.cpp \
WebCore/page/UserContentURLPattern.h \
WebCore/page/UserScript.h \
WebCore/page/UserScriptTypes.h \
WebCore/page/UserStyleSheet.h \
......
......@@ -1769,6 +1769,8 @@
'page/SecurityOriginHash.h',
'page/Settings.cpp',
'page/Settings.h',
'page/UserContentURLPattern.cpp',
'page/UserContentURLPattern.h',
'page/UserScript.h',
'page/UserScriptTypes.h',
'page/UserStyleSheet.h',
......
......@@ -1147,6 +1147,7 @@ SOURCES += \
page/SecurityOrigin.cpp \
page/Screen.cpp \
page/Settings.cpp \
page/UserContentURLPattern.cpp \
page/WindowFeatures.cpp \
page/XSSAuditor.cpp \
plugins/PluginData.cpp \
......
......@@ -17076,6 +17076,14 @@
RelativePath="..\page\Settings.h"
>
</File>
<File
RelativePath="..\page\UserContentURLPattern.cpp"
>
</File>
<File
RelativePath="..\page\UserContentURLPattern.h"
>
</File>
<File
RelativePath="..\page\UserScript.h"
>
......
......@@ -4307,6 +4307,8 @@
BCA846D70DC67A350026C309 /* RenderReplica.h in Headers */ = {isa = PBXBuildFile; fileRef = BCA846D50DC67A350026C309 /* RenderReplica.h */; };
BCA85A100C3AEAF4006F8308 /* DOMSVGNumberInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = BCA85A0F0C3AEAF4006F8308 /* DOMSVGNumberInternal.h */; };
BCAA90C30A7EBA60008B1229 /* Scrollbar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCAA90C20A7EBA60008B1229 /* Scrollbar.cpp */; };
BCACF3BC1072921A00C0C8A3 /* UserContentURLPattern.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCACF3BA1072921A00C0C8A3 /* UserContentURLPattern.cpp */; };
BCACF3BD1072921A00C0C8A3 /* UserContentURLPattern.h in Headers */ = {isa = PBXBuildFile; fileRef = BCACF3BB1072921A00C0C8A3 /* UserContentURLPattern.h */; };
BCAEFCAE1016CE4A0040D34E /* DOMRGBColor.mm in Sources */ = {isa = PBXBuildFile; fileRef = BCAEFCAD1016CE4A0040D34E /* DOMRGBColor.mm */; };
BCB16C170979C3BD00467741 /* Cache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCB16BFE0979C3BD00467741 /* Cache.cpp */; };
BCB16C180979C3BD00467741 /* Cache.h in Headers */ = {isa = PBXBuildFile; fileRef = BCB16BFF0979C3BD00467741 /* Cache.h */; settings = {ATTRIBUTES = (Private, ); }; };
......@@ -9394,6 +9396,8 @@
BCA846D50DC67A350026C309 /* RenderReplica.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderReplica.h; sourceTree = "<group>"; };
BCA85A0F0C3AEAF4006F8308 /* DOMSVGNumberInternal.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DOMSVGNumberInternal.h; sourceTree = "<group>"; };
BCAA90C20A7EBA60008B1229 /* Scrollbar.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Scrollbar.cpp; path = platform/Scrollbar.cpp; sourceTree = SOURCE_ROOT; };
BCACF3BA1072921A00C0C8A3 /* UserContentURLPattern.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UserContentURLPattern.cpp; sourceTree = "<group>"; };
BCACF3BB1072921A00C0C8A3 /* UserContentURLPattern.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UserContentURLPattern.h; sourceTree = "<group>"; };
BCAEFCAD1016CE4A0040D34E /* DOMRGBColor.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DOMRGBColor.mm; sourceTree = "<group>"; };
BCB16BFE0979C3BD00467741 /* Cache.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Cache.cpp; sourceTree = "<group>"; };
BCB16BFF0979C3BD00467741 /* Cache.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Cache.h; sourceTree = "<group>"; };
......@@ -11098,6 +11102,8 @@
BCD0E0F90E972C3500265DEA /* SecurityOriginHash.h */,
14C9A5E90B3D105F005A0232 /* Settings.cpp */,
F587863A02DE3A1401EA4122 /* Settings.h */,
BCACF3BA1072921A00C0C8A3 /* UserContentURLPattern.cpp */,
BCACF3BB1072921A00C0C8A3 /* UserContentURLPattern.h */,
BCA2B0601050475F0043BD1C /* UserScript.h */,
BCA2B08A10505BCD0043BD1C /* UserScriptTypes.h */,
BC8BF150105813BF00A40A07 /* UserStyleSheet.h */,
......@@ -17904,6 +17910,7 @@
7693BAD2106C2DCA007B0823 /* HaltablePlugin.h in Headers */,
7693BAD4106C2DCA007B0823 /* PluginHalter.h in Headers */,
7693BAD5106C2DCA007B0823 /* PluginHalterClient.h in Headers */,
BCACF3BD1072921A00C0C8A3 /* UserContentURLPattern.h in Headers */,
5DB1BC6A10715A6400EFAA49 /* TransformSource.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
......@@ -20018,6 +20025,7 @@
BCCE58AF1061E90C008FB35A /* JSDocumentFragmentCustom.cpp in Sources */,
14CD8D82106B529000A46D23 /* JSSharedWorkerCustom.cpp in Sources */,
7693BAD3106C2DCA007B0823 /* PluginHalter.cpp in Sources */,
BCACF3BC1072921A00C0C8A3 /* UserContentURLPattern.cpp in Sources */,
5DB1BC6B10715A6400EFAA49 /* TransformSourceLibxslt.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
......@@ -119,6 +119,7 @@
#include "TransformSource.h"
#include "TreeWalker.h"
#include "UIEvent.h"
#include "UserContentURLPattern.h"
#include "WebKitAnimationEvent.h"
#include "WebKitTransitionEvent.h"
#include "WheelEvent.h"
......@@ -1968,6 +1969,8 @@ const Vector<RefPtr<CSSStyleSheet> >* Document::pageGroupUserSheets() const
const UserStyleSheetVector* sheets = it->second;
for (unsigned i = 0; i < sheets->size(); ++i) {
const UserStyleSheet* sheet = sheets->at(i).get();
if (!UserContentURLPattern::matchesPatterns(url(), sheet->patterns()))
continue;
RefPtr<CSSStyleSheet> parsedSheet = CSSStyleSheet::create(const_cast<Document*>(this), sheet->url());
parsedSheet->setIsUserStyleSheet(true);
parsedSheet->parseString(sheet->source(), !inCompatMode());
......
......@@ -73,6 +73,7 @@
#include "Settings.h"
#include "TextIterator.h"
#include "TextResourceDecoder.h"
#include "UserContentURLPattern.h"
#include "XMLNames.h"
#include "htmlediting.h"
#include "markup.h"
......@@ -870,12 +871,16 @@ void Frame::injectUserScriptsForWorld(unsigned worldID, const UserScriptVector&
if (userScripts.isEmpty())
return;
Document* doc = document();
if (!doc)
return;
// FIXME: Need to implement pattern checking.
Vector<ScriptSourceCode> sourceCode;
unsigned count = userScripts.size();
for (unsigned i = 0; i < count; ++i) {
UserScript* script = userScripts[i].get();
if (script->injectionTime() == injectionTime)
if (script->injectionTime() == injectionTime && UserContentURLPattern::matchesPatterns(doc->url(), script->patterns()))
sourceCode.append(ScriptSourceCode(script->source(), script->url()));
}
script()->evaluateInIsolatedWorld(worldID, sourceCode);
......
/*
* Copyright (C) 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "UserContentURLPattern.h"
#include "KURL.h"
#include <wtf/StdLibExtras.h>
namespace WebCore {
bool UserContentURLPattern::matchesPatterns(const KURL& url, const Vector<String>& patterns)
{
// Treat no patterns at all as though a pattern of * was specified.
if (patterns.isEmpty())
return true;
for (unsigned i = 0; i < patterns.size(); ++i) {
UserContentURLPattern contentPattern(patterns[i]);
if (contentPattern.matches(url))
return true;
}
return false;
}
bool UserContentURLPattern::parse(const String& pattern)
{
DEFINE_STATIC_LOCAL(const String, schemeSeparator, ("://"));
int schemeEndPos = pattern.find(schemeSeparator);
if (schemeEndPos == -1)
return false;
m_scheme = pattern.left(schemeEndPos);
int hostStartPos = schemeEndPos + schemeSeparator.length();
if (hostStartPos >= static_cast<int>(pattern.length()))
return false;
int pathStartPos = 0;
if (m_scheme == "file")
pathStartPos = hostStartPos;
else {
int hostEndPos = pattern.find("/", hostStartPos);
if (hostEndPos == -1)
return false;
m_host = pattern.substring(hostStartPos, hostEndPos - hostStartPos);
// The first component can be '*', which means to match all subdomains.
Vector<String> hostComponents;
m_host.split(".", hostComponents);
if (hostComponents[0] == "*") {
m_matchSubdomains = true;
m_host = "";
for (unsigned i = 1; i < hostComponents.size(); ++i) {
m_host = m_host + hostComponents[i];
if (i < hostComponents.size() - 1)
m_host = m_host + ".";
}
}
// No other '*' can occur in the host.
if (m_host.find("*") != -1)
return false;
pathStartPos = hostEndPos;
}
m_path = pattern.right(pathStartPos);
return true;
}
bool UserContentURLPattern::matches(const KURL& test) const
{
if (m_invalid)
return false;
if (test.protocol() != m_scheme)
return false;
if (!matchesHost(test))
return false;
return matchesPath(test);
}
bool UserContentURLPattern::matchesHost(const KURL& test) const
{
if (test.host() == m_host)
return true;
if (!m_matchSubdomains)
return false;
// If we're matching subdomains, and we have no host, that means the pattern
// was <scheme>://*/<whatever>, so we match anything.
if (!m_host.length())
return true;
// Check if the test host is a subdomain of our host.
return test.host().endsWith(m_host, false);
}
struct MatchTester
{
const String& m_pattern;
unsigned m_patternIndex;
const String& m_test;
unsigned m_testIndex;
MatchTester(const String& pattern, const String& test)
: m_pattern(pattern)
, m_patternIndex(0)
, m_test(test)
, m_testIndex(0)
{
}
bool testStringFinished() const { return m_testIndex >= m_test.length(); }
bool patternStringFinished() const { return m_patternIndex >= m_pattern.length(); }
void eatWildcard()
{
while (!patternStringFinished()) {
if (m_pattern[m_patternIndex] != '*')
return;
m_patternIndex++;
}
}
void eatSameChars()
{
while (!patternStringFinished() && !testStringFinished()) {
if (m_pattern[m_patternIndex] == '*')
return;
if (m_pattern[m_patternIndex] != m_test[m_testIndex])
return;
m_patternIndex++;
m_testIndex++;
}
}
bool test()
{
// Eat all the matching chars.
eatSameChars();
// If the string is finished, then the pattern must be empty too, or contains
// only wildcards.
if (testStringFinished()) {
eatWildcard();
if (patternStringFinished())
return true;
return false;
}
// Pattern is empty but not string, this is not a match.
if (patternStringFinished())
return false;
// If we don't encounter a *, then we're hosed.
if (m_pattern[m_patternIndex] != '*')
return false;
while (!testStringFinished()) {
MatchTester nextMatch(*this);
nextMatch.m_patternIndex++;
if (nextMatch.test())
return true;
m_testIndex++;
}
// We reached the end of the string. Let's see if the pattern contains only
// wildcards.
eatWildcard();
return patternStringFinished();
}
};
bool UserContentURLPattern::matchesPath(const KURL& test) const
{
MatchTester match(m_path, test.path());
return match.test();
}
} // namespace WebCore
/*
* Copyright (C) 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef UserContentURLPattern_h
#define UserContentURLPattern_h
#include "PlatformString.h"
#include <wtf/Vector.h>
namespace WebCore {
class KURL;
class UserContentURLPattern {
public:
UserContentURLPattern(const String& pattern)
: m_matchSubdomains(false)
{
m_invalid = !parse(pattern);
}
bool matches(const KURL&) const;
const String& scheme() const { return m_scheme; }
const String& host() const { return m_host; }
const String& path() const { return m_path; }
bool matchSubdomains() const { return m_matchSubdomains; }
static bool matchesPatterns(const KURL&, const Vector<String>&);
private:
bool parse(const String& pattern);
bool matchesHost(const KURL&) const;
bool matchesPath(const KURL&) const;
bool m_invalid;
String m_scheme;
String m_host;
String m_path;
bool m_matchSubdomains;
};
} // namespace WebCore
#endif // UserContentURLPattern_h
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment