Backed out 10 changesets (bug 1246677) for causing frequent OSX browser_rules_completion-existing-property_01.js failures (10.6 and 10.10).
authorRyan VanderMeulen <ryanvm@gmail.com>
Wed, 24 Feb 2016 21:04:31 -0500
changeset 321674 8d2eef5f724985debb334f0d69465215bb200fe0
parent 321673 a951d792d9b008a7361233b6c71fbea29848ccb2
child 321675 ccfb45a887bf311871e3205f14ddbbb50ea2137e
push id5913
push userjlund@mozilla.com
push dateMon, 25 Apr 2016 16:57:49 +0000
treeherdermozilla-beta@dcaf0a6fa115 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1246677
milestone47.0a1
backs outa6d3a7a5e4ea08c41080c8a097fa08a0459db76e
5dcb51fcef157e980b5aa0ee1a5e81fcef709590
e450c5329a06f5a38933eed2f9541570f79ecb6f
a65e8badc4c41db874a2c4f65c6e801b9f5c04cc
0cdde48161bb6180b57c569f4ba4157324726ffa
bab3de413d374fbaf58f53117709ef34a3922c7b
e4f6cc6197cbe96800989280435f4378cccee0ce
34e6b56e419d6a0fd1eb74a3676fe924775eb234
5067508e5db4b626978ec32deec2e274720010c0
913b4129466e9de24eddbc730efd46b61936b354
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
Backed out 10 changesets (bug 1246677) for causing frequent OSX browser_rules_completion-existing-property_01.js failures (10.6 and 10.10). Backed out changeset a6d3a7a5e4ea (bug 1246677) Backed out changeset 5dcb51fcef15 (bug 1246677) Backed out changeset e450c5329a06 (bug 1246677) Backed out changeset a65e8badc4c4 (bug 1246677) Backed out changeset 0cdde48161bb (bug 1246677) Backed out changeset bab3de413d37 (bug 1246677) Backed out changeset e4f6cc6197cb (bug 1246677) Backed out changeset 34e6b56e419d (bug 1246677) Backed out changeset 5067508e5db4 (bug 1246677) Backed out changeset 913b4129466e (bug 1246677)
.eslintignore
devtools/client/inspector/rules/rules.js
devtools/client/inspector/rules/test/browser_rules_add-property-cancel_01.js
devtools/client/inspector/rules/test/browser_rules_add-property-cancel_02.js
devtools/client/inspector/rules/test/browser_rules_add-property-cancel_03.js
devtools/client/inspector/rules/test/browser_rules_add-property-svg.js
devtools/client/inspector/rules/test/browser_rules_add-property_01.js
devtools/client/inspector/rules/test/browser_rules_add-property_02.js
devtools/client/inspector/rules/test/browser_rules_add-rule_01.js
devtools/client/inspector/rules/test/browser_rules_add-rule_05.js
devtools/client/inspector/rules/test/browser_rules_authored.js
devtools/client/inspector/rules/test/browser_rules_authored_color.js
devtools/client/inspector/rules/test/browser_rules_authored_override.js
devtools/client/inspector/rules/test/browser_rules_colorUnit.js
devtools/client/inspector/rules/test/browser_rules_colorpicker-and-image-tooltip_01.js
devtools/client/inspector/rules/test/browser_rules_colorpicker-and-image-tooltip_02.js
devtools/client/inspector/rules/test/browser_rules_colorpicker-commit-on-ENTER.js
devtools/client/inspector/rules/test/browser_rules_colorpicker-edit-gradient.js
devtools/client/inspector/rules/test/browser_rules_colorpicker-multiple-changes.js
devtools/client/inspector/rules/test/browser_rules_colorpicker-release-outside-frame.js
devtools/client/inspector/rules/test/browser_rules_colorpicker-revert-on-ESC.js
devtools/client/inspector/rules/test/browser_rules_completion-existing-property_01.js
devtools/client/inspector/rules/test/browser_rules_completion-existing-property_02.js
devtools/client/inspector/rules/test/browser_rules_completion-new-property_01.js
devtools/client/inspector/rules/test/browser_rules_completion-new-property_02.js
devtools/client/inspector/rules/test/browser_rules_completion-popup-hidden-after-navigation.js
devtools/client/inspector/rules/test/browser_rules_computed-lists_02.js
devtools/client/inspector/rules/test/browser_rules_content_01.js
devtools/client/inspector/rules/test/browser_rules_content_02.js
devtools/client/inspector/rules/test/browser_rules_context-menu-show-mdn-docs-01.js
devtools/client/inspector/rules/test/browser_rules_context-menu-show-mdn-docs-02.js
devtools/client/inspector/rules/test/browser_rules_copy_styles.js
devtools/client/inspector/rules/test/browser_rules_cubicbezier-commit-on-ENTER.js
devtools/client/inspector/rules/test/browser_rules_cubicbezier-revert-on-ESC.js
devtools/client/inspector/rules/test/browser_rules_custom.js
devtools/client/inspector/rules/test/browser_rules_edit-property-cancel.js
devtools/client/inspector/rules/test/browser_rules_edit-property-increments.js
devtools/client/inspector/rules/test/browser_rules_edit-property-order.js
devtools/client/inspector/rules/test/browser_rules_edit-property-remove_01.js
devtools/client/inspector/rules/test/browser_rules_edit-property-remove_02.js
devtools/client/inspector/rules/test/browser_rules_edit-property-remove_03.js
devtools/client/inspector/rules/test/browser_rules_edit-property_01.js
devtools/client/inspector/rules/test/browser_rules_edit-property_02.js
devtools/client/inspector/rules/test/browser_rules_edit-property_04.js
devtools/client/inspector/rules/test/browser_rules_edit-property_05.js
devtools/client/inspector/rules/test/browser_rules_edit-property_06.js
devtools/client/inspector/rules/test/browser_rules_edit-property_07.js
devtools/client/inspector/rules/test/browser_rules_edit-selector_05.js
devtools/client/inspector/rules/test/browser_rules_editable-field-focus_02.js
devtools/client/inspector/rules/test/browser_rules_eyedropper.js
devtools/client/inspector/rules/test/browser_rules_filtereditor-commit-on-ENTER.js
devtools/client/inspector/rules/test/browser_rules_guessIndentation.js
devtools/client/inspector/rules/test/browser_rules_inherited-properties_01.js
devtools/client/inspector/rules/test/browser_rules_inherited-properties_02.js
devtools/client/inspector/rules/test/browser_rules_keyframeLineNumbers.js
devtools/client/inspector/rules/test/browser_rules_keyframes-rule_01.js
devtools/client/inspector/rules/test/browser_rules_keyframes-rule_02.js
devtools/client/inspector/rules/test/browser_rules_lineNumbers.js
devtools/client/inspector/rules/test/browser_rules_livepreview.js
devtools/client/inspector/rules/test/browser_rules_mark_overridden_01.js
devtools/client/inspector/rules/test/browser_rules_mark_overridden_03.js
devtools/client/inspector/rules/test/browser_rules_mark_overridden_04.js
devtools/client/inspector/rules/test/browser_rules_mark_overridden_05.js
devtools/client/inspector/rules/test/browser_rules_original-source-link.js
devtools/client/inspector/rules/test/browser_rules_pseudo-element_01.js
devtools/client/inspector/rules/test/browser_rules_refresh-no-flicker.js
devtools/client/inspector/rules/test/browser_rules_refresh-on-attribute-change_01.js
devtools/client/inspector/rules/test/browser_rules_refresh-on-attribute-change_02.js
devtools/client/inspector/rules/test/browser_rules_refresh-on-style-change.js
devtools/client/inspector/rules/test/browser_rules_search-filter-computed-list_01.js
devtools/client/inspector/rules/test/browser_rules_search-filter_01.js
devtools/client/inspector/rules/test/browser_rules_search-filter_08.js
devtools/client/inspector/rules/test/browser_rules_search-filter_09.js
devtools/client/inspector/rules/test/browser_rules_search-filter_10.js
devtools/client/inspector/rules/test/browser_rules_select-and-copy-styles.js
devtools/client/inspector/rules/test/browser_rules_selector_highlight.js
devtools/client/inspector/rules/test/browser_rules_strict-search-filter-computed-list_01.js
devtools/client/inspector/rules/test/browser_rules_strict-search-filter_01.js
devtools/client/inspector/rules/test/browser_rules_style-editor-link.js
devtools/client/inspector/rules/test/browser_rules_user-agent-styles.js
devtools/client/inspector/rules/test/browser_rules_user-property-reset.js
devtools/client/inspector/rules/test/doc_author-sheet.html
devtools/client/inspector/rules/test/doc_content_stylesheet.html
devtools/client/inspector/rules/test/doc_cssom.html
devtools/client/inspector/rules/test/doc_frame_script.js
devtools/client/inspector/rules/test/head.js
devtools/client/inspector/test/head.js
testing/eslint-plugin-mozilla/lib/helpers.js
--- a/.eslintignore
+++ b/.eslintignore
@@ -87,16 +87,17 @@ devtools/client/commandline/**
 devtools/client/debugger/**
 devtools/client/eyedropper/**
 devtools/client/framework/**
 # devtools/client/inspector/shared/*.js files are eslint-clean, so they aren't
 # included in the ignore list.
 devtools/client/inspector/computed/**
 devtools/client/inspector/fonts/**
 devtools/client/inspector/markup/test/**
+devtools/client/inspector/rules/**
 devtools/client/inspector/shared/test/**
 devtools/client/inspector/test/**
 devtools/client/inspector/*.js
 devtools/client/jsonview/**
 devtools/client/memory/**
 devtools/client/netmonitor/**
 devtools/client/performance/**
 devtools/client/projecteditor/**
--- a/devtools/client/inspector/rules/rules.js
+++ b/devtools/client/inspector/rules/rules.js
@@ -952,17 +952,17 @@ CssRuleView.prototype = {
       }
     }
   },
 
   _populate: function() {
     let elementStyle = this._elementStyle;
     return this._elementStyle.populate().then(() => {
       if (this._elementStyle !== elementStyle || this.isDestroyed) {
-        return null;
+        return;
       }
 
       this._clearRules();
       let onEditorsReady = this._createEditors();
       this.refreshPseudoClassPanel();
 
       // Notify anyone that cares that we refreshed.
       return onEditorsReady.then(() => {
@@ -1688,18 +1688,18 @@ RuleViewTool.prototype = {
     let location = promise.resolve(rule.location);
     if (Services.prefs.getBoolPref(PREF_ORIG_SOURCES)) {
       location = rule.getOriginalLocation();
     }
     location.then(({ source, href, line, column }) => {
       let target = this.inspector.target;
       if (Tools.styleEditor.isTargetSupported(target)) {
         gDevTools.showToolbox(target, "styleeditor").then(function(toolbox) {
-          let url = source || href;
-          toolbox.getCurrentPanel().selectStyleSheet(url, line, column);
+          let sheet = source || href;
+          toolbox.getCurrentPanel().selectStyleSheet(sheet, line, column);
         });
       }
       return;
     });
   },
 
   onPropertyChanged: function() {
     this.inspector.markDirty();
--- a/devtools/client/inspector/rules/test/browser_rules_add-property-cancel_01.js
+++ b/devtools/client/inspector/rules/test/browser_rules_add-property-cancel_01.js
@@ -17,27 +17,32 @@ const TEST_URI = `
   </style>
   <div id='testid' class='testclass'>Styled Node</div>
 `;
 
 add_task(function*() {
   yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
   let {inspector, view} = yield openRuleView();
   yield selectNode("#testid", inspector);
+  yield testCancelNew(view);
+});
 
+function* testCancelNew(view) {
   let elementRuleEditor = getRuleViewRuleEditor(view, 0);
-  let editor = yield focusNewRuleViewProperty(elementRuleEditor);
+  let editor = yield focusEditableField(view, elementRuleEditor.closeBrace);
   is(inplaceEditor(elementRuleEditor.newPropSpan), editor,
     "The new property editor got focused");
 
   info("Escape the new property editor");
   let onBlur = once(editor.input, "blur");
   EventUtils.synthesizeKey("VK_ESCAPE", {}, view.styleWindow);
   yield onBlur;
 
   info("Checking the state of cancelling a new property name editor");
+  ok(!elementRuleEditor.rule._applyingModifications,
+    "Shouldn't have an outstanding request after a cancel.");
   is(elementRuleEditor.rule.textProps.length, 0,
     "Should have cancelled creating a new text property.");
   ok(!elementRuleEditor.propertyList.hasChildNodes(),
     "Should not have any properties.");
   is(view.styleDocument.activeElement, view.styleDocument.documentElement,
     "Correct element has focus");
-});
+}
--- a/devtools/client/inspector/rules/test/browser_rules_add-property-cancel_02.js
+++ b/devtools/client/inspector/rules/test/browser_rules_add-property-cancel_02.js
@@ -16,19 +16,66 @@ const TEST_URI = `
 `;
 
 add_task(function*() {
   yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
   let {inspector, view} = yield openRuleView();
   yield selectNode("#testid", inspector);
 
   info("Test creating a new property and escaping");
-  yield addProperty(view, 1, "color", "red", "VK_ESCAPE", false);
+
+  let elementRuleEditor = getRuleViewRuleEditor(view, 1);
+
+  info("Focusing a new property name in the rule-view");
+  let editor = yield focusEditableField(view, elementRuleEditor.closeBrace);
+
+  is(inplaceEditor(elementRuleEditor.newPropSpan), editor,
+    "The new property editor got focused.");
+
+  info("Entering a value in the property name editor");
+  editor.input.value = "color";
+
+  info("Pressing return to commit and focus the new value field");
+  let onValueFocus = once(elementRuleEditor.element, "focus", true);
+  let onRuleViewChanged = view.once("ruleview-changed");
+  EventUtils.synthesizeKey("VK_RETURN", {}, view.styleWindow);
+  yield onValueFocus;
+  yield onRuleViewChanged;
+
+  // Getting the new value editor after focus
+  editor = inplaceEditor(view.styleDocument.activeElement);
+  let textProp = elementRuleEditor.rule.textProps[1];
+
+  is(elementRuleEditor.rule.textProps.length, 2,
+    "Created a new text property.");
+  is(elementRuleEditor.propertyList.children.length, 2,
+    "Created a property editor.");
+  is(editor, inplaceEditor(textProp.editor.valueSpan),
+    "Editing the value span now.");
+
+  info("Entering a property value");
+  editor.input.value = "red";
+
+  // Setting the input value above schedules a preview to be shown in 10ms
+  // which triggers a ruleview-changed event. If the event arrives at just the
+  // right moment after pressing escape but before the new property is removed
+  // from the rule view (it's done after a tick), the test continues too soon
+  // and the assertions below fail as the new property is still there (bug
+  // 1209295).
+  //
+  // Thus, wait for the ruleview-changed event triggered by the preview before
+  // continuing to discard the new property.
+  info("Waiting for preview to be applied.");
+  yield view.once("ruleview-changed");
+
+  info("Escaping out of the field");
+  onRuleViewChanged = view.once("ruleview-changed");
+  EventUtils.synthesizeKey("VK_ESCAPE", {}, view.styleWindow);
+  yield onRuleViewChanged;
 
   is(view.styleDocument.documentElement, view.styleDocument.activeElement,
     "Correct element has focus");
 
-  let elementRuleEditor = getRuleViewRuleEditor(view, 1);
   is(elementRuleEditor.rule.textProps.length, 1,
     "Removed the new text property.");
   is(elementRuleEditor.propertyList.children.length, 1,
     "Removed the property editor.");
 });
--- a/devtools/client/inspector/rules/test/browser_rules_add-property-cancel_03.js
+++ b/devtools/client/inspector/rules/test/browser_rules_add-property-cancel_03.js
@@ -4,40 +4,50 @@
 
 "use strict";
 
 // Tests adding a new property and escapes the property name editor with a
 // value.
 
 const TEST_URI = `
   <style type='text/css'>
-    div {
+    #testid {
       background-color: blue;
     }
+    .testclass {
+      background-color: green;
+    }
   </style>
-  <div>Test node</div>
+  <div id='testid' class='testclass'>Styled Node</div>
 `;
 
 add_task(function*() {
   yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
   let {inspector, view} = yield openRuleView();
-  yield selectNode("div", inspector);
+  yield selectNode("#testid", inspector);
+  yield testCancelNewOnEscape(inspector, view);
+});
 
-  // Add a property to the element's style declaration, add some text,
-  // then press escape.
+function* testCancelNewOnEscape(inspector, view) {
+  // Start at the beginning: start to add a rule to the element's style
+  // declaration, add some text, then press escape.
 
-  let elementRuleEditor = getRuleViewRuleEditor(view, 1);
-  let editor = yield focusNewRuleViewProperty(elementRuleEditor);
+  let elementRuleEditor = getRuleViewRuleEditor(view, 0);
+  let editor = yield focusEditableField(view, elementRuleEditor.closeBrace);
 
   is(inplaceEditor(elementRuleEditor.newPropSpan), editor,
     "Next focused editor should be the new property editor.");
 
   EventUtils.sendString("background", view.styleWindow);
 
   let onBlur = once(editor.input, "blur");
   EventUtils.synthesizeKey("VK_ESCAPE", {});
   yield onBlur;
 
-  is(elementRuleEditor.rule.textProps.length, 1,
+  ok(!elementRuleEditor.rule._applyingModifications,
+    "Shouldn't have an outstanding modification request after a cancel.");
+  is(elementRuleEditor.rule.textProps.length, 0,
     "Should have canceled creating a new text property.");
+  ok(!elementRuleEditor.propertyList.hasChildNodes(),
+    "Should not have any properties.");
   is(view.styleDocument.documentElement, view.styleDocument.activeElement,
     "Correct element has focus");
-});
+}
--- a/devtools/client/inspector/rules/test/browser_rules_add-property-svg.js
+++ b/devtools/client/inspector/rules/test/browser_rules_add-property-svg.js
@@ -8,15 +8,54 @@
 
 var TEST_URL = "chrome://global/skin/icons/warning.svg";
 var TEST_SELECTOR = "path";
 
 add_task(function*() {
   yield addTab(TEST_URL);
   let {inspector, view} = yield openRuleView();
   yield selectNode(TEST_SELECTOR, inspector);
+  yield testCreateNew(view);
+});
 
+function* testCreateNew(ruleView) {
   info("Test creating a new property");
-  yield addProperty(view, 0, "fill", "red");
+
+  let elementRuleEditor = getRuleViewRuleEditor(ruleView, 0);
+
+  info("Focusing a new property name in the rule-view");
+  let editor = yield focusEditableField(ruleView, elementRuleEditor.closeBrace);
+
+  is(inplaceEditor(elementRuleEditor.newPropSpan), editor,
+    "Next focused editor should be the new property editor.");
+
+  let input = editor.input;
+
+  info("Entering the property name");
+  input.value = "fill";
+
+  info("Pressing RETURN and waiting for the value field focus");
+  let onFocus = once(elementRuleEditor.element, "focus", true);
+  EventUtils.sendKey("return", ruleView.styleWindow);
+  yield onFocus;
+  yield elementRuleEditor.rule._applyingModifications;
+
+  editor = inplaceEditor(ruleView.styleDocument.activeElement);
+
+  is(elementRuleEditor.rule.textProps.length, 1,
+    "Should have created a new text property.");
+  is(elementRuleEditor.propertyList.children.length, 1,
+    "Should have created a property editor.");
+  let textProp = elementRuleEditor.rule.textProps[0];
+  is(editor, inplaceEditor(textProp.editor.valueSpan),
+    "Should be editing the value span now.");
+
+  editor.input.value = "red";
+  let onBlur = once(editor.input, "blur");
+  EventUtils.sendKey("return", ruleView.styleWindow);
+  yield onBlur;
+  yield elementRuleEditor.rule._applyingModifications;
+
+  is(textProp.value, "red", "Text prop should have been changed.");
 
   is((yield getComputedStyleProperty(TEST_SELECTOR, null, "fill")),
-     "rgb(255, 0, 0)", "The fill was changed to red");
-});
+    "rgb(255, 0, 0)", "The fill was changed to red");
+}
--- a/devtools/client/inspector/rules/test/browser_rules_add-property_01.js
+++ b/devtools/client/inspector/rules/test/browser_rules_add-property_01.js
@@ -1,15 +1,17 @@
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
-// Test adding an invalid property.
+// Testing various inplace-editor behaviors in the rule-view
+// FIXME: To be split in several test files, and some of the inplace-editor
+// focus/blur/commit/revert stuff should be factored out in head.js
 
 const TEST_URI = `
   <style type='text/css'>
     #testid {
       background-color: blue;
     }
     .testclass {
       background-color: green;
@@ -17,16 +19,56 @@ const TEST_URI = `
   </style>
   <div id='testid' class='testclass'>Styled Node</div>
 `;
 
 add_task(function*() {
   yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
   let {inspector, view} = yield openRuleView();
   yield selectNode("#testid", inspector);
+  yield testCreateNew(view);
+});
 
+function* testCreateNew(view) {
   info("Test creating a new property");
-  let textProp = yield addProperty(view, 0, "background-color", "#XYZ");
+
+  let elementRuleEditor = getRuleViewRuleEditor(view, 0);
+
+  info("Focusing a new property name in the rule-view");
+  let editor = yield focusEditableField(view, elementRuleEditor.closeBrace);
+
+  is(inplaceEditor(elementRuleEditor.newPropSpan), editor,
+    "The new property editor got focused");
+  let input = editor.input;
+
+  info("Entering background-color in the property name editor");
+  input.value = "background-color";
+
+  info("Pressing return to commit and focus the new value field");
+  let onModifications = view.once("ruleview-changed");
+  EventUtils.synthesizeKey("VK_RETURN", {}, view.styleWindow);
+  yield onModifications;
+
+  // Getting the new value editor after focus
+  editor = inplaceEditor(view.styleDocument.activeElement);
+  let textProp = elementRuleEditor.rule.textProps[0];
+
+  is(elementRuleEditor.rule.textProps.length, 1,
+    "Created a new text property.");
+  is(elementRuleEditor.propertyList.children.length, 1,
+    "Created a property editor.");
+  is(editor, inplaceEditor(textProp.editor.valueSpan),
+    "Editing the value span now.");
+
+  ok(!textProp.editor.element.classList.contains("ruleview-overridden"),
+    "property should not be overridden.");
+
+  info("Entering a value and bluring the field to expect a rule change");
+  editor.input.value = "#XYZ";
+
+  onModifications = view.once("ruleview-changed");
+  editor.input.blur();
+  yield onModifications;
 
   is(textProp.value, "#XYZ", "Text prop should have been changed.");
   is(textProp.overridden, true, "Property should be overridden");
   is(textProp.editor.isValid(), false, "#XYZ should not be a valid entry");
-});
+}
--- a/devtools/client/inspector/rules/test/browser_rules_add-property_02.js
+++ b/devtools/client/inspector/rules/test/browser_rules_add-property_02.js
@@ -1,15 +1,16 @@
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
-//
+// Tests all sorts of additions and updates of properties in the rule-view.
+// FIXME: TO BE SPLIT IN *MANY* SMALLER TESTS
 
 const TEST_URI = `
   <style type="text/css">
     #testid {
       background-color: blue;
     }
     .testclass, .unmatched {
       background-color: green;
@@ -17,53 +18,57 @@ const TEST_URI = `
   </style>
   <div id='testid' class='testclass'>Styled Node</div>
   <div id='testid2'>Styled Node</div>
 `;
 
 add_task(function*() {
   yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
   let {inspector, view} = yield openRuleView();
+  yield testCreateNew(inspector, view);
+});
 
-  info("Focus the new property name field");
-  let elementRuleEditor = getRuleViewRuleEditor(view, 0);
-  let editor = yield focusNewRuleViewProperty(elementRuleEditor);
-  let input = editor.input;
+function* testCreateNew(inspector, ruleView) {
+  // Create a new property.
+  let elementRuleEditor = getRuleViewRuleEditor(ruleView, 0);
+  let editor = yield focusEditableField(ruleView, elementRuleEditor.closeBrace);
 
   is(inplaceEditor(elementRuleEditor.newPropSpan), editor,
     "Next focused editor should be the new property editor.");
+
+  let input = editor.input;
+
   ok(input.selectionStart === 0 && input.selectionEnd === input.value.length,
     "Editor contents are selected.");
 
   // Try clicking on the editor's input again, shouldn't cause trouble
   // (see bug 761665).
-  EventUtils.synthesizeMouse(input, 1, 1, {}, view.styleWindow);
+  EventUtils.synthesizeMouse(input, 1, 1, {}, ruleView.styleWindow);
   input.select();
 
   info("Entering the property name");
-  editor.input.value = "background-color";
+  input.value = "background-color";
 
   info("Pressing RETURN and waiting for the value field focus");
-  let onNameAdded = view.once("ruleview-changed");
-  EventUtils.synthesizeKey("VK_RETURN", {}, view.styleWindow);
-  yield onNameAdded;
+  let onFocus = once(elementRuleEditor.element, "focus", true);
+  EventUtils.sendKey("return", ruleView.styleWindow);
+  yield onFocus;
+  yield elementRuleEditor.rule._applyingModifications;
 
-  editor = inplaceEditor(view.styleDocument.activeElement);
+  editor = inplaceEditor(ruleView.styleDocument.activeElement);
 
   is(elementRuleEditor.rule.textProps.length, 1,
     "Should have created a new text property.");
   is(elementRuleEditor.propertyList.children.length, 1,
     "Should have created a property editor.");
   let textProp = elementRuleEditor.rule.textProps[0];
   is(editor, inplaceEditor(textProp.editor.valueSpan),
     "Should be editing the value span now.");
 
-  info("Entering the property value");
-  // We're editing inline style, so expect a style attribute mutation.
   let onMutated = inspector.once("markupmutation");
-  let onValueAdded = view.once("ruleview-changed");
   editor.input.value = "purple";
-  EventUtils.synthesizeKey("VK_RETURN", {}, view.styleWindow);
-  yield onValueAdded;
+  let onBlur = once(editor.input, "blur");
+  EventUtils.sendKey("return", ruleView.styleWindow);
+  yield onBlur;
   yield onMutated;
 
   is(textProp.value, "purple", "Text prop should have been changed.");
-});
+}
--- a/devtools/client/inspector/rules/test/browser_rules_add-rule_01.js
+++ b/devtools/client/inspector/rules/test/browser_rules_add-rule_01.js
@@ -29,27 +29,26 @@ const TEST_DATA = [
   { node: ".class3.class4", expected: ".class3.class4" },
   { node: "p", expected: "p" },
   { node: "h1", expected: ".asd\\@\\@\\@\\@a\\!\\!\\!\\!\\:\\:\\:\\@asd" },
   { node: "h2", expected: "#asd\\@\\@\\@a\\!\\!2a" }
 ];
 
 add_task(function*() {
   yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
-  let {inspector, view, testActor} = yield openRuleView();
+  let {inspector, view} = yield openRuleView();
 
   for (let data of TEST_DATA) {
     let {node, expected} = data;
     yield selectNode(node, inspector);
     yield addNewRule(inspector, view);
     yield testNewRule(view, expected, 1);
 
     info("Resetting page content");
-    yield testActor.eval(
-      "content.document.body.innerHTML = `" + TEST_URI + "`;");
+    content.document.body.innerHTML = TEST_URI;
   }
 });
 
 function* testNewRule(view, expected, index) {
   let idRuleEditor = getRuleViewRuleEditor(view, index);
   let editor = idRuleEditor.selectorText.ownerDocument.activeElement;
   is(editor.value, expected,
       "Selector editor value is as expected: " + expected);
--- a/devtools/client/inspector/rules/test/browser_rules_add-rule_05.js
+++ b/devtools/client/inspector/rules/test/browser_rules_add-rule_05.js
@@ -29,27 +29,26 @@ const TEST_DATA = [
   { node: ".class3.class4", expected: ".class3.class4" },
   { node: "p", expected: "p" },
   { node: "h1", expected: ".asd\\@\\@\\@\\@a\\!\\!\\!\\!\\:\\:\\:\\@asd" },
   { node: "h2", expected: "#asd\\@\\@\\@a\\!\\!2a" }
 ];
 
 add_task(function*() {
   yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
-  let {inspector, view, testActor} = yield openRuleView();
+  let {inspector, view} = yield openRuleView();
 
   for (let data of TEST_DATA) {
     let {node, expected} = data;
     yield selectNode(node, inspector);
     yield addNewRuleFromContextMenu(inspector, view);
     yield testNewRule(view, expected, 1);
 
     info("Resetting page content");
-    yield testActor.eval(
-      "content.document.body.innerHTML = `" + TEST_URI + "`;");
+    content.document.body.innerHTML = TEST_URI;
   }
 });
 
 function* addNewRuleFromContextMenu(inspector, view) {
   info("Waiting for context menu to be shown");
   let onPopup = once(view._contextmenu._menupopup, "popupshown");
   let win = view.styleWindow;
 
--- a/devtools/client/inspector/rules/test/browser_rules_authored.js
+++ b/devtools/client/inspector/rules/test/browser_rules_authored.js
@@ -2,21 +2,21 @@
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 // Test for as-authored styles.
 
 function* createTestContent(style) {
-  let html = `<style type="text/css">
+  let content = `<style type="text/css">
       ${style}
       </style>
       <div id="testid" class="testclass">Styled Node</div>`;
-  yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(html));
+  yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(content));
 
   let {inspector, view} = yield openRuleView();
   yield selectNode("#testid", inspector);
   return view;
 }
 
 add_task(function* () {
   let view = yield createTestContent("#testid {" +
--- a/devtools/client/inspector/rules/test/browser_rules_authored_color.js
+++ b/devtools/client/inspector/rules/test/browser_rules_authored_color.js
@@ -2,22 +2,22 @@
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 // Test for as-authored styles.
 
 function* createTestContent(style) {
-  let html = `<style type="text/css">
+  let content = `<style type="text/css">
       ${style}
       </style>
       <div id="testid" class="testclass">Styled Node</div>`;
   let tab = yield addTab("data:text/html;charset=utf-8," +
-                         encodeURIComponent(html));
+                         encodeURIComponent(content));
 
   let {inspector, view} = yield openRuleView();
   yield selectNode("#testid", inspector);
   return {view, tab};
 }
 
 add_task(function* () {
   let colors = [
@@ -36,18 +36,20 @@ add_task(function* () {
 
     let cPicker = view.tooltips.colorPicker;
     let swatch = getRuleViewProperty(view, "#testid", "color").valueSpan
         .querySelector(".ruleview-colorswatch");
     let onShown = cPicker.tooltip.once("shown");
     swatch.click();
     yield onShown;
 
+    let testNode = getNode("#testid");
+
     yield simulateColorPickerChange(view, cPicker, [0, 255, 0, 1], {
-      selector: "#testid",
+      element: testNode,
       name: "color",
       value: "rgb(0, 255, 0)"
     });
 
     let spectrum = yield cPicker.spectrum;
     let onHidden = cPicker.tooltip.once("hidden");
     // Validating the color change ends up updating the rule view twice
     let onRuleViewChanged = waitForNEvents(view, "ruleview-changed", 2);
--- a/devtools/client/inspector/rules/test/browser_rules_authored_override.js
+++ b/devtools/client/inspector/rules/test/browser_rules_authored_override.js
@@ -2,21 +2,21 @@
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 // Test for as-authored styles.
 
 function* createTestContent(style) {
-  let html = `<style type="text/css">
+  let content = `<style type="text/css">
       ${style}
       </style>
       <div id="testid" class="testclass">Styled Node</div>`;
-  yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(html));
+  yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(content));
 
   let {inspector, view} = yield openRuleView();
   yield selectNode("#testid", inspector);
   return view;
 }
 
 add_task(function* () {
   let gradientText1 = "(orange, blue);";
@@ -37,17 +37,18 @@ add_task(function* () {
 
   // Initially the last property should be active.
   for (let i = 0; i < 3; ++i) {
     let prop = rule.textProps[i];
     is(prop.name, "background-image", "check the property name");
     is(prop.overridden, i !== 2, "check overridden for " + i);
   }
 
-  yield togglePropStatus(view, rule.textProps[2]);
+  rule.textProps[2].setEnabled(false);
+  yield rule._applyingModifications;
 
   // Now the first property should be active.
   for (let i = 0; i < 3; ++i) {
     let prop = rule.textProps[i];
     is(prop.overridden || !prop.enabled, i !== 0,
        "post-change check overridden for " + i);
   }
 });
--- a/devtools/client/inspector/rules/test/browser_rules_colorUnit.js
+++ b/devtools/client/inspector/rules/test/browser_rules_colorUnit.js
@@ -41,18 +41,20 @@ add_task(function*() {
 function* basicTest(view, name, result) {
   let cPicker = view.tooltips.colorPicker;
   let swatch = getRuleViewProperty(view, "#testid", "color").valueSpan
       .querySelector(".ruleview-colorswatch");
   let onShown = cPicker.tooltip.once("shown");
   swatch.click();
   yield onShown;
 
+  let testNode = getNode("#testid");
+
   yield simulateColorPickerChange(view, cPicker, [0, 255, 0, 1], {
-    selector: "#testid",
+    element: testNode,
     name: "color",
     value: "rgb(0, 255, 0)"
   });
 
   let spectrum = yield cPicker.spectrum;
   let onHidden = cPicker.tooltip.once("hidden");
   // Validating the color change ends up updating the rule view twice
   let onRuleViewChanged = waitForNEvents(view, "ruleview-changed", 2);
--- a/devtools/client/inspector/rules/test/browser_rules_colorpicker-and-image-tooltip_01.js
+++ b/devtools/client/inspector/rules/test/browser_rules_colorpicker-and-image-tooltip_01.js
@@ -34,18 +34,18 @@ function* testImageTooltipAfterColorChan
   is(anchor, url, "The anchor returned by the showOnHover callback is correct");
 
   info("Open the color picker tooltip and change the color");
   let picker = ruleView.tooltips.colorPicker;
   let onShown = picker.tooltip.once("shown");
   swatch.click();
   yield onShown;
   yield simulateColorPickerChange(ruleView, picker, [0, 0, 0, 1], {
-    selector: "body",
-    name: "background-image",
+    element: content.document.body,
+    name: "backgroundImage",
     value: 'url("chrome://global/skin/icons/warning-64.png"), linear-gradient(rgb(0, 0, 0), rgb(255, 0, 102) 400px)'
   });
 
   let spectrum = yield picker.spectrum;
   let onHidden = picker.tooltip.once("hidden");
   let onModifications = ruleView.once("ruleview-changed");
   EventUtils.sendKey("RETURN", spectrum.element.ownerDocument.defaultView);
   yield onHidden;
--- a/devtools/client/inspector/rules/test/browser_rules_colorpicker-and-image-tooltip_02.js
+++ b/devtools/client/inspector/rules/test/browser_rules_colorpicker-and-image-tooltip_02.js
@@ -15,16 +15,20 @@ const TEST_URI = `
     body {
       background: red url("chrome://global/skin/icons/warning-64.png")
         no-repeat center center;
     }
   </style>
   Testing the color picker tooltip!
 `;
 
+const PAGE_CONTENT = [
+
+].join("\n");
+
 add_task(function*() {
   yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
   let {view} = yield openRuleView();
   yield testColorChangeIsntRevertedWhenOtherTooltipIsShown(view);
 });
 
 function* testColorChangeIsntRevertedWhenOtherTooltipIsShown(ruleView) {
   let swatch = getRuleViewProperty(ruleView, "body", "background").valueSpan
@@ -32,18 +36,18 @@ function* testColorChangeIsntRevertedWhe
 
   info("Open the color picker tooltip and change the color");
   let picker = ruleView.tooltips.colorPicker;
   let onShown = picker.tooltip.once("shown");
   swatch.click();
   yield onShown;
 
   yield simulateColorPickerChange(ruleView, picker, [0, 0, 0, 1], {
-    selector: "body",
-    name: "background-color",
+    element: content.document.body,
+    name: "backgroundColor",
     value: "rgb(0, 0, 0)"
   });
 
   let spectrum = yield picker.spectrum;
   let onModifications = ruleView.once("ruleview-changed");
   let onHidden = picker.tooltip.once("hidden");
   EventUtils.sendKey("RETURN", spectrum.element.ownerDocument.defaultView);
   yield onHidden;
--- a/devtools/client/inspector/rules/test/browser_rules_colorpicker-commit-on-ENTER.js
+++ b/devtools/client/inspector/rules/test/browser_rules_colorpicker-commit-on-ENTER.js
@@ -28,34 +28,34 @@ add_task(function*() {
 function* testPressingEnterCommitsChanges(swatch, ruleView) {
   let cPicker = ruleView.tooltips.colorPicker;
 
   let onShown = cPicker.tooltip.once("shown");
   swatch.click();
   yield onShown;
 
   yield simulateColorPickerChange(ruleView, cPicker, [0, 255, 0, .5], {
-    selector: "body",
-    name: "border-left-color",
+    element: content.document.body,
+    name: "borderLeftColor",
     value: "rgba(0, 255, 0, 0.5)"
   });
 
   is(swatch.style.backgroundColor, "rgba(0, 255, 0, 0.5)",
     "The color swatch's background was updated");
   is(getRuleViewProperty(ruleView, "body", "border").valueSpan.textContent,
     "2em solid rgba(0, 255, 0, 0.5)",
     "The text of the border css property was updated");
 
   let onModified = ruleView.once("ruleview-changed");
   let spectrum = yield cPicker.spectrum;
   let onHidden = cPicker.tooltip.once("hidden");
   EventUtils.sendKey("RETURN", spectrum.element.ownerDocument.defaultView);
   yield onHidden;
   yield onModified;
 
-  is((yield getComputedStyleProperty("body", null, "border-left-color")),
+  is(content.getComputedStyle(content.document.body).borderLeftColor,
     "rgba(0, 255, 0, 0.5)", "The element's border was kept after RETURN");
   is(swatch.style.backgroundColor, "rgba(0, 255, 0, 0.5)",
     "The color swatch's background was kept after RETURN");
   is(getRuleViewProperty(ruleView, "body", "border").valueSpan.textContent,
     "2em solid rgba(0, 255, 0, 0.5)",
     "The text of the border css property was kept after RETURN");
 }
--- a/devtools/client/inspector/rules/test/browser_rules_colorpicker-edit-gradient.js
+++ b/devtools/client/inspector/rules/test/browser_rules_colorpicker-edit-gradient.js
@@ -46,32 +46,31 @@ function testColorParsing(view) {
 }
 
 function* testPickingNewColor(view) {
   // Grab the first color swatch and color in the gradient
   let ruleEl = getRuleViewProperty(view, "body", "background-image");
   let swatchEl = ruleEl.valueSpan.querySelector(".ruleview-colorswatch");
   let colorEl = ruleEl.valueSpan.querySelector(".ruleview-color");
 
-  info("Get the color picker tooltip and clicking on the swatch to show it");
+  info("Getting the color picker tooltip and clicking on the swatch to show it");
   let cPicker = view.tooltips.colorPicker;
   let onShown = cPicker.tooltip.once("shown");
   swatchEl.click();
   yield onShown;
 
   let change = {
-    selector: "body",
-    name: "background-image",
-    value: "linear-gradient(to left, rgb(1, 1, 1) 25%, " +
-           "rgb(51, 51, 51) 95%, rgb(0, 0, 0) 100%)"
+    element: content.document.body,
+    name: "backgroundImage",
+    value: "linear-gradient(to left, rgb(1, 1, 1) 25%, rgb(51, 51, 51) 95%, rgb(0, 0, 0) 100%)"
   };
   yield simulateColorPickerChange(view, cPicker, [1, 1, 1, 1], change);
 
   is(swatchEl.style.backgroundColor, "rgb(1, 1, 1)",
     "The color swatch's background was updated");
   is(colorEl.textContent, "#010101", "The color text was updated");
-  is((yield getComputedStyleProperty("body", null, "background-image")),
+  is(content.getComputedStyle(content.document.body).backgroundImage,
     "linear-gradient(to left, rgb(1, 1, 1) 25%, rgb(51, 51, 51) 95%, " +
       "rgb(0, 0, 0) 100%)",
     "The gradient has been updated correctly");
 
   yield hideTooltipAndWaitForRuleViewChanged(cPicker, view);
 }
--- a/devtools/client/inspector/rules/test/browser_rules_colorpicker-multiple-changes.js
+++ b/devtools/client/inspector/rules/test/browser_rules_colorpicker-multiple-changes.js
@@ -50,17 +50,17 @@ function* testSimpleMultipleColorChanges
   info("Changing the color several times");
   let colors = [
     {rgba: [0, 0, 0, 1], computed: "rgb(0, 0, 0)"},
     {rgba: [100, 100, 100, 1], computed: "rgb(100, 100, 100)"},
     {rgba: [200, 200, 200, 1], computed: "rgb(200, 200, 200)"}
   ];
   for (let {rgba, computed} of colors) {
     yield simulateColorPickerChange(ruleView, picker, rgba, {
-      selector: "p",
+      element: content.document.querySelector("p"),
       name: "color",
       value: computed
     });
   }
 }
 
 function* testComplexMultipleColorChanges(inspector, ruleView) {
   yield selectNode("body", inspector);
@@ -78,18 +78,18 @@ function* testComplexMultipleColorChange
   info("Changing the color several times");
   let colors = [
     {rgba: [0, 0, 0, 1], computed: "rgb(0, 0, 0)"},
     {rgba: [100, 100, 100, 1], computed: "rgb(100, 100, 100)"},
     {rgba: [200, 200, 200, 1], computed: "rgb(200, 200, 200)"}
   ];
   for (let {rgba, computed} of colors) {
     yield simulateColorPickerChange(ruleView, picker, rgba, {
-      selector: "body",
-      name: "background-color",
+      element: content.document.body,
+      name: "backgroundColor",
       value: computed
     });
   }
 
   info("Closing the color picker");
   yield hideTooltipAndWaitForRuleViewChanged(picker.tooltip, ruleView);
 }
 
@@ -109,16 +109,16 @@ function* testOverriddenMultipleColorCha
   info("Changing the color several times");
   let colors = [
     {rgba: [0, 0, 0, 1], computed: "rgb(0, 0, 0)"},
     {rgba: [100, 100, 100, 1], computed: "rgb(100, 100, 100)"},
     {rgba: [200, 200, 200, 1], computed: "rgb(200, 200, 200)"}
   ];
   for (let {rgba, computed} of colors) {
     yield simulateColorPickerChange(ruleView, picker, rgba, {
-      selector: "body",
+      element: content.document.body,
       name: "color",
       value: computed
     });
-    is((yield getComputedStyleProperty("p", null, "color")),
+    is(content.getComputedStyle(content.document.querySelector("p")).color,
       "rgb(200, 200, 200)", "The color of the P tag is still correct");
   }
 }
--- a/devtools/client/inspector/rules/test/browser_rules_colorpicker-release-outside-frame.js
+++ b/devtools/client/inspector/rules/test/browser_rules_colorpicker-release-outside-frame.js
@@ -39,18 +39,17 @@ add_task(function*() {
 
   // Releasing the button pressed by mousedown above on top of a different frame
   // does not make sense in this test as EventUtils doesn't preserve the context
   // i.e. the buttons that were pressed down between events.
 
   info("Moving mouse over color picker without any buttons pressed.");
 
   EventUtils.synthesizeMouse(spectrum.dragger, 10, 10, {
-    // -1 = no buttons are pressed down
-    button: -1,
+    button: -1, // -1 = no buttons are pressed down
     type: "mousemove",
   }, spectrum.dragger.ownerDocument.defaultView);
 });
 
 function* openColorPickerForSwatch(swatch, view) {
   let cPicker = view.tooltips.colorPicker;
   ok(cPicker, "The rule-view has the expected colorPicker property");
 
--- a/devtools/client/inspector/rules/test/browser_rules_colorpicker-revert-on-ESC.js
+++ b/devtools/client/inspector/rules/test/browser_rules_colorpicker-revert-on-ESC.js
@@ -18,22 +18,30 @@ const TEST_URI = `
 add_task(function*() {
   yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
   let {view} = yield openRuleView();
   yield testPressingEscapeRevertsChanges(view);
   yield testPressingEscapeRevertsChangesAndDisables(view);
 });
 
 function* testPressingEscapeRevertsChanges(view) {
-  let {swatch, propEditor, cPicker} = yield openColorPickerAndSelectColor(view,
-    1, 0, [0, 0, 0, 1], {
-      selector: "body",
-      name: "background-color",
-      value: "rgb(0, 0, 0)"
-    });
+  let ruleEditor = getRuleViewRuleEditor(view, 1);
+  let propEditor = ruleEditor.rule.textProps[0].editor;
+  let swatch = propEditor.valueSpan.querySelector(".ruleview-colorswatch");
+  let cPicker = view.tooltips.colorPicker;
+
+  let onShown = cPicker.tooltip.once("shown");
+  swatch.click();
+  yield onShown;
+
+  yield simulateColorPickerChange(view, cPicker, [0, 0, 0, 1], {
+    element: content.document.body,
+    name: "backgroundColor",
+    value: "rgb(0, 0, 0)"
+  });
 
   is(swatch.style.backgroundColor, "rgb(0, 0, 0)",
     "The color swatch's background was updated");
   is(propEditor.valueSpan.textContent, "#000",
     "The text of the background-color css property was updated");
 
   let spectrum = yield cPicker.spectrum;
 
@@ -47,60 +55,66 @@ function* testPressingEscapeRevertsChang
   yield waitForComputedStyleProperty("body", null, "background-color",
     "rgb(237, 237, 237)");
   is(propEditor.valueSpan.textContent, "#EDEDED",
     "Got expected property value.");
 }
 
 function* testPressingEscapeRevertsChangesAndDisables(view) {
   let ruleEditor = getRuleViewRuleEditor(view, 1);
+  let propEditor = ruleEditor.rule.textProps[0].editor;
+  let swatch = propEditor.valueSpan.querySelector(".ruleview-colorswatch");
+  let cPicker = view.tooltips.colorPicker;
 
   info("Disabling background-color property");
-  let textProp = ruleEditor.rule.textProps[0];
-  yield togglePropStatus(view, textProp);
+  propEditor.enable.click();
+  yield ruleEditor.rule._applyingModifications;
 
-  ok(textProp.editor.element.classList.contains("ruleview-overridden"),
+  ok(propEditor.element.classList.contains("ruleview-overridden"),
     "property is overridden.");
-  is(textProp.editor.enable.style.visibility, "visible",
+  is(propEditor.enable.style.visibility, "visible",
     "property enable checkbox is visible.");
-  ok(!textProp.editor.enable.getAttribute("checked"),
+  ok(!propEditor.enable.getAttribute("checked"),
     "property enable checkbox is not checked.");
-  ok(!textProp.editor.prop.enabled,
+  ok(!propEditor.prop.enabled,
     "background-color property is disabled.");
   let newValue = yield getRulePropertyValue("background-color");
   is(newValue, "", "background-color should have been unset.");
 
-  let {cPicker} = yield openColorPickerAndSelectColor(view,
-    1, 0, [0, 0, 0, 1]);
+  let onShown = cPicker.tooltip.once("shown");
+  swatch.click();
+  yield onShown;
 
-  ok(!textProp.editor.element.classList.contains("ruleview-overridden"),
+  ok(!propEditor.element.classList.contains("ruleview-overridden"),
     "property overridden is not displayed.");
-  is(textProp.editor.enable.style.visibility, "hidden",
+  is(propEditor.enable.style.visibility, "hidden",
     "property enable checkbox is hidden.");
 
   let spectrum = yield cPicker.spectrum;
+  info("Simulating a color picker change in the widget");
+  spectrum.rgb = [0, 0, 0, 1];
+  yield ruleEditor.rule._applyingModifications;
 
   info("Pressing ESCAPE to close the tooltip");
   let onHidden = cPicker.tooltip.once("hidden");
-  let onModifications = view.once("ruleview-changed");
   EventUtils.sendKey("ESCAPE", spectrum.element.ownerDocument.defaultView);
   yield onHidden;
-  yield onModifications;
+  yield ruleEditor.rule._applyingModifications;
 
-  ok(textProp.editor.element.classList.contains("ruleview-overridden"),
+  ok(propEditor.element.classList.contains("ruleview-overridden"),
     "property is overridden.");
-  is(textProp.editor.enable.style.visibility, "visible",
+  is(propEditor.enable.style.visibility, "visible",
     "property enable checkbox is visible.");
-  ok(!textProp.editor.enable.getAttribute("checked"),
+  ok(!propEditor.enable.getAttribute("checked"),
     "property enable checkbox is not checked.");
-  ok(!textProp.editor.prop.enabled,
+  ok(!propEditor.prop.enabled,
     "background-color property is disabled.");
   newValue = yield getRulePropertyValue("background-color");
   is(newValue, "", "background-color should have been unset.");
-  is(textProp.editor.valueSpan.textContent, "#EDEDED",
+  is(propEditor.valueSpan.textContent, "#EDEDED",
     "Got expected property value.");
 }
 
 function* getRulePropertyValue(name) {
   let propValue = yield executeInContent("Test:GetRulePropertyValue", {
     styleSheetIndex: 0,
     ruleIndex: 0,
     name: name
--- a/devtools/client/inspector/rules/test/browser_rules_completion-existing-property_01.js
+++ b/devtools/client/inspector/rules/test/browser_rules_completion-existing-property_01.js
@@ -53,23 +53,23 @@ var testData = [
   ["i", "fiill", -1, 0],
   ["VK_ESCAPE", null, -1, 0],
 ];
 
 const TEST_URI = "<h1 style='font: 24px serif'>Header</h1>";
 
 add_task(function*() {
   yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
-  let {toolbox, inspector, view, testActor} = yield openRuleView();
+  let {toolbox, inspector, view} = yield openRuleView();
 
   info("Test autocompletion after 1st page load");
   yield runAutocompletionTest(toolbox, inspector, view);
 
   info("Test autocompletion after page navigation");
-  yield reloadPage(inspector, testActor);
+  yield reloadPage(inspector);
   yield runAutocompletionTest(toolbox, inspector, view);
 });
 
 function* runAutocompletionTest(toolbox, inspector, view) {
   info("Selecting the test node");
   yield selectNode("h1", inspector);
 
   info("Focusing the css property editable field");
@@ -97,17 +97,17 @@ function* testCompletion([key, completio
     info("Waiting for after-suggest event on the editor");
     onSuggest = editor.once("after-suggest");
   }
 
   info("Synthesizing key " + key);
   EventUtils.synthesizeKey(key, {}, view.styleWindow);
 
   yield onSuggest;
-  yield waitForTick();
+  yield wait(1); // Equivalent of executeSoon
 
   info("Checking the state");
   if (completion != null) {
     is(editor.input.value, completion, "Correct value is autocompleted");
   }
   if (total == 0) {
     ok(!(editor.popup && editor.popup.isOpen), "Popup is closed");
   } else {
--- a/devtools/client/inspector/rules/test/browser_rules_completion-existing-property_02.js
+++ b/devtools/client/inspector/rules/test/browser_rules_completion-existing-property_02.js
@@ -35,23 +35,23 @@ var testData = [
   ["n", {}, "none", -1, 0],
   ["VK_RETURN", {}, null, -1, 0]
 ];
 
 const TEST_URI = "<h1 style='color: red'>Header</h1>";
 
 add_task(function*() {
   yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
-  let {toolbox, inspector, view, testActor} = yield openRuleView();
+  let {toolbox, inspector, view} = yield openRuleView();
 
   info("Test autocompletion after 1st page load");
   yield runAutocompletionTest(toolbox, inspector, view);
 
   info("Test autocompletion after page navigation");
-  yield reloadPage(inspector, testActor);
+  yield reloadPage(inspector);
   yield runAutocompletionTest(toolbox, inspector, view);
 });
 
 function* runAutocompletionTest(toolbox, inspector, view) {
   info("Selecting the test node");
   yield selectNode("h1", inspector);
 
   info("Focusing the css property editable value");
@@ -85,17 +85,17 @@ function* testCompletion([key, modifiers
     info("Waiting for after-suggest event on the editor");
     onKeyPress = editor.once("after-suggest");
   }
 
   info("Synthesizing key " + key + ", modifiers: " + Object.keys(modifiers));
   EventUtils.synthesizeKey(key, modifiers, view.styleWindow);
 
   yield onKeyPress;
-  yield waitForTick();
+  yield wait(1); // Equivalent of executeSoon
 
   // The key might have been a TAB or shift-TAB, in which case the editor will
   // be a new one
   editor = inplaceEditor(view.styleDocument.activeElement);
 
   info("Checking the state");
   if (completion != null) {
     is(editor.input.value, completion, "Correct value is autocompleted");
--- a/devtools/client/inspector/rules/test/browser_rules_completion-new-property_01.js
+++ b/devtools/client/inspector/rules/test/browser_rules_completion-new-property_01.js
@@ -36,23 +36,23 @@ var testData = [
   ["i", "fill", 0, 4],
   ["VK_ESCAPE", null, -1, 0],
 ];
 
 const TEST_URI = "<h1 style='border: 1px solid red'>Header</h1>";
 
 add_task(function*() {
   yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
-  let {toolbox, inspector, view, testActor} = yield openRuleView();
+  let {toolbox, inspector, view} = yield openRuleView();
 
   info("Test autocompletion after 1st page load");
   yield runAutocompletionTest(toolbox, inspector, view);
 
   info("Test autocompletion after page navigation");
-  yield reloadPage(inspector, testActor);
+  yield reloadPage(inspector);
   yield runAutocompletionTest(toolbox, inspector, view);
 });
 
 function* runAutocompletionTest(toolbox, inspector, view) {
   info("Selecting the test node");
   yield selectNode("h1", inspector);
 
   info("Focusing the css property editable field");
@@ -78,17 +78,17 @@ function* testCompletion([key, completio
     info("Waiting for after-suggest event on the editor");
     onSuggest = editor.once("after-suggest");
   }
 
   info("Synthesizing key " + key);
   EventUtils.synthesizeKey(key, {}, view.styleWindow);
 
   yield onSuggest;
-  yield waitForTick();
+  yield wait(1); // Equivalent of executeSoon
 
   info("Checking the state");
   if (completion != null) {
     is(editor.input.value, completion, "Correct value is autocompleted");
   }
   if (total == 0) {
     ok(!(editor.popup && editor.popup.isOpen), "Popup is closed");
   } else {
--- a/devtools/client/inspector/rules/test/browser_rules_completion-new-property_02.js
+++ b/devtools/client/inspector/rules/test/browser_rules_completion-new-property_02.js
@@ -45,23 +45,23 @@ const TEST_URI = `
       border: 1px solid red;
     }
   </style>
   <h1>Test element</h1>
 `;
 
 add_task(function*() {
   yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
-  let {toolbox, inspector, view, testActor} = yield openRuleView();
+  let {toolbox, inspector, view} = yield openRuleView();
 
   info("Test autocompletion after 1st page load");
   yield runAutocompletionTest(toolbox, inspector, view);
 
   info("Test autocompletion after page navigation");
-  yield reloadPage(inspector, testActor);
+  yield reloadPage(inspector);
   yield runAutocompletionTest(toolbox, inspector, view);
 });
 
 function* runAutocompletionTest(toolbox, inspector, view) {
   info("Selecting the test node");
   yield selectNode("h1", inspector);
 
   info("Focusing a new css property editable property");
@@ -96,17 +96,17 @@ function* testCompletion([key, modifiers
     info("Waiting for after-suggest event on the editor");
     onKeyPress = editor.once("after-suggest");
   }
 
   info("Synthesizing key " + key + ", modifiers: " + Object.keys(modifiers));
   EventUtils.synthesizeKey(key, modifiers, view.styleWindow);
 
   yield onKeyPress;
-  yield waitForTick();
+  yield wait(1); // Equivalent of executeSoon
 
   info("Checking the state");
   if (completion != null) {
     // The key might have been a TAB or shift-TAB, in which case the editor will
     // be a new one
     editor = inplaceEditor(view.styleDocument.activeElement);
     is(editor.input.value, completion, "Correct value is autocompleted");
   }
--- a/devtools/client/inspector/rules/test/browser_rules_completion-popup-hidden-after-navigation.js
+++ b/devtools/client/inspector/rules/test/browser_rules_completion-popup-hidden-after-navigation.js
@@ -5,17 +5,17 @@
 "use strict";
 
 // Tests that the ruleview autocomplete popup is hidden after page navigation.
 
 const TEST_URI = "<h1 style='font: 24px serif'></h1>";
 
 add_task(function*() {
   yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
-  let {inspector, view, testActor} = yield openRuleView();
+  let {inspector, view} = yield openRuleView();
 
   info("Test autocompletion popup is hidden after page navigation");
 
   info("Selecting the test node");
   yield selectNode("h1", inspector);
 
   info("Focusing the css property editable field");
   let propertyName = view.styleDocument
@@ -23,17 +23,17 @@ add_task(function*() {
   let editor = yield focusEditableField(view, propertyName);
 
   info("Pressing key VK_DOWN");
   let onSuggest = once(editor.input, "keypress");
   EventUtils.synthesizeKey("VK_DOWN", {}, view.styleWindow);
 
   info("Waiting for autocomplete popup to be displayed");
   yield onSuggest;
-  yield waitForTick();
+  yield wait(1);
 
   ok(view.popup && view.popup.isOpen, "Popup should be opened");
 
   info("Reloading the page");
-  yield reloadPage(inspector, testActor);
+  yield reloadPage(inspector);
 
   ok(!(view.popup && view.popup.isOpen), "Popup should be closed");
 });
--- a/devtools/client/inspector/rules/test/browser_rules_computed-lists_02.js
+++ b/devtools/client/inspector/rules/test/browser_rules_computed-lists_02.js
@@ -26,49 +26,43 @@ add_task(function*() {
 
 function* testComputedList(inspector, view) {
   let rule = getRuleViewRuleEditor(view, 1).rule;
   let propEditor = rule.textProps[0].editor;
   let expander = propEditor.expander;
 
   ok(!expander.hasAttribute("open"), "margin computed list is closed");
 
-  info("Opening the computed list of margin property");
+  info("Opening the computed list of margin property")
   expander.click();
   ok(expander.hasAttribute("open"), "margin computed list is open");
 
   let computed = propEditor.prop.computed;
   let computedDom = propEditor.computed;
   let propNames = [
     "margin-top",
     "margin-right",
     "margin-bottom",
     "margin-left"
   ];
 
   is(computed.length, propNames.length, "There should be 4 computed values");
-  is(computedDom.children.length, propNames.length,
-     "There should be 4 nodes in the DOM");
-
+  is(computedDom.children.length, propNames.length, "There should be 4 nodes in the DOM");
   propNames.forEach((propName, i) => {
     let propValue = i + "px";
-    is(computed[i].name, propName,
-       "Computed property #" + i + " has name " + propName);
-    is(computed[i].value, propValue,
-       "Computed property #" + i + " has value " + propValue);
-    is(computedDom.querySelectorAll(".ruleview-propertyname")[i].textContent,
-       propName,
-       "Computed property #" + i + " in DOM has correct name");
-    is(computedDom.querySelectorAll(".ruleview-propertyvalue")[i].textContent,
-       propValue,
-       "Computed property #" + i + " in DOM has correct value");
+    is(computed[i].name, propName, "Computed property #" + i + " has name " + propName);
+    is(computed[i].value, propValue, "Computed property #" + i + " has value " + propValue);
+    is(computedDom.getElementsByClassName("ruleview-propertyname")[i].textContent, propName,
+        "Computed property #" + i + " in DOM has correct name");
+    is(computedDom.getElementsByClassName("ruleview-propertyvalue")[i].textContent, propValue,
+        "Computed property #" + i + " in DOM has correct value");
   });
 
-  info("Closing the computed list of margin property");
+  info("Closing the computed list of margin property")
   expander.click();
   ok(!expander.hasAttribute("open"), "margin computed list is closed");
 
-  info("Opening the computed list of margin property");
+  info("Opening the computed list of margin property")
   expander.click();
   ok(expander.hasAttribute("open"), "margin computed list is open");
   is(computed.length, propNames.length, "Still 4 computed values");
   is(computedDom.children.length, propNames.length, "Still 4 nodes in the DOM");
 }
--- a/devtools/client/inspector/rules/test/browser_rules_content_01.js
+++ b/devtools/client/inspector/rules/test/browser_rules_content_01.js
@@ -1,51 +1,54 @@
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 // Test that the rule-view content is correct
 
-const TEST_URI = `
-  <style type="text/css">
-    @media screen and (min-width: 10px) {
-      #testid {
-        background-color: blue;
-      }
-    }
-    .testclass, .unmatched {
-      background-color: green;
-    }
-  </style>
-  <div id="testid" class="testclass">Styled Node</div>
-  <div id="testid2">Styled Node</div>
-`;
+add_task(function*() {
+  yield addTab("data:text/html;charset=utf-8,browser_ruleview_content.js");
+  let {toolbox, inspector, view} = yield openRuleView();
 
-add_task(function*() {
-  yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
-  let {inspector, view} = yield openRuleView();
+  info("Creating the test document");
+  let style = "" +
+    "@media screen and (min-width: 10px) {" +
+    "  #testid {" +
+    "    background-color: blue;" +
+    "  }" +
+    "}" +
+    ".testclass, .unmatched {" +
+    "  background-color: green;" +
+    "}";
+  let styleNode = addStyle(content.document, style);
+  content.document.body.innerHTML = "<div id='testid' class='testclass'>Styled Node</div>" +
+                                    "<div id='testid2'>Styled Node</div>";
 
+  yield testContentAfterNodeSelection(inspector, view);
+});
+
+function* testContentAfterNodeSelection(inspector, ruleView) {
   yield selectNode("#testid", inspector);
-  is(view.element.querySelectorAll("#noResults").length, 0,
+  is(ruleView.element.querySelectorAll("#noResults").length, 0,
     "After a highlight, no longer has a no-results element.");
 
-  yield clearCurrentNodeSelection(inspector);
-  is(view.element.querySelectorAll("#noResults").length, 1,
+  yield clearCurrentNodeSelection(inspector)
+  is(ruleView.element.querySelectorAll("#noResults").length, 1,
     "After highlighting null, has a no-results element again.");
 
   yield selectNode("#testid", inspector);
 
-  let linkText = getRuleViewLinkTextByIndex(view, 1);
-  is(linkText, "inline:3 @screen and (min-width: 10px)",
+  let linkText = getRuleViewLinkTextByIndex(ruleView, 1);
+  is(linkText, "inline:1 @screen and (min-width: 10px)",
     "link text at index 1 contains media query text.");
 
-  linkText = getRuleViewLinkTextByIndex(view, 2);
-  is(linkText, "inline:7",
+  linkText = getRuleViewLinkTextByIndex(ruleView, 2);
+  is(linkText, "inline:1",
     "link text at index 2 contains no media query text.");
 
-  let selector = getRuleViewRuleEditor(view, 2).selectorText;
-  is(selector.querySelector(".ruleview-selector-matched").textContent,
+  let classEditor = getRuleViewRuleEditor(ruleView, 2);
+  is(classEditor.selectorText.querySelector(".ruleview-selector-matched").textContent,
     ".testclass", ".textclass should be matched.");
-  is(selector.querySelector(".ruleview-selector-unmatched").textContent,
+  is(classEditor.selectorText.querySelector(".ruleview-selector-unmatched").textContent,
     ".unmatched", ".unmatched should not be matched.");
-});
+}
--- a/devtools/client/inspector/rules/test/browser_rules_content_02.js
+++ b/devtools/client/inspector/rules/test/browser_rules_content_02.js
@@ -1,26 +1,24 @@
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
-/* globals getTestActorWithoutToolbox */
+
 "use strict";
 
 // Test the rule-view content when the inspector gets opened via the page
 // ctx-menu "inspect element"
 
