-
Notifications
You must be signed in to change notification settings - Fork 2
/
background.js
235 lines (218 loc) · 9.48 KB
/
background.js
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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
// Set fluidDBHost to 'localhost:9000' if testing against a local FluidDB.
var fluidDBHost = 'fluiddb.fluidinfo.com';
var twitterUserURLRegex = new RegExp('^https?://twitter.com/#!/(\\w+)$');
var linkRegex = /^\w+:\/\//;
var currentSelection = null;
var tabThatCreatedCurrentSelection = null;
var maxSelectionLengthToLookup = 200;
// Tabs that were created as a part of the OAuth login process and which
// are candidates for auto-deletion (when OAuth authorization is granted).
var oauthAutoCloseTabs = {};
// Things we consider as possibly being an about value that corresponds to
// something that's being followed, e.g., '@username' or 'wordnik.com'.
var followeeRegex = /^@?([\w\.]+)$/;
var anonFluidinfoAPI = fluidinfo({instance: 'https://' + fluidDBHost + '/'});
var absoluteHref = function(linkURL, docURL) {
/*
* Turn a possibly relative linkURL (the href="" part of an <a> tag)
* into something absolute. If linkURL does not specify a host, use
* the one in the document's URL (given in docURL).
*/
var url;
if (linkRegex.test(linkURL)) {
// The link looks absolute (i.e., http:// or https:// or ftp://).
url = linkURL;
}
else if (linkURL.slice(0, 7).toLowerCase() === 'mailto:') {
url = linkURL.split(':')[1].toLowerCase();
}
else {
// A relative link. Prepend the current document protocol & host+port.
var parts = docURL.split('/');
if (linkURL.charAt(0) === '/') {
url = parts[0] + '//' + parts[2] + linkURL;
}
else {
url = parts[0] + '//' + parts[2] + '/' + linkURL;
}
}
return url;
};
// Listen for incoming messages from the tab content script or the sidebar
// iframe script with events (link mouseover, link mouseout, selection
// set/cleared, etc).
var handleMessage = function(e) {
var msg = e.message;
if (e.name === 'content') {
if (typeof msg.selection !== 'undefined') {
if (currentSelection === null || msg.selection !== currentSelection) {
tabThatCreatedCurrentSelection = safari.application.activeBrowserWindow.activeTab;
currentSelection = msg.selection;
removeContextMenuItemsByContext('selection');
addContextMenuItem(currentSelection, 'selection');
}
}
else if (msg.selectionCleared) {
if (currentSelection !== null) {
currentSelection = null;
removeContextMenuItemsByContext('selection');
}
}
else if (msg.mouseout) {
// The mouse moved off a link so clear all link-related context
// menu items.
removeContextMenuItemsByContext('link');
}
else if (msg.mouseover) {
// The mouse moved over a new link. Remove existing link-related
// context menu items.
removeContextMenuItemsByContext('link');
var url;
// There are <a> tags with no href in them.
if (msg.linkURL){
url = absoluteHref(msg.linkURL, msg.docURL);
addContextMenuItem(url, 'link');
}
// And there are <a> tags with no text in them.
if (msg.text) {
if (msg.linkURL) {
url = absoluteHref(msg.linkURL, msg.docURL);
var match = twitterUserURLRegex.exec(url);
if (match !== null) {
// We can test against match[1] as the regexp captures the username,
// so if it matched, match[1] will always be defined.
var name = match[1];
var lower = name.toLowerCase();
if (lower !== 'following' && lower !== 'followers') {
// Update with @name
addContextMenuItem('@' + name, 'link');
// Look for "fullname @username" text.
var spaceAt = msg.text.indexOf(' @');
if (spaceAt !== -1){
// Note that Twitter now put U-200F (RIGHT-TO-LEFT MARK) after
// people's names, and we need to zap it. You'll know if this
// creeps back in, as clicking on the link in the context menu
// will take you to something ending in %E2%80%8F (the UTF-8
// for that codepoint).
var fullname = msg.text.slice(0, spaceAt).replace(/^\s+|[\s\u200F]+$/g, '');
addContextMenuItem(fullname, 'link');
}
}
return;
}
}
addContextMenuItem(msg.text, 'link');
}
} else if (msg.toggleSidebar) {
var tab = safari.application.activeBrowserWindow.activeTab;
tab.page.dispatchMessage('background', {
action: 'toggle sidebar',
about: currentSelection || tab.url,
settings: {
sidebarSide: safari.extension.settings.sidebarSide,
sidebarWidth: safari.extension.settings.sidebarWidth
}
});
} else {
console.log('Unrecognized message sent by content script:');
console.log(msg);
}
}
else if (e.name === 'iframe') {
// Process messages coming from the sidebar iframe.
if (msg.action === 'hide sidebar') {
e.target.page.dispatchMessage('background', {
action: 'hide sidebar'
});
}
else if (msg.action === 'oauth login') {
var createdTab = safari.application.activeBrowserWindow.openTab();
createdTab.url = 'http://' + lovemedoHost + '/login/fluidinfo/';
// Mark the tab as something we want to close automatically.
oauthAutoCloseTabs[createdTab] = e.target;
}
else if (msg.action === 'open') {
var tab = safari.application.activeBrowserWindow.activeTab;
tab.url = absoluteHref(msg.linkURL, msg.docURL);
}
else {
console.log('Unrecognized message sent by sidebar iframe:');
console.log(msg);
}
}
else {
console.log('Got an unknown event.');
console.log(e);
}
};
safari.application.addEventListener('message', handleMessage, false);
// Listen for tab-closed events.
var handleClose = function(e) {
var tab = e.target;
// An OAuth login tab that's being closed should no longer be marked
// for auto deletion.
if (oauthAutoCloseTabs.hasOwnProperty(tab)) {
delete oauthAutoCloseTabs[tab];
}
};
// We have to capture the `close' event.
safari.application.addEventListener('close', handleClose, true);
// Listen for navigation events. These are sent when a page has finished loading.
var handleNavigate = function(e) {
var tab = e.target;
if (oauthAutoCloseTabs.hasOwnProperty(tab)) {
// This tab is a candidate for automatic closing after successful
// OAuth login.
var dashboardURLPrefix = 'http://' + lovemedoHost;
if (tab.url.slice(0, 39) === 'https://api.twitter.com/oauth/authorize') {
// We're in the intermediate state, the fate of the OAuth login
// attempt is still unknown. Do nothing.
}
else if (tab.url.slice(0, dashboardURLPrefix.length) === dashboardURLPrefix) {
// We're loading a valid Fluidinfo URL, so the OAuth
// approval was granted. Remove the OAuth tab. Tell the tab
// that made it to reload its sidebar now that login has
// succeeded, and make it the active tab so the user is
// returned to what they were originally looking at.
var tabOpener = oauthAutoCloseTabs[tab];
tabOpener.page.dispatchMessage('background', {action: 'reload'});
delete oauthAutoCloseTabs[tab];
tab.close();
tabOpener.activate();
}
else {
// The tab has gone on to do something else (i.e., it is no
// longer doing oauth stuff). Unmark it as a candidate for
// automatic deletion.
delete oauthAutoCloseTabs[tab];
}
}
};
// We have to capture the `navigate' event.
safari.application.addEventListener('navigate', handleNavigate, true);
// Set up the click listener on the extension icon.
var handleCommand = function(e) {
if (e.command === 'toggle-sidebar') {
var tab = safari.application.activeBrowserWindow.activeTab;
tab.page.dispatchMessage('background', {
action: 'toggle sidebar',
about: currentSelection || tab.url,
settings: {
sidebarSide: safari.extension.settings.sidebarSide,
sidebarWidth: safari.extension.settings.sidebarWidth
}
});
} else if (e.command === 'open-sidebar') {
openInSidebar(e.userInfo.about);
} else if (e.command === 'open-tab') {
openNewTab(e.userInfo.about);
} else if (e.command.slice(0, 13) === 'open-sidebar:') {
openInSidebar(e.command.slice(13));
} else if (e.command.slice(0, 9) === 'open-tab:') {
openNewTab(e.command.slice(9));
} else {
console.log('Got an unknown command:');
console.log(e.command);
}
};
safari.application.addEventListener('command', handleCommand, false);