Merge fx-team to m-c. a=merge
authorRyan VanderMeulen <ryanvm@gmail.com>
Fri, 29 Aug 2014 15:10:18 -0400
changeset 224013 8fdcd7e6ecb252f7168d69909884f55d874fff4e
parent 224003 11e4f1678eaba483e926440ab2ef8fe0e0dde99e (diff)
parent 224012 8f49394f80690a8b605e9363b19b12450e11da47 (current diff)
child 224014 9b3fbc3706311126d788897df0445908d52365e1
push id3979
push userraliiev@mozilla.com
push dateMon, 13 Oct 2014 16:35:44 +0000
treeherdermozilla-beta@30f2cc610691 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone34.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
Merge fx-team to m-c. a=merge
--- a/build/automationutils.py
+++ b/build/automationutils.py
@@ -26,19 +26,33 @@ import mozinfo
   "getDebuggerInfo",
   "DEBUGGER_INFO",
   "replaceBackSlashes",
   'KeyValueParseError',
   'parseKeyValue',
   'systemMemory',
   'environment',
   'dumpScreen',
-  "ShutdownLeaks"
+  "ShutdownLeaks",
+  "setAutomationLog",
   ]
 
+log = logging.getLogger()
+def resetGlobalLog():
+  while log.handlers:
+    log.removeHandler(log.handlers[0])
+  handler = logging.StreamHandler(sys.stdout)
+  log.setLevel(logging.INFO)
+  log.addHandler(handler)
+resetGlobalLog()
+
+def setAutomationLog(alt_logger):
+  global log
+  log = alt_logger
+
 # Map of debugging programs to information about them, like default arguments
 # and whether or not they are interactive.
 DEBUGGER_INFO = {
   # gdb requires that you supply the '--args' flag in order to pass arguments
   # after the executable name to the executable.
   "gdb": {
     "interactive": True,
     "args": "-q --args"
@@ -139,18 +153,16 @@ class ZipFileReader(object):
     if hasattr(self._zipfile, "extractall"):
       return self._zipfile.extractall(path)
 
     path = self._getnormalizedpath(path)
 
     for name in self._zipfile.namelist():
       self._extractname(name, path)
 
-log = logging.getLogger()
-
 def isURL(thing):
   """Return True if |thing| looks like a URL."""
   # We want to download URLs like http://... but not Windows paths like c:\...
   return len(urlparse(thing).scheme) >= 2
 
 # Python does not provide strsignal() even in the very latest 3.x.
 # This is a reasonable fake.
 def strsig(n):
@@ -495,19 +507,19 @@ def environment(xrePath, env=None, crash
   # ASan specific environment stuff
   asan = bool(mozinfo.info.get("asan"))
   if asan and (mozinfo.isLinux or mozinfo.isMac):
     try:
       # Symbolizer support
       llvmsym = os.path.join(xrePath, "llvm-symbolizer")
       if os.path.isfile(llvmsym):
         env["ASAN_SYMBOLIZER_PATH"] = llvmsym
-        log.info("INFO | runtests.py | ASan using symbolizer at %s", llvmsym)
+        log.info("INFO | runtests.py | ASan using symbolizer at %s" % llvmsym)
       else:
-        log.info("TEST-UNEXPECTED-FAIL | runtests.py | Failed to find ASan symbolizer at %s", llvmsym)
+        log.info("TEST-UNEXPECTED-FAIL | runtests.py | Failed to find ASan symbolizer at %s" % llvmsym)
 
       totalMemory = systemMemory()
 
       # Only 4 GB RAM or less available? Use custom ASan options to reduce
       # the amount of resources required to do the tests. Standard options
       # will otherwise lead to OOM conditions on the current test slaves.
       message = "INFO | runtests.py | ASan running in %s configuration"
       asanOptions = []
@@ -530,17 +542,17 @@ def environment(xrePath, env=None, crash
         env["LSAN_OPTIONS"] = ':'.join(lsanOptions)
         # Run shutdown GCs and CCs to avoid spurious leaks.
         env['MOZ_CC_RUN_DURING_SHUTDOWN'] = '1'
 
       if len(asanOptions):
         env['ASAN_OPTIONS'] = ':'.join(asanOptions)
 
     except OSError,err:
-      log.info("Failed determine available memory, disabling ASan low-memory configuration: %s", err.strerror)
+      log.info("Failed determine available memory, disabling ASan low-memory configuration: %s" % err.strerror)
     except:
       log.info("Failed determine available memory, disabling ASan low-memory configuration")
     else:
       log.info(message)
 
   return env
 
 def dumpScreen(utilityPath):
@@ -566,17 +578,17 @@ def dumpScreen(utilityPath):
 
   # Run the capture
   try:
     tmpfd, imgfilename = tempfile.mkstemp(prefix='mozilla-test-fail-screenshot_', suffix='.png', dir=parent_dir)
     os.close(tmpfd)
     returncode = subprocess.call(utility + [imgfilename])
     printstatus(returncode, utilityname)
   except OSError, err:
-    log.info("Failed to start %s for screenshot: %s",
+    log.info("Failed to start %s for screenshot: %s" %
              utility[0], err.strerror)
     return
 
 class ShutdownLeaks(object):
   """
   Parses the mochitest run log when running a debug build, assigns all leaked
   DOM windows (that are still around after test suite shutdown, despite running
   the GC) to the tests that created them and prints leak statistics.
--- a/build/sanitizers/lsan_suppressions.txt
+++ b/build/sanitizers/lsan_suppressions.txt
@@ -31,51 +31,21 @@ leak:GI___strdup
 ### Bug 979928 - WebRTC leaks. m2, m3.
 ###
 
 # WebRTC leaks added for Mochitest 2.
 leak:NR_reg_init
 # nr_reg_local_init should be redundant with NR_reg_init, but with 34 on Aurora
 # we get less stack frames for some reason.
 leak:nr_reg_local_init
-leak:fsmdef_init
 leak:r_log_register
 leak:nr_reg_set
-leak:ccsnap_device_init
-leak:ccsnap_line_init
-leak:media/webrtc/signaling/src/sipcc/core/common/init.c
-leak:cprPostMessage
-leak:mozilla::NrIceStunServer::Create
 
 # Additional WebRTC leak suppressions added for Mochitest 3.
 leak:mozilla::TransportLayerDtls::Setup
-leak:mozilla::NrIceTurnServer::Create
-# There are about 228KB of leaks from the call to |pmsg->sdp = cpr_malloc(sdp_size);|
-# in send_message_helper.
-leak:send_message_helper
-leak:fsmdef_ev_createoffer
-leak:fsmdef_ev_setremotedesc
-leak:fsmdef_ev_setlocaldesc
-leak:fsmdef_ev_createanswer
-# About 70KB of leaks under this stack.
-leak:vcmRxAllocICE_s
-leak:vcmRxStartICE_m
-# About 50KB of leaks under this stack.
-leak:ccsnap_EscapeStrToLocaleStr
-leak:gsmsdp_add_default_audio_formats_to_local_sdp
-leak:gsmsdp_add_default_video_formats_to_local_sdp
-leak:CCAPI_CallInfo_getMediaStreams
-
-# Intermittent Mochitest 3 WebRTC leaks, as seen in bug 1055910.
-leak:sdp_build_
-leak:VcmSIPCCBinding::CandidateReady
-leak:fsmdef_ev_foundcandidate
-leak:create_timecard
-leak:stamp_timecard
-
 
 ###
 ### Many leaks only affect some test suites.  The suite annotations are not checked.
 ###
 
 # Bug 981195 - Small leak in the parser. m4
 leak:TypeCompartment::fixObjectType
 
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -1239,19 +1239,22 @@ GK_ATOM(amplitude, "amplitude")
 GK_ATOM(animate, "animate")
 GK_ATOM(animateColor, "animateColor")
 GK_ATOM(animateMotion, "animateMotion")
 GK_ATOM(animateTransform, "animateTransform")
 GK_ATOM(arithmetic, "arithmetic")
 GK_ATOM(atop, "atop")
 GK_ATOM(azimuth, "azimuth")
 GK_ATOM(B, "B")
+GK_ATOM(backgroundColor, "background-color")
+GK_ATOM(background_image, "background-image")
 GK_ATOM(baseFrequency, "baseFrequency")
 GK_ATOM(baseline_shift, "baseline-shift")
 GK_ATOM(bias, "bias")
+GK_ATOM(caption_side, "caption-side")
 GK_ATOM(clip_path, "clip-path")
 GK_ATOM(clip_rule, "clip-rule")
 GK_ATOM(clipPath, "clipPath")
 GK_ATOM(clipPathUnits, "clipPathUnits")
 GK_ATOM(cm, "cm")
 GK_ATOM(colorInterpolation, "color-interpolation")
 GK_ATOM(colorInterpolationFilters, "color-interpolation-filters")
 GK_ATOM(colorProfile, "color-profile")
@@ -1309,16 +1312,17 @@ GK_ATOM(feTurbulence, "feTurbulence")
 GK_ATOM(fill, "fill")
 GK_ATOM(fill_opacity, "fill-opacity")
 GK_ATOM(fill_rule, "fill-rule")
 GK_ATOM(filter, "filter")
 // Parsing for filterRes may be removed in the future.
 // https://bugzilla.mozilla.org/show_bug.cgi?id=979472
 GK_ATOM(filterRes, "filterRes")
 GK_ATOM(filterUnits, "filterUnits")
+GK_ATOM(_float, "float")
 GK_ATOM(flood_color, "flood-color")
 GK_ATOM(flood_opacity, "flood-opacity")
 GK_ATOM(font_face, "font-face")
 GK_ATOM(font_face_format, "font-face-format")
 GK_ATOM(font_face_name, "font-face-name")
 GK_ATOM(font_face_src, "font-face-src")
 GK_ATOM(font_face_uri, "font-face-uri")
 GK_ATOM(font_family, "font-family")
@@ -1360,16 +1364,17 @@ GK_ATOM(kernelUnitLength, "kernelUnitLen
 GK_ATOM(lengthAdjust, "lengthAdjust")
 GK_ATOM(letter_spacing, "letter-spacing")
 GK_ATOM(lighten, "lighten")
 GK_ATOM(lighting_color, "lighting-color")
 GK_ATOM(limitingConeAngle, "limitingConeAngle")
 GK_ATOM(linear, "linear")
 GK_ATOM(linearGradient, "linearGradient")
 GK_ATOM(linearRGB, "linearRGB")
+GK_ATOM(list_style_type, "list-style-type")
 GK_ATOM(luminanceToAlpha, "luminanceToAlpha")
 GK_ATOM(magnify, "magnify")
 GK_ATOM(marker, "marker")
 GK_ATOM(marker_end, "marker-end")
 GK_ATOM(marker_mid, "marker-mid")
 GK_ATOM(marker_start, "marker-start")
 GK_ATOM(markerHeight, "markerHeight")
 GK_ATOM(markerUnits, "markerUnits")
@@ -1475,29 +1480,31 @@ GK_ATOM(tref, "tref")
 GK_ATOM(tspan, "tspan")
 GK_ATOM(turbulence, "turbulence")
 GK_ATOM(unicode_bidi, "unicode-bidi")
 GK_ATOM(userSpaceOnUse, "userSpaceOnUse")
 GK_ATOM(view, "view")
 GK_ATOM(viewBox, "viewBox")
 GK_ATOM(viewTarget, "viewTarget")
 GK_ATOM(vkern, "vkern")
+GK_ATOM(white_space, "white-space")
 GK_ATOM(word_spacing, "word-spacing")
 GK_ATOM(x, "x")
 GK_ATOM(x1, "x1")
 GK_ATOM(x2, "x2")
 GK_ATOM(xChannelSelector, "xChannelSelector")
 GK_ATOM(xor_, "xor")
 GK_ATOM(y, "y")
 GK_ATOM(y1, "y1")
 GK_ATOM(y2, "y2")
 GK_ATOM(yChannelSelector, "yChannelSelector")
 GK_ATOM(z, "z")
 GK_ATOM(zoomAndPan, "zoomAndPan")
 GK_ATOM(vector_effect, "vector-effect")
+GK_ATOM(vertical_align, "vertical-align")
 
 GK_ATOM(accumulate, "accumulate")
 GK_ATOM(additive, "additive")
 GK_ATOM(attributeName, "attributeName")
 GK_ATOM(attributeType, "attributeType")
 GK_ATOM(auto_reverse, "auto-reverse")
 GK_ATOM(begin, "begin")
 GK_ATOM(beginEvent, "beginEvent")
@@ -2198,17 +2205,16 @@ GK_ATOM(aria_selected, "aria-selected")
 GK_ATOM(aria_setsize, "aria-setsize")
 GK_ATOM(aria_sort, "aria-sort")
 GK_ATOM(aria_valuenow, "aria-valuenow")
 GK_ATOM(aria_valuemin, "aria-valuemin")
 GK_ATOM(aria_valuemax, "aria-valuemax")
 GK_ATOM(aria_valuetext, "aria-valuetext")
 GK_ATOM(AreaFrame, "AreaFrame")
 GK_ATOM(auto_generated, "auto-generated")
-GK_ATOM(backgroundColor, "background-color")
 GK_ATOM(checkable, "checkable")
 GK_ATOM(choices, "choices")
 GK_ATOM(columnheader, "columnheader")
 GK_ATOM(containerAtomic, "container-atomic")
 GK_ATOM(containerBusy, "container-busy")
 GK_ATOM(containerLive, "container-live")
 GK_ATOM(containerLiveRole, "container-live-role")
 GK_ATOM(containerRelevant, "container-relevant")
--- a/content/media/DecoderTraits.cpp
+++ b/content/media/DecoderTraits.cpp
@@ -43,16 +43,20 @@
 #include "nsIPrincipal.h"
 #include "mozilla/dom/HTMLMediaElement.h"
 #if ANDROID_VERSION >= 18
 #include "MediaCodecDecoder.h"
 #include "MediaCodecReader.h"
 #endif
 #endif
 #ifdef NECKO_PROTOCOL_rtsp
+#if ANDROID_VERSION >= 18
+#include "RtspMediaCodecDecoder.h"
+#include "RtspMediaCodecReader.h"
+#endif
 #include "RtspOmxDecoder.h"
 #include "RtspOmxReader.h"
 #endif
 #ifdef MOZ_WMF
 #include "WMFDecoder.h"
 #include "WMFReader.h"
 #endif
 #ifdef MOZ_DIRECTSHOW
@@ -550,17 +554,23 @@ InstantiateDecoder(const nsACString& aTy
 #else
     decoder = new MediaOmxDecoder();
 #endif
     return decoder.forget();
   }
 #endif
 #ifdef NECKO_PROTOCOL_rtsp
   if (IsRtspSupportedType(aType)) {
+#if ANDROID_VERSION >= 18
+    decoder = MediaDecoder::IsOmxAsyncEnabled()
+      ? static_cast<MediaDecoder*>(new RtspMediaCodecDecoder())
+      : static_cast<MediaDecoder*>(new RtspOmxDecoder());
+#else
     decoder = new RtspOmxDecoder();
+#endif
     return decoder.forget();
   }
 #endif
 #ifdef MOZ_ANDROID_OMX
   if (MediaDecoder::IsAndroidMediaEnabled() &&
       GetAndroidMediaPluginHost()->FindDecoder(aType, nullptr)) {
     decoder = new AndroidMediaDecoder(aType);
     return decoder.forget();
--- a/content/media/omx/MediaCodecDecoder.cpp
+++ b/content/media/omx/MediaCodecDecoder.cpp
@@ -1,18 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* 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 "MediaCodecDecoder.h"
 
-#include <stagefright/MediaSource.h>
-
 #include "MediaCodecReader.h"
 #include "MediaDecoderStateMachine.h"
 
 namespace mozilla {
 
 MediaDecoder*
 MediaCodecDecoder::Clone()
 {
--- a/content/media/omx/MediaCodecReader.cpp
+++ b/content/media/omx/MediaCodecReader.cpp
@@ -191,16 +191,17 @@ MediaCodecReader::CodecBufferInfo::Codec
   , mTimeUs(0)
   , mFlags(0)
 {
 }
 
 MediaCodecReader::MediaCodecReader(AbstractMediaDecoder* aDecoder)
   : MediaOmxCommonReader(aDecoder)
   , mColorConverterBufferSize(0)
+  , mExtractor(nullptr)
 {
   mHandler = new MessageHandler(this);
   mVideoListener = new VideoResourceListener(this);
 }
 
 MediaCodecReader::~MediaCodecReader()
 {
   MOZ_ASSERT(NS_IsMainThread(), "Should be on main thread.");
--- a/content/media/omx/MediaCodecReader.h
+++ b/content/media/omx/MediaCodecReader.h
@@ -128,16 +128,20 @@ protected:
   // Called on MediaCodecReader::mLooper thread.
   void onMessageReceived(const android::sp<android::AMessage>& aMessage);
 
   // Receive a notify from ResourceListener.
   // Called on Binder thread.
   virtual void codecReserved(Track& aTrack);
   virtual void codecCanceled(Track& aTrack);
 
+  virtual bool CreateExtractor();
+
+  android::sp<android::MediaExtractor> mExtractor;
+
 private:
   // An intermediary class that can be managed by android::sp<T>.
   // Redirect onMessageReceived() to MediaCodecReader.
   class MessageHandler : public android::AHandler
   {
   public:
     MessageHandler(MediaCodecReader* aReader);
     ~MessageHandler();
@@ -219,17 +223,16 @@ private:
 
   bool ReallocateResources();
   void ReleaseCriticalResources();
   void ReleaseResources();
 
   bool CreateLooper();
   void DestroyLooper();
 
-  bool CreateExtractor();
   void DestroyExtractor();
 
   bool CreateMediaSources();
   void DestroyMediaSources();
 
   bool CreateMediaCodecs();
   static bool CreateMediaCodec(android::sp<android::ALooper>& aLooper,
                                Track& aTrack,
@@ -271,17 +274,16 @@ private:
 
   uint8_t* GetColorConverterBuffer(int32_t aWidth, int32_t aHeight);
   void ClearColorConverterBuffer();
 
   android::sp<MessageHandler> mHandler;
   android::sp<VideoResourceListener> mVideoListener;
 
   android::sp<android::ALooper> mLooper;
-  android::sp<android::MediaExtractor> mExtractor;
 
   // media tracks
   AudioTrack mAudioTrack;
   VideoTrack mVideoTrack;
   AudioTrack mAudioOffloadTrack; // only Track::mSource is valid
 
   // color converter
   android::I420ColorConverterHelper mColorConverter;
--- a/content/media/omx/MediaOmxCommonDecoder.cpp
+++ b/content/media/omx/MediaOmxCommonDecoder.cpp
@@ -35,16 +35,18 @@ MediaOmxCommonDecoder::MediaOmxCommonDec
 {
 #ifdef PR_LOGGING
   if (!gMediaDecoderLog) {
     gMediaDecoderLog = PR_NewLogModule("MediaDecoder");
   }
 #endif
 }
 
+MediaOmxCommonDecoder::~MediaOmxCommonDecoder() {}
+
 void
 MediaOmxCommonDecoder::SetPlatformCanOffloadAudio(bool aCanOffloadAudio)
 {
   ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
   mCanOffloadAudio = aCanOffloadAudio;
 }
 
 bool
--- a/content/media/omx/MediaOmxCommonDecoder.h
+++ b/content/media/omx/MediaOmxCommonDecoder.h
@@ -40,16 +40,17 @@ public:
   void AudioOffloadTearDown();
 
   virtual MediaDecoderStateMachine* CreateStateMachine();
 
   virtual MediaOmxCommonReader* CreateReader() = 0;
   virtual MediaDecoderStateMachine* CreateStateMachine(MediaOmxCommonReader* aReader) = 0;
 
 protected:
+  virtual ~MediaOmxCommonDecoder();
   void PauseStateMachine();
   void ResumeStateMachine();
 
   MediaOmxCommonReader* mReader;
 
   // Offloaded audio track
   android::sp<android::MediaSource> mAudioTrack;
 
new file mode 100644
--- /dev/null
+++ b/content/media/omx/RtspExtractor.cpp
@@ -0,0 +1,221 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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 "RtspExtractor.h"
+
+#include "mozilla/ReentrantMonitor.h"
+
+using namespace android;
+
+#define FRAME_DEFAULT_SIZE 1024
+
+namespace mozilla {
+
+/* class RtspMediaSource : implements MediaSource for OMX.
+ * The decoder thread will trigger the MediaDecodeStateMachine to read a/v frame.
+ * Then RtspOmxReader calls OMX decoder to decode a/v frame. Finally the code
+ * path run into the read() here, it reads un-decoded frame data from mResource
+ * and construct a MediaBuffer for output to OMX decoder.
+ * */
+class RtspMediaSource MOZ_FINAL : public MediaSource {
+public:
+  RtspMediaSource(RtspMediaResource* aRtspMediaResource,
+                  ssize_t aTrackIdx,
+                  uint32_t aFrameMaxSize,
+                  const sp<MetaData>& aMeta)
+  : mRtspResource(aRtspMediaResource)
+  , mFormat(aMeta)
+  , mTrackIdx(aTrackIdx)
+  , mMonitor("RtspMediaSource.mMonitor")
+  , mIsStarted(false)
+  , mGroup(nullptr)
+  , mBuffer(nullptr)
+  , mFrameMaxSize(aFrameMaxSize) {}
+  virtual ~RtspMediaSource() {}
+  virtual status_t start(MetaData* params = nullptr) MOZ_OVERRIDE;
+  virtual status_t stop() MOZ_OVERRIDE;
+  virtual sp<MetaData> getFormat() MOZ_OVERRIDE {
+    ReentrantMonitorAutoEnter mon(mMonitor);
+    return mFormat;
+  }
+  virtual status_t read(MediaBuffer** buffer,
+                        const ReadOptions* options = nullptr) MOZ_OVERRIDE ;
+private:
+  nsRefPtr<RtspMediaResource> mRtspResource;
+  sp<MetaData> mFormat;
+  uint32_t mTrackIdx;
+  ReentrantMonitor mMonitor;
+  bool mIsStarted;
+
+  // mGroup owns the mBuffer. mFrameMaxSize is the mBuffer size.
+  // mBuffer is the input buffer for omx decoder.
+  nsAutoPtr<MediaBufferGroup> mGroup;
+  MediaBuffer* mBuffer;
+  uint32_t mFrameMaxSize;
+};
+
+status_t
+RtspMediaSource::start(MetaData* params)
+{
+  ReentrantMonitorAutoEnter mon(mMonitor);
+  if (!mIsStarted) {
+    // RtspMediaSource relinquish the ownership of MediaBuffer |buf| to mGroup.
+    mGroup = new MediaBufferGroup();
+    MediaBuffer* buf = new MediaBuffer(mFrameMaxSize);
+    mGroup->add_buffer(buf);
+    mIsStarted = true;
+  }
+  return OK;
+}
+
+status_t
+RtspMediaSource::stop()
+{
+  ReentrantMonitorAutoEnter mon(mMonitor);
+  if (mIsStarted) {
+    if (mBuffer) {
+      mBuffer->release();
+      mBuffer = nullptr;
+    }
+    mGroup = nullptr;
+    mIsStarted = false;
+  }
+  return OK;
+}
+
+status_t
+RtspMediaSource::read(MediaBuffer** out, const ReadOptions* options)
+{
+  ReentrantMonitorAutoEnter mon(mMonitor);
+  NS_ENSURE_TRUE(mIsStarted, MEDIA_ERROR_BASE);
+  NS_ENSURE_TRUE(out, MEDIA_ERROR_BASE);
+  *out = nullptr;
+
+  // Video/audio track's initial frame size is FRAME_DEFAULT_SIZE.
+  // We need to realloc the mBuffer if the mBuffer doesn't have enough space
+  // for next ReadFrameFromTrack function. (actualFrameSize > mFrameMaxSize)
+  status_t err;
+  uint32_t readCount;
+  uint32_t actualFrameSize;
+  uint64_t time;
+  nsresult rv;
+
+  while (1) {
+    err = mGroup->acquire_buffer(&mBuffer);
+    NS_ENSURE_TRUE(err == OK, err);
+    rv = mRtspResource->ReadFrameFromTrack((uint8_t *)mBuffer->data(),
+                                           mFrameMaxSize, mTrackIdx, readCount,
+                                           time, actualFrameSize);
+    if (NS_FAILED(rv)) {
+      // Release mGroup and mBuffer.
+      stop();
+      // Since RtspMediaSource is an implementation of Android media source,
+      // it's held by OMXCodec and isn't released yet. So we have to re-construct
+      // mGroup and mBuffer.
+      start();
+      NS_WARNING("ReadFrameFromTrack failed; releasing buffers and returning.");
+      return ERROR_END_OF_STREAM;
+    }
+    if (actualFrameSize > mFrameMaxSize) {
+      // release mGroup and mBuffer
+      stop();
+      // re-construct mGroup and mBuffer
+      mFrameMaxSize = actualFrameSize;
+      err = start();
+      NS_ENSURE_TRUE(err == OK, err);
+    } else {
+      // ReadFrameFromTrack success, break the while loop.
+      break;
+    }
+  }
+  mBuffer->set_range(0, readCount);
+  if (NS_SUCCEEDED(rv)) {
+    mBuffer->meta_data()->clear();
+    // fill the meta data
+    mBuffer->meta_data()->setInt64(kKeyTime, time);
+    *out = mBuffer;
+    mBuffer = nullptr;
+    return OK;
+  }
+
+  return ERROR_END_OF_STREAM;
+}
+
+size_t
+RtspExtractor::countTracks()
+{
+  uint8_t tracks = 0;
+  if (mController) {
+    mController->GetTotalTracks(&tracks);
+  }
+  return size_t(tracks);
+}
+
+sp<MediaSource>
+RtspExtractor::getTrack(size_t index)
+{
+  NS_ENSURE_TRUE(index < countTracks(), nullptr);
+  sp<MetaData> meta = getTrackMetaData(index);
+  sp<MediaSource> source = new RtspMediaSource(mRtspResource,
+                                               index,
+                                               FRAME_DEFAULT_SIZE,
+                                               meta);
+  return source;
+}
+
+sp<MetaData>
+RtspExtractor::getTrackMetaData(size_t index, uint32_t flag)
+{
+  NS_ENSURE_TRUE(index < countTracks(), nullptr);
+  sp<MetaData> meta = new MetaData();
+  nsCOMPtr<nsIStreamingProtocolMetaData> rtspMetadata;
+  mController->GetTrackMetaData(index, getter_AddRefs(rtspMetadata));
+
+  if (rtspMetadata) {
+    // Convert msMeta into meta.
+    // The getter function of nsIStreamingProtocolMetaData will initialize the
+    // metadata values to 0 before setting them.
+    nsCString mime;
+    rtspMetadata->GetMimeType(mime);
+    meta->setCString(kKeyMIMEType, mime.get());
+    uint32_t temp32;
+    rtspMetadata->GetWidth(&temp32);
+    meta->setInt32(kKeyWidth, temp32);
+    rtspMetadata->GetHeight(&temp32);
+    meta->setInt32(kKeyHeight, temp32);
+    rtspMetadata->GetSampleRate(&temp32);
+    meta->setInt32(kKeySampleRate, temp32);
+    rtspMetadata->GetChannelCount(&temp32);
+    meta->setInt32(kKeyChannelCount, temp32);
+    uint64_t temp64;
+    rtspMetadata->GetDuration(&temp64);
+    meta->setInt64(kKeyDuration, temp64);
+
+    nsCString tempCString;
+    rtspMetadata->GetEsdsData(tempCString);
+    if (tempCString.Length()) {
+      meta->setData(kKeyESDS, 0, tempCString.get(), tempCString.Length());
+    }
+    rtspMetadata->GetAvccData(tempCString);
+    if (tempCString.Length()) {
+      meta->setData(kKeyAVCC, 0, tempCString.get(), tempCString.Length());
+    }
+  }
+  return meta;
+}
+
+uint32_t
+RtspExtractor::flags() const
+{
+  if (mRtspResource->IsRealTime()) {
+    return 0;
+  } else {
+    return MediaExtractor::CAN_SEEK;
+  }
+}
+
+} // namespace mozilla
+
new file mode 100644
--- /dev/null
+++ b/content/media/omx/RtspExtractor.h
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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/. */
+
+#if !defined(RtspExtractor_h_)
+#define RtspExtractor_h_
+
+#include "RtspMediaResource.h"
+
+#include <stagefright/MediaBufferGroup.h>
+#include <stagefright/MediaExtractor.h>
+#include <stagefright/MediaSource.h>
+#include <stagefright/MetaData.h>
+
+namespace mozilla {
+
+// RtspExtractor is a custom extractor for Rtsp stream, whereas the other
+// XXXExtractors are made for container media content.
+// The extractor is used for |OmxDecoder::Init|, it provides the essential
+// information for creating OMXCodec instance.
+// For example, the |getTrackMetaData| returns metadata that includes the
+// codec type.
+class RtspExtractor: public android::MediaExtractor
+{
+public:
+  virtual size_t countTracks() MOZ_FINAL MOZ_OVERRIDE;
+  virtual android::sp<android::MediaSource> getTrack(size_t index)
+    MOZ_FINAL MOZ_OVERRIDE;
+  virtual android::sp<android::MetaData> getTrackMetaData(
+    size_t index, uint32_t flag = 0) MOZ_FINAL MOZ_OVERRIDE;
+  virtual uint32_t flags() const MOZ_FINAL MOZ_OVERRIDE;
+
+  RtspExtractor(RtspMediaResource* aResource)
+    : mRtspResource(aResource) {
+    MOZ_ASSERT(aResource);
+    mController = mRtspResource->GetMediaStreamController();
+    MOZ_ASSERT(mController);
+  }
+  virtual ~RtspExtractor() MOZ_OVERRIDE {}
+private:
+  // mRtspResource is a pointer to RtspMediaResource. When |getTrack| is called
+  // we use mRtspResource to construct a RtspMediaSource.
+  RtspMediaResource* mRtspResource;
+  // Through the mController in mRtspResource, we can get the essential
+  // information for the extractor.
+  nsRefPtr<nsIStreamingProtocolController> mController;
+};
+
+} // namespace mozilla
+
+#endif
new file mode 100644
--- /dev/null
+++ b/content/media/omx/RtspMediaCodecDecoder.cpp
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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 "RtspMediaCodecDecoder.h"
+
+#include "MediaDecoderStateMachine.h"
+#include "RtspMediaResource.h"
+#include "RtspMediaCodecReader.h"
+
+namespace mozilla {
+
+MediaDecoder*
+RtspMediaCodecDecoder::Clone()
+{
+  return new RtspMediaCodecDecoder();
+}
+
+MediaOmxCommonReader*
+RtspMediaCodecDecoder::CreateReader()
+{
+  return new RtspMediaCodecReader(this);
+}
+
+MediaDecoderStateMachine*
+RtspMediaCodecDecoder::CreateStateMachine(MediaOmxCommonReader* aReader)
+{
+  return new MediaDecoderStateMachine(this, aReader,
+                                      mResource->IsRealTime());
+}
+
+void
+RtspMediaCodecDecoder::ApplyStateToStateMachine(PlayState aState)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  MediaDecoder::ApplyStateToStateMachine(aState);
+
+  // Notify RTSP controller if the play state is ended.
+  // This is necessary for RTSP controller to transit its own state.
+  if (aState == PLAY_STATE_ENDED) {
+    nsRefPtr<RtspMediaResource> resource = mResource->GetRtspPointer();
+    if (resource) {
+      nsIStreamingProtocolController* controller =
+        resource->GetMediaStreamController();
+      if (controller) {
+        controller->PlaybackEnded();
+      }
+    }
+  }
+}
+
+} // namespace mozilla
+
new file mode 100644
--- /dev/null
+++ b/content/media/omx/RtspMediaCodecDecoder.h
@@ -0,0 +1,28 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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/. */
+
+#if !defined(RtspMediaCodecDecoder_h_)
+#define RtspMediaCodecDecoder_h_
+
+#include "MediaOmxCommonDecoder.h"
+
+namespace mozilla {
+
+class RtspMediaCodecDecoder MOZ_FINAL : public MediaOmxCommonDecoder
+{
+public:
+  virtual MediaDecoder* Clone() MOZ_OVERRIDE;
+
+  virtual MediaOmxCommonReader* CreateReader() MOZ_OVERRIDE;
+
+  virtual MediaDecoderStateMachine* CreateStateMachine(MediaOmxCommonReader* aReader) MOZ_OVERRIDE;
+
+  virtual void ApplyStateToStateMachine(PlayState aState) MOZ_OVERRIDE;
+};
+
+} // namespace mozilla
+
+#endif
new file mode 100644
--- /dev/null
+++ b/content/media/omx/RtspMediaCodecReader.cpp
@@ -0,0 +1,116 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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 "RtspMediaCodecReader.h"
+
+#include "RtspExtractor.h"
+#include "RtspMediaResource.h"
+#include "RtspMediaCodecDecoder.h"
+
+using namespace android;
+
+namespace mozilla {
+
+RtspMediaCodecReader::RtspMediaCodecReader(AbstractMediaDecoder* aDecoder)
+  : MediaCodecReader(aDecoder)
+{
+  NS_ASSERTION(mDecoder, "RtspMediaCodecReader mDecoder is null.");
+  NS_ASSERTION(mDecoder->GetResource(),
+               "RtspMediaCodecReader mDecoder->GetResource() is null.");
+  mRtspResource = mDecoder->GetResource()->GetRtspPointer();
+  MOZ_ASSERT(mRtspResource);
+}
+
+RtspMediaCodecReader::~RtspMediaCodecReader() {}
+
+bool
+RtspMediaCodecReader::CreateExtractor()
+{
+  if (mExtractor != nullptr) {
+    return true;
+  }
+
+  mExtractor = new RtspExtractor(mRtspResource);
+
+  return mExtractor != nullptr;
+}
+
+nsresult
+RtspMediaCodecReader::Seek(int64_t aTime, int64_t aStartTime,
+                           int64_t aEndTime, int64_t aCurrentTime)
+{
+  // The seek function of Rtsp is time-based, we call the SeekTime function in
+  // RtspMediaResource. The SeekTime function finally send a seek command to
+  // Rtsp stream server through network and also clear the buffer data in
+  // RtspMediaResource.
+  mRtspResource->SeekTime(aTime);
+
+  return MediaCodecReader::Seek(aTime, aStartTime, aEndTime, aCurrentTime);
+}
+
+void
+RtspMediaCodecReader::SetIdle()
+{
+  nsIStreamingProtocolController* controller =
+    mRtspResource->GetMediaStreamController();
+  if (controller) {
+    controller->Pause();
+  }
+  mRtspResource->SetSuspend(true);
+}
+
+void
+RtspMediaCodecReader::EnsureActive()
+{
+  // Need to start RTSP streaming OMXCodec decoding.
+  nsIStreamingProtocolController* controller =
+    mRtspResource->GetMediaStreamController();
+  if (controller) {
+    controller->Play();
+  }
+  mRtspResource->SetSuspend(false);
+}
+
+void
+RtspMediaCodecReader::RequestAudioData()
+{
+  EnsureActive();
+  MediaCodecReader::RequestAudioData();
+}
+
+void
+RtspMediaCodecReader::RequestVideoData(bool aSkipToNextKeyframe,
+                                       int64_t aTimeThreshold)
+{
+  EnsureActive();
+  MediaCodecReader::RequestVideoData(aSkipToNextKeyframe, aTimeThreshold);
+}
+
+nsresult
+RtspMediaCodecReader::ReadMetadata(MediaInfo* aInfo,
+                                   MetadataTags** aTags)
+{
+  nsresult rv = MediaCodecReader::ReadMetadata(aInfo, aTags);
+  if (rv == NS_OK && !IsWaitingMediaResources()) {
+    EnsureActive();
+  }
+
+  return rv;
+}
+
+// Called on Binder thread.
+void
+RtspMediaCodecReader::codecReserved(Track& aTrack)
+{
+  // TODO: fix me, we need a SeekTime(0) here because the
+  // MediaDecoderStateMachine will update the mStartTime after ReadMetadata.
+  MediaCodecReader::codecReserved(aTrack);
+  if (aTrack.mCodec != nullptr) {
+    mRtspResource->SeekTime(0);
+  }
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/content/media/omx/RtspMediaCodecReader.h
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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/. */
+
+#if !defined(RtspMediaCodecReader_h_)
+#define RtspMediaCodecReader_h_
+
+#include "MediaCodecReader.h"
+
+namespace mozilla {
+
+namespace dom {
+  class TimeRanges;
+}
+
+class AbstractMediaDecoder;
+class RtspMediaResource;
+
+/* RtspMediaCodecReader is a subclass of MediaCodecReader.
+ * The major reason that RtspMediaCodecReader inherit from MediaCodecReader is
+ * the same video/audio decoding logic we can reuse.
+ */
+class RtspMediaCodecReader MOZ_FINAL : public MediaCodecReader
+{
+protected:
+  // Provide a Rtsp extractor.
+  virtual bool CreateExtractor() MOZ_OVERRIDE;
+  // Ensure the play command is sent to Rtsp server.
+  void EnsureActive();
+
+public:
+  RtspMediaCodecReader(AbstractMediaDecoder* aDecoder);
+
+  virtual ~RtspMediaCodecReader();
+
+  // Implement a time-based seek instead of byte-based.
+  virtual nsresult Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime,
+                        int64_t aCurrentTime) MOZ_OVERRIDE;
+
+  // Override GetBuffered() to do nothing for below reasons:
+  // 1. Because the Rtsp stream is a/v separated. The buffered data in a/v
+  // tracks are not consistent with time stamp.
+  // For example: audio buffer: 1~2s, video buffer: 1.5~2.5s
+  // 2. Since the Rtsp is a realtime streaming, the buffer we made for
+  // RtspMediaResource is quite small. The small buffer implies the time ranges
+  // we returned are not useful for the MediaDecodeStateMachine. Unlike the
+  // ChannelMediaResource, it has a "cache" that can store the whole streaming
+  // data so the |GetBuffered| function can retrieve useful time ranges.
+  virtual nsresult GetBuffered(dom::TimeRanges* aBuffered,
+                               int64_t aStartTime) MOZ_OVERRIDE {
+    return NS_OK;
+  }
+
+  virtual void SetIdle() MOZ_OVERRIDE;
+
+  // Disptach a DecodeVideoFrameTask to decode video data.
+  virtual void RequestVideoData(bool aSkipToNextKeyframe,
+                                int64_t aTimeThreshold) MOZ_OVERRIDE;
+
+  // Disptach a DecodeAudioDataTask to decode audio data.
+  virtual void RequestAudioData() MOZ_OVERRIDE;
+
+  virtual nsresult ReadMetadata(MediaInfo* aInfo,
+                                MetadataTags** aTags) MOZ_OVERRIDE;
+
+  virtual void codecReserved(Track& aTrack) MOZ_OVERRIDE;
+
+private:
+  // A pointer to RtspMediaResource for calling the Rtsp specific function.
+  // The lifetime of mRtspResource is controlled by MediaDecoder. MediaDecoder
+  // holds the MediaDecoderStateMachine and RtspMediaResource.
+  // And MediaDecoderStateMachine holds this RtspMediaCodecReader.
+  RtspMediaResource* mRtspResource;
+};
+
+} // namespace mozilla
+
+#endif
--- a/content/media/omx/RtspOmxReader.cpp
+++ b/content/media/omx/RtspOmxReader.cpp
@@ -3,274 +3,25 @@
 /* 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 "RtspOmxReader.h"
 
 #include "AbstractMediaDecoder.h"
 #include "MediaDecoderStateMachine.h"
-#include "MPAPI.h"
-#include "mozilla/dom/TimeRanges.h"
-#include "mozilla/Mutex.h"
-#include "mozilla/TimeStamp.h"
 #include "OmxDecoder.h"
+#include "RtspExtractor.h"
 #include "RtspMediaResource.h"
 #include "RtspOmxDecoder.h"
-#include "VideoUtils.h"
-
-#include <stagefright/MediaExtractor.h>
-#include <stagefright/MediaBufferGroup.h>
-#include <stagefright/MetaData.h>
-
-#define FRAME_DEFAULT_SIZE 1024
 
 using namespace android;
 
 namespace mozilla {
 
-/* class RtspMediaSource : implements MediaSource for OMX.
- * The decoder thread will trigger the MediaDecodeStateMachine to read a/v frame.
- * Then RtspOmxReader calls OMX decoder to decode a/v frame. Finally the code
- * path run into the read() here, it reads un-decoded frame data from mResource
- * and construct a MediaBuffer for output to OMX decoder.
- * */
-class RtspMediaSource : public android::MediaSource {
-public:
-  RtspMediaSource(RtspMediaResource *aRtspMediaResource,
-                  ssize_t aTrackIdx,
-                  uint32_t aFrameMaxSize,
-                  const sp<MetaData>& aMeta)
-  : mRtspResource(aRtspMediaResource)
-  , mFormat(aMeta)
-  , mTrackIdx(aTrackIdx)
-  , mMonitor("RtspMediaSource.mMonitor")
-  , mIsStarted(false)
-  , mGroup(nullptr)
-  , mBuffer(nullptr)
-  , mFrameMaxSize(aFrameMaxSize) {
-    MOZ_COUNT_CTOR(RtspMediaSource);
-  };
-  virtual ~RtspMediaSource() {
-    MOZ_COUNT_DTOR(RtspMediaSource);
-  }
-  virtual status_t start(MetaData *params = nullptr) MOZ_FINAL MOZ_OVERRIDE;
-  virtual status_t stop() MOZ_FINAL MOZ_OVERRIDE;
-  virtual sp<MetaData> getFormat() MOZ_FINAL MOZ_OVERRIDE {
-    ReentrantMonitorAutoEnter mon(mMonitor);
-    return mFormat;
-  };
-  virtual status_t read(MediaBuffer **buffer,
-                        const ReadOptions *options = nullptr) MOZ_FINAL MOZ_OVERRIDE ;
-private:
-  nsRefPtr<RtspMediaResource> mRtspResource;
-  sp<MetaData> mFormat;
-  uint32_t mTrackIdx;
-  ReentrantMonitor mMonitor;
-  bool mIsStarted;
-
-  // mGroup owns the mBuffer. mFrameMaxSize is the mBuffer size.
-  // mBuffer is the input buffer for omx decoder.
-  nsAutoPtr<MediaBufferGroup> mGroup;
-  MediaBuffer* mBuffer;
-  uint32_t mFrameMaxSize;
-};
-
-status_t RtspMediaSource::start(MetaData *params)
-{
-  ReentrantMonitorAutoEnter mon(mMonitor);
-  if (!mIsStarted) {
-    // RtspMediaSource relinquish the ownership of MediaBuffer |buf| to mGroup.
-    mGroup = new MediaBufferGroup();
-    MediaBuffer* buf = new MediaBuffer(mFrameMaxSize);
-    mGroup->add_buffer(buf);
-    mIsStarted = true;
-  }
-  return OK;
-}
-
-status_t RtspMediaSource::stop()
-{
-  ReentrantMonitorAutoEnter mon(mMonitor);
-  if (mIsStarted) {
-    if (mBuffer) {
-      mBuffer->release();
-      mBuffer = nullptr;
-    }
-    mGroup = nullptr;
-    mIsStarted = false;
-  }
-  return OK;
-}
-
-status_t RtspMediaSource::read(MediaBuffer **out, const ReadOptions *options)
-{
-  ReentrantMonitorAutoEnter mon(mMonitor);
-  NS_ENSURE_TRUE(mIsStarted, MEDIA_ERROR_BASE);
-  NS_ENSURE_TRUE(out, MEDIA_ERROR_BASE);
-  *out = nullptr;
-
-  // Video/audio track's initial frame size is FRAME_DEFAULT_SIZE.
-  // We need to realloc the mBuffer if the mBuffer doesn't have enough space
-  // for next ReadFrameFromTrack function. (actualFrameSize > mFrameMaxSize)
-  status_t err;
-  uint32_t readCount;
-  uint32_t actualFrameSize;
-  uint64_t time;
-  nsresult rv;
-
-  while (1) {
-    err = mGroup->acquire_buffer(&mBuffer);
-    NS_ENSURE_TRUE(err == OK, err);
-
-    rv = mRtspResource->ReadFrameFromTrack((uint8_t *)mBuffer->data(),
-                                           mFrameMaxSize, mTrackIdx, readCount,
-                                           time, actualFrameSize);
-    if (NS_FAILED(rv)) {
-      // Release mGroup and mBuffer.
-      stop();
-      // Since RtspMediaSource is an implementation of Android media source,
-      // it's held by OMXCodec and isn't released yet. So we have to re-construct
-      // mGroup and mBuffer.
-      start();
-      NS_WARNING("ReadFrameFromTrack failed; releasing buffers and returning.");
-      return ERROR_CONNECTION_LOST;
-    }
-    if (actualFrameSize > mFrameMaxSize) {
-      // release mGroup and mBuffer
-      stop();
-      // re-construct mGroup and mBuffer
-      mFrameMaxSize = actualFrameSize;
-      err = start();
-      NS_ENSURE_TRUE(err == OK, err);
-    } else {
-      // ReadFrameFromTrack success, break the while loop.
-      break;
-    }
-  }
-  mBuffer->set_range(0, readCount);
-  if (NS_SUCCEEDED(rv)) {
-    mBuffer->meta_data()->clear();
-    // fill the meta data
-    mBuffer->meta_data()->setInt64(kKeyTime, time);
-    *out = mBuffer;
-    mBuffer = nullptr;
-    return OK;
-  }
-
-  return ERROR_END_OF_STREAM;
-}
-
-
-// RtspExtractor is a custom extractor for Rtsp stream, whereas the other
-// XXXExtractors are made for container media content.
-// The extractor is used for |OmxDecoder::Init|, it provides the essential
-// information for creating OMXCodec instance.
-// For example, the |getTrackMetaData| returns metadata that includes the
-// codec type.
-class RtspExtractor: public MediaExtractor
-{
-public:
-  virtual size_t countTracks() MOZ_FINAL MOZ_OVERRIDE;
-  virtual sp<android::MediaSource> getTrack(size_t index)
-    MOZ_FINAL MOZ_OVERRIDE;
-  virtual sp<MetaData> getTrackMetaData(
-    size_t index, uint32_t flag = 0) MOZ_FINAL MOZ_OVERRIDE;
-  virtual uint32_t flags() const MOZ_FINAL MOZ_OVERRIDE;
-
-  RtspExtractor(RtspMediaResource *aResource)
-    : mRtspResource(aResource) {
-    MOZ_COUNT_CTOR(RtspExtractor);
-    MOZ_ASSERT(aResource);
-    mController = mRtspResource->GetMediaStreamController();
-    MOZ_ASSERT(mController);
-  }
-  virtual ~RtspExtractor() MOZ_OVERRIDE {
-    MOZ_COUNT_DTOR(RtspExtractor);
-  }
-private:
-  // mRtspResource is a pointer to RtspMediaResource. When |getTrack| is called
-  // we use mRtspResource to construct a RtspMediaSource.
-  RtspMediaResource* mRtspResource;
-  // Through the mController in mRtspResource, we can get the essential
-  // information for the extractor.
-  nsRefPtr<nsIStreamingProtocolController> mController;
-};
-
-size_t RtspExtractor::countTracks()
-{
-  uint8_t tracks = 0;
-  if (mController) {
-    mController->GetTotalTracks(&tracks);
-  }
-  return size_t(tracks);
-}
-
-sp<android::MediaSource> RtspExtractor::getTrack(size_t index)
-{
-  NS_ENSURE_TRUE(index < countTracks(), nullptr);
-
-  sp<MetaData> meta = getTrackMetaData(index);
-  sp<android::MediaSource> source = new RtspMediaSource(mRtspResource,
-                                                        index,
-                                                        FRAME_DEFAULT_SIZE,
-                                                        meta);
-  return source;
-}
-
-sp<MetaData> RtspExtractor::getTrackMetaData(size_t index, uint32_t flag)
-{
-  NS_ENSURE_TRUE(index < countTracks(), nullptr);;
-
-  sp<MetaData> meta = new MetaData();
-  nsCOMPtr<nsIStreamingProtocolMetaData> rtspMetadata;
-  mController->GetTrackMetaData(index, getter_AddRefs(rtspMetadata));
-
-  if (rtspMetadata) {
-    // Convert msMeta into meta.
-    // The getter function of nsIStreamingProtocolMetaData will initialize the
-    // metadata values to 0 before setting them.
-    nsCString mime;
-    rtspMetadata->GetMimeType(mime);
-    meta->setCString(kKeyMIMEType, mime.get());
-    uint32_t temp32;
-    rtspMetadata->GetWidth(&temp32);
-    meta->setInt32(kKeyWidth, temp32);
-    rtspMetadata->GetHeight(&temp32);
-    meta->setInt32(kKeyHeight, temp32);
-    rtspMetadata->GetSampleRate(&temp32);
-    meta->setInt32(kKeySampleRate, temp32);
-    rtspMetadata->GetChannelCount(&temp32);
-    meta->setInt32(kKeyChannelCount, temp32);
-    uint64_t temp64;
-    rtspMetadata->GetDuration(&temp64);
-    meta->setInt64(kKeyDuration, temp64);
-
-    nsCString tempCString;
-    rtspMetadata->GetEsdsData(tempCString);
-    if (tempCString.Length()) {
-      meta->setData(kKeyESDS, 0, tempCString.get(), tempCString.Length());
-    }
-    rtspMetadata->GetAvccData(tempCString);
-    if (tempCString.Length()) {
-      meta->setData(kKeyAVCC, 0, tempCString.get(), tempCString.Length());
-    }
-  }
-  return meta;
-}
-
-uint32_t RtspExtractor::flags() const
-{
-  if (mRtspResource->IsRealTime()) {
-    return 0;
-  } else {
-    return MediaExtractor::CAN_SEEK;
-  }
-}
-
 nsresult RtspOmxReader::InitOmxDecoder()
 {
   if (!mOmxDecoder.get()) {
     NS_ASSERTION(mDecoder, "RtspOmxReader mDecoder is null.");
     NS_ASSERTION(mDecoder->GetResource(),
                  "RtspOmxReader mDecoder->GetResource() is null.");
     mExtractor = new RtspExtractor(mRtspResource);
     mOmxDecoder = new OmxDecoder(mDecoder->GetResource(), mDecoder);
--- a/content/media/omx/moz.build
+++ b/content/media/omx/moz.build
@@ -39,23 +39,34 @@ if CONFIG['MOZ_OMX_ENCODER']:
     ]
     SOURCES += [
         'OMXCodecDescriptorUtil.cpp',
         'OMXCodecWrapper.cpp',
     ]
 
 if 'rtsp' in CONFIG['NECKO_PROTOCOLS']:
     EXPORTS += [
+        'RtspExtractor.h',
         'RtspOmxDecoder.h',
         'RtspOmxReader.h',
     ]
     SOURCES += [
+        'RtspExtractor.cpp',
         'RtspOmxDecoder.cpp',
         'RtspOmxReader.cpp',
     ]
+    if CONFIG['ANDROID_VERSION'] >= '18':
+        EXPORTS += [
+            'RtspMediaCodecDecoder.h',
+            'RtspMediaCodecReader.h',
+        ]
+        SOURCES += [
+            'RtspMediaCodecDecoder.cpp',
+            'RtspMediaCodecReader.cpp',
+        ]
 
 if CONFIG['ANDROID_VERSION'] >= '18':
     EXPORTS += [
         'I420ColorConverterHelper.h',
         'MediaCodecDecoder.h',
         'MediaCodecProxy.h',
         'MediaCodecReader.h',
     ]
--- a/dom/audiochannel/AudioChannelAgent.cpp
+++ b/dom/audiochannel/AudioChannelAgent.cpp
@@ -109,17 +109,17 @@ AudioChannelAgent::InitInternal(nsIDOMWi
   mWithVideo = aWithVideo;
 
   return NS_OK;
 }
 
 /* boolean startPlaying (); */
 NS_IMETHODIMP AudioChannelAgent::StartPlaying(int32_t *_retval)
 {
-  AudioChannelService *service = AudioChannelService::GetAudioChannelService();
+  AudioChannelService *service = AudioChannelService::GetOrCreateAudioChannelService();
   if (mAudioChannelType == AUDIO_AGENT_CHANNEL_ERROR ||
       service == nullptr || mIsRegToService) {
     return NS_ERROR_FAILURE;
   }
 
   service->RegisterAudioChannelAgent(this,
     static_cast<AudioChannel>(mAudioChannelType), mWithVideo);
   *_retval = service->GetState(this, !mVisible);
@@ -130,42 +130,42 @@ NS_IMETHODIMP AudioChannelAgent::StartPl
 /* void stopPlaying (); */
 NS_IMETHODIMP AudioChannelAgent::StopPlaying(void)
 {
   if (mAudioChannelType == AUDIO_AGENT_CHANNEL_ERROR ||
       !mIsRegToService) {
     return NS_ERROR_FAILURE;
   }
 
-  AudioChannelService *service = AudioChannelService::GetAudioChannelService();
+  AudioChannelService *service = AudioChannelService::GetOrCreateAudioChannelService();
   service->UnregisterAudioChannelAgent(this);
   mIsRegToService = false;
   return NS_OK;
 }
 
 /* void setVisibilityState (in boolean visible); */
 NS_IMETHODIMP AudioChannelAgent::SetVisibilityState(bool visible)
 {
   bool oldVisibility = mVisible;
 
   nsCOMPtr<nsIAudioChannelAgentCallback> callback = GetCallback();
 
   mVisible = visible;
   if (mIsRegToService && oldVisibility != mVisible && callback) {
-    AudioChannelService *service = AudioChannelService::GetAudioChannelService();
+    AudioChannelService *service = AudioChannelService::GetOrCreateAudioChannelService();
     callback->CanPlayChanged(service->GetState(this, !mVisible));
   }
   return NS_OK;
 }
 
 void AudioChannelAgent::NotifyAudioChannelStateChanged()
 {
   nsCOMPtr<nsIAudioChannelAgentCallback> callback = GetCallback();
   if (callback) {
-    AudioChannelService *service = AudioChannelService::GetAudioChannelService();
+    AudioChannelService *service = AudioChannelService::GetOrCreateAudioChannelService();
     callback->CanPlayChanged(service->GetState(this, !mVisible));
   }
 }
 
 already_AddRefed<nsIAudioChannelAgentCallback>
 AudioChannelAgent::GetCallback()
 {
   nsCOMPtr<nsIAudioChannelAgentCallback> callback = mCallback;
--- a/dom/audiochannel/AudioChannelService.cpp
+++ b/dom/audiochannel/AudioChannelService.cpp
@@ -53,24 +53,38 @@ AudioChannelService*
 AudioChannelService::GetAudioChannelService()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (XRE_GetProcessType() != GeckoProcessType_Default) {
     return AudioChannelServiceChild::GetAudioChannelService();
   }
 
+  return gAudioChannelService;
+
+}
+
+// static
+AudioChannelService*
+AudioChannelService::GetOrCreateAudioChannelService()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  if (XRE_GetProcessType() != GeckoProcessType_Default) {
+    return AudioChannelServiceChild::GetOrCreateAudioChannelService();
+  }
+
   // If we already exist, exit early
   if (gAudioChannelService) {
     return gAudioChannelService;
   }
 
   // Create new instance, register, return
   nsRefPtr<AudioChannelService> service = new AudioChannelService();
-  NS_ENSURE_TRUE(service, nullptr);
+  MOZ_ASSERT(service);
 
   gAudioChannelService = service;
   return gAudioChannelService;
 }
 
 void
 AudioChannelService::Shutdown()
 {
--- a/dom/audiochannel/AudioChannelService.h
+++ b/dom/audiochannel/AudioChannelService.h
@@ -31,24 +31,29 @@ class AudioChannelService
 , public nsITimerCallback
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIOBSERVER
   NS_DECL_NSITIMERCALLBACK
 
   /**
-   * Returns the AudioChannelServce singleton. Only to be called from main
-   * thread.
-   *
-   * @return NS_OK on proper assignment, NS_ERROR_FAILURE otherwise.
+   * Returns the AudioChannelServce singleton or null if the process havn't create it before.
+   * Only to be called from main thread.
    */
   static AudioChannelService* GetAudioChannelService();
 
   /**
+   * Returns the AudioChannelServce singleton.
+   * If AudioChannelServce is not exist, create and return new one.
+   * Only to be called from main thread.
+   */
+  static AudioChannelService* GetOrCreateAudioChannelService();
+
+  /**
    * Shutdown the singleton.
    */
   static void Shutdown();
 
   /**
    * Any audio channel agent that starts playing should register itself to
    * this service, sharing the AudioChannel.
    */
--- a/dom/audiochannel/AudioChannelServiceChild.cpp
+++ b/dom/audiochannel/AudioChannelServiceChild.cpp
@@ -27,24 +27,34 @@ using namespace mozilla::hal;
 StaticRefPtr<AudioChannelServiceChild> gAudioChannelServiceChild;
 
 // static
 AudioChannelService*
 AudioChannelServiceChild::GetAudioChannelService()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
+  return gAudioChannelServiceChild;
+
+}
+
+// static
+AudioChannelService*
+AudioChannelServiceChild::GetOrCreateAudioChannelService()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
   // If we already exist, exit early
   if (gAudioChannelServiceChild) {
     return gAudioChannelServiceChild;
   }
 
   // Create new instance, register, return
   nsRefPtr<AudioChannelServiceChild> service = new AudioChannelServiceChild();
-  NS_ENSURE_TRUE(service, nullptr);
+  MOZ_ASSERT(service);
 
   gAudioChannelServiceChild = service;
   return gAudioChannelServiceChild;
 }
 
 void
 AudioChannelServiceChild::Shutdown()
 {
--- a/dom/audiochannel/AudioChannelServiceChild.h
+++ b/dom/audiochannel/AudioChannelServiceChild.h
@@ -16,23 +16,28 @@
 namespace mozilla {
 namespace dom {
 
 class AudioChannelServiceChild : public AudioChannelService
 {
 public:
 
   /**
-   * Returns the AudioChannelServce singleton. Only to be called from main
-   * thread.
-   *
-   * @return NS_OK on proper assignment, NS_ERROR_FAILURE otherwise.
+   * Returns the AudioChannelServce singleton or null if the process havn't create it before.
+   * Only to be called from main thread.
    */
   static AudioChannelService* GetAudioChannelService();
 
+  /**
+   * Returns the AudioChannelServce singleton.
+   * If AudioChannelServce is not exist, create and return new one.
+   * Only to be called from main thread.
+   */
+  static AudioChannelService* GetOrCreateAudioChannelService();
+
   static void Shutdown();
 
   virtual void RegisterAudioChannelAgent(AudioChannelAgent* aAgent,
                                          AudioChannel aChannel,
                                          bool aWithVideo);
   virtual void UnregisterAudioChannelAgent(AudioChannelAgent* aAgent);
 
   /**
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -3792,20 +3792,18 @@ nsPIDOMWindow::GetAudioGlobalVolume()
 
   return globalVolume;
 }
 
 void
 nsPIDOMWindow::RefreshMediaElements()
 {
   nsRefPtr<AudioChannelService> service =
-    AudioChannelService::GetAudioChannelService();
-  if (service) {
-    service->RefreshAgentsVolume(this);
-  }
+    AudioChannelService::GetOrCreateAudioChannelService();
+  service->RefreshAgentsVolume(this);
 }
 
 void
 nsPIDOMWindow::SendAfterRemotePaintIfRequested()
 {
   if (!mSendAfterRemotePaint) {
     return;
   }
--- a/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.cpp
@@ -1490,16 +1490,24 @@ BluetoothServiceBluedroid::DiscoveryStat
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   bool isDiscovering = (aState == true);
 
   DistributeSignal(
     BluetoothSignal(NS_LITERAL_STRING(DISCOVERY_STATE_CHANGED_ID),
                     NS_LITERAL_STRING(KEY_ADAPTER), isDiscovering));
+
+  // Distribute "PropertyChanged" signal to notice adapter this change since
+  // Bluedroid don' treat "discovering" as a property of adapter.
+  InfallibleTArray<BluetoothNamedValue> props;
+  BT_APPEND_NAMED_VALUE(props, "Discovering", BluetoothValue(isDiscovering));
+  DistributeSignal(BluetoothSignal(NS_LITERAL_STRING("PropertyChanged"),
+                                   NS_LITERAL_STRING(KEY_ADAPTER),
+                                   BluetoothValue(props)));
 }
 
 void
 BluetoothServiceBluedroid::PinRequestNotification(const nsAString& aRemoteBdAddr,
                                                   const nsAString& aBdName,
                                                   uint32_t aCod)
 {
   MOZ_ASSERT(NS_IsMainThread());
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -4,16 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "CanvasRenderingContext2D.h"
 
 #include "nsXULElement.h"
 
 #include "nsIServiceManager.h"
 #include "nsMathUtils.h"
+#include "SVGImageContext.h"
 
 #include "nsContentUtils.h"
 
 #include "nsIDocument.h"
 #include "mozilla/dom/HTMLCanvasElement.h"
 #include "nsSVGEffects.h"
 #include "nsPresContext.h"
 #include "nsIPresShell.h"
@@ -3479,21 +3480,23 @@ CanvasRenderingContext2D::DrawDirectlyTo
   nsRefPtr<gfxContext> context = new gfxContext(tempTarget);
   context->SetMatrix(contextMatrix);
   context->Scale(1.0 / contextScale.width, 1.0 / contextScale.height);
   context->Translate(gfxPoint(dest.x - src.x, dest.y - src.y));
 
   // FLAG_CLAMP is added for increased performance, since we never tile here.
   uint32_t modifiedFlags = image.mDrawingFlags | imgIContainer::FLAG_CLAMP;
 
+  SVGImageContext svgContext(scaledImageSize, Nothing(), CurrentState().globalAlpha);
+
   nsresult rv = image.mImgContainer->
     Draw(context, scaledImageSize,
          ImageRegion::Create(gfxRect(src.x, src.y, src.width, src.height)),
          image.mWhichFrame, GraphicsFilter::FILTER_GOOD,
-         Nothing(), modifiedFlags);
+         Some(svgContext), modifiedFlags);
 
   NS_ENSURE_SUCCESS_VOID(rv);
 }
 
 static bool
 IsStandardCompositeOp(CompositionOp op)
 {
     return (op == CompositionOp::OP_SOURCE ||
--- a/dom/events/IMEContentObserver.cpp
+++ b/dom/events/IMEContentObserver.cpp
@@ -5,17 +5,19 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "ContentEventHandler.h"
 #include "IMEContentObserver.h"
 #include "mozilla/AsyncEventDispatcher.h"
 #include "mozilla/AutoRestore.h"
 #include "mozilla/EventStateManager.h"
 #include "mozilla/IMEStateManager.h"
+#include "mozilla/MouseEvents.h"
 #include "mozilla/TextComposition.h"
+#include "mozilla/TextEvents.h"
 #include "mozilla/dom/Element.h"
 #include "nsAutoPtr.h"
 #include "nsContentUtils.h"
 #include "nsGkAtoms.h"
 #include "nsIAtom.h"
 #include "nsIContent.h"
 #include "nsIDocument.h"
 #include "nsIDOMDocument.h"
@@ -420,16 +422,86 @@ IMEContentObserver::Reflow(DOMHighResTim
 NS_IMETHODIMP
 IMEContentObserver::ReflowInterruptible(DOMHighResTimeStamp aStart,
                                         DOMHighResTimeStamp aEnd)
 {
   MaybeNotifyIMEOfPositionChange();
   return NS_OK;
 }
 
+bool
+IMEContentObserver::OnMouseButtonEvent(nsPresContext* aPresContext,
+                                       WidgetMouseEvent* aMouseEvent)
+{
+  if (!mUpdatePreference.WantMouseButtonEventOnChar()) {
+    return false;
+  }
+  if (!aMouseEvent->mFlags.mIsTrusted ||
+      aMouseEvent->mFlags.mDefaultPrevented ||
+      !aMouseEvent->widget) {
+    return false;
+  }
+  // Now, we need to notify only mouse down and mouse up event.
+  switch (aMouseEvent->message) {
+    case NS_MOUSE_BUTTON_UP:
+    case NS_MOUSE_BUTTON_DOWN:
+      break;
+    default:
+      return false;
+  }
+  if (NS_WARN_IF(!mWidget)) {
+    return false;
+  }
+
+  WidgetQueryContentEvent charAtPt(true, NS_QUERY_CHARACTER_AT_POINT,
+                                   aMouseEvent->widget);
+  charAtPt.refPoint = aMouseEvent->refPoint;
+  ContentEventHandler handler(aPresContext);
+  handler.OnQueryCharacterAtPoint(&charAtPt);
+  if (NS_WARN_IF(!charAtPt.mSucceeded) ||
+      charAtPt.mReply.mOffset == WidgetQueryContentEvent::NOT_FOUND) {
+    return false;
+  }
+
+  // The result character rect is relative to the top level widget.
+  // We should notify it with offset in the widget.
+  nsIWidget* topLevelWidget = mWidget->GetTopLevelWidget();
+  if (topLevelWidget && topLevelWidget != mWidget) {
+    charAtPt.mReply.mRect.MoveBy(
+      topLevelWidget->WidgetToScreenOffset() -
+        mWidget->WidgetToScreenOffset());
+  }
+  // The refPt is relative to its widget.
+  // We should notify it with offset in the widget.
+  if (aMouseEvent->widget != mWidget) {
+    charAtPt.refPoint += LayoutDeviceIntPoint::FromUntyped(
+      aMouseEvent->widget->WidgetToScreenOffset() -
+        mWidget->WidgetToScreenOffset());
+  }
+
+  IMENotification notification(NOTIFY_IME_OF_MOUSE_BUTTON_EVENT);
+  notification.mMouseButtonEventData.mEventMessage = aMouseEvent->message;
+  notification.mMouseButtonEventData.mOffset = charAtPt.mReply.mOffset;
+  notification.mMouseButtonEventData.mCursorPos.Set(
+    LayoutDeviceIntPoint::ToUntyped(charAtPt.refPoint));
+  notification.mMouseButtonEventData.mCharRect.Set(charAtPt.mReply.mRect);
+  notification.mMouseButtonEventData.mButton = aMouseEvent->button;
+  notification.mMouseButtonEventData.mButtons = aMouseEvent->buttons;
+  notification.mMouseButtonEventData.mModifiers = aMouseEvent->modifiers;
+
+  nsresult rv = mWidget->NotifyIME(notification);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return false;
+  }
+
+  bool consumed = (rv == NS_SUCCESS_EVENT_CONSUMED);
+  aMouseEvent->mFlags.mDefaultPrevented = consumed;
+  return consumed;
+}
+
 // Helper class, used for text change notification
 class TextChangeEvent : public nsRunnable
 {
 public:
   TextChangeEvent(IMEContentObserver* aDispatcher,
                   IMEContentObserver::TextChangeData& aData)
     : mDispatcher(aDispatcher)
     , mData(aData)
--- a/dom/events/IMEContentObserver.h
+++ b/dom/events/IMEContentObserver.h
@@ -55,16 +55,19 @@ public:
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
   NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTEWILLCHANGE
   NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
   NS_DECL_NSIREFLOWOBSERVER
 
   // nsIScrollObserver
   virtual void ScrollPositionChanged() MOZ_OVERRIDE;
 
+  bool OnMouseButtonEvent(nsPresContext* aPresContext,
+                          WidgetMouseEvent* aMouseEvent);
+
   void Init(nsIWidget* aWidget, nsPresContext* aPresContext,
             nsIContent* aContent);
   void Destroy();
   /**
    * IMEContentObserver is stored by EventStateManager during observing.
    * DisconnectFromEventStateManager() is called when EventStateManager stops
    * storing the instance.
    */
--- a/dom/events/IMEStateManager.cpp
+++ b/dom/events/IMEStateManager.cpp
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "prlog.h"
 
 #include "mozilla/IMEStateManager.h"
 
 #include "mozilla/Attributes.h"
 #include "mozilla/EventStates.h"
+#include "mozilla/MouseEvents.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 #include "mozilla/TextComposition.h"
 #include "mozilla/TextEvents.h"
 #include "mozilla/dom/HTMLFormElement.h"
 
 #include "HTMLInputElement.h"
 #include "IMEContentObserver.h"
@@ -467,16 +468,73 @@ IMEStateManager::OnInstalledMenuKeyboard
 
   InputContextAction action(InputContextAction::CAUSE_UNKNOWN,
     aInstalling ? InputContextAction::MENU_GOT_PSEUDO_FOCUS :
                   InputContextAction::MENU_LOST_PSEUDO_FOCUS);
   OnChangeFocusInternal(sPresContext, sContent, action);
 }
 
 // static
+bool
+IMEStateManager::OnMouseButtonEventInEditor(nsPresContext* aPresContext,
+                                            nsIContent* aContent,
+                                            nsIDOMMouseEvent* aMouseEvent)
+{
+  PR_LOG(sISMLog, PR_LOG_ALWAYS,
+    ("ISM: IMEStateManager::OnMouseButtonEventInEditor(aPresContext=0x%p, "
+     "aContent=0x%p, aMouseEvent=0x%p), sPresContext=0x%p, sContent=0x%p",
+     aPresContext, aContent, aMouseEvent, sPresContext, sContent));
+
+  if (sPresContext != aPresContext || sContent != aContent) {
+    PR_LOG(sISMLog, PR_LOG_DEBUG,
+      ("ISM:   IMEStateManager::OnMouseButtonEventInEditor(), "
+       "the mouse event isn't fired on the editor managed by ISM"));
+    return false;
+  }
+
+  if (!sActiveIMEContentObserver) {
+    PR_LOG(sISMLog, PR_LOG_DEBUG,
+      ("ISM:   IMEStateManager::OnMouseButtonEventInEditor(), "
+       "there is no active IMEContentObserver"));
+    return false;
+  }
+
+  if (!sActiveIMEContentObserver->IsManaging(aPresContext, aContent)) {
+    PR_LOG(sISMLog, PR_LOG_DEBUG,
+      ("ISM:   IMEStateManager::OnMouseButtonEventInEditor(), "
+       "the active IMEContentObserver isn't managing the editor"));
+    return false;
+  }
+
+  WidgetMouseEvent* internalEvent =
+    aMouseEvent->GetInternalNSEvent()->AsMouseEvent();
+  if (NS_WARN_IF(!internalEvent)) {
+    PR_LOG(sISMLog, PR_LOG_DEBUG,
+      ("ISM:   IMEStateManager::OnMouseButtonEventInEditor(), "
+       "the internal event of aMouseEvent isn't WidgetMouseEvent"));
+    return false;
+  }
+
+  bool consumed =
+    sActiveIMEContentObserver->OnMouseButtonEvent(aPresContext, internalEvent);
+
+#ifdef PR_LOGGING
+  nsAutoString eventType;
+  aMouseEvent->GetType(eventType);
+  PR_LOG(sISMLog, PR_LOG_ALWAYS,
+    ("ISM:   IMEStateManager::OnMouseButtonEventInEditor(), "
+     "mouse event (type=%s, button=%d) is %s",
+     NS_ConvertUTF16toUTF8(eventType).get(), internalEvent->button,
+     consumed ? "consumed" : "not consumed"));
+#endif
+
+  return consumed;
+}
+
+// static
 void
 IMEStateManager::OnClickInEditor(nsPresContext* aPresContext,
                                  nsIContent* aContent,
                                  nsIDOMMouseEvent* aMouseEvent)
 {
   PR_LOG(sISMLog, PR_LOG_ALWAYS,
     ("ISM: IMEStateManager::OnClickInEditor(aPresContext=0x%p, aContent=0x%p, "
      "aMouseEvent=0x%p), sPresContext=0x%p, sContent=0x%p",
--- a/dom/events/IMEStateManager.h
+++ b/dom/events/IMEStateManager.h
@@ -62,16 +62,23 @@ public:
                                            nsIContent** aRoot);
   // This method updates the current IME state.  However, if the enabled state
   // isn't changed by the new state, this method does nothing.
   // Note that this method changes the IME state of the active element in the
   // widget.  So, the caller must have focus.
   static void UpdateIMEState(const IMEState &aNewIMEState,
                              nsIContent* aContent);
 
+  // This method is called when user operates mouse button in focused editor
+  // and before the editor handles it.
+  // Returns true if IME consumes the event.  Otherwise, false.
+  static bool OnMouseButtonEventInEditor(nsPresContext* aPresContext,
+                                         nsIContent* aContent,
+                                         nsIDOMMouseEvent* aMouseEvent);
+
   // This method is called when user clicked in an editor.
   // aContent must be:
   //   If the editor is for <input> or <textarea>, the element.
   //   If the editor is for contenteditable, the active editinghost.
   //   If the editor is for designMode, nullptr.
   static void OnClickInEditor(nsPresContext* aPresContext,
                               nsIContent* aContent,
                               nsIDOMMouseEvent* aMouseEvent);
--- a/dom/inputmethod/forms.js
+++ b/dom/inputmethod/forms.js
@@ -13,16 +13,20 @@ let Cc = Components.classes;
 let Cu = Components.utils;
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import('resource://gre/modules/XPCOMUtils.jsm');
 XPCOMUtils.defineLazyServiceGetter(Services, "fm",
                                    "@mozilla.org/focus-manager;1",
                                    "nsIFocusManager");
 
+XPCOMUtils.defineLazyServiceGetter(Services, "threadManager",
+                                   "@mozilla.org/thread-manager;1",
+                                   "nsIThreadManager");
+
 XPCOMUtils.defineLazyGetter(this, "domWindowUtils", function () {
   return content.QueryInterface(Ci.nsIInterfaceRequestor)
                 .getInterface(Ci.nsIDOMWindowUtils);
 });
 
 const RESIZE_SCROLL_DELAY = 20;
 // In content editable node, when there are hidden elements such as <br>, it
 // may need more than one (usually less than 3 times) move/extend operations
@@ -245,19 +249,16 @@ let FormAssistant = {
       return;
 
     if (this.focusedElement) {
       this.focusedElement.removeEventListener('compositionend', this);
       if (this._observer) {
         this._observer.disconnect();
         this._observer = null;
       }
-      if (!element) {
-        this.focusedElement.blur();
-      }
       if (this._selectionPrivate) {
         this._selectionPrivate.removeSelectionListener(this);
         this._selectionPrivate = null;
       }
     }
 
     this._documentEncoder = null;
     if (this._editor) {
@@ -293,18 +294,19 @@ let FormAssistant = {
       let MutationObserver = element.ownerDocument.defaultView.MutationObserver;
       this._observer = new MutationObserver(function(mutations) {
         var del = [].some.call(mutations, function(m) {
           return [].some.call(m.removedNodes, function(n) {
             return n.contains(element);
           });
         });
         if (del && element === self.focusedElement) {
-          // item was deleted, fake a blur so all state gets set correctly
-          self.handleEvent({ target: element, type: "blur" });
+          self.hideKeyboard();
+          self.selectionStart = -1;
+          self.selectionEnd = -1;
         }
       });
 
       this._observer.observe(element.ownerDocument.body, {
         childList: true,
         subtree: true
       });
     }
@@ -373,18 +375,23 @@ let FormAssistant = {
       case "pagehide":
       case "beforeunload":
         // We are only interested to the pagehide and beforeunload events from
         // the root document.
         if (target && target != content.document) {
           break;
         }
         // fall through
+      case "submit":
+        if (this.focusedElement) {
+          this.focusedElement.blur();
+        }
+        break;
+
       case "blur":
-      case "submit":
         if (this.focusedElement) {
           this.hideKeyboard();
           this.selectionStart = -1;
           this.selectionEnd = -1;
         }
         break;
 
       case "resize":
@@ -429,16 +436,23 @@ let FormAssistant = {
           break;
         }
 
         CompositionManager.onCompositionEnd();
         break;
     }
   },
 
+  waitForNextTick: function(callback) {
+    var tm = Services.threadManager;
+    tm.mainThread.dispatch({
+      run: callback,
+    }, Components.interfaces.nsIThread.DISPATCH_NORMAL);
+  },
+
   receiveMessage: function fa_receiveMessage(msg) {
     let target = this.focusedElement;
     let json = msg.json;
 
     // To not break mozKeyboard contextId is optional
     if ('contextId' in json &&
         json.contextId !== this._focusCounter &&
         json.requestId) {
@@ -531,17 +545,20 @@ let FormAssistant = {
         if (valueChanged) {
           let event = target.ownerDocument.createEvent('HTMLEvents');
           event.initEvent('change', true, true);
           target.dispatchEvent(event);
         }
         break;
 
       case "Forms:Select:Blur": {
-        this.setFocusedElement(null);
+        if (this.focusedElement) {
+          this.focusedElement.blur();
+        }
+
         break;
       }
 
       case "Forms:SetSelectionRange":  {
         CompositionManager.endComposition('');
 
         let start = json.selectionStart;
         let end =  json.selectionEnd;
@@ -650,19 +667,30 @@ let FormAssistant = {
     this.setFocusedElement(target);
 
     let kbOpened = this.sendKeyboardState(target);
     if (this.isTextInputElement(target))
       this.isKeyboardOpened = kbOpened;
   },
 
   hideKeyboard: function fa_hideKeyboard() {
-    sendAsyncMessage("Forms:Input", { "type": "blur" });
-    this.isKeyboardOpened = false;
-    this.setFocusedElement(null);
+    var element = this.focusedElement;
+
+    // Wait for the next tick before unset the focused element and etc.
+    // If the user move from one input from another,
+    // the remote process should get one Forms:Input message instead of two.
+    this.waitForNextTick(function() {
+      if (element !== this.focusedElement) {
+        return;
+      }
+
+      this.isKeyboardOpened = false;
+      this.setFocusedElement(null);
+      sendAsyncMessage("Forms:Input", { "type": "blur" });
+    }.bind(this));
   },
 
   isFocusableElement: function fa_isFocusableElement(element) {
     if (element instanceof HTMLSelectElement ||
         element instanceof HTMLTextAreaElement)
       return true;
 
     if (element instanceof HTMLOptionElement &&
@@ -733,17 +761,17 @@ let FormAssistant = {
   _selectionTimeout: null,
 
   // Notify when the selection range changes
   updateSelection: function fa_updateSelection() {
     // A call to setSelectionRange on input field causes 2 selection changes
     // one to [0,0] and one to actual value. Both are sent in same tick.
     // Prevent firing two events in that scenario, always only use the last 1.
     //
-    // It is also a workaround for Bug 1053048, which prevents 
+    // It is also a workaround for Bug 1053048, which prevents
     // getSelectionInfo() accessing selectionStart or selectionEnd in the
     // callback function of nsISelectionListener::NotifySelectionChanged().
     if (this._selectionTimeout) {
       content.clearTimeout(this._selectionTimeout);
     }
     this._selectionTimeout = content.setTimeout(function() {
       if (!this.focusedElement) {
         return;
--- a/dom/inputmethod/mochitest/mochitest.ini
+++ b/dom/inputmethod/mochitest/mochitest.ini
@@ -14,8 +14,9 @@ support-files =
 [test_bug949059.html]
 [test_bug953044.html]
 [test_bug960946.html]
 [test_bug978918.html]
 [test_bug1026997.html]
 [test_bug1043828.html]
 [test_delete_focused_element.html]
 [test_sendkey_cancel.html]
+[test_two_inputs.html]
--- a/dom/inputmethod/mochitest/test_delete_focused_element.html
+++ b/dom/inputmethod/mochitest/test_delete_focused_element.html
@@ -29,17 +29,20 @@ function appFrameScript() {
   content.document.body.appendChild(textarea);
 
   textarea.onfocus = function() {
     textarea.parentNode.removeChild(textarea);
     sendAsyncMessage('test:InputMethod:finished', {});
   };
 
   content.setTimeout(function() {
-    textarea.focus();
+    content.setTimeout(function() {
+      textarea.focus();
+    }, 10);
+
     input.parentNode.removeChild(input);
   }, 0);
 }
 
 function runTest() {
   var timeoutId = null;
 
   // Create an app frame to recieve keyboard inputs.
new file mode 100644
--- /dev/null
+++ b/dom/inputmethod/mochitest/test_two_inputs.html
@@ -0,0 +1,106 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1057898
+-->
+<head>
+  <title>Test switching between two inputs</title>
+  <script type="application/javascript;version=1.7" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript;version=1.7" src="inputmethod_common.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=932145">Mozilla Bug 932145</a>
+<p id="display"></p>
+<pre id="test">
+<script class="testbody" type="application/javascript;version=1.7">
+
+// The input context.
+var gContext = null;
+
+inputmethod_setup(function() {
+  runTest();
+});
+
+let appFrameScript = function appFrameScript() {
+  let input1 = content.document.body.firstElementChild;
+  let input2 = content.document.body.children[1];
+
+  let i = 0;
+
+  input1.focus();
+
+  addMessageListener('test:next', function() {
+    i++;
+    switch (i) {
+      case 1:
+        input2.focus();
+
+        break;
+
+      case 2:
+        input2.blur();
+
+        break;
+    }
+  });
+};
+
+function runTest() {
+  let im = navigator.mozInputMethod;
+
+  let i = 0;
+  im.oninputcontextchange = function(evt) {
+    var inputcontext = navigator.mozInputMethod.inputcontext;
+
+    i++;
+    switch (i) {
+      case 1:
+        ok(!!inputcontext, 'Receving the first input context');
+        is(inputcontext.textAfterCursor, 'First');
+
+        mm.sendAsyncMessage('test:next');
+        break;
+
+      case 2:
+        ok(!!inputcontext, 'Receving the second input context');
+        is(inputcontext.textAfterCursor, 'Second');
+
+
+        mm.sendAsyncMessage('test:next');
+        break;
+
+      case 3:
+        is(inputcontext, null, 'Receving null inputcontext');
+
+        inputmethod_cleanup();
+        break;
+
+      default:
+        ok(false, 'Receving extra inputcontextchange calls');
+        inputmethod_cleanup();
+
+        break;
+    }
+  };
+
+  // Set current page as an input method.
+  SpecialPowers.wrap(im).setActive(true);
+
+  let iframe = document.createElement('iframe');
+  iframe.src = 'data:text/html,<html><body><input value="First"><input value="Second"></body></html>';
+  iframe.setAttribute('mozbrowser', true);
+  document.body.appendChild(iframe);
+
+  let mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
+
+  iframe.addEventListener('mozbrowserloadend', function() {
+    mm.loadFrameScript('data:,(' + encodeURIComponent(appFrameScript.toString()) + ')();', false);
+  });
+}
+
+</script>
+</pre>
+</body>
+</html>
+
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -2347,71 +2347,70 @@ ContentParent::RecvFirstIdle()
 
 bool
 ContentParent::RecvAudioChannelGetState(const AudioChannel& aChannel,
                                         const bool& aElementHidden,
                                         const bool& aElementWasHidden,
                                         AudioChannelState* aState)
 {
     nsRefPtr<AudioChannelService> service =
-        AudioChannelService::GetAudioChannelService();
+        AudioChannelService::GetOrCreateAudioChannelService();
     *aState = AUDIO_CHANNEL_STATE_NORMAL;
-    if (service) {
-        *aState = service->GetStateInternal(aChannel, mChildID,
-                                            aElementHidden, aElementWasHidden);
-    }
+    MOZ_ASSERT(service);
+    *aState = service->GetStateInternal(aChannel, mChildID,
+                                        aElementHidden, aElementWasHidden);
+
     return true;
 }
 
 bool
 ContentParent::RecvAudioChannelRegisterType(const AudioChannel& aChannel,
                                             const bool& aWithVideo)
 {
     nsRefPtr<AudioChannelService> service =
-        AudioChannelService::GetAudioChannelService();
-    if (service) {
-        service->RegisterType(aChannel, mChildID, aWithVideo);
-    }
+        AudioChannelService::GetOrCreateAudioChannelService();
+    MOZ_ASSERT(service);
+    service->RegisterType(aChannel, mChildID, aWithVideo);
+
     return true;
 }
 
 bool
 ContentParent::RecvAudioChannelUnregisterType(const AudioChannel& aChannel,
                                               const bool& aElementHidden,
                                               const bool& aWithVideo)
 {
     nsRefPtr<AudioChannelService> service =
-        AudioChannelService::GetAudioChannelService();
-    if (service) {
-        service->UnregisterType(aChannel, aElementHidden, mChildID, aWithVideo);
-    }
+        AudioChannelService::GetOrCreateAudioChannelService();
+    MOZ_ASSERT(service);
+    service->UnregisterType(aChannel, aElementHidden, mChildID, aWithVideo);
+
     return true;
 }
 
 bool
 ContentParent::RecvAudioChannelChangedNotification()
 {
     nsRefPtr<AudioChannelService> service =
-        AudioChannelService::GetAudioChannelService();
-    if (service) {
-       service->SendAudioChannelChangedNotification(ChildID());
-    }
+        AudioChannelService::GetOrCreateAudioChannelService();
+    MOZ_ASSERT(service);
+    service->SendAudioChannelChangedNotification(ChildID());
+
     return true;
 }
 
 bool
 ContentParent::RecvAudioChannelChangeDefVolChannel(const int32_t& aChannel,
                                                    const bool& aHidden)
 {
     nsRefPtr<AudioChannelService> service =
-        AudioChannelService::GetAudioChannelService();
-    if (service) {
-       service->SetDefaultVolumeControlChannelInternal(aChannel,
-                                                       aHidden, mChildID);
-    }
+        AudioChannelService::GetOrCreateAudioChannelService();
+    MOZ_ASSERT(service);
+    service->SetDefaultVolumeControlChannelInternal(aChannel,
+                                                    aHidden, mChildID);
     return true;
 }
 
 bool
 ContentParent::RecvDataStoreGetStores(
                                     const nsString& aName,
                                     const nsString& aOwner,
                                     const IPC::Principal& aPrincipal,
--- a/dom/ipc/ProcessPriorityManager.cpp
+++ b/dom/ipc/ProcessPriorityManager.cpp
@@ -990,17 +990,17 @@ ParticularProcessPriorityManager::Comput
       PROCESS_PRIORITY_FOREGROUND;
   }
 
   if ((mHoldsCPUWakeLock || mHoldsHighPriorityWakeLock) &&
       IsExpectingSystemMessage()) {
     return PROCESS_PRIORITY_BACKGROUND_PERCEIVABLE;
   }
 
-  AudioChannelService* service = AudioChannelService::GetAudioChannelService();
+  AudioChannelService* service = AudioChannelService::GetOrCreateAudioChannelService();
   if (service->ProcessContentOrNormalChannelIsActive(ChildID())) {
     return PROCESS_PRIORITY_BACKGROUND_PERCEIVABLE;
   }
 
   return HasAppType("homescreen") ?
          PROCESS_PRIORITY_BACKGROUND_HOMESCREEN :
          PROCESS_PRIORITY_BACKGROUND;
 }
--- a/dom/speakermanager/SpeakerManager.cpp
+++ b/dom/speakermanager/SpeakerManager.cpp
@@ -196,17 +196,17 @@ SpeakerManager::HandleEvent(nsIDOMEvent*
   if (mVisible && mForcespeaker) {
     service->ForceSpeaker(mForcespeaker, mVisible);
   }
   // If an application that has called forcespeaker=true, but no audio is
   // currently playing in the app itself, if application switch to
   // the background, we switch 'speakerforced' to false.
   if (!mVisible && mForcespeaker) {
     AudioChannelService* audioChannelService =
-      AudioChannelService::GetAudioChannelService();
+      AudioChannelService::GetOrCreateAudioChannelService();
     if (audioChannelService && !audioChannelService->AnyAudioChannelIsActive()) {
       service->ForceSpeaker(false, mVisible);
     }
   }
   return NS_OK;
 }
 
 void
--- a/dom/speakermanager/SpeakerManagerService.cpp
+++ b/dom/speakermanager/SpeakerManagerService.cpp
@@ -189,22 +189,22 @@ SpeakerManagerService::SpeakerManagerSer
   MOZ_COUNT_CTOR(SpeakerManagerService);
   if (XRE_GetProcessType() == GeckoProcessType_Default) {
     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
     if (obs) {
       obs->AddObserver(this, "ipc:content-shutdown", false);
     }
   }
   AudioChannelService* audioChannelService =
-    AudioChannelService::GetAudioChannelService();
+    AudioChannelService::GetOrCreateAudioChannelService();
   if (audioChannelService) {
     audioChannelService->RegisterSpeakerManager(this);
   }
 }
 
 SpeakerManagerService::~SpeakerManagerService()
 {
   MOZ_COUNT_DTOR(SpeakerManagerService);
   AudioChannelService* audioChannelService =
-    AudioChannelService::GetAudioChannelService();
+    AudioChannelService::GetOrCreateAudioChannelService();
   if (audioChannelService)
     audioChannelService->UnregisterSpeakerManager(this);
 }
--- a/dom/speakermanager/SpeakerManagerServiceChild.cpp
+++ b/dom/speakermanager/SpeakerManagerServiceChild.cpp
@@ -91,26 +91,26 @@ SpeakerManagerServiceChild::SetAudioChan
   for (uint32_t i = 0; i < mRegisteredSpeakerManagers.Length(); i++) {
     mRegisteredSpeakerManagers[i]->SetAudioChannelActive(aIsActive);
   }
 }
 
 SpeakerManagerServiceChild::SpeakerManagerServiceChild()
 {
   MOZ_ASSERT(NS_IsMainThread());
-  AudioChannelService* audioChannelService = AudioChannelService::GetAudioChannelService();
+  AudioChannelService* audioChannelService = AudioChannelService::GetOrCreateAudioChannelService();
   if (audioChannelService) {
     audioChannelService->RegisterSpeakerManager(this);
   }
   MOZ_COUNT_CTOR(SpeakerManagerServiceChild);
 }
 
 SpeakerManagerServiceChild::~SpeakerManagerServiceChild()
 {
-  AudioChannelService* audioChannelService = AudioChannelService::GetAudioChannelService();
+  AudioChannelService* audioChannelService = AudioChannelService::GetOrCreateAudioChannelService();
   if (audioChannelService) {
     audioChannelService->UnregisterSpeakerManager(this);
   }
   MOZ_COUNT_DTOR(SpeakerManagerServiceChild);
 }
 
 void
 SpeakerManagerServiceChild::Notify()
--- a/dom/system/gonk/AudioChannelManager.cpp
+++ b/dom/system/gonk/AudioChannelManager.cpp
@@ -127,17 +127,17 @@ void
 AudioChannelManager::NotifyVolumeControlChannelChanged()
 {
   nsCOMPtr<nsIDocShell> docshell = do_GetInterface(GetOwner());
   NS_ENSURE_TRUE_VOID(docshell);
 
   bool isActive = false;
   docshell->GetIsActive(&isActive);
 
-  AudioChannelService* service = AudioChannelService::GetAudioChannelService();
+  AudioChannelService* service = AudioChannelService::GetOrCreateAudioChannelService();
   if (isActive) {
     service->SetDefaultVolumeControlChannel(mVolumeChannel, isActive);
   } else {
     service->SetDefaultVolumeControlChannel(-1, isActive);
   }
 }
 
 NS_IMETHODIMP
--- a/dom/system/gonk/AudioManager.cpp
+++ b/dom/system/gonk/AudioManager.cpp
@@ -311,18 +311,18 @@ AudioManager::HandleAudioChannelProcessC
   // be called again and therefore the audio manager sets the
   // PHONE_STATE_IN_COMMUNICATION audio state.
 
   if ((mPhoneState == PHONE_STATE_IN_CALL) ||
       (mPhoneState == PHONE_STATE_RINGTONE)) {
     return;
   }
 
-  AudioChannelService *service = AudioChannelService::GetAudioChannelService();
-  NS_ENSURE_TRUE_VOID(service);
+  AudioChannelService *service = AudioChannelService::GetOrCreateAudioChannelService();
+  MOZ_ASSERT(service);
 
   bool telephonyChannelIsActive = service->TelephonyChannelIsActive();
   telephonyChannelIsActive ? SetPhoneState(PHONE_STATE_IN_COMMUNICATION) :
                              SetPhoneState(PHONE_STATE_NORMAL);
 }
 
 nsresult
 AudioManager::Observe(nsISupports* aSubject,
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -2583,17 +2583,17 @@ RilObject.prototype = {
       case MMI_SC_BAOICxH:
       case MMI_SC_BAIC:
       case MMI_SC_BAICr:
       case MMI_SC_BA_ALL:
       case MMI_SC_BA_MO:
       case MMI_SC_BA_MT:
         return MMI_KS_SC_CALL_BARRING;
       case MMI_SC_CALL_WAITING:
-        return MMI_SC_CALL_WAITING;
+        return MMI_KS_SC_CALL_WAITING;
       default:
         return MMI_KS_SC_USSD;
     }
   },
 
   sendMMI: function(options) {
     if (DEBUG) {
       this.context.debug("SendMMI " + JSON.stringify(options));
--- a/dom/tests/mochitest/general/test_interfaces.html
+++ b/dom/tests/mochitest/general/test_interfaces.html
@@ -73,31 +73,36 @@ var ecmaGlobals =
     "RangeError",
     "ReferenceError",
     "RegExp",
     "Set",
     {name: "SharedArrayBuffer", nightly: true},
     {name: "SIMD", nightly: true},
     "StopIteration",
     "String",
-    "Symbol",
     "SyntaxError",
     {name: "TypedObject", nightly: true},
     "TypeError",
     "Uint16Array",
     "Uint32Array",
     "Uint8Array",
     "Uint8ClampedArray",
     "URIError",
     "WeakMap",
     "WeakSet",
   ];
 // IMPORTANT: Do not change the list above without review from
 //            a JavaScript Engine peer!
 
+// Symbol is conditionally defined.
+// If it's defined, insert "Symbol" before "SyntaxError".
+if (typeof Symbol === "function") {
+  ecmaGlobals.splice(ecmaGlobals.indexOf("SyntaxError"), 0, "Symbol");
+}
+
 // IMPORTANT: Do not change the list below without review from a DOM peer,
 //            except to remove items from it!
 //
 // This is a list of interfaces that were prefixed with 'moz' instead of 'Moz'.
 // We should never to that again, interfaces in the DOM start with an uppercase
 // letter. If you think you need to add an interface here, DON'T. Rename your
 // interface.
 var legacyMozPrefixedInterfaces =
--- a/dom/wifi/WifiWorker.js
+++ b/dom/wifi/WifiWorker.js
@@ -1158,30 +1158,55 @@ var WifiManager = (function() {
     }
   }
 
   manager.disconnect = wifiCommand.disconnect;
   manager.reconnect = wifiCommand.reconnect;
   manager.reassociate = wifiCommand.reassociate;
 
   var networkConfigurationFields = [
-    "ssid", "bssid", "psk", "wep_key0", "wep_key1", "wep_key2", "wep_key3",
-    "wep_tx_keyidx", "priority", "key_mgmt", "scan_ssid", "disabled",
-    "identity", "password", "auth_alg", "phase1", "phase2", "eap", "pin",
-    "pcsc", "ca_cert", "subject_match"
+    {name: "ssid",          type: "string"},
+    {name: "bssid",         type: "string"},
+    {name: "psk",           type: "string"},
+    {name: "wep_key0",      type: "string"},
+    {name: "wep_key1",      type: "string"},
+    {name: "wep_key2",      type: "string"},
+    {name: "wep_key3",      type: "string"},
+    {name: "wep_tx_keyidx", type: "integer"},
+    {name: "priority",      type: "integer"},
+    {name: "key_mgmt",      type: "string"},
+    {name: "scan_ssid",     type: "string"},
+    {name: "disabled",      type: "integer"},
+    {name: "identity",      type: "string"},
+    {name: "password",      type: "string"},
+    {name: "auth_alg",      type: "string"},
+    {name: "phase1",        type: "string"},
+    {name: "phase2",        type: "string"},
+    {name: "eap",           type: "string"},
+    {name: "pin",           type: "string"},
+    {name: "pcsc",          type: "string"},
+    {name: "ca_cert",       type: "string"},
+    {name: "subject_match", type: "string"}
   ];
 
   manager.getNetworkConfiguration = function(config, callback) {
     var netId = config.netId;
     var done = 0;
     for (var n = 0; n < networkConfigurationFields.length; ++n) {
-      let fieldName = networkConfigurationFields[n];
+      let fieldName = networkConfigurationFields[n].name;
+      let fieldType = networkConfigurationFields[n].type;
       wifiCommand.getNetworkVariable(netId, fieldName, function(value) {
-        if (value !== null)
-          config[fieldName] = value;
+        if (value !== null) {
+          if (fieldType === "integer") {
+            config[fieldName] = parseInt(value, 10);
+          } else {
+            // value is string type by default.
+            config[fieldName] = value;
+          }
+        }
         if (++done == networkConfigurationFields.length)
           callback(config);
       });
     }
   }
   manager.setNetworkConfiguration = function(config, callback) {
     var netId = config.netId;
     var done = 0;
@@ -1190,17 +1215,17 @@ var WifiManager = (function() {
     function hasValidProperty(name) {
       return ((name in config) &&
                config[name] != null &&
                (["password", "wep_key0", "psk"].indexOf(name) === -1 ||
                 config[name] !== '*'));
     }
 
     for (var n = 0; n < networkConfigurationFields.length; ++n) {
-      let fieldName = networkConfigurationFields[n];
+      let fieldName = networkConfigurationFields[n].name;
       if (!hasValidProperty(fieldName)) {
         ++done;
       } else {
         wifiCommand.setNetworkVariable(netId, fieldName, config[fieldName], function(ok) {
           if (!ok)
             ++errors;
           if (++done == networkConfigurationFields.length)
             callback(errors == 0);
@@ -2513,18 +2538,20 @@ WifiWorker.prototype = {
         let network = networks[net];
         delete networks[net];
 
         if (!network.ssid) {
           WifiManager.removeNetwork(network.netId, function() {});
           continue;
         }
 
-        if (network.priority && network.priority > this._highestPriority)
+        if (network.hasOwnProperty("priority") &&
+            network.priority > this._highestPriority) {
           this._highestPriority = network.priority;
+        }
 
         let networkKey = getNetworkKey(network);
         // Accept latest config of same network(same SSID and same security).
         if (networks[networkKey]) {
           WifiManager.removeNetwork(networks[networkKey].netId, function() {});
         }
         networks[networkKey] = network;
       }
@@ -3143,16 +3170,20 @@ WifiWorker.prototype = {
     if (networkKey in this.configuredNetworks)
       configured = this.configuredNetworks[networkKey];
 
     netFromDOM(privnet, configured);
 
     privnet.priority = ++this._highestPriority;
     if (configured) {
       privnet.netId = configured.netId;
+      // Sync priority back to configured so if priority reaches MAX_PRIORITY,
+      // it can be sorted correctly in _reprioritizeNetworks() because the
+      // function sort network based on priority in configure list.
+      configured.priority = privnet.priority;
       WifiManager.updateNetwork(privnet, (function(ok) {
         if (!ok) {
           this._sendMessage(message, false, "Network is misconfigured", msg);
           return;
         }
 
         networkReady();
       }).bind(this));
--- a/dom/workers/test/test_worker_interfaces.js
+++ b/dom/workers/test/test_worker_interfaces.js
@@ -47,31 +47,36 @@ var ecmaGlobals =
     "RangeError",
     "ReferenceError",
     "RegExp",
     "Set",
     {name: "SharedArrayBuffer", nightly: true},
     {name: "SIMD", nightly: true},
     "StopIteration",
     "String",
-    "Symbol",
     "SyntaxError",
     {name: "TypedObject", nightly: true},
     "TypeError",
     "Uint16Array",
     "Uint32Array",
     "Uint8Array",
     "Uint8ClampedArray",
     "URIError",
     "WeakMap",
     "WeakSet",
   ];
 // IMPORTANT: Do not change the list above without review from
 //            a JavaScript Engine peer!
 
+// Symbol is conditionally defined.
+// If it's defined, insert "Symbol" before "SyntaxError".
+if (typeof Symbol === "function") {
+  ecmaGlobals.splice(ecmaGlobals.indexOf("SyntaxError"), 0, "Symbol");
+}
+
 // IMPORTANT: Do not change the list below without review from a DOM peer!
 var interfaceNamesInGlobalScope =
   [
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "Blob",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "DedicatedWorkerGlobalScope",
 // IMPORTANT: Do not change this list without review from a DOM peer!
--- a/editor/libeditor/ChangeAttributeTxn.cpp
+++ b/editor/libeditor/ChangeAttributeTxn.cpp
@@ -1,109 +1,92 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/dom/Element.h"        // for Element
+
 #include "ChangeAttributeTxn.h"
 #include "nsAString.h"
-#include "nsDebug.h"                    // for NS_ASSERTION
 #include "nsError.h"                    // for NS_ERROR_NOT_INITIALIZED, etc
-#include "nsIDOMElement.h"              // for nsIDOMElement
-#include "nsIEditor.h"                  // for nsIEditor
-#include "nsString.h"                   // for nsString
+
+using namespace mozilla;
+using namespace mozilla::dom;
 
-ChangeAttributeTxn::ChangeAttributeTxn()
+ChangeAttributeTxn::ChangeAttributeTxn(Element& aElement, nsIAtom& aAttribute,
+                                       const nsAString* aValue)
   : EditTxn()
+  , mElement(&aElement)
+  , mAttribute(&aAttribute)
+  , mValue(aValue ? *aValue : EmptyString())
+  , mRemoveAttribute(!aValue)
+  , mAttributeWasSet(false)
+  , mUndoValue()
 {
 }
 
 ChangeAttributeTxn::~ChangeAttributeTxn()
 {
 }
 
 NS_IMPL_CYCLE_COLLECTION_INHERITED(ChangeAttributeTxn, EditTxn,
                                    mElement)
 
 NS_IMPL_ADDREF_INHERITED(ChangeAttributeTxn, EditTxn)
 NS_IMPL_RELEASE_INHERITED(ChangeAttributeTxn, EditTxn)
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ChangeAttributeTxn)
 NS_INTERFACE_MAP_END_INHERITING(EditTxn)
 
-NS_IMETHODIMP ChangeAttributeTxn::Init(nsIEditor      *aEditor,
-                                       nsIDOMElement  *aElement,
-                                       const nsAString& aAttribute,
-                                       const nsAString& aValue,
-                                       bool aRemoveAttribute)
+NS_IMETHODIMP
+ChangeAttributeTxn::DoTransaction()
 {
-  NS_ASSERTION(aEditor && aElement, "bad arg");
-  if (!aEditor || !aElement) { return NS_ERROR_NULL_POINTER; }
+  // Need to get the current value of the attribute and save it, and set
+  // mAttributeWasSet
+  mAttributeWasSet = mElement->GetAttr(kNameSpaceID_None, mAttribute,
+                                       mUndoValue);
 
-  mEditor = aEditor;
-  mElement = do_QueryInterface(aElement);
-  mAttribute = aAttribute;
-  mValue = aValue;
-  mRemoveAttribute = aRemoveAttribute;
-  mAttributeWasSet=false;
-  mUndoValue.Truncate();
-  return NS_OK;
+  // XXX: hack until attribute-was-set code is implemented
+  if (!mUndoValue.IsEmpty()) {
+    mAttributeWasSet = true;
+  }
+  // XXX: end hack
+
+  // Now set the attribute to the new value
+  if (mRemoveAttribute) {
+    return mElement->UnsetAttr(kNameSpaceID_None, mAttribute, true);
+  }
+
+  return mElement->SetAttr(kNameSpaceID_None, mAttribute, mValue, true);
 }
 
-NS_IMETHODIMP ChangeAttributeTxn::DoTransaction(void)
+NS_IMETHODIMP
+ChangeAttributeTxn::UndoTransaction()
 {
-  NS_ASSERTION(mEditor && mElement, "bad state");
-  if (!mEditor || !mElement) { return NS_ERROR_NOT_INITIALIZED; }
-
-  // need to get the current value of the attribute and save it, and set mAttributeWasSet
-  nsresult result = mEditor->GetAttributeValue(mElement, mAttribute, mUndoValue, &mAttributeWasSet);
-  // XXX: hack until attribute-was-set code is implemented
-  if (!mUndoValue.IsEmpty())
-    mAttributeWasSet = true;
-  // XXX: end hack
-  
-  // now set the attribute to the new value
-  if (!mRemoveAttribute)
-    result = mElement->SetAttribute(mAttribute, mValue);
-  else
-    result = mElement->RemoveAttribute(mAttribute);
-
-  return result;
+  if (mAttributeWasSet) {
+    return mElement->SetAttr(kNameSpaceID_None, mAttribute, mUndoValue, true);
+  }
+  return mElement->UnsetAttr(kNameSpaceID_None, mAttribute, true);
 }
 
-NS_IMETHODIMP ChangeAttributeTxn::UndoTransaction(void)
+NS_IMETHODIMP
+ChangeAttributeTxn::RedoTransaction()
 {
-  NS_ASSERTION(mEditor && mElement, "bad state");
-  if (!mEditor || !mElement) { return NS_ERROR_NOT_INITIALIZED; }
+  if (mRemoveAttribute) {
+    return mElement->UnsetAttr(kNameSpaceID_None, mAttribute, true);
+  }
 
-  nsresult result;
-  if (mAttributeWasSet)
-    result = mElement->SetAttribute(mAttribute, mUndoValue);
-  else
-    result = mElement->RemoveAttribute(mAttribute);
-
-  return result;
+  return mElement->SetAttr(kNameSpaceID_None, mAttribute, mValue, true);
 }
 
-NS_IMETHODIMP ChangeAttributeTxn::RedoTransaction(void)
-{
-  NS_ASSERTION(mEditor && mElement, "bad state");
-  if (!mEditor || !mElement) { return NS_ERROR_NOT_INITIALIZED; }
-
-  nsresult result;
-  if (!mRemoveAttribute)
-    result = mElement->SetAttribute(mAttribute, mValue);
-  else
-    result = mElement->RemoveAttribute(mAttribute);
-
-  return result;
-}
-
-NS_IMETHODIMP ChangeAttributeTxn::GetTxnDescription(nsAString& aString)
+NS_IMETHODIMP
+ChangeAttributeTxn::GetTxnDescription(nsAString& aString)
 {
   aString.AssignLiteral("ChangeAttributeTxn: [mRemoveAttribute == ");
 
-  if (!mRemoveAttribute)
+  if (mRemoveAttribute) {
+    aString.AppendLiteral("true] ");
+  } else {
     aString.AppendLiteral("false] ");
-  else
-    aString.AppendLiteral("true] ");
-  aString += mAttribute;
+  }
+  aString += nsDependentAtomString(mAttribute);
   return NS_OK;
 }
--- a/editor/libeditor/ChangeAttributeTxn.h
+++ b/editor/libeditor/ChangeAttributeTxn.h
@@ -1,73 +1,69 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/. */
 
 #ifndef ChangeAttributeTxn_h__
 #define ChangeAttributeTxn_h__
 
-#include "EditTxn.h"
-#include "nsCOMPtr.h"
-#include "nsCycleCollectionParticipant.h"
-#include "nsIDOMElement.h"
-#include "nsISupportsImpl.h"
-#include "nsString.h"
-#include "nscore.h"
+#include "EditTxn.h"                      // base class
+#include "mozilla/Attributes.h"           // MOZ_OVERRIDE
+#include "nsCOMPtr.h"                     // nsCOMPtr members
+#include "nsCycleCollectionParticipant.h" // NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED
+#include "nsISupportsImpl.h"              // NS_DECL_ISUPPORTS_INHERITED
+#include "nsString.h"                     // nsString members
 
-class nsIEditor;
+class nsIAtom;
+
+namespace mozilla {
+namespace dom {
+
+class Element;
 
 /**
- * A transaction that changes an attribute of a content node. 
- * This transaction covers add, remove, and change attribute.
+ * A transaction that changes an attribute of a content node.  This transaction
+ * covers add, remove, and change attribute.
  */
 class ChangeAttributeTxn : public EditTxn
 {
 public:
-  /** Initialize the transaction.
-    * @param aEditor the object providing core editing operations
-    * @param aNode   the node whose attribute will be changed
+  /** @param aElement the element whose attribute will be changed
     * @param aAttribute the name of the attribute to change
-    * @param aValue     the new value for aAttribute, if aRemoveAttribute is false
-    * @param aRemoveAttribute if true, remove aAttribute from aNode
+    * @param aValue     the new value for aAttribute, or null to remove
     */
-  NS_IMETHOD Init(nsIEditor      *aEditor,
-                  nsIDOMElement  *aNode,
-                  const nsAString& aAttribute,
-                  const nsAString& aValue,
-                  bool aRemoveAttribute);
-
-  ChangeAttributeTxn();
+  ChangeAttributeTxn(Element& aElement, nsIAtom& aAttribute,
+                     const nsAString* aValue);
 
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ChangeAttributeTxn, EditTxn)
 
   NS_DECL_EDITTXN
 
-  NS_IMETHOD RedoTransaction();
+  NS_IMETHOD RedoTransaction() MOZ_OVERRIDE;
 
-protected:
+private:
   virtual ~ChangeAttributeTxn();
 
-  /** the editor that created this transaction */
-  nsIEditor*  mEditor;
-  
-  /** the element to operate upon */
-  nsCOMPtr<nsIDOMElement> mElement;
-  
-  /** the attribute to change */
-  nsString mAttribute;
+  /** The element to operate upon */
+  nsCOMPtr<Element> mElement;
 
-  /** the value to set the attribute to (ignored if mRemoveAttribute==true) */
+  /** The attribute to change */
+  nsCOMPtr<nsIAtom> mAttribute;
+
+  /** The value to set the attribute to (ignored if mRemoveAttribute==true) */
   nsString mValue;
 
-  /** the value to set the attribute to for undo */
-  nsString mUndoValue;
+  /** True if the operation is to remove mAttribute from mElement */
+  bool mRemoveAttribute;
 
-  /** true if the mAttribute was set on mElement at the time of execution */
-  bool     mAttributeWasSet;
+  /** True if the mAttribute was set on mElement at the time of execution */
+  bool mAttributeWasSet;
 
-  /** true if the operation is to remove mAttribute from mElement */
-  bool     mRemoveAttribute;
+  /** The value to set the attribute to for undo */
+  nsString mUndoValue;
 };
 
+}
+}
+
 #endif
rename from editor/libeditor/ChangeCSSInlineStyleTxn.cpp
rename to editor/libeditor/ChangeStyleTxn.cpp
--- a/editor/libeditor/ChangeCSSInlineStyleTxn.cpp
+++ b/editor/libeditor/ChangeStyleTxn.cpp
@@ -1,315 +1,299 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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 "ChangeCSSInlineStyleTxn.h"
+#include "ChangeStyleTxn.h"
+
+#include "mozilla/dom/Element.h"        // for Element
 #include "nsAString.h"                  // for nsAString_internal::Append, etc
-#include "nsCRT.h"                      // for nsCRT
+#include "nsCRT.h"                      // for nsCRT::IsAsciiSpace
 #include "nsDebug.h"                    // for NS_ENSURE_SUCCESS, etc
 #include "nsError.h"                    // for NS_ERROR_NULL_POINTER, etc
 #include "nsGkAtoms.h"                  // for nsGkAtoms, etc
-#include "nsIAtom.h"                    // for nsIAtom
 #include "nsIDOMCSSStyleDeclaration.h"  // for nsIDOMCSSStyleDeclaration
-#include "nsIDOMElement.h"              // for nsIDOMElement
-#include "nsIDOMElementCSSInlineStyle.h"
-#include "nsISupportsImpl.h"            // for EditTxn::QueryInterface, etc
-#include "nsISupportsUtils.h"           // for NS_ADDREF
+#include "nsIDOMElementCSSInlineStyle.h" // for nsIDOMElementCSSInlineStyle
 #include "nsLiteralString.h"            // for NS_LITERAL_STRING, etc
 #include "nsReadableUtils.h"            // for ToNewUnicode
 #include "nsString.h"                   // for nsAutoString, nsString, etc
-#include "nsUnicharUtils.h"
+#include "nsUnicharUtils.h"             // for nsCaseInsensitiveStringComparator
 #include "nsXPCOM.h"                    // for NS_Free
 
-class nsIEditor;
+using namespace mozilla;
+using namespace mozilla::dom;
 
 #define kNullCh (char16_t('\0'))
 
-NS_IMPL_CYCLE_COLLECTION_INHERITED(ChangeCSSInlineStyleTxn, EditTxn,
-                                   mElement)
+NS_IMPL_CYCLE_COLLECTION_INHERITED(ChangeStyleTxn, EditTxn, mElement)
 
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ChangeCSSInlineStyleTxn)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ChangeStyleTxn)
 NS_INTERFACE_MAP_END_INHERITING(EditTxn)
 
-// answers true if aValue is in the string list of white-space separated values aValueList
-// a case-sensitive search is performed if aCaseSensitive is true
+NS_IMPL_ADDREF_INHERITED(ChangeStyleTxn, EditTxn)
+NS_IMPL_RELEASE_INHERITED(ChangeStyleTxn, EditTxn)
+
+ChangeStyleTxn::~ChangeStyleTxn()
+{
+}
+
+// Answers true if aValue is in the string list of white-space separated values
+// aValueList.
 bool
-ChangeCSSInlineStyleTxn::ValueIncludes(const nsAString &aValueList, const nsAString &aValue, bool aCaseSensitive)
+ChangeStyleTxn::ValueIncludes(const nsAString &aValueList,
+                              const nsAString &aValue)
 {
-  nsAutoString  valueList(aValueList);
+  nsAutoString valueList(aValueList);
   bool result = false;
 
-  valueList.Append(kNullCh);  // put an extra null at the end
+  // put an extra null at the end
+  valueList.Append(kNullCh);
 
-  char16_t *value = ToNewUnicode(aValue);
-  char16_t *start = valueList.BeginWriting();
-  char16_t *end   = start;
+  char16_t* value = ToNewUnicode(aValue);
+  char16_t* start = valueList.BeginWriting();
+  char16_t* end = start;
 
   while (kNullCh != *start) {
-    while ((kNullCh != *start) && nsCRT::IsAsciiSpace(*start)) {  // skip leading space
+    while (kNullCh != *start && nsCRT::IsAsciiSpace(*start)) {
+      // skip leading space
       start++;
     }
     end = start;
 
-    while ((kNullCh != *end) && (false == nsCRT::IsAsciiSpace(*end))) { // look for space or end
+    while (kNullCh != *end && !nsCRT::IsAsciiSpace(*end)) {
+      // look for space or end
       end++;
     }
-    *end = kNullCh; // end string here
+    // end string here
+    *end = kNullCh;
 
     if (start < end) {
-      if (aCaseSensitive) {
-        if (!nsCRT::strcmp(value, start)) {
-          result = true;
-          break;
-        }
-      }
-      else {
-        if (nsDependentString(value).Equals(nsDependentString(start),
-                                            nsCaseInsensitiveStringComparator())) {
-          result = true;
-          break;
-        }
+      if (nsDependentString(value).Equals(nsDependentString(start),
+            nsCaseInsensitiveStringComparator())) {
+        result = true;
+        break;
       }
     }
     start = ++end;
   }
   NS_Free(value);
   return result;
 }
 
-// removes the value aRemoveValue from the string list of white-space separated values aValueList
+// Removes the value aRemoveValue from the string list of white-space separated
+// values aValueList
 void
-ChangeCSSInlineStyleTxn::RemoveValueFromListOfValues(nsAString & aValues, const nsAString  & aRemoveValue)
+ChangeStyleTxn::RemoveValueFromListOfValues(nsAString& aValues,
+                                            const nsAString& aRemoveValue)
 {
-  nsAutoString  classStr(aValues);  // copy to work buffer   nsAutoString  rv(aRemoveValue);
-  nsAutoString  outString;
-  classStr.Append(kNullCh);  // put an extra null at the end
+  nsAutoString classStr(aValues);
+  nsAutoString outString;
+  // put an extra null at the end
+  classStr.Append(kNullCh);
 
-  char16_t *start = classStr.BeginWriting();
-  char16_t *end   = start;
+  char16_t* start = classStr.BeginWriting();
+  char16_t* end = start;
 
   while (kNullCh != *start) {
-    while ((kNullCh != *start) && nsCRT::IsAsciiSpace(*start)) {  // skip leading space
+    while (kNullCh != *start && nsCRT::IsAsciiSpace(*start)) {
+      // skip leading space
       start++;
     }
     end = start;
 
-    while ((kNullCh != *end) && (false == nsCRT::IsAsciiSpace(*end))) { // look for space or end
+    while (kNullCh != *end && !nsCRT::IsAsciiSpace(*end)) {
+      // look for space or end
       end++;
     }
-    *end = kNullCh; // end string here
+    // end string here
+    *end = kNullCh;
 
-    if (start < end) {
-      if (!aRemoveValue.Equals(start)) {
-        outString.Append(start);
-        outString.Append(char16_t(' '));
-      }
+    if (start < end && !aRemoveValue.Equals(start)) {
+      outString.Append(start);
+      outString.Append(char16_t(' '));
     }
 
     start = ++end;
   }
   aValues.Assign(outString);
 }
 
-ChangeCSSInlineStyleTxn::ChangeCSSInlineStyleTxn()
+ChangeStyleTxn::ChangeStyleTxn(Element& aElement, nsIAtom& aProperty,
+                               const nsAString& aValue,
+                               EChangeType aChangeType)
   : EditTxn()
+  , mElement(&aElement)
+  , mProperty(&aProperty)
+  , mValue(aValue)
+  , mRemoveProperty(aChangeType == eRemove)
+  , mUndoValue()
+  , mRedoValue()
+  , mUndoAttributeWasSet(false)
+  , mRedoAttributeWasSet(false)
 {
 }
 
-NS_IMETHODIMP ChangeCSSInlineStyleTxn::Init(nsIEditor      *aEditor,
-                                            nsIDOMElement  *aElement,
-                                            nsIAtom        *aProperty,
-                                            const nsAString& aValue,
-                                            bool aRemoveProperty)
+NS_IMETHODIMP
+ChangeStyleTxn::DoTransaction()
 {
-  NS_ASSERTION(aEditor && aElement, "bad arg");
-  if (!aEditor || !aElement) { return NS_ERROR_NULL_POINTER; }
-
-  mEditor = aEditor;
-  mElement = do_QueryInterface(aElement);
-  mProperty = aProperty;
-  NS_ADDREF(mProperty);
-  mValue.Assign(aValue);
-  mRemoveProperty = aRemoveProperty;
-  mUndoAttributeWasSet = false;
-  mRedoAttributeWasSet = false;
-  mUndoValue.Truncate();
-  mRedoValue.Truncate();
-  return NS_OK;
-}
-
-NS_IMETHODIMP ChangeCSSInlineStyleTxn::DoTransaction(void)
-{
-  NS_ASSERTION(mEditor && mElement, "bad state");
-  if (!mEditor || !mElement) { return NS_ERROR_NOT_INITIALIZED; }
-
-  nsCOMPtr<nsIDOMElementCSSInlineStyle> inlineStyles = do_QueryInterface(mElement);
+  nsCOMPtr<nsIDOMElementCSSInlineStyle> inlineStyles =
+    do_QueryInterface(mElement);
   NS_ENSURE_TRUE(inlineStyles, NS_ERROR_NULL_POINTER);
 
   nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl;
   nsresult result = inlineStyles->GetStyle(getter_AddRefs(cssDecl));
   NS_ENSURE_SUCCESS(result, result);
   NS_ENSURE_TRUE(cssDecl, NS_ERROR_NULL_POINTER);
 
   nsAutoString propertyNameString;
   mProperty->ToString(propertyNameString);
 
-  NS_NAMED_LITERAL_STRING(styleAttr, "style");
-  result = mElement->HasAttribute(styleAttr, &mUndoAttributeWasSet);
-  NS_ENSURE_SUCCESS(result, result);
+  mUndoAttributeWasSet = mElement->HasAttr(kNameSpaceID_None,
+                                           nsGkAtoms::style);
 
   nsAutoString values;
   result = cssDecl->GetPropertyValue(propertyNameString, values);
-  NS_ENSURE_SUCCESS(result, result);     
+  NS_ENSURE_SUCCESS(result, result);
   mUndoValue.Assign(values);
 
-  // does this property accept more than 1 value ?
-  // we need to know that because of bug 62682
-  bool multiple = AcceptsMoreThanOneValue(mProperty);
-  
+  // Does this property accept more than one value? (bug 62682)
+  bool multiple = AcceptsMoreThanOneValue(*mProperty);
+
   if (mRemoveProperty) {
     nsAutoString returnString;
     if (multiple) {
-      // the property can have more than one value, let's remove only
-      // the value we have to remove and not the others
+      // Let's remove only the value we have to remove and not the others
 
-      // the 2 lines below are a workaround because nsDOMCSSDeclaration::GetPropertyCSSValue
-      // is not yet implemented (bug 62682)
+      // The two lines below are a workaround because
+      // nsDOMCSSDeclaration::GetPropertyCSSValue is not yet implemented (bug
+      // 62682)
       RemoveValueFromListOfValues(values, NS_LITERAL_STRING("none"));
       RemoveValueFromListOfValues(values, mValue);
       if (values.IsEmpty()) {
         result = cssDecl->RemoveProperty(propertyNameString, returnString);
-        NS_ENSURE_SUCCESS(result, result);     
-      }
-      else {
+        NS_ENSURE_SUCCESS(result, result);
+      } else {
         nsAutoString priority;
         result = cssDecl->GetPropertyPriority(propertyNameString, priority);
-        NS_ENSURE_SUCCESS(result, result);     
+        NS_ENSURE_SUCCESS(result, result);
         result = cssDecl->SetProperty(propertyNameString, values,
                                       priority);
-        NS_ENSURE_SUCCESS(result, result);     
+        NS_ENSURE_SUCCESS(result, result);
       }
-    }
-    else {
+    } else {
       result = cssDecl->RemoveProperty(propertyNameString, returnString);
-      NS_ENSURE_SUCCESS(result, result);     
+      NS_ENSURE_SUCCESS(result, result);
     }
-  }
-  else {
+  } else {
     nsAutoString priority;
     result = cssDecl->GetPropertyPriority(propertyNameString, priority);
     NS_ENSURE_SUCCESS(result, result);
     if (multiple) {
-      // the property can have more than one value, let's add
-      // the value we have to add to the others
+      // Let's add the value we have to add to the others
 
-      // the line below is a workaround because nsDOMCSSDeclaration::GetPropertyCSSValue
-      // is not yet implemented (bug 62682)
+      // The line below is a workaround because
+      // nsDOMCSSDeclaration::GetPropertyCSSValue is not yet implemented (bug
+      // 62682)
       AddValueToMultivalueProperty(values, mValue);
+    } else {
+      values.Assign(mValue);
     }
-    else
-      values.Assign(mValue);
     result = cssDecl->SetProperty(propertyNameString, values,
                                   priority);
-    NS_ENSURE_SUCCESS(result, result);     
+    NS_ENSURE_SUCCESS(result, result);
   }
 
-  // let's be sure we don't keep an empty style attribute
+  // Let's be sure we don't keep an empty style attribute
   uint32_t length;
   result = cssDecl->GetLength(&length);
-  NS_ENSURE_SUCCESS(result, result);     
+  NS_ENSURE_SUCCESS(result, result);
   if (!length) {
-    result = mElement->RemoveAttribute(styleAttr);
-    NS_ENSURE_SUCCESS(result, result);     
+    result = mElement->UnsetAttr(kNameSpaceID_None, nsGkAtoms::style, true);
+    NS_ENSURE_SUCCESS(result, result);
+  } else {
+    mRedoAttributeWasSet = true;
   }
-  else
-    mRedoAttributeWasSet = true;
 
   return cssDecl->GetPropertyValue(propertyNameString, mRedoValue);
 }
 
-nsresult ChangeCSSInlineStyleTxn::SetStyle(bool aAttributeWasSet,
-                                           nsAString & aValue)
+nsresult
+ChangeStyleTxn::SetStyle(bool aAttributeWasSet, nsAString& aValue)
 {
-  NS_ASSERTION(mEditor && mElement, "bad state");
-  if (!mEditor || !mElement) { return NS_ERROR_NOT_INITIALIZED; }
-
   nsresult result = NS_OK;
   if (aAttributeWasSet) {
-    // the style attribute was set and not empty, let's recreate the declaration
+    // The style attribute was not empty, let's recreate the declaration
     nsAutoString propertyNameString;
     mProperty->ToString(propertyNameString);
 
-    nsCOMPtr<nsIDOMElementCSSInlineStyle> inlineStyles = do_QueryInterface(mElement);
+    nsCOMPtr<nsIDOMElementCSSInlineStyle> inlineStyles =
+      do_QueryInterface(mElement);
     NS_ENSURE_TRUE(inlineStyles, NS_ERROR_NULL_POINTER);
     nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl;
     result = inlineStyles->GetStyle(getter_AddRefs(cssDecl));
     NS_ENSURE_SUCCESS(result, result);
     NS_ENSURE_TRUE(cssDecl, NS_ERROR_NULL_POINTER);
 
     if (aValue.IsEmpty()) {
-      // an empty value means we have to remove the property
+      // An empty value means we have to remove the property
       nsAutoString returnString;
       result = cssDecl->RemoveProperty(propertyNameString, returnString);
-    }
-    else {
-      // let's recreate the declaration as it was
+    } else {
+      // Let's recreate the declaration as it was
       nsAutoString priority;
       result = cssDecl->GetPropertyPriority(propertyNameString, priority);
       NS_ENSURE_SUCCESS(result, result);
       result = cssDecl->SetProperty(propertyNameString, aValue, priority);
     }
+  } else {
+    result = mElement->UnsetAttr(kNameSpaceID_None, nsGkAtoms::style, true);
   }
-  else
-    result = mElement->RemoveAttribute(NS_LITERAL_STRING("style"));
 
   return result;
 }
 
-NS_IMETHODIMP ChangeCSSInlineStyleTxn::UndoTransaction(void)
+NS_IMETHODIMP
+ChangeStyleTxn::UndoTransaction()
 {
   return SetStyle(mUndoAttributeWasSet, mUndoValue);
 }
 
-NS_IMETHODIMP ChangeCSSInlineStyleTxn::RedoTransaction(void)
+NS_IMETHODIMP
+ChangeStyleTxn::RedoTransaction()
 {
   return SetStyle(mRedoAttributeWasSet, mRedoValue);
 }
 
-NS_IMETHODIMP ChangeCSSInlineStyleTxn::GetTxnDescription(nsAString& aString)
+NS_IMETHODIMP
+ChangeStyleTxn::GetTxnDescription(nsAString& aString)
 {
-  aString.AssignLiteral("ChangeCSSInlineStyleTxn: [mRemoveProperty == ");
+  aString.AssignLiteral("ChangeStyleTxn: [mRemoveProperty == ");
 
-  if (!mRemoveProperty)
+  if (mRemoveProperty) {
+    aString.AppendLiteral("true] ");
+  } else {
     aString.AppendLiteral("false] ");
-  else
-    aString.AppendLiteral("true] ");
-  nsAutoString tempString;
-  mProperty->ToString(tempString);
-  aString += tempString;
+  }
+  aString += nsDependentAtomString(mProperty);
   return NS_OK;
 }
 
-// answers true if the CSS property accepts more than one value
+// True if the CSS property accepts more than one value
 bool
-ChangeCSSInlineStyleTxn::AcceptsMoreThanOneValue(nsIAtom *aCSSProperty)
+ChangeStyleTxn::AcceptsMoreThanOneValue(nsIAtom& aCSSProperty)
 {
-  return aCSSProperty == nsGkAtoms::text_decoration;
+  return &aCSSProperty == nsGkAtoms::text_decoration;
 }
 
-// adds the value aNewValue to the list of white-space separated values aValues
-NS_IMETHODIMP
-ChangeCSSInlineStyleTxn::AddValueToMultivalueProperty(nsAString & aValues, const nsAString & aNewValue)
+// Adds the value aNewValue to the list of white-space separated values aValues
+void
+ChangeStyleTxn::AddValueToMultivalueProperty(nsAString& aValues,
+                                             const nsAString& aNewValue)
 {
-  if (aValues.IsEmpty()
-      || aValues.LowerCaseEqualsLiteral("none")) {
-    // the list of values is empty of the value is 'none'
+  if (aValues.IsEmpty() || aValues.LowerCaseEqualsLiteral("none")) {
     aValues.Assign(aNewValue);
-  }
-  else if (!ValueIncludes(aValues, aNewValue, false)) {
-    // we already have another value but not this one; add it
+  } else if (!ValueIncludes(aValues, aNewValue)) {
+    // We already have another value but not this one; add it
     aValues.Append(char16_t(' '));
     aValues.Append(aNewValue);
   }
-  return NS_OK;
 }
rename from editor/libeditor/ChangeCSSInlineStyleTxn.h
rename to editor/libeditor/ChangeStyleTxn.h
--- a/editor/libeditor/ChangeCSSInlineStyleTxn.h
+++ b/editor/libeditor/ChangeStyleTxn.h
@@ -1,114 +1,112 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/. */
 
-#ifndef ChangeCSSInlineStyleTxn_h__
-#define ChangeCSSInlineStyleTxn_h__
+#ifndef ChangeStyleTxn_h__
+#define ChangeStyleTxn_h__
 
-#include "EditTxn.h"
-#include "nsCOMPtr.h"
-#include "nsCycleCollectionParticipant.h"
-#include "nsID.h"
-#include "nsIDOMElement.h"
-#include "nsString.h"
-#include "nscore.h"
+#include "EditTxn.h"                      // base class
+#include "nsCOMPtr.h"                     // nsCOMPtr members
+#include "nsCycleCollectionParticipant.h" // various macros
+#include "nsString.h"                     // nsString members
 
+class nsAString;
 class nsIAtom;
-class nsIEditor;
+
+namespace mozilla {
+namespace dom {
+class Element;
 
 /**
- * A transaction that changes the value of a CSS inline style of a content node. 
- * This transaction covers add, remove, and change a property's value.
+ * A transaction that changes the value of a CSS inline style of a content
+ * node.  This transaction covers add, remove, and change a property's value.
  */
-class ChangeCSSInlineStyleTxn : public EditTxn
+class ChangeStyleTxn : public EditTxn
 {
 public:
-  /** Initialize the transaction.
-    * @param aEditor         [IN] the object providing core editing operations
-    * @param aNode           [IN] the node whose style attribute will be changed
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ChangeStyleTxn, EditTxn)
+
+  NS_DECL_ISUPPORTS_INHERITED
+
+  NS_DECL_EDITTXN
+
+  NS_IMETHOD RedoTransaction() MOZ_OVERRIDE;
+
+  enum EChangeType { eSet, eRemove };
+
+  /** @param aNode           [IN] the node whose style attribute will be changed
     * @param aProperty       [IN] the name of the property to change
-    * @param aValue          [IN] the new value for aProperty, if aRemoveProperty is false
-    * @param aRemoveProperty [IN] if true, remove aProperty from style attribute
+    * @param aValue          [IN] new value for aProperty, or value to remove
+    * @param aChangeType     [IN] whether to set or remove
     */
-  NS_IMETHOD Init(nsIEditor      * aEditor,
-                  nsIDOMElement  * aElement,
-                  nsIAtom        * aProperty,
-                  const nsAString & aValue,
-                  bool aRemoveProperty);
+  ChangeStyleTxn(Element& aElement, nsIAtom& aProperty,
+                 const nsAString& aValue, EChangeType aChangeType);
 
-  /** returns true if the list of white-space separated values contains aValue
+  /** Returns true if the list of white-space separated values contains aValue
     *
     * @return                true if the value is in the list of values
     * @param aValueList      [IN] a list of white-space separated values
     * @param aValue          [IN] the value to look for in the list
-    * @param aCaseSensitive  [IN] a boolean being true if a case-sensitive search is needed
     */
-  static bool ValueIncludes(const nsAString & aValueList, const nsAString & aValue, bool aCaseSensitive);
+  static bool ValueIncludes(const nsAString& aValueList,
+                            const nsAString& aValue);
 
-  /** adds the value aNewValue to the list of white-space separated values aValues
+private:
+  ~ChangeStyleTxn();
+
+  /** Adds the value aNewValue to list of white-space separated values aValues
     *
     * @param aValues         [IN/OUT] a list of wite-space separated values
     * @param aNewValue       [IN] a value this code adds to aValues if it is not already in
     */
-  NS_IMETHOD AddValueToMultivalueProperty(nsAString & aValues, const nsAString  & aNewValue);
+  void AddValueToMultivalueProperty(nsAString& aValues,
+                                    const nsAString& aNewValue);
 
-  ChangeCSSInlineStyleTxn();
-
-private:
-  /** returns true if the property accepts more than one value
+  /** Returns true if the property accepts more than one value
     *
     * @return                true if the property accepts more than one value
     * @param aCSSProperty    [IN] the CSS property
     */
-  bool AcceptsMoreThanOneValue(nsIAtom * aCSSProperty);
+  bool AcceptsMoreThanOneValue(nsIAtom& aCSSProperty);
 
-  /** remove a value from a list of white-space separated values
+  /** Remove a value from a list of white-space separated values
     * @param aValues         [IN] a list of white-space separated values
     * @param aRemoveValue    [IN] the value to remove from the list
     */
-  void   RemoveValueFromListOfValues(nsAString & aValues, const nsAString  & aRemoveValue);
+  void RemoveValueFromListOfValues(nsAString& aValues,
+                                   const nsAString& aRemoveValue);
 
   /** If the boolean is true and if the value is not the empty string,
     * set the property in the transaction to that value; if the value
     * is empty, remove the property from element's styles. If the boolean
     * is false, just remove the style attribute.
     */
-  nsresult SetStyle(bool aAttributeWasSet, nsAString & aValue);
+  nsresult SetStyle(bool aAttributeWasSet, nsAString& aValue);
 
-public:
-  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ChangeCSSInlineStyleTxn, EditTxn)
-  NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
-
-  NS_DECL_EDITTXN
-
-  NS_IMETHOD RedoTransaction();
+  /** The element to operate upon */
+  nsCOMPtr<Element> mElement;
 
-protected:
+  /** The CSS property to change */
+  nsCOMPtr<nsIAtom> mProperty;
 
-  /** the editor that created this transaction */
-  nsIEditor *mEditor;
-  
-  /** the element to operate upon */
-  nsCOMPtr<nsIDOMElement> mElement;
-  
-  /** the CSS property to change */
-  nsIAtom *mProperty;
-
-  /** the value to set the property to (ignored if mRemoveProperty==true) */
+  /** The value to set the property to (ignored if mRemoveProperty==true) */
   nsString mValue;
 
-  /** the value to set the property to for undo */
+  /** true if the operation is to remove mProperty from mElement */
+  bool mRemoveProperty;
+
+  /** The value to set the property to for undo */
   nsString mUndoValue;
-  /** the value to set the property to for redo */
+  /** The value to set the property to for redo */
   nsString mRedoValue;
-  /** true if the style attribute was present and not empty before DoTransaction */
-  bool     mUndoAttributeWasSet;
-  /** true if the style attribute is present and not empty after DoTransaction */
-  bool     mRedoAttributeWasSet;
-
-  /** true if the operation is to remove mProperty from mElement */
-  bool     mRemoveProperty;
+  /** True if the style attribute was present and not empty before DoTransaction */
+  bool mUndoAttributeWasSet;
+  /** True if the style attribute is present and not empty after DoTransaction */
+  bool mRedoAttributeWasSet;
 };
 
+}
+}
+
 #endif
--- a/editor/libeditor/IMETextTxn.cpp
+++ b/editor/libeditor/IMETextTxn.cpp
@@ -1,178 +1,141 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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 "IMETextTxn.h"
-#include "mozilla/DebugOnly.h"          // for DebugOnly
-#include "mozilla/mozalloc.h"           // for operator new
-#include "mozilla/TextEvents.h"         // for TextRangeStyle
-#include "nsAString.h"                  // for nsAString_internal::Length, etc
-#include "nsAutoPtr.h"                  // for nsRefPtr
+
+#include "mozilla/dom/Selection.h"      // local var
+#include "mozilla/dom/Text.h"           // mTextNode
+#include "nsAString.h"                  // params
 #include "nsDebug.h"                    // for NS_ASSERTION, etc
+#include "nsEditor.h"                   // mEditor
 #include "nsError.h"                    // for NS_SUCCEEDED, NS_FAILED, etc
-#include "nsIDOMCharacterData.h"        // for nsIDOMCharacterData
-#include "nsIDOMRange.h"                // for nsRange::SetEnd, etc
-#include "nsIContent.h"                 // for nsIContent
-#include "nsIEditor.h"                  // for nsIEditor
-#include "nsIPresShell.h"               // for SelectionType
-#include "nsISelection.h"               // for nsISelection
-#include "nsISelectionController.h"     // for nsISelectionController, etc
-#include "nsISelectionPrivate.h"        // for nsISelectionPrivate
-#include "nsISupportsImpl.h"            // for nsRange::AddRef, etc
-#include "nsISupportsUtils.h"           // for NS_ADDREF_THIS, NS_RELEASE
-#include "nsITransaction.h"             // for nsITransaction
-#include "nsRange.h"                    // for nsRange
-#include "nsString.h"                   // for nsString
+#include "nsIPresShell.h"               // nsISelectionController constants
+#include "nsRange.h"                    // local var
 
 using namespace mozilla;
-
-// #define DEBUG_IMETXN
+using namespace mozilla::dom;
 
-IMETextTxn::IMETextTxn()
+IMETextTxn::IMETextTxn(Text& aTextNode, uint32_t aOffset,
+                       uint32_t aReplaceLength,
+                       TextRangeArray* aTextRangeArray,
+                       const nsAString& aStringToInsert,
+                       nsEditor& aEditor)
   : EditTxn()
+  , mTextNode(&aTextNode)
+  , mOffset(aOffset)
+  , mReplaceLength(aReplaceLength)
+  , mRanges(aTextRangeArray)
+  , mStringToInsert(aStringToInsert)
+  , mEditor(aEditor)
+  , mFixed(false)
+{
+}
+
+IMETextTxn::~IMETextTxn()
 {
 }
 
 NS_IMPL_CYCLE_COLLECTION_INHERITED(IMETextTxn, EditTxn,
-                                   mElement)
+                                   mTextNode)
 // mRangeList can't lead to cycles
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IMETextTxn)
-  if (aIID.Equals(IMETextTxn::GetCID())) {
-    *aInstancePtr = (void*)(IMETextTxn*)this;
-    NS_ADDREF_THIS();
-    return NS_OK;
-  } else
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsITransaction, IMETextTxn)
 NS_INTERFACE_MAP_END_INHERITING(EditTxn)
 
-NS_IMETHODIMP IMETextTxn::Init(nsIDOMCharacterData     *aElement,
-                               uint32_t                 aOffset,
-                               uint32_t                 aReplaceLength,
-                               TextRangeArray          *aTextRangeArray,
-                               const nsAString         &aStringToInsert,
-                               nsIEditor               *aEditor)
+NS_IMPL_ADDREF_INHERITED(IMETextTxn, EditTxn)
+NS_IMPL_RELEASE_INHERITED(IMETextTxn, EditTxn)
+
+NS_IMETHODIMP
+IMETextTxn::DoTransaction()
 {
-  NS_ENSURE_ARG_POINTER(aElement);
-  mElement = aElement;
-  mOffset = aOffset;
-  mReplaceLength = aReplaceLength;
-  mStringToInsert = aStringToInsert;
-  mEditor = aEditor;
-  mRanges = aTextRangeArray;
-  mFixed = false;
+  // Fail before making any changes if there's no selection controller
+  nsCOMPtr<nsISelectionController> selCon;
+  mEditor.GetSelectionController(getter_AddRefs(selCon));
+  NS_ENSURE_TRUE(selCon, NS_ERROR_NOT_INITIALIZED);
+
+  // Advance caret: This requires the presentation shell to get the selection.
+  nsresult res;
+  if (mReplaceLength == 0) {
+    res = mTextNode->InsertData(mOffset, mStringToInsert);
+  } else {
+    res = mTextNode->ReplaceData(mOffset, mReplaceLength, mStringToInsert);
+  }
+  NS_ENSURE_SUCCESS(res, res);
+
+  res = SetSelectionForRanges();
+  NS_ENSURE_SUCCESS(res, res);
+
   return NS_OK;
 }
 
-NS_IMETHODIMP IMETextTxn::DoTransaction(void)
+NS_IMETHODIMP
+IMETextTxn::UndoTransaction()
 {
-
-#ifdef DEBUG_IMETXN
-  printf("Do IME Text element = %p replace = %d len = %d\n", mElement.get(), mReplaceLength, mStringToInsert.Length());
-#endif
-
-  nsCOMPtr<nsISelectionController> selCon;
-  mEditor->GetSelectionController(getter_AddRefs(selCon));
-  NS_ENSURE_TRUE(selCon, NS_ERROR_NOT_INITIALIZED);
+  // Get the selection first so we'll fail before making any changes if we
+  // can't get it
+  nsRefPtr<Selection> selection = mEditor.GetSelection();
+  NS_ENSURE_TRUE(selection, NS_ERROR_NOT_INITIALIZED);
 
-  // advance caret: This requires the presentation shell to get the selection.
-  nsresult result;
-  if (mReplaceLength == 0) {
-    result = mElement->InsertData(mOffset, mStringToInsert);
-  } else {
-    result = mElement->ReplaceData(mOffset, mReplaceLength, mStringToInsert);
-  }
-  if (NS_SUCCEEDED(result)) {
-    result = SetSelectionForRanges();
-  }
+  nsresult res = mTextNode->DeleteData(mOffset, mStringToInsert.Length());
+  NS_ENSURE_SUCCESS(res, res);
 
-  return result;
+  // set the selection to the insertion point where the string was removed
+  res = selection->Collapse(mTextNode, mOffset);
+  NS_ASSERTION(NS_SUCCEEDED(res),
+               "Selection could not be collapsed after undo of IME insert.");
+  NS_ENSURE_SUCCESS(res, res);
+
+  return NS_OK;
 }
 
-NS_IMETHODIMP IMETextTxn::UndoTransaction(void)
+NS_IMETHODIMP
+IMETextTxn::Merge(nsITransaction* aTransaction, bool* aDidMerge)
 {
-#ifdef DEBUG_IMETXN
-  printf("Undo IME Text element = %p\n", mElement.get());
-#endif
-
-  nsCOMPtr<nsISelectionController> selCon;
-  mEditor->GetSelectionController(getter_AddRefs(selCon));
-  NS_ENSURE_TRUE(selCon, NS_ERROR_NOT_INITIALIZED);
+  NS_ENSURE_ARG_POINTER(aTransaction && aDidMerge);
 
-  nsresult result = mElement->DeleteData(mOffset, mStringToInsert.Length());
-  if (NS_SUCCEEDED(result))
-  { // set the selection to the insertion point where the string was removed
-    nsCOMPtr<nsISelection> selection;
-    result = selCon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(selection));
-    if (NS_SUCCEEDED(result) && selection) {
-      result = selection->Collapse(mElement, mOffset);
-      NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after undo of IME insert.");
-    }
-  }
-  return result;
-}
-
-NS_IMETHODIMP IMETextTxn::Merge(nsITransaction *aTransaction, bool *aDidMerge)
-{
-  NS_ASSERTION(aDidMerge, "illegal vaule- null ptr- aDidMerge");
-  NS_ASSERTION(aTransaction, "illegal vaule- null ptr- aTransaction");
-  NS_ENSURE_TRUE(aDidMerge && aTransaction, NS_ERROR_NULL_POINTER);
-    
-#ifdef DEBUG_IMETXN
-  printf("Merge IME Text element = %p\n", mElement.get());
-#endif
-
-  // 
-  // check to make sure we aren't fixed, if we are then nothing get's absorbed
-  //
+  // Check to make sure we aren't fixed, if we are then nothing gets absorbed
   if (mFixed) {
     *aDidMerge = false;
     return NS_OK;
   }
 
-  //
-  // if aTransaction is another IMETextTxn then absorb it
-  //
-  IMETextTxn*  otherTxn = nullptr;
-  nsresult result = aTransaction->QueryInterface(IMETextTxn::GetCID(),(void**)&otherTxn);
-  if (otherTxn && NS_SUCCEEDED(result))
-  {
-    //
-    //  we absorb the next IME transaction by adopting its insert string as our own
-    //
+  // If aTransaction is another IMETextTxn then absorb it
+  nsRefPtr<IMETextTxn> otherTxn = do_QueryObject(aTransaction);
+  if (otherTxn) {
+    // We absorb the next IME transaction by adopting its insert string
     mStringToInsert = otherTxn->mStringToInsert;
     mRanges = otherTxn->mRanges;
     *aDidMerge = true;
-#ifdef DEBUG_IMETXN
-    printf("IMETextTxn assimilated IMETextTxn:%p\n", aTransaction);
-#endif
-    NS_RELEASE(otherTxn);
     return NS_OK;
   }
 
   *aDidMerge = false;
   return NS_OK;
 }
 
-NS_IMETHODIMP IMETextTxn::MarkFixed(void)
+void
+IMETextTxn::MarkFixed()
 {
   mFixed = true;
-  return NS_OK;
 }
 
-NS_IMETHODIMP IMETextTxn::GetTxnDescription(nsAString& aString)
+NS_IMETHODIMP
+IMETextTxn::GetTxnDescription(nsAString& aString)
 {
   aString.AssignLiteral("IMETextTxn: ");
   aString += mStringToInsert;
   return NS_OK;
 }
 
-/* ============ protected methods ================== */
+/* ============ private methods ================== */
 static SelectionType
 ToSelectionType(uint32_t aTextRangeType)
 {
   switch(aTextRangeType) {
     case NS_TEXTRANGE_RAWINPUT:
       return nsISelectionController::SELECTION_IME_RAWINPUT;
     case NS_TEXTRANGE_SELECTEDRAWTEXT:
       return nsISelectionController::SELECTION_IME_SELECTEDRAWTEXT;
@@ -184,97 +147,93 @@ ToSelectionType(uint32_t aTextRangeType)
       MOZ_CRASH("Selection type is invalid");
       return nsISelectionController::SELECTION_NORMAL;
   }
 }
 
 nsresult
 IMETextTxn::SetSelectionForRanges()
 {
-  nsCOMPtr<nsISelectionController> selCon;
-  mEditor->GetSelectionController(getter_AddRefs(selCon));
-  NS_ENSURE_TRUE(selCon, NS_ERROR_NOT_INITIALIZED);
+  nsRefPtr<Selection> selection = mEditor.GetSelection();
+  NS_ENSURE_TRUE(selection, NS_ERROR_NOT_INITIALIZED);
 
-  nsCOMPtr<nsISelection> selection;
-  nsresult rv =
-    selCon->GetSelection(nsISelectionController::SELECTION_NORMAL,
-                         getter_AddRefs(selection));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsCOMPtr<nsISelectionPrivate> selPriv(do_QueryInterface(selection));
-  rv = selPriv->StartBatchChanges();
+  nsresult rv = selection->StartBatchChanges();
   NS_ENSURE_SUCCESS(rv, rv);
 
   // First, remove all selections of IME composition.
   static const SelectionType kIMESelections[] = {
     nsISelectionController::SELECTION_IME_RAWINPUT,
     nsISelectionController::SELECTION_IME_SELECTEDRAWTEXT,
     nsISelectionController::SELECTION_IME_CONVERTEDTEXT,
     nsISelectionController::SELECTION_IME_SELECTEDCONVERTEDTEXT
   };
+
+  nsCOMPtr<nsISelectionController> selCon;
+  mEditor.GetSelectionController(getter_AddRefs(selCon));
+  NS_ENSURE_TRUE(selCon, NS_ERROR_NOT_INITIALIZED);
+
   for (uint32_t i = 0; i < ArrayLength(kIMESelections); ++i) {
     nsCOMPtr<nsISelection> selectionOfIME;
     if (NS_FAILED(selCon->GetSelection(kIMESelections[i],
                                        getter_AddRefs(selectionOfIME)))) {
       continue;
     }
-    DebugOnly<nsresult> rv = selectionOfIME->RemoveAllRanges();
+    rv = selectionOfIME->RemoveAllRanges();
     NS_ASSERTION(NS_SUCCEEDED(rv),
                  "Failed to remove all ranges of IME selection");
   }
 
   // Set caret position and selection of IME composition with TextRangeArray.
   bool setCaret = false;
   uint32_t countOfRanges = mRanges ? mRanges->Length() : 0;
+
 #ifdef DEBUG
-  // When this sets selection (caret) offset to out of the content of
-  // the editor, let's crash the process only on debug build.  That makes such
-  // bugs detectable with automated tests.
-  uint32_t maxOffset = UINT32_MAX;
-  mElement->GetLength(&maxOffset);
+  // Bounds-checking on debug builds
+  uint32_t maxOffset = mTextNode->Length();
 #endif
+
   // The mStringToInsert may be truncated if maxlength attribute value doesn't
-  // allow to input all text of this composition. So, we can get actual length
+  // allow input of all text of this composition. So, we can get actual length
   // of the inserted string from it.
   uint32_t insertedLength = mStringToInsert.Length();
   for (uint32_t i = 0; i < countOfRanges; ++i) {
     const TextRange& textRange = mRanges->ElementAt(i);
 
     // Caret needs special handling since its length may be 0 and if it's not
     // specified explicitly, we need to handle it ourselves later.
     if (textRange.mRangeType == NS_TEXTRANGE_CARETPOSITION) {
       NS_ASSERTION(!setCaret, "The ranges already has caret position");
       NS_ASSERTION(!textRange.Length(), "nsEditor doesn't support wide caret");
       int32_t caretOffset = static_cast<int32_t>(
         mOffset + std::min(textRange.mStartOffset, insertedLength));
       MOZ_ASSERT(caretOffset >= 0 &&
                  static_cast<uint32_t>(caretOffset) <= maxOffset);
-      rv = selection->Collapse(mElement, caretOffset);
+      rv = selection->Collapse(mTextNode, caretOffset);
       setCaret = setCaret || NS_SUCCEEDED(rv);
       NS_ASSERTION(setCaret, "Failed to collapse normal selection");
       continue;
     }
 
-    // If the clause length is 0, it's should be a bug.
+    // If the clause length is 0, it should be a bug.
     if (!textRange.Length()) {
       NS_WARNING("Any clauses must not be empty");
       continue;
     }
 
     nsRefPtr<nsRange> clauseRange;
     int32_t startOffset = static_cast<int32_t>(
       mOffset + std::min(textRange.mStartOffset, insertedLength));
     MOZ_ASSERT(startOffset >= 0 &&
                static_cast<uint32_t>(startOffset) <= maxOffset);
     int32_t endOffset = static_cast<int32_t>(
       mOffset + std::min(textRange.mEndOffset, insertedLength));
     MOZ_ASSERT(endOffset >= startOffset &&
                static_cast<uint32_t>(endOffset) <= maxOffset);
-    rv = nsRange::CreateRange(mElement, startOffset,
-                              mElement, endOffset,
+    rv = nsRange::CreateRange(mTextNode, startOffset,
+                              mTextNode, endOffset,
                               getter_AddRefs(clauseRange));
     if (NS_FAILED(rv)) {
       NS_WARNING("Failed to create a DOM range for a clause of composition");
       break;
     }
 
     // Set the range of the clause to selection.
     nsCOMPtr<nsISelection> selectionOfIME;
@@ -307,19 +266,18 @@ IMETextTxn::SetSelectionForRanges()
   }
 
   // If the ranges doesn't include explicit caret position, let's set the
   // caret to the end of composition string.
   if (!setCaret) {
     int32_t caretOffset = static_cast<int32_t>(mOffset + insertedLength);
     MOZ_ASSERT(caretOffset >= 0 &&
                static_cast<uint32_t>(caretOffset) <= maxOffset);
-    rv = selection->Collapse(mElement, caretOffset);
+    rv = selection->Collapse(mTextNode, caretOffset);
     NS_ASSERTION(NS_SUCCEEDED(rv),
                  "Failed to set caret at the end of composition string");
   }
 
-  rv = selPriv->EndBatchChanges();
+  rv = selection->EndBatchChanges();
   NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to end batch changes");
 
   return rv;
 }
-
--- a/editor/libeditor/IMETextTxn.h
+++ b/editor/libeditor/IMETextTxn.h
@@ -1,91 +1,87 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/. */
 
 #ifndef IMETextTxn_h__
 #define IMETextTxn_h__
 
-#include "EditTxn.h"
-#include "nsCOMPtr.h"
-#include "nsCycleCollectionParticipant.h"
-#include "nsID.h"
-#include "nsIDOMCharacterData.h"
-#include "nsString.h"
-#include "nscore.h"
-#include "mozilla/TextRange.h"
+#include "EditTxn.h"                      // base class
+#include "nsAutoPtr.h"                    // mTextNode, mRanges
+#include "nsCycleCollectionParticipant.h" // various macros
+#include "nsString.h"                     // mStringToInsert
+
+class nsEditor;
 
-class nsITransaction;
+#define NS_IMETEXTTXN_IID \
+  { 0xb391355d, 0x346c, 0x43d1, \
+    { 0x85, 0xed, 0x9e, 0x65, 0xbe, 0xe7, 0x7e, 0x48 } }
+
+namespace mozilla {
 
-// {D4D25721-2813-11d3-9EA3-0060089FE59B}
-#define IME_TEXT_TXN_CID							\
-{0xd4d25721, 0x2813, 0x11d3,						\
-{0x9e, 0xa3, 0x0, 0x60, 0x8, 0x9f, 0xe5, 0x9b }}
+class TextRangeArray;
 
+namespace dom {
 
-class nsIEditor;
-
+class Text;
 
 /**
-  * A transaction that inserts text into a content node. 
+  * A transaction that inserts text into a content node.
   */
 class IMETextTxn : public EditTxn
 {
 public:
-  static const nsIID& GetCID() { static const nsIID iid = IME_TEXT_TXN_CID; return iid; }
+  NS_DECLARE_STATIC_IID_ACCESSOR(NS_IMETEXTTXN_IID)
 
-  /** initialize the transaction
-    * @param aElement the text content node
-    * @param aOffset  the location in aElement to do the insertion
+  /** @param aTextNode the text content node
+    * @param aOffset  the location in aTextNode to do the insertion
     * @param aReplaceLength the length of text to replace (0 == no replacement)
     * @param aTextRangeArray clauses and/or caret information. This may be null.
-    * @param aString  the new text to insert
-    * @param aSelCon used to get and set the selection
+    * @param aString the new text to insert
+    * @param aEditor used to get and set the selection
     */
-  NS_IMETHOD Init(nsIDOMCharacterData *aElement,
-                  uint32_t aOffset,
-                  uint32_t aReplaceLength,
-                  mozilla::TextRangeArray* aTextRangeArray,
-                  const nsAString& aString,
-                  nsIEditor* aEditor);
-
-  IMETextTxn();
+  IMETextTxn(Text& aTextNode, uint32_t aOffset, uint32_t aReplaceLength,
+             TextRangeArray* aTextRangeArray, const nsAString& aString,
+             nsEditor& aEditor);
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IMETextTxn, EditTxn)
 
+  NS_DECL_ISUPPORTS_INHERITED
+
   NS_DECL_EDITTXN
 
-  NS_IMETHOD Merge(nsITransaction *aTransaction, bool *aDidMerge);
-
-  NS_IMETHOD MarkFixed(void);
+  NS_IMETHOD Merge(nsITransaction* aTransaction, bool* aDidMerge) MOZ_OVERRIDE;
 
-// nsISupports declarations
+  void MarkFixed();
 
-  // override QueryInterface to handle IMETextTxn request
-  NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
-
-protected:
+private:
+  ~IMETextTxn();
 
   nsresult SetSelectionForRanges();
 
-  /** the text element to operate upon */
-  nsCOMPtr<nsIDOMCharacterData> mElement;
-  
-  /** the offsets into mElement where the insertion should be placed*/
+  /** The text element to operate upon */
+  nsRefPtr<Text> mTextNode;
+
+  /** The offsets into mTextNode where the insertion should be placed */
   uint32_t mOffset;
 
   uint32_t mReplaceLength;
 
-  /** the text to insert into mElement at mOffset */
-  nsString mStringToInsert;
-
-  /** the range list **/
+  /** The range list **/
   nsRefPtr<mozilla::TextRangeArray> mRanges;
 
-  /** the editor, which is used to get the selection controller */
-  nsIEditor *mEditor;
+  /** The text to insert into mTextNode at mOffset */
+  nsString mStringToInsert;
 
-  bool	mFixed;
+  /** The editor, which is used to get the selection controller */
+  nsEditor& mEditor;
+
+  bool mFixed;
 };
 
+NS_DEFINE_STATIC_IID_ACCESSOR(IMETextTxn, NS_IMETEXTTXN_IID)
+
+}
+}
+
 #endif
--- a/editor/libeditor/InsertTextTxn.cpp
+++ b/editor/libeditor/InsertTextTxn.cpp
@@ -1,153 +1,115 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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 <stdio.h>                      // for printf
+#include "InsertTextTxn.h"
 
-#include "InsertTextTxn.h"
-#include "nsAString.h"
+#include "mozilla/dom/Selection.h"      // Selection local var
+#include "mozilla/dom/Text.h"           // mTextNode
+#include "nsAString.h"                  // nsAString parameter
 #include "nsDebug.h"                    // for NS_ASSERTION, etc
+#include "nsEditor.h"                   // mEditor
 #include "nsError.h"                    // for NS_OK, etc
-#include "nsIDOMCharacterData.h"        // for nsIDOMCharacterData
-#include "nsIEditor.h"                  // for nsIEditor
-#include "nsISelection.h"               // for nsISelection
-#include "nsISupportsUtils.h"           // for NS_ADDREF_THIS, NS_RELEASE
-#include "nsITransaction.h"             // for nsITransaction
+
+using namespace mozilla;
+using namespace mozilla::dom;
+
+class nsITransaction;
 
-InsertTextTxn::InsertTextTxn()
+InsertTextTxn::InsertTextTxn(Text& aTextNode, uint32_t aOffset,
+                             const nsAString& aStringToInsert,
+                             nsEditor& aEditor)
   : EditTxn()
+  , mTextNode(&aTextNode)
+  , mOffset(aOffset)
+  , mStringToInsert(aStringToInsert)
+  , mEditor(aEditor)
 {
 }
 
 InsertTextTxn::~InsertTextTxn()
 {
 }
 
 NS_IMPL_CYCLE_COLLECTION_INHERITED(InsertTextTxn, EditTxn,
-                                   mElement)
+                                   mTextNode)
 
 NS_IMPL_ADDREF_INHERITED(InsertTextTxn, EditTxn)
 NS_IMPL_RELEASE_INHERITED(InsertTextTxn, EditTxn)
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(InsertTextTxn)
-  if (aIID.Equals(InsertTextTxn::GetCID())) {
-    *aInstancePtr = (void*)(InsertTextTxn*)this;
-    NS_ADDREF_THIS();
-    return NS_OK;
-  } else
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsITransaction, InsertTextTxn)
 NS_INTERFACE_MAP_END_INHERITING(EditTxn)
 
-NS_IMETHODIMP InsertTextTxn::Init(nsIDOMCharacterData *aElement,
-                                  uint32_t             aOffset,
-                                  const nsAString     &aStringToInsert,
-                                  nsIEditor           *aEditor)
+
+NS_IMETHODIMP
+InsertTextTxn::DoTransaction()
 {
-#if 0
-      nsAutoString text;
-      aElement->GetData(text);
-      printf("InsertTextTxn: Offset to insert at = %d. Text of the node to insert into:\n", aOffset);
-      wprintf(text.get());
-      printf("\n");
-#endif
+  nsresult res = mTextNode->InsertData(mOffset, mStringToInsert);
+  NS_ENSURE_SUCCESS(res, res);
 
-  NS_ASSERTION(aElement && aEditor, "bad args");
-  NS_ENSURE_TRUE(aElement && aEditor, NS_ERROR_NULL_POINTER);
+  // Only set selection to insertion point if editor gives permission
+  if (mEditor.GetShouldTxnSetSelection()) {
+    nsRefPtr<Selection> selection = mEditor.GetSelection();
+    NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
+    res = selection->Collapse(mTextNode,
+                              mOffset + mStringToInsert.Length());
+    NS_ASSERTION(NS_SUCCEEDED(res),
+                 "Selection could not be collapsed after insert");
+  } else {
+    // Do nothing - DOM Range gravity will adjust selection
+  }
 
-  mElement = do_QueryInterface(aElement);
-  mOffset = aOffset;
-  mStringToInsert = aStringToInsert;
-  mEditor = aEditor;
   return NS_OK;
 }
 
-NS_IMETHODIMP InsertTextTxn::DoTransaction(void)
+NS_IMETHODIMP
+InsertTextTxn::UndoTransaction()
 {
-  NS_ASSERTION(mElement && mEditor, "bad state");
-  if (!mElement || !mEditor) { return NS_ERROR_NOT_INITIALIZED; }
-
-  nsresult result = mElement->InsertData(mOffset, mStringToInsert);
-  NS_ENSURE_SUCCESS(result, result);
-
-  // only set selection to insertion point if editor gives permission
-  bool bAdjustSelection;
-  mEditor->ShouldTxnSetSelection(&bAdjustSelection);
-  if (bAdjustSelection)
-  {
-    nsCOMPtr<nsISelection> selection;
-    result = mEditor->GetSelection(getter_AddRefs(selection));
-    NS_ENSURE_SUCCESS(result, result);
-    NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
-    result = selection->Collapse(mElement, mOffset+mStringToInsert.Length());
-    NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after insert.");
-  }
-  else
-  {
-    // do nothing - dom range gravity will adjust selection
-  }
-
-  return result;
+  return mTextNode->DeleteData(mOffset, mStringToInsert.Length());
 }
 
-NS_IMETHODIMP InsertTextTxn::UndoTransaction(void)
+NS_IMETHODIMP
+InsertTextTxn::Merge(nsITransaction* aTransaction, bool* aDidMerge)
 {
-  NS_ASSERTION(mElement && mEditor, "bad state");
-  if (!mElement || !mEditor) { return NS_ERROR_NOT_INITIALIZED; }
+  if (!aTransaction || !aDidMerge) {
+    return NS_OK;
+  }
+  // Set out param default value
+  *aDidMerge = false;
 
-  uint32_t length = mStringToInsert.Length();
-  return mElement->DeleteData(mOffset, length);
+  // If aTransaction is a InsertTextTxn, and if the selection hasn't changed,
+  // then absorb it
+  nsRefPtr<InsertTextTxn> otherInsTxn = do_QueryObject(aTransaction);
+  if (otherInsTxn && IsSequentialInsert(*otherInsTxn)) {
+    nsAutoString otherData;
+    otherInsTxn->GetData(otherData);
+    mStringToInsert += otherData;
+    *aDidMerge = true;
+  }
+
+  return NS_OK;
 }
 
-NS_IMETHODIMP InsertTextTxn::Merge(nsITransaction *aTransaction, bool *aDidMerge)
-{
-  // set out param default value
-  if (aDidMerge)
-    *aDidMerge = false;
-  nsresult result = NS_OK;
-  if (aDidMerge && aTransaction)
-  {
-    // if aTransaction is a InsertTextTxn, and if the selection hasn't changed, 
-    // then absorb it
-    InsertTextTxn *otherInsTxn = nullptr;
-    aTransaction->QueryInterface(InsertTextTxn::GetCID(), (void **)&otherInsTxn);
-    if (otherInsTxn)
-    {
-      if (IsSequentialInsert(otherInsTxn))
-      {
-        nsAutoString otherData;
-        otherInsTxn->GetData(otherData);
-        mStringToInsert += otherData;
-        *aDidMerge = true;
-      }
-      NS_RELEASE(otherInsTxn);
-    }
-  }
-  return result;
-}
-
-NS_IMETHODIMP InsertTextTxn::GetTxnDescription(nsAString& aString)
+NS_IMETHODIMP
+InsertTextTxn::GetTxnDescription(nsAString& aString)
 {
   aString.AssignLiteral("InsertTextTxn: ");
   aString += mStringToInsert;
   return NS_OK;
 }
 
-/* ============ protected methods ================== */
+/* ============ private methods ================== */
 
-NS_IMETHODIMP InsertTextTxn::GetData(nsString& aResult)
+void
+InsertTextTxn::GetData(nsString& aResult)
 {
   aResult = mStringToInsert;
-  return NS_OK;
 }
 
-bool InsertTextTxn::IsSequentialInsert(InsertTextTxn *aOtherTxn)
+bool
+InsertTextTxn::IsSequentialInsert(InsertTextTxn& aOtherTxn)
 {
-  NS_ASSERTION(aOtherTxn, "null param");
-  if (aOtherTxn && aOtherTxn->mElement == mElement)
-  {
-    // here, we need to compare offsets.
-    int32_t length = mStringToInsert.Length();
-    if (aOtherTxn->mOffset == (mOffset + length))
-      return true;
-  }
-  return false;
+  return aOtherTxn.mTextNode == mTextNode &&
+         aOtherTxn.mOffset == mOffset + mStringToInsert.Length();
 }
--- a/editor/libeditor/InsertTextTxn.h
+++ b/editor/libeditor/InsertTextTxn.h
@@ -1,78 +1,79 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/. */
 
 #ifndef InsertTextTxn_h__
 #define InsertTextTxn_h__
 
-#include "EditTxn.h"                    // for EditTxn, NS_DECL_EDITTXN
-#include "nsCOMPtr.h"                   // for nsCOMPtr
-#include "nsCycleCollectionParticipant.h"
-#include "nsID.h"                       // for nsIID
-#include "nsIDOMCharacterData.h"        // for nsIDOMCharacterData
-#include "nsISupportsImpl.h"            // for NS_DECL_ISUPPORTS_INHERITED
-#include "nsString.h"                   // for nsString
-#include "nscore.h"                     // for NS_IMETHOD, nsAString
+#include "EditTxn.h"                    // base class
+#include "nsAutoPtr.h"                  // nsRefPtr members
+#include "nsCycleCollectionParticipant.h" // various macros
+#include "nsID.h"                       // NS_DECLARE_STATIC_IID_ACCESSOR
+#include "nsISupportsImpl.h"            // NS_DECL_ISUPPORTS_INHERITED
+#include "nsString.h"                   // nsString members
+#include "nscore.h"                     // NS_IMETHOD, nsAString
 
-class nsIEditor;
+class nsEditor;
 class nsITransaction;
 
+#define NS_INSERTTEXTTXN_IID \
+{ 0x8c9ad77f, 0x22a7, 0x4d01, \
+  { 0xb1, 0x59, 0x8a, 0x0f, 0xdb, 0x1d, 0x08, 0xe9 } }
 
-#define INSERT_TEXT_TXN_CID \
-{/* 93276f00-ab2c-11d2-8f4b-006008159b0c*/ \
-0x93276f00, 0xab2c, 0x11d2, \
-{0x8f, 0xb4, 0x0, 0x60, 0x8, 0x15, 0x9b, 0xc} }
+namespace mozilla {
+namespace dom {
+
+class Text;
 
 /**
-  * A transaction that inserts text into a content node. 
+  * A transaction that inserts text into a content node.
   */
 class InsertTextTxn : public EditTxn
 {
 public:
-
-  static const nsIID& GetCID() { static const nsIID iid = INSERT_TEXT_TXN_CID; return iid; }
+  NS_DECLARE_STATIC_IID_ACCESSOR(NS_INSERTTEXTTXN_IID)
 
-  /** initialize the transaction
-    * @param aElement the text content node
+  /** @param aElement the text content node
     * @param aOffset  the location in aElement to do the insertion
     * @param aString  the new text to insert
     * @param aPresShell used to get and set the selection
     */
-  NS_IMETHOD Init(nsIDOMCharacterData *aElement,
-                  uint32_t aOffset,
-                  const nsAString& aString,
-                  nsIEditor *aEditor);
-
-  InsertTextTxn();
+  InsertTextTxn(Text& aTextNode, uint32_t aOffset, const nsAString& aString,
+                nsEditor& aEditor);
 
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(InsertTextTxn, EditTxn)
 	
   NS_DECL_EDITTXN
 
-  NS_IMETHOD Merge(nsITransaction *aTransaction, bool *aDidMerge);
+  NS_IMETHOD Merge(nsITransaction* aTransaction, bool* aDidMerge) MOZ_OVERRIDE;
 
-  /** return the string data associated with this transaction */
-  NS_IMETHOD GetData(nsString& aResult);
+  /** Return the string data associated with this transaction */
+  void GetData(nsString& aResult);
 
-protected:
+private:
   virtual ~InsertTextTxn();
 
-  /** return true if aOtherTxn immediately follows this txn */
-  virtual bool IsSequentialInsert(InsertTextTxn *aOtherTxn);
-  
-  /** the text element to operate upon */
-  nsCOMPtr<nsIDOMCharacterData> mElement;
-  
-  /** the offset into mElement where the insertion is to take place */
+  /** Return true if aOtherTxn immediately follows this txn */
+  bool IsSequentialInsert(InsertTextTxn& aOtherTxn);
+
+  /** The Text node to operate upon */
+  nsRefPtr<Text> mTextNode;
+
+  /** The offset into mTextNode where the insertion is to take place */
   uint32_t mOffset;
 
-  /** the text to insert into mElement at mOffset */
+  /** The text to insert into mTextNode at mOffset */
   nsString mStringToInsert;
 
-  /** the editor, which we'll need to get the selection */
-  nsIEditor *mEditor;   
+  /** The editor, which we'll need to get the selection */
+  nsEditor& mEditor;
 };
 
+NS_DEFINE_STATIC_IID_ACCESSOR(InsertTextTxn, NS_INSERTTEXTTXN_IID)
+
+}
+}
+
 #endif
--- a/editor/libeditor/PlaceholderTxn.cpp
+++ b/editor/libeditor/PlaceholderTxn.cpp
@@ -121,19 +121,18 @@ NS_IMETHODIMP PlaceholderTxn::Merge(nsIT
 
   EditTxn *editTxn = (EditTxn*)aTransaction;  //XXX: hack, not safe!  need nsIEditTransaction!
   // determine if this incoming txn is a placeholder txn
   nsCOMPtr<nsIAbsorbingTransaction> plcTxn = do_QueryObject(editTxn);
 
   // we are absorbing all txn's if mAbsorb is lit.
   if (mAbsorb)
   { 
-    nsRefPtr<IMETextTxn> otherTxn;
-    if (NS_SUCCEEDED(aTransaction->QueryInterface(IMETextTxn::GetCID(), getter_AddRefs(otherTxn))) && otherTxn)
-    {
+    nsRefPtr<IMETextTxn> otherTxn = do_QueryObject(aTransaction);
+    if (otherTxn) {
       // special handling for IMETextTxn's: they need to merge with any previous
       // IMETextTxn in this placeholder, if possible.
       if (!mIMETextTxn) 
       {
         // this is the first IME txn in the placeholder
         mIMETextTxn =otherTxn;
         AppendChild(editTxn);
       }
--- a/editor/libeditor/PlaceholderTxn.h
+++ b/editor/libeditor/PlaceholderTxn.h
@@ -11,17 +11,22 @@
 #include "nsIAbsorbingTransaction.h"
 #include "nsIDOMNode.h"
 #include "nsCOMPtr.h"
 #include "nsWeakPtr.h"
 #include "nsWeakReference.h"
 #include "nsAutoPtr.h"
 
 class nsHTMLEditor;
+
+namespace mozilla {
+namespace dom {
 class IMETextTxn;
+}
+}
 
 /**
  * An aggregate transaction that knows how to absorb all subsequent
  * transactions with the same name.  This transaction does not "Do" anything.
  * But it absorbs other transactions via merge, and can undo/redo the
  * transactions it has absorbed.
  */
  
@@ -60,17 +65,17 @@ public:
   NS_IMETHOD RememberEndingSelection();
 
 protected:
   virtual ~PlaceholderTxn();
 
   /** the presentation shell, which we'll need to get the selection */
   bool        mAbsorb;          // do we auto absorb any and all transaction?
   nsWeakPtr   mForwarding;
-  IMETextTxn *mIMETextTxn;      // first IME txn in this placeholder - used for IME merging
+  mozilla::dom::IMETextTxn *mIMETextTxn;      // first IME txn in this placeholder - used for IME merging
                                 // non-owning for now - can't nsCOMPtr it due to broken transaction interfaces
   bool        mCommitted;       // do we stop auto absorbing any matching placeholder txns?
   // these next two members store the state of the selection in a safe way. 
   // selection at the start of the txn is stored, as is the selection at the end.
   // This is so that UndoTransaction() and RedoTransaction() can restore the
   // selection properly.
   nsAutoPtr<nsSelectionState> mStartSel; // use a pointer because this is constructed before we exist
   nsSelectionState  mEndSel;
--- a/editor/libeditor/TextEditorTest.cpp
+++ b/editor/libeditor/TextEditorTest.cpp
@@ -4,18 +4,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifdef DEBUG
 
 #include <stdio.h>
 
 #include "TextEditorTest.h"
 #include "nsDebug.h"
-#include "nsEditProperty.h"
 #include "nsError.h"
+#include "nsGkAtoms.h"
 #include "nsIDOMCharacterData.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMNodeList.h"
 #include "nsIEditor.h"
 #include "nsIHTMLEditor.h"
 #include "nsIPlaintextEditor.h"
 #include "nsISelection.h"
@@ -163,62 +163,68 @@ nsresult TextEditorTest::TestTextPropert
   NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE);
 
   bool any = false;
   bool all = false;
   bool first=false;
 
   const nsAFlatString& empty = EmptyString();
 
-  result = htmlEditor->GetInlineProperty(nsEditProperty::b, empty, empty, &first, &any, &all);
+  result = htmlEditor->GetInlineProperty(nsGkAtoms::b, empty, empty, &first,
+                                         &any, &all);
   TEST_RESULT(result);
   NS_ASSERTION(false==first, "first should be false");
   NS_ASSERTION(false==any, "any should be false");
   NS_ASSERTION(false==all, "all should be false");
-  result = htmlEditor->SetInlineProperty(nsEditProperty::b, empty, empty);
+  result = htmlEditor->SetInlineProperty(nsGkAtoms::b, empty, empty);
   TEST_RESULT(result);
-  result = htmlEditor->GetInlineProperty(nsEditProperty::b, empty, empty, &first, &any, &all);
+  result = htmlEditor->GetInlineProperty(nsGkAtoms::b, empty, empty, &first,
+                                         &any, &all);
   TEST_RESULT(result);
   NS_ASSERTION(true==first, "first should be true");
   NS_ASSERTION(true==any, "any should be true");
   NS_ASSERTION(true==all, "all should be true");
   mEditor->DebugDumpContent();
 
   // remove the bold we just set
   printf("set the whole first text node to not bold\n");
-  result = htmlEditor->RemoveInlineProperty(nsEditProperty::b, empty);
+  result = htmlEditor->RemoveInlineProperty(nsGkAtoms::b, empty);
   TEST_RESULT(result);
-  result = htmlEditor->GetInlineProperty(nsEditProperty::b, empty, empty, &first, &any, &all);
+  result = htmlEditor->GetInlineProperty(nsGkAtoms::b, empty, empty, &first,
+                                         &any, &all);
   TEST_RESULT(result);
   NS_ASSERTION(false==first, "first should be false");
   NS_ASSERTION(false==any, "any should be false");
   NS_ASSERTION(false==all, "all should be false");
   mEditor->DebugDumpContent();
 
   // set all but the first and last character to bold
   printf("set the first text node (1, length-1) to bold and italic, and (2, length-1) to underline.\n");
   selection->Collapse(textNode, 1);
   selection->Extend(textNode, length-1);
-  result = htmlEditor->SetInlineProperty(nsEditProperty::b, empty, empty);
+  result = htmlEditor->SetInlineProperty(nsGkAtoms::b, empty, empty);
   TEST_RESULT(result);
-  result = htmlEditor->GetInlineProperty(nsEditProperty::b, empty, empty, &first, &any, &all);
+  result = htmlEditor->GetInlineProperty(nsGkAtoms::b, empty, empty, &first,
+                                         &any, &all);
   TEST_RESULT(result);
   NS_ASSERTION(true==first, "first should be true");
   NS_ASSERTION(true==any, "any should be true");
   NS_ASSERTION(true==all, "all should be true");
   mEditor->DebugDumpContent();
   // make all that same text italic
-  result = htmlEditor->SetInlineProperty(nsEditProperty::i, empty, empty);
+  result = htmlEditor->SetInlineProperty(nsGkAtoms::i, empty, empty);
   TEST_RESULT(result);
-  result = htmlEditor->GetInlineProperty(nsEditProperty::i, empty, empty, &first, &any, &all);
+  result = htmlEditor->GetInlineProperty(nsGkAtoms::i, empty, empty, &first,
+                                         &any, &all);
   TEST_RESULT(result);
   NS_ASSERTION(true==first, "first should be true");
   NS_ASSERTION(true==any, "any should be true");
   NS_ASSERTION(true==all, "all should be true");
-  result = htmlEditor->GetInlineProperty(nsEditProperty::b, empty, empty, &first, &any, &all);
+  result = htmlEditor->GetInlineProperty(nsGkAtoms::b, empty, empty, &first,
+                                         &any, &all);
   TEST_RESULT(result);
   NS_ASSERTION(true==first, "first should be true");
   NS_ASSERTION(true==any, "any should be true");
   NS_ASSERTION(true==all, "all should be true");
   mEditor->DebugDumpContent();
 
   // make all the text underlined, except for the first 2 and last 2 characters
   result = doc->GetElementsByTagName(textTag, getter_AddRefs(nodeList));
@@ -229,19 +235,20 @@ nsresult TextEditorTest::TestTextPropert
   result = nodeList->Item(count-2, getter_AddRefs(textNode));
   TEST_RESULT(result);
   TEST_POINTER(textNode.get());
   textData = do_QueryInterface(textNode);
   textData->GetLength(&length);
   NS_ASSERTION(length==915, "wrong text node");
   selection->Collapse(textNode, 1);
   selection->Extend(textNode, length-2);
-  result = htmlEditor->SetInlineProperty(nsEditProperty::u, empty, empty);
+  result = htmlEditor->SetInlineProperty(nsGkAtoms::u, empty, empty);
   TEST_RESULT(result);
-  result = htmlEditor->GetInlineProperty(nsEditProperty::u, empty, empty, &first, &any, &all);
+  result = htmlEditor->GetInlineProperty(nsGkAtoms::u, empty, empty, &first,
+                                         &any, &all);
   TEST_RESULT(result);
   NS_ASSERTION(true==first, "first should be true");
   NS_ASSERTION(true==any, "any should be true");
   NS_ASSERTION(true==all, "all should be true");
   mEditor->DebugDumpContent();
 
   return result;
 }
--- a/editor/libeditor/TypeInState.cpp
+++ b/editor/libeditor/TypeInState.cpp
@@ -5,19 +5,19 @@
 
 
 #include <stddef.h>
 
 #include "TypeInState.h"
 #include "mozilla/mozalloc.h"
 #include "nsAString.h"
 #include "nsDebug.h"
-#include "nsEditProperty.h"
 #include "nsEditor.h"
 #include "nsError.h"
+#include "nsGkAtoms.h"
 #include "nsIDOMNode.h"
 #include "nsISelection.h"
 #include "nsISupportsBase.h"
 #include "nsISupportsImpl.h"
 #include "nsReadableUtils.h"
 #include "nsStringFwd.h"
 
 class nsIAtom;
@@ -126,21 +126,21 @@ void TypeInState::Reset()
 }
 
 
 void
 TypeInState::SetProp(nsIAtom* aProp, const nsAString& aAttr,
                      const nsAString& aValue)
 {
   // special case for big/small, these nest
-  if (nsEditProperty::big == aProp) {
+  if (nsGkAtoms::big == aProp) {
     mRelativeFontSize++;
     return;
   }
-  if (nsEditProperty::small == aProp) {
+  if (nsGkAtoms::small == aProp) {
     mRelativeFontSize--;
     return;
   }
 
   int32_t index;
   if (IsPropSet(aProp, aAttr, nullptr, index)) {
     // if it's already set, update the value
     mSetArray[index]->value = aValue;
--- a/editor/libeditor/moz.build
+++ b/editor/libeditor/moz.build
@@ -3,33 +3,32 @@
 # 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/.
 
 TEST_DIRS += ['tests']
 
 UNIFIED_SOURCES += [
     'ChangeAttributeTxn.cpp',
-    'ChangeCSSInlineStyleTxn.cpp',
+    'ChangeStyleTxn.cpp',
     'CreateElementTxn.cpp',
     'DeleteNodeTxn.cpp',
     'DeleteRangeTxn.cpp',
     'DeleteTextTxn.cpp',
     'EditAggregateTxn.cpp',
     'EditTxn.cpp',
     'IMETextTxn.cpp',
     'InsertNodeTxn.cpp',
     'InsertTextTxn.cpp',
     'JoinElementTxn.cpp',
     'nsEditor.cpp',
     'nsEditorCommands.cpp',
     'nsEditorController.cpp',
     'nsEditorEventListener.cpp',
     'nsEditorUtils.cpp',
-    'nsEditProperty.cpp',
     'nsHTMLAbsPosition.cpp',
     'nsHTMLAnonymousUtils.cpp',
     'nsHTMLCSSUtils.cpp',
     'nsHTMLDataTransfer.cpp',
     'nsHTMLEditor.cpp',
     'nsHTMLEditorEventListener.cpp',
     'nsHTMLEditorStyle.cpp',
     'nsHTMLEditRules.cpp',
deleted file mode 100644
--- a/editor/libeditor/nsEditProperty.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* 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 "nsMemory.h"
-#include "nsStaticAtom.h"
-#include "nsEditProperty.h"
-
-using namespace mozilla;
-
-#define EDITOR_ATOM(name_, value_) nsIAtom* nsEditProperty::name_ = 0;
-#include "nsEditPropertyAtomList.h" // IWYU pragma: keep
-#undef EDITOR_ATOM
-
-/* From the HTML 4.0 DTD, 
-
-INLINE:
-<!-- %inline; covers inline or "text-level" elements -->
- <!ENTITY % inline "#PCDATA | %fontstyle; | %phrase; | %special; | %formctrl;">
- <!ENTITY % fontstyle "TT | I | B | BIG | SMALL">
- <!ENTITY % phrase "EM | STRONG | DFN | CODE |
-                    SAMP | KBD | VAR | CITE | ABBR | ACRONYM" >
- <!ENTITY % special
-    "A | IMG | OBJECT | BR | SCRIPT | MAP | Q | SUB | SUP | SPAN | BDO">
- <!ENTITY % formctrl "INPUT | SELECT | TEXTAREA | LABEL | BUTTON">
-
-BLOCK:
-<!ENTITY % block
-      "P | %heading (h1-h6); | %list (UL | OL); | %preformatted (PRE); | DL | DIV | NOSCRIPT |
-       BLOCKQUOTE | FORM | HR | TABLE | FIELDSET | ADDRESS">
-
-But what about BODY, TR, TD, TH, CAPTION, COL, COLGROUP, THEAD, TFOOT, LI, DT, DD, LEGEND, etc.?
- 
-
-*/
-
-#define EDITOR_ATOM(name_, value_) NS_STATIC_ATOM_BUFFER(name_##_buffer, value_)
-#include "nsEditPropertyAtomList.h" // IWYU pragma: keep
-#undef EDITOR_ATOM
-
-void
-nsEditProperty::RegisterAtoms()
-{
-  // inline tags
-  static const nsStaticAtom property_atoms[] = {
-#define EDITOR_ATOM(name_, value_) NS_STATIC_ATOM(name_##_buffer, &name_),
-#include "nsEditPropertyAtomList.h" // IWYU pragma: keep
-#undef EDITOR_ATOM
-  };
-  
-  NS_RegisterStaticAtoms(property_atoms);
-}
deleted file mode 100644
--- a/editor/libeditor/nsEditProperty.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* 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/. */
-
-#ifndef __nsEditProperty_h__
-#define __nsEditProperty_h__
-
-#include "nsISupports.h"
-
-class nsIAtom;
-class nsString;
-
-/** simple interface for describing a single property as it relates to a range of content.
-  *
-  */
-
-class nsEditProperty
-{
-public:
-
-    static void RegisterAtoms();
-
-#define EDITOR_ATOM(name_, value_) static nsIAtom* name_;
-#include "nsEditPropertyAtomList.h"
-#undef EDITOR_ATOM
-
-};
-
-
-
-#endif
deleted file mode 100644
--- a/editor/libeditor/nsEditPropertyAtomList.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/* 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/. */
-
-// IWYU pragma: private, include "nsEditProperty.h"
-
-/******
-
-  This file contains the list of all editor nsIAtoms and their values
-
-  It is designed to be used as inline input to nsEditProperty.cpp *only*
-  through the magic of C preprocessing.
-
-  All entries must be enclosed in the macro EDITOR_ATOM which will have cruel
-  and unusual things done to it
-
-  It is recommended (but not strictly necessary) to keep all entries
-  in alphabetical order
-
-  The first argument to EDITOR_ATOM is the C++ identifier of the atom
-  The second argument is the string value of the atom
-
- ******/
-
-EDITOR_ATOM(a, "a")
-EDITOR_ATOM(abbr, "abbr")
-EDITOR_ATOM(acronym, "acronym")
-EDITOR_ATOM(address, "address")
-EDITOR_ATOM(article, "article")
-EDITOR_ATOM(aside, "aside")
-EDITOR_ATOM(b, "b")
-EDITOR_ATOM(bdo, "bdo")
-EDITOR_ATOM(big, "big")
-EDITOR_ATOM(blockquote, "blockquote")
-EDITOR_ATOM(body, "body")
-EDITOR_ATOM(br, "br")
-EDITOR_ATOM(button, "button")
-EDITOR_ATOM(caption, "caption")
-EDITOR_ATOM(center, "center")
-EDITOR_ATOM(cite, "cite")
-EDITOR_ATOM(code, "code")
-EDITOR_ATOM(col, "col")
-EDITOR_ATOM(colgroup, "colgroup")
-EDITOR_ATOM(color, "color")
-EDITOR_ATOM(cssBackgroundColor, "background-color")
-EDITOR_ATOM(cssBackgroundImage, "background-image")
-EDITOR_ATOM(cssBorder, "border")
-EDITOR_ATOM(cssBottom, "bottom")
-EDITOR_ATOM(cssCaptionSide, "caption-side")
-EDITOR_ATOM(cssCmUnit, "cm")
-EDITOR_ATOM(cssColor, "color")
-EDITOR_ATOM(cssDirection, "direction")
-EDITOR_ATOM(cssEmUnit, "em")
-EDITOR_ATOM(cssExUnit, "ex")
-EDITOR_ATOM(cssFloat, "float")
-EDITOR_ATOM(cssFontFamily, "font-family")
-EDITOR_ATOM(cssFontSize, "font-size")
-EDITOR_ATOM(cssFontStyle, "font-style")
-EDITOR_ATOM(cssFontWeight, "font-weight")
-EDITOR_ATOM(cssHeight, "height")
-EDITOR_ATOM(cssInUnit, "in")
-EDITOR_ATOM(cssLeft, "left")
-EDITOR_ATOM(cssListStyleType, "list-style-type")
-EDITOR_ATOM(cssMarginLeft, "margin-left")
-EDITOR_ATOM(cssMarginRight, "margin-right")
-EDITOR_ATOM(cssMmUnit, "mm")
-EDITOR_ATOM(cssMozUserModify, "-moz-user-modify")
-EDITOR_ATOM(cssMozUserSelect, "-moz-user-select")
-EDITOR_ATOM(cssPcUnit, "pc")
-EDITOR_ATOM(cssPercentUnit, "%")
-EDITOR_ATOM(cssPosition, "position")
-EDITOR_ATOM(cssPtUnit, "pt")
-EDITOR_ATOM(cssPxUnit, "px")
-EDITOR_ATOM(cssRight, "right")
-EDITOR_ATOM(cssTextAlign, "text-align")
-EDITOR_ATOM(cssTextDecoration, "text-decoration")
-EDITOR_ATOM(cssTop, "top")
-EDITOR_ATOM(cssVerticalAlign, "vertical-align")
-EDITOR_ATOM(cssWhitespace, "white-space")
-EDITOR_ATOM(cssWidth, "width")
-EDITOR_ATOM(cssZIndex, "z-index")
-EDITOR_ATOM(data, "data")
-EDITOR_ATOM(datalist, "datalist")
-EDITOR_ATOM(dd, "dd")
-EDITOR_ATOM(dfn, "dfn")
-EDITOR_ATOM(div, "div")
-EDITOR_ATOM(dl, "dl")
-EDITOR_ATOM(dt, "dt")
-EDITOR_ATOM(em, "em")
-EDITOR_ATOM(face, "face")
-EDITOR_ATOM(fieldset, "fieldset")
-EDITOR_ATOM(figcaption, "figcaption")
-EDITOR_ATOM(figure, "figure")
-EDITOR_ATOM(font, "font")
-EDITOR_ATOM(footer, "footer")
-EDITOR_ATOM(form, "form")
-EDITOR_ATOM(h1, "h1")
-EDITOR_ATOM(h2, "h2")
-EDITOR_ATOM(h3, "h3")
-EDITOR_ATOM(h4, "h4")
-EDITOR_ATOM(h5, "h5")
-EDITOR_ATOM(h6, "h6")
-EDITOR_ATOM(header, "header")
-EDITOR_ATOM(head, "head")
-EDITOR_ATOM(hgroup, "hgroup")
-EDITOR_ATOM(href, "href") // Use to differentiate between "a" for link, "a" for named anchor
-EDITOR_ATOM(hr, "hr")
-EDITOR_ATOM(html, "html")
-EDITOR_ATOM(i, "i")
-EDITOR_ATOM(img, "img")
-EDITOR_ATOM(input, "input")
-EDITOR_ATOM(kbd, "kbd")
-EDITOR_ATOM(keygen, "keygen")
-EDITOR_ATOM(label, "label")
-EDITOR_ATOM(legend, "legend")
-EDITOR_ATOM(li, "li")
-EDITOR_ATOM(main, "main")
-EDITOR_ATOM(map, "map")
-EDITOR_ATOM(mark, "mark")
-EDITOR_ATOM(meter, "meter")
-EDITOR_ATOM(menuitem, "menuitem")
-EDITOR_ATOM(mozdirty, "_moz_dirty")
-EDITOR_ATOM(mozEditorBogusNode, "_moz_editor_bogus_node")
-EDITOR_ATOM(name, "name")
-EDITOR_ATOM(nav, "nav")
-EDITOR_ATOM(noscript, "noscript")
-EDITOR_ATOM(object, "object")
-EDITOR_ATOM(ol, "ol")
-EDITOR_ATOM(output, "output")
-EDITOR_ATOM(p, "p")
-EDITOR_ATOM(pre, "pre")
-EDITOR_ATOM(progress, "progress")
-EDITOR_ATOM(q, "q")
-EDITOR_ATOM(rb, "rb")
-EDITOR_ATOM(rp, "rp")
-EDITOR_ATOM(rt, "rt")
-EDITOR_ATOM(rtc, "rtc")
-EDITOR_ATOM(ruby, "ruby")
-EDITOR_ATOM(samp, "samp")
-EDITOR_ATOM(script, "script")
-EDITOR_ATOM(section, "section")
-EDITOR_ATOM(select, "select")
-EDITOR_ATOM(size, "size")
-EDITOR_ATOM(small, "small")
-EDITOR_ATOM(span, "span")
-EDITOR_ATOM(s, "s")
-EDITOR_ATOM(strike, "strike")
-EDITOR_ATOM(strong, "strong")
-EDITOR_ATOM(sub, "sub")
-EDITOR_ATOM(sup, "sup")
-EDITOR_ATOM(table, "table")
-EDITOR_ATOM(tbody, "tbody")
-EDITOR_ATOM(td, "td")
-EDITOR_ATOM(textarea, "textarea")
-EDITOR_ATOM(tfoot, "tfoot")
-EDITOR_ATOM(thead, "thead")
-EDITOR_ATOM(th, "th")
-EDITOR_ATOM(time, "time")
-EDITOR_ATOM(tr, "tr")
-EDITOR_ATOM(track, "track")
-EDITOR_ATOM(tt, "tt")
-EDITOR_ATOM(ul, "ul")
-EDITOR_ATOM(u, "u")
-EDITOR_ATOM(var, "var")
--- a/editor/libeditor/nsEditor.cpp
+++ b/editor/libeditor/nsEditor.cpp
@@ -38,17 +38,16 @@
 #include "nsCaret.h"                    // for nsCaret
 #include "nsCaseTreatment.h"
 #include "nsCharTraits.h"               // for NS_IS_HIGH_SURROGATE, etc
 #include "nsComponentManagerUtils.h"    // for do_CreateInstance
 #include "nsComputedDOMStyle.h"         // for nsComputedDOMStyle
 #include "nsContentUtils.h"             // for nsContentUtils
 #include "nsDOMString.h"                // for DOMStringIsNull
 #include "nsDebug.h"                    // for NS_ENSURE_TRUE, etc
-#include "nsEditProperty.h"             // for nsEditProperty, etc
 #include "nsEditor.h"
 #include "nsEditorEventListener.h"      // for nsEditorEventListener
 #include "nsEditorUtils.h"              // for nsAutoRules, etc
 #include "nsError.h"                    // for NS_OK, etc
 #include "nsFocusManager.h"             // for nsFocusManager
 #include "nsFrameSelection.h"           // for nsFrameSelection
 #include "nsGkAtoms.h"                  // for nsGkAtoms, nsGkAtoms::dir
 #include "nsIAbsorbingTransaction.h"    // for nsIAbsorbingTransaction
@@ -1169,26 +1168,27 @@ nsEditor::CanPaste(int32_t aSelectionTyp
 }
 
 NS_IMETHODIMP
 nsEditor::CanPasteTransferable(nsITransferable *aTransferable, bool *aCanPaste)
 {
   return NS_ERROR_NOT_IMPLEMENTED; 
 }
 
-NS_IMETHODIMP 
-nsEditor::SetAttribute(nsIDOMElement *aElement, const nsAString & aAttribute, const nsAString & aValue)
-{
-  nsRefPtr<ChangeAttributeTxn> txn;
-  nsresult result = CreateTxnForSetAttribute(aElement, aAttribute, aValue,
-                                             getter_AddRefs(txn));
-  if (NS_SUCCEEDED(result))  {
-    result = DoTransaction(txn);  
-  }
-  return result;
+NS_IMETHODIMP
+nsEditor::SetAttribute(nsIDOMElement* aElement, const nsAString& aAttribute,
+                       const nsAString& aValue)
+{
+  nsCOMPtr<Element> element = do_QueryInterface(aElement);
+  NS_ENSURE_TRUE(element, NS_ERROR_NULL_POINTER);
+  nsCOMPtr<nsIAtom> attribute = do_GetAtom(aAttribute);
+
+  nsRefPtr<ChangeAttributeTxn> txn =
+    CreateTxnForSetAttribute(*element, *attribute, aValue);
+  return DoTransaction(txn);
 }
 
 NS_IMETHODIMP 
 nsEditor::GetAttributeValue(nsIDOMElement *aElement, 
                             const nsAString & aAttribute, 
                             nsAString & aResultValue, 
                             bool *aResultIsSet)
 {
@@ -1202,26 +1202,26 @@ nsEditor::GetAttributeValue(nsIDOMElemen
   NS_ENSURE_SUCCESS(rv, rv);
   if (!DOMStringIsNull(value)) {
     *aResultIsSet = true;
     aResultValue = value;
   }
   return rv;
 }
 
-NS_IMETHODIMP 
-nsEditor::RemoveAttribute(nsIDOMElement *aElement, const nsAString& aAttribute)
-{
-  nsRefPtr<ChangeAttributeTxn> txn;
-  nsresult result = CreateTxnForRemoveAttribute(aElement, aAttribute,
-                                                getter_AddRefs(txn));
-  if (NS_SUCCEEDED(result))  {
-    result = DoTransaction(txn);  
-  }
-  return result;
+NS_IMETHODIMP
+nsEditor::RemoveAttribute(nsIDOMElement* aElement, const nsAString& aAttribute)
+{
+  nsCOMPtr<Element> element = do_QueryInterface(aElement);
+  NS_ENSURE_TRUE(element, NS_ERROR_NULL_POINTER);
+  nsCOMPtr<nsIAtom> attribute = do_GetAtom(aAttribute);
+
+  nsRefPtr<ChangeAttributeTxn> txn =
+    CreateTxnForRemoveAttribute(*element, *attribute);
+  return DoTransaction(txn);
 }
 
 
 bool
 nsEditor::OutputsMozDirty()
 {
   // Return true for Composer (!eEditorAllowInteraction) or mail
   // (eEditorMailMask), but false for webpages.
@@ -1234,17 +1234,17 @@ NS_IMETHODIMP
 nsEditor::MarkNodeDirty(nsIDOMNode* aNode)
 {  
   // Mark the node dirty, but not for webpages (bug 599983)
   if (!OutputsMozDirty()) {
     return NS_OK;
   }
   nsCOMPtr<dom::Element> element = do_QueryInterface(aNode);
   if (element) {
-    element->SetAttr(kNameSpaceID_None, nsEditProperty::mozdirty,
+    element->SetAttr(kNameSpaceID_None, nsGkAtoms::mozdirty,
                      EmptyString(), false);
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP nsEditor::GetInlineSpellChecker(bool autoCreate,
                                               nsIInlineSpellChecker ** aInlineSpellChecker)
 {
@@ -2330,27 +2330,25 @@ nsEditor::InsertTextImpl(const nsAString
       NS_ENSURE_STATE(doc);
       nsRefPtr<nsTextNode> newNode = doc->CreateTextNode(EmptyString());
       // then we insert it into the dom tree
       res = InsertNode(newNode->AsDOMNode(), node->AsDOMNode(), offset);
       NS_ENSURE_SUCCESS(res, res);
       node = newNode;
       offset = 0;
     }
-    nsCOMPtr<nsIDOMCharacterData> charDataNode = do_QueryInterface(node);
-    NS_ENSURE_STATE(charDataNode);
-    res = InsertTextIntoTextNodeImpl(aStringToInsert, charDataNode, offset);
+    res = InsertTextIntoTextNodeImpl(aStringToInsert, *node->GetAsText(),
+                                     offset);
     NS_ENSURE_SUCCESS(res, res);
     offset += aStringToInsert.Length();
   } else {
     if (node->IsNodeOfType(nsINode::eTEXT)) {
       // we are inserting text into an existing text node.
-      nsCOMPtr<nsIDOMCharacterData> charDataNode = do_QueryInterface(node);
-      NS_ENSURE_STATE(charDataNode);
-      res = InsertTextIntoTextNodeImpl(aStringToInsert, charDataNode, offset);
+      res = InsertTextIntoTextNodeImpl(aStringToInsert, *node->GetAsText(),
+                                       offset);
       NS_ENSURE_SUCCESS(res, res);
       offset += aStringToInsert.Length();
     } else {
       // we are inserting text into a non-text node.  first we have to create a
       // textnode (this also populates it with the text)
       nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDoc);
       NS_ENSURE_STATE(doc);
       nsRefPtr<nsTextNode> newNode = doc->CreateTextNode(aStringToInsert);
@@ -2363,39 +2361,29 @@ nsEditor::InsertTextImpl(const nsAString
   }
 
   *aInOutNode = node->AsDOMNode();
   *aInOutOffset = static_cast<int32_t>(offset);
   return NS_OK;
 }
 
 
-nsresult nsEditor::InsertTextIntoTextNodeImpl(const nsAString& aStringToInsert,
-                                              Text* aTextNode,
-                                              int32_t aOffset,
-                                              bool aSuppressIME)
-{
-  return InsertTextIntoTextNodeImpl(aStringToInsert,
-      static_cast<nsIDOMCharacterData*>(GetAsDOMNode(aTextNode)),
-      aOffset, aSuppressIME);
-}
-
-nsresult nsEditor::InsertTextIntoTextNodeImpl(const nsAString& aStringToInsert, 
-                                              nsIDOMCharacterData *aTextNode, 
-                                              int32_t aOffset,
-                                              bool aSuppressIME)
+nsresult
+nsEditor::InsertTextIntoTextNodeImpl(const nsAString& aStringToInsert,
+                                     Text& aTextNode,
+                                     int32_t aOffset, bool aSuppressIME)
 {
   nsRefPtr<EditTxn> txn;
-  nsresult result = NS_OK;
   bool isIMETransaction = false;
   // aSuppressIME is used when editor must insert text, yet this text is not
-  // part of current ime operation.  example: adjusting whitespace around an ime insertion.
+  // part of the current IME operation. Example: adjusting whitespace around an
+  // IME insertion.
   if (mComposition && !aSuppressIME) {
     if (!mIMETextNode) {
-      mIMETextNode = aTextNode;
+      mIMETextNode = &aTextNode;
       mIMETextOffset = aOffset;
     }
     // Modify mPhonetic with raw text input clauses.
     const TextRangeArray* ranges = mComposition->GetRanges();
     for (uint32_t i = 0; i < (ranges ? ranges->Length() : 0); ++i) {
       const TextRange& textRange = ranges->ElementAt(i);
       if (!textRange.Length() ||
           textRange.mRangeType != NS_TEXTRANGE_RAWINPUT) {
@@ -2404,69 +2392,64 @@ nsresult nsEditor::InsertTextIntoTextNod
       if (!mPhonetic) {
         mPhonetic = new nsString();
       }
       nsAutoString stringToInsert(aStringToInsert);
       stringToInsert.Mid(*mPhonetic,
                          textRange.mStartOffset, textRange.Length());
     }
 
-    nsRefPtr<IMETextTxn> imeTxn;
-    result = CreateTxnForIMEText(aStringToInsert, getter_AddRefs(imeTxn));
-    txn = imeTxn;
+    txn = CreateTxnForIMEText(aStringToInsert);
     isIMETransaction = true;
+  } else {
+    txn = CreateTxnForInsertText(aStringToInsert, aTextNode, aOffset);
   }
-  else
-  {
-    nsRefPtr<InsertTextTxn> insertTxn;
-    result = CreateTxnForInsertText(aStringToInsert, aTextNode, aOffset,
-                                    getter_AddRefs(insertTxn));
-    txn = insertTxn;
+
+  // Let listeners know what's up
+  for (int32_t i = 0; i < mActionListeners.Count(); i++) {
+    mActionListeners[i]->WillInsertText(
+      static_cast<nsIDOMCharacterData*>(aTextNode.AsDOMNode()), aOffset,
+      aStringToInsert);
   }
-  NS_ENSURE_SUCCESS(result, result);
-
-  // let listeners know what's up
-  int32_t i;
-  for (i = 0; i < mActionListeners.Count(); i++)
-    mActionListeners[i]->WillInsertText(aTextNode, aOffset, aStringToInsert);
-  
-  // XXX we may not need these view batches anymore.  This is handled at a higher level now I believe
+
+  // XXX We may not need these view batches anymore.  This is handled at a
+  // higher level now I believe.
   BeginUpdateViewBatch();
-  result = DoTransaction(txn);
+  nsresult res = DoTransaction(txn);
   EndUpdateViewBatch();
 
   mRangeUpdater.SelAdjInsertText(aTextNode, aOffset, aStringToInsert);
-  
+
   // let listeners know what happened
-  for (i = 0; i < mActionListeners.Count(); i++)
-    mActionListeners[i]->DidInsertText(aTextNode, aOffset, aStringToInsert, result);
-
-  // Added some cruft here for bug 43366.  Layout was crashing because we left an 
-  // empty text node lying around in the document.  So I delete empty text nodes
-  // caused by IME.  I have to mark the IME transaction as "fixed", which means
-  // that furure ime txns won't merge with it.  This is because we don't want
-  // future ime txns trying to put their text into a node that is no longer in
-  // the document.  This does not break undo/redo, because all these txns are 
-  // wrapped in a parent PlaceHolder txn, and placeholder txns are already 
-  // savvy to having multiple ime txns inside them.
-  
-  // delete empty ime text node if there is one
-  if (isIMETransaction && mIMETextNode)
-  {
-    uint32_t len;
-    mIMETextNode->GetLength(&len);
-    if (!len)
-    {
+  for (int32_t i = 0; i < mActionListeners.Count(); i++) {
+    mActionListeners[i]->DidInsertText(
+      static_cast<nsIDOMCharacterData*>(aTextNode.AsDOMNode()),
+      aOffset, aStringToInsert, res);
+  }
+
+  // Added some cruft here for bug 43366.  Layout was crashing because we left
+  // an empty text node lying around in the document.  So I delete empty text
+  // nodes caused by IME.  I have to mark the IME transaction as "fixed", which
+  // means that furure IME txns won't merge with it.  This is because we don't
+  // want future IME txns trying to put their text into a node that is no
+  // longer in the document.  This does not break undo/redo, because all these
+  // txns are wrapped in a parent PlaceHolder txn, and placeholder txns are
+  // already savvy to having multiple ime txns inside them.
+
+  // Delete empty IME text node if there is one
+  if (isIMETransaction && mIMETextNode) {
+    uint32_t len = mIMETextNode->Length();
+    if (!len) {
       DeleteNode(mIMETextNode);
       mIMETextNode = nullptr;
-      static_cast<IMETextTxn*>(txn.get())->MarkFixed();  // mark the ime txn "fixed"
+      static_cast<IMETextTxn*>(txn.get())->MarkFixed();
     }
   }
-  
-  return result;
+
+  return res;
 }
 
 
 NS_IMETHODIMP nsEditor::SelectEntireDocument(nsISelection *aSelection)
 {
   if (!aSelection) { return NS_ERROR_NULL_POINTER; }
 
   nsCOMPtr<nsIDOMElement> rootElement = do_QueryInterface(GetRoot());
@@ -2544,32 +2527,23 @@ nsEditor::NotifyDocumentListeners(TDocum
     default:
       NS_NOTREACHED("Unknown notification");
   }
 
   return rv;
 }
 
 
-NS_IMETHODIMP nsEditor::CreateTxnForInsertText(const nsAString & aStringToInsert,
-                                               nsIDOMCharacterData *aTextNode,
-                                               int32_t aOffset,
-                                               InsertTextTxn ** aTxn)
-{
-  NS_ENSURE_TRUE(aTextNode && aTxn, NS_ERROR_NULL_POINTER);
-  nsresult rv;
-
-  nsRefPtr<InsertTextTxn> txn = new InsertTextTxn();
-  rv = txn->Init(aTextNode, aOffset, aStringToInsert, this);
-  if (NS_SUCCEEDED(rv))
-  {
-    txn.forget(aTxn);
-  }
-
-  return rv;
+already_AddRefed<InsertTextTxn>
+nsEditor::CreateTxnForInsertText(const nsAString& aStringToInsert,
+                                 Text& aTextNode, int32_t aOffset)
+{
+  nsRefPtr<InsertTextTxn> txn = new InsertTextTxn(aTextNode, aOffset,
+                                                  aStringToInsert, *this);
+  return txn.forget();
 }
 
 
 nsresult
 nsEditor::DeleteText(nsGenericDOMDataNode& aCharData, uint32_t aOffset,
                      uint32_t aLength)
 {
   nsRefPtr<DeleteTextTxn> txn =
@@ -4249,52 +4223,34 @@ nsEditor::DoAfterUndoTransaction()
 void
 nsEditor::DoAfterRedoTransaction()
 {
   // all redoable transactions are non-transient
   MOZ_ALWAYS_TRUE(NS_SUCCEEDED(
     IncrementModificationCount(1)));
 }
 
-NS_IMETHODIMP 
-nsEditor::CreateTxnForSetAttribute(nsIDOMElement *aElement, 
-                                   const nsAString& aAttribute, 
-                                   const nsAString& aValue,
-                                   ChangeAttributeTxn ** aTxn)
-{
-  NS_ENSURE_TRUE(aElement, NS_ERROR_NULL_POINTER);
-
-  nsRefPtr<ChangeAttributeTxn> txn = new ChangeAttributeTxn();
-
-  nsresult rv = txn->Init(this, aElement, aAttribute, aValue, false);
-  if (NS_SUCCEEDED(rv))
-  {
-    txn.forget(aTxn);
-  }
-
-  return rv;
-}
-
-
-NS_IMETHODIMP 
-nsEditor::CreateTxnForRemoveAttribute(nsIDOMElement *aElement, 
-                                      const nsAString& aAttribute,
-                                      ChangeAttributeTxn ** aTxn)
-{
-  NS_ENSURE_TRUE(aElement, NS_ERROR_NULL_POINTER);
-
-  nsRefPtr<ChangeAttributeTxn> txn = new ChangeAttributeTxn();
-
-  nsresult rv = txn->Init(this, aElement, aAttribute, EmptyString(), true);
-  if (NS_SUCCEEDED(rv))
-  {
-    txn.forget(aTxn);
-  }
-
-  return rv;
+already_AddRefed<ChangeAttributeTxn>
+nsEditor::CreateTxnForSetAttribute(Element& aElement, nsIAtom& aAttribute,
+                                   const nsAString& aValue)
+{
+  nsRefPtr<ChangeAttributeTxn> txn =
+    new ChangeAttributeTxn(aElement, aAttribute, &aValue);
+
+  return txn.forget();
+}
+
+
+already_AddRefed<ChangeAttributeTxn>
+nsEditor::CreateTxnForRemoveAttribute(Element& aElement, nsIAtom& aAttribute)
+{
+  nsRefPtr<ChangeAttributeTxn> txn =
+    new ChangeAttributeTxn(aElement, aAttribute, nullptr);
+
+  return txn.forget();
 }
 
 
 already_AddRefed<CreateElementTxn>
 nsEditor::CreateTxnForCreateElement(nsIAtom& aTag,
                                     nsINode& aParent,
                                     int32_t aPosition)
 {
@@ -4324,35 +4280,26 @@ nsEditor::CreateTxnForDeleteNode(nsINode
 
   nsresult res = txn->Init(this, aNode, &mRangeUpdater);
   NS_ENSURE_SUCCESS(res, res);
 
   txn.forget(aTxn);
   return NS_OK;
 }
 
-NS_IMETHODIMP 
-nsEditor::CreateTxnForIMEText(const nsAString& aStringToInsert,
-                              IMETextTxn ** aTxn)
-{
-  NS_ASSERTION(aTxn, "illegal value- null ptr- aTxn");
-     
-  nsRefPtr<IMETextTxn> txn = new IMETextTxn();
-
+already_AddRefed<IMETextTxn>
+nsEditor::CreateTxnForIMEText(const nsAString& aStringToInsert)
+{
   // During handling IME composition, mComposition must have been initialized.
   // TODO: We can simplify IMETextTxn::Init() with TextComposition class.
-  nsresult rv = txn->Init(mIMETextNode, mIMETextOffset,
-                          mComposition->String().Length(),
-                          mComposition->GetRanges(), aStringToInsert, this);
-  if (NS_SUCCEEDED(rv))
-  {
-    txn.forget(aTxn);
-  }
-
-  return rv;
+  nsRefPtr<IMETextTxn> txn = new IMETextTxn(*mIMETextNode, mIMETextOffset,
+                                            mComposition->String().Length(),
+                                            mComposition->GetRanges(),
+                                            aStringToInsert, *this);
+  return txn.forget();
 }
 
 
 NS_IMETHODIMP 
 nsEditor::CreateTxnForAddStyleSheet(CSSStyleSheet* aSheet, AddStyleSheetTxn* *aTxn)
 {
   nsRefPtr<AddStyleSheetTxn> txn = new AddStyleSheetTxn();
 
--- a/editor/libeditor/nsEditor.h
+++ b/editor/libeditor/nsEditor.h
@@ -8,36 +8,33 @@
 
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc.
 #include "mozilla/TypedEnum.h"          // for MOZ_BEGIN_ENUM_CLASS, etc.
 #include "mozilla/dom/Text.h"
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsCOMArray.h"                 // for nsCOMArray
 #include "nsCOMPtr.h"                   // for already_AddRefed, nsCOMPtr
 #include "nsCycleCollectionParticipant.h"
-#include "nsEditProperty.h"             // for nsEditProperty, etc
+#include "nsGkAtoms.h"
 #include "nsIEditor.h"                  // for nsIEditor::EDirection, etc
 #include "nsIEditorIMESupport.h"        // for NS_DECL_NSIEDITORIMESUPPORT, etc
 #include "nsIObserver.h"                // for NS_DECL_NSIOBSERVER, etc
 #include "nsIPhonetic.h"                // for NS_DECL_NSIPHONETIC, etc
 #include "nsIPlaintextEditor.h"         // for nsIPlaintextEditor, etc
 #include "nsISupportsImpl.h"            // for nsEditor::Release, etc
 #include "nsIWeakReferenceUtils.h"      // for nsWeakPtr
 #include "nsLiteralString.h"            // for NS_LITERAL_STRING
 #include "nsSelectionState.h"           // for nsRangeUpdater, etc
 #include "nsString.h"                   // for nsCString
 #include "nsWeakReference.h"            // for nsSupportsWeakReference
 #include "nscore.h"                     // for nsresult, nsAString, etc
 
 class AddStyleSheetTxn;
-class ChangeAttributeTxn;
 class DeleteNodeTxn;
 class EditAggregateTxn;
-class IMETextTxn;
-class InsertTextTxn;
 class JoinElementTxn;
 class RemoveStyleSheetTxn;
 class SplitElementTxn;
 class nsIAtom;
 class nsIContent;
 class nsIDOMCharacterData;
 class nsIDOMDataTransfer;
 class nsIDOMDocument;
@@ -64,34 +61,37 @@ class nsString;
 class nsTransactionManager;
 
 namespace mozilla {
 class CSSStyleSheet;
 class ErrorResult;
 class TextComposition;
 
 namespace dom {
+class ChangeAttributeTxn;
 class CreateElementTxn;
 class DataTransfer;
 class DeleteTextTxn;
 class Element;
 class EventTarget;
+class IMETextTxn;
+class InsertTextTxn;
 class InsertNodeTxn;
 class Selection;
 class Text;
 }  // namespace dom
 }  // namespace mozilla
 
 namespace mozilla {
 namespace widget {
 struct IMEState;
 } // namespace widget
 } // namespace mozilla
 
-#define kMOZEditorBogusNodeAttrAtom nsEditProperty::mozEditorBogusNode
+#define kMOZEditorBogusNodeAttrAtom nsGkAtoms::mozeditorbogusnode
 #define kMOZEditorBogusNodeValue NS_LITERAL_STRING("TRUE")
 
 // This is int32_t instead of int16_t because nsIInlineSpellChecker.idl's
 // spellCheckAfterEditorChange is defined to take it as a long.
 MOZ_BEGIN_ENUM_CLASS(EditAction, int32_t)
   ignore = -1,
   none = 0,
   undo,
@@ -202,21 +202,17 @@ public:
 
   virtual bool IsModifiableNode(nsINode *aNode);
 
   NS_IMETHOD InsertTextImpl(const nsAString& aStringToInsert, 
                                nsCOMPtr<nsIDOMNode> *aInOutNode, 
                                int32_t *aInOutOffset,
                                nsIDOMDocument *aDoc);
   nsresult InsertTextIntoTextNodeImpl(const nsAString& aStringToInsert,
-                                      mozilla::dom::Text* aTextNode,
-                                      int32_t aOffset,
-                                      bool aSuppressIME = false);
-  nsresult InsertTextIntoTextNodeImpl(const nsAString& aStringToInsert, 
-                                      nsIDOMCharacterData *aTextNode, 
+                                      mozilla::dom::Text& aTextNode,
                                       int32_t aOffset,
                                       bool aSuppressIME = false);
   NS_IMETHOD DeleteSelectionImpl(EDirection aAction,
                                  EStripWrappers aStripWrappers);
   NS_IMETHOD DeleteSelectionAndCreateNode(const nsAString& aTag,
                                            nsIDOMNode ** aNewNode);
 
   /* helper routines for node/parent manipulations */
@@ -253,28 +249,29 @@ public:
   void EndIMEComposition();
 
   void SwitchTextDirectionTo(uint32_t aDirection);
 
 protected:
   nsresult DetermineCurrentDirection();
   void FireInputEvent();
 
-  /** create a transaction for setting aAttribute to aValue on aElement
+  /** Create a transaction for setting aAttribute to aValue on aElement.  Never
+    * returns null.
     */
-  NS_IMETHOD CreateTxnForSetAttribute(nsIDOMElement *aElement,
-                                      const nsAString &  aAttribute,
-                                      const nsAString &  aValue,
-                                      ChangeAttributeTxn ** aTxn);
+  already_AddRefed<mozilla::dom::ChangeAttributeTxn>
+  CreateTxnForSetAttribute(mozilla::dom::Element& aElement,
+                           nsIAtom& aAttribute, const nsAString& aValue);
 
-  /** create a transaction for removing aAttribute on aElement
+  /** Create a transaction for removing aAttribute on aElement.  Never returns
+    * null.
     */
-  NS_IMETHOD CreateTxnForRemoveAttribute(nsIDOMElement *aElement,
-                                         const nsAString &  aAttribute,
-                                         ChangeAttributeTxn ** aTxn);
+  already_AddRefed<mozilla::dom::ChangeAttributeTxn>
+  CreateTxnForRemoveAttribute(mozilla::dom::Element& aElement,
+                              nsIAtom& aAttribute);
 
   /** create a transaction for creating a new child node of aParent of type aTag.
     */
   already_AddRefed<mozilla::dom::CreateElementTxn>
   CreateTxnForCreateElement(nsIAtom& aTag,
                             nsINode& aParent,
                             int32_t aPosition);
 
@@ -301,26 +298,26 @@ protected:
   nsresult CreateTxnForDeleteInsertionPoint(nsRange* aRange, 
                                             EDirection aAction, 
                                             EditAggregateTxn* aTxn,
                                             nsINode** aNode,
                                             int32_t* aOffset,
                                             int32_t* aLength);
 
 
-  /** create a transaction for inserting aStringToInsert into aTextNode
-    * if aTextNode is null, the string is inserted at the current selection.
+  /** Create a transaction for inserting aStringToInsert into aTextNode.  Never
+    * returns null.
     */
-  NS_IMETHOD CreateTxnForInsertText(const nsAString & aStringToInsert,
-                                    nsIDOMCharacterData *aTextNode,
-                                    int32_t aOffset,
-                                    InsertTextTxn ** aTxn);
+  already_AddRefed<mozilla::dom::InsertTextTxn>
+  CreateTxnForInsertText(const nsAString& aStringToInsert,
+                         mozilla::dom::Text& aTextNode, int32_t aOffset);
 
-  NS_IMETHOD CreateTxnForIMEText(const nsAString & aStringToInsert,
-                                 IMETextTxn ** aTxn);
+  // Never returns null.
+  already_AddRefed<mozilla::dom::IMETextTxn>
+  CreateTxnForIMEText(const nsAString & aStringToInsert);
 
   /** create a transaction for adding a style sheet
     */
   NS_IMETHOD CreateTxnForAddStyleSheet(mozilla::CSSStyleSheet* aSheet,
                                        AddStyleSheetTxn* *aTxn);
 
   /** create a transaction for removing a style sheet
     */
@@ -834,17 +831,17 @@ protected:
   };
   // Spellchecking
   nsCString mContentMIMEType;       // MIME type of the doc we are editing.
 
   nsCOMPtr<nsIInlineSpellChecker> mInlineSpellChecker;
 
   nsRefPtr<nsTransactionManager> mTxnMgr;
   nsCOMPtr<mozilla::dom::Element> mRootElement; // cached root node
-  nsCOMPtr<nsIDOMCharacterData>     mIMETextNode;      // current IME text node
+  nsRefPtr<mozilla::dom::Text>    mIMETextNode; // current IME text node
   nsCOMPtr<mozilla::dom::EventTarget> mEventTarget; // The form field as an event receiver
   nsCOMPtr<nsIDOMEventListener> mEventListener;
   nsWeakPtr        mSelConWeak;          // weak reference to the nsISelectionController
   nsWeakPtr        mPlaceHolderTxn;      // weak reference to placeholder for begin/end batch purposes
   nsWeakPtr        mDocWeak;             // weak reference to the nsIDOMDocument
   nsIAtom          *mPlaceHolderName;    // name of placeholder transaction
   nsSelectionState *mSelState;           // saved selection state for placeholder txn batching
   nsString         *mPhonetic;
--- a/editor/libeditor/nsEditorEventListener.cpp
+++ b/editor/libeditor/nsEditorEventListener.cpp
@@ -90,16 +90,17 @@ DoCommandCallback(Command aCommand, void
     controller->DoCommand(commandStr);
   }
 }
 
 nsEditorEventListener::nsEditorEventListener()
   : mEditor(nullptr)
   , mCommitText(false)
   , mInTransaction(false)
+  , mMouseDownOrUpConsumedByIME(false)
 #ifdef HANDLE_NATIVE_TEXT_DIRECTION_SWITCH
   , mHaveBidiKeyboards(false)
   , mShouldSwitchTextDirection(false)
   , mSwitchToRTL(false)
 #endif
 {
 }
 
@@ -294,16 +295,52 @@ nsEditorEventListener::UninstallFromEdit
 already_AddRefed<nsIPresShell>
 nsEditorEventListener::GetPresShell()
 {
   NS_PRECONDITION(mEditor,
     "The caller must check whether this is connected to an editor");
   return mEditor->GetPresShell();
 }
 
+nsPresContext*
+nsEditorEventListener::GetPresContext()
+{
+  nsCOMPtr<nsIPresShell> presShell = GetPresShell();
+  return presShell ? presShell->GetPresContext() : nullptr;
+}
+
+nsIContent*
+nsEditorEventListener::GetFocusedRootContent()
+{
+  NS_ENSURE_TRUE(mEditor, nullptr);
+
+  nsCOMPtr<nsIContent> focusedContent = mEditor->GetFocusedContent();
+  if (!focusedContent) {
+    return nullptr;
+  }
+
+  nsIDocument* composedDoc = focusedContent->GetComposedDoc();
+  NS_ENSURE_TRUE(composedDoc, nullptr);
+
+  return composedDoc->HasFlag(NODE_IS_EDITABLE) ? nullptr : focusedContent;
+}
+
+bool
+nsEditorEventListener::EditorHasFocus()
+{
+  NS_PRECONDITION(mEditor,
+    "The caller must check whether this is connected to an editor");
+  nsCOMPtr<nsIContent> focusedContent = mEditor->GetFocusedContent();
+  if (!focusedContent) {
+    return false;
+  }
+  nsIDocument* composedDoc = focusedContent->GetComposedDoc();
+  return !!composedDoc;
+}
+
 /**
  *  nsISupports implementation
  */
 
 NS_IMPL_ISUPPORTS(nsEditorEventListener, nsIDOMEventListener)
 
 /**
  *  nsIDOMEventListener implementation
@@ -364,26 +401,57 @@ nsEditorEventListener::HandleEvent(nsIDO
     // keypress
     case NS_KEY_PRESS: {
       nsCOMPtr<nsIDOMKeyEvent> keyEvent = do_QueryInterface(aEvent);
       return KeyPress(keyEvent);
     }
     // mousedown
     case NS_MOUSE_BUTTON_DOWN: {
       nsCOMPtr<nsIDOMMouseEvent> mouseEvent = do_QueryInterface(aEvent);
-      return MouseDown(mouseEvent);
+      NS_ENSURE_TRUE(mouseEvent, NS_OK);
+      // nsEditorEventListener may receive (1) all mousedown, mouseup and click
+      // events, (2) only mousedown event or (3) only mouseup event.
+      // mMouseDownOrUpConsumedByIME is used only for ignoring click event if
+      // preceding mousedown and/or mouseup event is consumed by IME.
+      // Therefore, even if case #2 or case #3 occurs,
+      // mMouseDownOrUpConsumedByIME is true here.  Therefore, we should always
+      // overwrite it here.
+      mMouseDownOrUpConsumedByIME = NotifyIMEOfMouseButtonEvent(mouseEvent);
+      return mMouseDownOrUpConsumedByIME ? NS_OK : MouseDown(mouseEvent);
     }
     // mouseup
     case NS_MOUSE_BUTTON_UP: {
       nsCOMPtr<nsIDOMMouseEvent> mouseEvent = do_QueryInterface(aEvent);
-      return MouseUp(mouseEvent);
+      NS_ENSURE_TRUE(mouseEvent, NS_OK);
+      // See above comment in the NS_MOUSE_BUTTON_DOWN case, first.
+      // This code assumes that case #1 is occuring.  However, if case #3 may
+      // occurs after case #2 and the mousedown is consumed,
+      // mMouseDownOrUpConsumedByIME is true even though nsEditorEventListener
+      // has not received the preceding mousedown event of this mouseup event.
+      // So, mMouseDownOrUpConsumedByIME may be invalid here.  However,
+      // this is not a matter because mMouseDownOrUpConsumedByIME is referred
+      // only by NS_MOUSE_CLICK case but click event is fired only in case #1.
+      // So, before a click event is fired, mMouseDownOrUpConsumedByIME is
+      // always initialized in the NS_MOUSE_BUTTON_DOWN case if it's referred.
+      if (NotifyIMEOfMouseButtonEvent(mouseEvent)) {
+        mMouseDownOrUpConsumedByIME = true;
+      }
+      return mMouseDownOrUpConsumedByIME ? NS_OK : MouseUp(mouseEvent);
     }
     // click
     case NS_MOUSE_CLICK: {
       nsCOMPtr<nsIDOMMouseEvent> mouseEvent = do_QueryInterface(aEvent);
+      NS_ENSURE_TRUE(mouseEvent, NS_OK);
+      // If the preceding mousedown event or mouseup event was consumed,
+      // editor shouldn't handle this click event.
+      if (mMouseDownOrUpConsumedByIME) {
+        mMouseDownOrUpConsumedByIME = false;
+        mouseEvent->PreventDefault();
+        return NS_OK;
+      }
       return MouseClick(mouseEvent);
     }
     // focus
     case NS_FOCUS_CONTENT:
       return Focus(aEvent);
     // blur
     case NS_BLUR_CONTENT:
       return Blur(aEvent);
@@ -587,37 +655,30 @@ nsEditorEventListener::KeyPress(nsIDOMKe
     aKeyEvent->PreventDefault();
   }
   return NS_OK;
 }
 
 nsresult
 nsEditorEventListener::MouseClick(nsIDOMMouseEvent* aMouseEvent)
 {
-  NS_ENSURE_TRUE(aMouseEvent, NS_OK);
-
   // nothing to do if editor isn't editable or clicked on out of the editor.
   if (mEditor->IsReadonly() || mEditor->IsDisabled() ||
       !mEditor->IsAcceptableInputEvent(aMouseEvent)) {
     return NS_OK;
   }
 
   // Notifies clicking on editor to IMEStateManager even when the event was
   // consumed.
-  nsCOMPtr<nsIContent> focusedContent = mEditor->GetFocusedContent();
-  if (focusedContent) {
-    nsIDocument* currentDoc = focusedContent->GetCurrentDoc();
-    nsCOMPtr<nsIPresShell> presShell = GetPresShell();
-    nsPresContext* presContext =
-      presShell ? presShell->GetPresContext() : nullptr;
-    if (presContext && currentDoc) {
-      IMEStateManager::OnClickInEditor(presContext,
-        currentDoc->HasFlag(NODE_IS_EDITABLE) ? nullptr : focusedContent,
-        aMouseEvent);
-    }
+  if (EditorHasFocus()) {
+    nsPresContext* presContext = GetPresContext();
+    if (presContext) {
+      IMEStateManager::OnClickInEditor(presContext, GetFocusedRootContent(),
+                                       aMouseEvent);
+     }
   }
 
   bool preventDefault;
   nsresult rv = aMouseEvent->GetDefaultPrevented(&preventDefault);
   if (NS_FAILED(rv) || preventDefault) {
     // We're done if 'preventdefault' is true (see for example bug 70698).
     return rv;
   }
@@ -689,21 +750,40 @@ nsEditorEventListener::HandleMiddleClick
   // again by the containing window:
   aMouseEvent->StopPropagation();
   aMouseEvent->PreventDefault();
 
   // We processed the event, whether drop/paste succeeded or not
   return NS_OK;
 }
 
+bool
+nsEditorEventListener::NotifyIMEOfMouseButtonEvent(
+                         nsIDOMMouseEvent* aMouseEvent)
+{
+  if (!EditorHasFocus()) {
+    return false;
+  }
+
+  bool defaultPrevented;
+  nsresult rv = aMouseEvent->GetDefaultPrevented(&defaultPrevented);
+  NS_ENSURE_SUCCESS(rv, false);
+  if (defaultPrevented) {
+    return false;
+  }
+  nsPresContext* presContext = GetPresContext();
+  NS_ENSURE_TRUE(presContext, false);
+  return IMEStateManager::OnMouseButtonEventInEditor(presContext,
+                                                     GetFocusedRootContent(),
+                                                     aMouseEvent);
+}
+
 nsresult
 nsEditorEventListener::MouseDown(nsIDOMMouseEvent* aMouseEvent)
 {
-  NS_ENSURE_TRUE(aMouseEvent, NS_OK);
-
   mEditor->ForceCompositionEnd();
   return NS_OK;
 }
 
 nsresult
 nsEditorEventListener::HandleText(nsIDOMEvent* aTextEvent)
 {
   if (!mEditor->IsAcceptableInputEvent(aTextEvent)) {
--- a/editor/libeditor/nsEditorEventListener.h
+++ b/editor/libeditor/nsEditorEventListener.h
@@ -68,24 +68,30 @@ protected:
   nsresult DragOver(nsIDOMDragEvent* aDragEvent);
   nsresult DragExit(nsIDOMDragEvent* aDragEvent);
   nsresult Drop(nsIDOMDragEvent* aDragEvent);
   nsresult DragGesture(nsIDOMDragEvent* aDragEvent);
 
   bool CanDrop(nsIDOMDragEvent* aEvent);
   void CleanupDragDropCaret();
   already_AddRefed<nsIPresShell> GetPresShell();
+  nsPresContext* GetPresContext();
+  nsIContent* GetFocusedRootContent();
+  // Returns true if IME consumes the mouse event.
+  bool NotifyIMEOfMouseButtonEvent(nsIDOMMouseEvent* aMouseEvent);
+  bool EditorHasFocus();
   bool IsFileControlTextBox();
   bool ShouldHandleNativeKeyBindings(nsIDOMKeyEvent* aKeyEvent);
   nsresult HandleMiddleClickPaste(nsIDOMMouseEvent* aMouseEvent);
 
   nsEditor* mEditor; // weak
   nsRefPtr<nsCaret> mCaret;
   bool mCommitText;
   bool mInTransaction;
+  bool mMouseDownOrUpConsumedByIME;
 #ifdef HANDLE_NATIVE_TEXT_DIRECTION_SWITCH
   bool mHaveBidiKeyboards;
   bool mShouldSwitchTextDirection;
   bool mSwitchToRTL;
 #endif
 };
 
 #endif // nsEditorEventListener_h__
--- a/editor/libeditor/nsHTMLAbsPosition.cpp
+++ b/editor/libeditor/nsHTMLAbsPosition.cpp
@@ -9,17 +9,16 @@
 #include "mozilla/dom/Element.h"
 #include "mozilla/mozalloc.h"
 #include "nsAString.h"
 #include "nsAlgorithm.h"
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsComputedDOMStyle.h"
 #include "nsDebug.h"
-#include "nsEditProperty.h"
 #include "nsEditRules.h"
 #include "nsEditor.h"
 #include "nsEditorUtils.h"
 #include "nsError.h"
 #include "nsGkAtoms.h"
 #include "nsHTMLCSSUtils.h"
 #include "nsHTMLEditRules.h"
 #include "nsHTMLEditUtils.h"
@@ -88,18 +87,18 @@ nsHTMLEditor::GetAbsolutelyPositionedSel
   nsCOMPtr<nsIDOMElement> element;
   nsresult res = GetSelectionContainer(getter_AddRefs(element));
   NS_ENSURE_SUCCESS(res, res);
 
   nsAutoString positionStr;
   nsCOMPtr<nsIDOMNode> node = do_QueryInterface(element);
   nsCOMPtr<nsIDOMNode> resultNode;
 
-  while (!resultNode && node && !nsEditor::NodeIsType(node, nsEditProperty::html)) {
-    res = mHTMLCSSUtils->GetComputedProperty(node, nsEditProperty::cssPosition,
+  while (!resultNode && node && !nsEditor::NodeIsType(node, nsGkAtoms::html)) {
+    res = mHTMLCSSUtils->GetComputedProperty(node, nsGkAtoms::position,
                                              positionStr);
     NS_ENSURE_SUCCESS(res, res);
     if (positionStr.EqualsLiteral("absolute"))
       resultNode = node;
     else {
       nsCOMPtr<nsIDOMNode> parentNode;
       res = node->GetParentNode(getter_AddRefs(parentNode));
       NS_ENSURE_SUCCESS(res, res);
@@ -151,28 +150,25 @@ nsHTMLEditor::RelativeChangeElementZInde
   zIndex = std::max(zIndex + aChange, 0);
   SetElementZIndex(aElement, zIndex);
   *aReturn = zIndex;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsHTMLEditor::SetElementZIndex(nsIDOMElement * aElement,
-                               int32_t aZindex)
+nsHTMLEditor::SetElementZIndex(nsIDOMElement* aElement, int32_t aZindex)
 {
-  NS_ENSURE_ARG_POINTER(aElement);
-  
+  nsCOMPtr<Element> element = do_QueryInterface(aElement);
+  NS_ENSURE_ARG_POINTER(element);
+
   nsAutoString zIndexStr;
   zIndexStr.AppendInt(aZindex);
 
-  mHTMLCSSUtils->SetCSSProperty(aElement,
-                                nsEditProperty::cssZIndex,
-                                zIndexStr,
-                                false);
+  mHTMLCSSUtils->SetCSSProperty(*element, *nsGkAtoms::z_index, zIndexStr);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHTMLEditor::RelativeChangeZIndex(int32_t aChange)
 {
   nsAutoEditBatch beginBatching(this);
   nsAutoRules beginRulesSniffing(this,
@@ -199,39 +195,37 @@ nsHTMLEditor::RelativeChangeZIndex(int32
 NS_IMETHODIMP
 nsHTMLEditor::GetElementZIndex(nsIDOMElement * aElement,
                                int32_t * aZindex)
 {
   nsAutoString zIndexStr;
   *aZindex = 0;
 
   nsresult res = mHTMLCSSUtils->GetSpecifiedProperty(aElement,
-                                                     nsEditProperty::cssZIndex,
+                                                     nsGkAtoms::z_index,
                                                      zIndexStr);
   NS_ENSURE_SUCCESS(res, res);
   if (zIndexStr.EqualsLiteral("auto")) {
     // we have to look at the positioned ancestors
     // cf. CSS 2 spec section 9.9.1
     nsCOMPtr<nsIDOMNode> parentNode;
     res = aElement->GetParentNode(getter_AddRefs(parentNode));
     NS_ENSURE_SUCCESS(res, res);
     nsCOMPtr<nsIDOMNode> node = parentNode;
     nsAutoString positionStr;
     while (node && 
            zIndexStr.EqualsLiteral("auto") &&
            !nsTextEditUtils::IsBody(node)) {
-      res = mHTMLCSSUtils->GetComputedProperty(node,
-                                               nsEditProperty::cssPosition,
+      res = mHTMLCSSUtils->GetComputedProperty(node, nsGkAtoms::position,
                                                positionStr);
       NS_ENSURE_SUCCESS(res, res);
       if (positionStr.EqualsLiteral("absolute")) {
         // ah, we found one, what's its z-index ? If its z-index is auto,
         // we have to continue climbing the document's tree
-        res = mHTMLCSSUtils->GetComputedProperty(node,
-                                                 nsEditProperty::cssZIndex,
+        res = mHTMLCSSUtils->GetComputedProperty(node, nsGkAtoms::z_index,
                                                  zIndexStr);
         NS_ENSURE_SUCCESS(res, res);
       }
       res = node->GetParentNode(getter_AddRefs(parentNode));
       NS_ENSURE_SUCCESS(res, res);
       node = parentNode;
     }
   }
@@ -467,24 +461,23 @@ nsHTMLEditor::SetFinalPosition(int32_t a
 
   nsAutoString x, y;
   x.AppendInt(newX);
   y.AppendInt(newY);
 
   // we want one transaction only from a user's point of view
   nsAutoEditBatch batchIt(this);
 
-  mHTMLCSSUtils->SetCSSPropertyPixels(mAbsolutelyPositionedObject,
-                                      nsEditProperty::cssTop,
-                                      newY,
-                                      false);
-  mHTMLCSSUtils->SetCSSPropertyPixels(mAbsolutelyPositionedObject,
-                                      nsEditProperty::cssLeft,
-                                      newX,
-                                      false);
+  nsCOMPtr<Element> absolutelyPositionedObject =
+    do_QueryInterface(mAbsolutelyPositionedObject);
+  NS_ENSURE_STATE(absolutelyPositionedObject);
+  mHTMLCSSUtils->SetCSSPropertyPixels(*absolutelyPositionedObject,
+                                      *nsGkAtoms::top, newY);
+  mHTMLCSSUtils->SetCSSPropertyPixels(*absolutelyPositionedObject,
+                                      *nsGkAtoms::left, newX);
   // keep track of that size
   mPositionedObjectX  = newX;
   mPositionedObjectY  = newY;
 
   return RefreshResizers();
 }
 
 void
@@ -494,40 +487,39 @@ nsHTMLEditor::AddPositioningOffset(int32
   int32_t positioningOffset =
     Preferences::GetInt("editor.positioning.offset", 0);
 
   aX += positioningOffset;
   aY += positioningOffset;
 }
 
 NS_IMETHODIMP
-nsHTMLEditor::AbsolutelyPositionElement(nsIDOMElement * aElement,
+nsHTMLEditor::AbsolutelyPositionElement(nsIDOMElement* aElement,
                                         bool aEnabled)
 {
-  NS_ENSURE_ARG_POINTER(aElement);
+  nsCOMPtr<Element> element = do_QueryInterface(aElement);
+  NS_ENSURE_ARG_POINTER(element);
 
   nsAutoString positionStr;
-  mHTMLCSSUtils->GetComputedProperty(aElement, nsEditProperty::cssPosition,
+  mHTMLCSSUtils->GetComputedProperty(aElement, nsGkAtoms::position,
                                      positionStr);
   bool isPositioned = (positionStr.EqualsLiteral("absolute"));
 
   // nothing to do if the element is already in the state we want
   if (isPositioned == aEnabled)
     return NS_OK;
 
   nsAutoEditBatch batchIt(this);
 
   if (aEnabled) {
     int32_t x, y;
     GetElementOrigin(aElement, x, y);
 
-    mHTMLCSSUtils->SetCSSProperty(aElement,
-                                  nsEditProperty::cssPosition,
-                                  NS_LITERAL_STRING("absolute"),
-                                  false);
+    mHTMLCSSUtils->SetCSSProperty(*element, *nsGkAtoms::position,
+                                  NS_LITERAL_STRING("absolute"));
 
     AddPositioningOffset(x, y);
     SnapToGrid(x, y);
     SetElementPosition(aElement, x, y);
 
     // we may need to create a br if the positioned element is alone in its
     // container
     nsCOMPtr<nsINode> element = do_QueryInterface(aElement);
@@ -536,36 +528,30 @@ nsHTMLEditor::AbsolutelyPositionElement(
     nsINode* parentNode = element->GetParentNode();
     if (parentNode->GetChildCount() == 1) {
       nsCOMPtr<nsIDOMNode> brNode;
       nsresult res = CreateBR(parentNode->AsDOMNode(), 0, address_of(brNode));
       NS_ENSURE_SUCCESS(res, res);
     }
   }
   else {
-    mHTMLCSSUtils->RemoveCSSProperty(aElement,
-                                     nsEditProperty::cssPosition,
-                                     EmptyString(), false);
-    mHTMLCSSUtils->RemoveCSSProperty(aElement,
-                                     nsEditProperty::cssTop,
-                                     EmptyString(), false);
-    mHTMLCSSUtils->RemoveCSSProperty(aElement,
-                                     nsEditProperty::cssLeft,
-                                     EmptyString(), false);
-    mHTMLCSSUtils->RemoveCSSProperty(aElement,
-                                     nsEditProperty::cssZIndex,
-                                     EmptyString(), false);
+    mHTMLCSSUtils->RemoveCSSProperty(*element, *nsGkAtoms::position,
+                                     EmptyString());
+    mHTMLCSSUtils->RemoveCSSProperty(*element, *nsGkAtoms::top,
+                                     EmptyString());
+    mHTMLCSSUtils->RemoveCSSProperty(*element, *nsGkAtoms::left,
+                                     EmptyString());
+    mHTMLCSSUtils->RemoveCSSProperty(*element, *nsGkAtoms::z_index,
+                                     EmptyString());
 
     if (!nsHTMLEditUtils::IsImage(aElement)) {
-      mHTMLCSSUtils->RemoveCSSProperty(aElement,
-                                       nsEditProperty::cssWidth,
-                                       EmptyString(), false);
-      mHTMLCSSUtils->RemoveCSSProperty(aElement,
-                                       nsEditProperty::cssHeight,
-                                       EmptyString(), false);
+      mHTMLCSSUtils->RemoveCSSProperty(*element, *nsGkAtoms::width,
+                                       EmptyString());
+      mHTMLCSSUtils->RemoveCSSProperty(*element, *nsGkAtoms::height,
+                                       EmptyString());
     }
 
     nsCOMPtr<dom::Element> element = do_QueryInterface(aElement);
     if (element && element->IsHTML(nsGkAtoms::div) && !HasStyleOrIdOrClass(element)) {
       nsRefPtr<nsHTMLEditRules> htmlRules = static_cast<nsHTMLEditRules*>(mRules.get());
       NS_ENSURE_TRUE(htmlRules, NS_ERROR_FAILURE);
       nsresult res = htmlRules->MakeSureElemStartsOrEndsOnCR(aElement);
       NS_ENSURE_SUCCESS(res, res);
@@ -603,26 +589,22 @@ nsHTMLEditor::GetGridSize(uint32_t * aSi
   *aSize = mGridSize;
   return NS_OK;
 }
 
 // self-explanatory
 NS_IMETHODIMP
 nsHTMLEditor::SetElementPosition(nsIDOMElement *aElement, int32_t aX, int32_t aY)
 {
+  nsCOMPtr<Element> element = do_QueryInterface(aElement);
+  NS_ENSURE_STATE(element);
   nsAutoEditBatch batchIt(this);
 
-  mHTMLCSSUtils->SetCSSPropertyPixels(aElement,
-                                      nsEditProperty::cssLeft,
-                                      aX,
-                                      false);
-  mHTMLCSSUtils->SetCSSPropertyPixels(aElement,
-                                      nsEditProperty::cssTop,
-                                      aY,
-                                      false);
+  mHTMLCSSUtils->SetCSSPropertyPixels(*element, *nsGkAtoms::left, aX);
+  mHTMLCSSUtils->SetCSSPropertyPixels(*element, *nsGkAtoms::top, aY);
   return NS_OK;
 }
 
 // self-explanatory
 NS_IMETHODIMP
 nsHTMLEditor::GetPositionedElement(nsIDOMElement ** aReturn)
 {
   *aReturn = mAbsolutelyPositionedObject;
@@ -644,25 +626,23 @@ nsHTMLEditor::CheckPositionedElementBGan
   //   If the background color is 'auto' and at least one of R G B values of
   //       the foreground is below #d0, use a white background
   // Otherwise don't change background/foreground
 
   aReturn.Truncate();
   
   nsAutoString bgImageStr;
   nsresult res =
-    mHTMLCSSUtils->GetComputedProperty(aElement,
-                                       nsEditProperty::cssBackgroundImage,
+    mHTMLCSSUtils->GetComputedProperty(aElement, nsGkAtoms::background_image,
                                        bgImageStr);
   NS_ENSURE_SUCCESS(res, res);
   if (bgImageStr.EqualsLiteral("none")) {
     nsAutoString bgColorStr;
     res =
-      mHTMLCSSUtils->GetComputedProperty(aElement,
-                                         nsEditProperty::cssBackgroundColor,
+      mHTMLCSSUtils->GetComputedProperty(aElement, nsGkAtoms::backgroundColor,
                                          bgColorStr);
     NS_ENSURE_SUCCESS(res, res);
     if (bgColorStr.EqualsLiteral("transparent")) {
       nsRefPtr<nsComputedDOMStyle> cssDecl =
         mHTMLCSSUtils->GetComputedStyle(aElement);
       NS_ENSURE_STATE(cssDecl);
 
       // from these declarations, get the one we want and that one only
--- a/editor/libeditor/nsHTMLAnonymousUtils.cpp
+++ b/editor/libeditor/nsHTMLAnonymousUtils.cpp
@@ -5,18 +5,18 @@
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/mozalloc.h"
 #include "nsAString.h"
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsComputedDOMStyle.h"
 #include "nsDebug.h"
-#include "nsEditProperty.h"
 #include "nsError.h"
+#include "nsGkAtoms.h"
 #include "nsHTMLCSSUtils.h"
 #include "nsHTMLEditor.h"
 #include "nsIAtom.h"
 #include "nsIContent.h"
 #include "nsID.h"
 #include "nsIDOMCSSPrimitiveValue.h"
 #include "nsIDOMCSSStyleDeclaration.h"
 #include "nsIDOMCSSValue.h"
@@ -310,30 +310,30 @@ nsHTMLEditor::CheckSelectionStateForAnon
     NS_ENSURE_SUCCESS(res, res);
   }
 
   if (mIsObjectResizingEnabled && cellElement) {
     // we are here because Resizing is enabled AND selection is contained in
     // a cell
 
     // get the enclosing table
-    if (nsEditProperty::img != focusTagAtom) {
+    if (nsGkAtoms::img != focusTagAtom) {
       // the element container of the selection is not an image, so we'll show
       // the resizers around the table
       nsCOMPtr<nsIDOMNode> tableNode = GetEnclosingTable(cellElement);
       focusElement = do_QueryInterface(tableNode);
-      focusTagAtom = nsEditProperty::table;
+      focusTagAtom = nsGkAtoms::table;
     }
   }
 
   // we allow resizers only around images, tables, and absolutely positioned
   // elements. If we don't have image/table, let's look at the latter case.
-  if (nsEditProperty::img != focusTagAtom &&
-      nsEditProperty::table != focusTagAtom)
+  if (nsGkAtoms::img != focusTagAtom && nsGkAtoms::table != focusTagAtom) {
     focusElement = absPosElement;
+  }
 
   // at this point, focusElement  contains the element for Resizing,
   //                cellElement   contains the element for InlineTableEditing
   //                absPosElement contains the element for Positioning
 
   // Note: All the Hide/Show methods below may change attributes on real
   // content which means a DOMAttrModified handler may cause arbitrary
   // side effects while this code runs (bug 420439).
@@ -360,18 +360,19 @@ nsHTMLEditor::CheckSelectionStateForAnon
   }
 
   // now, let's display all contextual UI for good
   nsIContent* hostContent = GetActiveEditingHost();
   nsCOMPtr<nsIDOMNode> hostNode = do_QueryInterface(hostContent);
 
   if (mIsObjectResizingEnabled && focusElement &&
       IsModifiableNode(focusElement) && focusElement != hostNode) {
-    if (nsEditProperty::img == focusTagAtom)
+    if (nsGkAtoms::img == focusTagAtom) {
       mResizedObjectIsAnImage = true;
+    }
     if (mResizedObject)
       res = RefreshResizers();
     else
       res = ShowResizers(focusElement);
     NS_ENSURE_SUCCESS(res, res);
   }
 
   if (mIsAbsolutelyPositioningEnabled && absPosElement &&
@@ -409,17 +410,17 @@ nsHTMLEditor::GetPositionAndDimensions(n
 
   // Is the element positioned ? let's check the cheap way first...
   bool isPositioned = false;
   nsresult res = aElement->HasAttribute(NS_LITERAL_STRING("_moz_abspos"), &isPositioned);
   NS_ENSURE_SUCCESS(res, res);
   if (!isPositioned) {
     // hmmm... the expensive way now...
     nsAutoString positionStr;
-    mHTMLCSSUtils->GetComputedProperty(aElement, nsEditProperty::cssPosition,
+    mHTMLCSSUtils->GetComputedProperty(aElement, nsGkAtoms::position,
                                        positionStr);
     isPositioned = positionStr.EqualsLiteral("absolute");
   }
 
   if (isPositioned) {
     // Yes, it is absolutely positioned
     mResizedObjectIsAbsolutelyPositioned = true;
 
--- a/editor/libeditor/nsHTMLCSSUtils.cpp
+++ b/editor/libeditor/nsHTMLCSSUtils.cpp
@@ -1,29 +1,28 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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 "ChangeCSSInlineStyleTxn.h"
+#include "ChangeStyleTxn.h"
 #include "EditTxn.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/css/Declaration.h"
 #include "mozilla/css/StyleRule.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/mozalloc.h"
 #include "nsAString.h"
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsColor.h"
 #include "nsComputedDOMStyle.h"
 #include "nsDebug.h"
 #include "nsDependentSubstring.h"
-#include "nsEditProperty.h"
 #include "nsError.h"
 #include "nsGkAtoms.h"
 #include "nsHTMLCSSUtils.h"
 #include "nsHTMLEditor.h"
 #include "nsIAtom.h"
 #include "nsIContent.h"
 #include "nsIDOMCSSStyleDeclaration.h"
 #include "nsIDOMElement.h"
@@ -40,16 +39,17 @@
 #include "nsReadableUtils.h"
 #include "nsString.h"
 #include "nsStringFwd.h"
 #include "nsStringIterator.h"
 #include "nsSubstringTuple.h"
 #include "nsUnicharUtils.h"
 
 using namespace mozilla;
+using namespace mozilla::dom;
 
 static
 void ProcessBValue(const nsAString * aInputString, nsAString & aOutputString,
                    const char * aDefaultValueString,
                    const char * aPrependString, const char* aAppendString)
 {
   if (aInputString && aInputString->EqualsLiteral("-moz-editor-invert-value")) {
       aOutputString.AssignLiteral("normal");
@@ -324,197 +324,176 @@ nsHTMLCSSUtils::IsCSSEditableProperty(ns
     content = content->GetParent();
     NS_ENSURE_TRUE(content, false);
   }
 
   nsIAtom *tagName = content->Tag();
   // brade: shouldn't some of the above go below the next block?
 
   // html inline styles B I TT U STRIKE and COLOR/FACE on FONT
-  if (nsEditProperty::b == aProperty
-      || nsEditProperty::i == aProperty
-      || nsEditProperty::tt == aProperty
-      || nsEditProperty::u == aProperty
-      || nsEditProperty::strike == aProperty
-      || ((nsEditProperty::font == aProperty) && aAttribute &&
-           (aAttribute->EqualsLiteral("color") ||
-            aAttribute->EqualsLiteral("face")))) {
+  if (nsGkAtoms::b == aProperty ||
+      nsGkAtoms::i == aProperty ||
+      nsGkAtoms::tt == aProperty ||
+      nsGkAtoms::u == aProperty ||
+      nsGkAtoms::strike == aProperty ||
+      (nsGkAtoms::font == aProperty && aAttribute &&
+       (aAttribute->EqualsLiteral("color") ||
+        aAttribute->EqualsLiteral("face")))) {
     return true;
   }
 
   // ALIGN attribute on elements supporting it
   if (aAttribute && (aAttribute->EqualsLiteral("align")) &&
-      (nsEditProperty::div == tagName
-       || nsEditProperty::p   == tagName
-       || nsEditProperty::h1  == tagName
-       || nsEditProperty::h2  == tagName
-       || nsEditProperty::h3  == tagName
-       || nsEditProperty::h4  == tagName
-       || nsEditProperty::h5  == tagName
-       || nsEditProperty::h6  == tagName
-       || nsEditProperty::td  == tagName
-       || nsEditProperty::th  == tagName
-       || nsEditProperty::table  == tagName
-       || nsEditProperty::hr  == tagName
+      (nsGkAtoms::div == tagName ||
+       nsGkAtoms::p   == tagName ||
+       nsGkAtoms::h1  == tagName ||
+       nsGkAtoms::h2  == tagName ||
+       nsGkAtoms::h3  == tagName ||
+       nsGkAtoms::h4  == tagName ||
+       nsGkAtoms::h5  == tagName ||
+       nsGkAtoms::h6  == tagName ||
+       nsGkAtoms::td  == tagName ||
+       nsGkAtoms::th  == tagName ||
+       nsGkAtoms::table  == tagName ||
+       nsGkAtoms::hr  == tagName ||
        // brade: for the above, why not use nsHTMLEditUtils::SupportsAlignAttr
        // brade: but it also checks for tbody, tfoot, thead
        // Let's add the following elements here even if ALIGN has not
        // the same meaning for them
-       || nsEditProperty::legend  == tagName
-       || nsEditProperty::caption == tagName)) {
+       nsGkAtoms::legend  == tagName ||
+       nsGkAtoms::caption == tagName)) {
     return true;
   }
 
   if (aAttribute && (aAttribute->EqualsLiteral("valign")) &&
-      (nsEditProperty::col == tagName
-       || nsEditProperty::colgroup   == tagName
-       || nsEditProperty::tbody  == tagName
-       || nsEditProperty::td  == tagName
-       || nsEditProperty::th  == tagName
-       || nsEditProperty::tfoot  == tagName
-       || nsEditProperty::thead  == tagName
-       || nsEditProperty::tr  == tagName)) {
+      (nsGkAtoms::col == tagName ||
+       nsGkAtoms::colgroup   == tagName ||
+       nsGkAtoms::tbody  == tagName ||
+       nsGkAtoms::td  == tagName ||
+       nsGkAtoms::th  == tagName ||
+       nsGkAtoms::tfoot  == tagName ||
+       nsGkAtoms::thead  == tagName ||
+       nsGkAtoms::tr  == tagName)) {
     return true;
   }
 
   // attributes TEXT, BACKGROUND and BGCOLOR on BODY
-  if (aAttribute && (nsEditProperty::body == tagName) &&
+  if (aAttribute && nsGkAtoms::body == tagName &&
       (aAttribute->EqualsLiteral("text")
        || aAttribute->EqualsLiteral("background")
        || aAttribute->EqualsLiteral("bgcolor"))) {
     return true;
   }
 
   // attribute BGCOLOR on other elements
   if (aAttribute && aAttribute->EqualsLiteral("bgcolor")) {
     return true;
   }
 
   // attributes HEIGHT, WIDTH and NOWRAP on TD and TH
-  if (aAttribute && ((nsEditProperty::td == tagName)
-                      || (nsEditProperty::th == tagName)) &&
+  if (aAttribute && (nsGkAtoms::td == tagName || nsGkAtoms::th == tagName) &&
       (aAttribute->EqualsLiteral("height")
        || aAttribute->EqualsLiteral("width")
        || aAttribute->EqualsLiteral("nowrap"))) {
     return true;
   }
 
   // attributes HEIGHT and WIDTH on TABLE
-  if (aAttribute && (nsEditProperty::table == tagName) &&
+  if (aAttribute && nsGkAtoms::table == tagName &&
       (aAttribute->EqualsLiteral("height")
        || aAttribute->EqualsLiteral("width"))) {
     return true;
   }
 
   // attributes SIZE and WIDTH on HR
-  if (aAttribute && (nsEditProperty::hr == tagName) &&
+  if (aAttribute && nsGkAtoms::hr == tagName &&
       (aAttribute->EqualsLiteral("size")
        || aAttribute->EqualsLiteral("width"))) {
     return true;
   }
 
   // attribute TYPE on OL UL LI
-  if (aAttribute && (nsEditProperty::ol == tagName
-                     || nsEditProperty::ul == tagName
-                     || nsEditProperty::li == tagName) &&
-      aAttribute->EqualsLiteral("type")) {
+  if (aAttribute &&
+      (nsGkAtoms::ol == tagName || nsGkAtoms::ul == tagName ||
+       nsGkAtoms::li == tagName) && aAttribute->EqualsLiteral("type")) {
     return true;
   }
 
-  if (aAttribute && nsEditProperty::img == tagName &&
+  if (aAttribute && nsGkAtoms::img == tagName &&
       (aAttribute->EqualsLiteral("border")
        || aAttribute->EqualsLiteral("width")
        || aAttribute->EqualsLiteral("height"))) {
     return true;
   }
 
   // other elements that we can align using CSS even if they
   // can't carry the html ALIGN attribute
   if (aAttribute && aAttribute->EqualsLiteral("align") &&
-      (nsEditProperty::ul == tagName
-       || nsEditProperty::ol == tagName
-       || nsEditProperty::dl == tagName
-       || nsEditProperty::li == tagName
-       || nsEditProperty::dd == tagName
-       || nsEditProperty::dt == tagName
-       || nsEditProperty::address == tagName
-       || nsEditProperty::pre == tagName
-       || nsEditProperty::ul == tagName)) {
+      (nsGkAtoms::ul == tagName ||
+       nsGkAtoms::ol == tagName ||
+       nsGkAtoms::dl == tagName ||
+       nsGkAtoms::li == tagName ||
+       nsGkAtoms::dd == tagName ||
+       nsGkAtoms::dt == tagName ||
+       nsGkAtoms::address == tagName ||
+       nsGkAtoms::pre == tagName ||
+       nsGkAtoms::ul == tagName)) {
     return true;
   }
 
   return false;
 }
 
-// the lowest level above the transaction; adds the css declaration "aProperty : aValue" to
-// the inline styles carried by aElement
+// The lowest level above the transaction; adds the CSS declaration
+// "aProperty : aValue" to the inline styles carried by aElement
 nsresult
-nsHTMLCSSUtils::SetCSSProperty(nsIDOMElement *aElement, nsIAtom * aProperty, const nsAString & aValue,
-                               bool aSuppressTransaction)
+nsHTMLCSSUtils::SetCSSProperty(Element& aElement, nsIAtom& aProperty,
+                               const nsAString& aValue, bool aSuppressTxn)
 {
-  nsRefPtr<ChangeCSSInlineStyleTxn> txn;
-  nsresult result = CreateCSSPropertyTxn(aElement, aProperty, aValue,
-                                         getter_AddRefs(txn), false);
-  if (NS_SUCCEEDED(result))  {
-    if (aSuppressTransaction) {
-      result = txn->DoTransaction();
-    }
-    else {
-      result = mHTMLEditor->DoTransaction(txn);
-    }
+  nsRefPtr<ChangeStyleTxn> txn =
+    CreateCSSPropertyTxn(aElement, aProperty, aValue, ChangeStyleTxn::eSet);
+  if (aSuppressTxn) {
+    return txn->DoTransaction();
   }
-  return result;
+  return mHTMLEditor->DoTransaction(txn);
 }
 
 nsresult
-nsHTMLCSSUtils::SetCSSPropertyPixels(nsIDOMElement *aElement,
-                                     nsIAtom *aProperty,
-                                     int32_t aIntValue,
-                                     bool aSuppressTransaction)
+nsHTMLCSSUtils::SetCSSPropertyPixels(Element& aElement, nsIAtom& aProperty,
+                                     int32_t aIntValue)
 {
   nsAutoString s;
   s.AppendInt(aIntValue);
   return SetCSSProperty(aElement, aProperty, s + NS_LITERAL_STRING("px"),
-                        aSuppressTransaction);
+                        /* suppress txn */ false);
 }
 
-// the lowest level above the transaction; removes the value aValue from the list of values
-// specified for the CSS property aProperty, or totally remove the declaration if this
-// property accepts only one value
+// The lowest level above the transaction; removes the value aValue from the
+// list of values specified for the CSS property aProperty, or totally remove
+// the declaration if this property accepts only one value
 nsresult
-nsHTMLCSSUtils::RemoveCSSProperty(nsIDOMElement *aElement, nsIAtom * aProperty, const nsAString & aValue,
-                                  bool aSuppressTransaction)
+nsHTMLCSSUtils::RemoveCSSProperty(Element& aElement, nsIAtom& aProperty,
+                                  const nsAString& aValue, bool aSuppressTxn)
 {
-  nsRefPtr<ChangeCSSInlineStyleTxn> txn;
-  nsresult result = CreateCSSPropertyTxn(aElement, aProperty, aValue,
-                                         getter_AddRefs(txn), true);
-  if (NS_SUCCEEDED(result))  {
-    if (aSuppressTransaction) {
-      result = txn->DoTransaction();
-    }
-    else {
-      result = mHTMLEditor->DoTransaction(txn);
-    }
+  nsRefPtr<ChangeStyleTxn> txn =
+    CreateCSSPropertyTxn(aElement, aProperty, aValue, ChangeStyleTxn::eRemove);
+  if (aSuppressTxn) {
+    return txn->DoTransaction();
   }
-  return result;
+  return mHTMLEditor->DoTransaction(txn);
 }
 
-nsresult 
-nsHTMLCSSUtils::CreateCSSPropertyTxn(nsIDOMElement *aElement, 
-                                     nsIAtom * aAttribute,
+already_AddRefed<ChangeStyleTxn>
+nsHTMLCSSUtils::CreateCSSPropertyTxn(Element& aElement, nsIAtom& aAttribute,
                                      const nsAString& aValue,
-                                     ChangeCSSInlineStyleTxn ** aTxn,
-                                     bool aRemoveProperty)
+                                     ChangeStyleTxn::EChangeType aChangeType)
 {
-  NS_ENSURE_TRUE(aElement, NS_ERROR_NULL_POINTER);
-
-  *aTxn = new ChangeCSSInlineStyleTxn();
-  NS_ENSURE_TRUE(*aTxn, NS_ERROR_OUT_OF_MEMORY);
-  NS_ADDREF(*aTxn);
-  return (*aTxn)->Init(mHTMLEditor, aElement, aAttribute, aValue, aRemoveProperty);
+  nsRefPtr<ChangeStyleTxn> txn =
+    new ChangeStyleTxn(aElement, aAttribute, aValue, aChangeType);
+  return txn.forget();
 }
 
 nsresult
 nsHTMLCSSUtils::GetSpecifiedProperty(nsIDOMNode *aNode, nsIAtom *aProperty,
                                      nsAString & aValue)
 {
   return GetCSSInlinePropertyBase(aNode, aProperty, aValue, eSpecified);
 }
@@ -596,37 +575,37 @@ nsHTMLCSSUtils::GetComputedStyle(dom::El
   return style.forget();
 }
 
 // remove the CSS style "aProperty : aPropertyValue" and possibly remove the whole node
 // if it is a span and if its only attribute is _moz_dirty
 nsresult
 nsHTMLCSSUtils::RemoveCSSInlineStyle(nsIDOMNode *aNode, nsIAtom *aProperty, const nsAString & aPropertyValue)
 {
-  nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(aNode);
+  nsCOMPtr<Element> element = do_QueryInterface(aNode);
+  NS_ENSURE_STATE(element);
 
   // remove the property from the style attribute
-  nsresult res = RemoveCSSProperty(elem, aProperty, aPropertyValue, false);
+  nsresult res = RemoveCSSProperty(*element, *aProperty, aPropertyValue);
   NS_ENSURE_SUCCESS(res, res);
 
-  nsCOMPtr<dom::Element> element = do_QueryInterface(aNode);
-  if (!element || !element->IsHTML(nsGkAtoms::span) ||
+  if (!element->IsHTML(nsGkAtoms::span) ||
       nsHTMLEditor::HasAttributes(element)) {
     return NS_OK;
   }
 
   return mHTMLEditor->RemoveContainer(element);
 }
 
 // Answers true is the property can be removed by setting a "none" CSS value
 // on a node
 bool
 nsHTMLCSSUtils::IsCSSInvertable(nsIAtom *aProperty, const nsAString *aAttribute)
 {
-  return bool(nsEditProperty::b == aProperty);
+  return nsGkAtoms::b == aProperty;
 }
 
 // Get the default browser background color if we need it for GetCSSBackgroundColorState
 void
 nsHTMLCSSUtils::GetDefaultBackgroundColor(nsAString & aColor)
 {
   if (Preferences::GetBool("editor.use_custom_colors", false)) {
     nsresult rv = Preferences::GetString("editor.background_color", &aColor);
@@ -708,71 +687,71 @@ nsHTMLCSSUtils::ParseLength(const nsAStr
 }
 
 void
 nsHTMLCSSUtils::GetCSSPropertyAtom(nsCSSEditableProperty aProperty, nsIAtom ** aAtom)
 {
   *aAtom = nullptr;
   switch (aProperty) {
     case eCSSEditableProperty_background_color:
-      *aAtom = nsEditProperty::cssBackgroundColor;
+      *aAtom = nsGkAtoms::backgroundColor;
       break;
     case eCSSEditableProperty_background_image:
-      *aAtom = nsEditProperty::cssBackgroundImage;
+      *aAtom = nsGkAtoms::background_image;
       break;
     case eCSSEditableProperty_border:
-      *aAtom = nsEditProperty::cssBorder;
+      *aAtom = nsGkAtoms::border;
       break;
     case eCSSEditableProperty_caption_side:
-      *aAtom = nsEditProperty::cssCaptionSide;
+      *aAtom = nsGkAtoms::caption_side;
       break;
     case eCSSEditableProperty_color:
-      *aAtom = nsEditProperty::cssColor;
+      *aAtom = nsGkAtoms::color;
       break;
     case eCSSEditableProperty_float:
-      *aAtom = nsEditProperty::cssFloat;
+      *aAtom = nsGkAtoms::_float;
       break;
     case eCSSEditableProperty_font_family:
-      *aAtom = nsEditProperty::cssFontFamily;
+      *aAtom = nsGkAtoms::font_family;
       break;
     case eCSSEditableProperty_font_size:
-      *aAtom = nsEditProperty::cssFontSize;
+      *aAtom = nsGkAtoms::font_size;
       break;
     case eCSSEditableProperty_font_style:
-      *aAtom = nsEditProperty::cssFontStyle;
+      *aAtom = nsGkAtoms::font_style;
       break;
     case eCSSEditableProperty_font_weight:
-      *aAtom = nsEditProperty::cssFontWeight;
+      *aAtom = nsGkAtoms::fontWeight;
       break;
     case eCSSEditableProperty_height:
-      *aAtom = nsEditProperty::cssHeight;
+      *aAtom = nsGkAtoms::height;
       break;
     case eCSSEditableProperty_list_style_type:
-      *aAtom = nsEditProperty::cssListStyleType;
+      *aAtom = nsGkAtoms::list_style_type;
       break;
     case eCSSEditableProperty_margin_left:
-      *aAtom = nsEditProperty::cssMarginLeft;
+      *aAtom = nsGkAtoms::marginLeft;
       break;
     case eCSSEditableProperty_margin_right:
-      *aAtom = nsEditProperty::cssMarginRight;
+      *aAtom = nsGkAtoms::marginRight;
       break;
     case eCSSEditableProperty_text_align:
-      *aAtom = nsEditProperty::cssTextAlign;
+      *aAtom = nsGkAtoms::textAlign;
       break;
     case eCSSEditableProperty_text_decoration:
-      *aAtom = nsEditProperty::cssTextDecoration;
+      *aAtom = nsGkAtoms::text_decoration;
       break;
     case eCSSEditableProperty_vertical_align:
-      *aAtom = nsEditProperty::cssVerticalAlign;
+      *aAtom = nsGkAtoms::vertical_align;
       break;
     case eCSSEditableProperty_whitespace:
-      *aAtom = nsEditProperty::cssWhitespace;
+      *aAtom = nsGkAtoms::white_space;
       break;
     case eCSSEditableProperty_width:
-      *aAtom = nsEditProperty::cssWidth;
+      *aAtom = nsGkAtoms::width;
       break;
     case eCSSEditableProperty_NONE:
       // intentionally empty
       break;
   }
 }
 
 // Populate aProperty and aValueArray with the CSS declarations equivalent to the
@@ -828,66 +807,66 @@ nsHTMLCSSUtils::GenerateCSSDeclarationsF
                                                      nsTArray<nsIAtom*>& cssPropertyArray,
                                                      nsTArray<nsString>& cssValueArray,
                                                      bool aGetOrRemoveRequest)
 {
   MOZ_ASSERT(aElement);
   nsIAtom* tagName = aElement->Tag();
   const nsHTMLCSSUtils::CSSEquivTable* equivTable = nullptr;
 
-  if (nsEditProperty::b == aHTMLProperty) {
+  if (nsGkAtoms::b == aHTMLProperty) {
     equivTable = boldEquivTable;
-  } else if (nsEditProperty::i == aHTMLProperty) {
+  } else if (nsGkAtoms::i == aHTMLProperty) {
     equivTable = italicEquivTable;
-  } else if (nsEditProperty::u == aHTMLProperty) {
+  } else if (nsGkAtoms::u == aHTMLProperty) {
     equivTable = underlineEquivTable;
-  } else if (nsEditProperty::strike == aHTMLProperty) {
+  } else if (nsGkAtoms::strike == aHTMLProperty) {
     equivTable = strikeEquivTable;
-  } else if (nsEditProperty::tt == aHTMLProperty) {
+  } else if (nsGkAtoms::tt == aHTMLProperty) {
     equivTable = ttEquivTable;
   } else if (aAttribute) {
-    if (nsEditProperty::font == aHTMLProperty &&
+    if (nsGkAtoms::font == aHTMLProperty &&
         aAttribute->EqualsLiteral("color")) {
       equivTable = fontColorEquivTable;
-    } else if (nsEditProperty::font == aHTMLProperty &&
+    } else if (nsGkAtoms::font == aHTMLProperty &&
                aAttribute->EqualsLiteral("face")) {
       equivTable = fontFaceEquivTable;
     } else if (aAttribute->EqualsLiteral("bgcolor")) {
       equivTable = bgcolorEquivTable;
     } else if (aAttribute->EqualsLiteral("background")) {
       equivTable = backgroundImageEquivTable;
     } else if (aAttribute->EqualsLiteral("text")) {
       equivTable = textColorEquivTable;
     } else if (aAttribute->EqualsLiteral("border")) {
       equivTable = borderEquivTable;
     } else if (aAttribute->EqualsLiteral("align")) {
-      if (nsEditProperty::table  == tagName) {
+      if (nsGkAtoms::table  == tagName) {
         equivTable = tableAlignEquivTable;
-      } else if (nsEditProperty::hr  == tagName) {
+      } else if (nsGkAtoms::hr  == tagName) {
         equivTable = hrAlignEquivTable;
-      } else if (nsEditProperty::legend  == tagName ||
-               nsEditProperty::caption == tagName) {
+      } else if (nsGkAtoms::legend  == tagName ||
+                 nsGkAtoms::caption == tagName) {
         equivTable = captionAlignEquivTable;
       } else {
         equivTable = textAlignEquivTable;
       }
     } else if (aAttribute->EqualsLiteral("valign")) {
       equivTable = verticalAlignEquivTable;
     } else if (aAttribute->EqualsLiteral("nowrap")) {
       equivTable = nowrapEquivTable;
     } else if (aAttribute->EqualsLiteral("width")) {
       equivTable = widthEquivTable;
     } else if (aAttribute->EqualsLiteral("height") ||
-               (nsEditProperty::hr == tagName &&
+               (nsGkAtoms::hr == tagName &&
                 aAttribute->EqualsLiteral("size"))) {
       equivTable = heightEquivTable;
     } else if (aAttribute->EqualsLiteral("type") &&
-               (nsEditProperty::ol == tagName
-                || nsEditProperty::ul == tagName
-                || nsEditProperty::li == tagName)) {
+               (nsGkAtoms::ol == tagName ||
+                nsGkAtoms::ul == tagName ||
+                nsGkAtoms::li == tagName)) {
       equivTable = listStyleTypeEquivTable;
     }
   }
   if (equivTable) {
     BuildCSSDeclarations(cssPropertyArray, cssValueArray, equivTable,
                          aValue, aGetOrRemoveRequest);
   }
 }
@@ -937,21 +916,20 @@ nsHTMLCSSUtils::SetCSSEquivalentToHTMLSt
 
   // Find the CSS equivalence to the HTML style
   nsTArray<nsIAtom*> cssPropertyArray;
   nsTArray<nsString> cssValueArray;
   GenerateCSSDeclarationsFromHTMLStyle(element, aHTMLProperty, aAttribute,
                                        aValue, cssPropertyArray, cssValueArray,
                                        false);
 
-  nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(element);
   // set the individual CSS inline styles
   *aCount = cssPropertyArray.Length();
   for (int32_t index = 0; index < *aCount; index++) {
-    nsresult res = SetCSSProperty(domElement, cssPropertyArray[index],
+    nsresult res = SetCSSProperty(*element, *cssPropertyArray[index],
                                   cssValueArray[index], aSuppressTransaction);
     NS_ENSURE_SUCCESS(res, res);
   }
   return NS_OK;
 }
 
 // Remove from aNode the CSS inline style equivalent to HTMLProperty/aAttribute/aValue for the node
 nsresult
@@ -986,22 +964,21 @@ nsHTMLCSSUtils::RemoveCSSEquivalentToHTM
 
   // Find the CSS equivalence to the HTML style
   nsTArray<nsIAtom*> cssPropertyArray;
   nsTArray<nsString> cssValueArray;
   GenerateCSSDeclarationsFromHTMLStyle(aElement, aHTMLProperty, aAttribute,
                                        aValue, cssPropertyArray, cssValueArray,
                                        true);
 
-  nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(aElement);
   // remove the individual CSS inline styles
   int32_t count = cssPropertyArray.Length();
   for (int32_t index = 0; index < count; index++) {
-    nsresult res = RemoveCSSProperty(domElement,
-                                     cssPropertyArray[index],
+    nsresult res = RemoveCSSProperty(*aElement,
+                                     *cssPropertyArray[index],
                                      cssValueArray[index],
                                      aSuppressTransaction);
     NS_ENSURE_SUCCESS(res, res);
   }
   return NS_OK;
 }
 
 // returns in aValueString the list of values for the CSS equivalences to
@@ -1091,17 +1068,17 @@ nsHTMLCSSUtils::IsCSSEquivalentToHTMLInl
                                                         valueString, aStyleType);
     NS_ENSURE_SUCCESS(res, res);
 
     // early way out if we can
     if (valueString.IsEmpty()) {
       return NS_OK;
     }
 
-    if (nsEditProperty::b == aHTMLProperty) {
+    if (nsGkAtoms::b == aHTMLProperty) {
       if (valueString.EqualsLiteral("bold")) {
         aIsSet = true;
       } else if (valueString.EqualsLiteral("normal")) {
         aIsSet = false;
       } else if (valueString.EqualsLiteral("bolder")) {
         aIsSet = true;
         valueString.AssignLiteral("bold");
       } else {
@@ -1112,31 +1089,31 @@ nsHTMLCSSUtils::IsCSSEquivalentToHTMLInl
         if (400 < weight) {
           aIsSet = true;
           valueString.AssignLiteral("bold");
         } else {
           aIsSet = false;
           valueString.AssignLiteral("normal");
         }
       }
-    } else if (nsEditProperty::i == aHTMLProperty) {
+    } else if (nsGkAtoms::i == aHTMLProperty) {
       if (valueString.EqualsLiteral("italic") ||
           valueString.EqualsLiteral("oblique")) {
         aIsSet = true;
       }
-    } else if (nsEditProperty::u == aHTMLProperty) {
+    } else if (nsGkAtoms::u == aHTMLProperty) {
       nsAutoString val;
       val.AssignLiteral("underline");
-      aIsSet = bool(ChangeCSSInlineStyleTxn::ValueIncludes(valueString, val, false));
-    } else if (nsEditProperty::strike == aHTMLProperty) {
+      aIsSet = ChangeStyleTxn::ValueIncludes(valueString, val);
+    } else if (nsGkAtoms::strike == aHTMLProperty) {
       nsAutoString val;
       val.AssignLiteral("line-through");
-      aIsSet = bool(ChangeCSSInlineStyleTxn::ValueIncludes(valueString, val, false));
+      aIsSet = ChangeStyleTxn::ValueIncludes(valueString, val);
     } else if (aHTMLAttribute &&
-               ((nsEditProperty::font == aHTMLProperty &&
+               ((nsGkAtoms::font == aHTMLProperty &&
                  aHTMLAttribute->EqualsLiteral("color")) ||
                 aHTMLAttribute->EqualsLiteral("bgcolor"))) {
       if (htmlValueString.IsEmpty()) {
         aIsSet = true;
       } else {
         nscolor rgba;
         nsAutoString subStr;
         htmlValueString.Right(subStr, htmlValueString.Length() - 1);
@@ -1171,19 +1148,19 @@ nsHTMLCSSUtils::IsCSSEquivalentToHTMLInl
 
           aIsSet = htmlColor.Equals(valueString,
                                     nsCaseInsensitiveStringComparator());
         } else {
           aIsSet = htmlValueString.Equals(valueString,
                                     nsCaseInsensitiveStringComparator());
         }
       }
-    } else if (nsEditProperty::tt == aHTMLProperty) {
+    } else if (nsGkAtoms::tt == aHTMLProperty) {
       aIsSet = StringBeginsWith(valueString, NS_LITERAL_STRING("monospace"));
-    } else if (nsEditProperty::font == aHTMLProperty && aHTMLAttribute &&
+    } else if (nsGkAtoms::font == aHTMLProperty && aHTMLAttribute &&
                aHTMLAttribute->EqualsLiteral("face")) {
       if (!htmlValueString.IsEmpty()) {
         const char16_t commaSpace[] = { char16_t(','), char16_t(' '), 0 };
         const char16_t comma[] = { char16_t(','), 0 };
         htmlValueString.ReplaceSubstring(commaSpace, comma);
         nsAutoString valueStringNorm(valueString);
         valueStringNorm.ReplaceSubstring(commaSpace, comma);
         aIsSet = htmlValueString.Equals(valueStringNorm,
@@ -1208,23 +1185,23 @@ nsHTMLCSSUtils::IsCSSEquivalentToHTMLInl
                                nsCaseInsensitiveStringComparator())) {
       aIsSet = true;
     }
 
     if (htmlValueString.EqualsLiteral("-moz-editor-invert-value")) {
       aIsSet = !aIsSet;
     }
 
-    if (nsEditProperty::u == aHTMLProperty || nsEditProperty::strike == aHTMLProperty) {
+    if (nsGkAtoms::u == aHTMLProperty || nsGkAtoms::strike == aHTMLProperty) {
       // unfortunately, the value of the text-decoration property is not inherited.
       // that means that we have to look at ancestors of node to see if they are underlined
       node = node->GetParentElement();  // set to null if it's not a dom element
     }
-  } while ((nsEditProperty::u == aHTMLProperty || nsEditProperty::strike == aHTMLProperty) &&
-           !aIsSet && node);
+  } while ((nsGkAtoms::u == aHTMLProperty ||
+            nsGkAtoms::strike == aHTMLProperty) && !aIsSet && node);
   return NS_OK;
 }
 
 void
 nsHTMLCSSUtils::SetCSSEnabled(bool aIsCSSPrefChecked)
 {
   mIsCSSPrefChecked = aIsCSSPrefChecked;
 }
--- a/editor/libeditor/nsHTMLCSSUtils.h
+++ b/editor/libeditor/nsHTMLCSSUtils.h
@@ -1,21 +1,21 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/. */
 
 #ifndef nsHTMLCSSUtils_h__
 #define nsHTMLCSSUtils_h__
 
+#include "ChangeStyleTxn.h"             // for ChangeStyleTxn::EChangeType
 #include "nsCOMPtr.h"                   // for already_AddRefed
 #include "nsTArray.h"                   // for nsTArray
 #include "nscore.h"                     // for nsAString, nsresult, nullptr
 
-class ChangeCSSInlineStyleTxn;
 class nsComputedDOMStyle;
 class nsIAtom;
 class nsIContent;
 class nsIDOMCSSStyleDeclaration;
 class nsIDOMElement;
 class nsIDOMNode;
 class nsINode;
 class nsString;
@@ -89,23 +89,24 @@ public:
   /** adds/remove a CSS declaration to the STYLE atrribute carried by a given element
     *
     * @param aElement       [IN] a DOM element
     * @param aProperty      [IN] an atom containing the CSS property to set
     * @param aValue         [IN] a string containing the value of the CSS property
     * @param aSuppressTransaction [IN] a boolean indicating, when true,
     *                                  that no transaction should be recorded
     */
-  nsresult    SetCSSProperty(nsIDOMElement * aElement, nsIAtom * aProperty,
-                             const nsAString & aValue,
-                             bool aSuppressTransaction);
-  nsresult    SetCSSPropertyPixels(nsIDOMElement *aElement, nsIAtom *aProperty,
-                                   int32_t aIntValue, bool aSuppressTxn);
-  nsresult    RemoveCSSProperty(nsIDOMElement * aElement, nsIAtom * aProperty,
-                                const nsAString & aPropertyValue, bool aSuppressTransaction);
+  nsresult SetCSSProperty(mozilla::dom::Element& aElement, nsIAtom& aProperty,
+                          const nsAString& aValue, bool aSuppressTxn = false);
+  nsresult SetCSSPropertyPixels(mozilla::dom::Element& aElement,
+                                nsIAtom& aProperty, int32_t aIntValue);
+  nsresult RemoveCSSProperty(mozilla::dom::Element& aElement,
+                             nsIAtom& aProperty,
+                             const nsAString& aPropertyValue,
+                             bool aSuppressTxn = false);
 
   /** directly adds/remove a CSS declaration to the STYLE atrribute carried by
     * a given element without going through the txn manager
     *
     * @param aElement       [IN] a DOM element
     * @param aProperty      [IN] a string containing the CSS property to set/remove
     * @param aValue         [IN] a string containing the new value of the CSS property
     */
@@ -369,29 +370,28 @@ private:
   void      GenerateCSSDeclarationsFromHTMLStyle(mozilla::dom::Element* aNode,
                                                  nsIAtom* aHTMLProperty,
                                                  const nsAString* aAttribute,
                                                  const nsAString* aValue,
                                                  nsTArray<nsIAtom*>& aPropertyArray,
                                                  nsTArray<nsString>& aValueArray,
                                                  bool aGetOrRemoveRequest);
 
-  /** creates a Transaction for setting or removing a css property
+  /** Creates a Transaction for setting or removing a CSS property.  Never
+    * returns null.
     *
     * @param aElement           [IN] a DOM element
     * @param aProperty          [IN] a CSS property
-    * @param aValue             [IN] the value to remove for this CSS property or the empty string if irrelevant
-    * @param aTxn               [OUT] the created transaction
-    * @param aRemoveProperty    [IN] true if we create a "remove" transaction, false for a "set"
+    * @param aValue             [IN] the value to set for this CSS property
+    * @param aChangeType        [IN] eSet to set, eRemove to remove
     */
-  nsresult    CreateCSSPropertyTxn(nsIDOMElement * aElement, 
-                                   nsIAtom * aProperty,
-                                   const nsAString & aValue,
-                                   ChangeCSSInlineStyleTxn ** aTxn,
-                                   bool aRemoveProperty);
+  already_AddRefed<mozilla::dom::ChangeStyleTxn>
+  CreateCSSPropertyTxn(mozilla::dom::Element& aElement,
+      nsIAtom& aProperty, const nsAString& aValue,
+      mozilla::dom::ChangeStyleTxn::EChangeType aChangeType);
 
   /** back-end for GetSpecifiedProperty and GetComputedProperty
    *
    * @param aNode               [IN] a DOM node
    * @param aProperty           [IN] a CSS property
    * @param aValue              [OUT] the retrieved value for this property
    * @param aStyleType          [IN] eSpecified or eComputed
    */
--- a/editor/libeditor/nsHTMLDataTransfer.cpp
+++ b/editor/libeditor/nsHTMLDataTransfer.cpp
@@ -17,17 +17,16 @@
 #include "nsCOMArray.h"
 #include "nsCOMPtr.h"
 #include "nsCRT.h"
 #include "nsCRTGlue.h"
 #include "nsComponentManagerUtils.h"
 #include "nsContentUtils.h"
 #include "nsDebug.h"
 #include "nsDependentSubstring.h"
-#include "nsEditProperty.h"
 #include "nsEditRules.h"
 #include "nsEditor.h"
 #include "nsEditorUtils.h"
 #include "nsError.h"
 #include "nsGkAtoms.h"
 #include "nsHTMLEditUtils.h"
 #include "nsHTMLEditor.h"
 #include "nsIClipboard.h"
@@ -1931,19 +1930,17 @@ void RemoveBodyAndHead(nsIDOMNode *aNode
   // find the body and head nodes if any.
   // look only at immediate children of aNode.
   aNode->GetFirstChild(getter_AddRefs(child));
   while (child)
   {
     if (nsTextEditUtils::IsBody(child))
     {
       body = child;
-    }
-    else if (nsEditor::NodeIsType(child, nsEditProperty::head))
-    {
+    } else if (nsEditor::NodeIsType(child, nsGkAtoms::head)) {
       head = child;
     }
     child->GetNextSibling(getter_AddRefs(tmp));
     child = tmp;
   }
   if (head)
   {
     aNode->RemoveChild(head, getter_AddRefs(tmp));
--- a/editor/libeditor/nsHTMLEditRules.cpp
+++ b/editor/libeditor/nsHTMLEditRules.cpp
@@ -15,17 +15,16 @@
 #include "nsAString.h"
 #include "nsAlgorithm.h"
 #include "nsCOMArray.h"
 #include "nsCRT.h"
 #include "nsCRTGlue.h"
 #include "nsComponentManagerUtils.h"
 #include "nsContentUtils.h"
 #include "nsDebug.h"
-#include "nsEditProperty.h"
 #include "nsEditor.h"
 #include "nsEditorUtils.h"
 #include "nsError.h"
 #include "nsGkAtoms.h"
 #include "nsHTMLCSSUtils.h"
 #include "nsHTMLEditRules.h"
 #include "nsHTMLEditUtils.h"
 #include "nsHTMLEditor.h"
@@ -185,35 +184,35 @@ nsHTMLEditRules::InitFields()
   mDidDeleteSelection = false;
   mDidRangedDelete = false;
   mRestoreContentEditableCount = false;
   mUtilRange = nullptr;
   mJoinOffset = 0;
   mNewBlock = nullptr;
   mRangeItem = new nsRangeStore();
   // populate mCachedStyles
-  mCachedStyles[0] = StyleCache(nsEditProperty::b, EmptyString(), EmptyString());
-  mCachedStyles[1] = StyleCache(nsEditProperty::i, EmptyString(), EmptyString());
-  mCachedStyles[2] = StyleCache(nsEditProperty::u, EmptyString(), EmptyString());
-  mCachedStyles[3] = StyleCache(nsEditProperty::font, NS_LITERAL_STRING("face"), EmptyString());
-  mCachedStyles[4] = StyleCache(nsEditProperty::font, NS_LITERAL_STRING("size"), EmptyString());
-  mCachedStyles[5] = StyleCache(nsEditProperty::font, NS_LITERAL_STRING("color"), EmptyString());
-  mCachedStyles[6] = StyleCache(nsEditProperty::tt, EmptyString(), EmptyString());
-  mCachedStyles[7] = StyleCache(nsEditProperty::em, EmptyString(), EmptyString());
-  mCachedStyles[8] = StyleCache(nsEditProperty::strong, EmptyString(), EmptyString());
-  mCachedStyles[9] = StyleCache(nsEditProperty::dfn, EmptyString(), EmptyString());
-  mCachedStyles[10] = StyleCache(nsEditProperty::code, EmptyString(), EmptyString());
-  mCachedStyles[11] = StyleCache(nsEditProperty::samp, EmptyString(), EmptyString());
-  mCachedStyles[12] = StyleCache(nsEditProperty::var, EmptyString(), EmptyString());
-  mCachedStyles[13] = StyleCache(nsEditProperty::cite, EmptyString(), EmptyString());
-  mCachedStyles[14] = StyleCache(nsEditProperty::abbr, EmptyString(), EmptyString());
-  mCachedStyles[15] = StyleCache(nsEditProperty::acronym, EmptyString(), EmptyString());
-  mCachedStyles[16] = StyleCache(nsEditProperty::cssBackgroundColor, EmptyString(), EmptyString());
-  mCachedStyles[17] = StyleCache(nsEditProperty::sub, EmptyString(), EmptyString());
-  mCachedStyles[18] = StyleCache(nsEditProperty::sup, EmptyString(), EmptyString());
+  mCachedStyles[0] = StyleCache(nsGkAtoms::b, EmptyString(), EmptyString());
+  mCachedStyles[1] = StyleCache(nsGkAtoms::i, EmptyString(), EmptyString());
+  mCachedStyles[2] = StyleCache(nsGkAtoms::u, EmptyString(), EmptyString());
+  mCachedStyles[3] = StyleCache(nsGkAtoms::font, NS_LITERAL_STRING("face"), EmptyString());
+  mCachedStyles[4] = StyleCache(nsGkAtoms::font, NS_LITERAL_STRING("size"), EmptyString());
+  mCachedStyles[5] = StyleCache(nsGkAtoms::font, NS_LITERAL_STRING("color"), EmptyString());
+  mCachedStyles[6] = StyleCache(nsGkAtoms::tt, EmptyString(), EmptyString());
+  mCachedStyles[7] = StyleCache(nsGkAtoms::em, EmptyString(), EmptyString());
+  mCachedStyles[8] = StyleCache(nsGkAtoms::strong, EmptyString(), EmptyString());
+  mCachedStyles[9] = StyleCache(nsGkAtoms::dfn, EmptyString(), EmptyString());
+  mCachedStyles[10] = StyleCache(nsGkAtoms::code, EmptyString(), EmptyString());
+  mCachedStyles[11] = StyleCache(nsGkAtoms::samp, EmptyString(), EmptyString());
+  mCachedStyles[12] = StyleCache(nsGkAtoms::var, EmptyString(), EmptyString());
+  mCachedStyles[13] = StyleCache(nsGkAtoms::cite, EmptyString(), EmptyString());
+  mCachedStyles[14] = StyleCache(nsGkAtoms::abbr, EmptyString(), EmptyString());
+  mCachedStyles[15] = StyleCache(nsGkAtoms::acronym, EmptyString(), EmptyString());
+  mCachedStyles[16] = StyleCache(nsGkAtoms::backgroundColor, EmptyString(), EmptyString());
+  mCachedStyles[17] = StyleCache(nsGkAtoms::sub, EmptyString(), EmptyString());
+  mCachedStyles[18] = StyleCache(nsGkAtoms::sup, EmptyString(), EmptyString());
 }
 
 nsHTMLEditRules::~nsHTMLEditRules()
 {
   // remove ourselves as a listener to edit actions
   // In some cases, we have already been removed by 
   // ~nsHTMLEditor, in which case we will get a null pointer here
   // which we ignore.  But this allows us to add the ability to
@@ -822,20 +821,18 @@ nsHTMLEditRules::GetAlignment(bool *aMix
   }
   else if (!mHTMLEditor) {
     return NS_ERROR_UNEXPECTED;
   }
   else if (mHTMLEditor->IsTextNode(parent)) 
   {
     // if we are in a text node, then that is the node of interest
     nodeToExamine = parent;
-  }
-  else if (nsEditor::NodeIsType(parent, nsEditProperty::html) &&
-           offset == rootOffset)
-  {
+  } else if (nsEditor::NodeIsType(parent, nsGkAtoms::html) &&
+             offset == rootOffset) {
     // if we have selected the body, let's look at the first editable node
     NS_ENSURE_STATE(mHTMLEditor);
     mHTMLEditor->GetNextNode(parent, offset, true, address_of(nodeToExamine));
   }
   else
   {
     nsCOMArray<nsIDOMRange> arrayOfRanges;
     res = GetPromotedRanges(selection, arrayOfRanges, EditAction::align);
@@ -943,19 +940,19 @@ nsHTMLEditRules::GetAlignment(bool *aMix
     if (NS_FAILED(res)) temp = nullptr;
     nodeToExamine = temp; 
   }
   return NS_OK;
 }
 
 nsIAtom* MarginPropertyAtomForIndent(nsHTMLCSSUtils* aHTMLCSSUtils, nsIDOMNode* aNode) {
   nsAutoString direction;
-  aHTMLCSSUtils->GetComputedProperty(aNode, nsEditProperty::cssDirection, direction);
+  aHTMLCSSUtils->GetComputedProperty(aNode, nsGkAtoms::direction, direction);
   return direction.EqualsLiteral("rtl") ?
-    nsEditProperty::cssMarginRight : nsEditProperty::cssMarginLeft;
+    nsGkAtoms::marginRight : nsGkAtoms::marginLeft;
 }
 
 nsresult 
 nsHTMLEditRules::GetIndentState(bool *aCanIndent, bool *aCanOutdent)
 {
   NS_ENSURE_TRUE(aCanIndent && aCanOutdent, NS_ERROR_FAILURE);
   *aCanIndent = true;    
   *aCanOutdent = false;
@@ -3140,33 +3137,32 @@ nsHTMLEditRules::WillMakeList(Selection*
                               const nsAString* aBulletType,
                               bool* aCancel,
                               bool* aHandled,
                               const nsAString* aItemType)
 {
   if (!aSelection || !aListType || !aCancel || !aHandled) {
     return NS_ERROR_NULL_POINTER;
   }
-  nsCOMPtr<nsIAtom> listTypeAtom = do_GetAtom(*aListType);
-  NS_ENSURE_TRUE(listTypeAtom, NS_ERROR_OUT_OF_MEMORY);
+  nsCOMPtr<nsIAtom> listType = do_GetAtom(*aListType);
 
   nsresult res = WillInsert(aSelection, aCancel);
   NS_ENSURE_SUCCESS(res, res);
 
   // initialize out param
   // we want to ignore result of WillInsert()
   *aCancel = false;
   *aHandled = false;
 
   // deduce what tag to use for list items
   nsCOMPtr<nsIAtom> itemType;
   if (aItemType) { 
     itemType = do_GetAtom(*aItemType);
     NS_ENSURE_TRUE(itemType, NS_ERROR_OUT_OF_MEMORY);
-  } else if (listTypeAtom == nsGkAtoms::dl) {
+  } else if (listType == nsGkAtoms::dl) {
     itemType = nsGkAtoms::dd;
   } else {
     itemType = nsGkAtoms::li;
   }
 
   // convert the selection ranges into "promoted" selection ranges:
   // this basically just expands the range to include the immediate
   // block parent, and then further expands to include any ancestors
@@ -3194,52 +3190,51 @@ nsHTMLEditRules::WillMakeList(Selection*
       bOnlyBreaks = false;
       break;
     }
   }
 
   // if no nodes, we make empty list.  Ditto if the user tried to make a list
   // of some # of breaks.
   if (!listCount || bOnlyBreaks) {
-    nsCOMPtr<nsIDOMNode> parent, theList, theListItem;
-    int32_t offset;
-
     // if only breaks, delete them
     if (bOnlyBreaks) {
       for (int32_t j = 0; j < (int32_t)listCount; j++) {
         NS_ENSURE_STATE(mHTMLEditor);
         res = mHTMLEditor->DeleteNode(arrayOfNodes[j]);
         NS_ENSURE_SUCCESS(res, res);
       }
     }
 
     // get selection location
-    NS_ENSURE_STATE(mHTMLEditor);
-    res = mHTMLEditor->GetStartNodeAndOffset(aSelection,
-                                             getter_AddRefs(parent), &offset);
-    NS_ENSURE_SUCCESS(res, res);
+    NS_ENSURE_STATE(aSelection->RangeCount());
+    nsCOMPtr<nsINode> parent = aSelection->GetRangeAt(0)->GetStartParent();
+    int32_t offset = aSelection->GetRangeAt(0)->StartOffset();
+    NS_ENSURE_STATE(parent);
 
     // make sure we can put a list here
     NS_ENSURE_STATE(mHTMLEditor);
-    if (!mHTMLEditor->CanContainTag(parent, listTypeAtom)) {
+    if (!mHTMLEditor->CanContainTag(parent->AsDOMNode(), listType)) {
       *aCancel = true;
       return NS_OK;
     }
-    res = SplitAsNeeded(aListType, address_of(parent), &offset);
-    NS_ENSURE_SUCCESS(res, res);
-    NS_ENSURE_STATE(mHTMLEditor);
-    res = mHTMLEditor->CreateNode(*aListType, parent, offset,
-                                  getter_AddRefs(theList));
+    res = SplitAsNeeded(*listType, parent, offset);
     NS_ENSURE_SUCCESS(res, res);
     NS_ENSURE_STATE(mHTMLEditor);
-    res = mHTMLEditor->CreateNode(nsDependentAtomString(itemType), theList, 0,
-                                  getter_AddRefs(theListItem));
-    NS_ENSURE_SUCCESS(res, res);
+    nsCOMPtr<Element> theList =
+      mHTMLEditor->CreateNode(listType, parent, offset);
+    NS_ENSURE_STATE(theList);
+
+    NS_ENSURE_STATE(mHTMLEditor);
+    nsCOMPtr<Element> theListItem =
+      mHTMLEditor->CreateNode(itemType, theList, 0);
+    NS_ENSURE_STATE(theListItem);
+
     // remember our new block for postprocessing
-    mNewBlock = theListItem;
+    mNewBlock = GetAsDOMNode(theListItem);
     // put selection in new list item
     res = aSelection->Collapse(theListItem, 0);
     // to prevent selection resetter from overriding us
     selectionResetter.Abort();
     *aHandled = true;
     return res;
   }
 
@@ -3248,132 +3243,122 @@ nsHTMLEditRules::WillMakeList(Selection*
 
   res = LookInsideDivBQandList(arrayOfNodes);
   NS_ENSURE_SUCCESS(res, res);
 
   // Ok, now go through all the nodes and put then in the list,
   // or whatever is approriate.  Wohoo!
 
   listCount = arrayOfNodes.Count();
-  nsCOMPtr<nsIDOMNode> curParent;
-  nsCOMPtr<nsIDOMNode> curList;
-  nsCOMPtr<nsIContent> curListAsContent;
-  nsCOMPtr<Element> prevListItem;
+  nsCOMPtr<nsINode> curParent;
+  nsCOMPtr<Element> curList, prevListItem;
 
   for (int32_t i = 0; i < listCount; i++) {
     // here's where we actually figure out what to do
     nsCOMPtr<nsIDOMNode> newBlock;
-    nsCOMPtr<nsIDOMNode> curNode = arrayOfNodes[i];
-    nsCOMPtr<nsIContent> curNodeAsContent = do_QueryInterface(curNode);
-    nsCOMPtr<Element> curNodeAsElement = curNodeAsContent->IsElement()
-      ? curNodeAsContent->AsElement() : nullptr;
+    nsCOMPtr<nsIContent> curNode = do_QueryInterface(arrayOfNodes[i]);
+    NS_ENSURE_STATE(curNode);
     int32_t offset;
     curParent = nsEditor::GetNodeLocation(curNode, &offset);
 
     // make sure we don't assemble content that is in different table cells
     // into the same list.  respect table cell boundaries when listifying.
     if (curList && InDifferentTableElements(curList, curNode)) {
       curList = nullptr;
     }
 
-    curListAsContent = do_QueryInterface(curList);
-    NS_ENSURE_STATE(curListAsContent || !curList);
-
     // if curNode is a Break, delete it, and quit remembering prev list item
     if (nsTextEditUtils::IsBreak(curNode)) {
       NS_ENSURE_STATE(mHTMLEditor);
       res = mHTMLEditor->DeleteNode(curNode);
       NS_ENSURE_SUCCESS(res, res);
       prevListItem = 0;
       continue;
-    } else if (IsEmptyInline(curNode)) {
+    } else if (IsEmptyInline(GetAsDOMNode(curNode))) {
       // if curNode is an empty inline container, delete it
       NS_ENSURE_STATE(mHTMLEditor);
       res = mHTMLEditor->DeleteNode(curNode);
       NS_ENSURE_SUCCESS(res, res);
       continue;
     }
 
     if (nsHTMLEditUtils::IsList(curNode)) {
       // do we have a curList already?
       if (curList && !nsEditorUtils::IsDescendantOf(curNode, curList)) {
         // move all of our children into curList.  cheezy way to do it: move
         // whole list and then RemoveContainer() on the list.  ConvertListType
         // first: that routine handles converting the list item types, if
         // needed
         NS_ENSURE_STATE(mHTMLEditor);
-        res = mHTMLEditor->MoveNode(curNodeAsContent, curListAsContent, -1);
+        res = mHTMLEditor->MoveNode(curNode, curList, -1);
         NS_ENSURE_SUCCESS(res, res);
-        res = ConvertListType(curNode, address_of(newBlock), listTypeAtom,
-                              itemType);
+        res = ConvertListType(GetAsDOMNode(curNode), address_of(newBlock),
+                              listType, itemType);
         NS_ENSURE_SUCCESS(res, res);
         NS_ENSURE_STATE(mHTMLEditor);
         res = mHTMLEditor->RemoveBlockContainer(newBlock);
         NS_ENSURE_SUCCESS(res, res);
       } else {
         // replace list with new list type
-        res = ConvertListType(curNode, address_of(newBlock), listTypeAtom,
-                              itemType);
+        res = ConvertListType(GetAsDOMNode(curNode), address_of(newBlock),
+                              listType, itemType);
         NS_ENSURE_SUCCESS(res, res);
-        curList = newBlock;
-        curListAsContent = do_QueryInterface(curList);
+        curList = do_QueryInterface(newBlock);
       }
       prevListItem = 0;
       continue;
     }
 
     if (nsHTMLEditUtils::IsListItem(curNode)) {
       NS_ENSURE_STATE(mHTMLEditor);
-      if (mHTMLEditor->GetTag(curParent) != listTypeAtom) {
+      if (curParent->Tag() != listType) {
         // list item is in wrong type of list. if we don't have a curList,
         // split the old list and make a new list of correct type.
         if (!curList || nsEditorUtils::IsDescendantOf(curNode, curList)) {
           NS_ENSURE_STATE(mHTMLEditor);
-          res = mHTMLEditor->SplitNode(curParent, offset,
+          res = mHTMLEditor->SplitNode(curParent->AsDOMNode(), offset,
                                        getter_AddRefs(newBlock));
           NS_ENSURE_SUCCESS(res, res);
           int32_t offset;
-          nsCOMPtr<nsIDOMNode> parent = nsEditor::GetNodeLocation(curParent, &offset);
+          nsCOMPtr<nsINode> parent = nsEditor::GetNodeLocation(curParent,
+                                                               &offset);
           NS_ENSURE_STATE(mHTMLEditor);
-          res = mHTMLEditor->CreateNode(*aListType, parent, offset,
-                                        getter_AddRefs(curList));
-          NS_ENSURE_SUCCESS(res, res);
-          curListAsContent = do_QueryInterface(curList);
+          curList = mHTMLEditor->CreateNode(listType, parent, offset);
+          NS_ENSURE_STATE(curList);
         }
         // move list item to new list
         NS_ENSURE_STATE(mHTMLEditor);
-        res = mHTMLEditor->MoveNode(curNodeAsContent, curListAsContent, -1);
+        res = mHTMLEditor->MoveNode(curNode, curList, -1);
         NS_ENSURE_SUCCESS(res, res);
         // convert list item type if needed
         NS_ENSURE_STATE(mHTMLEditor);
-        if (!mHTMLEditor->NodeIsType(curNode, itemType)) {
+        if (curNode->Tag() != itemType) {
           NS_ENSURE_STATE(mHTMLEditor);
-          NS_ENSURE_STATE(curNodeAsElement);
           newBlock = dont_AddRef(GetAsDOMNode(
-            mHTMLEditor->ReplaceContainer(curNodeAsElement, itemType).take()));
+            mHTMLEditor->ReplaceContainer(curNode->AsElement(),
+                                          itemType).take()));
           NS_ENSURE_STATE(newBlock);
         }
       } else {
         // item is in right type of list.  But we might still have to move it.
         // and we might need to convert list item types.
         if (!curList) {
-          curList = curParent;
-          curListAsContent = do_QueryInterface(curList);
+          curList = curParent->AsElement();
         } else if (curParent != curList) {
           // move list item to new list
           NS_ENSURE_STATE(mHTMLEditor);
-          res = mHTMLEditor->MoveNode(curNodeAsContent, curListAsContent, -1);
+          res = mHTMLEditor->MoveNode(curNode, curList, -1);
           NS_ENSURE_SUCCESS(res, res);
         }
         NS_ENSURE_STATE(mHTMLEditor);
-        if (!mHTMLEditor->NodeIsType(curNode, itemType)) {
+        if (curNode->Tag() != itemType) {
           NS_ENSURE_STATE(mHTMLEditor);
-          NS_ENSURE_STATE(curNodeAsElement);
           newBlock = dont_AddRef(GetAsDOMNode(
-            mHTMLEditor->ReplaceContainer(curNodeAsElement, itemType).take()));
+            mHTMLEditor->ReplaceContainer(curNode->AsElement(),
+                                          itemType).take()));
           NS_ENSURE_STATE(newBlock);
         }
       }
       nsCOMPtr<nsIDOMElement> curElement = do_QueryInterface(curNode);
       NS_NAMED_LITERAL_STRING(typestr, "type");
       if (aBulletType && !aBulletType->IsEmpty()) {
         NS_ENSURE_STATE(mHTMLEditor);
         res = mHTMLEditor->SetAttribute(curElement, typestr, *aBulletType);
@@ -3382,84 +3367,77 @@ nsHTMLEditRules::WillMakeList(Selection*
         res = mHTMLEditor->RemoveAttribute(curElement, typestr);
       }
       NS_ENSURE_SUCCESS(res, res);
       continue;
     }
 
     // if we hit a div clear our prevListItem, insert divs contents
     // into our node array, and remove the div
-    if (nsHTMLEditUtils::IsDiv(curNode)) {
+    if (curNode->Tag() == nsGkAtoms::div) {
       prevListItem = nullptr;
       int32_t j = i + 1;
-      res = GetInnerContent(curNode, arrayOfNodes, &j);
+      res = GetInnerContent(curNode->AsDOMNode(), arrayOfNodes, &j);
       NS_ENSURE_SUCCESS(res, res);
       NS_ENSURE_STATE(mHTMLEditor);
-      NS_ENSURE_STATE(curNodeAsElement);
-      res = mHTMLEditor->RemoveContainer(curNodeAsElement);
+      res = mHTMLEditor->RemoveContainer(curNode);
       NS_ENSURE_SUCCESS(res, res);
       listCount = arrayOfNodes.Count();
       continue;
     }
 
     // need to make a list to put things in if we haven't already,
     if (!curList) {
-      res = SplitAsNeeded(aListType, address_of(curParent), &offset);
+      res = SplitAsNeeded(*listType, curParent, offset);
       NS_ENSURE_SUCCESS(res, res);
       NS_ENSURE_STATE(mHTMLEditor);
-      res = mHTMLEditor->CreateNode(*aListType, curParent, offset,
-                                    getter_AddRefs(curList));
+      curList = mHTMLEditor->CreateNode(listType, curParent, offset);
       NS_ENSURE_SUCCESS(res, res);
-      curListAsContent = do_QueryInterface(curList);
       // remember our new block for postprocessing
-      mNewBlock = curList;
+      mNewBlock = GetAsDOMNode(curList);
       // curList is now the correct thing to put curNode in
       prevListItem = 0;
     }
 
     // if curNode isn't a list item, we must wrap it in one
     nsCOMPtr<Element> listItem;
     if (!nsHTMLEditUtils::IsListItem(curNode)) {
-      if (IsInlineNode(curNode) && prevListItem) {
+      if (IsInlineNode(GetAsDOMNode(curNode)) && prevListItem) {
         // this is a continuation of some inline nodes that belong together in
         // the same list item.  use prevListItem
         NS_ENSURE_STATE(mHTMLEditor);
-        res = mHTMLEditor->MoveNode(curNodeAsContent, prevListItem, -1);
+        res = mHTMLEditor->MoveNode(curNode, prevListItem, -1);
         NS_ENSURE_SUCCESS(res, res);
       } else {
         // don't wrap li around a paragraph.  instead replace paragraph with li
-        if (nsHTMLEditUtils::IsParagraph(curNode)) {
+        if (curNode->Tag() == nsGkAtoms::p) {
           NS_ENSURE_STATE(mHTMLEditor);
-          NS_ENSURE_STATE(curNodeAsElement);
-          listItem = mHTMLEditor->ReplaceContainer(curNodeAsElement, itemType);
+          listItem = mHTMLEditor->ReplaceContainer(curNode->AsElement(),
+                                                   itemType);
           NS_ENSURE_STATE(listItem);
         } else {
           NS_ENSURE_STATE(mHTMLEditor);
-          NS_ENSURE_STATE(curNodeAsContent);
-          listItem = mHTMLEditor->InsertContainerAbove(curNodeAsContent,
-                                                       itemType);
+          listItem = mHTMLEditor->InsertContainerAbove(curNode, itemType);
           NS_ENSURE_STATE(listItem);
         }
-        if (IsInlineNode(curNode)) {
+        if (IsInlineNode(GetAsDOMNode(curNode))) {
           prevListItem = listItem;
         } else {
           prevListItem = nullptr;
         }
       }
     } else {
-      listItem = curNodeAsElement;
+      listItem = curNode->AsElement();
     }
 
     if (listItem) {
       // if we made a new list item, deal with it: tuck the listItem into the
       // end of the active list
       NS_ENSURE_STATE(mHTMLEditor);
-      nsCOMPtr<nsINode> curList_ = do_QueryInterface(curList);
-      NS_ENSURE_STATE(curList_);
-      res = mHTMLEditor->MoveNode(listItem, curList_, -1);
+      res = mHTMLEditor->MoveNode(listItem, curList, -1);
       NS_ENSURE_SUCCESS(res, res);
     }
   }
 
   return res;
 }
 
 
@@ -3545,16 +3523,17 @@ nsHTMLEditRules::WillMakeDefListItem(Sel
 }
 
 nsresult
 nsHTMLEditRules::WillMakeBasicBlock(Selection* aSelection,
                                     const nsAString *aBlockType, 
                                     bool *aCancel,
                                     bool *aHandled)
 {
+  nsCOMPtr<nsIAtom> blockType = do_GetAtom(*aBlockType);
   if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
   // initialize out param
   *aCancel = false;
   *aHandled = false;
   
   nsresult res = WillInsert(aSelection, aCancel);
   NS_ENSURE_SUCCESS(res, res);
   // initialize out param
@@ -3588,51 +3567,54 @@ nsHTMLEditRules::WillMakeBasicBlock(Sele
   }
   
   // reset list count
   listCount = arrayOfNodes.Count();
   
   // if nothing visible in list, make an empty block
   if (ListIsEmptyLine(arrayOfNodes))
   {
-    nsCOMPtr<nsIDOMNode> parent, theBlock;
-    int32_t offset;
+    nsCOMPtr<nsIDOMNode> theBlock;
     
     // get selection location
-    NS_ENSURE_STATE(mHTMLEditor);
-    res = mHTMLEditor->GetStartNodeAndOffset(aSelection, getter_AddRefs(parent), &offset);
-    NS_ENSURE_SUCCESS(res, res);
+    NS_ENSURE_STATE(aSelection->RangeCount());
+    nsCOMPtr<nsINode> parent = aSelection->GetRangeAt(0)->GetStartParent();
+    int32_t offset = aSelection->GetRangeAt(0)->StartOffset();
+    NS_ENSURE_STATE(parent);
     if (tString.EqualsLiteral("normal") ||
         tString.IsEmpty() ) // we are removing blocks (going to "body text")
     {
-      nsCOMPtr<nsIDOMNode> curBlock = parent;
+      nsCOMPtr<nsIDOMNode> curBlock = parent->AsDOMNode();
       if (!IsBlockNode(curBlock)) {
         NS_ENSURE_STATE(mHTMLEditor);
-        curBlock = mHTMLEditor->GetBlockNodeParent(parent);
+        curBlock = dont_AddRef(GetAsDOMNode(
+          mHTMLEditor->GetBlockNodeParent(parent).take()));
       }
       nsCOMPtr<nsIDOMNode> curBlockPar;
       NS_ENSURE_TRUE(curBlock, NS_ERROR_NULL_POINTER);
       curBlock->GetParentNode(getter_AddRefs(curBlockPar));
       if (nsHTMLEditUtils::IsFormatNode(curBlock))
       {
         // if the first editable node after selection is a br, consume it.  Otherwise
         // it gets pushed into a following block after the split, which is visually bad.
         nsCOMPtr<nsIDOMNode> brNode;
         NS_ENSURE_STATE(mHTMLEditor);
-        res = mHTMLEditor->GetNextHTMLNode(parent, offset, address_of(brNode));
+        res = mHTMLEditor->GetNextHTMLNode(parent->AsDOMNode(), offset,
+                                           address_of(brNode));
         NS_ENSURE_SUCCESS(res, res);        
         if (brNode && nsTextEditUtils::IsBreak(brNode))
         {
           NS_ENSURE_STATE(mHTMLEditor);
           res = mHTMLEditor->DeleteNode(brNode);
           NS_ENSURE_SUCCESS(res, res); 
         }
         // do the splits!
         NS_ENSURE_STATE(mHTMLEditor);
-        res = mHTMLEditor->SplitNodeDeep(curBlock, parent, offset, &offset, true);
+        res = mHTMLEditor->SplitNodeDeep(curBlock, parent->AsDOMNode(), offset,
+                                         &offset, true);
         NS_ENSURE_SUCCESS(res, res);
         // put a br at the split point
         NS_ENSURE_STATE(mHTMLEditor);
         res = mHTMLEditor->CreateBR(curBlockPar, offset, address_of(brNode));
         NS_ENSURE_SUCCESS(res, res);
         // put selection at the split point
         res = aSelection->Collapse(curBlockPar, offset);
         selectionResetter.Abort();  // to prevent selection reseter from overriding us.
@@ -3640,32 +3622,34 @@ nsHTMLEditRules::WillMakeBasicBlock(Sele
       }
       // else nothing to do!
     }
     else  // we are making a block
     {   
       // consume a br, if needed
       nsCOMPtr<nsIDOMNode> brNode;
       NS_ENSURE_STATE(mHTMLEditor);
-      res = mHTMLEditor->GetNextHTMLNode(parent, offset, address_of(brNode), true);
+      res = mHTMLEditor->GetNextHTMLNode(parent->AsDOMNode(), offset,
+                                         address_of(brNode), true);
       NS_ENSURE_SUCCESS(res, res);
       if (brNode && nsTextEditUtils::IsBreak(brNode))
       {
         NS_ENSURE_STATE(mHTMLEditor);
         res = mHTMLEditor->DeleteNode(brNode);
         NS_ENSURE_SUCCESS(res, res);
         // we don't need to act on this node any more
         arrayOfNodes.RemoveObject(brNode);
       }
       // make sure we can put a block here
-      res = SplitAsNeeded(aBlockType, address_of(parent), &offset);
+      res = SplitAsNeeded(*blockType, parent, offset);
       NS_ENSURE_SUCCESS(res, res);
       NS_ENSURE_STATE(mHTMLEditor);
-      res = mHTMLEditor->CreateNode(*aBlockType, parent, offset, getter_AddRefs(theBlock));
-      NS_ENSURE_SUCCESS(res, res);
+      theBlock = dont_AddRef(GetAsDOMNode(
+        mHTMLEditor->CreateNode(blockType, parent, offset).take()));
+      NS_ENSURE_STATE(theBlock);
       // remember our new block for postprocessing
       mNewBlock = theBlock;
       // delete anything that was in the list of nodes
       for (int32_t j = arrayOfNodes.Count() - 1; j >= 0; --j) 
       {
         nsCOMPtr<nsIDOMNode> curNode = arrayOfNodes[0];
         NS_ENSURE_STATE(mHTMLEditor);
         res = mHTMLEditor->DeleteNode(curNode);
@@ -3779,36 +3763,35 @@ nsHTMLEditRules::WillCSSIndent(Selection
     // convert the selection ranges into "promoted" selection ranges:
     // this basically just expands the range to include the immediate
     // block parent, and then further expands to include any ancestors
     // whose children are all in the range
     res = GetNodesFromSelection(aSelection, EditAction::indent, arrayOfNodes);
     NS_ENSURE_SUCCESS(res, res);
   }
   
-  NS_NAMED_LITERAL_STRING(quoteType, "blockquote");
   // if nothing visible in list, make an empty block
   if (ListIsEmptyLine(arrayOfNodes))
   {
-    nsCOMPtr<nsIDOMNode> parent, theBlock;
-    int32_t offset;
-    nsAutoString quoteType(NS_LITERAL_STRING("div"));
     // get selection location
-    NS_ENSURE_STATE(mHTMLEditor);
-    res = mHTMLEditor->GetStartNodeAndOffset(aSelection, getter_AddRefs(parent), &offset);
-    NS_ENSURE_SUCCESS(res, res);
+    NS_ENSURE_STATE(aSelection->RangeCount());
+    nsCOMPtr<nsINode> parent = aSelection->GetRangeAt(0)->GetStartParent();
+    int32_t offset = aSelection->GetRangeAt(0)->StartOffset();
+    NS_ENSURE_STATE(parent);
+
     // make sure we can put a block here
-    res = SplitAsNeeded(&quoteType, address_of(parent), &offset);
+    res = SplitAsNeeded(*nsGkAtoms::div, parent, offset);
     NS_ENSURE_SUCCESS(res, res);
     NS_ENSURE_STATE(mHTMLEditor);
-    res = mHTMLEditor->CreateNode(quoteType, parent, offset, getter_AddRefs(theBlock));
-    NS_ENSURE_SUCCESS(res, res);
+    nsCOMPtr<Element> theBlock = mHTMLEditor->CreateNode(nsGkAtoms::div,
+                                                         parent, offset);
+    NS_ENSURE_STATE(theBlock);
     // remember our new block for postprocessing
-    mNewBlock = theBlock;
-    RelativeChangeIndentationOfElementNode(theBlock, +1);
+    mNewBlock = theBlock->AsDOMNode();
+    RelativeChangeIndentationOfElementNode(theBlock->AsDOMNode(), +1);
     // delete anything that was in the list of nodes
     for (int32_t j = arrayOfNodes.Count() - 1; j >= 0; --j) 
     {
       nsCOMPtr<nsIDOMNode> curNode = arrayOfNodes[0];
       NS_ENSURE_STATE(mHTMLEditor);
       res = mHTMLEditor->DeleteNode(curNode);
       NS_ENSURE_SUCCESS(res, res);
       arrayOfNodes.RemoveObjectAt(0);
@@ -3878,24 +3861,19 @@ nsHTMLEditRules::WillCSSIndent(Selection
       // check to see if curList is still appropriate.  Which it is if
       // curNode is still right after it in the same list.
       if (curList) {
         NS_ENSURE_STATE(mHTMLEditor);
         sibling = mHTMLEditor->GetPriorHTMLSibling(curNode);
       }
 
       if (!curList || (sibling && sibling != curList)) {
-        nsAutoString listTag;
-        curParent->Tag()->ToString(listTag);
-        ToLowerCase(listTag);
         // create a new nested list of correct type
-        nsCOMPtr<nsIDOMNode> curParentDOM = curParent->AsDOMNode();
-        res = SplitAsNeeded(&listTag, address_of(curParentDOM), &offset);
+        res = SplitAsNeeded(*curParent->Tag(), curParent, offset);
         NS_ENSURE_SUCCESS(res, res);
-        curParent = do_QueryInterface(curParentDOM);
         NS_ENSURE_STATE(mHTMLEditor);
         curList = mHTMLEditor->CreateNode(curParent->Tag(), curParent, offset);
         NS_ENSURE_STATE(curList);
         // curList is now the correct thing to put curNode in
         // remember our new block for postprocessing
         mNewBlock = curList->AsDOMNode();
       }
       // tuck the node into the end of the active list
@@ -3915,21 +3893,18 @@ nsHTMLEditRules::WillCSSIndent(Selection
         if (!curQuote)
         {
           // First, check that our element can contain a div.
           if (!mEditor->CanContainTag(GetAsDOMNode(curParent),
                                       nsGkAtoms::div)) {
             return NS_OK; // cancelled
           }
 
-          nsCOMPtr<nsIDOMNode> curParentDOM = curParent->AsDOMNode();
-          res = SplitAsNeeded(&NS_LITERAL_STRING("div"),
-                              address_of(curParentDOM), &offset);
+          res = SplitAsNeeded(*nsGkAtoms::div, curParent, offset);
           NS_ENSURE_SUCCESS(res, res);
-          curParent = do_QueryInterface(curParentDOM);
           NS_ENSURE_STATE(mHTMLEditor);
           curQuote = mHTMLEditor->CreateNode(nsGkAtoms::div, curParent,
                                              offset);
           NS_ENSURE_STATE(curQuote);
           RelativeChangeIndentationOfElementNode(curQuote->AsDOMNode(), +1);
           // remember our new block for postprocessing
           mNewBlock = curQuote->AsDOMNode();
           // curQuote is now the correct thing to put curNode in
@@ -3973,36 +3948,34 @@ nsHTMLEditRules::WillHTMLIndent(Selectio
   res = GetPromotedRanges(aSelection, arrayOfRanges, EditAction::indent);
   NS_ENSURE_SUCCESS(res, res);
   
   // use these ranges to contruct a list of nodes to act on.
   nsCOMArray<nsIDOMNode> arrayOfNodes;
   res = GetNodesForOperation(arrayOfRanges, arrayOfNodes, EditAction::indent);
   NS_ENSURE_SUCCESS(res, res);                                 
                                      
-  NS_NAMED_LITERAL_STRING(quoteType, "blockquote");
-
   // if nothing visible in list, make an empty block
   if (ListIsEmptyLine(arrayOfNodes))
   {
-    nsCOMPtr<nsIDOMNode> parent, theBlock;
-    int32_t offset;
-    
     // get selection location
-    NS_ENSURE_STATE(mHTMLEditor);
-    res = mHTMLEditor->GetStartNodeAndOffset(aSelection, getter_AddRefs(parent), &offset);
-    NS_ENSURE_SUCCESS(res, res);
+    NS_ENSURE_STATE(aSelection->RangeCount());
+    nsCOMPtr<nsINode> parent = aSelection->GetRangeAt(0)->GetStartParent();
+    int32_t offset = aSelection->GetRangeAt(0)->StartOffset();
+    NS_ENSURE_STATE(parent);
+
     // make sure we can put a block here
-    res = SplitAsNeeded(&quoteType, address_of(parent), &offset);
+    res = SplitAsNeeded(*nsGkAtoms::blockquote, parent, offset);
     NS_ENSURE_SUCCESS(res, res);
     NS_ENSURE_STATE(mHTMLEditor);
-    res = mHTMLEditor->CreateNode(quoteType, parent, offset, getter_AddRefs(theBlock));
-    NS_ENSURE_SUCCESS(res, res);
+    nsCOMPtr<Element> theBlock = mHTMLEditor->CreateNode(nsGkAtoms::blockquote,
+                                                         parent, offset);
+    NS_ENSURE_STATE(theBlock);
     // remember our new block for postprocessing
-    mNewBlock = theBlock;
+    mNewBlock = theBlock->AsDOMNode();
     // delete anything that was in the list of nodes
     for (int32_t j = arrayOfNodes.Count() - 1; j >= 0; --j) 
     {
       nsCOMPtr<nsIDOMNode> curNode = arrayOfNodes[0];
       NS_ENSURE_STATE(mHTMLEditor);
       res = mHTMLEditor->DeleteNode(curNode);
       NS_ENSURE_SUCCESS(res, res);
       arrayOfNodes.RemoveObjectAt(0);
@@ -4071,24 +4044,19 @@ nsHTMLEditRules::WillHTMLIndent(Selectio
       // curNode is still right after it in the same list.
       if (curList) {
         NS_ENSURE_STATE(mHTMLEditor);
         sibling = mHTMLEditor->GetPriorHTMLSibling(curNode);
       }
 
       if (!curList || (sibling && sibling != curList) )
       {
-        nsAutoString listTag;
-        curParent->Tag()->ToString(listTag);
-        ToLowerCase(listTag);
         // create a new nested list of correct type
-        nsCOMPtr<nsIDOMNode> curParentDOM = curParent->AsDOMNode();
-        res = SplitAsNeeded(&listTag, address_of(curParentDOM), &offset);
+        res = SplitAsNeeded(*curParent->Tag(), curParent, offset);
         NS_ENSURE_SUCCESS(res, res);
-        curParent = do_QueryInterface(curParentDOM);
         NS_ENSURE_STATE(mHTMLEditor);
         curList = mHTMLEditor->CreateNode(curParent->Tag(), curParent, offset);
         NS_ENSURE_STATE(curList);
         // curList is now the correct thing to put curNode in
         // remember our new block for postprocessing
         mNewBlock = curList->AsDOMNode();
       }
       // tuck the node into the end of the active list
@@ -4121,24 +4089,19 @@ nsHTMLEditRules::WillHTMLIndent(Selectio
         {
           sibling = nullptr;
           NS_ENSURE_STATE(mHTMLEditor);
           sibling = mHTMLEditor->GetPriorHTMLSibling(curNode);
         }
          
         if (!curList || (sibling && sibling != curList) )
         {
-          nsAutoString listTag;
-          curParent->Tag()->ToString(listTag);
-          ToLowerCase(listTag);
           // create a new nested list of correct type
-          nsCOMPtr<nsIDOMNode> curParentDOM = curParent->AsDOMNode();
-          res = SplitAsNeeded(&listTag, address_of(curParentDOM), &offset);
+          res = SplitAsNeeded(*curParent->Tag(), curParent, offset);
           NS_ENSURE_SUCCESS(res, res);
-          curParent = do_QueryInterface(curParentDOM);
           NS_ENSURE_STATE(mHTMLEditor);
           curList = mHTMLEditor->CreateNode(curParent->Tag(), curParent,
                                             offset);
           NS_ENSURE_STATE(curList);
         }
         NS_ENSURE_STATE(mHTMLEditor);
         res = mHTMLEditor->MoveNode(listItem, curList, -1);
         NS_ENSURE_SUCCESS(res, res);
@@ -4159,20 +4122,18 @@ nsHTMLEditRules::WillHTMLIndent(Selectio
         if (!curQuote) 
         {
           // First, check that our element can contain a blockquote.
           if (!mEditor->CanContainTag(GetAsDOMNode(curParent),
                                       nsGkAtoms::blockquote)) {
             return NS_OK; // cancelled
           }
 
-          nsCOMPtr<nsIDOMNode> curParentDOM = GetAsDOMNode(curParent);
-          res = SplitAsNeeded(&quoteType, address_of(curParentDOM), &offset);
+          res = SplitAsNeeded(*nsGkAtoms::blockquote, curParent, offset);
           NS_ENSURE_SUCCESS(res, res);
-          curParent = do_QueryInterface(curParentDOM);
           NS_ENSURE_STATE(mHTMLEditor);
           curQuote = mHTMLEditor->CreateNode(nsGkAtoms::blockquote, curParent,
                                              offset);
           NS_ENSURE_STATE(curQuote);
           // remember our new block for postprocessing
           mNewBlock = curQuote->AsDOMNode();
           // curQuote is now the correct thing to put curNode in
         }
@@ -4863,56 +4824,61 @@ nsHTMLEditRules::WillAlign(Selection* aS
       res = mHTMLEditor->GetStartNodeAndOffset(aSelection, getter_AddRefs(parent), &offset);
 
       if (!nsHTMLEditUtils::IsTableElement(parent) || nsHTMLEditUtils::IsTableCellOrCaption(parent))
         emptyDiv = true;
     }
   }
   if (emptyDiv)
   {
-    int32_t offset;
-    nsCOMPtr<nsIDOMNode> brNode, parent, theDiv, sib;
+    nsCOMPtr<nsIDOMNode> brNode, sib;
     NS_NAMED_LITERAL_STRING(divType, "div");
-    NS_ENSURE_STATE(mHTMLEditor);
-    res = mHTMLEditor->GetStartNodeAndOffset(aSelection, getter_AddRefs(parent), &offset);
-    NS_ENSURE_SUCCESS(res, res);
-    res = SplitAsNeeded(&divType, address_of(parent), &offset);
+
+    NS_ENSURE_STATE(aSelection->GetRangeAt(0));
+    nsCOMPtr<nsINode> parent = aSelection->GetRangeAt(0)->GetStartParent();
+    int32_t offset = aSelection->GetRangeAt(0)->StartOffset();
+    NS_ENSURE_STATE(parent);
+
+    res = SplitAsNeeded(*nsGkAtoms::div, parent, offset);
     NS_ENSURE_SUCCESS(res, res);
     // consume a trailing br, if any.  This is to keep an alignment from
     // creating extra lines, if possible.
     NS_ENSURE_STATE(mHTMLEditor);
-    res = mHTMLEditor->GetNextHTMLNode(parent, offset, address_of(brNode));
+    res = mHTMLEditor->GetNextHTMLNode(parent->AsDOMNode(), offset,
+                                       address_of(brNode));
     NS_ENSURE_SUCCESS(res, res);
     if (brNode && nsTextEditUtils::IsBreak(brNode))
     {
       // making use of html structure... if next node after where
       // we are putting our div is not a block, then the br we 
       // found is in same block we are, so its safe to consume it.
       NS_ENSURE_STATE(mHTMLEditor);
-      res = mHTMLEditor->GetNextHTMLSibling(parent, offset, address_of(sib));
+      res = mHTMLEditor->GetNextHTMLSibling(parent->AsDOMNode(), offset,
+                                            address_of(sib));
       NS_ENSURE_SUCCESS(res, res);
       if (!IsBlockNode(sib))
       {
         NS_ENSURE_STATE(mHTMLEditor);
         res = mHTMLEditor->DeleteNode(brNode);
         NS_ENSURE_SUCCESS(res, res);
       }
     }
     NS_ENSURE_STATE(mHTMLEditor);
-    res = mHTMLEditor->CreateNode(divType, parent, offset, getter_AddRefs(theDiv));
-    NS_ENSURE_SUCCESS(res, res);
+    nsCOMPtr<Element> theDiv = mHTMLEditor->CreateNode(nsGkAtoms::div, parent,
+                                                       offset);
+    NS_ENSURE_STATE(theDiv);
     // remember our new block for postprocessing
-    mNewBlock = theDiv;
+    mNewBlock = theDiv->AsDOMNode();
     // set up the alignment on the div, using HTML or CSS
     nsCOMPtr<nsIDOMElement> divElem = do_QueryInterface(theDiv);
     res = AlignBlock(divElem, alignType, true);
     NS_ENSURE_SUCCESS(res, res);
     *aHandled = true;
     // put in a moz-br so that it won't get deleted
-    res = CreateMozBR(theDiv, 0);
+    res = CreateMozBR(theDiv->AsDOMNode(), 0);
     NS_ENSURE_SUCCESS(res, res);
     res = aSelection->Collapse(theDiv, 0);
     selectionResetter.Abort();  // don't reset our selection in this case.
     return res;
   }
 
   // Next we detect all the transitions in the array, where a transition
   // means that adjacent nodes in the array don't have the same parent.
@@ -4996,21 +4962,18 @@ nsHTMLEditRules::WillAlign(Selection* aS
     // or if this node doesn't go in div we used earlier.
     if (!curDiv || transitionList[i])
     {
       // First, check that our element can contain a div.
       if (!mEditor->CanContainTag(GetAsDOMNode(curParent), nsGkAtoms::div)) {
         return NS_OK; // cancelled
       }
 
-      nsCOMPtr<nsIDOMNode> curParentDOM = GetAsDOMNode(curParent);
-      res = SplitAsNeeded(&NS_LITERAL_STRING("div"), address_of(curParentDOM),
-                          &offset);
+      res = SplitAsNeeded(*nsGkAtoms::div, curParent, offset);
       NS_ENSURE_SUCCESS(res, res);
-      curParent = do_QueryInterface(curParentDOM);
       NS_ENSURE_STATE(mHTMLEditor);
       curDiv = mHTMLEditor->CreateNode(nsGkAtoms::div, curParent, offset);
       NS_ENSURE_STATE(curDiv);
       // remember our new block for postprocessing
       mNewBlock = curDiv->AsDOMNode();
       // set up the alignment on the div
       nsCOMPtr<nsIDOMElement> divElem = do_QueryInterface(curDiv);
       res = AlignBlock(divElem, alignType, true);
@@ -7053,22 +7016,22 @@ nsHTMLEditRules::ReturnInListItem(nsISel
       NS_ENSURE_SUCCESS(res, res);
     } else {
       NS_ENSURE_STATE(mHTMLEditor);
       res = mHTMLEditor->IsEmptyNode(aListItem, &bIsEmptyNode, true);
       NS_ENSURE_SUCCESS(res, res);
       if (bIsEmptyNode) 
       {
         nsCOMPtr<nsIAtom> nodeAtom = nsEditor::GetTag(aListItem);
-        if (nodeAtom == nsEditProperty::dd || nodeAtom == nsEditProperty::dt)
-        {
+        if (nodeAtom == nsGkAtoms::dd || nodeAtom == nsGkAtoms::dt) {
           int32_t itemOffset;
           nsCOMPtr<nsIDOMNode> list = nsEditor::GetNodeLocation(aListItem, &itemOffset);
 
-          nsAutoString listTag((nodeAtom == nsEditProperty::dt) ? NS_LITERAL_STRING("dd") : NS_LITERAL_STRING("dt"));
+          nsAutoString listTag(nodeAtom == nsGkAtoms::dt
+            ? NS_LITERAL_STRING("dd") : NS_LITERAL_STRING("dt"));
           nsCOMPtr<nsIDOMNode> newListItem;
           NS_ENSURE_STATE(mHTMLEditor);
           res = mHTMLEditor->CreateNode(listTag, list, itemOffset+1, getter_AddRefs(newListItem));
           NS_ENSURE_SUCCESS(res, res);
           res = mEditor->DeleteNode(aListItem);
           NS_ENSURE_SUCCESS(res, res);
           return aSelection->Collapse(newListItem, 0);
         }
@@ -7173,21 +7136,18 @@ nsHTMLEditRules::MakeBlockquote(nsCOMArr
 
     {
       curNode->GetParentNode(getter_AddRefs(prevParent));
     }
     
     // if no curBlock, make one
     if (!curBlock)
     {
-      nsCOMPtr<nsIDOMNode> curParentDOM = GetAsDOMNode(curParent);
-      res = SplitAsNeeded(&NS_LITERAL_STRING("blockquote"),
-                          address_of(curParentDOM), &offset);
+      res = SplitAsNeeded(*nsGkAtoms::blockquote, curParent, offset);
       NS_ENSURE_SUCCESS(res, res);
-      curParent = do_QueryInterface(curParentDOM);
       NS_ENSURE_STATE(mHTMLEditor);
       curBlock = mHTMLEditor->CreateNode(nsGkAtoms::blockquote, curParent,
                                          offset);
       NS_ENSURE_STATE(curBlock);
       // remember our new block for postprocessing
       mNewBlock = curBlock->AsDOMNode();
       // note: doesn't matter if we set mNewBlock multiple times.
     }
@@ -7395,27 +7355,24 @@ nsHTMLEditRules::ApplyBlockStyle(nsCOMAr
       if (childCount)
       {
         res = ApplyBlockStyle(childArray, aBlockTag);
         NS_ENSURE_SUCCESS(res, res);
       }
       else
       {
         // make sure we can put a block here
-        nsCOMPtr<nsIDOMNode> curParentDOM = GetAsDOMNode(curParent);
-        res = SplitAsNeeded(aBlockTag, address_of(curParentDOM), &offset);
+        res = SplitAsNeeded(*blockTag, curParent, offset);
         NS_ENSURE_SUCCESS(res, res);
-        curParent = do_QueryInterface(curParentDOM);
-        nsCOMPtr<nsIDOMNode> theBlock;
         NS_ENSURE_STATE(mHTMLEditor);
-        res = mHTMLEditor->CreateNode(*aBlockTag, GetAsDOMNode(curParent),
-                                      offset, getter_AddRefs(theBlock));
-        NS_ENSURE_SUCCESS(res, res);
+        nsCOMPtr<Element> theBlock =
+          mHTMLEditor->CreateNode(blockTag, curParent, offset);
+        NS_ENSURE_STATE(theBlock);
         // remember our new block for postprocessing
-        mNewBlock = theBlock;
+        mNewBlock = theBlock->AsDOMNode();
       }
     }
     
     // if the node is a break, we honor it by putting further nodes in a new parent
     else if (curNodeTag.EqualsLiteral("br"))
     {
       if (curBlock)
       {
@@ -7423,20 +7380,18 @@ nsHTMLEditRules::ApplyBlockStyle(nsCOMAr
         NS_ENSURE_STATE(mHTMLEditor);
         res = mHTMLEditor->DeleteNode(curNode);
         NS_ENSURE_SUCCESS(res, res);
       }
       else
       {
         // the break is the first (or even only) node we encountered.  Create a
         // block for it.
-        nsCOMPtr<nsIDOMNode> curParentDOM = GetAsDOMNode(curParent);
-        res = SplitAsNeeded(aBlockTag, address_of(curParentDOM), &offset);
+        res = SplitAsNeeded(*blockTag, curParent, offset);
         NS_ENSURE_SUCCESS(res, res);
-        curParent = do_QueryInterface(curParentDOM);
         NS_ENSURE_STATE(mHTMLEditor);
         curBlock = mHTMLEditor->CreateNode(blockTag, curParent, offset);
         NS_ENSURE_STATE(curBlock);
         // remember our new block for postprocessing
         mNewBlock = curBlock->AsDOMNode();
         // note: doesn't matter if we set mNewBlock multiple times.
         NS_ENSURE_STATE(mHTMLEditor);
         res = mHTMLEditor->MoveNode(curNode, curBlock, -1);
@@ -7456,20 +7411,18 @@ nsHTMLEditRules::ApplyBlockStyle(nsCOMAr
       NS_ENSURE_STATE(mHTMLEditor);
       if (tString.LowerCaseEqualsLiteral("pre") 
         && (!mHTMLEditor->IsEditable(curNode)))
         continue; // do nothing to this block
       
       // if no curBlock, make one
       if (!curBlock)
       {
-        nsCOMPtr<nsIDOMNode> curParentDOM = GetAsDOMNode(curParent);
-        res = SplitAsNeeded(aBlockTag, address_of(curParentDOM), &offset);
+        res = SplitAsNeeded(*blockTag, curParent, offset);
         NS_ENSURE_SUCCESS(res, res);
-        curParent = do_QueryInterface(curParentDOM);
         NS_ENSURE_STATE(mHTMLEditor);
         curBlock = mHTMLEditor->CreateNode(blockTag, curParent, offset);
         NS_ENSURE_STATE(curBlock);
         // remember our new block for postprocessing
         mNewBlock = curBlock->AsDOMNode();
         // note: doesn't matter if we set mNewBlock multiple times.
       }
       
@@ -7482,70 +7435,66 @@ nsHTMLEditRules::ApplyBlockStyle(nsCOMAr
       res = mHTMLEditor->MoveNode(curNode, curBlock, -1);
       NS_ENSURE_SUCCESS(res, res);
     }
   }
   return res;
 }
 
 
-///////////////////////////////////////////////////////////////////////////
-// SplitAsNeeded:  given a tag name, split inOutParent up to the point   
-//                 where we can insert the tag.  Adjust inOutParent and
-//                 inOutOffset to pint to new location for tag.
-nsresult 
-nsHTMLEditRules::SplitAsNeeded(const nsAString *aTag, 
-                               nsCOMPtr<nsIDOMNode> *inOutParent,
-                               int32_t *inOutOffset)
-{
-  NS_ENSURE_TRUE(aTag && inOutParent && inOutOffset, NS_ERROR_NULL_POINTER);
-  NS_ENSURE_TRUE(*inOutParent, NS_ERROR_NULL_POINTER);
-  nsCOMPtr<nsIDOMNode> tagParent, temp, splitNode, parent = *inOutParent;
-  nsresult res = NS_OK;
-  nsCOMPtr<nsIAtom> tagAtom = do_GetAtom(*aTag);
-   
-  // check that we have a place that can legally contain the tag
-  while (!tagParent)
-  {
-    // sniffing up the parent tree until we find 
-    // a legal place for the block
-    if (!parent) break;
+///////////////////////////////////////////////////////////////////////////////
+// SplitAsNeeded: Given a tag name, split inOutParent up to the point where we
+//                can insert the tag.  Adjust inOutParent and inOutOffset to
+//                point to new location for tag.
+nsresult
+nsHTMLEditRules::SplitAsNeeded(nsIAtom& aTag,
+                               nsCOMPtr<nsINode>& inOutParent,
+                               int32_t& inOutOffset)
+{
+  NS_ENSURE_TRUE(inOutParent, NS_ERROR_NULL_POINTER);
+
+  // Check that we have a place that can legally contain the tag
+  nsCOMPtr<nsINode> tagParent, splitNode;
+  for (nsCOMPtr<nsINode> parent = inOutParent; parent;
+       parent = parent->GetParentNode()) {
+    // Sniffing up the parent tree until we find a legal place for the block
+
     // Don't leave the active editing host
     NS_ENSURE_STATE(mHTMLEditor);
     if (!mHTMLEditor->IsDescendantOfEditorRoot(parent)) {
-      nsCOMPtr<nsIContent> parentContent = do_QueryInterface(parent);
-      NS_ENSURE_STATE(mHTMLEditor);
-      if (parentContent != mHTMLEditor->GetActiveEditingHost()) {
-        break;
-      }
-    }
-    NS_ENSURE_STATE(mHTMLEditor);
-    if (mHTMLEditor->CanContainTag(parent, tagAtom)) {
+      NS_ENSURE_STATE(mHTMLEditor);
+      if (parent != mHTMLEditor->GetActiveEditingHost()) {
+        return NS_ERROR_FAILURE;
+      }
+    }
+
+    NS_ENSURE_STATE(mHTMLEditor);
+    if (mHTMLEditor->CanContainTag(parent->AsDOMNode(), &aTag)) {
+      // Success
       tagParent = parent;
       break;
     }
+
     splitNode = parent;
-    parent->GetParentNode(getter_AddRefs(temp));
-    parent = temp;
-  }
-  if (!tagParent)
-  {
-    // could not find a place to build tag!
+  }
+  if (!tagParent) {
+    // Could not find a place to build tag!
     return NS_ERROR_FAILURE;
   }
-  if (splitNode)
-  {
-    // we found a place for block, but above inOutParent.  We need to split nodes.
-    NS_ENSURE_STATE(mHTMLEditor);
-    res = mHTMLEditor->SplitNodeDeep(splitNode, *inOutParent, *inOutOffset, inOutOffset);
+  if (splitNode) {
+    // We found a place for block, but above inOutParent. We need to split.
+    NS_ENSURE_STATE(mHTMLEditor);
+    nsresult res = mHTMLEditor->SplitNodeDeep(splitNode->AsDOMNode(),
+                                              inOutParent->AsDOMNode(),
+                                              inOutOffset, &inOutOffset);
     NS_ENSURE_SUCCESS(res, res);
-    *inOutParent = tagParent;
-  }
-  return res;
-}      
+    inOutParent = tagParent;
+  }
+  return NS_OK;
+}
 
 ///////////////////////////////////////////////////////////////////////////
 // JoinNodesSmart:  join two nodes, doing whatever makes sense for their  
 //                  children (which often means joining them, too).
 //                  aNodeLeft & aNodeRight must be same type of node.
 nsresult 
 nsHTMLEditRules::JoinNodesSmart( nsIDOMNode *aNodeLeft, 
                                  nsIDOMNode *aNodeRight, 
@@ -8933,18 +8882,17 @@ nsHTMLEditRules::RemoveAlignment(nsIDOMN
     {
       tmp = nullptr;
     }
     bool isBlock;
     NS_ENSURE_STATE(mHTMLEditor);
     res = mHTMLEditor->NodeIsBlockStatic(child, &isBlock);
     NS_ENSURE_SUCCESS(res, res);
 
-    if (nsEditor::NodeIsType(child, nsEditProperty::center))
-    {
+    if (nsEditor::NodeIsType(child, nsGkAtoms::center)) {
       // the current node is a CENTER element
       // first remove children's alignment
       res = RemoveAlignment(child, aAlignType, true);
       NS_ENSURE_SUCCESS(res, res);
 
       // we may have to insert BRs in first and last position of element's children
       // if the nodes before/after are not blocks and not BRs
       res = MakeSureElemStartsOrEndsOnCR(child);
@@ -8974,17 +8922,18 @@ nsHTMLEditRules::RemoveAlignment(nsIDOMN
         {
           NS_ENSURE_STATE(mHTMLEditor);
           res = mHTMLEditor->SetAttributeOrEquivalent(curElem, NS_LITERAL_STRING("align"), aAlignType, false); 
         }
         else
         {
           nsAutoString dummyCssValue;
           NS_ENSURE_STATE(mHTMLEditor);
-          res = mHTMLEditor->mHTMLCSSUtils->RemoveCSSInlineStyle(child, nsEditProperty::cssTextAlign, dummyCssValue);
+          res = mHTMLEditor->mHTMLCSSUtils->RemoveCSSInlineStyle(child,
+            nsGkAtoms::textAlign, dummyCssValue);
         }
         NS_ENSURE_SUCCESS(res, res);
       }
       if (!nsHTMLEditUtils::IsTable(child))
       {
         // unless this is a table, look at children
         res = RemoveAlignment(child, aAlignType, true);
         NS_ENSURE_SUCCESS(res, res);
@@ -9120,66 +9069,71 @@ nsresult
 nsHTMLEditRules::RelativeChangeIndentationOfElementNode(nsIDOMNode *aNode, int8_t aRelativeChange)
 {
   NS_ENSURE_ARG_POINTER(aNode);
 
   if (aRelativeChange != 1 && aRelativeChange != -1) {
     return NS_ERROR_ILLEGAL_VALUE;
   }
 
-  nsCOMPtr<nsIDOMElement> element = do_QueryInterface(aNode);
+  nsCOMPtr<Element> element = do_QueryInterface(aNode);
   if (!element) {
     return NS_OK;
   }
 
   NS_ENSURE_STATE(mHTMLEditor);
-  nsIAtom* marginProperty = MarginPropertyAtomForIndent(mHTMLEditor->mHTMLCSSUtils, element);    
+  nsIAtom* marginProperty =
+    MarginPropertyAtomForIndent(mHTMLEditor->mHTMLCSSUtils,
+                                GetAsDOMNode(element));
   nsAutoString value;
   NS_ENSURE_STATE(mHTMLEditor);
   mHTMLEditor->mHTMLCSSUtils->GetSpecifiedProperty(aNode, marginProperty, value);
   float f;
   nsCOMPtr<nsIAtom> unit;
   NS_ENSURE_STATE(mHTMLEditor);
   mHTMLEditor->mHTMLCSSUtils->ParseLength(value, &f, getter_AddRefs(unit));
   if (0 == f) {
     nsAutoString defaultLengthUnit;
     NS_ENSURE_STATE(mHTMLEditor);
     mHTMLEditor->mHTMLCSSUtils->GetDefaultLengthUnit(defaultLengthUnit);
     unit = do_GetAtom(defaultLengthUnit);
   }
-  if      (nsEditProperty::cssInUnit == unit)
+  if        (nsGkAtoms::in == unit) {
             f += NS_EDITOR_INDENT_INCREMENT_IN * aRelativeChange;
-  else if (nsEditProperty::cssCmUnit == unit)
+  } else if (nsGkAtoms::cm == unit) {
             f += NS_EDITOR_INDENT_INCREMENT_CM * aRelativeChange;
-  else if (nsEditProperty::cssMmUnit == unit)
+  } else if (nsGkAtoms::mm == unit) {
             f += NS_EDITOR_INDENT_INCREMENT_MM * aRelativeChange;
-  else if (nsEditProperty::cssPtUnit == unit)
+  } else if (nsGkAtoms::pt == unit) {
             f += NS_EDITOR_INDENT_INCREMENT_PT * aRelativeChange;
-  else if (nsEditProperty::cssPcUnit == unit)
+  } else if (nsGkAtoms::pc == unit) {
             f += NS_EDITOR_INDENT_INCREMENT_PC * aRelativeChange;
-  else if (nsEditProperty::cssEmUnit == unit)
+  } else if (nsGkAtoms::em == unit) {
             f += NS_EDITOR_INDENT_INCREMENT_EM * aRelativeChange;
-  else if (nsEditProperty::cssExUnit == unit)
+  } else if (nsGkAtoms::ex == unit) {
             f += NS_EDITOR_INDENT_INCREMENT_EX * aRelativeChange;
-  else if (nsEditProperty::cssPxUnit == unit)
+  } else if (nsGkAtoms::px == unit) {
             f += NS_EDITOR_INDENT_INCREMENT_PX * aRelativeChange;
-  else if (nsEditProperty::cssPercentUnit == unit)
+  } else if (nsGkAtoms::percentage == unit) {
             f += NS_EDITOR_INDENT_INCREMENT_PERCENT * aRelativeChange;    
+  }
 
   if (0 < f) {
     nsAutoString newValue;
     newValue.AppendFloat(f);
     newValue.Append(nsDependentAtomString(unit));
     NS_ENSURE_STATE(mHTMLEditor);
-    mHTMLEditor->mHTMLCSSUtils->SetCSSProperty(element, marginProperty, newValue, false);
+    mHTMLEditor->mHTMLCSSUtils->SetCSSProperty(*element, *marginProperty,
+                                               newValue);
     return NS_OK;
   }
 
   NS_ENSURE_STATE(mHTMLEditor);
-  mHTMLEditor->mHTMLCSSUtils->RemoveCSSProperty(element, marginProperty, value, false);
+  mHTMLEditor->mHTMLCSSUtils->RemoveCSSProperty(*element, *marginProperty,
+                                                value);
 
   // remove unnecessary DIV blocks:
   // we could skip this section but that would cause a FAIL in
   // editor/libeditor/tests/browserscope/richtext.html, which expects
   // to unapply a CSS "indent" (<div style="margin-left: 40px;">) by
   // removing the DIV container instead of just removing the CSS property.
   nsCOMPtr<dom::Element> node = do_QueryInterface(aNode);
   if (!node || !node->IsHTML(nsGkAtoms::div) ||
@@ -9239,37 +9193,34 @@ nsHTMLEditRules::WillAbsolutePosition(Se
   NS_ENSURE_SUCCESS(res, res);
   
   // use these ranges to contruct a list of nodes to act on.
   nsCOMArray<nsIDOMNode> arrayOfNodes;
   res = GetNodesForOperation(arrayOfRanges, arrayOfNodes,
                              EditAction::setAbsolutePosition);
   NS_ENSURE_SUCCESS(res, res);                                 
                                      
-  NS_NAMED_LITERAL_STRING(divType, "div");
-
-
   // if nothing visible in list, make an empty block
   if (ListIsEmptyLine(arrayOfNodes))
   {
-    nsCOMPtr<nsIDOMNode> parent, thePositionedDiv;
-    int32_t offset;
-    
     // get selection location
-    NS_ENSURE_STATE(mHTMLEditor);
-    res = mHTMLEditor->GetStartNodeAndOffset(aSelection, getter_AddRefs(parent), &offset);
-    NS_ENSURE_SUCCESS(res, res);
+    NS_ENSURE_STATE(aSelection->RangeCount());
+    nsCOMPtr<nsINode> parent = aSelection->GetRangeAt(0)->GetStartParent();
+    int32_t offset = aSelection->GetRangeAt(0)->StartOffset();
+    NS_ENSURE_STATE(parent);
+
     // make sure we can put a block here
-    res = SplitAsNeeded(&divType, address_of(parent), &offset);
+    res = SplitAsNeeded(*nsGkAtoms::div, parent, offset);
     NS_ENSURE_SUCCESS(res, res);
     NS_ENSURE_STATE(mHTMLEditor);
-    res = mHTMLEditor->CreateNode(divType, parent, offset, getter_AddRefs(thePositionedDiv));
-    NS_ENSURE_SUCCESS(res, res);
+    nsCOMPtr<Element> thePositionedDiv =
+      mHTMLEditor->CreateNode(nsGkAtoms::div, parent, offset);
+    NS_ENSURE_STATE(thePositionedDiv);
     // remember our new block for postprocessing
-    mNewBlock = thePositionedDiv;
+    mNewBlock = thePositionedDiv->AsDOMNode();
     // delete anything that was in the list of nodes
     for (int32_t j = arrayOfNodes.Count() - 1; j >= 0; --j) 
     {
       nsCOMPtr<nsIDOMNode> curNode = arrayOfNodes[0];
       NS_ENSURE_STATE(mHTMLEditor);
       res = mHTMLEditor->DeleteNode(curNode);
       NS_ENSURE_SUCCESS(res, res);
       arrayOfNodes.RemoveObjectAt(0);
@@ -9308,24 +9259,19 @@ nsHTMLEditRules::WillAbsolutePosition(Se
       // curNode is still right after it in the same list.
       if (curList)
       {
         NS_ENSURE_STATE(mHTMLEditor);
         sibling = GetAsDOMNode(mHTMLEditor->GetPriorHTMLSibling(curNode));
       }
       
       if (!curList || (sibling && sibling != GetAsDOMNode(curList))) {
-        nsAutoString listTag;
-        curParent->Tag()->ToString(listTag);
-        ToLowerCase(listTag);
         // create a new nested list of correct type
-        nsCOMPtr<nsIDOMNode> curParentDOM = curParent->AsDOMNode();
-        res = SplitAsNeeded(&listTag, address_of(curParentDOM), &offset);
+        res = SplitAsNeeded(*curParent->Tag(), curParent, offset);
         NS_ENSURE_SUCCESS(res, res);
-        curParent = do_QueryInterface(curParentDOM);
         if (!curPositionedDiv) {
           nsCOMPtr<nsINode> curParentParent = curParent->GetParentNode();
           int32_t parentOffset = curParentParent
             ? curParentParent->IndexOf(curParent) : -1;
           NS_ENSURE_STATE(mHTMLEditor);
           curPositionedDiv = mHTMLEditor->CreateNode(nsGkAtoms::div, curParentParent,
                                                      parentOffset);
           mNewBlock = GetAsDOMNode(curPositionedDiv);
@@ -9366,24 +9312,19 @@ nsHTMLEditRules::WillAbsolutePosition(Se
         // curNode is still right after it in the same list.
         if (curList)
         {
           NS_ENSURE_STATE(mHTMLEditor);
           sibling = GetAsDOMNode(mHTMLEditor->GetPriorHTMLSibling(curNode));
         }
          
         if (!curList || (sibling && sibling != GetAsDOMNode(curList))) {
-          nsAutoString listTag;
-          curParent->Tag()->ToString(listTag);
-          ToLowerCase(listTag);
           // create a new nested list of correct type
-          nsCOMPtr<nsIDOMNode> curParentDOM = curParent->AsDOMNode();
-          res = SplitAsNeeded(&listTag, address_of(curParentDOM), &offset);
+          res = SplitAsNeeded(*curParent->Tag(), curParent, offset);
           NS_ENSURE_SUCCESS(res, res);
-          curParent = do_QueryInterface(curParentDOM);
           if (!curPositionedDiv) {
             nsCOMPtr<nsINode> curParentParent = curParent->GetParentNode();
             int32_t parentOffset = curParentParent ?
               curParentParent->IndexOf(curParent) : -1;
             NS_ENSURE_STATE(mHTMLEditor);
             curPositionedDiv = mHTMLEditor->CreateNode(nsGkAtoms::div,
                                                        curParentParent,
                                                        parentOffset);
@@ -9408,20 +9349,18 @@ nsHTMLEditRules::WillAbsolutePosition(Se
         if (!curPositionedDiv) 
         {
           if (curNode->Tag() == nsGkAtoms::div) {
             curPositionedDiv = curNode->AsElement();
             mNewBlock = GetAsDOMNode(curPositionedDiv);
             curList = nullptr;
             continue;
           }
-          nsCOMPtr<nsIDOMNode> curParentDOM = GetAsDOMNode(curParent);
-          res = SplitAsNeeded(&divType, address_of(curParentDOM), &offset);
+          res = SplitAsNeeded(*nsGkAtoms::div, curParent, offset);
           NS_ENSURE_SUCCESS(res, res);
-          curParent = do_QueryInterface(curParentDOM);
           NS_ENSURE_STATE(mHTMLEditor);
           curPositionedDiv = mHTMLEditor->CreateNode(nsGkAtoms::div, curParent,
                                                      offset);
           NS_ENSURE_STATE(curPositionedDiv);
           // remember our new block for postprocessing
           mNewBlock = GetAsDOMNode(curPositionedDiv);
           // curPositionedDiv is now the correct thing to put curNode in
         }
--- a/editor/libeditor/nsHTMLEditRules.h
+++ b/editor/libeditor/nsHTMLEditRules.h
@@ -281,17 +281,18 @@ protected:
   nsresult BustUpInlinesAtBRs(nsIDOMNode *inNode, 
                               nsCOMArray<nsIDOMNode>& outArrayOfNodes);
   nsCOMPtr<nsIDOMNode> GetHighestInlineParent(nsIDOMNode* aNode);
   nsresult MakeTransitionList(nsCOMArray<nsIDOMNode>& inArrayOfNodes, 
                               nsTArray<bool> &inTransitionArray);
   nsresult RemoveBlockStyle(nsCOMArray<nsIDOMNode>& arrayOfNodes);
   nsresult ApplyBlockStyle(nsCOMArray<nsIDOMNode>& arrayOfNodes, const nsAString *aBlockTag);
   nsresult MakeBlockquote(nsCOMArray<nsIDOMNode>& arrayOfNodes);
-  nsresult SplitAsNeeded(const nsAString *aTag, nsCOMPtr<nsIDOMNode> *inOutParent, int32_t *inOutOffset);
+  nsresult SplitAsNeeded(nsIAtom& aTag, nsCOMPtr<nsINode>& inOutParent,
+                         int32_t& inOutOffset);
   nsresult AddTerminatingBR(nsIDOMNode *aBlock);
   nsresult JoinNodesSmart( nsIDOMNode *aNodeLeft, 
                            nsIDOMNode *aNodeRight, 
                            nsCOMPtr<nsIDOMNode> *aOutMergeParent, 
                            int32_t *aOutMergeOffset);
   nsresult GetTopEnclosingMailCite(nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOutCiteNode, bool aPlaintext);
   nsresult PopListItem(nsIDOMNode *aListItem, bool *aOutOfList);
   nsresult RemoveListStructure(nsIDOMNode *aList);
--- a/editor/libeditor/nsHTMLEditUtils.cpp
+++ b/editor/libeditor/nsHTMLEditUtils.cpp
@@ -5,17 +5,16 @@
 
 #include "mozilla/ArrayUtils.h"         // for ArrayLength
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
 #include "mozilla/dom/Element.h"        // for Element, nsINode
 #include "nsAString.h"                  // for nsAString_internal::IsEmpty
 #include "nsCOMPtr.h"                   // for nsCOMPtr, operator==, etc
 #include "nsCaseTreatment.h"
 #include "nsDebug.h"                    // for NS_PRECONDITION, etc
-#include "nsEditProperty.h"             // for nsEditProperty, etc
 #include "nsEditor.h"                   // for nsEditor
 #include "nsError.h"                    // for NS_SUCCEEDED
 #include "nsGkAtoms.h"                  // for nsGkAtoms, nsGkAtoms::a, etc
 #include "nsHTMLEditUtils.h"
 #include "nsHTMLTags.h"
 #include "nsIAtom.h"                    // for nsIAtom
 #include "nsIDOMHTMLAnchorElement.h"    // for nsIDOMHTMLAnchorElement
 #include "nsIDOMNode.h"                 // for nsIDOMNode
@@ -26,17 +25,17 @@
 
 using namespace mozilla;
 
 ///////////////////////////////////////////////////////////////////////////
 //                  
 bool 
 nsHTMLEditUtils::IsBig(nsIDOMNode* aNode)
 {
-  return nsEditor::NodeIsType(aNode, nsEditProperty::big);
+  return nsEditor::NodeIsType(aNode, nsGkAtoms::big);
 }
 
 
 ///////////////////////////////////////////////////////////////////////////
 // IsInlineStyle true if node is an inline style
 //                  
 bool 
 nsHTMLEditUtils::IsInlineStyle(nsIDOMNode* aNode)
@@ -46,27 +45,27 @@ nsHTMLEditUtils::IsInlineStyle(nsIDOMNod
   return node && IsInlineStyle(node);
 }
 
 bool
 nsHTMLEditUtils::IsInlineStyle(nsINode* aNode)
 {
   MOZ_ASSERT(aNode);
   nsIAtom* nodeAtom = aNode->Tag();
-  return (nodeAtom == nsEditProperty::b)
-      || (nodeAtom == nsEditProperty::i)
-      || (nodeAtom == nsEditProperty::u)
-      || (nodeAtom == nsEditProperty::tt)
-      || (nodeAtom == nsEditProperty::s)
-      || (nodeAtom == nsEditProperty::strike)
-      || (nodeAtom == nsEditProperty::big)
-      || (nodeAtom == nsEditProperty::small)
-      || (nodeAtom == nsEditProperty::sub)
-      || (nodeAtom == nsEditProperty::sup)
-      || (nodeAtom == nsEditProperty::font);
+  return (nodeAtom == nsGkAtoms::b)
+      || (nodeAtom == nsGkAtoms::i)
+      || (nodeAtom == nsGkAtoms::u)
+      || (nodeAtom == nsGkAtoms::tt)
+      || (nodeAtom == nsGkAtoms::s)
+      || (nodeAtom == nsGkAtoms::strike)
+      || (nodeAtom == nsGkAtoms::big)
+      || (nodeAtom == nsGkAtoms::small)
+      || (nodeAtom == nsGkAtoms::sub)
+      || (nodeAtom == nsGkAtoms::sup)
+      || (nodeAtom == nsGkAtoms::font);
 }
 
 ///////////////////////////////////////////////////////////////////////////
 // IsFormatNode true if node is a format node
 // 
 bool
 nsHTMLEditUtils::IsFormatNode(nsIDOMNode* aNode)
 {
@@ -75,91 +74,91 @@ nsHTMLEditUtils::IsFormatNode(nsIDOMNode
   return node && IsFormatNode(node);
 }
 
 bool
 nsHTMLEditUtils::IsFormatNode(nsINode* aNode)
 {
   MOZ_ASSERT(aNode);
   nsIAtom* nodeAtom = aNode->Tag();
-  return (nodeAtom == nsEditProperty::p)
-      || (nodeAtom == nsEditProperty::pre)
-      || (nodeAtom == nsEditProperty::h1)
-      || (nodeAtom == nsEditProperty::h2)
-      || (nodeAtom == nsEditProperty::h3)
-      || (nodeAtom == nsEditProperty::h4)
-      || (nodeAtom == nsEditProperty::h5)
-      || (nodeAtom == nsEditProperty::h6)
-      || (nodeAtom == nsEditProperty::address);
+  return (nodeAtom == nsGkAtoms::p)
+      || (nodeAtom == nsGkAtoms::pre)
+      || (nodeAtom == nsGkAtoms::h1)
+      || (nodeAtom == nsGkAtoms::h2)
+      || (nodeAtom == nsGkAtoms::h3)
+      || (nodeAtom == nsGkAtoms::h4)
+      || (nodeAtom == nsGkAtoms::h5)
+      || (nodeAtom == nsGkAtoms::h6)
+      || (nodeAtom == nsGkAtoms::address);
 }
 
 ///////////////////////////////////////////////////////////////////////////
 // IsNodeThatCanOutdent true if node is a list, list item, or blockquote      
 //
 bool
 nsHTMLEditUtils::IsNodeThatCanOutdent(nsIDOMNode* aNode)
 {
   NS_PRECONDITION(aNode, "null parent passed to nsHTMLEditUtils::IsNodeThatCanOutdent");
   nsCOMPtr<nsIAtom> nodeAtom = nsEditor::GetTag(aNode);
-  return (nodeAtom == nsEditProperty::ul)
-      || (nodeAtom == nsEditProperty::ol)
-      || (nodeAtom == nsEditProperty::dl)
-      || (nodeAtom == nsEditProperty::li)
-      || (nodeAtom == nsEditProperty::dd)
-      || (nodeAtom == nsEditProperty::dt)
-      || (nodeAtom == nsEditProperty::blockquote);
+  return (nodeAtom == nsGkAtoms::ul)
+      || (nodeAtom == nsGkAtoms::ol)
+      || (nodeAtom == nsGkAtoms::dl)
+      || (nodeAtom == nsGkAtoms::li)
+      || (nodeAtom == nsGkAtoms::dd)
+      || (nodeAtom == nsGkAtoms::dt)
+      || (nodeAtom == nsGkAtoms::blockquote);
 }
 
 ///////////////////////////////////////////////////////////////////////////
 //                  
 bool 
 nsHTMLEditUtils::IsSmall(nsIDOMNode* aNode)
 {
-  return nsEditor::NodeIsType(aNode, nsEditProperty::small);
+  return nsEditor::NodeIsType(aNode, nsGkAtoms::small);
 }
 
 
 /********************************************************
  *  helper methods from nsHTMLEditRules
  ********************************************************/
  
 ///////////////////////////////////////////////////////////////////////////
 // IsHeader: true if node an html header
 //                  
 bool 
 nsHTMLEditUtils::IsHeader(nsIDOMNode* aNode)
 {
   NS_PRECONDITION(aNode, "null parent passed to nsHTMLEditUtils::IsHeader");
   nsCOMPtr<nsIAtom> nodeAtom = nsEditor::GetTag(aNode);
-  return (nodeAtom == nsEditProperty::h1)
-      || (nodeAtom == nsEditProperty::h2)
-      || (nodeAtom == nsEditProperty::h3)
-      || (nodeAtom == nsEditProperty::h4)
-      || (nodeAtom == nsEditProperty::h5)
-      || (nodeAtom == nsEditProperty::h6);
+  return (nodeAtom == nsGkAtoms::h1)
+      || (nodeAtom == nsGkAtoms::h2)
+      || (nodeAtom == nsGkAtoms::h3)
+      || (nodeAtom == nsGkAtoms::h4)
+      || (nodeAtom == nsGkAtoms::h5)
+      || (nodeAtom == nsGkAtoms::h6);
 }
 
 
 ///////////////////////////////////////////////////////////////////////////
 // IsParagraph: true if node an html paragraph
 //                  
 bool 
 nsHTMLEditUtils::IsParagraph(nsIDOMNode* aNode)
 {
-  return nsEditor::NodeIsType(aNode, nsEditProperty::p);
+  return nsEditor::NodeIsType(aNode, nsGkAtoms::p);
 }
 
 
 ///////////////////////////////////////////////////////////////////////////
 // IsHR: true if node an horizontal rule
 //                  
 bool 
 nsHTMLEditUtils::IsHR(nsIDOMNode* aNode)
 {
-  return nsEditor::NodeIsType(aNode, nsEditProperty::hr);
+  return nsEditor::NodeIsType(aNode, nsGkAtoms::hr);
 }
 
 
 ///////////////////////////////////////////////////////////////////////////
 // IsListItem: true if node an html list item
 //                  
 bool 
 nsHTMLEditUtils::IsListItem(nsIDOMNode* aNode)
@@ -169,19 +168,19 @@ nsHTMLEditUtils::IsListItem(nsIDOMNode* 
   return node && IsListItem(node);
 }
 
 bool
 nsHTMLEditUtils::IsListItem(nsINode* node)
 {
   MOZ_ASSERT(node);
   nsCOMPtr<nsIAtom> nodeAtom = node->Tag();
-  return (nodeAtom == nsEditProperty::li)
-      || (nodeAtom == nsEditProperty::dd)
-      || (nodeAtom == nsEditProperty::dt);
+  return (nodeAtom == nsGkAtoms::li)
+      || (nodeAtom == nsGkAtoms::dd)
+      || (nodeAtom == nsGkAtoms::dt);
 }
 
 
 ///////////////////////////////////////////////////////////////////////////
 // IsTableElement: true if node an html table, td, tr, ...
 //                  
 bool
 nsHTMLEditUtils::IsTableElement(nsIDOMNode* aNode)
@@ -191,24 +190,24 @@ nsHTMLEditUtils::IsTableElement(nsIDOMNo
   return node && IsTableElement(node);
 }
 
 bool
 nsHTMLEditUtils::IsTableElement(nsINode* node)
 {
   MOZ_ASSERT(node);
   nsCOMPtr<nsIAtom> nodeAtom = node->Tag();
-  return (nodeAtom == nsEditProperty::table)
-      || (nodeAtom == nsEditProperty::tr)
-      || (nodeAtom == nsEditProperty::td)
-      || (nodeAtom == nsEditProperty::th)
-      || (nodeAtom == nsEditProperty::thead)
-      || (nodeAtom == nsEditProperty::tfoot)
-      || (nodeAtom == nsEditProperty::tbody)
-      || (nodeAtom == nsEditProperty::caption);
+  return (nodeAtom == nsGkAtoms::table)
+      || (nodeAtom == nsGkAtoms::tr)
+      || (nodeAtom == nsGkAtoms::td)
+      || (nodeAtom == nsGkAtoms::th)
+      || (nodeAtom == nsGkAtoms::thead)
+      || (nodeAtom == nsGkAtoms::tfoot)
+      || (nodeAtom == nsGkAtoms::tbody)
+      || (nodeAtom == nsGkAtoms::caption);
 }
 
 ///////////////////////////////////////////////////////////////////////////
 // IsTableElementButNotTable: true if node an html td, tr, ... (doesn't include table)
 //                  
 bool 
 nsHTMLEditUtils::IsTableElementButNotTable(nsIDOMNode* aNode)
 {
@@ -217,47 +216,47 @@ nsHTMLEditUtils::IsTableElementButNotTab
   return node && IsTableElementButNotTable(node);
 }
 
 bool
 nsHTMLEditUtils::IsTableElementButNotTable(nsINode* aNode)
 {
   MOZ_ASSERT(aNode);
   nsCOMPtr<nsIAtom> nodeAtom = aNode->Tag();
-  return (nodeAtom == nsEditProperty::tr)
-      || (nodeAtom == nsEditProperty::td)
-      || (nodeAtom == nsEditProperty::th)
-      || (nodeAtom == nsEditProperty::thead)
-      || (nodeAtom == nsEditProperty::tfoot)
-      || (nodeAtom == nsEditProperty::tbody)
-      || (nodeAtom == nsEditProperty::caption);
+  return (nodeAtom == nsGkAtoms::tr)
+      || (nodeAtom == nsGkAtoms::td)
+      || (nodeAtom == nsGkAtoms::th)
+      || (nodeAtom == nsGkAtoms::thead)
+      || (nodeAtom == nsGkAtoms::tfoot)
+      || (nodeAtom == nsGkAtoms::tbody)
+      || (nodeAtom == nsGkAtoms::caption);
 }
 
 ///////////////////////////////////////////////////////////////////////////
 // IsTable: true if node an html table
 //                  
 bool
 nsHTMLEditUtils::IsTable(nsIDOMNode* aNode)
 {
-  return nsEditor::NodeIsType(aNode, nsEditProperty::table);
+  return nsEditor::NodeIsType(aNode, nsGkAtoms::table);
 }
 
 bool
 nsHTMLEditUtils::IsTable(nsINode* aNode)
 {
   return aNode && aNode->IsElement() && aNode->Tag() == nsGkAtoms::table;
 }
 
 ///////////////////////////////////////////////////////////////////////////
 // IsTableRow: true if node an html tr
 //                  
 bool 
 nsHTMLEditUtils::IsTableRow(nsIDOMNode* aNode)
 {
-  return nsEditor::NodeIsType(aNode, nsEditProperty::tr);
+  return nsEditor::NodeIsType(aNode, nsGkAtoms::tr);
 }
 
 
 ///////////////////////////////////////////////////////////////////////////
 // IsTableCell: true if node an html td or th
 //                  
 bool 
 nsHTMLEditUtils::IsTableCell(nsIDOMNode* aNode)
@@ -267,32 +266,32 @@ nsHTMLEditUtils::IsTableCell(nsIDOMNode*
   return node && IsTableCell(node);
 }
 
 bool
 nsHTMLEditUtils::IsTableCell(nsINode* node)
 {
   MOZ_ASSERT(node);
   nsCOMPtr<nsIAtom> nodeAtom = node->Tag();
-  return (nodeAtom == nsEditProperty::td)
-      || (nodeAtom == nsEditProperty::th);
+  return (nodeAtom == nsGkAtoms::td)
+      || (nodeAtom == nsGkAtoms::th);
 }
 
 
 ///////////////////////////////////////////////////////////////////////////
 // IsTableCell: true if node an html td or th
 //                  
 bool 
 nsHTMLEditUtils::IsTableCellOrCaption(nsIDOMNode* aNode)
 {
   NS_PRECONDITION(aNode, "null parent passed to nsHTMLEditUtils::IsTableCell");
   nsCOMPtr<nsIAtom> nodeAtom = nsEditor::GetTag(aNode);
-  return (nodeAtom == nsEditProperty::td)
-      || (nodeAtom == nsEditProperty::th)
-      || (nodeAtom == nsEditProperty::caption);
+  return (nodeAtom == nsGkAtoms::td)
+      || (nodeAtom == nsGkAtoms::th)
+      || (nodeAtom == nsGkAtoms::caption);
 }
 
 
 ///////////////////////////////////////////////////////////////////////////
 // IsList: true if node an html list
 //                  
 bool
 nsHTMLEditUtils::IsList(nsIDOMNode* aNode)
@@ -302,69 +301,69 @@ nsHTMLEditUtils::IsList(nsIDOMNode* aNod
   return node && IsList(node);
 }
 
 bool
 nsHTMLEditUtils::IsList(nsINode* node)
 {
   MOZ_ASSERT(node);
   nsCOMPtr<nsIAtom> nodeAtom = node->Tag();
-  return (nodeAtom == nsEditProperty::ul)
-      || (nodeAtom == nsEditProperty::ol)
-      || (nodeAtom == nsEditProperty::dl);
+  return (nodeAtom == nsGkAtoms::ul)
+      || (nodeAtom == nsGkAtoms::ol)
+      || (nodeAtom == nsGkAtoms::dl);
 }
 
 
 ///////////////////////////////////////////////////////////////////////////
 // IsOrderedList: true if node an html ordered list
 //                  
 bool 
 nsHTMLEditUtils::IsOrderedList(nsIDOMNode* aNode)
 {
-  return nsEditor::NodeIsType(aNode, nsEditProperty::ol);
+  return nsEditor::NodeIsType(aNode, nsGkAtoms::ol);
 }
 
 
 ///////////////////////////////////////////////////////////////////////////
 // IsUnorderedList: true if node an html unordered list
 //                  
 bool 
 nsHTMLEditUtils::IsUnorderedList(nsIDOMNode* aNode)
 {
-  return nsEditor::NodeIsType(aNode, nsEditProperty::ul);
+  return nsEditor::NodeIsType(aNode, nsGkAtoms::ul);
 }
 
 
 ///////////////////////////////////////////////////////////////////////////
 // IsBlockquote: true if node an html blockquote node
 //                  
 bool 
 nsHTMLEditUtils::IsBlockquote(nsIDOMNode* aNode)
 {
-  return nsEditor::NodeIsType(aNode, nsEditProperty::blockquote);
+  return nsEditor::NodeIsType(aNode, nsGkAtoms::blockquote);
 }
 
 
 ///////////////////////////////////////////////////////////////////////////
 // IsPre: true if node an html pre node
 //                  
 bool 
 nsHTMLEditUtils::IsPre(nsIDOMNode* aNode)
 {
-  return nsEditor::NodeIsType(aNode, nsEditProperty::pre);
+  return nsEditor::NodeIsType(aNode, nsGkAtoms::pre);
 }
 
 
 ///////////////////////////////////////////////////////////////////////////
 // IsImage: true if node an html image node
 //                  
 bool 
 nsHTMLEditUtils::IsImage(nsIDOMNode* aNode)
 {
-  return nsEditor::NodeIsType(aNode, nsEditProperty::img);
+  return nsEditor::NodeIsType(aNode, nsGkAtoms::img);
 }
 
 bool 
 nsHTMLEditUtils::IsLink(nsIDOMNode *aNode)
 {
   nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
   return node && IsLink(node);
 }
@@ -407,17 +406,17 @@ nsHTMLEditUtils::IsNamedAnchor(nsINode* 
 
 
 ///////////////////////////////////////////////////////////////////////////
 // IsDiv: true if node an html div node
 //                  
 bool 
 nsHTMLEditUtils::IsDiv(nsIDOMNode* aNode)
 {
-  return nsEditor::NodeIsType(aNode, nsEditProperty::div);
+  return nsEditor::NodeIsType(aNode, nsGkAtoms::div);
 }
 
 
 ///////////////////////////////////////////////////////////////////////////
 // IsMozDiv: true if node an html div node with type = _moz
 //                  
 bool 
 nsHTMLEditUtils::IsMozDiv(nsIDOMNode* aNode)
@@ -482,47 +481,47 @@ nsHTMLEditUtils::IsFormWidget(nsIDOMNode
   return node && IsFormWidget(node);
 }
 
 bool
 nsHTMLEditUtils::IsFormWidget(nsINode* aNode)
 {
   MOZ_ASSERT(aNode);
   nsCOMPtr<nsIAtom> nodeAtom = aNode->Tag();
-  return (nodeAtom == nsEditProperty::textarea)
-      || (nodeAtom == nsEditProperty::select)
-      || (nodeAtom == nsEditProperty::button)
-      || (nodeAtom == nsEditProperty::output)
-      || (nodeAtom == nsEditProperty::keygen)
-      || (nodeAtom == nsEditProperty::progress)
-      || (nodeAtom == nsEditProperty::meter)
-      || (nodeAtom == nsEditProperty::input);
+  return (nodeAtom == nsGkAtoms::textarea)
+      || (nodeAtom == nsGkAtoms::select)
+      || (nodeAtom == nsGkAtoms::button)
+      || (nodeAtom == nsGkAtoms::output)
+      || (nodeAtom == nsGkAtoms::keygen)
+      || (nodeAtom == nsGkAtoms::progress)
+      || (nodeAtom == nsGkAtoms::meter)
+      || (nodeAtom == nsGkAtoms::input);
 }
 
 bool
 nsHTMLEditUtils::SupportsAlignAttr(nsIDOMNode* aNode)
 {
   NS_PRECONDITION(aNode, "null node passed to nsHTMLEditUtils::SupportsAlignAttr");
   nsCOMPtr<nsIAtom> nodeAtom = nsEditor::GetTag(aNode);
-  return (nodeAtom == nsEditProperty::hr)
-      || (nodeAtom == nsEditProperty::table)
-      || (nodeAtom == nsEditProperty::tbody)
-      || (nodeAtom == nsEditProperty::tfoot)
-      || (nodeAtom == nsEditProperty::thead)
-      || (nodeAtom == nsEditProperty::tr)
-      || (nodeAtom == nsEditProperty::td)
-      || (nodeAtom == nsEditProperty::th)
-      || (nodeAtom == nsEditProperty::div)
-      || (nodeAtom == nsEditProperty::p)
-      || (nodeAtom == nsEditProperty::h1)
-      || (nodeAtom == nsEditProperty::h2)
-      || (nodeAtom == nsEditProperty::h3)
-      || (nodeAtom == nsEditProperty::h4)
-      || (nodeAtom == nsEditProperty::h5)
-      || (nodeAtom == nsEditProperty::h6);
+  return (nodeAtom == nsGkAtoms::hr)
+      || (nodeAtom == nsGkAtoms::table)
+      || (nodeAtom == nsGkAtoms::tbody)
+      || (nodeAtom == nsGkAtoms::tfoot)
+      || (nodeAtom == nsGkAtoms::thead)
+      || (nodeAtom == nsGkAtoms::tr)
+      || (nodeAtom == nsGkAtoms::td)
+      || (nodeAtom == nsGkAtoms::th)
+      || (nodeAtom == nsGkAtoms::div)
+      || (nodeAtom == nsGkAtoms::p)
+      || (nodeAtom == nsGkAtoms::h1)
+      || (nodeAtom == nsGkAtoms::h2)
+      || (nodeAtom == nsGkAtoms::h3)
+      || (nodeAtom == nsGkAtoms::h4)
+      || (nodeAtom == nsGkAtoms::h5)
+      || (nodeAtom == nsGkAtoms::h6);
 }
 
 // We use bitmasks to test containment of elements. Elements are marked to be
 // in certain groups by setting the mGroup member of the nsElementInfo struct
 // to the corresponding GROUP_ values (OR'ed together). Similarly, elements are
 // marked to allow containment of certain groups by setting the
 // mCanContainGroups member of the nsElementInfo struct to the corresponding
 // GROUP_ values (OR'ed together).
--- a/editor/libeditor/nsHTMLEditor.cpp
+++ b/editor/libeditor/nsHTMLEditor.cpp
@@ -703,41 +703,40 @@ nsHTMLEditor::HandleKeyPressEvent(nsIDOM
   return TypedText(str, eTypedText);
 }
 
 static void
 AssertParserServiceIsCorrect(nsIAtom* aTag, bool aIsBlock)
 {
 #ifdef DEBUG
   // Check this against what we would have said with the old code:
-  if (aTag==nsEditProperty::p          ||
-      aTag==nsEditProperty::div        ||
-      aTag==nsEditProperty::blockquote ||
-      aTag==nsEditProperty::h1         ||
-      aTag==nsEditProperty::h2         ||
-      aTag==nsEditProperty::h3         ||
-      aTag==nsEditProperty::h4         ||
-      aTag==nsEditProperty::h5         ||
-      aTag==nsEditProperty::h6         ||
-      aTag==nsEditProperty::ul         ||
-      aTag==nsEditProperty::ol         ||
-      aTag==nsEditProperty::dl         ||
-      aTag==nsEditProperty::noscript   ||
-      aTag==nsEditProperty::form       ||
-      aTag==nsEditProperty::hr         ||
-      aTag==nsEditProperty::table      ||
-      aTag==nsEditProperty::fieldset   ||
-      aTag==nsEditProperty::address    ||
-      aTag==nsEditProperty::col        ||
-      aTag==nsEditProperty::colgroup   ||
-      aTag==nsEditProperty::li         ||
-      aTag==nsEditProperty::dt         ||
-      aTag==nsEditProperty::dd         ||
-      aTag==nsEditProperty::legend     )
-  {
+  if (aTag == nsGkAtoms::p ||
+      aTag == nsGkAtoms::div ||
+      aTag == nsGkAtoms::blockquote ||
+      aTag == nsGkAtoms::h1 ||
+      aTag == nsGkAtoms::h2 ||
+      aTag == nsGkAtoms::h3 ||
+      aTag == nsGkAtoms::h4 ||
+      aTag == nsGkAtoms::h5 ||
+      aTag == nsGkAtoms::h6 ||
+      aTag == nsGkAtoms::ul ||
+      aTag == nsGkAtoms::ol ||
+      aTag == nsGkAtoms::dl ||
+      aTag == nsGkAtoms::noscript ||
+      aTag == nsGkAtoms::form ||
+      aTag == nsGkAtoms::hr ||
+      aTag == nsGkAtoms::table ||
+      aTag == nsGkAtoms::fieldset ||
+      aTag == nsGkAtoms::address ||
+      aTag == nsGkAtoms::col ||
+      aTag == nsGkAtoms::colgroup ||
+      aTag == nsGkAtoms::li ||
+      aTag == nsGkAtoms::dt ||
+      aTag == nsGkAtoms::dd ||
+      aTag == nsGkAtoms::legend) {
     if (!aIsBlock) {
       nsAutoString assertmsg (NS_LITERAL_STRING("Parser and editor disagree on blockness: "));
 
       nsAutoString tagName;
       aTag->ToString(tagName);
       assertmsg.Append(tagName);
       char* assertstr = ToNewCString(assertmsg);
       NS_ASSERTION(aIsBlock, assertstr);
@@ -756,29 +755,28 @@ nsHTMLEditor::NodeIsBlockStatic(const do
 {
   MOZ_ASSERT(aElement);
 
   nsIAtom* tagAtom = aElement->Tag();
   MOZ_ASSERT(tagAtom);
 
   // Nodes we know we want to treat as block
   // even though the parser says they're not:
-  if (tagAtom==nsEditProperty::body       ||
-      tagAtom==nsEditProperty::head       ||
-      tagAtom==nsEditProperty::tbody      ||
-      tagAtom==nsEditProperty::thead      ||
-      tagAtom==nsEditProperty::tfoot      ||
-      tagAtom==nsEditProperty::tr         ||
-      tagAtom==nsEditProperty::th         ||
-      tagAtom==nsEditProperty::td         ||
-      tagAtom==nsEditProperty::li         ||
-      tagAtom==nsEditProperty::dt         ||
-      tagAtom==nsEditProperty::dd         ||
-      tagAtom==nsEditProperty::pre)
-  {
+  if (tagAtom == nsGkAtoms::body ||
+      tagAtom == nsGkAtoms::head ||
+      tagAtom == nsGkAtoms::tbody ||
+      tagAtom == nsGkAtoms::thead ||
+      tagAtom == nsGkAtoms::tfoot ||
+      tagAtom == nsGkAtoms::tr ||
+      tagAtom == nsGkAtoms::th ||
+      tagAtom == nsGkAtoms::td ||
+      tagAtom == nsGkAtoms::li ||
+      tagAtom == nsGkAtoms::dt ||
+      tagAtom == nsGkAtoms::dd ||
+      tagAtom == nsGkAtoms::pre) {
     return true;
   }
 
   bool isBlock;
 #ifdef DEBUG
   // XXX we can't use DebugOnly here because VC++ is stupid (bug 802884)
   nsresult rv =
 #endif
@@ -1792,17 +1790,17 @@ nsHTMLEditor::GetCSSBackgroundColorState
       NS_ENSURE_TRUE(blockParent, NS_OK);
     }
 
     // Make sure to not walk off onto the Document node
     nsCOMPtr<nsIDOMElement> element;
     do {
       // retrieve the computed style of background-color for blockParent
       mHTMLCSSUtils->GetComputedProperty(blockParent,
-                                         nsEditProperty::cssBackgroundColor,
+                                         nsGkAtoms::backgroundColor,
                                          aOutColor);
       tmp.swap(blockParent);
       res = tmp->GetParentNode(getter_AddRefs(blockParent));
       element = do_QueryInterface(blockParent);
       // look at parent if the queried color is transparent and if the node to
       // examine is not the root of the document
     } while (aOutColor.EqualsLiteral("transparent") && element);
     if (aOutColor.EqualsLiteral("transparent")) {
@@ -1827,18 +1825,19 @@ nsHTMLEditor::GetCSSBackgroundColorState
       if (isBlock) {
         // yes it is a block; in that case, the text background color is transparent
         aOutColor.AssignLiteral("transparent");
         break;
       }
       else {
         // no, it's not; let's retrieve the computed style of background-color for the
         // node to examine
-        mHTMLCSSUtils->GetComputedProperty(nodeToExamine, nsEditProperty::cssBackgroundColor,
-                            aOutColor);
+        mHTMLCSSUtils->GetComputedProperty(nodeToExamine,
+                                           nsGkAtoms::backgroundColor,
+                                           aOutColor);
         if (!aOutColor.EqualsLiteral("transparent")) {
           break;
         }
       }
       tmp.swap(nodeToExamine);
       res = tmp->GetParentNode(getter_AddRefs(nodeToExamine));
       NS_ENSURE_SUCCESS(res, res);
     } while ( aOutColor.EqualsLiteral("transparent") && nodeToExamine );
@@ -2676,17 +2675,17 @@ nsHTMLEditor::InsertLinkAroundSelection(
       value.Truncate();
 
       res = attribute->GetName(name);
       NS_ENSURE_SUCCESS(res, res);
 
       res = attribute->GetValue(value);
       NS_ENSURE_SUCCESS(res, res);
 
-      res = SetInlineProperty(nsEditProperty::a, name, value);
+      res = SetInlineProperty(nsGkAtoms::a, name, value);
       NS_ENSURE_SUCCESS(res, res);
     }
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHTMLEditor::SetHTMLBackgroundColor(const nsAString& aColor)
--- a/editor/libeditor/nsHTMLEditor.h
+++ b/editor/libeditor/nsHTMLEditor.h
@@ -17,17 +17,16 @@
 
 #include "nsEditor.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMEventListener.h"
 #include "nsICSSLoaderObserver.h"
 
 #include "nsEditRules.h"
 
-#include "nsEditProperty.h"
 #include "nsHTMLCSSUtils.h"
 
 #include "nsHTMLObjectResizer.h"
 #include "nsIHTMLAbsPosEditor.h"
 #include "nsIHTMLInlineTableEditor.h"
 #include "nsIHTMLObjectResizeListener.h"
 #include "nsIHTMLObjectResizer.h"
 
--- a/editor/libeditor/nsHTMLEditorEventListener.cpp
+++ b/editor/libeditor/nsHTMLEditorEventListener.cpp
@@ -47,18 +47,16 @@ nsHTMLEditorEventListener::GetHTMLEditor
 {
   // mEditor must be nsHTMLEditor or its subclass.
   return static_cast<nsHTMLEditor*>(mEditor);
 }
 
 nsresult
 nsHTMLEditorEventListener::MouseUp(nsIDOMMouseEvent* aMouseEvent)
 {
-  NS_ENSURE_TRUE(aMouseEvent, NS_OK);
-
   nsHTMLEditor* htmlEditor = GetHTMLEditor();
 
   nsCOMPtr<nsIDOMEventTarget> target;
   nsresult rv = aMouseEvent->GetTarget(getter_AddRefs(target));
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ENSURE_TRUE(target, NS_ERROR_NULL_POINTER);
   nsCOMPtr<nsIDOMElement> element = do_QueryInterface(target);
 
@@ -68,18 +66,16 @@ nsHTMLEditorEventListener::MouseUp(nsIDO
   htmlEditor->MouseUp(clientX, clientY, element);
 
   return nsEditorEventListener::MouseUp(aMouseEvent);
 }
 
 nsresult
 nsHTMLEditorEventListener::MouseDown(nsIDOMMouseEvent* aMouseEvent)
 {
-  NS_ENSURE_TRUE(aMouseEvent, NS_OK);
-
   nsHTMLEditor* htmlEditor = GetHTMLEditor();
 
   // Detect only "context menu" click
   // XXX This should be easier to do!
   // But eDOMEvents_contextmenu and NS_CONTEXTMENU is not exposed in any event
   // interface :-(
   int16_t buttonNumber;
   nsresult rv = aMouseEvent->GetButton(&buttonNumber);
@@ -199,18 +195,16 @@ nsHTMLEditorEventListener::MouseDown(nsI
   }
 
   return nsEditorEventListener::MouseDown(aMouseEvent);
 }
 
 nsresult
 nsHTMLEditorEventListener::MouseClick(nsIDOMMouseEvent* aMouseEvent)
 {
-  NS_ENSURE_TRUE(aMouseEvent, NS_OK);
-
   nsCOMPtr<nsIDOMEventTarget> target;
   nsresult rv = aMouseEvent->GetTarget(getter_AddRefs(target));
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ENSURE_TRUE(target, NS_ERROR_NULL_POINTER);
   nsCOMPtr<nsIDOMElement> element = do_QueryInterface(target);
 
   GetHTMLEditor()->DoInlineTableEditingAction(element);
 
--- a/editor/libeditor/nsHTMLEditorStyle.cpp
+++ b/editor/libeditor/nsHTMLEditorStyle.cpp
@@ -10,17 +10,16 @@
 #include "nsAString.h"
 #include "nsAttrName.h"
 #include "nsAutoPtr.h"
 #include "nsCOMArray.h"
 #include "nsCOMPtr.h"
 #include "nsCaseTreatment.h"
 #include "nsComponentManagerUtils.h"
 #include "nsDebug.h"
-#include "nsEditProperty.h"
 #include "nsEditRules.h"
 #include "nsEditor.h"
 #include "nsEditorUtils.h"
 #include "nsError.h"
 #include "nsGkAtoms.h"
 #include "nsHTMLCSSUtils.h"
 #include "nsHTMLEditUtils.h"
 #include "nsHTMLEditor.h"
@@ -642,17 +641,17 @@ nsresult nsHTMLEditor::SplitStyleAbovePo
     if (useCSS && mHTMLCSSUtils->IsCSSEditableProperty(tmp, aProperty, aAttribute)) {
       // the HTML style defined by aProperty/aAttribute has a CSS equivalence
       // in this implementation for the node tmp; let's check if it carries those css styles
       nsAutoString firstValue;
       mHTMLCSSUtils->IsCSSEquivalentToHTMLInlineStyleSet(tmp, aProperty,
         aAttribute, isSet, firstValue, nsHTMLCSSUtils::eSpecified);
     }
     if ( (aProperty && NodeIsType(tmp, aProperty)) ||   // node is the correct inline prop
-         (aProperty == nsEditProperty::href && nsHTMLEditUtils::IsLink(tmp)) ||
+         (aProperty == nsGkAtoms::href && nsHTMLEditUtils::IsLink(tmp)) ||
                                                         // node is href - test if really <a href=...
          (!aProperty && NodeIsProperty(tmp)) ||         // or node is any prop, and we asked to split them all
          isSet)                                         // or the style is specified in the style attribute
     {
       // found a style node we need to split
       nsresult rv = SplitNodeDeep(tmp, *aNode, *aOffset, &offset, false,
                                   outLeftNode, outRightNode);
       NS_ENSURE_SUCCESS(rv, rv);
@@ -749,17 +748,19 @@ nsHTMLEditor::ClearStyle(nsCOMPtr<nsIDOM
 }
 
 bool nsHTMLEditor::NodeIsProperty(nsIDOMNode *aNode)
 {
   NS_ENSURE_TRUE(aNode, false);
   if (!IsContainer(aNode))  return false;
   if (!IsEditable(aNode))   return false;
   if (IsBlockNode(aNode))   return false;
-  if (NodeIsType(aNode, nsEditProperty::a)) return false;
+  if (NodeIsType(aNode, nsGkAtoms::a)) {
+    return false;
+  }
   return true;
 }
 
 nsresult nsHTMLEditor::ApplyDefaultProperties()
 {
   nsresult res = NS_OK;
   uint32_t j, defcon = mDefaultStyles.Length();
   for (j=0; j<defcon; j++)
@@ -798,19 +799,19 @@ nsresult nsHTMLEditor::RemoveStyleInside
   }
 
   // then process the node itself
   if (!aChildrenOnly &&
     (
       // node is prop we asked for
       (aProperty && NodeIsType(aNode, aProperty)) ||
       // but check for link (<a href=...)
-      (aProperty == nsEditProperty::href && nsHTMLEditUtils::IsLink(aNode)) ||
+      (aProperty == nsGkAtoms::href && nsHTMLEditUtils::IsLink(aNode)) ||
       // and for named anchors
-      (aProperty == nsEditProperty::name && nsHTMLEditUtils::IsNamedAnchor(aNode)) ||
+      (aProperty == nsGkAtoms::name && nsHTMLEditUtils::IsNamedAnchor(aNode)) ||
       // or node is any prop and we asked for that
       (!aProperty && NodeIsProperty(aNode))
     )
   ) {
     // if we weren't passed an attribute, then we want to 
     // remove any matching inlinestyles entirely
     if (!aAttribute || aAttribute->IsEmpty()) {
       NS_NAMED_LITERAL_STRING(styleAttr, "style");
@@ -869,17 +870,18 @@ nsresult nsHTMLEditor::RemoveStyleInside
       // remove the node if it is a span or font, if its style attribute is
       // empty or absent, and if it does not have a class nor an id
       RemoveElementIfNoStyleOrIdOrClass(aNode);
     }
   }
 
   if (!aChildrenOnly &&
     (
-      (aProperty == nsEditProperty::font) &&    // or node is big or small and we are setting font size
+      // Or node is big or small and we are setting font size
+      aProperty == nsGkAtoms::font &&
       (nsHTMLEditUtils::IsBig(aNode) || nsHTMLEditUtils::IsSmall(aNode)) &&
       (aAttribute && aAttribute->LowerCaseEqualsLiteral("size"))
     )
   ) {
     // if we are setting font size, remove any nested bigs and smalls
     return RemoveContainer(content);
   }
   return NS_OK;
@@ -1335,19 +1337,19 @@ nsresult nsHTMLEditor::RemoveInlinePrope
   nsRefPtr<Selection> selection = GetSelection();
   NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
 
   bool useCSS = IsCSSEnabled();
   if (selection->Collapsed()) {
     // manipulating text attributes on a collapsed selection only sets state for the next text insertion
 
     // For links, aProperty uses "href", use "a" instead
-    if (aProperty == nsEditProperty::href ||
-        aProperty == nsEditProperty::name)
-      aProperty = nsEditProperty::a;
+    if (aProperty == nsGkAtoms::href || aProperty == nsGkAtoms::name) {
+      aProperty = nsGkAtoms::a;
+    }
 
     if (aProperty) {
       mTypeInState->ClearProp(aProperty, *aAttribute);
     } else {
       mTypeInState->ClearAllProps();
     }
     return NS_OK;
   }
@@ -1364,18 +1366,17 @@ nsresult nsHTMLEditor::RemoveInlinePrope
   res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
   NS_ENSURE_SUCCESS(res, res);
   if (!cancel && !handled)
   {
     // loop thru the ranges in the selection
     uint32_t rangeCount = selection->GetRangeCount();
     for (uint32_t rangeIdx = 0; rangeIdx < rangeCount; ++rangeIdx) {
       nsRefPtr<nsRange> range = selection->GetRangeAt(rangeIdx);
-      if (aProperty == nsEditProperty::name)
-      {
+      if (aProperty == nsGkAtoms::name) {
         // promote range if it starts or end in a named anchor and we
         // want to remove named anchors
         res = PromoteRangeIfStartsOrEndsInNamedAnchor(range);
       }
       else {
         // adjust range to include any ancestors who's children are entirely selected
         res = PromoteInlineRange(range);
       }
@@ -1505,18 +1506,21 @@ nsHTMLEditor::RelativeFontChange( int32_
 
   // Get the selection 
   nsRefPtr<Selection> selection = GetSelection();
   NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
   // Is the selection collapsed?
   // if it's collapsed set typing state
   if (selection->Collapsed()) {
     nsCOMPtr<nsIAtom> atom;
-    if (aSizeChange==1) atom = nsEditProperty::big;
-    else                atom = nsEditProperty::small;
+    if (aSizeChange == 1) {
+      atom = nsGkAtoms::big;
+    } else {
+      atom = nsGkAtoms::small;
+    }
 
     // Let's see in what kind of element the selection is
     int32_t offset;
     nsCOMPtr<nsIDOMNode> selectedNode;
     GetStartNodeAndOffset(selection, getter_AddRefs(selectedNode), &offset);
     NS_ENSURE_TRUE(selectedNode, NS_OK);
     if (IsTextNode(selectedNode)) {
       nsCOMPtr<nsIDOMNode> parent;
@@ -1816,33 +1820,35 @@ nsHTMLEditor::GetFontFaceState(bool *aMi
   NS_ENSURE_TRUE(aMixed, NS_ERROR_FAILURE);
   *aMixed = true;
   outFace.Truncate();
 
   nsresult res;
   bool first, any, all;
   
   NS_NAMED_LITERAL_STRING(attr, "face");
-  res = GetInlinePropertyBase(nsEditProperty::font, &attr, nullptr, &first, &any, &all, &outFace);
+  res = GetInlinePropertyBase(nsGkAtoms::font, &attr, nullptr, &first, &any,
+                              &all, &outFace);
   NS_ENSURE_SUCCESS(res, res);
   if (any && !all) return res; // mixed
   if (all)
   {
     *aMixed = false;
     return res;
   }
   
   // if there is no font face, check for tt
-  res = GetInlinePropertyBase(nsEditProperty::tt, nullptr, nullptr, &first, &any, &all,nullptr);
+  res = GetInlinePropertyBase(nsGkAtoms::tt, nullptr, nullptr, &first, &any,
+                              &all,nullptr);
   NS_ENSURE_SUCCESS(res, res);
   if (any && !all) return res; // mixed
   if (all)
   {
     *aMixed = false;
-    nsEditProperty::tt->ToString(outFace);
+    outFace.AssignLiteral("tt");
   }
   
   if (!any)
   {
     // there was no font face attrs of any kind.  We are in normal font.
     outFace.Truncate();
     *aMixed = false;
   }
@@ -1855,17 +1861,18 @@ nsHTMLEditor::GetFontColorState(bool *aM
   NS_ENSURE_TRUE(aMixed, NS_ERROR_NULL_POINTER);
   *aMixed = true;
   aOutColor.Truncate();
   
   nsresult res;
   NS_NAMED_LITERAL_STRING(colorStr, "color");
   bool first, any, all;
   
-  res = GetInlinePropertyBase(nsEditProperty::font, &colorStr, nullptr, &first, &any, &all, &aOutColor);
+  res = GetInlinePropertyBase(nsGkAtoms::font, &colorStr, nullptr, &first,
+                              &any, &all, &aOutColor);
   NS_ENSURE_SUCCESS(res, res);
   if (any && !all) return res; // mixed
   if (all)
   {
     *aMixed = false;
     return res;
   }
   
--- a/editor/libeditor/nsHTMLObjectResizer.cpp
+++ b/editor/libeditor/nsHTMLObjectResizer.cpp
@@ -8,19 +8,19 @@
 #include "mozilla/Preferences.h"
 #include "mozilla/mozalloc.h"
 #include "nsAString.h"
 #include "nsAlgorithm.h"
 #include "nsAutoPtr.h"
 #include "nsCOMArray.h"
 #include "nsCOMPtr.h"
 #include "nsDebug.h"
-#include "nsEditProperty.h"
 #include "nsEditorUtils.h"
 #include "nsError.h"
+#include "nsGkAtoms.h"
 #include "nsHTMLCSSUtils.h"
 #include "nsHTMLEditUtils.h"
 #include "nsHTMLEditor.h"
 #include "nsHTMLObjectResizer.h"
 #include "nsIAtom.h"
 #include "nsIContent.h"
 #include "nsID.h"
 #include "nsIDOMDocument.h"
@@ -43,16 +43,17 @@
 #include "nsStringFwd.h"
 #include "nsSubstringTuple.h"
 #include "nscore.h"
 #include <algorithm>
 
 class nsISelection;
 
 using namespace mozilla;
+using namespace mozilla::dom;
 
 class nsHTMLEditUtils;
 
 // ==================================================================
 // DocumentResizeEventListener
 // ==================================================================
 NS_IMPL_ISUPPORTS(DocumentResizeEventListener, nsIDOMEventListener)
 
@@ -244,19 +245,19 @@ nsHTMLEditor::SetAllResizersPosition()
   int32_t h = mResizedObjectHeight;
 
   // now let's place all the resizers around the image
 
   // get the size of resizers
   nsAutoString value;
   float resizerWidth, resizerHeight;
   nsCOMPtr<nsIAtom> dummyUnit;
-  mHTMLCSSUtils->GetComputedProperty(mTopLeftHandle, nsEditProperty::cssWidth, value);
+  mHTMLCSSUtils->GetComputedProperty(mTopLeftHandle, nsGkAtoms::width, value);
   mHTMLCSSUtils->ParseLength(value, &resizerWidth, getter_AddRefs(dummyUnit));
-  mHTMLCSSUtils->GetComputedProperty(mTopLeftHandle, nsEditProperty::cssHeight, value);
+  mHTMLCSSUtils->GetComputedProperty(mTopLeftHandle, nsGkAtoms::height, value);
   mHTMLCSSUtils->ParseLength(value, &resizerHeight, getter_AddRefs(dummyUnit));
 
   int32_t rw  = (int32_t)((resizerWidth + 1) / 2);
   int32_t rh =  (int32_t)((resizerHeight+ 1) / 2);
 
   SetAnonymousElementPosition(x-rw,     y-rh, mTopLeftHandle);
   SetAnonymousElementPosition(x+w/2-rw, y-rh, mTopHandle);
   SetAnonymousElementPosition(x+w-rw-1, y-rh, mTopRightHandle);
@@ -927,85 +928,69 @@ nsHTMLEditor::SetFinalSize(int32_t aX, i
 
   // we want one transaction only from a user's point of view
   nsAutoEditBatch batchIt(this);
 
   NS_NAMED_LITERAL_STRING(widthStr,  "width");
   NS_NAMED_LITERAL_STRING(heightStr, "height");
   
   bool hasAttr = false;
+  nsCOMPtr<Element> resizedObject = do_QueryInterface(mResizedObject);
+  NS_ENSURE_TRUE(resizedObject, );
   if (mResizedObjectIsAbsolutelyPositioned) {
     if (setHeight)
-      mHTMLCSSUtils->SetCSSPropertyPixels(mResizedObject,
-                                          nsEditProperty::cssTop,
-                                          y,
-                                          false);
+      mHTMLCSSUtils->SetCSSPropertyPixels(*resizedObject, *nsGkAtoms::top, y);
     if (setWidth)
-      mHTMLCSSUtils->SetCSSPropertyPixels(mResizedObject,
-                                          nsEditProperty::cssLeft,
-                                          x,
-                                          false);
+      mHTMLCSSUtils->SetCSSPropertyPixels(*resizedObject, *nsGkAtoms::left, x);
   }
   if (IsCSSEnabled() || mResizedObjectIsAbsolutelyPositioned) {
     if (setWidth && NS_SUCCEEDED(mResizedObject->HasAttribute(widthStr, &hasAttr)) && hasAttr)
       RemoveAttribute(mResizedObject, widthStr);
 
     hasAttr = false;
     if (setHeight && NS_SUCCEEDED(mResizedObject->HasAttribute(heightStr, &hasAttr)) && hasAttr)
       RemoveAttribute(mResizedObject, heightStr);
 
     if (setWidth)
-      mHTMLCSSUtils->SetCSSPropertyPixels(mResizedObject,
-                                          nsEditProperty::cssWidth,
-                                          width,
-                                          false);
+      mHTMLCSSUtils->SetCSSPropertyPixels(*resizedObject, *nsGkAtoms::width,
+                                          width);
     if (setHeight)
-      mHTMLCSSUtils->SetCSSPropertyPixels(mResizedObject,
-                                    nsEditProperty::cssHeight,
-                                    height,
-                                    false);
+      mHTMLCSSUtils->SetCSSPropertyPixels(*resizedObject, *nsGkAtoms::height,
+                                          height);
   }
   else {
     // we use HTML size and remove all equivalent CSS properties
 
     // we set the CSS width and height to remove it later,
     // triggering an immediate reflow; otherwise, we have problems
     // with asynchronous reflow
     if (setWidth)
-      mHTMLCSSUtils->SetCSSPropertyPixels(mResizedObject,
-                                          nsEditProperty::cssWidth,
-                                          width,
-                                          false);
+      mHTMLCSSUtils->SetCSSPropertyPixels(*resizedObject, *nsGkAtoms::width,
+                                          width);
     if (setHeight)
-      mHTMLCSSUtils->SetCSSPropertyPixels(mResizedObject,
-                                          nsEditProperty::cssHeight,
-                                          height,
-                                          false);
+      mHTMLCSSUtils->SetCSSPropertyPixels(*resizedObject, *nsGkAtoms::height,
+                                          height);
 
     if (setWidth) {
       nsAutoString w;
       w.AppendInt(width);
       SetAttribute(mResizedObject, widthStr, w);
     }
     if (setHeight) {
       nsAutoString h;
       h.AppendInt(height);
       SetAttribute(mResizedObject, heightStr, h);
     }
 
     if (setWidth)
-      mHTMLCSSUtils->RemoveCSSProperty(mResizedObject,
-                                       nsEditProperty::cssWidth,
-                                       EmptyString(),
-                                       false);
+      mHTMLCSSUtils->RemoveCSSProperty(*resizedObject, *nsGkAtoms::width,
+                                       EmptyString());
     if (setHeight)
-      mHTMLCSSUtils->RemoveCSSProperty(mResizedObject,
-                                      nsEditProperty::cssHeight,
-                                      EmptyString(),
-                                      false);
+      mHTMLCSSUtils->RemoveCSSProperty(*resizedObject, *nsGkAtoms::height,
+                                       EmptyString());
   }
   // finally notify the listeners if any
   int32_t listenersCount = objectResizeEventListeners.Count();
   if (listenersCount) {
     nsCOMPtr<nsIHTMLObjectResizeListener> listener;
     int32_t index;
     for (index = 0; index < listenersCount; index++) {
       listener = objectResizeEventListeners[index];
--- a/editor/libeditor/nsSelectionState.cpp
+++ b/editor/libeditor/nsSelectionState.cpp
@@ -441,56 +441,46 @@ nsRangeUpdater::SelAdjJoinNodes(nsIDOMNo
 {
   nsCOMPtr<nsINode> leftNode = do_QueryInterface(aLeftNode);
   nsCOMPtr<nsINode> rightNode = do_QueryInterface(aRightNode);
   nsCOMPtr<nsINode> parent = do_QueryInterface(aParent);
   return SelAdjJoinNodes(leftNode, rightNode, parent, aOffset, aOldLeftNodeLength);
 }
 
 
-nsresult
-nsRangeUpdater::SelAdjInsertText(nsIContent* aTextNode, int32_t aOffset,
-                                 const nsAString &aString)
+void
+nsRangeUpdater::SelAdjInsertText(Text& aTextNode, int32_t aOffset,
+                                 const nsAString& aString)
 {
   if (mLock) {
     // lock set by Will/DidReplaceParent, etc...
-    return NS_OK;
+    return;
   }
 
   uint32_t count = mArray.Length();
   if (!count) {
-    return NS_OK;
+    return;
   }
-  NS_ENSURE_TRUE(aTextNode, NS_ERROR_NULL_POINTER);
 
   uint32_t len = aString.Length();
   for (uint32_t i = 0; i < count; i++) {
     nsRangeStore* item = mArray[i];
-    NS_ENSURE_TRUE(item, NS_ERROR_NULL_POINTER);
+    MOZ_ASSERT(item);
 
-    if (item->startNode == aTextNode && item->startOffset > aOffset) {
+    if (item->startNode == &aTextNode && item->startOffset > aOffset) {
       item->startOffset += len;
     }
-    if (item->endNode == aTextNode && item->endOffset > aOffset) {
+    if (item->endNode == &aTextNode && item->endOffset > aOffset) {
       item->endOffset += len;
     }
   }
-  return NS_OK;
+  return;
 }
 
 nsresult
-nsRangeUpdater::SelAdjInsertText(nsIDOMCharacterData* aTextNode,
-                                 int32_t aOffset, const nsAString &aString)
-{
-  nsCOMPtr<nsIContent> textNode = do_QueryInterface(aTextNode);
-  return SelAdjInsertText(textNode, aOffset, aString);
-}
-
-
-nsresult
 nsRangeUpdater::SelAdjDeleteText(nsIContent* aTextNode, int32_t aOffset,
                                  int32_t aLength)
 {
   if (mLock) {
     // lock set by Will/DidReplaceParent, etc...
     return NS_OK;
   }
 
--- a/editor/libeditor/nsSelectionState.h
+++ b/editor/libeditor/nsSelectionState.h
@@ -15,16 +15,17 @@
 class nsCycleCollectionTraversalCallback;
 class nsIDOMCharacterData;
 class nsIDOMRange;
 class nsISelection;
 class nsRange;
 namespace mozilla {
 namespace dom {
 class Selection;
+class Text;
 }
 }
 
 /***************************************************************************
  * class for recording selection info.  stores selection as collection of
  * { {startnode, startoffset} , {endnode, endoffset} } tuples.  Can't store
  * ranges since dom gravity will possibly change the ranges.
  */
@@ -103,19 +104,18 @@ class nsRangeUpdater
                              nsINode* aParent,
                              int32_t aOffset,
                              int32_t aOldLeftNodeLength);
     nsresult SelAdjJoinNodes(nsIDOMNode *aLeftNode, 
                              nsIDOMNode *aRightNode, 
                              nsIDOMNode *aParent, 
                              int32_t aOffset,
                              int32_t aOldLeftNodeLength);
-    nsresult SelAdjInsertText(nsIContent* aTextNode, int32_t aOffset,
+    void     SelAdjInsertText(mozilla::dom::Text& aTextNode, int32_t aOffset,
                               const nsAString &aString);
-    nsresult SelAdjInsertText(nsIDOMCharacterData *aTextNode, int32_t aOffset, const nsAString &aString);
     nsresult SelAdjDeleteText(nsIContent* aTextNode, int32_t aOffset,
                               int32_t aLength);
     nsresult SelAdjDeleteText(nsIDOMCharacterData *aTextNode, int32_t aOffset, int32_t aLength);
     // the following gravity routines need will/did sandwiches, because the other gravity
     // routines will be called inside of these sandwiches, but should be ignored.
     nsresult WillReplaceContainer();
     nsresult DidReplaceContainer(mozilla::dom::Element* aOriginalNode,
                                  mozilla::dom::Element* aNewNode);
--- a/editor/libeditor/nsTableEditor.cpp
+++ b/editor/libeditor/nsTableEditor.cpp
@@ -7,17 +7,16 @@
 
 #include "mozilla/Assertions.h"
 #include "mozilla/dom/Selection.h"
 #include "mozilla/dom/Element.h"
 #include "nsAString.h"
 #include "nsAlgorithm.h"
 #include "nsCOMPtr.h"
 #include "nsDebug.h"
-#include "nsEditProperty.h"
 #include "nsEditor.h"
 #include "nsEditorUtils.h"
 #include "nsError.h"
 #include "nsGkAtoms.h"
 #include "nsHTMLEditUtils.h"
 #include "nsHTMLEditor.h"
 #include "nsIAtom.h"
 #include "nsIContent.h"
@@ -235,28 +234,26 @@ nsHTMLEditor::GetFirstRow(nsIDOMElement*
 
   while (tableChild)
   {
     nsCOMPtr<nsIContent> content = do_QueryInterface(tableChild);
     if (content)
     {
       nsIAtom *atom = content->Tag();
 
-      if (atom == nsEditProperty::tr)
-      {
+      if (atom == nsGkAtoms::tr) {
         // Found a row directly under <table>
         *aRowNode = tableChild;
         NS_ADDREF(*aRowNode);
         return NS_OK;
       }
       // Look for row in one of the row container elements      
-      if (atom == nsEditProperty::tbody ||
-          atom == nsEditProperty::thead ||
-          atom == nsEditProperty::tfoot)
-      {
+      if (atom == nsGkAtoms::tbody ||
+          atom == nsGkAtoms::thead ||
+          atom == nsGkAtoms::tfoot) {
         nsCOMPtr<nsIDOMNode> rowNode;
         res = tableChild->GetFirstChild(getter_AddRefs(rowNode));
         NS_ENSURE_SUCCESS(res, res);
         
         // We can encounter textnodes here -- must find a row
         while (rowNode && !nsHTMLEditUtils::IsTableRow(rowNode))
         {
           nsCOMPtr<nsIDOMNode> nextNode;
@@ -1953,18 +1950,17 @@ nsHTMLEditor::SwitchTableCellHeaderType(
   // This is needed so ReplaceContainer can monitor selection
   //  when replacing nodes
   nsRefPtr<Selection> selection = GetSelection();
   NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
   nsAutoSelectionReset selectionResetter(selection, this);
 
   // Set to the opposite of current type
   nsCOMPtr<nsIAtom> atom = nsEditor::GetTag(aSourceCell);
-  nsIAtom* newCellType = atom == nsEditProperty::td
-    ? nsGkAtoms::th : nsGkAtoms::td;
+  nsIAtom* newCellType = atom == nsGkAtoms::td ? nsGkAtoms::th : nsGkAtoms::td;
 
   // This creates new node, moves children, copies attributes (true)
   //   and manages the selection!
   nsCOMPtr<Element> newNode = ReplaceContainer(sourceCell, newCellType,
       nullptr, nullptr, nsEditor::eCloneAttributes);
   NS_ENSURE_TRUE(newNode, NS_ERROR_FAILURE);
 
   // Return the new cell
@@ -3213,33 +3209,28 @@ nsHTMLEditor::GetSelectedOrParentTableEl
         selectedNode = anchorNode;
         // If anchor doesn't have a child, we can't be selecting a table element,
         //  so don't do the following:
       }
       else
       {
         nsCOMPtr<nsIAtom> atom = nsEditor::GetTag(selectedNode);
 
-        if (atom == nsEditProperty::td)
-        {
+        if (atom == nsGkAtoms::td) {
           tableOrCellElement = do_QueryInterface(selectedNode);
           aTagName = tdName;
           // Each cell is in its own selection range,
           //  so count signals multiple-cell selection
           res = selection->GetRangeCount(aSelectedCount);
           NS_ENSURE_SUCCESS(res, res);
-        }
-        else if (atom == nsEditProperty::table)
-        {
+        } else if (atom == nsGkAtoms::table) {
           tableOrCellElement = do_QueryInterface(selectedNode);
           aTagName.AssignLiteral("table");
           *aSelectedCount = 1;
-        }
-        else if (atom == nsEditProperty::tr)
-        {
+        } else if (atom == nsGkAtoms::tr) {
           tableOrCellElement = do_QueryInterface(selectedNode);
           aTagName.AssignLiteral("tr");
           *aSelectedCount = 1;
         }
       }
     }
     if (!tableOrCellElement)
     {
--- a/editor/libeditor/nsWSRunObject.cpp
+++ b/editor/libeditor/nsWSRunObject.cpp
@@ -1501,17 +1501,17 @@ nsWSRunObject::ConvertToNBSP(WSPoint aPo
       return NS_OK;
     }
   }
 
   // First, insert an nbsp
   nsAutoTxnsConserveSelection dontSpazMySelection(mHTMLEditor);
   nsAutoString nbspStr(nbsp);
   nsresult res = mHTMLEditor->InsertTextIntoTextNodeImpl(nbspStr,
-      aPoint.mTextNode, aPoint.mOffset, true);
+      *aPoint.mTextNode, aPoint.mOffset, true);
   NS_ENSURE_SUCCESS(res, res);
 
   // Next, find range of ws it will replace
   nsRefPtr<Text> startNode, endNode;
   int32_t startOffset = 0, endOffset = 0;
 
   GetAsciiWSBounds(eAfter, aPoint.mTextNode, aPoint.mOffset + 1,
                    getter_AddRefs(startNode), &startOffset,
@@ -1816,17 +1816,17 @@ nsWSRunObject::CheckTrailingNBSPOfRun(WS
         rightCheck = true;
       }
     }
     if (leftCheck && rightCheck) {
       // Now replace nbsp with space.  First, insert a space
       nsAutoTxnsConserveSelection dontSpazMySelection(mHTMLEditor);
       nsAutoString spaceStr(char16_t(32));
       res = mHTMLEditor->InsertTextIntoTextNodeImpl(spaceStr,
-                                                    thePoint.mTextNode,
+                                                    *thePoint.mTextNode,
                                                     thePoint.mOffset, true);
       NS_ENSURE_SUCCESS(res, res);
 
       // Finally, delete that nbsp
       res = DeleteChars(thePoint.mTextNode, thePoint.mOffset + 1,
                         thePoint.mTextNode, thePoint.mOffset + 2);
       NS_ENSURE_SUCCESS(res, res);
     } else if (!mPRE && spaceNBSP && rightCheck) {
@@ -1846,17 +1846,17 @@ nsWSRunObject::CheckTrailingNBSPOfRun(WS
       // Delete that nbsp
       res = DeleteChars(thePoint.mTextNode, thePoint.mOffset,
                         thePoint.mTextNode, thePoint.mOffset + 1);
       NS_ENSURE_SUCCESS(res, res);
 
       // Finally, insert that nbsp before the ASCII ws run
       nsAutoTxnsConserveSelection dontSpazMySelection(mHTMLEditor);
       nsAutoString nbspStr(nbsp);
-      res = mHTMLEditor->InsertTextIntoTextNodeImpl(nbspStr, startNode,
+      res = mHTMLEditor->InsertTextIntoTextNodeImpl(nbspStr, *startNode,
                                                     startOffset, true);
       NS_ENSURE_SUCCESS(res, res);
     }
   }
   return NS_OK;
 }
 
 nsresult
@@ -1882,17 +1882,17 @@ nsWSRunObject::CheckTrailingNBSP(WSFragm
       canConvert = true;
     }
   }
   if (canConvert) {
     // First, insert a space
     nsAutoTxnsConserveSelection dontSpazMySelection(mHTMLEditor);
     nsAutoString spaceStr(char16_t(32));
     nsresult res = mHTMLEditor->InsertTextIntoTextNodeImpl(spaceStr,
-        thePoint.mTextNode, thePoint.mOffset, true);
+        *thePoint.mTextNode, thePoint.mOffset, true);
     NS_ENSURE_SUCCESS(res, res);
 
     // Finally, delete that nbsp
     res = DeleteChars(thePoint.mTextNode, thePoint.mOffset + 1,
                       thePoint.mTextNode, thePoint.mOffset + 2);
     NS_ENSURE_SUCCESS(res, res);
   }
   return NS_OK;
@@ -1923,17 +1923,17 @@ nsWSRunObject::CheckLeadingNBSP(WSFragme
       canConvert = true;
     }
   }
   if (canConvert) {
     // First, insert a space
     nsAutoTxnsConserveSelection dontSpazMySelection(mHTMLEditor);
     nsAutoString spaceStr(char16_t(32));
     nsresult res = mHTMLEditor->InsertTextIntoTextNodeImpl(spaceStr,
-        thePoint.mTextNode, thePoint.mOffset, true);
+        *thePoint.mTextNode, thePoint.mOffset, true);
     NS_ENSURE_SUCCESS(res, res);
 
     // Finally, delete that nbsp
     res = DeleteChars(thePoint.mTextNode, thePoint.mOffset + 1,
                       thePoint.mTextNode, thePoint.mOffset + 2);
     NS_ENSURE_SUCCESS(res, res);
   }
   return NS_OK;
--- a/gfx/src/nsCoord.h
+++ b/gfx/src/nsCoord.h
@@ -52,16 +52,24 @@ typedef int32_t nscoord;
 
 inline void VERIFY_COORD(nscoord aCoord) {
 #ifdef NS_COORD_IS_FLOAT
   NS_ASSERTION(floorf(aCoord) == aCoord,
                "Coords cannot have fractions");
 #endif
 }
 
+inline nscoord NSCoordMulDiv(nscoord aMult1, nscoord aMult2, nscoord aDiv) {
+#ifdef NS_COORD_IS_FLOAT
+  return (aMult1 * aMult2 / aDiv);
+#else
+  return (int64_t(aMult1) * int64_t(aMult2) / int64_t(aDiv));
+#endif
+}
+
 inline nscoord NSToCoordRound(float aValue)
 {
 #if defined(XP_WIN32) && defined(_M_IX86) && !defined(__GNUC__) && !defined(__clang__)
   return NS_lroundup30(aValue);
 #else
   return nscoord(floorf(aValue + 0.5f));
 #endif /* XP_WIN32 && _M_IX86 && !__GNUC__ */
 }
--- a/gfx/thebes/gfxDrawable.cpp
+++ b/gfx/thebes/gfxDrawable.cpp
@@ -26,16 +26,17 @@ gfxSurfaceDrawable::gfxSurfaceDrawable(S
 {
 }
 
 bool
 gfxSurfaceDrawable::Draw(gfxContext* aContext,
                          const gfxRect& aFillRect,
                          bool aRepeat,
                          const GraphicsFilter& aFilter,
+                         gfxFloat aOpacity,
                          const gfxMatrix& aTransform)
 {
     ExtendMode extend = ExtendMode::CLAMP;
 
     if (aRepeat) {
         extend = ExtendMode::REPEAT;
     }
 
@@ -45,27 +46,28 @@ gfxSurfaceDrawable::Draw(gfxContext* aCo
     SurfacePattern pattern(mSourceSurface, extend,
                            patternTransform, ToFilter(aFilter));
 
     Rect fillRect = ToRect(aFillRect);
     DrawTarget* dt = aContext->GetDrawTarget();
 
     if (aContext->CurrentOperator() == gfxContext::OPERATOR_CLEAR) {
         dt->ClearRect(fillRect);
-    } else if (aContext->CurrentOperator() == gfxContext::OPERATOR_SOURCE) {
+    } else if (aContext->CurrentOperator() == gfxContext::OPERATOR_SOURCE &&
+               aOpacity == 1.0) {
         // Emulate cairo operator source which is bound by mask!
         dt->ClearRect(fillRect);
         dt->FillRect(fillRect, pattern);
     } else {
         CompositionOp op = CompositionOpForOp(aContext->CurrentOperator());
         AntialiasMode aaMode =
             aContext->CurrentAntialiasMode() == gfxContext::MODE_ALIASED ?
                 AntialiasMode::NONE :
                 AntialiasMode::SUBPIXEL;
-        dt->FillRect(fillRect, pattern, DrawOptions(1.0f, op, aaMode));
+        dt->FillRect(fillRect, pattern, DrawOptions(aOpacity, op, aaMode));
     }
     return true;
 }
 
 gfxCallbackDrawable::gfxCallbackDrawable(gfxDrawingCallback* aCallback,
                                          const gfxIntSize aSize)
  : gfxDrawable(aSize)
  , mCallback(aCallback)
@@ -91,25 +93,26 @@ gfxCallbackDrawable::MakeSurfaceDrawable
     return drawable.forget();
 }
 
 bool
 gfxCallbackDrawable::Draw(gfxContext* aContext,
                           const gfxRect& aFillRect,
                           bool aRepeat,
                           const GraphicsFilter& aFilter,
+                          gfxFloat aOpacity,
                           const gfxMatrix& aTransform)
 {
-    if (aRepeat && !mSurfaceDrawable) {
+    if ((aRepeat || aOpacity != 1.0) && !mSurfaceDrawable) {
         mSurfaceDrawable = MakeSurfaceDrawable(aFilter);
     }
 
     if (mSurfaceDrawable)
         return mSurfaceDrawable->Draw(aContext, aFillRect, aRepeat, aFilter,
-                                      aTransform);
+                                      aOpacity, aTransform);
 
     if (mCallback)
         return (*mCallback)(aContext, aFillRect, aFilter, aTransform);
 
     return false;
 }
 
 gfxPatternDrawable::gfxPatternDrawable(gfxPattern* aPattern,
@@ -132,17 +135,17 @@ public:
 
     virtual ~DrawingCallbackFromDrawable() {}
 
     virtual bool operator()(gfxContext* aContext,
                               const gfxRect& aFillRect,
                               const GraphicsFilter& aFilter,
                               const gfxMatrix& aTransform = gfxMatrix())
     {
-        return mDrawable->Draw(aContext, aFillRect, false, aFilter,
+        return mDrawable->Draw(aContext, aFillRect, false, aFilter, 1.0,
                                aTransform);
     }
 private:
     nsRefPtr<gfxDrawable> mDrawable;
 };
 
 already_AddRefed<gfxCallbackDrawable>
 gfxPatternDrawable::MakeCallbackDrawable()
@@ -154,35 +157,36 @@ gfxPatternDrawable::MakeCallbackDrawable
     return callbackDrawable.forget();
 }
 
 bool
 gfxPatternDrawable::Draw(gfxContext* aContext,
                          const gfxRect& aFillRect,
                          bool aRepeat,
                          const GraphicsFilter& aFilter,
+                         gfxFloat aOpacity,
                          const gfxMatrix& aTransform)
 {
     if (!mPattern)
         return false;
 
     if (aRepeat) {
         // We can't use mPattern directly: We want our repeated tiles to have
         // the size mSize, which might not be the case in mPattern.
         // So we need to draw mPattern into a surface of size mSize, create
         // a pattern from the surface and draw that pattern.
         // gfxCallbackDrawable and gfxSurfaceDrawable already know how to do
         // those things, so we use them here. Drawing mPattern into the surface
         // will happen through this Draw() method with aRepeat = false.
         nsRefPtr<gfxCallbackDrawable> callbackDrawable = MakeCallbackDrawable();
         return callbackDrawable->Draw(aContext, aFillRect, true, aFilter,
-                                      aTransform);
+                                      aOpacity, aTransform);
     }
 
     aContext->NewPath();
     gfxMatrix oldMatrix = mPattern->GetMatrix();
     mPattern->SetMatrix(aTransform * oldMatrix);
     aContext->SetPattern(mPattern);
     aContext->Rectangle(aFillRect);
-    aContext->Fill();
+    aContext->FillWithOpacity(aOpacity);
     mPattern->SetMatrix(oldMatrix);
     return true;
 }
--- a/gfx/thebes/gfxDrawable.h
+++ b/gfx/thebes/gfxDrawable.h
@@ -33,16 +33,17 @@ public:
      * draws using a gfxPattern, this is the matrix that should be set on the
      * pattern prior to rendering it.
      *  @return whether drawing was successful
      */
     virtual bool Draw(gfxContext* aContext,
                         const gfxRect& aFillRect,
                         bool aRepeat,
                         const GraphicsFilter& aFilter,
+                        gfxFloat aOpacity = 1.0,
                         const gfxMatrix& aTransform = gfxMatrix()) = 0;
     virtual gfxIntSize Size() { return mSize; }
 
 protected:
     // Protected destructor, to discourage deletion outside of Release():
     virtual ~gfxDrawable() {}
 
     const gfxIntSize mSize;
@@ -57,16 +58,17 @@ public:
     gfxSurfaceDrawable(mozilla::gfx::SourceSurface* aSurface, const gfxIntSize aSize,
                        const gfxMatrix aTransform = gfxMatrix());
     virtual ~gfxSurfaceDrawable() {}
 
     virtual bool Draw(gfxContext* aContext,
                         const gfxRect& aFillRect,
                         bool aRepeat,
                         const GraphicsFilter& aFilter,
+                        gfxFloat aOpacity = 1.0,
                         const gfxMatrix& aTransform = gfxMatrix());
     
 protected:
     mozilla::RefPtr<mozilla::gfx::SourceSurface> mSourceSurface;
     const gfxMatrix mTransform;
 };
 
 /**
@@ -102,16 +104,17 @@ class gfxCallbackDrawable : public gfxDr
 public:
     gfxCallbackDrawable(gfxDrawingCallback* aCallback, const gfxIntSize aSize);
     virtual ~gfxCallbackDrawable() {}
 
     virtual bool Draw(gfxContext* aContext,
                         const gfxRect& aFillRect,
                         bool aRepeat,
                         const GraphicsFilter& aFilter,
+                        gfxFloat aOpacity = 1.0,
                         const gfxMatrix& aTransform = gfxMatrix());
 
 protected:
     already_AddRefed<gfxSurfaceDrawable> MakeSurfaceDrawable(const GraphicsFilter aFilter = GraphicsFilter::FILTER_FAST);
 
     nsRefPtr<gfxDrawingCallback> mCallback;
     nsRefPtr<gfxSurfaceDrawable> mSurfaceDrawable;
 };
@@ -125,16 +128,17 @@ public:
     gfxPatternDrawable(gfxPattern* aPattern,
                        const gfxIntSize aSize);
     virtual ~gfxPatternDrawable();
 
     virtual bool Draw(gfxContext* aContext,
                         const gfxRect& aFillRect,
                         bool aRepeat,
                         const GraphicsFilter& aFilter,
+                        gfxFloat aOpacity = 1.0,
                         const gfxMatrix& aTransform = gfxMatrix());
 
 protected:
     already_AddRefed<gfxCallbackDrawable> MakeCallbackDrawable();
 
     nsRefPtr<gfxPattern> mPattern;
 };
 
--- a/gfx/thebes/gfxUtils.cpp
+++ b/gfx/thebes/gfxUtils.cpp
@@ -402,17 +402,17 @@ CreateSamplingRestrictedDrawable(gfxDraw
                                                                    aFormat);
     if (!target) {
       return nullptr;
     }
 
     nsRefPtr<gfxContext> tmpCtx = new gfxContext(target);
     tmpCtx->SetOperator(OptimalFillOperator());
     aDrawable->Draw(tmpCtx, needed - needed.TopLeft(), true,
-                    GraphicsFilter::FILTER_FAST, gfxMatrix().Translate(needed.TopLeft()));
+                    GraphicsFilter::FILTER_FAST, 1.0, gfxMatrix().Translate(needed.TopLeft()));
     RefPtr<SourceSurface> surface = target->Snapshot();
 
     nsRefPtr<gfxDrawable> drawable = new gfxSurfaceDrawable(surface, size, gfxMatrix().Translate(-needed.TopLeft()));
     return drawable.forget();
 }
 #endif // !MOZ_GFX_OPTIMIZE_MOBILE
 
 // working around cairo/pixman bug (bug 364968)
@@ -562,17 +562,18 @@ static GraphicsFilter ReduceResamplingFi
 
 /* static */ void
 gfxUtils::DrawPixelSnapped(gfxContext*         aContext,
                            gfxDrawable*        aDrawable,
                            const gfxSize&      aImageSize,
                            const ImageRegion&  aRegion,
                            const SurfaceFormat aFormat,
                            GraphicsFilter      aFilter,
-                           uint32_t            aImageFlags)
+                           uint32_t            aImageFlags,
+                           gfxFloat            aOpacity)
 {
     PROFILER_LABEL("gfxUtils", "DrawPixelSnapped",
       js::ProfileEntry::Category::GRAPHICS);
 
     gfxRect imageRect(gfxPoint(0, 0), aImageSize);
     gfxRect region(aRegion.Rect());
 
     bool doTile = !imageRect.Contains(region) &&
@@ -612,17 +613,17 @@ gfxUtils::DrawPixelSnapped(gfxContext*  
         }
         // We no longer need to tile: Either we never needed to, or we already
         // filled a surface with the tiled pattern; this surface can now be
         // drawn without tiling.
         doTile = false;
     }
 #endif
 
-    drawable->Draw(aContext, aRegion.Rect(), doTile, aFilter);
+    drawable->Draw(aContext, aRegion.Rect(), doTile, aFilter, aOpacity);
 }
 
 /* static */ int
 gfxUtils::ImageFormatToDepth(gfxImageFormat aFormat)
 {
     switch (aFormat) {
         case gfxImageFormat::ARGB32:
             return 32;
--- a/gfx/thebes/gfxUtils.h
+++ b/gfx/thebes/gfxUtils.h
@@ -76,17 +76,18 @@ public:
      * algorithm before passing them on to this method.
      */
     static void DrawPixelSnapped(gfxContext*        aContext,
                                  gfxDrawable*       aDrawable,
                                  const gfxSize&     aImageSize,
                                  const ImageRegion& aRegion,
                                  const mozilla::gfx::SurfaceFormat aFormat,
                                  GraphicsFilter     aFilter,
-                                 uint32_t           aImageFlags = imgIContainer::FLAG_NONE);
+                                 uint32_t           aImageFlags = imgIContainer::FLAG_NONE,
+                                 gfxFloat           aOpacity = 1.0);
 
     /**
      * Clip aContext to the region aRegion.
      */
     static void ClipToRegion(gfxContext* aContext, const nsIntRegion& aRegion);
 
     /**
      * Clip aTarget to the region aRegion.
--- a/image/src/VectorImage.cpp
+++ b/image/src/VectorImage.cpp
@@ -774,27 +774,29 @@ struct SVGDrawingParameters
     , size(aSize.width, aSize.height)
     , imageRect(0, 0, aSize.width, aSize.height)
     , region(aRegion)
     , filter(aFilter)
     , svgContext(aSVGContext)
     , viewportSize(aSVGContext ? aSVGContext->GetViewportSize() : aSize)
     , animationTime(aAnimationTime)
     , flags(aFlags)
+    , opacity(aSVGContext ? aSVGContext->GetGlobalOpacity() : 1.0)
   { }
 
   gfxContext*                   context;
   IntSize                       size;
   IntRect                       imageRect;
   ImageRegion                   region;
   GraphicsFilter                filter;
   const Maybe<SVGImageContext>& svgContext;
   nsIntSize                     viewportSize;
   float                         animationTime;
   uint32_t                      flags;
+  gfxFloat                      opacity;
 };
 
 //******************************************************************************
 /* [noscript] void draw(in gfxContext aContext,
  *                      in gfxGraphicsFilter aFilter,
  *                      [const] in gfxMatrix aUserSpaceToImageSpace,
  *                      [const] in gfxRect aFill,
  *                      [const] in nsIntRect aSubimage,
@@ -924,17 +926,17 @@ VectorImage::CreateDrawableAndShow(const
 void
 VectorImage::Show(gfxDrawable* aDrawable, const SVGDrawingParameters& aParams)
 {
   MOZ_ASSERT(aDrawable, "Should have a gfxDrawable by now");
   gfxUtils::DrawPixelSnapped(aParams.context, aDrawable,
                              ThebesIntSize(aParams.size),
                              aParams.region,
                              SurfaceFormat::B8G8R8A8,
-                             aParams.filter, aParams.flags);
+                             aParams.filter, aParams.flags, aParams.opacity);
 
   MOZ_ASSERT(mRenderingObserver, "Should have a rendering observer by now");
   mRenderingObserver->ResumeHonoringInvalidations();
 }
 
 //******************************************************************************
 /* void requestDecode() */
 NS_IMETHODIMP
--- a/js/src/builtin/Array.js
+++ b/js/src/builtin/Array.js
@@ -427,30 +427,28 @@ function ArrayFind(predicate/*, thisArg*
         ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.prototype.find');
     if (!IsCallable(predicate))
         ThrowError(JSMSG_NOT_FUNCTION, DecompileArg(0, predicate));
 
     /* Step 7. */
     var T = arguments.length > 1 ? arguments[1] : undefined;
 
     /* Steps 8-9. */
-    /* Steps a (implicit), and e. */
+    /* Steps a (implicit), and g. */
     /* Note: this will hang in some corner-case situations, because of IEEE-754 numbers'
      * imprecision for large values. Example:
      * var obj = { 18014398509481984: true, length: 18014398509481988 };
      * Array.prototype.find.call(obj, () => true);
      */
     for (var k = 0; k < len; k++) {
-        /* Steps b and c (implicit) */
-        if (k in O) {
-            /* Step d. */
-            var kValue = O[k];
-            if (callFunction(predicate, T, kValue, k, O))
-                return kValue;
-        }
+        /* Steps a-c. */
+        var kValue = O[k];
+        /* Steps d-f. */
+        if (callFunction(predicate, T, kValue, k, O))
+            return kValue;
     }
 
     /* Step 10. */
     return undefined;
 }
 
 /* ES6 draft 2013-05-14 15.4.3.23. */
 function ArrayFindIndex(predicate/*, thisArg*/) {
@@ -465,29 +463,26 @@ function ArrayFindIndex(predicate/*, thi
         ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.prototype.find');
     if (!IsCallable(predicate))
         ThrowError(JSMSG_NOT_FUNCTION, DecompileArg(0, predicate));
 
     /* Step 7. */
     var T = arguments.length > 1 ? arguments[1] : undefined;
 
     /* Steps 8-9. */
-    /* Steps a (implicit), and e. */
+    /* Steps a (implicit), and g. */
     /* Note: this will hang in some corner-case situations, because of IEEE-754 numbers'
      * imprecision for large values. Example:
      * var obj = { 18014398509481984: true, length: 18014398509481988 };
      * Array.prototype.find.call(obj, () => true);
      */
     for (var k = 0; k < len; k++) {
-        /* Steps b and c (implicit) */
-        if (k in O) {
-            /* Step d. */
-            if (callFunction(predicate, T, O[k], k, O))
-                return k;
-        }
+        /* Steps a-f. */
+        if (callFunction(predicate, T, O[k], k, O))
+            return k;
     }
 
     /* Step 10. */
     return -1;
 }
 
 /* ES6 draft 2013-09-27 22.1.3.3. */
 function ArrayCopyWithin(target, start, end = undefined) {
--- a/js/src/jit-test/tests/asm.js/testGlobals.js
+++ b/js/src/jit-test/tests/asm.js/testGlobals.js
@@ -118,19 +118,21 @@ assertEq(asmLink(asmCompile('global', 'i
 assertEq(asmLink(asmCompile('global', 'imp', USE_ASM + "var i=+imp.i; function f() { return +i } return f")(this, {i:1.4})), 1.4);
 assertEq(asmLink(asmCompile('global', 'imp', USE_ASM + "const i=+imp.i; function f() { return +i } return f")(this, {i:1.4})), 1.4);
 assertEq(asmLink(asmCompile(USE_ASM + "var g=0; function f() { var i=42; while (1) { break; } g = i; return g|0 } return f"))(), 42);
 assertAsmLinkFail(asmCompile('glob','foreign', USE_ASM + 'var i = +foreign.x; function f() {} return f'), null, {x:{valueOf:function() { return 42 }}});
 assertAsmLinkFail(asmCompile('glob','foreign', USE_ASM + 'var i = foreign.x|0; function f() {} return f'), null, {x:{valueOf:function() { return 42 }}});
 assertEq(asmLink(asmCompile('glob','foreign', USE_ASM + 'var i = foreign.x|0; function f() { return i|0} return f'), null, {x:"blah"})(), 0);
 assertEq(asmLink(asmCompile('glob','foreign', USE_ASM + 'var i = +foreign.x; function f() { return +i} return f'), null, {x:"blah"})(), NaN);
 assertEq(asmLink(asmCompile('glob','foreign', USE_ASM + 'var tof = glob.Math.fround; var i = tof(foreign.x); function f() { return +i} return f'), this, {x:"blah"})(), NaN);
-assertThrowsInstanceOf(() => asmCompile('glob','foreign',USE_ASM + 'var i = foreign.x|0; function f() { return i|0} return f')(null, {x:Symbol("blah")}), TypeError);
-assertThrowsInstanceOf(() => asmCompile('glob','foreign',USE_ASM + 'var i = +foreign.x; function f() { return +i} return f')(null, {x:Symbol("blah")}), TypeError);
-assertThrowsInstanceOf(() => asmCompile('glob','foreign',USE_ASM + 'var tof = glob.Math.fround; var i = tof(foreign.x); function f() { return +i} return f')(this, {x:Symbol("blah")}), TypeError);
+if (typeof Symbol === "function") {
+    assertThrowsInstanceOf(() => asmCompile('glob','foreign',USE_ASM + 'var i = foreign.x|0; function f() { return i|0} return f')(null, {x:Symbol("blah")}), TypeError);
+    assertThrowsInstanceOf(() => asmCompile('glob','foreign',USE_ASM + 'var i = +foreign.x; function f() { return +i} return f')(null, {x:Symbol("blah")}), TypeError);
+    assertThrowsInstanceOf(() => asmCompile('glob','foreign',USE_ASM + 'var tof = glob.Math.fround; var i = tof(foreign.x); function f() { return +i} return f')(this, {x:Symbol("blah")}), TypeError);
+}
 
 // Temporary workaround; this test can be removed when Emscripten is fixed and
 // the fix has propagated out to most apps:
 assertEq(asmLink(asmCompile('glob','foreign', USE_ASM + 'var i = foreign.i|0; function f() { return i|0} return f'), null, {i:function(){}})(), 0);
 assertEq(asmLink(asmCompile('glob','foreign', USE_ASM + 'var i = +foreign.i; function f() { return +i} return f'), null, {i:function(){}})(), NaN);
 assertEq(asmLink(asmCompile('glob','foreign', USE_ASM + 'var tof = glob.Math.fround; var i = tof(foreign.i); function f() { return +i} return f'), this, {i:function(){}})(), NaN);
 var module = asmCompile('glob','foreign', USE_ASM + 'var i = foreign.i|0; function f() { return i|0} return f');
 var fun = function() {}
--- a/js/src/jit-test/tests/symbol/typed-arrays.js
+++ b/js/src/jit-test/tests/symbol/typed-arrays.js
@@ -1,31 +1,31 @@
 load(libdir + "asserts.js");
 
 var LENGTH = 1024, SYMBOL_INDEX = 999;
 
-var sym = this.Symbol ? () => Symbol.for("comet") : () => NaN;
+if (typeof Symbol === "function") {
+    var big = [];
+    for (var i = 0; i < LENGTH; i++)
+        big[i] = (i === SYMBOL_INDEX ? Symbol.for("comet") : i);
 
-var big = [];
-for (var i = 0; i < LENGTH; i++)
-    big[i] = (i === SYMBOL_INDEX ? sym() : i);
+    var progress;
+    function copy(arr, big) {
+        for (var i = 0; i < LENGTH; i++) {
+            arr[i] = big[i];
+            progress = i;
+        }
+    }
 
-var progress;
-function copy(arr, big) {
-    for (var i = 0; i < LENGTH; i++) {
-        arr[i] = big[i];
-        progress = i;
+    for (var T of [Uint8Array, Uint8ClampedArray, Int16Array, Float32Array]) {
+        // Typed array constructors convert symbols using ToNumber, which throws.
+        assertThrowsInstanceOf(() => new T(big), TypeError);
+
+        // Element assignment does the same.
+        var arr = new T(big.length);
+        for (var k = 0; k < 3; k++) {
+            progress = -1;
+            assertThrowsInstanceOf(() => copy(arr, big), TypeError);
+            assertEq(progress, SYMBOL_INDEX - 1);
+            assertEq(arr[SYMBOL_INDEX], 0);
+        }
     }
 }
-