зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1372829 - part2: mozilla::EditorBase should cache raw pointer of nsISelectionController and nsIDocument with nsWeakPtr r=froydnj,m_kato
mozilla::EditorBase stores nsISelectionController and nsIDocument with nsWeakPtr. However, nsWeakPtr requires QI to retrieve actual pointer and it makes some damage to the performance. If mozilla::WeakPter were available for them, it'd be great. However, it's not available with nsISelectionController nor nsIDocument because it's possible to implement SupportsWeakPtr only with their subclasses but the subclasses shouldn't be referred by editor. Therefore, this patch creates mozilla::CachedWeakPtr<class T> which stores both raw pointer (as cache) and nsWeakPtr and when its cache is requested, it checks if the object referred by nsWeakPtr is still alive. Additionally, this patch hides the members from subclasses of EditorBase for reducing the maintenance cost. MozReview-Commit-ID: FvtM7453Vv8 --HG-- extra : rebase_source : a524a8ea327c3993645fafa81db8aef65090f1e0
This commit is contained in:
Родитель
46f0810215
Коммит
f337b95b60
|
@ -61,6 +61,7 @@ public:
|
|||
// nsIWeakReference
|
||||
NS_DECL_NSIWEAKREFERENCE
|
||||
virtual size_t SizeOfOnlyThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
|
||||
virtual bool IsAlive() const override { return mNode != nullptr; }
|
||||
|
||||
void NoticeNodeDestruction()
|
||||
{
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "mozilla/TextComposition.h" // for TextComposition
|
||||
#include "mozilla/TextEvents.h"
|
||||
#include "mozilla/dom/Element.h" // for Element, nsINode::AsElement
|
||||
#include "mozilla/dom/HTMLBodyElement.h"
|
||||
#include "mozilla/dom/Text.h"
|
||||
#include "mozilla/dom/Event.h"
|
||||
#include "mozilla/mozalloc.h" // for operator new, etc.
|
||||
|
@ -70,7 +71,6 @@
|
|||
#include "nsIDOMMouseEvent.h" // for nsIDOMMouseEvent
|
||||
#include "nsIDOMNode.h" // for nsIDOMNode, etc.
|
||||
#include "nsIDOMNodeList.h" // for nsIDOMNodeList
|
||||
#include "nsIDocument.h" // for nsIDocument
|
||||
#include "nsIDocumentStateListener.h" // for nsIDocumentStateListener
|
||||
#include "nsIEditActionListener.h" // for nsIEditActionListener
|
||||
#include "nsIEditorObserver.h" // for nsIEditorObserver
|
||||
|
@ -150,7 +150,8 @@ EditorBase::EditorBase()
|
|||
|
||||
EditorBase::~EditorBase()
|
||||
{
|
||||
NS_ASSERTION(!mDocWeak || mDidPreDestroy, "Why PreDestroy hasn't been called?");
|
||||
MOZ_ASSERT(!IsInitialized() || mDidPreDestroy,
|
||||
"Why PreDestroy hasn't been called?");
|
||||
|
||||
if (mComposition) {
|
||||
mComposition->OnEditorDestroyed();
|
||||
|
@ -208,20 +209,21 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(EditorBase)
|
|||
|
||||
|
||||
NS_IMETHODIMP
|
||||
EditorBase::Init(nsIDOMDocument* aDoc,
|
||||
EditorBase::Init(nsIDOMDocument* aDOMDocument,
|
||||
nsIContent* aRoot,
|
||||
nsISelectionController* aSelCon,
|
||||
nsISelectionController* aSelectionController,
|
||||
uint32_t aFlags,
|
||||
const nsAString& aValue)
|
||||
{
|
||||
MOZ_ASSERT(mAction == EditAction::none,
|
||||
"Initializing during an edit action is an error");
|
||||
MOZ_ASSERT(aDoc);
|
||||
if (!aDoc)
|
||||
MOZ_ASSERT(aDOMDocument);
|
||||
if (!aDOMDocument) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
// First only set flags, but other stuff shouldn't be initialized now.
|
||||
// Don't move this call after initializing mDocWeak.
|
||||
// Don't move this call after initializing mDocumentWeak.
|
||||
// SetFlags() can check whether it's called during initialization or not by
|
||||
// them. Note that SetFlags() will be called by PostCreate().
|
||||
#ifdef DEBUG
|
||||
|
@ -230,19 +232,21 @@ EditorBase::Init(nsIDOMDocument* aDoc,
|
|||
SetFlags(aFlags);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "SetFlags() failed");
|
||||
|
||||
mDocWeak = do_GetWeakReference(aDoc); // weak reference to doc
|
||||
nsCOMPtr<nsIDocument> document = do_QueryInterface(aDOMDocument);
|
||||
mDocumentWeak = document.get();
|
||||
// HTML editors currently don't have their own selection controller,
|
||||
// so they'll pass null as aSelCon, and we'll get the selection controller
|
||||
// off of the presshell.
|
||||
nsCOMPtr<nsISelectionController> selCon;
|
||||
if (aSelCon) {
|
||||
mSelConWeak = do_GetWeakReference(aSelCon); // weak reference to selectioncontroller
|
||||
selCon = aSelCon;
|
||||
nsCOMPtr<nsISelectionController> selectionController;
|
||||
if (aSelectionController) {
|
||||
mSelectionControllerWeak = aSelectionController;
|
||||
selectionController = aSelectionController;
|
||||
} else {
|
||||
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
|
||||
selCon = do_QueryInterface(presShell);
|
||||
selectionController = do_QueryInterface(presShell);
|
||||
}
|
||||
NS_ASSERTION(selCon, "Selection controller should be available at this point");
|
||||
MOZ_ASSERT(selectionController,
|
||||
"Selection controller should be available at this point");
|
||||
|
||||
//set up root element if we are passed one.
|
||||
if (aRoot)
|
||||
|
@ -259,13 +263,14 @@ EditorBase::Init(nsIDOMDocument* aDoc,
|
|||
mIMETextNode = nullptr;
|
||||
}
|
||||
|
||||
/* Show the caret */
|
||||
selCon->SetCaretReadOnly(false);
|
||||
selCon->SetDisplaySelection(nsISelectionController::SELECTION_ON);
|
||||
// Show the caret.
|
||||
selectionController->SetCaretReadOnly(false);
|
||||
selectionController->SetDisplaySelection(
|
||||
nsISelectionController::SELECTION_ON);
|
||||
// Show all the selection reflected to user.
|
||||
selectionController->SetSelectionFlags(nsISelectionDisplay::DISPLAY_ALL);
|
||||
|
||||
selCon->SetSelectionFlags(nsISelectionDisplay::DISPLAY_ALL);//we want to see all the selection reflected to user
|
||||
|
||||
NS_POSTCONDITION(mDocWeak, "bad state");
|
||||
MOZ_ASSERT(IsInitialized());
|
||||
|
||||
// Make sure that the editor will be destroyed properly
|
||||
mDidPreDestroy = false;
|
||||
|
@ -344,8 +349,9 @@ EditorBase::CreateEventListeners()
|
|||
nsresult
|
||||
EditorBase::InstallEventListeners()
|
||||
{
|
||||
NS_ENSURE_TRUE(mDocWeak && mEventListener,
|
||||
NS_ERROR_NOT_INITIALIZED);
|
||||
if (NS_WARN_IF(!IsInitialized()) || NS_WARN_IF(!mEventListener)) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
// Initialize the event target.
|
||||
nsCOMPtr<nsIContent> rootContent = GetRoot();
|
||||
|
@ -366,7 +372,7 @@ EditorBase::InstallEventListeners()
|
|||
void
|
||||
EditorBase::RemoveEventListeners()
|
||||
{
|
||||
if (!mDocWeak || !mEventListener) {
|
||||
if (!IsInitialized() || !mEventListener) {
|
||||
return;
|
||||
}
|
||||
reinterpret_cast<EditorEventListener*>(mEventListener.get())->Disconnect();
|
||||
|
@ -489,7 +495,7 @@ EditorBase::SetFlags(uint32_t aFlags)
|
|||
bool spellcheckerWasEnabled = CanEnableSpellCheck();
|
||||
mFlags = aFlags;
|
||||
|
||||
if (!mDocWeak) {
|
||||
if (!IsInitialized()) {
|
||||
// If we're initializing, we shouldn't do anything now.
|
||||
// SetFlags() will be called by PostCreate(),
|
||||
// we should synchronize some stuff for the flags at that time.
|
||||
|
@ -555,17 +561,15 @@ EditorBase::GetIsDocumentEditable(bool* aIsDocumentEditable)
|
|||
already_AddRefed<nsIDocument>
|
||||
EditorBase::GetDocument()
|
||||
{
|
||||
NS_PRECONDITION(mDocWeak, "bad state, mDocWeak weak pointer not initialized");
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
|
||||
return doc.forget();
|
||||
nsCOMPtr<nsIDocument> document = mDocumentWeak.get();
|
||||
return document.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<nsIDOMDocument>
|
||||
EditorBase::GetDOMDocument()
|
||||
{
|
||||
NS_PRECONDITION(mDocWeak, "bad state, mDocWeak weak pointer not initialized");
|
||||
nsCOMPtr<nsIDOMDocument> doc = do_QueryReferent(mDocWeak);
|
||||
return doc.forget();
|
||||
nsCOMPtr<nsIDOMDocument> domDocument = do_QueryInterface(mDocumentWeak);
|
||||
return domDocument.forget();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -578,11 +582,12 @@ EditorBase::GetDocument(nsIDOMDocument** aDoc)
|
|||
already_AddRefed<nsIPresShell>
|
||||
EditorBase::GetPresShell()
|
||||
{
|
||||
NS_PRECONDITION(mDocWeak, "bad state, null mDocWeak");
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
|
||||
NS_ENSURE_TRUE(doc, nullptr);
|
||||
nsCOMPtr<nsIPresShell> ps = doc->GetShell();
|
||||
return ps.forget();
|
||||
nsCOMPtr<nsIDocument> document = GetDocument();
|
||||
if (NS_WARN_IF(!document)) {
|
||||
return nullptr;
|
||||
}
|
||||
nsCOMPtr<nsIPresShell> presShell = document->GetShell();
|
||||
return presShell.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<nsIWidget>
|
||||
|
@ -628,14 +633,14 @@ EditorBase::GetSelectionController(nsISelectionController** aSel)
|
|||
already_AddRefed<nsISelectionController>
|
||||
EditorBase::GetSelectionController()
|
||||
{
|
||||
nsCOMPtr<nsISelectionController> selCon;
|
||||
if (mSelConWeak) {
|
||||
selCon = do_QueryReferent(mSelConWeak);
|
||||
nsCOMPtr<nsISelectionController> selectionController;
|
||||
if (mSelectionControllerWeak) {
|
||||
selectionController = mSelectionControllerWeak.get();
|
||||
} else {
|
||||
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
|
||||
selCon = do_QueryInterface(presShell);
|
||||
selectionController = do_QueryInterface(presShell);
|
||||
}
|
||||
return selCon.forget();
|
||||
return selectionController.forget();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -1043,7 +1048,8 @@ EditorBase::GetDocumentIsEmpty(bool* aDocumentIsEmpty)
|
|||
NS_IMETHODIMP
|
||||
EditorBase::SelectAll()
|
||||
{
|
||||
if (!mDocWeak) {
|
||||
// XXX Why doesn't this check if the document is alive?
|
||||
if (!IsInitialized()) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
ForceCompositionEnd();
|
||||
|
@ -1056,7 +1062,8 @@ EditorBase::SelectAll()
|
|||
NS_IMETHODIMP
|
||||
EditorBase::BeginningOfDocument()
|
||||
{
|
||||
if (!mDocWeak) {
|
||||
// XXX Why doesn't this check if the document is alive?
|
||||
if (!IsInitialized()) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
|
@ -1093,7 +1100,10 @@ EditorBase::BeginningOfDocument()
|
|||
NS_IMETHODIMP
|
||||
EditorBase::EndOfDocument()
|
||||
{
|
||||
NS_ENSURE_TRUE(mDocWeak, NS_ERROR_NOT_INITIALIZED);
|
||||
// XXX Why doesn't this check if the document is alive?
|
||||
if (NS_WARN_IF(!IsInitialized())) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
// get selection
|
||||
RefPtr<Selection> selection = GetSelection();
|
||||
|
@ -1128,20 +1138,22 @@ EditorBase::GetDocumentModified(bool* outDocModified)
|
|||
NS_IMETHODIMP
|
||||
EditorBase::GetDocumentCharacterSet(nsACString& characterSet)
|
||||
{
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
|
||||
NS_ENSURE_TRUE(doc, NS_ERROR_UNEXPECTED);
|
||||
|
||||
characterSet = doc->GetDocumentCharacterSet();
|
||||
nsCOMPtr<nsIDocument> document = GetDocument();
|
||||
if (NS_WARN_IF(!document)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
characterSet = document->GetDocumentCharacterSet();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
EditorBase::SetDocumentCharacterSet(const nsACString& characterSet)
|
||||
{
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
|
||||
NS_ENSURE_TRUE(doc, NS_ERROR_UNEXPECTED);
|
||||
|
||||
doc->SetDocumentCharacterSet(characterSet);
|
||||
nsCOMPtr<nsIDocument> document = GetDocument();
|
||||
if (NS_WARN_IF(!document)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
document->SetDocumentCharacterSet(characterSet);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -2007,12 +2019,17 @@ NS_IMETHODIMP
|
|||
EditorBase::DebugDumpContent()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
nsCOMPtr<nsIDOMHTMLDocument> doc = do_QueryReferent(mDocWeak);
|
||||
NS_ENSURE_TRUE(doc, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
nsCOMPtr<nsIDOMHTMLElement>bodyElem;
|
||||
doc->GetBody(getter_AddRefs(bodyElem));
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(bodyElem);
|
||||
nsCOMPtr<nsIDocument> document = GetDocument();
|
||||
if (NS_WARN_IF(!document)) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
nsCOMPtr<nsIDOMHTMLDocument> domHTMLDocument = do_QueryInterface(document);
|
||||
if (NS_WARN_IF(!domHTMLDocument)) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
nsCOMPtr<nsIDOMHTMLElement> bodyElement;
|
||||
domHTMLDocument->GetBody(getter_AddRefs(bodyElement));
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(bodyElement);
|
||||
if (content) {
|
||||
content->List();
|
||||
}
|
||||
|
@ -2312,18 +2329,20 @@ EditorBase::CloneAttributes(Element* aDest,
|
|||
nsresult
|
||||
EditorBase::ScrollSelectionIntoView(bool aScrollToAnchor)
|
||||
{
|
||||
nsCOMPtr<nsISelectionController> selCon;
|
||||
if (NS_SUCCEEDED(GetSelectionController(getter_AddRefs(selCon))) && selCon) {
|
||||
int16_t region = nsISelectionController::SELECTION_FOCUS_REGION;
|
||||
|
||||
if (aScrollToAnchor) {
|
||||
region = nsISelectionController::SELECTION_ANCHOR_REGION;
|
||||
}
|
||||
|
||||
selCon->ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL,
|
||||
region, nsISelectionController::SCROLL_OVERFLOW_HIDDEN);
|
||||
nsCOMPtr<nsISelectionController> selectionController =
|
||||
GetSelectionController();
|
||||
if (!selectionController) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
int16_t region = nsISelectionController::SELECTION_FOCUS_REGION;
|
||||
if (aScrollToAnchor) {
|
||||
region = nsISelectionController::SELECTION_ANCHOR_REGION;
|
||||
}
|
||||
selectionController->ScrollSelectionIntoView(
|
||||
nsISelectionController::SELECTION_NORMAL,
|
||||
region,
|
||||
nsISelectionController::SCROLL_OVERFLOW_HIDDEN);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -4787,22 +4806,27 @@ EditorBase::InitializeSelection(nsIDOMEventTarget* aFocusEventTarget)
|
|||
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
|
||||
NS_ENSURE_TRUE(presShell, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
nsCOMPtr<nsISelectionController> selCon;
|
||||
nsresult rv = GetSelectionController(getter_AddRefs(selCon));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsISelectionController> selectionController =
|
||||
GetSelectionController();
|
||||
if (NS_WARN_IF(!selectionController)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Init the caret
|
||||
RefPtr<nsCaret> caret = presShell->GetCaret();
|
||||
NS_ENSURE_TRUE(caret, NS_ERROR_UNEXPECTED);
|
||||
caret->SetIgnoreUserModify(false);
|
||||
caret->SetSelection(selection);
|
||||
selCon->SetCaretReadOnly(IsReadonly());
|
||||
selCon->SetCaretEnabled(true);
|
||||
selectionController->SetCaretReadOnly(IsReadonly());
|
||||
selectionController->SetCaretEnabled(true);
|
||||
|
||||
// Init selection
|
||||
selCon->SetDisplaySelection(nsISelectionController::SELECTION_ON);
|
||||
selCon->SetSelectionFlags(nsISelectionDisplay::DISPLAY_ALL);
|
||||
selCon->RepaintSelection(nsISelectionController::SELECTION_NORMAL);
|
||||
selectionController->SetDisplaySelection(
|
||||
nsISelectionController::SELECTION_ON);
|
||||
selectionController->SetSelectionFlags(
|
||||
nsISelectionDisplay::DISPLAY_ALL);
|
||||
selectionController->RepaintSelection(
|
||||
nsISelectionController::SELECTION_NORMAL);
|
||||
// If the computed selection root isn't root content, we should set it
|
||||
// as selection ancestor limit. However, if that is root element, it means
|
||||
// there is not limitation of the selection, then, we must set nullptr.
|
||||
|
@ -4852,9 +4876,11 @@ EditorBase::InitializeSelection(nsIDOMEventTarget* aFocusEventTarget)
|
|||
NS_IMETHODIMP
|
||||
EditorBase::FinalizeSelection()
|
||||
{
|
||||
nsCOMPtr<nsISelectionController> selCon;
|
||||
nsresult rv = GetSelectionController(getter_AddRefs(selCon));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsISelectionController> selectionController =
|
||||
GetSelectionController();
|
||||
if (NS_WARN_IF(!selectionController)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
RefPtr<Selection> selection = GetSelection();
|
||||
NS_ENSURE_STATE(selection);
|
||||
|
@ -4864,7 +4890,7 @@ EditorBase::FinalizeSelection()
|
|||
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
|
||||
NS_ENSURE_TRUE(presShell, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
selCon->SetCaretEnabled(false);
|
||||
selectionController->SetCaretEnabled(false);
|
||||
|
||||
nsFocusManager* fm = nsFocusManager::GetFocusManager();
|
||||
NS_ENSURE_TRUE(fm, NS_ERROR_NOT_INITIALIZED);
|
||||
|
@ -4879,25 +4905,30 @@ EditorBase::FinalizeSelection()
|
|||
ErrorResult ret;
|
||||
if (!doc || !doc->HasFocus(ret)) {
|
||||
// If the document already lost focus, mark the selection as disabled.
|
||||
selCon->SetDisplaySelection(nsISelectionController::SELECTION_DISABLED);
|
||||
selectionController->SetDisplaySelection(
|
||||
nsISelectionController::SELECTION_DISABLED);
|
||||
} else {
|
||||
// Otherwise, mark selection as normal because outside of a
|
||||
// contenteditable element should be selected with normal selection
|
||||
// color after here.
|
||||
selCon->SetDisplaySelection(nsISelectionController::SELECTION_ON);
|
||||
selectionController->SetDisplaySelection(
|
||||
nsISelectionController::SELECTION_ON);
|
||||
}
|
||||
} else if (IsFormWidget() || IsPasswordEditor() ||
|
||||
IsReadonly() || IsDisabled() || IsInputFiltered()) {
|
||||
// In <input> or <textarea>, the independent selection should be hidden
|
||||
// while this editor doesn't have focus.
|
||||
selCon->SetDisplaySelection(nsISelectionController::SELECTION_HIDDEN);
|
||||
selectionController->SetDisplaySelection(
|
||||
nsISelectionController::SELECTION_HIDDEN);
|
||||
} else {
|
||||
// Otherwise, although we're not sure how this case happens, the
|
||||
// independent selection should be marked as disabled.
|
||||
selCon->SetDisplaySelection(nsISelectionController::SELECTION_DISABLED);
|
||||
selectionController->SetDisplaySelection(
|
||||
nsISelectionController::SELECTION_DISABLED);
|
||||
}
|
||||
|
||||
selCon->RepaintSelection(nsISelectionController::SELECTION_NORMAL);
|
||||
selectionController->RepaintSelection(
|
||||
nsISelectionController::SELECTION_NORMAL);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -5108,8 +5139,11 @@ EditorBase::IsActiveInDOMWindow()
|
|||
nsFocusManager* fm = nsFocusManager::GetFocusManager();
|
||||
NS_ENSURE_TRUE(fm, false);
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
|
||||
nsPIDOMWindowOuter* ourWindow = doc->GetWindow();
|
||||
nsCOMPtr<nsIDocument> document = GetDocument();
|
||||
if (NS_WARN_IF(!document)) {
|
||||
return false;
|
||||
}
|
||||
nsPIDOMWindowOuter* ourWindow = document->GetWindow();
|
||||
nsCOMPtr<nsPIDOMWindowOuter> win;
|
||||
nsIContent* content =
|
||||
nsFocusManager::GetFocusedDescendant(ourWindow, false,
|
||||
|
@ -5219,10 +5253,11 @@ EditorBase::GetIMESelectionStartOffsetIn(nsINode* aTextNode)
|
|||
{
|
||||
MOZ_ASSERT(aTextNode, "aTextNode must not be nullptr");
|
||||
|
||||
nsCOMPtr<nsISelectionController> selectionController;
|
||||
nsresult rv = GetSelectionController(getter_AddRefs(selectionController));
|
||||
NS_ENSURE_SUCCESS(rv, -1);
|
||||
NS_ENSURE_TRUE(selectionController, -1);
|
||||
nsCOMPtr<nsISelectionController> selectionController =
|
||||
GetSelectionController();
|
||||
if (NS_WARN_IF(!selectionController)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t minOffset = INT32_MAX;
|
||||
static const SelectionType kIMESelectionTypes[] = {
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "nsCOMPtr.h" // for already_AddRefed, nsCOMPtr
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsIDocument.h" // for nsIDocument
|
||||
#include "nsIEditor.h" // for nsIEditor, etc.
|
||||
#include "nsIObserver.h" // for NS_DECL_NSIOBSERVER, etc.
|
||||
#include "nsIPlaintextEditor.h" // for nsIPlaintextEditor, etc.
|
||||
|
@ -35,7 +36,6 @@ class nsIDOMEvent;
|
|||
class nsIDOMEventListener;
|
||||
class nsIDOMEventTarget;
|
||||
class nsIDOMNode;
|
||||
class nsIDocument;
|
||||
class nsIDocumentStateListener;
|
||||
class nsIEditActionListener;
|
||||
class nsIEditorObserver;
|
||||
|
@ -137,6 +137,57 @@ namespace widget {
|
|||
struct IMEState;
|
||||
} // namespace widget
|
||||
|
||||
/**
|
||||
* CachedWeakPtr stores a pointer to a class which inherits nsIWeakReference.
|
||||
* If the instance of the class has already been destroyed, this returns
|
||||
* nullptr. Otherwise, returns cached pointer.
|
||||
*/
|
||||
template<class T>
|
||||
class CachedWeakPtr final
|
||||
{
|
||||
public:
|
||||
CachedWeakPtr<T>()
|
||||
: mCache(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
CachedWeakPtr<T>& operator=(T* aObject)
|
||||
{
|
||||
mWeakPtr = do_GetWeakReference(aObject);
|
||||
mCache = aObject;
|
||||
return *this;
|
||||
}
|
||||
CachedWeakPtr<T>& operator=(const nsCOMPtr<T>& aOther)
|
||||
{
|
||||
mWeakPtr = do_GetWeakReference(aOther);
|
||||
mCache = aOther;
|
||||
return *this;
|
||||
}
|
||||
CachedWeakPtr<T>& operator=(already_AddRefed<T>& aOther)
|
||||
{
|
||||
nsCOMPtr<T> other = aOther;
|
||||
mWeakPtr = do_GetWeakReference(other);
|
||||
mCache = other;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool IsAlive() const { return mWeakPtr && mWeakPtr->IsAlive(); }
|
||||
|
||||
explicit operator bool() const { return mWeakPtr; }
|
||||
operator T*() const { return get(); }
|
||||
T* get() const
|
||||
{
|
||||
if (mCache && !mWeakPtr->IsAlive()) {
|
||||
const_cast<CachedWeakPtr<T>*>(this)->mCache = nullptr;
|
||||
}
|
||||
return mCache;
|
||||
}
|
||||
|
||||
private:
|
||||
nsWeakPtr mWeakPtr;
|
||||
T* MOZ_NON_OWNING_REF mCache;
|
||||
};
|
||||
|
||||
#define kMOZEditorBogusNodeAttrAtom nsGkAtoms::mozeditorbogusnode
|
||||
#define kMOZEditorBogusNodeValue NS_LITERAL_STRING("TRUE")
|
||||
|
||||
|
@ -183,6 +234,7 @@ public:
|
|||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(EditorBase, nsIEditor)
|
||||
|
||||
bool IsInitialized() const { return !!mDocumentWeak; }
|
||||
already_AddRefed<nsIDOMDocument> GetDOMDocument();
|
||||
already_AddRefed<nsIDocument> GetDocument();
|
||||
already_AddRefed<nsIPresShell> GetPresShell();
|
||||
|
@ -888,7 +940,7 @@ public:
|
|||
|
||||
bool HasIndependentSelection() const
|
||||
{
|
||||
return !!mSelConWeak;
|
||||
return !!mSelectionControllerWeak;
|
||||
}
|
||||
|
||||
bool IsModifiable() const
|
||||
|
@ -986,6 +1038,14 @@ public:
|
|||
*/
|
||||
void HideCaret(bool aHide);
|
||||
|
||||
private:
|
||||
// Weak reference to the nsISelectionController.
|
||||
// Use GetSelectionController() to retrieve actual pointer.
|
||||
CachedWeakPtr<nsISelectionController> mSelectionControllerWeak;
|
||||
// Weak reference to the nsIDocument.
|
||||
// Use GetDocument() to retrieve actual pointer.
|
||||
CachedWeakPtr<nsIDocument> mDocumentWeak;
|
||||
|
||||
protected:
|
||||
enum Tristate
|
||||
{
|
||||
|
@ -1007,12 +1067,8 @@ protected:
|
|||
// The form field as an event receiver.
|
||||
nsCOMPtr<dom::EventTarget> mEventTarget;
|
||||
nsCOMPtr<nsIDOMEventListener> mEventListener;
|
||||
// Weak reference to the nsISelectionController.
|
||||
nsWeakPtr mSelConWeak;
|
||||
// Weak reference to placeholder for begin/end batch purposes.
|
||||
WeakPtr<PlaceholderTransaction> mPlaceholderTransactionWeak;
|
||||
// Weak reference to the nsIDOMDocument.
|
||||
nsWeakPtr mDocWeak;
|
||||
// Name of placeholder transaction.
|
||||
nsIAtom* mPlaceholderName;
|
||||
// Saved selection state for placeholder transaction batching.
|
||||
|
|
|
@ -164,7 +164,7 @@ HTMLEditor::~HTMLEditor()
|
|||
// free any default style propItems
|
||||
RemoveAllDefaultProperties();
|
||||
|
||||
if (mLinkHandler && mDocWeak) {
|
||||
if (mLinkHandler && IsInitialized()) {
|
||||
nsCOMPtr<nsIPresShell> ps = GetPresShell();
|
||||
|
||||
if (ps && ps->GetPresContext()) {
|
||||
|
@ -327,7 +327,7 @@ HTMLEditor::PreDestroy(bool aDestroyingFrames)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsINode> document = do_QueryReferent(mDocWeak);
|
||||
nsCOMPtr<nsIDocument> document = GetDocument();
|
||||
if (document) {
|
||||
document->RemoveMutationObserver(this);
|
||||
}
|
||||
|
@ -367,11 +367,14 @@ HTMLEditor::GetRootElement(nsIDOMElement** aRootElement)
|
|||
} else {
|
||||
// If there is no HTML body element,
|
||||
// we should use the document root element instead.
|
||||
nsCOMPtr<nsIDOMDocument> doc = do_QueryReferent(mDocWeak);
|
||||
NS_ENSURE_TRUE(doc, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
rv = doc->GetDocumentElement(getter_AddRefs(rootElement));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIDOMDocument> domDocument = GetDOMDocument();
|
||||
if (NS_WARN_IF(!domDocument)) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
rv = domDocument->GetDocumentElement(getter_AddRefs(rootElement));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
// Document can have no elements
|
||||
if (!rootElement) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
@ -440,8 +443,9 @@ HTMLEditor::CreateEventListeners()
|
|||
nsresult
|
||||
HTMLEditor::InstallEventListeners()
|
||||
{
|
||||
NS_ENSURE_TRUE(mDocWeak && mEventListener,
|
||||
NS_ERROR_NOT_INITIALIZED);
|
||||
if (NS_WARN_IF(!IsInitialized()) || NS_WARN_IF(!mEventListener)) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
// NOTE: HTMLEditor doesn't need to initialize mEventTarget here because
|
||||
// the target must be document node and it must be referenced as weak pointer.
|
||||
|
@ -454,7 +458,7 @@ HTMLEditor::InstallEventListeners()
|
|||
void
|
||||
HTMLEditor::RemoveEventListeners()
|
||||
{
|
||||
if (!mDocWeak) {
|
||||
if (!IsInitialized()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -516,7 +520,8 @@ HTMLEditor::InitRules()
|
|||
NS_IMETHODIMP
|
||||
HTMLEditor::BeginningOfDocument()
|
||||
{
|
||||
if (!mDocWeak) {
|
||||
// XXX Why doesn't this check if the document is alive?
|
||||
if (!IsInitialized()) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
|
@ -1195,11 +1200,13 @@ HTMLEditor::ReplaceHeadContentsWithHTML(const nsAString& aSourceToInsert)
|
|||
|
||||
// Do not use AutoRules -- rules code won't let us insert in <head>. Use
|
||||
// the head node as a parent and delete/insert directly.
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
|
||||
NS_ENSURE_TRUE(doc, NS_ERROR_NOT_INITIALIZED);
|
||||
nsCOMPtr<nsIDocument> document = GetDocument();
|
||||
if (NS_WARN_IF(!document)) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
RefPtr<nsContentList> nodeList =
|
||||
doc->GetElementsByTagName(NS_LITERAL_STRING("head"));
|
||||
document->GetElementsByTagName(NS_LITERAL_STRING("head"));
|
||||
NS_ENSURE_TRUE(nodeList, NS_ERROR_NULL_POINTER);
|
||||
|
||||
nsCOMPtr<nsIContent> headNode = nodeList->Item(0);
|
||||
|
@ -2713,7 +2720,7 @@ HTMLEditor::InsertLinkAroundSelection(nsIDOMElement* aAnchorElement)
|
|||
nsresult
|
||||
HTMLEditor::SetHTMLBackgroundColor(const nsAString& aColor)
|
||||
{
|
||||
NS_PRECONDITION(mDocWeak, "Missing Editor DOM Document");
|
||||
MOZ_ASSERT(IsInitialized(), "The HTMLEditor hasn't been initialized yet");
|
||||
|
||||
// Find a selected or enclosing table element to set background on
|
||||
nsCOMPtr<nsIDOMElement> element;
|
||||
|
@ -2761,7 +2768,7 @@ HTMLEditor::SetBodyAttribute(const nsAString& aAttribute,
|
|||
{
|
||||
// TODO: Check selection for Cell, Row, Column or table and do color on appropriate level
|
||||
|
||||
NS_ASSERTION(mDocWeak, "Missing Editor DOM Document");
|
||||
MOZ_ASSERT(IsInitialized(), "The HTMLEditor hasn't been initialized yet");
|
||||
|
||||
// Set the background color attribute on the body tag
|
||||
nsCOMPtr<nsIDOMElement> bodyElement = do_QueryInterface(GetRoot());
|
||||
|
@ -2840,7 +2847,9 @@ HTMLEditor::ReplaceStyleSheet(const nsAString& aURL)
|
|||
}
|
||||
|
||||
// Make sure the pres shell doesn't disappear during the load.
|
||||
NS_ENSURE_TRUE(mDocWeak, NS_ERROR_NOT_INITIALIZED);
|
||||
if (NS_WARN_IF(!IsInitialized())) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
nsCOMPtr<nsIPresShell> ps = GetPresShell();
|
||||
NS_ENSURE_TRUE(ps, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
|
@ -2945,7 +2954,9 @@ HTMLEditor::RemoveOverrideStyleSheet(const nsAString& aURL)
|
|||
|
||||
NS_ENSURE_TRUE(sheet, NS_OK); /// Don't fail if sheet not found
|
||||
|
||||
NS_ENSURE_TRUE(mDocWeak, NS_ERROR_NOT_INITIALIZED);
|
||||
if (NS_WARN_IF(!IsInitialized())) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
nsCOMPtr<nsIPresShell> ps = GetPresShell();
|
||||
NS_ENSURE_TRUE(ps, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
|
@ -2964,8 +2975,8 @@ HTMLEditor::EnableStyleSheet(const nsAString& aURL,
|
|||
NS_ENSURE_TRUE(sheet, NS_OK); // Don't fail if sheet not found
|
||||
|
||||
// Ensure the style sheet is owned by our document.
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
|
||||
sheet->SetAssociatedDocument(doc, StyleSheet::NotOwnedByDocument);
|
||||
nsCOMPtr<nsIDocument> document = GetDocument();
|
||||
sheet->SetAssociatedDocument(document, StyleSheet::NotOwnedByDocument);
|
||||
|
||||
return sheet->SetDisabled(!aEnable);
|
||||
}
|
||||
|
@ -2981,8 +2992,8 @@ HTMLEditor::EnableExistingStyleSheet(const nsAString& aURL)
|
|||
}
|
||||
|
||||
// Ensure the style sheet is owned by our document.
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
|
||||
sheet->SetAssociatedDocument(doc, StyleSheet::NotOwnedByDocument);
|
||||
nsCOMPtr<nsIDocument> document = GetDocument();
|
||||
sheet->SetAssociatedDocument(document, StyleSheet::NotOwnedByDocument);
|
||||
|
||||
if (sheet->IsServo()) {
|
||||
// XXXheycam ServoStyleSheets don't support being enabled/disabled yet.
|
||||
|
@ -3365,13 +3376,12 @@ HTMLEditor::GetIsSelectionEditable(bool* aIsSelectionEditable)
|
|||
|
||||
static nsresult
|
||||
SetSelectionAroundHeadChildren(Selection* aSelection,
|
||||
nsIWeakReference* aDocWeak)
|
||||
nsCOMPtr<nsIDocument>& aDocument)
|
||||
{
|
||||
// Set selection around <head> node
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryReferent(aDocWeak);
|
||||
NS_ENSURE_TRUE(doc, NS_ERROR_NOT_INITIALIZED);
|
||||
MOZ_ASSERT(aDocument);
|
||||
|
||||
dom::Element* headNode = doc->GetHeadElement();
|
||||
// Set selection around <head> node
|
||||
dom::Element* headNode = aDocument->GetHeadElement();
|
||||
NS_ENSURE_STATE(headNode);
|
||||
|
||||
// Collapse selection to before first child of the head,
|
||||
|
@ -3392,7 +3402,11 @@ HTMLEditor::GetHeadContentsAsHTML(nsAString& aOutputString)
|
|||
// Save current selection
|
||||
AutoSelectionRestorer selectionRestorer(selection, this);
|
||||
|
||||
nsresult rv = SetSelectionAroundHeadChildren(selection, mDocWeak);
|
||||
nsCOMPtr<nsIDocument> document = GetDocument();
|
||||
if (NS_WARN_IF(!document)) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
nsresult rv = SetSelectionAroundHeadChildren(selection, document);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = OutputToString(NS_LITERAL_STRING("text/html"),
|
||||
|
@ -4248,10 +4262,11 @@ HTMLEditor::IsVisTextNode(nsIContent* aNode,
|
|||
|
||||
uint32_t length = aNode->TextLength();
|
||||
if (aSafeToAskFrames) {
|
||||
nsCOMPtr<nsISelectionController> selCon;
|
||||
nsresult rv = GetSelectionController(getter_AddRefs(selCon));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(selCon, NS_ERROR_FAILURE);
|
||||
nsCOMPtr<nsISelectionController> selectionController =
|
||||
GetSelectionController();
|
||||
if (NS_WARN_IF(!selectionController)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
bool isVisible = false;
|
||||
// ask the selection controller for information about whether any
|
||||
// of the data in the node is really rendered. This is really
|
||||
|
@ -4259,7 +4274,8 @@ HTMLEditor::IsVisTextNode(nsIContent* aNode,
|
|||
// So we put a call in the selection controller interface, since it's already
|
||||
// in bed with frames anyway. (this is a fix for bug 22227, and a
|
||||
// partial fix for bug 46209)
|
||||
rv = selCon->CheckVisibilityContent(aNode, 0, length, &isVisible);
|
||||
nsresult rv = selectionController->CheckVisibilityContent(aNode, 0, length,
|
||||
&isVisible);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (isVisible) {
|
||||
*outIsEmptyNode = false;
|
||||
|
@ -4776,7 +4792,9 @@ HTMLEditor::GetElementOrigin(nsIDOMElement* aElement,
|
|||
aX = 0;
|
||||
aY = 0;
|
||||
|
||||
NS_ENSURE_TRUE(mDocWeak, NS_ERROR_NOT_INITIALIZED);
|
||||
if (NS_WARN_IF(!IsInitialized())) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
nsCOMPtr<nsIPresShell> ps = GetPresShell();
|
||||
NS_ENSURE_TRUE(ps, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
|
@ -4918,28 +4936,29 @@ HTMLEditor::GetReturnInParagraphCreatesNewParagraph(bool* aCreatesNewParagraph)
|
|||
already_AddRefed<nsIContent>
|
||||
HTMLEditor::GetFocusedContent()
|
||||
{
|
||||
NS_ENSURE_TRUE(mDocWeak, nullptr);
|
||||
|
||||
nsFocusManager* fm = nsFocusManager::GetFocusManager();
|
||||
NS_ENSURE_TRUE(fm, nullptr);
|
||||
|
||||
nsCOMPtr<nsIContent> focusedContent = fm->GetFocusedContent();
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
|
||||
bool inDesignMode = doc->HasFlag(NODE_IS_EDITABLE);
|
||||
nsCOMPtr<nsIDocument> document = GetDocument();
|
||||
if (NS_WARN_IF(!document)) {
|
||||
return nullptr;
|
||||
}
|
||||
bool inDesignMode = document->HasFlag(NODE_IS_EDITABLE);
|
||||
if (!focusedContent) {
|
||||
// in designMode, nobody gets focus in most cases.
|
||||
if (inDesignMode && OurWindowHasFocus()) {
|
||||
nsCOMPtr<nsIContent> docRoot = doc->GetRootElement();
|
||||
return docRoot.forget();
|
||||
nsCOMPtr<nsIContent> rootContent = document->GetRootElement();
|
||||
return rootContent.forget();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (inDesignMode) {
|
||||
return OurWindowHasFocus() &&
|
||||
nsContentUtils::ContentIsDescendantOf(focusedContent, doc) ?
|
||||
focusedContent.forget() : nullptr;
|
||||
nsContentUtils::ContentIsDescendantOf(focusedContent, document) ?
|
||||
focusedContent.forget() : nullptr;
|
||||
}
|
||||
|
||||
// We're HTML editor for contenteditable
|
||||
|
@ -4962,28 +4981,32 @@ HTMLEditor::GetFocusedContentForIME()
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
|
||||
NS_ENSURE_TRUE(doc, nullptr);
|
||||
return doc->HasFlag(NODE_IS_EDITABLE) ? nullptr : focusedContent.forget();
|
||||
nsCOMPtr<nsIDocument> document = GetDocument();
|
||||
if (NS_WARN_IF(!document)) {
|
||||
return nullptr;
|
||||
}
|
||||
return document->HasFlag(NODE_IS_EDITABLE) ? nullptr :
|
||||
focusedContent.forget();
|
||||
}
|
||||
|
||||
bool
|
||||
HTMLEditor::IsActiveInDOMWindow()
|
||||
{
|
||||
NS_ENSURE_TRUE(mDocWeak, false);
|
||||
|
||||
nsFocusManager* fm = nsFocusManager::GetFocusManager();
|
||||
NS_ENSURE_TRUE(fm, false);
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
|
||||
bool inDesignMode = doc->HasFlag(NODE_IS_EDITABLE);
|
||||
nsCOMPtr<nsIDocument> document = GetDocument();
|
||||
if (NS_WARN_IF(!document)) {
|
||||
return false;
|
||||
}
|
||||
bool inDesignMode = document->HasFlag(NODE_IS_EDITABLE);
|
||||
|
||||
// If we're in designMode, we're always active in the DOM window.
|
||||
if (inDesignMode) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nsPIDOMWindowOuter* ourWindow = doc->GetWindow();
|
||||
nsPIDOMWindowOuter* ourWindow = document->GetWindow();
|
||||
nsCOMPtr<nsPIDOMWindowOuter> win;
|
||||
nsIContent* content =
|
||||
nsFocusManager::GetFocusedDescendant(ourWindow, false,
|
||||
|
@ -5006,12 +5029,12 @@ HTMLEditor::IsActiveInDOMWindow()
|
|||
Element*
|
||||
HTMLEditor::GetActiveEditingHost()
|
||||
{
|
||||
NS_ENSURE_TRUE(mDocWeak, nullptr);
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
|
||||
NS_ENSURE_TRUE(doc, nullptr);
|
||||
if (doc->HasFlag(NODE_IS_EDITABLE)) {
|
||||
return doc->GetBodyElement();
|
||||
nsCOMPtr<nsIDocument> document = GetDocument();
|
||||
if (NS_WARN_IF(!document)) {
|
||||
return nullptr;
|
||||
}
|
||||
if (document->HasFlag(NODE_IS_EDITABLE)) {
|
||||
return document->GetBodyElement();
|
||||
}
|
||||
|
||||
// We're HTML editor for contenteditable
|
||||
|
@ -5040,8 +5063,8 @@ HTMLEditor::GetDOMEventTarget()
|
|||
// Don't use getDocument here, because we have no way of knowing
|
||||
// whether Init() was ever called. So we need to get the document
|
||||
// ourselves, if it exists.
|
||||
NS_PRECONDITION(mDocWeak, "This editor has not been initialized yet");
|
||||
nsCOMPtr<mozilla::dom::EventTarget> target = do_QueryReferent(mDocWeak);
|
||||
MOZ_ASSERT(IsInitialized(), "The HTMLEditor has not been initialized yet");
|
||||
nsCOMPtr<mozilla::dom::EventTarget> target = GetDocument();
|
||||
return target.forget();
|
||||
}
|
||||
|
||||
|
@ -5101,12 +5124,16 @@ HTMLEditor::ResetRootElementAndEventTarget()
|
|||
nsresult
|
||||
HTMLEditor::GetBodyElement(nsIDOMHTMLElement** aBody)
|
||||
{
|
||||
NS_PRECONDITION(mDocWeak, "bad state, null mDocWeak");
|
||||
nsCOMPtr<nsIDOMHTMLDocument> htmlDoc = do_QueryReferent(mDocWeak);
|
||||
if (!htmlDoc) {
|
||||
MOZ_ASSERT(IsInitialized(), "The HTMLEditor hasn't been initialized yet");
|
||||
nsCOMPtr<nsIDocument> document = GetDocument();
|
||||
if (NS_WARN_IF(!document)) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
return htmlDoc->GetBody(aBody);
|
||||
nsCOMPtr<nsIDOMHTMLDocument> domHTMLDocument = do_QueryInterface(document);
|
||||
if (!domHTMLDocument) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
return domHTMLDocument->GetBody(aBody);
|
||||
}
|
||||
|
||||
already_AddRefed<nsINode>
|
||||
|
@ -5126,14 +5153,13 @@ HTMLEditor::GetFocusedNode()
|
|||
return node.forget();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
|
||||
return doc.forget();
|
||||
nsCOMPtr<nsIDocument> document = GetDocument();
|
||||
return document.forget();
|
||||
}
|
||||
|
||||
bool
|
||||
HTMLEditor::OurWindowHasFocus()
|
||||
{
|
||||
NS_ENSURE_TRUE(mDocWeak, false);
|
||||
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
|
||||
NS_ENSURE_TRUE(fm, false);
|
||||
nsCOMPtr<mozIDOMWindowProxy> focusedWindow;
|
||||
|
@ -5141,8 +5167,11 @@ HTMLEditor::OurWindowHasFocus()
|
|||
if (!focusedWindow) {
|
||||
return false;
|
||||
}
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
|
||||
nsPIDOMWindowOuter* ourWindow = doc->GetWindow();
|
||||
nsCOMPtr<nsIDocument> document = GetDocument();
|
||||
if (NS_WARN_IF(!document)) {
|
||||
return false;
|
||||
}
|
||||
nsPIDOMWindowOuter* ourWindow = document->GetWindow();
|
||||
return ourWindow == focusedWindow;
|
||||
}
|
||||
|
||||
|
@ -5160,12 +5189,14 @@ HTMLEditor::IsAcceptableInputEvent(WidgetGUIEvent* aGUIEvent)
|
|||
return true;
|
||||
}
|
||||
|
||||
NS_ENSURE_TRUE(mDocWeak, false);
|
||||
|
||||
nsCOMPtr<nsIDOMEventTarget> target = aGUIEvent->GetDOMEventTarget();
|
||||
NS_ENSURE_TRUE(target, false);
|
||||
|
||||
nsCOMPtr<nsIDocument> document = do_QueryReferent(mDocWeak);
|
||||
nsCOMPtr<nsIDocument> document = GetDocument();
|
||||
if (NS_WARN_IF(!document)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (document->HasFlag(NODE_IS_EDITABLE)) {
|
||||
// If this editor is in designMode and the event target is the document,
|
||||
// the event is for this editor.
|
||||
|
|
|
@ -2590,7 +2590,6 @@ HTMLEditor::GetCellIndexes(nsIDOMElement* aCell,
|
|||
aCell = cell;
|
||||
}
|
||||
|
||||
NS_ENSURE_TRUE(mDocWeak, NS_ERROR_NOT_INITIALIZED);
|
||||
nsCOMPtr<nsIPresShell> ps = GetPresShell();
|
||||
NS_ENSURE_TRUE(ps, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
|
|
|
@ -37,6 +37,11 @@ interface nsIWeakReference : nsISupports
|
|||
|
||||
%{C++
|
||||
virtual size_t SizeOfOnlyThis(mozilla::MallocSizeOf aMallocSizeOf) const = 0;
|
||||
|
||||
/**
|
||||
* Returns true if the referring object is alive. Otherwise, false.
|
||||
*/
|
||||
virtual bool IsAlive() const = 0;
|
||||
%}
|
||||
};
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@ public:
|
|||
// nsIWeakReference...
|
||||
NS_DECL_NSIWEAKREFERENCE
|
||||
size_t SizeOfOnlyThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
|
||||
bool IsAlive() const override { return mReferent != nullptr; }
|
||||
|
||||
private:
|
||||
MOZ_WEAKREF_DECL_OWNINGTHREAD
|
||||
|
|
Загрузка…
Ссылка в новой задаче