Bug 501154, consolidate places where clipboard events are fired from, r=smaug,sr=neil

This commit is contained in:
Neil Deakin 2010-03-19 14:32:13 -04:00
parent aed5827557
commit 3ea1a5bd7d
14 changed files with 657 additions and 493 deletions

View File

@ -48,6 +48,7 @@ class nsITransferable;
class nsACString;
class nsAString;
class nsIDOMNode;
class nsIPresShell;
class nsCopySupport
{
@ -66,16 +67,51 @@ class nsCopySupport
static nsresult ImageCopy(nsIImageLoadingContent* aImageElement,
PRInt32 aCopyFlags);
// Given the current selection, find the target that
// 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);
/**
* Retrieve the selection for the given document. If the current focus
* within the document has its own selection, aSelection will be set to it
* and this focused content node returned. Otherwise, aSelection will be
* set to the document's selection and null will be returned.
*/
static nsIContent* GetSelectionForCopy(nsIDocument* aDocument,
nsISelection** aSelection);
/**
* Returns true if a copy operation is currently permitted based on the
* current focus and selection within the specified document.
*/
static PRBool CanCopy(nsIDocument* aDocument);
/**
* Fires a cut, copy or paste event, on the given presshell, depending
* on the value of aType, which should be either NS_CUT, NS_COPY or
* NS_PASTE, and perform the default copy action if the event was not
* cancelled.
*
* If aSelection is specified, then this selection is used as the target
* of the operation. Otherwise, GetSelectionForCopy is used to retrieve
* the current selection.
*
* This will fire a cut, copy or paste event at the node at the start
* point of the selection. If a cut or copy event is not cancelled, the
* selection is copied to the clipboard and true is returned. Paste events
* have no default behaviour but true will be returned. It is expected
* that the caller will execute any needed default paste behaviour. Also,
* note that this method only copies text to the clipboard, the caller is
* responsible for removing the content during a cut operation if true is
* returned.
*
* If the event is cancelled or an error occurs, false will be returned.
*/
static PRBool FireClipboardEvent(PRInt32 aType,
nsIPresShell* aPresShell,
nsISelection* aSelection);
};
#endif

View File

@ -50,18 +50,26 @@
#include "nsISupportsPrimitives.h"
#include "nsIDOMRange.h"
#include "imgIContainer.h"
#include "nsIPresShell.h"
#include "nsFocusManager.h"
#include "nsEventDispatcher.h"
#include "nsIDocShell.h"
#include "nsIContentViewerEdit.h"
#include "nsIClipboardDragDropHooks.h"
#include "nsIClipboardDragDropHookList.h"
#include "nsIClipboardHelper.h"
#include "nsISelectionController.h"
#include "nsPIDOMWindow.h"
#include "nsIDocument.h"
#include "nsIDOMNode.h"
#include "nsIDOMElement.h"
#include "nsIDOMDocument.h"
#include "nsIHTMLDocument.h"
#include "nsGkAtoms.h"
#include "nsGUIEvent.h"
#include "nsIFrame.h"
// image copy stuff
#include "nsIImageLoadingContent.h"
@ -582,26 +590,128 @@ static nsresult AppendDOMNode(nsITransferable *aTransferable,
return AppendString(aTransferable, context, kHTMLContext);
}
// Find the target that onbefore[copy,cut,paste] and on[copy,cut,paste]
// events will fire on -- the start node of the copy selection.
nsresult nsCopySupport::GetClipboardEventTarget(nsISelection *aSel,
nsIDOMNode **aEventTarget)
nsIContent*
nsCopySupport::GetSelectionForCopy(nsIDocument* aDocument, nsISelection** aSelection)
{
NS_ENSURE_ARG(aSel);
NS_ENSURE_ARG_POINTER(aEventTarget);
*aEventTarget = nsnull;
*aSelection = nsnull;
nsCOMPtr<nsIDOMRange> range;
nsresult rv = aSel->GetRangeAt(0, getter_AddRefs(range));
if (rv == NS_ERROR_INVALID_ARG) // empty selection
return NS_ERROR_FAILURE;
NS_ENSURE_SUCCESS(rv, rv);
nsIPresShell* presShell = aDocument->GetPrimaryShell();
if (!presShell)
return nsnull;
if (!range)
return NS_ERROR_FAILURE;
// check if the focused node in the window has a selection
nsCOMPtr<nsPIDOMWindow> focusedWindow;
nsIContent* content =
nsFocusManager::GetFocusedDescendant(aDocument->GetWindow(), PR_FALSE,
getter_AddRefs(focusedWindow));
if (content) {
nsIFrame* frame = content->GetPrimaryFrame();
if (frame) {
nsCOMPtr<nsISelectionController> selCon;
frame->GetSelectionController(presShell->GetPresContext(), getter_AddRefs(selCon));
if (selCon) {
selCon->GetSelection(nsISelectionController::SELECTION_NORMAL, aSelection);
return content;
}
}
}
rv = range->GetStartContainer(aEventTarget);
NS_ENSURE_SUCCESS(rv, rv);
return (*aEventTarget) ? NS_OK : NS_ERROR_FAILURE;
// if no selection was found, use the main selection for the window
NS_IF_ADDREF(*aSelection = presShell->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL));
return nsnull;
}
PRBool
nsCopySupport::CanCopy(nsIDocument* aDocument)
{
if (!aDocument)
return PR_FALSE;
nsCOMPtr<nsISelection> sel;
GetSelectionForCopy(aDocument, getter_AddRefs(sel));
PRBool isCollapsed;
sel->GetIsCollapsed(&isCollapsed);
return !isCollapsed;
}
PRBool
nsCopySupport::FireClipboardEvent(PRInt32 aType, nsIPresShell* aPresShell, nsISelection* aSelection)
{
NS_ASSERTION(aType == NS_CUT || aType == NS_COPY || aType == NS_PASTE,
"Invalid clipboard event type");
nsCOMPtr<nsIPresShell> presShell = aPresShell;
if (!presShell)
return PR_FALSE;
nsCOMPtr<nsIDocument> doc = presShell->GetDocument();
if (!doc)
return PR_FALSE;
nsCOMPtr<nsPIDOMWindow> piWindow = doc->GetWindow();
if (!piWindow)
return PR_FALSE;
// if a selection was not supplied, try to find it
nsCOMPtr<nsIContent> content;
nsCOMPtr<nsISelection> sel = aSelection;
if (!sel)
content = GetSelectionForCopy(doc, getter_AddRefs(sel));
// retrieve the event target node from the start of the selection
if (sel) {
// Only cut or copy when there is an uncollapsed selection
if (aType == NS_CUT || aType == NS_COPY) {
PRBool isCollapsed;
sel->GetIsCollapsed(&isCollapsed);
if (isCollapsed)
return PR_FALSE;
}
nsCOMPtr<nsIDOMRange> range;
nsresult rv = sel->GetRangeAt(0, getter_AddRefs(range));
if (NS_SUCCEEDED(rv) && range) {
nsCOMPtr<nsIDOMNode> startContainer;
range->GetStartContainer(getter_AddRefs(startContainer));
if (startContainer)
content = do_QueryInterface(startContainer);
}
}
// if no content node was set, just get the root
if (!content) {
content = doc->GetRootContent();
if (!content)
return PR_FALSE;
}
// It seems to be unsafe to fire an event handler during reflow (bug 393696)
if (!nsContentUtils::IsSafeToRunScript())
return PR_FALSE;
// next, fire the cut or copy event
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent evt(PR_TRUE, aType);
nsEventDispatcher::Dispatch(content, presShell->GetPresContext(), &evt, nsnull,
&status);
// if the event was cancelled, don't do the clipboard operation
if (status == nsEventStatus_eConsumeNoDefault)
return PR_FALSE;
// no need to do anything special during a paste. Either an event listener
// took care of it and cancelled the event, or the caller will handle it.
// Return true to indicate the event wasn't cancelled.
if (aType == NS_PASTE)
return PR_TRUE;
// call the copy code
if (NS_FAILED(nsCopySupport::HTMLCopy(sel, doc, nsIClipboard::kGlobalClipboard)))
return PR_FALSE;
// Now that we have copied, update the clipboard commands. This should have
// the effect of updating the paste menu item.
piWindow->UpdateCommands(NS_LITERAL_STRING("clipboard"));
return PR_TRUE;
}

