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

  1. function G_TabbedBrowserWatcher(tabBrowser, name, opt_filterAboutBlank) {
  2. this.debugZone = "tabbedbrowserwatcher";
  3. this.tabBrowser_ = tabBrowser;
  4. this.filterAboutBlank_ = !!opt_filterAboutBlank;
  5. this.events = G_TabbedBrowserWatcher.events;      // Convenience pointer
  6. G_Assert(this, typeof name == "string" && !!name,
  7. "Need a probabilistically unique name");
  8. this.name_ = name;
  9. this.mark_ = G_TabbedBrowserWatcher.mark_ + "-" + this.name_;
  10. this.registrar_ = new EventRegistrar(G_TabbedBrowserWatcher.events);
  11. this.tabbox_ = this.getTabBrowser().mTabBox;
  12. this.onDOMContentLoadedClosure_ = BindToObject(this.onDOMContentLoaded, this)
  13. this.tabbox_.addEventListener("DOMContentLoaded",
  14. this.onDOMContentLoadedClosure_, true);
  15. this.onDOMNodeInsertedClosure_ = BindToObject(this.onDOMNodeInserted, this);
  16. this.tabbox_.addEventListener("DOMNodeInserted",
  17. this.onDOMNodeInsertedClosure_, true);
  18. this.onTabSwitchClosure_ = BindToObject(this.onTabSwitch, this);
  19. this.tabbox_.addEventListener("select",
  20. this.onTabSwitchClosure_, true);
  21. var win = this.tabbox_.ownerDocument.defaultView;
  22. this.onChromeUnloadClosure_ = BindToObject(this.onChromeUnload_, this);
  23. win.addEventListener('unload', this.onChromeUnloadClosure_, false);
  24. this.lastTab_ = this.getCurrentBrowser();
  25. this.detectNewTabs_();
  26. }
  27. G_TabbedBrowserWatcher.events = {
  28. DOMCONTENTLOADED: "domcontentloaded",
  29. LOCATIONCHANGE: "locationchange",
  30. PAGESHOW: "pageshow",
  31. PAGEHIDE: "pagehide",
  32. LOAD: "load",
  33. UNLOAD: "unload",
  34. TABLOAD: "tabload",
  35. TABUNLOAD: "tabunload",
  36. TABSWITCH: "tabswitch",
  37. TABMOVE: "tabmove",
  38. };
  39. G_TabbedBrowserWatcher.mark_ = "watcher-marked";
  40. G_TabbedBrowserWatcher.prototype.onChromeUnload_ = function(event) {
  41. G_Debug(this, "Removing event listeners");
  42. if (this.tabbox_) {
  43. this.tabbox_.removeEventListener("DOMContentLoaded",
  44. this.onDOMContentLoadedClosure_, true);
  45. this.tabbox_.removeEventListener("DOMNodeInserted",
  46. this.onDOMNodeInsertedClosure_, true);
  47. this.tabbox_.removeEventListener("select",
  48. this.onTabSwitchClosure_, true);
  49. var win = this.tabbox_.ownerDocument.defaultView;
  50. win.removeEventListener('unload', this.onChromeUnloadClosure_, false);
  51. this.tabbox_ = null;
  52. }
  53. if (this.lastTab_) {
  54. this.lastTab_ = null;
  55. }
  56. if (this.tabBrowser_) {
  57. this.tabBrowser_ = null;
  58. }
  59. }
  60. G_TabbedBrowserWatcher.prototype.isInstrumented_ = function(browser) {
  61. return !!browser[this.mark_];
  62. }
  63. G_TabbedBrowserWatcher.prototype.instrumentBrowser_ = function(browser) {
  64. G_Assert(this, !this.isInstrumented_(browser),
  65. "Browser already instrumented!");
  66. new G_BrowserWatcher(this, browser);
  67. browser[this.mark_] = true;
  68. }
  69. G_TabbedBrowserWatcher.prototype.detectNewTabs_ = function() {
  70. var tb = this.getTabBrowser();
  71. for (var i = 0; i < tb.browsers.length; ++i)
  72. this.maybeFireTabLoad(tb.browsers[i]);
  73. }
  74. G_TabbedBrowserWatcher.prototype.registerListener = function(eventType,
  75. listener) {
  76. this.registrar_.registerListener(eventType, listener);
  77. }
  78. G_TabbedBrowserWatcher.prototype.removeListener = function(eventType,
  79. listener) {
  80. this.registrar_.removeListener(eventType, listener);
  81. }
  82. G_TabbedBrowserWatcher.prototype.fire = function(eventType, e) {
  83. this.registrar_.fire(eventType, e);
  84. }
  85. G_TabbedBrowserWatcher.prototype.fireDocEvent_ = function(eventType,
  86. doc,
  87. browser) {
  88. if (!this.tabBrowser_) {
  89. G_Debug(this, "Firing event after shutdown: " + eventType);
  90. return;
  91. }
  92. try {
  93. var isTop = (doc == browser.contentDocument);
  94. } catch(e) {
  95. var isTop = undefined;
  96. }
  97. var inSelected = (browser == this.getCurrentBrowser());
  98. var location = doc ? doc.location.href : undefined;
  99. if (!this.filterAboutBlank_ || location != "about:blank") {
  100. G_Debug(this, "firing " + eventType + " for " + location +
  101. (isTop ? " (isTop)" : "") + (inSelected ? " (inSelected)" : ""));
  102. this.fire(eventType, { "doc": doc,
  103. "isTop": isTop,
  104. "inSelected": inSelected,
  105. "browser": browser});
  106. }
  107. }
  108. G_TabbedBrowserWatcher.prototype.maybeFireTabLoad = function(browser) {
  109. if (!this.isInstrumented_(browser)) {            // Is it a new browser?
  110. this.instrumentBrowser_(browser);              // Add a G_BrowserWatcher
  111. G_Debug(this, "firing tabload");
  112. this.fire(this.events.TABLOAD, { "browser": browser });
  113. }
  114. }
  115. G_TabbedBrowserWatcher.prototype.onDOMContentLoaded = function(e) {
  116. G_Debug(this, "onDOMContentLoaded for a " + e.target);
  117. var doc = e.target;
  118. var browser = this.getBrowserFromDocument(doc);
  119. if (!browser) {
  120. G_Debug(this, "domcontentloaded: no browser for " + doc.location.href);
  121. return;
  122. }
  123. this.maybeFireTabLoad(browser);
  124. G_Debug(this, "DOMContentLoaded broken for forward/back buttons.");
  125. this.fireDocEvent_(this.events.DOMCONTENTLOADED, doc, browser);
  126. }
  127. G_TabbedBrowserWatcher.prototype.onDOMNodeInserted = function(e) {
  128. G_Debug(this, "onDOMNodeInserted for a " + e.target +
  129. " related: " + e.relatedNode);
  130. if (e.target.localName != "tab") {
  131. return;
  132. }
  133. if (!isDef(e.target._tPos)) {
  134. return;
  135. }
  136. var fromPos = e.target._tPos;
  137. var toPos;
  138. for (var i = 0; i < e.relatedNode.childNodes.length; i++) {
  139. var child = e.relatedNode.childNodes[i];
  140. if (child == e.target) {
  141. toPos = i;
  142. break;
  143. }
  144. }
  145. G_Debug(this, "firing tabmove");
  146. this.fire(this.events.TABMOVE, { "tab": e.target,
  147. "fromIndex": fromPos,
  148. "toIndex": toPos } );
  149. }
  150. G_TabbedBrowserWatcher.prototype.onTabSwitch = function(e) {
  151. if (e.target == null ||
  152. (e.target.localName != "tabs" && e.target.localName != "tabpanels"))
  153. return;
  154. var fromBrowser = this.lastTab_;
  155. var toBrowser = this.getCurrentBrowser();
  156. if (fromBrowser != toBrowser) {
  157. this.lastTab_ = toBrowser;
  158. G_Debug(this, "firing tabswitch");
  159. this.fire(this.events.TABSWITCH, { "fromBrowser": fromBrowser,
  160. "toBrowser": toBrowser });
  161. }
  162. }
  163. G_TabbedBrowserWatcher.prototype.getTabBrowser = function() {
  164. return this.tabBrowser_;
  165. }
  166. G_TabbedBrowserWatcher.prototype.getCurrentBrowser = function() {
  167. return this.getTabBrowser().selectedBrowser;
  168. }
  169. G_TabbedBrowserWatcher.prototype.getCurrentWindow = function() {
  170. return this.getCurrentBrowser().contentWindow;
  171. }
  172. G_TabbedBrowserWatcher.prototype.getBrowserFromDocument = function(doc) {
  173. function docInWindow(doc, win) {
  174. if (win.document == doc)
  175. return true;
  176. if (win.frames)
  177. for (var i = 0; i < win.frames.length; i++)
  178. if (docInWindow(doc, win.frames[i]))
  179. return true;
  180. return false;
  181. }
  182. var browsers = this.getTabBrowser().browsers;
  183. for (var i = 0; i < browsers.length; i++)
  184. if (docInWindow(doc, browsers[i].contentWindow))
  185. return browsers[i];
  186. return null;
  187. }
  188. G_TabbedBrowserWatcher.prototype.getDocumentFromURL = function(url,
  189. opt_browser) {
  190. function docWithURL(win, url) {
  191. if (win.document.location.href == url)
  192. return win.document;
  193. if (win.frames)
  194. for (var i = 0; i < win.frames.length; i++) {
  195. var rv = docWithURL(win.frames[i], url);
  196. if (rv)
  197. return rv;
  198. }
  199. return null;
  200. }
  201. if (opt_browser)
  202. return docWithURL(opt_browser.contentWindow, url);
  203. var browsers = this.getTabBrowser().browsers;
  204. for (var i=0; i < browsers.length; i++) {
  205. var rv = docWithURL(browsers[i].contentWindow, url);
  206. if (rv)
  207. return rv;
  208. }
  209. return null;
  210. }
  211. G_TabbedBrowserWatcher.prototype.getDocumentsFromURL = function(url,
  212. opt_browser) {
  213. var docs = [];
  214. function getDocsWithURL(win, url) {
  215. if (win.document.location.href == url)
  216. docs.push(win.document);
  217. if (win.frames)
  218. for (var i = 0; i < win.frames.length; i++)
  219. getDocsWithURL(win.frames[i], url);
  220. }
  221. if (opt_browser)
  222. return getDocsWithURL(opt_browser.contentWindow, url);
  223. var browsers = this.getTabBrowser().browsers;
  224. for (var i=0; i < browsers.length; i++)
  225. getDocsWithURL(browsers[i].contentWindow, url);
  226. return docs;
  227. }
  228. G_TabbedBrowserWatcher.prototype.getBrowserFromWindow = function(sub) {
  229. function containsSubWindow(sub, win) {
  230. if (win == sub)
  231. return true;
  232. if (win.frames)
  233. for (var i=0; i < win.frames.length; i++)
  234. if (containsSubWindow(sub, win.frames[i]))
  235. return true;
  236. return false;
  237. }
  238. var browsers = this.getTabBrowser().browsers;
  239. for (var i=0; i < browsers.length; i++)
  240. if (containsSubWindow(sub, browsers[i].contentWindow))
  241. return browsers[i];
  242. return null;
  243. }
  244. G_TabbedBrowserWatcher.getTabElementFromBrowser = function(tabBrowser,
  245. browser) {
  246. for (var i=0; i < tabBrowser.browsers.length; i++)
  247. if (tabBrowser.browsers[i] == browser)
  248. return tabBrowser.mTabContainer.childNodes[i];
  249. return null;
  250. }
  251. if (G_GDEBUG) {
  252. G_debugService.loggifier.loggify(G_TabbedBrowserWatcher.prototype);
  253. }
  254. function G_BrowserWatcher(tabbedBrowserWatcher, browser) {
  255. this.debugZone = "browserwatcher";
  256. this.parent_ = tabbedBrowserWatcher;
  257. this.browser_ = browser;
  258. this.onPageShowClosure_ = BindToObject(this.onPageShow, this);
  259. this.browser_.addEventListener("pageshow", this.onPageShowClosure_, true);
  260. this.onPageHideClosure_ = BindToObject(this.onPageHide, this);
  261. this.browser_.addEventListener("pagehide", this.onPageHideClosure_, true);
  262. this.onLoadClosure_ = BindToObject(this.onLoad, this);
  263. this.browser_.addEventListener("load", this.onLoadClosure_, true);
  264. this.onUnloadClosure_ = BindToObject(this.onUnload, this);
  265. this.browser_.addEventListener("unload", this.onUnloadClosure_, true);
  266. this.webProgressListener_ = {
  267. QueryInterface: function() { return this; },
  268. onLocationChange: bind(this.onLocationChange, this),
  269. onStateChange: function(){},
  270. onStatusChange: function(){},
  271. onSecurityChange: function(){},
  272. onProgressChange: function(){}
  273. };
  274. G_Debug(this, "adding progress listener");
  275. this.browser_.addProgressListener(this.webProgressListener_,
  276. Ci.nsIWebProgress.NOTIFY_LOCATION);
  277. G_Debug(this, "Done");
  278. }
  279. G_BrowserWatcher.prototype.onLocationChange = function(webProgress,
  280. request, location) {
  281. G_Debug(this, "onLocationChange for {%s}".subs(location.spec));
  282. if (!this.parent_) {
  283. G_Debug(this, "onLocationChange after tab close");
  284. return;
  285. }
  286. var e = { browser: this.browser_,
  287. isTop: true };
  288. this.parent_.fire(this.parent_.events.LOCATIONCHANGE, e);
  289. }
  290. G_BrowserWatcher.prototype.onPageShow = function(e) {
  291. G_Debug(this, "onPageShow for " + ((e.target) ? (e.target) : ("undefined")));
  292. if (e.target && e.target.nodeName == "#document") {
  293. var doc = e.target;
  294. this.parent_.fireDocEvent_(this.parent_.events.PAGESHOW,
  295. doc,
  296. this.browser_);
  297. }
  298. }
  299. G_BrowserWatcher.prototype.onLoad = function(e) {
  300. G_Debug(this, "onLoad for a " + e.target);
  301. if (!e.target) {
  302. G_Debug(this, "e.target is null; canceling onload event");
  303. return;
  304. }
  305. if (e.target.nodeName != "#document")
  306. return;
  307. var doc = e.target;
  308. this.parent_.fireDocEvent_(this.parent_.events.LOAD, doc, this.browser_);
  309. }
  310. G_BrowserWatcher.prototype.onUnload = function(e) {
  311. G_Debug(this, "onUnload for " + ((e.target) ? (e.target) : ("undefined")));
  312. var doc = e.target;
  313. if (doc && doc.nodeName == "#document")
  314. this.parent_.fireDocEvent_("unload", doc, this.browser_);
  315. if (!doc) {                // This is a closing tab
  316. G_Debug(this, "firing tabunload for a " + this.browser_ + "(" +
  317. this.browser_.nodename + ")");
  318. this.parent_.fire(this.parent_.events.TABUNLOAD,
  319. { "browser": this.browser_ });
  320. this.browser_.removeEventListener("pageshow", this.onPageShowClosure_, true);
  321. this.browser_.removeEventListener("pagehide", this.onPageHideClosure_, true);
  322. this.browser_.removeEventListener("load", this.onLoadClosure_, true);
  323. this.browser_.removeEventListener("unload", this.onUnloadClosure_, true);
  324. this.parent_ = null;
  325. this.browser_ = null;
  326. G_Debug(this, "Removed event listeners");
  327. }
  328. }
  329. G_BrowserWatcher.prototype.onPageHide = function(e) {
  330. G_Debug(this, "onPageHide for a " + e.target + "(" +
  331. e.target.nodeName + ")");
  332. if (e.target.nodeName != "#document")   // Ignore non-documents
  333. return;
  334. var doc = e.target;
  335. this.parent_.fireDocEvent_(this.parent_.events.PAGEHIDE, doc, this.browser_);
  336. }
  337.