Merge lp:~osomon/webbrowser-app/blacklist-selection into lp:webbrowser-app

Proposed by Olivier Tilloy
Status: Merged
Approved by: Olivier Tilloy
Approved revision: 451
Merged at revision: 451
Proposed branch: lp:~osomon/webbrowser-app/blacklist-selection
Merge into: lp:webbrowser-app
Diff against target: 348 lines (+175/-160)
1 file modified
src/Ubuntu/Components/Extras/Browser/selection.js (+175/-160)
To merge this branch: bzr merge lp:~osomon/webbrowser-app/blacklist-selection
Reviewer Review Type Date Requested Status
Alexandre Abreu (community) Approve
PS Jenkins bot continuous-integration Approve
Review via email: mp+206747@code.launchpad.net

Commit message

Do not install the selection event handlers on certain domains known to interfere with touch events.

To post a comment you must log in.
Revision history for this message
Olivier Tilloy (osomon) wrote :

• Are there any related MPs required for this MP to build/function as expected? NO

• Is your branch in sync with latest trunk (e.g. bzr pull lp:trunk -> no changes) YES

• Did you perform an exploratory manual test run of your code change and any related functionality on device or emulator? YES, on Galaxy Nexus

• Did you successfully run all tests found in your component's Test Plan (https://wiki.ubuntu.com/Process/Merges/TestPlan/<package-name>) on device or emulator? YES

• If you changed the UI, was the change specified/approved by design? N/A

• If you changed the packaging (debian), did you subscribe a core-dev to this MP? N/A

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Chris Wayne (cwayne) wrote :

I've just tested this and verified that it fixed the issue!

Revision history for this message
Alexandre Abreu (abreu-alexandre) :
review: Approve
Revision history for this message
Gustavo Pichorim Boiko (boiko) wrote :

