15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @fileoverview This file provides a class that can be used to open URLs based 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * on user interactions. It ensures a consistent behavior when it comes to 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * holding down Ctrl and Shift while clicking or activating the a link. 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This depends on the {@code chrome.windows} and {@code chrome.tabs} 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * extensions API. 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)cr.define('cr', function() { 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The kind of link open we want to perform. 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @enum {number} 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var LinkKind = { 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FOREGROUND_TAB: 0, 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BACKGROUND_TAB: 1, 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WINDOW: 2, 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SELF: 3, 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) INCOGNITO: 4 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This class is used to handle opening of links based on user actions. The 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * following actions are currently implemented: 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * * Press Ctrl and click a link. Or click a link with your middle mouse 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * button (or mousewheel). Or press Enter while holding Ctrl. 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Opens the link in a new tab in the background . 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * * Press Ctrl+Shift and click a link. Or press Shift and click a link with 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * your middle mouse button (or mousewheel). Or press Enter while holding 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Ctrl+Shift. 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Opens the link in a new tab and switches to the newly opened tab. 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * * Press Shift and click a link. Or press Enter while holding Shift. 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Opens the link in a new window. 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * On Mac, uses Command instead of Ctrl. 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * For keyboard support you need to use keydown. 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {!LocalStrings} localStrings The local strings object which is used 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * to localize the warning prompt in case the user tries to open a lot of 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * links. 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @constructor 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function LinkController(localStrings) { 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.localStrings_ = localStrings; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LinkController.prototype = { 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The number of links that can be opened before showing a warning confirm 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * message. 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) warningLimit: 15, 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The DOM window that we want to open links into in case we are opening 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * links in the same window. 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {!Window} 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window: window, 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This method is used for showing the warning confirm message when the 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * user is trying to open a lot of links. 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} The number of URLs to open. 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {string} The message to show the user. 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getWarningMessage: function(count) { 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.localStrings_.getStringF('should_open_all', count); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Open an URL from a mouse or keyboard event. 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} url The URL to open. 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {!Event} e The event triggering the opening of the URL. 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) openUrlFromEvent: function(url, e) { 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We only support keydown Enter and non right click events. 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (e.type == 'keydown' && e.keyIdentifier == 'Enter' || 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) e.button != 2) { 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var kind; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var ctrl = cr.isMac && e.metaKey || !cr.isMac && e.ctrlKey; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (e.button == 1 || ctrl) // middle, ctrl or keyboard 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kind = e.shiftKey ? LinkKind.FOREGROUND_TAB : LinkKind.BACKGROUND_TAB; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else // left or keyboard 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kind = e.shiftKey ? LinkKind.WINDOW : LinkKind.SELF; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.openUrls([url], kind); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Opens a URL in a new tab, window or incognito window. 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} url The URL to open. 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {LinkKind} kind The kind of open we want to do. 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) openUrl: function(url, kind) { 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.openUrls([url], kind); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Opens URLs in new tab, window or incognito mode. 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {!Array.<string>} urls The URLs to open. 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {LinkKind} kind The kind of open we want to do. 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) openUrls: function(urls, kind) { 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (urls.length < 1) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (urls.length > this.warningLimit) { 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!this.window.confirm(this.getWarningMessage(urls.length))) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Fix '#124' URLs since opening those in a new window does not work. We 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // prepend the base URL when we encounter those. 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var base = this.window.location.href.split('#')[0]; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) urls = urls.map(function(url) { 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return url[0] == '#' ? base + url : url; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var incognito = kind == LinkKind.INCOGNITO; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kind == LinkKind.WINDOW || incognito) { 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome.windows.create({ 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url: urls, 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) incognito: incognito 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (kind == LinkKind.FOREGROUND_TAB || 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kind == LinkKind.BACKGROUND_TAB) { 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) urls.forEach(function(url, i) { 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome.tabs.create({ 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url: url, 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selected: kind == LinkKind.FOREGROUND_TAB && !i 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.window.location.href = urls[0]; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Export 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return { 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LinkController: LinkController, 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LinkKind: LinkKind 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}); 156