Skip to content

Commit

Permalink
Make compatible with Manifest v3 (#256)
Browse files Browse the repository at this point in the history
* fix: browser storage version types
* fix: auth flow on firefox
* fix: scrobbling details do not update if scrobbling from a different tab
* fix: scrobbling item image does not appear in popup
* fix: history requests are not canceled
* fix: canceled requests do not throw error
* feat: change manifest version
* feat: add helper to check manifest version
* feat: change background script to service worker
* feat: separate permissions from host permissions
* feat: remove content security policy
* feat: rename browser action to action
* feat: remove web accessible resources
* feat: use scripting api to inject content scripts
* feat: use scripting api to inject functions
* feat: remove ports
* feat: remove axios
* feat: remove window/document references from background logic
  • Loading branch information
rafaelgomesxyz authored May 7, 2023
1 parent c3c1449 commit 397c195
Show file tree
Hide file tree
Showing 35 changed files with 452 additions and 405 deletions.
2 changes: 0 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,6 @@
"@mui/material": "^5.10.16",
"@mui/system": "^5.10.16",
"@mui/x-date-pickers": "^5.0.9",
"@rafaelgomesxyz/axios-rate-limit": "^1.3.1",
"axios": "^0.26.1",
"date-fns": "^2.29.3",
"deepmerge": "^4.2.2",
"history": "^4.10.1",
Expand Down
30 changes: 0 additions & 30 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 4 additions & 3 deletions src/apis/ServiceApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,8 @@ export abstract class ServiceApi {
async loadHistory(
itemsToLoad: number,
lastSync: number,
lastSyncId: string
lastSyncId: string,
cancelKey = 'default'
): Promise<ScrobbleItem[]> {
let items: ScrobbleItem[] = [];
try {
Expand All @@ -156,7 +157,7 @@ export abstract class ServiceApi {
responseItems = this.leftoverHistoryItems;
this.leftoverHistoryItems = [];
} else if (!this.hasReachedHistoryEnd) {
responseItems = await this.loadHistoryItems();
responseItems = await this.loadHistoryItems(cancelKey);
if (!this.hasCheckedHistoryCache) {
let firstItem: ScrobbleItemValues | null = null;
if (historyCache.items.length > 0) {
Expand Down Expand Up @@ -282,7 +283,7 @@ export abstract class ServiceApi {
*
* Should be overridden in the child class.
*/
loadHistoryItems(): Promise<unknown[]> {
loadHistoryItems(cancelKey = 'default'): Promise<unknown[]> {
Shared.errors.error('loadHistoryItems() is not implemented in this service!', new Error());
return Promise.resolve([]);
}
Expand Down
14 changes: 2 additions & 12 deletions src/apis/TraktApi.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { withHeaders, withRateLimit } from '@common/Requests';
import { Requests, withHeaders } from '@common/Requests';
import { Shared } from '@common/Shared';

export class TraktApi {
Expand All @@ -15,17 +15,7 @@ export class TraktApi {
SYNC_URL: string;
SETTINGS_URL: string;

requests = withRateLimit({
id: 'trakt-api',

/**
* @see https://trakt.docs.apiary.io/#introduction/rate-limiting
*/
maxRPS: {
'*': 1,
GET: 3,
},
});
requests = Requests;

isActivated = false;

Expand Down
13 changes: 6 additions & 7 deletions src/apis/TraktAuth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,18 @@ class _TraktAuth extends TraktApi {
this.manualAuth = {};
}

requiresCookies(): boolean {
return Shared.browser === 'firefox' ? !!Shared.storage.options.grantCookies : false;
}

getAuthorizeUrl(): string {
return `${this.AUTHORIZE_URL}?response_type=code&client_id=${
Shared.clientId
}&redirect_uri=${this.getRedirectUrl()}`;
}

getRedirectUrl(): string {
const requiresCookies = !!Shared.storage.options.grantCookies;
return this.isIdentityAvailable && !requiresCookies
return this.isIdentityAvailable && !this.requiresCookies()
? browser.identity.getRedirectURL()
: this.REDIRECT_URL;
}
Expand All @@ -54,11 +57,7 @@ class _TraktAuth extends TraktApi {

authorize(): Promise<TraktAuthDetails> {
let promise: Promise<TraktAuthDetails>;
let requiresCookies = false;
if (Shared.browser === 'firefox') {
requiresCookies = !!Shared.storage.options.grantCookies;
}
if (this.isIdentityAvailable && !requiresCookies) {
if (this.isIdentityAvailable && !this.requiresCookies()) {
promise = this.startIdentityAuth();
} else {
promise = new Promise<TraktAuthDetails>((resolve) => void this.startManualAuth(resolve));
Expand Down
2 changes: 1 addition & 1 deletion src/apis/TraktScrobble.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class _TraktScrobble extends TraktApi {
}
await this.send(item.trakt, this.START);
let { scrobblingDetails } = await Shared.storage.get('scrobblingDetails');
if (scrobblingDetails) {
if (scrobblingDetails?.tabId === Shared.tabId) {
scrobblingDetails.isPaused = false;
} else {
scrobblingDetails = {
Expand Down
2 changes: 0 additions & 2 deletions src/apis/TraktSync.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { TraktApi } from '@apis/TraktApi';
import { Cache, CacheItem } from '@common/Cache';
import { RequestPriority } from '@common/Requests';
import { Shared } from '@common/Shared';
import { Utils } from '@common/Utils';
import { ScrobbleItem } from '@models/Item';
Expand Down Expand Up @@ -56,7 +55,6 @@ class _TraktSync extends TraktApi {
url: this.getUrl(item),
method: 'GET',
cancelKey,
priority: RequestPriority.HIGH,
});
historyItems = JSON.parse(responseText) as TraktHistoryItem[];
traktHistoryItemsCache.set(databaseId, historyItems);
Expand Down
2 changes: 1 addition & 1 deletion src/common/AutoSync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ class _AutoSync {
await store.resetData();

try {
await api.loadHistory(Infinity, serviceValue.lastSync, serviceValue.lastSyncId);
await api.loadHistory(Infinity, serviceValue.lastSync, serviceValue.lastSyncId, 'autoSync');

items = store.data.items.filter(
(item) => item.progress >= Shared.storage.syncOptions.minPercentageWatched
Expand Down
34 changes: 21 additions & 13 deletions src/common/BrowserAction.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import { Messaging } from '@common/Messaging';
import { Requests } from '@common/Requests';
import { Shared } from '@common/Shared';
import browser, { Action as WebExtAction } from 'webextension-polyfill';

export interface BrowserActionRotating {
image: HTMLImageElement | null;
canvas: HTMLCanvasElement | null;
context: CanvasRenderingContext2D | null;
image: ImageBitmap | null;
canvas: OffscreenCanvas | null;
context: OffscreenCanvasRenderingContext2D | null;
degrees: number;
canceled: boolean;
}

class _BrowserAction {
instance = Shared.manifestVersion === 3 ? browser.action : browser.browserAction;
currentIcon = browser.runtime.getURL('images/uts-icon-38.png');
rotating: BrowserActionRotating | null = null;

Expand All @@ -30,7 +32,7 @@ class _BrowserAction {

async setTitle(title = 'Universal Trakt Scrobbler'): Promise<void> {
if (Shared.pageType === 'background') {
await browser.browserAction.setTitle({ title });
await this.instance.setTitle({ title });
} else {
await Messaging.toExtension({ action: 'set-title', title });
}
Expand All @@ -43,7 +45,7 @@ class _BrowserAction {
await this.setStaticIcon();
await this.setRotatingIcon();
} else {
await browser.browserAction.setIcon({
await this.instance.setIcon({
path: this.currentIcon,
});
}
Expand All @@ -59,7 +61,7 @@ class _BrowserAction {
await this.setStaticIcon();
await this.setRotatingIcon();
} else {
await browser.browserAction.setIcon({
await this.instance.setIcon({
path: this.currentIcon,
});
}
Expand All @@ -70,18 +72,24 @@ class _BrowserAction {

async setRotatingIcon(): Promise<void> {
if (Shared.pageType === 'background') {
const image = document.createElement('img');
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
const imageResponse = await Requests.fetch({
method: 'GET',
url: this.currentIcon,
});
const imageBlob = await imageResponse.blob();
const image = await createImageBitmap(imageBlob);
const canvas = new OffscreenCanvas(image.width, image.height);
const context = canvas.getContext('2d', {
willReadFrequently: true,
}) as OffscreenCanvasRenderingContext2D;
this.rotating = {
image,
canvas,
context,
degrees: 0,
canceled: false,
};
image.onload = () => void this.rotateIcon();
image.src = this.currentIcon;
await this.rotateIcon();
} else {
await Messaging.toExtension({ action: 'set-rotating-icon' });
}
Expand Down Expand Up @@ -114,7 +122,7 @@ class _BrowserAction {
context.rotate((degrees * Math.PI) / 180);
context.drawImage(image, -(image.width / 2), -(image.height / 2));

await browser.browserAction.setIcon({
await this.instance.setIcon({
imageData: context.getImageData(
0,
0,
Expand All @@ -133,7 +141,7 @@ class _BrowserAction {
this.rotating.degrees = 0;
}

window.setTimeout(() => void this.rotateIcon(), 30);
setTimeout(() => void this.rotateIcon(), 30);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/common/BrowserStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export type StorageValuesV11 = Omit<StorageValuesV10, 'version'> & {
version?: 11;
};

export type StorageValuesV10 = Omit<StorageValuesV8, 'version' | 'options'> & {
export type StorageValuesV10 = Omit<StorageValuesV9, 'version' | 'options'> & {
version?: 10;
options?: StorageValuesOptionsV4;
};
Expand Down
8 changes: 6 additions & 2 deletions src/common/Errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,14 @@ class _Errors {
environment: Shared.environment,
},
});
window.Rollbar = this.rollbar;
if (window) {
window.Rollbar = this.rollbar;
}
} else if (!allowRollbar && this.rollbar) {
delete this.rollbar;
delete window.Rollbar;
if (window) {
delete window.Rollbar;
}
}
}

Expand Down
Loading

0 comments on commit 397c195

Please sign in to comment.