Bug 1683226 - part 3: Get rid of pathes for handling plugin from `IMEStateManager`, `IMEContentObserver` and `ContentEventHandler` r=smaug

Differential Revision: https://phabricator.services.mozilla.com/D100102
This commit is contained in:
Masayuki Nakano 2020-12-21 05:52:49 +00:00
Родитель d876b20aaa
Коммит 5599ddec3c
7 изменённых файлов: 69 добавлений и 178 удалений

Просмотреть файл

@ -459,11 +459,6 @@ nsIContent* ContentEventHandler::GetFocusedContent() {
getter_AddRefs(focusedWindow));
}
bool ContentEventHandler::IsPlugin(nsIContent* aContent) {
return aContent &&
aContent->GetDesiredIMEState().mEnabled == IMEEnabled::Plugin;
}
nsresult ContentEventHandler::QueryContentRect(
nsIContent* aContent, WidgetQueryContentEvent* aEvent) {
MOZ_ASSERT(aContent, "aContent must not be null");
@ -2474,10 +2469,7 @@ nsresult ContentEventHandler::OnQueryEditorRect(
return rv;
}
nsIContent* focusedContent = GetFocusedContent();
if (NS_WARN_IF(NS_FAILED(QueryContentRect(
IsPlugin(focusedContent) ? focusedContent : mRootContent.get(),
aEvent)))) {
if (NS_WARN_IF(NS_FAILED(QueryContentRect(mRootContent, aEvent)))) {
return NS_ERROR_FAILURE;
}
@ -2719,19 +2711,12 @@ nsresult ContentEventHandler::OnQueryDOMWidgetHittest(
docFrame->PresContext()->DevPixelsToIntCSSPixels(eventLoc.y) -
docFrameRect.y);
Element* contentUnderMouse = mDocument->ElementFromPointHelper(
eventLocCSS.x, eventLocCSS.y, false, false, ViewportType::Visual);
if (contentUnderMouse) {
nsIWidget* targetWidget = nullptr;
nsIFrame* targetFrame = contentUnderMouse->GetPrimaryFrame();
nsIObjectFrame* pluginFrame = do_QueryFrame(targetFrame);
if (pluginFrame) {
targetWidget = pluginFrame->GetWidget();
} else if (targetFrame) {
targetWidget = targetFrame->GetNearestWidget();
}
if (aEvent->mWidget == targetWidget) {
aEvent->mReply->mWidgetIsHit = true;
if (Element* contentUnderMouse = mDocument->ElementFromPointHelper(
eventLocCSS.x, eventLocCSS.y, false, false, ViewportType::Visual)) {
if (nsIFrame* targetFrame = contentUnderMouse->GetPrimaryFrame()) {
if (aEvent->mWidget == targetFrame->GetNearestWidget()) {
aEvent->mReply->mWidgetIsHit = true;
}
}
}

Просмотреть файл

@ -292,8 +292,6 @@ class MOZ_STACK_CLASS ContentEventHandler {
static LineBreakType GetLineBreakType(bool aUseNativeLineBreak);
// Returns focused content (including its descendant documents).
nsIContent* GetFocusedContent();
// Returns true if the content is a plugin host.
bool IsPlugin(nsIContent* aContent);
// QueryContentRect() sets the rect of aContent's frame(s) to aEvent.
nsresult QueryContentRect(nsIContent* aContent,
WidgetQueryContentEvent* aEvent);

Просмотреть файл

@ -141,8 +141,8 @@ IMEContentObserver::IMEContentObserver()
#endif
}
void IMEContentObserver::Init(nsIWidget* aWidget, nsPresContext* aPresContext,
nsIContent* aContent, EditorBase* aEditorBase) {
void IMEContentObserver::Init(nsIWidget& aWidget, nsPresContext& aPresContext,
nsIContent* aContent, EditorBase& aEditorBase) {
State state = GetState();
if (NS_WARN_IF(state == eState_Observing)) {
return; // Nothing to do.
@ -156,22 +156,15 @@ void IMEContentObserver::Init(nsIWidget* aWidget, nsPresContext* aPresContext,
Clear();
}
mESM = aPresContext->EventStateManager();
mESM = aPresContext.EventStateManager();
mESM->OnStartToObserveContent(this);
mWidget = aWidget;
mWidget = &aWidget;
mIMENotificationRequests = &mWidget->IMENotificationRequestsRef();
if (aWidget->GetInputContext().mIMEState.mEnabled == IMEEnabled::Plugin) {
if (!InitWithPlugin(aPresContext, aContent)) {
Clear();
return;
}
} else {
if (!InitWithEditor(aPresContext, aContent, aEditorBase)) {
Clear();
return;
}
if (!InitWithEditor(aPresContext, aContent, aEditorBase)) {
Clear();
return;
}
if (firstInitialization) {
@ -228,22 +221,17 @@ void IMEContentObserver::OnIMEReceivedFocus() {
FlushMergeableNotifications();
}
bool IMEContentObserver::InitWithEditor(nsPresContext* aPresContext,
bool IMEContentObserver::InitWithEditor(nsPresContext& aPresContext,
nsIContent* aContent,
EditorBase* aEditorBase) {
MOZ_ASSERT(aEditorBase);
mEditableNode = IMEStateManager::GetRootEditableNode(aPresContext, aContent);
EditorBase& aEditorBase) {
mEditableNode = IMEStateManager::GetRootEditableNode(&aPresContext, aContent);
if (NS_WARN_IF(!mEditableNode)) {
return false;
}
mEditorBase = aEditorBase;
if (NS_WARN_IF(!mEditorBase)) {
return false;
}
mEditorBase = &aEditorBase;
RefPtr<PresShell> presShell = aPresContext->GetPresShell();
RefPtr<PresShell> presShell = aPresContext.GetPresShell();
// get selection and root content
nsCOMPtr<nsISelectionController> selCon;
@ -253,7 +241,7 @@ bool IMEContentObserver::InitWithEditor(nsPresContext* aPresContext,
return false;
}
frame->GetSelectionController(aPresContext, getter_AddRefs(selCon));
frame->GetSelectionController(&aPresContext, getter_AddRefs(selCon));
} else {
// mEditableNode is a document
selCon = presShell;
@ -289,62 +277,16 @@ bool IMEContentObserver::InitWithEditor(nsPresContext* aPresContext,
return false;
}
mDocShell = aPresContext->GetDocShell();
mDocShell = aPresContext.GetDocShell();
if (NS_WARN_IF(!mDocShell)) {
return false;
}
mDocumentObserver = new DocumentObserver(*this);
MOZ_ASSERT(!WasInitializedWithPlugin());
return true;
}
bool IMEContentObserver::InitWithPlugin(nsPresContext* aPresContext,
nsIContent* aContent) {
if (NS_WARN_IF(!aContent) ||
NS_WARN_IF(aContent->GetDesiredIMEState().mEnabled !=
IMEEnabled::Plugin)) {
return false;
}
nsIFrame* frame = aContent->GetPrimaryFrame();
if (NS_WARN_IF(!frame)) {
return false;
}
nsCOMPtr<nsISelectionController> selCon;
frame->GetSelectionController(aPresContext, getter_AddRefs(selCon));
if (NS_WARN_IF(!selCon)) {
return false;
}
mSelection = selCon->GetSelection(nsISelectionController::SELECTION_NORMAL);
if (NS_WARN_IF(!mSelection)) {
return false;
}
mEditorBase = nullptr;
mEditableNode = aContent;
mRootContent = aContent;
// Should be safe to clear mDocumentObserver here even though it *might*
// grab this instance because this is called by Init() and the callers of
// it and MaybeReinitialize() grabs this instance with local RefPtr.
// So, this won't cause refcount of this instance become 0.
mDocumentObserver = nullptr;
mDocShell = aPresContext->GetDocShell();
if (NS_WARN_IF(!mDocShell)) {
return false;
}
MOZ_ASSERT(WasInitializedWithPlugin());
return true;
}
bool IMEContentObserver::WasInitializedWithPlugin() const {
return mDocShell && !mEditorBase;
}
void IMEContentObserver::Clear() {
mEditorBase = nullptr;
mSelection = nullptr;
@ -381,18 +323,13 @@ void IMEContentObserver::ObserveEditableNode() {
mEditorBase->SetIMEContentObserver(this);
}
if (!WasInitializedWithPlugin()) {
// Add text change observer only when this starts to observe
// non-plugin content since we cannot detect text changes in
// plugins.
mRootContent->AddMutationObserver(this);
// If it's in a document (should be so), we can use document observer to
// reduce redundant computation of text change offsets.
dom::Document* doc = mRootContent->GetComposedDoc();
if (doc) {
RefPtr<DocumentObserver> documentObserver = mDocumentObserver;
documentObserver->Observe(doc);
}
mRootContent->AddMutationObserver(this);
// If it's in a document (should be so), we can use document observer to
// reduce redundant computation of text change offsets.
dom::Document* doc = mRootContent->GetComposedDoc();
if (doc) {
RefPtr<DocumentObserver> documentObserver = mDocumentObserver;
documentObserver->Observe(doc);
}
if (mDocShell) {
@ -498,18 +435,18 @@ bool IMEContentObserver::Destroyed() const { return !mWidget; }
void IMEContentObserver::DisconnectFromEventStateManager() { mESM = nullptr; }
bool IMEContentObserver::MaybeReinitialize(nsIWidget* aWidget,
nsPresContext* aPresContext,
bool IMEContentObserver::MaybeReinitialize(nsIWidget& aWidget,
nsPresContext& aPresContext,
nsIContent* aContent,
EditorBase* aEditorBase) {
if (!IsObservingContent(aPresContext, aContent)) {
EditorBase& aEditorBase) {
if (!IsObservingContent(&aPresContext, aContent)) {
return false;
}
if (GetState() == eState_StoppedObserving) {
Init(aWidget, aPresContext, aContent, aEditorBase);
}
return IsManaging(aPresContext, aContent);
return IsManaging(&aPresContext, aContent);
}
bool IMEContentObserver::IsManaging(nsPresContext* aPresContext,
@ -548,10 +485,8 @@ IMEContentObserver::State IMEContentObserver::GetState() const {
bool IMEContentObserver::IsObservingContent(nsPresContext* aPresContext,
nsIContent* aContent) const {
return IsInitializedWithPlugin()
? mRootContent == aContent && mRootContent != nullptr
: mEditableNode ==
IMEStateManager::GetRootEditableNode(aPresContext, aContent);
return mEditableNode ==
IMEStateManager::GetRootEditableNode(aPresContext, aContent);
}
bool IMEContentObserver::IsEditorHandlingEventForComposition() const {
@ -710,7 +645,7 @@ nsresult IMEContentObserver::HandleQueryContentEvent(
return rv;
}
if (aEvent->Succeeded() && !IsInitializedWithPlugin() &&
if (aEvent->Succeeded() &&
NS_WARN_IF(aEvent->mReply->mContentsRoot != mRootContent)) {
// Focus has changed unexpectedly, so make the query fail.
aEvent->mReply.reset();
@ -1308,10 +1243,6 @@ void IMEContentObserver::MaybeNotifyCompositionEventHandled() {
bool IMEContentObserver::UpdateSelectionCache(bool aRequireFlush /* = true */) {
MOZ_ASSERT(IsSafeToNotifyIME());
if (WasInitializedWithPlugin()) {
return false;
}
mSelectionData.ClearSelectionData();
// XXX Cannot we cache some information for reducing the cost to compute

Просмотреть файл

@ -81,18 +81,12 @@ class IMEContentObserver final : public nsStubMutationObserver,
*
* @param aWidget The widget which can access native IME.
* @param aPresContext The PresContext which has aContent.
* @param aContent An editable element or a plugin host element which
* user may use IME in.
* Or nullptr if this will observe design mode
* document.
* @param aEditorBase When aContent is an editable element or nullptr,
* non-nullptr referring an editor instance which
* manages aContent.
* Otherwise, i.e., this will observe a plugin content,
* should be nullptr.
* @param aContent An editable element or nullptr if this will observe
* design mode document.
* @param aEditorBase The editor which is associated with aContent.
*/
MOZ_CAN_RUN_SCRIPT void Init(nsIWidget* aWidget, nsPresContext* aPresContext,
nsIContent* aContent, EditorBase* aEditorBase);
MOZ_CAN_RUN_SCRIPT void Init(nsIWidget& aWidget, nsPresContext& aPresContext,
nsIContent* aContent, EditorBase& aEditorBase);
/**
* Destroy() finalizes the instance, i.e., stops observing contents and
@ -125,14 +119,13 @@ class IMEContentObserver final : public nsStubMutationObserver,
* @return Returns true if the instance is managing the content.
* Otherwise, false.
*/
MOZ_CAN_RUN_SCRIPT bool MaybeReinitialize(nsIWidget* aWidget,
nsPresContext* aPresContext,
MOZ_CAN_RUN_SCRIPT bool MaybeReinitialize(nsIWidget& aWidget,
nsPresContext& aPresContext,
nsIContent* aContent,
EditorBase* aEditorBase);
EditorBase& aEditorBase);
bool IsManaging(nsPresContext* aPresContext, nsIContent* aContent) const;
bool IsManaging(const TextComposition* aTextComposition) const;
bool WasInitializedWithPlugin() const;
bool WasInitializedWith(const EditorBase& aEditorBase) const {
return mEditorBase == &aEditorBase;
}
@ -182,11 +175,9 @@ class IMEContentObserver final : public nsStubMutationObserver,
eState_Observing
};
State GetState() const;
MOZ_CAN_RUN_SCRIPT bool InitWithEditor(nsPresContext* aPresContext,
MOZ_CAN_RUN_SCRIPT bool InitWithEditor(nsPresContext& aPresContext,
nsIContent* aContent,
EditorBase* aEditorBase);
bool InitWithPlugin(nsPresContext* aPresContext, nsIContent* aContent);
bool IsInitializedWithPlugin() const { return !mEditorBase; }
EditorBase& aEditorBase);
void OnIMEReceivedFocus();
void Clear();
bool IsObservingContent(nsPresContext* aPresContext,
@ -293,8 +284,6 @@ class IMEContentObserver final : public nsStubMutationObserver,
/**
* UpdateSelectionCache() updates mSelectionData with the latest selection.
* This should be called only when IsSafeToNotifyIME() returns true.
*
* Note that this does nothing if WasInitializedWithPlugin() returns true.
*/
MOZ_CAN_RUN_SCRIPT bool UpdateSelectionCache(bool aRequireFlush = true);

Просмотреть файл

@ -664,19 +664,8 @@ nsresult IMEStateManager::OnChangeFocusInternal(nsPresContext* aPresContext,
sPresContext = aPresContext;
sContent = aContent;
// Don't call CreateIMEContentObserver() here except when a plugin gets
// focus because it will be called from the focus event handler of focused
// editor.
if (newState.mEnabled == IMEEnabled::Plugin) {
CreateIMEContentObserver(nullptr);
if (sActiveIMEContentObserver) {
MOZ_LOG(sISMLog, LogLevel::Debug,
(" OnChangeFocusInternal(), an IMEContentObserver instance is "
"created for plugin and trying to flush its pending "
"notifications..."));
sActiveIMEContentObserver->TryToFlushPendingNotifications(false);
}
}
// Don't call CreateIMEContentObserver() here because it will be called from
// the focus event handler of focused editor.
return NS_OK;
}
@ -844,7 +833,7 @@ void IMEStateManager::OnFocusInEditor(nsPresContext* aPresContext,
DestroyIMEContentObserver();
}
CreateIMEContentObserver(&aEditorBase);
CreateIMEContentObserver(aEditorBase);
// Let's flush the focus notification now.
if (sActiveIMEContentObserver) {
@ -921,13 +910,13 @@ void IMEStateManager::OnReFocus(nsPresContext* aPresContext,
// static
void IMEStateManager::UpdateIMEState(const IMEState& aNewIMEState,
nsIContent* aContent,
EditorBase* aEditorBase) {
EditorBase& aEditorBase) {
MOZ_LOG(
sISMLog, LogLevel::Info,
("UpdateIMEState(aNewIMEState=%s, aContent=0x%p, aEditorBase=0x%p), "
"sPresContext=0x%p, sContent=0x%p, sWidget=0x%p (available: %s), "
"sActiveIMEContentObserver=0x%p, sIsGettingNewIMEState=%s",
ToString(aNewIMEState).c_str(), aContent, aEditorBase,
ToString(aNewIMEState).c_str(), aContent, &aEditorBase,
sPresContext.get(), sContent.get(), sWidget,
GetBoolName(sWidget && !sWidget->Destroyed()),
sActiveIMEContentObserver.get(), GetBoolName(sIsGettingNewIMEState)));
@ -939,15 +928,7 @@ void IMEStateManager::UpdateIMEState(const IMEState& aNewIMEState,
return;
}
RefPtr<PresShell> presShell;
if (!aEditorBase) {
MOZ_ASSERT(aContent, "we must have content");
Document* doc = aContent->OwnerDoc();
presShell = doc->GetPresShell();
} else {
presShell = aEditorBase->GetPresShell();
}
RefPtr<PresShell> presShell(aEditorBase.GetPresShell());
if (NS_WARN_IF(!presShell)) {
MOZ_LOG(sISMLog, LogLevel::Error,
(" UpdateIMEState(), FAILED due to "
@ -994,7 +975,7 @@ void IMEStateManager::UpdateIMEState(const IMEState& aNewIMEState,
return;
}
nsCOMPtr<nsIWidget> widget(sWidget);
OwningNonNull<nsIWidget> widget(*sWidget);
MOZ_ASSERT(!sPresContext->GetTextInputHandlingWidget() ||
sPresContext->GetTextInputHandlingWidget() == widget);
@ -1011,7 +992,7 @@ void IMEStateManager::UpdateIMEState(const IMEState& aNewIMEState,
(" UpdateIMEState(), try to reinitialize the "
"active IMEContentObserver"));
RefPtr<IMEContentObserver> contentObserver = sActiveIMEContentObserver;
RefPtr<nsPresContext> presContext = sPresContext;
OwningNonNull<nsPresContext> presContext(*sPresContext);
if (!contentObserver->MaybeReinitialize(widget, presContext, aContent,
aEditorBase)) {
MOZ_LOG(sISMLog, LogLevel::Error,
@ -1930,13 +1911,13 @@ void IMEStateManager::DestroyIMEContentObserver() {
}
// static
void IMEStateManager::CreateIMEContentObserver(EditorBase* aEditorBase) {
void IMEStateManager::CreateIMEContentObserver(EditorBase& aEditorBase) {
MOZ_LOG(sISMLog, LogLevel::Info,
("CreateIMEContentObserver(aEditorBase=0x%p), "
"sPresContext=0x%p, sContent=0x%p, sWidget=0x%p (available: %s), "
"sActiveIMEContentObserver=0x%p, "
"sActiveIMEContentObserver->IsManaging(sPresContext, sContent)=%s",
aEditorBase, sPresContext.get(), sContent.get(), sWidget,
&aEditorBase, sPresContext.get(), sContent.get(), sWidget,
GetBoolName(sWidget && !sWidget->Destroyed()),
sActiveIMEContentObserver.get(),
GetBoolName(sActiveIMEContentObserver
@ -1959,7 +1940,7 @@ void IMEStateManager::CreateIMEContentObserver(EditorBase* aEditorBase) {
return; // Sometimes, there are no widgets.
}
nsCOMPtr<nsIWidget> widget(sWidget);
OwningNonNull<nsIWidget> widget(*sWidget);
// If it's not text editable, we don't need to create IMEContentObserver.
if (!IsIMEObserverNeeded(widget->GetInputContext().mIMEState)) {
@ -1976,6 +1957,13 @@ void IMEStateManager::CreateIMEContentObserver(EditorBase* aEditorBase) {
return;
}
if (NS_WARN_IF(!sPresContext)) {
MOZ_LOG(sISMLog, LogLevel::Error,
(" CreateIMEContentObserver(), FAILED due to "
"the nsPresContext is nullptr"));
return;
}
MOZ_ASSERT(sPresContext->GetTextInputHandlingWidget() == widget);
MOZ_LOG(sISMLog, LogLevel::Debug,
@ -1988,7 +1976,7 @@ void IMEStateManager::CreateIMEContentObserver(EditorBase* aEditorBase) {
// We should hold the current instance here.
RefPtr<IMEContentObserver> activeIMEContentObserver(
sActiveIMEContentObserver);
RefPtr<nsPresContext> presContext = sPresContext;
OwningNonNull<nsPresContext> presContext(*sPresContext);
RefPtr<nsIContent> content = sContent;
activeIMEContentObserver->Init(widget, presContext, content, aEditorBase);
}

Просмотреть файл

@ -190,7 +190,7 @@ class IMEStateManager {
// asynchronously.
MOZ_CAN_RUN_SCRIPT_BOUNDARY static void UpdateIMEState(
const IMEState& aNewIMEState, nsIContent* aContent,
EditorBase* aEditorBase);
EditorBase& aEditorBase);
// This method is called when user operates mouse button in focused editor
// and before the editor handles it.
@ -315,7 +315,7 @@ class IMEStateManager {
// marked too. Probably, we should initialize IMEContentObserver
// asynchronously.
MOZ_CAN_RUN_SCRIPT_BOUNDARY static void CreateIMEContentObserver(
EditorBase* aEditorBase);
EditorBase& aEditorBase);
static void DestroyIMEContentObserver();

Просмотреть файл

@ -398,7 +398,7 @@ nsresult EditorBase::PostCreate() {
}
// May be null in design mode
nsCOMPtr<nsIContent> content = GetFocusedContentForIME();
IMEStateManager::UpdateIMEState(newState, content, this);
IMEStateManager::UpdateIMEState(newState, content, *this);
}
// FYI: This call might cause destroying this editor.
@ -637,7 +637,7 @@ NS_IMETHODIMP EditorBase::SetFlags(uint32_t aFlags) {
// NOTE: When the enabled state isn't going to be modified, this method
// is going to do nothing.
nsCOMPtr<nsIContent> content = GetFocusedContentForIME();
IMEStateManager::UpdateIMEState(newState, content, this);
IMEStateManager::UpdateIMEState(newState, content, *this);
}
}