View File

@ -89,8 +89,8 @@ nsContentEventHandler::InitCommon()
nsresult rv = mPresShell->FlushPendingNotifications(Flush_Layout);
NS_ENSURE_SUCCESS(rv, rv);
rv = mPresShell->GetSelectionForCopy(getter_AddRefs(mSelection));
NS_ENSURE_SUCCESS(rv, rv);
nsCopySupport::GetSelectionForCopy(mPresShell->GetDocument(),
getter_AddRefs(mSelection));
NS_ASSERTION(mSelection,
"GetSelectionForCopy succeeded, but the result is null");

View File

@ -40,12 +40,9 @@
#include "nsISupports.idl"
[scriptable, uuid(1691a02f-53b2-4cb8-8769-48e7efc908b8)]
[scriptable, uuid(AF13EA3A-D488-4308-B843-526E055AB943)]
interface nsIContentViewerEdit : nsISupports
{
void search();
readonly attribute boolean searchable;
void clearSelection();
void selectAll();
@ -62,12 +59,6 @@ interface nsIContentViewerEdit : nsISupports
void copyImage(in long aCopyFlags);
readonly attribute boolean inImage;
void cutSelection();
readonly attribute boolean cutable;
void paste();
readonly attribute boolean pasteable;
AString getContents(in string aMimeType, in boolean aSelectionOnly);
readonly attribute boolean canGetContents;
};

View File