As a formality before the MR enters the CI train, could the reviewer (in this case Chris) please go through the MP Review Checklist (https://wiki.ubuntu.com/Process/Merges/Checklists/system-apps) and answer the questions in a comment on the MR?

Revision history for this message
Gustavo Pichorim Boiko (boiko) wrote :

> As a formality before the MR enters the CI train, could the reviewer (in this
> case Chris) please go through the MP Review Checklist
> (https://wiki.ubuntu.com/Process/Merges/Checklists/system-apps) and answer the
> questions in a comment on the MR?

Oups, I just noticed it was not Chris who approved the MR, it was Alexandre, so if he could please go through that, it would be nice.

Revision history for this message
Alexandre Abreu (abreu-alexandre) wrote :

Did you perform an exploratory manual test run of the code change and any related functionality on device or emulator? YES

Did you successfully run all tests found in your component's Test Plan (https://wiki.ubuntu.com/Process/Merges/TestPlan/<package-name>) on device or emulator? YES

Did CI run pass? If not, please explain why. YES

Have you checked that submitter has accurately filled out the submitter checklist and has taken no shortcut? YES

452. By Olivier Tilloy

Let the selection handler listen to 'touchcancel' events for completeness.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/Ubuntu/Components/Extras/Browser/selection.js'
2--- src/Ubuntu/Components/Extras/Browser/selection.js 2013-10-10 12:02:43 +0000
3+++ src/Ubuntu/Components/Extras/Browser/selection.js 2014-02-19 15:54:03 +0000
4@@ -1,5 +1,5 @@
5 /*
6- * Copyright 2013 Canonical Ltd.
7+ * Copyright 2013-2014 Canonical Ltd.
8 *
9 * This file is part of webbrowser-app.
10 *
11@@ -16,163 +16,178 @@
12 * along with this program. If not, see <http://www.gnu.org/licenses/>.
13 */
14
15-function elementContainedInBox(element, box) {
16- var rect = element.getBoundingClientRect();
17- return ((box.left <= rect.left) && (box.right >= rect.right) &&
18- (box.top <= rect.top) && (box.bottom >= rect.bottom));
19-}
20-
21-function getImgFullUri(uri) {
22- if ((uri.slice(0, 7) === 'http://') ||
23- (uri.slice(0, 8) === 'https://') ||
24- (uri.slice(0, 7) === 'file://')) {
25- return uri;
26- } else if (uri.slice(0, 1) === '/') {
27- var docuri = document.documentURI;
28- var firstcolon = docuri.indexOf('://');
29- var protocol = 'http://';
30- if (firstcolon !== -1) {
31- protocol = docuri.slice(0, firstcolon + 3);
32- }
33- return protocol + document.domain + uri;
34- } else {
35- var base = document.baseURI;
36- var lastslash = base.lastIndexOf('/');
37- if (lastslash === -1) {
38- return base + '/' + uri;
39+// List of domains known to interfere with touch events listeners
40+var blacklist = [
41+ "m.8tracks.com", // http://pad.lv/1279903
42+];
43+if (blacklist.indexOf(document.domain) === -1) {
44+
45+ function elementContainedInBox(element, box) {
46+ var rect = element.getBoundingClientRect();
47+ return ((box.left <= rect.left) && (box.right >= rect.right) &&
48+ (box.top <= rect.top) && (box.bottom >= rect.bottom));
49+ }
50+
51+ function getImgFullUri(uri) {
52+ if ((uri.slice(0, 7) === 'http://') ||
53+ (uri.slice(0, 8) === 'https://') ||
54+ (uri.slice(0, 7) === 'file://')) {
55+ return uri;
56+ } else if (uri.slice(0, 1) === '/') {
57+ var docuri = document.documentURI;
58+ var firstcolon = docuri.indexOf('://');
59+ var protocol = 'http://';
60+ if (firstcolon !== -1) {
61+ protocol = docuri.slice(0, firstcolon + 3);
62+ }
63+ return protocol + document.domain + uri;
64 } else {
65- return base.slice(0, lastslash + 1) + uri;
66- }
67- }
68-}
69-
70-function getSelectedData(element) {
71- var node = element;
72- var data = new Object;
73-
74- var nodeName = node.nodeName.toLowerCase();
75- if (nodeName === 'img') {
76- data.img = getImgFullUri(node.getAttribute('src'));
77- } else if (nodeName === 'a') {
78- data.href = node.href;
79- data.title = node.title;
80- }
81-
82- // If the parent tag is a hyperlink, we want it too.
83- var parent = node.parentNode;
84- if ((nodeName !== 'a') && parent && (parent.nodeName.toLowerCase() === 'a')) {
85- data.href = parent.href;
86- data.title = parent.title;
87- node = parent;
88- }
89-
90- var boundingRect = node.getBoundingClientRect();
91- data.left = boundingRect.left;
92- data.top = boundingRect.top;
93- data.width = boundingRect.width;
94- data.height = boundingRect.height;
95-
96- node = node.cloneNode(true);
97- // filter out script nodes
98- var scripts = node.getElementsByTagName('script');
99- while (scripts.length > 0) {
100- var scriptNode = scripts[0];
101- if (scriptNode.parentNode) {
102- scriptNode.parentNode.removeChild(scriptNode);
103- }
104- }
105- data.html = node.outerHTML;
106- data.nodeName = node.nodeName.toLowerCase();
107- // FIXME: extract the text and images in the order they appear in the block,
108- // so that this order is respected when the data is pushed to the clipboard.
109- data.text = node.textContent;
110- var images = [];
111- var imgs = node.getElementsByTagName('img');
112- for (var i = 0; i < imgs.length; i++) {
113- images.push(getImgFullUri(imgs[i].getAttribute('src')));
114- }
115- if (images.length > 0) {
116- data.images = images;
117- }
118-
119- return data;
120-}
121-
122-function adjustSelection(selection) {
123- // FIXME: allow selecting two consecutive blocks, instead of
124- // interpolating to the containing block.
125- var centerX = (selection.left + selection.right) / 2;
126- var centerY = (selection.top + selection.bottom) / 2;
127- var element = document.elementFromPoint(centerX, centerY);
128- var parent = element;
129- while (elementContainedInBox(parent, selection)) {
130- parent = parent.parentNode;
131- }
132- element = parent;
133- return getSelectedData(element);
134-}
135-
136-function distance(touch1, touch2) {
137- return Math.sqrt(Math.pow(touch2.clientX - touch1.clientX, 2) +
138- Math.pow(touch2.clientY - touch1.clientY, 2));
139-}
140-
141-navigator.qt.onmessage = function(message) {
142- var data = null;
143- try {
144- data = JSON.parse(message.data);
145- } catch (error) {
146- return;
147- }
148- if ('query' in data) {
149- if (data.query === 'adjustselection') {
150- var selection = adjustSelection(data);
151- selection.event = 'selectionadjusted';
152- navigator.qt.postMessage(JSON.stringify(selection));
153- }
154- }
155-}
156-
157-var longpressObserver = -1;
158-var currentTouch = null;
159-var longpressDetected = false;
160-
161-function longPressDetected(x, y) {
162- longpressDetected = true;
163- var element = document.elementFromPoint(x, y);
164- var data = getSelectedData(element);
165- data.event = 'longpress';
166- navigator.qt.postMessage(JSON.stringify(data));
167-}
168-
169-function clearLongpressTimeout() {
170- clearTimeout(longpressObserver);
171- longpressObserver = -1;
172- currentTouch = null;
173-}
174-
175-var doc = document.documentElement;
176-
177-doc.addEventListener('touchstart', function(event) {
178- if (event.touches.length == 1) {
179- currentTouch = event.touches[0];
180- longpressObserver = setTimeout(longPressDetected, 800, currentTouch.clientX, currentTouch.clientY);
181- }
182-});
183-
184-doc.addEventListener('touchend', function(event) {
185- if (longpressDetected) {
186- longpressDetected = false;
187- event.preventDefault();
188- }
189- clearLongpressTimeout();
190-});
191-
192-doc.addEventListener('touchmove', function(event) {
193- if (!currentTouch) {
194- return;
195- }
196- if ((event.changedTouches.length > 1) || (distance(event.changedTouches[0], currentTouch) > 3)) {
197- clearLongpressTimeout();
198- }
199-});
200+ var base = document.baseURI;
201+ var lastslash = base.lastIndexOf('/');
202+ if (lastslash === -1) {
203+ return base + '/' + uri;
204+ } else {
205+ return base.slice(0, lastslash + 1) + uri;
206+ }
207+ }
208+ }
209+
210+ function getSelectedData(element) {
211+ var node = element;
212+ var data = new Object;
213+
214+ var nodeName = node.nodeName.toLowerCase();
215+ if (nodeName === 'img') {
216+ data.img = getImgFullUri(node.getAttribute('src'));
217+ } else if (nodeName === 'a') {
218+ data.href = node.href;
219+ data.title = node.title;
220+ }
221+
222+ // If the parent tag is a hyperlink, we want it too.
223+ var parent = node.parentNode;
224+ if ((nodeName !== 'a') && parent && (parent.nodeName.toLowerCase() === 'a')) {
225+ data.href = parent.href;
226+ data.title = parent.title;
227+ node = parent;
228+ }
229+
230+ var boundingRect = node.getBoundingClientRect();
231+ data.left = boundingRect.left;
232+ data.top = boundingRect.top;
233+ data.width = boundingRect.width;
234+ data.height = boundingRect.height;
235+
236+ node = node.cloneNode(true);
237+ // filter out script nodes
238+ var scripts = node.getElementsByTagName('script');
239+ while (scripts.length > 0) {
240+ var scriptNode = scripts[0];
241+ if (scriptNode.parentNode) {
242+ scriptNode.parentNode.removeChild(scriptNode);
243+ }
244+ }
245+ data.html = node.outerHTML;
246+ data.nodeName = node.nodeName.toLowerCase();
247+ // FIXME: extract the text and images in the order they appear in the block,
248+ // so that this order is respected when the data is pushed to the clipboard.
249+ data.text = node.textContent;
250+ var images = [];
251+ var imgs = node.getElementsByTagName('img');
252+ for (var i = 0; i < imgs.length; i++) {
253+ images.push(getImgFullUri(imgs[i].getAttribute('src')));
254+ }
255+ if (images.length > 0) {
256+ data.images = images;
257+ }
258+
259+ return data;
260+ }
261+
262+ function adjustSelection(selection) {
263+ // FIXME: allow selecting two consecutive blocks, instead of
264+ // interpolating to the containing block.
265+ var centerX = (selection.left + selection.right) / 2;
266+ var centerY = (selection.top + selection.bottom) / 2;
267+ var element = document.elementFromPoint(centerX, centerY);
268+ var parent = element;
269+ while (elementContainedInBox(parent, selection)) {
270+ parent = parent.parentNode;
271+ }
272+ element = parent;
273+ return getSelectedData(element);
274+ }
275+
276+ function distance(touch1, touch2) {
277+ return Math.sqrt(Math.pow(touch2.clientX - touch1.clientX, 2) +
278+ Math.pow(touch2.clientY - touch1.clientY, 2));
279+ }
280+
281+ navigator.qt.onmessage = function(message) {
282+ var data = null;
283+ try {
284+ data = JSON.parse(message.data);
285+ } catch (error) {
286+ return;
287+ }
288+ if ('query' in data) {
289+ if (data.query === 'adjustselection') {
290+ var selection = adjustSelection(data);
291+ selection.event = 'selectionadjusted';
292+ navigator.qt.postMessage(JSON.stringify(selection));
293+ }
294+ }
295+ }
296+
297+ var longpressObserver = -1;
298+ var currentTouch = null;
299+ var longpressDetected = false;
300+
301+ function longPressDetected(x, y) {
302+ longpressDetected = true;
303+ var element = document.elementFromPoint(x, y);
304+ var data = getSelectedData(element);
305+ data.event = 'longpress';
306+ navigator.qt.postMessage(JSON.stringify(data));
307+ }
308+
309+ function clearLongpressTimeout() {
310+ clearTimeout(longpressObserver);
311+ longpressObserver = -1;
312+ currentTouch = null;
313+ }
314+
315+ var doc = document.documentElement;
316+
317+ doc.addEventListener('touchstart', function(event) {
318+ if (event.touches.length == 1) {
319+ currentTouch = event.touches[0];
320+ longpressObserver = setTimeout(longPressDetected, 800, currentTouch.clientX, currentTouch.clientY);
321+ }
322+ });
323+
324+ doc.addEventListener('touchend', function(event) {
325+ if (longpressDetected) {
326+ longpressDetected = false;
327+ event.preventDefault();
328+ }
329+ clearLongpressTimeout();
330+ });
331+
332+ doc.addEventListener('touchmove', function(event) {
333+ if (!currentTouch) {
334+ return;
335+ }
336+ if ((event.changedTouches.length > 1) || (distance(event.changedTouches[0], currentTouch) > 3)) {
337+ clearLongpressTimeout();
338+ }
339+ });
340+
341+ doc.addEventListener('touchcancel', function(event) {
342+ if (longpressDetected) {
343+ longpressDetected = false;
344+ }
345+ clearLongpressTimeout();
346+ });
347+
348+}

Subscribers

People subscribed via source and target branches

to status/vote changes: