1/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
2/* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
7
8var EXPORTED_SYMBOLS = ["BlockedSiteChild"];
9
10ChromeUtils.defineModuleGetter(
11  this,
12  "SafeBrowsing",
13  "resource://gre/modules/SafeBrowsing.jsm"
14);
15
16function getSiteBlockedErrorDetails(docShell) {
17  let blockedInfo = {};
18  if (docShell.failedChannel) {
19    let classifiedChannel = docShell.failedChannel.QueryInterface(
20      Ci.nsIClassifiedChannel
21    );
22    if (classifiedChannel) {
23      let httpChannel = docShell.failedChannel.QueryInterface(
24        Ci.nsIHttpChannel
25      );
26
27      let reportUri = httpChannel.URI;
28
29      // Remove the query to avoid leaking sensitive data
30      if (reportUri instanceof Ci.nsIURL) {
31        reportUri = reportUri
32          .mutate()
33          .setQuery("")
34          .finalize();
35      }
36
37      let triggeringPrincipal = docShell.failedChannel.loadInfo
38        ? docShell.failedChannel.loadInfo.triggeringPrincipal
39        : null;
40      blockedInfo = {
41        list: classifiedChannel.matchedList,
42        triggeringPrincipal,
43        provider: classifiedChannel.matchedProvider,
44        uri: reportUri.asciiSpec,
45      };
46    }
47  }
48  return blockedInfo;
49}
50
51class BlockedSiteChild extends JSWindowActorChild {
52  receiveMessage(msg) {
53    if (msg.name == "DeceptiveBlockedDetails") {
54      return getSiteBlockedErrorDetails(this.docShell);
55    }
56    return null;
57  }
58
59  handleEvent(event) {
60    if (event.type == "AboutBlockedLoaded") {
61      this.onAboutBlockedLoaded(event);
62    } else if (event.type == "click" && event.button == 0) {
63      this.onClick(event);
64    }
65  }
66
67  onAboutBlockedLoaded(aEvent) {
68    let content = aEvent.target.ownerGlobal;
69
70    let blockedInfo = getSiteBlockedErrorDetails(this.docShell);
71    let provider = blockedInfo.provider || "";
72
73    let doc = content.document;
74
75    /**
76     * Set error description link in error details.
77     * For example, the "reported as a deceptive site" link for
78     * blocked phishing pages.
79     */
80    let desc = Services.prefs.getCharPref(
81      "browser.safebrowsing.provider." + provider + ".reportURL",
82      ""
83    );
84    if (desc) {
85      doc
86        .getElementById("error_desc_link")
87        .setAttribute("href", desc + encodeURIComponent(aEvent.detail.url));
88    }
89
90    // Set other links in error details.
91    switch (aEvent.detail.err) {
92      case "malware":
93        doc
94          .getElementById("report_detection")
95          .setAttribute(
96            "href",
97            SafeBrowsing.getReportURL("MalwareMistake", blockedInfo)
98          );
99        break;
100      case "unwanted":
101        doc
102          .getElementById("learn_more_link")
103          .setAttribute(
104            "href",
105            "https://www.google.com/about/unwanted-software-policy.html"
106          );
107        break;
108      case "phishing":
109        doc
110          .getElementById("report_detection")
111          .setAttribute(
112            "href",
113            SafeBrowsing.getReportURL("PhishMistake", blockedInfo) ||
114              "https://safebrowsing.google.com/safebrowsing/report_error/?tpl=mozilla"
115          );
116        doc
117          .getElementById("learn_more_link")
118          .setAttribute("href", "https://www.antiphishing.org//");
119        break;
120    }
121
122    // Set the firefox support url.
123    doc
124      .getElementById("firefox_support")
125      .setAttribute(
126        "href",
127        Services.urlFormatter.formatURLPref("app.support.baseURL") +
128          "phishing-malware"
129      );
130
131    // Show safe browsing details on load if the pref is set to true.
132    let showDetails = Services.prefs.getBoolPref(
133      "browser.xul.error_pages.show_safe_browsing_details_on_load"
134    );
135    if (showDetails) {
136      let details = content.document.getElementById(
137        "errorDescriptionContainer"
138      );
139      details.removeAttribute("hidden");
140    }
141
142    // Set safe browsing advisory link.
143    let advisoryUrl = Services.prefs.getCharPref(
144      "browser.safebrowsing.provider." + provider + ".advisoryURL",
145      ""
146    );
147    let advisoryDesc = content.document.getElementById("advisoryDescText");
148    if (!advisoryUrl) {
149      advisoryDesc.remove();
150      return;
151    }
152
153    let advisoryLinkText = Services.prefs.getCharPref(
154      "browser.safebrowsing.provider." + provider + ".advisoryName",
155      ""
156    );
157    if (!advisoryLinkText) {
158      advisoryDesc.remove();
159      return;
160    }
161
162    content.document.l10n.setAttributes(
163      advisoryDesc,
164      "safeb-palm-advisory-desc",
165      { advisoryname: advisoryLinkText }
166    );
167    content.document
168      .getElementById("advisory_provider")
169      .setAttribute("href", advisoryUrl);
170  }
171
172  onClick(event) {
173    let ownerDoc = event.target.ownerDocument;
174    if (!ownerDoc) {
175      return;
176    }
177
178    var reason = "phishing";
179    if (/e=malwareBlocked/.test(ownerDoc.documentURI)) {
180      reason = "malware";
181    } else if (/e=unwantedBlocked/.test(ownerDoc.documentURI)) {
182      reason = "unwanted";
183    } else if (/e=harmfulBlocked/.test(ownerDoc.documentURI)) {
184      reason = "harmful";
185    }
186
187    this.sendAsyncMessage("Browser:SiteBlockedError", {
188      location: ownerDoc.location.href,
189      reason,
190      elementId: event.target.getAttribute("id"),
191      blockedInfo: getSiteBlockedErrorDetails(this.docShell),
192    });
193  }
194}
195