--- a/dom/events/IMEStateManager.cpp
+++ b/dom/events/IMEStateManager.cpp
@@ -131,30 +131,42 @@ GetIMEStateSetOpenName(IMEState::Open aO
return "OPEN";
case IMEState::CLOSED:
return "CLOSED";
default:
return "illegal value";
}
}
+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;
TextCompositionArray* IMEStateManager::sTextCompositions = nullptr;
InputContext::Origin IMEStateManager::sOrigin = InputContext::ORIGIN_MAIN;
bool IMEStateManager::sInstalledMenuKeyboardListener = false;
bool IMEStateManager::sIsGettingNewIMEState = false;
bool IMEStateManager::sCheckForIMEUnawareWebApps = false;
bool IMEStateManager::sInputModeSupported = false;
-bool IMEStateManager::sRemoteHasFocus = false;
// static
void
IMEStateManager::Init()
{
Preferences::AddBoolVarCache(
&sCheckForIMEUnawareWebApps,
"intl.ime.hack.on_ime_unaware_apps.fire_key_events_for_composition",
@@ -221,17 +233,17 @@ IMEStateManager::StopIMEStateManagement(
{
MOZ_LOG(sISMLog, LogLevel::Info,
("StopIMEStateManagement()"));
// NOTE: Don't set input context from here since this has already lost
// 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;
sContent = nullptr;
sActiveTabParent = nullptr;
DestroyIMEContentObserver();
}
@@ -439,17 +451,17 @@ IMEStateManager::OnChangeFocusInternal(n
bool focusActuallyChanging =
(sContent != aContent || sPresContext != aPresContext ||
oldWidget != newWidget || sActiveTabParent != newTabParent);
if (oldWidget && focusActuallyChanging) {
// 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);
}
}
if (sActiveIMEContentObserver) {
// If there is active IMEContentObserver, it means that focused content was
// in this process. So, if a tab parent gets focus, it means that the
// focused editor in this process is being blurred.
if (newTabParent) {
@@ -473,21 +485,17 @@ IMEStateManager::OnChangeFocusInternal(n
if (!aPresContext) {
MOZ_LOG(sISMLog, LogLevel::Debug,
(" OnChangeFocusInternal(), "
"no nsPresContext is being activated"));
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 "
"getting focus"));
Unused << sActiveTabParent->SendStopIMEStateManagement();
}
if (NS_WARN_IF(!newWidget)) {
@@ -560,17 +568,18 @@ IMEStateManager::OnChangeFocusInternal(n
"neither focus nor IME state is changing"));
return NS_OK;
}
aAction.mFocusChange = InputContextAction::FOCUS_NOT_CHANGED;
// 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
// focus.
bool gotFocus = aContent || (newState.mEnabled == IMEState::ENABLED);
aAction.mFocusChange =
gotFocus ? InputContextAction::GOT_FOCUS :
InputContextAction::LOST_FOCUS;
@@ -918,17 +927,17 @@ IMEStateManager::UpdateIMEState(const IM
if (NS_WARN_IF(widget->Destroyed())) {
MOZ_LOG(sISMLog, LogLevel::Error,
(" UpdateIMEState(), widget has gone during getting input context"));
return;
}
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"));
return;
}
}
if (createTextStateManager) {
@@ -1438,191 +1447,193 @@ IMEStateManager::OnCompositionEventDisca
}
composition->OnCompositionEventDiscarded(aCompositionEvent);
}
// static
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,
(" NotifyIME(), FAILED due to no widget"));
return NS_ERROR_INVALID_ARG;
}
switch (aNotification.mMessage) {
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 (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..."));
- }
+ 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:
case NOTIFY_IME_OF_TEXT_CHANGE:
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);
return widget->NotifyIME(aNotification);
}
default:
// Other notifications should be sent only when there is composition.
// So, we need to handle the others below.
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(), the request to IME is ignored because "
+ "there is no active composition"));
+ return NS_OK;
+ }
- MOZ_LOG(sISMLog, LogLevel::Info,
- (" NotifyIME(), composition=0x%p, "
- "composition->IsSynthesizedForTests()=%s",
- composition.get(), GetBoolName(isSynthesizedForTests)));
+ 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");
}
MOZ_CRASH(
"Failed to handle the notification for non-synthesized composition");
return NS_ERROR_FAILURE;
}
// static
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;
}
nsIWidget* widget = aPresContext->GetRootWidget();
if (NS_WARN_IF(!widget)) {
MOZ_LOG(sISMLog, LogLevel::Error,
(" NotifyIME(), FAILED due to no widget for the "
"nsPresContext"));
return NS_ERROR_NOT_AVAILABLE;
}
- return NotifyIME(aMessage, widget, aOriginIsRemote);
+ return NotifyIME(aMessage, widget, aTabParent);
}
// static
bool
IMEStateManager::IsEditable(nsINode* node)
{
if (node->IsEditable()) {
return true;
--- a/dom/events/IMEStateManager.h
+++ b/dom/events/IMEStateManager.h
@@ -219,23 +219,23 @@ public:
GetTextCompositionFor(nsPresContext* aPresContext);
/**
* Send a notification to IME. It depends on the IME or platform spec what
* will occur (or not occur).
*/
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);
/**
* Returns active IMEContentObserver but may be nullptr if focused content
* isn't editable or focus in a remote process.
*/
@@ -275,21 +275,20 @@ protected:
// document has focus but there is no focused element, sContent may be
// nullptr.
static StaticRefPtr<nsIContent> sContent;
static StaticRefPtr<nsPresContext> sPresContext;
// sWidget is cache for the root widget of sPresContext. Even afer
// 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
// return cached input context safely.
static nsIWidget* sActiveInputContextWidget;
static StaticRefPtr<TabParent> sActiveTabParent;
// sActiveIMEContentObserver points to the currently active
// IMEContentObserver. This is null if there is no focused editor.
@@ -303,17 +302,16 @@ protected:
// Origin type of current process.
static InputContext::Origin sOrigin;
static bool sInstalledMenuKeyboardListener;
static bool sIsGettingNewIMEState;
static bool sCheckForIMEUnawareWebApps;
static bool sInputModeSupported;
- static bool sRemoteHasFocus;
class MOZ_STACK_CLASS GettingNewIMEStateBlocker final
{
public:
GettingNewIMEStateBlocker()
: mOldValue(IMEStateManager::sIsGettingNewIMEState)
{
IMEStateManager::sIsGettingNewIMEState = true;
--- a/dom/events/TextComposition.cpp
+++ b/dom/events/TextComposition.cpp
@@ -611,17 +611,17 @@ TextComposition::RequestToCommit(nsIWidg
}
return NS_OK;
}
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
TextComposition::EditorWillHandleCompositionChangeEvent(
const WidgetCompositionEvent* aCompositionChangeEvent)
{
mIsComposing = aCompositionChangeEvent->IsComposing();
mRanges = aCompositionChangeEvent->mRanges;
--- a/dom/events/TextComposition.h
+++ b/dom/events/TextComposition.h
@@ -70,16 +70,21 @@ public:
// XXX We should return |const TextRangeArray*| here, but it causes compile
// error due to inaccessible Release() method.
TextRangeArray* GetRanges() const { return mRanges; }
// Returns the widget which is proper to call NotifyIME().
nsIWidget* GetWidget() const
{
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; }
const widget::NativeIMEContext& GetNativeIMEContext() const
{
return mNativeContext;
}
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -138,16 +138,17 @@ NS_IMPL_ISUPPORTS(TabParent,
nsIWebBrowserPersistable)
TabParent::TabParent(nsIContentParent* aManager,
const TabId& aTabId,
const TabContext& aContext,
uint32_t aChromeFlags)
: TabContext(aContext)
, mFrameElement(nullptr)
+ , mContentCache(*this)
, mRect(0, 0, 0, 0)
, mDimensions(0, 0)
, mOrientation(0)
, mDPI(0)
, mRounding(0)
, mDefaultScale(0)
, mUpdatedDimensions(false)
, mSizeMode(nsSizeMode_Normal)
@@ -1740,17 +1741,17 @@ TabParent::RecvNotifyIMEFocus(const Cont
{
nsCOMPtr<nsIWidget> widget = GetWidget();
if (!widget) {
*aRequests = IMENotificationRequests();
return IPC_OK();
}
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();
}
return IPC_OK();
}
mozilla::ipc::IPCResult
@@ -1819,17 +1820,17 @@ TabParent::RecvNotifyIMEMouseButtonEvent
bool* aConsumedByIME)
{
nsCOMPtr<nsIWidget> widget = GetWidget();
if (!widget) {
*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();
}
mozilla::ipc::IPCResult
TabParent::RecvNotifyIMEPositionChange(const ContentCache& aContentCache,
const IMENotification& aIMENotification)
{
--- a/gfx/ipc/GPUProcessHost.h
+++ b/gfx/ipc/GPUProcessHost.h
@@ -22,17 +22,17 @@ class GPUChild;
// GPUProcessHost is the "parent process" container for a subprocess handle and
// IPC connection. It owns the parent process IPDL actor, which in this case,
// is a 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;
public:
class Listener {
public:
virtual void OnProcessLaunchComplete(GPUProcessHost* aHost)
{}
@@ -116,17 +116,17 @@ private:
void KillHard(const char* aReason);
void DestroyProcess();
private:
DISALLOW_COPY_AND_ASSIGN(GPUProcessHost);
Listener* mListener;
- ipc::TaskFactory<GPUProcessHost> mTaskFactory;
+ mozilla::ipc::TaskFactory<GPUProcessHost> mTaskFactory;
enum class LaunchPhase {
Unlaunched,
Waiting,
Complete
};
LaunchPhase mLaunchPhase;
--- a/gfx/ipc/GPUProcessManager.h
+++ b/gfx/ipc/GPUProcessManager.h
@@ -94,20 +94,20 @@ public:
LayerManager* aLayerManager,
CSSToLayoutDeviceScale aScale,
const CompositorOptions& aOptions,
bool aUseExternalSurfaceSize,
const gfx::IntSize& aSurfaceSize);
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
// pan/zoom-related events can be sent.
already_AddRefed<IAPZCTreeManager> GetAPZCTreeManagerForLayers(uint64_t aLayersId);
// Maps the layer tree and process together so that aOwningPID is allowed
// to access aLayersId across process.
@@ -180,23 +180,23 @@ public:
return mNumProcessAttempts > 0;
}
private:
// Called from our xpcom-shutdown observer.
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.
void RegisterRemoteProcessSession(RemoteCompositorSession* aSession);
void UnregisterRemoteProcessSession(RemoteCompositorSession* aSession);
// Called from InProcessCompositorSession. We track in process sessino so we can
// notify their owning widgets that the session must be restarted
@@ -253,17 +253,17 @@ private:
GPUProcessManager* mManager;
};
friend class Observer;
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;
uint32_t mResourceId;
uint32_t mNumProcessAttempts;
nsTArray<RefPtr<RemoteCompositorSession>> mRemoteSessions;
nsTArray<RefPtr<InProcessCompositorSession>> mInProcessSessions;
--- a/widget/ContentCache.cpp
+++ b/widget/ContentCache.cpp
@@ -1,28 +1,31 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: sw=2 ts=8 et :
*/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* 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*
GetBoolName(bool aBool)
{
return aBool ? "true" : "false";
}
@@ -506,18 +509,19 @@ ContentCacheInChild::SetSelection(nsIWid
}
Unused << NS_WARN_IF(!CacheTextRects(aWidget));
}
/*****************************************************************************
* mozilla::ContentCacheInParent
*****************************************************************************/
-ContentCacheInParent::ContentCacheInParent()
+ContentCacheInParent::ContentCacheInParent(TabParent& aTabParent)
: ContentCache()
+ , mTabParent(aTabParent)
, mCommitStringByRequest(nullptr)
, mPendingEventsNeedingAck(0)
, mCompositionStartInChild(UINT32_MAX)
, mPendingCompositionCount(0)
, mWidgetHasComposition(false)
{
}
@@ -1229,16 +1233,20 @@ ContentCacheInParent::RequestIMEToCommit
MOZ_LOG(sContentCacheLog, LogLevel::Warning,
(" 0x%p RequestToCommitComposition(), "
"does nothing due to no composition", this));
return false;
}
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));
mCommitStringByRequest = nullptr;
MOZ_LOG(sContentCacheLog, LogLevel::Info,
(" 0x%p RequestToCommitComposition(), "
"mWidgetHasComposition=%s, the composition %s committed synchronously",
@@ -1269,17 +1277,17 @@ ContentCacheInParent::RequestIMEToCommit
return true;
}
void
ContentCacheInParent::MaybeNotifyIME(nsIWidget* aWidget,
const IMENotification& aNotification)
{
if (!mPendingEventsNeedingAck) {
- IMEStateManager::NotifyIME(aNotification, aWidget, true);
+ IMEStateManager::NotifyIME(aNotification, aWidget, &mTabParent);
return;
}
switch (aNotification.mMessage) {
case NOTIFY_IME_OF_SELECTION_CHANGE:
mPendingSelectionChange.MergeWith(aNotification);
break;
case NOTIFY_IME_OF_TEXT_CHANGE:
@@ -1310,45 +1318,45 @@ ContentCacheInParent::FlushPendingNotifi
// First, text change notification should be sent because selection change
// notification notifies IME of current selection range in the latest content.
// So, IME may need the latest content before that.
if (mPendingTextChange.HasNotification()) {
IMENotification notification(mPendingTextChange);
if (!aWidget->Destroyed()) {
mPendingTextChange.Clear();
- IMEStateManager::NotifyIME(notification, aWidget, true);
+ IMEStateManager::NotifyIME(notification, aWidget, &mTabParent);
}
}
if (mPendingSelectionChange.HasNotification()) {
IMENotification notification(mPendingSelectionChange);
if (!aWidget->Destroyed()) {
mPendingSelectionChange.Clear();
- IMEStateManager::NotifyIME(notification, aWidget, true);
+ IMEStateManager::NotifyIME(notification, aWidget, &mTabParent);
}
}
// Layout change notification should be notified after selection change
// notification because IME may want to query position of new caret position.
if (mPendingLayoutChange.HasNotification()) {
IMENotification notification(mPendingLayoutChange);
if (!aWidget->Destroyed()) {
mPendingLayoutChange.Clear();
- IMEStateManager::NotifyIME(notification, aWidget, true);
+ IMEStateManager::NotifyIME(notification, aWidget, &mTabParent);
}
}
// Finally, send composition update notification because it notifies IME of
// finishing handling whole sending events.
if (mPendingCompositionUpdate.HasNotification()) {
IMENotification notification(mPendingCompositionUpdate);
if (!aWidget->Destroyed()) {
mPendingCompositionUpdate.Clear();
- IMEStateManager::NotifyIME(notification, aWidget, true);
+ IMEStateManager::NotifyIME(notification, aWidget, &mTabParent);
}
}
if (!--mPendingEventsNeedingAck && !aWidget->Destroyed() &&
(mPendingTextChange.HasNotification() ||
mPendingSelectionChange.HasNotification() ||
mPendingLayoutChange.HasNotification() ||
mPendingCompositionUpdate.HasNotification())) {
--- a/widget/ContentCache.h
+++ b/widget/ContentCache.h
@@ -18,16 +18,20 @@
#include "nsString.h"
#include "nsTArray.h"
#include "Units.h"
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
* content process.
*/
class ContentCache
{
@@ -313,17 +317,17 @@ private:
const IMENotification* aNotification = nullptr);
bool CacheTextRects(nsIWidget* aWidget,
const IMENotification* aNotification = nullptr);
};
class ContentCacheInParent final : public ContentCache
{
public:
- ContentCacheInParent();
+ explicit ContentCacheInParent(dom::TabParent& aTabParent);
/**
* AssignContent() is called when TabParent receives ContentCache from
* the content process. This doesn't copy composition information because
* it's managed by TabParent itself.
*/
void AssignContent(const ContentCache& aOther,
nsIWidget* aWidget,
@@ -401,16 +405,18 @@ public:
const IMENotification& aNotification);
private:
IMENotification mPendingSelectionChange;
IMENotification mPendingTextChange;
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.
nsAString* mCommitStringByRequest;
// mPendingEventsNeedingAck is increased before sending a composition event or
// a selection event and decreased after they are received in the child
// process.
uint32_t mPendingEventsNeedingAck;
@@ -427,16 +433,18 @@ private:
// mPendingCompositionCount is number of compositions which started in widget
// but not yet handled in the child process.
uint8_t mPendingCompositionCount;
// mWidgetHasComposition is true when the widget in this process thinks that
// IME has composition. So, this is set to true when eCompositionStart is
// 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
* cache forcibly.
*/
bool GetCaretRect(uint32_t aOffset,
bool aRoundToExistingOffset,
LayoutDeviceIntRect& aCaretRect) const;
--- a/widget/windows/WinIMEHandler.cpp
+++ b/widget/windows/WinIMEHandler.cpp
@@ -393,18 +393,19 @@ IMEHandler::GetOpenState(nsWindow* aWind
void
IMEHandler::OnDestroyWindow(nsWindow* aWindow)
{
// When focus is in remote process, but the window is being destroyed, we
// need to clean up TSFTextStore here since NOTIFY_IME_OF_BLUR won't reach
// 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));
}
#ifdef NS_ENABLE_TSF
// We need to do nothing here for TSF. Just restore the default context
// if it's been disassociated.
if (!sIsInTSFMode) {
// MSDN says we need to set IS_DEFAULT to avoid memory leak when we use