bgcore.js 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. (function() {
  2. singlefile.PageData = PageData;
  3. singlefile.DocData = DocData;
  4. function PageData(tabId, pageId, senderId, config, processSelection, processFrame, callback) {
  5. var timeoutError, that = this;
  6. this.pageId = pageId;
  7. this.docs = [];
  8. this.processedDocs = 0;
  9. this.initializedDocs = 0;
  10. this.processableDocs = 0;
  11. this.senderId = senderId;
  12. this.config = config;
  13. this.processSelection = processSelection;
  14. this.processFrame = processFrame;
  15. this.processing = true;
  16. this.tabId = tabId;
  17. this.requestManager = new singlefile.nio.RequestManager();
  18. this.progressIndex = 0;
  19. this.progressMax = 0;
  20. this.title = null;
  21. this.url = null;
  22. this.top = null;
  23. this.timeoutPageInit = null;
  24. this.portsId = [];
  25. this.contextmenuTime = null;
  26. this.frameDocData = null;
  27. timeoutError = setTimeout(function() {
  28. that.processing = false;
  29. chrome.extension.sendMessage(that.senderId, {
  30. processError : true,
  31. tabId : tabId
  32. });
  33. }, 15000);
  34. wininfo.init(tabId, function(processableDocs) {
  35. clearTimeout(timeoutError);
  36. that.processableDocs = processableDocs;
  37. callback();
  38. });
  39. }
  40. PageData.prototype = {
  41. initProcess : function() {
  42. var that = this;
  43. this.docs.forEach(function(docData) {
  44. if (that.config.processInBackground) {
  45. if (docData.processDocCallback)
  46. docData.processDocCallback();
  47. } else
  48. docData.process();
  49. });
  50. },
  51. processDoc : function(port, topWindow, winId, index, content, title, url, baseURI, characterSet, canvasData, contextmenuTime, callbacks) {
  52. var that = this, docData;
  53. docData = new DocData(port, winId, index, content, baseURI, characterSet, canvasData);
  54. if (topWindow) {
  55. this.top = docData;
  56. this.title = title || "";
  57. this.url = url;
  58. }
  59. this.docs.push(docData);
  60. if (this.processFrame && contextmenuTime && (!this.contextmenuTime || contextmenuTime > this.contextmenuTime)) {
  61. this.contextmenuTime = contextmenuTime;
  62. this.frameDocData = docData;
  63. }
  64. if (this.config.processInBackground && docData.content) {
  65. docData.parseContent();
  66. docData.processDocCallback = singlefile.initProcess(docData.doc, docData.doc.documentElement, topWindow, baseURI, characterSet, this.config,
  67. canvasData, this.requestManager, function(maxIndex) {
  68. callbacks.init(that, docData, maxIndex);
  69. }, function(index, maxIndex) {
  70. callbacks.progress(that, docData, index);
  71. }, function() {
  72. callbacks.end(that, docData);
  73. });
  74. }
  75. },
  76. processDocFragment : function(docData, mutationEventId, content) {
  77. var doc = document.implementation.createHTMLDocument();
  78. doc.body.innerHTML = content;
  79. docData.processDocCallback = singlefile.initProcess(doc, doc.documentElement, this.top == docData, docData.baseURI, docData.characterSet,
  80. this.config, null, this.requestManager, function() {
  81. docData.processDocCallback();
  82. }, null, function() {
  83. docData.setDocFragment(doc.body.innerHTML, mutationEventId);
  84. });
  85. },
  86. setDocContent : function(docData, content, callback) {
  87. var selectedDocData, that = this;
  88. function buildPage(docData, setFrameContent, getContent, callback) {
  89. function setContent(docData) {
  90. var parent = docData.parent;
  91. if (parent)
  92. setFrameContent(docData, function() {
  93. parent.processedChildren++;
  94. if (parent.processedChildren == parent.childrenLength)
  95. getContent(parent, function() {
  96. setContent(parent);
  97. });
  98. });
  99. else if (callback)
  100. callback(docData);
  101. }
  102. if (docData.childrenLength)
  103. docData.children.forEach(function(data) {
  104. buildPage(data, setFrameContent, getContent, callback);
  105. });
  106. else
  107. setContent(docData);
  108. }
  109. function bgPageEnd(pageData, docData, callback) {
  110. var content = singlefile.util.getDocContent(docData.doc);
  111. if (pageData.config.displayProcessedPage)
  112. pageData.top.setContent(content);
  113. else
  114. callback(pageData.tabId, pageData.pageId, pageData.top, content);
  115. }
  116. if (content)
  117. docData.content = content;
  118. this.processedDocs++;
  119. if (this.processSelection)
  120. if (this.config.processInBackground)
  121. bgPageEnd(this, docData, callback);
  122. else
  123. docData.getContent(function() {
  124. that.top.setContent(docData.content);
  125. });
  126. else if (this.processedDocs == this.docs.length) {
  127. this.docs.forEach(function(docData) {
  128. var parentWinId = docData.winId.match(/((?:\d*\.?)*)\.\d*/);
  129. parentWinId = parentWinId ? parentWinId[1] : null;
  130. if (parentWinId)
  131. that.docs.forEach(function(data) {
  132. if (data.winId && data.winId == parentWinId)
  133. docData.parent = data;
  134. });
  135. if (docData.parent)
  136. docData.parent.setChild(docData);
  137. });
  138. if (this.frameDocData) {
  139. selectedDocData = this.frameDocData;
  140. selectedDocData.parent = null;
  141. } else
  142. selectedDocData = this.top;
  143. if (this.config.processInBackground)
  144. buildPage(selectedDocData, function(docData, callback) {
  145. var content = encodeURI(singlefile.util.getDocContent(docData.doc)), maxFrameSize = that.config.maxFrameSize;
  146. if (maxFrameSize > 0 && content.length > maxFrameSize * 1024 * 1024)
  147. content = "";
  148. docData.parent.docFrames[docData.index].setAttribute("src", "data:text/html;charset=utf-8," + content);
  149. delete docData.doc;
  150. callback();
  151. }, function(docData, callback) {
  152. callback();
  153. }, function(docData) {
  154. bgPageEnd(that, docData, callback);
  155. });
  156. else
  157. buildPage(this.top, function(docData, callback) {
  158. docData.parent.setFrameContent(docData, callback);
  159. }, function(docData, callback) {
  160. docData.getContent(callback);
  161. }, function(docData) {
  162. docData.setContent();
  163. });
  164. }
  165. },
  166. computeProgress : function() {
  167. var that = this;
  168. this.progressIndex = 0;
  169. this.progressMax = 0;
  170. this.docs.forEach(function(docData) {
  171. that.progressIndex += docData.progressIndex || 0;
  172. that.progressMax += docData.progressMax || 0;
  173. });
  174. },
  175. getResourceContentRequest : function(url, requestId, winId, characterSet, mediaTypeParam, docData) {
  176. this.requestManager.send(url, function(content) {
  177. docData.getResourceContentResponse(content, requestId);
  178. }, characterSet, mediaTypeParam);
  179. },
  180. getDocData : function(winId) {
  181. var found;
  182. this.docs.forEach(function(docData) {
  183. if (docData.winId == winId)
  184. found = docData;
  185. });
  186. return found;
  187. }
  188. };
  189. function DocData(port, winId, index, content, baseURI, characterSet, canvasData) {
  190. this.port = port;
  191. this.content = content;
  192. this.baseURI = baseURI;
  193. this.characterSet = characterSet;
  194. this.canvasData = canvasData;
  195. this.winId = winId;
  196. this.index = index;
  197. this.children = [];
  198. this.doc = null;
  199. this.docFrames = null;
  200. this.processDocCallback = null;
  201. this.getContentCallback = null;
  202. this.setFrameContentCallback = null;
  203. this.processedChildren = 0;
  204. this.childrenLength = 0;
  205. }
  206. DocData.prototype = {
  207. parseContent : function() {
  208. var doc = document.implementation.createHTMLDocument();
  209. doc.open();
  210. doc.write(this.content);
  211. doc.close();
  212. this.doc = doc;
  213. this.docFrames = doc.querySelectorAll("iframe, frame");
  214. delete this.content;
  215. },
  216. setChild : function(childDoc) {
  217. this.children[childDoc.index] = childDoc;
  218. this.childrenLength++;
  219. },
  220. process : function() {
  221. this.port.postMessage({
  222. processDoc : true,
  223. winId : this.winId
  224. });
  225. },
  226. setDocFragment : function(content, mutationEventId) {
  227. this.port.postMessage({
  228. setDocFragment : true,
  229. content : content,
  230. mutationEventId : mutationEventId
  231. });
  232. },
  233. getResourceContentResponse : function(content, requestId) {
  234. this.port.postMessage({
  235. getResourceContentResponse : true,
  236. requestId : requestId,
  237. winId : this.winId,
  238. content : content
  239. });
  240. },
  241. setContent : function(content) {
  242. this.port.postMessage({
  243. setContentRequest : true,
  244. content : content,
  245. winProperties : singlefile.winProperties
  246. });
  247. },
  248. getContent : function(callback) {
  249. this.getContentCallback = callback;
  250. this.port.postMessage({
  251. getContentRequest : true,
  252. winId : this.winId
  253. });
  254. },
  255. setFrameContent : function(docData, callback) {
  256. docData.setFrameContentCallback = callback;
  257. this.port.postMessage({
  258. setFrameContentRequest : true,
  259. winId : this.winId,
  260. index : docData.index,
  261. content : docData.content
  262. });
  263. }
  264. };
  265. (function() {
  266. var property, winProperties = {};
  267. for (property in window)
  268. winProperties[property] = true;
  269. singlefile.winProperties = winProperties;
  270. })();
  271. })();