Bug 1259517 - Make dropping images in editors work in e10s. r=baku

This commit is contained in:
Blake Kaplan 2016-05-19 16:47:44 -07:00
parent 8e4ef7176d
commit 70d89c7d92
8 changed files with 193 additions and 8 deletions

View File

@ -22,6 +22,8 @@ LowMemoryTitle=Warning: Low memory
LowMemoryMessage=A script on this page has been stopped due to a low memory condition.
SpeculationFailed=An unbalanced tree was written using document.write() causing data from the network to be reparsed. For more information https://developer.mozilla.org/en/Optimizing_Your_Pages_for_Speculative_Parsing
DocumentWriteIgnored=A call to document.write() from an asynchronously-loaded external script was ignored.
# LOCALIZATION NOTE (EditorFileDropFailed): Do not translate contenteditable, %S is the error message explaining why the drop failed.
EditorFileDropFailed=Dropping a file into a contenteditable element failed: %S.
FormValidationTextTooLong=Please shorten this text to %S characters or less (you are currently using %S characters).
FormValidationValueMissing=Please fill out this field.
FormValidationCheckboxMissing=Please check this box if you want to proceed.

View File

@ -0,0 +1,34 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var { classes: Cc, interfaces: Ci, utils: Cu } = Components;
"use strict";
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
const EDITORUTILS_CID = Components.ID('{12e63991-86ac-4dff-bb1a-703495d67d17}');
function EditorUtils() {
}
EditorUtils.prototype = {
classID: EDITORUTILS_CID,
QueryInterface: XPCOMUtils.generateQI([ Ci.nsIEditorUtils ]),
slurpBlob(aBlob, aScope, aListener) {
let reader = new aScope.FileReader();
reader.addEventListener("load", (event) => {
aListener.onResult(event.target.result);
});
reader.addEventListener("error", (event) => {
aListener.onError(event.target.error.message);
});
reader.readAsBinaryString(aBlob);
},
};
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([EditorUtils]);

View File

@ -0,0 +1,2 @@
component {12e63991-86ac-4dff-bb1a-703495d67d17} EditorUtils.js
contract @mozilla.org/editor-utils;1 {12e63991-86ac-4dff-bb1a-703495d67d17}

View File

@ -70,6 +70,11 @@ LOCAL_INCLUDES += [
'/layout/xul',
]
EXTRA_COMPONENTS += [
'EditorUtils.js',
'EditorUtils.manifest',
]
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'

View File

