Bug 1177388 Create ContentCacheInParent and ContentCacheInChild for making their purpose clearer r=m_kato
authorMasayuki Nakano <masayuki@d-toybox.com>
Fri, 26 Jun 2015 08:21:13 +0900
changeset 250288 7b4ada358d96edb85c1fddd0e901171aa662a565
parent 250287 b70171b7816754826c46d2eb351504074ba5346d
child 250289 1a326aaaba371e18e090f98ca1c4474bbdce2fca
push id28951
push usercbook@mozilla.com
push dateFri, 26 Jun 2015 11:19:38 +0000
treeherdermozilla-central@56e207dbb3bd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersm_kato
bugs1177388
milestone41.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1177388 Create ContentCacheInParent and ContentCacheInChild for making their purpose clearer r=m_kato
dom/ipc/TabParent.h
widget/ContentCache.cpp
widget/ContentCache.h
widget/PuppetWidget.h
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -464,17 +464,17 @@ protected:
 
     bool InitBrowserConfiguration(const nsCString& aURI,
                                   BrowserConfiguration& aConfiguration);
 
     void SetHasContentOpener(bool aHasContentOpener);
 
     // IME
     static TabParent *mIMETabParent;
-    ContentCache mContentCache;
+    ContentCacheInParent mContentCache;
 
     nsIntRect mRect;
     ScreenIntSize mDimensions;
     ScreenOrientation mOrientation;
     float mDPI;
     CSSToLayoutDeviceScale mDefaultScale;
     bool mUpdatedDimensions;
     LayoutDeviceIntPoint mChromeOffset;
--- a/widget/ContentCache.cpp
+++ b/widget/ContentCache.cpp
@@ -112,315 +112,80 @@ public:
 
 /*****************************************************************************
  * mozilla::ContentCache
  *****************************************************************************/
 
 PRLogModuleInfo* sContentCacheLog = nullptr;
 
 ContentCache::ContentCache()
-  : mCompositionStart(UINT32_MAX)
-  , mCompositionEventsDuringRequest(0)
-  , mIsComposing(false)
-  , mRequestedToCommitOrCancelComposition(false)
-  , mIsChrome(XRE_GetProcessType() == GeckoProcessType_Default)
 {
   if (!sContentCacheLog) {
     sContentCacheLog = PR_NewLogModule("ContentCacheWidgets");
   }
 }
 
-void
-ContentCache::AssignContent(const ContentCache& aOther,
-                            const IMENotification* aNotification)
-{
-  if (NS_WARN_IF(!mIsChrome)) {
-    return;
-  }
-
-  mText = aOther.mText;
-  mSelection = aOther.mSelection;
-  mFirstCharRect = aOther.mFirstCharRect;
-  mCaret = aOther.mCaret;
-  mTextRectArray = aOther.mTextRectArray;
-  mEditorRect = aOther.mEditorRect;
+/*****************************************************************************
+ * mozilla::ContentCacheInChild
+ *****************************************************************************/
 
-  MOZ_LOG(sContentCacheLog, LogLevel::Info,
-    ("ContentCache: 0x%p (mIsChrome=%s) AssignContent(aNotification=%s), "
-     "Succeeded, mText.Length()=%u, mSelection={ mAnchor=%u, mFocus=%u, "
-     "mWritingMode=%s, mAnchorCharRect=%s, mFocusCharRect=%s, mRect=%s }, "
-     "mFirstCharRect=%s, mCaret={ mOffset=%u, mRect=%s }, mTextRectArray={ "
-     "mStart=%u, mRects.Length()=%u }, mEditorRect=%s",
-     this, GetBoolName(mIsChrome), GetNotificationName(aNotification),
-     mText.Length(), mSelection.mAnchor, mSelection.mFocus,
-     GetWritingModeName(mSelection.mWritingMode).get(),
-     GetRectText(mSelection.mAnchorCharRect).get(),
-     GetRectText(mSelection.mFocusCharRect).get(),
-     GetRectText(mSelection.mRect).get(), GetRectText(mFirstCharRect).get(),
-     mCaret.mOffset, GetRectText(mCaret.mRect).get(), mTextRectArray.mStart,
-     mTextRectArray.mRects.Length(), GetRectText(mEditorRect).get()));
+ContentCacheInChild::ContentCacheInChild()
+  : ContentCache()
+{
 }
 
 void
-ContentCache::Clear()
+ContentCacheInChild::Clear()
 {
   MOZ_LOG(sContentCacheLog, LogLevel::Info,
-    ("ContentCache: 0x%p (mIsChrome=%s) Clear()",
-     this, GetBoolName(mIsChrome)));
-
-  if (NS_WARN_IF(mIsChrome)) {
-    return;
-  }
+    ("ContentCacheInChild: 0x%p Clear()", this));
 
   mText.Truncate();
   mSelection.Clear();
   mFirstCharRect.SetEmpty();
   mCaret.Clear();
   mTextRectArray.Clear();
   mEditorRect.SetEmpty();
 }
 
 bool
