webext-schema 2.0.9 → 2.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1088 @@
1
+ /**
2
+ * browser.js
3
+ */
4
+
5
+ /* shared */
6
+ import { getType, isObjectNotEmpty, isString, logErr } from './common.js';
7
+
8
+ /* api */
9
+ const { permissions, runtime, tabs, windows } = browser;
10
+
11
+ /**
12
+ * check if permission is granted
13
+ *
14
+ * @param {object} perm - permissions.Permission
15
+ * @returns {boolean} - result
16
+ */
17
+ export const isPermissionGranted = async perm => {
18
+ const bool = await permissions.contains(perm);
19
+ return !!bool;
20
+ };
21
+
22
+ /* bookmarks */
23
+ /**
24
+ * create bookmark
25
+ *
26
+ * @param {object} opt - bookmarks.CreateDetails
27
+ * @returns {object} - bookmarks.BookmarkTreeNode
28
+ */
29
+ export const createBookmark = async opt => {
30
+ const isGranted = await isPermissionGranted({
31
+ permissions: ['bookmarks']
32
+ });
33
+ let node;
34
+ if (isGranted && isObjectNotEmpty(opt)) {
35
+ const { bookmarks } = browser;
36
+ node = await bookmarks.create(opt);
37
+ }
38
+ return node || null;
39
+ };
40
+
41
+ /**
42
+ * get bookmark tree node
43
+ *
44
+ * @param {string|Array} id - bookmark ID or array of bookmark IDs
45
+ * @returns {Array} - array of bookmarks.BookmarkTreeNode
46
+ */
47
+ export const getBookmarkTreeNode = async id => {
48
+ const isGranted = await isPermissionGranted({
49
+ permissions: ['bookmarks']
50
+ });
51
+ let res;
52
+ if (isGranted) {
53
+ const { bookmarks } = browser;
54
+ if (Array.isArray(id)) {
55
+ res = await bookmarks.get(id);
56
+ } else if (isString(id)) {
57
+ res = await bookmarks.getSubTree(id);
58
+ } else {
59
+ res = await bookmarks.getTree();
60
+ }
61
+ }
62
+ return res || null;
63
+ };
64
+
65
+ /* browserSettings */
66
+ /**
67
+ * get closeTabsByDoubleClick user value
68
+ *
69
+ * @returns {object} - user value
70
+ */
71
+ export const getCloseTabsByDoubleClickValue = async () => {
72
+ const isGranted = await isPermissionGranted({
73
+ permissions: ['browserSettings']
74
+ });
75
+ let userValue;
76
+ if (isGranted) {
77
+ const { browserSettings } = browser;
78
+ const { closeTabsByDoubleClick } = browserSettings;
79
+ userValue = await closeTabsByDoubleClick.get({});
80
+ }
81
+ return userValue || null;
82
+ };
83
+
84
+ /**
85
+ * set context menu on mouseup
86
+ *
87
+ * @returns {boolean} - result
88
+ */
89
+ export const setContextMenuOnMouseup = async () => {
90
+ const isGranted = await isPermissionGranted({
91
+ permissions: ['browserSettings']
92
+ });
93
+ let res;
94
+ if (isGranted) {
95
+ const { browserSettings } = browser;
96
+ const { contextMenuShowEvent } = browserSettings;
97
+ const { levelOfControl, value } = await contextMenuShowEvent.get({});
98
+ if (value === 'mouseup') {
99
+ res = true;
100
+ } else if (levelOfControl === 'controllable_by_this_extension') {
101
+ res = await contextMenuShowEvent.set({ value: 'mouseup' });
102
+ } else {
103
+ res = false;
104
+ }
105
+ }
106
+ return !!res;
107
+ };
108
+
109
+ /**
110
+ * clear context menu on mouseup
111
+ *
112
+ * @returns {boolean} - result
113
+ */
114
+ export const clearContextMenuOnMouseup = async () => {
115
+ const isGranted = await isPermissionGranted({
116
+ permissions: ['browserSettings']
117
+ });
118
+ let res;
119
+ if (isGranted) {
120
+ const { browserSettings } = browser;
121
+ const { contextMenuShowEvent } = browserSettings;
122
+ res = await contextMenuShowEvent.clear({});
123
+ }
124
+ return !!res;
125
+ };
126
+
127
+ /**
128
+ * get new tab position value
129
+ *
130
+ * @returns {object} - result
131
+ */
132
+ export const getNewTabPositionValue = async () => {
133
+ const isGranted = await isPermissionGranted({
134
+ permissions: ['browserSettings']
135
+ });
136
+ let res;
137
+ if (isGranted) {
138
+ const { browserSettings } = browser;
139
+ const { newTabPosition } = browserSettings;
140
+ res = await newTabPosition.get({});
141
+ }
142
+ return res || null;
143
+ };
144
+
145
+ /* commands */
146
+ /**
147
+ * is command customizable
148
+ *
149
+ * @returns {boolean} - result
150
+ */
151
+ export const isCommandCustomizable = async () => {
152
+ const isGranted = await isPermissionGranted({
153
+ permissions: ['commands']
154
+ });
155
+ let bool;
156
+ if (isGranted) {
157
+ const { commands } = browser;
158
+ bool = typeof commands.update === 'function' &&
159
+ typeof commands.reset === 'function';
160
+ }
161
+ return !!bool;
162
+ };
163
+
164
+ /**
165
+ * update command
166
+ *
167
+ * @param {string} id - command ID
168
+ * @param {string} value - key value
169
+ * @returns {?Function} - commands.update() | commands.reset()
170
+ */
171
+ export const updateCommand = async (id, value = '') => {
172
+ if (!isString(id)) {
173
+ throw new TypeError(`Expected String but got ${getType(id)}.`);
174
+ }
175
+ if (!isString(value)) {
176
+ throw new TypeError(`Expected String but got ${getType(value)}.`);
177
+ }
178
+ let func;
179
+ if (await isCommandCustomizable()) {
180
+ const { commands } = browser;
181
+ const shortcut =
182
+ value.trim().replace(/\+([a-z])$/, (m, c) => `+${c.toUpperCase()}`);
183
+ if (shortcut === '') {
184
+ func = commands.reset(id);
185
+ } else if (/^(?:(?:(?:Alt|Command|(?:Mac)?Ctrl)(?:\+Shift)?|Alt\+(?:Command|(?:Mac)?Ctrl)|Command\+(?:Alt|MacCtrl)|Ctrl\+(?:Alt|MacCtrl)|MacCtrl\+(?:Alt|Command|Ctrl))\+(?:[\dA-Z]|F(?:[1-9]|1[0-2])|(?:Page)?(?:Down|Up)|Left|Right|Comma|Period|Home|End|Delete|Insert|Space))|F(?:[1-9]|1[0-2])|Media(?:(?:Next|Prev)Track|PlayPause|Stop)$/.test(shortcut)) {
186
+ func = commands.update({
187
+ shortcut,
188
+ name: id
189
+ });
190
+ }
191
+ }
192
+ return func || null;
193
+ };
194
+
195
+ /* contextualIdentities */
196
+ /**
197
+ * get all contextual identities
198
+ *
199
+ * @returns {?Array} - array of contextualIdentities.ContextualIdentity
200
+ */
201
+ export const getAllContextualIdentities = async () => {
202
+ const isGranted = await isPermissionGranted({
203
+ permissions: ['contextualIdentities']
204
+ });
205
+ let arr;
206
+ if (isGranted) {
207
+ const { contextualIdentities } = browser;
208
+ try {
209
+ arr = await contextualIdentities.query({});
210
+ } catch (e) {
211
+ logErr(e);
212
+ }
213
+ }
214
+ return arr || null;
215
+ };
216
+
217
+ /**
218
+ * get contextual identities
219
+ *
220
+ * @param {string} cookieStoreId - cookie store ID
221
+ * @returns {object} - contextualIdentities.ContextualIdentity
222
+ */
223
+ export const getContextualId = async cookieStoreId => {
224
+ if (!isString(cookieStoreId)) {
225
+ throw new TypeError(`Expected String but got ${getType(cookieStoreId)}.`);
226
+ }
227
+ const isGranted = await isPermissionGranted({
228
+ permissions: ['contextualIdentities']
229
+ });
230
+ let id;
231
+ if (isGranted) {
232
+ const { contextualIdentities } = browser;
233
+ try {
234
+ id = await contextualIdentities.get(cookieStoreId);
235
+ } catch (e) {
236
+ logErr(e);
237
+ }
238
+ }
239
+ return id || null;
240
+ };
241
+
242
+ /* management */
243
+ /**
244
+ * get enabled theme
245
+ *
246
+ * @returns {?Array} - array of management.ExtensionInfo
247
+ */
248
+ export const getEnabledTheme = async () => {
249
+ const isGranted = await isPermissionGranted({
250
+ permissions: ['management']
251
+ });
252
+ let res;
253
+ if (isGranted) {
254
+ const { management } = browser;
255
+ const arr = await management.getAll();
256
+ if (Array.isArray(arr)) {
257
+ res = arr.filter(info =>
258
+ info.type && info.type === 'theme' && info.enabled && info
259
+ );
260
+ }
261
+ }
262
+ return res || null;
263
+ };
264
+
265
+ /**
266
+ * get extension info
267
+ *
268
+ * @param {string} id - extension ID
269
+ * @returns {object} - management.extensionInfo
270
+ */
271
+ export const getExtensionInfo = async id => {
272
+ if (!isString(id)) {
273
+ throw new TypeError(`Expected String but got ${getType(id)}.`);
274
+ }
275
+ const isGranted = await isPermissionGranted({
276
+ permissions: ['management']
277
+ });
278
+ let ext;
279
+ if (isGranted) {
280
+ const { management } = browser;
281
+ ext = await management.get(id);
282
+ }
283
+ return ext || null;
284
+ };
285
+
286
+ /**
287
+ * get external extensions
288
+ *
289
+ * @returns {?Array} -array of management.extensionInfo
290
+ */
291
+ export const getExternalExtensions = async () => {
292
+ const isGranted = await isPermissionGranted({
293
+ permissions: ['management']
294
+ });
295
+ let res;
296
+ if (isGranted) {
297
+ const { management } = browser;
298
+ const arr = await management.getAll();
299
+ if (Array.isArray(arr)) {
300
+ res = arr.filter(info => info.type && info.type === 'extension' && info);
301
+ }
302
+ }
303
+ return res || null;
304
+ };
305
+
306
+ /* notifications */
307
+ /**
308
+ * clear notification
309
+ *
310
+ * @param {string} id - notification ID
311
+ * @returns {?Function} - notifications.clear()
312
+ */
313
+ export const clearNotification = async id => {
314
+ if (!isString(id)) {
315
+ throw new TypeError(`Expected String but got ${getType(id)}.`);
316
+ }
317
+ const isGranted = await isPermissionGranted({
318
+ permissions: ['notifications']
319
+ });
320
+ let func;
321
+ if (isGranted) {
322
+ const { notifications } = browser;
323
+ func = notifications.clear(id);
324
+ }
325
+ return func || null;
326
+ };
327
+
328
+ /**
329
+ * create notification
330
+ *
331
+ * @param {string} id - notification ID
332
+ * @param {object} opt - options
333
+ * @returns {?Function} - notifications.create()
334
+ */
335
+ export const createNotification = async (id, opt) => {
336
+ if (!isString(id)) {
337
+ throw new TypeError(`Expected String but got ${getType(id)}.`);
338
+ }
339
+ const isGranted = await isPermissionGranted({
340
+ permissions: ['notifications']
341
+ });
342
+ let func;
343
+ if (isGranted) {
344
+ const { notifications } = browser;
345
+ !notifications.onClosed.hasListener(clearNotification) &&
346
+ notifications.onClosed.addListener(clearNotification);
347
+ func = notifications.create(id, opt);
348
+ }
349
+ return func || null;
350
+ };
351
+
352
+ /* permissions */
353
+ /**
354
+ * remove permission
355
+ *
356
+ * @param {string|Array} perm - permission
357
+ * @returns {boolean} - result
358
+ */
359
+ export const removePermission = async perm => {
360
+ if (!(isString(perm) || Array.isArray(perm))) {
361
+ throw new TypeError(`Expected String or Array but got ${getType(perm)}.`);
362
+ }
363
+ let bool;
364
+ if (isString(perm)) {
365
+ bool = await permissions.remove({
366
+ permissions: [perm]
367
+ });
368
+ } else {
369
+ bool = await permissions.remove({
370
+ permissions: perm
371
+ });
372
+ }
373
+ return !!bool;
374
+ };
375
+
376
+ /**
377
+ * request permission
378
+ *
379
+ * @param {string|Array} perm - permission
380
+ * @returns {boolean} - result
381
+ */
382
+ export const requestPermission = async perm => {
383
+ if (!(isString(perm) || Array.isArray(perm))) {
384
+ throw new TypeError(`Expected String or Array but got ${getType(perm)}.`);
385
+ }
386
+ let bool;
387
+ if (isString(perm)) {
388
+ bool = await permissions.request({
389
+ permissions: [perm]
390
+ });
391
+ } else {
392
+ bool = await permissions.request({
393
+ permissions: perm
394
+ });
395
+ }
396
+ return !!bool;
397
+ };
398
+
399
+ /* runtime */
400
+ /**
401
+ * get manifest icons
402
+ *
403
+ * @returns {object|string} - icons
404
+ */
405
+ export const getManifestIcons = () => {
406
+ const { icons } = runtime.getManifest();
407
+ return icons;
408
+ };
409
+
410
+ /**
411
+ * get OS
412
+ *
413
+ * @returns {string} - OS
414
+ */
415
+ export const getOs = async () => {
416
+ const { os } = await runtime.getPlatformInfo();
417
+ return os;
418
+ };
419
+
420
+ /**
421
+ * make a connection
422
+ *
423
+ * @param {string} [extId] - extension ID
424
+ * @param {object} [info] - info
425
+ * @returns {object} - runtime.Port
426
+ */
427
+ export const makeConnection = async (extId, info) => {
428
+ let port;
429
+ if (isString(extId)) {
430
+ if (isObjectNotEmpty(info)) {
431
+ port = await runtime.connect(extId, info);
432
+ } else {
433
+ port = await runtime.connect(extId);
434
+ }
435
+ } else if (isObjectNotEmpty(extId)) {
436
+ port = await runtime.connect(extId);
437
+ } else if (!extId && isObjectNotEmpty(info)) {
438
+ port = await runtime.connect(info);
439
+ } else {
440
+ port = await runtime.connect();
441
+ }
442
+ return port;
443
+ };
444
+
445
+ /**
446
+ * send message
447
+ *
448
+ * @param {number|string} id - tabId or extension ID
449
+ * @param {*} msg - message
450
+ * @param {object} opt - options
451
+ * @returns {?Function} - tabs.sendMessage() | runtime.sendMessage()
452
+ */
453
+ export const sendMessage = async (id, msg, opt) => {
454
+ let func;
455
+ if (msg) {
456
+ opt = isObjectNotEmpty(opt) ? opt : null;
457
+ if (Number.isInteger(id)) {
458
+ if (id !== tabs.TAB_ID_NONE) {
459
+ func = tabs.sendMessage(id, msg, opt);
460
+ }
461
+ } else if (id && isString(id)) {
462
+ func = runtime.sendMessage(id, msg, opt);
463
+ } else {
464
+ func = runtime.sendMessage(runtime.id, msg, opt);
465
+ }
466
+ }
467
+ return func || null;
468
+ };
469
+
470
+ /* search */
471
+ /**
472
+ * search with a search engine
473
+ *
474
+ * @param {string} query - search query
475
+ * @param {object} opt - options
476
+ * @returns {void}
477
+ */
478
+ export const searchWithSearchEngine = async (query, opt = {}) => {
479
+ if (!isString(query)) {
480
+ throw new TypeError(`Expected String but got ${getType(query)}.`);
481
+ }
482
+ const isGranted = await isPermissionGranted({
483
+ permissions: ['search']
484
+ });
485
+ if (isGranted) {
486
+ const { search } = browser;
487
+ opt.query = query;
488
+ await search.search(opt);
489
+ }
490
+ };
491
+
492
+ /* sessions */
493
+ /**
494
+ * get recently closed tab
495
+ *
496
+ * @param {number} windowId - window ID
497
+ * @returns {object} - tabs.Tab
498
+ */
499
+ export const getRecentlyClosedTab = async windowId => {
500
+ const isGranted = await isPermissionGranted({
501
+ permissions: ['sessions']
502
+ });
503
+ let tab;
504
+ if (isGranted) {
505
+ const { sessions } = browser;
506
+ const items = await sessions.getRecentlyClosed();
507
+ if (Array.isArray(items) && items.length) {
508
+ if (!Number.isInteger(windowId)) {
509
+ windowId = windows.WINDOW_ID_CURRENT;
510
+ }
511
+ for (const item of items) {
512
+ const { tab: itemTab } = item;
513
+ if (itemTab) {
514
+ const { windowId: itemWindowId } = itemTab;
515
+ if (itemWindowId === windowId) {
516
+ tab = itemTab;
517
+ break;
518
+ }
519
+ }
520
+ }
521
+ }
522
+ }
523
+ return tab || null;
524
+ };
525
+
526
+ /**
527
+ * get session window value
528
+ *
529
+ * @param {string} key - key
530
+ * @param {number} windowId - window ID
531
+ * @returns {string} - value
532
+ */
533
+ export const getSessionWindowValue = async (key, windowId) => {
534
+ if (!isString(key)) {
535
+ throw new TypeError(`Expected String but got ${getType(key)}.`);
536
+ }
537
+ if (!Number.isInteger(windowId)) {
538
+ windowId = windows.WINDOW_ID_CURRENT;
539
+ }
540
+ const isGranted = await isPermissionGranted({
541
+ permissions: ['sessions']
542
+ });
543
+ let value;
544
+ if (isGranted) {
545
+ const { sessions } = browser;
546
+ value = await sessions.getWindowValue(windowId, key);
547
+ }
548
+ return value || null;
549
+ };
550
+
551
+ /**
552
+ * restore session
553
+ *
554
+ * @param {string} sessionId - session ID
555
+ * @returns {object} - sessions.Session
556
+ */
557
+ export const restoreSession = async sessionId => {
558
+ if (!isString(sessionId)) {
559
+ throw new TypeError(`Expected String but got ${getType(sessionId)}.`);
560
+ }
561
+ const isGranted = await isPermissionGranted({
562
+ permissions: ['sessions']
563
+ });
564
+ let ses;
565
+ if (isGranted) {
566
+ const { sessions } = browser;
567
+ ses = await sessions.restore(sessionId);
568
+ }
569
+ return ses || null;
570
+ };
571
+
572
+ /**
573
+ * set session window value
574
+ *
575
+ * @param {string} key - key
576
+ * @param {string|object} value - value
577
+ * @param {number} windowId - window ID
578
+ * @returns {void}
579
+ */
580
+ export const setSessionWindowValue = async (key, value, windowId) => {
581
+ if (!isString(key)) {
582
+ throw new TypeError(`Expected String but got ${getType(key)}.`);
583
+ }
584
+ if (!Number.isInteger(windowId)) {
585
+ windowId = windows.WINDOW_ID_CURRENT;
586
+ }
587
+ const isGranted = await isPermissionGranted({
588
+ permissions: ['sessions']
589
+ });
590
+ if (isGranted) {
591
+ const { sessions } = browser;
592
+ await sessions.setWindowValue(windowId, key, value);
593
+ }
594
+ };
595
+
596
+ /* storage */
597
+ /**
598
+ * clear storage
599
+ *
600
+ * @returns {void}
601
+ */
602
+ export const clearStorage = async () => {
603
+ const isGranted = await isPermissionGranted({
604
+ permissions: ['storage']
605
+ });
606
+ if (isGranted) {
607
+ const { storage } = browser;
608
+ await storage.local.clear();
609
+ }
610
+ };
611
+
612
+ /**
613
+ * get all storage
614
+ *
615
+ * @returns {object} - stored data
616
+ */
617
+ export const getAllStorage = async () => {
618
+ const isGranted = await isPermissionGranted({
619
+ permissions: ['storage']
620
+ });
621
+ let data;
622
+ if (isGranted) {
623
+ const { storage } = browser;
624
+ data = await storage.local.get();
625
+ }
626
+ return data || null;
627
+ };
628
+
629
+ /**
630
+ * get storage
631
+ *
632
+ * @param {*} key - key
633
+ * @returns {object} - stored data
634
+ */
635
+ export const getStorage = async key => {
636
+ const isGranted = await isPermissionGranted({
637
+ permissions: ['storage']
638
+ });
639
+ let data;
640
+ if (isGranted) {
641
+ const { storage } = browser;
642
+ data = await storage.local.get(key);
643
+ }
644
+ return data || null;
645
+ };
646
+
647
+ /**
648
+ * remove storage
649
+ *
650
+ * @param {*} key - key
651
+ * @returns {void}
652
+ */
653
+ export const removeStorage = async key => {
654
+ const isGranted = await isPermissionGranted({
655
+ permissions: ['storage']
656
+ });
657
+ if (isGranted) {
658
+ const { storage } = browser;
659
+ await storage.local.remove(key);
660
+ }
661
+ };
662
+
663
+ /**
664
+ * set storage
665
+ *
666
+ * @param {object} obj - object to store
667
+ * @returns {void}
668
+ */
669
+ export const setStorage = async obj => {
670
+ const isGranted = await isPermissionGranted({
671
+ permissions: ['storage']
672
+ });
673
+ if (isGranted && obj) {
674
+ const { storage } = browser;
675
+ await storage.local.set(obj);
676
+ }
677
+ };
678
+
679
+ /* tabs */
680
+ /**
681
+ * create tab
682
+ *
683
+ * @param {object} opt - options
684
+ * @returns {object} - tabs.Tab
685
+ */
686
+ export const createTab = async (opt = {}) => {
687
+ const tab = await tabs.create(isObjectNotEmpty(opt) ? opt : null);
688
+ return tab;
689
+ };
690
+
691
+ /**
692
+ * duplicate tab
693
+ *
694
+ * @param {number} tabId - tab ID
695
+ * @param {object} opt - options
696
+ * @returns {object} - tabs.Tab
697
+ */
698
+ export const duplicateTab = async (tabId, opt) => {
699
+ if (!Number.isInteger(tabId)) {
700
+ throw new TypeError(`Expected Number but got ${getType(tabId)}.`);
701
+ }
702
+ const tab = await tabs.duplicate(tabId, isObjectNotEmpty(opt) ? opt : null);
703
+ return tab;
704
+ };
705
+
706
+ /**
707
+ * query tabs
708
+ *
709
+ * @param {object} opt - options
710
+ * @returns {?Array} - result
711
+ */
712
+ export const queryTabs = async opt => {
713
+ const res = await tabs.query(opt);
714
+ return res;
715
+ };
716
+
717
+ /**
718
+ * execute content script to existing tab
719
+ *
720
+ * @param {number|object} tabId - tab ID or options
721
+ * @param {object} opt - options
722
+ * @returns {?Array|boolean} - result
723
+ */
724
+ export const execScriptToTab = async (tabId, opt = {}) => {
725
+ let res;
726
+ try {
727
+ const isGranted = await isPermissionGranted({
728
+ permissions: ['activeTab']
729
+ });
730
+ if (Number.isInteger(tabId)) {
731
+ res = await tabs.executeScript(tabId, opt);
732
+ } else if (isGranted) {
733
+ if (isObjectNotEmpty(tabId)) {
734
+ res = await tabs.executeScript(tabId);
735
+ } else {
736
+ res = await tabs.executeScript(opt);
737
+ }
738
+ } else {
739
+ res = null;
740
+ }
741
+ } catch (e) {
742
+ res = logErr(e);
743
+ }
744
+ return res;
745
+ };
746
+
747
+ /**
748
+ * execute content script to existing tabs
749
+ *
750
+ * @param {object} opt - options
751
+ * @returns {Promise.<Array>} - results of each handler
752
+ */
753
+ export const execScriptToTabs = async (opt = {}) => {
754
+ const func = [];
755
+ const tabList = await queryTabs({
756
+ url: ['<all_urls>'],
757
+ windowType: 'normal'
758
+ });
759
+ for (const tab of tabList) {
760
+ const { id: tabId, url } = tab;
761
+ const { protocol } = new URL(url);
762
+ if (/^(?:data|f(?:tp|ile)|https?|wss?):/.test(protocol)) {
763
+ func.push(execScriptToTab(tabId, opt));
764
+ }
765
+ }
766
+ return Promise.all(func);
767
+ };
768
+
769
+ /**
770
+ * execute scripts to tab in order
771
+ *
772
+ * @param {number|Array} tabId - tabId or array of options
773
+ * @param {Array} opts - array of options
774
+ * @returns {*} - result of the last executed script
775
+ */
776
+ export const execScriptsToTabInOrder = async (tabId, opts = []) => {
777
+ const func = [];
778
+ let res;
779
+ if (Number.isInteger(tabId)) {
780
+ for (const item of opts) {
781
+ func.push(execScriptToTab(tabId, item));
782
+ }
783
+ } else {
784
+ let items;
785
+ if (Array.isArray(tabId) && tabId.length) {
786
+ items = tabId;
787
+ } else {
788
+ items = opts;
789
+ }
790
+ for (const item of items) {
791
+ func.push(execScriptToTab(item));
792
+ }
793
+ }
794
+ if (func.length) {
795
+ const { value } = await Promise.allSettled(func).then(a => a.pop());
796
+ res = value;
797
+ }
798
+ return res || null;
799
+ };
800
+
801
+ /**
802
+ * get active tab
803
+ *
804
+ * @param {number} windowId - window ID
805
+ * @returns {object} - tabs.Tab
806
+ */
807
+ export const getActiveTab = async windowId => {
808
+ if (!Number.isInteger(windowId)) {
809
+ windowId = windows.WINDOW_ID_CURRENT;
810
+ }
811
+ const [tab] = await queryTabs({
812
+ windowId,
813
+ active: true,
814
+ windowType: 'normal'
815
+ });
816
+ return tab;
817
+ };
818
+
819
+ /**
820
+ * get active tab ID
821
+ *
822
+ * @param {number} windowId - window ID
823
+ * @returns {?number} - tab ID
824
+ */
825
+ export const getActiveTabId = async windowId => {
826
+ if (!Number.isInteger(windowId)) {
827
+ windowId = windows.WINDOW_ID_CURRENT;
828
+ }
829
+ const { id } = await getActiveTab(windowId);
830
+ return id;
831
+ };
832
+
833
+ /**
834
+ * get all tabs in window
835
+ *
836
+ * @param {number} windowId - window ID
837
+ * @returns {?Array} - array of tabs.Tab
838
+ */
839
+ export const getAllTabsInWindow = async windowId => {
840
+ if (!Number.isInteger(windowId)) {
841
+ windowId = windows.WINDOW_ID_CURRENT;
842
+ }
843
+ const arr = await queryTabs({
844
+ windowId,
845
+ windowType: 'normal'
846
+ });
847
+ return arr;
848
+ };
849
+
850
+ /**
851
+ * get highlighted tab
852
+ *
853
+ * @param {number} windowId - window ID
854
+ * @returns {?Array} - array of tabs.Tab
855
+ */
856
+ export const getHighlightedTab = async windowId => {
857
+ if (!Number.isInteger(windowId)) {
858
+ windowId = windows.WINDOW_ID_CURRENT;
859
+ }
860
+ const arr = await queryTabs({
861
+ windowId,
862
+ highlighted: true,
863
+ windowType: 'normal'
864
+ });
865
+ return arr;
866
+ };
867
+
868
+ /**
869
+ * get tab
870
+ *
871
+ * @param {number} tabId - tab ID
872
+ * @returns {object} - tabs.Tab
873
+ */
874
+ export const getTab = async tabId => {
875
+ if (!Number.isInteger(tabId)) {
876
+ throw new TypeError(`Expected Number but got ${getType(tabId)}.`);
877
+ }
878
+ const tab = await tabs.get(tabId);
879
+ return tab;
880
+ };
881
+
882
+ /**
883
+ * highlight tab
884
+ *
885
+ * @param {number|Array} index - tab index
886
+ * @param {number} windowId - window ID
887
+ * @returns {object} - windows.Window
888
+ */
889
+ export const highlightTab = async (index, windowId) => {
890
+ if (!(Array.isArray(index) || Number.isInteger(index))) {
891
+ throw new TypeError(`Expected Number or Array but got ${getType(index)}.`);
892
+ }
893
+ if (!Number.isInteger(windowId)) {
894
+ windowId = windows.WINDOW_ID_CURRENT;
895
+ }
896
+ const opt = {
897
+ windowId,
898
+ tabs: index
899
+ };
900
+ const win = await tabs.highlight(opt);
901
+ return win;
902
+ };
903
+
904
+ /**
905
+ * move tab
906
+ *
907
+ * @param {number|Array} tabId - tab ID
908
+ * @param {object} opt - options
909
+ * @returns {?Array} - array of tabs.Tab
910
+ */
911
+ export const moveTab = async (tabId, opt) => {
912
+ if (!(Array.isArray(tabId) || Number.isInteger(tabId))) {
913
+ throw new TypeError(`Expected Number or Array but got ${getType(tabId)}.`);
914
+ }
915
+ let arr = await tabs.move(tabId, isObjectNotEmpty(opt) ? opt : null);
916
+ if (arr && !Array.isArray(arr)) {
917
+ arr = [arr];
918
+ }
919
+ return arr || null;
920
+ };
921
+
922
+ /**
923
+ * reload tab
924
+ *
925
+ * @param {number} tabId - tab ID
926
+ * @param {object} opt - options
927
+ * @returns {void}
928
+ */
929
+ export const reloadTab = async (tabId, opt) => {
930
+ if (!Number.isInteger(tabId)) {
931
+ throw new TypeError(`Expected Number but got ${getType(tabId)}.`);
932
+ }
933
+ await tabs.reload(tabId, isObjectNotEmpty(opt) ? opt : null);
934
+ };
935
+
936
+ /**
937
+ * remove tab
938
+ *
939
+ * @param {number|Array} arg - tab ID or array of tab ID
940
+ * @returns {void}
941
+ */
942
+ export const removeTab = async arg => {
943
+ if (Number.isInteger(arg)) {
944
+ arg = [arg];
945
+ }
946
+ if (!Array.isArray(arg)) {
947
+ throw new TypeError(`Expected Array but got ${getType(arg)}.`);
948
+ }
949
+ await tabs.remove(arg);
950
+ };
951
+
952
+ /**
953
+ * update tab
954
+ *
955
+ * @param {number} tabId - tab ID
956
+ * @param {object} opt - options
957
+ * @returns {object} - tabs.Tab
958
+ */
959
+ export const updateTab = async (tabId, opt) => {
960
+ if (!Number.isInteger(tabId)) {
961
+ throw new TypeError(`Expected Number but got ${getType(tabId)}.`);
962
+ }
963
+ const tab = await tabs.update(tabId, isObjectNotEmpty(opt) ? opt : null);
964
+ return tab;
965
+ };
966
+
967
+ /**
968
+ * warmup tab
969
+ *
970
+ * @param {number} tabId - tab ID
971
+ * @returns {void}
972
+ */
973
+ export const warmupTab = async tabId => {
974
+ if (!Number.isInteger(tabId)) {
975
+ throw new TypeError(`Expected Number but got ${getType(tabId)}.`);
976
+ }
977
+ typeof tabs.warmup === 'function' && await tabs.warmup(tabId);
978
+ };
979
+
980
+ /**
981
+ * is tab
982
+ *
983
+ * @param {*} tabId - tab ID
984
+ * @returns {boolean} - result
985
+ */
986
+ export const isTab = async tabId => {
987
+ if (!Number.isInteger(tabId)) {
988
+ throw new TypeError(`Expected Number but got ${getType(tabId)}.`);
989
+ }
990
+ let tab;
991
+ if (tabId !== tabs.TAB_ID_NONE) {
992
+ try {
993
+ tab = await tabs.get(tabId);
994
+ } catch (e) {
995
+ tab = false;
996
+ }
997
+ }
998
+ return !!tab;
999
+ };
1000
+
1001
+ /* theme */
1002
+ /**
1003
+ * get current theme
1004
+ *
1005
+ * @returns {object} - theme.Theme
1006
+ */
1007
+ export const getCurrentTheme = async () => {
1008
+ const isGranted = await isPermissionGranted({
1009
+ permissions: ['theme']
1010
+ });
1011
+ let currentTheme;
1012
+ if (isGranted) {
1013
+ const { theme } = browser;
1014
+ currentTheme = await theme.getCurrent();
1015
+ }
1016
+ return currentTheme || null;
1017
+ };
1018
+
1019
+ /* windows */
1020
+ /**
1021
+ * create new window
1022
+ *
1023
+ * @param {object} opt - options
1024
+ * @returns {object} - windows.Window
1025
+ */
1026
+ export const createNewWindow = async opt => {
1027
+ const win = await windows.create(isObjectNotEmpty(opt) ? opt : null);
1028
+ return win;
1029
+ };
1030
+
1031
+ /**
1032
+ * get all windows
1033
+ *
1034
+ * @param {boolean} populate - populate tabs
1035
+ * @returns {Array} - array of windows.Window
1036
+ */
1037
+ export const getAllNormalWindows = async (populate = false) => {
1038
+ const arr = await windows.getAll({
1039
+ populate,
1040
+ windowTypes: ['normal']
1041
+ });
1042
+ return arr;
1043
+ };
1044
+
1045
+ /**
1046
+ * get current window
1047
+ *
1048
+ * @param {object} opt - options
1049
+ * @returns {object} - windows.Window
1050
+ */
1051
+ export const getCurrentWindow = async opt => {
1052
+ const win = await windows.getCurrent(isObjectNotEmpty(opt) ? opt : null);
1053
+ return win;
1054
+ };
1055
+
1056
+ /**
1057
+ * get window
1058
+ *
1059
+ * @param {number} windowId - window ID
1060
+ * @param {object} opt - options
1061
+ * @returns {object} - windows.Window
1062
+ */
1063
+ export const getWindow = async (windowId, opt) => {
1064
+ if (!Number.isInteger(windowId)) {
1065
+ throw new TypeError(`Expected Number but got ${getType(windowId)}.`);
1066
+ }
1067
+ const win = await windows.get(windowId, isObjectNotEmpty(opt) ? opt : null);
1068
+ return win;
1069
+ };
1070
+
1071
+ /**
1072
+ * check whether incognito window exists
1073
+ *
1074
+ * @returns {boolean} - result
1075
+ */
1076
+ export const checkIncognitoWindowExists = async () => {
1077
+ const arr = await getAllNormalWindows();
1078
+ let bool;
1079
+ if (arr && arr.length) {
1080
+ for (const win of arr) {
1081
+ bool = win.incognito;
1082
+ if (bool) {
1083
+ break;
1084
+ }
1085
+ }
1086
+ }
1087
+ return !!bool;
1088
+ };