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:
Masayuki Nakano 2017-07-06 00:47:40 +09:00
Родитель c726abb366
Коммит d6e921676c
10 изменённых файлов: 154 добавлений и 122 удалений

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

@ -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<nsPresContext> IMEStateManager::sPresContext;
nsIWidget* IMEStateManager::sWidget = nullptr;
nsIWidget* IMEStateManager::sFocusedIMEWidget = nullptr;
StaticRefPtr<TabParent> IMEStateManager::sFocusedIMETabParent;
nsIWidget* IMEStateManager::sActiveInputContextWidget = nullptr;
StaticRefPtr<TabParent> IMEStateManager::sActiveTabParent;
StaticRefPtr<IMEContentObserver> IMEStateManager::sActiveIMEContentObserver;
@ -149,7 +162,6 @@ bool IMEStateManager::sInstalledMenuKeyboardListener = false;
bool IMEStateManager::sIsGettingNewIMEState = false;
bool IMEStateManager::sCheckForIMEUnawareWebApps = false;
bool IMEStateManager::sInputModeSupported = false;
bool IMEStateManager::sRemoteHasFocus = false;
// static
void
@ -226,7 +238,7 @@ IMEStateManager::StopIMEStateManagement()
// the rights to change input context.
if (sTextCompositions && sPresContext) {
NotifyIME(REQUEST_TO_COMMIT_COMPOSITION, sPresContext);
NotifyIME(REQUEST_TO_COMMIT_COMPOSITION, sPresContext, sActiveTabParent);
}
sActiveInputContextWidget = nullptr;
sPresContext = nullptr;
@ -444,7 +456,7 @@ IMEStateManager::OnChangeFocusInternal(nsPresContext* aPresContext,
// If we're deactivating, we shouldn't commit composition forcibly because
// the user may want to continue the composition.
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;
}
nsIContentParent* currentContentParent =
sActiveTabParent ? sActiveTabParent->Manager() : nullptr;
nsIContentParent* newContentParent =
newTabParent ? newTabParent->Manager() : nullptr;
if (sActiveTabParent && currentContentParent != newContentParent) {
if (sActiveTabParent && !IsSameProcess(sActiveTabParent, newTabParent)) {
MOZ_LOG(sISMLog, LogLevel::Debug,
(" OnChangeFocusInternal(), notifying previous "
"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
// composition here since the IME state is changing.
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) {
// If aContent isn't null or aContent is null but editable, somebody gets
@ -923,7 +932,7 @@ IMEStateManager::UpdateIMEState(const IMEState& aNewIMEState,
if (updateIMEState) {
// 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())) {
MOZ_LOG(sISMLog, LogLevel::Error,
(" UpdateIMEState(), widget has gone during committing composition"));
@ -1443,25 +1452,29 @@ IMEStateManager::OnCompositionEventDiscarded(
nsresult
IMEStateManager::NotifyIME(IMEMessage aMessage,
nsIWidget* aWidget,
bool aOriginIsRemote)
TabParent* aTabParent)
{
return IMEStateManager::NotifyIME(IMENotification(aMessage), aWidget,
aOriginIsRemote);
aTabParent);
}
// static
nsresult
IMEStateManager::NotifyIME(const IMENotification& aNotification,
nsIWidget* aWidget,
bool aOriginIsRemote)
TabParent* aTabParent)
{
MOZ_LOG(sISMLog, LogLevel::Info,
("NotifyIME(aNotification={ mMessage=%s }, "
"aWidget=0x%p, aOriginIsRemote=%s), sFocusedIMEWidget=0x%p, "
"sRemoteHasFocus=%s",
"aWidget=0x%p, aTabParent=0x%p), sFocusedIMEWidget=0x%p, "
"sActiveTabParent=0x%p, sFocusedIMETabParent=0x%p, "
"IsSameProcess(aTabParent, sActiveTabParent)=%s, "
"IsSameProcess(aTabParent, sFocusedIMETabParent)=%s",
ToChar(aNotification.mMessage), aWidget,
GetBoolName(aOriginIsRemote), sFocusedIMEWidget,
GetBoolName(sRemoteHasFocus)));
aTabParent, sFocusedIMEWidget, sActiveTabParent.get(),
sFocusedIMETabParent.get(),
GetBoolName(IsSameProcess(aTabParent, sActiveTabParent)),
GetBoolName(IsSameProcess(aTabParent, sFocusedIMETabParent))));
if (NS_WARN_IF(!aWidget)) {
MOZ_LOG(sISMLog, LogLevel::Error,
@ -1471,61 +1484,58 @@ IMEStateManager::NotifyIME(const IMENotification& aNotification,
switch (aNotification.mMessage) {
case NOTIFY_IME_OF_FOCUS: {
if (sFocusedIMEWidget) {
if (NS_WARN_IF(!sRemoteHasFocus && !aOriginIsRemote)) {
MOZ_LOG(sISMLog, LogLevel::Error,
(" 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..."));
// 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) {
MOZ_ASSERT(sFocusedIMETabParent || aTabParent,
"This case shouldn't be caused by focus move in this process");
nsCOMPtr<nsIWidget> focusedIMEWidget(sFocusedIMEWidget);
sFocusedIMEWidget = nullptr;
sRemoteHasFocus = false;
sFocusedIMETabParent = nullptr;
focusedIMEWidget->NotifyIME(IMENotification(NOTIFY_IME_OF_BLUR));
}
sRemoteHasFocus = aOriginIsRemote;
sFocusedIMETabParent = aTabParent;
sFocusedIMEWidget = aWidget;
nsCOMPtr<nsIWidget> widget(aWidget);
return widget->NotifyIME(aNotification);
}
case NOTIFY_IME_OF_BLUR: {
if (!sRemoteHasFocus && aOriginIsRemote) {
MOZ_LOG(sISMLog, LogLevel::Info,
(" NotifyIME(), received blur notification "
"after another one has focus, nothing to do..."));
if (!IsSameProcess(aTabParent, sFocusedIMETabParent)) {
MOZ_LOG(sISMLog, LogLevel::Warning,
(" NotifyIME(), WARNING, the received blur notification is ignored "
"because it's not from current focused IME process"));
return NS_OK;
}
if (NS_WARN_IF(sRemoteHasFocus && !aOriginIsRemote)) {
if (!sFocusedIMEWidget) {
MOZ_LOG(sISMLog, LogLevel::Error,
(" NotifyIME(), FAILED, received blur "
"notification from this process but the remote has focus"));
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"));
(" NotifyIME(), WARNING, received blur notification but there is "
"no focused IME widget"));
return NS_OK;
}
if (NS_WARN_IF(sFocusedIMEWidget != aWidget)) {
MOZ_LOG(sISMLog, LogLevel::Error,
(" NotifyIME(), FAILED, received blur "
"notification but there is no focused IME widget"));
MOZ_LOG(sISMLog, LogLevel::Warning,
(" NotifyIME(), WARNING, the received blur notification is ignored "
"because it's not for current focused IME widget"));
return NS_OK;
}
nsCOMPtr<nsIWidget> focusedIMEWidget(sFocusedIMEWidget);
sFocusedIMEWidget = nullptr;
sRemoteHasFocus = false;
sFocusedIMETabParent = nullptr;
return focusedIMEWidget->NotifyIME(IMENotification(NOTIFY_IME_OF_BLUR));
}
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_MOUSE_BUTTON_EVENT:
case NOTIFY_IME_OF_COMPOSITION_EVENT_HANDLED: {
if (!sRemoteHasFocus && aOriginIsRemote) {
MOZ_LOG(sISMLog, LogLevel::Info,
(" NotifyIME(), received content change "
"notification from the remote but it's already lost focus"));
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"));
if (!IsSameProcess(aTabParent, sFocusedIMETabParent)) {
MOZ_LOG(sISMLog, LogLevel::Warning,
(" NotifyIME(), WARNING, the received content change notification "
"is ignored because it's not from current focused IME process"));
return NS_OK;
}
if (!sFocusedIMEWidget) {
MOZ_LOG(sISMLog, LogLevel::Info,
(" NotifyIME(), received content change "
"notification but there is no focused IME widget"));
MOZ_LOG(sISMLog, LogLevel::Warning,
(" NotifyIME(), WARNING, the received content change notification "
"is ignored because there is no focused IME widget"));
return NS_OK;
}
if (NS_WARN_IF(sFocusedIMEWidget != aWidget)) {
MOZ_LOG(sISMLog, LogLevel::Error,
(" NotifyIME(), FAILED, received content "
"change notification for IME which has already lost focus, so, "
"nothing to do..."));
MOZ_LOG(sISMLog, LogLevel::Warning,
(" NotifyIME(), WARNING, the received content change notification "
"is ignored because it's not for current focused IME widget"));
return NS_OK;
}
nsCOMPtr<nsIWidget> widget(aWidget);
@ -1568,26 +1570,35 @@ IMEStateManager::NotifyIME(const IMENotification& aNotification,
break;
}
RefPtr<TextComposition> composition;
if (sTextCompositions) {
composition = sTextCompositions->GetCompositionFor(aWidget);
if (!sTextCompositions) {
MOZ_LOG(sISMLog, LogLevel::Info,
(" NotifyIME(), the request to IME is ignored because "
"there have been no compositions yet"));
return NS_OK;
}
bool isSynthesizedForTests =
composition && composition->IsSynthesizedForTests();
RefPtr<TextComposition> composition =
sTextCompositions->GetCompositionFor(aWidget);
if (!composition) {
MOZ_LOG(sISMLog, LogLevel::Info,
(" NotifyIME(), composition=0x%p, "
"composition->IsSynthesizedForTests()=%s",
composition.get(), GetBoolName(isSynthesizedForTests)));
(" NotifyIME(), the request to IME is ignored because "
"there is no active composition"));
return NS_OK;
}
if (!IsSameProcess(aTabParent, composition->GetTabParent())) {
MOZ_LOG(sISMLog, LogLevel::Warning,
(" NotifyIME(), WARNING, the request to IME is ignored because "
"it does not come from the remote process which has the composition "
"on aWidget"));
return NS_OK;
}
switch (aNotification.mMessage) {
case REQUEST_TO_COMMIT_COMPOSITION:
return composition ?
composition->RequestToCommit(aWidget, false) : NS_OK;
return composition->RequestToCommit(aWidget, false);
case REQUEST_TO_CANCEL_COMPOSITION:
return composition ?
composition->RequestToCommit(aWidget, true) : NS_OK;
return composition->RequestToCommit(aWidget, true);
default:
MOZ_CRASH("Unsupported notification");
}
@ -1600,11 +1611,11 @@ IMEStateManager::NotifyIME(const IMENotification& aNotification,
nsresult
IMEStateManager::NotifyIME(IMEMessage aMessage,
nsPresContext* aPresContext,
bool aOriginIsRemote)
TabParent* aTabParent)
{
MOZ_LOG(sISMLog, LogLevel::Info,
("NotifyIME(aMessage=%s, aPresContext=0x%p, aOriginIsRemote=%s)",
ToChar(aMessage), aPresContext, GetBoolName(aOriginIsRemote)));
("NotifyIME(aMessage=%s, aPresContext=0x%p, aTabParent=0x%p)",
ToChar(aMessage), aPresContext, aTabParent));
if (NS_WARN_IF(!CanHandleWith(aPresContext))) {
return NS_ERROR_INVALID_ARG;
@ -1617,7 +1628,7 @@ IMEStateManager::NotifyIME(IMEMessage aMessage,
"nsPresContext"));
return NS_ERROR_NOT_AVAILABLE;
}
return NotifyIME(aMessage, widget, aOriginIsRemote);
return NotifyIME(aMessage, widget, aTabParent);
}
// static

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

@ -224,13 +224,13 @@ public:
*/
static nsresult NotifyIME(const IMENotification& aNotification,
nsIWidget* aWidget,
bool aOriginIsRemote = false);
TabParent* aTabParent = nullptr);
static nsresult NotifyIME(IMEMessage aMessage,
nsIWidget* aWidget,
bool aOriginIsRemote = false);
TabParent* aTabParent = nullptr);
static nsresult NotifyIME(IMEMessage aMessage,
nsPresContext* aPresContext,
bool aOriginIsRemote = false);
TabParent* aTabParent = nullptr);
static nsINode* GetRootEditableNode(nsPresContext* aPresContext,
nsIContent* aContent);
@ -280,11 +280,10 @@ protected:
// sPresContext has gone, we need to clean up some IME state on the widget
// if the widget is available.
static nsIWidget* sWidget;
// sFocusedIMEWidget is, the widget which was sent to "focus" notification
// from IMEContentObserver and not yet sent "blur" notification.
// So, if this is not nullptr, the widget needs to receive "blur"
// notification.
// sFocusedIMETabParent is the tab parent, which send "focus" notification to
// sFocusedIMEWidget (and didn't yet sent "blur" notification).
static nsIWidget* sFocusedIMEWidget;
static StaticRefPtr<TabParent> sFocusedIMETabParent;
// sActiveInputContextWidget is the last widget whose SetInputContext() is
// called. This is important to reduce sync IPC cost with parent process.
// If IMEStateManager set input context to different widget, PuppetWidget can
@ -308,7 +307,6 @@ protected:
static bool sIsGettingNewIMEState;
static bool sCheckForIMEUnawareWebApps;
static bool sInputModeSupported;
static bool sRemoteHasFocus;
class MOZ_STACK_CLASS GettingNewIMEStateBlocker final
{

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

@ -616,7 +616,7 @@ nsresult
TextComposition::NotifyIME(IMEMessage aMessage)
{
NS_ENSURE_TRUE(mPresContext, NS_ERROR_NOT_AVAILABLE);
return IMEStateManager::NotifyIME(aMessage, mPresContext);
return IMEStateManager::NotifyIME(aMessage, mPresContext, mTabParent);
}
void

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

@ -75,6 +75,11 @@ public:
{
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
// came from nsDOMWindowUtils.
bool IsSynthesizedForTests() const { return mIsSynthesizedForTests; }

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

@ -143,6 +143,7 @@ TabParent::TabParent(nsIContentParent* aManager,
uint32_t aChromeFlags)
: TabContext(aContext)
, mFrameElement(nullptr)
, mContentCache(*this)
, mRect(0, 0, 0, 0)
, mDimensions(0, 0)
, mOrientation(0)
@ -1745,7 +1746,7 @@ TabParent::RecvNotifyIMEFocus(const ContentCache& aContentCache,
}
mContentCache.AssignContent(aContentCache, widget, &aIMENotification);
IMEStateManager::NotifyIME(aIMENotification, widget, true);
IMEStateManager::NotifyIME(aIMENotification, widget, this);
if (aIMENotification.mMessage == NOTIFY_IME_OF_FOCUS) {
*aRequests = widget->IMENotificationRequestsRef();
@ -1824,7 +1825,7 @@ TabParent::RecvNotifyIMEMouseButtonEvent(
*aConsumedByIME = false;
return IPC_OK();
}
nsresult rv = IMEStateManager::NotifyIME(aIMENotification, widget, true);
nsresult rv = IMEStateManager::NotifyIME(aIMENotification, widget, this);
*aConsumedByIME = rv == NS_SUCCESS_EVENT_CONSUMED;
return IPC_OK();
}

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

@ -27,7 +27,7 @@ class GPUChild;
// GPUProcessHosts are allocated and managed by GPUProcessManager. For all
// intents and purposes it is a singleton, though more than one may be allocated
// 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;
@ -121,7 +121,7 @@ private:
DISALLOW_COPY_AND_ASSIGN(GPUProcessHost);
Listener* mListener;
ipc::TaskFactory<GPUProcessHost> mTaskFactory;
mozilla::ipc::TaskFactory<GPUProcessHost> mTaskFactory;
enum class LaunchPhase {
Unlaunched,

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

@ -99,10 +99,10 @@ public:
bool CreateContentBridges(
base::ProcessId aOtherProcess,
ipc::Endpoint<PCompositorManagerChild>* aOutCompositor,
ipc::Endpoint<PImageBridgeChild>* aOutImageBridge,
ipc::Endpoint<PVRManagerChild>* aOutVRBridge,
ipc::Endpoint<dom::PVideoDecoderManagerChild>* aOutVideoManager,
mozilla::ipc::Endpoint<PCompositorManagerChild>* aOutCompositor,
mozilla::ipc::Endpoint<PImageBridgeChild>* aOutImageBridge,
mozilla::ipc::Endpoint<PVRManagerChild>* aOutVRBridge,
mozilla::ipc::Endpoint<dom::PVideoDecoderManagerChild>* aOutVideoManager,
nsTArray<uint32_t>* aNamespaces);
// This returns a reference to the APZCTreeManager to which
@ -185,13 +185,13 @@ private:
void OnXPCOMShutdown();
bool CreateContentCompositorManager(base::ProcessId aOtherProcess,
ipc::Endpoint<PCompositorManagerChild>* aOutEndpoint);
mozilla::ipc::Endpoint<PCompositorManagerChild>* aOutEndpoint);
bool CreateContentImageBridge(base::ProcessId aOtherProcess,
ipc::Endpoint<PImageBridgeChild>* aOutEndpoint);
mozilla::ipc::Endpoint<PImageBridgeChild>* aOutEndpoint);
bool CreateContentVRManager(base::ProcessId aOtherProcess,
ipc::Endpoint<PVRManagerChild>* aOutEndpoint);
mozilla::ipc::Endpoint<PVRManagerChild>* aOutEndpoint);
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
// notify their owning widgets that the session must be restarted.
@ -258,7 +258,7 @@ private:
bool mDecodeVideoOnGpuProcess = true;
RefPtr<Observer> mObserver;
ipc::TaskFactory<GPUProcessManager> mTaskFactory;
mozilla::ipc::TaskFactory<GPUProcessManager> mTaskFactory;
RefPtr<VsyncIOThreadHolder> mVsyncIOThread;
uint32_t mNextNamespace;
uint32_t mIdNamespace;

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

@ -6,18 +6,21 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/ContentCache.h"
#include "mozilla/IMEStateManager.h"
#include "mozilla/IntegerPrintfMacros.h"
#include "mozilla/Logging.h"
#include "mozilla/Move.h"
#include "mozilla/RefPtr.h"
#include "mozilla/SizePrintfMacros.h"
#include "mozilla/TextComposition.h"
#include "mozilla/TextEvents.h"
#include "mozilla/dom/TabParent.h"
#include "nsIWidget.h"
#include "mozilla/RefPtr.h"
#include "mozilla/Move.h"
#include "mozilla/IntegerPrintfMacros.h"
#include "mozilla/SizePrintfMacros.h"
namespace mozilla {
using namespace dom;
using namespace widget;
static const char*
@ -511,8 +514,9 @@ ContentCacheInChild::SetSelection(nsIWidget* aWidget,
* mozilla::ContentCacheInParent
*****************************************************************************/
ContentCacheInParent::ContentCacheInParent()
ContentCacheInParent::ContentCacheInParent(TabParent& aTabParent)
: ContentCache()
, mTabParent(aTabParent)
, mCommitStringByRequest(nullptr)
, mPendingEventsNeedingAck(0)
, mCompositionStartInChild(UINT32_MAX)
@ -1234,6 +1238,10 @@ ContentCacheInParent::RequestIMEToCommitComposition(nsIWidget* aWidget,
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 :
REQUEST_TO_COMMIT_COMPOSITION));
@ -1274,7 +1282,7 @@ ContentCacheInParent::MaybeNotifyIME(nsIWidget* aWidget,
const IMENotification& aNotification)
{
if (!mPendingEventsNeedingAck) {
IMEStateManager::NotifyIME(aNotification, aWidget, true);
IMEStateManager::NotifyIME(aNotification, aWidget, &mTabParent);
return;
}
@ -1315,7 +1323,7 @@ ContentCacheInParent::FlushPendingNotifications(nsIWidget* aWidget)
IMENotification notification(mPendingTextChange);
if (!aWidget->Destroyed()) {
mPendingTextChange.Clear();
IMEStateManager::NotifyIME(notification, aWidget, true);
IMEStateManager::NotifyIME(notification, aWidget, &mTabParent);
}
}
@ -1323,7 +1331,7 @@ ContentCacheInParent::FlushPendingNotifications(nsIWidget* aWidget)
IMENotification notification(mPendingSelectionChange);
if (!aWidget->Destroyed()) {
mPendingSelectionChange.Clear();
IMEStateManager::NotifyIME(notification, aWidget, true);
IMEStateManager::NotifyIME(notification, aWidget, &mTabParent);
}
}
@ -1333,7 +1341,7 @@ ContentCacheInParent::FlushPendingNotifications(nsIWidget* aWidget)
IMENotification notification(mPendingLayoutChange);
if (!aWidget->Destroyed()) {
mPendingLayoutChange.Clear();
IMEStateManager::NotifyIME(notification, aWidget, true);
IMEStateManager::NotifyIME(notification, aWidget, &mTabParent);
}
}
@ -1343,7 +1351,7 @@ ContentCacheInParent::FlushPendingNotifications(nsIWidget* aWidget)
IMENotification notification(mPendingCompositionUpdate);
if (!aWidget->Destroyed()) {
mPendingCompositionUpdate.Clear();
IMEStateManager::NotifyIME(notification, aWidget, true);
IMEStateManager::NotifyIME(notification, aWidget, &mTabParent);
}
}

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

@ -23,6 +23,10 @@ namespace mozilla {
class ContentCacheInParent;
namespace dom {
class TabParent;
} // namespace dom
/**
* ContentCache stores various information of the child content.
* This class has members which are necessary both in parent process and
@ -318,7 +322,7 @@ private:
class ContentCacheInParent final : public ContentCache
{
public:
ContentCacheInParent();
explicit ContentCacheInParent(dom::TabParent& aTabParent);
/**
* AssignContent() is called when TabParent receives ContentCache from
@ -406,6 +410,8 @@ private:
IMENotification mPendingLayoutChange;
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
// composition. Then, data value of dispatched composition events should
// be stored into the instance.
@ -432,6 +438,8 @@ private:
// dispatched and set to false when eCompositionCommit(AsIs) is dispatched.
bool mWidgetHasComposition;
ContentCacheInParent() = delete;
/**
* When following methods' aRoundToExistingOffset is true, even if specified
* 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
// it receives from the remote process.
if (sFocusedWindow == aWindow) {
NS_ASSERTION(aWindow->GetInputContext().IsOriginContentProcess(),
"input context of focused widget should be set from a remote process");
MOZ_ASSERT(aWindow->GetInputContext().IsOriginContentProcess(),
"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));
}