mirror of
				https://github.com/mozilla/gecko-dev.git
				synced 2025-11-04 10:18:41 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			177 lines
		
	
	
	
		
			4.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			177 lines
		
	
	
	
		
			4.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
/* This Source Code Form is subject to the terms of the Mozilla Public
 | 
						|
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 | 
						|
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | 
						|
 | 
						|
const lazy = {};
 | 
						|
 | 
						|
ChromeUtils.defineModuleGetter(
 | 
						|
  lazy,
 | 
						|
  "FaviconLoader",
 | 
						|
  "resource:///modules/FaviconLoader.jsm"
 | 
						|
);
 | 
						|
 | 
						|
export class LinkHandlerChild extends JSWindowActorChild {
 | 
						|
  constructor() {
 | 
						|
    super();
 | 
						|
 | 
						|
    this.seenTabIcon = false;
 | 
						|
    this._iconLoader = null;
 | 
						|
  }
 | 
						|
 | 
						|
  get iconLoader() {
 | 
						|
    if (!this._iconLoader) {
 | 
						|
      this._iconLoader = new lazy.FaviconLoader(this);
 | 
						|
    }
 | 
						|
    return this._iconLoader;
 | 
						|
  }
 | 
						|
 | 
						|
  addRootIcon() {
 | 
						|
    if (
 | 
						|
      !this.seenTabIcon &&
 | 
						|
      Services.prefs.getBoolPref("browser.chrome.guess_favicon", true) &&
 | 
						|
      Services.prefs.getBoolPref("browser.chrome.site_icons", true)
 | 
						|
    ) {
 | 
						|
      // Inject the default icon. Use documentURIObject so that we do the right
 | 
						|
      // thing with about:-style error pages. See bug 453442
 | 
						|
      let pageURI = this.document.documentURIObject;
 | 
						|
      if (["http", "https"].includes(pageURI.scheme)) {
 | 
						|
        this.seenTabIcon = true;
 | 
						|
        this.iconLoader.addDefaultIcon(pageURI);
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  onHeadParsed(event) {
 | 
						|
    if (event.target.ownerDocument != this.document) {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    // Per spec icons are meant to be in the <head> tag so we should have seen
 | 
						|
    // all the icons now so add the root icon if no other tab icons have been
 | 
						|
    // seen.
 | 
						|
    this.addRootIcon();
 | 
						|
 | 
						|
    // We're likely done with icon parsing so load the pending icons now.
 | 
						|
    if (this._iconLoader) {
 | 
						|
      this._iconLoader.onPageShow();
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  onPageShow(event) {
 | 
						|
    if (event.target != this.document) {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    this.addRootIcon();
 | 
						|
 | 
						|
    if (this._iconLoader) {
 | 
						|
      this._iconLoader.onPageShow();
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  onPageHide(event) {
 | 
						|
    if (event.target != this.document) {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    if (this._iconLoader) {
 | 
						|
      this._iconLoader.onPageHide();
 | 
						|
    }
 | 
						|
 | 
						|
    this.seenTabIcon = false;
 | 
						|
  }
 | 
						|
 | 
						|
  onLinkEvent(event) {
 | 
						|
    let link = event.target;
 | 
						|
    // Ignore sub-frames (bugs 305472, 479408).
 | 
						|
    if (link.ownerGlobal != this.contentWindow) {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    let rel = link.rel && link.rel.toLowerCase();
 | 
						|
    // We also check .getAttribute, since an empty href attribute will give us
 | 
						|
    // a link.href that is the same as the document.
 | 
						|
    if (!rel || !link.href || !link.getAttribute("href")) {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    // Note: following booleans only work for the current link, not for the
 | 
						|
    // whole content
 | 
						|
    let iconAdded = false;
 | 
						|
    let searchAdded = false;
 | 
						|
    let rels = {};
 | 
						|
    for (let relString of rel.split(/\s+/)) {
 | 
						|
      rels[relString] = true;
 | 
						|
    }
 | 
						|
 | 
						|
    for (let relVal in rels) {
 | 
						|
      let isRichIcon = false;
 | 
						|
 | 
						|
      switch (relVal) {
 | 
						|
        case "apple-touch-icon":
 | 
						|
        case "apple-touch-icon-precomposed":
 | 
						|
        case "fluid-icon":
 | 
						|
          isRichIcon = true;
 | 
						|
        // fall through
 | 
						|
        case "icon":
 | 
						|
          if (iconAdded || link.hasAttribute("mask")) {
 | 
						|
            // Masked icons are not supported yet.
 | 
						|
            break;
 | 
						|
          }
 | 
						|
 | 
						|
          if (!Services.prefs.getBoolPref("browser.chrome.site_icons", true)) {
 | 
						|
            return;
 | 
						|
          }
 | 
						|
 | 
						|
          if (this.iconLoader.addIconFromLink(link, isRichIcon)) {
 | 
						|
            iconAdded = true;
 | 
						|
            if (!isRichIcon) {
 | 
						|
              this.seenTabIcon = true;
 | 
						|
            }
 | 
						|
          }
 | 
						|
          break;
 | 
						|
        case "search":
 | 
						|
          if (
 | 
						|
            Services.policies &&
 | 
						|
            !Services.policies.isAllowed("installSearchEngine")
 | 
						|
          ) {
 | 
						|
            break;
 | 
						|
          }
 | 
						|
 | 
						|
          if (!searchAdded && event.type == "DOMLinkAdded") {
 | 
						|
            let type = link.type && link.type.toLowerCase();
 | 
						|
            type = type.replace(/^\s+|\s*(?:;.*)?$/g, "");
 | 
						|
 | 
						|
            // Note: This protocol list should be kept in sync with
 | 
						|
            // the one in OpenSearchEngine's install function.
 | 
						|
            let re = /^https?:/i;
 | 
						|
            if (
 | 
						|
              type == "application/opensearchdescription+xml" &&
 | 
						|
              link.title &&
 | 
						|
              re.test(link.href)
 | 
						|
            ) {
 | 
						|
              let engine = { title: link.title, href: link.href };
 | 
						|
              this.sendAsyncMessage("Link:AddSearch", {
 | 
						|
                engine,
 | 
						|
              });
 | 
						|
              searchAdded = true;
 | 
						|
            }
 | 
						|
          }
 | 
						|
          break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  handleEvent(event) {
 | 
						|
    switch (event.type) {
 | 
						|
      case "pageshow":
 | 
						|
        return this.onPageShow(event);
 | 
						|
      case "pagehide":
 | 
						|
        return this.onPageHide(event);
 | 
						|
      case "DOMHeadElementParsed":
 | 
						|
        return this.onHeadParsed(event);
 | 
						|
      default:
 | 
						|
        return this.onLinkEvent(event);
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 |