-const CONTENT = `
-  <body style="color:red;">
-    <div style="color:blue;">
-      <p style="color:green;">
-        <span style="color:yellow;">test element</span>
-      </p>
-    </div>
-  </body>
-`;
+const CONTENT = '<body style="color:red;">\
+                   <div style="color:blue;">\
+                     <p style="color:green;">\
+                       <span style="color:yellow;">test element</span>\
+                     </p>\
+                   </div>\
+                 </body>';
 
 const STRINGS = Services.strings
   .createBundle("chrome://devtools-shared/locale/styleinspector.properties");
 
 add_task(function*() {
   let tab = yield addTab("data:text/html;charset=utf-8," + CONTENT);
 
   let testActor = yield getTestActorWithoutToolbox(tab);
@@ -50,17 +48,15 @@ function checkRuleViewContent({styleDocu
 
   for (let rule of rules) {
     let selector = rule.querySelector(".ruleview-selectorcontainer");
     is(selector.textContent,
       STRINGS.GetStringFromName("rule.sourceElement"),
       "The rule's selector is correct");
 
     let propertyNames = [...rule.querySelectorAll(".ruleview-propertyname")];
-    is(propertyNames.length, 1,
-       "There's only one property name, as expected");
+    is(propertyNames.length, 1, "There's only one property name, as expected");
 
     let propertyValues = [...rule.querySelectorAll(".ruleview-propertyvalue")];
-    is(propertyValues.length, 1,
-       "There's only one property value, as expected");
+    is(propertyValues.length, 1, "There's only one property value, as expected");
   }
 }
 
--- a/devtools/client/inspector/rules/test/browser_rules_context-menu-show-mdn-docs-01.js
+++ b/devtools/client/inspector/rules/test/browser_rules_context-menu-show-mdn-docs-01.js
@@ -11,16 +11,18 @@
  * docs tooltip should be shown, containing docs from MDN for that property.
  *
  * This file tests that the context menu item is shown when it should be
  * shown and hidden when it should be hidden.
  */
 
 "use strict";
 
+const {setBaseCssDocsUrl} = require("devtools/client/shared/widgets/MdnDocsWidget");
+
 /**
  * The test document tries to confuse the context menu
  * code by having a tag called "padding" and a property
  * value called "margin".
  */
 const TEST_URI = `
   <html>
     <head>
--- a/devtools/client/inspector/rules/test/browser_rules_context-menu-show-mdn-docs-02.js
+++ b/devtools/client/inspector/rules/test/browser_rules_context-menu-show-mdn-docs-02.js
@@ -12,18 +12,17 @@
  *
  * This file tests that:
  * - clicking the context menu item shows the tooltip
  * - pressing "Escape" while the tooltip is showing hides the tooltip
  */
 
 "use strict";
 
-const {setBaseCssDocsUrl} =
-  require("devtools/client/shared/widgets/MdnDocsWidget");
+const {setBaseCssDocsUrl} = require("devtools/client/shared/widgets/MdnDocsWidget");
 
 const PROPERTYNAME = "color";
 
 const TEST_DOC = `
   <html>
     <body>
       <div style="color: red">
         Test "Show MDN Docs" context menu option
@@ -66,20 +65,23 @@ function* testShowMdnTooltip(view) {
  *  - the tooltip is hidden when we press Escape
  */
 function* testShowAndHideMdnTooltip(view) {
   yield testShowMdnTooltip(view);
 
   info("Quick check that the tooltip contents are set");
   let cssDocs = view.tooltips.cssDocs;
 
-  // FIXME: Remove the comment below when bug 1246896 is fixed.
-  /* eslint-disable mozilla/no-cpows-in-tests */
   let tooltipDocument = cssDocs.tooltip.content.contentDocument;
   let h1 = tooltipDocument.getElementById("property-name");
   is(h1.textContent, PROPERTYNAME, "The MDN docs tooltip h1 is correct");
 
   info("Simulate pressing the 'Escape' key");
   let onHidden = cssDocs.tooltip.once("hidden");
   EventUtils.sendKey("escape");
   yield onHidden;
   ok(true, "The MDN docs tooltip was hidden on pressing 'escape'");
 }
+
+/**
+ * Returns the root element for the rule view.
+ */
+var rootElement = view => (view.element) ? view.element : view.styleDocument;
--- a/devtools/client/inspector/rules/test/browser_rules_copy_styles.js
+++ b/devtools/client/inspector/rules/test/browser_rules_copy_styles.js
@@ -254,27 +254,30 @@ function* checkCopyStyle(view, node, men
   is(view._contextmenu.menuitemCopyRule.hidden,
      hidden.copyRule,
      "Copy Rule hidden attribute is as expected: " +
      hidden.copyRule);
 
   try {
     yield waitForClipboard(() => menuItem.click(),
       () => checkClipboardData(expectedPattern));
-  } catch (e) {
+  } catch(e) {
     failedClipboard(expectedPattern);
   }
 
   view._contextmenu._menupopup.hidePopup();
 }
 
 function* disableProperty(view, index) {
   let ruleEditor = getRuleViewRuleEditor(view, 1);
-  let textProp = ruleEditor.rule.textProps[index];
-  yield togglePropStatus(view, textProp);
+  let propEditor = ruleEditor.rule.textProps[index].editor;
+
+  info("Disabling a property");
+  propEditor.enable.click();
+  yield ruleEditor.rule._applyingModifications;
 }
 
 function checkClipboardData(expectedPattern) {
   let actual = SpecialPowers.getClipboardData("text/unicode");
   let expectedRegExp = new RegExp(expectedPattern, "g");
   return expectedRegExp.test(actual);
 }
 
--- a/devtools/client/inspector/rules/test/browser_rules_cubicbezier-commit-on-ENTER.js
+++ b/devtools/client/inspector/rules/test/browser_rules_cubicbezier-commit-on-ENTER.js
@@ -34,33 +34,30 @@ function* testPressingEnterCommitsChange
   swatch.click();
   yield onShown;
 
   let widget = yield bezierTooltip.widget;
   info("Simulating a change of curve in the widget");
   widget.coordinates = [0.1, 2, 0.9, -1];
   let expected = "cubic-bezier(0.1, 2, 0.9, -1)";
 
-  yield waitForSuccess(function*() {
-    let func = yield getComputedStyleProperty("body", null,
-                                              "transition-timing-function");
-    return func === expected;
+  yield waitForSuccess(() => {
+    return content.getComputedStyle(content.document.body)
+      .transitionTimingFunction === expected;
   }, "Waiting for the change to be previewed on the element");
 
   ok(getRuleViewProperty(ruleView, "body", "transition").valueSpan.textContent
     .indexOf("cubic-bezier(") !== -1,
     "The text of the timing-function was updated");
 
   info("Sending RETURN key within the tooltip document");
   // Pressing RETURN ends up doing 2 rule-view updates, one for the preview and
   // one for the commit when the tooltip closes.
   let onRuleViewChanged = waitForNEvents(ruleView, "ruleview-changed", 2);
   EventUtils.sendKey("RETURN", widget.parent.ownerDocument.defaultView);
   yield onRuleViewChanged;
 
-  let style = yield getComputedStyleProperty("body", null,
-                                             "transition-timing-function");
-  is(style, expected, "The element's timing-function was kept after RETURN");
-
-  let ruleViewStyle = getRuleViewProperty(ruleView, "body", "transition")
-                      .valueSpan.textContent.indexOf("cubic-bezier(") !== -1;
-  ok(ruleViewStyle, "The text of the timing-function was kept after RETURN");
+  is(content.getComputedStyle(content.document.body).transitionTimingFunction,
+    expected, "The element's timing-function was kept after RETURN");
+  ok(getRuleViewProperty(ruleView, "body", "transition").valueSpan.textContent
+    .indexOf("cubic-bezier(") !== -1,
+    "The text of the timing-function was kept after RETURN");
 }
--- a/devtools/client/inspector/rules/test/browser_rules_cubicbezier-revert-on-ESC.js
+++ b/devtools/client/inspector/rules/test/browser_rules_cubicbezier-revert-on-ESC.js
@@ -18,56 +18,87 @@ const TEST_URI = `
 add_task(function*() {
   yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
   let {view} = yield openRuleView();
   yield testPressingEscapeRevertsChanges(view);
   yield testPressingEscapeRevertsChangesAndDisables(view);
 });
 
 function* testPressingEscapeRevertsChanges(view) {
-  let {propEditor} = yield openCubicBezierAndChangeCoords(view, 1, 0,
-    [0.1, 2, 0.9, -1], {
-      selector: "body",
-      name: "animation-timing-function",
-      value: "cubic-bezier(0.1, 2, 0.9, -1)"
-    });
+  let ruleEditor = getRuleViewRuleEditor(view, 1);
+  let propEditor = ruleEditor.rule.textProps[0].editor;
+  let swatch = propEditor.valueSpan.querySelector(".ruleview-bezierswatch");
+  let bezierTooltip = view.tooltips.cubicBezier;
 
+  let onShown = bezierTooltip.tooltip.once("shown");
+  swatch.click();
+  yield onShown;
+
+  let widget = yield bezierTooltip.widget;
+  info("Simulating a change of curve in the widget");
+  widget.coordinates = [0.1, 2, 0.9, -1];
+  yield ruleEditor.rule._applyingModifications;
+
+  yield waitForComputedStyleProperty("body", null, "animation-timing-function",
+    "cubic-bezier(0.1, 2, 0.9, -1)");
   is(propEditor.valueSpan.textContent, "cubic-bezier(.1,2,.9,-1)",
     "Got expected property value.");
 
-  yield escapeTooltip(view);
+  info("Pressing ESCAPE to close the tooltip");
+  let onHidden = bezierTooltip.tooltip.once("hidden");
+  EventUtils.sendKey("ESCAPE", widget.parent.ownerDocument.defaultView);
+  yield onHidden;
+  yield ruleEditor.rule._applyingModifications;
 
   yield waitForComputedStyleProperty("body", null, "animation-timing-function",
     "linear");
   is(propEditor.valueSpan.textContent, "linear",
     "Got expected property value.");
 }
 
 function* testPressingEscapeRevertsChangesAndDisables(view) {
   let ruleEditor = getRuleViewRuleEditor(view, 1);
-  let textProp = ruleEditor.rule.textProps[0];
-  let propEditor = textProp.editor;
+  let propEditor = ruleEditor.rule.textProps[0].editor;
+  let swatch = propEditor.valueSpan.querySelector(".ruleview-bezierswatch");
+  let bezierTooltip = view.tooltips.cubicBezier;
 
   info("Disabling animation-timing-function property");
-  yield togglePropStatus(view, textProp);
+  propEditor.enable.click();
+  yield ruleEditor.rule._applyingModifications;
 
   ok(propEditor.element.classList.contains("ruleview-overridden"),
     "property is overridden.");
   is(propEditor.enable.style.visibility, "visible",
     "property enable checkbox is visible.");
   ok(!propEditor.enable.getAttribute("checked"),
     "property enable checkbox is not checked.");
   ok(!propEditor.prop.enabled,
     "animation-timing-function property is disabled.");
   let newValue = yield getRulePropertyValue("animation-timing-function");
   is(newValue, "", "animation-timing-function should have been unset.");
 
-  yield openCubicBezierAndChangeCoords(view, 1, 0, [0.1, 2, 0.9, -1]);
+  let onShown = bezierTooltip.tooltip.once("shown");
+  swatch.click();
+  yield onShown;
+
+  ok(!propEditor.element.classList.contains("ruleview-overridden"),
+    "property overridden is not displayed.");
+  is(propEditor.enable.style.visibility, "hidden",
+    "property enable checkbox is hidden.");
 
-  yield escapeTooltip(view);
+  let widget = yield bezierTooltip.widget;
+  info("Simulating a change of curve in the widget");
+  widget.coordinates = [0.1, 2, 0.9, -1];
+  yield ruleEditor.rule._applyingModifications;
+
+  info("Pressing ESCAPE to close the tooltip");
+  let onHidden = bezierTooltip.tooltip.once("hidden");
+  EventUtils.sendKey("ESCAPE", widget.parent.ownerDocument.defaultView);
+  yield onHidden;
+  yield ruleEditor.rule._applyingModifications;
 
   ok(propEditor.element.classList.contains("ruleview-overridden"),
     "property is overridden.");
   is(propEditor.enable.style.visibility, "visible",
     "property enable checkbox is visible.");
   ok(!propEditor.enable.getAttribute("checked"),
     "property enable checkbox is not checked.");
   ok(!propEditor.prop.enabled,
@@ -81,20 +112,8 @@ function* testPressingEscapeRevertsChang
 function* getRulePropertyValue(name) {
   let propValue = yield executeInContent("Test:GetRulePropertyValue", {
     styleSheetIndex: 0,
     ruleIndex: 0,
     name: name
   });
   return propValue;
 }
-
-function* escapeTooltip(view) {
-  info("Pressing ESCAPE to close the tooltip");
-
-  let bezierTooltip = view.tooltips.cubicBezier;
-  let widget = yield bezierTooltip.widget;
-  let onHidden = bezierTooltip.tooltip.once("hidden");
-  let onModifications = view.once("ruleview-changed");
-  EventUtils.sendKey("ESCAPE", widget.parent.ownerDocument.defaultView);
-  yield onHidden;
-  yield onModifications;
-}
--- a/devtools/client/inspector/rules/test/browser_rules_custom.js
+++ b/devtools/client/inspector/rules/test/browser_rules_custom.js
@@ -15,58 +15,66 @@ add_task(function*() {
   yield simpleCustomOverride(inspector, view);
   yield importantCustomOverride(inspector, view);
   yield disableCustomOverride(inspector, view);
 });
 
 function* simpleCustomOverride(inspector, view) {
   yield selectNode("#testidSimple", inspector);
 
-  let idRule = getRuleViewRuleEditor(view, 1).rule;
-  let idRuleProp = idRule.textProps[0];
-
-  is(idRuleProp.name, "--background-color",
-     "First ID prop should be --background-color");
-  ok(!idRuleProp.overridden, "ID prop should not be overridden.");
+  let elementStyle = view._elementStyle;
 
-  let classRule = getRuleViewRuleEditor(view, 2).rule;
-  let classRuleProp = classRule.textProps[0];
+  let idRule = elementStyle.rules[1];
+  let idProp = idRule.textProps[0];
+  is(idProp.name, "--background-color",
+     "First ID prop should be --background-color");
+  ok(!idProp.overridden, "ID prop should not be overridden.");
 
-  is(classRuleProp.name, "--background-color",
+  let classRule = elementStyle.rules[2];
+  let classProp = classRule.textProps[0];
+  is(classProp.name, "--background-color",
      "First class prop should be --background-color");
-  ok(classRuleProp.overridden, "Class property should be overridden.");
+  ok(classProp.overridden, "Class property should be overridden.");
 
   // Override --background-color by changing the element style.
-  let elementProp = yield addProperty(view, 0, "--background-color", "purple");
+  let elementRule = elementStyle.rules[0];
+  elementRule.createProperty("--background-color", "purple", "");
+  yield elementRule._applyingModifications;
 
-  is(classRuleProp.name, "--background-color",
+  let elementProp = elementRule.textProps[0];
+  is(classProp.name, "--background-color",
      "First element prop should now be --background-color");
   ok(!elementProp.overridden,
      "Element style property should not be overridden");
-  ok(idRuleProp.overridden, "ID property should be overridden");
-  ok(classRuleProp.overridden, "Class property should be overridden");
+  ok(idProp.overridden, "ID property should be overridden");
+  ok(classProp.overridden, "Class property should be overridden");
 }
 
 function* importantCustomOverride(inspector, view) {
   yield selectNode("#testidImportant", inspector);
 
-  let idRule = getRuleViewRuleEditor(view, 1).rule;
-  let idRuleProp = idRule.textProps[0];
-  ok(idRuleProp.overridden, "Not-important rule should be overridden.");
+  let elementStyle = view._elementStyle;
 
-  let classRule = getRuleViewRuleEditor(view, 2).rule;
-  let classRuleProp = classRule.textProps[0];
-  ok(!classRuleProp.overridden, "Important rule should not be overridden.");
+  let idRule = elementStyle.rules[1];
+  let idProp = idRule.textProps[0];
+  ok(idProp.overridden, "Not-important rule should be overridden.");
+
+  let classRule = elementStyle.rules[2];
+  let classProp = classRule.textProps[0];
+  ok(!classProp.overridden, "Important rule should not be overridden.");
 }
 
 function* disableCustomOverride(inspector, view) {
   yield selectNode("#testidDisable", inspector);
 
-  let idRule = getRuleViewRuleEditor(view, 1).rule;
-  let idRuleProp = idRule.textProps[0];
+  let elementStyle = view._elementStyle;
+
+  let idRule = elementStyle.rules[1];
+  let idProp = idRule.textProps[0];
 
-  yield togglePropStatus(view, idRuleProp);
+  idProp.setEnabled(false);
+  yield idRule._applyingModifications;
 
-  let classRule = getRuleViewRuleEditor(view, 2).rule;
-  let classRuleProp = classRule.textProps[0];
-  ok(!classRuleProp.overridden,
+  let classRule = elementStyle.rules[2];
+  let classProp = classRule.textProps[0];
+  ok(!classProp.overridden,
      "Class prop should not be overridden after id prop was disabled.");
 }
--- a/devtools/client/inspector/rules/test/browser_rules_edit-property-cancel.js
+++ b/devtools/client/inspector/rules/test/browser_rules_edit-property-cancel.js
@@ -15,40 +15,43 @@ const TEST_URI = `
   </style>
   <div id='testid'>Styled Node</div>
 `;
 
 add_task(function*() {
   yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
   let {inspector, view} = yield openRuleView();
   yield selectNode("#testid", inspector);
+  yield testEditPropertyAndCancel(inspector, view);
+});
 
+function* testEditPropertyAndCancel(inspector, view) {
   let ruleEditor = getRuleViewRuleEditor(view, 1);
   let propEditor = ruleEditor.rule.textProps[0].editor;
 
   yield focusEditableField(view, propEditor.nameSpan);
   yield sendCharsAndWaitForFocus(view, ruleEditor.element,
     ["VK_DELETE", "VK_ESCAPE"]);
+  yield ruleEditor.rule._applyingModifications;
 
   is(propEditor.nameSpan.textContent, "background-color",
     "'background-color' property name is correctly set.");
   is((yield getComputedStyleProperty("#testid", null, "background-color")),
     "rgb(0, 0, 255)", "#00F background color is set.");
 
   yield focusEditableField(view, propEditor.valueSpan);
-  let onValueDeleted = view.once("ruleview-changed");
   yield sendCharsAndWaitForFocus(view, ruleEditor.element,
     ["VK_DELETE", "VK_ESCAPE"]);
-  yield onValueDeleted;
+  yield ruleEditor.rule._applyingModifications;
 
   is(propEditor.valueSpan.textContent, "#00F",
     "'#00F' property value is correctly set.");
   is((yield getComputedStyleProperty("#testid", null, "background-color")),
     "rgb(0, 0, 255)", "#00F background color is set.");
-});
+}
 
 function* sendCharsAndWaitForFocus(view, element, chars) {
   let onFocus = once(element, "focus", true);
   for (let ch of chars) {
     EventUtils.sendChar(ch, view.styleWindow);
   }
   yield onFocus;
 }
--- a/devtools/client/inspector/rules/test/browser_rules_edit-property-increments.js
+++ b/devtools/client/inspector/rules/test/browser_rules_edit-property-increments.js
@@ -2,62 +2,63 @@
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 // Test that increasing/decreasing values in rule view using
 // arrow keys works correctly.
 
-const TEST_URI = `
-  <style>
-    #test {
-      margin-top: 0px;
-      padding-top: 0px;
-      color: #000000;
-      background-color: #000000;
-      background: none;
-      transition: initial;
-      z-index: 0;
-    }
-  </style>
-  <div id="test"></div>
-`;
-
 add_task(function*() {
-  yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
+  yield addTab("data:text/html;charset=utf-8,sample document for bug 722691");
+  createDocument();
 
   let {inspector, view} = yield openRuleView();
   yield selectNode("#test", inspector);
 
   yield testMarginIncrements(view);
   yield testVariousUnitIncrements(view);
   yield testHexIncrements(view);
   yield testRgbIncrements(view);
   yield testShorthandIncrements(view);
   yield testOddCases(view);
   yield testZeroValueIncrements(view);
 });
 
+function createDocument() {
+  content.document.body.innerHTML = "" +
+    "<style>" +
+    "  #test {" +
+    "    margin-top:0px;" +
+    "    padding-top: 0px;" +
+    "    color:#000000;" +
+    "    background-color: #000000;" +
+    "    background: none;" +
+    "    transition: initial;" +
+    "    z-index: 0;" +
+    "  }" +
+    "</style>" +
+    "<div id=\"test\"></div>";
+}
+
 function* testMarginIncrements(view) {
   info("Testing keyboard increments on the margin property");
 
   let idRuleEditor = getRuleViewRuleEditor(view, 1);
   let marginPropEditor = idRuleEditor.rule.textProps[0].editor;
 
   yield runIncrementTest(marginPropEditor, view, {
     1: {alt: true, start: "0px", end: "0.1px", selectAll: true},
     2: {start: "0px", end: "1px", selectAll: true},
     3: {shift: true, start: "0px", end: "10px", selectAll: true},
     4: {down: true, alt: true, start: "0.1px", end: "0px", selectAll: true},
     5: {down: true, start: "0px", end: "-1px", selectAll: true},
     6: {down: true, shift: true, start: "0px", end: "-10px", selectAll: true},
     7: {pageUp: true, shift: true, start: "0px", end: "100px", selectAll: true},
-    8: {pageDown: true, shift: true, start: "0px", end: "-100px",
-        selectAll: true},
+    8: {pageDown: true, shift: true, start: "0px", end: "-100px", selectAll: true},
     9: {start: "0", end: "1px", selectAll: true},
     10: {down: true, start: "0", end: "-1px", selectAll: true},
   });
 }
 
 function* testVariousUnitIncrements(view) {
   info("Testing keyboard increments on values with various units");
 
@@ -86,63 +87,52 @@ function* testHexIncrements(view) {
   let hexColorPropEditor = idRuleEditor.rule.textProps[2].editor;
 
   yield runIncrementTest(hexColorPropEditor, view, {
     1: {start: "#CCCCCC", end: "#CDCDCD", selectAll: true},
     2: {shift: true, start: "#CCCCCC", end: "#DCDCDC", selectAll: true},
     3: {start: "#CCCCCC", end: "#CDCCCC", selection: [1, 3]},
     4: {shift: true, start: "#CCCCCC", end: "#DCCCCC", selection: [1, 3]},
     5: {start: "#FFFFFF", end: "#FFFFFF", selectAll: true},
-    6: {down: true, shift: true, start: "#000000", end: "#000000",
-        selectAll: true}
+    6: {down: true, shift: true, start: "#000000", end: "#000000", selectAll: true}
   });
 }
 
 function* testRgbIncrements(view) {
   info("Testing keyboard increments with rgb colors");
 
   let idRuleEditor = getRuleViewRuleEditor(view, 1);
   let rgbColorPropEditor = idRuleEditor.rule.textProps[3].editor;
 
   yield runIncrementTest(rgbColorPropEditor, view, {
     1: {start: "rgb(0,0,0)", end: "rgb(0,1,0)", selection: [6, 7]},
-    2: {shift: true, start: "rgb(0,0,0)", end: "rgb(0,10,0)",
-        selection: [6, 7]},
+    2: {shift: true, start: "rgb(0,0,0)", end: "rgb(0,10,0)", selection: [6, 7]},
     3: {start: "rgb(0,255,0)", end: "rgb(0,255,0)", selection: [6, 9]},
-    4: {shift: true, start: "rgb(0,250,0)", end: "rgb(0,255,0)",
-        selection: [6, 9]},
+    4: {shift: true, start: "rgb(0,250,0)", end: "rgb(0,255,0)", selection: [6, 9]},
     5: {down: true, start: "rgb(0,0,0)", end: "rgb(0,0,0)", selection: [6, 7]},
-    6: {down: true, shift: true, start: "rgb(0,5,0)", end: "rgb(0,0,0)",
-        selection: [6, 7]}
+    6: {down: true, shift: true, start: "rgb(0,5,0)", end: "rgb(0,0,0)", selection: [6, 7]}
   });
 }
 
 function* testShorthandIncrements(view) {
   info("Testing keyboard increments within shorthand values");
 
   let idRuleEditor = getRuleViewRuleEditor(view, 1);
   let paddingPropEditor = idRuleEditor.rule.textProps[1].editor;
 
   yield runIncrementTest(paddingPropEditor, view, {
     1: {start: "0px 0px 0px 0px", end: "0px 1px 0px 0px", selection: [4, 7]},
-    2: {shift: true, start: "0px 0px 0px 0px", end: "0px 10px 0px 0px",
-        selection: [4, 7]},
+    2: {shift: true, start: "0px 0px 0px 0px", end: "0px 10px 0px 0px", selection: [4, 7]},
     3: {start: "0px 0px 0px 0px", end: "1px 0px 0px 0px", selectAll: true},
-    4: {shift: true, start: "0px 0px 0px 0px", end: "10px 0px 0px 0px",
-        selectAll: true},
-    5: {down: true, start: "0px 0px 0px 0px", end: "0px 0px -1px 0px",
-        selection: [8, 11]},
-    6: {down: true, shift: true, start: "0px 0px 0px 0px",
-        end: "-10px 0px 0px 0px", selectAll: true},
-    7: {up: true, start: "0.1em .1em 0em 0em", end: "0.1em 1.1em 0em 0em",
-        selection: [6, 9]},
-    8: {up: true, alt: true, start: "0.1em .9em 0em 0em",
-        end: "0.1em 1em 0em 0em", selection: [6, 9]},
-    9: {up: true, shift: true, start: "0.2em .2em 0em 0em",
-        end: "0.2em 10.2em 0em 0em", selection: [6, 9]}
+    4: {shift: true, start: "0px 0px 0px 0px", end: "10px 0px 0px 0px", selectAll: true},
+    5: {down: true, start: "0px 0px 0px 0px", end: "0px 0px -1px 0px", selection: [8, 11]},
+    6: {down: true, shift: true, start: "0px 0px 0px 0px", end: "-10px 0px 0px 0px", selectAll: true},
+    7: {up: true, start: "0.1em .1em 0em 0em", end: "0.1em 1.1em 0em 0em", selection: [6, 9]},
+    8: {up: true, alt: true, start: "0.1em .9em 0em 0em", end: "0.1em 1em 0em 0em", selection: [6, 9]},
+    9: {up: true, shift: true, start: "0.2em .2em 0em 0em", end: "0.2em 10.2em 0em 0em", selection: [6, 9]}
   });
 }
 
 function* testOddCases(view) {
   info("Testing some more odd cases");
 
   let idRuleEditor = getRuleViewRuleEditor(view, 1);
   let marginPropEditor = idRuleEditor.rule.textProps[0].editor;
@@ -150,29 +140,23 @@ function* testOddCases(view) {
   yield runIncrementTest(marginPropEditor, view, {
     1: {start: "98.7%", end: "99.7%", selection: [3, 3]},
     2: {alt: true, start: "98.7%", end: "98.8%", selection: [3, 3]},
     3: {start: "0", end: "1px"},
     4: {down: true, start: "0", end: "-1px"},
     5: {start: "'a=-1'", end: "'a=0'", selection: [4, 4]},
     6: {start: "0 -1px", end: "0 0px", selection: [2, 2]},
     7: {start: "url(-1)", end: "url(-1)", selection: [4, 4]},
-    8: {start: "url('test1.1.png')", end: "url('test1.2.png')",
-        selection: [11, 11]},
+    8: {start: "url('test1.1.png')", end: "url('test1.2.png')", selection: [11, 11]},
     9: {start: "url('test1.png')", end: "url('test2.png')", selection: [9, 9]},
-    10: {shift: true, start: "url('test1.1.png')", end: "url('test11.1.png')",
-         selection: [9, 9]},
-    11: {down: true, start: "url('test-1.png')", end: "url('test-2.png')",
-         selection: [9, 11]},
-    12: {start: "url('test1.1.png')", end: "url('test1.2.png')",
-         selection: [11, 12]},
-    13: {down: true, alt: true, start: "url('test-0.png')",
-         end: "url('test--0.1.png')", selection: [10, 11]},
-    14: {alt: true, start: "url('test--0.1.png')", end: "url('test-0.png')",
-         selection: [10, 14]}
+    10: {shift: true, start: "url('test1.1.png')", end: "url('test11.1.png')", selection: [9, 9]},
+    11: {down: true, start: "url('test-1.png')", end: "url('test-2.png')", selection: [9, 11]},
+    12: {start: "url('test1.1.png')", end: "url('test1.2.png')", selection: [11, 12]},
+    13: {down: true, alt: true, start: "url('test-0.png')", end: "url('test--0.1.png')", selection: [10, 11]},
+    14: {alt: true, start: "url('test--0.1.png')", end: "url('test-0.png')", selection: [10, 14]},
   });
 }
 
 function* testZeroValueIncrements(view) {
   info("Testing a valid unit is added when incrementing from 0");
 
   let idRuleEditor = getRuleViewRuleEditor(view, 1);
   let backgroundPropEditor = idRuleEditor.rule.textProps[4].editor;
@@ -229,25 +213,19 @@ function* testIncrement(editor, options,
   } else if (options.selection) {
     input.setSelectionRange(options.selection[0], options.selection[1]);
   }
 
   is(input.value, options.start, "Value initialized at " + options.start);
 
   let onRuleViewChanged = view.once("ruleview-changed");
   let onKeyUp = once(input, "keyup");
-
   let key;
   key = options.down ? "VK_DOWN" : "VK_UP";
-  if (options.pageDown) {
-    key = "VK_PAGE_DOWN";
-  } else if (options.pageUp) {
-    key = "VK_PAGE_UP";
-  }
-
+  key = options.pageDown ? "VK_PAGE_DOWN" : options.pageUp ? "VK_PAGE_UP" : key;
   EventUtils.synthesizeKey(key, {altKey: options.alt, shiftKey: options.shift},
     view.styleWindow);
   yield onKeyUp;
   // Only expect a change if the value actually changed!
   if (options.start !== options.end) {
     yield onRuleViewChanged;
   }
 
--- a/devtools/client/inspector/rules/test/browser_rules_edit-property-order.js
+++ b/devtools/client/inspector/rules/test/browser_rules_edit-property-order.js
@@ -1,89 +1,82 @@
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 // Checking properties orders and overrides in the rule-view.
 
-const TEST_URI = "<style>#testid {}</style><div id='testid'>Styled Node</div>";
+const TEST_URI = "<div id='testid'>Styled Node</div>";
 
 add_task(function*() {
   yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
   let {inspector, view} = yield openRuleView();
   yield selectNode("#testid", inspector);
 
+  let element = getNode("#testid");
   let elementStyle = view._elementStyle;
-  let elementRule = elementStyle.rules[1];
+  let elementRule = elementStyle.rules[0];
 
   info("Checking rules insertion order and checking the applied style");
-  let firstProp = yield addProperty(view, 1, "background-color", "green");
-  let secondProp = yield addProperty(view, 1, "background-color", "blue");
-
-  is(elementRule.textProps[0], firstProp,
-     "Rules should be in addition order.");
+  let firstProp = elementRule.createProperty("background-color", "green", "");
+  let secondProp = elementRule.createProperty("background-color", "blue", "");
+  is(elementRule.textProps[0], firstProp, "Rules should be in addition order.");
   is(elementRule.textProps[1], secondProp,
-     "Rules should be in addition order.");
-
-  // rgb(0, 0, 255) = blue
-  is((yield getValue("#testid", "background-color")), "rgb(0, 0, 255)",
-     "Second property should have been used.");
+    "Rules should be in addition order.");
+  yield elementRule._applyingModifications;
+  is(element.style.getPropertyValue("background-color"), "blue",
+    "Second property should have been used.");
 
   info("Removing the second property and checking the applied style again");
-  yield removeProperty(view, secondProp);
-  // rgb(0, 128, 0) = green
-  is((yield getValue("#testid", "background-color")), "rgb(0, 128, 0)",
-     "After deleting second property, first should be used.");
+  secondProp.remove();
+  yield elementRule._applyingModifications;
+  is(element.style.getPropertyValue("background-color"), "green",
+    "After deleting second property, first should be used.");
 
   info("Creating a new second property and checking that the insertion order " +
-     "is still the same");
-
-  secondProp = yield addProperty(view, 1, "background-color", "blue");
-
-  is((yield getValue("#testid", "background-color")), "rgb(0, 0, 255)",
-     "New property should be used.");
+    "is still the same");
+  secondProp = elementRule.createProperty("background-color", "blue", "");
+  yield elementRule._applyingModifications;
+  is(element.style.getPropertyValue("background-color"), "blue",
+    "New property should be used.");
   is(elementRule.textProps[0], firstProp,
-     "Rules shouldn't have switched places.");
+    "Rules shouldn't have switched places.");
   is(elementRule.textProps[1], secondProp,
-     "Rules shouldn't have switched places.");
+    "Rules shouldn't have switched places.");
 
   info("Disabling the second property and checking the applied style");
-  yield togglePropStatus(view, secondProp);
-
-  is((yield getValue("#testid", "background-color")), "rgb(0, 128, 0)",
-     "After disabling second property, first value should be used");
+  secondProp.setEnabled(false);
+  yield elementRule._applyingModifications;
+  is(element.style.getPropertyValue("background-color"), "green",
+    "After disabling second property, first value should be used");
 
   info("Disabling the first property too and checking the applied style");
-  yield togglePropStatus(view, firstProp);
-
-  is((yield getValue("#testid", "background-color")), "transparent",
-     "After disabling both properties, value should be empty.");
+  firstProp.setEnabled(false);
+  yield elementRule._applyingModifications;
+  is(element.style.getPropertyValue("background-color"), "",
+    "After disabling both properties, value should be empty.");
 
   info("Re-enabling the second propertyt and checking the applied style");
-  yield togglePropStatus(view, secondProp);
-
-  is((yield getValue("#testid", "background-color")), "rgb(0, 0, 255)",
-     "Value should be set correctly after re-enabling");
+  secondProp.setEnabled(true);
+  yield elementRule._applyingModifications;
+  is(element.style.getPropertyValue("background-color"), "blue",
+    "Value should be set correctly after re-enabling");
 
   info("Re-enabling the first property and checking the insertion order " +
-       "is still respected");
-  yield togglePropStatus(view, firstProp);
+    "is still respected");
+  firstProp.setEnabled(true);
+  yield elementRule._applyingModifications;
+  is(element.style.getPropertyValue("background-color"), "blue",
+    "Re-enabling an earlier property shouldn't make it override " +
+    "a later property.");
+  is(elementRule.textProps[0], firstProp,
+    "Rules shouldn't have switched places.");
+  is(elementRule.textProps[1], secondProp,
+    "Rules shouldn't have switched places.");
 
-  is((yield getValue("#testid", "background-color")), "rgb(0, 0, 255)",
-     "Re-enabling an earlier property shouldn't make it override " +
-     "a later property.");
-  is(elementRule.textProps[0], firstProp,
-     "Rules shouldn't have switched places.");
-  is(elementRule.textProps[1], secondProp,
-     "Rules shouldn't have switched places.");
   info("Modifying the first property and checking the applied style");
-  yield setProperty(view, firstProp, "purple");
-
-  is((yield getValue("#testid", "background-color")), "rgb(0, 0, 255)",
-     "Modifying an earlier property shouldn't override a later property.");
+  firstProp.setValue("purple", "");
+  yield elementRule._applyingModifications;
+  is(element.style.getPropertyValue("background-color"), "blue",
+    "Modifying an earlier property shouldn't override a later property.");
 });
-
-function* getValue(selector, propName) {
-  let value = yield getComputedStyleProperty(selector, null, propName);
-  return value;
-}
--- a/devtools/client/inspector/rules/test/browser_rules_edit-property-remove_01.js
+++ b/devtools/client/inspector/rules/test/browser_rules_edit-property-remove_01.js
@@ -17,51 +17,60 @@ const TEST_URI = `
   </style>
   <div id='testid'>Styled Node</div>
 `;
 
 add_task(function*() {
   yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
   let {inspector, view} = yield openRuleView();
   yield selectNode("#testid", inspector);
+  yield testEditPropertyAndRemove(inspector, view);
+});
 
-  info("Getting the first property in the #testid rule");
-  let rule = getRuleViewRuleEditor(view, 1).rule;
-  let prop = rule.textProps[0];
+function* testEditPropertyAndRemove(inspector, view) {
+  let ruleEditor = getRuleViewRuleEditor(view, 1);
+  let propEditor = ruleEditor.rule.textProps[0].editor;
 
-  info("Deleting the name of that property to remove the property");
-  yield removeProperty(view, prop, false);
+  yield focusEditableField(view, propEditor.nameSpan);
+  yield sendKeysAndWaitForFocus(view, ruleEditor.element,
+    ["VK_DELETE", "VK_RETURN"]);
+  yield ruleEditor.rule._applyingModifications;
 
   let newValue = yield executeInContent("Test:GetRulePropertyValue", {
     styleSheetIndex: 0,
     ruleIndex: 0,
     name: "background-color"
   });
   is(newValue, "", "background-color should have been unset.");
 
-  info("Getting the new first property in the rule");
-  prop = rule.textProps[0];
+  propEditor = ruleEditor.rule.textProps[0].editor;
 
   let editor = inplaceEditor(view.styleDocument.activeElement);
-  is(inplaceEditor(prop.editor.nameSpan), editor,
+  is(inplaceEditor(propEditor.nameSpan), editor,
     "Focus should have moved to the next property name");
 
-  info("Deleting the name of that property to remove the property");
-  view.styleDocument.activeElement.blur();
-  yield removeProperty(view, prop, false);
+  yield sendKeysAndWaitForFocus(view, ruleEditor.element,
+    ["VK_DELETE", "VK_RETURN"]);
+  yield ruleEditor.rule._applyingModifications;
 
   newValue = yield executeInContent("Test:GetRulePropertyValue", {
     styleSheetIndex: 0,
     ruleIndex: 0,
     name: "color"
   });
   is(newValue, "", "color should have been unset.");
 
   editor = inplaceEditor(view.styleDocument.activeElement);
-  is(inplaceEditor(rule.editor.newPropSpan), editor,
+  is(inplaceEditor(ruleEditor.newPropSpan), editor,
     "Focus should have moved to the new property span");
-  is(rule.textProps.length, 0,
+  is(ruleEditor.rule.textProps.length, 0,
     "All properties should have been removed.");
-  is(rule.editor.propertyList.children.length, 1,
+  is(ruleEditor.propertyList.children.length, 1,
     "Should have the new property span.");
+}
 
-  view.styleDocument.activeElement.blur();
-});
+function* sendKeysAndWaitForFocus(view, element, keys) {
+  let onFocus = once(element, "focus", true);
+  for (let key of keys) {
+    EventUtils.synthesizeKey(key, {}, view.styleWindow);
+  }
+  yield onFocus;
+}
--- a/devtools/client/inspector/rules/test/browser_rules_edit-property-remove_02.js
+++ b/devtools/client/inspector/rules/test/browser_rules_edit-property-remove_02.js
@@ -17,51 +17,62 @@ const TEST_URI = `
   </style>
   <div id='testid'>Styled Node</div>
 `;
 
 add_task(function*() {
   yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
   let {inspector, view} = yield openRuleView();
   yield selectNode("#testid", inspector);
+  yield testEditPropertyAndRemove(inspector, view);
+});
 
-  info("Getting the first property in the rule");
-  let rule = getRuleViewRuleEditor(view, 1).rule;
-  let prop = rule.textProps[0];
+function* testEditPropertyAndRemove(inspector, view) {
+  let ruleEditor = getRuleViewRuleEditor(view, 1);
+  let propEditor = ruleEditor.rule.textProps[0].editor;
 
-  info("Clearing the property value");
-  yield setProperty(view, prop, null, false);
+  yield focusEditableField(view, propEditor.valueSpan);
+  yield sendKeysAndWaitForFocus(view, ruleEditor.element,
+    ["VK_DELETE", "VK_RETURN"]);
+  yield ruleEditor.rule._applyingModifications;
 
   let newValue = yield executeInContent("Test:GetRulePropertyValue", {
     styleSheetIndex: 0,
     ruleIndex: 0,
     name: "background-color"
   });
   is(newValue, "", "background-color should have been unset.");
 
-  info("Getting the new first property in the rule");
-  prop = rule.textProps[0];
+  propEditor = ruleEditor.rule.textProps[0].editor;
 
   let editor = inplaceEditor(view.styleDocument.activeElement);
-  is(inplaceEditor(prop.editor.nameSpan), editor,
+  is(inplaceEditor(propEditor.nameSpan), editor,
     "Focus should have moved to the next property name");
-  view.styleDocument.activeElement.blur();
 
-  info("Clearing the property value");
-  yield setProperty(view, prop, null, false);
+  info("Focus the property value and remove the property");
+  let onChanged = view.once("ruleview-changed");
+  yield sendKeysAndWaitForFocus(view, ruleEditor.element,
+    ["VK_TAB", "VK_DELETE", "VK_RETURN"]);
+  yield onChanged;
 
   newValue = yield executeInContent("Test:GetRulePropertyValue", {
     styleSheetIndex: 0,
     ruleIndex: 0,
     name: "color"
   });
   is(newValue, "", "color should have been unset.");
 
   editor = inplaceEditor(view.styleDocument.activeElement);
-  is(inplaceEditor(rule.editor.newPropSpan), editor,
+  is(inplaceEditor(ruleEditor.newPropSpan), editor,
     "Focus should have moved to the new property span");
-  is(rule.textProps.length, 0,
+  is(ruleEditor.rule.textProps.length, 0,
     "All properties should have been removed.");
-  is(rule.editor.propertyList.children.length, 1,
+  is(ruleEditor.propertyList.children.length, 1,
     "Should have the new property span.");
+}
 
-  view.styleDocument.activeElement.blur();
-});
+function* sendKeysAndWaitForFocus(view, element, keys) {
+  let onFocus = once(element, "focus", true);
+  for (let key of keys) {
+    EventUtils.synthesizeKey(key, {}, view.styleWindow);
+  }
+  yield onFocus;
+}
--- a/devtools/client/inspector/rules/test/browser_rules_edit-property-remove_03.js
+++ b/devtools/client/inspector/rules/test/browser_rules_edit-property-remove_03.js
@@ -17,67 +17,74 @@ const TEST_URI = `
   </style>
   <div id='testid'>Styled Node</div>
 `;
 
 add_task(function*() {
   yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
   let {inspector, view} = yield openRuleView();
   yield selectNode("#testid", inspector);
+  yield testEditPropertyAndRemove(inspector, view);
+});
 
-  info("Getting the second property in the rule");
-  let rule = getRuleViewRuleEditor(view, 1).rule;
-  let prop = rule.textProps[1];
+function* testEditPropertyAndRemove(inspector, view) {
+  let ruleEditor = getRuleViewRuleEditor(view, 1);
+  let propEditor = ruleEditor.rule.textProps[1].editor;
 
-  info("Clearing the property value and pressing shift-tab");
-  let editor = yield focusEditableField(view, prop.editor.valueSpan);
-  let onValueDone = view.once("ruleview-changed");
-  editor.input.value = "";
-  EventUtils.synthesizeKey("VK_TAB", {shiftKey: true}, view.styleWindow);
-  yield onValueDone;
+  yield focusEditableField(view, propEditor.valueSpan);
+  yield sendKeysAndWaitForFocus(view, ruleEditor.element, [
+    { key: "VK_DELETE", modifiers: {} },
+    { key: "VK_TAB", modifiers: { shiftKey: true } }
+  ]);
+  yield ruleEditor.rule._applyingModifications;
 
   let newValue = yield executeInContent("Test:GetRulePropertyValue", {
     styleSheetIndex: 0,
     ruleIndex: 0,
     name: "color"
   });
   is(newValue, "", "color should have been unset.");
-  is(prop.editor.valueSpan.textContent, "",
+  is(propEditor.valueSpan.textContent, "",
     "'' property value is correctly set.");
 
-  info("Pressing shift-tab again to focus the previous property value");
-  let onValueFocused = view.once("ruleview-changed");
-  EventUtils.synthesizeKey("VK_TAB", {shiftKey: true}, view.styleWindow);
-  yield onValueFocused;
+  yield sendKeysAndWaitForFocus(view, ruleEditor.element, [
+    { key: "VK_TAB", modifiers: { shiftKey: true } }
+  ]);
+  yield ruleEditor.rule._applyingModifications;
 
-  info("Getting the first property in the rule");
-  prop = rule.textProps[0];
+  propEditor = ruleEditor.rule.textProps[0].editor;
 
-  editor = inplaceEditor(view.styleDocument.activeElement);
-  is(inplaceEditor(prop.editor.valueSpan), editor,
+  let editor = inplaceEditor(view.styleDocument.activeElement);
+  is(inplaceEditor(propEditor.valueSpan), editor,
     "Focus should have moved to the previous property value");
 
-  info("Pressing shift-tab again to focus the property name");
-  let onNameFocused = view.once("ruleview-changed");
-  EventUtils.synthesizeKey("VK_TAB", {shiftKey: true}, view.styleWindow);
-  yield onNameFocused;
+  info("Focus the property name and remove the property");
+  yield sendKeysAndWaitForFocus(view, ruleEditor.element, [
+    { key: "VK_TAB", modifiers: { shiftKey: true } },
+    { key: "VK_DELETE", modifiers: {} },
+    { key: "VK_TAB", modifiers: { shiftKey: true } }
+  ]);
 
-  info("Removing the name and pressing shift-tab to focus the selector");
-  let onNameDeleted = view.once("ruleview-changed");
-  EventUtils.synthesizeKey("VK_DELETE", {}, view.styleWindow);
-  EventUtils.synthesizeKey("VK_TAB", {shiftKey: true}, view.styleWindow);
-  yield onNameDeleted;
+  yield ruleEditor.rule._applyingModifications;
 
   newValue = yield executeInContent("Test:GetRulePropertyValue", {
     styleSheetIndex: 0,
     ruleIndex: 0,
     name: "background-color"
   });
   is(newValue, "", "background-color should have been unset.");
 
   editor = inplaceEditor(view.styleDocument.activeElement);
-  is(inplaceEditor(rule.editor.selectorText), editor,
+  is(inplaceEditor(ruleEditor.selectorText), editor,
     "Focus should have moved to the selector text.");
-  is(rule.textProps.length, 0,
+  is(ruleEditor.rule.textProps.length, 0,
     "All properties should have been removed.");
-  ok(!rule.editor.propertyList.hasChildNodes(),
+  ok(!ruleEditor.propertyList.hasChildNodes(),
     "Should not have any properties.");
-});
+}
+
+function* sendKeysAndWaitForFocus(view, element, keys) {
+  let onFocus = once(element, "focus", true);
+  for (let {key, modifiers} of keys) {
+    EventUtils.synthesizeKey(key, modifiers, view.styleWindow);
+  }
+  yield onFocus;
+}
--- a/devtools/client/inspector/rules/test/browser_rules_edit-property_01.js
+++ b/devtools/client/inspector/rules/test/browser_rules_edit-property_01.js
@@ -31,63 +31,69 @@ var TEST_DATA = [
   { name: "border", value: "solid 1px foo", isValid: false },
 ];
 
 add_task(function*() {
   yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
   let {inspector, view} = yield openRuleView();
   yield selectNode("#testid", inspector);
 
-  let rule = getRuleViewRuleEditor(view, 1).rule;
+  let ruleEditor = getRuleViewRuleEditor(view, 1);
   for (let {name, value, isValid} of TEST_DATA) {
-    yield testEditProperty(view, rule, name, value, isValid);
+    yield testEditProperty(ruleEditor, name, value, isValid);
   }
 });
 
-function* testEditProperty(view, rule, name, value, isValid) {
+function* testEditProperty(ruleEditor, name, value, isValid) {
   info("Test editing existing property name/value fields");
 
-  let doc = rule.editor.doc;
-  let prop = rule.textProps[0];
+  let doc = ruleEditor.doc;
+  let propEditor = ruleEditor.rule.textProps[0].editor;
 
   info("Focusing an existing property name in the rule-view");
-  let editor = yield focusEditableField(view, prop.editor.nameSpan, 32, 1);
+  let editor = yield focusEditableField(ruleEditor.ruleView,
+    propEditor.nameSpan, 32, 1);
 
-  is(inplaceEditor(prop.editor.nameSpan), editor,
+  is(inplaceEditor(propEditor.nameSpan), editor,
     "The property name editor got focused");
   let input = editor.input;
 
   info("Entering a new property name, including : to commit and " +
     "focus the value");
-  let onValueFocus = once(rule.editor.element, "focus", true);
-  let onNameDone = view.once("ruleview-changed");
+  let onValueFocus = once(ruleEditor.element, "focus", true);
+  let onModifications = ruleEditor.ruleView.once("ruleview-changed");
   EventUtils.sendString(name + ":", doc.defaultView);
   yield onValueFocus;
-  yield onNameDone;
+  yield onModifications;
 
   // Getting the value editor after focus
   editor = inplaceEditor(doc.activeElement);
   input = editor.input;
-  is(inplaceEditor(prop.editor.valueSpan), editor, "Focus moved to the value.");
+  is(inplaceEditor(propEditor.valueSpan), editor, "Focus moved to the value.");
 
   info("Entering a new value, including ; to commit and blur the value");
-  let onValueDone = view.once("ruleview-changed");
   let onBlur = once(input, "blur");
   EventUtils.sendString(value + ";", doc.defaultView);
   yield onBlur;
-  yield onValueDone;
+  yield ruleEditor.rule._applyingModifications;
 
-  is(prop.editor.isValid(), isValid,
+  is(propEditor.isValid(), isValid,
     value + " is " + isValid ? "valid" : "invalid");
 
   info("Checking that the style property was changed on the content page");
   let propValue = yield executeInContent("Test:GetRulePropertyValue", {
     styleSheetIndex: 0,
     ruleIndex: 0,
     name
   });
 
   if (isValid) {
     is(propValue, value, name + " should have been set.");
   } else {
     isnot(propValue, value, name + " shouldn't have been set.");
   }
+
+  info("Wait for remaining modifications to be applied");
+  yield ruleEditor.rule._applyingModifications;
+
+  is(ruleEditor.rule._applyingModifications, null,
+    "Reference to rule modification promise was removed after completion");
 }
--- a/devtools/client/inspector/rules/test/browser_rules_edit-property_02.js
+++ b/devtools/client/inspector/rules/test/browser_rules_edit-property_02.js
@@ -25,94 +25,106 @@ add_task(function*() {
   yield selectNode("#testid", inspector);
 
   yield testEditProperty(inspector, view);
   yield testDisableProperty(inspector, view);
   yield testPropertyStillMarkedDirty(inspector, view);
 });
 
 function* testEditProperty(inspector, ruleView) {
-  let idRule = getRuleViewRuleEditor(ruleView, 1).rule;
-  let prop = idRule.textProps[0];
+  let idRuleEditor = getRuleViewRuleEditor(ruleView, 1);
+  let propEditor = idRuleEditor.rule.textProps[0].editor;
 
-  let editor = yield focusEditableField(ruleView, prop.editor.nameSpan);
+  let editor = yield focusEditableField(ruleView, propEditor.nameSpan);
   let input = editor.input;
-  is(inplaceEditor(prop.editor.nameSpan), editor,
+  is(inplaceEditor(propEditor.nameSpan), editor,
     "Next focused editor should be the name editor.");
 
   ok(input.selectionStart === 0 && input.selectionEnd === input.value.length,
     "Editor contents are selected.");
 
   // Try clicking on the editor's input again, shouldn't cause trouble
   // (see bug 761665).
   EventUtils.synthesizeMouse(input, 1, 1, {}, ruleView.styleWindow);
   input.select();
 
   info("Entering property name \"border-color\" followed by a colon to " +
     "focus the value");
-  let onNameDone = ruleView.once("ruleview-changed");
-  let onFocus = once(idRule.editor.element, "focus", true);
+  let onFocus = once(idRuleEditor.element, "focus", true);
   EventUtils.sendString("border-color:", ruleView.styleWindow);
   yield onFocus;
-  yield onNameDone;
+  yield idRuleEditor.rule._applyingModifications;
 
   info("Verifying that the focused field is the valueSpan");
   editor = inplaceEditor(ruleView.styleDocument.activeElement);
   input = editor.input;
-  is(inplaceEditor(prop.editor.valueSpan), editor,
+  is(inplaceEditor(propEditor.valueSpan), editor,
     "Focus should have moved to the value.");
   ok(input.selectionStart === 0 && input.selectionEnd === input.value.length,
     "Editor contents are selected.");
 
   info("Entering a value following by a semi-colon to commit it");
   let onBlur = once(editor.input, "blur");
   // Use sendChar() to pass each character as a string so that we can test
-  // prop.editor.warning.hidden after each character.
+  // propEditor.warning.hidden after each character.
   for (let ch of "red;") {
-    let onPreviewDone = ruleView.once("ruleview-changed");
     EventUtils.sendChar(ch, ruleView.styleWindow);
-    yield onPreviewDone;
-    is(prop.editor.warning.hidden, true,
+    is(propEditor.warning.hidden, true,
       "warning triangle is hidden or shown as appropriate");
   }
   yield onBlur;
+  yield idRuleEditor.rule._applyingModifications;
 
   let newValue = yield executeInContent("Test:GetRulePropertyValue", {
     styleSheetIndex: 0,
     ruleIndex: 0,
     name: "border-color"
   });
   is(newValue, "red", "border-color should have been set.");
 
-  ruleView.styleDocument.activeElement.blur();
-  yield addProperty(ruleView, 1, "color", "red", ";");
+  info("Entering property name \"color\" followed by a colon to " +
+    "focus the value");
+  onFocus = once(idRuleEditor.element, "focus", true);
+  EventUtils.sendString("color:", ruleView.styleWindow);
+  yield onFocus;
+
+  info("Verifying that the focused field is the valueSpan");
+  editor = inplaceEditor(ruleView.styleDocument.activeElement);
+
+  info("Entering a value following by a semi-colon to commit it");
+  onBlur = once(editor.input, "blur");
+  EventUtils.sendString("red;", ruleView.styleWindow);
+  yield onBlur;
+  yield idRuleEditor.rule._applyingModifications;
 
   let props = ruleView.element.querySelectorAll(".ruleview-property");
   for (let i = 0; i < props.length; i++) {
     is(props[i].hasAttribute("dirty"), i <= 1,
       "props[" + i + "] marked dirty as appropriate");
   }
 }
 
 function* testDisableProperty(inspector, ruleView) {
-  let idRule = getRuleViewRuleEditor(ruleView, 1).rule;
-  let prop = idRule.textProps[0];
+  let idRuleEditor = getRuleViewRuleEditor(ruleView, 1);
+  let propEditor = idRuleEditor.rule.textProps[0].editor;
 
   info("Disabling a property");
-  yield togglePropStatus(ruleView, prop);
+  propEditor.enable.click();
+  yield idRuleEditor.rule._applyingModifications;
 
   let newValue = yield executeInContent("Test:GetRulePropertyValue", {
     styleSheetIndex: 0,
     ruleIndex: 0,
     name: "border-color"
   });
   is(newValue, "", "Border-color should have been unset.");
 
   info("Enabling the property again");
-  yield togglePropStatus(ruleView, prop);
+  propEditor.enable.click();
+  yield idRuleEditor.rule._applyingModifications;
 
   newValue = yield executeInContent("Test:GetRulePropertyValue", {
     styleSheetIndex: 0,
     ruleIndex: 0,
     name: "border-color"
   });
   is(newValue, "red", "Border-color should have been reset.");
 }
--- a/devtools/client/inspector/rules/test/browser_rules_edit-property_04.js
+++ b/devtools/client/inspector/rules/test/browser_rules_edit-property_04.js
@@ -15,70 +15,71 @@ const TEST_URI = `
   </style>
   <div id='testid'>Styled Node</div>
 `;
 
 add_task(function*() {
   yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
   let {inspector, view} = yield openRuleView();
   yield selectNode("#testid", inspector);
+  yield testDisableProperty(inspector, view);
+});
 
-  let rule = getRuleViewRuleEditor(view, 1).rule;
-  let prop = rule.textProps[0];
+function* testDisableProperty(inspector, view) {
+  let ruleEditor = getRuleViewRuleEditor(view, 1);
+  let propEditor = ruleEditor.rule.textProps[0].editor;
 
   info("Disabling a property");
-  yield togglePropStatus(view, prop);
+  propEditor.enable.click();
+  yield ruleEditor.rule._applyingModifications;
 
   let newValue = yield executeInContent("Test:GetRulePropertyValue", {
     styleSheetIndex: 0,
     ruleIndex: 0,
     name: "background-color"
   });
   is(newValue, "", "background-color should have been unset.");
 
-  yield testEditDisableProperty(view, rule, prop, "name", "VK_ESCAPE");
-  yield testEditDisableProperty(view, rule, prop, "value", "VK_ESCAPE");
-  yield testEditDisableProperty(view, rule, prop, "value", "VK_TAB");
-  yield testEditDisableProperty(view, rule, prop, "value", "VK_RETURN");
-});
+  yield testEditDisableProperty(view, ruleEditor, propEditor,
+    propEditor.nameSpan, "VK_ESCAPE");
+  yield testEditDisableProperty(view, ruleEditor, propEditor,
+    propEditor.valueSpan, "VK_ESCAPE");
+  yield testEditDisableProperty(view, ruleEditor, propEditor,
+    propEditor.valueSpan, "VK_TAB");
+  yield testEditDisableProperty(view, ruleEditor, propEditor,
+    propEditor.valueSpan, "VK_RETURN");
+}
 
-function* testEditDisableProperty(view, rule, prop, fieldType, commitKey) {
-  let field = fieldType === "name" ? prop.editor.nameSpan
-                                   : prop.editor.valueSpan;
+function* testEditDisableProperty(view, ruleEditor, propEditor,
+    editableField, commitKey) {
+  let editor = yield focusEditableField(view, editableField);
 
-  let editor = yield focusEditableField(view, field);
-
-  ok(!prop.editor.element.classList.contains("ruleview-overridden"),
+  ok(!propEditor.element.classList.contains("ruleview-overridden"),
     "property is not overridden.");
-  is(prop.editor.enable.style.visibility, "hidden",
+  is(propEditor.enable.style.visibility, "hidden",
     "property enable checkbox is hidden.");
 
   let newValue = yield executeInContent("Test:GetRulePropertyValue", {
     styleSheetIndex: 0,
     ruleIndex: 0,
     name: "background-color"
   });
   is(newValue, "", "background-color should remain unset.");
 
-  let onChangeDone;
-  if (fieldType === "value") {
-    onChangeDone = view.once("ruleview-changed");
-  }
-
   let onBlur = once(editor.input, "blur");
   EventUtils.synthesizeKey(commitKey, {}, view.styleWindow);
   yield onBlur;
-  yield onChangeDone;
+  yield ruleEditor.rule._applyingModifications;
 
-  ok(!prop.enabled, "property is disabled.");
-  ok(prop.editor.element.classList.contains("ruleview-overridden"),
+  ok(!propEditor.prop.enabled, "property is disabled.");
+  ok(propEditor.element.classList.contains("ruleview-overridden"),
     "property is overridden.");
-  is(prop.editor.enable.style.visibility, "visible",
+  is(propEditor.enable.style.visibility, "visible",
     "property enable checkbox is visible.");
-  ok(!prop.editor.enable.getAttribute("checked"),
+  ok(!propEditor.enable.getAttribute("checked"),
     "property enable checkbox is not checked.");
 
   newValue = yield executeInContent("Test:GetRulePropertyValue", {
     styleSheetIndex: 0,
     ruleIndex: 0,
     name: "background-color"
   });
   is(newValue, "", "background-color should remain unset.");
--- a/devtools/client/inspector/rules/test/browser_rules_edit-property_05.js
+++ b/devtools/client/inspector/rules/test/browser_rules_edit-property_05.js
@@ -15,62 +15,71 @@ const TEST_URI = `
   </style>
   <div id='testid'>Styled Node</div>
 `;
 
 add_task(function*() {
   yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
   let {inspector, view} = yield openRuleView();
   yield selectNode("#testid", inspector);
+  yield testEditingDisableProperty(inspector, view);
+});
 
-  let rule = getRuleViewRuleEditor(view, 1).rule;
-  let prop = rule.textProps[0];
+function* testEditingDisableProperty(inspector, view) {
+  let ruleEditor = getRuleViewRuleEditor(view, 1);
+  let propEditor = ruleEditor.rule.textProps[0].editor;
 
   info("Disabling background-color property");
-  yield togglePropStatus(view, prop);
+  propEditor.enable.click();
+  yield ruleEditor.rule._applyingModifications;
 
   let newValue = yield getRulePropertyValue("background-color");
   is(newValue, "", "background-color should have been unset.");
 
+  yield focusEditableField(view, propEditor.nameSpan);
+
   info("Entering a new property name, including : to commit and " +
        "focus the value");
-
-  yield focusEditableField(view, prop.editor.nameSpan);
-  let onNameDone = view.once("ruleview-changed");
+  let onValueFocus = once(ruleEditor.element, "focus", true);
   EventUtils.sendString("border-color:", view.styleWindow);
-  yield onNameDone;
+  yield onValueFocus;
+  yield ruleEditor.rule._applyingModifications;
 
   info("Escape editing the property value");
-  let onValueDone = view.once("ruleview-changed");
   EventUtils.synthesizeKey("VK_ESCAPE", {}, view.styleWindow);
-  yield onValueDone;
+  yield ruleEditor.rule._applyingModifications;
 
   newValue = yield getRulePropertyValue("border-color");
   is(newValue, "blue", "border-color should have been set.");
 
-  ok(prop.enabled, "border-color property is enabled.");
-  ok(!prop.editor.element.classList.contains("ruleview-overridden"),
+  ok(propEditor.prop.enabled, "border-color property is enabled.");
+  ok(!propEditor.element.classList.contains("ruleview-overridden"),
     "border-color is not overridden");
 
   info("Disabling border-color property");
-  yield togglePropStatus(view, prop);
+  propEditor.enable.click();
+  yield ruleEditor.rule._applyingModifications;
 
   newValue = yield getRulePropertyValue("border-color");
   is(newValue, "", "border-color should have been unset.");
 
   info("Enter a new property value for the border-color property");
-  yield setProperty(view, prop, "red");
+  let editor = yield focusEditableField(view, propEditor.valueSpan);
+  let onBlur = once(editor.input, "blur");
+  EventUtils.sendString("red;", view.styleWindow);
+  yield onBlur;
+  yield ruleEditor.rule._applyingModifications;
 
   newValue = yield getRulePropertyValue("border-color");
   is(newValue, "red", "new border-color should have been set.");
 
-  ok(prop.enabled, "border-color property is enabled.");
-  ok(!prop.editor.element.classList.contains("ruleview-overridden"),
+  ok(propEditor.prop.enabled, "border-color property is enabled.");
+  ok(!propEditor.element.classList.contains("ruleview-overridden"),
     "border-color is not overridden");
-});
+}
 
 function* getRulePropertyValue(name) {
   let propValue = yield executeInContent("Test:GetRulePropertyValue", {
     styleSheetIndex: 0,
     ruleIndex: 0,
     name: name
   });
   return propValue;
--- a/devtools/client/inspector/rules/test/browser_rules_edit-property_06.js
+++ b/devtools/client/inspector/rules/test/browser_rules_edit-property_06.js
@@ -17,36 +17,48 @@ const TEST_URI = `
   }
   </style>
 `;
 
 add_task(function*() {
   yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
   let {inspector, view} = yield openRuleView();
   yield selectNode("body", inspector);
+  yield testEditPropertyPriorityAndDisable(inspector, view);
+});
 
-  let rule = getRuleViewRuleEditor(view, 1).rule;
-  let prop = rule.textProps[0];
+function* testEditPropertyPriorityAndDisable(inspector, view) {
+  let ruleEditor = getRuleViewRuleEditor(view, 1);
+  let propEditor = ruleEditor.rule.textProps[0].editor;
 
   is((yield getComputedStyleProperty("body", null, "background-color")),
     "rgb(0, 128, 0)", "green background color is set.");
 
-  yield setProperty(view, prop, "red !important");
+  let editor = yield focusEditableField(view, propEditor.valueSpan);
+  let onBlur = once(editor.input, "blur");
+  EventUtils.sendString("red !important;", view.styleWindow);
+  yield onBlur;
+  yield ruleEditor.rule._applyingModifications;
 
-  is(prop.editor.valueSpan.textContent, "red !important",
+  is(propEditor.valueSpan.textContent, "red !important",
     "'red !important' property value is correctly set.");
   is((yield getComputedStyleProperty("body", null, "background-color")),
     "rgb(255, 0, 0)", "red background color is set.");
 
   info("Disabling red background color property");
-  yield togglePropStatus(view, prop);
+  propEditor.enable.click();
+  yield ruleEditor.rule._applyingModifications;
 
   is((yield getComputedStyleProperty("body", null, "background-color")),
     "rgb(0, 128, 0)", "green background color is set.");
 
-  yield setProperty(view, prop, "red");
+  editor = yield focusEditableField(view, propEditor.valueSpan);
+  onBlur = once(editor.input, "blur");
+  EventUtils.sendString("red;", view.styleWindow);
+  yield onBlur;
+  yield ruleEditor.rule._applyingModifications;
 
-  is(prop.editor.valueSpan.textContent, "red",
+  is(propEditor.valueSpan.textContent, "red",
     "'red' property value is correctly set.");
-  ok(prop.enabled, "red background-color property is enabled.");
+  ok(propEditor.prop.enabled, "red background-color property is enabled.");
   is((yield getComputedStyleProperty("body", null, "background-color")),
     "rgb(0, 128, 0)", "green background color is set.");
-});
+}
--- a/devtools/client/inspector/rules/test/browser_rules_edit-property_07.js
+++ b/devtools/client/inspector/rules/test/browser_rules_edit-property_07.js
@@ -15,36 +15,41 @@ const TEST_URI = `
   </style>
   <div id='testid'>Styled Node</div>
 `;
 
 add_task(function*() {
   yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
   let {inspector, view} = yield openRuleView();
   yield selectNode("#testid", inspector);
+  yield testEditDisableProperty(inspector, view);
+});
 
-  let rule = getRuleViewRuleEditor(view, 1).rule;
-  let prop = rule.textProps[0];
+function* testEditDisableProperty(inspector, view) {
+  let ruleEditor = getRuleViewRuleEditor(view, 1);
+  let propEditor = ruleEditor.rule.textProps[0].editor;
 
   info("Disabling red background color property");
-  yield togglePropStatus(view, prop);
-  ok(!prop.enabled, "red background-color property is disabled.");
+  propEditor.enable.click();
+  yield ruleEditor.rule._applyingModifications;
+
+  ok(!propEditor.prop.enabled, "red background-color property is disabled.");
 
-  let editor = yield focusEditableField(view, prop.editor.valueSpan);
-  let onDone = view.once("ruleview-changed");
-  editor.input.value = "red; color: red;";
-  EventUtils.synthesizeKey("VK_RETURN", {}, view.styleWindow);
-  yield onDone;
+  let editor = yield focusEditableField(view, propEditor.valueSpan);
+  let onBlur = once(editor.input, "blur");
+  EventUtils.sendString("red; color: red;", view.styleWindow);
+  yield onBlur;
+  yield ruleEditor.rule._applyingModifications;
 
-  is(prop.editor.valueSpan.textContent, "red",
+  is(propEditor.valueSpan.textContent, "red",
     "'red' property value is correctly set.");
-  ok(prop.enabled, "red background-color property is enabled.");
+  ok(propEditor.prop.enabled, "red background-color property is enabled.");
   is((yield getComputedStyleProperty("#testid", null, "background-color")),
     "rgb(255, 0, 0)", "red background color is set.");
 
-  let propEditor = rule.textProps[1].editor;
+  propEditor = ruleEditor.rule.textProps[1].editor;
   is(propEditor.nameSpan.textContent, "color",
     "new 'color' property name is correctly set.");
   is(propEditor.valueSpan.textContent, "red",
     "new 'red' property value is correctly set.");
   is((yield getComputedStyleProperty("#testid", null, "color")),
     "rgb(255, 0, 0)", "red color is set.");
-});
+}
--- a/devtools/client/inspector/rules/test/browser_rules_edit-selector_05.js
+++ b/devtools/client/inspector/rules/test/browser_rules_edit-selector_05.js
@@ -66,13 +66,48 @@ function* testEditSelector(view, name) {
 
 function* checkModifiedElement(view, name) {
   is(view._elementStyle.rules.length, 3, "Should have 3 rules.");
   ok(getRuleViewRule(view, name), "Rule with " + name + " selector exists.");
 }
 
 function* testAddProperty(view) {
   info("Test creating a new property");
-  let textProp = yield addProperty(view, 1, "text-align", "center");
+
+  let ruleEditor = getRuleViewRuleEditor(view, 1);
+
+  info("Focusing a new property name in the rule-view");
+  let editor = yield focusEditableField(view, ruleEditor.closeBrace);
+
+  is(inplaceEditor(ruleEditor.newPropSpan), editor,
+    "The new property editor got focused");
+  let input = editor.input;
+
+  info("Entering text-align in the property name editor");
+  input.value = "text-align";
+
+  info("Pressing return to commit and focus the new value field");
+  let onValueFocus = once(ruleEditor.element, "focus", true);
+  let onRuleViewChanged = view.once("ruleview-changed");
+  EventUtils.synthesizeKey("VK_RETURN", {}, view.styleWindow);
+  yield onValueFocus;
+  yield onRuleViewChanged;
+
+  // Getting the new value editor after focus
+  editor = inplaceEditor(view.styleDocument.activeElement);
+  let textProp = ruleEditor.rule.textProps[0];
+
+  is(ruleEditor.rule.textProps.length, 1, "Created a new text property.");
+  is(ruleEditor.propertyList.children.length, 1, "Created a property editor.");
+  is(editor, inplaceEditor(textProp.editor.valueSpan),
+    "Editing the value span now.");
+
+  info("Entering a value and bluring the field to expect a rule change");
+  editor.input.value = "center";
+  let onBlur = once(editor.input, "blur");
+  onRuleViewChanged = waitForNEvents(view, "ruleview-changed", 2);
+  editor.input.blur();
+  yield onBlur;
+  yield onRuleViewChanged;
 
   is(textProp.value, "center", "Text prop should have been changed.");
   is(textProp.overridden, false, "Property should not be overridden");
 }
--- a/devtools/client/inspector/rules/test/browser_rules_editable-field-focus_02.js
+++ b/devtools/client/inspector/rules/test/browser_rules_editable-field-focus_02.js
@@ -24,17 +24,17 @@ const TEST_URI = `
 
 add_task(function*() {
   yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
   let {inspector, view} = yield openRuleView();
   yield selectNode("#testid", inspector);
   yield testEditableFieldFocus(inspector, view, "VK_TAB", { shiftKey: true });
 });
 
-function* testEditableFieldFocus(inspector, view, commitKey, options = {}) {
+function* testEditableFieldFocus(inspector, view, commitKey, options={}) {
   let ruleEditor = getRuleViewRuleEditor(view, 2);
   let editor = yield focusEditableField(view, ruleEditor.selectorText);
   is(inplaceEditor(ruleEditor.selectorText), editor,
     "Focus should be in the 'div' rule selector");
 
   ruleEditor = getRuleViewRuleEditor(view, 1);
 
   yield focusNextField(view, ruleEditor, commitKey, options);
--- a/devtools/client/inspector/rules/test/browser_rules_eyedropper.js
+++ b/devtools/client/inspector/rules/test/browser_rules_eyedropper.js
@@ -5,16 +5,18 @@
 "use strict";
 
 // So we can test collecting telemetry on the eyedropper
 var oldCanRecord = Services.telemetry.canRecordExtended;
 Services.telemetry.canRecordExtended = true;
 registerCleanupFunction(function() {
   Services.telemetry.canRecordExtended = oldCanRecord;
 });
+const HISTOGRAM_ID = "DEVTOOLS_PICKER_EYEDROPPER_OPENED_COUNT";
+const FLAG_HISTOGRAM_ID = "DEVTOOLS_PICKER_EYEDROPPER_OPENED_PER_USER_FLAG";
 const EXPECTED_TELEMETRY = {
   "DEVTOOLS_PICKER_EYEDROPPER_OPENED_COUNT": 2,
   "DEVTOOLS_PICKER_EYEDROPPER_OPENED_PER_USER_FLAG": 1
 };
 
 const TEST_URI = `
   <style type="text/css">
     body {
@@ -33,20 +35,18 @@ const TEST_URI = `
       width: 20px;
       height: 20px;
       background-color: #f09;
     }
   </style>
   <body><div id="div1"></div><div id="div2"></div></body>
 `;
 
-// #f09
-const ORIGINAL_COLOR = "rgb(255, 0, 153)";
-// #ff5
-const EXPECTED_COLOR = "rgb(255, 255, 85)";
+const ORIGINAL_COLOR = "rgb(255, 0, 153)";  // #f09
+const EXPECTED_COLOR = "rgb(255, 255, 85)"; // #ff5
 
 // Test opening the eyedropper from the color picker. Pressing escape
 // to close it, and clicking the page to select a color.
 
 add_task(function*() {
   // clear telemetry so we can get accurate counts
   clearTelemetry();
 
@@ -98,17 +98,18 @@ function* testSelect(view, swatch, dropp
   inspectPage(dropper);
 
   yield onDestroyed;
   yield onRuleViewChanged;
 
   let color = swatch.style.backgroundColor;
   is(color, EXPECTED_COLOR, "swatch changed colors");
 
-  is((yield getComputedStyleProperty("div", null, "background-color")),
+  let element = content.document.querySelector("div");
+  is(content.window.getComputedStyle(element).backgroundColor,
      EXPECTED_COLOR,
      "div's color set to body color after dropper");
 }
 
 function clearTelemetry() {
   for (let histogramId in EXPECTED_TELEMETRY) {
     let histogram = Services.telemetry.getHistogramById(histogramId);
     histogram.clear();
@@ -142,17 +143,17 @@ function openEyedropper(view, swatch) {
     });
     dropperButton.click();
   });
 
   swatch.click();
   return deferred.promise;
 }
 
-function inspectPage(dropper, click = true) {
+function inspectPage(dropper, click=true) {
   let target = document.documentElement;
   let win = window;
 
   // get location of the content, offset from browser window
   let box = gBrowser.selectedBrowser.getBoundingClientRect();
   let x = box.left + 1;
   let y = box.top + 1;
 
--- a/devtools/client/inspector/rules/test/browser_rules_filtereditor-commit-on-ENTER.js
+++ b/devtools/client/inspector/rules/test/browser_rules_filtereditor-commit-on-ENTER.js
@@ -35,11 +35,12 @@ add_task(function*() {
   ok(true, "Changes previewed on the element");
 
   info("Press RETURN to commit changes");
   // Pressing return in the cssfilter tooltip triggeres 2 ruleview-changed
   onRuleViewChanged = waitForNEvents(view, "ruleview-changed", 2);
   EventUtils.sendKey("RETURN", widget.styleWindow);
   yield onRuleViewChanged;
 
-  is((yield getComputedStyleProperty("body", null, "filter")), "blur(2px)",
+  const computed = content.getComputedStyle(content.document.body);
+  is(computed.filter, "blur(2px)",
      "The elemenet's filter was kept after RETURN");
 });
--- a/devtools/client/inspector/rules/test/browser_rules_guessIndentation.js
+++ b/devtools/client/inspector/rules/test/browser_rules_guessIndentation.js
@@ -29,19 +29,45 @@ div {
        color: chartreuse;
 }
 `;
 
 add_task(function*() {
   yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
   let {toolbox, inspector, view} = yield openRuleView();
   yield selectNode("#testid", inspector);
+  yield testIndentation(toolbox, inspector, view);
+});
 
-  info("Add a new property in the rule-view");
-  yield addProperty(view, 2, "color", "chartreuse");
+function* testIndentation(toolbox, inspector, view) {
+  let ruleEditor = getRuleViewRuleEditor(view, 2);
+
+  info("Focusing a new property name in the rule-view");
+  let editor = yield focusEditableField(view, ruleEditor.closeBrace);
+
+  let input = editor.input;
+
+  info("Entering color in the property name editor");
+  input.value = "color";
 
-  info("Switch to the style-editor");
+  info("Pressing return to commit and focus the new value field");
+  let onValueFocus = once(ruleEditor.element, "focus", true);
+  let onModifications = ruleEditor.rule._applyingModifications;
+  EventUtils.synthesizeKey("VK_RETURN", {}, view.styleWindow);
+  yield onValueFocus;
+  yield onModifications;
+
+  // Getting the new value editor after focus
+  editor = inplaceEditor(view.styleDocument.activeElement);
+  info("Entering a value and bluring the field to expect a rule change");
+  editor.input.value = "chartreuse";
+  let onBlur = once(editor.input, "blur");
+  onModifications = ruleEditor.rule._applyingModifications;
+  editor.input.blur();
+  yield onBlur;
+  yield onModifications;
+
   let { UI } = yield toolbox.selectTool("styleeditor");
 
   let styleEditor = yield UI.editors[0].getSourceEditor();
   let text = styleEditor.sourceEditor.getText();
   is(text, expectedText, "style inspector changes are synced");
-});
+}
--- a/devtools/client/inspector/rules/test/browser_rules_inherited-properties_01.js
+++ b/devtools/client/inspector/rules/test/browser_rules_inherited-properties_01.js
@@ -2,16 +2,18 @@
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 // Check that inherited properties appear for a nested element in the
 // rule view.
 
+var {ELEMENT_STYLE} = require("devtools/server/actors/styles");
+
 const TEST_URI = `
   <style type="text/css">
     #test2 {
       background-color: green;
       color: purple;
     }
   </style>
   <div id="test2"><div id="test1">Styled Node</div></div>
--- a/devtools/client/inspector/rules/test/browser_rules_inherited-properties_02.js
+++ b/devtools/client/inspector/rules/test/browser_rules_inherited-properties_02.js
@@ -2,16 +2,18 @@
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 // Check that no inherited properties appear when the property does not apply
 // to the nested element.
 
+var {ELEMENT_STYLE} = require("devtools/server/actors/styles");
+
 const TEST_URI = `
   <style type="text/css">
     #test2 {
       background-color: green;
     }
   </style>
   <div id="test2"><div id="test1">Styled Node</div></div>
 `;
--- a/devtools/client/inspector/rules/test/browser_rules_keyframeLineNumbers.js
+++ b/devtools/client/inspector/rules/test/browser_rules_keyframeLineNumbers.js
@@ -9,17 +9,20 @@
 
 const TESTCASE_URI = URL_ROOT + "doc_keyframeLineNumbers.html";
 
 add_task(function*() {
   yield addTab(TESTCASE_URI);
   let { inspector, view } = yield openRuleView();
   yield selectNode("#outer", inspector);
 
-  info("Insert a new property, which will affect the line numbers");
-  yield addProperty(view, 1, "font-size", "72px");
+  // Insert a new property, which will affect the line numbers.
+  let elementRuleEditor = getRuleViewRuleEditor(view, 1);
+  let onRuleViewChanged = view.once("ruleview-changed");
+  yield createNewRuleViewProperty(elementRuleEditor, "font-size: 72px");
+  yield onRuleViewChanged;
 
   yield selectNode("#inner", inspector);
 
   let value = getRuleViewLinkTextByIndex(view, 3);
   // Note that this is relative to the <style>.
   is(value.slice(-3), ":27", "rule line number is 27");
 });
--- a/devtools/client/inspector/rules/test/browser_rules_keyframes-rule_01.js
+++ b/devtools/client/inspector/rules/test/browser_rules_keyframes-rule_01.js
@@ -60,19 +60,25 @@ function* testMoxy(inspector, view) {
   });
 
   assertGutters(view, {
     guttersNbs: 2,
     gutterHeading: ["Keyframes boxy", "Keyframes moxy"]
   });
 }
 
-function* assertKeyframeRules(selector, inspector, view, expected) {
+function* testNode(selector, inspector, view) {
+  let element = getNode(selector);
   yield selectNode(selector, inspector);
   let elementStyle = view._elementStyle;
+  return {element, elementStyle};
+}
+
+function* assertKeyframeRules(selector, inspector, view, expected) {
+  let {element, elementStyle} = yield testNode(selector, inspector, view);
 
   let rules = {
     elementRules: elementStyle.rules.filter(rule => !rule.keyframes),
     keyframeRules: elementStyle.rules.filter(rule => rule.keyframes)
   };
 
   is(rules.elementRules.length, expected.elementRulesNb, selector +
     " has the correct number of non keyframe element rules");
@@ -82,16 +88,18 @@ function* assertKeyframeRules(selector, 
   let i = 0;
   for (let keyframeRule of rules.keyframeRules) {
     ok(keyframeRule.keyframes.name == expected.keyframesRules[i],
       keyframeRule.keyframes.name + " has the correct keyframes name");
     ok(keyframeRule.domRule.keyText == expected.keyframeRules[i],
       keyframeRule.domRule.keyText + " selector heading is correct");
     i++;
   }
+
+  return {rules, element, elementStyle};
 }
 
 function assertGutters(view, expected) {
   let gutters = view.element.querySelectorAll(".theme-gutter");
 
   is(gutters.length, expected.guttersNbs,
     "There are " + gutters.length + " gutter headings");
 
--- a/devtools/client/inspector/rules/test/browser_rules_keyframes-rule_02.js
+++ b/devtools/client/inspector/rules/test/browser_rules_keyframes-rule_02.js
@@ -14,28 +14,26 @@ add_task(function*() {
   let {inspector, view} = yield openRuleView();
   yield testPacman(inspector, view);
   yield testBoxy(inspector, view);
 });
 
 function* testPacman(inspector, view) {
   info("Test content in the keyframes rule of #pacman");
 
-  let rules = yield getKeyframeRules("#pacman", inspector, view);
+  let {rules} = yield getKeyframeRules("#pacman", inspector, view);
 
   info("Test text properties for Keyframes #pacman");
 
   is(convertTextPropsToString(rules.keyframeRules[0].textProps),
     "left: 750px",
     "Keyframe pacman (100%) property is correct"
   );
 
   // Dynamic changes test disabled because of Bug 1050940
-  // If this part of the test is ever enabled again, it should be changed to
-  // use addProperty (in head.js) and stop using _applyingModifications
 
   // info("Test dynamic changes to keyframe rule for #pacman");
 
   // let defaultView = element.ownerDocument.defaultView;
   // let ruleEditor = view.element.children[5].childNodes[0]._ruleEditor;
   // ruleEditor.addProperty("opacity", "0");
 
   // yield ruleEditor._applyingModifications;
@@ -50,17 +48,17 @@ function* testPacman(inspector, view) {
 
   // is(defaultView.getComputedStyle(element).getPropertyValue("opacity"), "0",
   //   "Added opacity property should have been used.");
 }
 
 function* testBoxy(inspector, view) {
   info("Test content in the keyframes rule of #boxy");
 
-  let rules = yield getKeyframeRules("#boxy", inspector, view);
+  let {rules} = yield getKeyframeRules("#boxy", inspector, view);
 
   info("Test text properties for Keyframes #boxy");
 
   is(convertTextPropsToString(rules.keyframeRules[0].textProps),
     "background-color: blue",
     "Keyframe boxy (10%) property is correct"
   );
 
@@ -75,18 +73,20 @@ function* testBoxy(inspector, view) {
   );
 }
 
 function convertTextPropsToString(textProps) {
   return textProps.map(t => t.name + ": " + t.value).join("; ");
 }
 
 function* getKeyframeRules(selector, inspector, view) {
+  let element = getNode(selector);
+
   yield selectNode(selector, inspector);
   let elementStyle = view._elementStyle;
 
   let rules = {
     elementRules: elementStyle.rules.filter(rule => !rule.keyframes),
     keyframeRules: elementStyle.rules.filter(rule => rule.keyframes)
   };
 
-  return rules;
+  return {rules, element, elementStyle};
 }
--- a/devtools/client/inspector/rules/test/browser_rules_lineNumbers.js
+++ b/devtools/client/inspector/rules/test/browser_rules_lineNumbers.js
@@ -8,22 +8,45 @@
 // rules in the rule view.
 
 const TESTCASE_URI = URL_ROOT + "doc_ruleLineNumbers.html";
 
 add_task(function*() {
   yield addTab(TESTCASE_URI);
   let { inspector, view } = yield openRuleView();
   yield selectNode("#testid", inspector);
+  let elementRuleEditor = getRuleViewRuleEditor(view, 1);
 
   let bodyRuleEditor = getRuleViewRuleEditor(view, 3);
   let value = getRuleViewLinkTextByIndex(view, 2);
   // Note that this is relative to the <style>.
   is(value.slice(-2), ":6", "initial rule line number is 6");
 
+  info("Focusing a new property name in the rule-view");
+  let editor = yield focusEditableField(view, elementRuleEditor.closeBrace);
+
+  is(inplaceEditor(elementRuleEditor.newPropSpan), editor,
+    "The new property editor got focused");
+  let input = editor.input;
+
+  info("Entering font-size in the property name editor");
+  input.value = "font-size";
+
+  info("Pressing return to commit and focus the new value field");
   let onLocationChanged = once(bodyRuleEditor.rule.domRule, "location-changed");
-  yield addProperty(view, 1, "font-size", "23px");
+  let onValueFocus = once(elementRuleEditor.element, "focus", true);
+  EventUtils.synthesizeKey("VK_RETURN", {}, view.styleWindow);
+  yield onValueFocus;
+  yield elementRuleEditor.rule._applyingModifications;
+
+  // Getting the new value editor after focus
+  editor = inplaceEditor(view.styleDocument.activeElement);
+  info("Entering a value and bluring the field to expect a rule change");
+  editor.input.value = "23px";
+  editor.input.blur();
+  yield elementRuleEditor.rule._applyingModifications;
+
   yield onLocationChanged;
 
   let newBodyTitle = getRuleViewLinkTextByIndex(view, 2);
   // Note that this is relative to the <style>.
   is(newBodyTitle.slice(-2), ":7", "updated rule line number is 7");
 });
--- a/devtools/client/inspector/rules/test/browser_rules_livepreview.js
+++ b/devtools/client/inspector/rules/test/browser_rules_livepreview.js
@@ -37,35 +37,38 @@ add_task(function*() {
   yield selectNode("#testid", inspector);
 
   for (let data of TEST_DATA) {
     yield testLivePreviewData(data, view, "#testid");
   }
 });
 
 function* testLivePreviewData(data, ruleView, selector) {
-  let rule = getRuleViewRuleEditor(ruleView, 1).rule;
-  let propEditor = rule.textProps[0].editor;
+  let ruleEditor = getRuleViewRuleEditor(ruleView, 1);
+  let propEditor = ruleEditor.rule.textProps[0].editor;
 
   info("Focusing the property value inplace-editor");
   let editor = yield focusEditableField(ruleView, propEditor.valueSpan);
   is(inplaceEditor(propEditor.valueSpan), editor,
     "The focused editor is the value");
 
-  info("Entering value in the editor: " + data.value);
-  let onPreviewDone = ruleView.once("ruleview-changed");
+  info("Enter a value in the editor");
   EventUtils.sendString(data.value, ruleView.styleWindow);
-  yield onPreviewDone;
-
-  let onValueDone = ruleView.once("ruleview-changed");
   if (data.escape) {
     EventUtils.synthesizeKey("VK_ESCAPE", {});
   } else {
     EventUtils.synthesizeKey("VK_RETURN", {});
   }
-  yield onValueDone;
+
+  // Wait for the modifyproperties request to complete before
+  // checking the computed style.
+  for (let rule of ruleView._elementStyle.rules) {
+    if (rule._applyingModifications) {
+      yield rule._applyingModifications;
+    }
+  }
 
   // While the editor is still focused in, the display should have
   // changed already
   is((yield getComputedStyleProperty(selector, null, "display")),
     data.expected,
     "Element should be previewed as " + data.expected);
 }
--- a/devtools/client/inspector/rules/test/browser_rules_mark_overridden_01.js
+++ b/devtools/client/inspector/rules/test/browser_rules_mark_overridden_01.js
@@ -18,39 +18,47 @@ const TEST_URI = `
   </style>
   <div id='testid' class='testclass'>Styled Node</div>
 `;
 
 add_task(function*() {
   yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
   let {inspector, view} = yield openRuleView();
   yield selectNode("#testid", inspector);
+  yield testMarkOverridden(inspector, view);
+});
 
-  let idRule = getRuleViewRuleEditor(view, 1).rule;
+function* testMarkOverridden(inspector, view) {
+  let elementStyle = view._elementStyle;
+
+  let idRule = elementStyle.rules[1];
   let idProp = idRule.textProps[0];
   is(idProp.name, "background-color",
     "First ID property should be background-color");
   is(idProp.value, "blue", "First ID property value should be blue");
   ok(!idProp.overridden, "ID prop should not be overridden.");
   ok(!idProp.editor.element.classList.contains("ruleview-overridden"),
     "ID property editor should not have ruleview-overridden class");
 
-  let classRule = getRuleViewRuleEditor(view, 2).rule;
+  let classRule = elementStyle.rules[2];
   let classProp = classRule.textProps[0];
   is(classProp.name, "background-color",
     "First class prop should be background-color");
   is(classProp.value, "green", "First class property value should be green");
   ok(classProp.overridden, "Class property should be overridden.");
   ok(classProp.editor.element.classList.contains("ruleview-overridden"),
     "Class property editor should have ruleview-overridden class");
 
   // Override background-color by changing the element style.
-  let elementProp = yield addProperty(view, 0, "background-color", "purple");
+  let elementRule = elementStyle.rules[0];
+  elementRule.createProperty("background-color", "purple", "");
+  yield elementRule._applyingModifications;
 
+  let elementProp = elementRule.textProps[0];
   ok(!elementProp.overridden,
     "Element style property should not be overridden");
   ok(idProp.overridden, "ID property should be overridden");
   ok(idProp.editor.element.classList.contains("ruleview-overridden"),
     "ID property editor should have ruleview-overridden class");
   ok(classProp.overridden, "Class property should be overridden");
   ok(classProp.editor.element.classList.contains("ruleview-overridden"),
     "Class property editor should have ruleview-overridden class");
-});
+}
--- a/devtools/client/inspector/rules/test/browser_rules_mark_overridden_03.js
+++ b/devtools/client/inspector/rules/test/browser_rules_mark_overridden_03.js
@@ -18,24 +18,31 @@ const TEST_URI = `
   </style>
   <div id='testid' class='testclass'>Styled Node</div>
 `;
 
 add_task(function*() {
   yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
   let {inspector, view} = yield openRuleView();
   yield selectNode("#testid", inspector);
+  yield testMarkOverridden(inspector, view);
+});
 
-  let idRule = getRuleViewRuleEditor(view, 1).rule;
+function* testMarkOverridden(inspector, view) {
+  let elementStyle = view._elementStyle;
+
+  let idRule = elementStyle.rules[1];
   let idProp = idRule.textProps[0];
   ok(idProp.overridden, "Not-important rule should be overridden.");
 
-  let classRule = getRuleViewRuleEditor(view, 2).rule;
+  let classRule = elementStyle.rules[2];
   let classProp = classRule.textProps[0];
   ok(!classProp.overridden, "Important rule should not be overridden.");
 
-  ok(idProp.overridden, "ID property should be overridden.");
+  let elementRule = elementStyle.rules[0];
+  let elementProp = elementRule.createProperty("background-color", "purple",
+    "important");
+  yield elementRule._applyingModifications;
 
-  // FIXME: re-enable these 2 assertions when bug 1247737 is fixed.
-  // let elementProp = yield addProperty(view, 0, "background-color", "purple");
-  // ok(!elementProp.overridden, "New important prop should not be overriden.");
-  // ok(classProp.overridden, "Class property should be overridden.");
-});
+  ok(!elementProp.overridden, "New important prop should not be overriden.");
+  ok(idProp.overridden, "ID property should be overridden.");
+  ok(classProp.overridden, "Class property should be overridden.");
+}
--- a/devtools/client/inspector/rules/test/browser_rules_mark_overridden_04.js
+++ b/devtools/client/inspector/rules/test/browser_rules_mark_overridden_04.js
@@ -18,19 +18,25 @@ const TEST_URI = `
   </style>
   <div id='testid' class='testclass'>Styled Node</div>
 `;
 
 add_task(function*() {
   yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
   let {inspector, view} = yield openRuleView();
   yield selectNode("#testid", inspector);
+  yield testMarkOverridden(inspector, view);
+});
 
-  let idRule = getRuleViewRuleEditor(view, 1).rule;
+function* testMarkOverridden(inspector, view) {
+  let elementStyle = view._elementStyle;
+
+  let idRule = elementStyle.rules[1];
   let idProp = idRule.textProps[0];
 
-  yield togglePropStatus(view, idProp);
+  idProp.setEnabled(false);
+  yield idRule._applyingModifications;
 
-  let classRule = getRuleViewRuleEditor(view, 2).rule;
+  let classRule = elementStyle.rules[2];
   let classProp = classRule.textProps[0];
   ok(!classProp.overridden,
     "Class prop should not be overridden after id prop was disabled.");
-});
+}
--- a/devtools/client/inspector/rules/test/browser_rules_mark_overridden_05.js
+++ b/devtools/client/inspector/rules/test/browser_rules_mark_overridden_05.js
@@ -15,19 +15,23 @@ const TEST_URI = `
   </style>
   <div id='testid' class='testclass'>Styled Node</div>
 `;
 
 add_task(function*() {
   yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
   let {inspector, view} = yield openRuleView();
   yield selectNode("#testid", inspector);
+  yield testMarkOverridden(inspector, view);
+});
 
-  let rule = getRuleViewRuleEditor(view, 1).rule;
+function* testMarkOverridden(inspector, view) {
+  let ruleEditor = getRuleViewRuleEditor(view, 1);
 
-  yield addProperty(view, 1, "background-color", "red");
+  yield createNewRuleViewProperty(ruleEditor, "background-color: red;");
+  yield ruleEditor.rule._applyingModifications;
 
-  let firstProp = rule.textProps[0];
-  let secondProp = rule.textProps[1];
+  let firstProp = ruleEditor.rule.textProps[0];
+  let secondProp = ruleEditor.rule.textProps[1];
 
   ok(firstProp.overridden, "First property should be overridden.");
   ok(!secondProp.overridden, "Second property should not be overridden.");
-});
+}
--- a/devtools/client/inspector/rules/test/browser_rules_original-source-link.js
+++ b/devtools/client/inspector/rules/test/browser_rules_original-source-link.js
@@ -73,12 +73,13 @@ function editorSelected(editor) {
 
   let {line} = editor.sourceEditor.getCursor();
   is(line, 3, "cursor is at correct line number in original source");
 }
 
 function verifyLinkText(text, view) {
   info("Verifying that the rule-view stylesheet link is " + text);
   let label = getRuleViewLinkByIndex(view, 1).querySelector("label");
-  return waitForSuccess(function*() {
-    return label.getAttribute("value") == text;
-  }, "Link text changed to display correct location: " + text);
+  return waitForSuccess(
+    () => label.getAttribute("value") == text,
+    "Link text changed to display correct location: " + text
+  );
 }
--- a/devtools/client/inspector/rules/test/browser_rules_pseudo-element_01.js
+++ b/devtools/client/inspector/rules/test/browser_rules_pseudo-element_01.js
@@ -21,18 +21,18 @@ add_task(function*() {
   yield testBottomLeft(inspector, view);
   yield testParagraph(inspector, view);
   yield testBody(inspector, view);
 
   Services.prefs.clearUserPref(PSEUDO_PREF);
 });
 
 function* testTopLeft(inspector, view) {
-  let id = "#topleft";
-  let rules = yield assertPseudoElementRulesNumbers(id,
+  let selector = "#topleft";
+  let {rules} = yield assertPseudoElementRulesNumbers(selector,
     inspector, view, {
       elementRulesNb: 4,
       firstLineRulesNb: 2,
       firstLetterRulesNb: 1,
       selectionRulesNb: 0
     }
   );
 
@@ -53,74 +53,71 @@ function* testTopLeft(inspector, view) {
 
   info("Make sure that dblclicking on the header container also toggles " +
        "the pseudo elements");
   EventUtils.synthesizeMouseAtCenter(gutters[0], {clickCount: 2},
                                      view.styleWindow);
   ok(!view.element.firstChild.classList.contains("show-expandable-container"),
      "Pseudo Elements are collapsed by dblclicking");
 
+  let elementRule = rules.elementRules[0];
   let elementRuleView = getRuleViewRuleEditor(view, 3);
 
   let elementFirstLineRule = rules.firstLineRules[0];
-  let elementFirstLineRuleView =
-    [...view.element.children[1].children].filter(e => {
-      return e._ruleEditor && e._ruleEditor.rule === elementFirstLineRule;
-    })[0]._ruleEditor;
+  let elementFirstLineRuleView = [...view.element.children[1].children].filter(e => {
+    return e._ruleEditor && e._ruleEditor.rule === elementFirstLineRule;
+  })[0]._ruleEditor;
 
   is(convertTextPropsToString(elementFirstLineRule.textProps),
      "color: orange",
      "TopLeft firstLine properties are correct");
 
-  let onAdded = view.once("ruleview-changed");
   let firstProp = elementFirstLineRuleView.addProperty("background-color",
     "rgb(0, 255, 0)", "");
-  yield onAdded;
-
-  onAdded = view.once("ruleview-changed");
   let secondProp = elementFirstLineRuleView.addProperty("font-style",
     "italic", "");
-  yield onAdded;
 
   is(firstProp,
      elementFirstLineRule.textProps[elementFirstLineRule.textProps.length - 2],
      "First added property is on back of array");
   is(secondProp,
      elementFirstLineRule.textProps[elementFirstLineRule.textProps.length - 1],
      "Second added property is on back of array");
 
-  is((yield getComputedStyleProperty(id, ":first-line", "background-color")),
+  yield elementFirstLineRule._applyingModifications;
+
+  is((yield getComputedStyleProperty(selector, ":first-line", "background-color")),
      "rgb(0, 255, 0)", "Added property should have been used.");
-  is((yield getComputedStyleProperty(id, ":first-line", "font-style")),
+  is((yield getComputedStyleProperty(selector, ":first-line", "font-style")),
      "italic", "Added property should have been used.");
-  is((yield getComputedStyleProperty(id, null, "text-decoration")),
+  is((yield getComputedStyleProperty(selector, null, "text-decoration")),
      "none", "Added property should not apply to element");
 
-  yield togglePropStatus(view, firstProp);
+  firstProp.setEnabled(false);
+  yield elementFirstLineRule._applyingModifications;
 
-  is((yield getComputedStyleProperty(id, ":first-line", "background-color")),
+  is((yield getComputedStyleProperty(selector, ":first-line", "background-color")),
      "rgb(255, 0, 0)", "Disabled property should now have been used.");
-  is((yield getComputedStyleProperty(id, null, "background-color")),
+  is((yield getComputedStyleProperty(selector, null, "background-color")),
      "rgb(221, 221, 221)", "Added property should not apply to element");
 
-  yield togglePropStatus(view, firstProp);
+  firstProp.setEnabled(true);
+  yield elementFirstLineRule._applyingModifications;
 
-  is((yield getComputedStyleProperty(id, ":first-line", "background-color")),
+  is((yield getComputedStyleProperty(selector, ":first-line", "background-color")),
      "rgb(0, 255, 0)", "Added property should have been used.");
-  is((yield getComputedStyleProperty(id, null, "text-decoration")),
+  is((yield getComputedStyleProperty(selector, null, "text-decoration")),
      "none", "Added property should not apply to element");
 
-  onAdded = view.once("ruleview-changed");
-  firstProp = elementRuleView.addProperty("background-color",
-                                          "rgb(0, 0, 255)", "");
-  yield onAdded;
+  firstProp = elementRuleView.addProperty("background-color", "rgb(0, 0, 255)", "");
+  yield elementRule._applyingModifications;
 
-  is((yield getComputedStyleProperty(id, null, "background-color")),
+  is((yield getComputedStyleProperty(selector, null, "background-color")),
      "rgb(0, 0, 255)", "Added property should have been used.");
-  is((yield getComputedStyleProperty(id, ":first-line", "background-color")),
+  is((yield getComputedStyleProperty(selector, ":first-line", "background-color")),
      "rgb(0, 255, 0)", "Added prop does not apply to pseudo");
 }
 
 function* testTopRight(inspector, view) {
   yield assertPseudoElementRulesNumbers("#topright", inspector, view, {
     elementRulesNb: 4,
     firstLineRulesNb: 1,
     firstLetterRulesNb: 1,
@@ -153,23 +150,22 @@ function* testBottomLeft(inspector, view
     elementRulesNb: 4,
     firstLineRulesNb: 1,
     firstLetterRulesNb: 1,
     selectionRulesNb: 0
   });
 }
 
 function* testParagraph(inspector, view) {
-  let rules =
-    yield assertPseudoElementRulesNumbers("#bottomleft p", inspector, view, {
-      elementRulesNb: 3,
-      firstLineRulesNb: 1,
-      firstLetterRulesNb: 1,
-      selectionRulesNb: 1
-    });
+  let {rules} = yield assertPseudoElementRulesNumbers("#bottomleft p", inspector, view, {
+    elementRulesNb: 3,
+    firstLineRulesNb: 1,
+    firstLetterRulesNb: 1,
+    selectionRulesNb: 1
+  });
 
   assertGutters(view);
 
   let elementFirstLineRule = rules.firstLineRules[0];
   is(convertTextPropsToString(elementFirstLineRule.textProps),
      "background: blue",
      "Paragraph first-line properties are correct");
 
@@ -191,23 +187,24 @@ function* testBody(inspector, view) {
   is(gutters.length, 0, "There are no gutter headings");
 }
 
 function convertTextPropsToString(textProps) {
   return textProps.map(t => t.name + ": " + t.value).join("; ");
 }
 
 function* testNode(selector, inspector, view) {
+  let element = getNode(selector);
   yield selectNode(selector, inspector);
   let elementStyle = view._elementStyle;
-  return elementStyle;
+  return {element: element, elementStyle: elementStyle};
 }
 
 function* assertPseudoElementRulesNumbers(selector, inspector, view, ruleNbs) {
-  let elementStyle = yield testNode(selector, inspector, view);
+  let {element, elementStyle} = yield testNode(selector, inspector, view);
 
   let rules = {
     elementRules: elementStyle.rules.filter(rule => !rule.pseudoElement),
     firstLineRules: elementStyle.rules.filter(rule =>
       rule.pseudoElement === ":first-line"),
     firstLetterRules: elementStyle.rules.filter(rule =>
       rule.pseudoElement === ":first-letter"),
     selectionRules: elementStyle.rules.filter(rule =>
@@ -218,17 +215,17 @@ function* assertPseudoElementRulesNumber
      selector + " has the correct number of non pseudo element rules");
   is(rules.firstLineRules.length, ruleNbs.firstLineRulesNb,
      selector + " has the correct number of :first-line rules");
   is(rules.firstLetterRules.length, ruleNbs.firstLetterRulesNb,
      selector + " has the correct number of :first-letter rules");
   is(rules.selectionRules.length, ruleNbs.selectionRulesNb,
      selector + " has the correct number of :selection rules");
 
-  return rules;
+  return {rules, element, elementStyle};
 }
 
 function getGutters(view) {
   return view.element.querySelectorAll(".theme-gutter");
 }
 
 function assertGutters(view) {
   let gutters = getGutters(view);
--- a/devtools/client/inspector/rules/test/browser_rules_refresh-no-flicker.js
+++ b/devtools/client/inspector/rules/test/browser_rules_refresh-no-flicker.js
@@ -1,25 +1,24 @@
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 // Test that the rule view does not go blank while selecting a new node.
 
-const TESTCASE_URI = "data:text/html;charset=utf-8," +
-                     "<div id=\"testdiv\" style=\"font-size:10px;\">" +
-                     "Test div!</div>";
+const TESTCASE_URI = 'data:text/html;charset=utf-8,' +
+                     '<div id="testdiv" style="font-size:10px;">Test div!</div>';
 
 add_task(function*() {
   yield addTab(TESTCASE_URI);
 
   info("Opening the rule view and selecting the test node");
-  let {inspector, view} = yield openRuleView();
+  let {toolbox, inspector, view} = yield openRuleView();
   let testdiv = yield getNodeFront("#testdiv", inspector);
   yield selectNode(testdiv, inspector);
 
   let htmlBefore = view.element.innerHTML;
   ok(htmlBefore.indexOf("font-size") > -1,
      "The rule view should contain a font-size property.");
 
   // Do the selectNode call manually, because otherwise it's hard to guarantee
--- a/devtools/client/inspector/rules/test/browser_rules_refresh-on-attribute-change_01.js
+++ b/devtools/client/inspector/rules/test/browser_rules_refresh-on-attribute-change_01.js
@@ -17,35 +17,36 @@ const TEST_URI = `
   </style>
   <div id="testid" class="testclass" style="margin-top: 1px; padding-top: 5px;">
     Styled Node
   </div>
 `;
 
 add_task(function*() {
   yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
-  let {inspector, view, testActor} = yield openRuleView();
+  let {inspector, view} = yield openRuleView();
+  let testElement = getNode("#testid");
   yield selectNode("#testid", inspector);
 
   info("Checking that the rule-view has the element, #testid and " +
     ".testclass selectors");
   checkRuleViewContent(view, ["element", "#testid", ".testclass"]);
 
   info("Changing the node's ID attribute and waiting for the " +
     "rule-view refresh");
   let ruleViewRefreshed = inspector.once("rule-view-refreshed");
-  yield testActor.setAttribute("#testid", "id", "differentid");
+  testElement.setAttribute("id", "differentid");
   yield ruleViewRefreshed;
 
   info("Checking that the rule-view doesn't have the #testid selector anymore");
   checkRuleViewContent(view, ["element", ".testclass"]);
 
   info("Reverting the ID attribute change");
   ruleViewRefreshed = inspector.once("rule-view-refreshed");
-  yield testActor.setAttribute("#differentid", "id", "testid");
+  testElement.setAttribute("id", "testid");
   yield ruleViewRefreshed;
 
   info("Checking that the rule-view has all the selectors again");
   checkRuleViewContent(view, ["element", "#testid", ".testclass"]);
 });
 
 function checkRuleViewContent(view, expectedSelectors) {
   let selectors = view.styleDocument
--- a/devtools/client/inspector/rules/test/browser_rules_refresh-on-attribute-change_02.js
+++ b/devtools/client/inspector/rules/test/browser_rules_refresh-on-attribute-change_02.js
@@ -10,144 +10,144 @@
 const TEST_URI = `
   <div id="testid" class="testclass" style="margin-top: 1px; padding-top: 5px;">
     Styled Node
   </div>
 `;
 
 add_task(function*() {
   yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
-  let {inspector, view, testActor} = yield openRuleView();
+  let {inspector, view} = yield openRuleView();
+  let testElement = getNode("#testid");
   yield selectNode("#testid", inspector);
 
   yield testPropertyChanges(inspector, view);
-  yield testPropertyChange0(inspector, view, "#testid", testActor);
-  yield testPropertyChange1(inspector, view, "#testid", testActor);
-  yield testPropertyChange2(inspector, view, "#testid", testActor);
-  yield testPropertyChange3(inspector, view, "#testid", testActor);
-  yield testPropertyChange4(inspector, view, "#testid", testActor);
-  yield testPropertyChange5(inspector, view, "#testid", testActor);
-  yield testPropertyChange6(inspector, view, "#testid", testActor);
+  yield testPropertyChange0(inspector, view, testElement);
+  yield testPropertyChange1(inspector, view, testElement);
+  yield testPropertyChange2(inspector, view, testElement);
+  yield testPropertyChange3(inspector, view, testElement);
+  yield testPropertyChange4(inspector, view, testElement);
+  yield testPropertyChange5(inspector, view, testElement);
+  yield testPropertyChange6(inspector, view, testElement);
 });
 
 function* testPropertyChanges(inspector, ruleView) {
   info("Adding a second margin-top value in the element selector");
   let ruleEditor = ruleView._elementStyle.rules[0].editor;
   let onRefreshed = inspector.once("rule-view-refreshed");
   ruleEditor.addProperty("margin-top", "5px", "");
   yield onRefreshed;
 
   let rule = ruleView._elementStyle.rules[0];
   validateTextProp(rule.textProps[0], false, "margin-top", "1px",
     "Original margin property active");
 }
 
-function* testPropertyChange0(inspector, ruleView, selector, testActor) {
-  yield changeElementStyle(selector, "margin-top: 1px; padding-top: 5px",
-    inspector, testActor);
+function* testPropertyChange0(inspector, ruleView, testElement) {
+  yield changeElementStyle(testElement, "margin-top: 1px; padding-top: 5px",
+    inspector);
 
   let rule = ruleView._elementStyle.rules[0];
   is(rule.editor.element.querySelectorAll(".ruleview-property").length, 3,
     "Correct number of properties");
   validateTextProp(rule.textProps[0], true, "margin-top", "1px",
     "First margin property re-enabled");
   validateTextProp(rule.textProps[2], false, "margin-top", "5px",
     "Second margin property disabled");
 }
 
-function* testPropertyChange1(inspector, ruleView, selector, testActor) {
+function* testPropertyChange1(inspector, ruleView, testElement) {
   info("Now set it back to 5px, the 5px value should be re-enabled.");
-  yield changeElementStyle(selector, "margin-top: 5px; padding-top: 5px;",
-    inspector, testActor);
+  yield changeElementStyle(testElement, "margin-top: 5px; padding-top: 5px;",
+    inspector);
 
   let rule = ruleView._elementStyle.rules[0];
   is(rule.editor.element.querySelectorAll(".ruleview-property").length, 3,
     "Correct number of properties");
   validateTextProp(rule.textProps[0], false, "margin-top", "1px",
     "First margin property re-enabled");
   validateTextProp(rule.textProps[2], true, "margin-top", "5px",
     "Second margin property disabled");
 }
 
-function* testPropertyChange2(inspector, ruleView, selector, testActor) {
+function* testPropertyChange2(inspector, ruleView, testElement) {
   info("Set the margin property to a value that doesn't exist in the editor.");
   info("Should reuse the currently-enabled element (the second one.)");
-  yield changeElementStyle(selector, "margin-top: 15px; padding-top: 5px;",
-    inspector, testActor);
+  yield changeElementStyle(testElement, "margin-top: 15px; padding-top: 5px;",
+    inspector);
 
   let rule = ruleView._elementStyle.rules[0];
   is(rule.editor.element.querySelectorAll(".ruleview-property").length, 3,
     "Correct number of properties");
   validateTextProp(rule.textProps[0], false, "margin-top", "1px",
     "First margin property re-enabled");
   validateTextProp(rule.textProps[2], true, "margin-top", "15px",
     "Second margin property disabled");
 }
 
-function* testPropertyChange3(inspector, ruleView, selector, testActor) {
+function* testPropertyChange3(inspector, ruleView, testElement) {
   info("Remove the padding-top attribute. Should disable the padding " +
     "property but not remove it.");
-  yield changeElementStyle(selector, "margin-top: 5px;", inspector, testActor);
+  yield changeElementStyle(testElement, "margin-top: 5px;", inspector);
 
   let rule = ruleView._elementStyle.rules[0];
   is(rule.editor.element.querySelectorAll(".ruleview-property").length, 3,
     "Correct number of properties");
   validateTextProp(rule.textProps[1], false, "padding-top", "5px",
     "Padding property disabled");
 }
 
-function* testPropertyChange4(inspector, ruleView, selector, testActor) {
+function* testPropertyChange4(inspector, ruleView, testElement) {
   info("Put the padding-top attribute back in, should re-enable the " +
     "padding property.");
-  yield changeElementStyle(selector, "margin-top: 5px; padding-top: 25px",
-    inspector, testActor);
+  yield changeElementStyle(testElement, "margin-top: 5px; padding-top: 25px",
+    inspector);
 
   let rule = ruleView._elementStyle.rules[0];
   is(rule.editor.element.querySelectorAll(".ruleview-property").length, 3,
     "Correct number of properties");
   validateTextProp(rule.textProps[1], true, "padding-top", "25px",
     "Padding property enabled");
 }
 
-function* testPropertyChange5(inspector, ruleView, selector, testActor) {
+function* testPropertyChange5(inspector, ruleView, testElement) {
   info("Add an entirely new property");
-  yield changeElementStyle(selector,
-    "margin-top: 5px; padding-top: 25px; padding-left: 20px;",
-    inspector, testActor);
+  yield changeElementStyle(testElement,
+    "margin-top: 5px; padding-top: 25px; padding-left: 20px;", inspector);
 
   let rule = ruleView._elementStyle.rules[0];
   is(rule.editor.element.querySelectorAll(".ruleview-property").length, 4,
     "Added a property");
   validateTextProp(rule.textProps[3], true, "padding-left", "20px",
     "Padding property enabled");
 }
 
-function* testPropertyChange6(inspector, ruleView, selector, testActor) {
+function* testPropertyChange6(inspector, ruleView, testElement) {
   info("Add an entirely new property again");
-  yield changeElementStyle(selector, "background: red " +
+  yield changeElementStyle(testElement, "background: red " +
     "url(\"chrome://branding/content/about-logo.png\") repeat scroll 0% 0%",
-    inspector, testActor);
+    inspector);
 
   let rule = ruleView._elementStyle.rules[0];
   is(rule.editor.element.querySelectorAll(".ruleview-property").length, 5,
     "Added a property");
   validateTextProp(rule.textProps[4], true, "background",
                    "red url(\"chrome://branding/content/about-logo.png\") repeat scroll 0% 0%",
                    "shortcut property correctly set");
 }
 
-function* changeElementStyle(selector, style, inspector, testActor) {
+function* changeElementStyle(testElement, style, inspector) {
   let onRefreshed = inspector.once("rule-view-refreshed");
-  yield testActor.setAttribute(selector, "style", style);
+  testElement.setAttribute("style", style);
   yield onRefreshed;
 }
 
-function validateTextProp(prop, enabled, name, value, desc) {
-  is(prop.enabled, enabled, desc + ": enabled.");
-  is(prop.name, name, desc + ": name.");
-  is(prop.value, value, desc + ": value.");
+function validateTextProp(aProp, aEnabled, aName, aValue, aDesc) {
+  is(aProp.enabled, aEnabled, aDesc + ": enabled.");
+  is(aProp.name, aName, aDesc + ": name.");
+  is(aProp.value, aValue, aDesc + ": value.");
 
-  is(prop.editor.enable.hasAttribute("checked"), enabled,
-    desc + ": enabled checkbox.");
-  is(prop.editor.nameSpan.textContent, name, desc + ": name span.");
-  is(prop.editor.valueSpan.textContent,
-    value, desc + ": value span.");
+  is(aProp.editor.enable.hasAttribute("checked"), aEnabled,
+    aDesc + ": enabled checkbox.");
+  is(aProp.editor.nameSpan.textContent, aName, aDesc + ": name span.");
+  is(aProp.editor.valueSpan.textContent,
+    aValue, aDesc + ": value span.");
 }
--- a/devtools/client/inspector/rules/test/browser_rules_refresh-on-style-change.js
+++ b/devtools/client/inspector/rules/test/browser_rules_refresh-on-style-change.js
@@ -8,27 +8,27 @@
 // changed
 
 const TEST_URI = "<div id='testdiv' style='font-size: 10px;''>Test div!</div>";
 
 add_task(function*() {
   Services.prefs.setCharPref("devtools.defaultColorUnit", "name");
 
   yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
-  let {inspector, view, testActor} = yield openRuleView();
+  let {inspector, view} = yield openRuleView();
   yield selectNode("#testdiv", inspector);
 
   let fontSize = getRuleViewPropertyValue(view, "element", "font-size");
   is(fontSize, "10px", "The rule view shows the right font-size");
 
   info("Changing the node's style and waiting for the update");
   let onUpdated = inspector.once("rule-view-refreshed");
-  yield testActor.setAttribute("#testdiv", "style",
-    "font-size: 3em; color: lightgoldenrodyellow; " +
-    "text-align: right; text-transform: uppercase");
+  let div = getNode("#testdiv");
+  div.style.cssText = "font-size: 3em; color: lightgoldenrodyellow; " +
+    "text-align: right; text-transform: uppercase";
   yield onUpdated;
 
   let textAlign = getRuleViewPropertyValue(view, "element", "text-align");
   is(textAlign, "right", "The rule view shows the new text align.");
   let color = getRuleViewPropertyValue(view, "element", "color");
   is(color, "lightgoldenrodyellow", "The rule view shows the new color.");
   fontSize = getRuleViewPropertyValue(view, "element", "font-size");
   is(fontSize, "3em", "The rule view shows the new font size.");
--- a/devtools/client/inspector/rules/test/browser_rules_search-filter-computed-list_01.js
+++ b/devtools/client/inspector/rules/test/browser_rules_search-filter-computed-list_01.js
@@ -16,66 +16,61 @@ const TEST_URI = `
       background-color: red;
     }
   </style>
   <h1 id="testid" class="testclass">Styled Node</h1>
 `;
 
 const TEST_DATA = [
   {
-    desc: "Tests that the search filter works properly in the computed list " +
-          "for property names",
+    desc: "Tests that the search filter works properly in the computed list for property names",
     search: "margin",
     isExpanderOpen: false,
     isFilterOpen: false,
     isMarginHighlighted: true,
     isMarginTopHighlighted: true,
     isMarginRightHighlighted: true,
     isMarginBottomHighlighted: true,
     isMarginLeftHighlighted: true
   },
   {
-    desc: "Tests that the search filter works properly in the computed list " +
-          "for property values",
+    desc: "Tests that the search filter works properly in the computed list for property values",
     search: "0px",
     isExpanderOpen: false,
     isFilterOpen: false,
     isMarginHighlighted: true,
     isMarginTopHighlighted: false,
     isMarginRightHighlighted: true,
     isMarginBottomHighlighted: false,
     isMarginLeftHighlighted: true
   },
   {
-    desc: "Tests that the search filter works properly in the computed list " +
-          "for property line input",
+    desc: "Tests that the search filter works properly in the computed list for property line input",
     search: "margin-top:4px",
     isExpanderOpen: true,
     isFilterOpen: true,
     isMarginHighlighted: false,
     isMarginTopHighlighted: true,
     isMarginRightHighlighted: false,
     isMarginBottomHighlighted: false,
     isMarginLeftHighlighted: false
   },
   {
-    desc: "Tests that the search filter works properly in the computed list " +
-          "for parsed name",
+    desc: "Tests that the search filter works properly in the computed list for parsed name",
     search: "margin-top:",
     isExpanderOpen: true,
     isFilterOpen: true,
     isMarginHighlighted: false,
     isMarginTopHighlighted: true,
     isMarginRightHighlighted: false,
     isMarginBottomHighlighted: false,
     isMarginLeftHighlighted: false
   },
   {
-    desc: "Tests that the search filter works properly in the computed list " +
-          "for parsed property value",
+    desc: "Tests that the search filter works properly in the computed list for parsed property value",
     search: ":4px",
     isExpanderOpen: false,
     isFilterOpen: false,
     isMarginHighlighted: true,
     isMarginTopHighlighted: true,
     isMarginRightHighlighted: false,
     isMarginBottomHighlighted: true,
     isMarginLeftHighlighted: false
--- a/devtools/client/inspector/rules/test/browser_rules_search-filter_01.js
+++ b/devtools/client/inspector/rules/test/browser_rules_search-filter_01.js
@@ -27,23 +27,21 @@ const TEST_DATA = [
     desc: "Tests that the search filter works properly for property values",
     search: "00F"
   },
   {
     desc: "Tests that the search filter works properly for property line input",
     search: "background-color:#00F"
   },
   {
-    desc: "Tests that the search filter works properly for parsed property " +
-          "names",
+    desc: "Tests that the search filter works properly for parsed property names",
     search: "background:"
   },
   {
-    desc: "Tests that the search filter works properly for parsed property " +
-          "values",
+    desc: "Tests that the search filter works properly for parsed property values",
     search: ":00F"
   },
 ];
 
 add_task(function*() {
   yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
   let {inspector, view} = yield openRuleView();
   yield selectNode("#testid", inspector);
--- a/devtools/client/inspector/rules/test/browser_rules_search-filter_08.js
+++ b/devtools/client/inspector/rules/test/browser_rules_search-filter_08.js
@@ -26,17 +26,17 @@ add_task(function*() {
 
   info("Enter the test value in the search filter");
   yield setSearchFilter(view, SEARCH);
 
   info("Focus the height property value");
   let ruleEditor = getRuleViewRuleEditor(view, 1);
   let rule = ruleEditor.rule;
   let propEditor = rule.textProps[1].editor;
-  yield focusEditableField(view, propEditor.valueSpan);
+  let editor = yield focusEditableField(view, propEditor.valueSpan);
 
   info("Check that the correct rules are visible");
   is(view.element.children.length, 2, "Should have 2 rules.");
   is(rule.selectorText, "#testid", "Second rule is #testid.");
   ok(rule.textProps[0].editor.container.classList
     .contains("ruleview-highlight"),
     "width text property is correctly highlighted.");
   ok(!propEditor.container.classList.contains("ruleview-highlight"),
--- a/devtools/client/inspector/rules/test/browser_rules_search-filter_09.js
+++ b/devtools/client/inspector/rules/test/browser_rules_search-filter_09.js
@@ -25,17 +25,17 @@ add_task(function*() {
   yield selectNode("#testid", inspector);
 
   info("Enter the test value in the search filter");
   yield setSearchFilter(view, SEARCH);
 
   info("Start entering a new property in the rule");
   let ruleEditor = getRuleViewRuleEditor(view, 1);
   let rule = ruleEditor.rule;
-  let editor = yield focusNewRuleViewProperty(ruleEditor);
+  let editor = yield focusEditableField(view, ruleEditor.closeBrace);
 
   info("Check that the correct rules are visible");
   is(view.element.children.length, 2, "Should have 2 rules.");
   is(rule.selectorText, "#testid", "Second rule is #testid.");
   ok(rule.textProps[0].editor.container.classList
     .contains("ruleview-highlight"),
     "width text property is correctly highlighted.");
   ok(!rule.textProps[1].editor.container.classList
--- a/devtools/client/inspector/rules/test/browser_rules_search-filter_10.js
+++ b/devtools/client/inspector/rules/test/browser_rules_search-filter_10.js
@@ -15,25 +15,23 @@ const TEST_URI = `
       width: 100%;
     }
   </style>
   <div id="testid" class="testclass">Styled Node</div>
 `;
 
 const TEST_DATA = [
   {
-    desc: "Tests that the search filter works properly for a single rule " +
-          "selector",
+    desc: "Tests that the search filter works properly for a single rule selector",
     search: "#test",
     selectorText: "#testid",
     index: 0
   },
   {
-    desc: "Tests that the search filter works properly for multiple rule " +
-          "selectors",
+    desc: "Tests that the search filter works properly for multiple rule selectors",
     search: "body",
     selectorText: "html, body, div",
     index: 2
   }
 ];
 
 add_task(function*() {
   yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
--- a/devtools/client/inspector/rules/test/browser_rules_select-and-copy-styles.js
+++ b/devtools/client/inspector/rules/test/browser_rules_select-and-copy-styles.js
@@ -75,17 +75,17 @@ function* checkCopySelection(view) {
   yield onPopup;
 
   ok(!view._contextmenu.menuitemCopy.hidden,
     "Copy menu item is not hidden as expected");
 
   try {
     yield waitForClipboard(() => view._contextmenu.menuitemCopy.click(),
       () => checkClipboardData(expectedPattern));
-  } catch (e) {
+  } catch(e) {
     failedClipboard(expectedPattern);
   }
 
   view._contextmenu._menupopup.hidePopup();
 }
 
 function* checkSelectAll(view) {
   info("Testing select-all copy");
@@ -113,17 +113,17 @@ function* checkSelectAll(view) {
   yield onPopup;
 
   ok(!view._contextmenu.menuitemCopy.hidden,
     "Copy menu item is not hidden as expected");
 
   try {
     yield waitForClipboard(() => view._contextmenu.menuitemCopy.click(),
       () => checkClipboardData(expectedPattern));
-  } catch (e) {
+  } catch(e) {
     failedClipboard(expectedPattern);
   }
 
   view._contextmenu._menupopup.hidePopup();
 }
 
 function checkClipboardData(expectedPattern) {
   let actual = SpecialPowers.getClipboardData("text/unicode");
--- a/devtools/client/inspector/rules/test/browser_rules_selector_highlight.js
+++ b/devtools/client/inspector/rules/test/browser_rules_selector_highlight.js
@@ -2,16 +2,18 @@
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 // Tests that the rule view selector text is highlighted correctly according
 // to the components of the selector.
 
+const SEARCH = "00F";
+
 const TEST_URI = [
   "<style type='text/css'>",
   "  h1 {}",
   "  h1#testid {}",
   "  h1 + p {}",
   "  div[hidden=\"true\"] {}",
   "  div[title=\"test\"][checked=true] {}",
   "  p:empty {}",
--- a/devtools/client/inspector/rules/test/browser_rules_strict-search-filter-computed-list_01.js
+++ b/devtools/client/inspector/rules/test/browser_rules_strict-search-filter-computed-list_01.js
@@ -16,92 +16,85 @@ const TEST_URI = `
       background-color: red;
     }
   </style>
   <h1 id="testid" class="testclass">Styled Node</h1>
 `;
 
 const TEST_DATA = [
   {
-    desc: "Tests that the strict search filter works properly in the " +
-          "computed list for property names",
+    desc: "Tests that the strict search filter works properly in the computed list for property names",
     search: "`margin-left`",
     isExpanderOpen: true,
     isFilterOpen: true,
     isMarginHighlighted: false,
     isMarginTopHighlighted: false,
     isMarginRightHighlighted: false,
     isMarginBottomHighlighted: false,
     isMarginLeftHighlighted: true
   },
   {
-    desc: "Tests that the strict search filter works properly in the " +
-          "computed list for property values",
+    desc: "Tests that the strict search filter works properly in the computed list for property values",
     search: "`0px`",
     isExpanderOpen: true,
     isFilterOpen: true,
     isMarginHighlighted: false,
     isMarginTopHighlighted: false,
     isMarginRightHighlighted: true,
     isMarginBottomHighlighted: false,
     isMarginLeftHighlighted: false
   },
   {
-    desc: "Tests that the strict search filter works properly in the " +
-          "computed list for parsed property names",
+    desc: "Tests that the strict search filter works properly in the computed list for parsed property names",
     search: "`margin-left`:",
     isExpanderOpen: true,
     isFilterOpen: true,
     isMarginHighlighted: false,
     isMarginTopHighlighted: false,
     isMarginRightHighlighted: false,
     isMarginBottomHighlighted: false,
     isMarginLeftHighlighted: true
   },
   {
-    desc: "Tests that the strict search filter works properly in the " +
-          "computed list for parsed property values",
+    desc: "Tests that the strict search filter works properly in the computed list for parsed property values",
     search: ":`4px`",
     isExpanderOpen: true,
     isFilterOpen: true,
     isMarginHighlighted: false,
     isMarginTopHighlighted: true,
     isMarginRightHighlighted: false,
     isMarginBottomHighlighted: false,
     isMarginLeftHighlighted: false
   },
   {
-    desc: "Tests that the strict search filter works properly in the " +
-          "computed list for property line input",
+    desc: "Tests that the strict search filter works properly in the computed list for property line input",
     search: "`margin-top`:`4px`",
     isExpanderOpen: true,
     isFilterOpen: true,
     isMarginHighlighted: false,
     isMarginTopHighlighted: true,
     isMarginRightHighlighted: false,
     isMarginBottomHighlighted: false,
     isMarginLeftHighlighted: false
   },
   {
     desc: "Tests that the strict search filter works properly in the " +
-          "computed list for a parsed strict property name and non-strict " +
-          "property value",
+          "computed list for a parsed strict property name and non-strict property value",
     search: "`margin-top`:4px",
     isExpanderOpen: true,
     isFilterOpen: true,
     isMarginHighlighted: false,
     isMarginTopHighlighted: true,
     isMarginRightHighlighted: false,
     isMarginBottomHighlighted: false,
     isMarginLeftHighlighted: false
   },
   {
     desc: "Tests that the strict search filter works properly in the " +
-          "computed list for a parsed strict property value and non-strict " +
-          "property name",
+          "computed list for a parsed strict property value and non-strict property name",
     search: "i:`4px`",
     isExpanderOpen: true,
     isFilterOpen: true,
     isMarginHighlighted: false,
     isMarginTopHighlighted: true,
     isMarginRightHighlighted: false,
     isMarginBottomHighlighted: false,
     isMarginLeftHighlighted: false
--- a/devtools/client/inspector/rules/test/browser_rules_strict-search-filter_01.js
+++ b/devtools/client/inspector/rules/test/browser_rules_strict-search-filter_01.js
@@ -18,46 +18,41 @@ const TEST_URI = `
       background-color: #00F;
     }
   </style>
   <h1 id="testid" class="testclass">Styled Node</h1>
 `;
 
 const TEST_DATA = [
   {
-    desc: "Tests that the strict search filter works properly for property " +
-          "names",
+    desc: "Tests that the strict search filter works properly for property names",
     search: "`color`",
     ruleCount: 2,
     propertyIndex: 1
   },
   {
-    desc: "Tests that the strict search filter works properly for property " +
-          "values",
+    desc: "Tests that the strict search filter works properly for property values",
     search: "`2%`",
     ruleCount: 2,
     propertyIndex: 0
   },
   {
-    desc: "Tests that the strict search filter works properly for parsed " +
-          "property names",
+    desc: "Tests that the strict search filter works properly for parsed property names",
     search: "`color`:",
     ruleCount: 2,
     propertyIndex: 1
   },
   {
-    desc: "Tests that the strict search filter works properly for parsed " +
-          "property values",
+    desc: "Tests that the strict search filter works properly for parsed property values",
     search: ":`2%`",
     ruleCount: 2,
     propertyIndex: 0
   },
   {
-    desc: "Tests that the strict search filter works properly for property " +
-          "line input",
+    desc: "Tests that the strict search filter works properly for property line input",
     search: "`width`:`2%`",
     ruleCount: 2,
     propertyIndex: 0
   },
   {
     desc: "Tests that the search filter works properly for a parsed strict " +
           "property name and non-strict property value.",
     search: "`width`:2%",
--- a/devtools/client/inspector/rules/test/browser_rules_style-editor-link.js
+++ b/devtools/client/inspector/rules/test/browser_rules_style-editor-link.js
@@ -1,71 +1,73 @@
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
-// FIXME: Whitelisting this test.
+///////////////////
+//
+// Whitelisting this test.
 // As part of bug 1077403, the leaking uncaught rejection should be fixed.
+//
 thisTestLeaksUncaughtRejectionsAndShouldBeFixed("Error: Unknown sheet source");
 
 // Test the links from the rule-view to the styleeditor
 
-const STYLESHEET_URL = "data:text/css," + encodeURIComponent(
+const STYLESHEET_URL = "data:text/css,"+encodeURIComponent(
   ["#first {",
    "color: blue",
    "}"].join("\n"));
 
 const EXTERNAL_STYLESHEET_FILE_NAME = "doc_style_editor_link.css";
 const EXTERNAL_STYLESHEET_URL = URL_ROOT + EXTERNAL_STYLESHEET_FILE_NAME;
 
-const DOCUMENT_URL = "data:text/html;charset=utf-8," + encodeURIComponent(`
-  <html>
-  <head>
-  <title>Rule view style editor link test</title>
-  <style type="text/css">
-  html { color: #000000; }
-  div { font-variant: small-caps; color: #000000; }
-  .nomatches {color: #ff0000;}</style> <div id="first" style="margin: 10em;
-  font-size: 14pt; font-family: helvetica, sans-serif; color: #AAA">
-  </style>
-  <style>
-  div { font-weight: bold; }
-  </style>
-  <link rel="stylesheet" type="text/css" href="${STYLESHEET_URL}">
-  <link rel="stylesheet" type="text/css" href="${EXTERNAL_STYLESHEET_URL}">
-  </head>
-  <body>
-  <h1>Some header text</h1>
-  <p id="salutation" style="font-size: 12pt">hi.</p>
-  <p id="body" style="font-size: 12pt">I am a test-case. This text exists
-  solely to provide some things to
-  <span style="color: yellow" class="highlight">
-  highlight</span> and <span style="font-weight: bold">count</span>
-  style list-items in the box at right. If you are reading this,
-  you should go do something else instead. Maybe read a book. Or better
-  yet, write some test-cases for another bit of code.
-  <span style="font-style: italic">some text</span></p>
-  <p id="closing">more text</p>
-  <p>even more text</p>
-  </div>
-  </body>
-  </html>
-`);
+const DOCUMENT_URL = "data:text/html;charset=utf-8,"+encodeURIComponent(
+  ['<html>' +
+   '<head>' +
+   '<title>Rule view style editor link test</title>',
+   '<style type="text/css"> ',
+   'html { color: #000000; } ',
+   'div { font-variant: small-caps; color: #000000; } ',
+   '.nomatches {color: #ff0000;}</style> <div id="first" style="margin: 10em; ',
+   'font-size: 14pt; font-family: helvetica, sans-serif; color: #AAA">',
+   '</style>',
+   '<style>',
+   'div { font-weight: bold; }',
+   '</style>',
+   '<link rel="stylesheet" type="text/css" href="'+STYLESHEET_URL+'">',
+   '<link rel="stylesheet" type="text/css" href="'+EXTERNAL_STYLESHEET_URL+'">',
+   '</head>',
+   '<body>',
+   '<h1>Some header text</h1>',
+   '<p id="salutation" style="font-size: 12pt">hi.</p>',
+   '<p id="body" style="font-size: 12pt">I am a test-case. This text exists ',
+   'solely to provide some things to ',
+   '<span style="color: yellow" class="highlight">',
+   'highlight</span> and <span style="font-weight: bold">count</span> ',
+   'style list-items in the box at right. If you are reading this, ',
+   'you should go do something else instead. Maybe read a book. Or better ',
+   'yet, write some test-cases for another bit of code. ',
+   '<span style="font-style: italic">some text</span></p>',
+   '<p id="closing">more text</p>',
+   '<p>even more text</p>',
+   '</div>',
+   '</body>',
+   '</html>'].join("\n"));
 
 add_task(function*() {
   yield addTab(DOCUMENT_URL);
-  let {toolbox, inspector, view, testActor} = yield openRuleView();
+  let {toolbox, inspector, view} = yield openRuleView();
   yield selectNode("div", inspector);
 
   yield testInlineStyle(view);
-  yield testFirstInlineStyleSheet(view, toolbox, testActor);
-  yield testSecondInlineStyleSheet(view, toolbox, testActor);
-  yield testExternalStyleSheet(view, toolbox, testActor);
+  yield testFirstInlineStyleSheet(view, toolbox);
+  yield testSecondInlineStyleSheet(view, toolbox);
+  yield testExternalStyleSheet(view, toolbox);
 });
 
 function* testInlineStyle(view) {
   info("Testing inline style");
 
   let onTab = waitForTab();
   info("Clicking on the first link in the rule-view");
   clickLinkByIndex(view, 0);
@@ -73,83 +75,79 @@ function* testInlineStyle(view) {
   let tab = yield onTab;
 
   let tabURI = tab.linkedBrowser.documentURI.spec;
   ok(tabURI.startsWith("view-source:"), "View source tab is open");
   info("Closing tab");
   gBrowser.removeTab(tab);
 }
 
-function* testFirstInlineStyleSheet(view, toolbox, testActor) {
+function* testFirstInlineStyleSheet(view, toolbox) {
   info("Testing inline stylesheet");
 
   info("Listening for toolbox switch to the styleeditor");
   let onSwitch = waitForStyleEditor(toolbox);
 
   info("Clicking an inline stylesheet");
   clickLinkByIndex(view, 4);
   let editor = yield onSwitch;
 
   ok(true, "Switched to the style-editor panel in the toolbox");
 
-  yield validateStyleEditorSheet(editor, 0, testActor);
+  validateStyleEditorSheet(editor, 0);
 }
 
-function* testSecondInlineStyleSheet(view, toolbox, testActor) {
+function* testSecondInlineStyleSheet(view, toolbox) {
   info("Testing second inline stylesheet");
 
   info("Waiting for the stylesheet editor to be selected");
   let panel = toolbox.getCurrentPanel();
   let onSelected = panel.UI.once("editor-selected");
 
   info("Switching back to the inspector panel in the toolbox");
   yield toolbox.selectTool("inspector");
 
   info("Clicking on second inline stylesheet link");
   testRuleViewLinkLabel(view);
   clickLinkByIndex(view, 3);
   let editor = yield onSelected;
 
   is(toolbox.currentToolId, "styleeditor",
     "The style editor is selected again");
-  yield validateStyleEditorSheet(editor, 1, testActor);
+  validateStyleEditorSheet(editor, 1);
 }
 
-function* testExternalStyleSheet(view, toolbox, testActor) {
+function* testExternalStyleSheet(view, toolbox) {
   info("Testing external stylesheet");
 
   info("Waiting for the stylesheet editor to be selected");
   let panel = toolbox.getCurrentPanel();
   let onSelected = panel.UI.once("editor-selected");
 
   info("Switching back to the inspector panel in the toolbox");
   yield toolbox.selectTool("inspector");
 
   info("Clicking on an external stylesheet link");
   testRuleViewLinkLabel(view);
   clickLinkByIndex(view, 1);
   let editor = yield onSelected;
 
   is(toolbox.currentToolId, "styleeditor",
     "The style editor is selected again");
-  yield validateStyleEditorSheet(editor, 2, testActor);
+  validateStyleEditorSheet(editor, 2);
 }
 
-function* validateStyleEditorSheet(editor, expectedSheetIndex, testActor) {
+function validateStyleEditorSheet(editor, expectedSheetIndex) {
   info("validating style editor stylesheet");
   is(editor.styleSheet.styleSheetIndex, expectedSheetIndex,
      "loaded stylesheet index matches document stylesheet");
 
-  let href = editor.styleSheet.href || editor.styleSheet.nodeHref;
-
-  let expectedHref = yield testActor.eval(
-    `content.document.styleSheets[${expectedSheetIndex}].href ||
-     content.document.location.href`);
-
-  is(href, expectedHref, "loaded stylesheet href matches document stylesheet");
+  let sheet = content.document.styleSheets[expectedSheetIndex];
+  is(editor.styleSheet.href, sheet.href,
+    "loaded stylesheet href matches document stylesheet");
 }
 
 function testRuleViewLinkLabel(view) {
   let link = getRuleViewLinkByIndex(view, 2);
   let labelElem = link.querySelector(".ruleview-rule-source-label");
   let value = labelElem.getAttribute("value");
   let tooltipText = labelElem.getAttribute("tooltiptext");
 
--- a/devtools/client/inspector/rules/test/browser_rules_user-agent-styles.js
+++ b/devtools/client/inspector/rules/test/browser_rules_user-agent-styles.js
@@ -105,30 +105,27 @@ function* userAgentStylesVisible(inspect
     yield compareAppliedStylesWithUI(inspector, view, "ua");
 
     userRules = view._elementStyle.rules.filter(rule=>rule.editor.isEditable);
     uaRules = view._elementStyle.rules.filter(rule=>!rule.editor.isEditable);
     is(userRules.length, data.numUserRules, "Correct number of user rules");
     ok(uaRules.length > data.numUARules, "Has UA rules");
   }
 
-  ok(userRules.some(rule => rule.matchedSelectors.length === 1),
+  ok(userRules.some(rule=> rule.matchedSelectors.length === 1),
     "There is an inline style for element in user styles");
 
   // These tests rely on the "a" selector being the last test in
   // TEST_DATA.
-  ok(uaRules.some(rule => {
-    return rule.matchedSelectors.indexOf(":-moz-any-link") !== -1;
-  }), "There is a rule for :-moz-any-link");
-  ok(uaRules.some(rule => {
-    return rule.matchedSelectors.indexOf("*|*:link") !== -1;
-  }), "There is a rule for *|*:link");
-  ok(uaRules.some(rule => {
-    return rule.matchedSelectors.length === 1;
-  }), "Inline styles for ua styles");
+  ok(uaRules.some(rule=> rule.matchedSelectors.indexOf(":-moz-any-link") !== -1),
+    "There is a rule for :-moz-any-link");
+  ok(uaRules.some(rule=> rule.matchedSelectors.indexOf("*|*:link") !== -1),
+    "There is a rule for *|*:link");
+  ok(uaRules.some(rule=> rule.matchedSelectors.length === 1),
+    "Inline styles for ua styles");
 }
 
 function* userAgentStylesNotVisible(inspector, view) {
   info("Making sure that user agent styles are not currently visible");
 
   let userRules;
   let uaRules;
 
@@ -142,23 +139,21 @@ function* userAgentStylesNotVisible(insp
     is(uaRules.length, data.numUARules, "No UA rules");
   }
 }
 
 function* compareAppliedStylesWithUI(inspector, view, filter) {
   info("Making sure that UI is consistent with pageStyle.getApplied");
 
   let entries = yield inspector.pageStyle.getApplied(
-    inspector.selection.nodeFront,
-    {
-      inherited: true,
-      matchedSelectors: true,
-      filter: filter
-    }
-  );
+    inspector.selection.nodeFront, {
+    inherited: true,
+    matchedSelectors: true,
+    filter: filter
+  });
 
   // We may see multiple entries that map to a given rule; filter the
   // duplicates here to match what the UI does.
   let entryMap = new Map();
   for (let entry of entries) {
     entryMap.set(entry.rule, entry);
   }
   entries = [...entryMap.values()];
--- a/devtools/client/inspector/rules/test/browser_rules_user-property-reset.js
+++ b/devtools/client/inspector/rules/test/browser_rules_user-property-reset.js
@@ -9,28 +9,28 @@
 
 const TEST_URI = `
   <p id='id1' style='width:200px;'>element 1</p>
   <p id='id2' style='width:100px;'>element 2</p>
 `;
 
 add_task(function*() {
   yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
-  let {inspector, view, testActor} = yield openRuleView();
+  let {inspector, view} = yield openRuleView();
 
   yield selectNode("#id1", inspector);
   yield modifyRuleViewWidth("300px", view, inspector);
   yield assertRuleAndMarkupViewWidth("id1", "300px", view, inspector);
 
   yield selectNode("#id2", inspector);
   yield assertRuleAndMarkupViewWidth("id2", "100px", view, inspector);
   yield modifyRuleViewWidth("50px", view, inspector);
   yield assertRuleAndMarkupViewWidth("id2", "50px", view, inspector);
 
-  yield reloadPage(inspector, testActor);
+  yield reloadPage(inspector);
 
   yield selectNode("#id1", inspector);
   yield assertRuleAndMarkupViewWidth("id1", "200px", view, inspector);
   yield selectNode("#id2", inspector);
   yield assertRuleAndMarkupViewWidth("id2", "100px", view, inspector);
 });
 
 function getStyleRule(ruleView) {
--- a/devtools/client/inspector/rules/test/doc_author-sheet.html
+++ b/devtools/client/inspector/rules/test/doc_author-sheet.html
@@ -6,26 +6,26 @@
 
   <style>
   pre a {
     color: orange;
   }
   </style>
 
   <script>
-    "use strict";
-    var gIOService = SpecialPowers.Cc["@mozilla.org/network/io-service;1"]
-                                  .getService(SpecialPowers.Ci.nsIIOService);
+var gIOService = SpecialPowers.Cc["@mozilla.org/network/io-service;1"]
+  .getService(SpecialPowers.Ci.nsIIOService)
 
-    var style = "data:text/css,a { background-color: seagreen; }";
-    var uri = gIOService.newURI(style, null, null);
-    var windowUtils = SpecialPowers.wrap(window)
-        .QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
-        .getInterface(SpecialPowers.Ci.nsIDOMWindowUtils);
-    windowUtils.loadSheet(uri, windowUtils.AUTHOR_SHEET);
+var style = "data:text/css,a { background-color: seagreen; }";
+var uri = gIOService.newURI(style, null, null);
+var windowUtils = SpecialPowers.wrap(window)
+    .QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
+    .getInterface(SpecialPowers.Ci.nsIDOMWindowUtils);
+windowUtils.loadSheet(uri, windowUtils.AUTHOR_SHEET);
+
   </script>
 
 </head>
 <body>
   <input type=text placeholder=test></input>
   <input type=color></input>
   <input type=range></input>
   <input type=number></input>
--- a/devtools/client/inspector/rules/test/doc_content_stylesheet.html
+++ b/devtools/client/inspector/rules/test/doc_content_stylesheet.html
@@ -1,24 +1,22 @@
 <html>
 <head>
   <title>test</title>
 
   <link href="./doc_content_stylesheet_linked.css" rel="stylesheet" type="text/css">
 
   <script>
-    /* eslint no-unused-vars: [2, {"vars": "local"}] */
-    "use strict";
     // Load script.css
     function loadCSS() {
-      let link = document.createElement("link");
-      link.rel = "stylesheet";
-      link.type = "text/css";
+      var link = document.createElement('link');
+      link.rel = 'stylesheet';
+      link.type = 'text/css';
       link.href = "./doc_content_stylesheet_script.css";
-      document.getElementsByTagName("head")[0].appendChild(link);
+      document.getElementsByTagName('head')[0].appendChild(link);
     }
   </script>
 
   <style>
     table {
       border: 1px solid #000;
     }
   </style>
--- a/devtools/client/inspector/rules/test/doc_cssom.html
+++ b/devtools/client/inspector/rules/test/doc_cssom.html
@@ -1,16 +1,15 @@
 <!-- Any copyright is dedicated to the Public Domain.
      http://creativecommons.org/publicdomain/zero/1.0/ -->
 <html>
 <head>
   <title>CSSOM test</title>
 
   <script>
-    "use strict";
     window.onload = function() {
       let x = document.styleSheets[0];
       x.insertRule("div { color: seagreen; }", 1);
     };
   </script>
 
   <style>
     span { }
--- a/devtools/client/inspector/rules/test/doc_frame_script.js
+++ b/devtools/client/inspector/rules/test/doc_frame_script.js
@@ -1,27 +1,26 @@
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
-/* globals addMessageListener, sendAsyncMessage */
 
 "use strict";
 
 // A helper frame-script for brower/devtools/styleinspector tests.
 //
 // Most listeners in the script expect "Test:"-namespaced messages from chrome,
 // then execute code upon receiving, and immediately send back a message.
 // This is so that chrome test code can execute code in content and wait for a
 // response this way:
-// let response = yield executeInContent(browser, "Test:msgName", data, true);
-// The response message should have the same name "Test:msgName"
+// let response = yield executeInContent(browser, "Test:MessageName", data, true);
+// The response message should have the same name "Test:MessageName"
 //
 // Some listeners do not send a response message back.
 
-var {classes: Cc, interfaces: Ci, utils: Cu} = Components;
+var {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 
 var {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
 var {CssLogic} = require("devtools/shared/inspector/css-logic");
 var promise = require("promise");
 
 /**
  * Get a value for a given property name in a css rule in a stylesheet, given
  * their indexes
@@ -81,18 +80,17 @@ addMessageListener("Test:GetStyleSheetsI
  * - {String} selector: The selector used to obtain the element.
  * - {String} pseudo: pseudo id to query, or null.
  * - {String} name: name of the property
  * @return {String} The value, if found, null otherwise
  */
 addMessageListener("Test:GetComputedStylePropertyValue", function(msg) {
   let {selector, pseudo, name} = msg.data;
   let element = content.document.querySelector(selector);
-  let value = content.document.defaultView.getComputedStyle(element, pseudo)
-                                          .getPropertyValue(name);
+  let value = content.document.defaultView.getComputedStyle(element, pseudo).getPropertyValue(name);
   sendAsyncMessage("Test:GetComputedStylePropertyValue", value);
 });
 
 /**
  * Wait the property value from the computed style for an element and
  * compare it with the expected value
  * @param {Object} data Expects a data object with the following properties
  * - {String} selector: The selector used to obtain the element.
@@ -105,36 +103,39 @@ addMessageListener("Test:WaitForComputed
   let element = content.document.querySelector(selector);
   waitForSuccess(() => {
     let value = content.document.defaultView.getComputedStyle(element, pseudo)
                                             .getPropertyValue(name);
 
     return value === expected;
   }).then(() => {
     sendAsyncMessage("Test:WaitForComputedStylePropertyValue");
-  });
+  })
 });
 
+
 var dumpn = msg => dump(msg + "\n");
 
 /**
  * Polls a given function waiting for it to return true.
  *
  * @param {Function} validatorFn A validator function that returns a boolean.
  * This is called every few milliseconds to check if the result is true. When
  * it is true, the promise resolves.
+ * @param {String} name Optional name of the test. This is used to generate
+ * the success and failure messages.
  * @return a promise that resolves when the function returned true or rejects
  * if the timeout is reached
  */
-function waitForSuccess(validatorFn) {
+function waitForSuccess(validatorFn, name="untitled") {
   let def = promise.defer();
 
-  function wait(fn) {
-    if (fn()) {
+  function wait(validatorFn) {
+    if (validatorFn()) {
       def.resolve();
     } else {
-      setTimeout(() => wait(fn), 200);
+      setTimeout(() => wait(validatorFn), 200);
     }
   }
   wait(validatorFn);
 
   return def.promise;
 }
--- a/devtools/client/inspector/rules/test/head.js
+++ b/devtools/client/inspector/rules/test/head.js
@@ -1,24 +1,23 @@
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
-/* eslint no-unused-vars: [2, {"vars": "local"}] */
-/* import-globals-from ../../test/head.js */
 "use strict";
 
 // Import the inspector's head.js first (which itself imports shared-head.js).
 Services.scriptloader.loadSubScript(
   "chrome://mochitests/content/browser/devtools/client/inspector/test/head.js",
   this);
 
 registerCleanupFunction(() => {
   Services.prefs.clearUserPref("devtools.defaultColorUnit");
 });
 
+var {CssLogic} = require("devtools/shared/inspector/css-logic");
 var {getInplaceEditorForSpan: inplaceEditor} =
   require("devtools/client/shared/inplace-editor");
 
 const ROOT_TEST_DIR = getRootDirectory(gTestPath);
 const FRAME_SCRIPT_URL = ROOT_TEST_DIR + "doc_frame_script.js";
 
 registerCleanupFunction(() => {
   Services.prefs.clearUserPref("devtools.defaultColorUnit");
@@ -34,37 +33,51 @@ registerCleanupFunction(() => {
 var _addTab = addTab;
 addTab = function(url) {
   return _addTab(url).then(tab => {
     info("Loading the helper frame script " + FRAME_SCRIPT_URL);
     let browser = tab.linkedBrowser;
     browser.messageManager.loadFrameScript(FRAME_SCRIPT_URL, false);
     return tab;
   });
-};
+}
 
 /**
  * Open the toolbox, with the inspector tool visible, and the rule-view
  * sidebar tab selected.
  *
  * @return a promise that resolves when the inspector is ready and the rule
  * view is visible and ready
  */
 function openRuleView() {
-  return openInspectorSidebarTab("ruleview").then(data => {
+  return openInspectorSidebarTab("ruleview").then(({toolbox, inspector}) => {
     return {
-      toolbox: data.toolbox,
-      inspector: data.inspector,
-      testActor: data.testActor,
-      view: data.inspector.ruleview.view
+      toolbox,
+      inspector,
+      view: inspector.ruleview.view
     };
   });
 }
 
 /**
+ * Simple DOM node accesor function that takes either a node or a string css
+ * selector as argument and returns the corresponding node
+ *
+ * @param {String|DOMNode} nodeOrSelector
+ * @return {DOMNode|CPOW} Note that in e10s mode a CPOW object is returned which
+ * doesn't implement *all* of the DOMNode's properties
+ */
+function getNode(nodeOrSelector) {
+  info("Getting the node for '" + nodeOrSelector + "'");
+  return typeof nodeOrSelector === "string" ?
+    content.document.querySelector(nodeOrSelector) :
+    nodeOrSelector;
+}
+
+/**
  * Set the inspector's current selection to null so that no node is selected
  *
  * @param {InspectorPanel} inspector
  *        The instance of InspectorPanel currently loaded in the toolbox
  * @return a promise that resolves when the inspector is updated
  */
 function clearCurrentNodeSelection(inspector) {
   info("Clearing the current selection");
@@ -107,16 +120,30 @@ function waitForNEvents(target, eventNam
       break;
     }
   }
 
   return deferred.promise;
 }
 
 /**
+ * This shouldn't be used in the tests, but is useful when writing new tests or
+ * debugging existing tests in order to introduce delays in the test steps
+ *
+ * @param {Number} ms
+ *        The time to wait
+ * @return A promise that resolves when the time is passed
+ */
+function wait(ms) {
+  let def = promise.defer();
+  content.setTimeout(def.resolve, ms);
+  return def.promise;
+}
+
+/**
  * Wait for a content -> chrome message on the message manager (the window
  * messagemanager is used).
  *
  * @param {String} name
  *        The message name
  * @return {Promise} A promise that resolves to the response data when the
  * message has been received
  */
@@ -145,18 +172,17 @@ function waitForContentMessage(name) {
  * @param {Object} objects
  *        Optional CPOW objects to send along
  * @param {Boolean} expectResponse
  *        If set to false, don't wait for a response with the same name
  *        from the content script. Defaults to true.
  * @return {Promise} Resolves to the response data if a response is expected,
  * immediately resolves otherwise
  */
-function executeInContent(name, data = {}, objects = {},
-                          expectResponse = true) {
+function executeInContent(name, data={}, objects={}, expectResponse=true) {
   info("Sending message " + name + " to content");
   let mm = gBrowser.selectedBrowser.messageManager;
 
   mm.sendAsyncMessage(name, data, objects);
   if (expectResponse) {
     return waitForContentMessage(name);
   }
 
@@ -177,31 +203,16 @@ function executeInContent(name, data = {
 function* getComputedStyleProperty(selector, pseudo, propName) {
   return yield executeInContent("Test:GetComputedStylePropertyValue",
                                 {selector,
                                 pseudo,
                                 name: propName});
 }
 
 /**
- * Get an element's inline style property value.
- * @param {TestActor} testActor
- * @param {String} selector
- *        The selector used to obtain the element.
- * @param {String} name
- *        name of the property.
- */
-function getStyle(testActor, selector, propName) {
-  return testActor.eval(`
-    content.document.querySelector("${selector}")
-                    .style.getPropertyValue("${propName}");
-  `);
-}
-
-/**
  * Send an async message to the frame script and wait until the requested
  * computed style property has the expected value.
  *
  * @param {String} selector
  *        The selector used to obtain the element.
  * @param {String} pseudo
  *        pseudo id to query, or null.
  * @param {String} prop
@@ -220,18 +231,18 @@ function* waitForComputedStyleProperty(s
 }
 
 /**
  * Given an inplace editable element, click to switch it to edit mode, wait for
  * focus
  *
  * @return a promise that resolves to the inplace-editor element when ready
  */
-var focusEditableField = Task.async(function*(ruleView, editable, xOffset = 1,
-    yOffset = 1, options = {}) {
+var focusEditableField = Task.async(function*(ruleView, editable, xOffset=1,
+    yOffset=1, options={}) {
   let onFocus = once(editable.parentNode, "focus", true);
   info("Clicking on editable field to turn to edit mode");
   EventUtils.synthesizeMouse(editable, xOffset, yOffset, options,
     editable.ownerDocument.defaultView);
   yield onFocus;
 
   info("Editable field gained focus, returning the input field now");
   let onEdit = inplaceEditor(editable.ownerDocument.activeElement);
@@ -296,44 +307,61 @@ var waitForTab = Task.async(function*() 
   let tab = gBrowser.selectedTab;
   let browser = tab.linkedBrowser;
   yield once(browser, "load", true);
   info("The tab load completed");
   return tab;
 });
 
 /**
- * Polls a given generator function waiting for it to return true.
+ * Polls a given function waiting for it to return true.
  *
  * @param {Function} validatorFn
- *        A validator generator function that returns a boolean.
+ *        A validator function that returns a boolean.
  *        This is called every few milliseconds to check if the result is true.
  *        When it is true, the promise resolves.
  * @param {String} name
  *        Optional name of the test. This is used to generate
  *        the success and failure messages.
  * @return a promise that resolves when the function returned true or rejects
  * if the timeout is reached
  */
-var waitForSuccess = Task.async(function*(validatorFn, desc = "untitled") {
-  let i = 0;
-  while (true) {
-    info("Checking: " + desc);
-    if (yield validatorFn()) {
-      ok(true, "Success: " + desc);
-      break;
+function waitForSuccess(validatorFn, name="untitled") {
+  let def = promise.defer();
+
+  function wait(validator) {
+    if (validator()) {
+      ok(true, "Validator function " + name + " returned true");
+      def.resolve();
+    } else {
+      setTimeout(() => wait(validator), 200);
     }
-    i++;
-    if (i > 10) {
-      ok(false, "Failure: " + desc);
-      break;
-    }
-    yield new Promise(r => setTimeout(r, 200));
   }
-});
+  wait(validatorFn);
+
+  return def.promise;
+}
+
+/**
+ * Create a new style tag containing the given style text and append it to the
+ * document's head node
+ *
+ * @param {Document} doc
+ * @param {String} style
+ * @return {DOMNode} The newly created style node
+ */
+function addStyle(doc, style) {
+  info("Adding a new style tag to the document with style content: " +
+    style.substring(0, 50));
+  let node = doc.createElement("style");
+  node.setAttribute("type", "text/css");
+  node.textContent = style;
+  doc.getElementsByTagName("head")[0].appendChild(node);
+  return node;
+}
 
 /**
  * Get the dataURL for the font family tooltip.
  *
  * @param {String} font
  *        The font family value.
  * @param {object} nodeFront
  *        The NodeActor that will used to retrieve the dataURL for the
@@ -462,29 +490,27 @@ function getRuleViewSelector(view, selec
  */
 function getRuleViewSelectorHighlighterIcon(view, selectorText) {
   let rule = getRuleViewRule(view, selectorText);
   return rule.querySelector(".ruleview-selectorhighlighter");
 }
 
 /**
  * Simulate a color change in a given color picker tooltip, and optionally wait
- * for a given element in the page to have its style changed as a result.
- * Note that this function assumes that the colorpicker popup is already open
- * and it won't close it after having selected the new color.
+ * for a given element in the page to have its style changed as a result
  *
  * @param {RuleView} ruleView
  *        The related rule view instance
  * @param {SwatchColorPickerTooltip} colorPicker
  * @param {Array} newRgba
  *        The new color to be set [r, g, b, a]
  * @param {Object} expectedChange
  *        Optional object that needs the following props:
- *          - {String} selector The selector to the element in the page that
- *            will have its style changed.
+ *          - {DOMNode} element The element in the page that will have its
+ *            style changed.
  *          - {String} name The style name that will be changed
  *          - {String} value The expected style value
  * The style will be checked like so: getComputedStyle(element)[name] === value
  */
 var simulateColorPickerChange = Task.async(function*(ruleView, colorPicker,
     newRgba, expectedChange) {
   let onRuleViewChanged = ruleView.once("ruleview-changed");
   info("Getting the spectrum colorpicker object");
@@ -494,109 +520,24 @@ var simulateColorPickerChange = Task.asy
   info("Applying the change");
   spectrum.updateUI();
   spectrum.onChange();
   info("Waiting for rule-view to update");
   yield onRuleViewChanged;
 
   if (expectedChange) {
     info("Waiting for the style to be applied on the page");
-    let {selector, name, value} = expectedChange;
-    yield waitForComputedStyleProperty(selector, null, name, value);
+    yield waitForSuccess(() => {
+      let {element, name, value} = expectedChange;
+      return content.getComputedStyle(element)[name] === value;
+    }, "Color picker change applied on the page");
   }
 });
 
 /**
- * Open the color picker popup for a given property in a given rule and
- * simulate a color change. Optionally wait for a given element in the page to
- * have its style changed as a result.
- *
- * @param {RuleView} view
- *        The related rule view instance
- * @param {Number} ruleIndex
- *        Which rule to target in the rule view
- * @param {Number} propIndex
- *        Which property to target in the rule
- * @param {Array} newRgba
- *        The new color to be set [r, g, b, a]
- * @param {Object} expectedChange
- *        Optional object that needs the following props:
- *          - {String} selector The selector to the element in the page that
- *            will have its style changed.
- *          - {String} name The style name that will be changed
- *          - {String} value The expected style value
- * The style will be checked like so: getComputedStyle(element)[name] === value
- */
-var openColorPickerAndSelectColor = Task.async(function*(view, ruleIndex,
-    propIndex, newRgba, expectedChange) {
-  let ruleEditor = getRuleViewRuleEditor(view, ruleIndex);
-  let propEditor = ruleEditor.rule.textProps[propIndex].editor;
-  let swatch = propEditor.valueSpan.querySelector(".ruleview-colorswatch");
-  let cPicker = view.tooltips.colorPicker;
-
-  info("Opening the colorpicker by clicking the color swatch");
-  let onShown = cPicker.tooltip.once("shown");
-  swatch.click();
-  yield onShown;
-
-  yield simulateColorPickerChange(view, cPicker, newRgba, expectedChange);
-
-  return {propEditor, swatch, cPicker};
-});
-
-/**
- * Open the cubicbezier popup for a given property in a given rule and
- * simulate a curve change. Optionally wait for a given element in the page to
- * have its style changed as a result.
- *
- * @param {RuleView} view
- *        The related rule view instance
- * @param {Number} ruleIndex
- *        Which rule to target in the rule view
- * @param {Number} propIndex
- *        Which property to target in the rule
- * @param {Array} coords
- *        The new coordinates to be used, e.g. [0.1, 2, 0.9, -1]
- * @param {Object} expectedChange
- *        Optional object that needs the following props:
- *          - {String} selector The selector to the element in the page that
- *            will have its style changed.
- *          - {String} name The style name that will be changed
- *          - {String} value The expected style value
- * The style will be checked like so: getComputedStyle(element)[name] === value
- */
-var openCubicBezierAndChangeCoords = Task.async(function*(view, ruleIndex,
-    propIndex, coords, expectedChange) {
-  let ruleEditor = getRuleViewRuleEditor(view, ruleIndex);
-  let propEditor = ruleEditor.rule.textProps[propIndex].editor;
-  let swatch = propEditor.valueSpan.querySelector(".ruleview-bezierswatch");
-  let bezierTooltip = view.tooltips.cubicBezier;
-
-  info("Opening the cubicBezier by clicking the swatch");
-  let onShown = bezierTooltip.tooltip.once("shown");
-  swatch.click();
-  yield onShown;
-
-  let widget = yield bezierTooltip.widget;
-
-  info("Simulating a change of curve in the widget");
-  let onRuleViewChanged = view.once("ruleview-changed");
-  widget.coordinates = coords;
-  yield onRuleViewChanged;
-
-  if (expectedChange) {
-    info("Waiting for the style to be applied on the page");
-    let {selector, name, value} = expectedChange;
-    yield waitForComputedStyleProperty(selector, null, name, value);
-  }
-
-  return {propEditor, swatch, bezierTooltip};
-});
-
-/**
  * Get a rule-link from the rule-view given its index
  *
  * @param {CssRuleView} view
  *        The instance of the rule-view panel
  * @param {Number} index
  *        The index of the link to get
  * @return {DOMNode} The link if any at this index
  */
@@ -632,159 +573,16 @@ function getRuleViewLinkTextByIndex(view
  */
 function getRuleViewRuleEditor(view, childrenIndex, nodeIndex) {
   return nodeIndex !== undefined ?
     view.element.children[childrenIndex].childNodes[nodeIndex]._ruleEditor :
     view.element.children[childrenIndex]._ruleEditor;
 }
 
 /**
- * Simulate adding a new property in an existing rule in the rule-view.
- *
- * @param {CssRuleView} view
- *        The instance of the rule-view panel
- * @param {Number} ruleIndex
- *        The index of the rule to use. Note that if ruleIndex is 0, you might
- *        want to also listen to markupmutation events in your test since
- *        that's going to change the style attribute of the selected node.
- * @param {String} name
- *        The name for the new property
- * @param {String} value
- *        The value for the new property
- * @param {String} commitValueWith
- *        Which key should be used to commit the new value. VK_RETURN is used by
- *        default, but tests might want to use another key to test cancelling
- *        for exemple.
- * @param {Boolean} blurNewProperty
- *        After the new value has been added, a new property would have been
- *        focused. This parameter is true by default, and that causes the new
- *        property to be blurred. Set to false if you don't want this.
- * @return {TextProperty} The instance of the TextProperty that was added
- */
-var addProperty = Task.async(function*(view, ruleIndex, name, value,
-                                       commitValueWith = "VK_RETURN",
-                                       blurNewProperty = true) {
-  info("Adding new property " + name + ":" + value + " to rule " + ruleIndex);
-
-  let ruleEditor = getRuleViewRuleEditor(view, ruleIndex);
-  let editor = yield focusNewRuleViewProperty(ruleEditor);
-  let numOfProps = ruleEditor.rule.textProps.length;
-
-  info("Adding name " + name);
-  editor.input.value = name;
-  let onNameAdded = view.once("ruleview-changed");
-  EventUtils.synthesizeKey("VK_RETURN", {}, view.styleWindow);
-  yield onNameAdded;
-
-  // Focus has moved to the value inplace-editor automatically.
-  editor = inplaceEditor(view.styleDocument.activeElement);
-  let textProps = ruleEditor.rule.textProps;
-  let textProp = textProps[textProps.length - 1];
-
-  is(ruleEditor.rule.textProps.length, numOfProps + 1,
-     "A new test property was added");
-  is(editor, inplaceEditor(textProp.editor.valueSpan),
-     "The inplace editor appeared for the value");
-
-  info("Adding value " + value);
-  // Setting the input value schedules a preview to be shown in 10ms which
-  // triggers a ruleview-changed event (see bug 1209295).
-  let onPreview = view.once("ruleview-changed");
-  editor.input.value = value;
-  yield onPreview;
-
-  let onValueAdded = view.once("ruleview-changed");
-  EventUtils.synthesizeKey(commitValueWith, {}, view.styleWindow);
-  yield onValueAdded;
-
-  if (blurNewProperty) {
-    view.styleDocument.activeElement.blur();
-  }
-
-  return textProp;
-});
-
-/**
- * Simulate changing the value of a property in a rule in the rule-view.
- *
- * @param {CssRuleView} view
- *        The instance of the rule-view panel
- * @param {TextProperty} textProp
- *        The instance of the TextProperty to be changed
- * @param {String} value
- *        The new value to be used. If null is passed, then the value will be
- *        deleted
- * @param {Boolean} blurNewProperty
- *        After the value has been changed, a new property would have been
- *        focused. This parameter is true by default, and that causes the new
- *        property to be blurred. Set to false if you don't want this.
- */
-var setProperty = Task.async(function*(view, textProp, value,
-                                       blurNewProperty = true) {
-  yield focusEditableField(view, textProp.editor.valueSpan);
-
-  let onPreview = view.once("ruleview-changed");
-  if (value === null) {
-    EventUtils.synthesizeKey("VK_DELETE", {}, view.styleWindow);
-  } else {
-    EventUtils.sendString(value, view.styleWindow);
-  }
-  yield onPreview;
-
-  let onValueDone = view.once("ruleview-changed");
-  EventUtils.synthesizeKey("VK_RETURN", {}, view.styleWindow);
-  yield onValueDone;
-
-  if (blurNewProperty) {
-    view.styleDocument.activeElement.blur();
-  }
-});
-
-/**
- * Simulate removing a property from an existing rule in the rule-view.
- *
- * @param {CssRuleView} view
- *        The instance of the rule-view panel
- * @param {TextProperty} textProp
- *        The instance of the TextProperty to be removed
- * @param {Boolean} blurNewProperty
- *        After the property has been removed, a new property would have been
- *        focused. This parameter is true by default, and that causes the new
- *        property to be blurred. Set to false if you don't want this.
- */
-var removeProperty = Task.async(function*(view, textProp,
-                                          blurNewProperty = true) {
-  yield focusEditableField(view, textProp.editor.nameSpan);
-
-  let onModifications = view.once("ruleview-changed");
-  info("Deleting the property name now");
-  EventUtils.synthesizeKey("VK_DELETE", {}, view.styleWindow);
-  EventUtils.synthesizeKey("VK_RETURN", {}, view.styleWindow);
-  yield onModifications;
-
-  if (blurNewProperty) {
-    view.styleDocument.activeElement.blur();
-  }
-});
-
-/**
- * Simulate clicking the enable/disable checkbox next to a property in a rule.
- *
- * @param {CssRuleView} view
- *        The instance of the rule-view panel
- * @param {TextProperty} textProp
- *        The instance of the TextProperty to be enabled/disabled
- */
-var togglePropStatus = Task.async(function*(view, textProp) {
-  let onRuleViewRefreshed = view.once("ruleview-changed");
-  textProp.editor.enable.click();
-  yield onRuleViewRefreshed;
-});
-
-/**
  * Click on a rule-view's close brace to focus a new property name editor
  *
  * @param {RuleEditor} ruleEditor
  *        An instance of RuleEditor that will receive the new property
  * @return a promise that resolves to the newly created editor when ready and
  * focused
  */
 var focusNewRuleViewProperty = Task.async(function*(ruleEditor) {
@@ -846,24 +644,25 @@ var setSearchFilter = Task.async(functio
 });
 
 /**
  * Reload the current page and wait for the inspector to be initialized after
  * the navigation
  *
  * @param {InspectorPanel} inspector
  *        The instance of InspectorPanel currently loaded in the toolbox
- * @param {TestActor} testActor
- *        The current instance of the TestActor
+ * @return a promise that resolves after page reload and inspector
+ * initialization
  */
-function* reloadPage(inspector, testActor) {
+function reloadPage(inspector) {
   let onNewRoot = inspector.once("new-root");
-  yield testActor.eval("content.location.reload();");
-  yield onNewRoot;
-  yield inspector.markup._waitForChildren();
+  content.location.reload();
+  return onNewRoot.then(() => {
+    inspector.markup._waitForChildren();
+  });
 }
 
 /**
  * Create a new rule by clicking on the "add rule" button.
  *
  * @param {InspectorPanel} inspector
  *        The instance of InspectorPanel currently loaded in the toolbox
  * @param {CssRuleView} view
--- a/devtools/client/inspector/test/head.js
+++ b/devtools/client/inspector/test/head.js
@@ -1,14 +1,12 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* 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/. */
-/* eslint no-unused-vars: [2, {"vars": "local"}] */
-/* import-globals-from ../../framework/test/shared-head.js */
 "use strict";
 
 // Load the shared-head file first.
 Services.scriptloader.loadSubScript(
   "chrome://mochitests/content/browser/devtools/client/framework/test/shared-head.js",
   this);
 
 // Services.prefs.setBoolPref("devtools.debugger.log", true);
--- a/testing/eslint-plugin-mozilla/lib/helpers.js
+++ b/testing/eslint-plugin-mozilla/lib/helpers.js
@@ -309,64 +309,66 @@ module.exports = {
    * @param  {RuleContext} scope
    *         You should pass this from within a rule
    *         e.g. helpers.getIsHeadFile(this)
    *
    * @return {Boolean}
    *         True or false
    */
   getIsHeadFile: function(scope) {
-    var pathAndFilename = this.cleanUpPath(scope.getFilename());
+    var pathAndFilename = scope.getFilename();
 
     return /.*[\\/]head(_.+)?\.js$/.test(pathAndFilename);
   },
 
   /**
    * Check whether we might be in an xpcshell test.
    *
    * @param  {RuleContext} scope
    *         You should pass this from within a rule
    *         e.g. helpers.getIsXpcshellTest(this)
    *
    * @return {Boolean}
    *         True or false
    */
   getIsXpcshellTest: function(scope) {
-    var pathAndFilename = this.cleanUpPath(scope.getFilename());
+    var pathAndFilename = scope.getFilename();
 
     return /.*[\\/]test_.+\.js$/.test(pathAndFilename);
   },
 
   /**
    * Check whether we are in a browser mochitest.
    *
    * @param  {RuleContext} scope
    *         You should pass this from within a rule
    *         e.g. helpers.getIsBrowserMochitest(this)
    *
    * @return {Boolean}
    *         True or false
    */
   getIsBrowserMochitest: function(scope) {
-    var pathAndFilename = this.cleanUpPath(scope.getFilename());
+    var pathAndFilename = scope.getFilename();
 
     return /.*[\\/]browser_.+\.js$/.test(pathAndFilename);
   },
 
   /**
    * Check whether we are in a test of some kind.
    *
    * @param  {RuleContext} scope
    *         You should pass this from within a rule
    *         e.g. helpers.getIsTest(this)
    *
    * @return {Boolean}
    *         True or false
    */
   getIsTest: function(scope) {
+    var pathAndFilename = scope.getFilename();
+
     if (this.getIsXpcshellTest(scope)) {
       return true;
     }
 
     return this.getIsBrowserMochitest(scope);
   },
 
   /**
@@ -398,34 +400,25 @@ module.exports = {
    * executed by a text editor's plugin.
    * The value returned by context.getFileName() varies because of this.
    * This helper function makes sure to return an absolute file path for the
    * current context, by looking at process.cwd().
    * @param {Context} context
    * @return {String} The absolute path
    */
   getAbsoluteFilePath: function(context) {
-    var fileName = this.cleanUpPath(context.getFilename());
+    var fileName = context.getFilename();
     var cwd = process.cwd();
 
     if (path.isAbsolute(fileName)) {
       // Case 2: executed from the repo's root with mach:
       //   fileName: /path/to/mozilla/repo/a/b/c/d.js
       //   cwd: /path/to/mozilla/repo
       return fileName;
     } else {
       // Case 1: executed form in a nested directory, e.g. from a text editor:
       //   fileName: a/b/c/d.js
       //   cwd: /path/to/mozilla/repo/a/b/c
       var dirName = path.dirname(fileName);
       return cwd.slice(0, cwd.length - dirName.length) + fileName;
     }
-  },
-
-  /**
-   * When ESLint is run from SublimeText, paths retrieved from
-   * context.getFileName contain leading and trailing double-quote characters.
-   * These characters need to be removed.
-   */
-  cleanUpPath: function(path) {
-    return path.replace(/^"/, "").replace(/"$/, "");
   }
 };