-ContentCache::HandleQueryContentEvent(WidgetQueryContentEvent& aEvent,
-                                      nsIWidget* aWidget) const
-{
-  MOZ_ASSERT(aWidget);
-
-  if (NS_WARN_IF(!mIsChrome)) {
-    return false;
-  }
-
-  aEvent.mSucceeded = false;
-  aEvent.mWasAsync = false;
-  aEvent.mReply.mFocusedWidget = aWidget;
-
-  switch (aEvent.message) {
-    case NS_QUERY_SELECTED_TEXT:
-      MOZ_LOG(sContentCacheLog, LogLevel::Info,
-        ("ContentCache: 0x%p (mIsChrome=%s) HandleQueryContentEvent("
-         "aEvent={ message=NS_QUERY_SELECTED_TEXT }, aWidget=0x%p)",
-         this, GetBoolName(mIsChrome), aWidget));
-      if (NS_WARN_IF(!IsSelectionValid())) {
-        // If content cache hasn't been initialized properly, make the query
-        // failed.
-        MOZ_LOG(sContentCacheLog, LogLevel::Error,
-          ("ContentCache: 0x%p (mIsChrome=%s) HandleQueryContentEvent(), "
-           "FAILED because mSelection is not valid",
-           this, GetBoolName(mIsChrome)));
-        return true;
-      }
-      aEvent.mReply.mOffset = mSelection.StartOffset();
-      if (mSelection.Collapsed()) {
-        aEvent.mReply.mString.Truncate(0);
-      } else {
-        if (NS_WARN_IF(mSelection.EndOffset() > mText.Length())) {
-          MOZ_LOG(sContentCacheLog, LogLevel::Error,
-            ("ContentCache: 0x%p (mIsChrome=%s) HandleQueryContentEvent(), "
-             "FAILED because mSelection.EndOffset()=%u is larger than "
-             "mText.Length()=%u",
-             this, GetBoolName(mIsChrome), mSelection.EndOffset(),
-             mText.Length()));
-          return false;
-        }
-        aEvent.mReply.mString =
-          Substring(mText, aEvent.mReply.mOffset, mSelection.Length());
-      }
-      aEvent.mReply.mReversed = mSelection.Reversed();
-      aEvent.mReply.mHasSelection = true;
-      aEvent.mReply.mWritingMode = mSelection.mWritingMode;
-      MOZ_LOG(sContentCacheLog, LogLevel::Info,
-        ("ContentCache: 0x%p (mIsChrome=%s) HandleQueryContentEvent(), "
-         "Succeeded, aEvent={ mReply={ mOffset=%u, mString=\"%s\", "
-         "mReversed=%s, mHasSelection=%s, mWritingMode=%s } }",
-         this, GetBoolName(mIsChrome), aEvent.mReply.mOffset,
-         NS_ConvertUTF16toUTF8(aEvent.mReply.mString).get(),
-         GetBoolName(aEvent.mReply.mReversed),
-         GetBoolName(aEvent.mReply.mHasSelection),
-         GetWritingModeName(aEvent.mReply.mWritingMode).get()));
-      break;
-    case NS_QUERY_TEXT_CONTENT: {
-      MOZ_LOG(sContentCacheLog, LogLevel::Info,
-        ("ContentCache: 0x%p (mIsChrome=%s) HandleQueryContentEvent("
-         "aEvent={ message=NS_QUERY_TEXT_CONTENT, mInput={ mOffset=%u, "
-         "mLength=%u } }, aWidget=0x%p), mText.Length()=%u",
-         this, GetBoolName(mIsChrome), aEvent.mInput.mOffset,
-         aEvent.mInput.mLength, aWidget, mText.Length()));
-      uint32_t inputOffset = aEvent.mInput.mOffset;
-      uint32_t inputEndOffset =
-        std::min(aEvent.mInput.EndOffset(), mText.Length());
-      if (NS_WARN_IF(inputEndOffset < inputOffset)) {
-        MOZ_LOG(sContentCacheLog, LogLevel::Error,
-          ("ContentCache: 0x%p (mIsChrome=%s) HandleQueryContentEvent(), "
-           "FAILED because inputOffset=%u is larger than inputEndOffset=%u",
-           this, GetBoolName(mIsChrome), inputOffset, inputEndOffset));
-        return false;
-      }
-      aEvent.mReply.mOffset = inputOffset;
-      aEvent.mReply.mString =
-        Substring(mText, inputOffset, inputEndOffset - inputOffset);
-      MOZ_LOG(sContentCacheLog, LogLevel::Info,
-        ("ContentCache: 0x%p (mIsChrome=%s) HandleQueryContentEvent(), "
-         "Succeeded, aEvent={ mReply={ mOffset=%u, mString.Length()=%u } }",
-         this, GetBoolName(mIsChrome), aEvent.mReply.mOffset,
-         aEvent.mReply.mString.Length()));
-      break;
-    }
-    case NS_QUERY_TEXT_RECT:
-      MOZ_LOG(sContentCacheLog, LogLevel::Info,
-        ("ContentCache: 0x%p (mIsChrome=%s) HandleQueryContentEvent("
-         "aEvent={ message=NS_QUERY_TEXT_RECT, mInput={ mOffset=%u, "
-         "mLength=%u } }, aWidget=0x%p), mText.Length()=%u",
-         this, GetBoolName(mIsChrome), aEvent.mInput.mOffset,
-         aEvent.mInput.mLength, aWidget, mText.Length()));
-      if (NS_WARN_IF(!IsSelectionValid())) {
-        // If content cache hasn't been initialized properly, make the query
-        // failed.
-        MOZ_LOG(sContentCacheLog, LogLevel::Error,
-          ("ContentCache: 0x%p (mIsChrome=%s) HandleQueryContentEvent(), "
-           "FAILED because mSelection is not valid",
-           this, GetBoolName(mIsChrome)));
-        return true;
-      }
-      if (aEvent.mInput.mLength) {
-        if (NS_WARN_IF(!GetUnionTextRects(aEvent.mInput.mOffset,
-                                          aEvent.mInput.mLength,
-                                          aEvent.mReply.mRect))) {
-          // XXX We don't have cache for this request.
-          MOZ_LOG(sContentCacheLog, LogLevel::Error,
-            ("ContentCache: 0x%p (mIsChrome=%s) HandleQueryContentEvent(), "
-             "FAILED to get union rect",
-             this, GetBoolName(mIsChrome)));
-          return false;
-        }
-      } else {
-        // If the length is 0, we should return caret rect instead.
-        if (NS_WARN_IF(!GetCaretRect(aEvent.mInput.mOffset,
-                                     aEvent.mReply.mRect))) {
-          MOZ_LOG(sContentCacheLog, LogLevel::Error,
-            ("ContentCache: 0x%p (mIsChrome=%s) HandleQueryContentEvent(), "
-             "FAILED to get caret rect",
-             this, GetBoolName(mIsChrome)));
-          return false;
-        }
-      }
-      if (aEvent.mInput.mOffset < mText.Length()) {
-        aEvent.mReply.mString =
-          Substring(mText, aEvent.mInput.mOffset,
-                    mText.Length() >= aEvent.mInput.EndOffset() ?
-                      aEvent.mInput.mLength : UINT32_MAX);
-      } else {
-        aEvent.mReply.mString.Truncate(0);
-      }
-      aEvent.mReply.mOffset = aEvent.mInput.mOffset;
-      // XXX This may be wrong if storing range isn't in the selection range.
-      aEvent.mReply.mWritingMode = mSelection.mWritingMode;
-      MOZ_LOG(sContentCacheLog, LogLevel::Info,
-        ("ContentCache: 0x%p (mIsChrome=%s) HandleQueryContentEvent(), "
-         "Succeeded, aEvent={ mReply={ mOffset=%u, mString=\"%s\", "
-         "mWritingMode=%s, mRect=%s } }",
-         this, GetBoolName(mIsChrome), aEvent.mReply.mOffset,
-         NS_ConvertUTF16toUTF8(aEvent.mReply.mString).get(),
-         GetWritingModeName(aEvent.mReply.mWritingMode).get(),
-         GetRectText(aEvent.mReply.mRect).get()));
-      break;
-    case NS_QUERY_CARET_RECT:
-      MOZ_LOG(sContentCacheLog, LogLevel::Info,
-        ("ContentCache: 0x%p (mIsChrome=%s) HandleQueryContentEvent("
-         "aEvent={ message=NS_QUERY_CARET_RECT, mInput={ mOffset=%u } }, "
-         "aWidget=0x%p), mText.Length()=%u",
-         this, GetBoolName(mIsChrome), aEvent.mInput.mOffset, aWidget,
-         mText.Length()));
-      if (NS_WARN_IF(!IsSelectionValid())) {
-        // If content cache hasn't been initialized properly, make the query
-        // failed.
-        MOZ_LOG(sContentCacheLog, LogLevel::Error,
-          ("ContentCache: 0x%p (mIsChrome=%s) HandleQueryContentEvent(), "
-           "FAILED because mSelection is not valid",
-           this, GetBoolName(mIsChrome)));
-        return true;
-      }
-      if (NS_WARN_IF(!GetCaretRect(aEvent.mInput.mOffset,
-                                   aEvent.mReply.mRect))) {
-        MOZ_LOG(sContentCacheLog, LogLevel::Error,
-          ("ContentCache: 0x%p (mIsChrome=%s) HandleQueryContentEvent(), "
-           "FAILED to get caret rect",
-           this, GetBoolName(mIsChrome)));
-        return false;
-      }
-      aEvent.mReply.mOffset = aEvent.mInput.mOffset;
-      MOZ_LOG(sContentCacheLog, LogLevel::Info,
-        ("ContentCache: 0x%p (mIsChrome=%s) HandleQueryContentEvent(), "
-         "Succeeded, aEvent={ mReply={ mOffset=%u, mRect=%s } }",
-         this, GetBoolName(mIsChrome), aEvent.mReply.mOffset,
-         GetRectText(aEvent.mReply.mRect).get()));
-      break;
-    case NS_QUERY_EDITOR_RECT:
-      MOZ_LOG(sContentCacheLog, LogLevel::Info,
-        ("ContentCache: 0x%p (mIsChrome=%s) HandleQueryContentEvent("
-         "aEvent={ message=NS_QUERY_EDITOR_RECT }, aWidget=0x%p)",
-         this, GetBoolName(mIsChrome), aWidget));
-      aEvent.mReply.mRect = mEditorRect;
-      MOZ_LOG(sContentCacheLog, LogLevel::Info,
-        ("ContentCache: 0x%p (mIsChrome=%s) HandleQueryContentEvent(), "
-         "Succeeded, aEvent={ mReply={ mRect=%s } }",
-         this, GetBoolName(mIsChrome), GetRectText(aEvent.mReply.mRect).get()));
-      break;
-  }
-  aEvent.mSucceeded = true;
-  return true;
-}
-
-bool
-ContentCache::CacheAll(nsIWidget* aWidget,
-                       const IMENotification* aNotification)
+ContentCacheInChild::CacheAll(nsIWidget* aWidget,
+                              const IMENotification* aNotification)
 {
   MOZ_LOG(sContentCacheLog, LogLevel::Info,
-    ("ContentCache: 0x%p (mIsChrome=%s) CacheAll(aWidget=0x%p, "
+    ("ContentCacheInChild: 0x%p CacheAll(aWidget=0x%p, "
      "aNotification=%s)",
-     this, GetBoolName(mIsChrome), aWidget,
-     GetNotificationName(aNotification)));
-
-  // CacheAll() must be called in content process.
-  if (NS_WARN_IF(mIsChrome)) {
-    return false;
-  }
+     this, aWidget, GetNotificationName(aNotification)));
 
   if (NS_WARN_IF(!CacheText(aWidget, aNotification)) ||
       NS_WARN_IF(!CacheEditorRect(aWidget, aNotification))) {
     return false;
   }
   return true;
 }
 
 bool
