Home | History | Annotate | Download | only in cr
      1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 /**
      6  * @fileoverview This file provides a class that can be used to open URLs based
      7  * on user interactions. It ensures a consistent behavior when it comes to
      8  * holding down Ctrl and Shift while clicking or activating the a link.
      9  *
     10  * This depends on the {@code chrome.windows} and {@code chrome.tabs}
     11  * extensions API.
     12  */
     13 
     14 cr.define('cr', function() {
     15 
     16   /**
     17    * The kind of link open we want to perform.
     18    * @enum {number}
     19    */
     20   const LinkKind = {
     21     FOREGROUND_TAB: 0,
     22     BACKGROUND_TAB: 1,
     23     WINDOW: 2,
     24     SELF: 3,
     25     INCOGNITO: 4
     26   };
     27 
     28   /**
     29    * This class is used to handle opening of links based on user actions. The
     30    * following actions are currently implemented:
     31    *
     32    * * Press Ctrl and click a link. Or click a link with your middle mouse
     33    *   button (or mousewheel). Or press Enter while holding Ctrl.
     34    *     Opens the link in a new tab in the background .
     35    * * Press Ctrl+Shift and click a link. Or press Shift and click a link with
     36    *   your middle mouse button (or mousewheel). Or press Enter while holding
     37    *   Ctrl+Shift.
     38    *     Opens the link in a new tab and switches to the newly opened tab.
     39    * * Press Shift and click a link. Or press Enter while holding Shift.
     40    *     Opens the link in a new window.
     41    *
     42    * On Mac, uses Command instead of Ctrl.
     43    * For keyboard support you need to use keydown.
     44    *
     45    * @param {!LocalStrings} localStrings The local strings object which is used
     46    *     to localize the warning prompt in case the user tries to open a lot of
     47    *     links.
     48    * @constructor
     49    */
     50   function LinkController(localStrings) {
     51     this.localStrings_ = localStrings;
     52   }
     53 
     54   LinkController.prototype = {
     55     /**
     56      * The number of links that can be opened before showing a warning confirm
     57      * message.
     58      */
     59     warningLimit: 15,
     60 
     61     /**
     62      * The DOM window that we want to open links into in case we are opening
     63      * links in the same window.
     64      * @type {!Window}
     65      */
     66     window: window,
     67 
     68     /**
     69      * This method is used for showing the warning confirm message when the
     70      * user is trying to open a lot of links.
     71      * @param {number} The number of URLs to open.
     72      * @return {string} The message to show the user.
     73      */
     74     getWarningMessage: function(count) {
     75       return this.localStrings_.getStringF('should_open_all', count);
     76     },
     77 
     78     /**
     79      * Open an URL from a mouse or keyboard event.
     80      * @param {string} url The URL to open.
     81      * @param {!Event} e The event triggering the opening of the URL.
     82      */
     83     openUrlFromEvent: function(url, e) {
     84       // We only support keydown Enter and non right click events.
     85       if (e.type == 'keydown' && e.keyIdentifier == 'Enter' ||
     86           e.button != 2) {
     87         var kind;
     88         var ctrl = cr.isMac && e.metaKey || !cr.isMac && e.ctrlKey;
     89 
     90         if (e.button == 1 || ctrl) // middle, ctrl or keyboard
     91           kind = e.shiftKey ? LinkKind.FOREGROUND_TAB : LinkKind.BACKGROUND_TAB;
     92         else // left or keyboard
     93           kind = e.shiftKey ? LinkKind.WINDOW : LinkKind.SELF;
     94 
     95         this.openUrls([url], kind);
     96       }
     97     },
     98 
     99 
    100     /**
    101      * Opens a URL in a new tab, window or incognito window.
    102      * @param {string} url The URL to open.
    103      * @param {LinkKind} kind The kind of open we want to do.
    104      */
    105     openUrl: function (url, kind) {
    106       this.openUrls([url], kind);
    107     },
    108 
    109     /**
    110      * Opens URLs in new tab, window or incognito mode.
    111      * @param {!Array.<string>} urls The URLs to open.
    112      * @param {LinkKind} kind The kind of open we want to do.
    113      */
    114     openUrls: function (urls, kind) {
    115       if (urls.length < 1)
    116         return;
    117 
    118       if (urls.length > this.warningLimit) {
    119         if (!this.window.confirm(this.getWarningMessage(urls.length)))
    120           return;
    121       }
    122 
    123       // Fix '#124' URLs since opening those in a new window does not work. We
    124       // prepend the base URL when we encounter those.
    125       var base = this.window.location.href.split('#')[0];
    126       urls = urls.map(function(url) {
    127         return url[0] == '#' ? base + url : url;
    128       });
    129 
    130       var incognito = kind == LinkKind.INCOGNITO;
    131       if (kind == LinkKind.WINDOW || incognito) {
    132         chrome.windows.create({
    133           url: urls,
    134           incognito: incognito
    135         });
    136       } else if (kind == LinkKind.FOREGROUND_TAB ||
    137                  kind == LinkKind.BACKGROUND_TAB) {
    138         urls.forEach(function(url, i) {
    139           chrome.tabs.create({
    140             url: url,
    141             selected: kind == LinkKind.FOREGROUND_TAB && !i
    142           });
    143         });
    144       } else {
    145         this.window.location.href = urls[0];
    146       }
    147     }
    148   };
    149 
    150   // Export
    151   return {
    152     LinkController: LinkController,
    153     LinkKind: LinkKind
    154   };
    155 });
    156