Bug 921928 - Make <iframe mozbrower remote> a preferred target when fluffing
☠☠ backed out by 8803d874cbea ☠ ☠
authorAlexandre Lissy <lissyx@lissyx.dyndns.org>
Wed, 23 Oct 2013 09:08:00 +0100
changeset 166068 c6731046b7967cc53c99f20060009d6ddfc04e90
parent 166067 bd9cbc876172602a2d3a0cae2f059d3ac66fd826
child 166069 14fa49fdadfe25e0f57f146aa387b30ff253f72c
push id3066
push userakeybl@mozilla.com
push dateMon, 09 Dec 2013 19:58:46 +0000
treeherdermozilla-beta@a31a0dce83aa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs921928
milestone27.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 921928 - Make <iframe mozbrower remote> a preferred target when fluffing In bug 921928, the user places a call and then tries to do other actions (calls, SMS, contacts, ...) with actions very close to the attention screen. When trying to do those other actions, event fluffing is prioritizing the attention screen rather than user apps.
layout/base/PositionedEventTargeting.cpp
layout/base/tests/Makefile.in
layout/base/tests/test_event_target_iframe_apps_oop.html
layout/base/tests/test_event_target_iframe_oop.html
--- a/layout/base/PositionedEventTargeting.cpp
+++ b/layout/base/PositionedEventTargeting.cpp
@@ -169,16 +169,26 @@ IsElementClickable(nsIFrame* aFrame, nsI
     if (content->IsHTML()) {
       if (tag == nsGkAtoms::button ||
           tag == nsGkAtoms::input ||
           tag == nsGkAtoms::select ||
           tag == nsGkAtoms::textarea ||
           tag == nsGkAtoms::label) {
         return true;
       }
+      // Bug 921928: we don't have access to the content of remote iframe.
+      // So fluffing won't go there. We do an optimistic assumption here:
+      // that the content of the remote iframe needs to be a target.
+      if (tag == nsGkAtoms::iframe &&
+          content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::mozbrowser,
+                               nsGkAtoms::_true, eIgnoreCase) &&
+          content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::Remote,
+                               nsGkAtoms::_true, eIgnoreCase)) {
+        return true;
+      }
     } else if (content->IsXUL()) {
       nsIAtom* tag = content->Tag();
       // See nsCSSFrameConstructor::FindXULTagData. This code is not
       // really intended to be used with XUL, though.
       if (tag == nsGkAtoms::button ||
           tag == nsGkAtoms::checkbox ||
           tag == nsGkAtoms::radio ||
           tag == nsGkAtoms::autorepeatbutton ||
--- a/layout/base/tests/Makefile.in
+++ b/layout/base/tests/Makefile.in
@@ -110,16 +110,18 @@ MOCHITEST_FILES =	\
 		test_bug582181-2.html \
 		test_bug588174.html \
 		test_bug607529.html \
 		file_bug607529.html \
 		test_bug667512.html \
 		test_bug677878.html \
 		test_bug696020.html \
 		test_event_target_radius.html \
+		test_event_target_iframe_oop.html \
+		test_event_target_iframe_apps_oop.html \
 		test_mozPaintCount.html \
 		test_scroll_event_ordering.html \
 		test_scroll_selection_into_view.html \
 		test_bug583889.html \
 		bug583889_inner1.html \
 		bug583889_inner2.html \
 		test_bug582771.html \
 		test_bug603550.html \
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/test_event_target_iframe_apps_oop.html
@@ -0,0 +1,8 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test companion for bug 921928</title>
+</head>
+<body>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/test_event_target_iframe_oop.html
@@ -0,0 +1,175 @@
+<!DOCTYPE HTML>
+<html id="html" style="height:100%">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=921928
+-->
+<head>
+  <title>Test for bug 921928</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <style>
+  #dialer {
+    position: absolute;
+    left: 0;
+    top: 0;
+    width: 100%;
+    height: 50px;
+    background: green;
+  }
+
+  #apps {
+    position: absolute;
+    left: 0;
+    top: 51px;
+    width: 100%;
+    height: 100px;
+    background: blue;
+  }
+
+  .hit {
+    position: absolute;
+    width: 3px;
+    height: 3px;
+    z-index: 20;
+    background: red;
+    border: 1px solid red;
+  }
+  </style>
+</head>
+<body id="body" style="margin:0; width:100%; height:100%">
+<script type="application/javascript">
+SimpleTest.waitForExplicitFinish();
+
+var prefs = [
+  ["ui.mouse.radius.enabled", true],
+  ["ui.mouse.radius.inputSource.touchOnly", false],
+  ["ui.mouse.radius.leftmm", 12],
+  ["ui.mouse.radius.topmm", 8],
+  ["ui.mouse.radius.rightmm", 4],
+  ["ui.mouse.radius.bottommm", 4],
+  ["ui.mouse.radius.visitedweight", 50],
+  ["dom.mozBrowserFramesEnabled", true]
+];
+
+var eventTarget;
+var debugHit = [];
+
+function endTest() {
+  SimpleTest.finish();
+  SpecialPowers.removePermission("browser", location.href);
+  for (var pref in prefs) {
+    SpecialPowers.pushPrefEnv({"clear": pref[0]}, function() {});
+  }
+}
+
+function testMouseClick(idPosition, dx, dy, idTarget, msg, options) {
+  eventTarget = null;
+  synthesizeMouse(document.getElementById(idPosition), dx, dy, options || {});
+  try {
+    is(eventTarget.id, idTarget,
+       "checking '" + idPosition + "' offset " + dx + "," + dy + " [" + msg + "]");
+  } catch (ex) {
+    ok(false, "checking '" + idPosition + "' offset " + dx + "," + dy + " [" + msg + "]; got " + eventTarget);
+  }
+}
+
+function showDebug() {
+  for (var i = 0; i < debugHit.length; i++) {
+    document.body.appendChild(debugHit[i]);
+  }
+}
+
+/*
+  Setup the test environment: enabling event fluffing (all ui.* preferences),
+  and enabling remote process.
+*/
+function setupTest(cont) {
+  SpecialPowers.pushPrefEnv({"set": prefs}, cont);
+  SpecialPowers.addPermission("browser", true, document);
+}
+
+function execTest() {
+  /*
+     Creating two iframes that mimics the attention screen behavior on the
+     device:
+       - the 'dialer' iframe is the attention screen you have when a call is
+         in place. it is a green bar, so we copy it as green here too
+       - the 'apps' iframe mimics another application that is being run, be it
+         dialer, sms, ..., anything that the user might want to trigger during
+         a call
+
+     The bug we intent to reproduce here is that in this case, if the user taps
+     onto the top of the 'apps', the event fluffing code will in fact redirect
+     the event to the 'dialer' iframe. In practice, this is bug 921928 where
+     during a call the user wants to place a second call, and while typing the
+     phone number, wants to tap onto the 'delete' key to erase a digit, but ends
+     tapping and activating the dialer.
+   */
+  var dialer = document.createElement('iframe');
+  dialer.id = 'dialer';
+  dialer.src = '';
+  // Force OOP
+  dialer.setAttribute('mozbrowser', 'true');
+  dialer.setAttribute('remote', 'true');
+  document.body.appendChild(dialer);
+
+  var apps = document.createElement('iframe');
+  apps.id = 'apps';
+  apps.src = 'test_event_target_iframe_oop_apps.html';
+  // Force OOP
+  apps.setAttribute('mozbrowser', 'true');
+  apps.setAttribute('remote', 'true');
+  document.body.appendChild(apps);
+
+  var handleEvent = function(event) {
+    eventTarget = event.target;
+
+    // We draw a small red div to show where the event has tapped
+    var hit = document.createElement('div');
+    hit.style.left = (event.clientX - 1.5) + 'px';
+    hit.style.top = (event.clientY - 1.5) + 'px';
+    hit.classList.add('hit');
+    debugHit.push(hit);
+  };
+
+  // In real life, the 'dialer' has a 'mousedown', so we mimic one too,
+  // to reproduce the same behavior
+  dialer.addEventListener('mousedown', function(e) {});
+
+  // This event listener is just here to record what iframe has been hit,
+  // and sets the 'eventTarget' to the iframe's id value so that the
+  // testMouseClick() code can correctly check. We cannot add it on the
+  // 'apps' otherwise it will alter the behavior of the test.
+  document.addEventListener('mousedown', handleEvent);
+
+  // In the following, the coordinates are relative to the iframe
+
+  // First, we check that tapping onto the 'dialer' correctly triggers the
+  // dialer.
+  testMouseClick("dialer", 20, 15, "dialer", "correct hit on dialer with mouse input");
+  testMouseClick("dialer", 20, 15, "dialer", "correct hit on dialer with touch input", {
+    inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH
+  });
+
+  // Now this is it: we tap inside 'apps', but very close to the border between
+  // 'apps' and 'dialer'. Without the fix from this bug, this test will fail.
+  testMouseClick("apps", 20, 1, "apps", "apps <iframe mozbrowser remote> hit for mouse input");
+  testMouseClick("apps", 20, 1, "apps", "apps <iframe mozbrowser remote> hit for touch input", {
+    inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH
+  });
+
+  // Show small red spots of where the click happened
+  // showDebug();
+
+  endTest();
+}
+
+function runTest() {
+  setupTest(execTest);
+}
+
+addEventListener('load', function() { SimpleTest.executeSoon(runTest); });
+</script>
+</body>
+</html>