-ContentCache::CacheSelection(nsIWidget* aWidget,
-                             const IMENotification* aNotification)
+ContentCacheInChild::CacheSelection(nsIWidget* aWidget,
+                                    const IMENotification* aNotification)
 {
   MOZ_LOG(sContentCacheLog, LogLevel::Info,
-    ("ContentCache: 0x%p (mIsChrome=%s) CacheSelection(aWidget=0x%p, "
+    ("ContentCacheInChild: 0x%p CacheSelection(aWidget=0x%p, "
      "aNotification=%s)",
-     this, GetBoolName(mIsChrome), aWidget,
-     GetNotificationName(aNotification)));
-
-  // CacheSelection() must be called in content process.
-  if (NS_WARN_IF(mIsChrome)) {
-    return false;
-  }
+     this, aWidget, GetNotificationName(aNotification)));
 
   mCaret.Clear();
   mSelection.Clear();
 
   nsEventStatus status = nsEventStatus_eIgnore;
   WidgetQueryContentEvent selection(true, NS_QUERY_SELECTED_TEXT, aWidget);
   aWidget->DispatchEvent(&selection, status);
   if (NS_WARN_IF(!selection.mSucceeded)) {
     MOZ_LOG(sContentCacheLog, LogLevel::Error,
-      ("ContentCache: 0x%p (mIsChrome=%s) CacheSelection(), FAILED, "
-       "couldn't retrieve the selected text",
-       this, GetBoolName(mIsChrome)));
+      ("ContentCache: 0x%p CacheSelection(), FAILED, "
+       "couldn't retrieve the selected text", this));
     return false;
   }
   if (selection.mReply.mReversed) {
     mSelection.mAnchor =
       selection.mReply.mOffset + selection.mReply.mString.Length();
     mSelection.mFocus = selection.mReply.mOffset;
   } else {
     mSelection.mAnchor = selection.mReply.mOffset;
@@ -429,142 +194,116 @@ ContentCache::CacheSelection(nsIWidget* 
   }
   mSelection.mWritingMode = selection.GetWritingMode();
 
   return CacheCaret(aWidget, aNotification) &&
          CacheTextRects(aWidget, aNotification);
 }
 
 bool
-ContentCache::CacheCaret(nsIWidget* aWidget,
-                         const IMENotification* aNotification)
+ContentCacheInChild::CacheCaret(nsIWidget* aWidget,
+                                const IMENotification* aNotification)
 {
   MOZ_LOG(sContentCacheLog, LogLevel::Info,
-    ("ContentCache: 0x%p (mIsChrome=%s) CacheCaret(aWidget=0x%p, "
+    ("ContentCacheInChild: 0x%p CacheCaret(aWidget=0x%p, "
      "aNotification=%s)",
-     this, GetBoolName(mIsChrome), aWidget,
-     GetNotificationName(aNotification)));
-
-  // CacheCaret() must be called in content process.
-  if (NS_WARN_IF(mIsChrome)) {
-    return false;
-  }
+     this, aWidget, GetNotificationName(aNotification)));
 
   mCaret.Clear();
 
   if (NS_WARN_IF(!mSelection.IsValid())) {
     return false;
   }
 
   // XXX Should be mSelection.mFocus?
   mCaret.mOffset = mSelection.StartOffset();
 
   nsEventStatus status = nsEventStatus_eIgnore;
   WidgetQueryContentEvent caretRect(true, NS_QUERY_CARET_RECT, aWidget);
   caretRect.InitForQueryCaretRect(mCaret.mOffset);
   aWidget->DispatchEvent(&caretRect, status);
   if (NS_WARN_IF(!caretRect.mSucceeded)) {
     MOZ_LOG(sContentCacheLog, LogLevel::Error,
-      ("ContentCache: 0x%p (mIsChrome=%s) CacheCaret(), FAILED, "
+      ("ContentCacheInChild: 0x%p CacheCaret(), FAILED, "
        "couldn't retrieve the caret rect at offset=%u",
-       this, GetBoolName(mIsChrome), mCaret.mOffset));
+       this, mCaret.mOffset));
     mCaret.Clear();
     return false;
   }
   mCaret.mRect = caretRect.mReply.mRect;
   MOZ_LOG(sContentCacheLog, LogLevel::Info,
-    ("ContentCache: 0x%p (mIsChrome=%s) CacheCaret(), Succeeded, "
+    ("ContentCacheInChild: 0x%p CacheCaret(), Succeeded, "
      "mSelection={ mAnchor=%u, mFocus=%u, mWritingMode=%s }, "
      "mCaret={ mOffset=%u, mRect=%s }",
-     this, GetBoolName(mIsChrome), mSelection.mAnchor, mSelection.mFocus,
+     this, mSelection.mAnchor, mSelection.mFocus,
      GetWritingModeName(mSelection.mWritingMode).get(), mCaret.mOffset,
      GetRectText(mCaret.mRect).get()));
   return true;
 }
 
 bool
-ContentCache::CacheEditorRect(nsIWidget* aWidget,
-                              const IMENotification* aNotification)
+ContentCacheInChild::CacheEditorRect(nsIWidget* aWidget,
+                                     const IMENotification* aNotification)
 {
   MOZ_LOG(sContentCacheLog, LogLevel::Info,
-    ("ContentCache: 0x%p (mIsChrome=%s) CacheEditorRect(aWidget=0x%p, "
+    ("ContentCacheInChild: 0x%p CacheEditorRect(aWidget=0x%p, "
      "aNotification=%s)",
-     this, GetBoolName(mIsChrome), aWidget,
-     GetNotificationName(aNotification)));
-
-  // CacheEditorRect() must be called in content process.
-  if (NS_WARN_IF(mIsChrome)) {
-    return false;
-  }
+     this, aWidget, GetNotificationName(aNotification)));
 
   nsEventStatus status = nsEventStatus_eIgnore;
   WidgetQueryContentEvent editorRectEvent(true, NS_QUERY_EDITOR_RECT, aWidget);
   aWidget->DispatchEvent(&editorRectEvent, status);
   if (NS_WARN_IF(!editorRectEvent.mSucceeded)) {
     MOZ_LOG(sContentCacheLog, LogLevel::Error,
-      ("ContentCache: 0x%p (mIsChrome=%s) CacheEditorRect(), FAILED, "
-       "couldn't retrieve the editor rect",
-       this, GetBoolName(mIsChrome)));
+      ("ContentCacheInChild: 0x%p CacheEditorRect(), FAILED, "
+       "couldn't retrieve the editor rect", this));
     return false;
   }
   mEditorRect = editorRectEvent.mReply.mRect;
   MOZ_LOG(sContentCacheLog, LogLevel::Info,
-    ("ContentCache: 0x%p (mIsChrome=%s) CacheEditorRect(), Succeeded, "
-     "mEditorRect=%s",
-     this, GetBoolName(mIsChrome), GetRectText(mEditorRect).get()));
+    ("ContentCacheInChild: 0x%p CacheEditorRect(), Succeeded, "
+     "mEditorRect=%s", this, GetRectText(mEditorRect).get()));
   return true;
 }
 
 bool
-ContentCache::CacheText(nsIWidget* aWidget,
-                        const IMENotification* aNotification)
+ContentCacheInChild::CacheText(nsIWidget* aWidget,
+                               const IMENotification* aNotification)
 {
   MOZ_LOG(sContentCacheLog, LogLevel::Info,
-    ("ContentCache: 0x%p (mIsChrome=%s) CacheText(aWidget=0x%p, "
+    ("ContentCacheInChild: 0x%p CacheText(aWidget=0x%p, "
      "aNotification=%s)",
-     this, GetBoolName(mIsChrome), aWidget,
-     GetNotificationName(aNotification)));
-
-  // CacheText() must be called in content process.
-  if (NS_WARN_IF(mIsChrome)) {
-    return false;
-  }
+     this, aWidget, GetNotificationName(aNotification)));
 
   nsEventStatus status = nsEventStatus_eIgnore;
   WidgetQueryContentEvent queryText(true, NS_QUERY_TEXT_CONTENT, aWidget);
   queryText.InitForQueryTextContent(0, UINT32_MAX);
   aWidget->DispatchEvent(&queryText, status);
   if (NS_WARN_IF(!queryText.mSucceeded)) {
     MOZ_LOG(sContentCacheLog, LogLevel::Error,
-      ("ContentCache: 0x%p (mIsChrome=%s) CacheText(), FAILED, "
-       "couldn't retrieve whole text",
-       this, GetBoolName(mIsChrome)));
+      ("ContentCacheInChild: 0x%p CacheText(), FAILED, "
+       "couldn't retrieve whole text", this));
     mText.Truncate();
     return false;
   }
   mText = queryText.mReply.mString;
   MOZ_LOG(sContentCacheLog, LogLevel::Info,
-    ("ContentCache: 0x%p (mIsChrome=%s) CacheText(), Succeeded, "
-     "mText.Length()=%u",
-     this, GetBoolName(mIsChrome), mText.Length()));
+    ("ContentCacheInChild: 0x%p CacheText(), Succeeded, "
+     "mText.Length()=%u", this, mText.Length()));
 
   return CacheSelection(aWidget, aNotification);
 }
 
 bool
