Bug 479093 - Text sent to services includes body of <script> tags. r=smaug, r=josh, sr=roc

This commit is contained in:
Tom Dyas 2009-03-17 19:04:01 -07:00
Родитель 8bb593e370
Коммит 03b91d6b28
7 изменённых файлов: 200 добавлений и 66 удалений

Просмотреть файл

@ -70,6 +70,12 @@ class nsCopySupport
// before[copy,cut,paste] and [copy,cut,paste] events will fire on.
static nsresult GetClipboardEventTarget(nsISelection *aSel,
nsIDOMNode **aEventTarget);
// Get the selection as a transferable. Similar to HTMLCopy except does
// not deal with the clipboard.
static nsresult GetTransferableForSelection(nsISelection * aSelection,
nsIDocument * aDocument,
nsITransferable ** aTransferable);
};
#endif

Просмотреть файл

@ -86,13 +86,23 @@ static nsresult AppendString(nsITransferable *aTransferable,
static nsresult AppendDOMNode(nsITransferable *aTransferable,
nsIDOMNode *aDOMNode);
nsresult nsCopySupport::HTMLCopy(nsISelection *aSel, nsIDocument *aDoc, PRInt16 aClipboardID)
// Helper used for HTMLCopy and GetTransferableForSelection since both routines
// share common code.
static nsresult
SelectionCopyHelper(nsISelection *aSel, nsIDocument *aDoc,
PRBool doPutOnClipboard, PRInt16 aClipboardID,
nsITransferable ** aTransferable)
{
// Clear the output parameter for the transferable, if provided.
if (aTransferable) {
*aTransferable = nsnull;
}
nsresult rv = NS_OK;
PRBool bIsPlainTextContext = PR_FALSE;
rv = IsPlainTextContext(aSel, aDoc, &bIsPlainTextContext);
rv = nsCopySupport::IsPlainTextContext(aSel, aDoc, &bIsPlainTextContext);
if (NS_FAILED(rv))
return rv;
@ -114,6 +124,7 @@ nsresult nsCopySupport::HTMLCopy(nsISelection *aSel, nsIDocument *aDoc, PRInt16
rv = docEncoder->Init(domDoc, mimeType, flags);
if (NS_FAILED(rv))
return rv;
rv = docEncoder->SetSelection(aSel);
if (NS_FAILED(rv))
return rv;
@ -160,42 +171,40 @@ nsresult nsCopySupport::HTMLCopy(nsISelection *aSel, nsIDocument *aDoc, PRInt16
}
// Get the Clipboard
nsCOMPtr<nsIClipboard> clipboard(do_GetService(kCClipboardCID, &rv));
if (NS_FAILED(rv))
return rv;
nsCOMPtr<nsIClipboard> clipboard;
if (doPutOnClipboard) {
clipboard = do_GetService(kCClipboardCID, &rv);
if (NS_FAILED(rv))
return rv;
}
if ( clipboard )
{
if ((doPutOnClipboard && clipboard) || aTransferable != nsnull) {
// Create a transferable for putting data on the Clipboard
nsCOMPtr<nsITransferable> trans = do_CreateInstance(kCTransferableCID);
if ( trans )
{
if (bIsHTMLCopy)
{
if (trans) {
if (bIsHTMLCopy) {
// set up the data converter
trans->SetConverter(htmlConverter);
if (!buffer.IsEmpty())
{
if (!buffer.IsEmpty()) {
// Add the html DataFlavor to the transferable
rv = AppendString(trans, buffer, kHTMLMime);
NS_ENSURE_SUCCESS(rv, rv);
}
{
// Add the htmlcontext DataFlavor to the transferable
// Even if parents is empty string, this flavor should
// be attached to the transferable
rv = AppendString(trans, parents, kHTMLContext);
NS_ENSURE_SUCCESS(rv, rv);
}
if (!info.IsEmpty())
{
// Add the htmlcontext DataFlavor to the transferable
// Even if parents is empty string, this flavor should
// be attached to the transferable
rv = AppendString(trans, parents, kHTMLContext);
NS_ENSURE_SUCCESS(rv, rv);
if (!info.IsEmpty()) {
// Add the htmlinfo DataFlavor to the transferable
rv = AppendString(trans, info, kHTMLInfo);
NS_ENSURE_SUCCESS(rv, rv);
}
if (!plaintextBuffer.IsEmpty())
{
if (!plaintextBuffer.IsEmpty()) {
// unicode text
// Add the unicode DataFlavor to the transferable
// If we didn't have this, then nsDataObj::GetData matches text/unicode against
@ -223,28 +232,45 @@ nsresult nsCopySupport::HTMLCopy(nsISelection *aSel, nsIDocument *aDoc, PRInt16
NS_ENSURE_SUCCESS(rv, rv);
}
}
}
else
{
if (!textBuffer.IsEmpty())
{
// Add the unicode DataFlavor to the transferable
} else {
if (!textBuffer.IsEmpty()) {
// Add the unicode DataFlavor to the transferable
rv = AppendString(trans, textBuffer, kUnicodeMime);
NS_ENSURE_SUCCESS(rv, rv);
}
}
PRBool doPutOnClipboard = PR_TRUE;
DoHooks(aDoc, trans, &doPutOnClipboard);
if (doPutOnClipboard && clipboard) {
PRBool actuallyPutOnClipboard = PR_TRUE;
nsCopySupport::DoHooks(aDoc, trans, &actuallyPutOnClipboard);
// put the transferable on the clipboard
if (doPutOnClipboard)
clipboard->SetData(trans, nsnull, aClipboardID);
// put the transferable on the clipboard
if (actuallyPutOnClipboard)
clipboard->SetData(trans, nsnull, aClipboardID);
}
// Return the transferable to the caller if requested.
if (aTransferable != nsnull) {
trans.swap(*aTransferable);
}
}
}
return rv;
}
nsresult nsCopySupport::HTMLCopy(nsISelection *aSel, nsIDocument *aDoc, PRInt16 aClipboardID)
{
return SelectionCopyHelper(aSel, aDoc, PR_TRUE, aClipboardID, nsnull);
}
nsresult
nsCopySupport::GetTransferableForSelection(nsISelection * aSel,
nsIDocument * aDoc,
nsITransferable ** aTransferable)
{
return SelectionCopyHelper(aSel, aDoc, PR_FALSE, 0, aTransferable);
}
nsresult nsCopySupport::DoHooks(nsIDocument *aDoc, nsITransferable *aTrans,
PRBool *aDoPutOnClipboard)
{

Просмотреть файл

@ -48,6 +48,7 @@
#include "nsRange.h"
#include "nsGUIEvent.h"
#include "nsCaret.h"
#include "nsCopySupport.h"
#include "nsFrameSelection.h"
#include "nsIFrame.h"
#include "nsIView.h"
@ -92,6 +93,12 @@ nsContentEventHandler::Init(nsQueryContentEvent* aEvent)
NS_ASSERTION(mSelection,
"GetSelectionForCopy succeeded, but the result is null");
PRBool isCollapsed;
rv = mSelection->GetIsCollapsed(&isCollapsed);
if (NS_FAILED(rv))
return NS_ERROR_NOT_AVAILABLE;
aEvent->mReply.mHasSelection = !isCollapsed;
nsCOMPtr<nsIDOMRange> firstRange;
rv = mSelection->GetRangeAt(0, getter_AddRefs(firstRange));
// This shell doesn't support selection.
@ -111,7 +118,6 @@ nsContentEventHandler::Init(nsQueryContentEvent* aEvent)
rv = mPresShell->GetCaret(getter_AddRefs(caret));
NS_ENSURE_SUCCESS(rv, rv);
NS_ASSERTION(caret, "GetCaret succeeded, but the result is null");
PRBool isCollapsed;
nsRect r;
nsIView* view = nsnull;
rv = caret->GetCaretCoordinates(nsCaret::eRenderingViewCoordinates,
@ -684,6 +690,41 @@ nsContentEventHandler::OnQueryCaretRect(nsQueryContentEvent* aEvent)
return NS_OK;
}
nsresult
nsContentEventHandler::OnQueryContentState(nsQueryContentEvent * aEvent)
{
nsresult rv = Init(aEvent);
if (NS_FAILED(rv))
return rv;
aEvent->mSucceeded = PR_TRUE;
return NS_OK;
}
nsresult
nsContentEventHandler::OnQuerySelectionAsTransferable(nsQueryContentEvent* aEvent)
{
nsresult rv = Init(aEvent);
if (NS_FAILED(rv))
return rv;
if (!aEvent->mReply.mHasSelection) {
aEvent->mSucceeded = PR_TRUE;
aEvent->mReply.mTransferable = nsnull;
return NS_OK;
}
nsCOMPtr<nsIDocument> doc = mPresShell->GetDocument();
NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
rv = nsCopySupport::GetTransferableForSelection(mSelection, doc, getter_AddRefs(aEvent->mReply.mTransferable));
NS_ENSURE_SUCCESS(rv, rv);
aEvent->mSucceeded = PR_TRUE;
return NS_OK;
}
nsresult
nsContentEventHandler::GetFlatTextOffsetOfRange(nsIContent* aRootContent,
nsINode* aNode,

Просмотреть файл

@ -77,6 +77,10 @@ public:
nsresult OnQueryTextRect(nsQueryContentEvent* aEvent);
// NS_QUERY_EDITOR_RECT event handler
nsresult OnQueryEditorRect(nsQueryContentEvent* aEvent);
// NS_QUERY_CONTENT_STATE event handler
nsresult OnQueryContentState(nsQueryContentEvent* aEvent);
// NS_QUERY_SELECTION_AS_TRANSFERABLE event handler
nsresult OnQuerySelectionAsTransferable(nsQueryContentEvent* aEvent);
// NS_SELECTION_* event
nsresult OnSelectionEvent(nsSelectionEvent* aEvent);

Просмотреть файл

@ -1688,6 +1688,18 @@ nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext,
handler.OnQueryEditorRect((nsQueryContentEvent*)aEvent);
}
break;
case NS_QUERY_CONTENT_STATE:
{
nsContentEventHandler handler(mPresContext);
handler.OnQueryContentState(static_cast<nsQueryContentEvent*>(aEvent));
}
break;
case NS_QUERY_SELECTION_AS_TRANSFERABLE:
{
nsContentEventHandler handler(mPresContext);
handler.OnQuerySelectionAsTransferable(static_cast<nsQueryContentEvent*>(aEvent));
}
break;
case NS_SELECTION_SET:
{
nsContentEventHandler handler(mPresContext);

Просмотреть файл

@ -54,6 +54,7 @@
#include "nsIWidget.h"
#include "nsTArray.h"
#include "nsTraceRefcnt.h"
#include "nsITransferable.h"
class nsIRenderingContext;
class nsIRegion;
@ -362,6 +363,11 @@ class nsHashKey;
// Query for the bounding rect of the current focused frame. Result is relative
// to top level widget coordinates
#define NS_QUERY_EDITOR_RECT (NS_QUERY_CONTENT_EVENT_START + 5)
// Query for the current state of the content. The particular members of
// mReply that are set for each query content event will be valid on success.
#define NS_QUERY_CONTENT_STATE (NS_QUERY_CONTENT_EVENT_START + 6)
// Query for the selection in the form of a nsITransferable.
#define NS_QUERY_SELECTION_AS_TRANSFERABLE (NS_QUERY_CONTENT_EVENT_START + 7)
// Video events
#ifdef MOZ_MEDIA
@ -1012,6 +1018,9 @@ public:
// The return widget has the caret. This is set at all query events.
nsIWidget* mFocusedWidget;
PRPackedBool mReversed; // true if selection is reversed (end < start)
PRPackedBool mHasSelection; // true if the selection exists
// used by NS_QUERY_SELECTION_AS_TRANSFERABLE
nsCOMPtr<nsITransferable> mTransferable;
} mReply;
};

Просмотреть файл

@ -68,6 +68,7 @@
#include "nsIMenuRollup.h"
#include "nsDragService.h"
#include "nsClipboard.h"
#include "nsCursorManager.h"
#include "nsWindowMap.h"
#include "nsCocoaUtils.h"
@ -2391,10 +2392,15 @@ NSEvent* gLastDragEvent = nil;
if (!initialized) {
// Inform the OS about the types of services (from the "Services" menu)
// that we can handle.
NSArray *sendTypes = [NSArray arrayWithObject:NSStringPboardType];
NSArray *returnTypes = [NSArray array];
NSArray *sendTypes = [[NSArray alloc] initWithObjects:NSStringPboardType,NSHTMLPboardType,nil];
NSArray *returnTypes = [[NSArray alloc] init];
[NSApp registerServicesMenuSendTypes:sendTypes returnTypes:returnTypes];
[sendTypes release];
[returnTypes release];
initialized = YES;
}
}
@ -6427,7 +6433,7 @@ static BOOL keyUpAlreadySentKeyDown = NO;
#pragma mark -
// Support for the "Services" menu. We currently only support sending strings
// to services.
// and HTML to system services.
- (id)validRequestorForSendType:(NSString *)sendType
returnType:(NSString *)returnType
@ -6443,24 +6449,23 @@ static BOOL keyUpAlreadySentKeyDown = NO;
// returnType is nil if the service will not return any data.
//
// The following condition thus triggers when the service expects a string
// from us or no data at all AND when the service will not send back any
// data to us.
// or HTML from us or no data at all AND when the service will not send back
// any data to us.
if ((!sendType || [sendType isEqual:NSStringPboardType]) && !returnType) {
// Query Gecko window to determine if there is a current selection.
bool hasSelection = false;
if ((!sendType || [sendType isEqual:NSStringPboardType] ||
[sendType isEqual:NSHTMLPboardType]) && !returnType) {
// Query the Gecko window to determine if there is a current selection.
if (mGeckoChild) {
nsAutoRetainCocoaObject kungFuDeathGrip(self);
nsQueryContentEvent selection(PR_TRUE, NS_QUERY_SELECTED_TEXT,
mGeckoChild);
mGeckoChild->DispatchWindowEvent(selection);
if (selection.mSucceeded && !selection.mReply.mString.IsEmpty())
hasSelection = true;
}
// Return this object if it can handle the request.
if ((!sendType || hasSelection) && !returnType)
return self;
nsQueryContentEvent event(PR_TRUE, NS_QUERY_CONTENT_STATE, mGeckoChild);
mGeckoChild->DispatchWindowEvent(event);
// Return this object if it can handle the request.
if ((!sendType || (event.mSucceeded && event.mReply.mHasSelection)) &&
!returnType)
return self;
}
}
return [super validRequestorForSendType:sendType returnType:returnType];
@ -6475,24 +6480,55 @@ static BOOL keyUpAlreadySentKeyDown = NO;
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
nsAutoRetainCocoaObject kungFuDeathGrip(self);
// Ensure that the service will accept strings. (We only support strings.)
if ([types containsObject:NSStringPboardType] == NO)
// Make sure that the service will accept strings or HTML.
if ([types containsObject:NSStringPboardType] == NO &&
[types containsObject:NSHTMLPboardType] == NO)
return NO;
// Bail out if there is no Gecko object.
if (!mGeckoChild)
return NO;
// Obtain the current selection.
if (!mGeckoChild)
return NO;
nsQueryContentEvent selection(PR_TRUE, NS_QUERY_SELECTED_TEXT, mGeckoChild);
mGeckoChild->DispatchWindowEvent(selection);
if (!selection.mSucceeded || selection.mReply.mString.IsEmpty())
nsQueryContentEvent event(PR_TRUE,
NS_QUERY_SELECTION_AS_TRANSFERABLE,
mGeckoChild);
mGeckoChild->DispatchWindowEvent(event);
if (!event.mSucceeded || !event.mReply.mTransferable)
return NO;
// Copy the current selection to the pasteboard.
NSArray *typesDeclared = [NSArray arrayWithObject:NSStringPboardType];
[pboard declareTypes:typesDeclared owner:nil];
return [pboard setString:ToNSString(selection.mReply.mString)
forType:NSStringPboardType];
// Transform the transferable to an NSDictionary.
NSDictionary* pasteboardOutputDict = nsClipboard::PasteboardDictFromTransferable(event.mReply.mTransferable);
if (!pasteboardOutputDict)
return NO;
// Declare the pasteboard types.
unsigned int typeCount = [pasteboardOutputDict count];
NSMutableArray * types = [NSMutableArray arrayWithCapacity:typeCount];
[types addObjectsFromArray:[pasteboardOutputDict allKeys]];
[pboard declareTypes:types owner:nil];
// Write the data to the pasteboard.
for (unsigned int i = 0; i < typeCount; i++) {
NSString* currentKey = [types objectAtIndex:i];
id currentValue = [pasteboardOutputDict valueForKey:currentKey];
if (currentKey == NSStringPboardType ||
currentKey == kCorePboardType_url ||
currentKey == kCorePboardType_urld ||
currentKey == kCorePboardType_urln) {
[pboard setString:currentValue forType:currentKey];
} else if (currentKey == NSHTMLPboardType) {
[pboard setString:(nsClipboard::WrapHtmlForSystemPasteboard(currentValue)) forType:currentKey];
} else if (currentKey == NSTIFFPboardType) {
[pboard setData:currentValue forType:currentKey];
} else if (currentKey == NSFilesPromisePboardType) {
[pboard setPropertyList:currentValue forType:currentKey];
}
}
return YES;
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NO);
}