|
|
@@ -18,35 +18,34 @@
|
|
|
* along with SingleFile. If not, see <http://www.gnu.org/licenses/>.
|
|
|
*/
|
|
|
|
|
|
-/* global browser, window, top, document, HTMLHtmlElement, addEventListener, docHelper, timeout */
|
|
|
+/* global window, top, document, addEventListener, docHelper, timeout */
|
|
|
|
|
|
this.FrameTree = this.FrameTree || (() => {
|
|
|
|
|
|
const MESSAGE_PREFIX = "__FrameTree__";
|
|
|
const TIMEOUT_INIT_REQUEST_MESSAGE = 500;
|
|
|
|
|
|
+ let sessionId = 0;
|
|
|
+
|
|
|
const FrameTree = {
|
|
|
getFramesData
|
|
|
};
|
|
|
|
|
|
let sessions = new Map();
|
|
|
- if (window == top) {
|
|
|
- browser.runtime.onMessage.addListener(onTopBackgroundMessage);
|
|
|
- }
|
|
|
addEventListener("message", onFrameWindowMessage, false);
|
|
|
return FrameTree;
|
|
|
|
|
|
async function getFramesData(options) {
|
|
|
- const sessionId = options.sessionId;
|
|
|
- const sessionFramesData = sessions.get(sessionId);
|
|
|
- sessions.delete(sessionId);
|
|
|
- return sessionFramesData.frames.sort((frame1, frame2) => frame2.windowId.split(".").length - frame1.windowId.split(".").length);
|
|
|
- }
|
|
|
-
|
|
|
- function onTopBackgroundMessage(message) {
|
|
|
- if (message.method == "FrameTree.initRequest" && document.documentElement instanceof HTMLHtmlElement) {
|
|
|
- initRequest(message);
|
|
|
- }
|
|
|
+ options.sessionId = sessionId;
|
|
|
+ sessionId++;
|
|
|
+ return new Promise(resolve => {
|
|
|
+ sessions.set(options.sessionId, {
|
|
|
+ frames: [],
|
|
|
+ dataRequestCallbacks: new Map(),
|
|
|
+ resolve
|
|
|
+ });
|
|
|
+ initRequest({ windowId: "0", sessionId: options.sessionId, options });
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
function onFrameWindowMessage(event) {
|
|
|
@@ -65,11 +64,11 @@ this.FrameTree = this.FrameTree || (() => {
|
|
|
const sessionId = message.sessionId;
|
|
|
FrameTree.windowId = windowId;
|
|
|
const frameElements = document.querySelectorAll("iframe, frame, object[type=\"text/html\"][data]");
|
|
|
- sessions.set(message.sessionId, {
|
|
|
- frames: [],
|
|
|
- dataRequestCallbacks: new Map()
|
|
|
- });
|
|
|
if (window != top) {
|
|
|
+ sessions.set(message.sessionId, {
|
|
|
+ frames: [],
|
|
|
+ dataRequestCallbacks: new Map()
|
|
|
+ });
|
|
|
const docData = docHelper.preProcessDoc(document, window, message.options);
|
|
|
const content = docHelper.serialize(document);
|
|
|
docHelper.postProcessDoc(document, window, message.options);
|
|
|
@@ -80,28 +79,25 @@ this.FrameTree = this.FrameTree || (() => {
|
|
|
|
|
|
function initResponse(message) {
|
|
|
if (window == top) {
|
|
|
- if (message.framesData) {
|
|
|
- const sessionFramesData = sessions.get(message.sessionId);
|
|
|
+ const sessionFramesData = sessions.get(message.sessionId);
|
|
|
+ if (sessionFramesData) {
|
|
|
message.framesData.forEach(messageFrameData => {
|
|
|
let frameData = sessionFramesData.frames.find(frameData => messageFrameData.windowId == frameData.windowId);
|
|
|
if (!frameData) {
|
|
|
frameData = { windowId: messageFrameData.windowId };
|
|
|
sessionFramesData.frames.push(frameData);
|
|
|
}
|
|
|
-
|
|
|
frameData.content = messageFrameData.content;
|
|
|
frameData.baseURI = messageFrameData.baseURI;
|
|
|
frameData.title = messageFrameData.title;
|
|
|
frameData.emptyStyleRulesText = messageFrameData.emptyStyleRulesText;
|
|
|
frameData.canvasData = messageFrameData.canvasData;
|
|
|
-
|
|
|
frameData.processed = messageFrameData.processed;
|
|
|
});
|
|
|
-
|
|
|
const pendingCount = sessionFramesData.frames.filter(frameData => !frameData.processed).length;
|
|
|
- if (!pendingCount && !sessionFramesData.initResponseSent) {
|
|
|
- sessionFramesData.initResponseSent = true;
|
|
|
- browser.runtime.sendMessage({ method: "FrameTree.initResponse", sessionId: message.sessionId });
|
|
|
+ if (!pendingCount) {
|
|
|
+ sessions.delete(message.sessionId);
|
|
|
+ sessionFramesData.resolve(sessionFramesData.frames.sort((frame1, frame2) => frame2.windowId.split(".").length - frame1.windowId.split(".").length));
|
|
|
}
|
|
|
}
|
|
|
} else {
|
|
|
@@ -120,6 +116,7 @@ this.FrameTree = this.FrameTree || (() => {
|
|
|
framesData.push({ windowId: frameWinId });
|
|
|
try {
|
|
|
if (!frameElement.contentDocument) {
|
|
|
+ options.win = null;
|
|
|
frameElement.contentWindow.postMessage(MESSAGE_PREFIX + "::" + JSON.stringify({ method: "initRequest", windowId: frameWinId, sessionId, frameIndex, options }), "*");
|
|
|
timeout.set(() => top.postMessage(MESSAGE_PREFIX + "::" + JSON.stringify({ method: "initResponse", framesData: [], windowId: frameWinId, sessionId }), "*"), TIMEOUT_INIT_REQUEST_MESSAGE);
|
|
|
}
|