summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--devtools/client/framework/test/browser_toolbox_textbox_context_menu.js9
-rw-r--r--devtools/client/inspector/computed/test/browser_computed_search-filter_context-menu.js9
-rw-r--r--devtools/client/inspector/rules/test/browser_rules_search-filter_context-menu.js9
-rw-r--r--devtools/client/inspector/test/browser_inspector_search-filter_context-menu.js7
-rw-r--r--editor/libeditor/HTMLEditorDataTransfer.cpp7
-rw-r--r--editor/libeditor/TextEditorDataTransfer.cpp7
-rw-r--r--editor/libeditor/tests/chrome.ini1
-rw-r--r--editor/libeditor/tests/mochitest.ini2
-rw-r--r--editor/libeditor/tests/test_pasteImgTextarea.html20
-rw-r--r--editor/libeditor/tests/test_pasteImgTextarea.xul27
-rw-r--r--widget/windows/nsClipboard.cpp2
-rw-r--r--widget/windows/nsDataObj.cpp99
-rw-r--r--widget/windows/nsDataObj.h1
13 files changed, 156 insertions, 44 deletions
diff --git a/devtools/client/framework/test/browser_toolbox_textbox_context_menu.js b/devtools/client/framework/test/browser_toolbox_textbox_context_menu.js
index 2e5f3210e4..e2e9612553 100644
--- a/devtools/client/framework/test/browser_toolbox_textbox_context_menu.js
+++ b/devtools/client/framework/test/browser_toolbox_textbox_context_menu.js
@@ -36,15 +36,12 @@ add_task(function* () {
is(cmdDelete.getAttribute("disabled"), "true", "cmdDelete is disabled");
is(cmdSelectAll.getAttribute("disabled"), "true", "cmdSelectAll is disabled");
- // Cut/Copy items are enabled in context menu even if there
- // is no selection. See also Bug 1303033
+ // Cut/Copy/Paste items are enabled in context menu even if there
+ // is no selection. See also Bug 1303033, and 1317322
is(cmdCut.getAttribute("disabled"), "", "cmdCut is enabled");
is(cmdCopy.getAttribute("disabled"), "", "cmdCopy is enabled");
- if (isWindows()) {
- // emptyClipboard only works on Windows (666254), assert paste only for this OS.
- is(cmdPaste.getAttribute("disabled"), "true", "cmdPaste is disabled");
- }
+ is(cmdPaste.getAttribute("disabled"), "", "cmdPaste is enabled");
yield cleanup(toolbox);
});
diff --git a/devtools/client/inspector/computed/test/browser_computed_search-filter_context-menu.js b/devtools/client/inspector/computed/test/browser_computed_search-filter_context-menu.js
index b5dbe44754..b04a247f5b 100644
--- a/devtools/client/inspector/computed/test/browser_computed_search-filter_context-menu.js
+++ b/devtools/client/inspector/computed/test/browser_computed_search-filter_context-menu.js
@@ -45,15 +45,12 @@ add_task(function* () {
is(cmdDelete.getAttribute("disabled"), "true", "cmdDelete is disabled");
is(cmdSelectAll.getAttribute("disabled"), "true", "cmdSelectAll is disabled");
- // Cut/Copy items are enabled in context menu even if there
- // is no selection. See also Bug 1303033
+ // Cut/Copy/Paste items are enabled in context menu even if there is no
+ // selection. See also Bug 1303033, and 1317322
is(cmdCut.getAttribute("disabled"), "", "cmdCut is enabled");
is(cmdCopy.getAttribute("disabled"), "", "cmdCopy is enabled");
- if (isWindows()) {
- // emptyClipboard only works on Windows (666254), assert paste only for this OS.
- is(cmdPaste.getAttribute("disabled"), "true", "cmdPaste is disabled");
- }
+ is(cmdPaste.getAttribute("disabled"), "", "cmdPaste is enabled");
info("Closing context menu");
let onContextMenuHidden = once(searchContextMenu, "popuphidden");
diff --git a/devtools/client/inspector/rules/test/browser_rules_search-filter_context-menu.js b/devtools/client/inspector/rules/test/browser_rules_search-filter_context-menu.js
index 349f1b9b36..d66df91ab1 100644
--- a/devtools/client/inspector/rules/test/browser_rules_search-filter_context-menu.js
+++ b/devtools/client/inspector/rules/test/browser_rules_search-filter_context-menu.js
@@ -44,15 +44,12 @@ add_task(function* () {
is(cmdDelete.getAttribute("disabled"), "true", "cmdDelete is disabled");
is(cmdSelectAll.getAttribute("disabled"), "true", "cmdSelectAll is disabled");
- // Cut/Copy items are enabled in context menu even if there
- // is no selection. See also Bug 1303033
+ // Cut/Copy/Paste items are enabled in context menu even if there is no
+ // selection. See also Bug 1303033, and 1317322
is(cmdCut.getAttribute("disabled"), "", "cmdCut is enabled");
is(cmdCopy.getAttribute("disabled"), "", "cmdCopy is enabled");
- if (isWindows()) {
- // emptyClipboard only works on Windows (666254), assert paste only for this OS.
- is(cmdPaste.getAttribute("disabled"), "true", "cmdPaste is disabled");
- }
+ is(cmdPaste.getAttribute("disabled"), "", "cmdPaste is enabled");
info("Closing context menu");
let onContextMenuHidden = once(searchContextMenu, "popuphidden");
diff --git a/devtools/client/inspector/test/browser_inspector_search-filter_context-menu.js b/devtools/client/inspector/test/browser_inspector_search-filter_context-menu.js
index 137456468c..7bd4b5e6fc 100644
--- a/devtools/client/inspector/test/browser_inspector_search-filter_context-menu.js
+++ b/devtools/client/inspector/test/browser_inspector_search-filter_context-menu.js
@@ -43,14 +43,11 @@ add_task(function* () {
is(cmdSelectAll.getAttribute("disabled"), "true", "cmdSelectAll is disabled");
// Cut/Copy items are enabled in context menu even if there
- // is no selection. See also Bug 1303033
+ // is no selection. See also Bug 1303033, and 1317322
is(cmdCut.getAttribute("disabled"), "", "cmdCut is enabled");
is(cmdCopy.getAttribute("disabled"), "", "cmdCopy is enabled");
- if (isWindows()) {
- // emptyClipboard only works on Windows (666254), assert paste only for this OS.
- is(cmdPaste.getAttribute("disabled"), "true", "cmdPaste is disabled");
- }
+ is(cmdPaste.getAttribute("disabled"), "", "cmdPaste is enabled");
info("Closing context menu");
let onContextMenuHidden = once(searchContextMenu, "popuphidden");
diff --git a/editor/libeditor/HTMLEditorDataTransfer.cpp b/editor/libeditor/HTMLEditorDataTransfer.cpp
index ed350c0dd3..c56fbead77 100644
--- a/editor/libeditor/HTMLEditorDataTransfer.cpp
+++ b/editor/libeditor/HTMLEditorDataTransfer.cpp
@@ -1538,6 +1538,13 @@ HTMLEditor::CanPaste(int32_t aSelectionType,
NS_ENSURE_ARG_POINTER(aCanPaste);
*aCanPaste = false;
+ // Always enable the paste command when inside of a HTML or XHTML document.
+ nsCOMPtr<nsIDocument> doc = GetDocument();
+ if (doc && doc->IsHTMLOrXHTML()) {
+ *aCanPaste = true;
+ return NS_OK;
+ }
+
// can't paste if readonly
if (!IsModifiable()) {
return NS_OK;
diff --git a/editor/libeditor/TextEditorDataTransfer.cpp b/editor/libeditor/TextEditorDataTransfer.cpp
index 0388aa4a84..2cc2906fa0 100644
--- a/editor/libeditor/TextEditorDataTransfer.cpp
+++ b/editor/libeditor/TextEditorDataTransfer.cpp
@@ -383,6 +383,13 @@ TextEditor::CanPaste(int32_t aSelectionType,
NS_ENSURE_ARG_POINTER(aCanPaste);
*aCanPaste = false;
+ // Always enable the paste command when inside of a HTML or XHTML document.
+ nsCOMPtr<nsIDocument> doc = GetDocument();
+ if (doc && doc->IsHTMLOrXHTML()) {
+ *aCanPaste = true;
+ return NS_OK;
+ }
+
// can't paste if readonly
if (!IsModifiable()) {
return NS_OK;
diff --git a/editor/libeditor/tests/chrome.ini b/editor/libeditor/tests/chrome.ini
index 98db300014..dd13370a5c 100644
--- a/editor/libeditor/tests/chrome.ini
+++ b/editor/libeditor/tests/chrome.ini
@@ -12,3 +12,4 @@ support-files = green.png
[test_set_document_title_transaction.html]
[test_texteditor_keyevent_handling.html]
skip-if = (debug && os=='win') || (os == 'linux') # Bug 1116205, leaks on windows debug, fails delete key on linux
+[test_pasteImgTextarea.xul]
diff --git a/editor/libeditor/tests/mochitest.ini b/editor/libeditor/tests/mochitest.ini
index 4df3f606b6..33b1648192 100644
--- a/editor/libeditor/tests/mochitest.ini
+++ b/editor/libeditor/tests/mochitest.ini
@@ -247,3 +247,5 @@ skip-if = toolkit == 'android'
[test_css_chrome_load_access.html]
skip-if = toolkit == 'android' # chrome urls not available due to packaging
[test_selection_move_commands.html]
+[test_pasteImgTextarea.html]
+skip-if = toolkit == 'android' # bug 1299578
diff --git a/editor/libeditor/tests/test_pasteImgTextarea.html b/editor/libeditor/tests/test_pasteImgTextarea.html
new file mode 100644
index 0000000000..3168ae7290
--- /dev/null
+++ b/editor/libeditor/tests/test_pasteImgTextarea.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script src="/tests/SimpleTest/SpawnTask.js"></script>
+<img id="i" src="green.png">
+<textarea id="t"></textarea>
+
+<script>
+let loaded = new Promise(resolve => addLoadEvent(resolve));
+ add_task(function*() {
+ yield loaded;
+ SpecialPowers.setCommandNode(window, document.getElementById("i"));
+ SpecialPowers.doCommand(window, "cmd_copyImageContents");
+ let input = document.getElementById("t");
+ input.focus();
+ var controller =
+ SpecialPowers.wrap(input).controllers.getControllerForCommand("cmd_paste");
+ is(controller.isCommandEnabled("cmd_paste"), true,
+ "paste should be enabled in html textareas when an image is on the clipboard");
+ });
+</script>
diff --git a/editor/libeditor/tests/test_pasteImgTextarea.xul b/editor/libeditor/tests/test_pasteImgTextarea.xul
new file mode 100644
index 0000000000..545027aa32
--- /dev/null
+++ b/editor/libeditor/tests/test_pasteImgTextarea.xul
@@ -0,0 +1,27 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
+<window xmlns:html="http://www.w3.org/1999/xhtml"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SpawnTask.js"></script>
+
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ <html:img id="i" src="green.png" />
+ <html:textarea id="t"></html:textarea>
+ </body>
+ <script type="text/javascript"><![CDATA[
+ let loaded = new Promise(resolve => addLoadEvent(resolve));
+ add_task(function*() {
+ yield loaded;
+ SpecialPowers.setCommandNode(window, document.getElementById("i"));
+ SpecialPowers.doCommand(window, "cmd_copyImageContents");
+ let input = document.getElementById("t");
+ input.focus();
+ var controller =
+ SpecialPowers.wrap(input).controllers.getControllerForCommand("cmd_paste");
+ is(controller.isCommandEnabled("cmd_paste"), false,
+ "paste should not be enabled in xul textareas when an image is on the clipboard");
+ });
+ ]]></script>
+</window>
diff --git a/widget/windows/nsClipboard.cpp b/widget/windows/nsClipboard.cpp
index 1afee34961..0db1dd3424 100644
--- a/widget/windows/nsClipboard.cpp
+++ b/widget/windows/nsClipboard.cpp
@@ -65,7 +65,7 @@ nsClipboard::nsClipboard() : nsBaseClipboard()
nsCOMPtr<nsIObserverService> observerService =
do_GetService("@mozilla.org/observer-service;1");
if (observerService)
- observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, PR_FALSE);
+ observerService->AddObserver(this, NS_XPCOM_WILL_SHUTDOWN_OBSERVER_ID, PR_FALSE);
}
//-------------------------------------------------------------------------
diff --git a/widget/windows/nsDataObj.cpp b/widget/windows/nsDataObj.cpp
index 02ec3b2fea..977a87c08c 100644
--- a/widget/windows/nsDataObj.cpp
+++ b/widget/windows/nsDataObj.cpp
@@ -443,6 +443,82 @@ STDMETHODIMP_(ULONG) nsDataObj::AddRef()
return m_cRef;
}
+namespace {
+class RemoveTempFileHelper : public nsIObserver
+{
+public:
+ explicit RemoveTempFileHelper(nsIFile* aTempFile)
+ : mTempFile(aTempFile)
+ {
+ MOZ_ASSERT(mTempFile);
+ }
+
+ // The attach method is seperate from the constructor as we may be addref-ing
+ // ourself, and we want to be sure someone has a strong reference to us.
+ void Attach()
+ {
+ // We need to listen to both the xpcom shutdown message and our timer, and
+ // fire when the first of either of these two messages is received.
+ nsresult rv;
+ mTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return;
+ }
+ mTimer->Init(this, 500, nsITimer::TYPE_ONE_SHOT);
+
+ nsCOMPtr<nsIObserverService> observerService =
+ do_GetService("@mozilla.org/observer-service;1");
+ if (NS_WARN_IF(!observerService)) {
+ mTimer->Cancel();
+ mTimer = nullptr;
+ return;
+ }
+ observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
+ }
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIOBSERVER
+
+private:
+ ~RemoveTempFileHelper()
+ {
+ if (mTempFile) {
+ mTempFile->Remove(false);
+ }
+ }
+
+ nsCOMPtr<nsIFile> mTempFile;
+ nsCOMPtr<nsITimer> mTimer;
+};
+
+NS_IMPL_ISUPPORTS(RemoveTempFileHelper, nsIObserver);
+
+NS_IMETHODIMP
+RemoveTempFileHelper::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData)
+{
+ // Let's be careful and make sure that we don't die immediately
+ RefPtr<RemoveTempFileHelper> grip = this;
+
+ // Make sure that we aren't called again by destroying references to ourself.
+ nsCOMPtr<nsIObserverService> observerService =
+ do_GetService("@mozilla.org/observer-service;1");
+ if (observerService) {
+ observerService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
+ }
+
+ if (mTimer) {
+ mTimer->Cancel();
+ mTimer = nullptr;
+ }
+
+ // Remove the tempfile
+ if (mTempFile) {
+ mTempFile->Remove(false);
+ mTempFile = nullptr;
+ }
+ return NS_OK;
+}
+} // namespace
//-----------------------------------------------------
STDMETHODIMP_(ULONG) nsDataObj::Release()
@@ -456,17 +532,12 @@ STDMETHODIMP_(ULONG) nsDataObj::Release()
// We have released our last ref on this object and need to delete the
// temp file. External app acting as drop target may still need to open the
// temp file. Addref a timer so it can delay deleting file and destroying
- // this object. Delete file anyway and destroy this obj if there's a problem.
+ // this object.
if (mCachedTempFile) {
- nsresult rv;
- mTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
- if (NS_SUCCEEDED(rv)) {
- mTimer->InitWithFuncCallback(nsDataObj::RemoveTempFile, this,
- 500, nsITimer::TYPE_ONE_SHOT);
- return AddRef();
- }
- mCachedTempFile->Remove(false);
+ RefPtr<RemoveTempFileHelper> helper =
+ new RemoveTempFileHelper(mCachedTempFile);
mCachedTempFile = nullptr;
+ helper->Attach();
}
delete this;
@@ -2153,13 +2224,3 @@ HRESULT nsDataObj::GetFileContents_IStream(FORMATETC& aFE, STGMEDIUM& aSTG)
return S_OK;
}
-
-void nsDataObj::RemoveTempFile(nsITimer* aTimer, void* aClosure)
-{
- nsDataObj *timedDataObj = static_cast<nsDataObj *>(aClosure);
- if (timedDataObj->mCachedTempFile) {
- timedDataObj->mCachedTempFile->Remove(false);
- timedDataObj->mCachedTempFile = nullptr;
- }
- timedDataObj->Release();
-}
diff --git a/widget/windows/nsDataObj.h b/widget/windows/nsDataObj.h
index 2d7fb75ee6..61f209e857 100644
--- a/widget/windows/nsDataObj.h
+++ b/widget/windows/nsDataObj.h
@@ -289,7 +289,6 @@ protected:
bool LookupArbitraryFormat(FORMATETC *aFormat, LPDATAENTRY *aDataEntry, BOOL aAddorUpdate);
bool CopyMediumData(STGMEDIUM *aMediumDst, STGMEDIUM *aMediumSrc, LPFORMATETC aFormat, BOOL aSetData);
- static void RemoveTempFile(nsITimer* aTimer, void* aClosure);
};