summaryrefslogtreecommitdiff
path: root/chromium/chrome/browser/resources/cryptotoken/webrequestsender.js
blob: 329a6ab4074ff499970fd86f5a88f9c54e1c6f90 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview Provides a representation of a web request sender, and
 * utility functions for creating them.
 */
'use strict';

/**
 * @typedef {{
 *   origin: string,
 *   tlsChannelId: (string|undefined),
 *   tabId: (number|undefined)
 * }}
 */
var WebRequestSender;

/**
 * Creates an object representing the sender's origin, and, if available,
 * tab.
 * @param {MessageSender} messageSender The message sender.
 * @return {?WebRequestSender} The sender's origin and tab, or null if the
 *     sender is invalid.
 */
function createSenderFromMessageSender(messageSender) {
  var origin = getOriginFromUrl(/** @type {string} */ (messageSender.url));
  if (!origin) {
    return null;
  }
  var sender = {
    origin: origin
  };
  if (messageSender.tlsChannelId) {
    sender.tlsChannelId = messageSender.tlsChannelId;
  }
  if (messageSender.tab) {
    sender.tabId = messageSender.tab.id;
  }
  return sender;
}

/**
 * Checks whether the given tab could have sent a message from the given
 * origin.
 * @param {Tab} tab The tab to match
 * @param {string} origin The origin to check.
 * @return {Promise} A promise resolved with the tab id if it the tab could,
 *     have sent the request, and rejected if it can't.
 */
function tabMatchesOrigin(tab, origin) {
  // If the tab's origin matches, trust that the request came from this tab.
  if (getOriginFromUrl(tab.url) == origin) {
    return Promise.resolve(tab.id);
  }
  return Promise.reject(false);
}

/**
 * Attempts to ensure that the tabId of the sender is set, using chrome.tabs
 * when available.
 * @param {WebRequestSender} sender The request sender.
 * @return {Promise} A promise resolved once the tabId retrieval is done.
 *     The promise is rejected if the tabId is untrustworthy, e.g. if the
 *     user rapidly switched tabs.
 */
function getTabIdWhenPossible(sender) {
  if (sender.tabId) {
    // Already got it? Done.
    return Promise.resolve(true);
  } else if (!chrome.tabs) {
    // Can't get it? Done. (This happens to packaged apps, which can't access
    // chrome.tabs.)
    return Promise.resolve(true);
  } else {
    return new Promise(function(resolve, reject) {
      chrome.tabs.query({active: true, lastFocusedWindow: true},
          function(tabs) {
            if (!tabs.length) {
              // Safety check.
              reject(false);
              return;
            }
            var tab = tabs[0];
            tabMatchesOrigin(tab, sender.origin).then(function(tabId) {
              sender.tabId = tabId;
              resolve(true);
            }, function() {
              // Didn't match? Check if the debugger is open.
              if (tab.url.indexOf('chrome-devtools://') != 0) {
                reject(false);
                return;
              }
              // Debugger active: find first tab with the sender's origin.
              chrome.tabs.query({active: true}, function(tabs) {
                if (!tabs.length) {
                  // Safety check.
                  reject(false);
                  return;
                }
                var numRejected = 0;
                for (var i = 0; i < tabs.length; i++) {
                  tab = tabs[i];
                  tabMatchesOrigin(tab, sender.origin).then(function(tabId) {
                    sender.tabId = tabId;
                    resolve(true);
                  }, function() {
                    if (++numRejected >= tabs.length) {
                      // None matches: reject.
                      reject(false);
                    }
                  });
                }
              });
            });
          });
    });
  }
}

/**
 * Checks whether the given tab is in the foreground, i.e. is the active tab
 * of the focused window.
 * @param {number} tabId The tab id to check.
 * @return {Promise<boolean>} A promise for the result of the check.
 */
function tabInForeground(tabId) {
  return new Promise(function(resolve, reject) {
      if (!chrome.tabs || !chrome.tabs.get) {
        reject();
        return;
      }
      if (!chrome.windows || !chrome.windows.get) {
        reject();
        return;
      }
      chrome.tabs.get(tabId, function(tab) {
            if (chrome.runtime.lastError) {
              resolve(false);
              return;
            }
            if (!tab.active) {
              resolve(false);
              return;
            }
            chrome.windows.get(tab.windowId, function(aWindow) {
                  resolve(aWindow && aWindow.focused);
                });
          });
  });
}