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