mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1255270, r=mak a=ritu
ba=IDon'tThinkThisHookIsSupposedToBeEnforcedOnBeta47 MozReview-Commit-ID: 5fInAZiZMhl
This commit is contained in:
parent
97b377ca48
commit
32954f4653
@ -63,10 +63,6 @@
|
|||||||
Components.classes["@mozilla.org/docshell/urifixup;1"]
|
Components.classes["@mozilla.org/docshell/urifixup;1"]
|
||||||
.getService(Components.interfaces.nsIURIFixup);
|
.getService(Components.interfaces.nsIURIFixup);
|
||||||
</field>
|
</field>
|
||||||
<field name="mFaviconService" readonly="true">
|
|
||||||
Components.classes["@mozilla.org/browser/favicon-service;1"]
|
|
||||||
.getService(Components.interfaces.nsIFaviconService);
|
|
||||||
</field>
|
|
||||||
<field name="_placesAutocomplete" readonly="true">
|
<field name="_placesAutocomplete" readonly="true">
|
||||||
Components.classes["@mozilla.org/autocomplete/search;1?name=history"]
|
Components.classes["@mozilla.org/autocomplete/search;1?name=history"]
|
||||||
.getService(Components.interfaces.mozIPlacesAutoComplete);
|
.getService(Components.interfaces.mozIPlacesAutoComplete);
|
||||||
@ -75,9 +71,6 @@
|
|||||||
Components.classes["@mozilla.org/autocomplete/search;1?name=unifiedcomplete"]
|
Components.classes["@mozilla.org/autocomplete/search;1?name=unifiedcomplete"]
|
||||||
.getService(Components.interfaces.mozIPlacesAutoComplete);
|
.getService(Components.interfaces.mozIPlacesAutoComplete);
|
||||||
</field>
|
</field>
|
||||||
<field name="PlacesUtils" readonly="true">
|
|
||||||
(Components.utils.import("resource://gre/modules/PlacesUtils.jsm", {})).PlacesUtils;
|
|
||||||
</field>
|
|
||||||
<field name="AppConstants" readonly="true">
|
<field name="AppConstants" readonly="true">
|
||||||
(Components.utils.import("resource://gre/modules/AppConstants.jsm", {})).AppConstants;
|
(Components.utils.import("resource://gre/modules/AppConstants.jsm", {})).AppConstants;
|
||||||
</field>
|
</field>
|
||||||
@ -866,7 +859,7 @@
|
|||||||
let browser = this.getBrowserForTab(aTab);
|
let browser = this.getBrowserForTab(aTab);
|
||||||
browser.mIconURL = aURI instanceof Ci.nsIURI ? aURI.spec : aURI;
|
browser.mIconURL = aURI instanceof Ci.nsIURI ? aURI.spec : aURI;
|
||||||
|
|
||||||
if (aURI && this.mFaviconService) {
|
if (aURI) {
|
||||||
if (!(aURI instanceof Ci.nsIURI)) {
|
if (!(aURI instanceof Ci.nsIURI)) {
|
||||||
aURI = makeURI(aURI);
|
aURI = makeURI(aURI);
|
||||||
}
|
}
|
||||||
@ -876,12 +869,7 @@
|
|||||||
let loadingPrincipal = aLoadingPrincipal
|
let loadingPrincipal = aLoadingPrincipal
|
||||||
? aLoadingPrincipal
|
? aLoadingPrincipal
|
||||||
: Services.scriptSecurityManager.getSystemPrincipal();
|
: Services.scriptSecurityManager.getSystemPrincipal();
|
||||||
let loadType = PrivateBrowsingUtils.isWindowPrivate(window)
|
PlacesUIUtils.loadFavicon(browser, loadingPrincipal, aURI);
|
||||||
? this.mFaviconService.FAVICON_LOAD_PRIVATE
|
|
||||||
: this.mFaviconService.FAVICON_LOAD_NON_PRIVATE;
|
|
||||||
|
|
||||||
this.mFaviconService.setAndFetchFaviconForPage(
|
|
||||||
browser.currentURI, aURI, false, loadType, null, loadingPrincipal);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let sizedIconUrl = browser.mIconURL || "";
|
let sizedIconUrl = browser.mIconURL || "";
|
||||||
@ -954,12 +942,9 @@
|
|||||||
<parameter name="aURI"/>
|
<parameter name="aURI"/>
|
||||||
<body>
|
<body>
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
if (this.mFaviconService) {
|
if (!(aURI instanceof Ci.nsIURI))
|
||||||
if (!(aURI instanceof Ci.nsIURI))
|
aURI = makeURI(aURI);
|
||||||
aURI = makeURI(aURI);
|
return PlacesUtils.favicons.isFailedFavicon(aURI);
|
||||||
return this.mFaviconService.isFailedFavicon(aURI);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
]]>
|
]]>
|
||||||
</body>
|
</body>
|
||||||
</method>
|
</method>
|
||||||
|
@ -214,15 +214,6 @@ FeedWriter.prototype = {
|
|||||||
element.setAttribute(attribute, uri);
|
element.setAttribute(attribute, uri);
|
||||||
},
|
},
|
||||||
|
|
||||||
__faviconService: null,
|
|
||||||
get _faviconService() {
|
|
||||||
if (!this.__faviconService)
|
|
||||||
this.__faviconService = Cc["@mozilla.org/browser/favicon-service;1"].
|
|
||||||
getService(Ci.nsIFaviconService);
|
|
||||||
|
|
||||||
return this.__faviconService;
|
|
||||||
},
|
|
||||||
|
|
||||||
__bundle: null,
|
__bundle: null,
|
||||||
get _bundle() {
|
get _bundle() {
|
||||||
if (!this.__bundle) {
|
if (!this.__bundle) {
|
||||||
@ -1023,7 +1014,6 @@ FeedWriter.prototype = {
|
|||||||
prefs.removeObserver(PREF_AUDIO_SELECTED_APP, this);
|
prefs.removeObserver(PREF_AUDIO_SELECTED_APP, this);
|
||||||
|
|
||||||
this._removeFeedFromCache();
|
this._removeFeedFromCache();
|
||||||
this.__faviconService = null;
|
|
||||||
this.__bundle = null;
|
this.__bundle = null;
|
||||||
this._feedURI = null;
|
this._feedURI = null;
|
||||||
|
|
||||||
@ -1164,46 +1154,6 @@ FeedWriter.prototype = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the icon for the given web-reader item in the readers menu.
|
|
||||||
* The icon is fetched and stored through the favicon service.
|
|
||||||
*
|
|
||||||
* @param aReaderUrl
|
|
||||||
* the reader url.
|
|
||||||
* @param aMenuItem
|
|
||||||
* the reader item in the readers menulist.
|
|
||||||
*
|
|
||||||
* @note For privacy reasons we cannot set the image attribute directly
|
|
||||||
* to the icon url. See Bug 358878 for details.
|
|
||||||
*/
|
|
||||||
_setFaviconForWebReader:
|
|
||||||
function FW__setFaviconForWebReader(aReaderUrl, aMenuItem) {
|
|
||||||
let readerURI = makeURI(aReaderUrl);
|
|
||||||
if (!/^https?$/.test(readerURI.scheme)) {
|
|
||||||
// Don't try to get a favicon for non http(s) URIs.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let faviconURI = makeURI(readerURI.prePath + "/favicon.ico");
|
|
||||||
let self = this;
|
|
||||||
let usePrivateBrowsing = this._window.QueryInterface(Ci.nsIInterfaceRequestor)
|
|
||||||
.getInterface(Ci.nsIWebNavigation)
|
|
||||||
.QueryInterface(Ci.nsIDocShell)
|
|
||||||
.QueryInterface(Ci.nsILoadContext)
|
|
||||||
.usePrivateBrowsing;
|
|
||||||
let nullPrincipal = Cc["@mozilla.org/nullprincipal;1"]
|
|
||||||
.createInstance(Ci.nsIPrincipal);
|
|
||||||
this._faviconService.setAndFetchFaviconForPage(readerURI, faviconURI, false,
|
|
||||||
usePrivateBrowsing ? this._faviconService.FAVICON_LOAD_PRIVATE
|
|
||||||
: this._faviconService.FAVICON_LOAD_NON_PRIVATE,
|
|
||||||
function (aURI, aDataLen, aData, aMimeType) {
|
|
||||||
if (aDataLen > 0) {
|
|
||||||
let dataURL = "data:" + aMimeType + ";base64," +
|
|
||||||
btoa(String.fromCharCode.apply(null, aData));
|
|
||||||
aMenuItem.setAttribute('image', dataURL);
|
|
||||||
}
|
|
||||||
}, nullPrincipal);
|
|
||||||
},
|
|
||||||
|
|
||||||
get _mm() {
|
get _mm() {
|
||||||
let mm = this._window.QueryInterface(Ci.nsIInterfaceRequestor).
|
let mm = this._window.QueryInterface(Ci.nsIInterfaceRequestor).
|
||||||
getInterface(Ci.nsIDocShell).
|
getInterface(Ci.nsIDocShell).
|
||||||
|
@ -12,6 +12,7 @@ var Cu = Components.utils;
|
|||||||
|
|
||||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
Cu.import("resource://gre/modules/Services.jsm");
|
Cu.import("resource://gre/modules/Services.jsm");
|
||||||
|
Cu.import("resource://gre/modules/Timer.jsm");
|
||||||
|
|
||||||
Cu.import("resource://gre/modules/PlacesUtils.jsm");
|
Cu.import("resource://gre/modules/PlacesUtils.jsm");
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
|
XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
|
||||||
@ -37,6 +38,11 @@ XPCOMUtils.defineLazyModuleGetter(this, "CloudSync",
|
|||||||
XPCOMUtils.defineLazyModuleGetter(this, "Weave",
|
XPCOMUtils.defineLazyModuleGetter(this, "Weave",
|
||||||
"resource://services-sync/main.js");
|
"resource://services-sync/main.js");
|
||||||
|
|
||||||
|
const gInContentProcess = Services.appinfo.processType == Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT;
|
||||||
|
const FAVICON_REQUEST_TIMEOUT = 60 * 1000;
|
||||||
|
// Map from windows to arrays of data about pending favicon loads.
|
||||||
|
let gFaviconLoadDataMap = new Map();
|
||||||
|
|
||||||
// copied from utilityOverlay.js
|
// copied from utilityOverlay.js
|
||||||
const TAB_DROP_TYPE = "application/x-moz-tabbrowser-tab";
|
const TAB_DROP_TYPE = "application/x-moz-tabbrowser-tab";
|
||||||
|
|
||||||
@ -77,6 +83,149 @@ function IsLivemark(aItemId) {
|
|||||||
return self.ids.has(aItemId);
|
return self.ids.has(aItemId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let InternalFaviconLoader = {
|
||||||
|
/**
|
||||||
|
* This gets called for every inner window that is destroyed.
|
||||||
|
* In the parent process, we process the destruction ourselves. In the child process,
|
||||||
|
* we notify the parent which will then process it based on that message.
|
||||||
|
*/
|
||||||
|
observe(subject, topic, data) {
|
||||||
|
let innerWindowID = subject.QueryInterface(Ci.nsISupportsPRUint64).data;
|
||||||
|
this.onInnerDestroyed(innerWindowID);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Actually cancel the request, and clear the timeout for cancelling it.
|
||||||
|
*/
|
||||||
|
_cancelRequest({uri, innerWindowID, timerID, callback}, reason) {
|
||||||
|
// Break cycle
|
||||||
|
let request = callback.request;
|
||||||
|
delete callback.request;
|
||||||
|
// Ensure we don't time out.
|
||||||
|
clearTimeout(timerID);
|
||||||
|
try {
|
||||||
|
request.cancel();
|
||||||
|
} catch (ex) {
|
||||||
|
Cu.reportError("When cancelling a request for " + uri.spec + " because " + reason + ", it was already canceled!");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called for every inner that gets destroyed, only in the parent process.
|
||||||
|
*/
|
||||||
|
onInnerDestroyed(innerID) {
|
||||||
|
for (let [window, loadDataForWindow] of gFaviconLoadDataMap) {
|
||||||
|
let newLoadDataForWindow = loadDataForWindow.filter(loadData => {
|
||||||
|
let innerWasDestroyed = loadData.innerWindowID == innerID;
|
||||||
|
if (innerWasDestroyed) {
|
||||||
|
this._cancelRequest(loadData, "the inner window was destroyed");
|
||||||
|
}
|
||||||
|
// Keep the items whose inner is still alive.
|
||||||
|
return !innerWasDestroyed;
|
||||||
|
});
|
||||||
|
// Map iteration with for...of is safe against modification, so
|
||||||
|
// now just replace the old value:
|
||||||
|
gFaviconLoadDataMap.set(window, newLoadDataForWindow);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when a toplevel chrome window unloads. We use this to tidy up after ourselves,
|
||||||
|
* avoid leaks, and cancel any remaining requests. The last part should in theory be
|
||||||
|
* handled by the inner-window-destroyed handlers. We clean up just to be on the safe side.
|
||||||
|
*/
|
||||||
|
onUnload(win) {
|
||||||
|
let loadDataForWindow = gFaviconLoadDataMap.get(win);
|
||||||
|
if (loadDataForWindow) {
|
||||||
|
for (let loadData of loadDataForWindow) {
|
||||||
|
this._cancelRequest(loadData, "the chrome window went away");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gFaviconLoadDataMap.delete(win);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a function to use as a nsIFaviconDataCallback, so we can remove cancelling
|
||||||
|
* information when the request succeeds. Note that right now there are some edge-cases,
|
||||||
|
* such as about: URIs with chrome:// favicons where the success callback is not invoked.
|
||||||
|
* This is OK: we will 'cancel' the request after the timeout (or when the window goes
|
||||||
|
* away) but that will be a no-op in such cases.
|
||||||
|
*/
|
||||||
|
_makeCompletionCallback(win, id) {
|
||||||
|
return {
|
||||||
|
onComplete(uri) {
|
||||||
|
let loadDataForWindow = gFaviconLoadDataMap.get(win);
|
||||||
|
if (loadDataForWindow) {
|
||||||
|
let itemIndex = loadDataForWindow.findIndex(loadData => {
|
||||||
|
return loadData.innerWindowID == id &&
|
||||||
|
loadData.uri.equals(uri) &&
|
||||||
|
loadData.callback.request == this.request;
|
||||||
|
});
|
||||||
|
if (itemIndex != -1) {
|
||||||
|
let loadData = loadDataForWindow[itemIndex];
|
||||||
|
clearTimeout(loadData.timerID);
|
||||||
|
loadDataForWindow.splice(itemIndex, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete this.request;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
ensureInitialized() {
|
||||||
|
if (this._initialized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._initialized = true;
|
||||||
|
|
||||||
|
Services.obs.addObserver(this, "inner-window-destroyed", false);
|
||||||
|
Services.ppmm.addMessageListener("Toolkit:inner-window-destroyed", msg => {
|
||||||
|
this.onInnerDestroyed(msg.data);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
loadFavicon(browser, principal, uri) {
|
||||||
|
this.ensureInitialized();
|
||||||
|
let win = browser.ownerDocument.defaultView;
|
||||||
|
if (!gFaviconLoadDataMap.has(win)) {
|
||||||
|
gFaviconLoadDataMap.set(win, []);
|
||||||
|
let unloadHandler = event => {
|
||||||
|
let doc = event.target;
|
||||||
|
let eventWin = doc.defaultview;
|
||||||
|
if (win == win.top && doc.documentURI != "about:blank") {
|
||||||
|
win.removeEventListener("unload", unloadHandler);
|
||||||
|
this.onUnload(win);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
win.addEventListener("unload", unloadHandler, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// First we do the actual setAndFetch call:
|
||||||
|
let {innerWindowID, currentURI} = browser;
|
||||||
|
let loadType = PrivateBrowsingUtils.isWindowPrivate(win)
|
||||||
|
? PlacesUtils.favicons.FAVICON_LOAD_PRIVATE
|
||||||
|
: PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE;
|
||||||
|
let callback = this._makeCompletionCallback(win, innerWindowID);
|
||||||
|
let request = PlacesUtils.favicons.setAndFetchFaviconForPage(currentURI, uri, false,
|
||||||
|
loadType, callback, principal);
|
||||||
|
|
||||||
|
// Now register the result so we can cancel it if/when necessary.
|
||||||
|
if (!request) {
|
||||||
|
// The favicon service can return with success but no-op (and leave request
|
||||||
|
// as null) if the icon is the same as the page (e.g. for images) or if it is
|
||||||
|
// the favicon for an error page. In this case, we do not need to do anything else.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
callback.request = request;
|
||||||
|
let loadData = {innerWindowID, uri, callback};
|
||||||
|
loadData.timerID = setTimeout(() => {
|
||||||
|
this._cancelRequest(loadData, "it timed out");
|
||||||
|
}, FAVICON_REQUEST_TIMEOUT);
|
||||||
|
let loadDataForWindow = gFaviconLoadDataMap.get(win);
|
||||||
|
loadDataForWindow.push(loadData);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
this.PlacesUIUtils = {
|
this.PlacesUIUtils = {
|
||||||
ORGANIZER_LEFTPANE_VERSION: 7,
|
ORGANIZER_LEFTPANE_VERSION: 7,
|
||||||
ORGANIZER_FOLDER_ANNO: "PlacesOrganizer/OrganizerFolder",
|
ORGANIZER_FOLDER_ANNO: "PlacesOrganizer/OrganizerFolder",
|
||||||
@ -481,6 +630,19 @@ this.PlacesUIUtils = {
|
|||||||
return RecentWindow.getMostRecentBrowserWindow();
|
return RecentWindow.getMostRecentBrowserWindow();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set and fetch a favicon. Can only be used from the parent process.
|
||||||
|
* @param browser {Browser} The XUL browser element for which we're fetching a favicon.
|
||||||
|
* @param principal {Principal} The loading principal to use for the fetch.
|
||||||
|
* @param uri {URI} The URI to fetch.
|
||||||
|
*/
|
||||||
|
loadFavicon(browser, principal, uri) {
|
||||||
|
if (gInContentProcess) {
|
||||||
|
throw new Error("Can't track loads from within the child process!");
|
||||||
|
}
|
||||||
|
InternalFaviconLoader.loadFavicon(browser, principal, uri);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the closet ancestor places view for the given DOM node
|
* Returns the closet ancestor places view for the given DOM node
|
||||||
* @param aNode
|
* @param aNode
|
||||||
|
@ -605,7 +605,9 @@ AsyncFetchAndSetIconForPage::AsyncOnChannelRedirect(
|
|||||||
, nsIAsyncVerifyRedirectCallback *cb
|
, nsIAsyncVerifyRedirectCallback *cb
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
(void)cb->OnRedirectVerifyCallback(NS_OK);
|
// If we've been canceled, stop the redirect with NS_BINDING_ABORTED, and
|
||||||
|
// handle the cancel on the original channel.
|
||||||
|
(void)cb->OnRedirectVerifyCallback(mCanceled ? NS_BINDING_ABORTED : NS_OK);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,9 +12,21 @@ var { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
|||||||
Cu.import("resource://gre/modules/RemotePageManager.jsm");
|
Cu.import("resource://gre/modules/RemotePageManager.jsm");
|
||||||
Cu.import("resource://gre/modules/Services.jsm");
|
Cu.import("resource://gre/modules/Services.jsm");
|
||||||
|
|
||||||
|
const gInContentProcess = Services.appinfo.processType == Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT;
|
||||||
|
|
||||||
Services.cpmm.addMessageListener("gmp-plugin-crash", msg => {
|
Services.cpmm.addMessageListener("gmp-plugin-crash", msg => {
|
||||||
let gmpservice = Cc["@mozilla.org/gecko-media-plugin-service;1"]
|
let gmpservice = Cc["@mozilla.org/gecko-media-plugin-service;1"]
|
||||||
.getService(Ci.mozIGeckoMediaPluginService);
|
.getService(Ci.mozIGeckoMediaPluginService);
|
||||||
|
|
||||||
gmpservice.RunPluginCrashCallbacks(msg.data.pluginID, msg.data.pluginName);
|
gmpservice.RunPluginCrashCallbacks(msg.data.pluginID, msg.data.pluginName);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Forward inner-window-destroyed notifications with the inner window ID,
|
||||||
|
// so that code in the parent that should do something when content
|
||||||
|
// windows go away can do it
|
||||||
|
if (gInContentProcess) {
|
||||||
|
Services.obs.addObserver((subject, topic, data) => {
|
||||||
|
let innerWindowID = subject.QueryInterface(Ci.nsISupportsPRUint64).data;
|
||||||
|
Services.cpmm.sendAsyncMessage("Toolkit:inner-window-destroyed", innerWindowID);
|
||||||
|
}, "inner-window-destroyed", false);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user