home *** CD-ROM | disk | FTP | other *** search
- function YaCanvasQueue(aGrabber) {
- this._grabber = aGrabber;
- this._elements = [];
- this._activeElementsMaxLength = 5;
- }
-
- YaCanvasQueue.prototype = {
- destroy: function() {
- this.clear();
- this._grabber = null;
- },
-
- get size() {
- return this._elements.length;
- },
-
- get isEmpty() {
- return !this.size;
- },
-
- isURLInQueue: function(aURL) {
- return this._elements.some(function(elm) { return aURL === elm.url; });
- },
-
- clear: function() {
- this._elements = [];
- },
-
- push: function(aURL) {
- if (this.isURLInQueue(aURL))
- return false;
-
- this._elements.push({url: aURL, active: false});
-
- this.checkNeedProccess();
-
- return true;
- },
-
- remove: function(aURL) {
- this._elements = this._elements.filter(function(el) { return el.url !== aURL; });
- this.checkNeedProccess();
- },
-
- get nextElement() {
- return this._elements.filter(function(el) { return el.active === false; })[0];
- },
-
- get activeElementsLength() {
- return this._elements.filter(function(el) { return el.active === true; }).length;
- },
-
- checkNeedProccess: function() {
- if (this.isEmpty || !this._grabber.isGrabberFrameReady)
- return false;
-
- let element;
- while (this.activeElementsLength < this._activeElementsMaxLength &&
- (element = this.nextElement)) {
- element.active = true;
- this._grabber._getCanvasForURL(element.url);
- }
-
- return true;
- },
-
- _getCanvasCallback: function(aPageData) {
- this.remove(aPageData.url);
- }
- }
-
- function SShotProgressListener(aSShotGrabber) {
- this.SShotGrabber = aSShotGrabber;
- }
-
- SShotProgressListener.prototype = {
- _getRequestStatus: function(aFrame) {
- let webNavigation = aFrame.webNavigation;
-
- let httpStatus = 404;
- let channel = (webNavigation && 'currentDocumentChannel' in webNavigation) ?
- webNavigation.currentDocumentChannel :
- null;
-
- if (channel) {
- try {
- channel = channel.QueryInterface(Ci.nsIHttpChannel);
- httpStatus = channel.responseStatus;
- } catch(e) {
- if (channel.URI && channel.contentType == "application/xhtml+xml" && channel.URI.scheme == "file") {
- httpStatus = 200;
- }
- }
- }
-
- return httpStatus;
- },
-
- onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus) {
- const Ci = Components.interfaces,
- Cr = Components.results;
-
- if ((aStateFlags & Ci.nsIWebProgressListener.STATE_IS_WINDOW) &&
- (aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK) &&
- (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP)) {
-
- aWebProgress.QueryInterface(Ci.nsIWebNavigation);
- if (!aWebProgress.document)
- return;
-
- let targetFrame = this.SShotGrabber._getFrameForDocument(aWebProgress.document);
- if (!targetFrame)
- return;
-
- let httpStatus = this._getRequestStatus(targetFrame);
-
- this.SShotGrabber._onPageLoadTimed(targetFrame, httpStatus);
- }
- },
-
- onProgressChange : function() { return 0; },
- onLocationChange : function() { return 0; },
- onStatusChange : function() { return 0; },
- onSecurityChange : function() { return 0; },
-
- QueryInterface: function(aIID) {
- const Ci = Components.interfaces;
- if (aIID.equals(Ci.nsIWebProgressListener) ||
- aIID.equals(Ci.nsISupportsWeakReference) ||
- aIID.equals(Ci.nsISupports))
- return this;
-
- throw Components.results.NS_NOINTERFACE;
- }
- };
-
-
- function YaSShotGrabber(aListener, aSizeProps) {
- if (!(aListener && 'onSShotCreated' in aListener))
- throw new Error("YaSShotGrabber need onSShotCreated for listener");
-
- this._listener = aListener;
-
- this._progressListener = new SShotProgressListener(this);
-
- this._canvasQueue = new YaCanvasQueue(this);
- this.__frameLoader = null;
- this.__frameLoaderId = "yaSShotGrabberFrame-" + Date.now();
-
- this.SIZE = {
- SCREEN: { WIDTH: 1024, HEIGHT: 768 },
- CANVAS: { WIDTH: 600, HEIGHT: 450 }
- }
- }
-
- YaSShotGrabber.prototype = {
- CANVAS_CAPTURE_TIMEOUT: 1500,
-
- isURLInQueue: function(aURL) {
- return this._canvasQueue.isURLInQueue(aURL);
- },
-
- getCanvasForURL: function(aURL) {
- return this._canvasQueue.push(aURL);
- },
-
- _setFrameEventListeners: function(aFrame, aSet) {
- let fn = (aSet ? "add" : "remove") + "ProgressListener";
-
- try {
- let webProgress = aFrame.docShell
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebProgress);
- webProgress[fn](this._progressListener, Ci.nsIWebProgress.NOTIFY_STATE_NETWORK);
- } catch(e) {}
- },
-
- _getCanvasForURL: function(aURL) {
- let doc = this._frameLoader.contentDocument;
- let iframe = doc.createElement("iframe");
-
- iframe.setAttribute("type", "content");
- iframe.setAttribute("yaSSURL", aURL);
-
- iframe.setAttribute("style",
- "width: {W}px !important; height: {H}px !important; \
- max-width: {W}px !important; max-height: {H}px !important; \
- min-width: {W}px !important; min-height: {H}px !important; \
- overflow: hidden !important;"
- .replace(/\{W\}/g, this.SIZE.SCREEN.WIDTH)
- .replace(/\{H\}/g, this.SIZE.SCREEN.HEIGHT));
-
- doc.lastChild.appendChild(iframe);
-
- var webNav = iframe.docShell.QueryInterface(Ci.nsIWebNavigation);
- webNav.stop(Ci.nsIWebNavigation.STOP_NETWORK);
-
- this._setFrameEventListeners(iframe, true);
-
- try {
- iframe.webNavigation.loadURI(aURL, Ci.nsIWebNavigation.LOAD_FLAGS_NONE, null, null, null);
- } catch(e) {
- this._onPageLoadTimed(iframe, 404);
- }
- },
-
- _onFinishForURL: function(aPageData) {
- this._canvasQueue._getCanvasCallback(aPageData);
- this._listener.onSShotCreated(aPageData);
- },
-
- get _hiddenWindow() {
- let hiddenWindow = Cc["@mozilla.org/appshell/appShellService;1"]
- .getService(Ci.nsIAppShellService).hiddenDOMWindow;
-
- if (!hiddenWindow)
- return null;
-
- delete this._hiddenWindow;
- this.__defineGetter__("_hiddenWindow", function(){ return hiddenWindow; })
- return this._hiddenWindow;
- },
-
- destroy: function() {
- this._canvasQueue.destroy();
- this._canvasQueue = null;
-
- this._framesArray
- .forEach(function(aFrame) {
- this._setFrameEventListeners(aFrame, false);
- aFrame.parentNode.removeChild(aFrame);
- }, this);
-
- if (this.__frameLoader) {
- try {
- this.__frameLoader.removeEventListener("pageshow", this, false);
- this.__frameLoader.parentNode.removeChild(this.__frameLoader);
- } catch(e) {}
- }
-
- this._progressListener = null;
-
- this._listener = null;
- this.__frameLoader = null;
- },
-
- get isGrabberFrameReady() {
- return !!this._frameLoader;
- },
-
- get _frameLoader() {
- let hiddenWindow = this._hiddenWindow;
-
- if (hiddenWindow && !this.__frameLoader) {
- this.__frameLoader = hiddenWindow.document.createElement("iframe");
- this.__frameLoader.addEventListener("pageshow", this, false);
- this.__frameLoader.setAttribute("id", this.__frameLoaderId);
- this.__frameLoader.setAttribute("src", "chrome://yasearch/content/hiddenwindow.xul");
-
- hiddenWindow.document.documentElement.appendChild(this.__frameLoader);
- }
-
- return null;
- },
-
- get _framesArray() {
- return this.__frameLoader ?
- Array.slice(this.__frameLoader.contentDocument.getElementsByTagName("iframe")) :
- [];
- },
-
- _getFrameForDocument: function(aTarget) {
- return this._framesArray
- .filter(function(aFrame) { return aFrame.contentDocument === aTarget; })[0];
- },
-
- _isRequestSuccess: function(aHttpStatus) {
- return !!((aHttpStatus >= 200 && aHttpStatus <= 299) || aHttpStatus === 304);
- },
-
- handleEvent: function(aEvent) {
- if (!aEvent.isTrusted)
- return;
-
- switch (aEvent.type) {
- case "pageshow":
- if (this.__frameLoader && aEvent.target == this.__frameLoader.contentDocument) {
- this.__frameLoader.removeEventListener("pageshow", this, false);
-
- delete this._frameLoader;
- let frameLoader = this.__frameLoader;
- this.__defineGetter__("_frameLoader", function(){ return frameLoader; })
-
- this._canvasQueue.checkNeedProccess();
- }
- break;
-
- default:
- break;
- }
- },
-
- _onPageLoadTimed: function(aTargetFrame, aHttpStatus) {
- this._setFrameEventListeners(aTargetFrame, false);
-
- var me = this;
- new G_Timer(function(){me._onPageLoad(aTargetFrame, aHttpStatus)}, this.CANVAS_CAPTURE_TIMEOUT);
- },
-
- _onPageLoad: function(aTargetFrame, aHttpStatus) {
- let result = {
- url: aTargetFrame.getAttribute("yaSSURL"),
- httpStatus: aHttpStatus,
- checkTime: Date.now()
- };
-
- if (this._isRequestSuccess(aHttpStatus)) {
- let doc = aTargetFrame.contentDocument;
- let safeUnicode = gYaSearchService.safeUnicode;
-
- result.title = safeUnicode(doc.title.toString());
- result.urlReal = safeUnicode(doc.location.toString());
- result.faviconUrl = safeUnicode(this._getDocumentFaviconURL(doc));
- result.img = this._getFrameCanvasData(aTargetFrame);
- }
-
- aTargetFrame.parentNode.removeChild(aTargetFrame);
-
- this._onFinishForURL(result);
- },
-
- _getFrameCanvasData: function(aFrame) {
- let canvas = this._frameLoader.contentDocument.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
-
- canvas.width = this.SIZE.CANVAS.WIDTH;
- canvas.height = this.SIZE.CANVAS.HEIGHT;
-
- let ctx = canvas.getContext("2d");
-
- ctx.scale(this.SIZE.CANVAS.WIDTH / this.SIZE.SCREEN.WIDTH,
- this.SIZE.CANVAS.HEIGHT / this.SIZE.SCREEN.HEIGHT);
-
- let win = aFrame.contentWindow;
- ctx.drawWindow(win,
- win.pageXOffset,
- win.pageYOffset,
- win.pageXOffset + this.SIZE.SCREEN.WIDTH,
- win.pageYOffset + this.SIZE.SCREEN.HEIGHT,
- "rgb(255,255,255)");
-
- return canvas.toDataURL("image/png", "");
- },
-
- _createFaviconURL: function(aURL) {
- let url,
- uri = gYaSearchService.makeURI(aURL);
-
- if (uri && /^https?$/.test(uri.scheme))
- url = uri.prePath + "/favicon.ico";
-
- return url;
- },
-
- _getDocumentFaviconURL: function(aDocument) {
- let url = Array.slice(aDocument.getElementsByTagName("link"))
- .filter(function(aLinkElement) {
- return !!(/icon/.test(aLinkElement.rel) && /^https?:\/\//.test(aLinkElement.href));
- })[0];
-
- if (url)
- url = url.href;
-
- return (url || this._createFaviconURL(aDocument.location) || "");
- }
- }