home *** CD-ROM | disk | FTP | other *** search
/ Chip 2011 November / CHIP_2011_11.iso / Programy / Narzedzia / AIMP2 / aimp_2.61.583.exe / $TEMP / YandexPackSetup.msi / fil7E8B1D5B55761F0C097FFD1EAAA47942 < prev    next >
Text File  |  2010-07-12  |  21KB  |  753 lines

  1. var gYaFTab = {
  2.   _compatibilityMode: null,
  3.   
  4.   get compatibilityMode() {
  5.     if (this._compatibilityMode === null) {
  6.       // ftab.compatibility pref:
  7.       //   0 - always false
  8.       //   1 - depends (default)
  9.       //   2 - always true
  10.       let compatibilityMode = gYaSearchService.getIntPref("yasearch.general.ftab.compatibility");
  11.       
  12.       switch (compatibilityMode) {
  13.         case 1:
  14.           const COMPATIBILITY_LIST = ["{c45c406e-ab73-11d8-be73-000a95be3b12}",//webdeveloper
  15.                                       "{dc572301-7619-498c-a57d-39143191b318}"//tmp
  16.                                      ];
  17.           
  18.           const ExtensionManager = Cc["@mozilla.org/extensions/manager;1"].getService(Ci.nsIExtensionManager);
  19.           const PREFIX_ITEM_URI = "urn:mozilla:item:";
  20.           const PREFIX_NS_EM = "http://www.mozilla.org/2004/em-rdf#";
  21.           const RdfService = Cc["@mozilla.org/rdf/rdf-service;1"].getService(Ci.nsIRDFService)
  22.           const nsIRDFLiteral = Ci.nsIRDFLiteral;
  23.           
  24.           function isExtEnabled(aExtID) {
  25.             let enabled = true;
  26.             let itemResource = RdfService.GetResource(PREFIX_ITEM_URI + aExtID);
  27.             if (itemResource) {
  28.               let ds = ExtensionManager.datasource;
  29.               let target = ds.GetTarget(itemResource, RdfService.GetResource(PREFIX_NS_EM + "isDisabled"), true);
  30.               if (target && target instanceof nsIRDFLiteral)
  31.                 enabled = (target.Value != "true");
  32.             }
  33.             return enabled;
  34.           }
  35.           
  36.           let extItems = ExtensionManager.getItemList(Ci.nsIUpdateItem.TYPE_EXTENSION, {});
  37.           this._compatibilityMode = !!extItems.some(function(item) {
  38.             return COMPATIBILITY_LIST.indexOf(item.id) > -1 && isExtEnabled(item.id);
  39.           });
  40.           
  41.           break;
  42.         
  43.         case 2:
  44.           this._compatibilityMode = true;
  45.           break;
  46.         
  47.         case 0:
  48.         default:
  49.           this._compatibilityMode = false;
  50.           break;
  51.       }
  52.     }
  53.     
  54.     return this._compatibilityMode;
  55.   },
  56.   
  57.   _init: function() {
  58.     OBSERVER_SERVICE.addObserver(this, "quit-application", false);
  59.     this.ProtocolHandler.addHandler(this.barProtocolHandler);
  60.   },
  61.   
  62.   _uninit: function() {
  63.     this.ProtocolHandler.removeHandler(this.barProtocolHandler);
  64.     OBSERVER_SERVICE.removeObserver(this, "quit-application");
  65.     this._stop();
  66.   },
  67.   
  68.   observe: function(aSubject, aTopic, aData) {
  69.     if (aTopic === "quit-application") {
  70.       this._uninit();
  71.     }
  72.   },
  73.   
  74.   barProtocolHandler: {
  75.     canHandleSpec: function(aSpec) {
  76.       return (aSpec && aSpec.toLowerCase() === "tabs");
  77.     },
  78.     
  79.     newURI: function(aSpec, aOriginalCharset, aBaseURI) {
  80.       if (!this.canHandleSpec(aSpec))
  81.         return null;
  82.       
  83.       return "chrome://yasearch/content/ftab/ftab.xul";
  84.     },
  85.  
  86.     newChannel: function(aURI) {
  87.       return null;
  88.     }
  89.   },
  90.   
  91.   // exp
  92.   get settings() {
  93.     delete this.settings;
  94.     
  95.     Cu.import("resource://yasearch/JSON.jsm");
  96.     
  97.     const kFactor = 0.75;
  98.     const kMaxRows = 8;
  99.     const kMaxCols = 8;
  100.     
  101.     let thumbsInRow = 3,
  102.         thumbsInCol = 3;
  103.     
  104.     let settingsStr = gYaSearchService.getCharPref("yasearch.general.ftab.settings");//{"rows":3,"cols":3}
  105.     
  106.     if (settingsStr) {
  107.       let settings;
  108.       try {
  109.         settings = JSON.parse(settingsStr);
  110.       } catch(e) {}
  111.       
  112.       if (settings && settings.rows && settings.cols) {
  113.         thumbsInRow = Math.min(kMaxCols, Math.max(2, parseInt(settings.cols, 10)));
  114.         thumbsInCol = Math.min(kMaxRows, Math.max(2, parseInt(settings.rows, 10)));
  115.       }
  116.     }
  117.     
  118.     return this.settings = {
  119.       MAX_THUMBS: kMaxRows * kMaxCols,
  120.       thumbsInRow: thumbsInRow,
  121.       thumbsInCol: thumbsInCol,
  122.       thumbsNmb: thumbsInRow * thumbsInCol,
  123.       screenFactor: kFactor * (thumbsInCol / thumbsInRow)
  124.     };
  125.   },
  126.   
  127.   PAGES_DATA_VERSION: 1,
  128.   
  129.   _pagesData: null,
  130.   
  131.   get _pagesDataFile() {
  132.     delete this._pagesDataFile;
  133.     
  134.     let fileName = "ftab.data.xml";
  135.     
  136.     let file = gYaSearchService.getYandexDir();
  137.     file.append(fileName);
  138.     
  139.     if (!file.exists() || !file.isFile()) {
  140.       try {
  141.         file.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0755);
  142.       } catch(e) {}
  143.     }
  144.     
  145.     return this._pagesDataFile = (file.exists() && file.isFile() && file.isReadable()) ? file : null;
  146.   },
  147.   
  148.   _loadPagesDataXML: function() {
  149.     let dataFile = this._pagesDataFile;
  150.     let data = dataFile ? gYaSearchService.readFile(dataFile) : "";
  151.     
  152.     let userData = gYaSearchService.safeE4Xml(data,
  153.                    '<data version="' + this.PAGES_DATA_VERSION + '"><pages/></data>', 'data');
  154.     
  155.     return userData;
  156.   },
  157.   
  158.   _stringToURI: function(aString) {
  159.     var uri = null;
  160.     var URIFixup = Components.classes["@mozilla.org/docshell/urifixup;1"]
  161.                              .getService(Components.interfaces.nsIURIFixup);
  162.     try {
  163.       uri = URIFixup.createFixupURI(aString, URIFixup.FIXUP_FLAG_NONE);
  164.     } catch(e) {}
  165.     
  166.     return uri;
  167.   },
  168.   
  169.   getURLFromString: function(aString) {
  170.     let uri = this._stringToURI(aString);
  171.     
  172.     if (uri && uri.spec && (uri.scheme == "file" || (uri.host && /^https?$/.test(uri.scheme))))
  173.       return uri.spec.split("#")[0];
  174.     
  175.     return null;
  176.   },
  177.   
  178.   _loadPagesData: function() {
  179.     if (this._pagesData)
  180.       return;
  181.     
  182.     let pagesData = this._loadPagesDataXML();
  183.     
  184.     for each (let page in pagesData.pages.page) {
  185.       page.@status = "restore";
  186.       
  187.       let url = this.getURLFromString(page.@url.toString());
  188.       
  189.       if (!url)
  190.         delete page.@url;
  191.       
  192.       page.@index = parseInt(page.@index,10);
  193.     }
  194.     
  195.     let maxIndex = this.settings.MAX_THUMBS;
  196.     let notValidPages = pagesData.pages.page.(function::attribute("url").toString() == "" ||
  197.                                               function::attribute("index") > maxIndex ||
  198.                                               function::attribute("index") < 1);
  199.     while (notValidPages[0])
  200.       delete notValidPages[0];
  201.     
  202.     this._pagesData = pagesData;
  203.     
  204.     let thumbsNmb = this.settings.thumbsNmb;
  205.     
  206.     for each (let page in pagesData.pages.page) {
  207.       if (page.@index <= thumbsNmb)
  208.         this.getURLDataForPage(page);
  209.     }
  210.   },
  211.   
  212.   __savePagesDataTimer: null,
  213.   
  214.   _savePagesDataTimed: function() {
  215.     if (this.__savePagesDataTimer)
  216.       this.__savePagesDataTimer.cancel();
  217.     
  218.     let me = this;
  219.     this.__savePagesDataTimer = new G_Timer(function() {
  220.       me._savePagesData();
  221.     }, 10 * 1000);
  222.   },
  223.   
  224.   _savePagesData: function() {
  225.     if (!this._pagesData)
  226.       return;
  227.     
  228.     let data = <data version={this.PAGES_DATA_VERSION}><pages/></data>;
  229.     
  230.     for each (let page in this._pagesData.pages.page) {
  231.       let _page = <page url={page.@url} index={page.@index}/>
  232.       
  233.       for each (var aAttrName in ["custom_title"]) {
  234.         if (page.attribute(aAttrName).length()) {
  235.           _page.@[aAttrName] = page.@[aAttrName].toString();
  236.         }
  237.       }
  238.       
  239.       data.pages.page += _page;
  240.     }
  241.     
  242.     let dataFile = this._pagesDataFile;
  243.     if (dataFile)
  244.       gYaSearchService.writeFile(dataFile, data);
  245.   },
  246.   
  247.   _destroyPagesData: function() {
  248.     this._savePagesData();
  249.     this.__pagesDataDOM = null;
  250.     this.__pagesDataDOMCloned = null;
  251.     this._pagesData = null;
  252.   },
  253.   
  254.   _getPageByIndex: function(aPageIndex) {
  255.     let pages = this._getPagesByAttribute("index", aPageIndex);
  256.     return pages && pages.length() ? pages[0] : null;
  257.   },
  258.   
  259.   _getPagesByAttribute: function(aAttrName, aAttrValue) {
  260.     if (!this._pagesData)
  261.       return;
  262.     
  263.     return this._pagesData.pages.page.(function::attribute(aAttrName) == aAttrValue);
  264.   },
  265.   
  266.   _deletePageByIndex: function(aPageIndex) {
  267.     let existedPages = this._getPagesByAttribute("index", aPageIndex);
  268.     if (!existedPages.length())
  269.       return;
  270.     
  271.     while (existedPages[0])
  272.       delete existedPages[0];
  273.     
  274.     return true;
  275.   },
  276.   
  277.   addPage: function(aPageIndex, aURL, aTitle, aRefreshConditions) {
  278.     if (!this._pagesData)
  279.       return;
  280.     
  281.     this._deletePageByIndex(aPageIndex);
  282.     
  283.     let page = <page url={aURL} index={aPageIndex}/>;
  284.     if (typeof aTitle === "string")
  285.       page.@custom_title = aTitle;
  286.     
  287.     this.getURLDataForPage(page, aRefreshConditions);
  288.     this._pagesData.pages.page += page;
  289.     
  290.     this.__pagesDataDOM = null;
  291.     this.notifyTabClients("UPDATE_PROPS", {pageIndex: aPageIndex, url: aURL});
  292.   },
  293.   
  294.   removePage: function(aPageIndex) {
  295.     if (!this._pagesData)
  296.       return;
  297.     
  298.     if (this._deletePageByIndex(aPageIndex)) {
  299.       this.__pagesDataDOM = null;
  300.       this.notifyTabClients("UPDATE_PROPS", {pageIndex: aPageIndex});
  301.     }
  302.   },
  303.   
  304.   swapPages: function(aPageIndexFrom, aPageIndexTo) {
  305.     if (!(aPageIndexFrom && aPageIndexTo))
  306.       return;
  307.     
  308.     let fromPage = this._getPageByIndex(aPageIndexFrom);
  309.     let toPage = this._getPageByIndex(aPageIndexTo);
  310.     
  311.     if (fromPage)
  312.       fromPage.@index = aPageIndexTo;
  313.     
  314.     if (toPage)
  315.       toPage.@index = aPageIndexFrom;
  316.     
  317.     this.__pagesDataDOM = null;
  318.     this.notifyTabClients("UPDATE_PROPS", {pageIndex: aPageIndexFrom});
  319.     this.notifyTabClients("UPDATE_PROPS", {pageIndex: aPageIndexTo});
  320.   },
  321.   
  322.   updatePageProps: function(aData) {
  323.     if (!aData || !this._pagesData)
  324.       return;
  325.     
  326.     let url = aData.url;
  327.     
  328.     for each (let page in this._getPagesByAttribute("url", url))
  329.       for (let [propName, propValue] in Iterator(aData))
  330.         page.@[propName] = propValue || "";
  331.     
  332.     this.__pagesDataDOM = null;
  333.     this.notifyTabClients("UPDATE_PROPS", {url: url});
  334.   },
  335.   
  336.   setPageProps: function(aPageIndex, aData, aRefreshConditions) {
  337.     if (!this._pagesData)
  338.       return;
  339.     
  340.     if (("title" in aData) && !("custom_title" in aData)) {
  341.       aData.custom_title = aData.title;
  342.       aData.title = "";
  343.     }
  344.     
  345.     let safeUnicode = gYaSearchService.safeUnicode;
  346.     for (let [propName, propValue] in Iterator(aData))
  347.       aData[propName] = safeUnicode(propValue);
  348.     
  349.     aPageIndex = aPageIndex.toString();
  350.     
  351.     let page = this._getPageByIndex(aPageIndex);
  352.     
  353.     if (!page)
  354.       return this.addPage(aPageIndex, aData.url, aData.custom_title, aRefreshConditions);
  355.     
  356.     let prevURL = page.@url.toString();
  357.     
  358.     for (let [propName, propValue] in Iterator(aData))
  359.       page.@[propName] = propValue || "";
  360.     
  361.     this.getURLDataForPage(page, aRefreshConditions);
  362.     
  363.     this.__pagesDataDOM = null;
  364.     this.notifyTabClients("UPDATE_PROPS", {pageIndex: aPageIndex, url: aData.url || null});
  365.   },
  366.   
  367.   getPageProps: function(aPageIndex) {
  368.     if (!this._pagesData)
  369.       return;
  370.     
  371.     aPageIndex = aPageIndex.toString();
  372.     
  373.     let result;
  374.     let page = this._getPageByIndex(aPageIndex);
  375.     
  376.     if (page) {
  377.       result = {
  378.         index: aPageIndex,
  379.         title: (page.@custom_title.toString() || page.@title.toString()),
  380.         url: page.@url.toString(),
  381.         state: page.@state.toString()
  382.       };
  383.       
  384.       result.img = this.getAboutImgURL(result.url);
  385.       
  386.     } else {
  387.       result = {
  388.         index: aPageIndex,
  389.         title: "",
  390.         url: "",
  391.         img: "",
  392.         state: ""
  393.       };
  394.     }
  395.     
  396.     return result;
  397.   },
  398.   
  399.   getPropsForURL: function(aURL) {
  400.     let page = <page url={aURL}/>;
  401.     this.getURLDataForPage(page);
  402.     
  403.     let props = {};
  404.     ["url", "title", "img", "state"].forEach(function(attr) {
  405.       props[attr] = page.@[attr].toString() || "";
  406.     });
  407.     
  408.     return props;
  409.   },
  410.   
  411.   getImageForURL: function(aURL) {
  412.     return gYaStorage.getImageForURL(aURL);
  413.   },
  414.   
  415.   get secURLParam() {
  416.     delete this.secURLParam;
  417.     return this.secURLParam = (gYaSearchService.generateGUID.toString()).replace(/\{|\}|\-/g, "");
  418.   },
  419.   
  420.   __pagesDataDOM: null,
  421.   __pagesDataDOMCloned: null,
  422.   
  423.   get _pagesDataDOM() {
  424.     if (!this.__pagesDataDOM) {
  425.       this.__pagesDataDOMCloned = null;
  426.       
  427.       this.__pagesDataDOM = gYaSearchService.getDOMDocContent2("ftab/xsl-thumbs-template.xsl",
  428.                                 gYaSearchService.domParser.parseFromString(this._pagesData.toSource(), "text/xml"),
  429.                                 { secURLParam: this.secURLParam,
  430.                                   thumbsInRow: this.settings.thumbsInRow,
  431.                                   thumbsInCol: this.settings.thumbsInCol });
  432.     }
  433.     
  434.     var me = this;
  435.     new G_Timer(function() {
  436.       me.__pagesDataDOMCloned = me.__pagesDataDOM ? me.__pagesDataDOM.cloneNode(true) : null;
  437.     }, 2000);
  438.     
  439.     let res = this.__pagesDataDOMCloned || this.__pagesDataDOM.cloneNode(true);
  440.     this.__pagesDataDOMCloned = null;
  441.     
  442.     return res;
  443.   },
  444.   
  445.   _cleanUpTimer: null,
  446.   
  447.   _cleanUp: function() {
  448.     if (!this._pagesData)
  449.       return;
  450.     
  451.     let urls = [];
  452.     for each (let page in this._pagesData.pages.page) {
  453.       let url = page.@url.toString();
  454.       if (url && urls.indexOf(url) === -1) {
  455.         urls.push(url);
  456.       }
  457.     }
  458.     
  459.     gYaStorage._dbCleanupOldURLData(urls);
  460.   },
  461.   
  462.   _isRunned: false,
  463.   
  464.   _run: function() {
  465.     if (this._isRunned)
  466.       return;
  467.     
  468.     this._loadPagesData();
  469.     
  470.     var me = this;
  471.     this._cleanUpTimer = new G_Timer(function() { me._cleanUp(); }, 60*60*1000, true);
  472.     
  473.     this._isRunned = true;
  474.   },
  475.   
  476.   _stop: function() {
  477.     if (!this._isRunned)
  478.       return;
  479.     
  480.     if (this._SShotGrabber) {
  481.       this._SShotGrabber.destroy();
  482.       this._SShotGrabber = null;
  483.     }
  484.     
  485.     this._tabClients = [];
  486.     this._destroyPagesData();
  487.     
  488.     if (this._cleanUpTimer) {
  489.       this._cleanUpTimer.cancel();
  490.       this._cleanUpTimer = null;
  491.     }
  492.     
  493.     this._isRunned = false;
  494.   },
  495.   
  496.   _checkCanStop: function() {
  497.   },
  498.   
  499.   _tabClients: [],
  500.   
  501.   createTabClient: function(aYaFTabObject) {
  502.     if (this._tabClients.some(function(aTabClient) { return aTabClient === aYaFTabObject; }))
  503.       return;
  504.     
  505.     this._tabClients.push(aYaFTabObject);
  506.     
  507.     this._run();
  508.     
  509.     return this._pagesDataDOM;
  510.   },
  511.   
  512.   destroyTabClient: function(aYaFTabObject) {
  513.     this._tabClients = this._tabClients.filter(function(aTabClient) { return aTabClient !== aYaFTabObject; });
  514.     this._checkCanStop();
  515.   },
  516.   
  517.   notifyTabClients: function(aTopic, aData, aTabClient) {
  518.     (aTabClient ? [aTabClient] : this._tabClients)
  519.     .forEach(function(aTabClient) {
  520.       aTabClient.observe(aTopic, aData);
  521.     });
  522.     
  523.     if (aTopic == "UPDATE_PROPS") {
  524.       this._savePagesDataTimed();
  525.     }
  526.   },
  527.   
  528.   getURLData: function(aURL, aRefreshConditions) {
  529.     let url = this.getURLFromString(aURL);
  530.     if (!url)
  531.       return;
  532.     
  533.     let urlData = gYaStorage.getURLData(url);
  534.     
  535.     if (urlData && urlData.img)
  536.       urlData.img = this.getAboutImgURL(url);
  537.     
  538.     if (this._isScreenExpired(url, urlData, aRefreshConditions))
  539.       this.getSShotForURL(url);
  540.     
  541.     return urlData;
  542.   },
  543.   
  544.   getURLDataForPage: function(aPage, aRefreshConditions) {
  545.     let url = this.getURLFromString(aPage.@url.toString());
  546.     if (!url)
  547.       return;
  548.     
  549.     let urlData = this.getURLData(url, aRefreshConditions) || {};
  550.     
  551.     if (this.SShotGrabber.isURLInQueue(url))
  552.       urlData.state = "busy";
  553.     
  554.     for (let [propName, propValue] in Iterator(urlData))
  555.       aPage.@[propName] = propValue || "";
  556.     
  557.     return urlData;
  558.   },
  559.   
  560.   getURLsData: function(aURLs) {},
  561.   
  562.   _SShotGrabber: null,
  563.   get SShotGrabber() {
  564.     return this._SShotGrabber || (this._SShotGrabber = new YaSShotGrabber(this));
  565.   },
  566.   
  567.   _isScreenExpired: function(aURL, aURLData, aRefreshConditions) {
  568.     let url = this.getURLFromString(aURL);
  569.     if (!url)
  570.       return false;
  571.     
  572.     if (this.SShotGrabber.isURLInQueue(url))
  573.       return false;
  574.     
  575.     let urlData = (typeof aURLData === "undefined") ? this.getURLData(url) : aURLData;
  576.     if (!urlData)
  577.       return true;
  578.     
  579.     let checkTimeDiff = Math.abs(Date.now() - urlData.checkTime);
  580.     
  581.     if (aRefreshConditions) {
  582.       if ("forcedRefresh" in aRefreshConditions && aRefreshConditions.forcedRefresh === true)
  583.         return true;
  584.       
  585.       if ("checkedTimeMin" in aRefreshConditions && aRefreshConditions.checkedTimeMin > urlData.checkTime)
  586.         return true;
  587.       
  588.       if ("olderThan" in aRefreshConditions && checkTimeDiff > aRefreshConditions.olderThan)
  589.         return true;
  590.     }
  591.     
  592.     if ((checkTimeDiff > (7 * DAY_SECS)) || (urlData.httpStatus == 404 && checkTimeDiff > (3 * DAY_SECS))) {
  593.       return true;
  594.     }
  595.     
  596.     return false;
  597.   },
  598.   
  599.   getSShotForURL: function(aURL) {
  600.     if (this.SShotGrabber.getCanvasForURL(aURL)) {
  601.       this.updatePageProps({url: aURL, state: "busy"});
  602.     }
  603.   },
  604.   
  605.   getAboutImgURL: function(aURL) {
  606.     return aURL ? ("about:yandex-tabs?sec=" + this.secURLParam + "&image=" + aURL) : null;
  607.   },
  608.   
  609.   _removeImgURLFromCache: function(aURL) {
  610.     let uri = gYaSearchService.makeURI(aURL);
  611.     if (uri) {
  612.       try {
  613.         const imageCache = Cc["@mozilla.org/image/cache;1"].getService(Ci.imgICache);
  614.         imageCache.removeEntry(uri);
  615.       } catch(e) {}
  616.     }
  617.   },
  618.   
  619.   onSShotCreated: function(aPageData) {
  620.     gYaStorage.setURLData(aPageData);
  621.     
  622.     if (aPageData) {
  623.       let imgURL = this.getAboutImgURL(aPageData.url);
  624.       this._removeImgURLFromCache(imgURL);
  625.       aPageData.img = imgURL;
  626.     }
  627.     
  628.     this.updatePageProps(gYaStorage.getURLData(aPageData.url));
  629.   },
  630.   
  631.   getSitesFromHistory: function(aMaxResults, aOnComplete) {
  632.     if (!aOnComplete)
  633.       return;
  634.     
  635.     let me = this;
  636.     new G_Timer(function() {
  637.       me._getSitesFromHistory(aMaxResults, aOnComplete);
  638.     }, 0);
  639.   },
  640.   
  641.   _getSitesFromHistory: function(aMaxResults, aOnComplete) {
  642.     let maxResults = aMaxResults || 10;
  643.     
  644.     let historyService = Cc["@mozilla.org/browser/nav-history-service;1"].getService(Ci.nsINavHistoryService);
  645.     
  646.     let query = historyService.getNewQuery();
  647.     
  648.     let options = historyService.getNewQueryOptions();
  649.     options.maxResults = maxResults * 2;
  650.     options.sortingMode = options.SORT_BY_DATE_DESCENDING;
  651.     
  652.     let result = (historyService.executeQuery(query, options)).root;
  653.     result.containerOpen = true;
  654.     
  655.     let faviconService = Cc["@mozilla.org/browser/favicon-service;1"].getService(Ci.nsIFaviconService);
  656.     let ioservice = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
  657.     
  658.     const nsIURI = Ci.nsIURI;
  659.     
  660.     let sites = [];
  661.     for (let i = 0, count = result.childCount; i < count && i < maxResults; i++) {
  662.       let node = result.getChild(i);
  663.       
  664.       let nodeURI = ioservice.newURI(node.uri, null, null);
  665.       
  666.       if (!/^https?|file$/.test(nodeURI.scheme))
  667.         continue;
  668.       
  669.       if (/\.swf$/.test(nodeURI.spec))
  670.         continue;
  671.       
  672.       let title = node.title;
  673.       let icon = node.icon ?
  674.                      (node.icon instanceof nsIURI ? node.icon.spec : node.icon) :
  675.                      faviconService.getFaviconImageForPage(nodeURI).spec;
  676.       
  677.       let pathForTitle = nodeURI.path.split("?")[0].split("/").pop();
  678.       
  679.       if (title == nodeURI.path || title == pathForTitle) {
  680.         if (!node.icon)
  681.           continue;
  682.         
  683.         title = nodeURI.spec;
  684.       }
  685.       
  686.       sites.push({
  687.         title: title,
  688.         url: node.uri,
  689.         icon: icon
  690.       });
  691.     }
  692.     
  693.     result.containerOpen = false;
  694.     
  695.     if (aOnComplete) {
  696.       aOnComplete(sites);
  697.       aOnComplete = null;
  698.     }
  699.   },
  700.   
  701.   findSites: function(aSearchString, aOnComplete) {
  702.     if (!aOnComplete)
  703.       return;
  704.     
  705.     let me = this;
  706.     new G_Timer(function() {
  707.       me._findSites(aSearchString, aOnComplete);
  708.     }, 0);
  709.   },
  710.   
  711.   _findSites: function(aSearchString, aOnComplete) {
  712.     let acomplete = Cc["@mozilla.org/autocomplete/search;1?name=history"]
  713.                         .getService(Ci.nsIAutoCompleteSearch);
  714.     
  715.     let callback = function(aResult) {
  716.       if (aOnComplete) {
  717.         aOnComplete(aResult);
  718.         aOnComplete = null;
  719.       }
  720.     };
  721.  
  722.     acomplete.startSearch(aSearchString, "", null, ({
  723.       onSearchResult: function(search, result) {
  724.         switch (result.searchResult) {
  725.           case result.RESULT_NOMATCH:
  726.             return callback();
  727.           
  728.           case result.RESULT_SUCCESS:
  729.           case result.RESULT_SUCCESS_ONGOING:
  730.             acomplete.stopSearch();
  731.             
  732.             let sites = [];
  733.             for (let i = 0, count = result.matchCount; i < count; i++) {
  734.               sites.push({
  735.                 title: result.getCommentAt(i),
  736.                 url: result.getValueAt(i),
  737.                 icon: result.getImageAt(i)
  738.               });
  739.             }
  740.             callback(sites);
  741.             break;
  742.           
  743.           default:
  744.             break;
  745.         }
  746.       }
  747.     }));
  748.   }
  749. };
  750.  
  751. Components.utils.import("resource://yasearch/bar.protocol.jsm", gYaFTab);
  752.  
  753. gYaFTab._init();