PageRenderTime 54ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/src/mailaccount.class.js

https://github.com/AndersSahlin/MailCheckerPlus
JavaScript | 707 lines | 616 code | 48 blank | 43 comment | 69 complexity | 1c6763e0d4c73711abff6565250df2ef MD5 | raw file
Possible License(s): GPL-3.0
  1. /// <reference path="chrome-api-vsdoc.js" />
  2. /// <reference path="jquery-1.4.2.js" />
  3. /// <reference path="encoder.js" />
  4. /*
  5. *********************************
  6. MailAccount class
  7. by Anders Sahlin a.k.a. destructoBOT (malakeen@gmail.com)
  8. for Mail Checker Plus for Google Mail�
  9. https://chrome.google.com/extensions/detail/gffjhibehnempbkeheiccaincokdjbfe
  10. *********************************
  11. */
  12. function MailAccount(settingsObj) {
  13. // Check global settings
  14. var pollInterval = localStorage["gc_poll"];
  15. var requestTimeout = 10000;
  16. var openInTab = (localStorage["gc_open_tabs"] != null && localStorage["gc_open_tabs"] == "true");
  17. var archiveAsRead = (localStorage["gc_archive_read"] != null && localStorage["gc_archive_read"] == "true");
  18. // var mailURL = (localStorage["gc_force_ssl"] != null && localStorage["gc_force_ssl"] == "true") ? "https://" : "http://";
  19. // Always use SSL, things become messy otherwise
  20. var mailURL = "https://mail.google.com";
  21. if (settingsObj.domain != null) {
  22. // This is a GAFYD account
  23. if (settingsObj.domain[0] === '/') {
  24. mailURL += settingsObj.domain;
  25. } else {
  26. mailURL += "/a/" + settingsObj.domain + "/";
  27. }
  28. } else if (settingsObj.accountNr != null) {
  29. // This is a Google account with multiple sessions activated
  30. mailURL += "/mail/u/" + settingsObj.accountNr + "/";
  31. } else {
  32. // Standard one-session Gmail account
  33. mailURL += "/mail/";
  34. }
  35. var inboxLabel = localStorage["gc_open_label"];
  36. var atomLabel = localStorage["gc_check_label"];
  37. var mailArray = new Array();
  38. var newestMail;
  39. var unreadCount = -1;
  40. var mailTitle;
  41. var mailAddress;
  42. var abortTimerId;
  43. var gmailAt = null;
  44. var errorLives = 5;
  45. var isStopped = false;
  46. var requestTimer;
  47. this.onUpdate;
  48. this.onError;
  49. this.isDefault;
  50. // Debug output (if enabled, might cause memory leaks)
  51. var verbose = false;
  52. // Without this/that, no internal calls to onUpdate or onError can be made...
  53. var that = this;
  54. function onGetInboxSuccess(data, callback) {
  55. var foundNewMail = false;
  56. var parser = new DOMParser();
  57. xmlDocument = $(parser.parseFromString(data, "text/xml"));
  58. var fullCount = xmlDocument.find('fullcount').text();
  59. mailTitle = $(xmlDocument.find('title')[0]).text().replace("Gmail - ", "");
  60. mailAddress = mailTitle.match(/([\S]+@[\S]+)/ig)[0];
  61. //newestMail = null;
  62. var newMailArray = new Array();
  63. if (fullCount < unreadCount || unreadCount == -1) {
  64. // Mail count has been reduced, so we need to reload all mail.
  65. // TODO: Find the old mail(s) and remove them instead.
  66. foundNewMail = true;
  67. mailArray = new Array();
  68. }
  69. // Parse xml data for each mail entry
  70. xmlDocument.find('entry').each(function () {
  71. var title = $(this).find('title').text();
  72. var shortTitle = title;
  73. var summary = $(this).find('summary').text();
  74. var issued = (new Date()).setISO8601($(this).find('issued').text());
  75. var link = $(this).find('link').attr('href');
  76. var id = link.replace(/.*message_id=(\d\w*).*/, "$1");
  77. var authorName = $(this).find('author').find('name').text();
  78. var authorMail = $(this).find('author').find('email').text();
  79. // Data checks
  80. if (authorName == null || authorName.length < 1)
  81. authorName = "(unknown sender)";
  82. if (title == null || title.length < 1) {
  83. shortTitle = title = "(No subject)";
  84. } else if (title.length > 63) {
  85. shortTitle = title.substr(0, 60) + "...";
  86. }
  87. // Encode content to prevent XSS attacks
  88. title = Encoder.XSSEncode(title, true);
  89. shortTitle = Encoder.XSSEncode(shortTitle, true);
  90. summary = Encoder.XSSEncode(summary, true);
  91. authorMail = Encoder.XSSEncode(authorMail, true);
  92. authorName = Encoder.XSSEncode(authorName, true);
  93. // Construct a new mail object
  94. var mailObject = {
  95. "id": id,
  96. "title": title,
  97. "shortTitle": shortTitle,
  98. "summary": summary,
  99. "link": link,
  100. "issued": issued,
  101. "authorName": authorName,
  102. "authorMail": authorMail
  103. };
  104. var isNewMail = true;
  105. $.each(mailArray, function (i, oldMail) {
  106. if (oldMail.id == mailObject.id)
  107. isNewMail = false; // This mail is not new
  108. });
  109. if (isNewMail) {
  110. foundNewMail = true;
  111. newMailArray.push(mailObject);
  112. }
  113. });
  114. // Sort new mail by date
  115. newMailArray.sort(function (a, b) {
  116. if (a.issued > b.issued)
  117. return -1;
  118. if (a.issued < b.issued)
  119. return 1;
  120. return 0;
  121. });
  122. // See if there is a new mail present
  123. if (newMailArray.length > 0) {
  124. newestMail = newMailArray[0];
  125. }
  126. // Insert new mail into mail array
  127. $.each(newMailArray, function (i, newMail) {
  128. mailArray.push(newMail);
  129. });
  130. // Sort all mail by date
  131. mailArray.sort(function (a, b) {
  132. if (a.issued > b.issued)
  133. return -1;
  134. if (a.issued < b.issued)
  135. return 1;
  136. return 0;
  137. });
  138. // We've found new mail, alert others!
  139. if (foundNewMail) {
  140. handleSuccess(fullCount);
  141. } else {
  142. logToConsole(mailURL + "feed/atom/" + atomLabel + " - No new mail found.");
  143. }
  144. if (callback != null) {
  145. window.setTimeout(callback, 0);
  146. }
  147. }
  148. // Handles a successful getInboxCount call and schedules a new one
  149. function handleSuccess(count) {
  150. logToConsole("success!");
  151. window.clearTimeout(abortTimerId);
  152. errorLives = 5;
  153. updateUnreadCount(count);
  154. //scheduleRequest();
  155. }
  156. // Handles a unsuccessful getInboxCount call and schedules a new one
  157. function handleError(xhr, text, err) {
  158. logToConsole("error! " + xhr + " " + text + " " + err);
  159. window.clearTimeout(abortTimerId);
  160. if (errorLives > 0)
  161. errorLives--;
  162. if (errorLives == 0) {
  163. errorLives = -1;
  164. setLoggedOutState();
  165. }
  166. //scheduleRequest();
  167. }
  168. // Retreives inbox count and populates mail array
  169. function getInboxCount(callback) {
  170. try {
  171. logToConsole("requesting " + mailURL + "feed/atom/" + atomLabel);
  172. $.ajax({
  173. type: "GET",
  174. dataType: "text",
  175. url: mailURL + "feed/atom/" + atomLabel,
  176. timeout: requestTimeout,
  177. success: function (data) { onGetInboxSuccess(data, callback); },
  178. error: function (xhr, status, err) { handleError(xhr, status, err); }
  179. });
  180. if (gmailAt == null) {
  181. getAt();
  182. }
  183. } catch (e) {
  184. console.error("exception: " + e);
  185. handleError();
  186. }
  187. }
  188. // Schedules a new getInboxCount call
  189. function scheduleRequest(interval) {
  190. if (isStopped) {
  191. return;
  192. }
  193. logToConsole("scheduling new request");
  194. if (interval != null) {
  195. window.setTimeout(getInboxCount, interval);
  196. } else {
  197. requestTimer = window.setTimeout(getInboxCount, pollInterval);
  198. window.setTimeout(scheduleRequest, pollInterval);
  199. }
  200. }
  201. // Updates unread count and calls onUpdate event
  202. function updateUnreadCount(count) {
  203. if (unreadCount != count) {
  204. unreadCount = count;
  205. logToConsole("unread count: " + unreadCount);
  206. if (that.onUpdate != null) {
  207. try {
  208. logToConsole("trying to call onUpdate...");
  209. that.onUpdate(that);
  210. }
  211. catch (e) {
  212. console.error(e);
  213. }
  214. }
  215. }
  216. }
  217. // Calls onError and resets data
  218. function setLoggedOutState() {
  219. if (that.onError != null) {
  220. try {
  221. logToConsole("trying to call onError...");
  222. that.onError(that);
  223. }
  224. catch (e) {
  225. console.error(e);
  226. }
  227. }
  228. unreadCount = -1;
  229. mailArray = new Array();
  230. }
  231. function logToConsole(text) {
  232. if (verbose)
  233. console.log(text);
  234. }
  235. // Send a POST action to Gmail
  236. function postAction(postObj) {
  237. if (gmailAt == null) {
  238. getAt(postAction, postObj);
  239. } else {
  240. var threadid = postObj.threadid;
  241. var action = postObj.action;
  242. var postURL = mailURL.replace("http:", "https:");
  243. postURL += "h/" + Math.ceil(1000000 * Math.random()) + "/";
  244. var postParams = "t=" + threadid + "&at=" + gmailAt + "&act=" + action;
  245. logToConsole(postURL);
  246. logToConsole(postParams);
  247. var postXHR = new XMLHttpRequest();
  248. postXHR.onreadystatechange = function () {
  249. if (this.readyState == 4 && this.status == 200) {
  250. // Post successful! Refresh once
  251. window.setTimeout(getInboxCount, 0);
  252. } else if (this.readyState == 4 && this.status == 401) {
  253. }
  254. }
  255. postXHR.onerror = function (error) {
  256. logToConsole("mark as read error: " + error);
  257. }
  258. postXHR.open("POST", postURL, true);
  259. postXHR.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
  260. postXHR.send(postParams);
  261. }
  262. }
  263. // Opens the basic HTML version of Gmail and fetches the Gmail_AT value needed for POST's
  264. function getAt(callback, tag) {
  265. var getURL = mailURL + "h/" + Math.ceil(1000000 * Math.random()) + "/?ui=html&zy=c";
  266. var gat_xhr = new XMLHttpRequest();
  267. gat_xhr.onreadystatechange = function () {
  268. if (this.readyState == 4 && this.status == 200) {
  269. //logToConsole(this.responseText);
  270. var matches = this.responseText.match(/\at=([^"]+)/);
  271. //logToConsole(matches);
  272. if (matches != null && matches.length > 0) {
  273. gmailAt = matches[1];
  274. //logToConsole(gmailAt);
  275. if (callback != null) {
  276. callback(tag);
  277. }
  278. }
  279. } else if (this.readyState == 4 && this.status == 401) {
  280. }
  281. }
  282. gat_xhr.onerror = function (error) {
  283. logToConsole("get gmail_at error: " + error);
  284. }
  285. gat_xhr.open("GET", getURL, true);
  286. gat_xhr.send(null);
  287. }
  288. /* Public methods */
  289. // Starts the scheduler
  290. this.startScheduler = function () {
  291. logToConsole("starting scheduler...");
  292. getInboxCount();
  293. scheduleRequest();
  294. }
  295. // Stops the scheduler
  296. this.stopScheduler = function () {
  297. logToConsole("stopping scheduler...");
  298. isStopped = true;
  299. if (requestTimer != null) {
  300. window.clearTimeout(requestTimer);
  301. }
  302. delete that;
  303. }
  304. // Opens the inbox
  305. this.openInbox = function () {
  306. // See if there is any Gmail tab open
  307. logToConsole('Opening inbox');
  308. chrome.windows.getAll({ populate: true }, function (windows) {
  309. for (var w in windows) {
  310. for (var i in windows[w].tabs) {
  311. var tab = windows[w].tabs[i];
  312. if (tab.url.indexOf(mailURL) >= 0) {
  313. chrome.tabs.update(tab.id, { selected: true });
  314. return;
  315. } else if (tab.url.indexOf(mailURL.replace("http:", "https:")) >= 0) {
  316. chrome.tabs.update(tab.id, { selected: true });
  317. return;
  318. } else if (tab.url.indexOf(mailURL.replace("https:", "http:")) >= 0) {
  319. chrome.tabs.update(tab.id, { selected: true });
  320. return;
  321. }
  322. }
  323. }
  324. chrome.tabs.create({ url: mailURL + inboxLabel });
  325. });
  326. }
  327. // // Opens unread label
  328. // this.openUnread = function () {
  329. // // See if there is any Gmail tab open
  330. // chrome.windows.getAll({ populate: true }, function (windows) {
  331. // for (var w in windows) {
  332. // for (var i in windows[w].tabs) {
  333. // var tab = windows[w].tabs[i];
  334. // if (tab.url.indexOf(mailURL) >= 0) {
  335. // chrome.tabs.update(tab.id, { selected: true });
  336. // return;
  337. // } else if (tab.url.indexOf(mailURL.replace("http:", "https:")) >= 0) {
  338. // chrome.tabs.update(tab.id, { selected: true });
  339. // return;
  340. // } else if (tab.url.indexOf(mailURL.replace("https:", "http:")) >= 0) {
  341. // chrome.tabs.update(tab.id, { selected: true });
  342. // return;
  343. // }
  344. // }
  345. // }
  346. // chrome.tabs.create({ url: mailURL + unreadLabel });
  347. // });
  348. // }
  349. // Opens a thread
  350. this.openThread = function (threadid) {
  351. if (threadid != null) {
  352. chrome.tabs.create({ url: mailURL + inboxLabel + "/" + threadid });
  353. postAction({ "threadid": threadid, "action": "rd" });
  354. scheduleRequest(1000);
  355. }
  356. }
  357. // Fetches content of thread
  358. this.getThread = function (accountid, threadid, callback) {
  359. if (threadid != null) {
  360. var getURL = mailURL.replace('http:', 'https:') + "h/" + Math.ceil(1000000 * Math.random()) + "/?v=pt&th=" + threadid;
  361. var gt_xhr = new XMLHttpRequest();
  362. gt_xhr.onreadystatechange = function () {
  363. if (this.readyState == 4 && this.status == 200) {
  364. // var markAsRead = (localStorage["gc_showfull_read"] != null && localStorage["gc_showfull_read"] == "true");
  365. // if(markAsRead)
  366. // that.readThread(threadid);
  367. var matches = this.responseText.match(/<hr>[\s\S]?<table[^>]*>([\s\S]*?)<\/table>(?=[\s\S]?<hr>)/gi);
  368. //var matches = matchRecursiveRegExp(this.responseText, "<div class=[\"]?msg[\"]?>", "</div>", "gi")
  369. //logToConsole(this.responseText);
  370. //logToConsole(matches[matches.length - 1]);
  371. //logToConsole(matches);
  372. if (matches != null && matches.length > 0) {
  373. var threadbody = matches[matches.length - 1];
  374. threadbody = threadbody.replace(/<tr>[\s\S]*?<tr>/, "");
  375. threadbody = threadbody.replace(/<td colspan="?2"?>[\s\S]*?<td colspan="?2"?>/, "");
  376. threadbody = threadbody.replace(/cellpadding="?12"?/g, "");
  377. threadbody = threadbody.replace(/font size="?-1"?/g, 'font');
  378. threadbody = threadbody.replace(/<hr>/g, "");
  379. threadbody = threadbody.replace(/(href="?)\/mail\//g, "$1" + mailURL);
  380. threadbody = threadbody.replace(/(src="?)\/mail\//g, "$1" + mailURL);
  381. //threadbody += "<span class=\"lowerright\">[<a href=\"javascript:showReply('" + threadid + "');\" title=\"Write quick reply\">reply</a>]&nbsp;[<a href=\"javascript:hideBody('" + threadid + "');\" title=\"Show summary\">less</a>]</span>";
  382. logToConsole(threadbody);
  383. if (callback != null) {
  384. callback(accountid, threadid, threadbody);
  385. }
  386. }
  387. } else if (this.readyState == 4 && this.status == 401) {
  388. }
  389. }
  390. gt_xhr.onerror = function (error) {
  391. logToConsole("get thread error: " + error);
  392. }
  393. gt_xhr.open("GET", getURL, true);
  394. gt_xhr.send(null);
  395. }
  396. }
  397. // Posts a reply to a thread
  398. this.replyToThread = function (replyObj) {
  399. if (gmailAt == null) {
  400. getAt(that.replyToThread, replyObj);
  401. } else {
  402. var threadid = replyObj.id;
  403. var reply = escape(replyObj.body);
  404. var callback = replyObj.callback;
  405. var postURL = mailURL + "h/" + Math.ceil(1000000 * Math.random()) + "/" + "?v=b&qrt=n&fv=cv&rm=12553ee9085c11ca&at=xn3j33xxbkqkoyej1zgstnt6zkxb1c&pv=cv&th=12553ee9085c11ca&cs=qfnq";
  406. var postParams = /*"v=b&qrt=n&fv=cv&rm=12553ee9085c11ca&at=xn3j33xxbkqkoyej1zgstnt6zkxb1c&pv=cv&th=12553ee9085c11ca&cs=qfnq" +
  407. "&th=" + threadid + "&at=" + gmailAt +*/"body=" + reply;
  408. logToConsole(postParams);
  409. var postXHR = new XMLHttpRequest();
  410. postXHR.onreadystatechange = function () {
  411. if (this.readyState == 4 && this.status == 200) {
  412. // Reply successful! Fire callback
  413. // callback();
  414. } else if (this.readyState == 4 && this.status == 401) {
  415. }
  416. }
  417. postXHR.onerror = function (error) {
  418. logToConsole("reply to thread error: " + error);
  419. }
  420. postXHR.open("POST", postURL, true);
  421. postXHR.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
  422. postXHR.send(postParams);
  423. }
  424. }
  425. // Marks a thread as read
  426. this.readThread = function (threadid) {
  427. if (threadid != null) {
  428. postAction({ "threadid": threadid, "action": "rd" });
  429. }
  430. }
  431. // Marks a thread as read
  432. this.unreadThread = function (threadid) {
  433. if (threadid != null) {
  434. postAction({ "threadid": threadid, "action": "ur" });
  435. }
  436. }
  437. // Archives a thread
  438. this.archiveThread = function (threadid) {
  439. if (threadid != null) {
  440. postAction({ "threadid": threadid, "action": "arch" });
  441. if (archiveAsRead) {
  442. postAction({ "threadid": threadid, "action": "rd" });
  443. }
  444. }
  445. }
  446. // Deletes a thread
  447. this.deleteThread = function (threadid) {
  448. if (threadid != null) {
  449. postAction({ "threadid": threadid, "action": "rd" });
  450. postAction({ "threadid": threadid, "action": "tr" });
  451. }
  452. }
  453. // Deletes a thread
  454. this.spamThread = function (threadid) {
  455. if (threadid != null) {
  456. postAction({ "threadid": threadid, "action": "sp" });
  457. }
  458. }
  459. // Stars a thread
  460. this.starThread = function (threadid) {
  461. if (threadid != null) {
  462. postAction({ "threadid": threadid, "action": "st" });
  463. }
  464. }
  465. // Retrieves unread count
  466. this.getUnreadCount = function () {
  467. return Number(unreadCount);
  468. }
  469. // Returns the "Gmail - Inbox for..." link
  470. this.getInboxLink = function () {
  471. if (mailTitle != null && mailTitle != "")
  472. return mailTitle;
  473. return mailURL;
  474. }
  475. // Returns the email address for the current account
  476. this.getAddress = function () {
  477. if (mailAddress != null && mailAddress != "")
  478. return mailAddress;
  479. return "(unknown account)";
  480. }
  481. // Returns the mail array
  482. this.getMail = function () {
  483. return mailArray;
  484. }
  485. // Returns the newest mail
  486. this.getNewestMail = function () {
  487. return newestMail;
  488. }
  489. // Opens the newest thread
  490. this.openNewestMail = function () {
  491. if (newestMail != null) {
  492. that.openThread(newestMail.id);
  493. }
  494. }
  495. // Reads the newest thread
  496. this.readNewestMail = function () {
  497. if (newestMail != null) {
  498. that.readThread(newestMail.id);
  499. }
  500. }
  501. // Spams the newest thread
  502. this.spamNewestMail = function () {
  503. if (newestMail != null) {
  504. that.spamThread(newestMail.id);
  505. }
  506. }
  507. // Deletes the newest thread
  508. this.deleteNewestMail = function () {
  509. if (newestMail != null) {
  510. that.deleteThread(newestMail.id);
  511. }
  512. }
  513. // Archive the newest thread
  514. this.archiveNewestMail = function () {
  515. if (newestMail != null) {
  516. that.archiveThread(newestMail.id);
  517. }
  518. }
  519. // Stars the newest thread
  520. this.starNewestMail = function () {
  521. if (newestMail != null) {
  522. that.starThread(newestMail.id);
  523. }
  524. }
  525. // Returns the mail URL
  526. this.getURL = function () {
  527. return mailURL;
  528. }
  529. this.getNewAt = function () {
  530. getAt();
  531. }
  532. // Refresh the unread items
  533. this.refreshInbox = function (callback) {
  534. getInboxCount(callback);
  535. }
  536. // Opens the Compose window
  537. this.composeNew = function () {
  538. if (openInTab) {
  539. chrome.tabs.create({ url: mailURL + "?view=cm&fs=1&tf=1" });
  540. } else {
  541. window.open(mailURL + "?view=cm&fs=1&tf=1", 'Compose new message', 'width=640,height=480');
  542. }
  543. }
  544. // Opens the Compose window and embeds the current page title and URL
  545. this.sendPage = function (tab) {
  546. var body = encodeURIComponent(unescape(tab.url));
  547. var subject = encodeURIComponent(unescape(tab.title));
  548. subject = subject.replace('%AB', '%2D'); // Special case: escape for %AB
  549. var urlToOpen = mailURL + "?view=cm&fs=1&tf=1" + "&su=" + subject + "&body=" + body;
  550. if (openInTab) {
  551. chrome.tabs.create({ url: urlToOpen });
  552. } else {
  553. window.open(urlToOpen, 'Compose new message', 'width=640,height=480');
  554. }
  555. }
  556. // Opens the Compose window with pre-filled data
  557. this.replyTo = function (mail) {
  558. //this.getThread(mail.id, replyToCallback);
  559. var to = encodeURIComponent(mail.authorMail); // Escape sender email
  560. var subject = Encoder.htmlDecode(mail.title); // Escape subject string
  561. subject = (subject.search(/^Re: /i) > -1) ? subject : "Re: " + subject; // Add 'Re: ' if not already there
  562. subject = encodeURIComponent(subject);
  563. // threadbody = encodeURIComponent(threadbody);
  564. var issued = mail.issued;
  565. var threadbody = "\r\n\r\n" + issued.toString() + " <" + mail.authorMail + ">:\r\n" + Encoder.htmlDecode(mail.summary);
  566. threadbody = encodeURIComponent(threadbody);
  567. var replyURL = mailURL.replace('http:', 'https:') + "?view=cm&tf=1&to=" + to + "&su=" + subject + "&body=" + threadbody;
  568. logToConsole(replyURL);
  569. if (openInTab) {
  570. chrome.tabs.create({ url: replyURL });
  571. } else {
  572. window.open(replyURL, 'Compose new message', 'width=640,height=480');
  573. //chrome.windows.create({url: replyURL});
  574. }
  575. }
  576. function replyToCallback(threadid, threadbody) {
  577. var mail;
  578. for (var i in mailArray) {
  579. if (mailArray[i].id == threadid) {
  580. mail = mailArray[i];
  581. break;
  582. }
  583. }
  584. if (mail == null)
  585. return;
  586. var to = encodeURIComponent(mail.authorMail); // Escape sender email
  587. var subject = mail.title; // Escape subject string
  588. subject = (subject.search(/^Re: /i) > -1) ? subject : "Re: " + subject; // Add 'Re: ' if not already there
  589. subject = encodeURIComponent(subject);
  590. threadbody = encodeURIComponent(threadbody);
  591. var replyURL = mailURL + "?view=cm&fs=1&tf=1&to=" + to + "&su=" + subject + "&body=" + mail.summary;
  592. if (openInTab) {
  593. chrome.tabs.create({ url: replyURL });
  594. } else {
  595. window.open(replyURL, 'Compose new message', 'width=640,height=480');
  596. //chrome.windows.create({url: replyURL});
  597. }
  598. }
  599. // No idea, actually...
  600. function NSResolver(prefix) {
  601. if (prefix == 'gmail') {
  602. return 'http://purl.org/atom/ns#';
  603. }
  604. }
  605. // Called when the user updates a tab
  606. chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
  607. if (changeInfo.status == 'loading' && (tab.url.indexOf(mailURL) == 0 || tab.url.indexOf(mailURL.replace("http:", "https:")) == 0 || tab.url.indexOf(mailURL.replace("https:", "http:")) == 0)) {
  608. logToConsole("saw gmail! updating...");
  609. window.setTimeout(getInboxCount, 0);
  610. }
  611. });
  612. }