({ count, tabId })
| 365 | }, |
| 366 | |
| 367 | async nextFrame({ count, tabId }) { |
| 368 | // We're assuming that these frames are returned in the order that they appear on the page. This |
| 369 | // seems to be the case empirically. If it's ever needed, we could also sort by frameId. |
| 370 | let frameIds = await getFrameIdsForTab(tabId); |
| 371 | const promises = frameIds.map(async (frameId) => { |
| 372 | // It is possible that this sendMessage call fails, if a frame gets unloaded while the request |
| 373 | // is in flight. |
| 374 | let isError = false; |
| 375 | const status = await (chrome.tabs.sendMessage(tabId, { handler: "getFocusStatus" }, { |
| 376 | frameId: frameId, |
| 377 | }).catch((_) => { |
| 378 | isError = true; |
| 379 | })); |
| 380 | return { frameId, status, isError }; |
| 381 | }); |
| 382 | |
| 383 | const frameResponses = (await Promise.all(promises)).filter((r) => !r.isError); |
| 384 | |
| 385 | const focusedFrameId = frameResponses.find(({ status }) => status.focused)?.frameId; |
| 386 | // It's theoretically possible that focusedFrameId is null if the user switched tabs or away |
| 387 | // from the browser while the request is in flight. |
| 388 | if (focusedFrameId == null) return; |
| 389 | |
| 390 | // Prune any frames which gave an error response (i.e. they disappeared). |
| 391 | frameIds = frameResponses.filter((r) => r.status.focusable).map((r) => r.frameId); |
| 392 | |
| 393 | const index = frameIds.indexOf(focusedFrameId); |
| 394 | count = count ?? 1; |
| 395 | const nextIndex = (index + count) % frameIds.length; |
| 396 | if (index == nextIndex) return; |
| 397 | await chrome.tabs.sendMessage(tabId, { handler: "focusFrame", highlight: true }, { |
| 398 | frameId: frameIds[nextIndex], |
| 399 | }); |
| 400 | }, |
| 401 | |
| 402 | async closeTabsOnLeft(request) { |
| 403 | await removeTabsRelative("before", request); |
nothing calls this directly
no test coverage detected