Commit 71960d78 authored by hyatt@apple.com's avatar hyatt@apple.com

WebCore: https://bugs.webkit.org/show_bug.cgi?id=28890, make simple user script injection work.

        
Reviewed by Adam Roben.

This patch adds new API for adding and removing user scripts from page groups.  User scripts
are bundled together in isolated worlds (you can have multiple scripts together in the same
world).

Added userscripts/ directory for holding new tests (along with a simple test of script injection).

* WebCore.base.exp:
* WebCore.vcproj/WebCore.vcproj:
* WebCore.xcodeproj/project.pbxproj:
* bindings/js/ScriptController.cpp:
(WebCore::ScriptController::evaluateInIsolatedWorld):
* bindings/js/ScriptController.h:
* bindings/v8/ScriptController.cpp:
(WebCore::ScriptController::evaluateInIsolatedWorld):
* bindings/v8/ScriptController.h:
* loader/FrameLoader.cpp:
(WebCore::FrameLoader::finishedParsing):
(WebCore::FrameLoader::dispatchDocumentElementAvailable):
* page/Frame.cpp:
(WebCore::Frame::injectUserScripts):
(WebCore::Frame::injectUserScriptsForWorld):
* page/Frame.h:
* page/PageGroup.cpp:
(WebCore::PageGroup::~PageGroup):
(WebCore::PageGroup::addUserScript):
(WebCore::PageGroup::removeUserContentForWorld):
(WebCore::PageGroup::removeAllUserContent):
* page/PageGroup.h:
(WebCore::PageGroup::userScripts):
* page/UserScript.h: Added.
(WebCore::UserScript::UserScript):
(WebCore::UserScript::source):
(WebCore::UserScript::url):
(WebCore::UserScript::patterns):
(WebCore::UserScript::worldID):
(WebCore::UserScript::injectionTime):
* page/UserScriptTypes.h: Added.
(WebCore::):

WebKit/mac: https://bugs.webkit.org/show_bug.cgi?id=28890, make simple user script injection work.
        
Reviewed by Adam Roben.

This patch adds new API for adding and removing user scripts from page groups.  User scripts
are bundled together in isolated worlds (you can have multiple scripts together in the same
world).

Added userscripts/ directory for holding new tests (along with a simple test of script injection).

* WebView/WebView.mm:
(+[WebView _addUserScriptToGroup:source:url:worldID:patterns:injectionTime:]):
(+[WebView _removeUserContentFromGroup:worldID:]):
(+[WebView _removeAllUserContentFromGroup:]):
* WebView/WebViewPrivate.h:

LayoutTests: https://bugs.webkit.org/show_bug.cgi?id=28890, make simple user script injection work.
        
Reviewed by Adam Roben.

This patch adds new API for adding and removing user scripts from page groups.  User scripts
are bundled together in isolated worlds (you can have multiple scripts together in the same
world).

Added userscripts/ directory for holding new tests (along with a simple test of script injection).

