Merge mozilla-central to inbound. a=merge CLOSED TREE

This commit is contained in:
Oana Pop Rus 2019-05-29 01:12:31 +03:00
commit 93d39a5bc3
359 changed files with 5558 additions and 4085 deletions

View File

@ -25,7 +25,6 @@ exclude =
python/devtools/migrate-l10n/migrate/main.py,
python/l10n/fluent_migrations,
python/mozbuild/dumbmake,
python/mozbuild/mozbuild,
servo/components/style,
testing/jsshell/benchmark.py,
testing/marionette/mach_commands.py,
@ -69,6 +68,7 @@ exclude =
memory/moz.configure,
mobile/android/*.configure,
node_modules,
python/mozbuild/mozbuild/test/configure/data,
security/nss/,
testing/marionette/harness/marionette_harness/runner/mixins,
testing/marionette/harness/marionette_harness/tests,
@ -92,6 +92,8 @@ ignore =
per-file-ignores =
ipc/ipdl/*: F403, F405
# cpp_eclipse has a lot of multi-line embedded XML which exceeds line length
python/mozbuild/mozbuild/backend/cpp_eclipse.py: E501
testing/firefox-ui/**/__init__.py: F401
testing/marionette/**/__init__.py: F401
testing/mozharness/configs/*: E124, E127, E128, E131, E231, E261, E265, E266, E501, W391

View File

@ -503,8 +503,13 @@ pref("browser.tabs.delayHidingAudioPlayingIconMS", 3000);
pref("browser.tabs.remote.separatePrivilegedContentProcess", true);
#endif
// Turn on HTTP response process selection.
#ifdef NIGHTLY_BUILD
pref("browser.tabs.remote.useHTTPResponseProcessSelection", true);
#else
// Disabled outside of nightly due to bug 1554217
pref("browser.tabs.remote.useHTTPResponseProcessSelection", false);
#endif
// Unload tabs when available memory is running low
pref("browser.tabs.unloadOnLowMemory", true);

View File

@ -1440,6 +1440,10 @@ var gBrowserInit = {
}
}
if (Services.prefs.getBoolPref("toolkit.legacyUserProfileCustomizations.windowIcon", false)) {
document.documentElement.setAttribute("icon", "main-window");
}
// Call this after we set attributes that might change toolbars' computed
// text color.
ToolbarIconColor.init();
@ -8061,7 +8065,7 @@ var RestoreLastSessionObserver = {
!PrivateBrowsingUtils.isWindowPrivate(window)) {
Services.obs.addObserver(this, "sessionstore-last-session-cleared", true);
goSetCommandEnabled("Browser:RestoreLastSession", true);
} else if (SessionStartup.isAutomaticRestoreEnabled()) {
} else if (SessionStore.willAutoRestore) {
document.getElementById("Browser:RestoreLastSession").setAttribute("hidden", true);
}
},

View File

@ -416,6 +416,7 @@ XPCOMUtils.defineLazyGetter(this, "WeaveService", () =>
// lazy module getters
XPCOMUtils.defineLazyModuleGetters(this, {
AboutCertViewerHandler: "resource://gre/modules/AboutCertViewerHandler.jsm",
AboutNetErrorHandler: "resource:///modules/aboutpages/AboutNetErrorHandler.jsm",
AboutPrivateBrowsingHandler: "resource:///modules/aboutpages/AboutPrivateBrowsingHandler.jsm",
AboutProtectionsHandler: "resource:///modules/aboutpages/AboutProtectionsHandler.jsm",
@ -1386,6 +1387,8 @@ BrowserGlue.prototype = {
NewTabUtils.init();
AboutCertViewerHandler.init();
AboutNetErrorHandler.init();
AboutPrivateBrowsingHandler.init();
@ -1538,6 +1541,7 @@ BrowserGlue.prototype = {
PageThumbs.uninit();
NewTabUtils.uninit();
AboutCertViewerHandler.uninit();
AboutNetErrorHandler.uninit();
AboutPrivateBrowsingHandler.uninit();
AboutProtectionsHandler.uninit();

View File

@ -35,7 +35,6 @@ XPCOMUtils.defineLazyServiceGetter(this, "Telemetry",
XPCOMUtils.defineLazyModuleGetters(this, {
RunState: "resource:///modules/sessionstore/RunState.jsm",
SessionStartup: "resource:///modules/sessionstore/SessionStartup.jsm",
SessionStore: "resource:///modules/sessionstore/SessionStore.jsm",
SessionWorker: "resource:///modules/sessionstore/SessionWorker.jsm",
});
@ -382,8 +381,7 @@ var SessionFileInternal = {
RunState.setClosed();
}
let performShutdownCleanup = isFinalWrite &&
!SessionStartup.isAutomaticRestoreEnabled();
let performShutdownCleanup = isFinalWrite && !SessionStore.willAutoRestore;
this._attempts++;
let options = {isFinalWrite, performShutdownCleanup};

View File

@ -155,6 +155,9 @@ const RESTORE_TAB_CONTENT_REASON = {
NAVIGATE_AND_RESTORE: 1,
};
// 'browser.startup.page' preference value to resume the previous session.
const BROWSER_STARTUP_RESUME_SESSION = 3;
ChromeUtils.import("resource://gre/modules/PrivateBrowsingUtils.jsm", this);
ChromeUtils.import("resource://gre/modules/Services.jsm", this);
ChromeUtils.import("resource://gre/modules/TelemetryTimestamps.jsm", this);
@ -233,6 +236,10 @@ var SessionStore = {
return SessionStoreInternal.lastClosedObjectType;
},
get willAutoRestore() {
return SessionStoreInternal.willAutoRestore;
},
init: function ss_init() {
SessionStoreInternal.init();
},
@ -619,6 +626,16 @@ var SessionStoreInternal = {
return "tab";
},
/**
* Returns a boolean that determines whether the session will be automatically
* restored upon the _next_ startup or a restart.
*/
get willAutoRestore() {
return !PrivateBrowsingUtils.permanentPrivateBrowsing &&
(Services.prefs.getBoolPref("browser.sessionstore.resume_session_once") ||
Services.prefs.getIntPref("browser.startup.page") == BROWSER_STARTUP_RESUME_SESSION);
},
/**
* Initialize the sessionstore service.
*/

View File

@ -306,6 +306,7 @@ early_options = early_options()
# This gives access to the sandbox. Don't copy this blindly.
@imports('__sandbox__')
@imports('os')
@imports('six')
def mozconfig_options(mozconfig, automation, help):
if mozconfig['path']:
if 'MOZ_AUTOMATION_MOZCONFIG' in mozconfig['env']['added']:
@ -331,15 +332,15 @@ def mozconfig_options(mozconfig, automation, help):
log.info(' %s' % arg)
helper.add(arg, origin='mozconfig', args=helper._args)
for key, value in mozconfig['env']['added'].iteritems():
for key, value in six.iteritems(mozconfig['env']['added']):
add(key, value)
os.environ[key] = value
for key, (_, value) in mozconfig['env']['modified'].iteritems():
for key, (_, value) in six.iteritems(mozconfig['env']['modified']):
add(key, value)
os.environ[key] = value
for key, value in mozconfig['vars']['added'].iteritems():
for key, value in six.iteritems(mozconfig['vars']['added']):
add(key, value)
for key, (_, value) in mozconfig['vars']['modified'].iteritems():
for key, (_, value) in six.iteritems(mozconfig['vars']['modified']):
add(key, value)

View File