@ -18,6 +18,7 @@
#include "nsCRT.h"
#include "nsCRTGlue.h"
#include "nsComponentManagerUtils.h"
#include "nsIScriptError.h"
#include "nsContentUtils.h"
#include "nsDebug.h"
#include "nsDependentSubstring.h"
@ -1009,6 +1010,77 @@ nsHTMLEditor::ParseCFHTML(nsCString & aCfhtml, char16_t **aStuffToPaste, char16_
return NS_OK;
}
static nsresult
ImgFromData(const nsACString& aType, const nsACString& aData, nsString& aOutput)
{
nsAutoCString data64;
nsresult rv = Base64Encode(aData, data64);
NS_ENSURE_SUCCESS(rv, rv);
aOutput.AssignLiteral("<IMG src=\"data:");
AppendUTF8toUTF16(aType, aOutput);
aOutput.AppendLiteral(";base64,");
AppendUTF8toUTF16(data64, aOutput);
aOutput.AppendLiteral("\" alt=\"\" >");
return NS_OK;
}
NS_IMPL_ISUPPORTS(nsHTMLEditor::BlobReader, nsIEditorBlobListener)
nsHTMLEditor::BlobReader::BlobReader(BlobImpl* aBlob, nsHTMLEditor* aEditor,
bool aIsSafe, nsIDOMDocument* aSourceDoc,
nsIDOMNode* aDestinationNode,
int32_t aDestOffset,
bool aDoDeleteSelection)
: mBlob(aBlob)
, mEditor(aEditor)
, mIsSafe(aIsSafe)
, mSourceDoc(aSourceDoc)
, mDestinationNode(aDestinationNode)
, mDestOffset(aDestOffset)
, mDoDeleteSelection(aDoDeleteSelection)
{
MOZ_ASSERT(mBlob);
MOZ_ASSERT(mEditor);
MOZ_ASSERT(mDestinationNode);
}
NS_IMETHODIMP
nsHTMLEditor::BlobReader::OnResult(const nsACString& aResult)
{
nsString blobType;
mBlob->GetType(blobType);
NS_ConvertUTF16toUTF8 type(blobType);
nsAutoString stuffToPaste;
nsresult rv = ImgFromData(type, aResult, stuffToPaste);
NS_ENSURE_SUCCESS(rv, rv);
nsAutoEditBatch beginBatching(mEditor);
rv = mEditor->DoInsertHTMLWithContext(stuffToPaste, EmptyString(), EmptyString(),
NS_LITERAL_STRING(kFileMime),
mSourceDoc,
mDestinationNode, mDestOffset,
mDoDeleteSelection,
mIsSafe, false);
return rv;
}
NS_IMETHODIMP
nsHTMLEditor::BlobReader::OnError(const nsAString& aError)
{
nsCOMPtr<nsINode> destNode = do_QueryInterface(mDestinationNode);
const nsPromiseFlatString& flat = PromiseFlatString(aError);
const char16_t* error = flat.get();
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
NS_LITERAL_CSTRING("Editor"),
destNode->OwnerDoc(),
nsContentUtils::eDOM_PROPERTIES,
"EditorFileDropFailed",
&error, 1);
return NS_OK;
}
nsresult nsHTMLEditor::InsertObject(const char* aType, nsISupports* aObject, bool aIsSafe,
nsIDOMDocument *aSourceDoc,
nsIDOMNode *aDestinationNode,
@ -1017,6 +1089,23 @@ nsresult nsHTMLEditor::InsertObject(const char* aType, nsISupports* aObject, boo
{
nsresult rv;
if (nsCOMPtr<BlobImpl> blob = do_QueryInterface(aObject)) {
RefPtr<BlobReader> br = new BlobReader(blob, this, aIsSafe, aSourceDoc,
aDestinationNode, aDestOffset,
aDoDeleteSelection);
nsCOMPtr<nsIEditorUtils> utils =
do_GetService("@mozilla.org/editor-utils;1");
NS_ENSURE_TRUE(utils, NS_ERROR_FAILURE);
nsCOMPtr<nsINode> node = do_QueryInterface(aDestinationNode);
MOZ_ASSERT(node);
nsCOMPtr<nsIDOMBlob> domBlob = Blob::Create(node->GetOwnerGlobal(), blob);
NS_ENSURE_TRUE(domBlob, NS_ERROR_FAILURE);
return utils->SlurpBlob(domBlob, node->OwnerDoc()->GetWindow(), br);
}
nsAutoCString type(aType);
// Check to see if we can insert an image file
@ -1064,16 +1153,10 @@ nsresult nsHTMLEditor::InsertObject(const char* aType, nsISupports* aObject, boo
NS_ENSURE_SUCCESS(rv, rv);
}
nsAutoCString data64;
rv = Base64Encode(imageData, data64);
nsAutoString stuffToPaste;
rv = ImgFromData(type, imageData, stuffToPaste);
NS_ENSURE_SUCCESS(rv, rv);
nsAutoString stuffToPaste;
stuffToPaste.AssignLiteral("<IMG src=\"data:");
AppendUTF8toUTF16(type, stuffToPaste);
stuffToPaste.AppendLiteral(";base64,");
AppendUTF8toUTF16(data64, stuffToPaste);
stuffToPaste.AppendLiteral("\" alt=\"\" >");
nsAutoEditBatch beginBatching(this);
rv = DoInsertHTMLWithContext(stuffToPaste, EmptyString(), EmptyString(),
NS_LITERAL_STRING(kFileMime),

View File

@ -13,6 +13,7 @@
#include "nsITableEditor.h"
#include "nsIEditorMailSupport.h"
#include "nsIEditorStyleSheets.h"
#include "nsIEditorUtils.h"
#include "nsEditor.h"
#include "nsIDOMElement.h"
@ -56,6 +57,7 @@ struct PropItem;
namespace mozilla {
template<class T> class OwningNonNull;
namespace dom {
class BlobImpl;
class DocumentFragment;
} // namespace dom
namespace widget {
@ -405,6 +407,30 @@ public:
}
protected:
class BlobReader final : public nsIEditorBlobListener
{
public:
BlobReader(mozilla::dom::BlobImpl* aBlob, nsHTMLEditor* aEditor,
bool aIsSafe, nsIDOMDocument* aSourceDoc,
nsIDOMNode* aDestinationNode, int32_t aDestOffset,
bool aDoDeleteSelection);
NS_DECL_ISUPPORTS
NS_DECL_NSIEDITORBLOBLISTENER
private:
~BlobReader()
{
}
RefPtr<mozilla::dom::BlobImpl> mBlob;
RefPtr<nsHTMLEditor> mEditor;
bool mIsSafe;
nsCOMPtr<nsIDOMDocument> mSourceDoc;
nsCOMPtr<nsIDOMNode> mDestinationNode;
int32_t mDestOffset;
bool mDoDeleteSelection;
};
NS_IMETHOD InitRules() override;

View File

@ -21,6 +21,7 @@ XPIDL_SOURCES += [
'nsIEditorObserver.idl',
'nsIEditorSpellCheck.idl',
'nsIEditorStyleSheets.idl',
'nsIEditorUtils.idl',
'nsIHTMLAbsPosEditor.idl',
'nsIHTMLEditor.idl',
'nsIHTMLInlineTableEditor.idl',

32
editor/nsIEditorUtils.idl Normal file
View File

@ -0,0 +1,32 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsISupports.idl"
#include "domstubs.idl"
interface nsIDOMBlob;
interface mozIDOMWindowProxy;
[scriptable, uuid(eb8b8ad9-5d8f-43bd-8ce5-5b943c180d56)]
interface nsIEditorBlobListener : nsISupports
{
void onResult(in ACString aResult);
void onError(in AString aErrorName);
};
/**
* A collection of utility functions that editors can use that are more easily
* done in JavaScript.
*/
[scriptable, uuid(4bf94928-575e-4bd1-8321-a2c4b3d0119e)]
interface nsIEditorUtils : nsISupports
{
/**
* Given a blob, returns the data from that blob, asynchronously.
*/
void slurpBlob(in nsIDOMBlob aBlob, in mozIDOMWindowProxy aScope,
in nsIEditorBlobListener aListener);
};