aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShin'ya Ueoka <ueokande@i-beam.org>2021-09-25 18:17:50 +0900
committerShin'ya Ueoka <ueokande@i-beam.org>2021-09-25 18:57:07 +0900
commita0f2c3ee107508e406a4a41cbda76ecd2d3f0d8f (patch)
tree2a14c2b99fa32e3a7c7473adaa60c8f544a9a56d
parentfa3500e3bbd11caa0e7ad1633b85f95600cf962f (diff)
Discover frames on search by count of connections
When a tab switches pages quickly, a disconnect event on top frame is sometime delivered after second connect event. In addition, `tabs.onUpdated()` event is independent on port connection event. Now the background script finds alive frames by only port connection.
-rw-r--r--src/background/Application.ts1
-rw-r--r--src/background/repositories/ReadyFrameRepository.ts37
-rw-r--r--src/background/usecases/ReadyFrameUseCase.ts18
-rw-r--r--test/background/mock/MockReadyFrameRepository.ts4
-rw-r--r--test/background/repositories/ReadyFrameRepository.test.ts13
5 files changed, 31 insertions, 42 deletions
diff --git a/src/background/Application.ts b/src/background/Application.ts
index c7bcc42..b439d19 100644
--- a/src/background/Application.ts
+++ b/src/background/Application.ts
@@ -31,7 +31,6 @@ export default class Application {
browser.tabs.onUpdated.addListener((tabId: number, info) => {
if (info.status == "loading") {
- this.frameRepository.clearFrameIds(tabId);
this.findRepository.deleteLocalState(tabId);
}
});
diff --git a/src/background/repositories/ReadyFrameRepository.ts b/src/background/repositories/ReadyFrameRepository.ts
index aa5d986..c993858 100644
--- a/src/background/repositories/ReadyFrameRepository.ts
+++ b/src/background/repositories/ReadyFrameRepository.ts
@@ -2,11 +2,9 @@ import MemoryStorage from "../infrastructures/MemoryStorage";
const REPOSITORY_KEY = "readyFrameRepository";
-type State = { [tabId: number]: number[] };
+type State = { [tabId: number]: { [frameId: number]: number } };
export default interface ReadyFrameRepository {
- clearFrameIds(tabId: number): Promise<void>;
-
addFrameId(tabId: number, frameId: number): Promise<void>;
removeFrameId(tabId: number, frameId: number): Promise<void>;
@@ -21,22 +19,14 @@ export class ReadyFrameRepositoryImpl implements ReadyFrameRepository {
this.cache = new MemoryStorage();
}
- clearFrameIds(tabId: number): Promise<void> {
- let state: State | undefined = this.cache.get(REPOSITORY_KEY);
- if (typeof state === "undefined") {
- state = {};
- }
- delete state[tabId];
- this.cache.set(REPOSITORY_KEY, state);
- return Promise.resolve();
- }
-
addFrameId(tabId: number, frameId: number): Promise<void> {
let state: State | undefined = this.cache.get(REPOSITORY_KEY);
if (typeof state === "undefined") {
state = {};
}
- state[tabId] = (state[tabId] || []).concat(frameId).sort();
+ const tab = state[tabId] || {};
+ tab[frameId] = (tab[frameId] || 0) + 1;
+ state[tabId] = tab;
this.cache.set(REPOSITORY_KEY, state);
return Promise.resolve();
}
@@ -50,7 +40,15 @@ export class ReadyFrameRepositoryImpl implements ReadyFrameRepository {
if (typeof ids === "undefined") {
return Promise.resolve();
}
- state[tabId] = ids.filter((id) => id != frameId);
+ const tab = state[tabId] || {};
+ tab[frameId] = (tab[frameId] || 0) - 1;
+ if (tab[frameId] == 0) {
+ delete tab[frameId];
+ }
+ if (Object.keys(tab).length === 0) {
+ delete state[tabId];
+ }
+
this.cache.set(REPOSITORY_KEY, state);
return Promise.resolve();
}
@@ -60,6 +58,13 @@ export class ReadyFrameRepositoryImpl implements ReadyFrameRepository {
if (typeof state === "undefined") {
return Promise.resolve(undefined);
}
- return Promise.resolve(state[tabId]);
+ const tab = state[tabId];
+ if (typeof tab === "undefined") {
+ return Promise.resolve(undefined);
+ }
+ const frameIds = Object.keys(tab)
+ .map((v) => Number(v))
+ .sort();
+ return Promise.resolve(frameIds);
}
}
diff --git a/src/background/usecases/ReadyFrameUseCase.ts b/src/background/usecases/ReadyFrameUseCase.ts
deleted file mode 100644
index 81bee0c..0000000
--- a/src/background/usecases/ReadyFrameUseCase.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import { inject, injectable } from "tsyringe";
-import ReadyFrameRepository from "../repositories/ReadyFrameRepository";
-
-@injectable()
-export default class ReadyFrameUseCase {
- constructor(
- @inject("ReadyFrameRepository")
- private readonly frameRepository: ReadyFrameRepository
- ) {}
-
- async addReadyFrame(tabId: number, frameId: number): Promise<void> {
- return this.frameRepository.addFrameId(tabId, frameId);
- }
-
- async clearReadyFrame(tabId: number): Promise<void> {
- return this.frameRepository.clearFrameIds(tabId);
- }
-}
diff --git a/test/background/mock/MockReadyFrameRepository.ts b/test/background/mock/MockReadyFrameRepository.ts
index a95b2e1..4a5ec52 100644
--- a/test/background/mock/MockReadyFrameRepository.ts
+++ b/test/background/mock/MockReadyFrameRepository.ts
@@ -1,10 +1,6 @@
import ReadyFrameRepository from "../../../src/background/repositories/ReadyFrameRepository";
export default class MockReadyFrameRepository implements ReadyFrameRepository {
- clearFrameIds(_tabId: number): Promise<void> {
- throw new Error("not implemented");
- }
-
addFrameId(_tabId: number, _fraemId: number): Promise<void> {
throw new Error("not implemented");
}
diff --git a/test/background/repositories/ReadyFrameRepository.test.ts b/test/background/repositories/ReadyFrameRepository.test.ts
index 888f3f5..71f20af 100644
--- a/test/background/repositories/ReadyFrameRepository.test.ts
+++ b/test/background/repositories/ReadyFrameRepository.test.ts
@@ -15,12 +15,19 @@ describe("background/repositories/ReadyFrameRepositoryImpl", () => {
await sut.addFrameId(1, 12);
await sut.addFrameId(1, 11);
await sut.addFrameId(2, 20);
+ await sut.addFrameId(2, 21);
+ await sut.addFrameId(2, 21);
expect(await sut.getFrameIds(1)).to.deep.equal([10, 11, 12]);
- expect(await sut.getFrameIds(2)).to.deep.equal([20]);
+ expect(await sut.getFrameIds(2)).to.deep.equal([20, 21]);
- await sut.clearFrameIds(1);
+ await sut.removeFrameId(2, 21);
+ expect(await sut.getFrameIds(2)).to.deep.equal([20, 21]);
- expect(await sut.getFrameIds(1)).to.be.undefined;
+ await sut.removeFrameId(2, 21);
+ expect(await sut.getFrameIds(2)).to.deep.equal([20]);
+
+ await sut.removeFrameId(2, 20);
+ expect(await sut.getFrameIds(2)).to.be.undefined;
});
});