-ContentCache::QueryCharRect(nsIWidget* aWidget,
-                            uint32_t aOffset,
-                            LayoutDeviceIntRect& aCharRect) const
+ContentCacheInChild::QueryCharRect(nsIWidget* aWidget,
+                                   uint32_t aOffset,
+                                   LayoutDeviceIntRect& aCharRect) const
 {
   aCharRect.SetEmpty();
 
-  if (NS_WARN_IF(mIsChrome)) {
-    return false;
-  }
-
   nsEventStatus status = nsEventStatus_eIgnore;
   WidgetQueryContentEvent textRect(true, NS_QUERY_TEXT_RECT, aWidget);
   textRect.InitForQueryTextRect(aOffset, 1);
   aWidget->DispatchEvent(&textRect, status);
   if (NS_WARN_IF(!textRect.mSucceeded)) {
     return false;
   }
   aCharRect = textRect.mReply.mRect;
@@ -575,31 +314,25 @@ ContentCache::QueryCharRect(nsIWidget* a
   }
   if (NS_WARN_IF(!aCharRect.width)) {
     aCharRect.width = 1;
   }
   return true;
 }
 
 bool
-ContentCache::CacheTextRects(nsIWidget* aWidget,
-                             const IMENotification* aNotification)
+ContentCacheInChild::CacheTextRects(nsIWidget* aWidget,
+                                    const IMENotification* aNotification)
 {
   MOZ_LOG(sContentCacheLog, LogLevel::Info,
-    ("ContentCache: 0x%p (mIsChrome=%s) CacheTextRects(aWidget=0x%p, "
+    ("ContentCacheInChild: 0x%p CacheTextRects(aWidget=0x%p, "
      "aNotification=%s), mCaret={ mOffset=%u, IsValid()=%s }",
-     this, GetBoolName(mIsChrome), aWidget,
-     GetNotificationName(aNotification), mCaret.mOffset,
+     this, aWidget, GetNotificationName(aNotification), mCaret.mOffset,
      GetBoolName(mCaret.IsValid())));
 
-  // CacheTextRects() must be called in content process.
-  if (NS_WARN_IF(mIsChrome)) {
-    return false;
-  }
-
   mTextRectArray.Clear();
   mSelection.mAnchorCharRect.SetEmpty();
   mSelection.mFocusCharRect.SetEmpty();
   mSelection.mRect.SetEmpty();
   mFirstCharRect.SetEmpty();
 
   if (NS_WARN_IF(!mSelection.IsValid())) {
     return false;
@@ -615,144 +348,352 @@ ContentCache::CacheTextRects(nsIWidget* 
     uint32_t length = textComposition->LastData().Length();
     mTextRectArray.mRects.SetCapacity(length);
     mTextRectArray.mStart = textComposition->NativeOffsetOfStartComposition();
     uint32_t endOffset = mTextRectArray.mStart + length;
     for (uint32_t i = mTextRectArray.mStart; i < endOffset; i++) {
       LayoutDeviceIntRect charRect;
       if (NS_WARN_IF(!QueryCharRect(aWidget, i, charRect))) {
         MOZ_LOG(sContentCacheLog, LogLevel::Error,
-          ("ContentCache: 0x%p (mIsChrome=%s) CacheTextRects(), FAILED, "
-           "couldn't retrieve text rect at offset=%u",
-           this, GetBoolName(mIsChrome), i));
+          ("ContentCacheInChild: 0x%p CacheTextRects(), FAILED, "
+           "couldn't retrieve text rect at offset=%u", this, i));
         mTextRectArray.Clear();
         return false;
       }
       mTextRectArray.mRects.AppendElement(charRect);
     }
   }
 
   if (mTextRectArray.InRange(mSelection.mAnchor)) {
     mSelection.mAnchorCharRect = mTextRectArray.GetRect(mSelection.mAnchor);
   } else {
     LayoutDeviceIntRect charRect;
     if (NS_WARN_IF(!QueryCharRect(aWidget, mSelection.mAnchor, charRect))) {
       MOZ_LOG(sContentCacheLog, LogLevel::Error,
-        ("ContentCache: 0x%p (mIsChrome=%s) CacheTextRects(), FAILED, "
+        ("ContentCacheInChild: 0x%p CacheTextRects(), FAILED, "
          "couldn't retrieve text rect at anchor of selection (%u)",
-         this, GetBoolName(mIsChrome), mSelection.mAnchor));
+         this, mSelection.mAnchor));
     }
     mSelection.mAnchorCharRect = charRect;
   }
 
   if (mSelection.Collapsed()) {
     mSelection.mFocusCharRect = mSelection.mAnchorCharRect;
   } else if (mTextRectArray.InRange(mSelection.mFocus)) {
     mSelection.mFocusCharRect = mTextRectArray.GetRect(mSelection.mFocus);
   } else {
     LayoutDeviceIntRect charRect;
     if (NS_WARN_IF(!QueryCharRect(aWidget, mSelection.mFocus, charRect))) {
       MOZ_LOG(sContentCacheLog, LogLevel::Error,
-        ("ContentCache: 0x%p (mIsChrome=%s) CacheTextRects(), FAILED, "
+        ("ContentCacheInChild: 0x%p CacheTextRects(), FAILED, "
          "couldn't retrieve text rect at focus of selection (%u)",
-         this, GetBoolName(mIsChrome), mSelection.mFocus));
+         this, mSelection.mFocus));
     }
     mSelection.mFocusCharRect = charRect;
   }
 
   if (!mSelection.Collapsed()) {
     nsEventStatus status = nsEventStatus_eIgnore;
     WidgetQueryContentEvent textRect(true, NS_QUERY_TEXT_RECT, aWidget);
     textRect.InitForQueryTextRect(mSelection.StartOffset(),
                                   mSelection.Length());
     aWidget->DispatchEvent(&textRect, status);
     if (NS_WARN_IF(!textRect.mSucceeded)) {
       MOZ_LOG(sContentCacheLog, LogLevel::Error,
-        ("ContentCache: 0x%p (mIsChrome=%s) CacheTextRects(), FAILED, "
-         "couldn't retrieve text rect of whole selected text",
-         this, GetBoolName(mIsChrome)));
+        ("ContentCacheInChild: 0x%p CacheTextRects(), FAILED, "
+         "couldn't retrieve text rect of whole selected text", this));
     } else {
       mSelection.mRect = textRect.mReply.mRect;
     }
   }
 
   if (!mSelection.mFocus) {
     mFirstCharRect = mSelection.mFocusCharRect;
   } else if (!mSelection.mAnchor) {
     mFirstCharRect = mSelection.mAnchorCharRect;
   } else if (mTextRectArray.InRange(0)) {
     mFirstCharRect = mTextRectArray.GetRect(0);
   } else {
     LayoutDeviceIntRect charRect;
     if (NS_WARN_IF(!QueryCharRect(aWidget, 0, charRect))) {
       MOZ_LOG(sContentCacheLog, LogLevel::Error,
-        ("ContentCache: 0x%p (mIsChrome=%s) CacheTextRects(), FAILED, "
-         "couldn't retrieve first char rect",
-         this, GetBoolName(mIsChrome)));
+        ("ContentCacheInChild: 0x%p CacheTextRects(), FAILED, "
+         "couldn't retrieve first char rect", this));
     } else {
       mFirstCharRect = charRect;
     }
   }
 
   MOZ_LOG(sContentCacheLog, LogLevel::Info,
-    ("ContentCache: 0x%p (mIsChrome=%s) CacheTextRects(), Succeeded, "
+    ("ContentCacheInChild: 0x%p CacheTextRects(), Succeeded, "
      "mText.Length()=%u, mTextRectArray={ mStart=%u, mRects.Length()=%u }, "
      "mSelection={ mAnchor=%u, mAnchorCharRect=%s, mFocus=%u, "
      "mFocusCharRect=%s, mRect=%s }, mFirstCharRect=%s",
-     this, GetBoolName(mIsChrome), mText.Length(), mTextRectArray.mStart,
+     this, mText.Length(), mTextRectArray.mStart,
      mTextRectArray.mRects.Length(), mSelection.mAnchor,
      GetRectText(mSelection.mAnchorCharRect).get(), mSelection.mFocus,
      GetRectText(mSelection.mFocusCharRect).get(),
      GetRectText(mSelection.mRect).get(), GetRectText(mFirstCharRect).get()));
   return true;
 }
 
 void
