• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
14cr.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