172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/** 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * The global object. 772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * @type {!Object} 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst global = this; 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// TODO(estade): This should be removed and calls replaced with cr.isMac 1272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenconst IS_MAC = /^Mac/.test(navigator.platform); 1372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/** 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Alias for document.getElementById. 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * @param {string} id The ID of the element to find. 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * @return {HTMLElement} The found element or null if not found. 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochfunction $(id) { 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return document.getElementById(id); 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/** 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Calls chrome.send with a callback and restores the original afterwards. 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * @param {string} name The name of the message to send. 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * @param {!Array} params The parameters to send. 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * @param {string} callbackName The name of the function that the backend calls. 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * @param {!Function} The function to call. 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochfunction chromeSend(name, params, callbackName, callback) { 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch var old = global[callbackName]; 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch global[callbackName] = function() { 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // restore 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch global[callbackName] = old; 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch var args = Array.prototype.slice.call(arguments); 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return callback.apply(global, args); 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch chrome.send(name, params); 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/** 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Generates a CSS url string. 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * @param {string} s The URL to generate the CSS url for. 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * @return {string} The CSS url string. 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochfunction url(s) { 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // http://www.w3.org/TR/css3-values/#uris 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Parentheses, commas, whitespace characters, single quotes (') and double 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // quotes (") appearing in a URI must be escaped with a backslash 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch var s2 = s.replace(/(\(|\)|\,|\s|\'|\"|\\)/g, '\\$1'); 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // WebKit has a bug when it comes to URLs that end with \ 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // https://bugs.webkit.org/show_bug.cgi?id=28885 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (/\\\\$/.test(s2)) { 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Add a space to work around the WebKit bug. 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch s2 += ' '; 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return 'url("' + s2 + '")'; 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 60731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 61731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick/** 62731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick * Parses query parameters from Location. 63731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick * @param {string} s The URL to generate the CSS url for. 64731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick * @return {object} Dictionary containing name value pairs for URL 65731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick */ 66731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickfunction parseQueryParams(location) { 67731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick var params = {}; 68731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick var query = unescape(location.search.substring(1)); 69731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick var vars = query.split("&"); 70731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick for (var i=0; i < vars.length; i++) { 71731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick var pair = vars[i].split("="); 72731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick params[pair[0]] = pair[1]; 73731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 74731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return params; 7572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 7672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 7772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenfunction findAncestorByClass(el, className) { 7872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return findAncestor(el, function(el) { 7972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (el.classList) 8072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return el.classList.contains(className); 8172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return null; 8272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen }); 8372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 8472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 8572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen/** 8672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * Return the first ancestor for which the {@code predicate} returns true. 8772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * @param {Node} node The node to check. 8872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * @param {function(Node) : boolean} predicate The function that tests the 8972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * nodes. 9072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * @return {Node} The found ancestor or null if not found. 9172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen */ 9272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenfunction findAncestor(node, predicate) { 9372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var last = false; 9472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen while (node != null && !(last = predicate(node))) { 9572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen node = node.parentNode; 9672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 9772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return last ? node : null; 9872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 9972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 10072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenfunction swapDomNodes(a, b) { 10172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var afterA = a.nextSibling; 10272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (afterA == b) { 10372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen swapDomNodes(b, a); 10472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return; 10572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 10672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var aParent = a.parentNode; 10772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen b.parentNode.replaceChild(a, b); 10872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen aParent.insertBefore(b, afterA); 10972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 11072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 111dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Handle click on a link. If the link points to a chrome: or file: url, then 112dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// call into the browser to do the navigation. 113dc0f95d653279beabeb9817299e2902918ba123eKristian Monsendocument.addEventListener('click', function(e) { 11472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Allow preventDefault to work. 11572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!e.returnValue) 11672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return; 11772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 11872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var el = e.target; 11972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (el.nodeType == Node.ELEMENT_NODE && 12072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen el.webkitMatchesSelector('A, A *')) { 12172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen while (el.tagName != 'A') { 12272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen el = el.parentElement; 12372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 12472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 12572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if ((el.protocol == 'file:' || el.protocol == 'about:') && 126dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen (e.button == 0 || e.button == 1)) { 127ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen chrome.send('navigateToUrl', [ 128ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen el.href, 129ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen el.target, 130ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen e.button, 131ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen e.altKey, 132ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen e.ctrlKey, 133ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen e.metaKey, 134ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen e.shiftKey 135ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ]); 13672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen e.preventDefault(); 13772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 13872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 139dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}); 140