-ContentCache::SetSelection(nsIWidget* aWidget,
-                           uint32_t aStartOffset,
-                           uint32_t aLength,
-                           bool aReversed,
-                           const WritingMode& aWritingMode)
+ContentCacheInChild::SetSelection(nsIWidget* aWidget,
+                                  uint32_t aStartOffset,
+                                  uint32_t aLength,
+                                  bool aReversed,
+                                  const WritingMode& aWritingMode)
 {
   MOZ_LOG(sContentCacheLog, LogLevel::Info,
-    ("ContentCache: 0x%p (mIsChrome=%s) SetSelection(aStartOffset=%u, "
+    ("ContentCacheInChild: 0x%p SetSelection(aStartOffset=%u, "
      "aLength=%u, aReversed=%s, aWritingMode=%s), mText.Length()=%u",
-     this, GetBoolName(mIsChrome), aStartOffset, aLength,
-     GetBoolName(aReversed), GetWritingModeName(aWritingMode).get(),
-     mText.Length()));
-
-  if (NS_WARN_IF(mIsChrome)) {
-    return;
-  }
+     this, aStartOffset, aLength, GetBoolName(aReversed),
+     GetWritingModeName(aWritingMode).get(), mText.Length()));
 
   if (!aReversed) {
     mSelection.mAnchor = aStartOffset;
     mSelection.mFocus = aStartOffset + aLength;
   } else {
     mSelection.mAnchor = aStartOffset + aLength;
     mSelection.mFocus = aStartOffset;
   }
   mSelection.mWritingMode = aWritingMode;
 
   if (NS_WARN_IF(!CacheCaret(aWidget))) {
     return;
   }
   NS_WARN_IF(!CacheTextRects(aWidget));
 }
 
+/*****************************************************************************
+ * mozilla::ContentCacheInParent
+ *****************************************************************************/
+
+ContentCacheInParent::ContentCacheInParent()
+  : ContentCache()
+  , mCompositionStart(UINT32_MAX)
+  , mCompositionEventsDuringRequest(0)
+  , mIsComposing(false)
+  , mRequestedToCommitOrCancelComposition(false)
+{
+}
+
+void
+ContentCacheInParent::AssignContent(const ContentCache& aOther,
+                                    const IMENotification* aNotification)
+{
+  mText = aOther.mText;
+  mSelection = aOther.mSelection;
+  mFirstCharRect = aOther.mFirstCharRect;
+  mCaret = aOther.mCaret;
+  mTextRectArray = aOther.mTextRectArray;
+  mEditorRect = aOther.mEditorRect;
+
+  MOZ_LOG(sContentCacheLog, LogLevel::Info,
+    ("ContentCacheInParent: 0x%p AssignContent(aNotification=%s), "
+     "Succeeded, mText.Length()=%u, mSelection={ mAnchor=%u, mFocus=%u, "
+     "mWritingMode=%s, mAnchorCharRect=%s, mFocusCharRect=%s, mRect=%s }, "
+     "mFirstCharRect=%s, mCaret={ mOffset=%u, mRect=%s }, mTextRectArray={ "
+     "mStart=%u, mRects.Length()=%u }, mEditorRect=%s",
+     this, GetNotificationName(aNotification),
+     mText.Length(), mSelection.mAnchor, mSelection.mFocus,
+     GetWritingModeName(mSelection.mWritingMode).get(),
+     GetRectText(mSelection.mAnchorCharRect).get(),
+     GetRectText(mSelection.mFocusCharRect).get(),
+     GetRectText(mSelection.mRect).get(), GetRectText(mFirstCharRect).get(),
+     mCaret.mOffset, GetRectText(mCaret.mRect).get(), mTextRectArray.mStart,
+     mTextRectArray.mRects.Length(), GetRectText(mEditorRect).get()));
+}
+
 bool
-ContentCache::GetTextRect(uint32_t aOffset,
-                          LayoutDeviceIntRect& aTextRect) const
+ContentCacheInParent::HandleQueryContentEvent(WidgetQueryContentEvent& aEvent,
+                                              nsIWidget* aWidget) const
+{
+  MOZ_ASSERT(aWidget);
+
+  aEvent.mSucceeded = false;
+  aEvent.mWasAsync = false;
+  aEvent.mReply.mFocusedWidget = aWidget;
+
+  switch (aEvent.message) {
+    case NS_QUERY_SELECTED_TEXT:
+      MOZ_LOG(sContentCacheLog, LogLevel::Info,
+        ("ContentCacheInParent: 0x%p HandleQueryContentEvent("
+         "aEvent={ message=NS_QUERY_SELECTED_TEXT }, aWidget=0x%p)",
+         this, aWidget));
+      if (NS_WARN_IF(!IsSelectionValid())) {
+        // If content cache hasn't been initialized properly, make the query
+        // failed.
+        MOZ_LOG(sContentCacheLog, LogLevel::Error,
+          ("ContentCacheInParent: 0x%p HandleQueryContentEvent(), "
+           "FAILED because mSelection is not valid", this));
+        return true;
+      }
+      aEvent.mReply.mOffset = mSelection.StartOffset();
+      if (mSelection.Collapsed()) {
+        aEvent.mReply.mString.Truncate(0);
+      } else {
+        if (NS_WARN_IF(mSelection.EndOffset() > mText.Length())) {
+          MOZ_LOG(sContentCacheLog, LogLevel::Error,
+            ("ContentCacheInParent: 0x%p HandleQueryContentEvent(), "
+             "FAILED because mSelection.EndOffset()=%u is larger than "
+             "mText.Length()=%u",
+             this, mSelection.EndOffset(), mText.Length()));
+          return false;
+        }
+        aEvent.mReply.mString =
+          Substring(mText, aEvent.mReply.mOffset, mSelection.Length());
+      }
+      aEvent.mReply.mReversed = mSelection.Reversed();
+      aEvent.mReply.mHasSelection = true;
+      aEvent.mReply.mWritingMode = mSelection.mWritingMode;
+      MOZ_LOG(sContentCacheLog, LogLevel::Info,
+        ("ContentCacheInParent: 0x%p HandleQueryContentEvent(), "
+         "Succeeded, aEvent={ mReply={ mOffset=%u, mString=\"%s\", "
+         "mReversed=%s, mHasSelection=%s, mWritingMode=%s } }",
+         this, aEvent.mReply.mOffset,
+         NS_ConvertUTF16toUTF8(aEvent.mReply.mString).get(),
+         GetBoolName(aEvent.mReply.mReversed),
+         GetBoolName(aEvent.mReply.mHasSelection),
+         GetWritingModeName(aEvent.mReply.mWritingMode).get()));
+      break;
+    case NS_QUERY_TEXT_CONTENT: {
+      MOZ_LOG(sContentCacheLog, LogLevel::Info,
+        ("ContentCacheInParent: 0x%p HandleQueryContentEvent("
+         "aEvent={ message=NS_QUERY_TEXT_CONTENT, mInput={ mOffset=%u, "
+         "mLength=%u } }, aWidget=0x%p), mText.Length()=%u",
+         this, aEvent.mInput.mOffset,
+         aEvent.mInput.mLength, aWidget, mText.Length()));
+      uint32_t inputOffset = aEvent.mInput.mOffset;
+      uint32_t inputEndOffset =
+        std::min(aEvent.mInput.EndOffset(), mText.Length());
+      if (NS_WARN_IF(inputEndOffset < inputOffset)) {
+        MOZ_LOG(sContentCacheLog, LogLevel::Error,
+          ("ContentCacheInParent: 0x%p HandleQueryContentEvent(), "
+           "FAILED because inputOffset=%u is larger than inputEndOffset=%u",
+           this, inputOffset, inputEndOffset));
+        return false;
+      }
+      aEvent.mReply.mOffset = inputOffset;
+      aEvent.mReply.mString =
+        Substring(mText, inputOffset, inputEndOffset - inputOffset);
+      MOZ_LOG(sContentCacheLog, LogLevel::Info,
+        ("ContentCacheInParent: 0x%p HandleQueryContentEvent(), "
+         "Succeeded, aEvent={ mReply={ mOffset=%u, mString.Length()=%u } }",
+         this, aEvent.mReply.mOffset, aEvent.mReply.mString.Length()));
+      break;
+    }
+    case NS_QUERY_TEXT_RECT:
+      MOZ_LOG(sContentCacheLog, LogLevel::Info,
+        ("ContentCacheInParent: 0x%p HandleQueryContentEvent("
+         "aEvent={ message=NS_QUERY_TEXT_RECT, mInput={ mOffset=%u, "
+         "mLength=%u } }, aWidget=0x%p), mText.Length()=%u",
+         this, aEvent.mInput.mOffset, aEvent.mInput.mLength, aWidget,
+         mText.Length()));
+      if (NS_WARN_IF(!IsSelectionValid())) {
+        // If content cache hasn't been initialized properly, make the query
+        // failed.
+        MOZ_LOG(sContentCacheLog, LogLevel::Error,
+          ("ContentCacheInParent: 0x%p HandleQueryContentEvent(), "
+           "FAILED because mSelection is not valid", this));
+        return true;
+      }
+      if (aEvent.mInput.mLength) {
+        if (NS_WARN_IF(!GetUnionTextRects(aEvent.mInput.mOffset,
+                                          aEvent.mInput.mLength,
+                                          aEvent.mReply.mRect))) {
+          // XXX We don't have cache for this request.
+          MOZ_LOG(sContentCacheLog, LogLevel::Error,
+            ("ContentCacheInParent: 0x%p HandleQueryContentEvent(), "
+             "FAILED to get union rect", this));
+          return false;
+        }
+      } else {
+        // If the length is 0, we should return caret rect instead.
+        if (NS_WARN_IF(!GetCaretRect(aEvent.mInput.mOffset,
+                                     aEvent.mReply.mRect))) {
+          MOZ_LOG(sContentCacheLog, LogLevel::Error,
+            ("ContentCacheInParent: 0x%p HandleQueryContentEvent(), "
+             "FAILED to get caret rect", this));
+          return false;
+        }
+      }
+      if (aEvent.mInput.mOffset < mText.Length()) {
+        aEvent.mReply.mString =
+          Substring(mText, aEvent.mInput.mOffset,
+                    mText.Length() >= aEvent.mInput.EndOffset() ?
+                      aEvent.mInput.mLength : UINT32_MAX);
+      } else {
+        aEvent.mReply.mString.Truncate(0);
+      }
+      aEvent.mReply.mOffset = aEvent.mInput.mOffset;
+      // XXX This may be wrong if storing range isn't in the selection range.
+      aEvent.mReply.mWritingMode = mSelection.mWritingMode;
+      MOZ_LOG(sContentCacheLog, LogLevel::Info,
+        ("ContentCacheInParent: 0x%p HandleQueryContentEvent(), "
+         "Succeeded, aEvent={ mReply={ mOffset=%u, mString=\"%s\", "
+         "mWritingMode=%s, mRect=%s } }",
+         this, aEvent.mReply.mOffset,
+         NS_ConvertUTF16toUTF8(aEvent.mReply.mString).get(),
+         GetWritingModeName(aEvent.mReply.mWritingMode).get(),
+         GetRectText(aEvent.mReply.mRect).get()));
+      break;
+    case NS_QUERY_CARET_RECT:
+      MOZ_LOG(sContentCacheLog, LogLevel::Info,
+        ("ContentCacheInParent: 0x%p HandleQueryContentEvent("
+         "aEvent={ message=NS_QUERY_CARET_RECT, mInput={ mOffset=%u } }, "
+         "aWidget=0x%p), mText.Length()=%u",
+         this, aEvent.mInput.mOffset, aWidget, mText.Length()));
+      if (NS_WARN_IF(!IsSelectionValid())) {
+        // If content cache hasn't been initialized properly, make the query
+        // failed.
+        MOZ_LOG(sContentCacheLog, LogLevel::Error,
+          ("ContentCacheInParent: 0x%p HandleQueryContentEvent(), "
+           "FAILED because mSelection is not valid", this));
+        return true;
+      }
+      if (NS_WARN_IF(!GetCaretRect(aEvent.mInput.mOffset,
+                                   aEvent.mReply.mRect))) {
+        MOZ_LOG(sContentCacheLog, LogLevel::Error,
+          ("ContentCacheInParent: 0x%p HandleQueryContentEvent(), "
+           "FAILED to get caret rect", this));
+        return false;
+      }
+      aEvent.mReply.mOffset = aEvent.mInput.mOffset;
+      MOZ_LOG(sContentCacheLog, LogLevel::Info,
+        ("ContentCacheInParent: 0x%p HandleQueryContentEvent(), "
+         "Succeeded, aEvent={ mReply={ mOffset=%u, mRect=%s } }",
+         this, aEvent.mReply.mOffset, GetRectText(aEvent.mReply.mRect).get()));
+      break;
+    case NS_QUERY_EDITOR_RECT:
+      MOZ_LOG(sContentCacheLog, LogLevel::Info,
+        ("ContentCacheInParent: 0x%p HandleQueryContentEvent("
+         "aEvent={ message=NS_QUERY_EDITOR_RECT }, aWidget=0x%p)",
+         this, aWidget));
+      aEvent.mReply.mRect = mEditorRect;
+      MOZ_LOG(sContentCacheLog, LogLevel::Info,
+        ("ContentCacheInParent: 0x%p HandleQueryContentEvent(), "
+         "Succeeded, aEvent={ mReply={ mRect=%s } }",
+         this, GetRectText(aEvent.mReply.mRect).get()));
+      break;
+  }
+  aEvent.mSucceeded = true;
+  return true;
+}
+
+bool
+ContentCacheInParent::GetTextRect(uint32_t aOffset,
+                                  LayoutDeviceIntRect& aTextRect) const
 {
   MOZ_LOG(sContentCacheLog, LogLevel::Info,
-    ("ContentCache: 0x%p (mIsChrome=%s) GetTextRect(aOffset=%u), "
+    ("ContentCacheInParent: 0x%p GetTextRect(aOffset=%u), "
      "mTextRectArray={ mStart=%u, mRects.Length()=%u }, "
      "mSelection={ mAnchor=%u, mFocus=%u }",
-     this, GetBoolName(mIsChrome), aOffset, mTextRectArray.mStart,
-     mTextRectArray.mRects.Length(), mSelection.mAnchor, mSelection.mFocus));
+     this, aOffset, mTextRectArray.mStart, mTextRectArray.mRects.Length(),
+     mSelection.mAnchor, mSelection.mFocus));
 
   if (!aOffset) {
     NS_WARN_IF(mFirstCharRect.IsEmpty());
     aTextRect = mFirstCharRect;
     return !aTextRect.IsEmpty();
   }
   if (aOffset == mSelection.mAnchor) {
     NS_WARN_IF(mSelection.mAnchorCharRect.IsEmpty());
@@ -769,27 +710,27 @@ ContentCache::GetTextRect(uint32_t aOffs
     aTextRect.SetEmpty();
     return false;
   }
   aTextRect = mTextRectArray.GetRect(aOffset);
   return true;
 }
 
 bool
-ContentCache::GetUnionTextRects(uint32_t aOffset,
-                                uint32_t aLength,
-                                LayoutDeviceIntRect& aUnionTextRect) const
+ContentCacheInParent::GetUnionTextRects(
+                        uint32_t aOffset,
+                        uint32_t aLength,
+                        LayoutDeviceIntRect& aUnionTextRect) const
 {
   MOZ_LOG(sContentCacheLog, LogLevel::Info,
-    ("ContentCache: 0x%p (mIsChrome=%s) GetUnionTextRects(aOffset=%u, "
+    ("ContentCacheInParent: 0x%p GetUnionTextRects(aOffset=%u, "
      "aLength=%u), mTextRectArray={ mStart=%u, mRects.Length()=%u }, "
      "mSelection={ mAnchor=%u, mFocus=%u }",
-     this, GetBoolName(mIsChrome), aOffset, aLength,
-     mTextRectArray.mStart, mTextRectArray.mRects.Length(),
-     mSelection.mAnchor, mSelection.mFocus));
+     this, aOffset, aLength, mTextRectArray.mStart,
+     mTextRectArray.mRects.Length(), mSelection.mAnchor, mSelection.mFocus));
 
   CheckedInt<uint32_t> endOffset =
     CheckedInt<uint32_t>(aOffset) + aLength;
   if (!endOffset.isValid()) {
     return false;
   }
 
   if (!mSelection.Collapsed() &&
@@ -843,29 +784,28 @@ ContentCache::GetUnionTextRects(uint32_t
   }
   if (aOffset <= mSelection.mFocus && mSelection.mFocus < endOffset.value()) {
     aUnionTextRect = aUnionTextRect.Union(mSelection.mFocusCharRect);
   }
   return !aUnionTextRect.IsEmpty();
 }
 
 bool
-ContentCache::GetCaretRect(uint32_t aOffset,
-                           LayoutDeviceIntRect& aCaretRect) const
+ContentCacheInParent::GetCaretRect(uint32_t aOffset,
+                                   LayoutDeviceIntRect& aCaretRect) const
 {
   MOZ_LOG(sContentCacheLog, LogLevel::Info,
-    ("ContentCache: 0x%p (mIsChrome=%s) GetCaretRect(aOffset=%u), "
+    ("ContentCacheInParent: 0x%p GetCaretRect(aOffset=%u), "
      "mCaret={ mOffset=%u, mRect=%s, IsValid()=%s }, mTextRectArray={ "
      "mStart=%u, mRects.Length()=%u }, mSelection={ mAnchor=%u, mFocus=%u, "
      "mWritingMode=%s, mAnchorCharRect=%s, mFocusCharRect=%s }, "
      "mFirstCharRect=%s",
-     this, GetBoolName(mIsChrome), aOffset, mCaret.mOffset,
-     GetRectText(mCaret.mRect).get(), GetBoolName(mCaret.IsValid()),
-     mTextRectArray.mStart, mTextRectArray.mRects.Length(),
-     mSelection.mAnchor, mSelection.mFocus,
+     this, aOffset, mCaret.mOffset, GetRectText(mCaret.mRect).get(),
+     GetBoolName(mCaret.IsValid()), mTextRectArray.mStart,
+     mTextRectArray.mRects.Length(), mSelection.mAnchor, mSelection.mFocus,
      GetWritingModeName(mSelection.mWritingMode).get(),
      GetRectText(mSelection.mAnchorCharRect).get(),
      GetRectText(mSelection.mFocusCharRect).get(),
      GetRectText(mFirstCharRect).get()));
 
   if (mCaret.IsValid() && mCaret.mOffset == aOffset) {
     aCaretRect = mCaret.mRect;
     return true;
@@ -895,31 +835,27 @@ ContentCache::GetCaretRect(uint32_t aOff
     aCaretRect.height = mCaret.IsValid() ? mCaret.mRect.height : 1;
   } else {
     aCaretRect.width = mCaret.IsValid() ? mCaret.mRect.width : 1;
   }
   return true;
 }
 
 bool
-ContentCache::OnCompositionEvent(const WidgetCompositionEvent& aEvent)
+ContentCacheInParent::OnCompositionEvent(const WidgetCompositionEvent& aEvent)
 {
   MOZ_LOG(sContentCacheLog, LogLevel::Info,
-    ("ContentCache: 0x%p (mIsChrome=%s) OnCompositionEvent(aEvent={ "
+    ("ContentCacheInParent: 0x%p OnCompositionEvent(aEvent={ "
      "message=%s, mData=\"%s\" (Length()=%u), mRanges->Length()=%u }), "
      "mIsComposing=%s, mRequestedToCommitOrCancelComposition=%s",
-     this, GetBoolName(mIsChrome), GetEventMessageName(aEvent.message),
+     this, GetEventMessageName(aEvent.message),
      NS_ConvertUTF16toUTF8(aEvent.mData).get(), aEvent.mData.Length(),
      aEvent.mRanges ? aEvent.mRanges->Length() : 0, GetBoolName(mIsComposing),
      GetBoolName(mRequestedToCommitOrCancelComposition)));
 
-  if (NS_WARN_IF(!mIsChrome)) {
-    return false;
-  }
-
   if (!aEvent.CausesDOMTextEvent()) {
     MOZ_ASSERT(aEvent.message == NS_COMPOSITION_START);
     mIsComposing = !aEvent.CausesDOMCompositionEndEvent();
     mCompositionStart = mSelection.StartOffset();
     // XXX What's this case??
     if (mRequestedToCommitOrCancelComposition) {
       mCommitStringByRequest = aEvent.mData;
       mCompositionEventsDuringRequest++;
@@ -948,47 +884,42 @@ ContentCache::OnCompositionEvent(const W
   if (!mIsComposing) {
     mCompositionStart = mSelection.StartOffset();
   }
   mIsComposing = !aEvent.CausesDOMCompositionEndEvent();
   return true;
 }
 
 uint32_t
-ContentCache::RequestToCommitComposition(nsIWidget* aWidget,
-                                         bool aCancel,
-                                         nsAString& aLastString)
+ContentCacheInParent::RequestToCommitComposition(nsIWidget* aWidget,
+                                                 bool aCancel,
+                                                 nsAString& aLastString)
 {
   MOZ_LOG(sContentCacheLog, LogLevel::Info,
-    ("ContentCache: 0x%p (mIsChrome=%s) RequestToCommitComposition(aWidget=%p, "
+    ("ContentCacheInParent: 0x%p RequestToCommitComposition(aWidget=%p, "
      "aCancel=%s), mIsComposing=%s, mRequestedToCommitOrCancelComposition=%s, "
      "mCompositionEventsDuringRequest=%u",
-     this, GetBoolName(mIsChrome), aWidget, GetBoolName(aCancel),
-     GetBoolName(mIsComposing),
+     this, aWidget, GetBoolName(aCancel), GetBoolName(mIsComposing),
      GetBoolName(mRequestedToCommitOrCancelComposition),
      mCompositionEventsDuringRequest));
 
-  if (NS_WARN_IF(!mIsChrome)) {
-    return 0;
-  }
-
   mRequestedToCommitOrCancelComposition = true;
   mCompositionEventsDuringRequest = 0;
 
   aWidget->NotifyIME(IMENotification(aCancel ? REQUEST_TO_CANCEL_COMPOSITION :
                                                REQUEST_TO_COMMIT_COMPOSITION));
 
   mRequestedToCommitOrCancelComposition = false;
   aLastString = mCommitStringByRequest;
   mCommitStringByRequest.Truncate(0);
   return mCompositionEventsDuringRequest;
 }
 
 void
-ContentCache::InitNotification(IMENotification& aNotification) const
+ContentCacheInParent::InitNotification(IMENotification& aNotification) const
 {
   if (NS_WARN_IF(aNotification.mMessage != NOTIFY_IME_OF_SELECTION_CHANGE)) {
     return;
   }
   aNotification.mSelectionChangeData.mOffset = mSelection.StartOffset();
   aNotification.mSelectionChangeData.mLength = mSelection.Length();
   aNotification.mSelectionChangeData.mReversed = mSelection.Reversed();
   aNotification.mSelectionChangeData.SetWritingMode(mSelection.mWritingMode);
--- a/widget/ContentCache.h
+++ b/widget/ContentCache.h
@@ -21,147 +21,35 @@
 class nsIWidget;
 
 namespace mozilla {
 
 namespace widget {
 struct IMENotification;
 }
 
+class ContentCacheInParent;
+
 /**
- * ContentCache stores various information of the child content both on
- * PuppetWidget (child process) and TabParent (chrome process).
- * When PuppetWidget receives some notifications of content state change,
- * Cache*() are called.  Then, stored data is modified for the latest content
- * in PuppetWidget.  After that, PuppetWidget sends the ContentCache to
- * TabParent.  In this time, TabParent stores the latest content data with
- * AssignContent().
+ * ContentCache stores various information of the child content.
+ * This class has members which are necessary both in parent process and
+ * content process.
  */
 
-class ContentCache final
+class ContentCache
 {
 public:
   typedef InfallibleTArray<LayoutDeviceIntRect> RectArray;
   typedef widget::IMENotification IMENotification;
 
   ContentCache();
 
-  /**
-   * When IME loses focus, this should be called and making this forget the
-   * content for reducing footprint.
-   * This must be called in content process.
-   */
-  void Clear();
-
-  /**
-   * AssignContent() is called when TabParent receives ContentCache from
-   * the content process.  This doesn't copy composition information because
-   * it's managed by TabParent itself.
-   * This must be called in chrome process.
-   */
-  void AssignContent(const ContentCache& aOther,
-                     const IMENotification* aNotification = nullptr);
-
-  /**
-   * HandleQueryContentEvent() sets content data to aEvent.mReply.
-   * This must be called in chrome process.
-   *
-   * For NS_QUERY_SELECTED_TEXT, fail if the cache doesn't contain the whole
-   *  selected range. (This shouldn't happen because PuppetWidget should have
-   *  already sent the whole selection.)
-   *
-   * For NS_QUERY_TEXT_CONTENT, fail only if the cache doesn't overlap with
-   *  the queried range. Note the difference from above. We use
-   *  this behavior because a normal NS_QUERY_TEXT_CONTENT event is allowed to
-   *  have out-of-bounds offsets, so that widget can request content without
-   *  knowing the exact length of text. It's up to widget to handle cases when
-   *  the returned offset/length are different from the queried offset/length.
-   *
-   * For NS_QUERY_TEXT_RECT, fail if cached offset/length aren't equals to input.
-   *   Cocoa widget always queries selected offset, so it works on it.
-   *
-   * For NS_QUERY_CARET_RECT, fail if cached offset isn't equals to input
-   *
-   * For NS_QUERY_EDITOR_RECT, always success
-   */
-  bool HandleQueryContentEvent(WidgetQueryContentEvent& aEvent,
-                               nsIWidget* aWidget) const;
-
-  /**
-   * Cache*() retrieves the latest content information and store them.
-   * Be aware, CacheSelection() calls CacheTextRects(), and also CacheText()
-   * calls CacheSelection().  So, related data is also retrieved automatically.
-   * These methods must be called in content process.
-   */
-  bool CacheEditorRect(nsIWidget* aWidget,
-                       const IMENotification* aNotification = nullptr);
-  bool CacheSelection(nsIWidget* aWidget,
-                      const IMENotification* aNotification = nullptr);
-  bool CacheText(nsIWidget* aWidget,
-                 const IMENotification* aNotification = nullptr);
-
-  bool CacheAll(nsIWidget* aWidget,
-                const IMENotification* aNotification = nullptr);
-
-  /**
-   * OnCompositionEvent() should be called before sending composition string.
-   * This returns true if the event should be sent.  Otherwise, false.
-   * This must be called in chrome process.
-   */
-  bool OnCompositionEvent(const WidgetCompositionEvent& aCompositionEvent);
-  /**
-   * RequestToCommitComposition() requests to commit or cancel composition to
-   * the widget.  If it's handled synchronously, this returns the number of
-   * composition events after that.
-   * This must be called in chrome process.
-   *
-   * @param aWidget     The widget to be requested to commit or cancel
-   *                    the composition.
-   * @param aCancel     When the caller tries to cancel the composition, true.
-   *                    Otherwise, i.e., tries to commit the composition, false.
-   * @param aLastString The last composition string before requesting to
-   *                    commit or cancel composition.
-   * @return            The count of composition events ignored after a call of
-   *                    WillRequestToCommitOrCancelComposition().
-   */
-  uint32_t RequestToCommitComposition(nsIWidget* aWidget,
-                                      bool aCancel,
-                                      nsAString& aLastString);
-
-  /**
-   * InitNotification() initializes aNotification with stored data.
-   *
-   * @param aNotification       Must be NOTIFY_IME_OF_SELECTION_CHANGE.
-   */
-  void InitNotification(IMENotification& aNotification) const;
-
-  /**
-   * SetSelection() modifies selection with specified raw data. And also this
-   * tries to retrieve text rects too.
-   * This must be called in content process.
-   */
-  void SetSelection(nsIWidget* aWidget,
-                    uint32_t aStartOffset,
-                    uint32_t aLength,
-                    bool aReversed,
-                    const WritingMode& aWritingMode);
-
-private:
+protected:
   // Whole text in the target
   nsString mText;
-  // This is commit string which is caused by our request.
-  // This value is valid only in chrome process.
-  nsString mCommitStringByRequest;
-  // Start offset of the composition string.
-  // This value is valid only in chrome process.
-  uint32_t mCompositionStart;
-  // Count of composition events during requesting commit or cancel the
-  // composition.
-  // This value is valid only in chrome process.
-  uint32_t mCompositionEventsDuringRequest;
 
   struct Selection final
   {
     // Following values are offset in "flat text".
     uint32_t mAnchor;
     uint32_t mFocus;
 
     WritingMode mWritingMode;
@@ -328,35 +216,150 @@ private:
     LayoutDeviceIntRect GetRect(uint32_t aOffset) const;
     LayoutDeviceIntRect GetUnionRect(uint32_t aOffset, uint32_t aLength) const;
     LayoutDeviceIntRect GetUnionRectAsFarAsPossible(uint32_t aOffset,
                                                     uint32_t aLength) const;
   } mTextRectArray;
 
   LayoutDeviceIntRect mEditorRect;
 
-  // mIsComposing is valid only in chrome process.
-  bool mIsComposing;
-  // mRequestedToCommitOrCancelComposition is valid only in chrome process.
-  bool mRequestedToCommitOrCancelComposition;
-  bool mIsChrome;
+  friend class ContentCacheInParent;
+  friend struct IPC::ParamTraits<ContentCache>;
+};
+
+class ContentCacheInChild final : public ContentCache
+{
+public:
+  ContentCacheInChild();
+
+  /**
+   * When IME loses focus, this should be called and making this forget the
+   * content for reducing footprint.
+   */
+  void Clear();
 
+  /**
+   * Cache*() retrieves the latest content information and store them.
+   * Be aware, CacheSelection() calls CacheTextRects(), and also CacheText()
+   * calls CacheSelection().  So, related data is also retrieved automatically.
+   */
+  bool CacheEditorRect(nsIWidget* aWidget,
+                       const IMENotification* aNotification = nullptr);
+  bool CacheSelection(nsIWidget* aWidget,
+                      const IMENotification* aNotification = nullptr);
+  bool CacheText(nsIWidget* aWidget,
+                 const IMENotification* aNotification = nullptr);
+
+  bool CacheAll(nsIWidget* aWidget,
+                const IMENotification* aNotification = nullptr);
+
+  /**
+   * SetSelection() modifies selection with specified raw data. And also this
+   * tries to retrieve text rects too.
+   */
+  void SetSelection(nsIWidget* aWidget,
+                    uint32_t aStartOffset,
+                    uint32_t aLength,
+                    bool aReversed,
+                    const WritingMode& aWritingMode);
+
+private:
   bool QueryCharRect(nsIWidget* aWidget,
                      uint32_t aOffset,
                      LayoutDeviceIntRect& aCharRect) const;
   bool CacheCaret(nsIWidget* aWidget,
                   const IMENotification* aNotification = nullptr);
   bool CacheTextRects(nsIWidget* aWidget,
                       const IMENotification* aNotification = nullptr);
+};
+
+class ContentCacheInParent final : public ContentCache
+{
+public:
+  ContentCacheInParent();
+
+  /**
+   * 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,
+                     const IMENotification* aNotification = nullptr);
+
+  /**
+   * HandleQueryContentEvent() sets content data to aEvent.mReply.
+   *
+   * For NS_QUERY_SELECTED_TEXT, fail if the cache doesn't contain the whole
+   *  selected range. (This shouldn't happen because PuppetWidget should have
+   *  already sent the whole selection.)
+   *
+   * For NS_QUERY_TEXT_CONTENT, fail only if the cache doesn't overlap with
+   *  the queried range. Note the difference from above. We use
+   *  this behavior because a normal NS_QUERY_TEXT_CONTENT event is allowed to
+   *  have out-of-bounds offsets, so that widget can request content without
+   *  knowing the exact length of text. It's up to widget to handle cases when
+   *  the returned offset/length are different from the queried offset/length.
+   *
+   * For NS_QUERY_TEXT_RECT, fail if cached offset/length aren't equals to input.
+   *   Cocoa widget always queries selected offset, so it works on it.
+   *
+   * For NS_QUERY_CARET_RECT, fail if cached offset isn't equals to input
+   *
+   * For NS_QUERY_EDITOR_RECT, always success
+   */
+  bool HandleQueryContentEvent(WidgetQueryContentEvent& aEvent,
+                               nsIWidget* aWidget) const;
+
+  /**
+   * OnCompositionEvent() should be called before sending composition string.
+   * This returns true if the event should be sent.  Otherwise, false.
+   */
+  bool OnCompositionEvent(const WidgetCompositionEvent& aCompositionEvent);
+
+  /**
+   * RequestToCommitComposition() requests to commit or cancel composition to
+   * the widget.  If it's handled synchronously, this returns the number of
+   * composition events after that.
+   *
+   * @param aWidget     The widget to be requested to commit or cancel
+   *                    the composition.
+   * @param aCancel     When the caller tries to cancel the composition, true.
+   *                    Otherwise, i.e., tries to commit the composition, false.
+   * @param aLastString The last composition string before requesting to
+   *                    commit or cancel composition.
+   * @return            The count of composition events ignored after a call of
+   *                    WillRequestToCommitOrCancelComposition().
+   */
+  uint32_t RequestToCommitComposition(nsIWidget* aWidget,
+                                      bool aCancel,
+                                      nsAString& aLastString);
+
+  /**
+   * InitNotification() initializes aNotification with stored data.
+   *
+   * @param aNotification       Must be NOTIFY_IME_OF_SELECTION_CHANGE.
+   */
+  void InitNotification(IMENotification& aNotification) const;
+
+private:
+  // This is commit string which is caused by our request.
+  nsString mCommitStringByRequest;
+  // Start offset of the composition string.
+  uint32_t mCompositionStart;
+  // Count of composition events during requesting commit or cancel the
+  // composition.
+  uint32_t mCompositionEventsDuringRequest;
+
+  bool mIsComposing;
+  bool mRequestedToCommitOrCancelComposition;
 
   bool GetCaretRect(uint32_t aOffset, LayoutDeviceIntRect& aCaretRect) const;
   bool GetTextRect(uint32_t aOffset,
                    LayoutDeviceIntRect& aTextRect) const;
   bool GetUnionTextRects(uint32_t aOffset,
                          uint32_t aLength,
                          LayoutDeviceIntRect& aUnionTextRect) const;
 
-  friend struct IPC::ParamTraits<ContentCache>;
 };
 
 } // namespace mozilla
 
 #endif // mozilla_ContentCache_h
--- a/widget/PuppetWidget.h
+++ b/widget/PuppetWidget.h
@@ -308,17 +308,17 @@ private:
   nsIntRegion mDirtyRegion;
   nsRevocableEventPtr<PaintTask> mPaintTask;
   nsRefPtr<MemoryPressureObserver> mMemoryPressureObserver;
   // XXX/cjones: keeping this around until we teach LayerManager to do
   // retained-content-only transactions
   mozilla::RefPtr<DrawTarget> mDrawTarget;
   // IME
   nsIMEUpdatePreference mIMEPreferenceOfParent;
-  ContentCache mContentCache;
+  ContentCacheInChild mContentCache;
   bool mNeedIMEStateInit;
 
   // The DPI of the screen corresponding to this widget
   float mDPI;
   double mDefaultScale;
 
   // Precomputed answers for ExecuteNativeKeyBinding
   bool mNativeKeyCommandsValid;