зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1377672 - part3: IMEStateManager::NotifyIME() should ignore notifications and requests which comes from unexpected process r=m_kato,smaug
IME should receive notifications and requests only from proper process. E.g., IME shouldn't commit composition by a request which came from previous focused process. This patch makes that IMEStateManager::NotifyIME() takes pointer to TabParent optionally. If the request or notification came from remote process, it should be non-nullptr. Then, this makes it ignore notifications and requests from unexpected process. Note that this patch also touches some gfx headers because they use |ipc::| but compiler is confused at the ambiguousness between |mozilla::ipc::| and |mozilla::dom::ipc::|. Finally, this patch changes the NS_ASSERTION in IMEHandler::OnDestroyWindow() to MOZ_ASSERT because the orange caused by the NS_ASSERTION was not realized since there was already an intermittent orange bug caused by different NS_ASSERTION. MozReview-Commit-ID: 9CgKXQRJWmN --HG-- extra : source : f3b5711908870c5e0e852a399a07e0ae721a12f1
This commit is contained in:
Родитель
c726abb366
Коммит
d6e921676c
|
@ -136,10 +136,23 @@ GetIMEStateSetOpenName(IMEState::Open aOpen)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
IsSameProcess(const TabParent* aTabParent1, const TabParent* aTabParent2)
|
||||||
|
{
|
||||||
|
if (aTabParent1 == aTabParent2) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!aTabParent1 != !aTabParent2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return aTabParent1->Manager() == aTabParent2->Manager();
|
||||||
|
}
|
||||||
|
|
||||||
StaticRefPtr<nsIContent> IMEStateManager::sContent;
|
StaticRefPtr<nsIContent> IMEStateManager::sContent;
|
||||||
StaticRefPtr<nsPresContext> IMEStateManager::sPresContext;
|
StaticRefPtr<nsPresContext> IMEStateManager::sPresContext;
|
||||||
nsIWidget* IMEStateManager::sWidget = nullptr;
|
nsIWidget* IMEStateManager::sWidget = nullptr;
|
||||||
nsIWidget* IMEStateManager::sFocusedIMEWidget = nullptr;
|
nsIWidget* IMEStateManager::sFocusedIMEWidget = nullptr;
|
||||||
|
StaticRefPtr<TabParent> IMEStateManager::sFocusedIMETabParent;
|
||||||
nsIWidget* IMEStateManager::sActiveInputContextWidget = nullptr;
|
nsIWidget* IMEStateManager::sActiveInputContextWidget = nullptr;
|
||||||
StaticRefPtr<TabParent> IMEStateManager::sActiveTabParent;
|
StaticRefPtr<TabParent> IMEStateManager::sActiveTabParent;
|
||||||
StaticRefPtr<IMEContentObserver> IMEStateManager::sActiveIMEContentObserver;
|
StaticRefPtr<IMEContentObserver> IMEStateManager::sActiveIMEContentObserver;
|
||||||
|
@ -149,7 +162,6 @@ bool IMEStateManager::sInstalledMenuKeyboardListener = false;
|
||||||
bool IMEStateManager::sIsGettingNewIMEState = false;
|
bool IMEStateManager::sIsGettingNewIMEState = false;
|
||||||
bool IMEStateManager::sCheckForIMEUnawareWebApps = false;
|
bool IMEStateManager::sCheckForIMEUnawareWebApps = false;
|
||||||
bool IMEStateManager::sInputModeSupported = false;
|
bool IMEStateManager::sInputModeSupported = false;
|
||||||
bool IMEStateManager::sRemoteHasFocus = false;
|
|
||||||
|
|
||||||
// static
|
// static
|
||||||
void
|
void
|
||||||
|
@ -226,7 +238,7 @@ IMEStateManager::StopIMEStateManagement()
|
||||||
// the rights to change input context.
|
// the rights to change input context.
|
||||||
|
|
||||||
if (sTextCompositions && sPresContext) {
|
if (sTextCompositions && sPresContext) {
|
||||||
NotifyIME(REQUEST_TO_COMMIT_COMPOSITION, sPresContext);
|
NotifyIME(REQUEST_TO_COMMIT_COMPOSITION, sPresContext, sActiveTabParent);
|
||||||
}
|
}
|
||||||
sActiveInputContextWidget = nullptr;
|
sActiveInputContextWidget = nullptr;
|
||||||
sPresContext = nullptr;
|
sPresContext = nullptr;
|
||||||
|
@ -444,7 +456,7 @@ IMEStateManager::OnChangeFocusInternal(nsPresContext* aPresContext,
|
||||||
// If we're deactivating, we shouldn't commit composition forcibly because
|
// If we're deactivating, we shouldn't commit composition forcibly because
|
||||||
// the user may want to continue the composition.
|
// the user may want to continue the composition.
|
||||||
if (aPresContext) {
|
if (aPresContext) {
|
||||||
NotifyIME(REQUEST_TO_COMMIT_COMPOSITION, oldWidget);
|
NotifyIME(REQUEST_TO_COMMIT_COMPOSITION, oldWidget, sFocusedIMETabParent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -478,11 +490,7 @@ IMEStateManager::OnChangeFocusInternal(nsPresContext* aPresContext,
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsIContentParent* currentContentParent =
|
if (sActiveTabParent && !IsSameProcess(sActiveTabParent, newTabParent)) {
|
||||||
sActiveTabParent ? sActiveTabParent->Manager() : nullptr;
|
|
||||||
nsIContentParent* newContentParent =
|
|
||||||
newTabParent ? newTabParent->Manager() : nullptr;
|
|
||||||
if (sActiveTabParent && currentContentParent != newContentParent) {
|
|
||||||
MOZ_LOG(sISMLog, LogLevel::Debug,
|
MOZ_LOG(sISMLog, LogLevel::Debug,
|
||||||
(" OnChangeFocusInternal(), notifying previous "
|
(" OnChangeFocusInternal(), notifying previous "
|
||||||
"focused child process of parent process or another child process "
|
"focused child process of parent process or another child process "
|
||||||
|
@ -565,7 +573,8 @@ IMEStateManager::OnChangeFocusInternal(nsPresContext* aPresContext,
|
||||||
// Even if focus isn't changing actually, we should commit current
|
// Even if focus isn't changing actually, we should commit current
|
||||||
// composition here since the IME state is changing.
|
// composition here since the IME state is changing.
|
||||||
if (sPresContext && oldWidget && !focusActuallyChanging) {
|
if (sPresContext && oldWidget && !focusActuallyChanging) {
|
||||||
NotifyIME(REQUEST_TO_COMMIT_COMPOSITION, oldWidget);
|
NotifyIME(REQUEST_TO_COMMIT_COMPOSITION, oldWidget,
|
||||||
|
sFocusedIMETabParent);
|
||||||
}
|
}
|
||||||
} else if (aAction.mFocusChange == InputContextAction::FOCUS_NOT_CHANGED) {
|
} else if (aAction.mFocusChange == InputContextAction::FOCUS_NOT_CHANGED) {
|
||||||
// If aContent isn't null or aContent is null but editable, somebody gets
|
// If aContent isn't null or aContent is null but editable, somebody gets
|
||||||
|
@ -923,7 +932,7 @@ IMEStateManager::UpdateIMEState(const IMEState& aNewIMEState,
|
||||||
|
|
||||||
if (updateIMEState) {
|
if (updateIMEState) {
|
||||||
// commit current composition before modifying IME state.
|
// commit current composition before modifying IME state.
|
||||||
NotifyIME(REQUEST_TO_COMMIT_COMPOSITION, widget);
|
NotifyIME(REQUEST_TO_COMMIT_COMPOSITION, widget, sFocusedIMETabParent);
|
||||||
if (NS_WARN_IF(widget->Destroyed())) {
|
if (NS_WARN_IF(widget->Destroyed())) {
|
||||||
MOZ_LOG(sISMLog, LogLevel::Error,
|
MOZ_LOG(sISMLog, LogLevel::Error,
|
||||||
(" UpdateIMEState(), widget has gone during committing composition"));
|
(" UpdateIMEState(), widget has gone during committing composition"));
|
||||||
|
@ -1443,25 +1452,29 @@ IMEStateManager::OnCompositionEventDiscarded(
|
||||||
nsresult
|
nsresult
|
||||||
IMEStateManager::NotifyIME(IMEMessage aMessage,
|
IMEStateManager::NotifyIME(IMEMessage aMessage,
|
||||||
nsIWidget* aWidget,
|
nsIWidget* aWidget,
|
||||||
bool aOriginIsRemote)
|
TabParent* aTabParent)
|
||||||
{
|
{
|
||||||
return IMEStateManager::NotifyIME(IMENotification(aMessage), aWidget,
|
return IMEStateManager::NotifyIME(IMENotification(aMessage), aWidget,
|
||||||
aOriginIsRemote);
|
aTabParent);
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
nsresult
|
nsresult
|
||||||
IMEStateManager::NotifyIME(const IMENotification& aNotification,
|
IMEStateManager::NotifyIME(const IMENotification& aNotification,
|
||||||
nsIWidget* aWidget,
|
nsIWidget* aWidget,
|
||||||
bool aOriginIsRemote)
|
TabParent* aTabParent)
|
||||||
{
|
{
|
||||||
MOZ_LOG(sISMLog, LogLevel::Info,
|
MOZ_LOG(sISMLog, LogLevel::Info,
|
||||||
("NotifyIME(aNotification={ mMessage=%s }, "
|
("NotifyIME(aNotification={ mMessage=%s }, "
|
||||||
"aWidget=0x%p, aOriginIsRemote=%s), sFocusedIMEWidget=0x%p, "
|
"aWidget=0x%p, aTabParent=0x%p), sFocusedIMEWidget=0x%p, "
|
||||||
"sRemoteHasFocus=%s",
|
"sActiveTabParent=0x%p, sFocusedIMETabParent=0x%p, "
|
||||||
|
"IsSameProcess(aTabParent, sActiveTabParent)=%s, "
|
||||||
|
"IsSameProcess(aTabParent, sFocusedIMETabParent)=%s",
|
||||||
ToChar(aNotification.mMessage), aWidget,
|
ToChar(aNotification.mMessage), aWidget,
|
||||||
GetBoolName(aOriginIsRemote), sFocusedIMEWidget,
|
aTabParent, sFocusedIMEWidget, sActiveTabParent.get(),
|
||||||
GetBoolName(sRemoteHasFocus)));
|
sFocusedIMETabParent.get(),
|
||||||
|
GetBoolName(IsSameProcess(aTabParent, sActiveTabParent)),
|
||||||
|
GetBoolName(IsSameProcess(aTabParent, sFocusedIMETabParent))));
|
||||||
|
|
||||||
if (NS_WARN_IF(!aWidget)) {
|
if (NS_WARN_IF(!aWidget)) {
|
||||||
MOZ_LOG(sISMLog, LogLevel::Error,
|
MOZ_LOG(sISMLog, LogLevel::Error,
|
||||||
|
@ -1471,61 +1484,58 @@ IMEStateManager::NotifyIME(const IMENotification& aNotification,
|
||||||
|
|
||||||
switch (aNotification.mMessage) {
|
switch (aNotification.mMessage) {
|
||||||
case NOTIFY_IME_OF_FOCUS: {
|
case NOTIFY_IME_OF_FOCUS: {
|
||||||
|
// If focus notification comes from a remote process which already lost
|
||||||
|
// focus, we shouldn't accept the focus notification. Then, following
|
||||||
|
// notifications from the process will be ignored.
|
||||||
|
if (NS_WARN_IF(!IsSameProcess(aTabParent, sActiveTabParent))) {
|
||||||
|
MOZ_ASSERT(aTabParent,
|
||||||
|
"Why was the input context initialized for a remote process but "
|
||||||
|
"does this process get IME focus?");
|
||||||
|
MOZ_LOG(sISMLog, LogLevel::Warning,
|
||||||
|
(" NotifyIME(), WARNING, the received focus notification is ignored "
|
||||||
|
"because input context was initialized for %s, perhaps, it came "
|
||||||
|
"from a busy remote process",
|
||||||
|
sActiveTabParent ? "another remote process" : "current process"));
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
// If there is pending blur notification for current focused IME,
|
||||||
|
// we should notify IME of blur by ourselves. Then, we should ignore
|
||||||
|
// following notifications coming from the process.
|
||||||
if (sFocusedIMEWidget) {
|
if (sFocusedIMEWidget) {
|
||||||
if (NS_WARN_IF(!sRemoteHasFocus && !aOriginIsRemote)) {
|
MOZ_ASSERT(sFocusedIMETabParent || aTabParent,
|
||||||
MOZ_LOG(sISMLog, LogLevel::Error,
|
"This case shouldn't be caused by focus move in this process");
|
||||||
(" NotifyIME(), although, this process is "
|
|
||||||
"getting IME focus but there was focused IME widget"));
|
|
||||||
} else {
|
|
||||||
MOZ_LOG(sISMLog, LogLevel::Info,
|
|
||||||
(" NotifyIME(), tries to notify IME of "
|
|
||||||
"blur first because remote process's blur notification hasn't "
|
|
||||||
"been received yet..."));
|
|
||||||
}
|
|
||||||
nsCOMPtr<nsIWidget> focusedIMEWidget(sFocusedIMEWidget);
|
nsCOMPtr<nsIWidget> focusedIMEWidget(sFocusedIMEWidget);
|
||||||
sFocusedIMEWidget = nullptr;
|
sFocusedIMEWidget = nullptr;
|
||||||
sRemoteHasFocus = false;
|
sFocusedIMETabParent = nullptr;
|
||||||
focusedIMEWidget->NotifyIME(IMENotification(NOTIFY_IME_OF_BLUR));
|
focusedIMEWidget->NotifyIME(IMENotification(NOTIFY_IME_OF_BLUR));
|
||||||
}
|
}
|
||||||
sRemoteHasFocus = aOriginIsRemote;
|
sFocusedIMETabParent = aTabParent;
|
||||||
sFocusedIMEWidget = aWidget;
|
sFocusedIMEWidget = aWidget;
|
||||||
nsCOMPtr<nsIWidget> widget(aWidget);
|
nsCOMPtr<nsIWidget> widget(aWidget);
|
||||||
return widget->NotifyIME(aNotification);
|
return widget->NotifyIME(aNotification);
|
||||||
}
|
}
|
||||||
case NOTIFY_IME_OF_BLUR: {
|
case NOTIFY_IME_OF_BLUR: {
|
||||||
if (!sRemoteHasFocus && aOriginIsRemote) {
|
if (!IsSameProcess(aTabParent, sFocusedIMETabParent)) {
|
||||||
MOZ_LOG(sISMLog, LogLevel::Info,
|
MOZ_LOG(sISMLog, LogLevel::Warning,
|
||||||
(" NotifyIME(), received blur notification "
|
(" NotifyIME(), WARNING, the received blur notification is ignored "
|
||||||
"after another one has focus, nothing to do..."));
|
"because it's not from current focused IME process"));
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
if (NS_WARN_IF(sRemoteHasFocus && !aOriginIsRemote)) {
|
if (!sFocusedIMEWidget) {
|
||||||
MOZ_LOG(sISMLog, LogLevel::Error,
|
MOZ_LOG(sISMLog, LogLevel::Error,
|
||||||
(" NotifyIME(), FAILED, received blur "
|
(" NotifyIME(), WARNING, received blur notification but there is "
|
||||||
"notification from this process but the remote has focus"));
|
"no focused IME widget"));
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
if (!sFocusedIMEWidget && aOriginIsRemote) {
|
|
||||||
MOZ_LOG(sISMLog, LogLevel::Info,
|
|
||||||
(" NotifyIME(), received blur notification "
|
|
||||||
"but the remote has already lost focus"));
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
if (NS_WARN_IF(!sFocusedIMEWidget)) {
|
|
||||||
MOZ_LOG(sISMLog, LogLevel::Error,
|
|
||||||
(" NotifyIME(), FAILED, received blur "
|
|
||||||
"notification but there is no focused IME widget"));
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
if (NS_WARN_IF(sFocusedIMEWidget != aWidget)) {
|
if (NS_WARN_IF(sFocusedIMEWidget != aWidget)) {
|
||||||
MOZ_LOG(sISMLog, LogLevel::Error,
|
MOZ_LOG(sISMLog, LogLevel::Warning,
|
||||||
(" NotifyIME(), FAILED, received blur "
|
(" NotifyIME(), WARNING, the received blur notification is ignored "
|
||||||
"notification but there is no focused IME widget"));
|
"because it's not for current focused IME widget"));
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
nsCOMPtr<nsIWidget> focusedIMEWidget(sFocusedIMEWidget);
|
nsCOMPtr<nsIWidget> focusedIMEWidget(sFocusedIMEWidget);
|
||||||
sFocusedIMEWidget = nullptr;
|
sFocusedIMEWidget = nullptr;
|
||||||
sRemoteHasFocus = false;
|
sFocusedIMETabParent = nullptr;
|
||||||
return focusedIMEWidget->NotifyIME(IMENotification(NOTIFY_IME_OF_BLUR));
|
return focusedIMEWidget->NotifyIME(IMENotification(NOTIFY_IME_OF_BLUR));
|
||||||
}
|
}
|
||||||
case NOTIFY_IME_OF_SELECTION_CHANGE:
|
case NOTIFY_IME_OF_SELECTION_CHANGE:
|
||||||
|
@ -1533,30 +1543,22 @@ IMEStateManager::NotifyIME(const IMENotification& aNotification,
|
||||||
case NOTIFY_IME_OF_POSITION_CHANGE:
|
case NOTIFY_IME_OF_POSITION_CHANGE:
|
||||||
case NOTIFY_IME_OF_MOUSE_BUTTON_EVENT:
|
case NOTIFY_IME_OF_MOUSE_BUTTON_EVENT:
|
||||||
case NOTIFY_IME_OF_COMPOSITION_EVENT_HANDLED: {
|
case NOTIFY_IME_OF_COMPOSITION_EVENT_HANDLED: {
|
||||||
if (!sRemoteHasFocus && aOriginIsRemote) {
|
if (!IsSameProcess(aTabParent, sFocusedIMETabParent)) {
|
||||||
MOZ_LOG(sISMLog, LogLevel::Info,
|
MOZ_LOG(sISMLog, LogLevel::Warning,
|
||||||
(" NotifyIME(), received content change "
|
(" NotifyIME(), WARNING, the received content change notification "
|
||||||
"notification from the remote but it's already lost focus"));
|
"is ignored because it's not from current focused IME process"));
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
if (NS_WARN_IF(sRemoteHasFocus && !aOriginIsRemote)) {
|
|
||||||
MOZ_LOG(sISMLog, LogLevel::Error,
|
|
||||||
(" NotifyIME(), FAILED, received content "
|
|
||||||
"change notification from this process but the remote has already "
|
|
||||||
"gotten focus"));
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
if (!sFocusedIMEWidget) {
|
if (!sFocusedIMEWidget) {
|
||||||
MOZ_LOG(sISMLog, LogLevel::Info,
|
MOZ_LOG(sISMLog, LogLevel::Warning,
|
||||||
(" NotifyIME(), received content change "
|
(" NotifyIME(), WARNING, the received content change notification "
|
||||||
"notification but there is no focused IME widget"));
|
"is ignored because there is no focused IME widget"));
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
if (NS_WARN_IF(sFocusedIMEWidget != aWidget)) {
|
if (NS_WARN_IF(sFocusedIMEWidget != aWidget)) {
|
||||||
MOZ_LOG(sISMLog, LogLevel::Error,
|
MOZ_LOG(sISMLog, LogLevel::Warning,
|
||||||
(" NotifyIME(), FAILED, received content "
|
(" NotifyIME(), WARNING, the received content change notification "
|
||||||
"change notification for IME which has already lost focus, so, "
|
"is ignored because it's not for current focused IME widget"));
|
||||||
"nothing to do..."));
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
nsCOMPtr<nsIWidget> widget(aWidget);
|
nsCOMPtr<nsIWidget> widget(aWidget);
|
||||||
|
@ -1568,26 +1570,35 @@ IMEStateManager::NotifyIME(const IMENotification& aNotification,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<TextComposition> composition;
|
if (!sTextCompositions) {
|
||||||
if (sTextCompositions) {
|
MOZ_LOG(sISMLog, LogLevel::Info,
|
||||||
composition = sTextCompositions->GetCompositionFor(aWidget);
|
(" NotifyIME(), the request to IME is ignored because "
|
||||||
|
"there have been no compositions yet"));
|
||||||
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isSynthesizedForTests =
|
RefPtr<TextComposition> composition =
|
||||||
composition && composition->IsSynthesizedForTests();
|
sTextCompositions->GetCompositionFor(aWidget);
|
||||||
|
if (!composition) {
|
||||||
|
MOZ_LOG(sISMLog, LogLevel::Info,
|
||||||
|
(" NotifyIME(), the request to IME is ignored because "
|
||||||
|
"there is no active composition"));
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
MOZ_LOG(sISMLog, LogLevel::Info,
|
if (!IsSameProcess(aTabParent, composition->GetTabParent())) {
|
||||||
(" NotifyIME(), composition=0x%p, "
|
MOZ_LOG(sISMLog, LogLevel::Warning,
|
||||||
"composition->IsSynthesizedForTests()=%s",
|
(" NotifyIME(), WARNING, the request to IME is ignored because "
|
||||||
composition.get(), GetBoolName(isSynthesizedForTests)));
|
"it does not come from the remote process which has the composition "
|
||||||
|
"on aWidget"));
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
switch (aNotification.mMessage) {
|
switch (aNotification.mMessage) {
|
||||||
case REQUEST_TO_COMMIT_COMPOSITION:
|
case REQUEST_TO_COMMIT_COMPOSITION:
|
||||||
return composition ?
|
return composition->RequestToCommit(aWidget, false);
|
||||||
composition->RequestToCommit(aWidget, false) : NS_OK;
|
|
||||||
case REQUEST_TO_CANCEL_COMPOSITION:
|
case REQUEST_TO_CANCEL_COMPOSITION:
|
||||||
return composition ?
|
return composition->RequestToCommit(aWidget, true);
|
||||||
composition->RequestToCommit(aWidget, true) : NS_OK;
|
|
||||||
default:
|
default:
|
||||||
MOZ_CRASH("Unsupported notification");
|
MOZ_CRASH("Unsupported notification");
|
||||||
}
|
}
|
||||||
|
@ -1600,11 +1611,11 @@ IMEStateManager::NotifyIME(const IMENotification& aNotification,
|
||||||
nsresult
|
nsresult
|
||||||
IMEStateManager::NotifyIME(IMEMessage aMessage,
|
IMEStateManager::NotifyIME(IMEMessage aMessage,
|
||||||
nsPresContext* aPresContext,
|
nsPresContext* aPresContext,
|
||||||
bool aOriginIsRemote)
|
TabParent* aTabParent)
|
||||||
{
|
{
|
||||||
MOZ_LOG(sISMLog, LogLevel::Info,
|
MOZ_LOG(sISMLog, LogLevel::Info,
|
||||||
("NotifyIME(aMessage=%s, aPresContext=0x%p, aOriginIsRemote=%s)",
|
("NotifyIME(aMessage=%s, aPresContext=0x%p, aTabParent=0x%p)",
|
||||||
ToChar(aMessage), aPresContext, GetBoolName(aOriginIsRemote)));
|
ToChar(aMessage), aPresContext, aTabParent));
|
||||||
|
|
||||||
if (NS_WARN_IF(!CanHandleWith(aPresContext))) {
|
if (NS_WARN_IF(!CanHandleWith(aPresContext))) {
|
||||||
return NS_ERROR_INVALID_ARG;
|
return NS_ERROR_INVALID_ARG;
|
||||||
|
@ -1617,7 +1628,7 @@ IMEStateManager::NotifyIME(IMEMessage aMessage,
|
||||||
"nsPresContext"));
|
"nsPresContext"));
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
}
|
}
|
||||||
return NotifyIME(aMessage, widget, aOriginIsRemote);
|
return NotifyIME(aMessage, widget, aTabParent);
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
|
|
|
@ -224,13 +224,13 @@ public:
|
||||||
*/
|
*/
|
||||||
static nsresult NotifyIME(const IMENotification& aNotification,
|
static nsresult NotifyIME(const IMENotification& aNotification,
|
||||||
nsIWidget* aWidget,
|
nsIWidget* aWidget,
|
||||||
bool aOriginIsRemote = false);
|
TabParent* aTabParent = nullptr);
|
||||||
static nsresult NotifyIME(IMEMessage aMessage,
|
static nsresult NotifyIME(IMEMessage aMessage,
|
||||||
nsIWidget* aWidget,
|
nsIWidget* aWidget,
|
||||||
bool aOriginIsRemote = false);
|
TabParent* aTabParent = nullptr);
|
||||||
static nsresult NotifyIME(IMEMessage aMessage,
|
static nsresult NotifyIME(IMEMessage aMessage,
|
||||||
nsPresContext* aPresContext,
|
nsPresContext* aPresContext,
|
||||||
bool aOriginIsRemote = false);
|
TabParent* aTabParent = nullptr);
|
||||||
|
|
||||||
static nsINode* GetRootEditableNode(nsPresContext* aPresContext,
|
static nsINode* GetRootEditableNode(nsPresContext* aPresContext,
|
||||||
nsIContent* aContent);
|
nsIContent* aContent);
|
||||||
|
@ -280,11 +280,10 @@ protected:
|
||||||
// sPresContext has gone, we need to clean up some IME state on the widget
|
// sPresContext has gone, we need to clean up some IME state on the widget
|
||||||
// if the widget is available.
|
// if the widget is available.
|
||||||
static nsIWidget* sWidget;
|
static nsIWidget* sWidget;
|
||||||
// sFocusedIMEWidget is, the widget which was sent to "focus" notification
|
// sFocusedIMETabParent is the tab parent, which send "focus" notification to
|
||||||
// from IMEContentObserver and not yet sent "blur" notification.
|
// sFocusedIMEWidget (and didn't yet sent "blur" notification).
|
||||||
// So, if this is not nullptr, the widget needs to receive "blur"
|
|
||||||
// notification.
|
|
||||||
static nsIWidget* sFocusedIMEWidget;
|
static nsIWidget* sFocusedIMEWidget;
|
||||||
|
static StaticRefPtr<TabParent> sFocusedIMETabParent;
|
||||||
// sActiveInputContextWidget is the last widget whose SetInputContext() is
|
// sActiveInputContextWidget is the last widget whose SetInputContext() is
|
||||||
// called. This is important to reduce sync IPC cost with parent process.
|
// called. This is important to reduce sync IPC cost with parent process.
|
||||||
// If IMEStateManager set input context to different widget, PuppetWidget can
|
// If IMEStateManager set input context to different widget, PuppetWidget can
|
||||||
|
@ -308,7 +307,6 @@ protected:
|
||||||
static bool sIsGettingNewIMEState;
|
static bool sIsGettingNewIMEState;
|
||||||
static bool sCheckForIMEUnawareWebApps;
|
static bool sCheckForIMEUnawareWebApps;
|
||||||
static bool sInputModeSupported;
|
static bool sInputModeSupported;
|
||||||
static bool sRemoteHasFocus;
|
|
||||||
|
|
||||||
class MOZ_STACK_CLASS GettingNewIMEStateBlocker final
|
class MOZ_STACK_CLASS GettingNewIMEStateBlocker final
|
||||||
{
|
{
|
||||||
|
|
|
@ -616,7 +616,7 @@ nsresult
|
||||||
TextComposition::NotifyIME(IMEMessage aMessage)
|
TextComposition::NotifyIME(IMEMessage aMessage)
|
||||||
{
|
{
|
||||||
NS_ENSURE_TRUE(mPresContext, NS_ERROR_NOT_AVAILABLE);
|
NS_ENSURE_TRUE(mPresContext, NS_ERROR_NOT_AVAILABLE);
|
||||||
return IMEStateManager::NotifyIME(aMessage, mPresContext);
|
return IMEStateManager::NotifyIME(aMessage, mPresContext, mTabParent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -75,6 +75,11 @@ public:
|
||||||
{
|
{
|
||||||
return mPresContext ? mPresContext->GetRootWidget() : nullptr;
|
return mPresContext ? mPresContext->GetRootWidget() : nullptr;
|
||||||
}
|
}
|
||||||
|
// Returns the tab parent which has this composition in its remote process.
|
||||||
|
TabParent* GetTabParent() const
|
||||||
|
{
|
||||||
|
return mTabParent;
|
||||||
|
}
|
||||||
// Returns true if the composition is started with synthesized event which
|
// Returns true if the composition is started with synthesized event which
|
||||||
// came from nsDOMWindowUtils.
|
// came from nsDOMWindowUtils.
|
||||||
bool IsSynthesizedForTests() const { return mIsSynthesizedForTests; }
|
bool IsSynthesizedForTests() const { return mIsSynthesizedForTests; }
|
||||||
|
|
|
@ -143,6 +143,7 @@ TabParent::TabParent(nsIContentParent* aManager,
|
||||||
uint32_t aChromeFlags)
|
uint32_t aChromeFlags)
|
||||||
: TabContext(aContext)
|
: TabContext(aContext)
|
||||||
, mFrameElement(nullptr)
|
, mFrameElement(nullptr)
|
||||||
|
, mContentCache(*this)
|
||||||
, mRect(0, 0, 0, 0)
|
, mRect(0, 0, 0, 0)
|
||||||
, mDimensions(0, 0)
|
, mDimensions(0, 0)
|
||||||
, mOrientation(0)
|
, mOrientation(0)
|
||||||
|
@ -1745,7 +1746,7 @@ TabParent::RecvNotifyIMEFocus(const ContentCache& aContentCache,
|
||||||
}
|
}
|
||||||
|
|
||||||
mContentCache.AssignContent(aContentCache, widget, &aIMENotification);
|
mContentCache.AssignContent(aContentCache, widget, &aIMENotification);
|
||||||
IMEStateManager::NotifyIME(aIMENotification, widget, true);
|
IMEStateManager::NotifyIME(aIMENotification, widget, this);
|
||||||
|
|
||||||
if (aIMENotification.mMessage == NOTIFY_IME_OF_FOCUS) {
|
if (aIMENotification.mMessage == NOTIFY_IME_OF_FOCUS) {
|
||||||
*aRequests = widget->IMENotificationRequestsRef();
|
*aRequests = widget->IMENotificationRequestsRef();
|
||||||
|
@ -1824,7 +1825,7 @@ TabParent::RecvNotifyIMEMouseButtonEvent(
|
||||||
*aConsumedByIME = false;
|
*aConsumedByIME = false;
|
||||||
return IPC_OK();
|
return IPC_OK();
|
||||||
}
|
}
|
||||||
nsresult rv = IMEStateManager::NotifyIME(aIMENotification, widget, true);
|
nsresult rv = IMEStateManager::NotifyIME(aIMENotification, widget, this);
|
||||||
*aConsumedByIME = rv == NS_SUCCESS_EVENT_CONSUMED;
|
*aConsumedByIME = rv == NS_SUCCESS_EVENT_CONSUMED;
|
||||||
return IPC_OK();
|
return IPC_OK();
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ class GPUChild;
|
||||||
// GPUProcessHosts are allocated and managed by GPUProcessManager. For all
|
// GPUProcessHosts are allocated and managed by GPUProcessManager. For all
|
||||||
// intents and purposes it is a singleton, though more than one may be allocated
|
// intents and purposes it is a singleton, though more than one may be allocated
|
||||||
// at a time due to its shutdown being asynchronous.
|
// at a time due to its shutdown being asynchronous.
|
||||||
class GPUProcessHost final : public ipc::GeckoChildProcessHost
|
class GPUProcessHost final : public mozilla::ipc::GeckoChildProcessHost
|
||||||
{
|
{
|
||||||
friend class GPUChild;
|
friend class GPUChild;
|
||||||
|
|
||||||
|
@ -121,7 +121,7 @@ private:
|
||||||
DISALLOW_COPY_AND_ASSIGN(GPUProcessHost);
|
DISALLOW_COPY_AND_ASSIGN(GPUProcessHost);
|
||||||
|
|
||||||
Listener* mListener;
|
Listener* mListener;
|
||||||
ipc::TaskFactory<GPUProcessHost> mTaskFactory;
|
mozilla::ipc::TaskFactory<GPUProcessHost> mTaskFactory;
|
||||||
|
|
||||||
enum class LaunchPhase {
|
enum class LaunchPhase {
|
||||||
Unlaunched,
|
Unlaunched,
|
||||||
|
|
|
@ -99,10 +99,10 @@ public:
|
||||||
|
|
||||||
bool CreateContentBridges(
|
bool CreateContentBridges(
|
||||||
base::ProcessId aOtherProcess,
|
base::ProcessId aOtherProcess,
|
||||||
ipc::Endpoint<PCompositorManagerChild>* aOutCompositor,
|
mozilla::ipc::Endpoint<PCompositorManagerChild>* aOutCompositor,
|
||||||
ipc::Endpoint<PImageBridgeChild>* aOutImageBridge,
|
mozilla::ipc::Endpoint<PImageBridgeChild>* aOutImageBridge,
|
||||||
ipc::Endpoint<PVRManagerChild>* aOutVRBridge,
|
mozilla::ipc::Endpoint<PVRManagerChild>* aOutVRBridge,
|
||||||
ipc::Endpoint<dom::PVideoDecoderManagerChild>* aOutVideoManager,
|
mozilla::ipc::Endpoint<dom::PVideoDecoderManagerChild>* aOutVideoManager,
|
||||||
nsTArray<uint32_t>* aNamespaces);
|
nsTArray<uint32_t>* aNamespaces);
|
||||||
|
|
||||||
// This returns a reference to the APZCTreeManager to which
|
// This returns a reference to the APZCTreeManager to which
|
||||||
|
@ -185,13 +185,13 @@ private:
|
||||||
void OnXPCOMShutdown();
|
void OnXPCOMShutdown();
|
||||||
|
|
||||||
bool CreateContentCompositorManager(base::ProcessId aOtherProcess,
|
bool CreateContentCompositorManager(base::ProcessId aOtherProcess,
|
||||||
ipc::Endpoint<PCompositorManagerChild>* aOutEndpoint);
|
mozilla::ipc::Endpoint<PCompositorManagerChild>* aOutEndpoint);
|
||||||
bool CreateContentImageBridge(base::ProcessId aOtherProcess,
|
bool CreateContentImageBridge(base::ProcessId aOtherProcess,
|
||||||
ipc::Endpoint<PImageBridgeChild>* aOutEndpoint);
|
mozilla::ipc::Endpoint<PImageBridgeChild>* aOutEndpoint);
|
||||||
bool CreateContentVRManager(base::ProcessId aOtherProcess,
|
bool CreateContentVRManager(base::ProcessId aOtherProcess,
|
||||||
ipc::Endpoint<PVRManagerChild>* aOutEndpoint);
|
mozilla::ipc::Endpoint<PVRManagerChild>* aOutEndpoint);
|
||||||
void CreateContentVideoDecoderManager(base::ProcessId aOtherProcess,
|
void CreateContentVideoDecoderManager(base::ProcessId aOtherProcess,
|
||||||
ipc::Endpoint<dom::PVideoDecoderManagerChild>* aOutEndPoint);
|
mozilla::ipc::Endpoint<dom::PVideoDecoderManagerChild>* aOutEndPoint);
|
||||||
|
|
||||||
// Called from RemoteCompositorSession. We track remote sessions so we can
|
// Called from RemoteCompositorSession. We track remote sessions so we can
|
||||||
// notify their owning widgets that the session must be restarted.
|
// notify their owning widgets that the session must be restarted.
|
||||||
|
@ -258,7 +258,7 @@ private:
|
||||||
bool mDecodeVideoOnGpuProcess = true;
|
bool mDecodeVideoOnGpuProcess = true;
|
||||||
|
|
||||||
RefPtr<Observer> mObserver;
|
RefPtr<Observer> mObserver;
|
||||||
ipc::TaskFactory<GPUProcessManager> mTaskFactory;
|
mozilla::ipc::TaskFactory<GPUProcessManager> mTaskFactory;
|
||||||
RefPtr<VsyncIOThreadHolder> mVsyncIOThread;
|
RefPtr<VsyncIOThreadHolder> mVsyncIOThread;
|
||||||
uint32_t mNextNamespace;
|
uint32_t mNextNamespace;
|
||||||
uint32_t mIdNamespace;
|
uint32_t mIdNamespace;
|
||||||
|
|
|
@ -6,18 +6,21 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "mozilla/ContentCache.h"
|
#include "mozilla/ContentCache.h"
|
||||||
|
|
||||||
#include "mozilla/IMEStateManager.h"
|
#include "mozilla/IMEStateManager.h"
|
||||||
|
#include "mozilla/IntegerPrintfMacros.h"
|
||||||
#include "mozilla/Logging.h"
|
#include "mozilla/Logging.h"
|
||||||
|
#include "mozilla/Move.h"
|
||||||
|
#include "mozilla/RefPtr.h"
|
||||||
|
#include "mozilla/SizePrintfMacros.h"
|
||||||
#include "mozilla/TextComposition.h"
|
#include "mozilla/TextComposition.h"
|
||||||
#include "mozilla/TextEvents.h"
|
#include "mozilla/TextEvents.h"
|
||||||
|
#include "mozilla/dom/TabParent.h"
|
||||||
#include "nsIWidget.h"
|
#include "nsIWidget.h"
|
||||||
#include "mozilla/RefPtr.h"
|
|
||||||
#include "mozilla/Move.h"
|
|
||||||
#include "mozilla/IntegerPrintfMacros.h"
|
|
||||||
#include "mozilla/SizePrintfMacros.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
|
using namespace dom;
|
||||||
using namespace widget;
|
using namespace widget;
|
||||||
|
|
||||||
static const char*
|
static const char*
|
||||||
|
@ -511,8 +514,9 @@ ContentCacheInChild::SetSelection(nsIWidget* aWidget,
|
||||||
* mozilla::ContentCacheInParent
|
* mozilla::ContentCacheInParent
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
ContentCacheInParent::ContentCacheInParent()
|
ContentCacheInParent::ContentCacheInParent(TabParent& aTabParent)
|
||||||
: ContentCache()
|
: ContentCache()
|
||||||
|
, mTabParent(aTabParent)
|
||||||
, mCommitStringByRequest(nullptr)
|
, mCommitStringByRequest(nullptr)
|
||||||
, mPendingEventsNeedingAck(0)
|
, mPendingEventsNeedingAck(0)
|
||||||
, mCompositionStartInChild(UINT32_MAX)
|
, mCompositionStartInChild(UINT32_MAX)
|
||||||
|
@ -1234,6 +1238,10 @@ ContentCacheInParent::RequestIMEToCommitComposition(nsIWidget* aWidget,
|
||||||
|
|
||||||
mCommitStringByRequest = &aCommittedString;
|
mCommitStringByRequest = &aCommittedString;
|
||||||
|
|
||||||
|
// TODO: This request may be too late. For example, while the remote process
|
||||||
|
// was busy, focus may be already changed to the main process and the
|
||||||
|
// composition has already been canceled by IMEStateManager. So, this
|
||||||
|
// should check if IME focus is in the TabParent.
|
||||||
aWidget->NotifyIME(IMENotification(aCancel ? REQUEST_TO_CANCEL_COMPOSITION :
|
aWidget->NotifyIME(IMENotification(aCancel ? REQUEST_TO_CANCEL_COMPOSITION :
|
||||||
REQUEST_TO_COMMIT_COMPOSITION));
|
REQUEST_TO_COMMIT_COMPOSITION));
|
||||||
|
|
||||||
|
@ -1274,7 +1282,7 @@ ContentCacheInParent::MaybeNotifyIME(nsIWidget* aWidget,
|
||||||
const IMENotification& aNotification)
|
const IMENotification& aNotification)
|
||||||
{
|
{
|
||||||
if (!mPendingEventsNeedingAck) {
|
if (!mPendingEventsNeedingAck) {
|
||||||
IMEStateManager::NotifyIME(aNotification, aWidget, true);
|
IMEStateManager::NotifyIME(aNotification, aWidget, &mTabParent);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1315,7 +1323,7 @@ ContentCacheInParent::FlushPendingNotifications(nsIWidget* aWidget)
|
||||||
IMENotification notification(mPendingTextChange);
|
IMENotification notification(mPendingTextChange);
|
||||||
if (!aWidget->Destroyed()) {
|
if (!aWidget->Destroyed()) {
|
||||||
mPendingTextChange.Clear();
|
mPendingTextChange.Clear();
|
||||||
IMEStateManager::NotifyIME(notification, aWidget, true);
|
IMEStateManager::NotifyIME(notification, aWidget, &mTabParent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1323,7 +1331,7 @@ ContentCacheInParent::FlushPendingNotifications(nsIWidget* aWidget)
|
||||||
IMENotification notification(mPendingSelectionChange);
|
IMENotification notification(mPendingSelectionChange);
|
||||||
if (!aWidget->Destroyed()) {
|
if (!aWidget->Destroyed()) {
|
||||||
mPendingSelectionChange.Clear();
|
mPendingSelectionChange.Clear();
|
||||||
IMEStateManager::NotifyIME(notification, aWidget, true);
|
IMEStateManager::NotifyIME(notification, aWidget, &mTabParent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1333,7 +1341,7 @@ ContentCacheInParent::FlushPendingNotifications(nsIWidget* aWidget)
|
||||||
IMENotification notification(mPendingLayoutChange);
|
IMENotification notification(mPendingLayoutChange);
|
||||||
if (!aWidget->Destroyed()) {
|
if (!aWidget->Destroyed()) {
|
||||||
mPendingLayoutChange.Clear();
|
mPendingLayoutChange.Clear();
|
||||||
IMEStateManager::NotifyIME(notification, aWidget, true);
|
IMEStateManager::NotifyIME(notification, aWidget, &mTabParent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1343,7 +1351,7 @@ ContentCacheInParent::FlushPendingNotifications(nsIWidget* aWidget)
|
||||||
IMENotification notification(mPendingCompositionUpdate);
|
IMENotification notification(mPendingCompositionUpdate);
|
||||||
if (!aWidget->Destroyed()) {
|
if (!aWidget->Destroyed()) {
|
||||||
mPendingCompositionUpdate.Clear();
|
mPendingCompositionUpdate.Clear();
|
||||||
IMEStateManager::NotifyIME(notification, aWidget, true);
|
IMEStateManager::NotifyIME(notification, aWidget, &mTabParent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,10 @@ namespace mozilla {
|
||||||
|
|
||||||
class ContentCacheInParent;
|
class ContentCacheInParent;
|
||||||
|
|
||||||
|
namespace dom {
|
||||||
|
class TabParent;
|
||||||
|
} // namespace dom
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ContentCache stores various information of the child content.
|
* ContentCache stores various information of the child content.
|
||||||
* This class has members which are necessary both in parent process and
|
* This class has members which are necessary both in parent process and
|
||||||
|
@ -318,7 +322,7 @@ private:
|
||||||
class ContentCacheInParent final : public ContentCache
|
class ContentCacheInParent final : public ContentCache
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ContentCacheInParent();
|
explicit ContentCacheInParent(dom::TabParent& aTabParent);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AssignContent() is called when TabParent receives ContentCache from
|
* AssignContent() is called when TabParent receives ContentCache from
|
||||||
|
@ -406,6 +410,8 @@ private:
|
||||||
IMENotification mPendingLayoutChange;
|
IMENotification mPendingLayoutChange;
|
||||||
IMENotification mPendingCompositionUpdate;
|
IMENotification mPendingCompositionUpdate;
|
||||||
|
|
||||||
|
// mTabParent is owner of the instance.
|
||||||
|
dom::TabParent& MOZ_NON_OWNING_REF mTabParent;
|
||||||
// This is not nullptr only while the instance is requesting IME to
|
// This is not nullptr only while the instance is requesting IME to
|
||||||
// composition. Then, data value of dispatched composition events should
|
// composition. Then, data value of dispatched composition events should
|
||||||
// be stored into the instance.
|
// be stored into the instance.
|
||||||
|
@ -432,6 +438,8 @@ private:
|
||||||
// dispatched and set to false when eCompositionCommit(AsIs) is dispatched.
|
// dispatched and set to false when eCompositionCommit(AsIs) is dispatched.
|
||||||
bool mWidgetHasComposition;
|
bool mWidgetHasComposition;
|
||||||
|
|
||||||
|
ContentCacheInParent() = delete;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When following methods' aRoundToExistingOffset is true, even if specified
|
* When following methods' aRoundToExistingOffset is true, even if specified
|
||||||
* offset or range is out of bounds, the result is computed with the existing
|
* offset or range is out of bounds, the result is computed with the existing
|
||||||
|
|
|
@ -398,8 +398,9 @@ IMEHandler::OnDestroyWindow(nsWindow* aWindow)
|
||||||
// here because TabParent already lost the reference to the nsWindow when
|
// here because TabParent already lost the reference to the nsWindow when
|
||||||
// it receives from the remote process.
|
// it receives from the remote process.
|
||||||
if (sFocusedWindow == aWindow) {
|
if (sFocusedWindow == aWindow) {
|
||||||
NS_ASSERTION(aWindow->GetInputContext().IsOriginContentProcess(),
|
MOZ_ASSERT(aWindow->GetInputContext().IsOriginContentProcess(),
|
||||||
"input context of focused widget should be set from a remote process");
|
"input context of focused widget should've been set by a remote process "
|
||||||
|
"if IME focus isn't cleared before destroying the widget");
|
||||||
NotifyIME(aWindow, IMENotification(NOTIFY_IME_OF_BLUR));
|
NotifyIME(aWindow, IMENotification(NOTIFY_IME_OF_BLUR));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче