diff --git a/dom/html/nsHTMLDocument.cpp b/dom/html/nsHTMLDocument.cpp
index 3cc31eb2992e..0986f6f37c91 100644
--- a/dom/html/nsHTMLDocument.cpp
+++ b/dom/html/nsHTMLDocument.cpp
@@ -3251,8 +3251,11 @@ nsHTMLDocument::ExecCommand(const nsAString& commandID,
return false;
}
+ bool isCutCopy = (commandID.LowerCaseEqualsLiteral("cut") ||
+ commandID.LowerCaseEqualsLiteral("copy"));
+
// if editing is not on, bail
- if (!IsEditingOnAfterFlush()) {
+ if (!isCutCopy && !IsEditingOnAfterFlush()) {
rv.Throw(NS_ERROR_FAILURE);
return false;
}
@@ -3262,14 +3265,33 @@ nsHTMLDocument::ExecCommand(const nsAString& commandID,
return false;
}
+ // special case for cut & copy
+ // cut & copy are allowed in non editable documents
+ if (isCutCopy) {
+ if (!nsContentUtils::IsCutCopyAllowed()) {
+ return false;
+ }
+
+ // For cut & copy commands, we need the behaviour from nsWindowRoot::GetControllers
+ // which is to look at the focused element, and defer to a focused textbox's controller
+ // The code past taken by other commands in ExecCommand always uses the window directly,
+ // rather than deferring to the textbox, which is desireable for most editor commands,
+ // but not 'cut' and 'copy' (as those should allow copying out of embedded editors).
+ // This behaviour is invoked if we call DoCommand directly on the docShell.
+ nsCOMPtr docShell(mDocumentContainer);
+ if (docShell) {
+ nsresult res = docShell->DoCommand(cmdToDispatch.get());
+ return NS_SUCCEEDED(res);
+ }
+ return false;
+ }
+
if (commandID.LowerCaseEqualsLiteral("gethtml")) {
rv.Throw(NS_ERROR_FAILURE);
return false;
}
- bool restricted = commandID.LowerCaseEqualsLiteral("cut") ||
- commandID.LowerCaseEqualsLiteral("copy")||
- commandID.LowerCaseEqualsLiteral("paste");
+ bool restricted = commandID.LowerCaseEqualsLiteral("paste");
if (restricted && !nsContentUtils::IsCallerChrome()) {
rv = NS_ERROR_DOM_SECURITY_ERR;
return false;