@ -59,6 +59,8 @@
#include "nsIContentViewerEdit.h"
#include "nsIContentViewer.h"
#include "nsFocusManager.h"
#include "nsCopySupport.h"
#include "nsGUIEvent.h"
#include "nsIClipboardDragDropHooks.h"
#include "nsIClipboardDragDropHookList.h"
@ -407,7 +409,71 @@ nsSelectCommand::DoSelectCommand(const char *aCommandName, nsIDOMWindow *aWindow
#pragma mark -
#endif
class nsClipboardBaseCommand : public nsIControllerCommand
class nsClipboardCommand : public nsIControllerCommand
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSICONTROLLERCOMMAND
};
NS_IMPL_ISUPPORTS1(nsClipboardCommand, nsIControllerCommand)
nsresult
nsClipboardCommand::IsCommandEnabled(const char* aCommandName, nsISupports *aContext, PRBool *outCmdEnabled)
{
NS_ENSURE_ARG_POINTER(outCmdEnabled);
*outCmdEnabled = PR_FALSE;
if (strcmp(aCommandName, "cmd_copy"))
return NS_OK;
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aContext);
NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
nsCOMPtr<nsIDocument> doc = do_QueryInterface(window->GetExtantDocument());
*outCmdEnabled = nsCopySupport::CanCopy(doc);
return NS_OK;
}
nsresult
nsClipboardCommand::DoCommand(const char *aCommandName, nsISupports *aContext)
{
if (strcmp(aCommandName, "cmd_copy"))
return NS_OK;
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aContext);
NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
nsIDocShell *docShell = window->GetDocShell();
NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
nsCOMPtr<nsIPresShell> presShell;
docShell->GetPresShell(getter_AddRefs(presShell));
NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
nsCopySupport::FireClipboardEvent(NS_COPY, presShell, nsnull);
return NS_OK;
}
NS_IMETHODIMP
nsClipboardCommand::GetCommandStateParams(const char *aCommandName,
nsICommandParams *aParams, nsISupports *aCommandContext)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult
nsClipboardCommand::DoCommandParams(const char *aCommandName, nsICommandParams* aParams, nsISupports *aContext)
{
return DoCommand(aCommandName, aContext);
}
#if 0
#pragma mark -
#endif
class nsSelectionCommand : public nsIControllerCommand
{
public:
@ -425,19 +491,19 @@ protected:
};
NS_IMPL_ISUPPORTS1(nsClipboardBaseCommand, nsIControllerCommand)
NS_IMPL_ISUPPORTS1(nsSelectionCommand, nsIControllerCommand)
/*---------------------------------------------------------------------------
nsClipboardBaseCommand
nsSelectionCommand
----------------------------------------------------------------------------*/
NS_IMETHODIMP
nsClipboardBaseCommand::IsCommandEnabled(const char * aCommandName,
nsISupports *aCommandContext,
PRBool *outCmdEnabled)
nsSelectionCommand::IsCommandEnabled(const char * aCommandName,
nsISupports *aCommandContext,
PRBool *outCmdEnabled)
{
NS_ENSURE_ARG_POINTER(outCmdEnabled);
*outCmdEnabled = PR_FALSE;
@ -450,8 +516,8 @@ nsClipboardBaseCommand::IsCommandEnabled(const char * aCommandName,
}
NS_IMETHODIMP
nsClipboardBaseCommand::DoCommand(const char *aCommandName,
nsISupports *aCommandContext)
nsSelectionCommand::DoCommand(const char *aCommandName,
nsISupports *aCommandContext)
{
nsCOMPtr<nsIContentViewerEdit> contentEdit;
GetContentViewerEditFromContext(aCommandContext, getter_AddRefs(contentEdit));
@ -461,17 +527,17 @@ nsClipboardBaseCommand::DoCommand(const char *aCommandName,
}
NS_IMETHODIMP
nsClipboardBaseCommand::GetCommandStateParams(const char *aCommandName,
nsICommandParams *aParams,
nsISupports *aCommandContext)
nsSelectionCommand::GetCommandStateParams(const char *aCommandName,
nsICommandParams *aParams,
nsISupports *aCommandContext)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsClipboardBaseCommand::DoCommandParams(const char *aCommandName,
nsICommandParams *aParams,
nsISupports *aCommandContext)
nsSelectionCommand::DoCommandParams(const char *aCommandName,
nsICommandParams *aParams,
nsISupports *aCommandContext)
{
nsCOMPtr<nsIContentViewerEdit> contentEdit;
GetContentViewerEditFromContext(aCommandContext, getter_AddRefs(contentEdit));
@ -481,8 +547,8 @@ nsClipboardBaseCommand::DoCommandParams(const char *aCommandName,
}
nsresult
nsClipboardBaseCommand::GetContentViewerEditFromContext(nsISupports *aContext,
nsIContentViewerEdit **aEditInterface)
nsSelectionCommand::GetContentViewerEditFromContext(nsISupports *aContext,
nsIContentViewerEdit **aEditInterface)
{
NS_ENSURE_ARG(aEditInterface);
*aEditInterface = nsnull;
@ -508,7 +574,7 @@ nsClipboardBaseCommand::GetContentViewerEditFromContext(nsISupports *aContext,
#endif
#define NS_DECL_CLIPBOARD_COMMAND(_cmd) \
class _cmd : public nsClipboardBaseCommand \
class _cmd : public nsSelectionCommand \
{ \
protected: \
\
@ -519,68 +585,11 @@ protected:
/* no member variables, please, we're stateless! */ \
};
NS_DECL_CLIPBOARD_COMMAND(nsClipboardCopyCommand)
NS_DECL_CLIPBOARD_COMMAND(nsClipboardCutCommand)
NS_DECL_CLIPBOARD_COMMAND(nsClipboardPasteCommand)
NS_DECL_CLIPBOARD_COMMAND(nsClipboardCopyLinkCommand)
NS_DECL_CLIPBOARD_COMMAND(nsClipboardImageCommands)
NS_DECL_CLIPBOARD_COMMAND(nsClipboardSelectAllNoneCommands)
NS_DECL_CLIPBOARD_COMMAND(nsClipboardGetContentsCommand)
#if 0
#pragma mark -
#endif
nsresult
nsClipboardCutCommand::IsClipboardCommandEnabled(const char* aCommandName, nsIContentViewerEdit* aEdit, PRBool *outCmdEnabled)
{
return aEdit->GetCutable(outCmdEnabled);
}
nsresult
nsClipboardCutCommand::DoClipboardCommand(const char *aCommandName, nsIContentViewerEdit* aEdit, nsICommandParams* aParams)
{
return aEdit->CutSelection();
}
#if 0
#pragma mark -
#endif
nsresult
nsClipboardCopyCommand::IsClipboardCommandEnabled(const char* aCommandName, nsIContentViewerEdit* aEdit, PRBool *outCmdEnabled)
{
return aEdit->GetCopyable(outCmdEnabled);
}
nsresult
nsClipboardCopyCommand::DoClipboardCommand(const char *aCommandName, nsIContentViewerEdit* aEdit, nsICommandParams* aParams)
{
return aEdit->CopySelection();
}
#if 0
#pragma mark -
#endif
nsresult
nsClipboardPasteCommand::IsClipboardCommandEnabled(const char* aCommandName, nsIContentViewerEdit* aEdit, PRBool *outCmdEnabled)
{
return aEdit->GetPasteable(outCmdEnabled);
}
nsresult
nsClipboardPasteCommand::DoClipboardCommand(const char *aCommandName, nsIContentViewerEdit* aEdit, nsICommandParams* aParams)
{
return aEdit->Paste();
}
#if 0
#pragma mark -
#endif
nsresult
nsClipboardCopyLinkCommand::IsClipboardCommandEnabled(const char* aCommandName, nsIContentViewerEdit* aEdit, PRBool *outCmdEnabled)
{
@ -965,9 +974,9 @@ nsWindowCommandRegistration::RegisterWindowCommands(
NS_REGISTER_NEXT_COMMAND(nsSelectCommand, sSelectTopString);
NS_REGISTER_LAST_COMMAND(nsSelectCommand, sSelectBottomString);
NS_REGISTER_ONE_COMMAND(nsClipboardCopyCommand, "cmd_copy");
NS_REGISTER_ONE_COMMAND(nsClipboardCutCommand, "cmd_cut");
NS_REGISTER_ONE_COMMAND(nsClipboardPasteCommand, "cmd_paste");
NS_REGISTER_ONE_COMMAND(nsClipboardCommand, "cmd_cut");
NS_REGISTER_ONE_COMMAND(nsClipboardCommand, "cmd_copy");
NS_REGISTER_ONE_COMMAND(nsClipboardCommand, "cmd_paste");
NS_REGISTER_ONE_COMMAND(nsClipboardCopyLinkCommand, "cmd_copyLink");
NS_REGISTER_FIRST_COMMAND(nsClipboardImageCommands, sCopyImageLocationString);
NS_REGISTER_NEXT_COMMAND(nsClipboardImageCommands, sCopyImageContentsString);

View File

@ -55,6 +55,7 @@ _TEST_FILES = \
test_offsets.js \
test_offsets.xul \
test_windowProperties.html \
test_clipboard_events.html \
$(NULL)
libs:: $(_TEST_FILES)

View File

@ -0,0 +1,322 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for Clipboard Events</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="border: 3px solid black; padding: 3em;">CONTENT TEXT<input id="content-input" value="INPUT TEXT"></div>
<pre id="test">
<script class="testbody" type="text/javascript;version=1.7">
// Enable full privledges for clipboard read/write operations.
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var content = document.getElementById("content");
var contentInput = document.getElementById("content-input");
var clipboardInitialValue = "empty";
// Test that clearing and reading the clipboard works. A random number
// is used to make sure that leftover clipboard values from a previous
// test run don't cause a false-positive test.
var cb_text = "empty_" + Math.random();
setClipboardText(cb_text);
is(getClipboardText(), cb_text, "set/get clipboard text failed");
// Some test functions need to be run with delays.
var delayedTests = [];
// Ensure window focus before running tests, otherwise key events can
// misfire. We set the onfocus event handler here to actually begin
// running tests, and call window.focus() afterwards.
window.onfocus = function()
{
window.onfocus = null;
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
// A list of test functions to run. Before each test function is run, the
// clipboard is initialized to clipboardInitialValue, and the contents of
// div#content are set as the window's selection.
var testFunctions = [
test_dom_oncopy,
test_dom_oncut,
test_dom_onpaste,
test_dom_oncopy_abort,
test_input_oncopy,
test_input_oncut,
test_input_onpaste,
test_input_oncopy_abort,
test_input_oncut_abort,
test_input_onpaste_abort,
];
// Run the main tests. This will also populate the delayedTests array
for (let i = 0; i < testFunctions.length; i++) {
// Init clipboard
setClipboardText(clipboardInitialValue);
// Reset value of contentInput.
contentInput.value = "INPUT TEXT";
var func = testFunctions[i];
func();
}
SimpleTest.finish();
}
// Calling .focus begins the test run.
SimpleTest.waitForExplicitFinish();
window.focus();
function getClipboardText() {
var trans = Components.classes["@mozilla.org/widget/transferable;1"]
.createInstance();
trans = trans.QueryInterface(Components.interfaces.nsITransferable);
trans.addDataFlavor("text/unicode");
var clipboard = Components.classes["@mozilla.org/widget/clipboard;1"]
.getService();
clipboard = clipboard.QueryInterface(Components.interfaces.nsIClipboard);
clipboard.getData(trans, clipboard.kGlobalClipboard);
var str = new Object();
var strLen = new Object();
try {
trans.getTransferData("text/unicode", str, strLen);
} catch(e) {
// NS_ERROR_FAILURE will occur if the transferable object has no
// text/unicode data in it. In that case, it's not an error:
if (e instanceof Components.interfaces.nsIXPCException &&
e.result == Components.results.NS_ERROR_FAILURE) {
return null;
} else {
// if we don't know how to handle it then rethrow
throw e;
}
}
if (!str) return null;
str = str.value.QueryInterface(Components.interfaces.nsISupportsString);
if (!str) return null;
str = str.data.substring(0, strLen.value / 2);
if (!str) return null;
return str;
}
function setClipboardText(text) {
var helper = Components.classes["@mozilla.org/widget/clipboardhelper;1"]
.getService(Components.interfaces.nsIClipboardHelper);
helper.copyString(text);
}
function selectContentDiv() {
// Set selection
var selection = window.getSelection();
selection.removeAllRanges();
selection.selectAllChildren(content);
}
function selectContentInput() {
contentInput.select();
contentInput.focus();
}
function test_dom_oncopy() {
// Setup an oncopy event handler, fire copy. Ensure that the event
// handler was called, and the clipboard contents have set to CONTENT TEXT.
// Test firing oncopy event on ctrl-c:
selectContentDiv();
var oncopy_fired = false;
content.oncopy = function() { oncopy_fired = true; };
try {
synthesizeKey("c", {accelKey: 1});
ok(oncopy_fired, "copy event firing on DOM element");
is(getClipboardText(), "CONTENT TEXT",
"copy on DOM element set clipboard correctly");
} finally {
content.oncopy = null;
}
}
function test_dom_oncut() {
// Setup an oncut event handler, fire cut. Ensure that the event handler
// was called. The <div> doesn't handle a cut, so ensure that the
// clipboard text is clipboardInitialValue, NOT "CONTENT TEXT".
selectContentDiv();
var oncut_fired = false;
content.oncut = function() { oncut_fired = true; };
try {
synthesizeKey("x", {accelKey: 1});
ok(!oncut_fired, "cut event firing on DOM element")
is(getClipboardText(), clipboardInitialValue,
"cut on DOM element did not modify clipboard");
} finally {
content.oncut = null;
}
}
function test_dom_onpaste() {
// Setup an onpaste event handler, fire paste. Ensure that the event
// handler was called.
selectContentDiv();
var onpaste_fired = false;
content.onpaste = function() { onpaste_fired = true; };
try {
synthesizeKey("v", {accelKey: 1});
ok(!onpaste_fired, "paste event firing on DOM element");
} finally {
content.onpaste = null;
}
}
function test_dom_oncopy_abort() {
// Setup an oncopy event handler that aborts the copy, and fire the copy
// event. Ensure that the event handler was fired, and the clipboard
// contents have not been modified.
selectContentDiv();
var oncopy_fired = false;
content.oncopy = function() { oncopy_fired = true; return false; };
try {
synthesizeKey("c", {accelKey: 1});
ok(oncopy_fired, "copy event (to-be-cancelled) firing on DOM element");
is(getClipboardText(), clipboardInitialValue,
"aborted copy on DOM element did not modify clipboard");
} finally {
content.oncopy = null;
}
}
function test_input_oncopy() {
// Setup an oncopy event handler, fire copy. Ensure that the event
// handler was called, and the clipboard contents have set to INPUT TEXT.
// Test firing oncopy event on ctrl-c:
selectContentInput();
var oncopy_fired = false;
contentInput.oncopy = function() { oncopy_fired = true; };
try {
synthesizeKey("c", {accelKey: 1});
ok(oncopy_fired, "copy event firing on plaintext editor");
is(getClipboardText(), "INPUT TEXT",
"copy on plaintext editor set clipboard correctly");
} finally {
contentInput.oncopy = null;
}
}
function test_input_oncut() {
// Setup an oncut event handler, and fire cut. Ensure that the event
// handler was fired, the clipboard contains the INPUT TEXT, and
// that the input itself is empty.
selectContentInput();
var oncut_fired = false;
contentInput.oncut = function() { oncut_fired = true; };
try {
synthesizeKey("x", {accelKey: 1});
ok(oncut_fired, "cut event firing on plaintext editor");
is(getClipboardText(), "INPUT TEXT",
"cut on plaintext editor set clipboard correctly");
is(contentInput.value, "",
"cut on plaintext editor emptied editor");
} finally {
contentInput.oncut = null;
}
}
function test_input_onpaste() {
// Setup an onpaste event handler, and fire paste. Ensure that the event
// handler was fired, the clipboard contents didn't change, and that the
// input value did change (ie. paste succeeded).
selectContentInput();
var onpaste_fired = false;
contentInput.onpaste = function() { onpaste_fired = true; };
try {
synthesizeKey("v", {accelKey: 1});
ok(onpaste_fired, "paste event firing on plaintext editor");
is(getClipboardText(), clipboardInitialValue,
"paste on plaintext editor did not modify clipboard contents");
is(contentInput.value, clipboardInitialValue,
"paste on plaintext editor did modify editor value");
} finally {
contentInput.onpaste = null;
}
}
function test_input_oncopy_abort() {
// Setup an oncopy event handler, fire copy. Ensure that the event
// handler was called, and that the clipboard value did NOT change.
selectContentInput();
var oncopy_fired = false;
contentInput.oncopy = function() { oncopy_fired = true; return false; };
try {
synthesizeKey("c", {accelKey: 1});
ok(oncopy_fired, "copy event (to-be-cancelled) firing on plaintext editor");
is(getClipboardText(), clipboardInitialValue,
"aborted copy on plaintext editor did not modify clipboard");
} finally {
contentInput.oncopy = null;
}
}
function test_input_oncut_abort() {
// Setup an oncut event handler, and fire cut. Ensure that the event
// handler was fired, the clipboard contains the INPUT TEXT, and
// that the input itself is empty.
selectContentInput();
var oncut_fired = false;
contentInput.oncut = function() { oncut_fired = true; return false; };
try {
synthesizeKey("x", {accelKey: 1});
ok(oncut_fired, "cut event (to-be-cancelled) firing on plaintext editor");
is(getClipboardText(), clipboardInitialValue,
"aborted cut on plaintext editor did not modify clipboard.");
is(contentInput.value, "INPUT TEXT",
"aborted cut on plaintext editor did not modify editor contents");
} finally {
contentInput.oncut = null;
}
}
function test_input_onpaste_abort() {
// Setup an onpaste event handler, and fire paste. Ensure that the event
// handler was fired, the clipboard contents didn't change, and that the
// input value did change (ie. paste succeeded).
selectContentInput();
var onpaste_fired = false;
contentInput.onpaste = function() { onpaste_fired = true; return false; };
try {
synthesizeKey("v", {accelKey: 1});
ok(onpaste_fired,
"paste event (to-be-cancelled) firing on plaintext editor");
is(getClipboardText(), clipboardInitialValue,
"aborted paste on plaintext editor did not modify clipboard");
is(contentInput.value, "INPUT TEXT",
"aborted paste on plaintext editor did not modify modified editor value");
} finally {
contentInput.onpaste = null;
}
}
</script>
</pre>
</body>
</html>

View File

@ -1847,14 +1847,11 @@ PRBool nsHTMLEditor::HavePrivateHTMLFlavor(nsIClipboard *aClipboard)
NS_IMETHODIMP nsHTMLEditor::Paste(PRInt32 aSelectionType)
{
ForceCompositionEnd();
PRBool preventDefault;
nsresult rv = FireClipboardEvent(NS_PASTE, &preventDefault);
if (NS_FAILED(rv) || preventDefault)
return rv;
if (!FireClipboardEvent(NS_PASTE))
return NS_OK;
// Get Clipboard Service
nsresult rv;
nsCOMPtr<nsIClipboard> clipboard(do_GetService("@mozilla.org/widget/clipboard;1", &rv));
if (NS_FAILED(rv))
return rv;
@ -1932,12 +1929,8 @@ NS_IMETHODIMP nsHTMLEditor::Paste(PRInt32 aSelectionType)
NS_IMETHODIMP nsHTMLEditor::PasteTransferable(nsITransferable *aTransferable)
{
ForceCompositionEnd();
PRBool preventDefault;
nsresult rv = FireClipboardEvent(NS_PASTE, &preventDefault);
if (NS_FAILED(rv) || preventDefault)
return rv;
if (!FireClipboardEvent(NS_PASTE))
return NS_OK;
// handle transferable hooks
nsCOMPtr<nsIDOMDocument> domdoc;
@ -1948,10 +1941,8 @@ NS_IMETHODIMP nsHTMLEditor::PasteTransferable(nsITransferable *aTransferable)
// Beware! This may flush notifications via synchronous
// ScrollSelectionIntoView.
nsAutoString contextStr, infoStr;
rv = InsertFromTransferable(aTransferable, nsnull, contextStr, infoStr,
nsnull, 0, PR_TRUE);
return rv;
return InsertFromTransferable(aTransferable, nsnull, contextStr, infoStr,
nsnull, 0, PR_TRUE);
}
//

View File

@ -60,6 +60,7 @@
#include "nsITransferable.h"
#include "nsIDragService.h"
#include "nsIDOMNSUIEvent.h"
#include "nsCopySupport.h"
// Misc
#include "nsEditorUtils.h"
@ -409,14 +410,11 @@ NS_IMETHODIMP nsPlaintextEditor::DoDrag(nsIDOMEvent *aDragEvent)
NS_IMETHODIMP nsPlaintextEditor::Paste(PRInt32 aSelectionType)
{
ForceCompositionEnd();
PRBool preventDefault;
nsresult rv = FireClipboardEvent(NS_PASTE, &preventDefault);
if (NS_FAILED(rv) || preventDefault)
return rv;
if (!FireClipboardEvent(NS_PASTE))
return NS_OK;
// Get Clipboard Service
nsresult rv;
nsCOMPtr<nsIClipboard> clipboard(do_GetService("@mozilla.org/widget/clipboard;1", &rv));
if ( NS_FAILED(rv) )
return rv;
@ -446,12 +444,8 @@ NS_IMETHODIMP nsPlaintextEditor::Paste(PRInt32 aSelectionType)
NS_IMETHODIMP nsPlaintextEditor::PasteTransferable(nsITransferable *aTransferable)
{
ForceCompositionEnd();
PRBool preventDefault;
nsresult rv = FireClipboardEvent(NS_PASTE, &preventDefault);
if (NS_FAILED(rv) || preventDefault)
return rv;
if (!FireClipboardEvent(NS_PASTE))
return NS_OK;
if (!IsModifiable())
return NS_OK;
@ -464,9 +458,7 @@ NS_IMETHODIMP nsPlaintextEditor::PasteTransferable(nsITransferable *aTransferabl
// Beware! This may flush notifications via synchronous
// ScrollSelectionIntoView.
rv = InsertTextFromTransferable(aTransferable, nsnull, nsnull, PR_TRUE);
return rv;
return InsertTextFromTransferable(aTransferable, nsnull, nsnull, PR_TRUE);
}
NS_IMETHODIMP nsPlaintextEditor::CanPaste(PRInt32 aSelectionType, PRBool *aCanPaste)

View File

@ -1142,128 +1142,66 @@ nsPlaintextEditor::Redo(PRUint32 aCount)
return result;
}
nsresult nsPlaintextEditor::GetClipboardEventTarget(nsIDOMNode** aEventTarget)
PRBool
nsPlaintextEditor::CanCutOrCopy()
{
NS_ENSURE_ARG_POINTER(aEventTarget);
*aEventTarget = nsnull;
nsCOMPtr<nsISelection> selection;
nsresult res = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(res))
return res;
if (NS_FAILED(GetSelection(getter_AddRefs(selection))))
return PR_FALSE;
return nsCopySupport::GetClipboardEventTarget(selection, aEventTarget);
PRBool isCollapsed;
selection->GetIsCollapsed(&isCollapsed);
return !isCollapsed;
}
nsresult nsPlaintextEditor::FireClipboardEvent(PRUint32 msg,
PRBool* aPreventDefault)
PRBool
nsPlaintextEditor::FireClipboardEvent(PRInt32 aType)
{
*aPreventDefault = PR_FALSE;
if (aType == NS_PASTE)
ForceCompositionEnd();
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
if (!ps)
return NS_ERROR_NOT_INITIALIZED;
nsCOMPtr<nsIPresShell> presShell = do_QueryReferent(mPresShellWeak);
NS_ENSURE_TRUE(presShell, PR_FALSE);
// Unsafe to fire event during reflow (bug 396108)
PRBool isReflowing = PR_TRUE;
nsresult rv = ps->IsReflowLocked(&isReflowing);
if (NS_FAILED(rv) || isReflowing)
return NS_OK;
nsCOMPtr<nsISelection> selection;
if (NS_FAILED(GetSelection(getter_AddRefs(selection))))
return PR_FALSE;
nsCOMPtr<nsIDOMNode> eventTarget;
rv = GetClipboardEventTarget(getter_AddRefs(eventTarget));
if (NS_FAILED(rv))
// On failure to get event target, just forget about it and don't fire.
return NS_OK;
if (!nsCopySupport::FireClipboardEvent(aType, presShell, selection))
return PR_FALSE;
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent evt(PR_TRUE, msg);
nsEventDispatcher::Dispatch(eventTarget, ps->GetPresContext(), &evt,
nsnull, &status);
// if event handler return'd false (PreventDefault)
if (status == nsEventStatus_eConsumeNoDefault)
*aPreventDefault = PR_TRUE;
// Did the event handler cause the editor to be destroyed? (ie. the input
// element was removed from the document) Don't proceed with command,
// could crash, definitely does during paste.
if (mDidPreDestroy)
return NS_ERROR_NOT_INITIALIZED;
return NS_OK;
// If the event handler caused the editor to be destroyed, return false.
// Otherwise return true to indicate that the event was not cancelled.
return !mDidPreDestroy;
}
NS_IMETHODIMP nsPlaintextEditor::Cut()
{
PRBool preventDefault;
nsresult rv = FireClipboardEvent(NS_CUT, &preventDefault);
if (NS_FAILED(rv) || preventDefault)
return rv;
nsCOMPtr<nsISelection> selection;
rv = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(rv))
return rv;
PRBool isCollapsed;
if (NS_SUCCEEDED(selection->GetIsCollapsed(&isCollapsed)) && isCollapsed)
return NS_OK; // just return ok so no JS error is thrown
// ps should be guaranteed by FireClipboardEvent not failing
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
rv = ps->DoCopy();
if (NS_SUCCEEDED(rv))
rv = DeleteSelection(eNone);
return rv;
if (FireClipboardEvent(NS_CUT))
return DeleteSelection(eNone);
return NS_OK;
}
NS_IMETHODIMP nsPlaintextEditor::CanCut(PRBool *aCanCut)
{
NS_ENSURE_ARG_POINTER(aCanCut);
*aCanCut = PR_FALSE;
nsCOMPtr<nsISelection> selection;
nsresult rv = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(rv)) return rv;
PRBool isCollapsed;
rv = selection->GetIsCollapsed(&isCollapsed);
if (NS_FAILED(rv)) return rv;
*aCanCut = !isCollapsed && IsModifiable();
*aCanCut = IsModifiable() && CanCutOrCopy();
return NS_OK;
}
NS_IMETHODIMP nsPlaintextEditor::Copy()
{
PRBool preventDefault;
nsresult rv = FireClipboardEvent(NS_COPY, &preventDefault);
if (NS_FAILED(rv) || preventDefault)
return rv;
// ps should be guaranteed by FireClipboardEvent not failing
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
return ps->DoCopy();
FireClipboardEvent(NS_COPY);
return NS_OK;
}
NS_IMETHODIMP nsPlaintextEditor::CanCopy(PRBool *aCanCopy)
{
NS_ENSURE_ARG_POINTER(aCanCopy);
*aCanCopy = PR_FALSE;
nsCOMPtr<nsISelection> selection;
nsresult rv = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(rv)) return rv;
PRBool isCollapsed;
rv = selection->GetIsCollapsed(&isCollapsed);
if (NS_FAILED(rv)) return rv;
*aCanCopy = !isCollapsed;
*aCanCopy = CanCutOrCopy();
return NS_OK;
}
// Shared between OutputToString and OutputToStream
NS_IMETHODIMP
nsPlaintextEditor::GetAndInitDocEncoder(const nsAString& aFormatType,

View File

@ -219,10 +219,8 @@ protected:
PRBool mIgnoreSpuriousDragEvent;
NS_IMETHOD IgnoreSpuriousDragEvent(PRBool aIgnoreSpuriousDragEvent) {mIgnoreSpuriousDragEvent = aIgnoreSpuriousDragEvent; return NS_OK;}
// Wrapper for nsCopySupport::GetClipboardEventTarget, finds target to fire
// [cut,copy,paste] and [beforecut,beforecopy,beforepaste] events at.
nsresult GetClipboardEventTarget(nsIDOMNode** aEventTarget);
nsresult FireClipboardEvent(PRUint32 msg, PRBool* aPreventDefault);
PRBool CanCutOrCopy();
PRBool FireClipboardEvent(PRInt32 aType);
// Data members
protected:

View File

@ -398,9 +398,6 @@ private:
nsresult GetDocumentSelection(nsISelection **aSelection);
nsresult GetClipboardEventTarget(nsIDOMNode **aEventTarget);
nsresult FireClipboardEvent(PRUint32 msg, PRBool* aPreventDefault);
void DestroyPresShell();
#ifdef NS_PRINTING
@ -2410,8 +2407,7 @@ DocumentViewerImpl::CreateDeviceContext(nsIView* aContainerView)
}
// Return the selection for the document. Note that text fields have their
// own selection, which cannot be accessed with this method. Use
// mPresShell->GetSelectionForCopy() instead.
// own selection, which cannot be accessed with this method.
nsresult DocumentViewerImpl::GetDocumentSelection(nsISelection **aSelection)
{
NS_ENSURE_ARG_POINTER(aSelection);
@ -2431,25 +2427,12 @@ nsresult DocumentViewerImpl::GetDocumentSelection(nsISelection **aSelection)
* nsIContentViewerEdit
* ======================================================================================== */
NS_IMETHODIMP DocumentViewerImpl::Search()
{
// Nothing to do here.
return NS_OK;
}
NS_IMETHODIMP DocumentViewerImpl::GetSearchable(PRBool *aSearchable)
{
// Nothing to do here.
*aSearchable = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP DocumentViewerImpl::ClearSelection()
{
nsresult rv;
nsCOMPtr<nsISelection> selection;
// use mPresShell->GetSelectionForCopy() ?
// use nsCopySupport::GetSelectionForCopy() ?
rv = GetDocumentSelection(getter_AddRefs(selection));
if (NS_FAILED(rv)) return rv;
@ -2464,7 +2447,7 @@ NS_IMETHODIMP DocumentViewerImpl::SelectAll()
nsCOMPtr<nsISelection> selection;
nsresult rv;
// use mPresShell->GetSelectionForCopy() ?
// use nsCopySupport::GetSelectionForCopy() ?
rv = GetDocumentSelection(getter_AddRefs(selection));
if (NS_FAILED(rv)) return rv;
@ -2494,12 +2477,8 @@ NS_IMETHODIMP DocumentViewerImpl::SelectAll()
NS_IMETHODIMP DocumentViewerImpl::CopySelection()
{
PRBool preventDefault;
nsresult rv = FireClipboardEvent(NS_COPY, &preventDefault);
if (NS_FAILED(rv) || preventDefault)
return rv;
return mPresShell->DoCopy();
nsCopySupport::FireClipboardEvent(NS_COPY, mPresShell, nsnull);
return NS_OK;
}
NS_IMETHODIMP DocumentViewerImpl::CopyLinkLocation()
@ -2532,118 +2511,47 @@ NS_IMETHODIMP DocumentViewerImpl::CopyImage(PRInt32 aCopyFlags)
return nsCopySupport::ImageCopy(node, aCopyFlags);
}
nsresult DocumentViewerImpl::GetClipboardEventTarget(nsIDOMNode** aEventTarget)
{
NS_ENSURE_ARG_POINTER(aEventTarget);
*aEventTarget = nsnull;
if (!mPresShell)
return NS_ERROR_NOT_INITIALIZED;
nsCOMPtr<nsISelection> sel;
nsresult rv = mPresShell->GetSelectionForCopy(getter_AddRefs(sel));
if (NS_FAILED(rv))
return rv;
if (!sel)
return NS_ERROR_FAILURE;
return nsCopySupport::GetClipboardEventTarget(sel, aEventTarget);
}
nsresult DocumentViewerImpl::FireClipboardEvent(PRUint32 msg,
PRBool* aPreventDefault)
{
*aPreventDefault = PR_FALSE;
NS_ENSURE_TRUE(mPresContext, NS_ERROR_NOT_INITIALIZED);
NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_INITIALIZED);
// It seems to be unsafe to fire an event handler during reflow (bug 393696)
PRBool isReflowing = PR_TRUE;
nsresult rv = mPresShell->IsReflowLocked(&isReflowing);
if (NS_FAILED(rv) || isReflowing)
return NS_OK;
nsCOMPtr<nsIDOMNode> eventTarget;
rv = GetClipboardEventTarget(getter_AddRefs(eventTarget));
if (NS_FAILED(rv))
// On failure to get event target, just forget about it and don't fire.
return NS_OK;
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent evt(PR_TRUE, msg);
nsEventDispatcher::Dispatch(eventTarget, mPresContext, &evt, nsnull,
&status);
// if event handler return'd false (PreventDefault)
if (status == nsEventStatus_eConsumeNoDefault)
*aPreventDefault = PR_TRUE;
// Ensure that the calling function can use mPresShell -- if the event
// handler closed this window, mPresShell will be gone.
NS_ENSURE_STATE(mPresShell);
return NS_OK;
}
NS_IMETHODIMP DocumentViewerImpl::GetCopyable(PRBool *aCopyable)
{
NS_ENSURE_ARG_POINTER(aCopyable);
*aCopyable = PR_FALSE;
NS_ENSURE_STATE(mPresShell);
nsCOMPtr<nsISelection> selection;
nsresult rv = mPresShell->GetSelectionForCopy(getter_AddRefs(selection));
if (NS_FAILED(rv))
return rv;
PRBool isCollapsed;
selection->GetIsCollapsed(&isCollapsed);
*aCopyable = !isCollapsed;
return NS_OK;
}
NS_IMETHODIMP DocumentViewerImpl::CutSelection()
{
// preventDefault's value is ignored because cut from the document has no
// default behaviour.
PRBool preventDefault;
return FireClipboardEvent(NS_CUT, &preventDefault);
}
NS_IMETHODIMP DocumentViewerImpl::GetCutable(PRBool *aCutable)
{
NS_ENSURE_ARG_POINTER(aCutable);
*aCutable = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP DocumentViewerImpl::Paste()
{
// preventDefault's value is ignored because paste into the document has no
// default behaviour.
PRBool preventDefault;
return FireClipboardEvent(NS_PASTE, &preventDefault);
}
NS_IMETHODIMP DocumentViewerImpl::GetPasteable(PRBool *aPasteable)
{
NS_ENSURE_ARG_POINTER(aPasteable);
*aPasteable = PR_FALSE;
*aCopyable = nsCopySupport::CanCopy(mDocument);
return NS_OK;
}
/* AString getContents (in string mimeType, in boolean selectionOnly); */
NS_IMETHODIMP DocumentViewerImpl::GetContents(const char *mimeType, PRBool selectionOnly, nsAString& aOutValue)
{
aOutValue.Truncate();
NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_INITIALIZED);
return mPresShell->DoGetContents(nsDependentCString(mimeType), 0, selectionOnly, aOutValue);
NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_INITIALIZED);
// Now we have the selection. Make sure it's nonzero:
nsCOMPtr<nsISelection> sel;
if (selectionOnly) {
nsCopySupport::GetSelectionForCopy(mDocument, getter_AddRefs(sel));
NS_ENSURE_TRUE(sel, NS_ERROR_FAILURE);
PRBool isCollapsed;
sel->GetIsCollapsed(&isCollapsed);
if (isCollapsed)
return NS_OK;
}
// call the copy code
return nsCopySupport::GetContents(nsDependentCString(mimeType), 0, sel,
mDocument, aOutValue);
}
/* readonly attribute boolean canGetContents; */
NS_IMETHODIMP DocumentViewerImpl::GetCanGetContents(PRBool *aCanGetContents)
{
return GetCopyable(aCanGetContents);
NS_ENSURE_ARG_POINTER(aCanGetContents);
*aCanGetContents = PR_FALSE;
NS_ENSURE_STATE(mDocument);
*aCanGetContents = nsCopySupport::CanCopy(mDocument);
return NS_OK;
}
#ifdef XP_MAC

View File

@ -127,8 +127,8 @@ typedef struct CapturingContentInfo {
} CapturingContentInfo;
#define NS_IPRESSHELL_IID \
{ 0xe5e070ce, 0xbc17, 0x4b5f, \
{ 0xb2, 0x21, 0xbf, 0xc3, 0xe1, 0x68, 0xbe, 0x9b } }
{ 0x0e170e5f, 0xf6d4, 0x44c5, \
{ 0xbc, 0x2c, 0x44, 0x94, 0x20, 0x7e, 0xcc, 0x30 } }
// Constants for ScrollContentIntoView() function
#define NS_PRESSHELL_SCROLL_TOP 0
@ -578,27 +578,11 @@ public:
*/
NS_IMETHOD NotifyDestroyingFrame(nsIFrame* aFrame) = 0;
/**
* Notify the Clipboard that we have something to copy.
*/
NS_IMETHOD DoCopy() = 0;
/**
* Get the selection of the focussed element (either the page selection,
* or the selection for a text field).
*/
NS_IMETHOD GetSelectionForCopy(nsISelection** outSelection) = 0;
/**
* Get link location.
*/
NS_IMETHOD GetLinkLocation(nsIDOMNode* aNode, nsAString& aLocation) = 0;
/**
* Get the doc or the selection as text or html.
*/
NS_IMETHOD DoGetContents(const nsACString& aMimeType, PRUint32 aFlags, PRBool aSelectionOnly, nsAString& outValue) = 0;
/**
* Get the caret, if it exists. AddRefs it.
*/

View File

@ -738,12 +738,8 @@ public:
NS_IMETHOD SetIgnoreFrameDestruction(PRBool aIgnore);
NS_IMETHOD NotifyDestroyingFrame(nsIFrame* aFrame);
NS_IMETHOD DoCopy();
NS_IMETHOD GetSelectionForCopy(nsISelection** outSelection);
NS_IMETHOD GetLinkLocation(nsIDOMNode* aNode, nsAString& aLocationString);
NS_IMETHOD DoGetContents(const nsACString& aMimeType, PRUint32 aFlags, PRBool aSelectionOnly, nsAString& outValue);
NS_IMETHOD CaptureHistoryState(nsILayoutHistoryState** aLayoutHistoryState, PRBool aLeavingPage);
@ -4298,57 +4294,6 @@ NS_IMETHODIMP PresShell::GetLinkLocation(nsIDOMNode* aNode, nsAString& aLocation
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
PresShell::GetSelectionForCopy(nsISelection** outSelection)
{
nsresult rv = NS_OK;
*outSelection = nsnull;
if (!mDocument) return NS_ERROR_FAILURE;
nsCOMPtr<nsIContent> content;
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
if (fm) {
nsCOMPtr<nsIDOMWindow> window = do_QueryInterface(mDocument->GetWindow());
nsCOMPtr<nsIDOMElement> focusedElement;
fm->GetFocusedElementForWindow(window, PR_FALSE, nsnull, getter_AddRefs(focusedElement));
content = do_QueryInterface(focusedElement);
}
nsCOMPtr<nsISelection> sel;
if (content)
{
//check to see if we need to get selection from frame
//optimization that MAY need to be expanded as more things implement their own "selection"
nsCOMPtr<nsIDOMNSHTMLInputElement> htmlInputElement(do_QueryInterface(content));
nsCOMPtr<nsIDOMNSHTMLTextAreaElement> htmlTextAreaElement(do_QueryInterface(content));
if (htmlInputElement || htmlTextAreaElement)
{
nsIFrame *htmlInputFrame = content->GetPrimaryFrame();
if (!htmlInputFrame) return NS_ERROR_FAILURE;
nsCOMPtr<nsISelectionController> selCon;
rv = htmlInputFrame->
GetSelectionController(mPresContext,getter_AddRefs(selCon));
if (NS_FAILED(rv)) return rv;
if (!selCon) return NS_ERROR_FAILURE;
rv = selCon->GetSelection(nsISelectionController::SELECTION_NORMAL,
getter_AddRefs(sel));
}
}
if (!sel) {
sel = mSelection->GetSelection(nsISelectionController::SELECTION_NORMAL);
rv = NS_OK;
}
*outSelection = sel;
NS_IF_ADDREF(*outSelection);
return rv;
}
NS_IMETHODIMP_(void)
PresShell::DispatchSynthMouseMove(nsGUIEvent *aEvent,
PRBool aFlushOnHoverChange)
@ -4405,67 +4350,6 @@ PresShell::ClearMouseCapture(nsIView* aView)
gCaptureInfo.mAllowed = PR_FALSE;
}
NS_IMETHODIMP
PresShell::DoGetContents(const nsACString& aMimeType, PRUint32 aFlags, PRBool aSelectionOnly, nsAString& aOutValue)
{
aOutValue.Truncate();
if (!mDocument) return NS_ERROR_FAILURE;
nsresult rv;
nsCOMPtr<nsISelection> sel;
// Now we have the selection. Make sure it's nonzero:
if (aSelectionOnly)
{
rv = GetSelectionForCopy(getter_AddRefs(sel));
if (NS_FAILED(rv)) return rv;
if (!sel) return NS_ERROR_FAILURE;
PRBool isCollapsed;
sel->GetIsCollapsed(&isCollapsed);
if (isCollapsed)
return NS_OK;
}
// call the copy code
return nsCopySupport::GetContents(aMimeType, aFlags, sel,
mDocument, aOutValue);
}
NS_IMETHODIMP
PresShell::DoCopy()
{
if (!mDocument) return NS_ERROR_FAILURE;
nsCOMPtr<nsISelection> sel;
nsresult rv = GetSelectionForCopy(getter_AddRefs(sel));
if (NS_FAILED(rv))
return rv;
if (!sel)
return NS_ERROR_FAILURE;
// Now we have the selection. Make sure it's nonzero:
PRBool isCollapsed;
sel->GetIsCollapsed(&isCollapsed);
if (isCollapsed)
return NS_OK;
// call the copy code
rv = nsCopySupport::HTMLCopy(sel, mDocument, nsIClipboard::kGlobalClipboard);
if (NS_FAILED(rv))
return rv;
// Now that we have copied, update the Paste menu item
nsPIDOMWindow *domWindow = mDocument->GetWindow();
if (domWindow)
{
domWindow->UpdateCommands(NS_LITERAL_STRING("clipboard"));
}
return NS_OK;
}
NS_IMETHODIMP
PresShell::CaptureHistoryState(nsILayoutHistoryState** aState, PRBool aLeavingPage)
{