@ -63,18 +63,13 @@ if __name__ == '__main__':
for path in prefpaths:
prefs.update(Preferences.read_prefs(path))
interpolation = {"server": "%s:%d" % httpd.httpd.server_address}
interpolation = {"server": "%s:%d" % httpd.httpd.server_address,
"OOP": "false"}
for k, v in prefs.items():
if isinstance(v, string_types):
v = v.format(**interpolation)
prefs[k] = Preferences.cast(v)
# Enforce e10s. This isn't in one of the user.js files because those
# are shared with android, which doesn't want this on. We can't
# interpolate because the formatting code only works for strings,
# and this is a bool pref.
prefs["browser.tabs.remote.autostart"] = True
profile = FirefoxProfile(profile=profilePath,
preferences=prefs,
addons=[os.path.join(
@ -85,9 +80,10 @@ if __name__ == '__main__':
env = os.environ.copy()
env["MOZ_CRASHREPORTER_NO_REPORT"] = "1"
env["XPCOM_DEBUG_BREAK"] = "warn"
# We disable sandboxing to make writing profiling data actually work
# Bug 1553850 considers fixing this.
env["MOZ_DISABLE_CONTENT_SANDBOX"] = "1"
# TODO should use e10s and gather data from all processes (bug 1196094).
# Note that unittest-required/user.js sets the autostart pref, but it
# is ignored by the code in nsAppRunner.
env["MOZ_FORCE_DISABLE_E10S"] = "1"
# For VC12+, make sure we can find the right bitness of pgort1x0.dll
if not substs.get('HAVE_64BIT_BUILD'):

View File

@ -63,13 +63,6 @@ nsChromeProtocolHandler::GetProtocolFlags(uint32_t* result) {
return NS_OK;
}
NS_IMETHODIMP
nsChromeProtocolHandler::NewURI(const nsACString& aSpec, const char* aCharset,
nsIURI* aBaseURI, nsIURI** result) {
return nsChromeProtocolHandler::CreateNewURI(aSpec, aCharset, aBaseURI,
result);
}
/* static */ nsresult nsChromeProtocolHandler::CreateNewURI(
const nsACString& aSpec, const char* aCharset, nsIURI* aBaseURI,
nsIURI** result) {

View File

@ -20,16 +20,6 @@ ProtocolHandler.prototype =
{
defaultPort: -1,
allowPort: () => false,
newURI(aSpec, aCharset, aBaseURI) {
let mutator = Cc["@mozilla.org/network/standard-url-mutator;1"]
.createInstance(Ci.nsIURIMutator);
if (aBaseURI) {
mutator.setSpec(aBaseURI.resolve(aSpec));
} else {
mutator.setSpec(aSpec);
}
return mutator.finalize();
},
newChannel() { throw Cr.NS_ERROR_NOT_IMPLEMENTED; },
QueryInterface: ChromeUtils.generateQI([
Ci.nsIProtocolHandler,

View File

@ -6,7 +6,10 @@
# longer present in a complete update. The current working directory is used for
# the location to enumerate and to create the precomplete file.
from __future__ import unicode_literals
import os
import io
def get_build_entries(root_path):
@ -54,13 +57,13 @@ def generate_precomplete(root_path):
precomplete_file_path = os.path.join(root_path, rel_path_precomplete)
# Open the file so it exists before building the list of files and open it
# in binary mode to prevent OS specific line endings.
precomplete_file = open(precomplete_file_path, "wb")
precomplete_file = io.open(precomplete_file_path, mode="wt", newline='\n')
rel_file_path_list, rel_dir_path_list = get_build_entries(root_path)
for rel_file_path in rel_file_path_list:
precomplete_file.writelines("remove \""+rel_file_path+"\"\n")
precomplete_file.write("remove \""+rel_file_path+"\"\n")
for rel_dir_path in rel_dir_path_list:
precomplete_file.writelines("rmdir \""+rel_dir_path+"\"\n")
precomplete_file.write("rmdir \""+rel_dir_path+"\"\n")
precomplete_file.close()

View File

@ -14,6 +14,7 @@ import textwrap
base_dir = os.path.abspath(os.path.dirname(__file__))
sys.path.insert(0, os.path.join(base_dir, 'python', 'mozbuild'))
sys.path.insert(0, os.path.join(base_dir, 'third_party', 'python', 'six'))
from mozbuild.configure import (
ConfigureSandbox,
TRACE,

View File

@ -53,6 +53,7 @@ type State = {
selectedResultIndex: number,
count: number,
index: number,
inputFocused: boolean,
};
type Props = {
@ -82,6 +83,7 @@ class SearchBar extends Component<Props, State> {
selectedResultIndex: 0,
count: 0,
index: -1,
inputFocused: false,
};
}
@ -146,7 +148,7 @@ class SearchBar extends Component<Props, State> {
e.stopPropagation();
e.preventDefault();
}
this.setState({ query: "" });
this.setState({ query: "", inputFocused: false });
};
toggleSearch = (e: SyntheticKeyboardEvent<HTMLElement>) => {
@ -162,10 +164,10 @@ class SearchBar extends Component<Props, State> {
const query = editor.codeMirror.getSelection() || this.state.query;
if (query !== "") {
this.setState({ query });
this.setState({ query, inputFocused: true });
this.doSearch(query);
} else {
this.setState({ query: "" });
this.setState({ query: "", inputFocused: true });
}
}
};
@ -198,6 +200,14 @@ class SearchBar extends Component<Props, State> {
return this.doSearch(e.target.value);
};
onFocus = (e: SyntheticFocusEvent<HTMLElement>) => {
this.setState({ inputFocused: true });
};
onBlur = (e: SyntheticFocusEvent<HTMLElement>) => {
this.setState({ inputFocused: false });
};
onKeyDown = (e: any) => {
if (e.key !== "Enter" && e.key !== "F3") {
return;
@ -320,11 +330,14 @@ class SearchBar extends Component<Props, State> {
summaryMsg={this.buildSummaryMsg()}
isLoading={false}
onChange={this.onChange}
onFocus={this.onFocus}
onBlur={this.onBlur}
showErrorEmoji={this.shouldShowErrorEmoji()}
onKeyDown={this.onKeyDown}
onHistoryScroll={this.onHistoryScroll}
handleNext={e => this.traverseResults(e, false)}
handlePrev={e => this.traverseResults(e, true)}
shouldFocus={this.state.inputFocused}
showClose={false}
/>
<div className="search-bottom-bar">

View File

@ -10,12 +10,15 @@ exports[`SearchBar should render 1`] = `
handlePrev={[Function]}
hasPrefix={false}
isLoading={false}
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onHistoryScroll={[Function]}
onKeyDown={[Function]}
placeholder="Find in file…"
query=""
selectedItemId=""
shouldFocus={false}
showClose={false}
showErrorEmoji={false}
size=""
@ -80,12 +83,15 @@ exports[`showErrorEmoji false if no query + no results 1`] = `
handlePrev={[Function]}
hasPrefix={false}
isLoading={false}
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onHistoryScroll={[Function]}
onKeyDown={[Function]}
placeholder="Find in file…"
query=""
selectedItemId=""
shouldFocus={false}
showClose={false}
showErrorEmoji={false}
size=""
@ -148,12 +154,15 @@ exports[`showErrorEmoji false if query + results 1`] = `
handlePrev={[Function]}
hasPrefix={false}
isLoading={false}
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onHistoryScroll={[Function]}
onKeyDown={[Function]}
placeholder="Find in file…"
query="test"
selectedItemId=""
shouldFocus={false}
showClose={false}
showErrorEmoji={false}
size=""
@ -216,12 +225,15 @@ exports[`showErrorEmoji true if query + no results 1`] = `
handlePrev={[Function]}
hasPrefix={false}
isLoading={false}
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onHistoryScroll={[Function]}
onKeyDown={[Function]}
placeholder="Find in file…"
query="test"
selectedItemId=""
shouldFocus={false}
showClose={false}
showErrorEmoji={true}
size=""

View File

@ -56,6 +56,7 @@ type Item = Result | Match;
type State = {
inputValue: string,
inputFocused: boolean,
focusedItem: ?Item,
};
@ -89,6 +90,7 @@ export class ProjectSearch extends Component<Props, State> {
super(props);
this.state = {
inputValue: this.props.query || "",
inputFocused: false,
focusedItem: null,
};
}
@ -177,7 +179,11 @@ export class ProjectSearch extends Component<Props, State> {
};
onEnterPress = () => {
if (!this.isProjectSearchEnabled() || !this.state.focusedItem) {
if (
!this.isProjectSearchEnabled() ||
!this.state.focusedItem ||
this.state.inputFocused
) {
return;
}
if (this.state.focusedItem.type === "MATCH") {
@ -295,6 +301,8 @@ export class ProjectSearch extends Component<Props, State> {
summaryMsg={this.renderSummary()}
isLoading={status === statusType.fetching}
onChange={this.inputOnChange}
onFocus={() => this.setState({ inputFocused: true })}
onBlur={() => this.setState({ inputFocused: false })}
onKeyDown={this.onKeyDown}
onHistoryScroll={this.onHistoryScroll}
handleClose={

View File

@ -22,6 +22,7 @@ import {
isSymbolsLoading,
getContext,
} from "../selectors";
import { memoizeLast } from "../utils/memoizeLast";
import { scrollList } from "../utils/result-list";
import {
formatSymbols,
@ -131,11 +132,15 @@ export class QuickOpenModal extends Component<Props, State> {
return query.split(":")[0];
};
formatSources = memoizeLast((displayedSources, tabs) => {
const tabUrls = new Set(tabs.map((tab: Tab) => tab.url));
return formatSources(displayedSources, tabUrls);
});
searchSources = (query: string) => {
const { displayedSources, tabs } = this.props;
const tabUrls = new Set(tabs.map((tab: Tab) => tab.url));
const sources = formatSources(displayedSources, tabUrls);
const sources = this.formatSources(displayedSources, tabs);
const results =
query == "" ? sources : filter(sources, this.dropGoto(query));
return this.setResults(results);

View File

@ -35,13 +35,16 @@ type Props = {
handleNext?: (e: SyntheticMouseEvent<HTMLButtonElement>) => void,
handlePrev?: (e: SyntheticMouseEvent<HTMLButtonElement>) => void,
hasPrefix?: boolean,
onBlur?: (e: SyntheticFocusEvent<HTMLInputElement>) => void,
onChange: (e: SyntheticInputEvent<HTMLInputElement>) => void,
onFocus?: (e: SyntheticFocusEvent<HTMLInputElement>) => void,
onKeyDown: (e: SyntheticKeyboardEvent<HTMLInputElement>) => void,
onKeyUp?: (e: SyntheticKeyboardEvent<HTMLInputElement>) => void,
onHistoryScroll?: (historyValue: string) => void,
placeholder: string,
query: string,
selectedItemId?: string,
shouldFocus?: boolean,
showErrorEmoji: boolean,
size: string,
summaryMsg: string,
@ -77,6 +80,12 @@ class SearchInput extends Component<Props, State> {
this.setFocus();
}
componentDidUpdate(prevProps: Props) {
if (this.props.shouldFocus && !prevProps.shouldFocus) {
this.setFocus();
}
}
setFocus() {
if (this.$input) {
const input = this.$input;
@ -115,6 +124,22 @@ class SearchInput extends Component<Props, State> {
];
}
onFocus = (e: SyntheticFocusEvent<HTMLInputElement>) => {
const { onFocus } = this.props;
if (onFocus) {
onFocus(e);
}
};
onBlur = (e: SyntheticFocusEvent<HTMLInputElement>) => {
const { onBlur } = this.props;
if (onBlur) {
onBlur(e);
}
};
onKeyDown = (e: any) => {
const { onHistoryScroll, onKeyDown } = this.props;
if (!onHistoryScroll) {
@ -209,6 +234,8 @@ class SearchInput extends Component<Props, State> {
onChange,
onKeyDown: e => this.onKeyDown(e),
onKeyUp,
onFocus: e => this.onFocus(e),
onBlur: e => this.onBlur(e),
"aria-autocomplete": "list",
"aria-controls": "result-list",
"aria-activedescendant":

View File

@ -19,7 +19,9 @@ exports[`SearchInput renders 1`] = `
aria-autocomplete="list"
aria-controls="result-list"
className=""
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder="A placeholder"
spellCheck={false}
@ -56,7 +58,9 @@ exports[`SearchInput shows nav buttons 1`] = `
aria-autocomplete="list"
aria-controls="result-list"
className=""
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder="A placeholder"
spellCheck={false}
@ -119,7 +123,9 @@ exports[`SearchInput shows svg error emoji 1`] = `
aria-autocomplete="list"
aria-controls="result-list"
className="empty"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder="A placeholder"
spellCheck={false}
@ -182,7 +188,9 @@ exports[`SearchInput shows svg magnifying glass 1`] = `
aria-autocomplete="list"
aria-controls="result-list"
className=""
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder="A placeholder"
spellCheck={false}

View File

@ -16,7 +16,9 @@ exports[`ProjectSearch found no search results 1`] = `
handleClose={[MockFunction]}
hasPrefix={false}
isLoading={false}
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onHistoryScroll={[Function]}
onKeyDown={[Function]}
placeholder="Find in files…"
@ -117,7 +119,9 @@ exports[`ProjectSearch found search results 1`] = `
handleClose={[MockFunction]}
hasPrefix={false}
isLoading={false}
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onHistoryScroll={[Function]}
onKeyDown={[Function]}
placeholder="Find in files…"
@ -150,7 +154,9 @@ exports[`ProjectSearch found search results 1`] = `
aria-autocomplete="list"
aria-controls="result-list"
className=""
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder="Find in files…"
spellCheck={false}
@ -744,7 +750,9 @@ exports[`ProjectSearch should display loading message while search is in progres
handleClose={[MockFunction]}
hasPrefix={false}
isLoading={true}
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onHistoryScroll={[Function]}
onKeyDown={[Function]}
placeholder="Find in files…"
@ -781,7 +789,9 @@ exports[`ProjectSearch showErrorEmoji false if not done & no results 1`] = `
handleClose={[MockFunction]}
hasPrefix={false}
isLoading={true}
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onHistoryScroll={[Function]}
onKeyDown={[Function]}
placeholder="Find in files…"
@ -818,7 +828,9 @@ exports[`ProjectSearch showErrorEmoji false if not done & results 1`] = `
handleClose={[MockFunction]}
hasPrefix={false}
isLoading={true}
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onHistoryScroll={[Function]}
onKeyDown={[Function]}
placeholder="Find in files…"
@ -863,7 +875,9 @@ exports[`ProjectSearch turns off shortcuts on unmount 1`] = `
handleClose={[MockFunction]}
hasPrefix={false}
isLoading={false}
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onHistoryScroll={[Function]}
onKeyDown={[Function]}
placeholder="Find in files…"
@ -895,7 +909,9 @@ exports[`ProjectSearch where <Enter> has not been pressed 1`] = `
handleClose={[MockFunction]}
hasPrefix={false}
isLoading={false}
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onHistoryScroll={[Function]}
onKeyDown={[Function]}
placeholder="Find in files…"

View File

@ -98,7 +98,9 @@ exports[`QuickOpenModal Basic render with mount & searchType = functions 1`] = `
aria-autocomplete="list"
aria-controls="result-list"
className="empty"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder="Go to file…"
spellCheck={false}
@ -229,7 +231,9 @@ exports[`QuickOpenModal Basic render with mount & searchType = variables 1`] = `
aria-autocomplete="list"
aria-controls="result-list"
className="empty"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder="Go to file…"
spellCheck={false}
@ -343,7 +347,9 @@ exports[`QuickOpenModal Basic render with mount 1`] = `
aria-autocomplete="list"
aria-controls="result-list"
className=""
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder="Go to file…"
spellCheck={false}
@ -509,7 +515,9 @@ exports[`QuickOpenModal Simple goto search query = :abc & searchType = goto 1`]
aria-autocomplete="list"
aria-controls="result-list"
className="empty"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder="Go to file…"
spellCheck={false}
@ -628,7 +636,9 @@ exports[`QuickOpenModal showErrorEmoji false when count + query 1`] = `
aria-autocomplete="list"
aria-controls="result-list"
className=""
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder="Go to file…"
spellCheck={false}
@ -790,7 +800,9 @@ exports[`QuickOpenModal showErrorEmoji false when goto numeric ':2222' 1`] = `
aria-autocomplete="list"
aria-controls="result-list"
className=""
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder="Go to file…"
spellCheck={false}
@ -909,7 +921,9 @@ exports[`QuickOpenModal showErrorEmoji false when no query 1`] = `
aria-autocomplete="list"
aria-controls="result-list"
className=""
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder="Go to file…"
spellCheck={false}
@ -1039,7 +1053,9 @@ exports[`QuickOpenModal showErrorEmoji true when goto not numeric ':22k22' 1`] =
aria-autocomplete="list"
aria-controls="result-list"
className="empty"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder="Go to file…"
spellCheck={false}
@ -1158,7 +1174,9 @@ exports[`QuickOpenModal showErrorEmoji true when no count + query 1`] = `
aria-autocomplete="list"
aria-controls="result-list"
className="empty"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder="Go to file…"
spellCheck={false}
@ -1335,7 +1353,9 @@ exports[`QuickOpenModal updateResults on enable 2`] = `
aria-autocomplete="list"
aria-controls="result-list"
className=""
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder="Go to file…"
spellCheck={false}

View File

@ -0,0 +1,27 @@
/* 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/>. */
export function memoizeLast(fn) {
let lastArgs: any[];
let lastResult: any;
const memoized = (...args) => {
if (
lastArgs &&
args.length === lastArgs.length &&
args.every((arg, i) => arg === lastArgs[i])
) {
return lastResult;
}
lastArgs = args;
lastResult = fn(...args);
return lastResult;
};
return memoized;
}
export default memoizeLast;

View File

@ -33,6 +33,7 @@ CompiledModules(
'log.js',
'makeRecord.js',
'memoize.js',
'memoizeLast.js',
'memoizableAction.js',
'path.js',
'prefs.js',

View File

@ -0,0 +1,33 @@
/* 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/>. */
// @flow
import { memoizeLast } from "../memoizeLast";
const a = { number: 3 };
const b = { number: 4 };
function add(...numberObjects) {
return numberObjects.reduce((prev, cur) => prev + cur.number, 0);
}
describe("memozie", () => {
it("should re-calculate when a value changes", () => {
const mAdd = memoizeLast(add);
mAdd(a);
expect(mAdd(a)).toEqual(3);
mAdd(b);
expect(mAdd(b)).toEqual(4);
});
it("should only run once", () => {
const mockAdd = jest.fn(add);
const mAdd = memoizeLast(mockAdd);
mAdd(a);
mAdd(a);
expect(mockAdd.mock.calls[0]).toEqual([{ number: 3 }]);
});
});

View File

@ -64,4 +64,10 @@ add_task(async function() {
// selecting another source keeps search open
await selectSource(dbg, "simple2");
ok(findElement(dbg, "searchField"), "Search field is still visible");
// search is always focused regardless of when or how it was opened
pressKey(dbg, "fileSearch");
await clickElement(dbg, "codeMirror");
pressKey(dbg, "fileSearch");
is(dbg.win.document.activeElement.tagName, "INPUT", "Search field focused");
});

View File

@ -240,11 +240,15 @@ networkMenu.sizeCached=cached
# by a service worker.
networkMenu.sizeServiceWorker=service worker
# LOCALIZATION NOTE (networkMenu.sizeServiceWorker): This is the label displayed
# LOCALIZATION NOTE (networkMenu.blockedBy): This is the label displayed
# in the network menu specifying the request was blocked by something.
# %S is replaced by the blocked reason, which could be "DevTools", "CORS", etc.
networkMenu.blockedBy=blocked by %S
# LOCALIZATION NOTE (networkMenu.blocked): This is a generic message for a
# URL that has been blocked for an unknown reason
networkMenu.blocked=blocked
# LOCALIZATION NOTE (networkMenu.totalMS2): This is the label displayed
# in the network menu specifying the time for a request to finish (in milliseconds).
networkMenu.totalMS2=%S ms

View File

@ -10,6 +10,7 @@ const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const { getFormattedSize } = require("../utils/format-utils");
const { L10N } = require("../utils/l10n");
const { propertiesEqual } = require("../utils/request-utils");
const { BLOCKED_REASON_MESSAGES } = require("../constants");
const SIZE_CACHED = L10N.getStr("networkMenu.sizeCached");
const SIZE_SERVICE_WORKER = L10N.getStr("networkMenu.sizeServiceWorker");
@ -45,7 +46,7 @@ class RequestListColumnTransferredSize extends Component {
let text;
if (blockedReason) {
text = L10N.getFormatStr("networkMenu.blockedBy", blockedReason);
text = BLOCKED_REASON_MESSAGES[blockedReason] || L10N.getStr("networkMenu.blocked");
} else if (fromCache || status === "304") {
text = SIZE_CACHED;
} else if (fromServiceWorker) {

View File

@ -400,6 +400,41 @@ const SUPPORTED_HTTP_CODES = [
"511",
];
// Keys are the codes provided by server, values are localization messages
// prefixed by "netmonitor.blocked."
const BLOCKED_REASON_MESSAGES = {
devtools: "Blocked by DevTools",
1001: "CORS disabled",
1002: "CORS Failed",
1003: "CORS Not HTTP",
1004: "CORS Multiple Origin Not Allowed",
1005: "CORS Missing Allow Origin",
1006: "CORS No Allow Credentials",
1007: "CORS Allow Origin Not Matching Origin",
1008: "CORS Missing Allow Credentials",
1009: "CORS Origin Header Missing",
1010: "CORS External Redirect Not Allowed",
1011: "CORS Preflight Did Not Succeed",
1012: "CORS Invalid Allow Method",
1013: "CORS Method Not Found",
1014: "CORS Invalid Allow Header",
1015: "CORS Missing Allow Header",
2001: "Malware",
2002: "Phishing",
2003: "Unwanted",
2004: "Tracking",
2005: "Blocked",
2006: "Harmful",
3001: "Mixed Block",
4000: "CSP",
4001: "CSP No Data Protocol",
4002: "CSP Web Extension",
4003: "CSP ContentBlocked",
4004: "CSP Data Document",
4005: "CSP Web Browser",
4006: "CSP Preload",
};
const general = {
ACTIVITY_TYPE,
EVENTS,
@ -415,6 +450,7 @@ const general = {
MIN_COLUMN_WIDTH,
DEFAULT_COLUMN_WIDTH,
SUPPORTED_HTTP_CODES,
BLOCKED_REASON_MESSAGES,
};
// flatten constants

View File

@ -9,6 +9,7 @@ support-files =
html_brotli-test-page.html
html_image-tooltip-test-page.html
html_cors-test-page.html
html_csp-test-page.html
html_custom-get-page.html
html_cyrillic-test-page.html
html_frame-test-page.html
@ -77,6 +78,7 @@ support-files =
[browser_net_background_update.js]
[browser_net_autoscroll.js]
[browser_net_block.js]
[browser_net_block-csp.js]
[browser_net_cached-status.js]
skip-if = verify
[browser_net_cause.js]
@ -223,6 +225,7 @@ skip-if = true # TODO: fix the test
[browser_net_timing-division.js]
[browser_net_tracking-resources.js]
[browser_net_truncate-post-data.js]
skip-if = (os == 'win' && os_version == '6.1' && !debug) # Bug 1547150
[browser_net_truncate.js]
[browser_net_view-source-debugger.js]
[browser_net_waterfall-click.js]

View File

@ -0,0 +1,43 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
/**
* Test that CSP violations display in the netmonitor when blocked
*/
add_task(async function() {
const { tab, monitor } = await initNetMonitor(CSP_URL);
const { document, store, windowRequire } = monitor.panelWin;
const Actions = windowRequire("devtools/client/netmonitor/src/actions/index");
const {
getDisplayedRequests,
getSortedRequests,
} = windowRequire("devtools/client/netmonitor/src/selectors/index");
store.dispatch(Actions.batchEnable(false));
tab.linkedBrowser.reload();
await waitForNetworkEvents(monitor, 2);
info("Waiting until the requests appear in netmonitor");
// Ensure the attempt to load a JS file shows a blocked CSP error
verifyRequestItemTarget(
document,
getDisplayedRequests(store.getState()),
getSortedRequests(store.getState()).get(1),
"GET",
EXAMPLE_URL + "js_websocket-worker-test.js",
{
transferred: "CSP Preload",
cause: { type: "script" },
type: "",
}
);
await teardown(monitor);
});

View File

@ -87,13 +87,13 @@ add_task(async function() {
}
ok(!normalRequestState.blockedReason, "Normal request is not blocked");
ok(!normalRequestSize.includes("blocked"), "Normal request has a size");
ok(!normalRequestSize.includes("Blocked"), "Normal request has a size");
ok(blockedRequestState.blockedReason, "Blocked request is blocked");
ok(blockedRequestSize.includes("blocked"), "Blocked request shows reason as size");
ok(blockedRequestSize.includes("Blocked"), "Blocked request shows reason as size");
ok(!unblockedRequestState.blockedReason, "Unblocked request is not blocked");
ok(!unblockedRequestSize.includes("blocked"), "Unblocked request has a size");
ok(!unblockedRequestSize.includes("Blocked"), "Unblocked request has a size");
return teardown(monitor);
});

View File

@ -78,6 +78,7 @@ const SEND_BEACON_URL = EXAMPLE_URL + "html_send-beacon.html";
const CORS_URL = EXAMPLE_URL + "html_cors-test-page.html";
const PAUSE_URL = EXAMPLE_URL + "html_pause-test-page.html";
const OPEN_REQUEST_IN_TAB_URL = EXAMPLE_URL + "html_open-request-in-tab.html";
const CSP_URL = EXAMPLE_URL + "html_csp-test-page.html";
const SIMPLE_SJS = EXAMPLE_URL + "sjs_simple-test-server.sjs";
const SIMPLE_UNSORTED_COOKIES_SJS = EXAMPLE_URL + "sjs_simple-unsorted-cookies-test-server.sjs";

View File

@ -0,0 +1,17 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset=utf-8>
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<meta http-equiv="Content-Security-Policy" content="script-src 'none';">
<title>Tests breaking CSP with script</title>
</head>
<body>
The script in this page will CSP:
<script src="js_websocket-worker-test.js"></script>
</body>
</html>

View File

@ -262,12 +262,12 @@ NetworkObserver.prototype = {
}
const channel = subject.QueryInterface(Ci.nsIHttpChannel);
if (!matchRequest(channel, this.filters)) {
return;
}
"add your handling code here";
const blockedCode = channel.loadInfo.requestBlockingReason;
this._httpResponseExaminer(subject, topic, blockedCode);
},
/**
@ -279,7 +279,7 @@ NetworkObserver.prototype = {
* @param string topic
* @returns void
*/
_httpResponseExaminer: function(subject, topic) {
_httpResponseExaminer: function(subject, topic, blockedReason) {
// The httpResponseExaminer is used to retrieve the uncached response
// headers. The data retrieved is stored in openResponses. The
// NetworkResponseListener is responsible with updating the httpActivity
@ -287,7 +287,8 @@ NetworkObserver.prototype = {
if (!this.owner ||
(topic != "http-on-examine-response" &&
topic != "http-on-examine-cached-response") ||
topic != "http-on-examine-cached-response" &&
topic != "http-on-failed-opening-request") ||
!(subject instanceof Ci.nsIHttpChannel)) {
return;
}
@ -307,26 +308,28 @@ NetworkObserver.prototype = {
const setCookieHeaders = [];
channel.visitOriginalResponseHeaders({
visitHeader: function(name, value) {
const lowerName = name.toLowerCase();
if (lowerName == "set-cookie") {
setCookieHeaders.push(value);
}
response.headers.push({ name: name, value: value });
},
});
if (!blockedReason) {
channel.visitOriginalResponseHeaders({
visitHeader: function(name, value) {
const lowerName = name.toLowerCase();
if (lowerName == "set-cookie") {
setCookieHeaders.push(value);
}
response.headers.push({ name: name, value: value });
},
});
if (!response.headers.length) {
// No need to continue.
return;
}
if (!response.headers.length) {
// No need to continue.
return;
}
if (setCookieHeaders.length) {
response.cookies = setCookieHeaders.reduce((result, header) => {
const cookies = NetworkHelper.parseSetCookieHeader(header);
return result.concat(cookies);
}, []);
if (setCookieHeaders.length) {
response.cookies = setCookieHeaders.reduce((result, header) => {
const cookies = NetworkHelper.parseSetCookieHeader(header);
return result.concat(cookies);
}, []);
}
}
// Determine the HTTP version.
@ -334,14 +337,16 @@ NetworkObserver.prototype = {
const httpVersionMin = {};
channel.QueryInterface(Ci.nsIHttpChannelInternal);
channel.getResponseVersion(httpVersionMaj, httpVersionMin);
if (!blockedReason) {
channel.getResponseVersion(httpVersionMaj, httpVersionMin);
response.status = channel.responseStatus;
response.statusText = channel.responseStatusText;
response.httpVersion = "HTTP/" + httpVersionMaj.value + "." +
response.status = channel.responseStatus;
response.statusText = channel.responseStatusText;
response.httpVersion = "HTTP/" + httpVersionMaj.value + "." +
httpVersionMin.value;
this.openResponses.set(channel, response);
this.openResponses.set(channel, response);
}
if (topic === "http-on-examine-cached-response") {
// Service worker requests emits cached-response notification on non-e10s,
@ -370,6 +375,8 @@ NetworkObserver.prototype = {
const timings = this._setupHarTimings(httpActivity, true);
httpActivity.owner.addEventTimings(timings.total, timings.timings,
timings.offsets);
} else if (topic === "http-on-failed-opening-request") {
this._createNetworkEvent(channel, {blockedReason});
}
},
@ -506,7 +513,8 @@ NetworkObserver.prototype = {
*
*/
_createNetworkEvent: function(channel, { timestamp, extraStringData,
fromCache, fromServiceWorker }) {
fromCache, fromServiceWorker,
blockedReason }) {
const httpActivity = this.createOrGetActivityObject(channel);
channel.QueryInterface(Ci.nsIPrivateBrowsingChannel);
@ -596,9 +604,13 @@ NetworkObserver.prototype = {
// Check the request URL with ones manually blocked by the user in DevTools.
// If it's meant to be blocked, we cancel the request and annotate the event.
if (this.blockedURLs.has(httpActivity.url)) {
channel.cancel(Cr.NS_BINDING_ABORTED);
event.blockedReason = "DevTools";
if (!blockedReason) {
if (this.blockedURLs.has(httpActivity.url)) {
channel.cancel(Cr.NS_BINDING_ABORTED);
event.blockedReason = "devtools";
}
} else {
event.blockedReason = blockedReason;
}
httpActivity.owner = this.owner.onNetworkEvent(event);

View File

@ -138,9 +138,14 @@ class InactivePropertyHelper {
"vertical-align",
],
when: () => {
return !this.checkStyle("display", ["inline", "table-cell"]) &&
!this.cssRule.selectorText.includes("::first-letter") &&
!this.cssRule.selectorText.includes("::first-line");
const { selectorText } = this.cssRule;
const isFirstLetter = selectorText && selectorText.includes("::first-letter");
const isFirstLine = selectorText && selectorText.includes("::first-line");
const isInlineLevel = this.checkStyle("display", ["inline", "table-cell"]);
return !isInlineLevel && !isFirstLetter && !isFirstLine;
},
fixId: "inactive-css-not-inline-or-tablecell-fix",
msgId: "inactive-css-not-inline-or-tablecell",

View File

@ -126,7 +126,7 @@ skip-if = e10s # Bug 1183605 - devtools/server/tests/browser/ tests are still di
[browser_storage_dynamic_windows.js]
[browser_storage_listings.js]
[browser_storage_updates.js]
skip-if = (verify && debug && (os == 'mac' || os == 'linux'))
skip-if = (verify && debug && (os == 'mac' || os == 'linux')) || (os == 'win' && debug) # Bug 1493369
[browser_stylesheets_getTextEmpty.js]
[browser_stylesheets_nested-iframes.js]
[browser_register_actor.js]

View File

@ -341,12 +341,7 @@ void BrowsingContext::RestoreChildren(Children&& aChildren, bool aFromIPC) {
if (!aFromIPC && XRE_IsContentProcess()) {
auto cc = ContentChild::GetSingleton();
MOZ_DIAGNOSTIC_ASSERT(cc);
nsTArray<BrowsingContextId> contexts(aChildren.Length());
for (BrowsingContext* child : aChildren) {
contexts.AppendElement(child->Id());
}
cc->SendRestoreBrowsingContextChildren(this, contexts);
cc->SendRestoreBrowsingContextChildren(this, aChildren);
}
}

View File

@ -190,25 +190,6 @@ void DOMIntersectionObserver::TakeRecords(
mQueuedEntries.Clear();
}
static bool CheckSimilarOrigin(nsINode* aNode1, nsINode* aNode2) {
nsIPrincipal* principal1 = aNode1->NodePrincipal();
nsIPrincipal* principal2 = aNode2->NodePrincipal();
nsAutoCString baseDomain1;
nsAutoCString baseDomain2;
nsresult rv = principal1->GetBaseDomain(baseDomain1);
if (NS_FAILED(rv)) {
return principal1 == principal2;
}
rv = principal2->GetBaseDomain(baseDomain2);
if (NS_FAILED(rv)) {
return principal1 == principal2;
}
return baseDomain1 == baseDomain2;
}
static Maybe<nsRect> EdgeInclusiveIntersection(const nsRect& aRect,
const nsRect& aOtherRect) {
nscoord left = std::max(aRect.x, aOtherRect.x);
@ -221,22 +202,41 @@ static Maybe<nsRect> EdgeInclusiveIntersection(const nsRect& aRect,
return Some(nsRect(left, top, right - left, bottom - top));
}
enum class BrowsingContextInfo {
SimilarOriginBrowsingContext,
DifferentOriginBrowsingContext,
UnknownBrowsingContext
};
enum class BrowsingContextOrigin { Similar, Different, Unknown };
// FIXME(emilio): The whole concept of "units of related similar-origin browsing
// contexts" is gone, but this is still in the spec, see
// https://github.com/w3c/IntersectionObserver/issues/161
static BrowsingContextOrigin SimilarOrigin(const Element& aTarget,
const Element* aRoot) {
if (!aRoot) {
return BrowsingContextOrigin::Unknown;
}
nsIPrincipal* principal1 = aTarget.NodePrincipal();
nsIPrincipal* principal2 = aRoot->NodePrincipal();
if (principal1 == principal2) {
return BrowsingContextOrigin::Similar;
}
nsAutoCString baseDomain1;
nsAutoCString baseDomain2;
if (NS_FAILED(principal1->GetBaseDomain(baseDomain1)) ||
NS_FAILED(principal2->GetBaseDomain(baseDomain2))) {
return BrowsingContextOrigin::Different;
}
return baseDomain1 == baseDomain2 ? BrowsingContextOrigin::Similar
: BrowsingContextOrigin::Different;
}
void DOMIntersectionObserver::Update(Document* aDocument,
DOMHighResTimeStamp time) {
Element* root = nullptr;
nsIFrame* rootFrame = nullptr;
nsRect rootRect;
nsIFrame* rootFrame = nullptr;
Element* root = mRoot;
if (mRoot) {
root = mRoot;
rootFrame = root->GetPrimaryFrame();
if (rootFrame) {
if ((rootFrame = mRoot->GetPrimaryFrame())) {
nsRect rootRectRelativeToRootFrame;
if (rootFrame->IsScrollFrame()) {
// rootRectRelativeToRootFrame should be the content rect of rootFrame,
@ -252,33 +252,28 @@ void DOMIntersectionObserver::Update(Document* aDocument,
rootRect = nsLayoutUtils::TransformFrameRectToAncestor(
rootFrame, rootRectRelativeToRootFrame, containingBlock);
}
} else {
RefPtr<PresShell> presShell = aDocument->GetPresShell();
if (presShell) {
rootFrame = presShell->GetRootScrollFrame();
if (rootFrame) {
nsPresContext* presContext = rootFrame->PresContext();
while (!presContext->IsRootContentDocument()) {
presContext = presContext->GetParentPresContext();
if (!presContext) {
break;
}
nsIFrame* rootScrollFrame =
presContext->PresShell()->GetRootScrollFrame();
if (rootScrollFrame) {
rootFrame = rootScrollFrame;
} else {
break;
}
} else if (PresShell* presShell = aDocument->GetPresShell()) {
// FIXME(emilio): This shouldn't probably go through the presShell and just
// through the document tree.
rootFrame = presShell->GetRootScrollFrame();
if (rootFrame) {
nsPresContext* presContext = rootFrame->PresContext();
while (!presContext->IsRootContentDocument()) {
presContext = presContext->GetParentPresContext();
if (!presContext) {
break;
}
root = rootFrame->GetContent()->AsElement();
nsIScrollableFrame* scrollFrame = do_QueryFrame(rootFrame);
// If we end up with a null root frame for some reason, we'll proceed
// with an empty root intersection rect.
if (scrollFrame) {
rootRect = scrollFrame->GetScrollPortRect();
nsIFrame* rootScrollFrame =
presContext->PresShell()->GetRootScrollFrame();
if (rootScrollFrame) {
rootFrame = rootScrollFrame;
} else {
break;
}
}
root = rootFrame->GetContent()->AsElement();
nsIScrollableFrame* scrollFrame = do_QueryFrame(rootFrame);
rootRect = scrollFrame->GetScrollPortRect();
}
}
@ -290,8 +285,7 @@ void DOMIntersectionObserver::Update(Document* aDocument,
nsLayoutUtils::ComputeCBDependentValue(basis, mRootMargin.Get(side));
}
for (size_t i = 0; i < mObservationTargets.Length(); ++i) {
Element* target = mObservationTargets.ElementAt(i);
for (Element* target : mObservationTargets) {
nsIFrame* targetFrame = target->GetPrimaryFrame();
nsIFrame* originalTargetFrame = targetFrame;
nsRect targetRect;
@ -347,22 +341,13 @@ void DOMIntersectionObserver::Update(Document* aDocument,
}
nsRect rootIntersectionRect;
BrowsingContextInfo isInSimilarOriginBrowsingContext =
BrowsingContextInfo::UnknownBrowsingContext;
if (rootFrame && targetFrame) {
// FIXME(emilio): Why only if there are frames?
rootIntersectionRect = rootRect;
}
if (root && target) {
isInSimilarOriginBrowsingContext =
CheckSimilarOrigin(root, target)
? BrowsingContextInfo::SimilarOriginBrowsingContext
: BrowsingContextInfo::DifferentOriginBrowsingContext;
}
if (isInSimilarOriginBrowsingContext ==
BrowsingContextInfo::SimilarOriginBrowsingContext) {
BrowsingContextOrigin origin = SimilarOrigin(*target, root);
if (origin == BrowsingContextOrigin::Similar) {
rootIntersectionRect.Inflate(rootMargin);
}
@ -416,13 +401,12 @@ void DOMIntersectionObserver::Update(Document* aDocument,
}
if (target->UpdateIntersectionObservation(this, threshold)) {
QueueIntersectionObserverEntry(
target, time,
isInSimilarOriginBrowsingContext ==
BrowsingContextInfo::DifferentOriginBrowsingContext
? Nothing()
: Some(rootIntersectionRect),
targetRect, intersectionRect, intersectionRatio);
QueueIntersectionObserverEntry(target, time,
origin == BrowsingContextOrigin::Different
? Nothing()
: Some(rootIntersectionRect),
targetRect, intersectionRect,
intersectionRatio);
}
}
}

View File

@ -5845,7 +5845,7 @@ nsresult nsContentUtils::GetThreadSafeASCIIOrigin(nsIURI* aURI,
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIURI> uri;
nsresult rv = NS_NewURIOnAnyThread(getter_AddRefs(uri), path);
nsresult rv = NS_NewURI(getter_AddRefs(uri), path);
if (rv == NS_ERROR_UNKNOWN_PROTOCOL) {
return NS_ERROR_UNKNOWN_PROTOCOL;
}

View File

@ -2605,7 +2605,7 @@ bool nsFrameLoader::TryRemoteBrowserInternal() {
RefPtr<ContentParent> openerContentParent;
RefPtr<BrowserParent> sameTabGroupAs;
if (auto* host = BrowserHost::GetFrom(parentDocShell->GetOpener())) {
openerContentParent = host->GetActor()->Manager();
openerContentParent = host->GetContentParent();
}
// <iframe mozbrowser> gets to skip these checks.

View File

@ -18,6 +18,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=682305
</div>
<pre id="test">
<script class="testbody" type="application/javascript">
"use strict";
SimpleTest.waitForExplicitFinish();
/*
@ -107,12 +110,6 @@ CustomProtocol.prototype = {
allowPort: function allowPort() {
return false;
},
newURI: function newURI(spec, charset, baseURI) {
return Cc["@mozilla.org/network/simple-uri-mutator;1"]
.createInstance(Ci.nsIURIMutator)
.setSpec(spec)
.finalize();
},
newChannel: function newChannel(URI, loadInfo) {
return new CustomChannel(URI, loadInfo);
},

View File

@ -777,13 +777,6 @@ BlobURLProtocolHandler::GetFlagsForURI(nsIURI* aURI, uint32_t* aResult) {
return NS_OK;
}
NS_IMETHODIMP
BlobURLProtocolHandler::NewURI(const nsACString& aSpec, const char* aCharset,
nsIURI* aBaseURI, nsIURI** aResult) {
return BlobURLProtocolHandler::CreateNewURI(aSpec, aCharset, aBaseURI,
aResult);
}
/* static */ nsresult BlobURLProtocolHandler::CreateNewURI(
const nsACString& aSpec, const char* aCharset, nsIURI* aBaseURI,
nsIURI** aResult) {

View File

@ -77,35 +77,3 @@ FontTableURIProtocolHandler::GetScheme(nsACString& result) {
result.AssignLiteral(FONTTABLEURI_SCHEME);
return NS_OK;
}
NS_IMETHODIMP
FontTableURIProtocolHandler::NewURI(const nsACString& aSpec,
const char* aCharset, nsIURI* aBaseURI,
nsIURI** aResult) {
nsresult rv;
nsCOMPtr<nsIURI> uri;
// Either you got here via a ref or a fonttable: uri
if (aSpec.Length() && aSpec.CharAt(0) == '#') {
rv = NS_MutateURI(aBaseURI).SetRef(aSpec).Finalize(uri);
NS_ENSURE_SUCCESS(rv, rv);
} else {
// Relative URIs (other than #ref) are not meaningful within the
// fonttable: scheme.
// If aSpec is a relative URI -other- than a bare #ref,
// this will leave uri empty, and we'll return a failure code below.
rv = NS_MutateURI(new mozilla::net::nsSimpleURI::Mutator())
.SetSpec(aSpec)
.Finalize(uri);
NS_ENSURE_SUCCESS(rv, rv);
}
bool schemeIs;
if (NS_FAILED(uri->SchemeIs(FONTTABLEURI_SCHEME, &schemeIs)) || !schemeIs) {
NS_WARNING("Non-fonttable spec in FontTableURIProtocolHandler");
return NS_ERROR_NOT_AVAILABLE;
}
uri.forget(aResult);
return NS_OK;
}

View File

@ -3844,17 +3844,10 @@ mozilla::ipc::IPCResult ContentChild::RecvCacheBrowsingContextChildren(
}
mozilla::ipc::IPCResult ContentChild::RecvRestoreBrowsingContextChildren(
BrowsingContext* aContext, nsTArray<BrowsingContextId>&& aChildren) {
BrowsingContext* aContext, BrowsingContext::Children&& aChildren) {
MOZ_DIAGNOSTIC_ASSERT(aContext);
BrowsingContext::Children children(aChildren.Length());
for (auto id : aChildren) {
RefPtr<BrowsingContext> child = BrowsingContext::Get(id);
children.AppendElement(child);
}
aContext->RestoreChildren(std::move(children), /* aFromIPC */ true);
aContext->RestoreChildren(std::move(aChildren), /* aFromIPC */ true);
return IPC_OK();
}

View File

@ -722,7 +722,7 @@ class ContentChild final : public PContentChild,
BrowsingContext* aContext);
mozilla::ipc::IPCResult RecvRestoreBrowsingContextChildren(
BrowsingContext* aContext, nsTArray<BrowsingContextId>&& aChildren);
BrowsingContext* aContext, BrowsingContext::Children&& aChildren);
mozilla::ipc::IPCResult RecvRegisterBrowsingContextGroup(
nsTArray<BrowsingContext::IPCInitializer>&& aInits);

View File

@ -5820,7 +5820,7 @@ mozilla::ipc::IPCResult ContentParent::RecvCacheBrowsingContextChildren(
}
mozilla::ipc::IPCResult ContentParent::RecvRestoreBrowsingContextChildren(
BrowsingContext* aContext, nsTArray<BrowsingContextId>&& aChildren) {
BrowsingContext* aContext, BrowsingContext::Children&& aChildren) {
if (!aContext) {
MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
("ParentIPC: Trying to restore already detached"));
@ -5840,14 +5840,7 @@ mozilla::ipc::IPCResult ContentParent::RecvRestoreBrowsingContextChildren(
return IPC_OK();
}
BrowsingContext::Children children(aChildren.Length());
for (auto id : aChildren) {
RefPtr<BrowsingContext> child = BrowsingContext::Get(id);
children.AppendElement(child);
}
aContext->RestoreChildren(std::move(children), /* aFromIPC */ true);
aContext->RestoreChildren(std::move(aChildren), /* aFromIPC */ true);
aContext->Group()->EachOtherParent(this, [&](ContentParent* aParent) {
Unused << aParent->SendRestoreBrowsingContextChildren(aContext, aChildren);

View File

@ -629,7 +629,7 @@ class ContentParent final : public PContentParent,
BrowsingContext* aContext);
mozilla::ipc::IPCResult RecvRestoreBrowsingContextChildren(
BrowsingContext* aContext, nsTArray<BrowsingContextId>&& aChildren);
BrowsingContext* aContext, BrowsingContext::Children&& aChildren);
mozilla::ipc::IPCResult RecvWindowClose(BrowsingContext* aContext,
bool aTrustedCaller);

View File

@ -43,7 +43,6 @@ class IdType {
typedef IdType<BrowserParent> TabId;
typedef IdType<ContentParent> ContentParentId;
typedef IdType<BrowsingContext> BrowsingContextId;
} // namespace dom
} // namespace mozilla

View File

@ -97,7 +97,6 @@ using mozilla::Telemetry::DiscardedData from "mozilla/TelemetryComms.h";
using mozilla::CrossProcessMutexHandle from "mozilla/ipc/CrossProcessMutex.h";
using refcounted class nsIInputStream from "mozilla/ipc/IPCStreamUtils.h";
using refcounted class mozilla::dom::BrowsingContext from "mozilla/dom/BrowsingContext.h";
using mozilla::dom::BrowsingContextId from "mozilla/dom/ipc/IdType.h";
using mozilla::dom::BrowsingContextTransaction from "mozilla/dom/BrowsingContext.h";
using mozilla::dom::BrowsingContextFieldEpochs from "mozilla/dom/BrowsingContext.h";
using mozilla::dom::BrowsingContextInitializer from "mozilla/dom/BrowsingContext.h";
@ -1450,7 +1449,7 @@ both:
* Re-attach all BrowsingContexts in a 'aContext'.
*/
async RestoreBrowsingContextChildren(BrowsingContext aContext,
BrowsingContextId[] aChildren);
BrowsingContext[] aChildren);
async WindowClose(BrowsingContext aContext, bool aTrustedCaller);
async WindowFocus(BrowsingContext aContext);

View File

@ -1106,11 +1106,6 @@ nsJSProtocolHandler::GetProtocolFlags(uint32_t* result) {
URI_OPENING_EXECUTES_SCRIPT;
return NS_OK;
}
NS_IMETHODIMP
nsJSProtocolHandler::NewURI(const nsACString& aSpec, const char* aCharset,
nsIURI* aBaseURI, nsIURI** result) {
return nsJSProtocolHandler::CreateNewURI(aSpec, aCharset, aBaseURI, result);
}
/* static */ nsresult nsJSProtocolHandler::CreateNewURI(const nsACString& aSpec,
const char* aCharset,

View File

@ -138,11 +138,9 @@ already_AddRefed<MediaRawData> SampleIterator::GetNext() {
if (moofParser->mSinf.mDefaultEncryptionType == AtomType("cenc")) {
cryptoScheme = CryptoScheme::Cenc;
writer->mCrypto.mCryptoScheme = CryptoScheme::Cenc;
writer->mCrypto.mInitDataType = NS_LITERAL_STRING("cenc");
} else if (moofParser->mSinf.mDefaultEncryptionType == AtomType("cbcs")) {
cryptoScheme = CryptoScheme::Cbcs;
writer->mCrypto.mCryptoScheme = CryptoScheme::Cbcs;
writer->mCrypto.mInitDataType = NS_LITERAL_STRING("cenc");
} else {
MOZ_ASSERT_UNREACHABLE(
"Sample description entry reports sample is encrypted, but no "
@ -151,17 +149,18 @@ already_AddRefed<MediaRawData> SampleIterator::GetNext() {
}
}
// We need to check if this moof has init data the CDM expects us to surface.
// This should happen when handling the first sample, even if that sample
// isn't encrypted (samples later in the moof may be).
if (mCurrentSample == 0) {
const nsTArray<Moof>& moofs = moofParser->Moofs();
const Moof* currentMoof = &moofs[mCurrentMoof];
if (!currentMoof->mPsshes.IsEmpty()) {
MOZ_ASSERT(sampleDescriptionEntry->mIsEncryptedEntry,
"Unencrypted fragments should not contain pssh boxes");
MOZ_ASSERT(cryptoScheme != CryptoScheme::None);
// This Moof contained crypto init data. Report that. We only report
// the init data on the Moof's first sample, to avoid reporting it more
// than once per Moof.
writer->mCrypto.mInitDatas.AppendElements(currentMoof->mPsshes);
writer->mCrypto.mInitDataType = NS_LITERAL_STRING("cenc");
}
}

View File

@ -0,0 +1 @@
Cache-Control: no-store

View File

@ -0,0 +1 @@
Cache-Control: no-store

View File

@ -79,6 +79,10 @@ support-files =
bipbop-cenc-videoinit.mp4^headers^
bipbop-cenc-video-10s.mp4
bipbop-cenc-video-10s.mp4^headers^
bipbop-clearkey-keyrotation-clear-lead-audio.mp4
bipbop-clearkey-keyrotation-clear-lead-audio.mp4^headers^
bipbop-clearkey-keyrotation-clear-lead-video.mp4
bipbop-clearkey-keyrotation-clear-lead-video.mp4^headers^
bipbop_225w_175kbps.mp4
bipbop_225w_175kbps.mp4^headers^
bipbop_225w_175kbps-cenc-audio-key1-1.m4s

View File

@ -10,64 +10,84 @@
</head>
<body>
<video controls id="video"></video>
<div id="log"></div>
<script class="testbody" type="text/javascript">
let manager = new MediaTestManager;
SimpleTest.waitForExplicitFinish();
let psshTests = [
{ name: "bear-640x360-cenc-key-rotation",
tracks : [
{
name: "video",
type: "video/mp4; codecs=\"avc1.64000d\"",
fragments: ["bear-640x360-v_frag-cenc-key_rotation.mp4"],
initDatas: 6
},
{
name: "audio",
type: "audio/mp4; codecs=\"mp4a.40.2\"",
fragments: ["bear-640x360-a_frag-cenc-key_rotation.mp4"],
initDatas: 7
}
],
keys : {
"30313233343536373839303132333435" :
"ebdd62f16814d27b68ef122afce4ae3c"
}
},
{ name: "bipbop-clearkey-keyrotation-clear-lead",
tracks : [
{
name: "video",
type: "video/mp4; codecs=\"avc1.4d4015\"",
fragments: ["bipbop-clearkey-keyrotation-clear-lead-video.mp4"],
initDatas: 3
},
{
name: "audio",
type: "audio/mp4; codecs=\"mp4a.40.2\"",
fragments: ["bipbop-clearkey-keyrotation-clear-lead-audio.mp4"],
initDatas: 3
}
],
keys : {
"00112233445566778899aabbccddeeff" :
"00112233445566778899aabbccddeeff",
"112233445566778899aabbccddeeff00" :
"112233445566778899aabbccddeeff00"
}
}
];
function e(id) {
return document.getElementById(id);
// Specialized create media keys function, since the one in eme.js relies
// on listening for encrypted events, and we want to manage those
// ourselves within this test.
async function createAndSetMediaKeys(video, test, token) {
function streamType(type) {
var x = test.tracks.find(o => o.name == type);
return x ? x.type : undefined;
}
function log(msg) {
var log_pane = e('log');
log_pane.appendChild(document.createTextNode(msg));
log_pane.appendChild(document.createElement("br"));
var configuration = { initDataTypes: ["cenc"] };
if (streamType("video")) {
configuration.videoCapabilities = [{contentType: streamType("video")}];
}
function DownloadMedia(url, type, mediaSource) {
return new Promise((resolve, reject) => {
var sourceBuffer = mediaSource.addSourceBuffer(type);
fetch(url)
.then((response) => { return response.arrayBuffer(); })
.then((arrayBuffer) => {
once(sourceBuffer, "updateend", resolve);
sourceBuffer.appendBuffer(arrayBuffer);
});
});
if (streamType("audio")) {
configuration.audioCapabilities = [{contentType: streamType("audio")}];
}
let keySystemAccess = await navigator.requestMediaKeySystemAccess(
"org.w3.clearkey", [configuration]);
let mediaKeys = await keySystemAccess.createMediaKeys();
return video.setMediaKeys(mediaKeys);
}
function LoadMSE(video, tracks) {
var ms = new MediaSource();
video.src = URL.createObjectURL(ms);
once(ms, "sourceopen", () => {
Promise.all(tracks.map(track => DownloadMedia(track.url, track.type, ms)))
.then(() => {
ms.endOfStream();
})
});
}
function startTest(test, token) {
manager.started(token);
let video = document.createElement("video");
document.body.appendChild(video);
function CreateMediaKeys(video, configurations) {
return navigator.requestMediaKeySystemAccess("org.w3.clearkey", configurations)
.then((keySystemAccess) => {
return keySystemAccess.createMediaKeys();
}, bail("Failed to request key system access."))
let encryptedEventCount = 0;
.then((mediaKeys) => {
video.mediaKeys = mediaKeys;
return video.setMediaKeys(mediaKeys);
}, bail("Failed to set media keys."));
}
var encryptedEventCount = 0;
var initDatas = new Map();
var keys = {
"30313233343536373839303132333435" : "ebdd62f16814d27b68ef122afce4ae3c"
};
let initDatas = new Map();
function handleEncrypted(event) {
// We get one 'encrypted' event for every run of contiguous PSSH boxes
@ -77,65 +97,44 @@
// data is also repeated.
encryptedEventCount++;
var hexStr = StringToHex(new TextDecoder().decode(event.initData));
let hexStr = StringToHex(new TextDecoder().decode(event.initData));
if (initDatas.has(hexStr)) {
// Already have a session for this.
return;
}
initDatas.set(hexStr, session);
var initData = new Uint8Array(event.initData);
log("encrypted event => len=" + initData.length + " " + hexStr);
var session = event.target.mediaKeys.createSession();
session.addEventListener("message", function(event) {
event.target.update(GenerateClearKeyLicense(event.message, keys));
let initData = new Uint8Array(event.initData);
is(event.initDataType, "cenc", "'encrypted' event should have 'cenc' " +
"initDataType");
Log(token, "encrypted event => len=" + initData.length + " " + hexStr);
let session = event.target.mediaKeys.createSession();
initDatas.set(hexStr, session);
session.addEventListener("message", event => {
event.target.update(
GenerateClearKeyLicense(event.message, test.keys));
});
session.generateRequest(event.initDataType, event.initData);
}
const videoContentType = "video/mp4; codecs=\"avc1.64000d\"";
const audioContentType = "audio/mp4; codecs=\"mp4a.40.2\"";
var tracks = [
{
type: videoContentType,
url: "bear-640x360-v_frag-cenc-key_rotation.mp4",
initDatas: 6,
},
{
type: audioContentType,
url: "bear-640x360-a_frag-cenc-key_rotation.mp4",
initDatas: 7,
}
];
var configurations = [{
initDataTypes: ["cenc"],
audioCapabilities: [{
contentType: audioContentType
}],
videoCapabilities: [{
contentType: videoContentType
}]
}];
var video = document.getElementById("video");
video.addEventListener("encrypted", handleEncrypted, false);
video.addEventListener("ended", ()=>{
var expectedEncryptedEvents = tracks.reduce((sum, track) => sum += track.initDatas, 0);
is(encryptedEventCount, expectedEncryptedEvents, "Should get one 'encrypted' event per run of contiguous PSSH boxes in media.");
SimpleTest.finish();
video.addEventListener("ended", () => {
let expectedEncryptedEvents =
test.tracks.reduce((sum, track) => sum += track.initDatas, 0);
is(encryptedEventCount, expectedEncryptedEvents,
"Should get one 'encrypted' event per run of contiguous PSSH " +
"boxes in media.");
manager.finished(token);
});
video.autoplay = true;
CreateMediaKeys(video, configurations)
.then(()=>{
LoadMSE(video, tracks);
});
createAndSetMediaKeys(video, test, token)
.then(() => LoadTest(test, video, token))
}
manager.runTests(psshTests, startTest);
</script>
</body>

View File

@ -37,18 +37,6 @@ NS_IMETHODIMP nsIndexedDBProtocolHandler::GetProtocolFlags(
return NS_OK;
}
NS_IMETHODIMP nsIndexedDBProtocolHandler::NewURI(const nsACString& aSpec,
const char* aOriginCharset,
nsIURI* aBaseURI,
nsIURI** _retval) {
nsCOMPtr<nsIURI> baseURI(aBaseURI);
return NS_MutateURI(new nsStandardURL::Mutator())
.Apply(NS_MutatorMethod(
&nsIStandardURLMutator::Init, nsIStandardURL::URLTYPE_AUTHORITY, 0,
nsCString(aSpec), aOriginCharset, baseURI, nullptr))
.Finalize(_retval);
}
NS_IMETHODIMP
nsIndexedDBProtocolHandler::NewChannel(nsIURI* aURI, nsILoadInfo* aLoadInfo,
nsIChannel** _retval) {

View File

@ -412,8 +412,8 @@ void URLWorker::Init(const nsAString& aURL, const Optional<nsAString>& aBase,
bool useProxy = false;
nsCOMPtr<nsIURI> baseURI;
if (aBase.WasPassed()) {
rv = NS_NewURIOnAnyThread(getter_AddRefs(baseURI),
NS_ConvertUTF16toUTF8(aBase.Value()));
rv = NS_NewURI(getter_AddRefs(baseURI),
NS_ConvertUTF16toUTF8(aBase.Value()));
if (NS_FAILED(rv)) {
if (rv != NS_ERROR_UNKNOWN_PROTOCOL) {
aRv.ThrowTypeError<MSG_INVALID_URL>(aBase.Value());
@ -426,8 +426,8 @@ void URLWorker::Init(const nsAString& aURL, const Optional<nsAString>& aBase,
// Let's see if we can parse aURI on this thread.
nsCOMPtr<nsIURI> uri;
if (!useProxy) {
rv = NS_NewURIOnAnyThread(getter_AddRefs(uri), NS_ConvertUTF16toUTF8(aURL),
nullptr, baseURI);
rv = NS_NewURI(getter_AddRefs(uri), NS_ConvertUTF16toUTF8(aURL), nullptr,
baseURI);
if (NS_FAILED(rv)) {
if (rv != NS_ERROR_UNKNOWN_PROTOCOL) {
aRv.ThrowTypeError<MSG_INVALID_URL>(aURL);

View File

@ -426,7 +426,7 @@
is(url.href, "ftp://tmp/test");
url = new URL("scheme://tmp\\test", base);
is(url.href, "scheme://tmp\\test");
is(url.href, "scheme://tmp/test");
</script>
<script>

View File

@ -45,8 +45,8 @@ VRProcessManager::~VRProcessManager() {
MOZ_COUNT_DTOR(VRProcessManager);
if (mObserver) {
mObserver->Unregister();
nsContentUtils::UnregisterShutdownObserver(mObserver);
Preferences::RemoveObserver(mObserver, "");
mObserver = nullptr;
}
@ -193,8 +193,6 @@ VRProcessManager::Observer::Observe(nsISupports* aSubject, const char* aTopic,
return NS_OK;
}
void VRProcessManager::Observer::Unregister() { mManager = nullptr; }
void VRProcessManager::CleanShutdown() { DestroyProcess(); }
void VRProcessManager::OnXPCOMShutdown() {

View File

@ -65,7 +65,6 @@ class VRProcessManager final : public VRProcessParent::Listener {
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
explicit Observer(VRProcessManager* aManager);
void Unregister();
protected:
~Observer() {}

View File

@ -17,6 +17,10 @@ FINAL_LIBRARY = 'xul'
include('/ipc/chromium/chromium-config.mozbuild')
EXPORTS += [
'nsIconURI.h',
]
platform = None
if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:

View File

@ -54,15 +54,6 @@ nsIconProtocolHandler::GetProtocolFlags(uint32_t* result) {
return NS_OK;
}
NS_IMETHODIMP
nsIconProtocolHandler::NewURI(const nsACString& aSpec,
const char* aOriginCharset, // ignored
nsIURI* aBaseURI, nsIURI** result) {
return NS_MutateURI(new nsMozIconURI::Mutator())
.SetSpec(aSpec)
.Finalize(result);
}
NS_IMETHODIMP
nsIconProtocolHandler::NewChannel(nsIURI* url, nsILoadInfo* aLoadInfo,
nsIChannel** result) {

View File

@ -26,6 +26,11 @@ DIRS += [
'/mozglue',
]
if CONFIG['JS_BUILD_BINAST']:
DIRS += [
'/modules/brotli',
]
if CONFIG['USE_ICU']:
DIRS += [
'/config/external/icu',

View File

@ -52,6 +52,11 @@ USE_LIBS += [
'zlib',
]
if CONFIG['JS_BUILD_BINAST']:
USE_LIBS += [
'brotli',
]
if CONFIG['OS_ARCH'] not in ('WINNT', 'HP-UX'):
OS_LIBS += [
'm',

View File

@ -8,7 +8,7 @@
#include "mozilla/Result.h" // MOZ_TRY*
#include <string.h> // memcmp
#include <string.h> // memcmp, memmove
#include "frontend/BinAST-macros.h" // BINJS_TRY*, BINJS_MOZ_TRY*
#include "vm/JSScript.h" // ScriptSource
@ -43,6 +43,72 @@ BinASTTokenReaderContext::~BinASTTokenReaderContext() {
if (metadata_ && metadataOwned_ == MetadataOwnership::Owned) {
UniqueBinASTSourceMetadataPtr ptr(metadata_);
}
if (decoder_) {
BrotliDecoderDestroyInstance(decoder_);
}
}
template <>
JS::Result<Ok>
BinASTTokenReaderContext::readBuf<BinASTTokenReaderContext::Compression::No>(
uint8_t* bytes, uint32_t len) {
return Base::readBuf(bytes, len);
}
template <>
JS::Result<Ok>
BinASTTokenReaderContext::readBuf<BinASTTokenReaderContext::Compression::Yes>(
uint8_t* bytes, uint32_t len) {
while (availableDecodedLength() < len) {
if (availableDecodedLength()) {
memmove(bytes, decodedBufferBegin(), availableDecodedLength());
bytes += availableDecodedLength();
len -= availableDecodedLength();
}
if (isEOF()) {
return raiseError("Unexpected end of file");
}
// We have exhausted the in-memory buffer. Start from the beginning.
decodedBegin_ = 0;
size_t inSize = stop_ - current_;
size_t outSize = DECODED_BUFFER_SIZE;
uint8_t* out = decodedBuffer_;
BrotliDecoderResult result;
result = BrotliDecoderDecompressStream(decoder_, &inSize, &current_,
&outSize, &out,
/* total_out = */ nullptr);
if (result == BROTLI_DECODER_RESULT_ERROR) {
return raiseError("Failed to decompress brotli stream");
}
decodedEnd_ = out - decodedBuffer_;
}
memmove(bytes, decodedBufferBegin(), len);
decodedBegin_ += len;
return Ok();
}
bool BinASTTokenReaderContext::isEOF() const {
return BrotliDecoderIsFinished(decoder_);
}
template <>
JS::Result<uint8_t> BinASTTokenReaderContext::readByte<
BinASTTokenReaderContext::Compression::No>() {
return Base::readByte();
}
template <>
JS::Result<uint8_t> BinASTTokenReaderContext::readByte<
BinASTTokenReaderContext::Compression::Yes>() {
uint8_t buf;
MOZ_TRY(readBuf<Compression::Yes>(&buf, 1));
return buf;
}
BinASTSourceMetadata* BinASTTokenReaderContext::takeMetadata() {
@ -65,13 +131,20 @@ JS::Result<Ok> BinASTTokenReaderContext::readHeader() {
// Read global headers.
MOZ_TRY(readConst(CX_MAGIC_HEADER));
BINJS_MOZ_TRY_DECL(version, readVarU32());
BINJS_MOZ_TRY_DECL(version, readVarU32<Compression::No>());
if (version != MAGIC_FORMAT_VERSION) {
return raiseError("Format version not implemented");
}
// TODO: handle `LinkToSharedDictionary` and remaining things here.
decoder_ = BrotliDecoderCreateInstance(/* alloc_func = */ nullptr,
/* free_func = */ nullptr,
/* opaque = */ nullptr);
if (!decoder_) {
return raiseError("Failed to create brotli decoder");
}
// TODO: handle strings and models here.
return raiseError("Not Yet Implemented");
}
@ -169,13 +242,14 @@ JS::Result<Ok> BinASTTokenReaderContext::AutoList::done() {
//
// Encoded as variable length number.
MOZ_MUST_USE JS::Result<uint32_t> BinASTTokenReaderContext::readVarU32() {
template <BinASTTokenReaderContext::Compression compression>
JS::Result<uint32_t> BinASTTokenReaderContext::readVarU32() {
uint32_t result = 0;
uint32_t shift = 0;
while (true) {
MOZ_ASSERT(shift < 32);
uint32_t byte;
MOZ_TRY_VAR(byte, readByte());
MOZ_TRY_VAR(byte, readByte<compression>());
const uint32_t newResult = result | (byte & 0x7f) << shift;
if (newResult < result) {
@ -195,6 +269,10 @@ MOZ_MUST_USE JS::Result<uint32_t> BinASTTokenReaderContext::readVarU32() {
}
}
JS::Result<uint32_t> BinASTTokenReaderContext::readUnsignedLong(const Context&) {
return readVarU32<Compression::Yes>();
}
BinASTTokenReaderContext::AutoTaggedTuple::AutoTaggedTuple(
BinASTTokenReaderContext& reader)
: AutoBase(reader) {}

View File

@ -12,6 +12,8 @@
#include "mozilla/Maybe.h" // mozilla::Maybe
#include <brotli/decode.h> // BrotliDecoderState
#include <stddef.h> // size_t
#include <stdint.h> // uint8_t, uint32_t
@ -48,6 +50,8 @@ class ErrorReporter;
* - the reader does not support lookahead or pushback.
*/
class MOZ_STACK_CLASS BinASTTokenReaderContext : public BinASTTokenReaderBase {
using Base = BinASTTokenReaderBase;
public:
class AutoList;
class AutoTaggedTuple;
@ -82,6 +86,51 @@ class MOZ_STACK_CLASS BinASTTokenReaderContext : public BinASTTokenReaderBase {
~BinASTTokenReaderContext();
private:
// {readByte, readBuf, readVarU32} are implemented both for uncompressed
// stream and brotli-compressed stream.
//
// Uncompressed variant is for reading the magic header, and compressed
// variant is for reading the remaining part.
//
// Once compressed variant is called, the underlying uncompressed stream is
// buffered and uncompressed variant cannot be called.
enum class Compression { No, Yes };
// Buffer that holds already brotli-decoded but not yet used data.
// decodedBuffer[decodedBegin, decodedEnd) holds the data.
static const size_t DECODED_BUFFER_SIZE = 128;
uint8_t decodedBuffer_[DECODED_BUFFER_SIZE];
size_t decodedBegin_ = 0;
size_t decodedEnd_ = 0;
// The number of already decoded bytes.
size_t availableDecodedLength() const { return decodedEnd_ - decodedBegin_; }
// The beginning of decoded buffer.
const uint8_t* decodedBufferBegin() const {
return decodedBuffer_ + decodedBegin_;
}
// Returns true if the brotli stream finished.
bool isEOF() const;
/**
* Read a single byte.
*/
template <Compression compression>
MOZ_MUST_USE JS::Result<uint8_t> readByte();
/**
* Read several bytes.
*
* If there is not enough data, or if the tokenizer has previously been
* poisoned, return an error.
*/
template <Compression compression>
MOZ_MUST_USE JS::Result<Ok> readBuf(uint8_t* bytes, uint32_t len);
public:
/**
* Read the header of the file.
*/
@ -196,14 +245,13 @@ class MOZ_STACK_CLASS BinASTTokenReaderContext : public BinASTTokenReaderBase {
/**
* Read a single unsigned long.
*/
MOZ_MUST_USE JS::Result<uint32_t> readUnsignedLong(const Context&) {
return readVarU32();
}
MOZ_MUST_USE JS::Result<uint32_t> readUnsignedLong(const Context&);
private:
/**
* Read a single uint32_t.
*/
template <Compression compression>
MOZ_MUST_USE JS::Result<uint32_t> readVarU32();
private:
@ -219,6 +267,8 @@ class MOZ_STACK_CLASS BinASTTokenReaderContext : public BinASTTokenReaderBase {
const uint8_t* posBeforeTree_;
BrotliDecoderState* decoder_ = nullptr;
public:
BinASTTokenReaderContext(const BinASTTokenReaderContext&) = delete;
BinASTTokenReaderContext(BinASTTokenReaderContext&&) = delete;

View File

@ -100,6 +100,7 @@ case $cmd in
${MKDIR} -p ${tgtpath}/modules
cp -pPR \
${TOPSRCDIR}/modules/brotli \
${TOPSRCDIR}/modules/fdlibm \
${TOPSRCDIR}/modules/zlib \
${tgtpath}/modules/

View File

@ -43,7 +43,9 @@ function run_test() {
// try on a new object using the resolved URL
var res = Cc["@mozilla.org/network/protocol;1?name=resource"]
.getService(Ci.nsIResProtocolHandler);
var resURI = res.newURI("resource://gre/modules/XPCOMUtils.jsm");
var resURI = Cc["@mozilla.org/network/io-service;1"]
.getService(Ci.nsIIOService)
.newURI("resource://gre/modules/XPCOMUtils.jsm");
dump("resURI: " + resURI + "\n");
var filePath = res.resolveURI(resURI);
var scope3 = {};

View File

@ -61,6 +61,9 @@ typedef void* SockOptArg;
#endif // WEBRTC_POSIX
#if defined(WEBRTC_POSIX) && !defined(WEBRTC_MAC) && !defined(WEBRTC_BSD) && !defined(__native_client__)
#if defined(WEBRTC_LINUX)
#include <linux/sockios.h>
#endif
int64_t GetSocketRecvTimestamp(int socket) {
struct timeval tv_ioctl;

View File

@ -88,16 +88,6 @@ nsJARProtocolHandler::GetProtocolFlags(uint32_t* result) {
return NS_OK;
}
NS_IMETHODIMP
nsJARProtocolHandler::NewURI(const nsACString& aSpec, const char* aCharset,
nsIURI* aBaseURI, nsIURI** result) {
nsCOMPtr<nsIURI> base(aBaseURI);
return NS_MutateURI(new nsJARURI::Mutator())
.Apply(NS_MutatorMethod(&nsIJARURIMutator::SetSpecBaseCharset,
nsCString(aSpec), base, aCharset))
.Finalize(result);
}
NS_IMETHODIMP
nsJARProtocolHandler::NewChannel(nsIURI* uri, nsILoadInfo* aLoadInfo,
nsIChannel** result) {

View File

@ -5101,7 +5101,6 @@ pref("gfx.apitrace.enabled",false);
#ifdef MOZ_X11
#ifdef MOZ_WIDGET_GTK
pref("gfx.xrender.enabled",false);
pref("widget.chrome.allow-gtk-dark-theme", false);
pref("widget.content.allow-gtk-dark-theme", false);
#endif
#endif

View File

@ -62,6 +62,10 @@
#include "nsContentUtils.h"
#include "nsExceptionHandler.h"
#ifdef MOZ_WIDGET_GTK
# include "nsGIOProtocolHandler.h"
#endif
namespace mozilla {
namespace net {
@ -708,24 +712,14 @@ nsIOService::GetProtocolHandler(const char* scheme,
}
#ifdef MOZ_WIDGET_GTK
// check to see whether GVFS can handle this URI scheme. if it can
// create a nsIURI for the "scheme:", then we assume it has support for
// the requested protocol. otherwise, we failover to using the default
// protocol handler.
// check to see whether GVFS can handle this URI scheme. otherwise, we
// failover to using the default protocol handler.
rv =
CallGetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "moz-gio", result);
if (NS_SUCCEEDED(rv)) {
nsAutoCString spec(scheme);
spec.Append(':');
nsCOMPtr<nsIURI> uri;
rv = (*result)->NewURI(spec, nullptr, nullptr, getter_AddRefs(uri));
if (NS_SUCCEEDED(rv)) {
return rv;
}
NS_RELEASE(*result);
RefPtr<nsGIOProtocolHandler> gioHandler =
nsGIOProtocolHandler::GetSingleton();
if (gioHandler->IsSupportedProtocol(nsCString(scheme))) {
gioHandler.forget(result);
return NS_OK;
}
#endif
}
@ -802,34 +796,7 @@ class AutoIncrement {
nsresult nsIOService::NewURI(const nsACString& aSpec, const char* aCharset,
nsIURI* aBaseURI, nsIURI** result) {
NS_ASSERTION(NS_IsMainThread(), "wrong thread");
static uint32_t recursionCount = 0;
if (recursionCount >= MAX_RECURSION_COUNT) return NS_ERROR_MALFORMED_URI;
AutoIncrement inc(&recursionCount);
nsAutoCString scheme;
nsresult rv = ExtractScheme(aSpec, scheme);
if (NS_FAILED(rv)) {
// then aSpec is relative
if (!aBaseURI) return NS_ERROR_MALFORMED_URI;
if (!aSpec.IsEmpty() && aSpec[0] == '#') {
// Looks like a reference instead of a fully-specified URI.
// --> initialize |uri| as a clone of |aBaseURI|, with ref appended.
return NS_GetURIWithNewRef(aBaseURI, aSpec, result);
}
rv = aBaseURI->GetScheme(scheme);
if (NS_FAILED(rv)) return rv;
}
// now get the handler for this scheme
nsCOMPtr<nsIProtocolHandler> handler;
rv = GetProtocolHandler(scheme.get(), getter_AddRefs(handler));
if (NS_FAILED(rv)) return rv;
return handler->NewURI(aSpec, aCharset, aBaseURI, result);
return NS_NewURI(result, aSpec, aCharset, aBaseURI, nullptr);
}
NS_IMETHODIMP

View File

@ -80,35 +80,6 @@ interface nsIProtocolHandler : nsISupports
}
%}
/**
* Makes a URI object that is suitable for loading by this protocol,
* where the URI string is given as an UTF-8 string. The caller may
* provide the charset from which the URI string originated, so that
* the URI string can be translated back to that charset (if necessary)
* before communicating with, for example, the origin server of the URI
* string. (Many servers do not support UTF-8 IRIs at the present time,
* so we must be careful about tracking the native charset of the origin
* server.)
*
* @param aSpec - the URI string in UTF-8 encoding. depending
* on the protocol implementation, unicode character
* sequences may or may not be %xx escaped.
* @param aOriginCharset - the charset of the document from which this URI
* string originated. this corresponds to the
* charset that should be used when communicating
* this URI to an origin server, for example. if
* null, then UTF-8 encoding is assumed (i.e.,
* no charset transformation from aSpec).
* @param aBaseURI - if null, aSpec must specify an absolute URI.
* otherwise, aSpec may be resolved relative
* to aBaseURI, depending on the protocol.
* If the protocol has no concept of relative
* URI aBaseURI will simply be ignored.
*/
nsIURI newURI(in AUTF8String aSpec,
[optional] in string aOriginCharset,
[optional] in nsIURI aBaseURI);
/**
* Constructs a new channel from the given URI for this protocol handler and
* sets the loadInfo for the constructed channel.

View File

@ -97,7 +97,12 @@
#include "mozilla/dom/BlobURLProtocolHandler.h"
#include "nsStreamUtils.h"
#include "nsSocketTransportService2.h"
#include "nsViewSourceHandler.h"
#include "nsJARURI.h"
#include "nsIconURI.h"
#include "nsAboutProtocolHandler.h"
#include "nsResProtocolHandler.h"
#include "mozilla/net/ExtensionProtocolHandler.h"
#include <limits>
using namespace mozilla;
@ -1616,19 +1621,6 @@ nsresult NS_ReadInputStreamToString(nsIInputStream* aInputStream,
return NS_OK;
}
nsresult NS_NewURI(
nsIURI** result, const nsACString& spec,
const char* charset /* = nullptr */, nsIURI* baseURI /* = nullptr */,
nsIIOService*
ioService /* = nullptr */) // pass in nsIIOService to optimize callers
{
nsresult rv;
nsCOMPtr<nsIIOService> grip;
rv = net_EnsureIOService(&ioService, grip);
if (ioService) rv = ioService->NewURI(spec, charset, baseURI, result);
return rv;
}
nsresult NS_NewURI(
nsIURI** result, const nsACString& spec, NotNull<const Encoding*> encoding,
nsIURI* baseURI /* = nullptr */,
@ -1708,10 +1700,10 @@ class TlsAutoIncrement {
T& mVar;
};
nsresult NS_NewURIOnAnyThread(nsIURI** aURI, const nsACString& aSpec,
const char* aCharset /* = nullptr */,
nsIURI* aBaseURI /* = nullptr */,
nsIIOService* aIOService /* = nullptr */) {
nsresult NS_NewURI(nsIURI** aURI, const nsACString& aSpec,
const char* aCharset /* = nullptr */,
nsIURI* aBaseURI /* = nullptr */,
nsIIOService* aIOService /* = nullptr */) {
TlsAutoIncrement<decltype(gTlsURLRecursionCount)> inc(gTlsURLRecursionCount);
if (inc.value() >= MAX_RECURSION_COUNT) {
return NS_ERROR_MALFORMED_URI;
@ -1746,6 +1738,9 @@ nsresult NS_NewURIOnAnyThread(nsIURI** aURI, const nsACString& aSpec,
if (scheme.EqualsLiteral("ftp")) {
return NewStandardURI(aSpec, aCharset, aBaseURI, 21, aURI);
}
if (scheme.EqualsLiteral("ssh")) {
return NewStandardURI(aSpec, aCharset, aBaseURI, 22, aURI);
}
if (scheme.EqualsLiteral("file")) {
nsAutoCString buf(aSpec);
@ -1793,13 +1788,99 @@ nsresult NS_NewURIOnAnyThread(nsIURI** aURI, const nsACString& aSpec,
aURI);
}
if (NS_IsMainThread()) {
// XXX (valentin): this fallback should be removed once we get rid of
// nsIProtocolHandler.newURI
return NS_NewURI(aURI, aSpec, aCharset, aBaseURI, aIOService);
if (scheme.EqualsLiteral("view-source")) {
return nsViewSourceHandler::CreateNewURI(aSpec, aCharset, aBaseURI, aURI);
}
return NS_ERROR_UNKNOWN_PROTOCOL;
if (scheme.EqualsLiteral("resource")) {
RefPtr<nsResProtocolHandler> handler = nsResProtocolHandler::GetSingleton();
if (!handler) {
return NS_ERROR_NOT_AVAILABLE;
}
return handler->NewURI(aSpec, aCharset, aBaseURI, aURI);
}
if (scheme.EqualsLiteral("indexeddb")) {
nsCOMPtr<nsIURI> base(aBaseURI);
return NS_MutateURI(new nsStandardURL::Mutator())
.Apply(NS_MutatorMethod(&nsIStandardURLMutator::Init,
nsIStandardURL::URLTYPE_AUTHORITY, 0,
nsCString(aSpec), aCharset, base, nullptr))
.Finalize(aURI);
}
if (scheme.EqualsLiteral("moz-extension")) {
if (!NS_IsMainThread()) {
return NS_ERROR_UNKNOWN_PROTOCOL;
}
// TODO: must be thread safe
MOZ_ASSERT(NS_IsMainThread());
RefPtr<mozilla::net::ExtensionProtocolHandler> handler =
mozilla::net::ExtensionProtocolHandler::GetSingleton();
if (!handler) {
return NS_ERROR_NOT_AVAILABLE;
}
return handler->NewURI(aSpec, aCharset, aBaseURI, aURI);
}
if (scheme.EqualsLiteral("about")) {
return nsAboutProtocolHandler::CreateNewURI(aSpec, aCharset, aBaseURI,
aURI);
}
if (scheme.EqualsLiteral("jar")) {
nsCOMPtr<nsIURI> base(aBaseURI);
return NS_MutateURI(new nsJARURI::Mutator())
.Apply(NS_MutatorMethod(&nsIJARURIMutator::SetSpecBaseCharset,
nsCString(aSpec), base, aCharset))
.Finalize(aURI);
}
if (scheme.EqualsLiteral("moz-icon")) {
return NS_MutateURI(new nsMozIconURI::Mutator())
.SetSpec(aSpec)
.Finalize(aURI);
}
#ifdef MOZ_WIDGET_GTK
if (scheme.EqualsLiteral("smb") || scheme.EqualsLiteral("sftp")) {
nsCOMPtr<nsIURI> base(aBaseURI);
return NS_MutateURI(new nsStandardURL::Mutator())
.Apply(NS_MutatorMethod(&nsIStandardURLMutator::Init,
nsIStandardURL::URLTYPE_STANDARD, -1,
nsCString(aSpec), aCharset, base, nullptr))
.Finalize(aURI);
}
#endif
if (scheme.EqualsLiteral("android")) {
nsCOMPtr<nsIURI> base(aBaseURI);
return NS_MutateURI(NS_STANDARDURLMUTATOR_CONTRACTID)
.Apply(NS_MutatorMethod(&nsIStandardURLMutator::Init,
nsIStandardURL::URLTYPE_STANDARD, -1,
nsCString(aSpec), aCharset, base, nullptr))
.Finalize(aURI);
}
if (aBaseURI) {
nsAutoCString newSpec;
rv = aBaseURI->Resolve(aSpec, newSpec);
NS_ENSURE_SUCCESS(rv, rv);
nsAutoCString newScheme;
rv = net_ExtractURLScheme(newSpec, newScheme);
if (NS_SUCCEEDED(rv)) {
// The scheme shouldn't really change at this point.
MOZ_DIAGNOSTIC_ASSERT(newScheme == scheme);
}
return NS_MutateURI(new nsSimpleURI::Mutator())
.SetSpec(newSpec)
.Finalize(aURI);
}
// Falls back to external protocol handler.
return NS_MutateURI(new nsSimpleURI::Mutator()).SetSpec(aSpec).Finalize(aURI);
}
nsresult NS_GetSanitizedURIStringFromURI(nsIURI* aUri,

View File

@ -101,19 +101,6 @@ nsresult NS_NewURI(nsIURI** result, const char* spec, nsIURI* baseURI = nullptr,
nsIIOService* ioService =
nullptr); // pass in nsIIOService to optimize callers
// This function attempts to create an nsIURI on any thread. This implies we
// can't instantiate a protcol handler, since protocol handers may have a JS
// implementation so they can't work off-main-thread.
// When called off the main thread, if the nsIURI can't be created without
// instantiating protocol handlers, the method will return
// NS_ERROR_UNKNOWN_PROTOCOL. The caller may retry on the main thread.
// When called on the main thread, this function will fall back on calling
// nsIProtocolHandler.newURI
nsresult NS_NewURIOnAnyThread(nsIURI** aResult, const nsACString& aSpec,
const char* aCharset = nullptr,
nsIURI* aBaseURI = nullptr,
nsIIOService* aIOService = nullptr);
nsresult NS_NewFileURI(
nsIURI** result, nsIFile* spec,
nsIIOService* ioService =

View File

@ -21,6 +21,7 @@
#include "mozilla/MemoryReporting.h"
#include "mozilla/ipc/URIUtils.h"
#include "nsIURIMutator.h"
#include "mozilla/net/MozURL.h"
using namespace mozilla::ipc;
@ -581,7 +582,41 @@ nsresult nsSimpleURI::CloneInternal(
NS_IMETHODIMP
nsSimpleURI::Resolve(const nsACString& relativePath, nsACString& result) {
result = relativePath;
nsAutoCString scheme;
nsresult rv = net_ExtractURLScheme(relativePath, scheme);
if (NS_SUCCEEDED(rv)) {
result = relativePath;
return NS_OK;
}
nsAutoCString spec;
rv = GetAsciiSpec(spec);
if (NS_WARN_IF(NS_FAILED(rv))) {
// If getting the spec fails for some reason, preserve behaviour and just
// return the relative path.
result = relativePath;
return NS_OK;
}
RefPtr<MozURL> url;
rv = MozURL::Init(getter_AddRefs(url), spec);
if (NS_WARN_IF(NS_FAILED(rv))) {
// If parsing the current url fails, we revert to the previous behaviour
// and just return the relative path.
result = relativePath;
return NS_OK;
}
RefPtr<MozURL> url2;
rv = MozURL::Init(getter_AddRefs(url2), relativePath, url);
if (NS_WARN_IF(NS_FAILED(rv))) {
// If parsing the relative url fails, we revert to the previous behaviour
// and just return the relative path.
result = relativePath;
return NS_OK;
}
result = url2->Spec();
return NS_OK;
}

View File

@ -316,7 +316,7 @@ Classes = [
'singleton': True,
'type': 'nsResProtocolHandler',
'headers': ['/netwerk/protocol/res/nsResProtocolHandler.h'],
'init_method': 'Init',
'constructor': 'nsResProtocolHandler::GetSingleton',
},
{
'cid': '{9c7ec5d1-23f9-11d5-aea8-8fcc0793e97f}',

View File

@ -11,6 +11,7 @@ XPIDL_SOURCES += [
XPIDL_MODULE = 'necko_about'
EXPORTS += [
'nsAboutProtocolHandler.h',
'nsAboutProtocolUtils.h',
]

View File

@ -36,15 +36,32 @@ static bool IsSafeForUntrustedContent(nsIAboutModule* aModule, nsIURI* aURI) {
return (flags & nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT) != 0;
}
static bool IsSafeToLinkForUntrustedContent(nsIAboutModule* aModule,
nsIURI* aURI) {
uint32_t flags;
nsresult rv = aModule->GetURIFlags(aURI, &flags);
NS_ENSURE_SUCCESS(rv, false);
static bool IsSafeToLinkForUntrustedContent(nsIURI* aURI) {
nsAutoCString path;
aURI->GetPathQueryRef(path);
return (flags & nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT) &&
(flags & nsIAboutModule::MAKE_LINKABLE);
int32_t f = path.FindChar('#');
if (f >= 0) {
path.SetLength(f);
}
f = path.FindChar('?');
if (f >= 0) {
path.SetLength(f);
}
ToLowerCase(path);
// The about modules for these URL types have the
// URI_SAFE_FOR_UNTRUSTED_CONTENT and MAKE_LINKABLE flags set.
if (path.EqualsLiteral("blank") || path.EqualsLiteral("license") ||
path.EqualsLiteral("logo") || path.EqualsLiteral("srcdoc")) {
return true;
}
return false;
}
////////////////////////////////////////////////////////////////////////////////
NS_IMPL_ISUPPORTS(nsAboutProtocolHandler, nsIProtocolHandler,
@ -104,11 +121,12 @@ nsAboutProtocolHandler::GetFlagsForURI(nsIURI* aURI, uint32_t* aFlags) {
return NS_OK;
}
NS_IMETHODIMP
nsAboutProtocolHandler::NewURI(const nsACString& aSpec,
const char* aCharset, // ignore charset info
nsIURI* aBaseURI, nsIURI** result) {
*result = nullptr;
// static
nsresult nsAboutProtocolHandler::CreateNewURI(const nsACString& aSpec,
const char* aCharset,
nsIURI* aBaseURI,
nsIURI** aResult) {
*aResult = nullptr;
nsresult rv;
// Use a simple URI to parse out some stuff first
@ -119,18 +137,7 @@ nsAboutProtocolHandler::NewURI(const nsACString& aSpec,
return rv;
}
// Unfortunately, people create random about: URIs that don't correspond to
// about: modules... Since those URIs will never open a channel, might as
// well consider them unsafe for better perf, and just in case.
bool isSafe = false;
nsCOMPtr<nsIAboutModule> aboutMod;
rv = NS_GetAboutModule(url, getter_AddRefs(aboutMod));
if (NS_SUCCEEDED(rv)) {
isSafe = IsSafeToLinkForUntrustedContent(aboutMod, url);
}
if (isSafe) {
if (IsSafeToLinkForUntrustedContent(url)) {
// We need to indicate that this baby is safe. Use an inner URI that
// no one but the security manager will see. Make sure to preserve our
// path, in case someone decides to hardcode checks for particular
@ -154,7 +161,7 @@ nsAboutProtocolHandler::NewURI(const nsACString& aSpec,
NS_ENSURE_SUCCESS(rv, rv);
}
url.swap(*result);
url.swap(*aResult);
return NS_OK;
}
@ -294,19 +301,6 @@ nsSafeAboutProtocolHandler::GetProtocolFlags(uint32_t* result) {
return NS_OK;
}
NS_IMETHODIMP
nsSafeAboutProtocolHandler::NewURI(const nsACString& aSpec,
const char* aCharset, // ignore charset info
nsIURI* aBaseURI, nsIURI** result) {
nsresult rv =
NS_MutateURI(new nsSimpleURI::Mutator()).SetSpec(aSpec).Finalize(result);
if (NS_FAILED(rv)) {
return rv;
}
return NS_OK;
}
NS_IMETHODIMP
nsSafeAboutProtocolHandler::NewChannel(nsIURI* uri, nsILoadInfo* aLoadInfo,
nsIChannel** result) {

View File

@ -30,6 +30,9 @@ class nsAboutProtocolHandler : public nsIProtocolHandlerWithDynamicFlags,
// nsAboutProtocolHandler methods:
nsAboutProtocolHandler() = default;
static nsresult CreateNewURI(const nsACString& aSpec, const char* aCharset,
nsIURI* aBaseURI, nsIURI** result);
private:
virtual ~nsAboutProtocolHandler() = default;
};

View File

@ -68,6 +68,9 @@ interface nsIAboutModule : nsISupports
/**
* A flag that indicates that this URI should be linkable from content.
* Ignored unless URI_SAFE_FOR_UNTRUSTED_CONTENT is also specified.
*
* When adding a new about module with this flag make sure to also update
* IsSafeToLinkForUntrustedContent() in nsAboutProtocolHandler.cpp
*/
const unsigned long MAKE_LINKABLE = (1 << 7);

View File

@ -47,13 +47,6 @@ nsDataHandler::GetProtocolFlags(uint32_t* result) {
return NS_OK;
}
NS_IMETHODIMP
nsDataHandler::NewURI(const nsACString& aSpec,
const char* aCharset, // ignore charset info
nsIURI* aBaseURI, nsIURI** result) {
return nsDataHandler::CreateNewURI(aSpec, aCharset, aBaseURI, result);
}
/* static */ nsresult nsDataHandler::CreateNewURI(const nsACString& aSpec,
const char* aCharset,
nsIURI* aBaseURI,

View File

@ -143,26 +143,6 @@ nsFileProtocolHandler::GetProtocolFlags(uint32_t* result) {
return NS_OK;
}
NS_IMETHODIMP
nsFileProtocolHandler::NewURI(const nsACString& spec, const char* charset,
nsIURI* aBaseURI, nsIURI** result) {
nsAutoCString buf(spec);
#if defined(XP_WIN)
buf.Truncate();
if (!net_NormalizeFileURL(spec, buf)) {
buf = spec;
}
#endif
nsCOMPtr<nsIURI> base(aBaseURI);
return NS_MutateURI(new nsStandardURL::Mutator())
.Apply(NS_MutatorMethod(&nsIFileURLMutator::MarkFileURL))
.Apply(NS_MutatorMethod(&nsIStandardURLMutator::Init,
nsIStandardURL::URLTYPE_NO_AUTHORITY, -1, buf,
charset, base, nullptr))
.Finalize(result);
}
NS_IMETHODIMP
nsFileProtocolHandler::NewChannel(nsIURI* uri, nsILoadInfo* aLoadInfo,
nsIChannel** result) {

View File

@ -139,37 +139,6 @@ nsFtpProtocolHandler::GetProtocolFlags(uint32_t* result) {
return NS_OK;
}
NS_IMETHODIMP
nsFtpProtocolHandler::NewURI(const nsACString& aSpec, const char* aCharset,
nsIURI* aBaseURI, nsIURI** result) {
if (!mEnabled) {
return NS_ERROR_UNKNOWN_PROTOCOL;
}
nsAutoCString spec(aSpec);
spec.Trim(" \t\n\r"); // Match NS_IsAsciiWhitespace instead of HTML5
char* fwdPtr = spec.BeginWriting();
// now unescape it... %xx reduced inline to resulting character
int32_t len = NS_UnescapeURL(fwdPtr);
// NS_UnescapeURL() modified spec's buffer, truncate to ensure
// spec knows its new length.
spec.Truncate(len);
// return an error if we find a NUL, CR, or LF in the path
if (spec.FindCharInSet(CRLF) >= 0 || spec.FindChar('\0') >= 0)
return NS_ERROR_MALFORMED_URI;
nsCOMPtr<nsIURI> base(aBaseURI);
return NS_MutateURI(NS_STANDARDURLMUTATOR_CONTRACTID)
.Apply(NS_MutatorMethod(&nsIStandardURLMutator::Init,
nsIStandardURL::URLTYPE_AUTHORITY, 21,
nsCString(aSpec), aCharset, base, nullptr))
.Finalize(result);
}
NS_IMETHODIMP
nsFtpProtocolHandler::NewChannel(nsIURI* url, nsILoadInfo* aLoadInfo,
nsIChannel** result) {

View File

@ -8,6 +8,9 @@ Classes = [
{
'cid': '{ee706783-3af8-4d19-9e84-e2ebfe213480}',
'contract_ids': ['@mozilla.org/network/protocol;1?name=moz-gio'],
'singleton': True,
'type': 'nsGIOProtocolHandler',
'headers': ['nsGIOProtocolHandler.h'],
'constructor': 'nsGIOProtocolHandler::GetSingleton',
},
]

View File

@ -12,6 +12,10 @@ XPCOM_MANIFESTS += [
'components.conf',
]
EXPORTS += [
'nsGIOProtocolHandler.h',
]
FINAL_LIBRARY = 'xul'
CXXFLAGS += CONFIG['TK_CFLAGS']

View File

@ -7,7 +7,9 @@
* This code is based on original Mozilla gnome-vfs extension. It implements
* input stream provided by GVFS/GIO.
*/
#include "nsGIOProtocolHandler.h"
#include "mozilla/Components.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/NullPrincipal.h"
#include "nsIPrefService.h"
#include "nsIPrefBranch.h"
@ -827,34 +829,19 @@ static void mount_operation_ask_password(
//-----------------------------------------------------------------------------
class nsGIOProtocolHandler final : public nsIProtocolHandler,
public nsIObserver {
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIPROTOCOLHANDLER
NS_DECL_NSIOBSERVER
mozilla::StaticRefPtr<nsGIOProtocolHandler> nsGIOProtocolHandler::sSingleton;
nsresult Init();
private:
~nsGIOProtocolHandler() {}
void InitSupportedProtocolsPref(nsIPrefBranch* prefs);
bool IsSupportedProtocol(const nsCString& spec);
nsCString mSupportedProtocols;
};
already_AddRefed<nsGIOProtocolHandler> nsGIOProtocolHandler::GetSingleton() {
if (!sSingleton) {
sSingleton = new nsGIOProtocolHandler();
sSingleton->Init();
ClearOnShutdown(&sSingleton);
}
return do_AddRef(sSingleton);
}
NS_IMPL_ISUPPORTS(nsGIOProtocolHandler, nsIProtocolHandler, nsIObserver)
NS_IMPL_COMPONENT_FACTORY(nsGIOProtocolHandler) {
auto inst = MakeRefPtr<nsGIOProtocolHandler>();
if (NS_SUCCEEDED(inst->Init())) {
return inst.forget().downcast<nsIProtocolHandler>();
}
return nullptr;
}
nsresult nsGIOProtocolHandler::Init() {
nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
if (prefs) {
@ -925,53 +912,27 @@ nsGIOProtocolHandler::GetProtocolFlags(uint32_t* aProtocolFlags) {
return NS_OK;
}
NS_IMETHODIMP
nsGIOProtocolHandler::NewURI(const nsACString& aSpec,
const char* aOriginCharset, nsIURI* aBaseURI,
nsIURI** aResult) {
const nsCString flatSpec(aSpec);
LOG(("gio: NewURI [spec=%s]\n", flatSpec.get()));
static bool IsValidGIOScheme(const nsACString& aScheme) {
// Verify that GIO supports this URI scheme.
GVfs* gvfs = g_vfs_get_default();
if (!aBaseURI) {
// XXX Is it good to support all GIO protocols?
if (!IsSupportedProtocol(flatSpec)) return NS_ERROR_UNKNOWN_PROTOCOL;
int32_t colon_location = flatSpec.FindChar(':');
if (colon_location <= 0) return NS_ERROR_UNKNOWN_PROTOCOL;
// Verify that GIO supports this URI scheme.
bool uri_scheme_supported = false;
GVfs* gvfs = g_vfs_get_default();
if (!gvfs) {
g_warning("Cannot get GVfs object.");
return NS_ERROR_UNKNOWN_PROTOCOL;
}
const gchar* const* uri_schemes = g_vfs_get_supported_uri_schemes(gvfs);
while (*uri_schemes != nullptr) {
// While flatSpec ends with ':' the uri_scheme does not. Therefore do not
// compare last character.
if (StringHead(flatSpec, colon_location).Equals(*uri_schemes)) {
uri_scheme_supported = true;
break;
}
uri_schemes++;
}
if (!uri_scheme_supported) {
return NS_ERROR_UNKNOWN_PROTOCOL;
}
if (!gvfs) {
g_warning("Cannot get GVfs object.");
return false;
}
nsCOMPtr<nsIURI> base(aBaseURI);
return NS_MutateURI(NS_STANDARDURLMUTATOR_CONTRACTID)
.Apply(NS_MutatorMethod(&nsIStandardURLMutator::Init,
nsIStandardURL::URLTYPE_STANDARD, -1, flatSpec,
aOriginCharset, base, nullptr))
.Finalize(aResult);
const gchar* const* uri_schemes = g_vfs_get_supported_uri_schemes(gvfs);
while (*uri_schemes != nullptr) {
// While flatSpec ends with ':' the uri_scheme does not. Therefore do not
// compare last character.
if (aScheme.Equals(*uri_schemes)) {
return true;
}
uri_schemes++;
}
return false;
}
NS_IMETHODIMP
@ -984,6 +945,20 @@ nsGIOProtocolHandler::NewChannel(nsIURI* aURI, nsILoadInfo* aLoadInfo,
rv = aURI->GetSpec(spec);
if (NS_FAILED(rv)) return rv;
if (!IsSupportedProtocol(spec)) {
return NS_ERROR_UNKNOWN_PROTOCOL;
}
nsAutoCString scheme;
rv = aURI->GetScheme(scheme);
if (NS_FAILED(rv)) {
return rv;
}
if (!IsValidGIOScheme(scheme)) {
return NS_ERROR_UNKNOWN_PROTOCOL;
}
RefPtr<nsGIOInputStream> stream = new nsGIOInputStream(spec);
if (!stream) {
return NS_ERROR_OUT_OF_MEMORY;

View File

@ -0,0 +1,33 @@
/* 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/. */
#ifndef nsGIOProtocolHandler_h___
#define nsGIOProtocolHandler_h___
#include "nsIProtocolHandler.h"
#include "nsIObserver.h"
#include "nsIPrefBranch.h"
#include "nsStringFwd.h"
class nsGIOProtocolHandler final : public nsIProtocolHandler,
public nsIObserver {
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIPROTOCOLHANDLER
NS_DECL_NSIOBSERVER
static already_AddRefed<nsGIOProtocolHandler> GetSingleton();
bool IsSupportedProtocol(const nsCString& spec);
private:
nsresult Init();
~nsGIOProtocolHandler() = default;
void InitSupportedProtocolsPref(nsIPrefBranch* prefs);
static mozilla::StaticRefPtr<nsGIOProtocolHandler> sSingleton;
nsCString mSupportedProtocols;
};
#endif // nsGIOProtocolHandler_h___

View File

@ -856,6 +856,10 @@ MOZ_MUST_USE nsresult HttpAsyncAborter<T>::AsyncAbort(nsresult status) {
template <class T>
inline void HttpAsyncAborter<T>::HandleAsyncAbort() {
MOZ_ASSERT(!mCallOnResume, "How did that happen?");
nsresult status = mThis->mStatus;
MOZ_LOG(gHttpLog, LogLevel::Debug,
("HttpAsyncAborter::HandleAsyncAbort [this=%p status=%" PRIx32 "]\n",
mThis, static_cast<uint32_t>(status)));
if (mThis->mSuspendCount) {
MOZ_LOG(

View File

@ -5240,6 +5240,44 @@ nsresult nsHttpChannel::ReadFromCache(bool alreadyMarkedValid) {
nsresult rv;
// notify "http-on-may-change-process" observers
gHttpHandler->OnMayChangeProcess(this);
if (mRedirectContentProcessIdPromise) {
PushRedirectAsyncFunc(&nsHttpChannel::ContinueReadFromCache);
rv = StartCrossProcessRedirect();
if (NS_SUCCEEDED(rv)) {
return NS_OK;
}
PopRedirectAsyncFunc(&nsHttpChannel::ContinueReadFromCache);
}
return ContinueReadFromCache(NS_OK);
}
nsresult nsHttpChannel::ContinueReadFromCache(nsresult rv) {
LOG(("nsHttpChannel::ContinueReadFromCache [this=%p] spec: %s\n", this,
mSpec.get()));
// The channel may have been cancelled in the meantime, either by the
// consumer or the channel classifier. In that case, we need to AsyncAbort
// to ensure OnStart/StopRequest are called.
// This should only be an error code if the cross-process redirect failed,
// and OnRedirectVerifyCallback was called with an error code.
if (NS_FAILED(rv)) {
// rv can only be an error code if this was a failed cross-process redirect
// It shouldn't have happened during a revalidation.
MOZ_ASSERT(!mDidReval, "Should not be a 304 response");
// Also, this should not be possible.
MOZ_ASSERT(!mCachedContentIsPartial, "Unexpected partially cached page?");
MOZ_ASSERT(!mCachePump);
CloseCacheEntry(false);
DoAsyncAbort(NS_FAILED(mStatus) ? mStatus : rv);
return rv;
}
// Keep the conditions below in sync with the conditions in
// StartBufferingCachedEntity.

View File

@ -409,6 +409,7 @@ class nsHttpChannel final : public HttpBaseChannel,
int64_t* aContentLength);
bool ShouldUpdateOfflineCacheEntry();
MOZ_MUST_USE nsresult ReadFromCache(bool alreadyMarkedValid);
MOZ_MUST_USE nsresult ContinueReadFromCache(nsresult rv);
void CloseCacheEntry(bool doomOnFailure);
void CloseOfflineCacheEntry();
MOZ_MUST_USE nsresult InitCacheEntry();

View File

@ -140,16 +140,6 @@ namespace net {
LazyLogModule gHttpLog("nsHttp");
static nsresult NewURI(const nsACString& aSpec, const char* aCharset,
nsIURI* aBaseURI, int32_t aDefaultPort, nsIURI** aURI) {
nsCOMPtr<nsIURI> base(aBaseURI);
return NS_MutateURI(new nsStandardURL::Mutator())
.Apply(NS_MutatorMethod(&nsIStandardURLMutator::Init,
nsIStandardURL::URLTYPE_AUTHORITY, aDefaultPort,
nsCString(aSpec), aCharset, base, nullptr))
.Finalize(aURI);
}
#ifdef ANDROID
static nsCString GetDeviceModelId() {
// Assumed to be running on the main thread
@ -1990,13 +1980,6 @@ nsHttpHandler::GetProtocolFlags(uint32_t* result) {
return NS_OK;
}
NS_IMETHODIMP
nsHttpHandler::NewURI(const nsACString& aSpec, const char* aCharset,
nsIURI* aBaseURI, nsIURI** aURI) {
return mozilla::net::NewURI(aSpec, aCharset, aBaseURI, NS_HTTP_DEFAULT_PORT,
aURI);
}
NS_IMETHODIMP
nsHttpHandler::NewChannel(nsIURI* uri, nsILoadInfo* aLoadInfo,
nsIChannel** result) {
@ -2537,13 +2520,6 @@ nsHttpsHandler::GetProtocolFlags(uint32_t* aProtocolFlags) {
return NS_OK;
}
NS_IMETHODIMP
nsHttpsHandler::NewURI(const nsACString& aSpec, const char* aOriginCharset,
nsIURI* aBaseURI, nsIURI** _retval) {
return mozilla::net::NewURI(aSpec, aOriginCharset, aBaseURI,
NS_HTTPS_DEFAULT_PORT, _retval);
}
NS_IMETHODIMP
nsHttpsHandler::NewChannel(nsIURI* aURI, nsILoadInfo* aLoadInfo,
nsIChannel** _retval) {

View File

@ -200,6 +200,7 @@ SubstitutingProtocolHandler::SubstitutingProtocolHandler(const char* aScheme,
uint32_t aFlags,
bool aEnforceFileOrJar)
: mScheme(aScheme),
mSubstitutionsLock("SubstitutingProtocolHandler::mSubstitutions"),
mSubstitutions(16),
mEnforceFileOrJar(aEnforceFileOrJar) {
mFlags.emplace(aFlags);
@ -207,7 +208,10 @@ SubstitutingProtocolHandler::SubstitutingProtocolHandler(const char* aScheme,
}
SubstitutingProtocolHandler::SubstitutingProtocolHandler(const char* aScheme)
: mScheme(aScheme), mSubstitutions(16), mEnforceFileOrJar(true) {
: mScheme(aScheme),
mSubstitutionsLock("SubstitutingProtocolHandler::mSubstitutions"),
mSubstitutions(16),
mEnforceFileOrJar(true) {
ConstructInternal();
}
@ -223,6 +227,7 @@ void SubstitutingProtocolHandler::ConstructInternal() {
nsresult SubstitutingProtocolHandler::CollectSubstitutions(
InfallibleTArray<SubstitutionMapping>& aMappings) {
AutoReadLock lock(mSubstitutionsLock);
for (auto iter = mSubstitutions.ConstIter(); !iter.Done(); iter.Next()) {
SubstitutionEntry& entry = iter.Data();
nsCOMPtr<nsIURI> uri = entry.baseURI;
@ -348,22 +353,14 @@ nsresult SubstitutingProtocolHandler::NewURI(const nsACString& aSpec,
rv = uri->GetHost(host);
if (NS_FAILED(rv)) return rv;
uint32_t flags;
rv = GetSubstitutionFlags(host, &flags);
if (NS_FAILED(rv)) {
// This protocol has not been registered yet or does not exist,
// we can assume we don't expose nsIJARURI
uri.forget(aResult);
return NS_OK;
// "android" is the only root that would return the RESOLVE_JAR_URI flag
// see nsResProtocolHandler::GetSubstitutionInternal
if (host.EqualsLiteral("android")) {
return ResolveJARURI(uri, aResult);
}
if (flags & nsISubstitutingProtocolHandler::RESOLVE_JAR_URI) {
rv = ResolveJARURI(uri, aResult);
} else {
uri.forget(aResult);
}
return rv;
uri.forget(aResult);
return NS_OK;
}
nsresult SubstitutingProtocolHandler::ResolveJARURI(nsIURL* aURL,
@ -387,9 +384,9 @@ nsresult SubstitutingProtocolHandler::ResolveJARURI(nsIURL* aURL,
if (!jarURI) {
// This substitution does not resolve to a jar: URL, so we just
// return the plain SubstitutionURL
*aResult = aURL;
NS_ADDREF(*aResult);
return rv;
nsCOMPtr<nsIURI> url = aURL;
url.forget(aResult);
return NS_OK;
}
nsCOMPtr<nsIJARURI> result = new SubstitutingJARURI(aURL, jarURI);
@ -456,7 +453,10 @@ nsresult SubstitutingProtocolHandler::SetSubstitutionWithFlags(
ToLowerCase(origRoot, root);
if (!baseURI) {
mSubstitutions.Remove(root);
{
AutoWriteLock lock(mSubstitutionsLock);
mSubstitutions.Remove(root);
}
NotifyObservers(root, baseURI);
return SendSubstitution(root, baseURI, flags);
}
@ -474,9 +474,12 @@ nsresult SubstitutingProtocolHandler::SetSubstitutionWithFlags(
return NS_ERROR_INVALID_ARG;
}
SubstitutionEntry& entry = mSubstitutions.GetOrInsert(root);
entry.baseURI = baseURI;
entry.flags = flags;
{
AutoWriteLock lock(mSubstitutionsLock);
SubstitutionEntry& entry = mSubstitutions.GetOrInsert(root);
entry.baseURI = baseURI;
entry.flags = flags;
}
NotifyObservers(root, baseURI);
return SendSubstitution(root, baseURI, flags);
}
@ -491,9 +494,12 @@ nsresult SubstitutingProtocolHandler::SetSubstitutionWithFlags(
mIOService->NewURI(newBase, nullptr, nullptr, getter_AddRefs(newBaseURI));
NS_ENSURE_SUCCESS(rv, rv);
SubstitutionEntry& entry = mSubstitutions.GetOrInsert(root);
entry.baseURI = newBaseURI;
entry.flags = flags;
{
AutoWriteLock lock(mSubstitutionsLock);
SubstitutionEntry& entry = mSubstitutions.GetOrInsert(root);
entry.baseURI = newBaseURI;
entry.flags = flags;
}
NotifyObservers(root, baseURI);
return SendSubstitution(root, newBaseURI, flags);
}
@ -505,11 +511,14 @@ nsresult SubstitutingProtocolHandler::GetSubstitution(
nsAutoCString root;
ToLowerCase(origRoot, root);
SubstitutionEntry entry;
if (mSubstitutions.Get(root, &entry)) {
nsCOMPtr<nsIURI> baseURI = entry.baseURI;
baseURI.forget(result);
return NS_OK;
{
AutoReadLock lock(mSubstitutionsLock);
SubstitutionEntry entry;
if (mSubstitutions.Get(root, &entry)) {
nsCOMPtr<nsIURI> baseURI = entry.baseURI;
baseURI.forget(result);
return NS_OK;
}
}
uint32_t flags;
@ -526,10 +535,15 @@ nsresult SubstitutingProtocolHandler::GetSubstitutionFlags(
#endif
*flags = 0;
SubstitutionEntry entry;
if (mSubstitutions.Get(root, &entry)) {
*flags = entry.flags;
return NS_OK;
{
AutoReadLock lock(mSubstitutionsLock);
SubstitutionEntry entry;
if (mSubstitutions.Get(root, &entry)) {
*flags = entry.flags;
return NS_OK;
}
}
nsCOMPtr<nsIURI> baseURI;

View File

@ -15,6 +15,7 @@
#include "nsJARURI.h"
#include "mozilla/chrome/RegistryMessageUtils.h"
#include "mozilla/Maybe.h"
#include "mozilla/RWLock.h"
class nsIIOService;
@ -32,14 +33,18 @@ class SubstitutingProtocolHandler {
bool aEnforceFileOrJar = true);
explicit SubstitutingProtocolHandler(const char* aScheme);
NS_INLINE_DECL_REFCOUNTING(SubstitutingProtocolHandler);
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SubstitutingProtocolHandler);
NS_DECL_NON_VIRTUAL_NSIPROTOCOLHANDLER;
NS_DECL_NON_VIRTUAL_NSISUBSTITUTINGPROTOCOLHANDLER;
bool HasSubstitution(const nsACString& aRoot) const {
AutoReadLock lock(const_cast<RWLock&>(mSubstitutionsLock));
return mSubstitutions.Get(aRoot, nullptr);
}
nsresult NewURI(const nsACString& aSpec, const char* aCharset,
nsIURI* aBaseURI, nsIURI** aResult);
MOZ_MUST_USE nsresult
CollectSubstitutions(InfallibleTArray<SubstitutionMapping>& aResources);
@ -97,6 +102,8 @@ class SubstitutingProtocolHandler {
nsCString mScheme;
Maybe<uint32_t> mFlags;
RWLock mSubstitutionsLock;
nsDataHashtable<nsCStringHashKey, SubstitutionEntry> mSubstitutions;
nsCOMPtr<nsIIOService> mIOService;

View File

@ -19,6 +19,10 @@ EXPORTS.mozilla.net += [
'SubstitutingURL.h',
]
EXPORTS += [
'nsResProtocolHandler.h',
]
UNIFIED_SOURCES += [
'ExtensionProtocolHandler.cpp',
'nsResProtocolHandler.cpp',

View File

@ -25,6 +25,20 @@ using mozilla::dom::ContentParent;
#define kGRE "gre"
#define kAndroid "android"
mozilla::StaticRefPtr<nsResProtocolHandler> nsResProtocolHandler::sSingleton;
already_AddRefed<nsResProtocolHandler> nsResProtocolHandler::GetSingleton() {
if (!sSingleton) {
RefPtr<nsResProtocolHandler> handler = new nsResProtocolHandler();
if (NS_WARN_IF(NS_FAILED(handler->Init()))) {
return nullptr;
}
sSingleton = handler;
ClearOnShutdown(&sSingleton);
}
return do_AddRef(sSingleton);
}
nsresult nsResProtocolHandler::Init() {
nsresult rv;
rv = mozilla::Omnijar::GetURIString(mozilla::Omnijar::APP, mAppURI);

View File

@ -6,7 +6,7 @@
#ifndef nsResProtocolHandler_h___
#define nsResProtocolHandler_h___
#include "SubstitutingProtocolHandler.h"
#include "mozilla/net/SubstitutingProtocolHandler.h"
#include "nsIResProtocolHandler.h"
#include "nsInterfaceHashtable.h"
@ -23,6 +23,8 @@ class nsResProtocolHandler final
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIRESPROTOCOLHANDLER
static already_AddRefed<nsResProtocolHandler> GetSingleton();
NS_FORWARD_NSIPROTOCOLHANDLER(mozilla::net::SubstitutingProtocolHandler::)
nsResProtocolHandler()
@ -32,8 +34,6 @@ class nsResProtocolHandler final
URI_IS_POTENTIALLY_TRUSTWORTHY,
/* aEnforceFileOrJar = */ false) {}
MOZ_MUST_USE nsresult Init();
NS_IMETHOD SetSubstitution(const nsACString& aRoot,
nsIURI* aBaseURI) override;
NS_IMETHOD SetSubstitutionWithFlags(const nsACString& aRoot, nsIURI* aBaseURI,
@ -71,6 +71,9 @@ class nsResProtocolHandler final
nsACString& aResult) override;
private:
MOZ_MUST_USE nsresult Init();
static mozilla::StaticRefPtr<nsResProtocolHandler> sSingleton;
nsCString mAppURI;
nsCString mGREURI;
#ifdef ANDROID

Some files were not shown because too many files have changed in this diff Show More