Bug 1612802 - Make `IMEStateManager` stop notifying `PuppetWidget` of editor state changes while its `StopIMEStateManagement()` r=m_kato

Currently, `BrowserParent` rejects any notifications which come after
it blurs from IME focus.
https://searchfox.org/mozilla-central/rev/919607a3610222099fbfb0113c98b77888ebcbfb/dom/ipc/BrowserParent.cpp#2157,2169,2181,2192,2203,2216

But for saving unnecessary IPC messages, we should make `IMEStateManager` in
a content process stop sending notifications which occurs during its
`StopIMEStateManagement()` is called.

Differential Revision: https://phabricator.services.mozilla.com/D93176
This commit is contained in:
Masayuki Nakano 2020-10-13 23:29:29 +00:00
Родитель ceddaceffd
Коммит 190b2c2740
5 изменённых файлов: 50 добавлений и 4 удалений

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

@ -476,6 +476,9 @@ nsPresContext* IMEContentObserver::GetPresContext() const {
void IMEContentObserver::Destroy() {
// WARNING: When you change this method, you have to check Unlink() too.
// Note that don't send any notifications later from here. I.e., notify
// IMEStateManager of the blur synchronously because IMEStateManager needs to
// stop notifying the main process if this is requested by the main process.
NotifyIMEOfBlur();
UnregisterObservers();
Clear();

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

@ -9,6 +9,7 @@
#include "mozilla/IMEStateManager.h"
#include "mozilla/Attributes.h"
#include "mozilla/AutoRestore.h"
#include "mozilla/EditorBase.h"
#include "mozilla/EventListenerManager.h"
#include "mozilla/EventStates.h"
@ -76,6 +77,7 @@ InputContext::Origin IMEStateManager::sOrigin = InputContext::ORIGIN_MAIN;
InputContext IMEStateManager::sActiveChildInputContext;
bool IMEStateManager::sInstalledMenuKeyboardListener = false;
bool IMEStateManager::sIsGettingNewIMEState = false;
bool IMEStateManager::sCleaningUpForStoppingIMEStateManagement = false;
// static
void IMEStateManager::Init() {
@ -203,6 +205,15 @@ void IMEStateManager::StopIMEStateManagement() {
// NOTE: Don't set input context from here since this has already lost
// the rights to change input context.
// The requestee of this method in the main process must destroy its
// active IMEContentObserver for making existing composition end and
// make it be possible to start new composition in new focused process.
// Therefore, we shouldn't notify the main process of any changes which
// occurred after here.
AutoRestore<bool> restoreStoppingIMEStateManagementState(
sCleaningUpForStoppingIMEStateManagement);
sCleaningUpForStoppingIMEStateManagement = true;
if (sTextCompositions && sPresContext) {
NotifyIME(REQUEST_TO_COMMIT_COMPOSITION, sPresContext, nullptr);
}
@ -1550,12 +1561,14 @@ nsresult IMEStateManager::NotifyIME(const IMENotification& aNotification,
"aWidget=0x%p, aBrowserParent=0x%p), sFocusedIMEWidget=0x%p, "
"BrowserParent::GetFocused()=0x%p, sFocusedIMEBrowserParent=0x%p, "
"aBrowserParent == BrowserParent::GetFocused()=%s, "
"aBrowserParent == sFocusedIMEBrowserParent=%s",
"aBrowserParent == sFocusedIMEBrowserParent=%s, "
"CanSendNotificationToTheMainProcess()=%s",
ToChar(aNotification.mMessage), aWidget, aBrowserParent,
sFocusedIMEWidget, BrowserParent::GetFocused(),
sFocusedIMEBrowserParent.get(),
GetBoolName(aBrowserParent == BrowserParent::GetFocused()),
GetBoolName(aBrowserParent == sFocusedIMEBrowserParent)));
GetBoolName(aBrowserParent == sFocusedIMEBrowserParent),
GetBoolName(CanSendNotificationToTheMainProcess())));
if (NS_WARN_IF(!aWidget)) {
MOZ_LOG(sISMLog, LogLevel::Error,
@ -1565,6 +1578,8 @@ nsresult IMEStateManager::NotifyIME(const IMENotification& aNotification,
switch (aNotification.mMessage) {
case NOTIFY_IME_OF_FOCUS: {
MOZ_ASSERT(CanSendNotificationToTheMainProcess());
// If focus notification comes from a remote browser which already lost
// focus, we shouldn't accept the focus notification. Then, following
// notifications from the process will be ignored.
@ -1632,7 +1647,10 @@ nsresult IMEStateManager::NotifyIME(const IMENotification& aNotification,
nsCOMPtr<nsIWidget> focusedIMEWidget(sFocusedIMEWidget);
sFocusedIMEWidget = nullptr;
sFocusedIMEBrowserParent = nullptr;
return focusedIMEWidget->NotifyIME(IMENotification(NOTIFY_IME_OF_BLUR));
return CanSendNotificationToTheMainProcess()
? focusedIMEWidget->NotifyIME(
IMENotification(NOTIFY_IME_OF_BLUR))
: NS_OK;
}
case NOTIFY_IME_OF_SELECTION_CHANGE:
case NOTIFY_IME_OF_TEXT_CHANGE:
@ -1660,6 +1678,9 @@ nsresult IMEStateManager::NotifyIME(const IMENotification& aNotification,
"is ignored because it's not for current focused IME widget"));
return NS_OK;
}
if (!CanSendNotificationToTheMainProcess()) {
return NS_OK;
}
nsCOMPtr<nsIWidget> widget(aWidget);
return widget->NotifyIME(aNotification);
}

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

@ -78,6 +78,15 @@ class IMEStateManager {
return sFocusedIMEBrowserParent == aBrowserParent;
}
/**
* If CanSendNotificationToTheMainProcess() returns false (it should occur
* only in a content process), we shouldn't notify the main process of
* any focused editor changes since the content process was blurred.
*/
static bool CanSendNotificationToTheMainProcess() {
return !sCleaningUpForStoppingIMEStateManagement;
}
/**
* Focus moved between browsers from aBlur to aFocus. (nullptr means the
* chrome process.)
@ -369,6 +378,10 @@ class IMEStateManager {
static bool sIsGettingNewIMEState;
static bool sCheckForIMEUnawareWebApps;
// Set to true only if this is an instance in a content process and
// only while `IMEStateManager::StopIMEStateManagement()`.
static bool sCleaningUpForStoppingIMEStateManagement;
class MOZ_STACK_CLASS GettingNewIMEStateBlocker final {
public:
GettingNewIMEStateBlocker()

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

@ -563,7 +563,7 @@ nsresult TextComposition::RequestToCommit(nsIWidget* aWidget, bool aDiscard) {
RefPtr<TextComposition> kungFuDeathGrip(this);
const nsAutoString lastData(mLastData);
{
if (IMEStateManager::CanSendNotificationToTheMainProcess()) {
AutoRestore<bool> saveRequestingCancel(mIsRequestingCancel);
AutoRestore<bool> saveRequestingCommit(mIsRequestingCommit);
if (aDiscard) {

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

@ -743,6 +743,8 @@ NativeIMEContext PuppetWidget::GetNativeIMEContext() {
nsresult PuppetWidget::NotifyIMEOfFocusChange(
const IMENotification& aIMENotification) {
MOZ_ASSERT(IMEStateManager::CanSendNotificationToTheMainProcess());
if (!mBrowserChild) {
return NS_ERROR_FAILURE;
}
@ -789,6 +791,8 @@ nsresult PuppetWidget::NotifyIMEOfFocusChange(
nsresult PuppetWidget::NotifyIMEOfCompositionUpdate(
const IMENotification& aIMENotification) {
MOZ_ASSERT(IMEStateManager::CanSendNotificationToTheMainProcess());
if (NS_WARN_IF(!mBrowserChild)) {
return NS_ERROR_FAILURE;
}
@ -804,8 +808,10 @@ nsresult PuppetWidget::NotifyIMEOfCompositionUpdate(
nsresult PuppetWidget::NotifyIMEOfTextChange(
const IMENotification& aIMENotification) {
MOZ_ASSERT(IMEStateManager::CanSendNotificationToTheMainProcess());
MOZ_ASSERT(aIMENotification.mMessage == NOTIFY_IME_OF_TEXT_CHANGE,
"Passed wrong notification");
if (!mBrowserChild) {
return NS_ERROR_FAILURE;
}
@ -835,6 +841,7 @@ nsresult PuppetWidget::NotifyIMEOfTextChange(
nsresult PuppetWidget::NotifyIMEOfSelectionChange(
const IMENotification& aIMENotification) {
MOZ_ASSERT(IMEStateManager::CanSendNotificationToTheMainProcess());
MOZ_ASSERT(aIMENotification.mMessage == NOTIFY_IME_OF_SELECTION_CHANGE,
"Passed wrong notification");
if (!mBrowserChild) {
@ -862,6 +869,7 @@ nsresult PuppetWidget::NotifyIMEOfSelectionChange(
nsresult PuppetWidget::NotifyIMEOfMouseButtonEvent(
const IMENotification& aIMENotification) {
MOZ_ASSERT(IMEStateManager::CanSendNotificationToTheMainProcess());
if (!mBrowserChild) {
return NS_ERROR_FAILURE;
}
@ -883,6 +891,7 @@ nsresult PuppetWidget::NotifyIMEOfMouseButtonEvent(
nsresult PuppetWidget::NotifyIMEOfPositionChange(
const IMENotification& aIMENotification) {
MOZ_ASSERT(IMEStateManager::CanSendNotificationToTheMainProcess());
if (NS_WARN_IF(!mBrowserChild)) {
return NS_ERROR_FAILURE;
}