home *** CD-ROM | disk | FTP | other *** search
/ Minami 83 / MINAMI83.iso / Extra / DivXInstaller.exe / $PLUGINSDIR / GoogleToolbarFirefox.msi / xpi / amulet-jslib / content-analyzer.js < prev    next >
Text File  |  2006-08-07  |  11KB  |  326 lines

  1. function PROT_ContentAnalyzer(listWarden, threadQueue, opt_testing) {
  2. this.listWarden_ = listWarden;
  3. this.threadQueue_ = threadQueue;
  4. this.testing_ = !!opt_testing;
  5. this.debugZone = "contentanalyzer";
  6. this.docs_ = [];
  7. this.time_ = PROT_ContentAnalyzer.MIN_TIME;
  8. this.numNodes_ = PROT_ContentAnalyzer.MIN_NODES;
  9. this.reportURL = PROT_globalStore.getResultsReportURL();
  10. this.urlCrypto_ = null;
  11. this.useCrypto_ = !this.testing_;
  12. this.prefs_ = new G_Preferences();
  13. var contentAnalyzerEnabledPrefName =
  14. PROT_globalStore.getContentAnalyzerEnabledPrefName();
  15. var contentAnalyzerPrefObserver = BindToObject(this.onPrefChanged,
  16. this);
  17. this.prefs_.addObserver(contentAnalyzerEnabledPrefName,
  18. contentAnalyzerPrefObserver);
  19. this.isEnabled_ = false;
  20. this.onPrefChanged(contentAnalyzerEnabledPrefName);
  21. G_Debug(this, "content analyzer initialized");
  22. }
  23. PROT_ContentAnalyzer.MAX_DOCS = 3;
  24. PROT_ContentAnalyzer.MAX_TIME = 60*1000;
  25. PROT_ContentAnalyzer.MAX_NODES = 500;
  26. PROT_ContentAnalyzer.prototype.onPrefChanged = function(prefName) {
  27. this.isEnabled_ = this.prefs_.getPref(prefName, false);
  28. var compatibleVersion = (new G_ThisFirefoxVersion()).
  29. compareToString("1.5.0.2");
  30. if (compatibleVersion < 0)
  31. this.isEnabled_ = false;
  32. this.maybeToggleDoWork();
  33. }
  34. PROT_ContentAnalyzer.prototype.maybeToggleDoWork = function() {
  35. if (this.isEnabled_ === true) {
  36. this.iterator_ = new PROT_SafeDOMIterator(this.listWarden_,
  37. this,
  38. this.threadQueue_);
  39. this.alarm_ = new G_Alarm(BindToObject(this.doWork, this),
  40. 1000,
  41. true /* repeating */);
  42. } else if (this.isEnabled_ === false) {
  43. if (this.alarm_) {
  44. this.alarm_.cancel();
  45. this.alarm_ = null;
  46. }
  47. if (this.iterator_) {
  48. this.iterator_.shutdown();
  49. this.iterator_ = null;
  50. }
  51. }
  52. }
  53. PROT_ContentAnalyzer.prototype.maybeAnalyzeDoc = function(doc) {
  54. if (!this.isEnabled_ || !doc || !doc.URL)
  55. return;
  56. this.listWarden_.isWhiteURL(doc.URL,
  57. BindToObject(this.maybeAnalyzeDoc_,
  58. this, doc));
  59. }
  60. PROT_ContentAnalyzer.prototype.maybeAnalyzeDoc_ = function(doc, status) {
  61. if (PROT_ListWarden.IN_WHITELIST == status)
  62. return;
  63. G_Debug(this, "Not in whitelist: " + doc.URL);
  64. if (this.docs_.length < PROT_ContentAnalyzer.MAX_DOCS) {
  65. this.docs_.push(doc);
  66. G_Debug(this, "pushing " + doc.URL.slice(-50));
  67. this.numDrops_ = 0;
  68. } else {
  69. G_Debug(this, this.docs_.length + " docs on queue, skipping " + doc.URL.slice(-50));
  70. this.numDrops_++;
  71. if (this.numDrops_ >= 2) {
  72. G_Debug(this, "too many drops, aborting");
  73. this.iterator_.abort();
  74. }
  75. }
  76. }
  77. PROT_ContentAnalyzer.prototype.doWork = function() {
  78. if (!this.isEnabled_)
  79. return;
  80. if (this.docs_.length > 0 && this.iterator_.isReady()) {
  81. this.iterator_.start(this.docs_[0],
  82. PROT_ContentAnalyzer.MAX_TIME,
  83. PROT_ContentAnalyzer.MAX_NODES);
  84. }
  85. }
  86. PROT_ContentAnalyzer.prototype.reportResults = function(doc, results) {
  87. if (!this.urlCrypto_)
  88. this.urlCrypto_ = new PROT_UrlCrypto();
  89. var reportURL = this.reportURL;
  90. var params = {"url": doc.URL, "results": results};
  91. if (this.useCrypto_) {
  92. params = this.urlCrypto_.maybeCryptParams(params);
  93. }
  94. for (var param in params) {
  95. reportURL += param + "=" +
  96. encodeURIComponent(params[param]) + "&";
  97. }
  98. G_Debug(this, "reportURL: " + reportURL);
  99. if (this.prefs_.getPref(PROT_globalStore.getSendUserReportsPrefName(),
  100. false))
  101. (new PROT_XMLFetcher(true /* strip cookies */)).get(reportURL, null /* no cb */);
  102. }
  103. PROT_ContentAnalyzer.prototype.docIsComplete = function(doc, results) {
  104. if (!this.testing_ && results != "") {
  105. this.reportResults(doc, results);
  106. }
  107. if (results == "")
  108. G_Debug(this, "empty results for " + doc.URL.slice(-50));
  109. else
  110. G_Debug(this, "sandbox results for " + doc.URL + ": " + results);
  111. this.docs_.shift();
  112. }
  113. function PROT_SafeDOMIterator(listWarden, contentAnalyzer, threadQueue) {
  114. this.contentAnalyzer_ = contentAnalyzer;
  115. this.threadQueue_ = threadQueue;
  116. this.debugZone = "domiterator";
  117. this.registrar_ = new EventRegistrar(["abort", "reset", "results", "meta"]);
  118. this.attrs = {};
  119. this.status_ = PROT_SafeDOMIterator.states.READY;
  120. this.sandboxMgr_ = new PROT_SandboxManager(this,
  121. listWarden,
  122. "goog-sandbox-text");
  123. }
  124. PROT_SafeDOMIterator.prototype.shutdown = function() {
  125. this.sandboxMgr_.shutdown();
  126. }
  127. PROT_SafeDOMIterator.whatToShow = Ci.nsIDOMNodeFilter.SHOW_ELEMENT |
  128. Ci.nsIDOMNodeFilter.SHOW_TEXT;
  129. PROT_SafeDOMIterator.CHUNK_SIZE = 10;
  130. PROT_SafeDOMIterator.states = { WORKING: "working",
  131. READY: "ready",
  132. ABORT: "abort"}
  133. PROT_SafeDOMIterator.MULTIPLIER = 2.5;
  134. PROT_SafeDOMIterator.prototype.start = function(doc, maxTime, maxNodes) {
  135. if (!doc || !this.isReady()) {
  136. G_Debug(this, "is ready: " + this.isReady());
  137. return;
  138. }
  139. this.doc_ = doc;
  140. this.maxTime_ = maxTime;
  141. this.maxNodes_ = maxNodes;
  142. this.fire("reset", {});
  143. this.fire("meta", { url: doc.URL,
  144. title: doc.title,
  145. referrer: doc.referrer,
  146. callback: BindToObject(this.maybeStartWalk, this) });
  147. }
  148. PROT_SafeDOMIterator.prototype.maybeStartWalk = function(shouldWalk) {
  149. if (!shouldWalk) {
  150. this.status_ = PROT_SafeDOMIterator.states.READY;
  151. G_Debug(this, "sandbox not interested, ignoring " + this.doc_.URL.slice(-50));
  152. this.contentAnalyzer_.docIsComplete(this.doc_, "");
  153. return;
  154. }
  155. this.status_ = PROT_SafeDOMIterator.states.WORKING;
  156. this.iter_ = this.doc_.createTreeWalker(this.doc_.documentElement,
  157. PROT_SafeDOMIterator.whatToShow,
  158. null, /* no NodeFilter */
  159. true /* expand entities */);
  160. new G_Alarm(BindToObject(this.abort, this), this.maxTime_);
  161. this.alarm_ = new G_ConditionalAlarm(BindToObject(this.maybeAbort, this),
  162. 1*1000 /* period in ms */,
  163. true /* repeating */);
  164. this.targetNodes_ =
  165. PROT_SafeDOMIterator.CHUNK_SIZE*PROT_SafeDOMIterator.MULTIPLIER;
  166. this.numNodes_ = 0;
  167. this.threadQueue_.addWorker(BindToObject(this.walkDOM, this),
  168. BindToObject(this.finishIfComplete, this));
  169. this.threadQueue_.run();
  170. }
  171. PROT_SafeDOMIterator.prototype.maybeAbort = function() {
  172. if (this.numNodes_ < this.targetNodes_ ||
  173. !this.iter_.currentNode ||
  174. this.numNodes_ >= this.maxNodes_) {
  175. this.abort();
  176. return true;
  177. }
  178. this.targetNodes_ = this.numNodes_ +
  179. PROT_SafeDOMIterator.CHUNK_SIZE*PROT_SafeDOMIterator.MULTIPLIER;
  180. G_Debug(this, "current nodes: " + this.numNodes_ + " target nodes: " +
  181. this.targetNodes_);
  182. return false;
  183. }
  184. PROT_SafeDOMIterator.prototype.extractFeatures = function(n) {
  185. if (!(this.attrs.hasOwnProperty(n.nodeName)))
  186. return;
  187. var attrs = this.attrs[n.nodeName];
  188. var values = {};
  189. var MAX_LEN = 1024; // Never pass more than 1K to the sandbox
  190. values.nodeName = n.nodeName;
  191. for (var i = 0; i < attrs.length; i++) {
  192. if (attrs[i] == "nodeValue" && n.nodeName == "#text") {
  193. values[attrs[i]] = n[attrs[i]].toString().substring(0, MAX_LEN);
  194. } else if (n.getAttribute(attrs[i])) {
  195. values[attrs[i]] = n.getAttribute(attrs[i]).substring(0, MAX_LEN);
  196. } else {
  197. values[attrs[i]] = "undefined";
  198. }
  199. }
  200. return values;
  201. }
  202. PROT_SafeDOMIterator.prototype.union = function(attrs1, attrs2) {
  203. var newattrs = attrs1.concat(attrs2);
  204. newattrs = newattrs.sort();
  205. for (var i = newattrs.length-1; i >= 1; i--) {
  206. if (newattrs[i] == newattrs[i-1] || !newattrs[i])
  207. newattrs.splice(i, 1);
  208. }
  209. return newattrs;
  210. }
  211. PROT_SafeDOMIterator.prototype.registerEvent = function(eventType, attrs) {
  212. if (!this.registrar_.isKnownEventType(eventType)) {
  213. this.registrar_.addEventType(eventType);
  214. }
  215. if (!this.attrs[eventType])
  216. this.attrs[eventType] = [];
  217. this.attrs[eventType] = this.union(this.attrs[eventType], attrs);
  218. }
  219. PROT_SafeDOMIterator.prototype.registerHandler = function(nodeName,
  220. handler,
  221. attrs) {
  222. this.registrar_.registerListener(nodeName, handler);
  223. this.registerEvent(nodeName, attrs);
  224. }
  225. PROT_SafeDOMIterator.prototype.removeHandlers = function() {
  226. this.registrar_ = new EventRegistrar(["abort", "reset", "results", "meta"]);
  227. }
  228. PROT_SafeDOMIterator.prototype.fire = function(eventType, e) {
  229. this.registrar_.fire(eventType, e);
  230. }
  231. PROT_SafeDOMIterator.prototype.walkDOM = function() {
  232. for (var i = 0; i < PROT_SafeDOMIterator.CHUNK_SIZE; i++) {
  233. var n = this.iter_.nextNode();
  234. if (!n)
  235. return;
  236. if (!(this.attrs.hasOwnProperty(n.nodeName))) {
  237. continue;
  238. }
  239. var event = this.extractFeatures(n);
  240. event.callback = BindToObject(this.maybeSetAbort, this);
  241. this.fire(n.nodeName, event);
  242. }
  243. this.numNodes_ += PROT_SafeDOMIterator.CHUNK_SIZE;
  244. G_Debug(this, "curr number nodes: " + this.numNodes_);
  245. }
  246. PROT_SafeDOMIterator.prototype.finishIfComplete = function() {
  247. if (this.shouldAbort() || this.numNodes_ >= this.maxNodes_) {
  248. G_Debug(this, "done. aborting: " + this.shouldAbort());
  249. this.fire("results", { callback: BindToObject(this.getResults, this) });
  250. return true;
  251. }
  252. G_Debug(this, "not done yet");
  253. return false;
  254. }
  255. PROT_SafeDOMIterator.prototype.isReady = function() {
  256. return this.status_ == PROT_SafeDOMIterator.states.READY &&
  257. this.sandboxMgr_.hasData();
  258. }
  259. PROT_SafeDOMIterator.prototype.abort = function() {
  260. if (this.status_ == PROT_SafeDOMIterator.states.WORKING) {
  261. G_Debug(this, "aborting");
  262. this.status_ = PROT_SafeDOMIterator.states.ABORT;
  263. this.alarm_.cancel();
  264. this.alarm_ = null;
  265. } else {
  266. }
  267. }
  268. PROT_SafeDOMIterator.prototype.shouldAbort = function() {
  269. return this.status_ == PROT_SafeDOMIterator.states.ABORT;
  270. }
  271. PROT_SafeDOMIterator.prototype.maybeSetAbort = function(should_abort) {
  272. if (should_abort && !this.isReady()) {
  273. this.status_ = PROT_SafeDOMIterator.states.ABORT;
  274. }
  275. }
  276. PROT_SafeDOMIterator.prototype.getResults = function(results) {
  277. this.status_ = PROT_SafeDOMIterator.states.READY;
  278. if (typeof results != "string") {
  279. G_Debug(this, "sandbox returned wrong type for results: " + typeof
  280. results);
  281. } else {
  282. this.contentAnalyzer_.docIsComplete(this.doc_, results);
  283. }
  284. }
  285. var TEST_PROT_ContentAnalyzer = function(doc, listWarden) {
  286. var z = "contentanalyzer UNITTEST";
  287. G_debugService.enableZone(z);
  288. G_Debug(z, "Starting");
  289. var contentAnalyzer = new PROT_ContentAnalyzer(listWarden,
  290. new TH_ThreadQueue(),
  291. true /* testing */);
  292. var createDocFromString = function(doc, s, opt_id) {
  293. var iframe = doc.createElement("iframe");
  294. doc.documentElement.appendChild(iframe);
  295. iframe.setAttribute('id', opt_id);
  296. iframe.style.maxHeight = '0px';
  297. iframe.style.minHeight = '0px !important';
  298. var innerdoc = iframe.contentDocument;
  299. innerdoc.write(s);
  300. function docNClosure(doc, closure) {
  301. this.doc = doc;
  302. this.closure = closure;
  303. }
  304. function close() {
  305. doc.documentElement.removeChild(iframe);
  306. }
  307. return new docNClosure(innerdoc, close);
  308. }
  309. var iframeHtml = "<h1>Ebay affiliate</h1>";
  310. iframeHtml += "<img src=http://pics.ebaystatic.com/aw/pics/logos/logoEbay_150x70.gif>";
  311. iframeHtml += "<a href=http://ourpaypal.com>paypal.com</a>";
  312. iframeHtml += "<a href=http://paypal.com/privacy.html>Privacy policy</a>";
  313. iframeHtml += "<a href=http://somewhere.com>Not a juicy link</a>";
  314. iframeHtml += "<img src=http://somewhere_else.com>";
  315. iframeHtml += "<b><form action=\"/bad\" method=\"post\"><input type=\"text\" name=\"cc\">your credit card here</form>";
  316. var docNClosure = createDocFromString(doc,
  317. iframeHtml,
  318. 'unittestiframe');
  319. new G_Alarm(BindToObject(contentAnalyzer.maybeAnalyzeDoc,
  320. contentAnalyzer,
  321. docNClosure.doc),
  322. 5000);
  323. new G_Alarm(docNClosure.closure, 10*1000);
  324. new G_Alarm(function() { G_Debug(z, "Passed"); }, 15*1000);
  325. }
  326.