* platform/mac/userscripts: Added.
* platform/mac/userscripts/script-run-at-end-expected.txt: Added.
* userscripts: Added.
* userscripts/script-run-at-end.html: Added.



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@48057 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 96360249
2009-09-03 Dave Hyatt <hyatt@apple.com>
Reviewed by Adam Roben.
https://bugs.webkit.org/show_bug.cgi?id=28890, make simple user script injection work.
This patch adds new API for adding and removing user scripts from page groups. User scripts
are bundled together in isolated worlds (you can have multiple scripts together in the same
world).
Added userscripts/ directory for holding new tests (along with a simple test of script injection).
* platform/mac/userscripts: Added.
* platform/mac/userscripts/script-run-at-end-expected.txt: Added.
* userscripts: Added.
* userscripts/script-run-at-end.html: Added.
2009-09-04 Alexey Proskuryakov <ap@apple.com>
Reviewed by Eric Seidel.
......
......@@ -5904,3 +5904,6 @@ fast/events/pageshow-pagehide.html
# No TextInputController
fast/forms/input-maxlength-ime-completed.html
fast/forms/input-maxlength-ime-preedit.html
# No User Scripts
userscripts
......@@ -4831,3 +4831,6 @@ http/tests/xmlhttprequest/cross-origin-cookie-storage.html
# https://bugs.webkit.org/show_bug.cgi?id=28952
fast/workers/worker-multi-port.html
fast/workers/worker-context-multi-port.html
# No User Scripts
userscripts
......@@ -653,3 +653,6 @@ http/tests/xmlhttprequest/origin-whitelisting-subdomains.html
# No TextInputController
fast/forms/input-maxlength-ime-completed.html
fast/forms/input-maxlength-ime-preedit.html
# No User Scripts
userscripts
<!DOCTYPE HTML>
<html>
<head>
<script>
if (window.layoutTestController) {
layoutTestController.dumpAsText();
layoutTestController.addUserScript("document.getElementById('target').innerHTML = 'PASS'", false);
}
</script>
</head>
<body>
<div id="target">FAIL</div>
</body>
</html>
2009-09-03 Dave Hyatt <hyatt@apple.com>
Reviewed by Adam Roben.
https://bugs.webkit.org/show_bug.cgi?id=28890, make simple user script injection work.
This patch adds new API for adding and removing user scripts from page groups. User scripts
are bundled together in isolated worlds (you can have multiple scripts together in the same
world).
Added userscripts/ directory for holding new tests (along with a simple test of script injection).
* WebCore.base.exp:
* WebCore.vcproj/WebCore.vcproj:
* WebCore.xcodeproj/project.pbxproj:
* bindings/js/ScriptController.cpp:
(WebCore::ScriptController::evaluateInIsolatedWorld):
* bindings/js/ScriptController.h:
* bindings/v8/ScriptController.cpp:
(WebCore::ScriptController::evaluateInIsolatedWorld):
* bindings/v8/ScriptController.h:
* loader/FrameLoader.cpp:
(WebCore::FrameLoader::finishedParsing):
(WebCore::FrameLoader::dispatchDocumentElementAvailable):
* page/Frame.cpp:
(WebCore::Frame::injectUserScripts):
(WebCore::Frame::injectUserScriptsForWorld):
* page/Frame.h:
* page/PageGroup.cpp:
(WebCore::PageGroup::~PageGroup):
(WebCore::PageGroup::addUserScript):
(WebCore::PageGroup::removeUserContentForWorld):
(WebCore::PageGroup::removeAllUserContent):
* page/PageGroup.h:
(WebCore::PageGroup::userScripts):
* page/UserScript.h: Added.
(WebCore::UserScript::UserScript):
(WebCore::UserScript::source):
(WebCore::UserScript::url):
(WebCore::UserScript::patterns):
(WebCore::UserScript::worldID):
(WebCore::UserScript::injectionTime):
* page/UserScriptTypes.h: Added.
(WebCore::):
2009-09-04 Alexey Proskuryakov <ap@apple.com>
Reviewed by Eric Seidel.
......@@ -1333,6 +1333,8 @@ webcore_sources += \
WebCore/page/SecurityOriginHash.h \
WebCore/page/Settings.cpp \
WebCore/page/Settings.h \
WebCore/page/UserScript.h \
WebCore/page/UserScriptTypes.h \
WebCore/page/WebKitPoint.h \
WebCore/page/WindowFeatures.cpp \
WebCore/page/WindowFeatures.h \
......
......@@ -742,10 +742,14 @@ __ZN7WebCore9HTMLNames9iframeTagE
__ZN7WebCore9HTMLNames9scriptTagE
__ZN7WebCore9PageCache11setCapacityEi
__ZN7WebCore9PageCache27releaseAutoreleasedPagesNowEv
__ZN7WebCore9PageGroup13addUserScriptERKNS_6StringERKNS_4KURLERKN3WTF6VectorIS1_Lm0EEEjNS_23UserScriptInjectionTimeE
__ZN7WebCore9PageGroup14addVisitedLinkEPKtm
__ZN7WebCore9PageGroup20removeAllUserContentEv
__ZN7WebCore9PageGroup17closeLocalStorageEv
__ZN7WebCore9PageGroup21removeAllVisitedLinksEv
__ZN7WebCore9PageGroup25removeUserContentForWorldEj
__ZN7WebCore9PageGroup26setShouldTrackVisitedLinksEb
__ZN7WebCore9PageGroup9pageGroupERKNS_6StringE
__ZN7WebCore9TimerBase4stopEv
__ZN7WebCore9TimerBase5startEdd
__ZN7WebCore9TimerBaseC2Ev
......
......@@ -1696,6 +1696,8 @@
'page/SecurityOriginHash.h',
'page/Settings.cpp',
'page/Settings.h',
'page/UserScript.h',
'page/UserScriptTypes.h',
'page/WebKitPoint.h',
'page/WindowFeatures.cpp',
'page/WindowFeatures.h',
......
......@@ -17116,6 +17116,14 @@
RelativePath="..\page\Settings.h"
>
</File>
<File
RelativePath="..\page\UserScript.h"
>
</File>
<File
RelativePath="..\page\UserScriptTypes.h"
>
</File>
<File
RelativePath="..\page\WebKitPoint.h"
>
......
......@@ -4237,6 +4237,8 @@
BC9BC64E0E7C4889008B9849 /* ScrollbarClient.h in Headers */ = {isa = PBXBuildFile; fileRef = BC9BC64D0E7C4889008B9849 /* ScrollbarClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
BCA169A20BFD55B40019CA76 /* JSHTMLTableCaptionElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCA169A00BFD55B40019CA76 /* JSHTMLTableCaptionElement.cpp */; };
BCA169A30BFD55B40019CA76 /* JSHTMLTableCaptionElement.h in Headers */ = {isa = PBXBuildFile; fileRef = BCA169A10BFD55B40019CA76 /* JSHTMLTableCaptionElement.h */; };
BCA2B061105047600043BD1C /* UserScript.h in Headers */ = {isa = PBXBuildFile; fileRef = BCA2B0601050475F0043BD1C /* UserScript.h */; settings = {ATTRIBUTES = (Private, ); }; };
BCA2B08B10505BCD0043BD1C /* UserScriptTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = BCA2B08A10505BCD0043BD1C /* UserScriptTypes.h */; settings = {ATTRIBUTES = (Private, ); }; };
BCA83E4F0D7CE1E9003421A8 /* JSClipboard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCA83E4D0D7CE1E9003421A8 /* JSClipboard.cpp */; };
BCA83E500D7CE1E9003421A8 /* JSClipboard.h in Headers */ = {isa = PBXBuildFile; fileRef = BCA83E4E0D7CE1E9003421A8 /* JSClipboard.h */; };
BCA83E520D7CE205003421A8 /* JSClipboardCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCA83E510D7CE205003421A8 /* JSClipboardCustom.cpp */; };
......@@ -9247,6 +9249,8 @@
BC9BC64D0E7C4889008B9849 /* ScrollbarClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScrollbarClient.h; sourceTree = "<group>"; };
BCA169A00BFD55B40019CA76 /* JSHTMLTableCaptionElement.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = JSHTMLTableCaptionElement.cpp; sourceTree = "<group>"; };
BCA169A10BFD55B40019CA76 /* JSHTMLTableCaptionElement.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = JSHTMLTableCaptionElement.h; sourceTree = "<group>"; };
BCA2B0601050475F0043BD1C /* UserScript.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UserScript.h; sourceTree = "<group>"; };
BCA2B08A10505BCD0043BD1C /* UserScriptTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UserScriptTypes.h; sourceTree = "<group>"; };
BCA378BA0D15F64200B793D6 /* ScheduledAction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScheduledAction.cpp; sourceTree = "<group>"; };
BCA378BB0D15F64200B793D6 /* ScheduledAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScheduledAction.h; sourceTree = "<group>"; };
BCA83E360D7CDC4E003421A8 /* Clipboard.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Clipboard.idl; sourceTree = "<group>"; };
......@@ -10897,6 +10901,8 @@
BCD0E0F90E972C3500265DEA /* SecurityOriginHash.h */,
14C9A5E90B3D105F005A0232 /* Settings.cpp */,
F587863A02DE3A1401EA4122 /* Settings.h */,
BCA2B0601050475F0043BD1C /* UserScript.h */,
BCA2B08A10505BCD0043BD1C /* UserScriptTypes.h */,
494BD7930F55C8EE00747828 /* WebKitPoint.h */,
494BD7940F55C8EE00747828 /* WebKitPoint.idl */,
BC8243E60D0CFD7500460C8F /* WindowFeatures.cpp */,
......@@ -17579,6 +17585,8 @@
49C7B9E31042D32F0009D447 /* CanvasShader.h in Headers */,
49C7B9E61042D32F0009D447 /* CanvasTexture.h in Headers */,
49C7BA001042D38C0009D447 /* Canvas3DLayer.h in Headers */,
BCA2B061105047600043BD1C /* UserScript.h in Headers */,
BCA2B08B10505BCD0043BD1C /* UserScriptTypes.h in Headers */,
E1284BB110449FFA00EAEB52 /* JSPageTransitionEvent.h in Headers */,
E1284BD61044A01E00EAEB52 /* DOMPageTransitionEvent.h in Headers */,
510D4A34103165EE0049EA54 /* SocketStreamErrorBase.h in Headers */,
......@@ -131,6 +131,14 @@ ScriptValue ScriptController::evaluate(const ScriptSourceCode& sourceCode)
return JSValue();
}
void ScriptController::evaluateInIsolatedWorld(unsigned /* worldID */, const Vector<ScriptSourceCode>& sourceCode)
{
// FIXME: Actually support isolated worlds!
unsigned size = sourceCode.size();
for (unsigned i = 0; i < size; ++i)
evaluate(sourceCode[i]);
}
void ScriptController::clearWindowShell()
{
if (!m_windowShell)
......
......@@ -81,6 +81,7 @@ public:
}
ScriptValue evaluate(const ScriptSourceCode&);
void evaluateInIsolatedWorld(unsigned worldID, const Vector<ScriptSourceCode>&);
void setEventHandlerLineNumber(int lineno) { m_handlerLineNumber = lineno; }
int eventHandlerLineNumber() { return m_handlerLineNumber; }
......
......@@ -179,6 +179,12 @@ bool ScriptController::processingUserGesture() const
return false;
}
void ScriptController::evaluateInIsolatedWorld(unsigned worldID, const Vector<ScriptSourceCode>& sources)
{
// FIXME: Get rid of extensionGroup here.
m_proxy->evaluateInNewWorld(sources, 1);
}
void ScriptController::evaluateInNewWorld(const Vector<ScriptSourceCode>& sources, int extensionGroup)
{
m_proxy->evaluateInNewWorld(sources, extensionGroup);
......
......@@ -64,10 +64,13 @@ namespace WebCore {
// as a string.
ScriptValue evaluate(const ScriptSourceCode&);
void evaluateInIsolatedWorld(unsigned worldID, const Vector<ScriptSourceCode>&);
// Executes JavaScript in a new world associated with the web frame. The
// script gets its own global scope, its own prototypes for intrinsic
// JavaScript objects (String, Array, and so-on), and its own wrappers for
// all DOM nodes and DOM constructors.
// FIXME: Move to using evaluateInIsolatedWorld instead.
void evaluateInNewWorld(const Vector<ScriptSourceCode>&, int extensionGroup);
// Executes JavaScript in a new context associated with the web frame. The
......
......@@ -1213,6 +1213,8 @@ void FrameLoader::finishedParsing()
if (m_creatingInitialEmptyDocument)
return;
m_frame->injectUserScripts(InjectAtDocumentEnd);
// This can be called from the Frame's destructor, in which case we shouldn't protect ourselves
// because doing so will cause us to re-enter the destructor when protector goes out of scope.
// Null-checking the FrameView indicates whether or not we're in the destructor.
......@@ -5109,6 +5111,7 @@ String FrameLoader::referrer() const
void FrameLoader::dispatchDocumentElementAvailable()
{
m_frame->injectUserScripts(InjectAtDocumentStart);
m_client->documentElementAvailable();
}
......
......@@ -60,6 +60,7 @@
#include "Navigator.h"
#include "NodeList.h"
#include "Page.h"
#include "PageGroup.h"
#include "RegularExpression.h"
#include "RenderPart.h"
#include "RenderTableCell.h"
......@@ -67,6 +68,8 @@
#include "RenderTheme.h"
#include "RenderView.h"
#include "ScriptController.h"
#include "ScriptSourceCode.h"
#include "ScriptValue.h"
#include "Settings.h"
#include "TextIterator.h"
#include "TextResourceDecoder.h"
......@@ -841,6 +844,37 @@ void Frame::reapplyStyles()
m_doc->updateStyleSelector();
}
void Frame::injectUserScripts(UserScriptInjectionTime injectionTime)
{
ASSERT(m_page);
if (!m_page)
return;
// Walk the hashtable. Inject by world.
const UserScriptMap* userScripts = m_page->group().userScripts();
if (!userScripts)
return;
UserScriptMap::const_iterator end = userScripts->end();
for (UserScriptMap::const_iterator it = userScripts->begin(); it != end; ++it)
injectUserScriptsForWorld(it->first, *it->second, injectionTime);
}
void Frame::injectUserScriptsForWorld(unsigned worldID, const UserScriptVector& userScripts, UserScriptInjectionTime injectionTime)
{
if (userScripts.isEmpty())
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)
sourceCode.append(ScriptSourceCode(script->source(), script->url()));
}
script()->evaluateInIsolatedWorld(worldID, sourceCode);
}
bool Frame::shouldChangeSelection(const VisibleSelection& newSelection) const
{
return shouldChangeSelection(selection()->selection(), newSelection, newSelection.affinity(), false);
......
......@@ -41,6 +41,7 @@
#include "ScrollBehavior.h"
#include "SelectionController.h"
#include "TextGranularity.h"
#include "UserScriptTypes.h"
#if PLATFORM(WIN)
#include "FrameWin.h"
......@@ -129,6 +130,10 @@ namespace WebCore {
void createView(const IntSize&, const Color&, bool, const IntSize &, bool,
ScrollbarMode = ScrollbarAuto, ScrollbarMode = ScrollbarAuto);
void injectUserScripts(UserScriptInjectionTime);
private:
void injectUserScriptsForWorld(unsigned worldID, const UserScriptVector&, UserScriptInjectionTime);
private:
Frame(Page*, HTMLFrameOwnerElement*, FrameLoaderClient*);
......
......@@ -66,6 +66,11 @@ PageGroup::PageGroup(Page* page)
addPage(page);
}
PageGroup::~PageGroup()
{
removeAllUserContent();
}
typedef HashMap<String, PageGroup*> PageGroupMap;
static PageGroupMap* pageGroups = 0;
......@@ -193,4 +198,38 @@ StorageNamespace* PageGroup::localStorage()
}
#endif
void PageGroup::addUserScript(const String& source, const KURL& url, const Vector<String>& patterns,
unsigned worldID, UserScriptInjectionTime injectionTime)
{
if (worldID == UINT_MAX)
return;
OwnPtr<UserScript> userScript(new UserScript(source, url, patterns, worldID, injectionTime));
if (!m_userScripts)
m_userScripts.set(new UserScriptMap);
UserScriptVector*& scriptsInWorld = m_userScripts->add(worldID, 0).first->second;
if (!scriptsInWorld)
scriptsInWorld = new UserScriptVector;
scriptsInWorld->append(userScript.release());
}
void PageGroup::removeUserContentForWorld(unsigned worldID)
{
if (!m_userScripts)
return;
UserScriptMap::iterator it = m_userScripts->find(worldID);
if (it != m_userScripts->end()) {
m_userScripts->remove(it);
delete it->second;
}
}
void PageGroup::removeAllUserContent()
{
if (m_userScripts) {
deleteAllValues(*m_userScripts);
m_userScripts.clear();
}
}
} // namespace WebCore
......@@ -30,6 +30,7 @@
#include <wtf/Noncopyable.h>
#include "LinkHash.h"
#include "StringHash.h"
#include "UserScript.h"
namespace WebCore {
......@@ -41,6 +42,7 @@ namespace WebCore {
public:
PageGroup(const String& name);
PageGroup(Page*);
~PageGroup();
static PageGroup* pageGroup(const String& groupName);
static void closeLocalStorage();
......@@ -67,6 +69,13 @@ namespace WebCore {
bool hasLocalStorage() { return m_localStorage; }
#endif
void addUserScript(const String& source, const KURL&, const Vector<String>& patterns,
unsigned worldID, UserScriptInjectionTime);
const UserScriptMap* userScripts() const { return m_userScripts.get(); }
void removeUserContentForWorld(unsigned);
void removeAllUserContent();
private:
void addVisitedLink(LinkHash stringHash);
......@@ -81,6 +90,8 @@ namespace WebCore {
#if ENABLE(DOM_STORAGE)
RefPtr<StorageNamespace> m_localStorage;
#endif
OwnPtr<UserScriptMap> m_userScripts;
};
} // 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 UserScript_h
#define UserScript_h
#include "KURL.h"
#include "UserScriptTypes.h"
#include <wtf/OwnPtr.h>
#include <wtf/Vector.h>
namespace WebCore {
class UserScript {
public:
UserScript(const String& source, const KURL& url,
const Vector<String>& patterns, unsigned worldID,
UserScriptInjectionTime injectionTime)
: m_source(source)
, m_url(url)
, m_patterns(patterns)
, m_worldID(worldID)
, m_injectionTime(injectionTime)
{
}
const String& source() const { return m_source; }
const KURL& url() const { return m_url; }
const Vector<String>& patterns() const { return m_patterns; }
unsigned worldID() const { return m_worldID; }
UserScriptInjectionTime injectionTime() const { return m_injectionTime; }
private:
String m_source;
KURL m_url;
Vector<String> m_patterns;
unsigned m_worldID;
UserScriptInjectionTime m_injectionTime;
};
} // namsepace WebCore
#endif // UserScript_h
/*
* 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 UserScriptTypes_h
#define UserScriptTypes_h
#include <wtf/HashMap.h>
#include <wtf/Vector.h>
namespace WebCore {
enum UserScriptInjectionTime { InjectAtDocumentStart, InjectAtDocumentEnd };
class UserScript;
typedef Vector<OwnPtr<UserScript> > UserScriptVector;
typedef HashMap<int, UserScriptVector*> UserScriptMap;
} // namsepace WebCore
#endif // UserScriptTypes_h
2009-09-03 Dave Hyatt <hyatt@apple.com>
Reviewed by Adam Roben.
https://bugs.webkit.org/show_bug.cgi?id=28890, make simple user script injection work.
This patch adds new API for adding and removing user scripts from page groups. User scripts
are bundled together in isolated worlds (you can have multiple scripts together in the same
world).
Added userscripts/ directory for holding new tests (along with a simple test of script injection).
* WebView/WebView.mm:
(+[WebView _addUserScriptToGroup:source:url:worldID:patterns:injectionTime:]):
(+[WebView _removeUserContentFromGroup:worldID:]):
(+[WebView _removeAllUserContentFromGroup:]):
* WebView/WebViewPrivate.h:
2009-09-04 Adam Barth <abarth@webkit.org>
Reviewed by Eric Seidel.
......
......@@ -2110,6 +2110,54 @@ static inline IMP getMethod(id o, SEL s)
_private->page->focusController()->setActive([[self window] isKeyWindow]);
}
+ (void)_addUserScriptToGroup:(NSString *)groupName source:(NSString *)source url:(NSURL *)url worldID:(unsigned)worldID patterns:(NSArray *)patterns injectionTime:(WebUserScriptInjectionTime)injectionTime
{
String group(groupName);
if (group.isEmpty() || worldID == UINT_MAX)
return;
PageGroup* pageGroup = PageGroup::pageGroup(group);
if (!pageGroup)
return;
// Convert the patterns into a Vector.
Vector<String> patternsVector;
NSUInteger count = [patterns count];
for (NSUInteger i = 0; i < count; ++i) {
id entry = [patterns objectAtIndex: i];
if ([entry isKindOfClass:[NSString class]])
patternsVector.append(String((NSString*)entry));
}
pageGroup->addUserScript(source, url, patternsVector, worldID,
injectionTime == WebInjectAtDocumentStart ? InjectAtDocumentStart : InjectAtDocumentEnd);
}
+ (void)_removeUserContentFromGroup:(NSString *)groupName worldID:(unsigned)worldID
{
String group(groupName);
if (group.isEmpty())
return;
PageGroup* pageGroup = PageGroup::pageGroup(group);
if (!pageGroup)
return;
pageGroup->removeUserContentForWorld(worldID);
}
+ (void)_removeAllUserContentFromGroup:(NSString *)groupName
{
String group(groupName);
if (group.isEmpty())
return;
PageGroup* pageGroup = PageGroup::pageGroup(group);
if (!pageGroup)
return;
pageGroup->removeAllUserContent();
}
@end
@implementation _WebSafeForwarder
......
......@@ -76,6 +76,11 @@ typedef enum {
} WebDashboardBehavior;
#endif
typedef enum {
WebInjectAtDocumentStart,
WebInjectAtDocumentEnd,
} WebUserScriptInjectionTime;
@interface WebController : NSTreeController {
IBOutlet WebView *webView;
}
......@@ -452,6 +457,10 @@ Could be worth adding to the API.
// Removes all white list entries created with _whiteListAccessFromOrigin.
+ (void)_resetOriginAccessWhiteLists;
+ (void)_addUserScriptToGroup:(NSString *)groupName source:(NSString *)source url:(NSURL *)url worldID:(unsigned)worldID patterns:(NSArray *)patterns injectionTime:(WebUserScriptInjectionTime)injectionTime;
+ (void)_removeUserContentFromGroup:(NSString *)groupName worldID:(unsigned)worldID;
+ (void)_removeAllUserContentFromGroup:(NSString *)groupName;
@end
@interface WebView (WebViewPrintingPrivate)
......
......@@ -912,6 +912,20 @@ static JSValueRef whiteListAccessFromOriginCallback(JSContextRef context, JSObje
return JSValueMakeUndefined(context);
}
static JSValueRef addUserScriptCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
{
if (argumentCount != 2)
return JSValueMakeUndefined(context);
JSRetainPtr<JSStringRef> source(Adopt, JSValueToStringCopy(context, arguments[0], exception));
ASSERT(!*exception);
bool runAtStart = JSValueToBoolean(context, arguments[1]);
LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
controller->addUserScript(source.get(), runAtStart);
return JSValueMakeUndefined(context);
}
// Static Values
static JSValueRef getGlobalFlagCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
......@@ -988,6 +1002,7 @@ JSStaticFunction* LayoutTestController::staticFunctions()
{
static JSStaticFunction staticFunctions[] = {
{ "addDisallowedURL", addDisallowedURLCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "addUserScript", addUserScriptCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "clearAllDatabases", clearAllDatabasesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "clearBackForwardList", clearBackForwardListCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "clearPersistentUserStyleSheet", clearPersistentUserStyleSheetCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
......
......@@ -185,6 +185,8 @@ public:
void whiteListAccessFromOrigin(JSStringRef sourceOrigin, JSStringRef destinationProtocol, JSStringRef destinationHost, bool allowDestinationSubdomains);
void addUserScript(JSStringRef source, bool runAtStart);
private:
bool m_dumpAsText;
bool m_dumpAsPDF;
......