author | Phil Ringnalda <philringnalda@gmail.com> |
Wed, 04 Jan 2017 18:33:32 -0800 | |
changeset 327995 | f13abb8ba9f366c9f32a3146245adf642528becd |
parent 327947 | 1bf65dbb4d71ccc02ad63b95a039112073d83e5e (current diff) |
parent 327994 | c8883a87c6dc7c8d355fc93c9ee08bb75cfbf7db (diff) |
child 327996 | cdc8047be15ca4e2c3ac4c725a20d7d091715f52 |
child 328026 | f39d44b3c6f4da5e4c6c7d2d22dbef545af40518 |
child 328102 | 1263bd6737db6dc404f1be0f5bfb0557e67ae7c3 |
child 342022 | 7c478db08c287d9205834bc998d84fb1a01eac47 |
push id | 31160 |
push user | philringnalda@gmail.com |
push date | Thu, 05 Jan 2017 02:33:44 +0000 |
treeherder | mozilla-central@f13abb8ba9f3 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | merge |
milestone | 53.0a1 |
first release with | nightly linux32
f13abb8ba9f3
/
53.0a1
/
20170105030229
/
files
nightly linux64
f13abb8ba9f3
/
53.0a1
/
20170105030229
/
files
nightly mac
f13abb8ba9f3
/
53.0a1
/
20170105030229
/
files
nightly win32
f13abb8ba9f3
/
53.0a1
/
20170105030229
/
files
nightly win64
f13abb8ba9f3
/
53.0a1
/
20170105030229
/
files
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
releases | nightly linux32
53.0a1
/
20170105030229
/
pushlog to previous
nightly linux64
53.0a1
/
20170105030229
/
pushlog to previous
nightly mac
53.0a1
/
20170105030229
/
pushlog to previous
nightly win32
53.0a1
/
20170105030229
/
pushlog to previous
nightly win64
53.0a1
/
20170105030229
/
pushlog to previous
|
--- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -1151,16 +1151,19 @@ pref("browser.newtab.preload", true); pref("browser.newtabpage.introShown", false); // Toggles the content of 'about:newtab'. Shows the grid when enabled. pref("browser.newtabpage.enabled", true); // Toggles the enhanced content of 'about:newtab'. Shows sponsored tiles. sticky_pref("browser.newtabpage.enhanced", true); +// enables Activity Stream inspired layout +pref("browser.newtabpage.compact", false); + // number of rows of newtab grid pref("browser.newtabpage.rows", 3); // number of columns of newtab grid pref("browser.newtabpage.columns", 5); // directory tiles download URL pref("browser.newtabpage.directory.source", "https://tiles.services.mozilla.com/v3/links/fetch/%LOCALE%/%CHANNEL%");
--- a/browser/base/content/newtab/grid.js +++ b/browser/base/content/newtab/grid.js @@ -204,50 +204,52 @@ var gGrid = { // let's bail out to avoid caching zero heights and widths. // We'll be called again when DOMContentLoaded fires. // Same goes for the grid if that's not ready yet. if (!this.isDocumentLoaded || !this._ready) { return; } // Save the cell's computed height/width including margin and border - if (this._cellMargin === undefined) { + if (this._cellHeight === undefined) { let refCell = document.querySelector(".newtab-cell"); - this._cellMargin = parseFloat(getComputedStyle(refCell).marginTop); - this._cellHeight = refCell.offsetHeight + this._cellMargin + - parseFloat(getComputedStyle(refCell).marginBottom); - this._cellWidth = refCell.offsetWidth + this._cellMargin; + let style = getComputedStyle(refCell); + this._cellHeight = refCell.offsetHeight + + parseFloat(style.marginTop) + parseFloat(style.marginBottom); + this._cellWidth = refCell.offsetWidth + + parseFloat(style.marginLeft) + parseFloat(style.marginRight); } let searchContainer = document.querySelector("#newtab-search-container"); // Save search-container margin height - if (this._searchContainerMargin === undefined) { - this._searchContainerMargin = parseFloat(getComputedStyle(searchContainer).marginBottom) + - parseFloat(getComputedStyle(searchContainer).marginTop); + if (this._searchContainerMargin === undefined) { + let style = getComputedStyle(searchContainer); + this._searchContainerMargin = parseFloat(style.marginBottom) + + parseFloat(style.marginTop); } // Find the number of rows we can place into view port - let availHeight = document.documentElement.clientHeight - this._cellMargin - + let availHeight = document.documentElement.clientHeight - searchContainer.offsetHeight - this._searchContainerMargin; let visibleRows = Math.floor(availHeight / this._cellHeight); // Find the number of columns that fit into view port let maxGridWidth = gGridPrefs.gridColumns * this._cellWidth + GRID_WIDTH_EXTRA; // available width is current grid width, but no greater than maxGridWidth let availWidth = Math.min(document.querySelector("#newtab-grid").clientWidth, maxGridWidth); // finally get the number of columns we can fit into view port - let gridColumns = Math.floor(availWidth / this._cellWidth); + let gridColumns = Math.floor(availWidth / this._cellWidth); // walk sites backwords until a pinned or history tile is found or visibleRows reached let tileIndex = Math.min(gGridPrefs.gridRows * gridColumns, this.sites.length) - 1; while (tileIndex >= visibleRows * gridColumns) { if (this._isHistoricalTile(tileIndex)) { break; } - tileIndex --; + tileIndex--; } // Compute the actual number of grid rows we will display (potentially // with a scroll bar). tileIndex now points to a historical tile with // heighest index or to the last index of the visible row, if none found // Dividing tileIndex by number of tiles in a column gives the rows let gridRows = Math.floor(tileIndex / gridColumns) + 1;
--- a/browser/base/content/newtab/newTab.css +++ b/browser/base/content/newtab/newTab.css @@ -131,16 +131,22 @@ input[type=button] { /* CELLS */ .newtab-cell { display: -moz-box; height: 210px; margin: 20px 10px 35px; width: 290px; } +body.compact .newtab-cell { + width: 110px; + height: 110px; + margin: 12px; +} + /* SITES */ .newtab-site { position: relative; -moz-box-flex: 1; transition: 100ms ease-out; transition-property: top, left, opacity; } @@ -174,20 +180,17 @@ input[type=button] { text-align: center; } .newtab-sponsored, .newtab-title { bottom: 0; white-space: nowrap; text-overflow: ellipsis; - font-size: 13px; - line-height: 30px; vertical-align: middle; - background-color: #F2F2F2; } .newtab-suggested { border: 1px solid transparent; border-radius: 2px; font-size: 12px; height: 17px; line-height: 17px; @@ -203,18 +206,16 @@ input[type=button] { .newtab-suggested-bounds { max-height: 34px; /* 34 / 17 = 2 lines maximum */ } .newtab-title { left: 0; padding: 0 4px; - border: 1px solid #FFFFFF; - border-radius: 0px 0px 8px 8px; } .newtab-sponsored { background-color: #FFFFFF; border: 1px solid #E2E2E2; border-radius: 3px; color: #4A4A4A; cursor: pointer; @@ -282,17 +283,16 @@ input[type=button] { pointer-events: none; position: static; width: 18px; } /* CONTROLS */ .newtab-control { position: absolute; - top: 4px; opacity: 0; transition: opacity 100ms ease-out; } .newtab-control:-moz-focusring, .newtab-cell:not([ignorehover]) > .newtab-site:hover > .newtab-control { opacity: 1; } @@ -302,26 +302,16 @@ input[type=button] { } @media (-moz-touch-enabled) { .newtab-control { opacity: 1; } } -.newtab-control-pin:dir(ltr), -.newtab-control-block:dir(rtl) { - left: 4px; -} - -.newtab-control-block:dir(ltr), -.newtab-control-pin:dir(rtl) { - right: 4px; -} - /* DRAG & DROP */ /* * This is just a temporary drag element used for dataTransfer.setDragImage() * so that we can use custom drag images and elements. It needs an opacity of * 0.01 so that the core code detects that it's in fact a visible element. */ .newtab-drag { @@ -334,16 +324,21 @@ input[type=button] { /* SEARCH */ #newtab-search-container { display: -moz-box; position: relative; -moz-box-pack: center; margin: 40px 0 15px; } +body.compact #newtab-search-container { + margin-top: 0; + margin-bottom: 80px; +} + #newtab-search-container[page-disabled] { opacity: 0; pointer-events: none; } #newtab-search-form { display: -moz-box; position: relative;
--- a/browser/base/content/newtab/page.js +++ b/browser/base/content/newtab/page.js @@ -114,23 +114,27 @@ var gPage = { this._initialized = true; // Set submit button label for when CSS background are disabled (e.g. // high contrast mode). document.getElementById("newtab-search-submit").value = document.body.getAttribute("dir") == "ltr" ? "\u25B6" : "\u25C0"; + if (Services.prefs.getBoolPref("browser.newtabpage.compact")) { + document.body.classList.add("compact"); + } + // Initialize search. gSearch.init(); if (document.hidden) { addEventListener("visibilitychange", this); } else { - setTimeout(_ => this.onPageFirstVisible()); + setTimeout(() => this.onPageFirstVisible()); } // Initialize and render the grid. gGrid.init(); // Initialize the drop target shim. gDropTargetShim.init();
--- a/browser/base/content/test/newtab/browser_newtab_bug991210.js +++ b/browser/base/content/test/newtab/browser_newtab_bug991210.js @@ -15,18 +15,17 @@ add_task(function* () { NewTabUtils.links.addProvider(afterLoadProvider); // wait until about:newtab loads before calling provider callback yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:newtab"); afterLoadProvider.callback([]); yield ContentTask.spawn(gBrowser.selectedBrowser, {}, function* () { - let {_cellMargin, _cellHeight, _cellWidth, node} = content.gGrid; - Assert.notEqual(_cellMargin, null, "grid has a computed cell margin"); + let {_cellHeight, _cellWidth, node} = content.gGrid; Assert.notEqual(_cellHeight, null, "grid has a computed cell height"); Assert.notEqual(_cellWidth, null, "grid has a computed cell width"); let {height, maxHeight, maxWidth} = node.style; Assert.notEqual(height, "", "grid has a computed grid height"); Assert.notEqual(maxHeight, "", "grid has a computed grid max-height"); Assert.notEqual(maxWidth, "", "grid has a computed grid max-width"); });
--- a/browser/themes/shared/newtab/newTab.inc.css +++ b/browser/themes/shared/newtab/newTab.inc.css @@ -96,99 +96,150 @@ background-image: -moz-image-rect(url(chrome://browser/skin/newtab/controls.svg), 0, 64, 32, 32); background-color: #FFFFFF; border: solid 1px #CCCCCC; border-radius: 2px; } /* CELLS */ .newtab-cell { + --cell-corner-radius: 8px; background-color: rgba(255,255,255,.2); - border-radius: 8px; + border-radius: var(--cell-corner-radius); +} + +body.compact .newtab-cell { + --cell-corner-radius: 2px; } .newtab-cell:empty { outline: 2px dashed #c1c1c1; - -moz-outline-radius: 8px; + outline-offset: -2px; + -moz-outline-radius: var(--cell-corner-radius); } /* SITES */ -.newtab-site { - border-radius: inherit; +body:not(.compact) .newtab-site { + border-radius: var(--cell-corner-radius); box-shadow: 0 1px 3px #c1c1c1; text-decoration: none; transition-property: top, left, opacity, box-shadow, background-color; } -.newtab-cell:not([ignorehover]) .newtab-control:hover ~ .newtab-link, -.newtab-cell:not([ignorehover]) .newtab-link:hover, -.newtab-site[dragged] { +body:not(.compact) .newtab-cell:not([ignorehover]) .newtab-control:hover ~ .newtab-link, +body:not(.compact) .newtab-cell:not([ignorehover]) .newtab-link:hover, +body:not(.compact) .newtab-site[dragged] { border: 2px solid white; box-shadow: 0 0 6px 1px #add6ff; margin: -2px; } .newtab-site[dragged] { transition-property: box-shadow, background-color; background-color: rgb(242,242,242); } /* LINKS */ .newtab-link { - border-radius: 10px; + border-radius: var(--cell-corner-radius); overflow: hidden; } /*** * If you change the sizes here, change them in newTab.css * and the preference values: * toolkit.pageThumbs.minWidth * toolkit.pageThumbs.minHeight */ /* THUMBNAILS */ .newtab-thumbnail { background-origin: padding-box; background-clip: padding-box; background-repeat: no-repeat; background-size: cover; - border-radius: 8px 8px 0px 0px; height: 180px; transition: opacity 100ms ease-out; } +body.compact .newtab-thumbnail { + height: 100%; + border-radius: calc(var(--cell-corner-radius) + 1px); + outline: 1px solid hsla(0,0%,0%,.1); + -moz-outline-radius: var(--cell-corner-radius); + outline-offset: -1px; +} + .newtab-cell:not([ignorehover]) .newtab-site:hover .newtab-thumbnail.enhanced-content { opacity: 0; } .newtab-site[type=affiliate] .newtab-thumbnail, .newtab-site[type=enhanced] .newtab-thumbnail, .newtab-site[type=organic] .newtab-thumbnail, .newtab-site[type=sponsored] .newtab-thumbnail { background-position: center center; +} + +.newtab-site[type=affiliate] .newtab-thumbnail, +body:not(.compact) .newtab-site[type=enhanced] .newtab-thumbnail, +body:not(.compact) .newtab-site[type=organic] .newtab-thumbnail, +body:not(.compact) .newtab-site[type=sponsored] .newtab-thumbnail { background-size: auto; } /* TITLES */ -.newtab-sponsored, + +.newtab-title { + background-color: #F2F2F2; + font-size: 13px; + line-height: 30px; + border: 1px solid #fff; + border-radius: 0 0 var(--cell-corner-radius) var(--cell-corner-radius); +} + +body.compact .newtab-title { + background-color: hsla(0,0%,100%,.8); + font-size: 12px; + line-height: 21px; +} + .newtab-title, -.newtab-suggested { +.newtab-suggested { color: #5c5c5c; } +body.compact .newtab-title, +body.compact .newtab-suggested { + color: black; +} + +body.compact .newtab-title { + border: 1px solid hsla(0,0%,80%,.8); + border-top-color: hsla(0,0%,0%,.1); + background-clip: padding-box; +} + .newtab-suggested[active] { background-color: rgba(51, 51, 51, 0.95); border: 0; color: white; } -.newtab-site:hover .newtab-title { +body:not(.compact) .newtab-site:hover .newtab-title { color: white; background-color: #333; - border: 1px solid #333; - border-top: 1px solid white; + border-color: #333; + border-top-color: white; +} + +body.compact .newtab-site:hover .newtab-title { + color: white; + background-color: hsla(0,0%,20%,.8); + border-color: hsla(0,0%,0%,.8); + border-top-color: white; } .newtab-site[pinned] .newtab-title { padding-inline-start: 24px; } .newtab-site[pinned] .newtab-title::before { background-image: -moz-image-rect(url("chrome://browser/skin/newtab/controls.svg"), 7, 278, 28, 266); @@ -209,16 +260,41 @@ /* CONTROLS */ .newtab-control { background-color: transparent; background-size: 24px; border: none; height: 24px; width: 24px; + top: 4px; +} + +.newtab-control-pin:dir(ltr), +.newtab-control-block:dir(rtl) { + left: 4px; +} + +.newtab-control-block:dir(ltr), +.newtab-control-pin:dir(rtl) { + right: 4px; +} + +body.compact .newtab-control { + top: -8px; +} + +body.compact .newtab-control-pin:dir(ltr), +body.compact .newtab-control-block:dir(rtl) { + left: -8px; +} + +body.compact .newtab-control-block:dir(ltr), +body.compact .newtab-control-pin:dir(rtl) { + right: -8px; } .newtab-control-pin, .newtab-site[pinned] .newtab-control-pin:hover:active { background-image: -moz-image-rect(url(chrome://browser/skin/newtab/controls.svg), 0, 96, 32, 64); } .newtab-control-pin:hover,
--- a/build/build-clang/build-clang.py +++ b/build/build-clang/build-clang.py @@ -219,16 +219,17 @@ def build_one_stage(cc, cxx, src_dir, st "-DLLVM_ENABLE_ASSERTIONS=%s" % ("ON" if assertions else "OFF"), "-DPYTHON_EXECUTABLE=%s" % slashify_path(python_path), "-DCMAKE_INSTALL_PREFIX=%s" % inst_dir, "-DLLVM_TOOL_LIBCXX_BUILD=%s" % ("ON" if build_libcxx else "OFF"), "-DLIBCXX_LIBCPPABI_VERSION=\"\"", src_dir]; if is_windows(): cmake_args.insert(-1, "-DLLVM_EXPORT_SYMBOLS_FOR_PLUGINS=ON") + cmake_args.insert(-1, "-DLLVM_USE_CRT_RELEASE=MT") build_package(build_dir, cmake_args) if is_linux(): install_libgcc(gcc_dir, inst_dir) # For some reasons the import library clang.lib of clang.exe is not # installed, so we copy it by ourselves. if is_windows(): install_import_library(build_dir, inst_dir)
--- a/caps/nsPrincipal.cpp +++ b/caps/nsPrincipal.cpp @@ -178,19 +178,34 @@ nsPrincipal::GetOriginInternal(nsACStrin // nsIStandardURL. So, we query to a nsIStandardURL, and fail if we aren't // an instance of an nsIStandardURL nsIStandardURLs have the good property // of escaping the '^' character in their specs, which means that we can be // sure that the caret character (which is reserved for delimiting the end // of the spec, and the beginning of the origin attributes) is not present // in the origin string nsCOMPtr<nsIStandardURL> standardURL = do_QueryInterface(origin); NS_ENSURE_TRUE(standardURL, NS_ERROR_FAILURE); + rv = origin->GetAsciiSpec(aOrigin); NS_ENSURE_SUCCESS(rv, rv); + // The origin, when taken from the spec, should not contain the ref part of + // the URL. + + int32_t pos = aOrigin.FindChar('?'); + int32_t hashPos = aOrigin.FindChar('#'); + + if (hashPos != kNotFound && (pos == kNotFound || hashPos < pos)) { + pos = hashPos; + } + + if (pos != kNotFound) { + aOrigin.Truncate(pos); + } + return NS_OK; } bool nsPrincipal::SubsumesInternal(nsIPrincipal* aOther, BasePrincipal::DocumentDomainConsideration aConsideration) { MOZ_ASSERT(aOther);
--- a/devtools/client/jar.mn +++ b/devtools/client/jar.mn @@ -5,19 +5,16 @@ devtools.jar: % content devtools %content/ content/shared/vendor/d3.js (shared/vendor/d3.js) content/shared/vendor/dagre-d3.js (shared/vendor/dagre-d3.js) content/shared/widgets/widgets.css (shared/widgets/widgets.css) content/shared/widgets/VariablesView.xul (shared/widgets/VariablesView.xul) content/projecteditor/chrome/content/projecteditor.xul (projecteditor/chrome/content/projecteditor.xul) content/projecteditor/lib/helpers/readdir.js (projecteditor/lib/helpers/readdir.js) - content/projecteditor/chrome/content/projecteditor-loader.xul (projecteditor/chrome/content/projecteditor-loader.xul) - content/projecteditor/chrome/content/projecteditor-test.xul (projecteditor/chrome/content/projecteditor-test.xul) - content/projecteditor/chrome/content/projecteditor-loader.js (projecteditor/chrome/content/projecteditor-loader.js) content/netmonitor/netmonitor.xul (netmonitor/netmonitor.xul) content/netmonitor/netmonitor.js (netmonitor/netmonitor.js) content/webconsole/webconsole.xul (webconsole/webconsole.xul) * content/scratchpad/scratchpad.xul (scratchpad/scratchpad.xul) content/scratchpad/scratchpad.js (scratchpad/scratchpad.js) content/shared/splitview.css (shared/splitview.css) content/shared/theme-switching.js (shared/theme-switching.js) content/shared/frame-script-utils.js (shared/frame-script-utils.js) @@ -174,17 +171,16 @@ devtools.jar: skin/images/webconsole.svg (themes/images/webconsole.svg) skin/images/breadcrumbs-divider@2x.png (themes/images/breadcrumbs-divider@2x.png) skin/images/breadcrumbs-scrollbutton.png (themes/images/breadcrumbs-scrollbutton.png) skin/images/breadcrumbs-scrollbutton@2x.png (themes/images/breadcrumbs-scrollbutton@2x.png) skin/animationinspector.css (themes/animationinspector.css) skin/canvasdebugger.css (themes/canvasdebugger.css) skin/debugger.css (themes/debugger.css) skin/netmonitor.css (themes/netmonitor.css) - skin/dom.css (themes/dom.css) skin/performance.css (themes/performance.css) skin/memory.css (themes/memory.css) skin/scratchpad.css (themes/scratchpad.css) skin/shadereditor.css (themes/shadereditor.css) skin/storage.css (themes/storage.css) skin/splitview.css (themes/splitview.css) skin/styleeditor.css (themes/styleeditor.css) skin/webaudioeditor.css (themes/webaudioeditor.css)
deleted file mode 100644 --- a/devtools/client/projecteditor/chrome/content/projecteditor-loader.js +++ /dev/null @@ -1,176 +0,0 @@ -var Cu = Components.utils; -const {require} = Cu.import("resource://devtools/shared/Loader.jsm", {}); -const {FileUtils} = Cu.import("resource://gre/modules/FileUtils.jsm", {}); -const {NetUtil} = Cu.import("resource://gre/modules/NetUtil.jsm", {}); -const promise = require("promise"); -const ProjectEditor = require("devtools/client/projecteditor/lib/projecteditor"); - -const SAMPLE_PATH = buildTempDirectoryStructure(); -const SAMPLE_NAME = "DevTools Content Application Name"; -const SAMPLE_PROJECT_URL = "data:text/html;charset=utf-8,<body><h1>Project Overview</h1></body>"; -const SAMPLE_ICON = "chrome://devtools/skin/images/tool-debugger.svg"; - -/** - * Create a workspace for working on projecteditor, available at - * chrome://devtools/content/projecteditor/chrome/content/projecteditor-loader.xul. - * This emulates the integration points that the app manager uses. - */ -var appManagerEditor; - -// Log a message to the project overview URL to make development easier -function log(msg) { - if (!appManagerEditor) { - return; - } - - let doc = appManagerEditor.iframe.contentDocument; - let el = doc.createElement("p"); - el.textContent = msg; - doc.body.appendChild(el); -} - -document.addEventListener("DOMContentLoaded", function onDOMReady(e) { - document.removeEventListener("DOMContentLoaded", onDOMReady, false); - let iframe = document.getElementById("projecteditor-iframe"); - window.projecteditor = ProjectEditor.ProjectEditor(iframe); - - projecteditor.on("onEditorCreated", (editor, a) => { - log("editor created: " + editor); - if (editor.label === "app-manager") { - appManagerEditor = editor; - appManagerEditor.on("load", function foo() { - appManagerEditor.off("load", foo); - log("Working on: " + SAMPLE_PATH); - }); - } - }); - projecteditor.on("onEditorDestroyed", (editor) => { - log("editor destroyed: " + editor); - }); - projecteditor.on("onEditorSave", (editor, resource) => { - log("editor saved: " + editor, resource.path); - }); - projecteditor.on("onTreeSelected", (resource) => { - log("tree selected: " + resource.path); - }); - projecteditor.on("onEditorLoad", (editor) => { - log("editor loaded: " + editor); - }); - projecteditor.on("onEditorActivated", (editor) => { - log("editor focused: " + editor); - }); - projecteditor.on("onEditorDeactivated", (editor) => { - log("editor blur: " + editor); - }); - projecteditor.on("onEditorChange", (editor) => { - log("editor changed: " + editor); - }); - projecteditor.on("onCommand", (cmd) => { - log("Command: " + cmd); - }); - - projecteditor.loaded.then(() => { - projecteditor.setProjectToAppPath(SAMPLE_PATH, { - name: SAMPLE_NAME, - iconUrl: SAMPLE_ICON, - projectOverviewURL: SAMPLE_PROJECT_URL, - validationStatus: "valid" - }).then(() => { - let allResources = projecteditor.project.allResources(); - console.log("All resources have been loaded", allResources, allResources.map(r=>r.basename).join("|")); - }); - - }); - -}, false); - -/** - * Build a temporary directory as a workspace for this loader - * https://developer.mozilla.org/en-US/Add-ons/Code_snippets/File_I_O - */ -function buildTempDirectoryStructure() { - - // First create (and remove) the temp dir to discard any changes - let TEMP_DIR = FileUtils.getDir("TmpD", ["ProjectEditor"], true); - TEMP_DIR.remove(true); - - // Now rebuild our fake project. - TEMP_DIR = FileUtils.getDir("TmpD", ["ProjectEditor"], true); - - FileUtils.getDir("TmpD", ["ProjectEditor", "css"], true); - FileUtils.getDir("TmpD", ["ProjectEditor", "data"], true); - FileUtils.getDir("TmpD", ["ProjectEditor", "img", "icons"], true); - FileUtils.getDir("TmpD", ["ProjectEditor", "js"], true); - - let htmlFile = FileUtils.getFile("TmpD", ["ProjectEditor", "index.html"]); - htmlFile.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE); - writeToFile(htmlFile, [ - "<!DOCTYPE html>", - '<html lang="en">', - " <head>", - ' <meta charset="utf-8" />', - " <title>ProjectEditor Temp File</title>", - ' <link rel="stylesheet" href="style.css" />', - " </head>", - ' <body id="home">', - " <p>ProjectEditor Temp File</p>", - " </body>", - "</html>"].join("\n") - ); - - let readmeFile = FileUtils.getFile("TmpD", ["ProjectEditor", "README.md"]); - readmeFile.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE); - writeToFile(readmeFile, [ - "## Readme" - ].join("\n") - ); - - let licenseFile = FileUtils.getFile("TmpD", ["ProjectEditor", "LICENSE"]); - licenseFile.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE); - writeToFile(licenseFile, [ - "/* 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/. */" - ].join("\n") - ); - - let cssFile = FileUtils.getFile("TmpD", ["ProjectEditor", "css", "styles.css"]); - cssFile.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE); - writeToFile(cssFile, [ - "body {", - " background: red;", - "}" - ].join("\n") - ); - - FileUtils.getFile("TmpD", ["ProjectEditor", "js", "script.js"]).createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE); - - FileUtils.getFile("TmpD", ["ProjectEditor", "img", "fake.png"]).createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE); - FileUtils.getFile("TmpD", ["ProjectEditor", "img", "icons", "16x16.png"]).createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE); - FileUtils.getFile("TmpD", ["ProjectEditor", "img", "icons", "32x32.png"]).createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE); - FileUtils.getFile("TmpD", ["ProjectEditor", "img", "icons", "128x128.png"]).createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE); - FileUtils.getFile("TmpD", ["ProjectEditor", "img", "icons", "vector.svg"]).createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE); - - return TEMP_DIR.path; -} - - -// https://developer.mozilla.org/en-US/Add-ons/Code_snippets/File_I_O#Writing_to_a_file -function writeToFile(file, data) { - - let defer = promise.defer(); - var ostream = FileUtils.openSafeFileOutputStream(file); - - var converter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"]. - createInstance(Components.interfaces.nsIScriptableUnicodeConverter); - converter.charset = "UTF-8"; - var istream = converter.convertToInputStream(data); - - // The last argument (the callback) is optional. - NetUtil.asyncCopy(istream, ostream, function (status) { - if (!Components.isSuccessCode(status)) { - // Handle error! - console.log("ERROR WRITING TEMP FILE", status); - } - }); -}
deleted file mode 100644 --- a/devtools/client/projecteditor/chrome/content/projecteditor-loader.xul +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- 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/. --> -<!DOCTYPE window [ -<!ENTITY % toolboxDTD SYSTEM "chrome://devtools/locale/toolbox.dtd" > - %toolboxDTD; -]> - -<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> - -<script type="application/javascript;version=1.8" src="projecteditor-loader.js"></script> - - <commandset id="toolbox-commandset"> - <command id="projecteditor-cmd-close" oncommand="window.close();"/> - </commandset> - - <keyset id="projecteditor-keyset"> - <key id="projecteditor-key-close" - key="&closeCmd.key;" - command="projecteditor-cmd-close" - modifiers="accel"/> - </keyset> - - <iframe id="projecteditor-iframe" flex="1" forceOwnRefreshDriver=""></iframe> -</window>
--- a/devtools/client/projecteditor/test/browser.ini +++ b/devtools/client/projecteditor/test/browser.ini @@ -1,15 +1,16 @@ [DEFAULT] tags = devtools subsuite = devtools support-files = head.js helper_homepage.html helper_edits.js + projecteditor-test.xul [browser_projecteditor_app_options.js] [browser_projecteditor_confirm_unsaved.js] [browser_projecteditor_contextmenu_01.js] [browser_projecteditor_contextmenu_02.js] skip-if = true # Bug 1173950 [browser_projecteditor_delete_file.js] skip-if = e10s # Frequent failures in e10s - Bug 1020027
--- a/devtools/client/projecteditor/test/browser_projecteditor_immediate_destroy.js +++ b/devtools/client/projecteditor/test/browser_projecteditor_immediate_destroy.js @@ -12,17 +12,17 @@ thisTestLeaksUncaughtRejectionsAndShould thisTestLeaksUncaughtRejectionsAndShouldBeFixed("TypeError: this.window is null"); // Test that projecteditor can be destroyed in various states of loading // without causing any leaks or exceptions. add_task(function* () { info("Testing tab closure when projecteditor is in various states"); - let loaderUrl = "chrome://devtools/content/projecteditor/chrome/content/projecteditor-test.xul"; + let loaderUrl = "chrome://mochitests/content/browser/devtools/client/projecteditor/test/projecteditor-test.xul"; yield addTab(loaderUrl).then(() => { let iframe = content.document.getElementById("projecteditor-iframe"); ok(iframe, "Tab has placeholder iframe for projecteditor"); info("Closing the tab without doing anything"); gBrowser.removeCurrentTab(); });
--- a/devtools/client/projecteditor/test/head.js +++ b/devtools/client/projecteditor/test/head.js @@ -104,17 +104,17 @@ function addProjectEditorTabForTempDirec return addProjectEditorTab(opts).then((projecteditor) => { return projecteditor.setProjectToAppPath(TEMP_PATH, customOpts).then(() => { return projecteditor; }); }); } function addProjectEditorTab(opts = {}) { - return addTab("chrome://devtools/content/projecteditor/chrome/content/projecteditor-test.xul").then(() => { + return addTab("chrome://mochitests/content/browser/devtools/client/projecteditor/test/projecteditor-test.xul").then(() => { let iframe = content.document.getElementById("projecteditor-iframe"); if (opts.menubar !== false) { opts.menubar = content.document.querySelector("menubar"); } let projecteditor = ProjectEditor.ProjectEditor(iframe, opts); ok(iframe, "Tab has placeholder iframe for projecteditor");
rename from devtools/client/projecteditor/chrome/content/projecteditor-test.xul rename to devtools/client/projecteditor/test/projecteditor-test.xul
--- a/devtools/client/shims/moz.build +++ b/devtools/client/shims/moz.build @@ -6,13 +6,8 @@ # Unlike most DevTools build files, this file does not use DevToolsModules # because these files are here for add-on compatibility, and so they must be # installed to previously defined locations. EXTRA_JS_MODULES.devtools += [ 'gDevTools.jsm', ] - -# Extra compatibility layer for transitional URLs used for part of 44 cycle -EXTRA_JS_MODULES.devtools.client.framework += [ - 'gDevTools.jsm', -]
deleted file mode 100644 --- a/devtools/client/themes/dom.css +++ /dev/null @@ -1,9 +0,0 @@ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* 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/. */ - -:root.theme-dark { -} -:root.theme-light { -}
--- a/devtools/client/webconsole/test/browser.ini +++ b/devtools/client/webconsole/test/browser.ini @@ -71,16 +71,17 @@ support-files = test-console-assert.html test-console-clear.html test-console-count.html test-console-count-external-file.js test-console-extras.html test-console-replaced-api.html test-console-server-logging.sjs test-console-server-logging-array.sjs + test-console-server-logging-backtrace.sjs test-console.html test-console-workers.html test-console-table.html test-console-output-02.html test-console-output-03.html test-console-output-04.html test-console-output-dom-elements.html test-console-output-events.html
--- a/devtools/client/webconsole/test/browser_console_server_logging.js +++ b/devtools/client/webconsole/test/browser_console_server_logging.js @@ -60,15 +60,58 @@ add_task(function* () { severity: SEVERITY_LOG, }], }); // Clean up filter hud.setFilterState("serverlog", false); yield updateServerLoggingListener(hud); }); +add_task(function* () { + const TEST_URI = "http://example.com/browser/devtools/client/webconsole/test/test-console-server-logging-backtrace.sjs"; + + yield loadTab(TEST_URI); + + let hud = yield openConsole(); + + // Set logging filter and wait till it's set on the backend + hud.setFilterState("serverlog", true); + yield updateServerLoggingListener(hud); + + BrowserReloadSkipCache(); + // Note that the test is also checking out the (printf like) + // formatters and encoding of UTF8 characters (see the one at the end). + yield waitForMessages({ + webconsole: hud, + messages: [{ + text: "correct 1", + category: CATEGORY_SERVER, + severity: SEVERITY_ERROR, + source: {url: "/some/path/to/file.py", line: 33} + }, { + text: "correct 2", + category: CATEGORY_SERVER, + severity: SEVERITY_ERROR, + source: {url: "/some/path/to/file.py", line: 33} + }, { + text: "wrong 1", + category: CATEGORY_SERVER, + severity: SEVERITY_ERROR, + source: {url: "/some/path/to/file.py:33wrong"} + }, { + text: "wrong 2", + category: CATEGORY_SERVER, + severity: SEVERITY_ERROR, + source: {url: "/some/path/to/file.py"} + }], + }); + // Clean up filter + hud.setFilterState("serverlog", false); + yield updateServerLoggingListener(hud); +}); + function updateServerLoggingListener(hud) { let deferred = promise.defer(); hud.ui._updateServerLoggingListener(response => { deferred.resolve(response); }); return deferred.promise; }
new file mode 100644 --- /dev/null +++ b/devtools/client/webconsole/test/test-console-server-logging-backtrace.sjs @@ -0,0 +1,44 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +function handleRequest(request, response) +{ + var page = "<!DOCTYPE html><html>" + + "<head><meta charset='utf-8'></head>" + + "<body><p>hello world!</p></body>" + + "</html>"; + + var data = { + "version": "4.1.0", + "columns": ["log", "backtrace", "type"], + "rows":[[ + ["correct 1"], + "/some/path/to/file.py : 33", + "error" + ], [ + ["correct 2"], + "/some/path/to/file.py:33", + "error" + ], [ + ["wrong 1"], + "/some/path/to/file.py:33wrong", + "error" + ], [ + ["wrong 2"], + "/some/path/to/file.py", + "error" + ]], + }; + + // Put log into headers. + var value = b64EncodeUnicode(JSON.stringify(data)); + response.setHeader("X-ChromeLogger-Data", value, false); + + response.write(page); +} + +function b64EncodeUnicode(str) { + return btoa(unescape(encodeURIComponent(str))); +}
--- a/devtools/client/webide/test/chrome.ini +++ b/devtools/client/webide/test/chrome.ini @@ -43,16 +43,17 @@ support-files = templates.json ../../shared/test/browser_devices.json validator/* [test_basic.html] [test_newapp.html] skip-if = (os == "win" && os_version == "10.0") # Bug 1197053 [test_import.html] +skip-if = (os == "linux") # Bug 1024734 [test_duplicate_import.html] [test_runtime.html] [test_manifestUpdate.html] [test_addons.html] skip-if = true # Bug 1201392 - Update add-ons after migration [test_device_runtime.html] [test_autoconnect_runtime.html] [test_autoselect_project.html]
--- a/devtools/shared/apps/moz.build +++ b/devtools/shared/apps/moz.build @@ -1,10 +1,9 @@ # vim: set filetype=python: # 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/. DevToolsModules( 'app-actor-front.js', - 'Devices.jsm', - 'Simulator.jsm' + 'Devices.jsm' )
deleted file mode 100644 --- a/devtools/shared/shims/Simulator.jsm +++ /dev/null @@ -1,34 +0,0 @@ -/* 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/. */ - -"use strict"; - -/** - * This file only exists to support add-ons which import this module at a - * specific path. - */ - -const Cu = Components.utils; - -const { Services } = Cu.import("resource://gre/modules/Services.jsm", {}); - -const WARNING_PREF = "devtools.migration.warnings"; -if (Services.prefs.getBoolPref(WARNING_PREF)) { - const { Deprecated } = Cu.import("resource://gre/modules/Deprecated.jsm", {}); - Deprecated.warning("This path to Simulator.jsm is deprecated. Please use " + - "Cu.import(\"resource://devtools/shared/" + - "apps/Simulator.jsm\") to load this module.", - "https://bugzil.la/912121"); -} - -this.EXPORTED_SYMBOLS = [ - "Simulator", -]; - -const module = - Cu.import("resource://devtools/shared/apps/Simulator.jsm", {}); - -for (let symbol of this.EXPORTED_SYMBOLS) { - this[symbol] = module[symbol]; -}
--- a/devtools/shared/shims/moz.build +++ b/devtools/shared/shims/moz.build @@ -12,20 +12,14 @@ # /toolkit modules. Disable any DIST_SUBDIR from parent files here. DIST_SUBDIR = '' EXTRA_JS_MODULES.devtools += [ 'Console.jsm', 'dbg-client.jsm', 'event-emitter.js', 'Loader.jsm', - 'Simulator.jsm', ] # Extra compatibility layer for transitional URLs used for part of 44 cycle EXTRA_JS_MODULES.devtools.shared += [ - 'Console.jsm', 'Loader.jsm', ] - -EXTRA_JS_MODULES.devtools.shared.apps += [ - 'Simulator.jsm', -]
--- a/devtools/shared/webconsole/server-logger.js +++ b/devtools/shared/webconsole/server-logger.js @@ -300,49 +300,33 @@ var ServerLoggingListener = Class({ if (showLabel) { rawLogs.unshift(label); } } // If multiple logs come from the same line only the first log // has info about the backtrace. So, remember the last valid // location and use it for those that not set. - let location = this.parseBacktrace(backtrace); + let location = parseBacktrace(backtrace); if (location) { lastLocation = location; } else { location = lastLocation; } parsedMessage.push({ logs: rawLogs, location: location, type: type }); } return parsedMessage; }, - parseBacktrace: function (backtrace) { - if (!backtrace) { - return null; - } - - let result = backtrace.match(/\s*(\d+)$/); - if (!result || result.length < 2) { - return backtrace; - } - - return { - url: backtrace.slice(0, -result[0].length), - line: result[1] - }; - }, - getColumnMap: function (data) { let columnMap = new Map(); let columnName; for (let key in data.columns) { columnName = data.columns[key]; columnMap.set(columnName, key); } @@ -498,17 +482,34 @@ function format(msg) { if (typeof log == "object") { delete log.___class_name; } } return msg; } +function parseBacktrace(backtrace) { + if (!backtrace) { + return null; + } + + let result = backtrace.match(/^(.+?)\s*:\s*(\d+)$/); + if (!result || result.length != 3) { + return { url: backtrace }; + } + + return { + url: result[1], + line: parseInt(result[2], 10) + }; +} + // These helper are cloned from SDK to avoid loading to // much SDK modules just because of two functions. function getInnerId(win) { return win.QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsIDOMWindowUtils).currentInnerWindowID; } // Exports from this module exports.ServerLoggingListener = ServerLoggingListener; +exports.parseBacktrace = parseBacktrace;
--- a/dom/base/nsContentIterator.cpp +++ b/dom/base/nsContentIterator.cpp @@ -369,18 +369,18 @@ nsContentIterator::Init(nsIDOMRange* aDO // XXX: In the future, if start offset is after the last // character in the cdata node, should we set mFirst to // the next sibling? // If the node has no child, the child may be <br> or something. // So, we shouldn't skip the empty node if the start offset is 0. // In other words, if the offset is 1, the node should be ignored. if (!startIsData && startIndx) { - mFirst = GetNextSibling(startNode); - NS_WARNING_ASSERTION(mFirst, "GetNextSibling returned null"); + mFirst = NextNode(startNode); + NS_WARNING_ASSERTION(mFirst, "NextNode returned null"); // Does mFirst node really intersect the range? The range could be // 'degenerate', i.e., not collapsed but still contain no content. if (mFirst && NS_WARN_IF(!NodeIsInTraversalRange(mFirst, mPre, startNode, startIndx, endNode, endIndx))) { mFirst = nullptr; } @@ -425,18 +425,18 @@ nsContentIterator::Init(nsIDOMRange* aDO if (NS_WARN_IF(!endNode->IsContent())) { // Not much else to do here... mLast = nullptr; } else { // If the end node is an empty element and the end offset is 0, // the last element should be the previous node (i.e., shouldn't // include the end node in the range). if (!endIsData && !endNode->HasChildren() && !endIndx) { - mLast = GetPrevSibling(endNode); - NS_WARNING_ASSERTION(mLast, "GetPrevSibling returned null"); + mLast = PrevNode(endNode); + NS_WARNING_ASSERTION(mLast, "PrevNode returned null"); if (NS_WARN_IF(!NodeIsInTraversalRange(mLast, mPre, startNode, startIndx, endNode, endIndx))) { mLast = nullptr; } } else { mLast = endNode->AsContent(); }
--- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -12,17 +12,17 @@ // Local Includes #include "Navigator.h" #include "nsContentSecurityManager.h" #include "nsScreen.h" #include "nsHistory.h" #include "nsDOMNavigationTiming.h" #include "nsIDOMStorageManager.h" -#include "mozilla/dom/DOMStorage.h" +#include "mozilla/dom/Storage.h" #include "mozilla/dom/IdleRequest.h" #include "mozilla/dom/Performance.h" #include "mozilla/dom/StorageEvent.h" #include "mozilla/dom/StorageEventBinding.h" #include "mozilla/dom/Timeout.h" #include "mozilla/dom/TimeoutManager.h" #include "mozilla/IntegerPrintfMacros.h" #if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK) @@ -10618,17 +10618,17 @@ nsGlobalWindow::GetComputedStyleHelper(E bool aDefaultStylesOnly, ErrorResult& aError) { FORWARD_TO_OUTER_OR_THROW(GetComputedStyleHelperOuter, (aElt, aPseudoElt, aDefaultStylesOnly), aError, nullptr); } -DOMStorage* +Storage* nsGlobalWindow::GetSessionStorage(ErrorResult& aError) { MOZ_RELEASE_ASSERT(IsInnerWindow()); nsIPrincipal *principal = GetPrincipal(); nsIDocShell* docShell = GetDocShell(); if (!principal || !docShell || !Preferences::GetBool(kStorageEnabled)) { @@ -10681,17 +10681,17 @@ nsGlobalWindow::GetSessionStorage(ErrorR nsCOMPtr<nsIDOMStorage> storage; aError = storageManager->CreateStorage(AsInner(), principal, documentURI, getter_AddRefs(storage)); if (aError.Failed()) { return nullptr; } - mSessionStorage = static_cast<DOMStorage*>(storage.get()); + mSessionStorage = static_cast<Storage*>(storage.get()); MOZ_ASSERT(mSessionStorage); if (MOZ_LOG_TEST(gDOMLeakPRLog, LogLevel::Debug)) { PR_LogPrint("nsGlobalWindow %p tried to get a new sessionStorage %p", this, mSessionStorage.get()); } if (!mSessionStorage) { aError.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); @@ -10701,17 +10701,17 @@ nsGlobalWindow::GetSessionStorage(ErrorR if (MOZ_LOG_TEST(gDOMLeakPRLog, LogLevel::Debug)) { PR_LogPrint("nsGlobalWindow %p returns %p sessionStorage", this, mSessionStorage.get()); } return mSessionStorage; } -DOMStorage* +Storage* nsGlobalWindow::GetLocalStorage(ErrorResult& aError) { MOZ_RELEASE_ASSERT(IsInnerWindow()); if (!Preferences::GetBool(kStorageEnabled)) { return nullptr; } @@ -10749,17 +10749,17 @@ nsGlobalWindow::GetLocalStorage(ErrorRes nsCOMPtr<nsIDOMStorage> storage; aError = storageManager->CreateStorage(AsInner(), principal, documentURI, getter_AddRefs(storage)); if (aError.Failed()) { return nullptr; } - mLocalStorage = static_cast<DOMStorage*>(storage.get()); + mLocalStorage = static_cast<Storage*>(storage.get()); MOZ_ASSERT(mLocalStorage); } return mLocalStorage; } IDBFactory* nsGlobalWindow::GetIndexedDB(ErrorResult& aError) @@ -11580,17 +11580,17 @@ nsGlobalWindow::Observe(nsISupports* aSu nsIPrincipal *principal; nsresult rv; RefPtr<StorageEvent> event = static_cast<StorageEvent*>(aSubject); if (!event) { return NS_ERROR_FAILURE; } - RefPtr<DOMStorage> changingStorage = event->GetStorageArea(); + RefPtr<Storage> changingStorage = event->GetStorageArea(); if (!changingStorage) { return NS_ERROR_FAILURE; } nsCOMPtr<nsIDOMStorage> istorage = changingStorage.get(); bool fireMozStorageChanged = false; nsAutoString eventType; @@ -11606,17 +11606,17 @@ nsGlobalWindow::Observe(nsISupports* aSu if (NS_FAILED(rv)) { return rv; } MOZ_ASSERT((privateBrowsingId > 0) == isPrivateBrowsing); switch (changingStorage->GetType()) { - case DOMStorage::SessionStorage: + case Storage::SessionStorage: { bool check = false; nsCOMPtr<nsIDOMStorageManager> storageManager = do_QueryInterface(GetDocShell()); if (storageManager) { rv = storageManager->CheckStorage(principal, istorage, &check); if (NS_FAILED(rv)) { return rv; @@ -11636,17 +11636,17 @@ nsGlobalWindow::Observe(nsISupports* aSu fireMozStorageChanged = mSessionStorage == changingStorage; if (fireMozStorageChanged) { eventType.AssignLiteral("MozSessionStorageChanged"); } break; } - case DOMStorage::LocalStorage: + case Storage::LocalStorage: { // Allow event fire only for the same principal storages // XXX We have to use EqualsIgnoreDomain after bug 495337 lands nsIPrincipal* storagePrincipal = changingStorage->GetPrincipal(); bool equals = false; rv = storagePrincipal->Equals(principal, &equals); NS_ENSURE_SUCCESS(rv, rv); @@ -11774,24 +11774,24 @@ nsGlobalWindow::CloneStorageEvent(const dict.mBubbles = aEvent->Bubbles(); dict.mCancelable = aEvent->Cancelable(); aEvent->GetKey(dict.mKey); aEvent->GetOldValue(dict.mOldValue); aEvent->GetNewValue(dict.mNewValue); aEvent->GetUrl(dict.mUrl); - RefPtr<DOMStorage> storageArea = aEvent->GetStorageArea(); + RefPtr<Storage> storageArea = aEvent->GetStorageArea(); MOZ_ASSERT(storageArea); - RefPtr<DOMStorage> storage; - if (storageArea->GetType() == DOMStorage::LocalStorage) { + RefPtr<Storage> storage; + if (storageArea->GetType() == Storage::LocalStorage) { storage = GetLocalStorage(aRv); } else { - MOZ_ASSERT(storageArea->GetType() == DOMStorage::SessionStorage); + MOZ_ASSERT(storageArea->GetType() == Storage::SessionStorage); storage = GetSessionStorage(aRv); } if (aRv.Failed() || !storage) { return nullptr; } MOZ_ASSERT(storage);
--- a/dom/base/nsGlobalWindow.h +++ b/dom/base/nsGlobalWindow.h @@ -990,18 +990,18 @@ public: const mozilla::dom::Optional<int32_t>& aTimeout, const mozilla::dom::Sequence<JS::Value>& /* unused */, mozilla::ErrorResult& aError); void ClearInterval(int32_t aHandle); void Atob(const nsAString& aAsciiBase64String, nsAString& aBinaryData, mozilla::ErrorResult& aError); void Btoa(const nsAString& aBinaryData, nsAString& aAsciiBase64String, mozilla::ErrorResult& aError); - mozilla::dom::DOMStorage* GetSessionStorage(mozilla::ErrorResult& aError); - mozilla::dom::DOMStorage* + mozilla::dom::Storage* GetSessionStorage(mozilla::ErrorResult& aError); + mozilla::dom::Storage* GetLocalStorage(mozilla::ErrorResult& aError); mozilla::dom::Selection* GetSelectionOuter(); mozilla::dom::Selection* GetSelection(mozilla::ErrorResult& aError); already_AddRefed<nsISelection> GetSelection() override; mozilla::dom::IDBFactory* GetIndexedDB(mozilla::ErrorResult& aError); already_AddRefed<nsICSSDeclaration> GetComputedStyle(mozilla::dom::Element& aElt, const nsAString& aPseudoElt, mozilla::ErrorResult& aError) override; @@ -1879,31 +1879,30 @@ protected: // We need to store an nsISupports pointer to this object because the // mozilla::dom::External class doesn't exist on b2g and using the type // forward declared here means that ~nsGlobalWindow wouldn't compile because // it wouldn't see the ~External function's declaration. nsCOMPtr<nsISupports> mExternal; RefPtr<mozilla::dom::MozSelfSupport> mMozSelfSupport; - RefPtr<mozilla::dom::DOMStorage> mLocalStorage; - RefPtr<mozilla::dom::DOMStorage> mSessionStorage; + RefPtr<mozilla::dom::Storage> mLocalStorage; + RefPtr<mozilla::dom::Storage> mSessionStorage; // These member variable are used only on inner windows. RefPtr<mozilla::EventListenerManager> mListenerManager; RefPtr<mozilla::dom::Location> mLocation; RefPtr<nsHistory> mHistory; RefPtr<mozilla::dom::CustomElementRegistry> mCustomElements; // These member variables are used on both inner and the outer windows. nsCOMPtr<nsIPrincipal> mDocumentPrincipal; - typedef nsTArray<RefPtr<mozilla::dom::StorageEvent>> nsDOMStorageEventArray; - nsDOMStorageEventArray mPendingStorageEvents; - + typedef nsTArray<RefPtr<mozilla::dom::StorageEvent>> nsStorageEventArray; + nsStorageEventArray mPendingStorageEvents; uint32_t mSuspendDepth; uint32_t mFreezeDepth; // the method that was used to focus mFocusedNode uint32_t mFocusMethod; uint32_t mSerial;
--- a/dom/bindings/Bindings.conf +++ b/dom/bindings/Bindings.conf @@ -758,20 +758,16 @@ DOMInterfaces = { 'headerFile': 'mozilla/dom/workers/bindings/SharedWorker.h', 'implicitJSContext': [ 'constructor' ], }, 'SharedWorkerGlobalScope': { 'headerFile': 'mozilla/dom/WorkerScope.h', }, -'Storage': { - 'nativeType': 'mozilla::dom::DOMStorage', -}, - 'StyleSheet': { 'nativeType': 'mozilla::StyleSheet', 'headerFile': 'mozilla/StyleSheetInlines.h', }, 'SVGAnimatedLengthList': { 'nativeType': 'mozilla::DOMSVGAnimatedLengthList', 'headerFile': 'DOMSVGAnimatedLengthList.h',
--- a/dom/bindings/SimpleGlobalObject.cpp +++ b/dom/bindings/SimpleGlobalObject.cpp @@ -99,17 +99,23 @@ SimpleGlobalObject::Create(GlobalType gl JS::Rooted<JSObject*> global(RootingCx()); { // Scope to ensure the AutoJSAPI destructor runs before we end up returning AutoJSAPI jsapi; jsapi.Init(); JSContext* cx = jsapi.cx(); JS::CompartmentOptions options; - options.creationOptions().setInvisibleToDebugger(true); + options.creationOptions() + .setInvisibleToDebugger(true) + // Put our SimpleGlobalObjects in the system zone, so we won't create + // lots of zones for what are probably very short-lived + // compartments. This should help them be GCed quicker and take up + // less memory before they're GCed. + .setZone(JS::SystemZone); if (NS_IsMainThread()) { nsCOMPtr<nsIPrincipal> principal = nsNullPrincipal::Create(); options.creationOptions().setTrace(xpc::TraceXPCGlobal); global = xpc::CreateGlobalObject(cx, js::Jsvalify(&SimpleGlobalClass), nsJSPrincipals::get(principal), options); } else {
--- a/dom/events/StorageEvent.cpp +++ b/dom/events/StorageEvent.cpp @@ -1,16 +1,16 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* 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/. */ #include "mozilla/dom/StorageEvent.h" -#include "mozilla/dom/DOMStorage.h" +#include "mozilla/dom/Storage.h" namespace mozilla { namespace dom { NS_IMPL_CYCLE_COLLECTION_CLASS(StorageEvent) NS_IMPL_ADDREF_INHERITED(StorageEvent, Event) NS_IMPL_RELEASE_INHERITED(StorageEvent, Event) @@ -80,17 +80,17 @@ StorageEvent::Constructor(const GlobalOb } void StorageEvent::InitStorageEvent(const nsAString& aType, bool aCanBubble, bool aCancelable, const nsAString& aKey, const nsAString& aOldValue, const nsAString& aNewValue, const nsAString& aURL, - DOMStorage* aStorageArea) + Storage* aStorageArea) { NS_ENSURE_TRUE_VOID(!mEvent->mFlags.mIsBeingDispatched); InitEvent(aType, aCanBubble, aCancelable); mKey = aKey; mOldValue = aOldValue; mNewValue = aNewValue; mUrl = aURL;
--- a/dom/events/StorageEvent.h +++ b/dom/events/StorageEvent.h @@ -11,34 +11,34 @@ #include "mozilla/ErrorResult.h" #include "mozilla/dom/BindingUtils.h" #include "mozilla/dom/Event.h" #include "mozilla/dom/StorageEventBinding.h" namespace mozilla { namespace dom { -class DOMStorage; +class Storage; class StorageEvent : public Event { public: NS_DECL_ISUPPORTS_INHERITED NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(StorageEvent, Event) explicit StorageEvent(EventTarget* aOwner); protected: virtual ~StorageEvent(); nsString mKey; nsString mOldValue; nsString mNewValue; nsString mUrl; - RefPtr<DOMStorage> mStorageArea; + RefPtr<Storage> mStorageArea; public: virtual StorageEvent* AsStorageEvent(); virtual JSObject* WrapObjectInternal(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override; static already_AddRefed<StorageEvent> Constructor(EventTarget* aOwner, const nsAString& aType, @@ -48,17 +48,17 @@ public: Constructor(const GlobalObject& aGlobal, const nsAString& aType, const StorageEventInit& aEventInitDict, ErrorResult& aRv); void InitStorageEvent(const nsAString& aType, bool aCanBubble, bool aCancelable, const nsAString& aKey, const nsAString& aOldValue, const nsAString& aNewValue, const nsAString& aURL, - DOMStorage* aStorageArea); + Storage* aStorageArea); void GetKey(nsString& aRetVal) const { aRetVal = mKey; } void GetOldValue(nsString& aRetVal) const { @@ -70,17 +70,17 @@ public: aRetVal = mNewValue; } void GetUrl(nsString& aRetVal) const { aRetVal = mUrl; } - DOMStorage* GetStorageArea() const + Storage* GetStorageArea() const { return mStorageArea; } }; } // namespace dom } // namespace mozilla
--- a/dom/fetch/InternalRequest.cpp +++ b/dom/fetch/InternalRequest.cpp @@ -437,35 +437,17 @@ InternalRequest::MapChannelToRequestMode RequestCredentials InternalRequest::MapChannelToRequestCredentials(nsIChannel* aChannel) { MOZ_ASSERT(aChannel); nsCOMPtr<nsILoadInfo> loadInfo; MOZ_ALWAYS_SUCCEEDS(aChannel->GetLoadInfo(getter_AddRefs(loadInfo))); - - // TODO: Remove following code after stylesheet and image support cookie policy - if (loadInfo->GetSecurityMode() == nsILoadInfo::SEC_NORMAL) { - uint32_t loadFlags; - aChannel->GetLoadFlags(&loadFlags); - - if (loadFlags & nsIRequest::LOAD_ANONYMOUS) { - return RequestCredentials::Omit; - } else { - bool includeCrossOrigin; - nsCOMPtr<nsIHttpChannelInternal> internalChannel = do_QueryInterface(aChannel); - - internalChannel->GetCorsIncludeCredentials(&includeCrossOrigin); - if (includeCrossOrigin) { - return RequestCredentials::Include; - } - } - return RequestCredentials::Same_origin; - } + MOZ_DIAGNOSTIC_ASSERT(loadInfo->GetSecurityMode() != nsILoadInfo::SEC_NORMAL); uint32_t cookiePolicy = loadInfo->GetCookiePolicy(); if (cookiePolicy == nsILoadInfo::SEC_COOKIES_INCLUDE) { return RequestCredentials::Include; } else if (cookiePolicy == nsILoadInfo::SEC_COOKIES_OMIT) { return RequestCredentials::Omit; } else if (cookiePolicy == nsILoadInfo::SEC_COOKIES_SAME_ORIGIN) {
--- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -23,23 +23,23 @@ #include "mozilla/devtools/HeapSnapshotTempFileHelperChild.h" #include "mozilla/docshell/OfflineCacheUpdateChild.h" #include "mozilla/dom/ContentBridgeChild.h" #include "mozilla/dom/ContentBridgeParent.h" #include "mozilla/dom/VideoDecoderManagerChild.h" #include "mozilla/dom/ContentParent.h" #include "mozilla/dom/DataTransfer.h" #include "mozilla/dom/DocGroup.h" -#include "mozilla/dom/DOMStorageIPC.h" #include "mozilla/dom/ExternalHelperAppChild.h" #include "mozilla/dom/FlyWebPublishedServerIPC.h" #include "mozilla/dom/GetFilesHelper.h" #include "mozilla/dom/PCrashReporterChild.h" #include "mozilla/dom/ProcessGlobal.h" #include "mozilla/dom/PushNotifier.h" +#include "mozilla/dom/StorageIPC.h" #include "mozilla/dom/TabGroup.h" #include "mozilla/dom/workers/ServiceWorkerManager.h" #include "mozilla/dom/nsIContentChild.h" #include "mozilla/dom/URLClassifierChild.h" #include "mozilla/dom/ipc/BlobChild.h" #include "mozilla/gfx/gfxVars.h" #include "mozilla/psm/PSMContentListener.h" #include "mozilla/hal_sandbox/PHalChild.h" @@ -1947,17 +1947,17 @@ ContentChild::AllocPStorageChild() { MOZ_CRASH("We should never be manually allocating PStorageChild actors"); return nullptr; } bool ContentChild::DeallocPStorageChild(PStorageChild* aActor) { - DOMStorageDBChild* child = static_cast<DOMStorageDBChild*>(aActor); + StorageDBChild* child = static_cast<StorageDBChild*>(aActor); child->ReleaseIPDLReference(); return true; } PSpeechSynthesisChild* ContentChild::AllocPSpeechSynthesisChild() { #ifdef MOZ_WEBSPEECH
--- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -36,28 +36,28 @@ #include "mozilla/WindowsVersion.h" #endif #include "mozilla/ClearOnShutdown.h" #include "mozilla/StyleSheetInlines.h" #include "mozilla/DataStorage.h" #include "mozilla/devtools/HeapSnapshotTempFileHelperParent.h" #include "mozilla/docshell/OfflineCacheUpdateParent.h" #include "mozilla/dom/DataTransfer.h" -#include "mozilla/dom/DOMStorageIPC.h" #include "mozilla/dom/Element.h" #include "mozilla/dom/File.h" #include "mozilla/dom/ExternalHelperAppParent.h" #include "mozilla/dom/GetFilesHelper.h" #include "mozilla/dom/GeolocationBinding.h" #include "mozilla/dom/Notification.h" #include "mozilla/dom/PContentBridgeParent.h" #include "mozilla/dom/PContentPermissionRequestParent.h" #include "mozilla/dom/PCycleCollectWithLogsParent.h" #include "mozilla/dom/PMemoryReportRequestParent.h" #include "mozilla/dom/ServiceWorkerRegistrar.h" +#include "mozilla/dom/StorageIPC.h" #include "mozilla/dom/devicestorage/DeviceStorageRequestParent.h" #include "mozilla/dom/power/PowerManagerService.h" #include "mozilla/dom/Permissions.h" #include "mozilla/dom/PresentationParent.h" #include "mozilla/dom/PPresentationParent.h" #include "mozilla/dom/PushNotifier.h" #include "mozilla/dom/FlyWebPublishedServerIPC.h" #include "mozilla/dom/quota/QuotaManagerService.h" @@ -3035,23 +3035,23 @@ bool ContentParent::DeallocPMediaParent(media::PMediaParent *aActor) { return media::DeallocPMediaParent(aActor); } PStorageParent* ContentParent::AllocPStorageParent() { - return new DOMStorageDBParent(); + return new StorageDBParent(); } bool ContentParent::DeallocPStorageParent(PStorageParent* aActor) { - DOMStorageDBParent* child = static_cast<DOMStorageDBParent*>(aActor); + StorageDBParent* child = static_cast<StorageDBParent*>(aActor); child->ReleaseIPDLReference(); return true; } PPresentationParent* ContentParent::AllocPPresentationParent() { RefPtr<PresentationParent> actor = new PresentationParent();
--- a/dom/storage/PStorage.ipdl +++ b/dom/storage/PStorage.ipdl @@ -4,42 +4,49 @@ * 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/. */ include protocol PContent; namespace mozilla { namespace dom { -/* This protocol bridges async access to the database thread running on the parent process - * and caches running on the child process. +/* This protocol bridges async access to the database thread running on the + * parent process and caches running on the child process. */ nested(upto inside_cpow) sync protocol PStorage { manager PContent; parent: async __delete__(); - nested(inside_cpow) sync Preload(nsCString originSuffix, nsCString originNoSuffix, uint32_t alreadyLoadedCount) + nested(inside_cpow) sync Preload(nsCString originSuffix, + nsCString originNoSuffix, + uint32_t alreadyLoadedCount) returns (nsString[] keys, nsString[] values, nsresult rv); - async AsyncPreload(nsCString originSuffix, nsCString originNoSuffix, bool priority); + async AsyncPreload(nsCString originSuffix, nsCString originNoSuffix, + bool priority); async AsyncGetUsage(nsCString scope); - async AsyncAddItem(nsCString originSuffix, nsCString originNoSuffix, nsString key, nsString value); - async AsyncUpdateItem(nsCString originSuffix, nsCString originNoSuffix, nsString key, nsString value); - async AsyncRemoveItem(nsCString originSuffix, nsCString originNoSuffix, nsString key); + async AsyncAddItem(nsCString originSuffix, nsCString originNoSuffix, + nsString key, nsString value); + async AsyncUpdateItem(nsCString originSuffix, nsCString originNoSuffix, + nsString key, nsString value); + async AsyncRemoveItem(nsCString originSuffix, nsCString originNoSuffix, + nsString key); async AsyncClear(nsCString originSuffix, nsCString originNoSuffix); async AsyncFlush(); child: async Observe(nsCString topic, nsString originAttributesPattern, nsCString originScope); async OriginsHavingData(nsCString[] origins); - async LoadItem(nsCString originSuffix, nsCString originNoSuffix, nsString key, nsString value); + async LoadItem(nsCString originSuffix, nsCString originNoSuffix, nsString key, + nsString value); async LoadDone(nsCString originSuffix, nsCString originNoSuffix, nsresult rv); async LoadUsage(nsCString scope, int64_t usage); async Error(nsresult rv); }; } }
rename from dom/storage/DOMStorage.cpp rename to dom/storage/Storage.cpp --- a/dom/storage/DOMStorage.cpp +++ b/dom/storage/Storage.cpp @@ -1,17 +1,17 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* 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/. */ -#include "DOMStorage.h" -#include "DOMStorageCache.h" -#include "DOMStorageManager.h" +#include "Storage.h" +#include "StorageCache.h" +#include "StorageManager.h" #include "nsIObserverService.h" #include "nsIScriptSecurityManager.h" #include "nsIPermissionManager.h" #include "nsIPrincipal.h" #include "nsICookiePermission.h" #include "mozilla/dom/StorageBinding.h" @@ -22,98 +22,98 @@ #include "mozilla/EnumSet.h" #include "nsThreadUtils.h" #include "nsContentUtils.h" #include "nsServiceManagerUtils.h" namespace mozilla { namespace dom { -NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(DOMStorage, mManager, mPrincipal, mWindow) +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Storage, mManager, mPrincipal, mWindow) -NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMStorage) -NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMStorage) +NS_IMPL_CYCLE_COLLECTING_ADDREF(Storage) +NS_IMPL_CYCLE_COLLECTING_RELEASE(Storage) -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMStorage) +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Storage) NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMStorage) NS_INTERFACE_MAP_ENTRY(nsIDOMStorage) NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) NS_INTERFACE_MAP_END -DOMStorage::DOMStorage(nsPIDOMWindowInner* aWindow, - DOMStorageManager* aManager, - DOMStorageCache* aCache, - const nsAString& aDocumentURI, - nsIPrincipal* aPrincipal) -: mWindow(aWindow) -, mManager(aManager) -, mCache(aCache) -, mDocumentURI(aDocumentURI) -, mPrincipal(aPrincipal) -, mIsSessionOnly(false) +Storage::Storage(nsPIDOMWindowInner* aWindow, + StorageManagerBase* aManager, + StorageCache* aCache, + const nsAString& aDocumentURI, + nsIPrincipal* aPrincipal) + : mWindow(aWindow) + , mManager(aManager) + , mCache(aCache) + , mDocumentURI(aDocumentURI) + , mPrincipal(aPrincipal) + , mIsSessionOnly(false) { mCache->Preload(); } -DOMStorage::~DOMStorage() +Storage::~Storage() { mCache->KeepAlive(); } /* virtual */ JSObject* -DOMStorage::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) +Storage::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) { return StorageBinding::Wrap(aCx, this, aGivenProto); } uint32_t -DOMStorage::GetLength(nsIPrincipal& aSubjectPrincipal, - ErrorResult& aRv) +Storage::GetLength(nsIPrincipal& aSubjectPrincipal, + ErrorResult& aRv) { if (!CanUseStorage(aSubjectPrincipal)) { aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); return 0; } uint32_t length; aRv = mCache->GetLength(this, &length); return length; } void -DOMStorage::Key(uint32_t aIndex, nsAString& aResult, - nsIPrincipal& aSubjectPrincipal, - ErrorResult& aRv) +Storage::Key(uint32_t aIndex, nsAString& aResult, + nsIPrincipal& aSubjectPrincipal, + ErrorResult& aRv) { if (!CanUseStorage(aSubjectPrincipal)) { aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); return; } aRv = mCache->GetKey(this, aIndex, aResult); } void -DOMStorage::GetItem(const nsAString& aKey, nsAString& aResult, - nsIPrincipal& aSubjectPrincipal, - ErrorResult& aRv) +Storage::GetItem(const nsAString& aKey, nsAString& aResult, + nsIPrincipal& aSubjectPrincipal, + ErrorResult& aRv) { if (!CanUseStorage(aSubjectPrincipal)) { aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); return; } aRv = mCache->GetItem(this, aKey, aResult); } void -DOMStorage::SetItem(const nsAString& aKey, const nsAString& aData, - nsIPrincipal& aSubjectPrincipal, - ErrorResult& aRv) +Storage::SetItem(const nsAString& aKey, const nsAString& aData, + nsIPrincipal& aSubjectPrincipal, + ErrorResult& aRv) { if (!CanUseStorage(aSubjectPrincipal)) { aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); return; } nsString data; bool ok = data.Assign(aData, fallible); @@ -129,19 +129,18 @@ DOMStorage::SetItem(const nsAString& aKe } if (!aRv.ErrorCodeIs(NS_SUCCESS_DOM_NO_OPERATION)) { BroadcastChangeNotification(aKey, old, aData); } } void -DOMStorage::RemoveItem(const nsAString& aKey, - nsIPrincipal& aSubjectPrincipal, - ErrorResult& aRv) +Storage::RemoveItem(const nsAString& aKey, nsIPrincipal& aSubjectPrincipal, + ErrorResult& aRv) { if (!CanUseStorage(aSubjectPrincipal)) { aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); return; } nsAutoString old; aRv = mCache->RemoveItem(this, aKey, old); @@ -150,18 +149,17 @@ DOMStorage::RemoveItem(const nsAString& } if (!aRv.ErrorCodeIs(NS_SUCCESS_DOM_NO_OPERATION)) { BroadcastChangeNotification(aKey, old, NullString()); } } void -DOMStorage::Clear(nsIPrincipal& aSubjectPrincipal, - ErrorResult& aRv) +Storage::Clear(nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv) { if (!CanUseStorage(aSubjectPrincipal)) { aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); return; } aRv = mCache->Clear(this); if (NS_WARN_IF(aRv.Failed())) { @@ -204,19 +202,19 @@ StorageNotifierRunnable::Run() mType); } return NS_OK; } } // namespace void -DOMStorage::BroadcastChangeNotification(const nsSubstring& aKey, - const nsSubstring& aOldValue, - const nsSubstring& aNewValue) +Storage::BroadcastChangeNotification(const nsSubstring& aKey, + const nsSubstring& aOldValue, + const nsSubstring& aNewValue) { StorageEventInit dict; dict.mBubbles = false; dict.mCancelable = false; dict.mKey = aKey; dict.mNewValue = aNewValue; dict.mOldValue = aOldValue; dict.mStorageArea = this; @@ -235,17 +233,17 @@ DOMStorage::BroadcastChangeNotification( IsPrivate()); NS_DispatchToMainThread(r); } static const char kPermissionType[] = "cookie"; static const char kStorageEnabled[] = "dom.storage.enabled"; bool -DOMStorage::CanUseStorage(nsIPrincipal& aSubjectPrincipal) +Storage::CanUseStorage(nsIPrincipal& aSubjectPrincipal) { // This method is responsible for correct setting of mIsSessionOnly. if (!mozilla::Preferences::GetBool(kStorageEnabled)) { return false; } nsContentUtils::StorageAccess access = @@ -254,57 +252,58 @@ DOMStorage::CanUseStorage(nsIPrincipal& if (access == nsContentUtils::StorageAccess::eDeny) { return false; } mIsSessionOnly = access <= nsContentUtils::StorageAccess::eSessionScoped; return CanAccess(&aSubjectPrincipal); } -DOMStorage::StorageType -DOMStorage::GetType() const +Storage::StorageType +Storage::GetType() const { return mManager->Type(); } nsIPrincipal* -DOMStorage::GetPrincipal() +Storage::GetPrincipal() { return mPrincipal; } -// Defined in DOMStorageManager.cpp +// Defined in StorageManager.cpp extern bool -PrincipalsEqual(nsIPrincipal* aObjectPrincipal, nsIPrincipal* aSubjectPrincipal); +PrincipalsEqual(nsIPrincipal* aObjectPrincipal, + nsIPrincipal* aSubjectPrincipal); bool -DOMStorage::PrincipalEquals(nsIPrincipal* aPrincipal) +Storage::PrincipalEquals(nsIPrincipal* aPrincipal) { return PrincipalsEqual(mPrincipal, aPrincipal); } bool -DOMStorage::IsPrivate() const +Storage::IsPrivate() const { uint32_t privateBrowsingId = 0; nsresult rv = mPrincipal->GetPrivateBrowsingId(&privateBrowsingId); if (NS_FAILED(rv)) { return false; } return privateBrowsingId > 0; } bool -DOMStorage::CanAccess(nsIPrincipal* aPrincipal) +Storage::CanAccess(nsIPrincipal* aPrincipal) { return !aPrincipal || aPrincipal->Subsumes(mPrincipal); } void -DOMStorage::GetSupportedNames(nsTArray<nsString>& aKeys) +Storage::GetSupportedNames(nsTArray<nsString>& aKeys) { if (!CanUseStorage(*nsContentUtils::SubjectPrincipal())) { // return just an empty array aKeys.Clear(); return; } mCache->GetKeys(this, aKeys);
rename from dom/storage/DOMStorage.h rename to dom/storage/Storage.h --- a/dom/storage/DOMStorage.h +++ b/dom/storage/Storage.h @@ -1,74 +1,75 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* 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 nsDOMStorage_h___ -#define nsDOMStorage_h___ +#ifndef mozilla_dom_Storage_h +#define mozilla_dom_Storage_h #include "mozilla/Attributes.h" #include "mozilla/ErrorResult.h" #include "mozilla/Maybe.h" #include "nsIDOMStorage.h" #include "nsCycleCollectionParticipant.h" #include "nsWeakReference.h" #include "nsWrapperCache.h" #include "nsISupports.h" class nsIPrincipal; class nsPIDOMWindowInner; namespace mozilla { namespace dom { -class DOMStorageManager; -class DOMStorageCache; +class StorageManagerBase; +class StorageCache; -class DOMStorage final +class Storage final : public nsIDOMStorage , public nsSupportsWeakReference , public nsWrapperCache { public: NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(DOMStorage, + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(Storage, nsIDOMStorage) enum StorageType { LocalStorage = 1, SessionStorage = 2 }; StorageType GetType() const; - DOMStorageManager* GetManager() const + StorageManagerBase* GetManager() const { return mManager; } - DOMStorageCache const* GetCache() const + StorageCache const* GetCache() const { return mCache; } nsIPrincipal* GetPrincipal(); bool PrincipalEquals(nsIPrincipal* aPrincipal); bool CanAccess(nsIPrincipal* aPrincipal); - DOMStorage(nsPIDOMWindowInner* aWindow, - DOMStorageManager* aManager, - DOMStorageCache* aCache, - const nsAString& aDocumentURI, - nsIPrincipal* aPrincipal); + Storage(nsPIDOMWindowInner* aWindow, + StorageManagerBase* aManager, + StorageCache* aCache, + const nsAString& aDocumentURI, + nsIPrincipal* aPrincipal); // WebIDL - JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override; + JSObject* WrapObject(JSContext* aCx, + JS::Handle<JSObject*> aGivenProto) override; nsPIDOMWindowInner* GetParentObject() const { return mWindow; } uint32_t GetLength(nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv); @@ -116,53 +117,53 @@ public: } void Clear(nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv); bool IsPrivate() const; bool IsSessionOnly() const { return mIsSessionOnly; } - bool IsForkOf(const DOMStorage* aOther) const + bool IsForkOf(const Storage* aOther) const { MOZ_ASSERT(aOther); return mCache == aOther->mCache; } protected: // The method checks whether the caller can use a storage. // CanUseStorage is called before any DOM initiated operation // on a storage is about to happen and ensures that the storage's // session-only flag is properly set according the current settings. // It is an optimization since the privileges check and session only // state determination are complex and share the code (comes hand in // hand together). bool CanUseStorage(nsIPrincipal& aSubjectPrincipal); private: - ~DOMStorage(); + ~Storage(); - friend class DOMStorageManager; - friend class DOMStorageCache; + friend class StorageManagerBase; + friend class StorageCache; nsCOMPtr<nsPIDOMWindowInner> mWindow; - RefPtr<DOMStorageManager> mManager; - RefPtr<DOMStorageCache> mCache; + RefPtr<StorageManagerBase> mManager; + RefPtr<StorageCache> mCache; nsString mDocumentURI; - // Principal this DOMStorage (i.e. localStorage or sessionStorage) has + // Principal this Storage (i.e. localStorage or sessionStorage) has // been created for nsCOMPtr<nsIPrincipal> mPrincipal; // Whether storage is set to persist data only per session, may change // dynamically and is set by CanUseStorage function that is called // before any operation on the storage. bool mIsSessionOnly : 1; void BroadcastChangeNotification(const nsSubstring& aKey, const nsSubstring& aOldValue, const nsSubstring& aNewValue); }; } // namespace dom } // namespace mozilla -#endif /* nsDOMStorage_h___ */ +#endif // mozilla_dom_Storage_h
rename from dom/storage/DOMStorageCache.cpp rename to dom/storage/StorageCache.cpp --- a/dom/storage/DOMStorageCache.cpp +++ b/dom/storage/StorageCache.cpp @@ -1,36 +1,36 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* 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/. */ -#include "DOMStorageCache.h" +#include "StorageCache.h" -#include "DOMStorage.h" -#include "DOMStorageDBThread.h" -#include "DOMStorageIPC.h" -#include "DOMStorageManager.h" +#include "Storage.h" +#include "StorageDBThread.h" +#include "StorageIPC.h" +#include "StorageManager.h" #include "nsAutoPtr.h" #include "nsDOMString.h" #include "nsXULAppAPI.h" #include "mozilla/Unused.h" #include "nsProxyRelease.h" #include "nsThreadUtils.h" namespace mozilla { namespace dom { #define DOM_STORAGE_CACHE_KEEP_ALIVE_TIME_MS 20000 // static -DOMStorageDBBridge* DOMStorageCache::sDatabase = nullptr; -bool DOMStorageCache::sDatabaseDown = false; +StorageDBBridge* StorageCache::sDatabase = nullptr; +bool StorageCache::sDatabaseDown = false; namespace { const uint32_t kDefaultSet = 0; const uint32_t kPrivateSet = 1; const uint32_t kSessionSet = 2; inline uint32_t @@ -43,94 +43,94 @@ GetDataSetIndex(bool aPrivate, bool aSes if (aSessionOnly) { return kSessionSet; } return kDefaultSet; } inline uint32_t -GetDataSetIndex(const DOMStorage* aStorage) +GetDataSetIndex(const Storage* aStorage) { return GetDataSetIndex(aStorage->IsPrivate(), aStorage->IsSessionOnly()); } } // namespace -// DOMStorageCacheBridge +// StorageCacheBridge -NS_IMPL_ADDREF(DOMStorageCacheBridge) +NS_IMPL_ADDREF(StorageCacheBridge) // Since there is no consumer of return value of Release, we can turn this -// method to void to make implementation of asynchronous DOMStorageCache::Release +// method to void to make implementation of asynchronous StorageCache::Release // much simpler. -NS_IMETHODIMP_(void) DOMStorageCacheBridge::Release(void) +NS_IMETHODIMP_(void) StorageCacheBridge::Release(void) { MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release"); nsrefcnt count = --mRefCnt; - NS_LOG_RELEASE(this, count, "DOMStorageCacheBridge"); + NS_LOG_RELEASE(this, count, "StorageCacheBridge"); if (0 == count) { mRefCnt = 1; /* stabilize */ /* enable this to find non-threadsafe destructors: */ /* NS_ASSERT_OWNINGTHREAD(_class); */ delete (this); } } -// DOMStorageCache +// StorageCache -DOMStorageCache::DOMStorageCache(const nsACString* aOriginNoSuffix) -: mOriginNoSuffix(*aOriginNoSuffix) -, mMonitor("DOMStorageCache") -, mLoaded(false) -, mLoadResult(NS_OK) -, mInitialized(false) -, mPersistent(false) -, mSessionOnlyDataSetActive(false) -, mPreloadTelemetryRecorded(false) +StorageCache::StorageCache(const nsACString* aOriginNoSuffix) + : mOriginNoSuffix(*aOriginNoSuffix) + , mMonitor("StorageCache") + , mLoaded(false) + , mLoadResult(NS_OK) + , mInitialized(false) + , mPersistent(false) + , mSessionOnlyDataSetActive(false) + , mPreloadTelemetryRecorded(false) { - MOZ_COUNT_CTOR(DOMStorageCache); + MOZ_COUNT_CTOR(StorageCache); } -DOMStorageCache::~DOMStorageCache() +StorageCache::~StorageCache() { if (mManager) { mManager->DropCache(this); } - MOZ_COUNT_DTOR(DOMStorageCache); + MOZ_COUNT_DTOR(StorageCache); } NS_IMETHODIMP_(void) -DOMStorageCache::Release(void) +StorageCache::Release(void) { // We must actually release on the main thread since the cache removes it // self from the manager's hash table. And we don't want to lock access to // that hash table. if (NS_IsMainThread()) { - DOMStorageCacheBridge::Release(); + StorageCacheBridge::Release(); return; } - RefPtr<nsRunnableMethod<DOMStorageCacheBridge, void, false> > event = - NewNonOwningRunnableMethod(static_cast<DOMStorageCacheBridge*>(this), - &DOMStorageCacheBridge::Release); + RefPtr<nsRunnableMethod<StorageCacheBridge, void, false> > event = + NewNonOwningRunnableMethod(static_cast<StorageCacheBridge*>(this), + &StorageCacheBridge::Release); nsresult rv = NS_DispatchToMainThread(event); if (NS_FAILED(rv)) { - NS_WARNING("DOMStorageCache::Release() on a non-main thread"); - DOMStorageCacheBridge::Release(); + NS_WARNING("StorageCache::Release() on a non-main thread"); + StorageCacheBridge::Release(); } } void -DOMStorageCache::Init(DOMStorageManager* aManager, - bool aPersistent, - nsIPrincipal* aPrincipal, - const nsACString& aQuotaOriginScope) +StorageCache::Init(StorageManagerBase* aManager, + bool aPersistent, + nsIPrincipal* aPrincipal, + const nsACString& aQuotaOriginScope) { if (mInitialized) { return; } mInitialized = true; mPrincipal = aPrincipal; aPrincipal->OriginAttributesRef().CreateSuffix(mOriginSuffix); @@ -151,31 +151,31 @@ DOMStorageCache::Init(DOMStorageManager* MOZ_ASSERT(StringBeginsWith(mQuotaOriginScope, mOriginSuffix)); MOZ_ASSERT(mOriginSuffix.IsEmpty() != StringBeginsWith(mQuotaOriginScope, NS_LITERAL_CSTRING("^"))); mUsage = aManager->GetOriginUsage(mQuotaOriginScope); } inline bool -DOMStorageCache::Persist(const DOMStorage* aStorage) const +StorageCache::Persist(const Storage* aStorage) const { return mPersistent && !aStorage->IsSessionOnly() && !aStorage->IsPrivate(); } const nsCString -DOMStorageCache::Origin() const +StorageCache::Origin() const { - return DOMStorageManager::CreateOrigin(mOriginSuffix, mOriginNoSuffix); + return StorageManagerBase::CreateOrigin(mOriginSuffix, mOriginNoSuffix); } -DOMStorageCache::Data& -DOMStorageCache::DataSet(const DOMStorage* aStorage) +StorageCache::Data& +StorageCache::DataSet(const Storage* aStorage) { uint32_t index = GetDataSetIndex(aStorage); if (index == kSessionSet && !mSessionOnlyDataSetActive) { // Session only data set is demanded but not filled with // current data set, copy to session only set now. WaitForPreload(Telemetry::LOCALDOMSTORAGE_SESSIONONLY_PRELOAD_BLOCKING_MS); @@ -193,48 +193,48 @@ DOMStorageCache::DataSet(const DOMStorag // for all session only data ProcessUsageDelta(kSessionSet, defaultSet.mOriginQuotaUsage); } return mData[index]; } bool -DOMStorageCache::ProcessUsageDelta(const DOMStorage* aStorage, int64_t aDelta) +StorageCache::ProcessUsageDelta(const Storage* aStorage, int64_t aDelta) { return ProcessUsageDelta(GetDataSetIndex(aStorage), aDelta); } bool -DOMStorageCache::ProcessUsageDelta(uint32_t aGetDataSetIndex, const int64_t aDelta) +StorageCache::ProcessUsageDelta(uint32_t aGetDataSetIndex, const int64_t aDelta) { // Check if we are in a low disk space situation if (aDelta > 0 && mManager && mManager->IsLowDiskSpace()) { return false; } // Check limit per this origin Data& data = mData[aGetDataSetIndex]; uint64_t newOriginUsage = data.mOriginQuotaUsage + aDelta; - if (aDelta > 0 && newOriginUsage > DOMStorageManager::GetQuota()) { + if (aDelta > 0 && newOriginUsage > StorageManagerBase::GetQuota()) { return false; } // Now check eTLD+1 limit if (mUsage && !mUsage->CheckAndSetETLD1UsageDelta(aGetDataSetIndex, aDelta)) { return false; } // Update size in our data set data.mOriginQuotaUsage = newOriginUsage; return true; } void -DOMStorageCache::Preload() +StorageCache::Preload() { if (mLoaded || !mPersistent) { return; } if (!StartDatabase()) { mLoaded = true; mLoadResult = NS_ERROR_FAILURE; @@ -243,87 +243,92 @@ DOMStorageCache::Preload() sDatabase->AsyncPreload(this); } namespace { // This class is passed to timer as a tick observer. It refers the cache // and keeps it alive for a time. -class DOMStorageCacheHolder : public nsITimerCallback +class StorageCacheHolder : public nsITimerCallback { - virtual ~DOMStorageCacheHolder() {} + virtual ~StorageCacheHolder() {} NS_DECL_ISUPPORTS NS_IMETHOD Notify(nsITimer* aTimer) override { mCache = nullptr; return NS_OK; } - RefPtr<DOMStorageCache> mCache; + RefPtr<StorageCache> mCache; public: - explicit DOMStorageCacheHolder(DOMStorageCache* aCache) : mCache(aCache) {} + explicit StorageCacheHolder(StorageCache* aCache) : mCache(aCache) {} }; -NS_IMPL_ISUPPORTS(DOMStorageCacheHolder, nsITimerCallback) +NS_IMPL_ISUPPORTS(StorageCacheHolder, nsITimerCallback) } // namespace void -DOMStorageCache::KeepAlive() +StorageCache::KeepAlive() { // Missing reference back to the manager means the cache is not responsible // for its lifetime. Used for keeping sessionStorage live forever. if (!mManager) { return; } if (!NS_IsMainThread()) { // Timer and the holder must be initialized on the main thread. - NS_DispatchToMainThread(NewRunnableMethod(this, &DOMStorageCache::KeepAlive)); + NS_DispatchToMainThread(NewRunnableMethod(this, &StorageCache::KeepAlive)); return; } nsCOMPtr<nsITimer> timer = do_CreateInstance("@mozilla.org/timer;1"); if (!timer) { return; } - RefPtr<DOMStorageCacheHolder> holder = new DOMStorageCacheHolder(this); + RefPtr<StorageCacheHolder> holder = new StorageCacheHolder(this); timer->InitWithCallback(holder, DOM_STORAGE_CACHE_KEEP_ALIVE_TIME_MS, nsITimer::TYPE_ONE_SHOT); mKeepAliveTimer.swap(timer); } namespace { // The AutoTimer provided by telemetry headers is only using static, // i.e. compile time known ID, but here we know the ID only at run time. // Hence a new class. class TelemetryAutoTimer { public: explicit TelemetryAutoTimer(Telemetry::ID aId) - : id(aId), start(TimeStamp::Now()) {} + : id(aId), start(TimeStamp::Now()) + {} + ~TelemetryAutoTimer() - { Telemetry::AccumulateDelta_impl<Telemetry::Millisecond>::compute(id, start); } + { + Telemetry::AccumulateDelta_impl<Telemetry::Millisecond>::compute(id, start); + } + private: Telemetry::ID id; const TimeStamp start; }; } // namespace void -DOMStorageCache::WaitForPreload(Telemetry::ID aTelemetryID) +StorageCache::WaitForPreload(Telemetry::ID aTelemetryID) { if (!mPersistent) { return; } bool loaded = mLoaded; // Telemetry of rates of pending preloads @@ -349,31 +354,32 @@ DOMStorageCache::WaitForPreload(Telemetr // No need to check sDatabase for being non-null since preload is either // done before we've shut the DB down or when the DB could not start, // preload has not even be started. sDatabase->SyncPreload(this); } nsresult -DOMStorageCache::GetLength(const DOMStorage* aStorage, uint32_t* aRetval) +StorageCache::GetLength(const Storage* aStorage, uint32_t* aRetval) { if (Persist(aStorage)) { WaitForPreload(Telemetry::LOCALDOMSTORAGE_GETLENGTH_BLOCKING_MS); if (NS_FAILED(mLoadResult)) { return mLoadResult; } } *aRetval = DataSet(aStorage).mKeys.Count(); return NS_OK; } nsresult -DOMStorageCache::GetKey(const DOMStorage* aStorage, uint32_t aIndex, nsAString& aRetval) +StorageCache::GetKey(const Storage* aStorage, uint32_t aIndex, + nsAString& aRetval) { // XXX: This does a linear search for the key at index, which would // suck if there's a large numer of indexes. Do we care? If so, // maybe we need to have a lazily populated key array here or // something? if (Persist(aStorage)) { WaitForPreload(Telemetry::LOCALDOMSTORAGE_GETKEY_BLOCKING_MS); if (NS_FAILED(mLoadResult)) { @@ -389,34 +395,34 @@ DOMStorageCache::GetKey(const DOMStorage } aIndex--; } return NS_OK; } void -DOMStorageCache::GetKeys(const DOMStorage* aStorage, nsTArray<nsString>& aKeys) +StorageCache::GetKeys(const Storage* aStorage, nsTArray<nsString>& aKeys) { if (Persist(aStorage)) { WaitForPreload(Telemetry::LOCALDOMSTORAGE_GETALLKEYS_BLOCKING_MS); } if (NS_FAILED(mLoadResult)) { return; } for (auto iter = DataSet(aStorage).mKeys.Iter(); !iter.Done(); iter.Next()) { aKeys.AppendElement(iter.Key()); } } nsresult -DOMStorageCache::GetItem(const DOMStorage* aStorage, const nsAString& aKey, - nsAString& aRetval) +StorageCache::GetItem(const Storage* aStorage, const nsAString& aKey, + nsAString& aRetval) { if (Persist(aStorage)) { WaitForPreload(Telemetry::LOCALDOMSTORAGE_GETVALUE_BLOCKING_MS); if (NS_FAILED(mLoadResult)) { return mLoadResult; } } @@ -427,18 +433,18 @@ DOMStorageCache::GetItem(const DOMStorag } aRetval = value; return NS_OK; } nsresult -DOMStorageCache::SetItem(const DOMStorage* aStorage, const nsAString& aKey, - const nsString& aValue, nsString& aOld) +StorageCache::SetItem(const Storage* aStorage, const nsAString& aKey, + const nsString& aValue, nsString& aOld) { // Size of the cache that will change after this action. int64_t delta = 0; if (Persist(aStorage)) { WaitForPreload(Telemetry::LOCALDOMSTORAGE_SETVALUE_BLOCKING_MS); if (NS_FAILED(mLoadResult)) { return mLoadResult; @@ -479,18 +485,18 @@ DOMStorageCache::SetItem(const DOMStorag return sDatabase->AsyncUpdateItem(this, aKey, aValue); } return NS_OK; } nsresult -DOMStorageCache::RemoveItem(const DOMStorage* aStorage, const nsAString& aKey, - nsString& aOld) +StorageCache::RemoveItem(const Storage* aStorage, const nsAString& aKey, + nsString& aOld) { if (Persist(aStorage)) { WaitForPreload(Telemetry::LOCALDOMSTORAGE_REMOVEKEY_BLOCKING_MS); if (NS_FAILED(mLoadResult)) { return mLoadResult; } } @@ -515,17 +521,17 @@ DOMStorageCache::RemoveItem(const DOMSto return sDatabase->AsyncRemoveItem(this, aKey); } return NS_OK; } nsresult -DOMStorageCache::Clear(const DOMStorage* aStorage) +StorageCache::Clear(const Storage* aStorage) { bool refresh = false; if (Persist(aStorage)) { // We need to preload all data (know the size) before we can proceeed // to correctly decrease cached usage number. // XXX as in case of unload, this is not technically needed now, but // after super-scope quota introduction we have to do this. Get telemetry // right now. @@ -555,17 +561,17 @@ DOMStorageCache::Clear(const DOMStorage* return sDatabase->AsyncClear(this); } return hadData ? NS_OK : NS_SUCCESS_DOM_NO_OPERATION; } void -DOMStorageCache::CloneFrom(const DOMStorageCache* aThat) +StorageCache::CloneFrom(const StorageCache* aThat) { // This will never be called on anything else than SessionStorage. // This means mData will never be touched on any other thread than // the main thread and it never went through the loading process. MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(!mPersistent); MOZ_ASSERT(!(bool)aThat->mLoaded); @@ -577,28 +583,29 @@ DOMStorageCache::CloneFrom(const DOMStor for (uint32_t i = 0; i < kDataSetCount; ++i) { for (auto it = aThat->mData[i].mKeys.ConstIter(); !it.Done(); it.Next()) { mData[i].mKeys.Put(it.Key(), it.UserData()); } ProcessUsageDelta(i, aThat->mData[i].mOriginQuotaUsage); } } -// Defined in DOMStorageManager.cpp +// Defined in StorageManager.cpp extern bool -PrincipalsEqual(nsIPrincipal* aObjectPrincipal, nsIPrincipal* aSubjectPrincipal); +PrincipalsEqual(nsIPrincipal* aObjectPrincipal, + nsIPrincipal* aSubjectPrincipal); bool -DOMStorageCache::CheckPrincipal(nsIPrincipal* aPrincipal) const +StorageCache::CheckPrincipal(nsIPrincipal* aPrincipal) const { return PrincipalsEqual(mPrincipal, aPrincipal); } void -DOMStorageCache::UnloadItems(uint32_t aUnloadFlags) +StorageCache::UnloadItems(uint32_t aUnloadFlags) { if (aUnloadFlags & kUnloadDefault) { // Must wait for preload to pass correct usage to ProcessUsageDelta // XXX this is not technically needed right now since there is just // per-origin isolated quota handling, but when we introduce super- // -scope quotas, we have to do this. Better to start getting // telemetry right now. WaitForPreload(Telemetry::LOCALDOMSTORAGE_UNLOAD_BLOCKING_MS); @@ -624,28 +631,28 @@ DOMStorageCache::UnloadItems(uint32_t aU mData[kDefaultSet].mKeys.Clear(); mLoaded = false; // This is only used in testing code Preload(); } #endif } -// DOMStorageCacheBridge +// StorageCacheBridge uint32_t -DOMStorageCache::LoadedCount() +StorageCache::LoadedCount() { MonitorAutoLock monitor(mMonitor); Data& data = mData[kDefaultSet]; return data.mKeys.Count(); } bool -DOMStorageCache::LoadItem(const nsAString& aKey, const nsString& aValue) +StorageCache::LoadItem(const nsAString& aKey, const nsString& aValue) { MonitorAutoLock monitor(mMonitor); if (mLoaded) { return false; } Data& data = mData[kDefaultSet]; if (data.mKeys.Get(aKey, nullptr)) { @@ -653,39 +660,39 @@ DOMStorageCache::LoadItem(const nsAStrin } data.mKeys.Put(aKey, aValue); data.mOriginQuotaUsage += aKey.Length() + aValue.Length(); return true; } void -DOMStorageCache::LoadDone(nsresult aRv) +StorageCache::LoadDone(nsresult aRv) { // Keep the preloaded cache alive for a time KeepAlive(); MonitorAutoLock monitor(mMonitor); mLoadResult = aRv; mLoaded = true; monitor.Notify(); } void -DOMStorageCache::LoadWait() +StorageCache::LoadWait() { MonitorAutoLock monitor(mMonitor); while (!mLoaded) { monitor.Wait(); } } -// DOMStorageUsage +// StorageUsage -DOMStorageUsage::DOMStorageUsage(const nsACString& aOriginScope) +StorageUsage::StorageUsage(const nsACString& aOriginScope) : mOriginScope(aOriginScope) { mUsage[kDefaultSet] = mUsage[kPrivateSet] = mUsage[kSessionSet] = 0LL; } namespace { class LoadUsageRunnable : public Runnable @@ -701,106 +708,107 @@ private: int64_t mDelta; NS_IMETHOD Run() override { *mTarget = mDelta; return NS_OK; } }; } // namespace void -DOMStorageUsage::LoadUsage(const int64_t aUsage) +StorageUsage::LoadUsage(const int64_t aUsage) { // Using kDefaultSet index since it is the index for the persitent data // stored in the database we have just loaded usage for. if (!NS_IsMainThread()) { // In single process scenario we get this call from the DB thread RefPtr<LoadUsageRunnable> r = new LoadUsageRunnable(mUsage + kDefaultSet, aUsage); NS_DispatchToMainThread(r); } else { // On a child process we get this on the main thread already mUsage[kDefaultSet] += aUsage; } } bool -DOMStorageUsage::CheckAndSetETLD1UsageDelta(uint32_t aDataSetIndex, const int64_t aDelta) +StorageUsage::CheckAndSetETLD1UsageDelta(uint32_t aDataSetIndex, + const int64_t aDelta) { MOZ_ASSERT(NS_IsMainThread()); int64_t newUsage = mUsage[aDataSetIndex] + aDelta; - if (aDelta > 0 && newUsage > DOMStorageManager::GetQuota()) { + if (aDelta > 0 && newUsage > StorageManagerBase::GetQuota()) { return false; } mUsage[aDataSetIndex] = newUsage; return true; } // static -DOMStorageDBBridge* -DOMStorageCache::StartDatabase() +StorageDBBridge* +StorageCache::StartDatabase() { if (sDatabase || sDatabaseDown) { // When sDatabaseDown is at true, sDatabase is null. // Checking sDatabaseDown flag here prevents reinitialization of // the database after shutdown. return sDatabase; } if (XRE_IsParentProcess()) { - nsAutoPtr<DOMStorageDBThread> db(new DOMStorageDBThread()); + nsAutoPtr<StorageDBThread> db(new StorageDBThread()); nsresult rv = db->Init(); if (NS_FAILED(rv)) { return nullptr; } sDatabase = db.forget(); } else { // Use DOMLocalStorageManager::Ensure in case we're called from // DOMSessionStorageManager's initializer and we haven't yet initialized the // local storage manager. - RefPtr<DOMStorageDBChild> db = new DOMStorageDBChild( + RefPtr<StorageDBChild> db = new StorageDBChild( DOMLocalStorageManager::Ensure()); nsresult rv = db->Init(); if (NS_FAILED(rv)) { return nullptr; } db.forget(&sDatabase); } return sDatabase; } // static -DOMStorageDBBridge* -DOMStorageCache::GetDatabase() +StorageDBBridge* +StorageCache::GetDatabase() { return sDatabase; } // static nsresult -DOMStorageCache::StopDatabase() +StorageCache::StopDatabase() { if (!sDatabase) { return NS_OK; } sDatabaseDown = true; nsresult rv = sDatabase->Shutdown(); if (XRE_IsParentProcess()) { delete sDatabase; } else { - DOMStorageDBChild* child = static_cast<DOMStorageDBChild*>(sDatabase); + StorageDBChild* child = static_cast<StorageDBChild*>(sDatabase); NS_RELEASE(child); } sDatabase = nullptr; return rv; } } // namespace dom
rename from dom/storage/DOMStorageCache.h rename to dom/storage/StorageCache.h --- a/dom/storage/DOMStorageCache.h +++ b/dom/storage/StorageCache.h @@ -1,49 +1,49 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* 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 nsDOMStorageCache_h___ -#define nsDOMStorageCache_h___ +#ifndef mozilla_dom_StorageCache_h +#define mozilla_dom_StorageCache_h #include "nsIPrincipal.h" #include "nsITimer.h" #include "nsString.h" #include "nsDataHashtable.h" #include "nsHashKeys.h" #include "mozilla/Monitor.h" #include "mozilla/Telemetry.h" #include "mozilla/Atomics.h" namespace mozilla { namespace dom { -class DOMStorage; -class DOMStorageUsage; -class DOMStorageManager; -class DOMStorageDBBridge; +class Storage; +class StorageUsage; +class StorageManagerBase; +class StorageDBBridge; // Interface class on which only the database or IPC may call. // Used to populate the cache with DB data. -class DOMStorageCacheBridge +class StorageCacheBridge { public: NS_IMETHOD_(MozExternalRefCountType) AddRef(void); NS_IMETHOD_(void) Release(void); - // The origin of the cache, result is concatenation of OriginNoSuffix() and OriginSuffix(), - // see below. + // The origin of the cache, result is concatenation of OriginNoSuffix() and + // OriginSuffix(), see below. virtual const nsCString Origin() const = 0; - // The origin attributes suffix alone, this is usually passed as an |aOriginSuffix| - // argument to various methods + // The origin attributes suffix alone, this is usually passed as an + // |aOriginSuffix| argument to various methods virtual const nsCString& OriginSuffix() const = 0; // The origin in the database usage format (reversed) and without the suffix virtual const nsCString& OriginNoSuffix() const = 0; // Whether the cache is already fully loaded virtual bool Loaded() = 0; @@ -58,77 +58,81 @@ public: // to this cache virtual void LoadDone(nsresult aRv) = 0; // Use to synchronously wait until the cache gets fully loaded with data, // this method exits after LoadDone has been called virtual void LoadWait() = 0; protected: - virtual ~DOMStorageCacheBridge() {} + virtual ~StorageCacheBridge() {} ThreadSafeAutoRefCnt mRefCnt; NS_DECL_OWNINGTHREAD }; // Implementation of scope cache that is responsible for preloading data // for persistent storage (localStorage) and hold data for non-private, // private and session-only cookie modes. It is also responsible for // persisting data changes using the database, works as a write-back cache. -class DOMStorageCache : public DOMStorageCacheBridge +class StorageCache : public StorageCacheBridge { public: NS_IMETHOD_(void) Release(void); // Note: We pass aOriginNoSuffix through the ctor here, because - // DOMStorageCacheHashKey's ctor is creating this class and + // StorageCacheHashKey's ctor is creating this class and // accepts reversed-origin-no-suffix as an argument - the hashing key. - explicit DOMStorageCache(const nsACString* aOriginNoSuffix); + explicit StorageCache(const nsACString* aOriginNoSuffix); protected: - virtual ~DOMStorageCache(); + virtual ~StorageCache(); public: - void Init(DOMStorageManager* aManager, bool aPersistent, nsIPrincipal* aPrincipal, - const nsACString& aQuotaOriginScope); + void Init(StorageManagerBase* aManager, bool aPersistent, + nsIPrincipal* aPrincipal, const nsACString& aQuotaOriginScope); // Copies all data from the other storage. - void CloneFrom(const DOMStorageCache* aThat); + void CloneFrom(const StorageCache* aThat); // Starts async preload of this cache if it persistent and not loaded. void Preload(); - // Keeps the cache alive (i.e. present in the manager's hash table) for a time. + // Keeps the cache alive (i.e. present in the manager's hash table) for a + // time. void KeepAlive(); // The set of methods that are invoked by DOM storage web API. - // We are passing the DOMStorage object just to let the cache + // We are passing the Storage object just to let the cache // read properties like mPrincipal and mSessionOnly. // Get* methods return error when load from the database has failed. - nsresult GetLength(const DOMStorage* aStorage, uint32_t* aRetval); - nsresult GetKey(const DOMStorage* aStorage, uint32_t index, nsAString& aRetval); - nsresult GetItem(const DOMStorage* aStorage, const nsAString& aKey, nsAString& aRetval); - nsresult SetItem(const DOMStorage* aStorage, const nsAString& aKey, const nsString& aValue, nsString& aOld); - nsresult RemoveItem(const DOMStorage* aStorage, const nsAString& aKey, nsString& aOld); - nsresult Clear(const DOMStorage* aStorage); + nsresult GetLength(const Storage* aStorage, uint32_t* aRetval); + nsresult GetKey(const Storage* aStorage, uint32_t index, nsAString& aRetval); + nsresult GetItem(const Storage* aStorage, const nsAString& aKey, + nsAString& aRetval); + nsresult SetItem(const Storage* aStorage, const nsAString& aKey, + const nsString& aValue, nsString& aOld); + nsresult RemoveItem(const Storage* aStorage, const nsAString& aKey, + nsString& aOld); + nsresult Clear(const Storage* aStorage); - void GetKeys(const DOMStorage* aStorage, nsTArray<nsString>& aKeys); + void GetKeys(const Storage* aStorage, nsTArray<nsString>& aKeys); // Whether the principal equals principal the cache was created for bool CheckPrincipal(nsIPrincipal* aPrincipal) const; nsIPrincipal* Principal() const { return mPrincipal; } // Starts the database engine thread or the IPC bridge - static DOMStorageDBBridge* StartDatabase(); - static DOMStorageDBBridge* GetDatabase(); + static StorageDBBridge* StartDatabase(); + static StorageDBBridge* GetDatabase(); // Stops the thread and flushes all uncommited data static nsresult StopDatabase(); - // DOMStorageCacheBridge + // StorageCacheBridge virtual const nsCString Origin() const; virtual const nsCString& OriginNoSuffix() const { return mOriginNoSuffix; } virtual const nsCString& OriginSuffix() const { return mOriginSuffix; } virtual bool Loaded() { return mLoaded; } virtual uint32_t LoadedCount(); virtual bool LoadItem(const nsAString& aKey, const nsString& aValue); virtual void LoadDone(nsresult aRv); @@ -147,17 +151,17 @@ public: public: // Number of data sets we keep: default, private, session static const uint32_t kDataSetCount = 3; private: // API to clear the cache data, this is invoked by chrome operations // like cookie deletion. - friend class DOMStorageManager; + friend class StorageManagerBase; static const uint32_t kUnloadDefault = 1 << 0; static const uint32_t kUnloadPrivate = 1 << 1; static const uint32_t kUnloadSession = 1 << 2; static const uint32_t kUnloadComplete = kUnloadDefault | kUnloadPrivate | kUnloadSession; #ifdef DOM_STORAGE_TESTS @@ -166,44 +170,44 @@ private: void UnloadItems(uint32_t aUnloadFlags); private: // Synchronously blocks until the cache is fully loaded from the database void WaitForPreload(mozilla::Telemetry::ID aTelemetryID); // Helper to get one of the 3 data sets (regular, private, session) - Data& DataSet(const DOMStorage* aStorage); + Data& DataSet(const Storage* aStorage); // Whether the storage change is about to persist - bool Persist(const DOMStorage* aStorage) const; + bool Persist(const Storage* aStorage) const; // Changes the quota usage on the given data set if it fits the quota. // If not, then false is returned and no change to the set must be done. bool ProcessUsageDelta(uint32_t aGetDataSetIndex, const int64_t aDelta); - bool ProcessUsageDelta(const DOMStorage* aStorage, const int64_t aDelta); + bool ProcessUsageDelta(const Storage* aStorage, const int64_t aDelta); private: // When a cache is reponsible for its life time (in case of localStorage data - // cache) we need to refer our manager since removal of the cache from the hash - // table is handled in the destructor by call to the manager. - // Cache could potentially overlive the manager, hence the hard ref. - RefPtr<DOMStorageManager> mManager; + // cache) we need to refer our manager since removal of the cache from the + // hash table is handled in the destructor by call to the manager. Cache + // could potentially overlive the manager, hence the hard ref. + RefPtr<StorageManagerBase> mManager; // Reference to the usage counter object we check on for eTLD+1 quota limit. // Obtained from the manager during initialization (Init method). - RefPtr<DOMStorageUsage> mUsage; + RefPtr<StorageUsage> mUsage; // Timer that holds this cache alive for a while after it has been preloaded. nsCOMPtr<nsITimer> mKeepAliveTimer; - // Principal the cache has been initially created for, this is used only - // for sessionStorage access checks since sessionStorage objects are strictly - // scoped by a principal. localStorage objects on the other hand are scoped by - // origin only. + // Principal the cache has been initially created for, this is used only for + // sessionStorage access checks since sessionStorage objects are strictly + // scoped by a principal. localStorage objects on the other hand are scoped + // by origin only. nsCOMPtr<nsIPrincipal> mPrincipal; // The origin this cache belongs to in the "DB format", i.e. reversed nsCString mOriginNoSuffix; // The origin attributes suffix nsCString mOriginSuffix; @@ -236,53 +240,54 @@ private: bool mPersistent : 1; // - False when the session-only data set was never used. // - True after access to session-only data has been made for the first time. // We also fill session-only data set with the default one at that moment. // Drops back to false when session-only data are cleared from chrome. bool mSessionOnlyDataSetActive : 1; - // Whether we have already captured state of the cache preload on our first access. + // Whether we have already captured state of the cache preload on our first + // access. bool mPreloadTelemetryRecorded : 1; - // DOMStorageDBThread on the parent or single process, - // DOMStorageDBChild on the child process. - static DOMStorageDBBridge* sDatabase; + // StorageDBThread on the parent or single process, + // StorageDBChild on the child process. + static StorageDBBridge* sDatabase; // False until we shut the database down. static bool sDatabaseDown; }; -// DOMStorageUsage +// StorageUsage // Infrastructure to manage and check eTLD+1 quota -class DOMStorageUsageBridge +class StorageUsageBridge { public: - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DOMStorageUsageBridge) + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(StorageUsageBridge) virtual const nsCString& OriginScope() = 0; virtual void LoadUsage(const int64_t aUsage) = 0; protected: // Protected destructor, to discourage deletion outside of Release(): - virtual ~DOMStorageUsageBridge() {} + virtual ~StorageUsageBridge() {} }; -class DOMStorageUsage : public DOMStorageUsageBridge +class StorageUsage : public StorageUsageBridge { public: - explicit DOMStorageUsage(const nsACString& aOriginScope); + explicit StorageUsage(const nsACString& aOriginScope); bool CheckAndSetETLD1UsageDelta(uint32_t aDataSetIndex, int64_t aUsageDelta); private: virtual const nsCString& OriginScope() { return mOriginScope; } virtual void LoadUsage(const int64_t aUsage); nsCString mOriginScope; - int64_t mUsage[DOMStorageCache::kDataSetCount]; + int64_t mUsage[StorageCache::kDataSetCount]; }; } // namespace dom } // namespace mozilla -#endif +#endif // mozilla_dom_StorageCache_h
rename from dom/storage/DOMStorageDBThread.cpp rename to dom/storage/StorageDBThread.cpp --- a/dom/storage/DOMStorageDBThread.cpp +++ b/dom/storage/StorageDBThread.cpp @@ -1,18 +1,18 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* 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/. */ -#include "DOMStorageDBThread.h" -#include "DOMStorageDBUpdater.h" -#include "DOMStorageCache.h" -#include "DOMStorageManager.h" +#include "StorageDBThread.h" +#include "StorageDBUpdater.h" +#include "StorageCache.h" +#include "StorageManager.h" #include "nsIEffectiveTLDService.h" #include "nsDirectoryServiceUtils.h" #include "nsAppDirectoryServiceDefs.h" #include "nsThreadUtils.h" #include "nsProxyRelease.h" #include "mozStorageCID.h" #include "mozStorageHelper.h" @@ -39,32 +39,33 @@ // Current version of the database schema #define CURRENT_SCHEMA_VERSION 1 namespace mozilla { namespace dom { namespace { // anon -// This is only a compatibility code for schema version 0. Returns the 'scope' key -// in the schema version 0 format for the scope column. +// This is only a compatibility code for schema version 0. Returns the 'scope' +// key in the schema version 0 format for the scope column. nsCString -Scheme0Scope(DOMStorageCacheBridge* aCache) +Scheme0Scope(StorageCacheBridge* aCache) { nsCString result; nsCString suffix = aCache->OriginSuffix(); PrincipalOriginAttributes oa; if (!suffix.IsEmpty()) { DebugOnly<bool> success = oa.PopulateFromSuffix(suffix); MOZ_ASSERT(success); } - if (oa.mAppId != nsIScriptSecurityManager::NO_APP_ID || oa.mInIsolatedMozBrowser) { + if (oa.mAppId != nsIScriptSecurityManager::NO_APP_ID || + oa.mInIsolatedMozBrowser) { result.AppendInt(oa.mAppId); result.Append(':'); result.Append(oa.mInIsolatedMozBrowser ? 't' : 'f'); result.Append(':'); } // If there is more than just appid and/or inbrowser stored in origin // attributes, put it to the schema 0 scope as well. We must do that @@ -97,38 +98,38 @@ Scheme0Scope(DOMStorageCacheBridge* aCac result.Append(aCache->OriginNoSuffix()); return result; } } // anon -DOMStorageDBBridge::DOMStorageDBBridge() +StorageDBBridge::StorageDBBridge() { } -DOMStorageDBThread::DOMStorageDBThread() -: mThread(nullptr) -, mThreadObserver(new ThreadObserver()) -, mStopIOThread(false) -, mWALModeEnabled(false) -, mDBReady(false) -, mStatus(NS_OK) -, mWorkerStatements(mWorkerConnection) -, mReaderStatements(mReaderConnection) -, mDirtyEpoch(0) -, mFlushImmediately(false) -, mPriorityCounter(0) +StorageDBThread::StorageDBThread() + : mThread(nullptr) + , mThreadObserver(new ThreadObserver()) + , mStopIOThread(false) + , mWALModeEnabled(false) + , mDBReady(false) + , mStatus(NS_OK) + , mWorkerStatements(mWorkerConnection) + , mReaderStatements(mReaderConnection) + , mDirtyEpoch(0) + , mFlushImmediately(false) + , mPriorityCounter(0) { } nsresult -DOMStorageDBThread::Init() +StorageDBThread::Init() { nsresult rv; // Need to determine location on the main thread, since // NS_GetSpecialDirectory access the atom table that can // be accessed only on the main thread. rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(mDatabaseFile)); @@ -141,28 +142,28 @@ DOMStorageDBThread::Init() nsCOMPtr<mozIStorageService> service = do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); // Need to keep the lock to avoid setting mThread later then // the thread body executes. MonitorAutoLock monitor(mThreadObserver->GetMonitor()); - mThread = PR_CreateThread(PR_USER_THREAD, &DOMStorageDBThread::ThreadFunc, this, - PR_PRIORITY_LOW, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, - 262144); + mThread = PR_CreateThread(PR_USER_THREAD, &StorageDBThread::ThreadFunc, this, + PR_PRIORITY_LOW, PR_GLOBAL_THREAD, + PR_JOINABLE_THREAD, 262144); if (!mThread) { return NS_ERROR_OUT_OF_MEMORY; } return NS_OK; } nsresult -DOMStorageDBThread::Shutdown() +StorageDBThread::Shutdown() { if (!mThread) { return NS_ERROR_NOT_INITIALIZED; } Telemetry::AutoTimer<Telemetry::LOCALDOMSTORAGE_SHUTDOWN_DATABASE_MS> timer; { @@ -176,31 +177,31 @@ DOMStorageDBThread::Shutdown() PR_JoinThread(mThread); mThread = nullptr; return mStatus; } void -DOMStorageDBThread::SyncPreload(DOMStorageCacheBridge* aCache, bool aForceSync) +StorageDBThread::SyncPreload(StorageCacheBridge* aCache, bool aForceSync) { PROFILER_LABEL_FUNC(js::ProfileEntry::Category::STORAGE); if (!aForceSync && aCache->LoadedCount()) { // Preload already started for this cache, just wait for it to finish. // LoadWait will exit after LoadDone on the cache has been called. SetHigherPriority(); aCache->LoadWait(); SetDefaultPriority(); return; } // Bypass sync load when an update is pending in the queue to write, we would - // get incosistent data in the cache. Also don't allow sync main-thread preload - // when DB open and init is still pending on the background thread. + // get incosistent data in the cache. Also don't allow sync main-thread + // preload when DB open and init is still pending on the background thread. if (mDBReady && mWALModeEnabled) { bool pendingTasks; { MonitorAutoLock monitor(mThreadObserver->GetMonitor()); pendingTasks = mPendingTasks.IsOriginUpdatePending(aCache->OriginSuffix(), aCache->OriginNoSuffix()) || mPendingTasks.IsOriginClearPending(aCache->OriginSuffix(), aCache->OriginNoSuffix()); } @@ -219,46 +220,46 @@ DOMStorageDBThread::SyncPreload(DOMStora // LoadWait exits after LoadDone of the cache has been called. if (NS_SUCCEEDED(rv)) { aCache->LoadWait(); } } void -DOMStorageDBThread::AsyncFlush() +StorageDBThread::AsyncFlush() { MonitorAutoLock monitor(mThreadObserver->GetMonitor()); mFlushImmediately = true; monitor.Notify(); } bool -DOMStorageDBThread::ShouldPreloadOrigin(const nsACString& aOrigin) +StorageDBThread::ShouldPreloadOrigin(const nsACString& aOrigin) { MonitorAutoLock monitor(mThreadObserver->GetMonitor()); return mOriginsHavingData.Contains(aOrigin); } void -DOMStorageDBThread::GetOriginsHavingData(InfallibleTArray<nsCString>* aOrigins) +StorageDBThread::GetOriginsHavingData(InfallibleTArray<nsCString>* aOrigins) { MonitorAutoLock monitor(mThreadObserver->GetMonitor()); for (auto iter = mOriginsHavingData.Iter(); !iter.Done(); iter.Next()) { aOrigins->AppendElement(iter.Get()->GetKey()); } } nsresult -DOMStorageDBThread::InsertDBOp(DOMStorageDBThread::DBOperation* aOperation) +StorageDBThread::InsertDBOp(StorageDBThread::DBOperation* aOperation) { MonitorAutoLock monitor(mThreadObserver->GetMonitor()); // Sentinel to don't forget to delete the operation when we exit early. - nsAutoPtr<DOMStorageDBThread::DBOperation> opScope(aOperation); + nsAutoPtr<StorageDBThread::DBOperation> opScope(aOperation); if (NS_FAILED(mStatus)) { MonitorAutoUnlock unlock(mThreadObserver->GetMonitor()); aOperation->Finalize(mStatus); return mStatus; } if (mStopIOThread) { @@ -269,25 +270,26 @@ DOMStorageDBThread::InsertDBOp(DOMStorag switch (aOperation->Type()) { case DBOperation::opPreload: case DBOperation::opPreloadUrgent: if (mPendingTasks.IsOriginUpdatePending(aOperation->OriginSuffix(), aOperation->OriginNoSuffix())) { // If there is a pending update operation for the scope first do the flush // before we preload the cache. This may happen in an extremely rare case // when a child process throws away its cache before flush on the parent - // has finished. If we would preloaded the cache as a priority operation - // before the pending flush, we would have got an inconsistent cache content. + // has finished. If we would preloaded the cache as a priority operation + // before the pending flush, we would have got an inconsistent cache + // content. mFlushImmediately = true; } else if (mPendingTasks.IsOriginClearPending(aOperation->OriginSuffix(), aOperation->OriginNoSuffix())) { // The scope is scheduled to be cleared, so just quickly load as empty. // We need to do this to prevent load of the DB data before the scope has // actually been cleared from the database. Preloads are processed - // immediately before update and clear operations on the database that - // are flushed periodically in batches. + // immediately before update and clear operations on the database that are + // flushed periodically in batches. MonitorAutoUnlock unlock(mThreadObserver->GetMonitor()); aOperation->Finalize(NS_OK); return NS_OK; } MOZ_FALLTHROUGH; case DBOperation::opGetUsage: if (aOperation->Type() == DBOperation::opPreloadUrgent) { @@ -315,43 +317,43 @@ DOMStorageDBThread::InsertDBOp(DOMStorag ScheduleFlush(); break; } return NS_OK; } void -DOMStorageDBThread::SetHigherPriority() +StorageDBThread::SetHigherPriority() { ++mPriorityCounter; PR_SetThreadPriority(mThread, PR_PRIORITY_URGENT); } void -DOMStorageDBThread::SetDefaultPriority() +StorageDBThread::SetDefaultPriority() { if (--mPriorityCounter <= 0) { PR_SetThreadPriority(mThread, PR_PRIORITY_LOW); } } void -DOMStorageDBThread::ThreadFunc(void* aArg) +StorageDBThread::ThreadFunc(void* aArg) { PR_SetCurrentThreadName("localStorage DB"); mozilla::IOInterposer::RegisterCurrentThread(); - DOMStorageDBThread* thread = static_cast<DOMStorageDBThread*>(aArg); + StorageDBThread* thread = static_cast<StorageDBThread*>(aArg); thread->ThreadFunc(); mozilla::IOInterposer::UnregisterCurrentThread(); } void -DOMStorageDBThread::ThreadFunc() +StorageDBThread::ThreadFunc() { nsresult rv = InitDatabase(); MonitorAutoLock lockMonitor(mThreadObserver->GetMonitor()); if (NS_FAILED(rv)) { mStatus = rv; mStopIOThread = true; @@ -412,47 +414,47 @@ DOMStorageDBThread::ThreadFunc() mStatus = ShutdownDatabase(); if (threadInternal) { threadInternal->SetObserver(nullptr); } } -NS_IMPL_ISUPPORTS(DOMStorageDBThread::ThreadObserver, nsIThreadObserver) +NS_IMPL_ISUPPORTS(StorageDBThread::ThreadObserver, nsIThreadObserver) NS_IMETHODIMP -DOMStorageDBThread::ThreadObserver::OnDispatchedEvent(nsIThreadInternal *thread) +StorageDBThread::ThreadObserver::OnDispatchedEvent(nsIThreadInternal* aThread) { MonitorAutoLock lock(mMonitor); mHasPendingEvents = true; lock.Notify(); return NS_OK; } NS_IMETHODIMP -DOMStorageDBThread::ThreadObserver::OnProcessNextEvent(nsIThreadInternal *thread, - bool mayWait) +StorageDBThread::ThreadObserver::OnProcessNextEvent(nsIThreadInternal* aThread, + bool mayWait) { return NS_OK; } NS_IMETHODIMP -DOMStorageDBThread::ThreadObserver::AfterProcessNextEvent(nsIThreadInternal *thread, - bool eventWasProcessed) +StorageDBThread::ThreadObserver::AfterProcessNextEvent(nsIThreadInternal* aThread, + bool eventWasProcessed) { return NS_OK; } extern void ReverseString(const nsCSubstring& aSource, nsCSubstring& aResult); nsresult -DOMStorageDBThread::OpenDatabaseConnection() +StorageDBThread::OpenDatabaseConnection() { nsresult rv; MOZ_ASSERT(!NS_IsMainThread()); nsCOMPtr<mozIStorageService> service = do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); @@ -465,44 +467,44 @@ DOMStorageDBThread::OpenDatabaseConnecti rv = service->OpenUnsharedDatabase(mDatabaseFile, getter_AddRefs(mWorkerConnection)); } NS_ENSURE_SUCCESS(rv, rv); return NS_OK; } nsresult -DOMStorageDBThread::OpenAndUpdateDatabase() +StorageDBThread::OpenAndUpdateDatabase() { nsresult rv; // Here we are on the worker thread. This opens the worker connection. MOZ_ASSERT(!NS_IsMainThread()); rv = OpenDatabaseConnection(); NS_ENSURE_SUCCESS(rv, rv); rv = TryJournalMode(); NS_ENSURE_SUCCESS(rv, rv); return NS_OK; } nsresult -DOMStorageDBThread::InitDatabase() +StorageDBThread::InitDatabase() { nsresult rv; // Here we are on the worker thread. This opens the worker connection. MOZ_ASSERT(!NS_IsMainThread()); rv = OpenAndUpdateDatabase(); NS_ENSURE_SUCCESS(rv, rv); - rv = DOMStorageDBUpdater::Update(mWorkerConnection); + rv = StorageDBUpdater::Update(mWorkerConnection); if (NS_FAILED(rv)) { // Update has failed, rather throw the database away and try // opening and setting it up again. rv = mWorkerConnection->Close(); mWorkerConnection = nullptr; NS_ENSURE_SUCCESS(rv, rv); rv = mDatabaseFile->Remove(false); @@ -512,24 +514,24 @@ DOMStorageDBThread::InitDatabase() NS_ENSURE_SUCCESS(rv, rv); } // Create a read-only clone (void)mWorkerConnection->Clone(true, getter_AddRefs(mReaderConnection)); NS_ENSURE_TRUE(mReaderConnection, NS_ERROR_FAILURE); // Database open and all initiation operation are done. Switching this flag - // to true allow main thread to read directly from the database. - // If we would allow this sooner, we would have opened a window where main thread - // read might operate on a totaly broken and incosistent database. + // to true allow main thread to read directly from the database. If we would + // allow this sooner, we would have opened a window where main thread read + // might operate on a totally broken and incosistent database. mDBReady = true; // List scopes having any stored data nsCOMPtr<mozIStorageStatement> stmt; - // Note: result of this select must match DOMStorageManager::CreateOrigin() + // Note: result of this select must match StorageManager::CreateOrigin() rv = mWorkerConnection->CreateStatement(NS_LITERAL_CSTRING( "SELECT DISTINCT originAttributes || ':' || originKey FROM webappsstore2"), getter_AddRefs(stmt)); NS_ENSURE_SUCCESS(rv, rv); mozStorageStatementScoper scope(stmt); bool exists; while (NS_SUCCEEDED(rv = stmt->ExecuteStep(&exists)) && exists) { @@ -540,17 +542,17 @@ DOMStorageDBThread::InitDatabase() MonitorAutoLock monitor(mThreadObserver->GetMonitor()); mOriginsHavingData.PutEntry(foundOrigin); } return NS_OK; } nsresult -DOMStorageDBThread::SetJournalMode(bool aIsWal) +StorageDBThread::SetJournalMode(bool aIsWal) { nsresult rv; nsAutoCString stmtString( MOZ_STORAGE_UNIQUIFY_QUERY_STR "PRAGMA journal_mode = "); if (aIsWal) { stmtString.AppendLiteral("wal"); } else { @@ -576,17 +578,17 @@ DOMStorageDBThread::SetJournalMode(bool (!aIsWal && !journalMode.EqualsLiteral("truncate"))) { return NS_ERROR_FAILURE; } return NS_OK; } nsresult -DOMStorageDBThread::TryJournalMode() +StorageDBThread::TryJournalMode() { nsresult rv; rv = SetJournalMode(true); if (NS_FAILED(rv)) { mWALModeEnabled = false; rv = SetJournalMode(false); @@ -597,17 +599,17 @@ DOMStorageDBThread::TryJournalMode() rv = ConfigureWALBehavior(); NS_ENSURE_SUCCESS(rv, rv); } return NS_OK; } nsresult -DOMStorageDBThread::ConfigureWALBehavior() +StorageDBThread::ConfigureWALBehavior() { // Get the DB's page size nsCOMPtr<mozIStorageStatement> stmt; nsresult rv = mWorkerConnection->CreateStatement(NS_LITERAL_CSTRING( MOZ_STORAGE_UNIQUIFY_QUERY_STR "PRAGMA page_size" ), getter_AddRefs(stmt)); NS_ENSURE_SUCCESS(rv, rv); @@ -625,26 +627,27 @@ DOMStorageDBThread::ConfigureWALBehavior nsAutoCString thresholdPragma("PRAGMA wal_autocheckpoint = "); thresholdPragma.AppendInt(thresholdInPages); rv = mWorkerConnection->ExecuteSimpleSQL(thresholdPragma); NS_ENSURE_SUCCESS(rv, rv); // Set the maximum WAL log size to reduce footprint on mobile (large empty // WAL files will be truncated) nsAutoCString journalSizePragma("PRAGMA journal_size_limit = "); - // bug 600307: mak recommends setting this to 3 times the auto-checkpoint threshold + // bug 600307: mak recommends setting this to 3 times the auto-checkpoint + // threshold journalSizePragma.AppendInt(MAX_WAL_SIZE_BYTES * 3); rv = mWorkerConnection->ExecuteSimpleSQL(journalSizePragma); NS_ENSURE_SUCCESS(rv, rv); return NS_OK; } nsresult -DOMStorageDBThread::ShutdownDatabase() +StorageDBThread::ShutdownDatabase() { // Has to be called on the worker thread. MOZ_ASSERT(!NS_IsMainThread()); nsresult rv = mStatus; mDBReady = false; @@ -663,38 +666,39 @@ DOMStorageDBThread::ShutdownDatabase() rv = mWorkerConnection->Close(); mWorkerConnection = nullptr; } return rv; } void -DOMStorageDBThread::ScheduleFlush() +StorageDBThread::ScheduleFlush() { if (mDirtyEpoch) { return; // Already scheduled } - mDirtyEpoch = PR_IntervalNow() | 1; // Must be non-zero to indicate we are scheduled + // Must be non-zero to indicate we are scheduled + mDirtyEpoch = PR_IntervalNow() | 1; // Wake the monitor from indefinite sleep... (mThreadObserver->GetMonitor()).Notify(); } void -DOMStorageDBThread::UnscheduleFlush() +StorageDBThread::UnscheduleFlush() { // We are just about to do the flush, drop flags mFlushImmediately = false; mDirtyEpoch = 0; } PRIntervalTime -DOMStorageDBThread::TimeUntilFlush() +StorageDBThread::TimeUntilFlush() { if (mFlushImmediately) { return 0; // Do it now regardless the timeout. } static_assert(PR_INTERVAL_NO_TIMEOUT != 0, "PR_INTERVAL_NO_TIMEOUT must be non-zero"); @@ -709,22 +713,22 @@ DOMStorageDBThread::TimeUntilFlush() if (age > kMaxAge) { return 0; // It is time. } return kMaxAge - age; // Time left, this is used to sleep the monitor } void -DOMStorageDBThread::NotifyFlushCompletion() +StorageDBThread::NotifyFlushCompletion() { #ifdef DOM_STORAGE_TESTS if (!NS_IsMainThread()) { - RefPtr<nsRunnableMethod<DOMStorageDBThread, void, false> > event = - NewNonOwningRunnableMethod(this, &DOMStorageDBThread::NotifyFlushCompletion); + RefPtr<nsRunnableMethod<StorageDBThread, void, false> > event = + NewNonOwningRunnableMethod(this, &StorageDBThread::NotifyFlushCompletion); NS_DispatchToMainThread(event); return; } nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); if (obs) { obs->NotifyObservers(nullptr, "domstorage-test-flushed", nullptr); } @@ -772,123 +776,123 @@ OriginAttrsPatternMatchSQLFunction::OnFu NS_ENSURE_SUCCESS(rv, rv); outVar.forget(aResult); return NS_OK; } } // namespace -// DOMStorageDBThread::DBOperation +// StorageDBThread::DBOperation -DOMStorageDBThread::DBOperation::DBOperation(const OperationType aType, - DOMStorageCacheBridge* aCache, - const nsAString& aKey, - const nsAString& aValue) +StorageDBThread::DBOperation::DBOperation(const OperationType aType, + StorageCacheBridge* aCache, + const nsAString& aKey, + const nsAString& aValue) : mType(aType) , mCache(aCache) , mKey(aKey) , mValue(aValue) { MOZ_ASSERT(mType == opPreload || mType == opPreloadUrgent || mType == opAddItem || mType == opUpdateItem || mType == opRemoveItem || mType == opClear || mType == opClearAll); - MOZ_COUNT_CTOR(DOMStorageDBThread::DBOperation); + MOZ_COUNT_CTOR(StorageDBThread::DBOperation); } -DOMStorageDBThread::DBOperation::DBOperation(const OperationType aType, - DOMStorageUsageBridge* aUsage) +StorageDBThread::DBOperation::DBOperation(const OperationType aType, + StorageUsageBridge* aUsage) : mType(aType) , mUsage(aUsage) { MOZ_ASSERT(mType == opGetUsage); - MOZ_COUNT_CTOR(DOMStorageDBThread::DBOperation); + MOZ_COUNT_CTOR(StorageDBThread::DBOperation); } -DOMStorageDBThread::DBOperation::DBOperation(const OperationType aType, - const nsACString& aOriginNoSuffix) +StorageDBThread::DBOperation::DBOperation(const OperationType aType, + const nsACString& aOriginNoSuffix) : mType(aType) , mCache(nullptr) , mOrigin(aOriginNoSuffix) { MOZ_ASSERT(mType == opClearMatchingOrigin); - MOZ_COUNT_CTOR(DOMStorageDBThread::DBOperation); + MOZ_COUNT_CTOR(StorageDBThread::DBOperation); } -DOMStorageDBThread::DBOperation::DBOperation(const OperationType aType, - const OriginAttributesPattern& aOriginNoSuffix) +StorageDBThread::DBOperation::DBOperation(const OperationType aType, + const OriginAttributesPattern& aOriginNoSuffix) : mType(aType) , mCache(nullptr) , mOriginPattern(aOriginNoSuffix) { MOZ_ASSERT(mType == opClearMatchingOriginAttributes); - MOZ_COUNT_CTOR(DOMStorageDBThread::DBOperation); + MOZ_COUNT_CTOR(StorageDBThread::DBOperation); } -DOMStorageDBThread::DBOperation::~DBOperation() +StorageDBThread::DBOperation::~DBOperation() { - MOZ_COUNT_DTOR(DOMStorageDBThread::DBOperation); + MOZ_COUNT_DTOR(StorageDBThread::DBOperation); } const nsCString -DOMStorageDBThread::DBOperation::OriginNoSuffix() const +StorageDBThread::DBOperation::OriginNoSuffix() const { if (mCache) { return mCache->OriginNoSuffix(); } return EmptyCString(); } const nsCString -DOMStorageDBThread::DBOperation::OriginSuffix() const +StorageDBThread::DBOperation::OriginSuffix() const { if (mCache) { return mCache->OriginSuffix(); } return EmptyCString(); } const nsCString -DOMStorageDBThread::DBOperation::Origin() const +StorageDBThread::DBOperation::Origin() const { if (mCache) { return mCache->Origin(); } return mOrigin; } const nsCString -DOMStorageDBThread::DBOperation::Target() const +StorageDBThread::DBOperation::Target() const { switch (mType) { case opAddItem: case opUpdateItem: case opRemoveItem: return Origin() + NS_LITERAL_CSTRING("|") + NS_ConvertUTF16toUTF8(mKey); default: return Origin(); } } void -DOMStorageDBThread::DBOperation::PerformAndFinalize(DOMStorageDBThread* aThread) +StorageDBThread::DBOperation::PerformAndFinalize(StorageDBThread* aThread) { Finalize(Perform(aThread)); } nsresult -DOMStorageDBThread::DBOperation::Perform(DOMStorageDBThread* aThread) +StorageDBThread::DBOperation::Perform(StorageDBThread* aThread) { nsresult rv; switch (mType) { case opPreload: case opPreloadUrgent: { // Already loaded? @@ -1095,27 +1099,28 @@ DOMStorageDBThread::DBOperation::Perform rv = stmt->BindUTF8StringByName(NS_LITERAL_CSTRING("scope"), mOrigin + NS_LITERAL_CSTRING("*")); NS_ENSURE_SUCCESS(rv, rv); rv = stmt->Execute(); NS_ENSURE_SUCCESS(rv, rv); - // No need to selectively clear mOriginsHavingData here. That hashtable only - // prevents preload for scopes with no data. Leaving a false record in it has - // a negligible effect on performance. + // No need to selectively clear mOriginsHavingData here. That hashtable + // only prevents preload for scopes with no data. Leaving a false record in + // it has a negligible effect on performance. break; } case opClearMatchingOriginAttributes: { MOZ_ASSERT(!NS_IsMainThread()); - // Register the ORIGIN_ATTRS_PATTERN_MATCH function, initialized with the pattern + // Register the ORIGIN_ATTRS_PATTERN_MATCH function, initialized with the + // pattern nsCOMPtr<mozIStorageFunction> patternMatchFunction( new OriginAttrsPatternMatchSQLFunction(mOriginPattern)); rv = aThread->mWorkerConnection->CreateFunction( NS_LITERAL_CSTRING("ORIGIN_ATTRS_PATTERN_MATCH"), 1, patternMatchFunction); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<mozIStorageStatement> stmt = aThread->mWorkerStatements.GetCachedStatement( @@ -1131,40 +1136,40 @@ DOMStorageDBThread::DBOperation::Perform } // Always remove the function aThread->mWorkerConnection->RemoveFunction( NS_LITERAL_CSTRING("ORIGIN_ATTRS_PATTERN_MATCH")); NS_ENSURE_SUCCESS(rv, rv); - // No need to selectively clear mOriginsHavingData here. That hashtable only - // prevents preload for scopes with no data. Leaving a false record in it has - // a negligible effect on performance. + // No need to selectively clear mOriginsHavingData here. That hashtable + // only prevents preload for scopes with no data. Leaving a false record in + // it has a negligible effect on performance. break; } default: NS_ERROR("Unknown task type"); break; } return NS_OK; } void -DOMStorageDBThread::DBOperation::Finalize(nsresult aRv) +StorageDBThread::DBOperation::Finalize(nsresult aRv) { switch (mType) { case opPreloadUrgent: case opPreload: if (NS_FAILED(aRv)) { // When we are here, something failed when loading from the database. - // Notify that the storage is loaded to prevent deadlock of the main thread, - // even though it is actually empty or incomplete. + // Notify that the storage is loaded to prevent deadlock of the main + // thread, even though it is actually empty or incomplete. NS_WARNING("Failed to preload localStorage"); } mCache->LoadDone(aRv); break; case opGetUsage: if (NS_FAILED(aRv)) { @@ -1178,87 +1183,91 @@ DOMStorageDBThread::DBOperation::Finaliz NS_WARNING("localStorage update/clear operation failed," " data may not persist or clean up"); } break; } } -// DOMStorageDBThread::PendingOperations +// StorageDBThread::PendingOperations -DOMStorageDBThread::PendingOperations::PendingOperations() +StorageDBThread::PendingOperations::PendingOperations() : mFlushFailureCount(0) { } bool -DOMStorageDBThread::PendingOperations::HasTasks() const +StorageDBThread::PendingOperations::HasTasks() const { return !!mUpdates.Count() || !!mClears.Count(); } namespace { -bool OriginPatternMatches(const nsACString& aOriginSuffix, const OriginAttributesPattern& aPattern) +bool OriginPatternMatches(const nsACString& aOriginSuffix, + const OriginAttributesPattern& aPattern) { PrincipalOriginAttributes oa; DebugOnly<bool> rv = oa.PopulateFromSuffix(aOriginSuffix); MOZ_ASSERT(rv); return aPattern.Matches(oa); } } // namespace bool -DOMStorageDBThread::PendingOperations::CheckForCoalesceOpportunity(DBOperation* aNewOp, - DBOperation::OperationType aPendingType, - DBOperation::OperationType aNewType) +StorageDBThread::PendingOperations::CheckForCoalesceOpportunity(DBOperation* aNewOp, + DBOperation::OperationType aPendingType, + DBOperation::OperationType aNewType) { if (aNewOp->Type() != aNewType) { return false; } - DOMStorageDBThread::DBOperation* pendingTask; + StorageDBThread::DBOperation* pendingTask; if (!mUpdates.Get(aNewOp->Target(), &pendingTask)) { return false; } if (pendingTask->Type() != aPendingType) { return false; } return true; } void -DOMStorageDBThread::PendingOperations::Add(DOMStorageDBThread::DBOperation* aOperation) +StorageDBThread::PendingOperations::Add(StorageDBThread::DBOperation* aOperation) { // Optimize: when a key to remove has never been written to disk // just bypass this operation. A key is new when an operation scheduled // to write it to the database is of type opAddItem. - if (CheckForCoalesceOpportunity(aOperation, DBOperation::opAddItem, DBOperation::opRemoveItem)) { + if (CheckForCoalesceOpportunity(aOperation, DBOperation::opAddItem, + DBOperation::opRemoveItem)) { mUpdates.Remove(aOperation->Target()); delete aOperation; return; } // Optimize: when changing a key that is new and has never been // written to disk, keep type of the operation to store it at opAddItem. // This allows optimization to just forget adding a new key when // it is removed from the storage before flush. - if (CheckForCoalesceOpportunity(aOperation, DBOperation::opAddItem, DBOperation::opUpdateItem)) { + if (CheckForCoalesceOpportunity(aOperation, DBOperation::opAddItem, + DBOperation::opUpdateItem)) { aOperation->mType = DBOperation::opAddItem; } // Optimize: to prevent lose of remove operation on a key when doing // remove/set/remove on a previously existing key we have to change // opAddItem to opUpdateItem on the new operation when there is opRemoveItem // pending for the key. - if (CheckForCoalesceOpportunity(aOperation, DBOperation::opRemoveItem, DBOperation::opAddItem)) { + if (CheckForCoalesceOpportunity(aOperation, DBOperation::opRemoveItem, + DBOperation::opAddItem)) { aOperation->mType = DBOperation::opUpdateItem; } switch (aOperation->Type()) { // Operations on single keys case DBOperation::opAddItem: @@ -1268,20 +1277,20 @@ DOMStorageDBThread::PendingOperations::A mUpdates.Put(aOperation->Target(), aOperation); break; // Clear operations case DBOperation::opClear: case DBOperation::opClearMatchingOrigin: case DBOperation::opClearMatchingOriginAttributes: - // Drop all update (insert/remove) operations for equivavelent or matching scope. - // We do this as an optimization as well as a must based on the logic, - // if we would not delete the update tasks, changes would have been stored - // to the database after clear operations have been executed. + // Drop all update (insert/remove) operations for equivavelent or matching + // scope. We do this as an optimization as well as a must based on the + // logic, if we would not delete the update tasks, changes would have been + // stored to the database after clear operations have been executed. for (auto iter = mUpdates.Iter(); !iter.Done(); iter.Next()) { nsAutoPtr<DBOperation>& pendingTask = iter.Data(); if (aOperation->Type() == DBOperation::opClear && (pendingTask->OriginNoSuffix() != aOperation->OriginNoSuffix() || pendingTask->OriginSuffix() != aOperation->OriginSuffix())) { continue; } @@ -1311,17 +1320,17 @@ DOMStorageDBThread::PendingOperations::A default: MOZ_ASSERT(false); break; } } bool -DOMStorageDBThread::PendingOperations::Prepare() +StorageDBThread::PendingOperations::Prepare() { // Called under the lock // First collect clear operations and then updates, we can // do this since whenever a clear operation for a scope is // scheduled, we drop all updates matching that scope. So, // all scope-related update operations we have here now were // scheduled after the clear operations. @@ -1334,42 +1343,42 @@ DOMStorageDBThread::PendingOperations::P mExecList.AppendElement(iter.Data().forget()); } mUpdates.Clear(); return !!mExecList.Length(); } nsresult -DOMStorageDBThread::PendingOperations::Execute(DOMStorageDBThread* aThread) +StorageDBThread::PendingOperations::Execute(StorageDBThread* aThread) { // Called outside the lock mozStorageTransaction transaction(aThread->mWorkerConnection, false); nsresult rv; for (uint32_t i = 0; i < mExecList.Length(); ++i) { - DOMStorageDBThread::DBOperation* task = mExecList[i]; + StorageDBThread::DBOperation* task = mExecList[i]; rv = task->Perform(aThread); if (NS_FAILED(rv)) { return rv; } } rv = transaction.Commit(); if (NS_FAILED(rv)) { return rv; } return NS_OK; } bool -DOMStorageDBThread::PendingOperations::Finalize(nsresult aRv) +StorageDBThread::PendingOperations::Finalize(nsresult aRv) { // Called under the lock // The list is kept on a failure to retry it if (NS_FAILED(aRv)) { // XXX Followup: we may try to reopen the database and flush these // pending tasks, however testing showed that even though I/O is actually // broken some amount of operations is left in sqlite+system buffers and @@ -1386,47 +1395,48 @@ DOMStorageDBThread::PendingOperations::F mFlushFailureCount = 0; mExecList.Clear(); return true; } namespace { bool -FindPendingClearForOrigin(const nsACString& aOriginSuffix, const nsACString& aOriginNoSuffix, - DOMStorageDBThread::DBOperation* aPendingOperation) +FindPendingClearForOrigin(const nsACString& aOriginSuffix, + const nsACString& aOriginNoSuffix, + StorageDBThread::DBOperation* aPendingOperation) { - if (aPendingOperation->Type() == DOMStorageDBThread::DBOperation::opClearAll) { + if (aPendingOperation->Type() == StorageDBThread::DBOperation::opClearAll) { return true; } - if (aPendingOperation->Type() == DOMStorageDBThread::DBOperation::opClear && + if (aPendingOperation->Type() == StorageDBThread::DBOperation::opClear && aOriginNoSuffix == aPendingOperation->OriginNoSuffix() && aOriginSuffix == aPendingOperation->OriginSuffix()) { return true; } - if (aPendingOperation->Type() == DOMStorageDBThread::DBOperation::opClearMatchingOrigin && + if (aPendingOperation->Type() == StorageDBThread::DBOperation::opClearMatchingOrigin && StringBeginsWith(aOriginNoSuffix, aPendingOperation->Origin())) { return true; } - if (aPendingOperation->Type() == DOMStorageDBThread::DBOperation::opClearMatchingOriginAttributes && + if (aPendingOperation->Type() == StorageDBThread::DBOperation::opClearMatchingOriginAttributes && OriginPatternMatches(aOriginSuffix, aPendingOperation->OriginPattern())) { return true; } return false; } } // namespace bool -DOMStorageDBThread::PendingOperations::IsOriginClearPending(const nsACString& aOriginSuffix, - const nsACString& aOriginNoSuffix) const +StorageDBThread::PendingOperations::IsOriginClearPending(const nsACString& aOriginSuffix, + const nsACString& aOriginNoSuffix) const { // Called under the lock for (auto iter = mClears.ConstIter(); !iter.Done(); iter.Next()) { if (FindPendingClearForOrigin(aOriginSuffix, aOriginNoSuffix, iter.UserData())) { return true; } } @@ -1438,35 +1448,36 @@ DOMStorageDBThread::PendingOperations::I } return false; } namespace { bool -FindPendingUpdateForOrigin(const nsACString& aOriginSuffix, const nsACString& aOriginNoSuffix, - DOMStorageDBThread::DBOperation* aPendingOperation) +FindPendingUpdateForOrigin(const nsACString& aOriginSuffix, + const nsACString& aOriginNoSuffix, + StorageDBThread::DBOperation* aPendingOperation) { - if ((aPendingOperation->Type() == DOMStorageDBThread::DBOperation::opAddItem || - aPendingOperation->Type() == DOMStorageDBThread::DBOperation::opUpdateItem || - aPendingOperation->Type() == DOMStorageDBThread::DBOperation::opRemoveItem) && + if ((aPendingOperation->Type() == StorageDBThread::DBOperation::opAddItem || + aPendingOperation->Type() == StorageDBThread::DBOperation::opUpdateItem || + aPendingOperation->Type() == StorageDBThread::DBOperation::opRemoveItem) && aOriginNoSuffix == aPendingOperation->OriginNoSuffix() && aOriginSuffix == aPendingOperation->OriginSuffix()) { return true; } return false; } } // namespace bool -DOMStorageDBThread::PendingOperations::IsOriginUpdatePending(const nsACString& aOriginSuffix, - const nsACString& aOriginNoSuffix) const +StorageDBThread::PendingOperations::IsOriginUpdatePending(const nsACString& aOriginSuffix, + const nsACString& aOriginNoSuffix) const { // Called under the lock for (auto iter = mUpdates.ConstIter(); !iter.Done(); iter.Next()) { if (FindPendingUpdateForOrigin(aOriginSuffix, aOriginNoSuffix, iter.UserData())) { return true; } }
rename from dom/storage/DOMStorageDBThread.h rename to dom/storage/StorageDBThread.h --- a/dom/storage/DOMStorageDBThread.h +++ b/dom/storage/StorageDBThread.h @@ -1,16 +1,16 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* 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 DOMStorageDBThread_h___ -#define DOMStorageDBThread_h___ +#ifndef mozilla_dom_StorageDBThread_h +#define mozilla_dom_StorageDBThread_h #include "prthread.h" #include "prinrval.h" #include "nsTArray.h" #include "mozilla/Atomics.h" #include "mozilla/Monitor.h" #include "mozilla/BasePrincipal.h" #include "mozilla/storage/StatementCache.h" @@ -21,87 +21,100 @@ #include "nsIFile.h" #include "nsIThreadInternal.h" class mozIStorageConnection; namespace mozilla { namespace dom { -class DOMStorageCacheBridge; -class DOMStorageUsageBridge; -class DOMStorageUsage; +class StorageCacheBridge; +class StorageUsageBridge; +class StorageUsage; typedef mozilla::storage::StatementCache<mozIStorageStatement> StatementCache; // Interface used by the cache to post operations to the asynchronous // database thread or process. -class DOMStorageDBBridge +class StorageDBBridge { public: - DOMStorageDBBridge(); - virtual ~DOMStorageDBBridge() {} + StorageDBBridge(); + virtual ~StorageDBBridge() {} // Ensures the database engine is started virtual nsresult Init() = 0; // Releases the database and disallows its usage virtual nsresult Shutdown() = 0; // Asynchronously fills the cache with data from the database for first use. - // When |aPriority| is true, the preload operation is scheduled as the first one. - // This method is responsible to keep hard reference to the cache for the time of - // the preload or, when preload cannot be performed, call LoadDone() immediately. - virtual void AsyncPreload(DOMStorageCacheBridge* aCache, bool aPriority = false) = 0; + // When |aPriority| is true, the preload operation is scheduled as the first + // one. This method is responsible to keep hard reference to the cache for + // the time of the preload or, when preload cannot be performed, call + // LoadDone() immediately. + virtual void AsyncPreload(StorageCacheBridge* aCache, bool aPriority = false) = 0; - // Asynchronously fill the |usage| object with actual usage of data by its scope. - // The scope is eTLD+1 tops, never deeper subdomains. - virtual void AsyncGetUsage(DOMStorageUsageBridge* aUsage) = 0; + // Asynchronously fill the |usage| object with actual usage of data by its + // scope. The scope is eTLD+1 tops, never deeper subdomains. + virtual void AsyncGetUsage(StorageUsageBridge* aUsage) = 0; - // Synchronously fills the cache, when |aForceSync| is false and cache already got some - // data before, the method waits for the running preload to finish - virtual void SyncPreload(DOMStorageCacheBridge* aCache, bool aForceSync = false) = 0; + // Synchronously fills the cache, when |aForceSync| is false and cache already + // got some data before, the method waits for the running preload to finish + virtual void SyncPreload(StorageCacheBridge* aCache, + bool aForceSync = false) = 0; - // Called when an existing key is modified in the storage, schedules update to the database - virtual nsresult AsyncAddItem(DOMStorageCacheBridge* aCache, const nsAString& aKey, const nsAString& aValue) = 0; + // Called when an existing key is modified in the storage, schedules update to + // the database + virtual nsresult AsyncAddItem(StorageCacheBridge* aCache, + const nsAString& aKey, + const nsAString& aValue) = 0; - // Called when an existing key is modified in the storage, schedules update to the database - virtual nsresult AsyncUpdateItem(DOMStorageCacheBridge* aCache, const nsAString& aKey, const nsAString& aValue) = 0; + // Called when an existing key is modified in the storage, schedules update to + // the database + virtual nsresult AsyncUpdateItem(StorageCacheBridge* aCache, + const nsAString& aKey, + const nsAString& aValue) = 0; - // Called when an item is removed from the storage, schedules delete of the key - virtual nsresult AsyncRemoveItem(DOMStorageCacheBridge* aCache, const nsAString& aKey) = 0; + // Called when an item is removed from the storage, schedules delete of the + // key + virtual nsresult AsyncRemoveItem(StorageCacheBridge* aCache, + const nsAString& aKey) = 0; - // Called when the whole storage is cleared by the DOM API, schedules delete of the scope - virtual nsresult AsyncClear(DOMStorageCacheBridge* aCache) = 0; + // Called when the whole storage is cleared by the DOM API, schedules delete + // of the scope + virtual nsresult AsyncClear(StorageCacheBridge* aCache) = 0; - // Called when chrome deletes e.g. cookies, schedules delete of the whole database + // Called when chrome deletes e.g. cookies, schedules delete of the whole + // database virtual void AsyncClearAll() = 0; // Called when only a domain and its subdomains is about to clear virtual void AsyncClearMatchingOrigin(const nsACString& aOriginNoSuffix) = 0; // Called when data matching an origin pattern have to be cleared virtual void AsyncClearMatchingOriginAttributes(const OriginAttributesPattern& aPattern) = 0; // Forces scheduled DB operations to be early flushed to the disk virtual void AsyncFlush() = 0; - // Check whether the scope has any data stored on disk and is thus allowed to preload + // Check whether the scope has any data stored on disk and is thus allowed to + // preload virtual bool ShouldPreloadOrigin(const nsACString& aOriginNoSuffix) = 0; // Get the complete list of scopes having data virtual void GetOriginsHavingData(InfallibleTArray<nsCString>* aOrigins) = 0; }; // The implementation of the the database engine, this directly works // with the sqlite or any other db API we are based on // This class is resposible for collecting and processing asynchronous -// DB operations over caches (DOMStorageCache) communicating though -// DOMStorageCacheBridge interface class -class DOMStorageDBThread final : public DOMStorageDBBridge +// DB operations over caches (StorageCache) communicating though +// StorageCacheBridge interface class +class StorageDBThread final : public StorageDBBridge { public: class PendingOperations; // Representation of a singe database task, like adding and removing keys, // (pre)loading the whole origin data, cleaning. class DBOperation { @@ -119,107 +132,116 @@ public: opAddItem, opUpdateItem, opRemoveItem, // Clears a specific single origin data opClear, // Operations invoked by chrome - // Clear all the data stored in the database, for all scopes, no exceptions + // Clear all the data stored in the database, for all scopes, no + // exceptions opClearAll, - // Clear data under a domain and all its subdomains regardless OriginAttributes value + // Clear data under a domain and all its subdomains regardless + // OriginAttributes value opClearMatchingOrigin, // Clear all data matching an OriginAttributesPattern regardless a domain opClearMatchingOriginAttributes, } OperationType; explicit DBOperation(const OperationType aType, - DOMStorageCacheBridge* aCache = nullptr, + StorageCacheBridge* aCache = nullptr, const nsAString& aKey = EmptyString(), const nsAString& aValue = EmptyString()); DBOperation(const OperationType aType, - DOMStorageUsageBridge* aUsage); + StorageUsageBridge* aUsage); DBOperation(const OperationType aType, const nsACString& aOriginNoSuffix); DBOperation(const OperationType aType, const OriginAttributesPattern& aOriginNoSuffix); ~DBOperation(); - // Executes the operation, doesn't necessarity have to be called on the I/O thread - void PerformAndFinalize(DOMStorageDBThread* aThread); + // Executes the operation, doesn't necessarity have to be called on the I/O + // thread + void PerformAndFinalize(StorageDBThread* aThread); // Finalize the operation, i.e. do any internal cleanup and finish calls void Finalize(nsresult aRv); // The operation type OperationType Type() const { return mType; } // The origin in the database usage format (reversed) const nsCString OriginNoSuffix() const; // The origin attributes suffix const nsCString OriginSuffix() const; - // |origin suffix + origin key| the operation is working with - // or a scope pattern to delete with simple SQL's "LIKE %" from the database. + // |origin suffix + origin key| the operation is working with or a scope + // pattern to delete with simple SQL's "LIKE %" from the database. const nsCString Origin() const; // |origin suffix + origin key + key| the operation is working with const nsCString Target() const; // Pattern to delete matching data with this op - const OriginAttributesPattern& OriginPattern() const { return mOriginPattern; } + const OriginAttributesPattern& OriginPattern() const + { + return mOriginPattern; + } private: // The operation implementation body - nsresult Perform(DOMStorageDBThread* aThread); + nsresult Perform(StorageDBThread* aThread); friend class PendingOperations; OperationType mType; - RefPtr<DOMStorageCacheBridge> mCache; - RefPtr<DOMStorageUsageBridge> mUsage; + RefPtr<StorageCacheBridge> mCache; + RefPtr<StorageUsageBridge> mUsage; nsString const mKey; nsString const mValue; nsCString const mOrigin; OriginAttributesPattern const mOriginPattern; }; // Encapsulation of collective and coalescing logic for all pending operations // except preloads that are handled separately as priority operations class PendingOperations { public: PendingOperations(); - // Method responsible for coalescing redundant update operations with the same - // |Target()| or clear operations with the same or matching |Origin()| + // Method responsible for coalescing redundant update operations with the + // same |Target()| or clear operations with the same or matching |Origin()| void Add(DBOperation* aOperation); // True when there are some scheduled operations to flush on disk bool HasTasks() const; - // Moves collected operations to a local flat list to allow execution of the operation - // list out of the thread lock + // Moves collected operations to a local flat list to allow execution of the + // operation list out of the thread lock bool Prepare(); - // Executes the previously |Prepared()'ed| list of operations, retuns result, but doesn't - // handle it in any way in case of a failure - nsresult Execute(DOMStorageDBThread* aThread); + // Executes the previously |Prepared()'ed| list of operations, returns + // result, but doesn't handle it in any way in case of a failure + nsresult Execute(StorageDBThread* aThread); - // Finalizes the pending operation list, returns false when too many operations failed - // to flush what indicates a long standing issue with the database access. + // Finalizes the pending operation list, returns false when too many + // operations failed to flush what indicates a long standing issue with the + // database access. bool Finalize(nsresult aRv); - // true when a clear that deletes the given origin attr pattern and/or origin key - // is among the pending operations; when a preload for that scope is being scheduled, - // it must be finished right away - bool IsOriginClearPending(const nsACString& aOriginSuffix, const nsACString& aOriginNoSuffix) const; + // true when a clear that deletes the given origin attr pattern and/or + // origin key is among the pending operations; when a preload for that scope + // is being scheduled, it must be finished right away + bool IsOriginClearPending(const nsACString& aOriginSuffix, + const nsACString& aOriginNoSuffix) const; // Checks whether there is a pending update operation for this scope. - bool IsOriginUpdatePending(const nsACString& aOriginSuffix, const nsACString& aOriginNoSuffix) const; + bool IsOriginUpdatePending(const nsACString& aOriginSuffix, + const nsACString& aOriginNoSuffix) const; private: // Returns true iff new operation is of type newType and there is a pending // operation of type pendingType for the same key (target). bool CheckForCoalesceOpportunity(DBOperation* aNewOp, DBOperation::OperationType aPendingType, DBOperation::OperationType aNewType); @@ -238,17 +260,17 @@ public: class ThreadObserver final : public nsIThreadObserver { NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_NSITHREADOBSERVER ThreadObserver() : mHasPendingEvents(false) - , mMonitor("DOMStorageThreadMonitor") + , mMonitor("StorageThreadMonitor") { } bool HasPendingEvents() { mMonitor.AssertCurrentThreadOwns(); return mHasPendingEvents; } void ClearPendingEvents() { @@ -260,50 +282,80 @@ public: private: virtual ~ThreadObserver() {} bool mHasPendingEvents; // The monitor we drive the thread with Monitor mMonitor; }; public: - DOMStorageDBThread(); - virtual ~DOMStorageDBThread() {} + StorageDBThread(); + virtual ~StorageDBThread() {} virtual nsresult Init(); virtual nsresult Shutdown(); - virtual void AsyncPreload(DOMStorageCacheBridge* aCache, bool aPriority = false) - { InsertDBOp(new DBOperation(aPriority ? DBOperation::opPreloadUrgent : DBOperation::opPreload, aCache)); } + virtual void AsyncPreload(StorageCacheBridge* aCache, bool aPriority = false) + { + InsertDBOp(new DBOperation(aPriority + ? DBOperation::opPreloadUrgent + : DBOperation::opPreload, + aCache)); + } - virtual void SyncPreload(DOMStorageCacheBridge* aCache, bool aForce = false); + virtual void SyncPreload(StorageCacheBridge* aCache, bool aForce = false); - virtual void AsyncGetUsage(DOMStorageUsageBridge * aUsage) - { InsertDBOp(new DBOperation(DBOperation::opGetUsage, aUsage)); } + virtual void AsyncGetUsage(StorageUsageBridge* aUsage) + { + InsertDBOp(new DBOperation(DBOperation::opGetUsage, aUsage)); + } - virtual nsresult AsyncAddItem(DOMStorageCacheBridge* aCache, const nsAString& aKey, const nsAString& aValue) - { return InsertDBOp(new DBOperation(DBOperation::opAddItem, aCache, aKey, aValue)); } - - virtual nsresult AsyncUpdateItem(DOMStorageCacheBridge* aCache, const nsAString& aKey, const nsAString& aValue) - { return InsertDBOp(new DBOperation(DBOperation::opUpdateItem, aCache, aKey, aValue)); } + virtual nsresult AsyncAddItem(StorageCacheBridge* aCache, + const nsAString& aKey, + const nsAString& aValue) + { + return InsertDBOp(new DBOperation(DBOperation::opAddItem, aCache, aKey, + aValue)); + } - virtual nsresult AsyncRemoveItem(DOMStorageCacheBridge* aCache, const nsAString& aKey) - { return InsertDBOp(new DBOperation(DBOperation::opRemoveItem, aCache, aKey)); } + virtual nsresult AsyncUpdateItem(StorageCacheBridge* aCache, + const nsAString& aKey, + const nsAString& aValue) + { + return InsertDBOp(new DBOperation(DBOperation::opUpdateItem, aCache, aKey, + aValue)); + } - virtual nsresult AsyncClear(DOMStorageCacheBridge* aCache) - { return InsertDBOp(new DBOperation(DBOperation::opClear, aCache)); } + virtual nsresult AsyncRemoveItem(StorageCacheBridge* aCache, + const nsAString& aKey) + { + return InsertDBOp(new DBOperation(DBOperation::opRemoveItem, aCache, aKey)); + } + + virtual nsresult AsyncClear(StorageCacheBridge* aCache) + { + return InsertDBOp(new DBOperation(DBOperation::opClear, aCache)); + } virtual void AsyncClearAll() - { InsertDBOp(new DBOperation(DBOperation::opClearAll)); } + { + InsertDBOp(new DBOperation(DBOperation::opClearAll)); + } virtual void AsyncClearMatchingOrigin(const nsACString& aOriginNoSuffix) - { InsertDBOp(new DBOperation(DBOperation::opClearMatchingOrigin, aOriginNoSuffix)); } + { + InsertDBOp(new DBOperation(DBOperation::opClearMatchingOrigin, + aOriginNoSuffix)); + } virtual void AsyncClearMatchingOriginAttributes(const OriginAttributesPattern& aPattern) - { InsertDBOp(new DBOperation(DBOperation::opClearMatchingOriginAttributes, aPattern)); } + { + InsertDBOp(new DBOperation(DBOperation::opClearMatchingOriginAttributes, + aPattern)); + } virtual void AsyncFlush(); virtual bool ShouldPreloadOrigin(const nsACString& aOrigin); virtual void GetOriginsHavingData(InfallibleTArray<nsCString>* aOrigins); private: nsCOMPtr<nsIFile> mDatabaseFile; @@ -321,17 +373,18 @@ private: // Whether DB has already been open, avoid races between main thread reads // and pending DB init in the background I/O thread Atomic<bool, ReleaseAcquire> mDBReady; // State of the database initiation nsresult mStatus; - // List of origins (including origin attributes suffix) having data, for optimization purposes only + // List of origins (including origin attributes suffix) having data, for + // optimization purposes only nsTHashtable<nsCStringHashKey> mOriginsHavingData; // Connection used by the worker thread for all read and write ops nsCOMPtr<mozIStorageConnection> mWorkerConnection; // Connection used only on the main thread for sync read operations nsCOMPtr<mozIStorageConnection> mReaderConnection; @@ -399,9 +452,9 @@ private: // Thread loop static void ThreadFunc(void* aArg); void ThreadFunc(); }; } // namespace dom } // namespace mozilla -#endif /* DOMStorageDBThread_h___ */ +#endif // mozilla_dom_StorageDBThread_h
rename from dom/storage/DOMStorageDBUpdater.cpp rename to dom/storage/StorageDBUpdater.cpp --- a/dom/storage/DOMStorageDBUpdater.cpp +++ b/dom/storage/StorageDBUpdater.cpp @@ -1,15 +1,15 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* 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/. */ -#include "DOMStorageManager.h" +#include "StorageManager.h" #include "mozIStorageBindingParamsArray.h" #include "mozIStorageBindingParams.h" #include "mozIStorageValueArray.h" #include "mozIStorageFunction.h" #include "mozilla/BasePrincipal.h" #include "nsVariant.h" #include "mozilla/Services.h" @@ -57,17 +57,18 @@ nsReverseStringSQLFunction::OnFunctionCa return NS_OK; } // "scope" to "origin attributes suffix" and "origin key" convertor class ExtractOriginData : protected mozilla::Tokenizer { public: - ExtractOriginData(const nsACString& scope, nsACString& suffix, nsACString& origin) + ExtractOriginData(const nsACString& scope, nsACString& suffix, + nsACString& origin) : mozilla::Tokenizer(scope) { using mozilla::OriginAttributes; // Parse optional appId:isInIsolatedMozBrowserElement: string, in case // we don't find it, the scope is our new origin key and suffix // is empty. suffix.Truncate(); @@ -107,17 +108,18 @@ public: // If the profile went through schema 1 -> schema 0 -> schema 1 switching // we may have stored the full attributes origin suffix when there were // more than just appId and inIsolatedMozBrowser set on storage principal's // OriginAttributes. // // To preserve full uniqueness we store this suffix to the scope key. // Schema 0 code will just ignore it while keeping the scoping unique. // - // The whole scope string is in one of the following forms (when we are here): + // The whole scope string is in one of the following forms (when we are + // here): // // "1001:f:^appId=1001&inBrowser=false&addonId=101:gro.allizom.rxd.:https:443" // "1001:f:gro.allizom.rxd.:https:443" // | // +- the parser cursor position. // // If there is '^', the full origin attributes suffix follows. We search // for ':' since it is the delimiter used in the scope string and is never @@ -192,17 +194,17 @@ GetOriginParticular::OnFunctionCall( NS_ENSURE_SUCCESS(rv, rv); outVar.forget(aResult); return NS_OK; } } // namespace -namespace DOMStorageDBUpdater { +namespace StorageDBUpdater { nsresult CreateSchema1Tables(mozIStorageConnection *aWorkerConnection) { nsresult rv; rv = aWorkerConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING( "CREATE TABLE IF NOT EXISTS webappsstore2 (" "originAttributes TEXT, " @@ -259,19 +261,21 @@ nsresult Update(mozIStorageConnection *a NS_ENSURE_SUCCESS(rv, rv); rv = aWorkerConnection->TableExists(NS_LITERAL_CSTRING("webappsstore"), &webappsstoreExists); NS_ENSURE_SUCCESS(rv, rv); rv = aWorkerConnection->TableExists(NS_LITERAL_CSTRING("moz_webappsstore"), &moz_webappsstoreExists); NS_ENSURE_SUCCESS(rv, rv); - if (!webappsstore2Exists && !webappsstoreExists && !moz_webappsstoreExists) { - // The database is empty, this is the first start. Just create the schema table - // and break to the next version to update to, i.e. bypass update from the old version. + if (!webappsstore2Exists && !webappsstoreExists && + !moz_webappsstoreExists) { + // The database is empty, this is the first start. Just create the schema + // table and break to the next version to update to, i.e. bypass update + // from the old version. rv = CreateSchema1Tables(aWorkerConnection); NS_ENSURE_SUCCESS(rv, rv); rv = aWorkerConnection->SetSchemaVersion(CURRENT_SCHEMA_VERSION); NS_ENSURE_SUCCESS(rv, rv); break; @@ -292,17 +296,18 @@ nsresult Update(mozIStorageConnection *a rv = aWorkerConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING( "CREATE UNIQUE INDEX IF NOT EXISTS scope_key_index" " ON webappsstore2(scope, key)")); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<mozIStorageFunction> function1(new nsReverseStringSQLFunction()); NS_ENSURE_TRUE(function1, NS_ERROR_OUT_OF_MEMORY); - rv = aWorkerConnection->CreateFunction(NS_LITERAL_CSTRING("REVERSESTRING"), 1, function1); + rv = aWorkerConnection->CreateFunction(NS_LITERAL_CSTRING("REVERSESTRING"), + 1, function1); NS_ENSURE_SUCCESS(rv, rv); // Check if there is storage of Gecko 1.9.0 and if so, upgrade that storage // to actual webappsstore2 table and drop the obsolete table. First process // this newer table upgrade to priority potential duplicates from older // storage table. if (webappsstoreExists) { rv = aWorkerConnection->ExecuteSimpleSQL( @@ -330,40 +335,42 @@ nsresult Update(mozIStorageConnection *a rv = aWorkerConnection->ExecuteSimpleSQL( NS_LITERAL_CSTRING("DROP TABLE moz_webappsstore")); NS_ENSURE_SUCCESS(rv, rv); } aWorkerConnection->RemoveFunction(NS_LITERAL_CSTRING("REVERSESTRING")); - // Update the scoping to match the new implememntation: split to oa suffix and origin key - // First rename the old table, we want to remove some columns no longer needed, - // but even before that drop all indexes from it (CREATE IF NOT EXISTS for index on the - // new table would falsely find the index!) + // Update the scoping to match the new implememntation: split to oa suffix + // and origin key First rename the old table, we want to remove some columns + // no longer needed, but even before that drop all indexes from it (CREATE + // IF NOT EXISTS for index on the new table would falsely find the index!) rv = aWorkerConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING( "DROP INDEX IF EXISTS webappsstore2.origin_key_index")); NS_ENSURE_SUCCESS(rv, rv); rv = aWorkerConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING( "DROP INDEX IF EXISTS webappsstore2.scope_key_index")); NS_ENSURE_SUCCESS(rv, rv); rv = aWorkerConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING( "ALTER TABLE webappsstore2 RENAME TO webappsstore2_old")); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<mozIStorageFunction> oaSuffixFunc( new GetOriginParticular(GetOriginParticular::ORIGIN_ATTRIBUTES_SUFFIX)); - rv = aWorkerConnection->CreateFunction(NS_LITERAL_CSTRING("GET_ORIGIN_SUFFIX"), 1, oaSuffixFunc); + rv = aWorkerConnection->CreateFunction(NS_LITERAL_CSTRING("GET_ORIGIN_SUFFIX"), + 1, oaSuffixFunc); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<mozIStorageFunction> originKeyFunc( new GetOriginParticular(GetOriginParticular::ORIGIN_KEY)); - rv = aWorkerConnection->CreateFunction(NS_LITERAL_CSTRING("GET_ORIGIN_KEY"), 1, originKeyFunc); + rv = aWorkerConnection->CreateFunction(NS_LITERAL_CSTRING("GET_ORIGIN_KEY"), + 1, originKeyFunc); NS_ENSURE_SUCCESS(rv, rv); // Here we ensure this schema tables when we are updating. rv = CreateSchema1Tables(aWorkerConnection); NS_ENSURE_SUCCESS(rv, rv); rv = aWorkerConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING( "INSERT OR IGNORE INTO " @@ -397,21 +404,21 @@ nsresult Update(mozIStorageConnection *a MOZ_ASSERT(false); break; } // switch rv = transaction.Commit(); NS_ENSURE_SUCCESS(rv, rv); if (doVacuum) { - // In some cases this can make the disk file of the database significantly smaller. - // VACUUM cannot be executed inside a transaction. + // In some cases this can make the disk file of the database significantly + // smaller. VACUUM cannot be executed inside a transaction. rv = aWorkerConnection->ExecuteSimpleSQL( NS_LITERAL_CSTRING("VACUUM")); NS_ENSURE_SUCCESS(rv, rv); } return NS_OK; } -} // namespace DOMStorageDBUpdater +} // namespace StorageDBUpdater } // namespace dom } // namespace mozilla
rename from dom/storage/DOMStorageDBUpdater.h rename to dom/storage/StorageDBUpdater.h --- a/dom/storage/DOMStorageDBUpdater.h +++ b/dom/storage/StorageDBUpdater.h @@ -1,22 +1,22 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* 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 DOMStorageDBUpdater_h___ -#define DOMStorageDBUpdater_h___ +#ifndef mozilla_dom_StorageDBUpdater_h +#define mozilla_dom_StorageDBUpdater_h namespace mozilla { namespace dom { -namespace DOMStorageDBUpdater { +namespace StorageDBUpdater { -nsresult Update(mozIStorageConnection *aWorkerConnection); +nsresult Update(mozIStorageConnection* aWorkerConnection); -} // DOMStorageDBUpdater +} // StorageDBUpdater } // dom } // mozilla -#endif +#endif // mozilla_dom_StorageDBUpdater_h
rename from dom/storage/DOMStorageIPC.cpp rename to dom/storage/StorageIPC.cpp --- a/dom/storage/DOMStorageIPC.cpp +++ b/dom/storage/StorageIPC.cpp @@ -1,325 +1,328 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* 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/. */ -#include "DOMStorageIPC.h" +#include "StorageIPC.h" -#include "DOMStorageManager.h" +#include "StorageManager.h" #include "mozilla/dom/ContentChild.h" #include "mozilla/dom/ContentParent.h" #include "mozilla/Unused.h" #include "nsIDiskSpaceWatcher.h" #include "nsThreadUtils.h" namespace mozilla { namespace dom { // ---------------------------------------------------------------------------- // Child // ---------------------------------------------------------------------------- -NS_IMPL_ADDREF(DOMStorageDBChild) +NS_IMPL_ADDREF(StorageDBChild) -NS_IMETHODIMP_(MozExternalRefCountType) DOMStorageDBChild::Release(void) +NS_IMETHODIMP_(MozExternalRefCountType) StorageDBChild::Release(void) { NS_PRECONDITION(0 != mRefCnt, "dup release"); nsrefcnt count = --mRefCnt; - NS_LOG_RELEASE(this, count, "DOMStorageDBChild"); + NS_LOG_RELEASE(this, count, "StorageDBChild"); if (count == 1 && mIPCOpen) { Send__delete__(this); return 0; } if (count == 0) { mRefCnt = 1; delete this; return 0; } return count; } void -DOMStorageDBChild::AddIPDLReference() +StorageDBChild::AddIPDLReference() { MOZ_ASSERT(!mIPCOpen, "Attempting to retain multiple IPDL references"); mIPCOpen = true; AddRef(); } void -DOMStorageDBChild::ReleaseIPDLReference() +StorageDBChild::ReleaseIPDLReference() { MOZ_ASSERT(mIPCOpen, "Attempting to release non-existent IPDL reference"); mIPCOpen = false; Release(); } -DOMStorageDBChild::DOMStorageDBChild(DOMLocalStorageManager* aManager) +StorageDBChild::StorageDBChild(DOMLocalStorageManager* aManager) : mManager(aManager) , mStatus(NS_OK) , mIPCOpen(false) { } -DOMStorageDBChild::~DOMStorageDBChild() +StorageDBChild::~StorageDBChild() { } nsTHashtable<nsCStringHashKey>& -DOMStorageDBChild::OriginsHavingData() +StorageDBChild::OriginsHavingData() { if (!mOriginsHavingData) { mOriginsHavingData = new nsTHashtable<nsCStringHashKey>; } return *mOriginsHavingData; } nsresult -DOMStorageDBChild::Init() +StorageDBChild::Init() { ContentChild* child = ContentChild::GetSingleton(); AddIPDLReference(); child->SendPStorageConstructor(this); return NS_OK; } nsresult -DOMStorageDBChild::Shutdown() +StorageDBChild::Shutdown() { // There is nothing to do here, IPC will release automatically and // the actual thread running on the parent process will also stop // automatically in profile-before-change topic observer. return NS_OK; } void -DOMStorageDBChild::AsyncPreload(DOMStorageCacheBridge* aCache, bool aPriority) +StorageDBChild::AsyncPreload(StorageCacheBridge* aCache, bool aPriority) { if (mIPCOpen) { // Adding ref to cache for the time of preload. This ensures a reference to // to the cache and that all keys will load into this cache object. mLoadingCaches.PutEntry(aCache); - SendAsyncPreload(aCache->OriginSuffix(), aCache->OriginNoSuffix(), aPriority); + SendAsyncPreload(aCache->OriginSuffix(), aCache->OriginNoSuffix(), + aPriority); } else { // No IPC, no love. But the LoadDone call is expected. aCache->LoadDone(NS_ERROR_UNEXPECTED); } } void -DOMStorageDBChild::AsyncGetUsage(DOMStorageUsageBridge* aUsage) +StorageDBChild::AsyncGetUsage(StorageUsageBridge* aUsage) { if (mIPCOpen) { SendAsyncGetUsage(aUsage->OriginScope()); } } void -DOMStorageDBChild::SyncPreload(DOMStorageCacheBridge* aCache, bool aForceSync) +StorageDBChild::SyncPreload(StorageCacheBridge* aCache, bool aForceSync) { if (NS_FAILED(mStatus)) { aCache->LoadDone(mStatus); return; } if (!mIPCOpen) { aCache->LoadDone(NS_ERROR_UNEXPECTED); return; } // There is no way to put the child process to a wait state to receive all - // incoming async responses from the parent, hence we have to do a sync preload - // instead. We are smart though, we only demand keys that are left to load in - // case the async preload has already loaded some keys. + // incoming async responses from the parent, hence we have to do a sync + // preload instead. We are smart though, we only demand keys that are left to + // load in case the async preload has already loaded some keys. InfallibleTArray<nsString> keys, values; nsresult rv; - SendPreload(aCache->OriginSuffix(), aCache->OriginNoSuffix(), aCache->LoadedCount(), - &keys, &values, &rv); + SendPreload(aCache->OriginSuffix(), aCache->OriginNoSuffix(), + aCache->LoadedCount(), &keys, &values, &rv); for (uint32_t i = 0; i < keys.Length(); ++i) { aCache->LoadItem(keys[i], values[i]); } aCache->LoadDone(rv); } nsresult -DOMStorageDBChild::AsyncAddItem(DOMStorageCacheBridge* aCache, - const nsAString& aKey, - const nsAString& aValue) +StorageDBChild::AsyncAddItem(StorageCacheBridge* aCache, + const nsAString& aKey, + const nsAString& aValue) { if (NS_FAILED(mStatus) || !mIPCOpen) { return mStatus; } SendAsyncAddItem(aCache->OriginSuffix(), aCache->OriginNoSuffix(), nsString(aKey), nsString(aValue)); OriginsHavingData().PutEntry(aCache->Origin()); return NS_OK; } nsresult -DOMStorageDBChild::AsyncUpdateItem(DOMStorageCacheBridge* aCache, - const nsAString& aKey, - const nsAString& aValue) +StorageDBChild::AsyncUpdateItem(StorageCacheBridge* aCache, + const nsAString& aKey, + const nsAString& aValue) { if (NS_FAILED(mStatus) || !mIPCOpen) { return mStatus; } SendAsyncUpdateItem(aCache->OriginSuffix(), aCache->OriginNoSuffix(), nsString(aKey), nsString(aValue)); OriginsHavingData().PutEntry(aCache->Origin()); return NS_OK; } nsresult -DOMStorageDBChild::AsyncRemoveItem(DOMStorageCacheBridge* aCache, - const nsAString& aKey) +StorageDBChild::AsyncRemoveItem(StorageCacheBridge* aCache, + const nsAString& aKey) { if (NS_FAILED(mStatus) || !mIPCOpen) { return mStatus; } SendAsyncRemoveItem(aCache->OriginSuffix(), aCache->OriginNoSuffix(), nsString(aKey)); return NS_OK; } nsresult -DOMStorageDBChild::AsyncClear(DOMStorageCacheBridge* aCache) +StorageDBChild::AsyncClear(StorageCacheBridge* aCache) { if (NS_FAILED(mStatus) || !mIPCOpen) { return mStatus; } SendAsyncClear(aCache->OriginSuffix(), aCache->OriginNoSuffix()); OriginsHavingData().RemoveEntry(aCache->Origin()); return NS_OK; } bool -DOMStorageDBChild::ShouldPreloadOrigin(const nsACString& aOrigin) +StorageDBChild::ShouldPreloadOrigin(const nsACString& aOrigin) { // Return true if we didn't receive the origins list yet. // I tend to rather preserve a bit of early-after-start performance // than a bit of memory here. return !mOriginsHavingData || mOriginsHavingData->Contains(aOrigin); } mozilla::ipc::IPCResult -DOMStorageDBChild::RecvObserve(const nsCString& aTopic, - const nsString& aOriginAttributesPattern, - const nsCString& aOriginScope) +StorageDBChild::RecvObserve(const nsCString& aTopic, + const nsString& aOriginAttributesPattern, + const nsCString& aOriginScope) { - DOMStorageObserver::Self()->Notify( + StorageObserver::Self()->Notify( aTopic.get(), aOriginAttributesPattern, aOriginScope); return IPC_OK(); } mozilla::ipc::IPCResult -DOMStorageDBChild::RecvOriginsHavingData(nsTArray<nsCString>&& aOrigins) +StorageDBChild::RecvOriginsHavingData(nsTArray<nsCString>&& aOrigins) { for (uint32_t i = 0; i < aOrigins.Length(); ++i) { OriginsHavingData().PutEntry(aOrigins[i]); } return IPC_OK(); } mozilla::ipc::IPCResult -DOMStorageDBChild::RecvLoadItem(const nsCString& aOriginSuffix, - const nsCString& aOriginNoSuffix, - const nsString& aKey, - const nsString& aValue) +StorageDBChild::RecvLoadItem(const nsCString& aOriginSuffix, + const nsCString& aOriginNoSuffix, + const nsString& aKey, + const nsString& aValue) { - DOMStorageCache* aCache = mManager->GetCache(aOriginSuffix, aOriginNoSuffix); + StorageCache* aCache = mManager->GetCache(aOriginSuffix, aOriginNoSuffix); if (aCache) { aCache->LoadItem(aKey, aValue); } return IPC_OK(); } mozilla::ipc::IPCResult -DOMStorageDBChild::RecvLoadDone(const nsCString& aOriginSuffix, - const nsCString& aOriginNoSuffix, - const nsresult& aRv) +StorageDBChild::RecvLoadDone(const nsCString& aOriginSuffix, + const nsCString& aOriginNoSuffix, + const nsresult& aRv) { - DOMStorageCache* aCache = mManager->GetCache(aOriginSuffix, aOriginNoSuffix); + StorageCache* aCache = mManager->GetCache(aOriginSuffix, aOriginNoSuffix); if (aCache) { aCache->LoadDone(aRv); // Just drop reference to this cache now since the load is done. - mLoadingCaches.RemoveEntry(static_cast<DOMStorageCacheBridge*>(aCache)); + mLoadingCaches.RemoveEntry(static_cast<StorageCacheBridge*>(aCache)); } return IPC_OK(); } mozilla::ipc::IPCResult -DOMStorageDBChild::RecvLoadUsage(const nsCString& aOriginNoSuffix, const int64_t& aUsage) +StorageDBChild::RecvLoadUsage(const nsCString& aOriginNoSuffix, + const int64_t& aUsage) { - RefPtr<DOMStorageUsageBridge> scopeUsage = mManager->GetOriginUsage(aOriginNoSuffix); + RefPtr<StorageUsageBridge> scopeUsage = + mManager->GetOriginUsage(aOriginNoSuffix); scopeUsage->LoadUsage(aUsage); return IPC_OK(); } mozilla::ipc::IPCResult -DOMStorageDBChild::RecvError(const nsresult& aRv) +StorageDBChild::RecvError(const nsresult& aRv) { mStatus = aRv; return IPC_OK(); } // ---------------------------------------------------------------------------- // Parent // ---------------------------------------------------------------------------- -NS_IMPL_ADDREF(DOMStorageDBParent) -NS_IMPL_RELEASE(DOMStorageDBParent) +NS_IMPL_ADDREF(StorageDBParent) +NS_IMPL_RELEASE(StorageDBParent) void -DOMStorageDBParent::AddIPDLReference() +StorageDBParent::AddIPDLReference() { MOZ_ASSERT(!mIPCOpen, "Attempting to retain multiple IPDL references"); mIPCOpen = true; AddRef(); } void -DOMStorageDBParent::ReleaseIPDLReference() +StorageDBParent::ReleaseIPDLReference() { MOZ_ASSERT(mIPCOpen, "Attempting to release non-existent IPDL reference"); mIPCOpen = false; Release(); } namespace { class SendInitialChildDataRunnable : public Runnable { public: - explicit SendInitialChildDataRunnable(DOMStorageDBParent* aParent) + explicit SendInitialChildDataRunnable(StorageDBParent* aParent) : mParent(aParent) {} private: NS_IMETHOD Run() override { if (!mParent->IPCOpen()) { return NS_OK; } - DOMStorageDBBridge* db = DOMStorageCache::GetDatabase(); + StorageDBBridge* db = StorageCache::GetDatabase(); if (db) { InfallibleTArray<nsCString> scopes; db->GetOriginsHavingData(&scopes); mozilla::Unused << mParent->SendOriginsHavingData(scopes); } // We need to check if the device is in a low disk space situation, so // we can forbid in that case any write in localStorage. @@ -335,94 +338,96 @@ private: if (lowDiskSpace) { mozilla::Unused << mParent->SendObserve( nsDependentCString("low-disk-space"), EmptyString(), EmptyCString()); } return NS_OK; } - RefPtr<DOMStorageDBParent> mParent; + RefPtr<StorageDBParent> mParent; }; } // namespace -DOMStorageDBParent::DOMStorageDBParent() +StorageDBParent::StorageDBParent() : mIPCOpen(false) { - DOMStorageObserver* observer = DOMStorageObserver::Self(); + StorageObserver* observer = StorageObserver::Self(); if (observer) { observer->AddSink(this); } // We are always open by IPC only AddIPDLReference(); // Cannot send directly from here since the channel // is not completely built at this moment. RefPtr<SendInitialChildDataRunnable> r = new SendInitialChildDataRunnable(this); NS_DispatchToCurrentThread(r); } -DOMStorageDBParent::~DOMStorageDBParent() +StorageDBParent::~StorageDBParent() { - DOMStorageObserver* observer = DOMStorageObserver::Self(); + StorageObserver* observer = StorageObserver::Self(); if (observer) { observer->RemoveSink(this); } } -DOMStorageDBParent::CacheParentBridge* -DOMStorageDBParent::NewCache(const nsACString& aOriginSuffix, const nsACString& aOriginNoSuffix) +StorageDBParent::CacheParentBridge* +StorageDBParent::NewCache(const nsACString& aOriginSuffix, + const nsACString& aOriginNoSuffix) { return new CacheParentBridge(this, aOriginSuffix, aOriginNoSuffix); } void -DOMStorageDBParent::ActorDestroy(ActorDestroyReason aWhy) +StorageDBParent::ActorDestroy(ActorDestroyReason aWhy) { // Implement me! Bug 1005169 } mozilla::ipc::IPCResult -DOMStorageDBParent::RecvAsyncPreload(const nsCString& aOriginSuffix, - const nsCString& aOriginNoSuffix, - const bool& aPriority) +StorageDBParent::RecvAsyncPreload(const nsCString& aOriginSuffix, + const nsCString& aOriginNoSuffix, + const bool& aPriority) { - DOMStorageDBBridge* db = DOMStorageCache::StartDatabase(); + StorageDBBridge* db = StorageCache::StartDatabase(); if (!db) { return IPC_FAIL_NO_REASON(this); } db->AsyncPreload(NewCache(aOriginSuffix, aOriginNoSuffix), aPriority); return IPC_OK(); } mozilla::ipc::IPCResult -DOMStorageDBParent::RecvAsyncGetUsage(const nsCString& aOriginNoSuffix) +StorageDBParent::RecvAsyncGetUsage(const nsCString& aOriginNoSuffix) { - DOMStorageDBBridge* db = DOMStorageCache::StartDatabase(); + StorageDBBridge* db = StorageCache::StartDatabase(); if (!db) { return IPC_FAIL_NO_REASON(this); } // The object releases it self in LoadUsage method - RefPtr<UsageParentBridge> usage = new UsageParentBridge(this, aOriginNoSuffix); + RefPtr<UsageParentBridge> usage = + new UsageParentBridge(this, aOriginNoSuffix); db->AsyncGetUsage(usage); return IPC_OK(); } namespace { -// We need another implementation of DOMStorageCacheBridge to do +// We need another implementation of StorageCacheBridge to do // synchronous IPC preload. This class just receives Load* notifications // and fills the returning arguments of RecvPreload with the database // values for us. -class SyncLoadCacheHelper : public DOMStorageCacheBridge +class SyncLoadCacheHelper : public StorageCacheBridge { public: SyncLoadCacheHelper(const nsCString& aOriginSuffix, const nsCString& aOriginNoSuffix, uint32_t aAlreadyLoadedCount, InfallibleTArray<nsString>* aKeys, InfallibleTArray<nsString>* aValues, nsresult* rv) @@ -436,17 +441,17 @@ public: , mLoadedCount(aAlreadyLoadedCount) { // Precaution *mRv = NS_ERROR_UNEXPECTED; } virtual const nsCString Origin() const { - return DOMStorageManager::CreateOrigin(mSuffix, mOrigin); + return StorageManagerBase::CreateOrigin(mSuffix, mOrigin); } virtual const nsCString& OriginNoSuffix() const { return mOrigin; } virtual const nsCString& OriginSuffix() const { return mSuffix; } virtual bool Loaded() { return mLoaded; } virtual uint32_t LoadedCount() { return mLoadedCount; } virtual bool LoadItem(const nsAString& aKey, const nsString& aValue) { // Called on the aCache background thread @@ -486,126 +491,130 @@ private: nsresult* mRv; bool mLoaded; uint32_t mLoadedCount; }; } // namespace mozilla::ipc::IPCResult -DOMStorageDBParent::RecvPreload(const nsCString& aOriginSuffix, - const nsCString& aOriginNoSuffix, - const uint32_t& aAlreadyLoadedCount, - InfallibleTArray<nsString>* aKeys, - InfallibleTArray<nsString>* aValues, - nsresult* aRv) +StorageDBParent::RecvPreload(const nsCString& aOriginSuffix, + const nsCString& aOriginNoSuffix, + const uint32_t& aAlreadyLoadedCount, + InfallibleTArray<nsString>* aKeys, + InfallibleTArray<nsString>* aValues, + nsresult* aRv) { - DOMStorageDBBridge* db = DOMStorageCache::StartDatabase(); + StorageDBBridge* db = StorageCache::StartDatabase(); if (!db) { return IPC_FAIL_NO_REASON(this); } RefPtr<SyncLoadCacheHelper> cache( - new SyncLoadCacheHelper(aOriginSuffix, aOriginNoSuffix, aAlreadyLoadedCount, aKeys, aValues, aRv)); + new SyncLoadCacheHelper(aOriginSuffix, aOriginNoSuffix, aAlreadyLoadedCount, + aKeys, aValues, aRv)); db->SyncPreload(cache, true); return IPC_OK(); } mozilla::ipc::IPCResult -DOMStorageDBParent::RecvAsyncAddItem(const nsCString& aOriginSuffix, - const nsCString& aOriginNoSuffix, - const nsString& aKey, - const nsString& aValue) +StorageDBParent::RecvAsyncAddItem(const nsCString& aOriginSuffix, + const nsCString& aOriginNoSuffix, + const nsString& aKey, + const nsString& aValue) { - DOMStorageDBBridge* db = DOMStorageCache::StartDatabase(); + StorageDBBridge* db = StorageCache::StartDatabase(); if (!db) { return IPC_FAIL_NO_REASON(this); } - nsresult rv = db->AsyncAddItem(NewCache(aOriginSuffix, aOriginNoSuffix), aKey, aValue); + nsresult rv = db->AsyncAddItem(NewCache(aOriginSuffix, aOriginNoSuffix), aKey, + aValue); if (NS_FAILED(rv) && mIPCOpen) { mozilla::Unused << SendError(rv); } return IPC_OK(); } mozilla::ipc::IPCResult -DOMStorageDBParent::RecvAsyncUpdateItem(const nsCString& aOriginSuffix, - const nsCString& aOriginNoSuffix, - const nsString& aKey, - const nsString& aValue) +StorageDBParent::RecvAsyncUpdateItem(const nsCString& aOriginSuffix, + const nsCString& aOriginNoSuffix, + const nsString& aKey, + const nsString& aValue) { - DOMStorageDBBridge* db = DOMStorageCache::StartDatabase(); + StorageDBBridge* db = StorageCache::StartDatabase(); if (!db) { return IPC_FAIL_NO_REASON(this); } - nsresult rv = db->AsyncUpdateItem(NewCache(aOriginSuffix, aOriginNoSuffix), aKey, aValue); + nsresult rv = db->AsyncUpdateItem(NewCache(aOriginSuffix, aOriginNoSuffix), + aKey, aValue); if (NS_FAILED(rv) && mIPCOpen) { mozilla::Unused << SendError(rv); } return IPC_OK(); } mozilla::ipc::IPCResult -DOMStorageDBParent::RecvAsyncRemoveItem(const nsCString& aOriginSuffix, - const nsCString& aOriginNoSuffix, - const nsString& aKey) +StorageDBParent::RecvAsyncRemoveItem(const nsCString& aOriginSuffix, + const nsCString& aOriginNoSuffix, + const nsString& aKey) { - DOMStorageDBBridge* db = DOMStorageCache::StartDatabase(); + StorageDBBridge* db = StorageCache::StartDatabase(); if (!db) { return IPC_FAIL_NO_REASON(this); } - nsresult rv = db->AsyncRemoveItem(NewCache(aOriginSuffix, aOriginNoSuffix), aKey); + nsresult rv = db->AsyncRemoveItem(NewCache(aOriginSuffix, aOriginNoSuffix), + aKey); if (NS_FAILED(rv) && mIPCOpen) { mozilla::Unused << SendError(rv); } return IPC_OK(); } mozilla::ipc::IPCResult -DOMStorageDBParent::RecvAsyncClear(const nsCString& aOriginSuffix, - const nsCString& aOriginNoSuffix) +StorageDBParent::RecvAsyncClear(const nsCString& aOriginSuffix, + const nsCString& aOriginNoSuffix) { - DOMStorageDBBridge* db = DOMStorageCache::StartDatabase(); + StorageDBBridge* db = StorageCache::StartDatabase(); if (!db) { return IPC_FAIL_NO_REASON(this); } nsresult rv = db->AsyncClear(NewCache(aOriginSuffix, aOriginNoSuffix)); if (NS_FAILED(rv) && mIPCOpen) { mozilla::Unused << SendError(rv); } return IPC_OK(); } mozilla::ipc::IPCResult -DOMStorageDBParent::RecvAsyncFlush() +StorageDBParent::RecvAsyncFlush() { - DOMStorageDBBridge* db = DOMStorageCache::GetDatabase(); + StorageDBBridge* db = StorageCache::GetDatabase(); if (!db) { return IPC_FAIL_NO_REASON(this); } db->AsyncFlush(); return IPC_OK(); } -// DOMStorageObserverSink +// StorageObserverSink nsresult -DOMStorageDBParent::Observe(const char* aTopic, - const nsAString& aOriginAttributesPattern, - const nsACString& aOriginScope) +StorageDBParent::Observe(const char* aTopic, + const nsAString& aOriginAttributesPattern, + const nsACString& aOriginScope) { if (mIPCOpen) { mozilla::Unused << SendObserve(nsDependentCString(aTopic), nsString(aOriginAttributesPattern), nsCString(aOriginScope)); } return NS_OK; @@ -617,44 +626,44 @@ namespace { class LoadRunnable : public Runnable { public: enum TaskType { loadItem, loadDone }; - LoadRunnable(DOMStorageDBParent* aParent, + LoadRunnable(StorageDBParent* aParent, TaskType aType, const nsACString& aOriginSuffix, const nsACString& aOriginNoSuffix, const nsAString& aKey = EmptyString(), const nsAString& aValue = EmptyString()) : mParent(aParent) , mType(aType) , mSuffix(aOriginSuffix) , mOrigin(aOriginNoSuffix) , mKey(aKey) , mValue(aValue) { } - LoadRunnable(DOMStorageDBParent* aParent, + LoadRunnable(StorageDBParent* aParent, TaskType aType, const nsACString& aOriginSuffix, const nsACString& aOriginNoSuffix, nsresult aRv) : mParent(aParent) , mType(aType) , mSuffix(aOriginSuffix) , mOrigin(aOriginNoSuffix) , mRv(aRv) { } private: - RefPtr<DOMStorageDBParent> mParent; + RefPtr<StorageDBParent> mParent; TaskType mType; nsCString mSuffix, mOrigin; nsString mKey; nsString mValue; nsresult mRv; NS_IMETHOD Run() override { @@ -673,93 +682,97 @@ private: } return NS_OK; } }; } // namespace -// DOMStorageDBParent::CacheParentBridge +// StorageDBParent::CacheParentBridge const nsCString -DOMStorageDBParent::CacheParentBridge::Origin() const +StorageDBParent::CacheParentBridge::Origin() const { - return DOMStorageManager::CreateOrigin(mOriginSuffix, mOriginNoSuffix); + return StorageManagerBase::CreateOrigin(mOriginSuffix, mOriginNoSuffix); } bool -DOMStorageDBParent::CacheParentBridge::LoadItem(const nsAString& aKey, const nsString& aValue) +StorageDBParent::CacheParentBridge::LoadItem(const nsAString& aKey, + const nsString& aValue) { if (mLoaded) { return false; } ++mLoadedCount; RefPtr<LoadRunnable> r = - new LoadRunnable(mParent, LoadRunnable::loadItem, mOriginSuffix, mOriginNoSuffix, aKey, aValue); + new LoadRunnable(mParent, LoadRunnable::loadItem, mOriginSuffix, + mOriginNoSuffix, aKey, aValue); NS_DispatchToMainThread(r); return true; } void -DOMStorageDBParent::CacheParentBridge::LoadDone(nsresult aRv) +StorageDBParent::CacheParentBridge::LoadDone(nsresult aRv) { // Prevent send of duplicate LoadDone. if (mLoaded) { return; } mLoaded = true; RefPtr<LoadRunnable> r = - new LoadRunnable(mParent, LoadRunnable::loadDone, mOriginSuffix, mOriginNoSuffix, aRv); + new LoadRunnable(mParent, LoadRunnable::loadDone, mOriginSuffix, + mOriginNoSuffix, aRv); NS_DispatchToMainThread(r); } void -DOMStorageDBParent::CacheParentBridge::LoadWait() +StorageDBParent::CacheParentBridge::LoadWait() { // Should never be called on this implementation MOZ_ASSERT(false); } -// DOMStorageDBParent::UsageParentBridge +// StorageDBParent::UsageParentBridge namespace { class UsageRunnable : public Runnable { public: - UsageRunnable(DOMStorageDBParent* aParent, const nsACString& aOriginScope, const int64_t& aUsage) - : mParent(aParent) - , mOriginScope(aOriginScope) - , mUsage(aUsage) + UsageRunnable(StorageDBParent* aParent, const nsACString& aOriginScope, + const int64_t& aUsage) + : mParent(aParent) + , mOriginScope(aOriginScope) + , mUsage(aUsage) {} private: NS_IMETHOD Run() override { if (!mParent->IPCOpen()) { return NS_OK; } mozilla::Unused << mParent->SendLoadUsage(mOriginScope, mUsage); return NS_OK; } - RefPtr<DOMStorageDBParent> mParent; + RefPtr<StorageDBParent> mParent; nsCString mOriginScope; int64_t mUsage; }; } // namespace void -DOMStorageDBParent::UsageParentBridge::LoadUsage(const int64_t aUsage) +StorageDBParent::UsageParentBridge::LoadUsage(const int64_t aUsage) { RefPtr<UsageRunnable> r = new UsageRunnable(mParent, mOriginScope, aUsage); NS_DispatchToMainThread(r); } } // namespace dom } // namespace mozilla
rename from dom/storage/DOMStorageIPC.h rename to dom/storage/StorageIPC.h --- a/dom/storage/DOMStorageIPC.h +++ b/dom/storage/StorageIPC.h @@ -1,63 +1,67 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* 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 nsDOMStorageIPC_h___ -#define nsDOMStorageIPC_h___ +#ifndef mozilla_dom_StorageIPC_h +#define mozilla_dom_StorageIPC_h #include "mozilla/dom/PStorageChild.h" #include "mozilla/dom/PStorageParent.h" -#include "DOMStorageDBThread.h" -#include "DOMStorageCache.h" -#include "DOMStorageObserver.h" +#include "StorageDBThread.h" +#include "StorageCache.h" +#include "StorageObserver.h" #include "mozilla/Mutex.h" #include "nsAutoPtr.h" namespace mozilla { class OriginAttributesPattern; namespace dom { class DOMLocalStorageManager; // Child side of the IPC protocol, exposes as DB interface but // is responsible to send all requests to the parent process // and expects asynchronous answers. Those are then transparently // forwarded back to consumers on the child process. -class DOMStorageDBChild final : public DOMStorageDBBridge - , public PStorageChild +class StorageDBChild final : public StorageDBBridge + , public PStorageChild { - virtual ~DOMStorageDBChild(); + virtual ~StorageDBChild(); public: - explicit DOMStorageDBChild(DOMLocalStorageManager* aManager); + explicit StorageDBChild(DOMLocalStorageManager* aManager); NS_IMETHOD_(MozExternalRefCountType) AddRef(void); NS_IMETHOD_(MozExternalRefCountType) Release(void); void AddIPDLReference(); void ReleaseIPDLReference(); virtual nsresult Init(); virtual nsresult Shutdown(); - virtual void AsyncPreload(DOMStorageCacheBridge* aCache, bool aPriority = false); - virtual void AsyncGetUsage(DOMStorageUsageBridge* aUsage); + virtual void AsyncPreload(StorageCacheBridge* aCache, bool aPriority = false); + virtual void AsyncGetUsage(StorageUsageBridge* aUsage); - virtual void SyncPreload(DOMStorageCacheBridge* aCache, bool aForceSync = false); + virtual void SyncPreload(StorageCacheBridge* aCache, bool aForceSync = false); - virtual nsresult AsyncAddItem(DOMStorageCacheBridge* aCache, const nsAString& aKey, const nsAString& aValue); - virtual nsresult AsyncUpdateItem(DOMStorageCacheBridge* aCache, const nsAString& aKey, const nsAString& aValue); - virtual nsresult AsyncRemoveItem(DOMStorageCacheBridge* aCache, const nsAString& aKey); - virtual nsresult AsyncClear(DOMStorageCacheBridge* aCache); + virtual nsresult AsyncAddItem(StorageCacheBridge* aCache, + const nsAString& aKey, const nsAString& aValue); + virtual nsresult AsyncUpdateItem(StorageCacheBridge* aCache, + const nsAString& aKey, + const nsAString& aValue); + virtual nsresult AsyncRemoveItem(StorageCacheBridge* aCache, + const nsAString& aKey); + virtual nsresult AsyncClear(StorageCacheBridge* aCache); virtual void AsyncClearAll() { if (mOriginsHavingData) { mOriginsHavingData->Clear(); /* NO-OP on the child process otherwise */ } } @@ -98,121 +102,139 @@ private: // Held to get caches to forward answers to. RefPtr<DOMLocalStorageManager> mManager; // Origins having data hash, for optimization purposes only nsAutoPtr<nsTHashtable<nsCStringHashKey>> mOriginsHavingData; // List of caches waiting for preload. This ensures the contract that // AsyncPreload call references the cache for time of the preload. - nsTHashtable<nsRefPtrHashKey<DOMStorageCacheBridge>> mLoadingCaches; + nsTHashtable<nsRefPtrHashKey<StorageCacheBridge>> mLoadingCaches; // Status of the remote database nsresult mStatus; bool mIPCOpen; }; // Receives async requests from child processes and is responsible // to send back responses from the DB thread. Exposes as a fake -// DOMStorageCache consumer. +// StorageCache consumer. // Also responsible for forwardning all chrome operation notifications // such as cookie cleaning etc to the child process. -class DOMStorageDBParent final : public PStorageParent - , public DOMStorageObserverSink +class StorageDBParent final : public PStorageParent + , public StorageObserverSink { - virtual ~DOMStorageDBParent(); + virtual ~StorageDBParent(); public: - DOMStorageDBParent(); + StorageDBParent(); NS_IMETHOD_(MozExternalRefCountType) AddRef(void); NS_IMETHOD_(MozExternalRefCountType) Release(void); void AddIPDLReference(); void ReleaseIPDLReference(); bool IPCOpen() { return mIPCOpen; } public: // Fake cache class receiving async callbacks from DB thread, sending // them back to appropriate cache object on the child process. - class CacheParentBridge : public DOMStorageCacheBridge { + class CacheParentBridge : public StorageCacheBridge { public: - CacheParentBridge(DOMStorageDBParent* aParentDB, + CacheParentBridge(StorageDBParent* aParentDB, const nsACString& aOriginSuffix, const nsACString& aOriginNoSuffix) : mParent(aParentDB) , mOriginSuffix(aOriginSuffix), mOriginNoSuffix(aOriginNoSuffix) , mLoaded(false), mLoadedCount(0) {} virtual ~CacheParentBridge() {} - // DOMStorageCacheBridge + // StorageCacheBridge virtual const nsCString Origin() const; virtual const nsCString& OriginNoSuffix() const { return mOriginNoSuffix; } virtual const nsCString& OriginSuffix() const { return mOriginSuffix; } virtual bool Loaded() { return mLoaded; } virtual uint32_t LoadedCount() { return mLoadedCount; } virtual bool LoadItem(const nsAString& aKey, const nsString& aValue); virtual void LoadDone(nsresult aRv); virtual void LoadWait(); private: - RefPtr<DOMStorageDBParent> mParent; + RefPtr<StorageDBParent> mParent; nsCString mOriginSuffix, mOriginNoSuffix; bool mLoaded; uint32_t mLoadedCount; }; // Fake usage class receiving async callbacks from DB thread - class UsageParentBridge : public DOMStorageUsageBridge + class UsageParentBridge : public StorageUsageBridge { public: - UsageParentBridge(DOMStorageDBParent* aParentDB, const nsACString& aOriginScope) + UsageParentBridge(StorageDBParent* aParentDB, + const nsACString& aOriginScope) : mParent(aParentDB), mOriginScope(aOriginScope) {} virtual ~UsageParentBridge() {} - // DOMStorageUsageBridge + // StorageUsageBridge virtual const nsCString& OriginScope() { return mOriginScope; } virtual void LoadUsage(const int64_t usage); private: - RefPtr<DOMStorageDBParent> mParent; + RefPtr<StorageDBParent> mParent; nsCString mOriginScope; }; private: // IPC virtual void ActorDestroy(ActorDestroyReason aWhy) override; - mozilla::ipc::IPCResult RecvAsyncPreload(const nsCString& aOriginSuffix, const nsCString& aOriginNoSuffix, const bool& aPriority) override; - mozilla::ipc::IPCResult RecvPreload(const nsCString& aOriginSuffix, const nsCString& aOriginNoSuffix, const uint32_t& aAlreadyLoadedCount, - InfallibleTArray<nsString>* aKeys, InfallibleTArray<nsString>* aValues, + mozilla::ipc::IPCResult RecvAsyncPreload(const nsCString& aOriginSuffix, + const nsCString& aOriginNoSuffix, + const bool& aPriority) override; + mozilla::ipc::IPCResult RecvPreload(const nsCString& aOriginSuffix, + const nsCString& aOriginNoSuffix, + const uint32_t& aAlreadyLoadedCount, + InfallibleTArray<nsString>* aKeys, + InfallibleTArray<nsString>* aValues, nsresult* aRv) override; mozilla::ipc::IPCResult RecvAsyncGetUsage(const nsCString& aOriginNoSuffix) override; - mozilla::ipc::IPCResult RecvAsyncAddItem(const nsCString& aOriginSuffix, const nsCString& aOriginNoSuffix, const nsString& aKey, const nsString& aValue) override; - mozilla::ipc::IPCResult RecvAsyncUpdateItem(const nsCString& aOriginSuffix, const nsCString& aOriginNoSuffix, const nsString& aKey, const nsString& aValue) override; - mozilla::ipc::IPCResult RecvAsyncRemoveItem(const nsCString& aOriginSuffix, const nsCString& aOriginNoSuffix, const nsString& aKey) override; - mozilla::ipc::IPCResult RecvAsyncClear(const nsCString& aOriginSuffix, const nsCString& aOriginNoSuffix) override; + mozilla::ipc::IPCResult RecvAsyncAddItem(const nsCString& aOriginSuffix, + const nsCString& aOriginNoSuffix, + const nsString& aKey, + const nsString& aValue) override; + mozilla::ipc::IPCResult RecvAsyncUpdateItem(const nsCString& aOriginSuffix, + const nsCString& aOriginNoSuffix, + const nsString& aKey, + const nsString& aValue) override; + mozilla::ipc::IPCResult RecvAsyncRemoveItem(const nsCString& aOriginSuffix, + const nsCString& aOriginNoSuffix, + const nsString& aKey) override; + mozilla::ipc::IPCResult RecvAsyncClear(const nsCString& aOriginSuffix, + const nsCString& aOriginNoSuffix) override; mozilla::ipc::IPCResult RecvAsyncFlush() override; - // DOMStorageObserverSink - virtual nsresult Observe(const char* aTopic, const nsAString& aOriginAttrPattern, const nsACString& aOriginScope) override; + // StorageObserverSink + virtual nsresult Observe(const char* aTopic, + const nsAString& aOriginAttrPattern, + const nsACString& aOriginScope) override; private: - CacheParentBridge* NewCache(const nsACString& aOriginSuffix, const nsACString& aOriginNoSuffix); + CacheParentBridge* NewCache(const nsACString& aOriginSuffix, + const nsACString& aOriginNoSuffix); ThreadSafeAutoRefCnt mRefCnt; NS_DECL_OWNINGTHREAD // True when IPC channel is open and Send*() methods are OK to use. bool mIPCOpen; }; } // namespace dom } // namespace mozilla -#endif +#endif // mozilla_dom_StorageIPC_h
rename from dom/storage/DOMStorageManager.cpp rename to dom/storage/StorageManager.cpp --- a/dom/storage/DOMStorageManager.cpp +++ b/dom/storage/StorageManager.cpp @@ -1,17 +1,17 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* 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/. */ -#include "DOMStorageManager.h" -#include "DOMStorage.h" -#include "DOMStorageDBThread.h" +#include "StorageManager.h" +#include "Storage.h" +#include "StorageDBThread.h" #include "nsIScriptSecurityManager.h" #include "nsIEffectiveTLDService.h" #include "nsNetUtil.h" #include "nsNetCID.h" #include "nsIURL.h" #include "nsPrintfCString.h" @@ -35,21 +35,22 @@ int32_t gQuotaLimit = DEFAULT_QUOTA_LIMI } // namespace DOMLocalStorageManager* DOMLocalStorageManager::sSelf = nullptr; // static uint32_t -DOMStorageManager::GetQuota() +StorageManagerBase::GetQuota() { static bool preferencesInitialized = false; if (!preferencesInitialized) { - mozilla::Preferences::AddIntVarCache(&gQuotaLimit, "dom.storage.default_quota", + mozilla::Preferences::AddIntVarCache(&gQuotaLimit, + "dom.storage.default_quota", DEFAULT_QUOTA_LIMIT); preferencesInitialized = true; } return gQuotaLimit * 1024; // pref is in kBs } void @@ -92,35 +93,35 @@ PrincipalsEqual(nsIPrincipal* aObjectPri if (!aObjectPrincipal) { return false; } return aSubjectPrincipal->Equals(aObjectPrincipal); } -NS_IMPL_ISUPPORTS(DOMStorageManager, +NS_IMPL_ISUPPORTS(StorageManagerBase, nsIDOMStorageManager) -DOMStorageManager::DOMStorageManager(DOMStorage::StorageType aType) +StorageManagerBase::StorageManagerBase(Storage::StorageType aType) : mCaches(8) , mType(aType) , mLowDiskSpace(false) { - DOMStorageObserver* observer = DOMStorageObserver::Self(); - NS_ASSERTION(observer, "No DOMStorageObserver, cannot observe private data delete notifications!"); + StorageObserver* observer = StorageObserver::Self(); + NS_ASSERTION(observer, "No StorageObserver, cannot observe private data delete notifications!"); if (observer) { observer->AddSink(this); } } -DOMStorageManager::~DOMStorageManager() +StorageManagerBase::~StorageManagerBase() { - DOMStorageObserver* observer = DOMStorageObserver::Self(); + StorageObserver* observer = StorageObserver::Self(); if (observer) { observer->RemoveSink(this); } } namespace { nsresult @@ -211,71 +212,73 @@ CreateQuotaDBKey(nsIPrincipal* aPrincipa return NS_OK; } } // namespace // static nsCString -DOMStorageManager::CreateOrigin(const nsACString& aOriginSuffix, const nsACString& aOriginNoSuffix) +StorageManagerBase::CreateOrigin(const nsACString& aOriginSuffix, + const nsACString& aOriginNoSuffix) { // Note: some hard-coded sqlite statements are dependent on the format this // method returns. Changing this without updating those sqlite statements // will cause malfunction. nsAutoCString scope; scope.Append(aOriginSuffix); scope.Append(':'); scope.Append(aOriginNoSuffix); return scope; } -DOMStorageCache* -DOMStorageManager::GetCache(const nsACString& aOriginSuffix, const nsACString& aOriginNoSuffix) +StorageCache* +StorageManagerBase::GetCache(const nsACString& aOriginSuffix, + const nsACString& aOriginNoSuffix) { CacheOriginHashtable* table = mCaches.LookupOrAdd(aOriginSuffix); - DOMStorageCacheHashKey* entry = table->GetEntry(aOriginNoSuffix); + StorageCacheHashKey* entry = table->GetEntry(aOriginNoSuffix); if (!entry) { return nullptr; } return entry->cache(); } -already_AddRefed<DOMStorageUsage> -DOMStorageManager::GetOriginUsage(const nsACString& aOriginNoSuffix) +already_AddRefed<StorageUsage> +StorageManagerBase::GetOriginUsage(const nsACString& aOriginNoSuffix) { - RefPtr<DOMStorageUsage> usage; + RefPtr<StorageUsage> usage; if (mUsages.Get(aOriginNoSuffix, &usage)) { return usage.forget(); } - usage = new DOMStorageUsage(aOriginNoSuffix); + usage = new StorageUsage(aOriginNoSuffix); if (mType == LocalStorage) { - DOMStorageDBBridge* db = DOMStorageCache::StartDatabase(); + StorageDBBridge* db = StorageCache::StartDatabase(); if (db) { db->AsyncGetUsage(usage); } } mUsages.Put(aOriginNoSuffix, usage); return usage.forget(); } -already_AddRefed<DOMStorageCache> -DOMStorageManager::PutCache(const nsACString& aOriginSuffix, - const nsACString& aOriginNoSuffix, - nsIPrincipal* aPrincipal) +already_AddRefed<StorageCache> +StorageManagerBase::PutCache(const nsACString& aOriginSuffix, + const nsACString& aOriginNoSuffix, + nsIPrincipal* aPrincipal) { CacheOriginHashtable* table = mCaches.LookupOrAdd(aOriginSuffix); - DOMStorageCacheHashKey* entry = table->PutEntry(aOriginNoSuffix); - RefPtr<DOMStorageCache> cache = entry->cache(); + StorageCacheHashKey* entry = table->PutEntry(aOriginNoSuffix); + RefPtr<StorageCache> cache = entry->cache(); nsAutoCString quotaOrigin; CreateQuotaDBKey(aPrincipal, quotaOrigin); switch (mType) { case SessionStorage: // Lifetime handled by the manager, don't persist entry->HardRef(); @@ -290,59 +293,59 @@ DOMStorageManager::PutCache(const nsACSt default: MOZ_ASSERT(false); } return cache.forget(); } void -DOMStorageManager::DropCache(DOMStorageCache* aCache) +StorageManagerBase::DropCache(StorageCache* aCache) { if (!NS_IsMainThread()) { - NS_WARNING("DOMStorageManager::DropCache called on a non-main thread, shutting down?"); + NS_WARNING("StorageManager::DropCache called on a non-main thread, shutting down?"); } CacheOriginHashtable* table = mCaches.LookupOrAdd(aCache->OriginSuffix()); table->RemoveEntry(aCache->OriginNoSuffix()); } nsresult -DOMStorageManager::GetStorageInternal(bool aCreate, - mozIDOMWindow* aWindow, - nsIPrincipal* aPrincipal, - const nsAString& aDocumentURI, - nsIDOMStorage** aRetval) +StorageManagerBase::GetStorageInternal(bool aCreate, + mozIDOMWindow* aWindow, + nsIPrincipal* aPrincipal, + const nsAString& aDocumentURI, + nsIDOMStorage** aRetval) { nsresult rv; nsAutoCString originAttrSuffix; aPrincipal->OriginAttributesRef().CreateSuffix(originAttrSuffix); nsAutoCString originKey; rv = AppendOriginNoSuffix(aPrincipal, originKey); if (NS_FAILED(rv)) { return NS_ERROR_NOT_AVAILABLE; } - RefPtr<DOMStorageCache> cache = GetCache(originAttrSuffix, originKey); + RefPtr<StorageCache> cache = GetCache(originAttrSuffix, originKey); // Get or create a cache for the given scope if (!cache) { if (!aCreate) { *aRetval = nullptr; return NS_OK; } if (!aRetval) { // This is a demand to just preload the cache, if the scope has // no data stored, bypass creation and preload of the cache. - DOMStorageDBBridge* db = DOMStorageCache::GetDatabase(); + StorageDBBridge* db = StorageCache::GetDatabase(); if (db) { - if (!db->ShouldPreloadOrigin(DOMStorageManager::CreateOrigin(originAttrSuffix, originKey))) { + if (!db->ShouldPreloadOrigin(StorageManagerBase::CreateOrigin(originAttrSuffix, originKey))) { return NS_OK; } } else { if (originKey.EqualsLiteral("knalb.:about")) { return NS_OK; } } } @@ -354,87 +357,87 @@ DOMStorageManager::GetStorageInternal(bo if (!cache->CheckPrincipal(aPrincipal)) { return NS_ERROR_DOM_SECURITY_ERR; } } if (aRetval) { nsCOMPtr<nsPIDOMWindowInner> inner = nsPIDOMWindowInner::From(aWindow); - nsCOMPtr<nsIDOMStorage> storage = new DOMStorage( + nsCOMPtr<nsIDOMStorage> storage = new Storage( inner, this, cache, aDocumentURI, aPrincipal); storage.forget(aRetval); } return NS_OK; } NS_IMETHODIMP -DOMStorageManager::PrecacheStorage(nsIPrincipal* aPrincipal) +StorageManagerBase::PrecacheStorage(nsIPrincipal* aPrincipal) { return GetStorageInternal(true, nullptr, aPrincipal, EmptyString(), nullptr); } NS_IMETHODIMP -DOMStorageManager::CreateStorage(mozIDOMWindow* aWindow, - nsIPrincipal* aPrincipal, - const nsAString& aDocumentURI, - nsIDOMStorage** aRetval) +StorageManagerBase::CreateStorage(mozIDOMWindow* aWindow, + nsIPrincipal* aPrincipal, + const nsAString& aDocumentURI, + nsIDOMStorage** aRetval) { return GetStorageInternal(true, aWindow, aPrincipal, aDocumentURI, aRetval); } NS_IMETHODIMP -DOMStorageManager::GetStorage(mozIDOMWindow* aWindow, - nsIPrincipal* aPrincipal, - nsIDOMStorage** aRetval) +StorageManagerBase::GetStorage(mozIDOMWindow* aWindow, + nsIPrincipal* aPrincipal, + nsIDOMStorage** aRetval) { return GetStorageInternal(false, aWindow, aPrincipal, EmptyString(), aRetval); } NS_IMETHODIMP -DOMStorageManager::CloneStorage(nsIDOMStorage* aStorage) +StorageManagerBase::CloneStorage(nsIDOMStorage* aStorage) { if (mType != SessionStorage) { // Cloning is supported only for sessionStorage return NS_ERROR_NOT_IMPLEMENTED; } - RefPtr<DOMStorage> storage = static_cast<DOMStorage*>(aStorage); + RefPtr<Storage> storage = static_cast<Storage*>(aStorage); if (!storage) { return NS_ERROR_UNEXPECTED; } - const DOMStorageCache* origCache = storage->GetCache(); + const StorageCache* origCache = storage->GetCache(); - DOMStorageCache* existingCache = GetCache(origCache->OriginSuffix(), - origCache->OriginNoSuffix()); + StorageCache* existingCache = GetCache(origCache->OriginSuffix(), + origCache->OriginNoSuffix()); if (existingCache) { // Do not replace an existing sessionStorage. return NS_ERROR_NOT_AVAILABLE; } // Since this manager is sessionStorage manager, PutCache hard references // the cache in our hashtable. - RefPtr<DOMStorageCache> newCache = PutCache(origCache->OriginSuffix(), - origCache->OriginNoSuffix(), - origCache->Principal()); + RefPtr<StorageCache> newCache = PutCache(origCache->OriginSuffix(), + origCache->OriginNoSuffix(), + origCache->Principal()); newCache->CloneFrom(origCache); return NS_OK; } NS_IMETHODIMP -DOMStorageManager::CheckStorage(nsIPrincipal* aPrincipal, - nsIDOMStorage* aStorage, - bool* aRetval) +StorageManagerBase::CheckStorage(nsIPrincipal* aPrincipal, + nsIDOMStorage* aStorage, + bool* aRetval) { nsresult rv; - RefPtr<DOMStorage> storage = static_cast<DOMStorage*>(aStorage); + RefPtr<Storage> storage = static_cast<Storage*>(aStorage); if (!storage) { return NS_ERROR_UNEXPECTED; } *aRetval = false; if (!aPrincipal) { return NS_ERROR_NOT_AVAILABLE; @@ -444,121 +447,121 @@ DOMStorageManager::CheckStorage(nsIPrinc aPrincipal->OriginAttributesRef().CreateSuffix(suffix); nsAutoCString origin; rv = AppendOriginNoSuffix(aPrincipal, origin); if (NS_FAILED(rv)) { return rv; } - DOMStorageCache* cache = GetCache(suffix, origin); + StorageCache* cache = GetCache(suffix, origin); if (cache != storage->GetCache()) { return NS_OK; } if (!storage->PrincipalEquals(aPrincipal)) { return NS_OK; } *aRetval = true; return NS_OK; } // Obsolete nsIDOMStorageManager methods NS_IMETHODIMP -DOMStorageManager::GetLocalStorageForPrincipal(nsIPrincipal* aPrincipal, - const nsAString& aDocumentURI, - nsIDOMStorage** aRetval) +StorageManagerBase::GetLocalStorageForPrincipal(nsIPrincipal* aPrincipal, + const nsAString& aDocumentURI, + nsIDOMStorage** aRetval) { if (mType != LocalStorage) { return NS_ERROR_UNEXPECTED; } return CreateStorage(nullptr, aPrincipal, aDocumentURI, aRetval); } void -DOMStorageManager::ClearCaches(uint32_t aUnloadFlags, - const OriginAttributesPattern& aPattern, - const nsACString& aOriginScope) +StorageManagerBase::ClearCaches(uint32_t aUnloadFlags, + const OriginAttributesPattern& aPattern, + const nsACString& aOriginScope) { for (auto iter1 = mCaches.Iter(); !iter1.Done(); iter1.Next()) { PrincipalOriginAttributes oa; DebugOnly<bool> rv = oa.PopulateFromSuffix(iter1.Key()); MOZ_ASSERT(rv); if (!aPattern.Matches(oa)) { // This table doesn't match the given origin attributes pattern continue; } CacheOriginHashtable* table = iter1.Data(); for (auto iter2 = table->Iter(); !iter2.Done(); iter2.Next()) { - DOMStorageCache* cache = iter2.Get()->cache(); + StorageCache* cache = iter2.Get()->cache(); if (aOriginScope.IsEmpty() || StringBeginsWith(cache->OriginNoSuffix(), aOriginScope)) { cache->UnloadItems(aUnloadFlags); } } } } nsresult -DOMStorageManager::Observe(const char* aTopic, - const nsAString& aOriginAttributesPattern, - const nsACString& aOriginScope) +StorageManagerBase::Observe(const char* aTopic, + const nsAString& aOriginAttributesPattern, + const nsACString& aOriginScope) { OriginAttributesPattern pattern; if (!pattern.Init(aOriginAttributesPattern)) { NS_ERROR("Cannot parse origin attributes pattern"); return NS_ERROR_FAILURE; } // Clear everything, caches + database if (!strcmp(aTopic, "cookie-cleared")) { - ClearCaches(DOMStorageCache::kUnloadComplete, pattern, EmptyCString()); + ClearCaches(StorageCache::kUnloadComplete, pattern, EmptyCString()); return NS_OK; } // Clear from caches everything that has been stored // while in session-only mode if (!strcmp(aTopic, "session-only-cleared")) { - ClearCaches(DOMStorageCache::kUnloadSession, pattern, aOriginScope); + ClearCaches(StorageCache::kUnloadSession, pattern, aOriginScope); return NS_OK; } // Clear everything (including so and pb data) from caches and database // for the gived domain and subdomains. if (!strcmp(aTopic, "domain-data-cleared")) { - ClearCaches(DOMStorageCache::kUnloadComplete, pattern, aOriginScope); + ClearCaches(StorageCache::kUnloadComplete, pattern, aOriginScope); return NS_OK; } // Clear all private-browsing caches if (!strcmp(aTopic, "private-browsing-data-cleared")) { - ClearCaches(DOMStorageCache::kUnloadPrivate, pattern, EmptyCString()); + ClearCaches(StorageCache::kUnloadPrivate, pattern, EmptyCString()); return NS_OK; } // Clear localStorage data beloging to an origin pattern if (!strcmp(aTopic, "origin-attr-pattern-cleared")) { // sessionStorage is expected to stay if (mType == SessionStorage) { return NS_OK; } - ClearCaches(DOMStorageCache::kUnloadComplete, pattern, EmptyCString()); + ClearCaches(StorageCache::kUnloadComplete, pattern, EmptyCString()); return NS_OK; } if (!strcmp(aTopic, "profile-change")) { // For case caches are still referenced - clear them completely - ClearCaches(DOMStorageCache::kUnloadComplete, pattern, EmptyCString()); + ClearCaches(StorageCache::kUnloadComplete, pattern, EmptyCString()); mCaches.Clear(); return NS_OK; } if (!strcmp(aTopic, "low-disk-space")) { if (mType == LocalStorage) { mLowDiskSpace = true; } @@ -576,17 +579,17 @@ DOMStorageManager::Observe(const char* a #ifdef DOM_STORAGE_TESTS if (!strcmp(aTopic, "test-reload")) { if (mType != LocalStorage) { return NS_OK; } // This immediately completely reloads all caches from the database. - ClearCaches(DOMStorageCache::kTestReload, pattern, EmptyCString()); + ClearCaches(StorageCache::kTestReload, pattern, EmptyCString()); return NS_OK; } if (!strcmp(aTopic, "test-flushed")) { if (!XRE_IsParentProcess()) { nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); if (obs) { obs->NotifyObservers(nullptr, "domstorage-test-flushed", nullptr); @@ -599,26 +602,26 @@ DOMStorageManager::Observe(const char* a NS_ERROR("Unexpected topic"); return NS_ERROR_UNEXPECTED; } // DOMLocalStorageManager DOMLocalStorageManager::DOMLocalStorageManager() - : DOMStorageManager(LocalStorage) + : StorageManagerBase(LocalStorage) { NS_ASSERTION(!sSelf, "Somebody is trying to do_CreateInstance(\"@mozilla/dom/localStorage-manager;1\""); sSelf = this; if (!XRE_IsParentProcess()) { // Do this only on the child process. The thread IPC bridge // is also used to communicate chrome observer notifications. // Note: must be called after we set sSelf - DOMStorageCache::StartDatabase(); + StorageCache::StartDatabase(); } } DOMLocalStorageManager::~DOMLocalStorageManager() { sSelf = nullptr; } @@ -635,19 +638,19 @@ DOMLocalStorageManager::Ensure() MOZ_ASSERT(sSelf, "Didn't initialize?"); return sSelf; } // DOMSessionStorageManager DOMSessionStorageManager::DOMSessionStorageManager() - : DOMStorageManager(SessionStorage) + : StorageManagerBase(SessionStorage) { if (!XRE_IsParentProcess()) { // Do this only on the child process. The thread IPC bridge // is also used to communicate chrome observer notifications. - DOMStorageCache::StartDatabase(); + StorageCache::StartDatabase(); } } } // namespace dom } // namespace mozilla
rename from dom/storage/DOMStorageManager.h rename to dom/storage/StorageManager.h --- a/dom/storage/DOMStorageManager.h +++ b/dom/storage/StorageManager.h @@ -1,154 +1,156 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* 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 nsDOMStorageManager_h__ -#define nsDOMStorageManager_h__ +#ifndef mozilla_dom_StorageManager_h +#define mozilla_dom_StorageManager_h #include "nsIDOMStorageManager.h" -#include "DOMStorageObserver.h" +#include "StorageObserver.h" -#include "DOMStorageCache.h" -#include "mozilla/dom/DOMStorage.h" +#include "StorageCache.h" +#include "mozilla/dom/Storage.h" #include "nsTHashtable.h" #include "nsDataHashtable.h" #include "nsClassHashtable.h" #include "nsHashKeys.h" namespace mozilla { class OriginAttributesPattern; namespace dom { -const DOMStorage::StorageType SessionStorage = DOMStorage::SessionStorage; -const DOMStorage::StorageType LocalStorage = DOMStorage::LocalStorage; +const Storage::StorageType SessionStorage = Storage::SessionStorage; +const Storage::StorageType LocalStorage = Storage::LocalStorage; -class DOMStorageManager : public nsIDOMStorageManager - , public DOMStorageObserverSink +class StorageManagerBase : public nsIDOMStorageManager + , public StorageObserverSink { NS_DECL_ISUPPORTS NS_DECL_NSIDOMSTORAGEMANAGER public: - virtual DOMStorage::StorageType Type() { return mType; } + virtual Storage::StorageType Type() { return mType; } // Reads the preference for DOM storage quota static uint32_t GetQuota(); // Gets (but not ensures) cache for the given scope - DOMStorageCache* GetCache(const nsACString& aOriginSuffix, const nsACString& aOriginNoSuffix); + StorageCache* GetCache(const nsACString& aOriginSuffix, + const nsACString& aOriginNoSuffix); // Returns object keeping usage cache for the scope. - already_AddRefed<DOMStorageUsage> GetOriginUsage(const nsACString& aOriginNoSuffix); + already_AddRefed<StorageUsage> GetOriginUsage(const nsACString& aOriginNoSuffix); - static nsCString CreateOrigin(const nsACString& aOriginSuffix, const nsACString& aOriginNoSuffix); + static nsCString CreateOrigin(const nsACString& aOriginSuffix, + const nsACString& aOriginNoSuffix); protected: - explicit DOMStorageManager(DOMStorage::StorageType aType); - virtual ~DOMStorageManager(); + explicit StorageManagerBase(Storage::StorageType aType); + virtual ~StorageManagerBase(); private: - // DOMStorageObserverSink, handler to various chrome clearing notification + // StorageObserverSink, handler to various chrome clearing notification virtual nsresult Observe(const char* aTopic, const nsAString& aOriginAttributesPattern, const nsACString& aOriginScope) override; // Since nsTHashtable doesn't like multiple inheritance, we have to aggregate - // DOMStorageCache into the entry. - class DOMStorageCacheHashKey : public nsCStringHashKey + // StorageCache into the entry. + class StorageCacheHashKey : public nsCStringHashKey { public: - explicit DOMStorageCacheHashKey(const nsACString* aKey) + explicit StorageCacheHashKey(const nsACString* aKey) : nsCStringHashKey(aKey) - , mCache(new DOMStorageCache(aKey)) + , mCache(new StorageCache(aKey)) {} - DOMStorageCacheHashKey(const DOMStorageCacheHashKey& aOther) + StorageCacheHashKey(const StorageCacheHashKey& aOther) : nsCStringHashKey(aOther) { NS_ERROR("Shouldn't be called"); } - DOMStorageCache* cache() { return mCache; } + StorageCache* cache() { return mCache; } // Keep the cache referenced forever, used for sessionStorage. void HardRef() { mCacheRef = mCache; } private: // weak ref only since cache references its manager. - DOMStorageCache* mCache; + StorageCache* mCache; // hard ref when this is sessionStorage to keep it alive forever. - RefPtr<DOMStorageCache> mCacheRef; + RefPtr<StorageCache> mCacheRef; }; - // Ensures cache for a scope, when it doesn't exist it is created and initalized, - // this also starts preload of persistent data. - already_AddRefed<DOMStorageCache> PutCache(const nsACString& aOriginSuffix, - const nsACString& aOriginNoSuffix, - nsIPrincipal* aPrincipal); + // Ensures cache for a scope, when it doesn't exist it is created and + // initalized, this also starts preload of persistent data. + already_AddRefed<StorageCache> PutCache(const nsACString& aOriginSuffix, + const nsACString& aOriginNoSuffix, + nsIPrincipal* aPrincipal); // Helper for creation of DOM storage objects nsresult GetStorageInternal(bool aCreate, mozIDOMWindow* aWindow, nsIPrincipal* aPrincipal, const nsAString& aDocumentURI, nsIDOMStorage** aRetval); // Suffix->origin->cache map - typedef nsTHashtable<DOMStorageCacheHashKey> CacheOriginHashtable; + typedef nsTHashtable<StorageCacheHashKey> CacheOriginHashtable; nsClassHashtable<nsCStringHashKey, CacheOriginHashtable> mCaches; - const DOMStorage::StorageType mType; + const Storage::StorageType mType; // If mLowDiskSpace is true it indicates a low device storage situation and // so no localStorage writes are allowed. sessionStorage writes are still // allowed. bool mLowDiskSpace; bool IsLowDiskSpace() const { return mLowDiskSpace; }; void ClearCaches(uint32_t aUnloadFlags, const OriginAttributesPattern& aPattern, const nsACString& aKeyPrefix); protected: // Keeps usage cache objects for eTLD+1 scopes we have touched. - nsDataHashtable<nsCStringHashKey, RefPtr<DOMStorageUsage> > mUsages; + nsDataHashtable<nsCStringHashKey, RefPtr<StorageUsage> > mUsages; - friend class DOMStorageCache; - // Releases cache since it is no longer referrered by any DOMStorage object. - virtual void DropCache(DOMStorageCache* aCache); + friend class StorageCache; + // Releases cache since it is no longer referrered by any Storage object. + virtual void DropCache(StorageCache* aCache); }; // Derived classes to allow two different contract ids, one for localStorage and // one for sessionStorage management. localStorage manager is used as service -// scoped to the application while sessionStorage managers are instantiated by each -// top doc shell in the application since sessionStorages are isolated per top level -// browsing context. The code may easily by shared by both. +// scoped to the application while sessionStorage managers are instantiated by +// each top doc shell in the application since sessionStorages are isolated per +// top level browsing context. The code may easily by shared by both. -class DOMLocalStorageManager final : public DOMStorageManager +class DOMLocalStorageManager final : public StorageManagerBase { public: DOMLocalStorageManager(); virtual ~DOMLocalStorageManager(); // Global getter of localStorage manager service static DOMLocalStorageManager* Self() { return sSelf; } // Like Self, but creates an instance if we're not yet initialized. static DOMLocalStorageManager* Ensure(); private: static DOMLocalStorageManager* sSelf; }; -class DOMSessionStorageManager final : public DOMStorageManager +class DOMSessionStorageManager final : public StorageManagerBase { public: DOMSessionStorageManager(); }; } // namespace dom } // namespace mozilla -#endif /* nsDOMStorageManager_h__ */ +#endif // mozilla_dom_StorageManager_h
rename from dom/storage/DOMStorageObserver.cpp rename to dom/storage/StorageObserver.cpp --- a/dom/storage/DOMStorageObserver.cpp +++ b/dom/storage/StorageObserver.cpp @@ -1,18 +1,18 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* 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/. */ -#include "DOMStorageObserver.h" +#include "StorageObserver.h" -#include "DOMStorageDBThread.h" -#include "DOMStorageCache.h" +#include "StorageDBThread.h" +#include "StorageCache.h" #include "mozilla/BasePrincipal.h" #include "nsIObserverService.h" #include "nsIURI.h" #include "nsIURL.h" #include "nsIScriptSecurityManager.h" #include "nsIPermission.h" #include "nsIIDNService.h" @@ -29,39 +29,39 @@ namespace mozilla { namespace dom { static const char kStartupTopic[] = "sessionstore-windows-restored"; static const uint32_t kStartupDelay = 0; const char kTestingPref[] = "dom.storage.testing"; -NS_IMPL_ISUPPORTS(DOMStorageObserver, +NS_IMPL_ISUPPORTS(StorageObserver, nsIObserver, nsISupportsWeakReference) -DOMStorageObserver* DOMStorageObserver::sSelf = nullptr; +StorageObserver* StorageObserver::sSelf = nullptr; extern nsresult CreateReversedDomain(const nsACString& aAsciiDomain, nsACString& aKey); // static nsresult -DOMStorageObserver::Init() +StorageObserver::Init() { if (sSelf) { return NS_OK; } nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); if (!obs) { return NS_ERROR_UNEXPECTED; } - sSelf = new DOMStorageObserver(); + sSelf = new StorageObserver(); NS_ADDREF(sSelf); // Chrome clear operations. obs->AddObserver(sSelf, kStartupTopic, true); obs->AddObserver(sSelf, "cookie-changed", true); obs->AddObserver(sSelf, "perm-changed", true); obs->AddObserver(sSelf, "browser:purge-domain-data", true); obs->AddObserver(sSelf, "last-pb-context-exited", true); @@ -80,29 +80,29 @@ DOMStorageObserver::Init() Preferences::RegisterCallbackAndCall(TestingPrefChanged, kTestingPref); #endif return NS_OK; } // static nsresult -DOMStorageObserver::Shutdown() +StorageObserver::Shutdown() { if (!sSelf) { return NS_ERROR_NOT_INITIALIZED; } NS_RELEASE(sSelf); return NS_OK; } // static void -DOMStorageObserver::TestingPrefChanged(const char* aPrefName, void* aClosure) +StorageObserver::TestingPrefChanged(const char* aPrefName, void* aClosure) { nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); if (!obs) { return; } if (Preferences::GetBool(kTestingPref)) { obs->AddObserver(sSelf, "domstorage-test-flush-force", true); @@ -117,42 +117,42 @@ DOMStorageObserver::TestingPrefChanged(c // Only to forward to child process. obs->RemoveObserver(sSelf, "domstorage-test-flushed"); } obs->RemoveObserver(sSelf, "domstorage-test-reload"); } } void -DOMStorageObserver::AddSink(DOMStorageObserverSink* aObs) +StorageObserver::AddSink(StorageObserverSink* aObs) { mSinks.AppendElement(aObs); } void -DOMStorageObserver::RemoveSink(DOMStorageObserverSink* aObs) +StorageObserver::RemoveSink(StorageObserverSink* aObs) { mSinks.RemoveElement(aObs); } void -DOMStorageObserver::Notify(const char* aTopic, - const nsAString& aOriginAttributesPattern, - const nsACString& aOriginScope) +StorageObserver::Notify(const char* aTopic, + const nsAString& aOriginAttributesPattern, + const nsACString& aOriginScope) { for (uint32_t i = 0; i < mSinks.Length(); ++i) { - DOMStorageObserverSink* sink = mSinks[i]; + StorageObserverSink* sink = mSinks[i]; sink->Observe(aTopic, aOriginAttributesPattern, aOriginScope); } } NS_IMETHODIMP -DOMStorageObserver::Observe(nsISupports* aSubject, - const char* aTopic, - const char16_t* aData) +StorageObserver::Observe(nsISupports* aSubject, + const char* aTopic, + const char16_t* aData) { nsresult rv; // Start the thread that opens the database. if (!strcmp(aTopic, kStartupTopic)) { nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); obs->RemoveObserver(this, kStartupTopic); @@ -171,30 +171,30 @@ DOMStorageObserver::Observe(nsISupports* nsCOMPtr<nsITimer> timer = do_QueryInterface(aSubject); if (!timer) { return NS_ERROR_UNEXPECTED; } if (timer == mDBThreadStartDelayTimer) { mDBThreadStartDelayTimer = nullptr; - DOMStorageDBBridge* db = DOMStorageCache::StartDatabase(); + StorageDBBridge* db = StorageCache::StartDatabase(); NS_ENSURE_TRUE(db, NS_ERROR_FAILURE); } return NS_OK; } // Clear everything, caches + database if (!strcmp(aTopic, "cookie-changed")) { if (!NS_LITERAL_STRING("cleared").Equals(aData)) { return NS_OK; } - DOMStorageDBBridge* db = DOMStorageCache::StartDatabase(); + StorageDBBridge* db = StorageCache::StartDatabase(); NS_ENSURE_TRUE(db, NS_ERROR_FAILURE); db->AsyncClearAll(); Notify("cookie-cleared"); return NS_OK; } @@ -241,42 +241,44 @@ DOMStorageObserver::Observe(nsISupports* if (host.IsEmpty()) { return NS_OK; } nsAutoCString originScope; rv = CreateReversedDomain(host, originScope); NS_ENSURE_SUCCESS(rv, rv); - Notify("session-only-cleared", NS_ConvertUTF8toUTF16(originSuffix), originScope); + Notify("session-only-cleared", NS_ConvertUTF8toUTF16(originSuffix), + originScope); return NS_OK; } // Clear everything (including so and pb data) from caches and database // for the gived domain and subdomains. if (!strcmp(aTopic, "browser:purge-domain-data")) { // Convert the domain name to the ACE format nsAutoCString aceDomain; nsCOMPtr<nsIIDNService> converter = do_GetService(NS_IDNSERVICE_CONTRACTID); if (converter) { rv = converter->ConvertUTF8toACE(NS_ConvertUTF16toUTF8(aData), aceDomain); NS_ENSURE_SUCCESS(rv, rv); } else { - // In case the IDN service is not available, this is the best we can come up with! + // In case the IDN service is not available, this is the best we can come + // up with! NS_EscapeURL(NS_ConvertUTF16toUTF8(aData), esc_OnlyNonASCII | esc_AlwaysCopy, aceDomain); } nsAutoCString originScope; rv = CreateReversedDomain(aceDomain, originScope); NS_ENSURE_SUCCESS(rv, rv); - DOMStorageDBBridge* db = DOMStorageCache::StartDatabase(); + StorageDBBridge* db = StorageCache::StartDatabase(); NS_ENSURE_TRUE(db, NS_ERROR_FAILURE); db->AsyncClearMatchingOrigin(originScope); Notify("domain-data-cleared", EmptyString(), originScope); return NS_OK; } @@ -291,17 +293,17 @@ DOMStorageObserver::Observe(nsISupports* // Clear data of the origins whose prefixes will match the suffix. if (!strcmp(aTopic, "clear-origin-attributes-data")) { OriginAttributesPattern pattern; if (!pattern.Init(nsDependentString(aData))) { NS_ERROR("Cannot parse origin attributes pattern"); return NS_ERROR_FAILURE; } - DOMStorageDBBridge* db = DOMStorageCache::StartDatabase(); + StorageDBBridge* db = StorageCache::StartDatabase(); NS_ENSURE_TRUE(db, NS_ERROR_FAILURE); db->AsyncClearMatchingOriginAttributes(pattern); Notify("origin-attr-pattern-cleared", nsDependentString(aData)); return NS_OK; } @@ -309,19 +311,19 @@ DOMStorageObserver::Observe(nsISupports* if (!strcmp(aTopic, "profile-after-change")) { Notify("profile-change"); return NS_OK; } if (!strcmp(aTopic, "profile-before-change") || !strcmp(aTopic, "xpcom-shutdown")) { - rv = DOMStorageCache::StopDatabase(); + rv = StorageCache::StopDatabase(); if (NS_FAILED(rv)) { - NS_WARNING("Error while stopping DOMStorage DB background thread"); + NS_WARNING("Error while stopping Storage DB background thread"); } return NS_OK; } if (!strcmp(aTopic, "disk-space-watcher")) { if (NS_LITERAL_STRING("full").Equals(aData)) { Notify("low-disk-space"); @@ -329,17 +331,17 @@ DOMStorageObserver::Observe(nsISupports* Notify("no-low-disk-space"); } return NS_OK; } #ifdef DOM_STORAGE_TESTS if (!strcmp(aTopic, "domstorage-test-flush-force")) { - DOMStorageDBBridge* db = DOMStorageCache::GetDatabase(); + StorageDBBridge* db = StorageCache::GetDatabase(); if (db) { db->AsyncFlush(); } return NS_OK; } if (!strcmp(aTopic, "domstorage-test-flushed")) {
rename from dom/storage/DOMStorageObserver.h rename to dom/storage/StorageObserver.h --- a/dom/storage/DOMStorageObserver.h +++ b/dom/storage/StorageObserver.h @@ -1,69 +1,69 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* 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 nsIDOMStorageObserver_h__ -#define nsIDOMStorageObserver_h__ +#ifndef mozilla_dom_StorageObserver_h +#define mozilla_dom_StorageObserver_h #include "nsIObserver.h" #include "nsITimer.h" #include "nsWeakReference.h" #include "nsTArray.h" #include "nsString.h" namespace mozilla { namespace dom { -class DOMStorageObserver; +class StorageObserver; -// Implementers are DOMStorageManager and DOMStorageDBParent to forward to +// Implementers are StorageManager and StorageDBParent to forward to // child processes. -class DOMStorageObserverSink +class StorageObserverSink { public: - virtual ~DOMStorageObserverSink() {} + virtual ~StorageObserverSink() {} private: - friend class DOMStorageObserver; + friend class StorageObserver; virtual nsresult Observe(const char* aTopic, const nsAString& aOriginAttributesPattern, const nsACString& aOriginScope) = 0; }; -// Statically (though layout statics) initialized observer receiving and processing -// chrome clearing notifications, such as cookie deletion etc. -class DOMStorageObserver : public nsIObserver - , public nsSupportsWeakReference +// Statically (through layout statics) initialized observer receiving and +// processing chrome clearing notifications, such as cookie deletion etc. +class StorageObserver : public nsIObserver + , public nsSupportsWeakReference { public: NS_DECL_ISUPPORTS NS_DECL_NSIOBSERVER static nsresult Init(); static nsresult Shutdown(); - static DOMStorageObserver* Self() { return sSelf; } + static StorageObserver* Self() { return sSelf; } - void AddSink(DOMStorageObserverSink* aObs); - void RemoveSink(DOMStorageObserverSink* aObs); + void AddSink(StorageObserverSink* aObs); + void RemoveSink(StorageObserverSink* aObs); void Notify(const char* aTopic, const nsAString& aOriginAttributesPattern = EmptyString(), const nsACString& aOriginScope = EmptyCString()); private: - virtual ~DOMStorageObserver() {} + virtual ~StorageObserver() {} static void TestingPrefChanged(const char* aPrefName, void* aClosure); - static DOMStorageObserver* sSelf; + static StorageObserver* sSelf; // Weak references - nsTArray<DOMStorageObserverSink*> mSinks; + nsTArray<StorageObserverSink*> mSinks; nsCOMPtr<nsITimer> mDBThreadStartDelayTimer; }; } // namespace dom } // namespace mozilla -#endif +#endif // mozilla_dom_StorageObserver_h
--- a/dom/storage/moz.build +++ b/dom/storage/moz.build @@ -1,27 +1,27 @@ # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- # vim: set filetype=python: # 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/. EXPORTS.mozilla.dom += [ - 'DOMStorage.h', - 'DOMStorageIPC.h', + 'Storage.h', + 'StorageIPC.h', ] UNIFIED_SOURCES += [ - 'DOMStorage.cpp', - 'DOMStorageCache.cpp', - 'DOMStorageDBThread.cpp', - 'DOMStorageDBUpdater.cpp', - 'DOMStorageIPC.cpp', - 'DOMStorageManager.cpp', - 'DOMStorageObserver.cpp', + 'Storage.cpp', + 'StorageCache.cpp', + 'StorageDBThread.cpp', + 'StorageDBUpdater.cpp', + 'StorageIPC.cpp', + 'StorageManager.cpp', + 'StorageObserver.cpp', ] IPDL_SOURCES += [ 'PStorage.ipdl', ] include('/ipc/chromium/chromium-config.mozbuild')
--- a/embedding/components/windowwatcher/nsWindowWatcher.cpp +++ b/embedding/components/windowwatcher/nsWindowWatcher.cpp @@ -57,17 +57,17 @@ #include "nsFocusManager.h" #include "nsIPresShell.h" #include "nsPresContext.h" #include "nsContentUtils.h" #include "nsIPrefBranch.h" #include "nsIPrefService.h" #include "nsSandboxFlags.h" #include "mozilla/Preferences.h" -#include "mozilla/dom/DOMStorage.h" +#include "mozilla/dom/Storage.h" #include "mozilla/dom/ScriptSettings.h" #include "mozilla/dom/TabParent.h" #include "mozilla/dom/DocGroup.h" #include "mozilla/dom/TabGroup.h" #include "nsIXULWindow.h" #include "nsIXULBrowserWindow.h" #include "nsGlobalWindow.h"
--- a/gfx/2d/2D.h +++ b/gfx/2d/2D.h @@ -37,16 +37,19 @@ struct _cairo_surface; typedef _cairo_surface cairo_surface_t; struct _cairo_scaled_font; typedef _cairo_scaled_font cairo_scaled_font_t; struct _FcPattern; typedef _FcPattern FcPattern; +struct FT_LibraryRec_; +typedef FT_LibraryRec_* FT_Library; + struct ID3D11Texture2D; struct ID3D11Device; struct ID2D1Device; struct IDWriteFactory; struct IDWriteRenderingParams; struct IDWriteFontFace; class GrContext; @@ -671,18 +674,19 @@ struct GlyphMetrics * the font used for the drawing call. */ class ScaledFont : public external::AtomicRefCounted<ScaledFont> { public: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFont) virtual ~ScaledFont() {} - typedef void (*FontFileDataOutput)(const uint8_t *aData, uint32_t aLength, uint32_t aIndex, Float aGlyphSize, void *aBaton); - typedef void (*FontDescriptorOutput)(const uint8_t *aData, uint32_t aLength, Float aFontSize, void *aBaton); + typedef void (*FontFileDataOutput)(const uint8_t* aData, uint32_t aLength, uint32_t aIndex, Float aGlyphSize, void* aBaton); + typedef void (*FontInstanceDataOutput)(const uint8_t* aData, uint32_t aLength, void* aBaton); + typedef void (*FontDescriptorOutput)(const uint8_t* aData, uint32_t aLength, Float aFontSize, void* aBaton); virtual FontType GetType() const = 0; virtual AntialiasMode GetDefaultAAMode() { if (gfxPrefs::DisableAllTextAA()) { return AntialiasMode::NONE; } return AntialiasMode::DEFAULT; @@ -703,16 +707,18 @@ public: virtual void CopyGlyphsToBuilder(const GlyphBuffer &aBuffer, PathBuilder *aBuilder, const Matrix *aTransformHint = nullptr) = 0; /* This gets the metrics of a set of glyphs for the current font face. */ virtual void GetGlyphDesignMetrics(const uint16_t* aGlyphIndices, uint32_t aNumGlyphs, GlyphMetrics* aGlyphMetrics) = 0; virtual bool GetFontFileData(FontFileDataOutput, void *) { return false; } + virtual bool GetFontInstanceData(FontInstanceDataOutput, void *) { return false; } + virtual bool GetFontDescriptor(FontDescriptorOutput, void *) { return false; } void AddUserData(UserDataKey *key, void *userData, void (*destroy)(void*)) { mUserData.Add(key, userData, destroy); } void *GetUserData(UserDataKey *key) { return mUserData.Get(key); } @@ -733,20 +739,23 @@ public: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(NativeFontResource) /** * Creates a ScaledFont using the font corresponding to the index and * the given glyph size. * * @param aIndex index for the font within the resource. * @param aGlyphSize the size of ScaledFont required. + * @param aInstanceData pointer to read-only buffer of any available instance data. + * @param aInstanceDataLength the size of the instance data. * @return an already_addrefed ScaledFont, containing nullptr if failed. */ virtual already_AddRefed<ScaledFont> - CreateScaledFont(uint32_t aIndex, Float aGlyphSize) = 0; + CreateScaledFont(uint32_t aIndex, Float aGlyphSize, + const uint8_t* aInstanceData, uint32_t aInstanceDataLength) = 0; virtual ~NativeFontResource() {}; }; /** This class is designed to allow passing additional glyph rendering * parameters to the glyph drawing functions. This is an empty wrapper class * merely used to allow holding on to and passing around platform specific * parameters. This is because different platforms have unique rendering @@ -1391,16 +1400,23 @@ public: * @param aSize Size of the TrueType data * @param aType Type of NativeFontResource that should be created. * @return a NativeFontResource of nullptr if failed. */ static already_AddRefed<NativeFontResource> CreateNativeFontResource(uint8_t *aData, uint32_t aSize, FontType aType); /** + * This creates a scaled font of the given type based on font descriptor + * data retrieved from ScaledFont::GetFontDescriptor. + */ + static already_AddRefed<ScaledFont> + CreateScaledFontFromFontDescriptor(FontType aType, const uint8_t* aData, uint32_t aDataLength, Float aSize); + + /** * This creates a scaled font with an associated cairo_scaled_font_t, and * must be used when using the Cairo backend. The NativeFont and * cairo_scaled_font_t* parameters must correspond to the same font. */ static already_AddRefed<ScaledFont> CreateScaledFontWithCairo(const NativeFont &aNativeFont, Float aSize, cairo_scaled_font_t* aScaledFont); /** @@ -1489,16 +1505,25 @@ public: static already_AddRefed<DrawTarget> CreateDrawTargetWithSkCanvas(SkCanvas* aCanvas); #endif #ifdef XP_DARWIN static already_AddRefed<GlyphRenderingOptions> CreateCGGlyphRenderingOptions(const Color &aFontSmoothingBackgroundColor); #endif +#ifdef MOZ_ENABLE_FREETYPE + static void SetFTLibrary(FT_Library aFTLibrary); + static FT_Library GetFTLibrary(); + +private: + static FT_Library mFTLibrary; +public: +#endif + #ifdef WIN32 static already_AddRefed<DrawTarget> CreateDrawTargetForD3D11Texture(ID3D11Texture2D *aTexture, SurfaceFormat aFormat); /* * Attempts to create and install a D2D1 device from the supplied Direct3D11 device. * Returns true on success, or false on failure and leaves the D2D1/Direct3D11 devices unset. */ static bool SetDirect3D11Device(ID3D11Device *aDevice);
--- a/gfx/2d/DrawTargetSkia.cpp +++ b/gfx/2d/DrawTargetSkia.cpp @@ -1582,21 +1582,21 @@ DrawTargetSkia::CreateSimilarDrawTarget( if (target->InitWithGrContext(mGrContext.get(), aSize, aFormat, true)) { return target.forget(); } // Otherwise, just fall back to a software draw target. } #endif #ifdef DEBUG - // Check that our SkCanvas isn't backed by vector storage such as PDF. If it - // is then we want similar storage to avoid losing fidelity (if and when this - // DrawTarget is Snapshot()'ed, drawning a raster back into this DrawTarget - // will lose fidelity). - if (mCanvas->imageInfo().colorType() == kUnknown_SkColorType) { + if (!IsBackedByPixels(mCanvas.get())) { + // If our canvas is backed by vector storage such as PDF then we want to + // create a new DrawTarget with similar storage to avoid losing fidelity + // (fidelity will be lost if the returned DT is Snapshot()'ed and drawn + // back onto us since a raster will be drawn instead of vector commands). NS_WARNING("Not backed by pixels - we need to handle PDF backed SkCanvas"); } #endif if (!target->Init(aSize, aFormat)) { return nullptr; } return target.forget(); @@ -1788,19 +1788,17 @@ bool DrawTargetSkia::Init(SkCanvas* aCanvas) { mCanvas = sk_ref_sp(aCanvas); SkImageInfo imageInfo = mCanvas->imageInfo(); // If the canvas is backed by pixels we clear it to be on the safe side. If // it's not (for example, for PDF output) we don't. - bool isBackedByPixels = imageInfo.colorType() != kUnknown_SkColorType; - if (isBackedByPixels) { - // Note for PDF backed SkCanvas |alphaType == kUnknown_SkAlphaType|. + if (IsBackedByPixels(mCanvas.get())) { SkColor clearColor = imageInfo.isOpaque() ? SK_ColorBLACK : SK_ColorTRANSPARENT; mCanvas->clear(clearColor); } SkISize size = mCanvas->getBaseLayerSize(); mSize.width = size.width(); mSize.height = size.height(); mFormat = SkiaColorTypeToGfxFormat(imageInfo.colorType(),
--- a/gfx/2d/Factory.cpp +++ b/gfx/2d/Factory.cpp @@ -27,16 +27,17 @@ #ifdef XP_DARWIN #include "ScaledFontMac.h" #include "NativeFontResourceMac.h" #endif #ifdef MOZ_WIDGET_GTK #include "ScaledFontFontconfig.h" +#include "NativeFontResourceFontconfig.h" #endif #ifdef WIN32 #include "DrawTargetD2D1.h" #include "ScaledFontDWrite.h" #include "NativeFontResourceDWrite.h" #include <d3d10_1.h> #include "HelpersD2D.h" @@ -151,16 +152,20 @@ HasCPUIDBit(unsigned int level, CPUIDReg #endif namespace mozilla { namespace gfx { // In Gecko, this value is managed by gfx.logging.level in gfxPrefs. int32_t LoggingPrefs::sGfxLogLevel = LOG_DEFAULT; +#ifdef MOZ_ENABLE_FREETYPE +FT_Library Factory::mFTLibrary = nullptr; +#endif + #ifdef WIN32 ID3D11Device *Factory::mD3D11Device = nullptr; ID2D1Device *Factory::mD2D1Device = nullptr; IDWriteFactory *Factory::mDWriteFactory = nullptr; #endif DrawEventRecorder *Factory::mRecorder; @@ -187,16 +192,22 @@ Factory::Init(const Config& aConfig) void Factory::ShutDown() { if (sConfig) { delete sConfig->mLogForwarder; delete sConfig; sConfig = nullptr; } + +#ifdef MOZ_ENABLE_FREETYPE + if (mFTLibrary) { + mFTLibrary = nullptr; + } +#endif } bool Factory::HasSSE2() { #if defined(__SSE2__) || defined(_M_X64) || \ (defined(_M_IX86_FP) && _M_IX86_FP >= 2) // gcc with -msse2 (default on OSX and x86-64) @@ -509,30 +520,50 @@ Factory::CreateNativeFontResource(uint8_ #ifdef WIN32 if (GetDWriteFactory()) { return NativeFontResourceDWrite::Create(aData, aSize, /* aNeedsCairo = */ true); } else { return NativeFontResourceGDI::Create(aData, aSize, /* aNeedsCairo = */ true); } -#elif XP_DARWIN +#elif defined(XP_DARWIN) return NativeFontResourceMac::Create(aData, aSize); +#elif defined(MOZ_WIDGET_GTK) + return NativeFontResourceFontconfig::Create(aData, aSize); #else gfxWarning() << "Unable to create cairo scaled font from truetype data"; return nullptr; #endif } default: gfxWarning() << "Unable to create requested font resource from truetype data"; return nullptr; } } already_AddRefed<ScaledFont> +Factory::CreateScaledFontFromFontDescriptor(FontType aType, const uint8_t* aData, uint32_t aDataLength, Float aSize) +{ + switch (aType) { +#ifdef WIN32 + case FontType::GDI: + return ScaledFontWin::CreateFromFontDescriptor(aData, aDataLength, aSize); +#endif +#ifdef MOZ_WIDGET_GTK + case FontType::FONTCONFIG: + return ScaledFontFontconfig::CreateFromFontDescriptor(aData, aDataLength, aSize); +#endif + default: + gfxWarning() << "Invalid type specified for ScaledFont font descriptor"; + return nullptr; + } +} + +already_AddRefed<ScaledFont> Factory::CreateScaledFontWithCairo(const NativeFont& aNativeFont, Float aSize, cairo_scaled_font_t* aScaledFont) { #ifdef USE_CAIRO // In theory, we could pull the NativeFont out of the cairo_scaled_font_t*, // but that would require a lot of code that would be otherwise repeated in // various backends. // Therefore, we just reuse CreateScaledFontForNativeFont's implementation. RefPtr<ScaledFont> font = CreateScaledFontForNativeFont(aNativeFont, aSize); @@ -564,16 +595,31 @@ Factory::CreateDualDrawTarget(DrawTarget if (mRecorder) { retVal = new DrawTargetRecording(mRecorder, retVal); } return retVal.forget(); } +#ifdef MOZ_ENABLE_FREETYPE +void +Factory::SetFTLibrary(FT_Library aFTLibrary) +{ + mFTLibrary = aFTLibrary; +} + +FT_Library +Factory::GetFTLibrary() +{ + MOZ_ASSERT(mFTLibrary); + return mFTLibrary; +} +#endif + #ifdef WIN32 already_AddRefed<DrawTarget> Factory::CreateDrawTargetForD3D11Texture(ID3D11Texture2D *aTexture, SurfaceFormat aFormat) { MOZ_ASSERT(aTexture); RefPtr<DrawTargetD2D1> newTarget;
--- a/gfx/2d/HelpersSkia.h +++ b/gfx/2d/HelpersSkia.h @@ -366,12 +366,31 @@ static inline FillRule GetFillRule(SkPat default: NS_WARNING("Unsupported fill type\n"); break; } return FillRule::FILL_EVEN_ODD; } +/** + * Returns true if the canvas is backed by pixels. Returns false if the canvas + * wraps an SkPDFDocument, for example. + * + * Note: It is not clear whether the test used to implement this function may + * result in it returning false in some circumstances even when the canvas + * _is_ pixel backed. In other words maybe it is possible for such a canvas to + * have kUnknown_SkPixelGeometry? + */ +static inline bool IsBackedByPixels(const SkCanvas* aCanvas) +{ + SkSurfaceProps props(0, kUnknown_SkPixelGeometry); + if (!aCanvas->getProps(&props) || + props.pixelGeometry() == kUnknown_SkPixelGeometry) { + return false; + } + return true; +} + } // namespace gfx } // namespace mozilla #endif /* MOZILLA_GFX_HELPERSSKIA_H_ */
--- a/gfx/2d/NativeFontResourceDWrite.cpp +++ b/gfx/2d/NativeFontResourceDWrite.cpp @@ -254,17 +254,18 @@ NativeFontResourceDWrite::Create(uint8_t RefPtr<NativeFontResourceDWrite> fontResource = new NativeFontResourceDWrite(factory, fontFile.forget(), faceType, numberOfFaces, aNeedsCairo); return fontResource.forget(); } already_AddRefed<ScaledFont> -NativeFontResourceDWrite::CreateScaledFont(uint32_t aIndex, Float aGlyphSize) +NativeFontResourceDWrite::CreateScaledFont(uint32_t aIndex, Float aGlyphSize, + const uint8_t* aInstanceData, uint32_t aInstanceDataLength) { if (aIndex >= mNumberOfFaces) { gfxWarning() << "Font face index is too high for font resource."; return nullptr; } IDWriteFontFile *fontFile = mFontFile; RefPtr<IDWriteFontFace> fontFace;
--- a/gfx/2d/NativeFontResourceDWrite.h +++ b/gfx/2d/NativeFontResourceDWrite.h @@ -27,17 +27,18 @@ public: * @param aDataLength length of data. * @param aNeedsCairo whether the ScaledFont created needs a cairo scaled font * @return Referenced NativeFontResourceDWrite or nullptr if invalid. */ static already_AddRefed<NativeFontResourceDWrite> Create(uint8_t *aFontData, uint32_t aDataLength, bool aNeedsCairo); already_AddRefed<ScaledFont> - CreateScaledFont(uint32_t aIndex, Float aGlyphSize) final; + CreateScaledFont(uint32_t aIndex, Float aGlyphSize, + const uint8_t* aInstanceData, uint32_t aInstanceDataLength) final; private: NativeFontResourceDWrite(IDWriteFactory *aFactory, already_AddRefed<IDWriteFontFile> aFontFile, DWRITE_FONT_FACE_TYPE aFaceType, uint32_t aNumberOfFaces, bool aNeedsCairo) : mFactory(aFactory), mFontFile(aFontFile), mFaceType(aFaceType) , mNumberOfFaces(aNumberOfFaces), mNeedsCairo(aNeedsCairo) @@ -48,9 +49,9 @@ private: DWRITE_FONT_FACE_TYPE mFaceType; uint32_t mNumberOfFaces; bool mNeedsCairo; }; } // gfx } // mozilla -#endif // mozilla_gfx_NativeFontResourceDWrite_h \ No newline at end of file +#endif // mozilla_gfx_NativeFontResourceDWrite_h
new file mode 100644 --- /dev/null +++ b/gfx/2d/NativeFontResourceFontconfig.cpp @@ -0,0 +1,65 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#include "NativeFontResourceFontconfig.h" +#include "ScaledFontFontconfig.h" +#include "Logging.h" + +namespace mozilla { +namespace gfx { + +NativeFontResourceFontconfig::NativeFontResourceFontconfig(UniquePtr<uint8_t[]>&& aFontData, FT_Face aFace) + : mFontData(Move(aFontData)), + mFace(aFace) +{ +} + +NativeFontResourceFontconfig::~NativeFontResourceFontconfig() +{ + if (mFace) { + FT_Done_Face(mFace); + mFace = nullptr; + } +} + +already_AddRefed<NativeFontResourceFontconfig> +NativeFontResourceFontconfig::Create(uint8_t *aFontData, uint32_t aDataLength) +{ + if (!aFontData || !aDataLength) { + return nullptr; + } + UniquePtr<uint8_t[]> fontData(new uint8_t[aDataLength]); + memcpy(fontData.get(), aFontData, aDataLength); + + FT_Face face; + if (FT_New_Memory_Face(Factory::GetFTLibrary(), fontData.get(), aDataLength, 0, &face) != FT_Err_Ok) { + return nullptr; + } + if (FT_Select_Charmap(face, FT_ENCODING_UNICODE) != FT_Err_Ok) { + FT_Done_Face(face); + return nullptr; + } + + RefPtr<NativeFontResourceFontconfig> resource = + new NativeFontResourceFontconfig(Move(fontData), face); + return resource.forget(); +} + +already_AddRefed<ScaledFont> +NativeFontResourceFontconfig::CreateScaledFont(uint32_t aIndex, Float aGlyphSize, + const uint8_t* aInstanceData, uint32_t aInstanceDataLength) +{ + if (aInstanceDataLength < sizeof(ScaledFontFontconfig::InstanceData)) { + gfxWarning() << "Fontconfig scaled font instance data is truncated."; + return nullptr; + } + return ScaledFontFontconfig::CreateFromInstanceData( + *reinterpret_cast<const ScaledFontFontconfig::InstanceData*>(aInstanceData), + mFace, nullptr, 0, aGlyphSize); +} + +} // gfx +} // mozilla
new file mode 100644 --- /dev/null +++ b/gfx/2d/NativeFontResourceFontconfig.h @@ -0,0 +1,41 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 mozilla_gfx_NativeFontResourceFontconfig_h +#define mozilla_gfx_NativeFontResourceFontconfig_h + +#include "2D.h" + +#include <cairo-ft.h> + +namespace mozilla { +namespace gfx { + +class NativeFontResourceFontconfig final : public NativeFontResource +{ +public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(NativeFontResourceFontconfig) + + static already_AddRefed<NativeFontResourceFontconfig> + Create(uint8_t *aFontData, uint32_t aDataLength); + + already_AddRefed<ScaledFont> + CreateScaledFont(uint32_t aIndex, Float aGlyphSize, + const uint8_t* aInstanceData, uint32_t aInstanceDataLength) final; + + ~NativeFontResourceFontconfig(); + +private: + NativeFontResourceFontconfig(UniquePtr<uint8_t[]>&& aFontData, FT_Face aFace); + + UniquePtr<uint8_t[]> mFontData; + FT_Face mFace; +}; + +} // gfx +} // mozilla + +#endif // mozilla_gfx_NativeFontResourceFontconfig_h
--- a/gfx/2d/NativeFontResourceGDI.cpp +++ b/gfx/2d/NativeFontResourceGDI.cpp @@ -60,17 +60,18 @@ NativeFontResourceGDI::Create(uint8_t *a } NativeFontResourceGDI::~NativeFontResourceGDI() { ::RemoveFontMemResourceEx(mFontResourceHandle); } already_AddRefed<ScaledFont> -NativeFontResourceGDI::CreateScaledFont(uint32_t aIndex, Float aGlyphSize) +NativeFontResourceGDI::CreateScaledFont(uint32_t aIndex, Float aGlyphSize, + const uint8_t* aInstanceData, uint32_t aInstanceDataLength) { if (aIndex >= mFontNames.length()) { gfxWarning() << "Font index is too high for font resource."; return nullptr; } if (mFontNames[aIndex].empty()) { gfxWarning() << "Font name for index is empty.";
--- a/gfx/2d/NativeFontResourceGDI.h +++ b/gfx/2d/NativeFontResourceGDI.h @@ -31,17 +31,18 @@ public: * @return Referenced NativeFontResourceGDI or nullptr if invalid. */ static already_AddRefed<NativeFontResourceGDI> Create(uint8_t *aFontData, uint32_t aDataLength, bool aNeedsCairo); ~NativeFontResourceGDI(); already_AddRefed<ScaledFont> - CreateScaledFont(uint32_t aIndex, Float aGlyphSize) final; + CreateScaledFont(uint32_t aIndex, Float aGlyphSize, + const uint8_t* aInstanceData, uint32_t aInstanceDataLength) final; private: NativeFontResourceGDI(HANDLE aFontResourceHandle, Vector<mozilla::u16string>&& aFontNames, bool aNeedsCairo) : mFontResourceHandle(aFontResourceHandle), mFontNames(Move(aFontNames)) , mNeedsCairo(aNeedsCairo) {} @@ -49,9 +50,9 @@ private: HANDLE mFontResourceHandle; Vector<mozilla::u16string> mFontNames; bool mNeedsCairo; }; } // gfx } // mozilla -#endif // mozilla_gfx_NativeFontResourceGDI_h \ No newline at end of file +#endif // mozilla_gfx_NativeFontResourceGDI_h
--- a/gfx/2d/NativeFontResourceMac.cpp +++ b/gfx/2d/NativeFontResourceMac.cpp @@ -45,17 +45,18 @@ NativeFontResourceMac::Create(uint8_t *a // passes ownership of fontRef to the NativeFontResourceMac instance RefPtr<NativeFontResourceMac> fontResource = new NativeFontResourceMac(fontRef); return fontResource.forget(); } already_AddRefed<ScaledFont> -NativeFontResourceMac::CreateScaledFont(uint32_t aIndex, Float aGlyphSize) +NativeFontResourceMac::CreateScaledFont(uint32_t aIndex, Float aGlyphSize, + const uint8_t* aInstanceData, uint32_t aInstanceDataLength) { RefPtr<ScaledFontBase> scaledFont = new ScaledFontMac(mFontRef, aGlyphSize); if (!scaledFont->PopulateCairoScaledFont()) { gfxWarning() << "Unable to create cairo scaled Mac font."; return nullptr; }
--- a/gfx/2d/NativeFontResourceMac.h +++ b/gfx/2d/NativeFontResourceMac.h @@ -18,17 +18,18 @@ class NativeFontResourceMac final : publ { public: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(NativeFontResourceMac) static already_AddRefed<NativeFontResourceMac> Create(uint8_t *aFontData, uint32_t aDataLength); already_AddRefed<ScaledFont> - CreateScaledFont(uint32_t aIndex, Float aGlyphSize); + CreateScaledFont(uint32_t aIndex, Float aGlyphSize, + const uint8_t* aInstanceData, uint32_t aInstanceDataLength) final; ~NativeFontResourceMac() { CFRelease(mFontRef); } private: explicit NativeFontResourceMac(CGFontRef aFontRef) : mFontRef(aFontRef) {}
--- a/gfx/2d/RecordedEvent.cpp +++ b/gfx/2d/RecordedEvent.cpp @@ -1581,42 +1581,37 @@ RecordedFontData::RecordedFontData(istre RecordedFontDescriptor::~RecordedFontDescriptor() { } bool RecordedFontDescriptor::PlayEvent(Translator *aTranslator) const { - MOZ_ASSERT(mType == FontType::GDI); - - NativeFont nativeFont; - nativeFont.mType = (NativeFontType)mType; - nativeFont.mFont = (void*)&mData[0]; - RefPtr<ScaledFont> font = - Factory::CreateScaledFontForNativeFont(nativeFont, mFontSize); - -#ifdef USE_CAIRO_SCALED_FONT - static_cast<ScaledFontBase*>(font.get())->PopulateCairoScaledFont(); -#endif + Factory::CreateScaledFontFromFontDescriptor(mType, mData.data(), mData.size(), mFontSize); + if (!font) { + gfxDevCrash(LogReason::InvalidFont) << + "Failed creating ScaledFont of type " << int(mType) << " from font descriptor"; + return false; + } aTranslator->AddScaledFont(mRefPtr, font); return true; } void RecordedFontDescriptor::RecordToStream(std::ostream &aStream) const { MOZ_ASSERT(mHasDesc); WriteElement(aStream, mType); WriteElement(aStream, mFontSize); WriteElement(aStream, mRefPtr); WriteElement(aStream, (size_t)mData.size()); - aStream.write((char*)&mData[0], mData.size()); + aStream.write((char*)mData.data(), mData.size()); } void RecordedFontDescriptor::OutputSimpleEventInfo(stringstream &aStringStream) const { aStringStream << "[" << mRefPtr << "] Font Descriptor"; } @@ -1632,56 +1627,70 @@ RecordedFontDescriptor::RecordedFontDesc { ReadElement(aStream, mType); ReadElement(aStream, mFontSize); ReadElement(aStream, mRefPtr); size_t size; ReadElement(aStream, size); mData.resize(size); - aStream.read((char*)&mData[0], size); + aStream.read((char*)mData.data(), size); } bool RecordedScaledFontCreation::PlayEvent(Translator *aTranslator) const { NativeFontResource *fontResource = aTranslator->LookupNativeFontResource(mFontDataKey); if (!fontResource) { gfxDevCrash(LogReason::NativeFontResourceNotFound) << "NativeFontResource lookup failed for key |" << hexa(mFontDataKey) << "|."; return false; } - RefPtr<ScaledFont> scaledFont = fontResource->CreateScaledFont(mIndex, mGlyphSize); + RefPtr<ScaledFont> scaledFont = + fontResource->CreateScaledFont(mIndex, mGlyphSize, mInstanceData.data(), mInstanceData.size()); aTranslator->AddScaledFont(mRefPtr, scaledFont); return true; } void RecordedScaledFontCreation::RecordToStream(std::ostream &aStream) const { WriteElement(aStream, mRefPtr); WriteElement(aStream, mFontDataKey); WriteElement(aStream, mIndex); WriteElement(aStream, mGlyphSize); + WriteElement(aStream, (size_t)mInstanceData.size()); + aStream.write((char*)mInstanceData.data(), mInstanceData.size()); } void RecordedScaledFontCreation::OutputSimpleEventInfo(stringstream &aStringStream) const { aStringStream << "[" << mRefPtr << "] ScaledFont Created"; } +void +RecordedScaledFontCreation::SetFontInstanceData(const uint8_t *aData, uint32_t aSize) +{ + mInstanceData.assign(aData, aData + aSize); +} + RecordedScaledFontCreation::RecordedScaledFontCreation(istream &aStream) : RecordedEvent(SCALEDFONTCREATION) { ReadElement(aStream, mRefPtr); ReadElement(aStream, mFontDataKey); ReadElement(aStream, mIndex); ReadElement(aStream, mGlyphSize); + + size_t size; + ReadElement(aStream, size); + mInstanceData.resize(size); + aStream.read((char*)mInstanceData.data(), size); } bool RecordedScaledFontDestruction::PlayEvent(Translator *aTranslator) const { aTranslator->RemoveScaledFont(mRefPtr); return true; }
--- a/gfx/2d/RecordedEvent.h +++ b/gfx/2d/RecordedEvent.h @@ -19,17 +19,17 @@ struct PathOp; class PathRecording; const uint32_t kMagicInt = 0xc001feed; // A change in major revision means a change in event binary format, causing // loss of backwards compatibility. Old streams will not work in a player // using a newer major revision. And new streams will not work in a player // using an older major revision. -const uint16_t kMajorRevision = 5; +const uint16_t kMajorRevision = 6; // A change in minor revision means additions of new events. New streams will // not play in older players. const uint16_t kMinorRevision = 0; struct ReferencePtr { ReferencePtr() : mLongPtr(0) @@ -1042,25 +1042,25 @@ public: bool GetFontDetails(RecordedFontDetails& fontDetails); private: friend class RecordedEvent; uint8_t *mData; RecordedFontDetails mFontDetails; - bool mGetFontFileDataSucceeded = false; + bool mGetFontFileDataSucceeded; MOZ_IMPLICIT RecordedFontData(std::istream &aStream); }; class RecordedFontDescriptor : public RecordedEvent { public: - static void FontDescCb(const uint8_t *aData, uint32_t aSize, + static void FontDescCb(const uint8_t* aData, uint32_t aSize, Float aFontSize, void* aBaton) { auto recordedFontDesc = static_cast<RecordedFontDescriptor*>(aBaton); recordedFontDesc->SetFontDescriptor(aData, aSize, aFontSize); } explicit RecordedFontDescriptor(ScaledFont* aScaledFont) : RecordedEvent(FONTDESC) @@ -1095,39 +1095,51 @@ private: ReferencePtr mRefPtr; MOZ_IMPLICIT RecordedFontDescriptor(std::istream &aStream); }; class RecordedScaledFontCreation : public RecordedEvent { public: - RecordedScaledFontCreation(ReferencePtr aRefPtr, + static void FontInstanceDataProc(const uint8_t* aData, uint32_t aSize, void* aBaton) + { + auto recordedScaledFontCreation = static_cast<RecordedScaledFontCreation*>(aBaton); + recordedScaledFontCreation->SetFontInstanceData(aData, aSize); + } + + RecordedScaledFontCreation(ScaledFont* aScaledFont, RecordedFontDetails aFontDetails) - : RecordedEvent(SCALEDFONTCREATION), mRefPtr(aRefPtr) + : RecordedEvent(SCALEDFONTCREATION) + , mRefPtr(aScaledFont) , mFontDataKey(aFontDetails.fontDataKey) - , mGlyphSize(aFontDetails.glyphSize) , mIndex(aFontDetails.index) + , mGlyphSize(aFontDetails.glyphSize) + , mIndex(aFontDetails.index) { + aScaledFont->GetFontInstanceData(FontInstanceDataProc, this); } virtual bool PlayEvent(Translator *aTranslator) const; virtual void RecordToStream(std::ostream &aStream) const; virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const; virtual std::string GetName() const { return "ScaledFont Creation"; } virtual ReferencePtr GetObjectRef() const { return mRefPtr; } + void SetFontInstanceData(const uint8_t *aData, uint32_t aSize); + private: friend class RecordedEvent; ReferencePtr mRefPtr; uint64_t mFontDataKey; Float mGlyphSize; uint32_t mIndex; + std::vector<uint8_t> mInstanceData; MOZ_IMPLICIT RecordedScaledFontCreation(std::istream &aStream); }; class RecordedScaledFontDestruction : public RecordedEvent { public: MOZ_IMPLICIT RecordedScaledFontDestruction(ReferencePtr aRefPtr) : RecordedEvent(SCALEDFONTDESTRUCTION), mRefPtr(aRefPtr)
--- a/gfx/2d/ScaledFontFontconfig.cpp +++ b/gfx/2d/ScaledFontFontconfig.cpp @@ -5,16 +5,20 @@ #include "ScaledFontFontconfig.h" #include "Logging.h" #ifdef USE_SKIA #include "skia/include/ports/SkTypeface_cairo.h" #endif +#include FT_TRUETYPE_TABLES_H + +#include <fontconfig/fcfreetype.h> + namespace mozilla { namespace gfx { // On Linux and Android our "platform" font is a cairo_scaled_font_t and we use // an SkFontHost implementation that allows Skia to render using this. // This is mainly because FT_Face is not good for sharing between libraries, which // is a requirement when we consider runtime switchable backends and so on ScaledFontFontconfig::ScaledFontFontconfig(cairo_scaled_font_t* aScaledFont, @@ -38,10 +42,321 @@ SkTypeface* ScaledFontFontconfig::GetSkT if (!mTypeface) { mTypeface = SkCreateTypefaceFromCairoFTFontWithFontconfig(mScaledFont, mPattern); } return mTypeface; } #endif +bool +ScaledFontFontconfig::GetFontFileData(FontFileDataOutput aDataCallback, void* aBaton) +{ + bool success = false; + // Lock the Cairo scaled font to force it to resolve the Fontconfig pattern to an FT_Face. + if (FT_Face face = cairo_ft_scaled_font_lock_face(GetCairoScaledFont())) { + FT_ULong length = 0; + // Request the SFNT file. This may not always succeed for all font types. + if (FT_Load_Sfnt_Table(face, 0, 0, nullptr, &length) == FT_Err_Ok) { + uint8_t* fontData = new uint8_t[length]; + if (FT_Load_Sfnt_Table(face, 0, 0, fontData, &length) == FT_Err_Ok) { + aDataCallback(fontData, length, 0, mSize, aBaton); + success = true; + } + delete[] fontData; + } + cairo_ft_scaled_font_unlock_face(GetCairoScaledFont()); + } + return success; +} + +ScaledFontFontconfig::InstanceData::InstanceData(cairo_scaled_font_t* aScaledFont, FcPattern* aPattern) + : mFlags(0) + , mHintStyle(FC_HINT_NONE) + , mSubpixelOrder(FC_RGBA_UNKNOWN) + , mLcdFilter(FC_LCD_LEGACY) +{ + // Record relevant Fontconfig properties into instance data. + FcBool autohint; + if (FcPatternGetBool(aPattern, FC_AUTOHINT, 0, &autohint) == FcResultMatch && autohint) { + mFlags |= AUTOHINT; + } + FcBool bitmap; + if (FcPatternGetBool(aPattern, FC_EMBEDDED_BITMAP, 0, &bitmap) == FcResultMatch && bitmap) { + mFlags |= EMBEDDED_BITMAP; + } + FcBool embolden; + if (FcPatternGetBool(aPattern, FC_EMBOLDEN, 0, &embolden) == FcResultMatch && embolden) { + mFlags |= EMBOLDEN; + } + FcBool vertical; + if (FcPatternGetBool(aPattern, FC_VERTICAL_LAYOUT, 0, &vertical) == FcResultMatch && vertical) { + mFlags |= VERTICAL_LAYOUT; + } + + FcBool antialias; + if (FcPatternGetBool(aPattern, FC_ANTIALIAS, 0, &antialias) != FcResultMatch || antialias) { + mFlags |= ANTIALIAS; + + // Only record subpixel order and lcd filtering if antialiasing is enabled. + int rgba; + if (FcPatternGetInteger(aPattern, FC_RGBA, 0, &rgba) == FcResultMatch) { + mSubpixelOrder = rgba; + } + int filter; + if (FcPatternGetInteger(aPattern, FC_LCD_FILTER, 0, &filter) == FcResultMatch) { + mLcdFilter = filter; + } + } + + cairo_font_options_t* fontOptions = cairo_font_options_create(); + cairo_scaled_font_get_font_options(aScaledFont, fontOptions); + // For printer fonts, Cairo hint metrics and hinting will be disabled. + // For other fonts, allow hint metrics and hinting. + if (cairo_font_options_get_hint_metrics(fontOptions) != CAIRO_HINT_METRICS_OFF) { + mFlags |= HINT_METRICS; + + FcBool hinting; + if (FcPatternGetBool(aPattern, FC_HINTING, 0, &hinting) != FcResultMatch || hinting) { + int hintstyle; + if (FcPatternGetInteger(aPattern, FC_HINT_STYLE, 0, &hintstyle) != FcResultMatch) { + hintstyle = FC_HINT_FULL; + } + mHintStyle = hintstyle; + } + } + cairo_font_options_destroy(fontOptions); + + // Some fonts supply an adjusted size or otherwise use the font matrix for italicization. + // Record the scale and the skew to accomodate both of these cases. + cairo_matrix_t fontMatrix; + cairo_scaled_font_get_font_matrix(aScaledFont, &fontMatrix); + mScale = Float(fontMatrix.xx); + mSkew = Float(fontMatrix.xy); +} + +void +ScaledFontFontconfig::InstanceData::SetupPattern(FcPattern* aPattern) const +{ + if (mFlags & AUTOHINT) { + FcPatternAddBool(aPattern, FC_AUTOHINT, FcTrue); + } + if (mFlags & EMBEDDED_BITMAP) { + FcPatternAddBool(aPattern, FC_EMBEDDED_BITMAP, FcTrue); + } + if (mFlags & EMBOLDEN) { + FcPatternAddBool(aPattern, FC_EMBOLDEN, FcTrue); + } + if (mFlags & VERTICAL_LAYOUT) { + FcPatternAddBool(aPattern, FC_VERTICAL_LAYOUT, FcTrue); + } + + if (mFlags & ANTIALIAS) { + FcPatternAddBool(aPattern, FC_ANTIALIAS, FcTrue); + if (mSubpixelOrder != FC_RGBA_UNKNOWN) { + FcPatternAddInteger(aPattern, FC_RGBA, mSubpixelOrder); + } + if (mLcdFilter != FC_LCD_LEGACY) { + FcPatternAddInteger(aPattern, FC_LCD_FILTER, mLcdFilter); + } + } else { + FcPatternAddBool(aPattern, FC_ANTIALIAS, FcFalse); + } + + if (mHintStyle) { + FcPatternAddBool(aPattern, FC_HINTING, FcTrue); + FcPatternAddInteger(aPattern, FC_HINT_STYLE, mHintStyle); + } else { + FcPatternAddBool(aPattern, FC_HINTING, FcFalse); + } +} + +void +ScaledFontFontconfig::InstanceData::SetupFontOptions(cairo_font_options_t* aFontOptions) const +{ + // Try to build a sane initial set of Cairo font options based on the Fontconfig + // pattern. + if (mFlags & HINT_METRICS) { + // For regular (non-printer) fonts, enable hint metrics as well as hinting + // and (possibly subpixel) antialiasing. + cairo_font_options_set_hint_metrics(aFontOptions, CAIRO_HINT_METRICS_ON); + + cairo_hint_style_t hinting; + switch (mHintStyle) { + case FC_HINT_NONE: + hinting = CAIRO_HINT_STYLE_NONE; + break; + case FC_HINT_SLIGHT: + hinting = CAIRO_HINT_STYLE_SLIGHT; + break; + case FC_HINT_MEDIUM: + default: + hinting = CAIRO_HINT_STYLE_MEDIUM; + break; + case FC_HINT_FULL: + hinting = CAIRO_HINT_STYLE_FULL; + break; + } + cairo_font_options_set_hint_style(aFontOptions, hinting); + + if (mFlags & ANTIALIAS) { + cairo_subpixel_order_t subpixel = CAIRO_SUBPIXEL_ORDER_DEFAULT; + switch (mSubpixelOrder) { + case FC_RGBA_RGB: + subpixel = CAIRO_SUBPIXEL_ORDER_RGB; + break; + case FC_RGBA_BGR: + subpixel = CAIRO_SUBPIXEL_ORDER_BGR; + break; + case FC_RGBA_VRGB: + subpixel = CAIRO_SUBPIXEL_ORDER_VRGB; + break; + case FC_RGBA_VBGR: + subpixel = CAIRO_SUBPIXEL_ORDER_VBGR; + break; + default: + break; + } + if (subpixel != CAIRO_SUBPIXEL_ORDER_DEFAULT) { + cairo_font_options_set_antialias(aFontOptions, CAIRO_ANTIALIAS_SUBPIXEL); + cairo_font_options_set_subpixel_order(aFontOptions, subpixel); + } else { + cairo_font_options_set_antialias(aFontOptions, CAIRO_ANTIALIAS_GRAY); + } + } else { + cairo_font_options_set_antialias(aFontOptions, CAIRO_ANTIALIAS_NONE); + } + } else { + // For printer fonts, disable hint metrics and hinting. Don't allow subpixel + // antialiasing. + cairo_font_options_set_hint_metrics(aFontOptions, CAIRO_HINT_METRICS_OFF); + cairo_font_options_set_hint_style(aFontOptions, CAIRO_HINT_STYLE_NONE); + cairo_font_options_set_antialias(aFontOptions, + mFlags & ANTIALIAS ? CAIRO_ANTIALIAS_GRAY : CAIRO_ANTIALIAS_NONE); + } +} + +void +ScaledFontFontconfig::InstanceData::SetupFontMatrix(cairo_matrix_t* aFontMatrix) const +{ + // Build a font matrix that will reproduce a possibly adjusted size + // and any italics/skew. This is just the concatenation of a simple + // scale matrix with a matrix that skews on the X axis. + cairo_matrix_init(aFontMatrix, mScale, 0, mSkew, mScale, 0, 0); +} + +bool +ScaledFontFontconfig::GetFontInstanceData(FontInstanceDataOutput aCb, void* aBaton) +{ + InstanceData instance(GetCairoScaledFont(), mPattern); + + aCb(reinterpret_cast<uint8_t*>(&instance), sizeof(instance), aBaton); + return true; +} + +bool +ScaledFontFontconfig::GetFontDescriptor(FontDescriptorOutput aCb, void* aBaton) +{ + // Check if the Fontconfig pattern uses a font file and index to specify which + // font to load. If so, record these as a font descriptor along with any instance + // data required to rebuild a scaled font from it. + FcChar8* pathname = nullptr; + if (FcPatternGetString(mPattern, FC_FILE, 0, &pathname) != FcResultMatch) { + return false; + } + int index = 0; + FcPatternGetInteger(mPattern, FC_INDEX, 0, &index); + if (index < 0) { + return false; + } + + size_t pathLength = strlen(reinterpret_cast<char*>(pathname)) + 1; + size_t dataLength = sizeof(FontDescriptor) + pathLength; + uint8_t* data = new uint8_t[dataLength]; + FontDescriptor* desc = reinterpret_cast<FontDescriptor*>(data); + desc->mPathLength = pathLength; + desc->mIndex = index; + desc->mInstanceData = InstanceData(GetCairoScaledFont(), mPattern); + memcpy(data + sizeof(FontDescriptor), pathname, pathLength); + + aCb(data, dataLength, mSize, aBaton); + return true; +} + +already_AddRefed<ScaledFont> +ScaledFontFontconfig::CreateFromInstanceData(const InstanceData& aInstanceData, + FT_Face aFace, const char* aPathname, uint32_t aIndex, + Float aSize) + +{ + FcPattern* pattern = FcPatternCreate(); + if (!pattern) { + gfxWarning() << "Failing initializing Fontconfig pattern for scaled font"; + return nullptr; + } + if (aFace) { + FcPatternAddFTFace(pattern, FC_FT_FACE, aFace); + } else { + FcPatternAddString(pattern, FC_FILE, reinterpret_cast<const FcChar8*>(aPathname)); + FcPatternAddInteger(pattern, FC_INDEX, aIndex); + } + FcPatternAddDouble(pattern, FC_PIXEL_SIZE, aSize); + aInstanceData.SetupPattern(pattern); + + cairo_font_face_t* font = cairo_ft_font_face_create_for_pattern(pattern); + if (cairo_font_face_status(font) != CAIRO_STATUS_SUCCESS) { + gfxWarning() << "Failed creating Cairo font face for Fontconfig pattern"; + FcPatternDestroy(pattern); + return nullptr; + } + + cairo_matrix_t sizeMatrix; + aInstanceData.SetupFontMatrix(&sizeMatrix); + + cairo_matrix_t identityMatrix; + cairo_matrix_init_identity(&identityMatrix); + + cairo_font_options_t *fontOptions = cairo_font_options_create(); + aInstanceData.SetupFontOptions(fontOptions); + + cairo_scaled_font_t* cairoScaledFont = + cairo_scaled_font_create(font, &sizeMatrix, &identityMatrix, fontOptions); + + cairo_font_options_destroy(fontOptions); + cairo_font_face_destroy(font); + + if (cairo_scaled_font_status(cairoScaledFont) != CAIRO_STATUS_SUCCESS) { + gfxWarning() << "Failed creating Cairo scaled font for font face"; + FcPatternDestroy(pattern); + return nullptr; + } + + RefPtr<ScaledFontFontconfig> scaledFont = + new ScaledFontFontconfig(cairoScaledFont, pattern, aSize); + + FcPatternDestroy(pattern); + + return scaledFont.forget(); +} + +already_AddRefed<ScaledFont> +ScaledFontFontconfig::CreateFromFontDescriptor(const uint8_t* aData, uint32_t aDataLength, Float aSize) +{ + if (aDataLength < sizeof(FontDescriptor)) { + gfxWarning() << "Fontconfig font descriptor is truncated."; + return nullptr; + } + const FontDescriptor* desc = reinterpret_cast<const FontDescriptor*>(aData); + if (desc->mPathLength < 1 || + desc->mPathLength > aDataLength - sizeof(FontDescriptor)) { + gfxWarning() << "Pathname in Fontconfig font descriptor has invalid size."; + return nullptr; + } + const char* pathname = reinterpret_cast<const char*>(aData + sizeof(FontDescriptor)); + if (pathname[desc->mPathLength - 1] != '\0') { + gfxWarning() << "Pathname in Fontconfig font descriptor is not terminated."; + return nullptr; + } + return CreateFromInstanceData(desc->mInstanceData, nullptr, pathname, desc->mIndex, aSize); +} + } // namespace gfx } // namespace mozilla
--- a/gfx/2d/ScaledFontFontconfig.h +++ b/gfx/2d/ScaledFontFontconfig.h @@ -3,35 +3,84 @@ * 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 MOZILLA_GFX_SCALEDFONTFONTCONFIG_H_ #define MOZILLA_GFX_SCALEDFONTFONTCONFIG_H_ #include "ScaledFontBase.h" -#include <fontconfig/fontconfig.h> -#include <cairo.h> +#include <cairo-ft.h> namespace mozilla { namespace gfx { +class NativeFontResourceFontconfig; + class ScaledFontFontconfig : public ScaledFontBase { public: - MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFontFontconfig) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFontFontconfig, override) ScaledFontFontconfig(cairo_scaled_font_t* aScaledFont, FcPattern* aPattern, Float aSize); ~ScaledFontFontconfig(); - virtual FontType GetType() const { return FontType::FONTCONFIG; } + FontType GetType() const override { return FontType::FONTCONFIG; } #ifdef USE_SKIA - virtual SkTypeface* GetSkTypeface(); + SkTypeface* GetSkTypeface() override; #endif + bool GetFontFileData(FontFileDataOutput aDataCallback, void* aBaton) override; + + bool GetFontInstanceData(FontInstanceDataOutput aCb, void* aBaton) override; + + bool GetFontDescriptor(FontDescriptorOutput aCb, void* aBaton) override; + + static already_AddRefed<ScaledFont> + CreateFromFontDescriptor(const uint8_t* aData, uint32_t aDataLength, Float aSize); + private: + friend class NativeFontResourceFontconfig; + + struct InstanceData + { + enum { + ANTIALIAS = 1 << 0, + AUTOHINT = 1 << 1, + EMBEDDED_BITMAP = 1 << 2, + EMBOLDEN = 1 << 3, + VERTICAL_LAYOUT = 1 << 4, + HINT_METRICS = 1 << 5 + }; + + InstanceData(cairo_scaled_font_t* aScaledFont, FcPattern* aPattern); + + void SetupPattern(FcPattern* aPattern) const; + void SetupFontOptions(cairo_font_options_t* aFontOptions) const; + void SetupFontMatrix(cairo_matrix_t* aFontMatrix) const; + + uint8_t mFlags; + uint8_t mHintStyle; + uint8_t mSubpixelOrder; + uint8_t mLcdFilter; + Float mScale; + Float mSkew; + }; + + struct FontDescriptor + { + uint32_t mPathLength; + uint32_t mIndex; + InstanceData mInstanceData; + }; + + static already_AddRefed<ScaledFont> + CreateFromInstanceData(const InstanceData& aInstanceData, + FT_Face aFace, const char* aPathname, uint32_t aIndex, + Float aSize); + FcPattern* mPattern; }; } } #endif /* MOZILLA_GFX_SCALEDFONTFONTCONFIG_H_ */
--- a/gfx/2d/ScaledFontWin.cpp +++ b/gfx/2d/ScaledFontWin.cpp @@ -83,16 +83,33 @@ ScaledFontWin::GetFontFileData(FontFileD bool ScaledFontWin::GetFontDescriptor(FontDescriptorOutput aCb, void* aBaton) { aCb(reinterpret_cast<uint8_t*>(&mLogFont), sizeof(mLogFont), mSize, aBaton); return true; } +already_AddRefed<ScaledFont> +ScaledFontWin::CreateFromFontDescriptor(const uint8_t* aData, uint32_t aDataLength, Float aSize) +{ + NativeFont nativeFont; + nativeFont.mType = NativeFontType::GDI_FONT_FACE; + nativeFont.mFont = (void*)aData; + + RefPtr<ScaledFont> font = + Factory::CreateScaledFontForNativeFont(nativeFont, aSize); + +#ifdef USE_CAIRO_SCALED_FONT + static_cast<ScaledFontBase*>(font.get())->PopulateCairoScaledFont(); +#endif + + return font.forget(); +} + AntialiasMode ScaledFontWin::GetDefaultAAMode() { return GetSystemDefaultAAMode(); } #ifdef USE_SKIA SkTypeface* ScaledFontWin::GetSkTypeface()
--- a/gfx/2d/ScaledFontWin.h +++ b/gfx/2d/ScaledFontWin.h @@ -18,16 +18,20 @@ public: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFontWin) ScaledFontWin(LOGFONT* aFont, Float aSize); virtual FontType GetType() const { return FontType::GDI; } bool GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton) override; virtual bool GetFontDescriptor(FontDescriptorOutput aCb, void* aBaton) override; + + static already_AddRefed<ScaledFont> + CreateFromFontDescriptor(const uint8_t* aData, uint32_t aDataLength, Float aSize); + virtual AntialiasMode GetDefaultAAMode() override; #ifdef USE_SKIA virtual SkTypeface* GetSkTypeface(); #endif protected: #ifdef USE_CAIRO_SCALED_FONT
--- a/gfx/2d/moz.build +++ b/gfx/2d/moz.build @@ -85,16 +85,17 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'wi if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'windows': SOURCES += [ 'JobScheduler_posix.cpp', ] if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk2', 'gtk3'): SOURCES += [ + 'NativeFontResourceFontconfig.cpp', 'ScaledFontFontconfig.cpp', ] if CONFIG['MOZ_ENABLE_SKIA']: UNIFIED_SOURCES += [ 'convolver.cpp', ] SOURCES += [
--- a/gfx/layers/ImageContainer.cpp +++ b/gfx/layers/ImageContainer.cpp @@ -11,17 +11,16 @@ #include "gfxPlatform.h" // for gfxPlatform #include "gfxUtils.h" // for gfxUtils #include "libyuv.h" #include "mozilla/RefPtr.h" // for already_AddRefed #include "mozilla/ipc/CrossProcessMutex.h" // for CrossProcessMutex, etc #include "mozilla/layers/CompositorTypes.h" #include "mozilla/layers/ImageBridgeChild.h" // for ImageBridgeChild #include "mozilla/layers/ImageClient.h" // for ImageClient -#include "mozilla/layers/ImageContainerChild.h" #include "mozilla/layers/LayersMessages.h" #include "mozilla/layers/SharedPlanarYCbCrImage.h" #include "mozilla/layers/SharedRGBImage.h" #include "mozilla/layers/TextureClientRecycleAllocator.h" #include "mozilla/gfx/gfxVars.h" #include "nsISupportsUtils.h" // for NS_IF_ADDREF #include "YCbCrUtils.h" // for YCbCr conversions #include "gfx2DGlue.h" @@ -104,18 +103,17 @@ ImageContainer::EnsureImageClient(bool a // If we're not forcing a new ImageClient, then we can skip this if we don't have an existing // ImageClient, or if the existing one belongs to an IPC actor that is still open. if (!aCreate && (!mImageClient || mImageClient->GetForwarder()->GetLayersIPCActor()->IPCOpen())) { return; } RefPtr<ImageBridgeChild> imageBridge = ImageBridgeChild::GetSingleton(); if (imageBridge) { - mIPDLChild = new ImageContainerChild(this); - mImageClient = imageBridge->CreateImageClient(CompositableType::IMAGE, this, mIPDLChild); + mImageClient = imageBridge->CreateImageClient(CompositableType::IMAGE, this); if (mImageClient) { mAsyncContainerID = mImageClient->GetAsyncID(); } } } ImageContainer::ImageContainer(Mode flag) : mReentrantMonitor("ImageContainer.mReentrantMonitor"), @@ -143,20 +141,19 @@ ImageContainer::ImageContainer(uint64_t mAsyncContainerID(aAsyncContainerID), mCurrentProducerID(-1) { MOZ_ASSERT(mAsyncContainerID != sInvalidAsyncContainerId); } ImageContainer::~ImageContainer() { - if (mIPDLChild) { - mIPDLChild->ForgetImageContainer(); + if (mAsyncContainerID) { if (RefPtr<ImageBridgeChild> imageBridge = ImageBridgeChild::GetSingleton()) { - imageBridge->ReleaseImageContainer(mIPDLChild); + imageBridge->ForgetImageContainer(mAsyncContainerID); } } } RefPtr<PlanarYCbCrImage> ImageContainer::CreatePlanarYCbCrImage() { ReentrantMonitorAutoEnter mon(mReentrantMonitor); @@ -355,17 +352,17 @@ ImageContainer::GetCurrentSize() if (mCurrentImages.IsEmpty()) { return gfx::IntSize(0, 0); } return mCurrentImages[0].mImage->GetSize(); } void -ImageContainer::NotifyCompositeInternal(const ImageCompositeNotification& aNotification) +ImageContainer::NotifyComposite(const ImageCompositeNotification& aNotification) { ReentrantMonitorAutoEnter mon(mReentrantMonitor); // An image composition notification is sent the first time a particular // image is composited by an ImageHost. Thus, every time we receive such // a notification, a new image has been painted. ++mPaintCount; @@ -755,22 +752,16 @@ SourceSurfaceImage::GetTextureClient(Kno } textureClient->SyncWithObject(aForwarder->GetSyncObject()); mTextureClients.Put(aForwarder->GetSerial(), textureClient); return textureClient; } -PImageContainerChild* -ImageContainer::GetPImageContainerChild() -{ - return mIPDLChild; -} - ImageContainer::ProducerID ImageContainer::AllocateProducerID() { // Callable on all threads. static Atomic<ImageContainer::ProducerID> sProducerID(0u); return ++sProducerID; }
--- a/gfx/layers/ImageContainer.h +++ b/gfx/layers/ImageContainer.h @@ -557,16 +557,18 @@ public: * Every expired image that is never composited is counted as dropped. */ uint32_t GetDroppedImageCount() { ReentrantMonitorAutoEnter mon(mReentrantMonitor); return mDroppedImageCount; } + void NotifyComposite(const ImageCompositeNotification& aNotification); + PImageContainerChild* GetPImageContainerChild(); /** * Main thread only. */ static ProducerID AllocateProducerID(); private: @@ -580,18 +582,16 @@ private: // This is called to ensure we have an active image, this may not be true // when we're storing image information in a RemoteImageData structure. // NOTE: If we have remote data mRemoteDataMutex should be locked when // calling this function! void EnsureActiveImage(); void EnsureImageClient(bool aCreate); - void NotifyCompositeInternal(const ImageCompositeNotification& aNotification); - // ReentrantMonitor to protect thread safe access to the "current // image", and any other state which is shared between threads. ReentrantMonitor mReentrantMonitor; nsTArray<OwningImage> mCurrentImages; // Updates every time mActiveImage changes uint32_t mGenerationCounter; @@ -627,20 +627,16 @@ private: uint64_t mAsyncContainerID; nsTArray<FrameID> mFrameIDsNotYetComposited; // ProducerID for last current image(s), including the frames in // mFrameIDsNotYetComposited ProducerID mCurrentProducerID; - // Object must be released on the ImageBridge thread. Field is immutable - // after creation of the ImageContainer. - RefPtr<ImageContainerChild> mIPDLChild; - static mozilla::Atomic<uint32_t> sGenerationCounter; }; class AutoLockImage { public: explicit AutoLockImage(ImageContainer *aContainer) {
--- a/gfx/layers/client/CompositableChild.cpp +++ b/gfx/layers/client/CompositableChild.cpp @@ -20,36 +20,34 @@ CompositableChild::CreateActor() /* static */ void CompositableChild::DestroyActor(PCompositableChild* aChild) { static_cast<CompositableChild*>(aChild)->Release(); } CompositableChild::CompositableChild() : mCompositableClient(nullptr), - mAsyncID(0), mCanSend(true) { } CompositableChild::~CompositableChild() { } bool CompositableChild::IsConnected() const { return mCompositableClient && mCanSend; } void -CompositableChild::Init(CompositableClient* aCompositable, uint64_t aAsyncID) +CompositableChild::Init(CompositableClient* aCompositable) { mCompositableClient = aCompositable; - mAsyncID = aAsyncID; } void CompositableChild::RevokeCompositableClient() { mCompositableClient = nullptr; } @@ -68,25 +66,26 @@ CompositableChild::ActorDestroy(ActorDes if (mCompositableClient) { mCompositableClient->mCompositableChild = nullptr; mCompositableClient = nullptr; } } /* static */ PCompositableChild* -AsyncCompositableChild::CreateActor() +AsyncCompositableChild::CreateActor(uint64_t aAsyncID) { - AsyncCompositableChild* child = new AsyncCompositableChild(); + AsyncCompositableChild* child = new AsyncCompositableChild(aAsyncID); child->AddRef(); return child; } -AsyncCompositableChild::AsyncCompositableChild() - : mLock("AsyncCompositableChild.mLock") +AsyncCompositableChild::AsyncCompositableChild(uint64_t aAsyncID) + : mLock("AsyncCompositableChild.mLock"), + mAsyncID(aAsyncID) { } AsyncCompositableChild::~AsyncCompositableChild() { } void
--- a/gfx/layers/client/CompositableChild.h +++ b/gfx/layers/client/CompositableChild.h @@ -26,66 +26,66 @@ class AsyncCompositableChild; class CompositableChild : public PCompositableChild { public: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositableChild) static PCompositableChild* CreateActor(); static void DestroyActor(PCompositableChild* aChild); - void Init(CompositableClient* aCompositable, uint64_t aAsyncID); + void Init(CompositableClient* aCompositable); virtual void RevokeCompositableClient(); virtual void ActorDestroy(ActorDestroyReason) override; virtual RefPtr<CompositableClient> GetCompositableClient(); virtual AsyncCompositableChild* AsAsyncCompositableChild() { return nullptr; } - uint64_t GetAsyncID() const { - return mAsyncID; - } - // These should only be called on the IPDL thread. bool IsConnected() const; bool CanSend() const { return mCanSend; } protected: CompositableChild(); virtual ~CompositableChild(); protected: CompositableClient* mCompositableClient; - uint64_t mAsyncID; bool mCanSend; }; // This CompositableChild can be used off the main thread. class AsyncCompositableChild final : public CompositableChild { public: - static PCompositableChild* CreateActor(); + static PCompositableChild* CreateActor(uint64_t aAsyncID); void RevokeCompositableClient() override; RefPtr<CompositableClient> GetCompositableClient() override; void ActorDestroy(ActorDestroyReason) override; AsyncCompositableChild* AsAsyncCompositableChild() override { return this; } + uint64_t GetAsyncID() const { + return mAsyncID; + } + protected: - AsyncCompositableChild(); + explicit AsyncCompositableChild(uint64_t aAsyncID); ~AsyncCompositableChild() override; private: Mutex mLock; + uint64_t mAsyncID; }; } // namespace layers } // namespace mozilla #endif // mozilla_gfx_layers_client_CompositableChild_h
--- a/gfx/layers/client/CompositableClient.cpp +++ b/gfx/layers/client/CompositableClient.cpp @@ -29,18 +29,19 @@ using namespace mozilla::gfx; void CompositableClient::InitIPDLActor(PCompositableChild* aActor, uint64_t aAsyncID) { MOZ_ASSERT(aActor); mForwarder->AssertInForwarderThread(); + mAsyncID = aAsyncID; mCompositableChild = static_cast<CompositableChild*>(aActor); - mCompositableChild->Init(this, aAsyncID); + mCompositableChild->Init(this); } /* static */ RefPtr<CompositableClient> CompositableClient::FromIPDLActor(PCompositableChild* aActor) { MOZ_ASSERT(aActor); RefPtr<CompositableClient> client = static_cast<CompositableChild*>(aActor)->GetCompositableClient(); @@ -51,16 +52,17 @@ CompositableClient::FromIPDLActor(PCompo client->mForwarder->AssertInForwarderThread(); return client; } CompositableClient::CompositableClient(CompositableForwarder* aForwarder, TextureFlags aTextureFlags) : mForwarder(aForwarder) , mTextureFlags(aTextureFlags) +, mAsyncID(0) { } CompositableClient::~CompositableClient() { Destroy(); } @@ -115,17 +117,17 @@ CompositableClient::Destroy() mForwarder->Destroy(mCompositableChild); mCompositableChild = nullptr; } uint64_t CompositableClient::GetAsyncID() const { if (mCompositableChild) { - return mCompositableChild->GetAsyncID(); + return mAsyncID; } return 0; // zero is always an invalid async ID } already_AddRefed<TextureClient> CompositableClient::CreateBufferTextureClient(gfx::SurfaceFormat aFormat, gfx::IntSize aSize, gfx::BackendType aMoz2DBackend,
--- a/gfx/layers/client/CompositableClient.h +++ b/gfx/layers/client/CompositableClient.h @@ -176,16 +176,18 @@ public: protected: RefPtr<CompositableChild> mCompositableChild; RefPtr<CompositableForwarder> mForwarder; // Some layers may want to enforce some flags to all their textures // (like disallowing tiling) TextureFlags mTextureFlags; RefPtr<TextureClientRecycleAllocator> mTextureClientRecycler; + uint64_t mAsyncID; + friend class CompositableChild; }; /** * Helper to call RemoveTexture at the end of a scope. */ struct AutoRemoveTexture {
--- a/gfx/layers/composite/CompositableHost.cpp +++ b/gfx/layers/composite/CompositableHost.cpp @@ -6,17 +6,16 @@ #include "CompositableHost.h" #include <map> // for _Rb_tree_iterator, map, etc #include <utility> // for pair #include "ContentHost.h" // for ContentHostDoubleBuffered, etc #include "Effects.h" // for EffectMask, Effect, etc #include "gfxUtils.h" #include "ImageHost.h" // for ImageHostBuffered, etc #include "TiledContentHost.h" // for TiledContentHost -#include "mozilla/layers/ImageContainerParent.h" #include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor #include "mozilla/layers/TextureHost.h" // for TextureHost, etc #include "mozilla/RefPtr.h" // for nsRefPtr #include "nsDebug.h" // for NS_WARNING #include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc #include "gfxPlatform.h" // for gfxPlatform #include "mozilla/layers/PCompositableParent.h" #include "IPDLActor.h" @@ -35,52 +34,39 @@ class Compositor; * * CompositableParent is owned by the IPDL system. It's deletion is triggered * by either the CompositableChild's deletion, or by the IPDL communication * going down. */ class CompositableParent : public ParentActor<PCompositableParent> { public: - CompositableParent(CompositableParentManager* aMgr, - const TextureInfo& aTextureInfo, - uint64_t aID = 0, - PImageContainerParent* aImageContainer = nullptr) + CompositableParent(CompositableParentManager* aMgr, const TextureInfo& aTextureInfo) { MOZ_COUNT_CTOR(CompositableParent); mHost = CompositableHost::Create(aTextureInfo); - mHost->SetAsyncID(aID); - if (aID) { - CompositableMap::Set(aID, this); - } - if (aImageContainer) { - mHost->SetImageContainer( - static_cast<ImageContainerParent*>(aImageContainer)); - } } ~CompositableParent() { MOZ_COUNT_DTOR(CompositableParent); - CompositableMap::Erase(mHost->GetAsyncID()); } virtual void Destroy() override { if (mHost) { mHost->Detach(nullptr, CompositableHost::FORCE_DETACH); } } RefPtr<CompositableHost> mHost; }; CompositableHost::CompositableHost(const TextureInfo& aTextureInfo) : mTextureInfo(aTextureInfo) - , mAsyncID(0) , mCompositorID(0) , mCompositor(nullptr) , mLayer(nullptr) , mFlashCounter(0) , mAttached(false) , mKeepAttached(false) { MOZ_COUNT_CTOR(CompositableHost); @@ -88,21 +74,19 @@ CompositableHost::CompositableHost(const CompositableHost::~CompositableHost() { MOZ_COUNT_DTOR(CompositableHost); } PCompositableParent* CompositableHost::CreateIPDLActor(CompositableParentManager* aMgr, - const TextureInfo& aTextureInfo, - uint64_t aID, - PImageContainerParent* aImageContainer) + const TextureInfo& aTextureInfo) { - return new CompositableParent(aMgr, aTextureInfo, aID, aImageContainer); + return new CompositableParent(aMgr, aTextureInfo); } bool CompositableHost::DestroyIPDLActor(PCompositableParent* aActor) { delete aActor; return true; } @@ -226,67 +210,10 @@ CompositableHost::DumpTextureHost(std::s } void CompositableHost::ReceivedDestroy(PCompositableParent* aActor) { static_cast<CompositableParent*>(aActor)->RecvDestroy(); } -namespace CompositableMap { - -typedef std::map<uint64_t, PCompositableParent*> CompositableMap_t; -static CompositableMap_t* sCompositableMap = nullptr; -bool IsCreated() { - return sCompositableMap != nullptr; -} -PCompositableParent* Get(uint64_t aID) -{ - if (!IsCreated() || aID == 0) { - return nullptr; - } - CompositableMap_t::iterator it = sCompositableMap->find(aID); - if (it == sCompositableMap->end()) { - return nullptr; - } - return it->second; -} -void Set(uint64_t aID, PCompositableParent* aParent) -{ - if (!IsCreated() || aID == 0) { - return; - } - (*sCompositableMap)[aID] = aParent; -} -void Erase(uint64_t aID) -{ - if (!IsCreated() || aID == 0) { - return; - } - CompositableMap_t::iterator it = sCompositableMap->find(aID); - if (it != sCompositableMap->end()) { - sCompositableMap->erase(it); - } -} -void Clear() -{ - if (!IsCreated()) { - return; - } - sCompositableMap->clear(); -} -void Create() -{ - if (sCompositableMap == nullptr) { - sCompositableMap = new CompositableMap_t; - } -} -void Destroy() -{ - Clear(); - delete sCompositableMap; - sCompositableMap = nullptr; -} - -} // namespace CompositableMap - } // namespace layers } // namespace mozilla
--- a/gfx/layers/composite/CompositableHost.h +++ b/gfx/layers/composite/CompositableHost.h @@ -35,23 +35,36 @@ namespace gfx { class DataSourceSurface; } // namespace gfx namespace layers { class Layer; class LayerComposite; class Compositor; -class ImageContainerParent; class ThebesBufferData; class TiledContentHost; class CompositableParentManager; class PCompositableParent; struct EffectChain; +struct AsyncCompositableRef +{ + AsyncCompositableRef() + : mProcessId(mozilla::ipc::kInvalidProcessId), + mAsyncId(0) + {} + AsyncCompositableRef(base::ProcessId aProcessId, uint64_t aAsyncId) + : mProcessId(aProcessId), mAsyncId(aAsyncId) + {} + explicit operator bool() const { return !!mAsyncId; } + base::ProcessId mProcessId; + uint64_t mAsyncId; +}; + /** * The compositor-side counterpart to CompositableClient. Responsible for * updating textures and data about textures from IPC and how textures are * composited (tiling, double buffering, etc.). * * Update (for images/canvases) and UpdateThebes (for Thebes) are called during * the layers transaction to update the Compositbale's textures from the * content side. The actual update (and any syncronous upload) is done by the @@ -130,18 +143,16 @@ public: Compositor* GetCompositor() const { return mCompositor; } Layer* GetLayer() const { return mLayer; } void SetLayer(Layer* aLayer) { mLayer = aLayer; } - virtual void SetImageContainer(ImageContainerParent* aImageContainer) {} - virtual TiledContentHost* AsTiledContentHost() { return nullptr; } typedef uint32_t AttachFlags; static const AttachFlags NO_FLAGS = 0; static const AttachFlags ALLOW_REATTACH = 1; static const AttachFlags KEEP_ATTACHED = 2; static const AttachFlags FORCE_DETACH = 2; @@ -207,48 +218,45 @@ public: // Called every time this is composited void BumpFlashCounter() { mFlashCounter = mFlashCounter >= DIAGNOSTIC_FLASH_COUNTER_MAX ? DIAGNOSTIC_FLASH_COUNTER_MAX : mFlashCounter + 1; } static PCompositableParent* CreateIPDLActor(CompositableParentManager* mgr, - const TextureInfo& textureInfo, - uint64_t asyncID, - PImageContainerParent* aImageContainer = nullptr); + const TextureInfo& textureInfo); static bool DestroyIPDLActor(PCompositableParent* actor); static CompositableHost* FromIPDLActor(PCompositableParent* actor); uint64_t GetCompositorID() const { return mCompositorID; } - uint64_t GetAsyncID() const { return mAsyncID; } + const AsyncCompositableRef& GetAsyncRef() const { return mAsyncRef; } + void SetAsyncRef(const AsyncCompositableRef& aRef) { mAsyncRef = aRef; } void SetCompositorID(uint64_t aID) { mCompositorID = aID; } - void SetAsyncID(uint64_t aID) { mAsyncID = aID; } - virtual bool Lock() { return false; } virtual void Unlock() { } virtual already_AddRefed<TexturedEffect> GenEffect(const gfx::SamplingFilter aSamplingFilter) { return nullptr; } /// Called when shutting down the layer tree. /// This is a good place to clear all potential gpu resources before the widget /// is is destroyed. virtual void CleanupResources() {} protected: TextureInfo mTextureInfo; - uint64_t mAsyncID; + AsyncCompositableRef mAsyncRef; uint64_t mCompositorID; RefPtr<Compositor> mCompositor; Layer* mLayer; uint32_t mFlashCounter; // used when the pref "layers.flash-borders" is true. bool mAttached; bool mKeepAttached; }; @@ -270,49 +278,12 @@ public: bool Failed() const { return !mSucceeded; } private: RefPtr<CompositableHost> mHost; bool mSucceeded; }; -/** - * Global CompositableMap, to use in the compositor thread only. - * - * PCompositable and PLayer can, in the case of async textures, be managed by - * different top level protocols. In this case they don't share the same - * communication channel and we can't send an OpAttachCompositable (PCompositable, - * PLayer) message. - * - * In order to attach a layer and the right compositable if the the compositable - * is async, we store references to the async compositables in a CompositableMap - * that is accessed only on the compositor thread. During a layer transaction we - * send the message OpAttachAsyncCompositable(ID, PLayer), and on the compositor - * side we lookup the ID in the map and attach the corresponding compositable to - * the layer. - * - * CompositableMap must be global because the image bridge doesn't have any - * reference to whatever we have created with PLayerTransaction. So, the only way to - * actually connect these two worlds is to have something global that they can - * both query (in the same thread). The map is not allocated the map on the - * stack to avoid the badness of static initialization. - * - * Also, we have a compositor/PLayerTransaction protocol/etc. per layer manager, and the - * ImageBridge is used by all the existing compositors that have a video, so - * there isn't an instance or "something" that lives outside the boudaries of a - * given layer manager on the compositor thread except the image bridge and the - * thread itself. - */ -namespace CompositableMap { - void Create(); - void Destroy(); - PCompositableParent* Get(uint64_t aID); - void Set(uint64_t aID, PCompositableParent* aParent); - void Erase(uint64_t aID); - void Clear(); -} // namespace CompositableMap - - } // namespace layers } // namespace mozilla #endif
--- a/gfx/layers/composite/ImageHost.cpp +++ b/gfx/layers/composite/ImageHost.cpp @@ -5,17 +5,16 @@ #include "ImageHost.h" #include "LayersLogging.h" // for AppendToString #include "composite/CompositableHost.h" // for CompositableHost, etc #include "ipc/IPCMessageUtils.h" // for null_t #include "mozilla/layers/Compositor.h" // for Compositor #include "mozilla/layers/Effects.h" // for TexturedEffect, Effect, etc -#include "mozilla/layers/ImageContainerParent.h" #include "mozilla/layers/LayerManagerComposite.h" // for TexturedEffect, Effect, etc #include "nsAString.h" #include "nsDebug.h" // for NS_WARNING, NS_ASSERTION #include "nsPrintfCString.h" // for nsPrintfCString #include "nsString.h" // for nsAutoCString #define BIAS_TIME_MS 1.0 @@ -24,26 +23,24 @@ namespace mozilla { using namespace gfx; namespace layers { class ISurfaceAllocator; ImageHost::ImageHost(const TextureInfo& aTextureInfo) : CompositableHost(aTextureInfo) - , mImageContainer(nullptr) , mLastFrameID(-1) , mLastProducerID(-1) , mBias(BIAS_NONE) , mLocked(false) {} ImageHost::~ImageHost() { - SetImageContainer(nullptr); } void ImageHost::UseTextureHost(const nsTArray<TimedTexture>& aTextures) { MOZ_ASSERT(!mLocked); CompositableHost::UseTextureHost(aTextures); @@ -344,22 +341,25 @@ ImageHost::Composite(LayerComposite* aLa DiagnosticFlags diagnosticFlags = DiagnosticFlags::IMAGE; if (effect->mType == EffectTypes::NV12) { diagnosticFlags |= DiagnosticFlags::NV12; } else if (effect->mType == EffectTypes::YCBCR) { diagnosticFlags |= DiagnosticFlags::YCBCR; } if (mLastFrameID != img->mFrameID || mLastProducerID != img->mProducerID) { - if (mImageContainer) { + if (mAsyncRef) { + ImageCompositeNotificationInfo info; + info.mImageBridgeProcessId = mAsyncRef.mProcessId; + info.mNotification = ImageCompositeNotification( + mAsyncRef.mAsyncId, + img->mTimeStamp, GetCompositor()->GetCompositionTime(), + img->mFrameID, img->mProducerID); static_cast<LayerManagerComposite*>(aLayer->GetLayerManager())-> - AppendImageCompositeNotification(ImageCompositeNotification( - mImageContainer, nullptr, - img->mTimeStamp, GetCompositor()->GetCompositionTime(), - img->mFrameID, img->mProducerID)); + AppendImageCompositeNotification(info); } mLastFrameID = img->mFrameID; mLastProducerID = img->mProducerID; } aEffectChain.mPrimaryEffect = effect; gfx::Rect pictureRect(0, 0, img->mPictureRect.width, img->mPictureRect.height); BigImageIterator* it = mCurrentTextureSource->AsBigImageIterator(); if (it) { @@ -573,22 +573,10 @@ ImageHost::GenEffect(const gfx::Sampling return CreateTexturedEffect(mCurrentTextureHost, mCurrentTextureSource, aSamplingFilter, isAlphaPremultiplied, GetRenderState()); } -void -ImageHost::SetImageContainer(ImageContainerParent* aImageContainer) -{ - if (mImageContainer) { - mImageContainer->mImageHosts.RemoveElement(this); - } - mImageContainer = aImageContainer; - if (mImageContainer) { - mImageContainer->mImageHosts.AppendElement(this); - } -} - } // namespace layers } // namespace mozilla
--- a/gfx/layers/composite/ImageHost.h +++ b/gfx/layers/composite/ImageHost.h @@ -62,18 +62,16 @@ public: virtual TextureHost* GetAsTextureHost(gfx::IntRect* aPictureRect = nullptr) override; virtual void Attach(Layer* aLayer, Compositor* aCompositor, AttachFlags aFlags = NO_FLAGS) override; virtual void SetCompositor(Compositor* aCompositor) override; - virtual void SetImageContainer(ImageContainerParent* aImageContainer) override; - gfx::IntSize GetImageSize() const override; virtual LayerRenderState GetRenderState() override; virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix) override; virtual void Dump(std::stringstream& aStream, const char* aPrefix = "", @@ -142,18 +140,16 @@ protected: * it depends only on mImages, mCompositor->GetCompositionTime(), and mBias. * mBias is updated at the end of Composite(). */ const TimedImage* ChooseImage() const; TimedImage* ChooseImage(); int ChooseImageIndex() const; nsTArray<TimedImage> mImages; - // Weak reference, will be null if mImageContainer has been destroyed. - ImageContainerParent* mImageContainer; int32_t mLastFrameID; int32_t mLastProducerID; /** * Bias to apply to the next frame. */ Bias mBias; bool mLocked;
--- a/gfx/layers/composite/LayerManagerComposite.h +++ b/gfx/layers/composite/LayerManagerComposite.h @@ -60,16 +60,21 @@ class RefLayerComposite; class PaintedLayerComposite; class TextRenderer; class CompositingRenderTarget; struct FPSState; class PaintCounter; static const int kVisualWarningDuration = 150; // ms +struct ImageCompositeNotificationInfo { + base::ProcessId mImageBridgeProcessId; + ImageCompositeNotification mNotification; +}; + // An implementation of LayerManager that acts as a pair with ClientLayerManager // and is mirrored across IPDL. This gets managed/updated by LayerTransactionParent. class HostLayerManager : public LayerManager { public: HostLayerManager(); ~HostLayerManager(); @@ -123,17 +128,17 @@ public: virtual void UpdateRenderBounds(const gfx::IntRect& aRect) {} // Called by CompositorBridgeParent when a new compositor has been created due // to a device reset. The layer manager must clear any cached resources // attached to the old compositor, and make a best effort at ignoring // layer or texture updates against the old compositor. virtual void ChangeCompositor(Compositor* aNewCompositor) = 0; - void ExtractImageCompositeNotifications(nsTArray<ImageCompositeNotification>* aNotifications) + void ExtractImageCompositeNotifications(nsTArray<ImageCompositeNotificationInfo>* aNotifications) { aNotifications->AppendElements(Move(mImageCompositeNotifications)); } /** * LayerManagerComposite provides sophisticated debug overlays * that can request a next frame. */ @@ -160,17 +165,17 @@ public: // overlay. void SetWindowOverlayChanged() { mWindowOverlayChanged = true; } void SetPaintTime(const TimeDuration& aPaintTime) { mLastPaintTime = aPaintTime; } protected: bool mDebugOverlayWantsNextFrame; - nsTArray<ImageCompositeNotification> mImageCompositeNotifications; + nsTArray<ImageCompositeNotificationInfo> mImageCompositeNotifications; // Testing property. If hardware composer is supported, this will return // true if the last frame was deemed 'too complicated' to be rendered. float mWarningLevel; mozilla::TimeStamp mWarnTime; bool mWindowOverlayChanged; TimeDuration mLastPaintTime; TimeStamp mRenderStartTime; @@ -341,27 +346,30 @@ public: mUnusedApzTransformWarning = true; } void DisabledApzWarning() { mDisabledApzWarning = true; } bool AsyncPanZoomEnabled() const override; - void AppendImageCompositeNotification(const ImageCompositeNotification& aNotification) +public: + void AppendImageCompositeNotification(const ImageCompositeNotificationInfo& aNotification) { // Only send composite notifications when we're drawing to the screen, // because that's what they mean. // Also when we're not drawing to the screen, DidComposite will not be // called to extract and send these notifications, so they might linger // and contain stale ImageContainerParent pointers. if (!mCompositor->GetTargetContext()) { mImageCompositeNotifications.AppendElement(aNotification); } } + +public: virtual TextureFactoryIdentifier GetTextureFactoryIdentifier() override { return mCompositor->GetTextureFactoryIdentifier(); } void ForcePresent() override { mCompositor->ForcePresent(); } private:
--- a/gfx/layers/ipc/CompositorBridgeParent.cpp +++ b/gfx/layers/ipc/CompositorBridgeParent.cpp @@ -1137,58 +1137,54 @@ CompositorBridgeParent::ScheduleRotation NewCancelableRunnableMethod(this, &CompositorBridgeParent::ForceComposition); mForceCompositionTask = task; ScheduleTask(task.forget(), gfxPrefs::OrientationSyncMillis()); } } void CompositorBridgeParent::ShadowLayersUpdated(LayerTransactionParent* aLayerTree, - const uint64_t& aTransactionId, - const TargetConfig& aTargetConfig, - const InfallibleTArray<PluginWindowData>& aUnused, - bool aIsFirstPaint, - bool aScheduleComposite, - uint32_t aPaintSequenceNumber, - bool aIsRepeatTransaction, - int32_t aPaintSyncId, + const TransactionInfo& aInfo, bool aHitTestUpdate) { - ScheduleRotationOnCompositorThread(aTargetConfig, aIsFirstPaint); + const TargetConfig& targetConfig = aInfo.targetConfig(); + + ScheduleRotationOnCompositorThread(targetConfig, aInfo.isFirstPaint()); // Instruct the LayerManager to update its render bounds now. Since all the orientation // change, dimension change would be done at the stage, update the size here is free of // race condition. - mLayerManager->UpdateRenderBounds(aTargetConfig.naturalBounds()); - mLayerManager->SetRegionToClear(aTargetConfig.clearRegion()); + mLayerManager->UpdateRenderBounds(targetConfig.naturalBounds()); + mLayerManager->SetRegionToClear(targetConfig.clearRegion()); if (mLayerManager->GetCompositor()) { - mLayerManager->GetCompositor()->SetScreenRotation(aTargetConfig.rotation()); + mLayerManager->GetCompositor()->SetScreenRotation(targetConfig.rotation()); } - mCompositionManager->Updated(aIsFirstPaint, aTargetConfig, aPaintSyncId); + mCompositionManager->Updated(aInfo.isFirstPaint(), targetConfig, aInfo.paintSyncId()); Layer* root = aLayerTree->GetRoot(); mLayerManager->SetRoot(root); - if (mApzcTreeManager && !aIsRepeatTransaction && aHitTestUpdate) { + if (mApzcTreeManager && !aInfo.isRepeatTransaction() && aHitTestUpdate) { AutoResolveRefLayers resolve(mCompositionManager); - mApzcTreeManager->UpdateHitTestingTree(mRootLayerTreeID, root, aIsFirstPaint, - mRootLayerTreeID, aPaintSequenceNumber); + mApzcTreeManager->UpdateHitTestingTree( + mRootLayerTreeID, root, aInfo.isFirstPaint(), + mRootLayerTreeID, aInfo.paintSequenceNumber()); } // The transaction ID might get reset to 1 if the page gets reloaded, see // https://bugzilla.mozilla.org/show_bug.cgi?id=1145295#c41 // Otherwise, it should be continually increasing. - MOZ_ASSERT(aTransactionId == 1 || aTransactionId > mPendingTransaction); - mPendingTransaction = aTransactionId; + MOZ_ASSERT(aInfo.id() == 1 || aInfo.id() > mPendingTransaction); + mPendingTransaction = aInfo.id(); if (root) { SetShadowProperties(root); } - if (aScheduleComposite) { + if (aInfo.scheduleComposite()) { ScheduleComposition(); if (mPaused) { TimeStamp now = TimeStamp::Now(); DidComposite(now, now); } } mLayerManager->NotifyShadowTreeTransaction(); } @@ -1719,17 +1715,17 @@ CompositorBridgeParent::LayerTreeState:: void CompositorBridgeParent::DidComposite(TimeStamp& aCompositeStart, TimeStamp& aCompositeEnd) { Unused << SendDidComposite(0, mPendingTransaction, aCompositeStart, aCompositeEnd); mPendingTransaction = 0; if (mLayerManager) { - nsTArray<ImageCompositeNotification> notifications; + nsTArray<ImageCompositeNotificationInfo> notifications; mLayerManager->ExtractImageCompositeNotifications(¬ifications); if (!notifications.IsEmpty()) { Unused << ImageBridgeParent::NotifyImageComposites(notifications); } } MonitorAutoLock lock(*sIndirectLayerTreesLock); ForEachIndirectLayerTree([&] (LayerTreeState* lts, const uint64_t& aLayersId) -> void {
--- a/gfx/layers/ipc/CompositorBridgeParent.h +++ b/gfx/layers/ipc/CompositorBridgeParent.h @@ -85,24 +85,17 @@ private: class CompositorBridgeParentBase : public PCompositorBridgeParent, public HostIPCAllocator, public ShmemAllocator, public MetricsSharingController { public: virtual void ShadowLayersUpdated(LayerTransactionParent* aLayerTree, - const uint64_t& aTransactionId, - const TargetConfig& aTargetConfig, - const InfallibleTArray<PluginWindowData>& aPlugins, - bool aIsFirstPaint, - bool aScheduleComposite, - uint32_t aPaintSequenceNumber, - bool aIsRepeatTransaction, - int32_t aPaintSyncId, + const TransactionInfo& aInfo, bool aHitTestUpdate) = 0; virtual AsyncCompositionManager* GetCompositionManager(LayerTransactionParent* aLayerTree) { return nullptr; } virtual void NotifyClearCachedResources(LayerTransactionParent* aLayerTree) { } virtual void ForceComposite(LayerTransactionParent* aLayerTree) { } virtual bool SetTestSampleTime(LayerTransactionParent* aLayerTree, @@ -215,24 +208,17 @@ public: virtual mozilla::ipc::IPCResult RecvNotifyApproximatelyVisibleRegion(const ScrollableLayerGuid& aGuid, const CSSIntRegion& aRegion) override; virtual mozilla::ipc::IPCResult RecvAllPluginsCaptured() override; virtual void ActorDestroy(ActorDestroyReason why) override; virtual void ShadowLayersUpdated(LayerTransactionParent* aLayerTree, - const uint64_t& aTransactionId, - const TargetConfig& aTargetConfig, - const InfallibleTArray<PluginWindowData>& aPlugins, - bool aIsFirstPaint, - bool aScheduleComposite, - uint32_t aPaintSequenceNumber, - bool aIsRepeatTransaction, - int32_t aPaintSyncId, + const TransactionInfo& aInfo, bool aHitTestUpdate) override; virtual void ForceComposite(LayerTransactionParent* aLayerTree) override; virtual bool SetTestSampleTime(LayerTransactionParent* aLayerTree, const TimeStamp& aTime) override; virtual void LeaveTestMode(LayerTransactionParent* aLayerTree) override; virtual void ApplyAsyncProperties(LayerTransactionParent* aLayerTree) override; virtual void FlushApzRepaints(const LayerTransactionParent* aLayerTree) override;
--- a/gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp +++ b/gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp @@ -203,64 +203,64 @@ CrossProcessCompositorBridgeParent::Recv } } return IPC_FAIL_NO_REASON(this); } void CrossProcessCompositorBridgeParent::ShadowLayersUpdated( LayerTransactionParent* aLayerTree, - const uint64_t& aTransactionId, - const TargetConfig& aTargetConfig, - const InfallibleTArray<PluginWindowData>& aPlugins, - bool aIsFirstPaint, - bool aScheduleComposite, - uint32_t aPaintSequenceNumber, - bool aIsRepeatTransaction, - int32_t /*aPaintSyncId: unused*/, + const TransactionInfo& aInfo, bool aHitTestUpdate) { uint64_t id = aLayerTree->GetId(); MOZ_ASSERT(id != 0); CompositorBridgeParent::LayerTreeState* state = CompositorBridgeParent::GetIndirectShadowTree(id); if (!state) { return; } MOZ_ASSERT(state->mParent); - state->mParent->ScheduleRotationOnCompositorThread(aTargetConfig, aIsFirstPaint); + state->mParent->ScheduleRotationOnCompositorThread( + aInfo.targetConfig(), + aInfo.isFirstPaint()); Layer* shadowRoot = aLayerTree->GetRoot(); if (shadowRoot) { CompositorBridgeParent::SetShadowProperties(shadowRoot); } - UpdateIndirectTree(id, shadowRoot, aTargetConfig); + UpdateIndirectTree(id, shadowRoot, aInfo.targetConfig()); // Cache the plugin data for this remote layer tree - state->mPluginData = aPlugins; + state->mPluginData = aInfo.plugins(); state->mUpdatedPluginDataAvailable = true; - state->mParent->NotifyShadowTreeTransaction(id, aIsFirstPaint, aScheduleComposite, - aPaintSequenceNumber, aIsRepeatTransaction, aHitTestUpdate); + state->mParent->NotifyShadowTreeTransaction( + id, + aInfo.isFirstPaint(), + aInfo.scheduleComposite(), + aInfo.paintSequenceNumber(), + aInfo.isRepeatTransaction(), + aHitTestUpdate); // Send the 'remote paint ready' message to the content thread if it has already asked. if(mNotifyAfterRemotePaint) { Unused << SendRemotePaintIsReady(); mNotifyAfterRemotePaint = false; } if (aLayerTree->ShouldParentObserveEpoch()) { // Note that we send this through the window compositor, since this needs // to reach the widget owning the tab. Unused << state->mParent->SendObserveLayerUpdate(id, aLayerTree->GetChildEpoch(), true); } - aLayerTree->SetPendingTransactionId(aTransactionId); + aLayerTree->SetPendingTransactionId(aInfo.id()); } void CrossProcessCompositorBridgeParent::DidComposite( uint64_t aId, TimeStamp& aCompositeStart, TimeStamp& aCompositeEnd) {
--- a/gfx/layers/ipc/CrossProcessCompositorBridgeParent.h +++ b/gfx/layers/ipc/CrossProcessCompositorBridgeParent.h @@ -89,24 +89,17 @@ public: AllocPLayerTransactionParent(const nsTArray<LayersBackend>& aBackendHints, const uint64_t& aId, TextureFactoryIdentifier* aTextureFactoryIdentifier, bool *aSuccess) override; virtual bool DeallocPLayerTransactionParent(PLayerTransactionParent* aLayers) override; virtual void ShadowLayersUpdated(LayerTransactionParent* aLayerTree, - const uint64_t& aTransactionId, - const TargetConfig& aTargetConfig, - const InfallibleTArray<PluginWindowData>& aPlugins, - bool aIsFirstPaint, - bool aScheduleComposite, - uint32_t aPaintSequenceNumber, - bool aIsRepeatTransaction, - int32_t /*aPaintSyncId: unused*/, + const TransactionInfo& aInfo, bool aHitTestUpdate) override; virtual void ForceComposite(LayerTransactionParent* aLayerTree) override; virtual void NotifyClearCachedResources(LayerTransactionParent* aLayerTree) override; virtual bool SetTestSampleTime(LayerTransactionParent* aLayerTree, const TimeStamp& aTime) override; virtual void LeaveTestMode(LayerTransactionParent* aLayerTree) override; virtual void ApplyAsyncProperties(LayerTransactionParent* aLayerTree) override;
--- a/gfx/layers/ipc/ImageBridgeChild.cpp +++ b/gfx/layers/ipc/ImageBridgeChild.cpp @@ -23,17 +23,16 @@ #include "mozilla/layers/AsyncCanvasRenderer.h" #include "mozilla/media/MediaSystemResourceManager.h" // for MediaSystemResourceManager #include "mozilla/media/MediaSystemResourceManagerChild.h" // for MediaSystemResourceManagerChild #include "mozilla/layers/CompositableChild.h" #include "mozilla/layers/CompositableClient.h" // for CompositableChild, etc #include "mozilla/layers/CompositorThread.h" #include "mozilla/layers/ISurfaceAllocator.h" // for ISurfaceAllocator #include "mozilla/layers/ImageClient.h" // for ImageClient -#include "mozilla/layers/ImageContainerChild.h" #include "mozilla/layers/LayersMessages.h" // for CompositableOperation #include "mozilla/layers/PCompositableChild.h" // for PCompositableChild #include "mozilla/layers/TextureClient.h" // for TextureClient #include "mozilla/dom/ContentChild.h" #include "mozilla/mozalloc.h" // for operator new, etc #include "mtransport/runnable_utils.h" #include "nsContentUtils.h" #include "nsISupportsImpl.h" // for ImageContainer::AddRef, etc @@ -326,21 +325,20 @@ ImageBridgeChild::DeallocPImageBridgeChi { this->Release(); } void ImageBridgeChild::CreateImageClientSync(SynchronousTask* aTask, RefPtr<ImageClient>* result, CompositableType aType, - ImageContainer* aImageContainer, - ImageContainerChild* aContainerChild) + ImageContainer* aImageContainer) { AutoCompleteTask complete(aTask); - *result = CreateImageClientNow(aType, aImageContainer, aContainerChild); + *result = CreateImageClientNow(aType, aImageContainer); } // dispatched function void ImageBridgeChild::CreateCanvasClientSync(SynchronousTask* aTask, CanvasClient::CanvasClientType aType, TextureFlags aFlags, RefPtr<CanvasClient>* const outResult) @@ -348,16 +346,17 @@ ImageBridgeChild::CreateCanvasClientSync AutoCompleteTask complete(aTask); *outResult = CreateCanvasClientNow(aType, aFlags); } ImageBridgeChild::ImageBridgeChild() : mCanSend(false) , mCalledClose(false) , mFwdTransactionId(0) + , mContainerMapLock("ImageBridgeChild.mContainerMapLock") { MOZ_ASSERT(NS_IsMainThread()); mTxn = new CompositableTransaction(); } ImageBridgeChild::~ImageBridgeChild() { @@ -375,79 +374,78 @@ ImageBridgeChild::MarkShutDown() void ImageBridgeChild::Connect(CompositableClient* aCompositable, ImageContainer* aImageContainer) { MOZ_ASSERT(aCompositable); MOZ_ASSERT(InImageBridgeChildThread()); MOZ_ASSERT(CanSend()); - uint64_t id = 0; + // Note: this is static, rather than per-IBC, so IDs are not re-used across + // ImageBridgeChild instances. This is relevant for the GPU process, where + // we don't want old IDs to potentially leak into a recreated ImageBridge. + static uint64_t sNextID = 1; + uint64_t id = sNextID++; - PImageContainerChild* imageContainerChild = nullptr; - if (aImageContainer) - imageContainerChild = aImageContainer->GetPImageContainerChild(); + { + MutexAutoLock lock(mContainerMapLock); + MOZ_ASSERT(!mImageContainers.Contains(id)); + mImageContainers.Put(id, aImageContainer); + } PCompositableChild* child = - SendPCompositableConstructor(aCompositable->GetTextureInfo(), - imageContainerChild, &id); + SendPCompositableConstructor(aCompositable->GetTextureInfo(), id); if (!child) { return; } aCompositable->InitIPDLActor(child, id); } +void +ImageBridgeChild::ForgetImageContainer(uint64_t aAsyncContainerID) +{ + MutexAutoLock lock(mContainerMapLock); + mImageContainers.Remove(aAsyncContainerID); +} + PCompositableChild* -ImageBridgeChild::AllocPCompositableChild(const TextureInfo& aInfo, - PImageContainerChild* aChild, uint64_t* aID) +ImageBridgeChild::AllocPCompositableChild(const TextureInfo& aInfo, const uint64_t& aID) { MOZ_ASSERT(CanSend()); - return AsyncCompositableChild::CreateActor(); + return AsyncCompositableChild::CreateActor(aID); } bool ImageBridgeChild::DeallocPCompositableChild(PCompositableChild* aActor) { + AsyncCompositableChild* actor = static_cast<AsyncCompositableChild*>(aActor); + MOZ_ASSERT(actor->GetAsyncID()); + + { + MutexAutoLock lock(mContainerMapLock); + mImageContainers.Remove(actor->GetAsyncID()); + } + AsyncCompositableChild::DestroyActor(aActor); return true; } - Thread* ImageBridgeChild::GetThread() const { return sImageBridgeChildThread; } /* static */ RefPtr<ImageBridgeChild> ImageBridgeChild::GetSingleton() { StaticMutexAutoLock lock(sImageBridgeSingletonLock); return sImageBridgeChildSingleton; } void -ImageBridgeChild::ReleaseImageContainer(RefPtr<ImageContainerChild> aChild) -{ - if (!aChild) { - return; - } - - if (!InImageBridgeChildThread()) { - RefPtr<Runnable> runnable = WrapRunnable( - RefPtr<ImageBridgeChild>(this), - &ImageBridgeChild::ReleaseImageContainer, - aChild); - GetMessageLoop()->PostTask(runnable.forget()); - return; - } - - aChild->SendAsyncDelete(); -} - -void ImageBridgeChild::ReleaseTextureClientNow(TextureClient* aClient) { MOZ_ASSERT(InImageBridgeChildThread()); RELEASE_MANUALLY(aClient); } /* static */ void ImageBridgeChild::DispatchReleaseTextureClient(TextureClient* aClient) @@ -847,59 +845,49 @@ ImageBridgeChild::IdentifyCompositorText { if (RefPtr<ImageBridgeChild> child = GetSingleton()) { child->IdentifyTextureHost(aIdentifier); } } RefPtr<ImageClient> ImageBridgeChild::CreateImageClient(CompositableType aType, - ImageContainer* aImageContainer, - ImageContainerChild* aContainerChild) + ImageContainer* aImageContainer) { if (InImageBridgeChildThread()) { - return CreateImageClientNow(aType, aImageContainer, aContainerChild); + return CreateImageClientNow(aType, aImageContainer); } SynchronousTask task("CreateImageClient Lock"); RefPtr<ImageClient> result = nullptr; RefPtr<Runnable> runnable = WrapRunnable( RefPtr<ImageBridgeChild>(this), &ImageBridgeChild::CreateImageClientSync, &task, &result, aType, - aImageContainer, - aContainerChild); + aImageContainer); GetMessageLoop()->PostTask(runnable.forget()); task.Wait(); return result; } RefPtr<ImageClient> ImageBridgeChild::CreateImageClientNow(CompositableType aType, - ImageContainer* aImageContainer, - ImageContainerChild* aContainerChild) + ImageContainer* aImageContainer) { MOZ_ASSERT(InImageBridgeChildThread()); if (!CanSend()) { return nullptr; } - if (aImageContainer) { - aContainerChild->RegisterWithIPDL(); - if (!SendPImageContainerConstructor(aContainerChild)) { - return nullptr; - } - } - RefPtr<ImageClient> client = ImageClient::CreateImageClient(aType, this, TextureFlags::NO_FLAGS); MOZ_ASSERT(client, "failed to create ImageClient"); if (client) { client->Connect(aImageContainer); } return client; } @@ -1088,31 +1076,16 @@ ImageBridgeChild::AllocPMediaSystemResou bool ImageBridgeChild::DeallocPMediaSystemResourceManagerChild(PMediaSystemResourceManagerChild* aActor) { MOZ_ASSERT(aActor); delete static_cast<mozilla::media::MediaSystemResourceManagerChild*>(aActor); return true; } -PImageContainerChild* -ImageBridgeChild::AllocPImageContainerChild() -{ - // we always use the "power-user" ctor - MOZ_CRASH("not reached"); - return nullptr; -} - -bool -ImageBridgeChild::DeallocPImageContainerChild(PImageContainerChild* actor) -{ - static_cast<ImageContainerChild*>(actor)->UnregisterFromIPDL(); - return true; -} - mozilla::ipc::IPCResult ImageBridgeChild::RecvParentAsyncMessages(InfallibleTArray<AsyncParentMessageData>&& aMessages) { for (AsyncParentMessageArray::index_type i = 0; i < aMessages.Length(); ++i) { const AsyncParentMessageData& message = aMessages[i]; switch (message.type()) { case AsyncParentMessageData::TOpNotifyNotUsed: { @@ -1127,20 +1100,23 @@ ImageBridgeChild::RecvParentAsyncMessage } return IPC_OK(); } mozilla::ipc::IPCResult ImageBridgeChild::RecvDidComposite(InfallibleTArray<ImageCompositeNotification>&& aNotifications) { for (auto& n : aNotifications) { - ImageContainerChild* child = - static_cast<ImageContainerChild*>(n.imageContainerChild()); - if (child) { - child->NotifyComposite(n); + RefPtr<ImageContainer> imageContainer; + { + MutexAutoLock lock(mContainerMapLock); + imageContainer = mImageContainers.Get(n.asyncCompositableID()); + } + if (imageContainer) { + imageContainer->NotifyComposite(n); } } return IPC_OK(); } PTextureChild* ImageBridgeChild::CreateTexture(const SurfaceDescriptor& aSharedData, LayersBackend aLayersBackend,
--- a/gfx/layers/ipc/ImageBridgeChild.h +++ b/gfx/layers/ipc/ImageBridgeChild.h @@ -34,17 +34,16 @@ namespace ipc { class Shmem; } // namespace ipc namespace layers { class AsyncCanvasRenderer; class ImageClient; class ImageContainer; -class ImageContainerChild; class ImageBridgeParent; class CompositableClient; struct CompositableTransaction; class Image; class TextureClient; class SynchronousTask; struct AllocShmemParams; @@ -165,56 +164,48 @@ public: * * Can be called from any thread. */ virtual MessageLoop * GetMessageLoop() const override; virtual base::ProcessId GetParentPid() const override { return OtherPid(); } PCompositableChild* AllocPCompositableChild(const TextureInfo& aInfo, - PImageContainerChild* aChild, uint64_t* aID) override; + const uint64_t& aID) override; bool DeallocPCompositableChild(PCompositableChild* aActor) override; virtual PTextureChild* AllocPTextureChild(const SurfaceDescriptor& aSharedData, const LayersBackend& aLayersBackend, const TextureFlags& aFlags, const uint64_t& aSerial) override; virtual bool DeallocPTextureChild(PTextureChild* actor) override; PMediaSystemResourceManagerChild* AllocPMediaSystemResourceManagerChild() override; bool DeallocPMediaSystemResourceManagerChild(PMediaSystemResourceManagerChild* aActor) override; - virtual PImageContainerChild* - AllocPImageContainerChild() override; - virtual bool - DeallocPImageContainerChild(PImageContainerChild* actor) override; - virtual mozilla::ipc::IPCResult RecvParentAsyncMessages(InfallibleTArray<AsyncParentMessageData>&& aMessages) override; virtual mozilla::ipc::IPCResult RecvDidComposite(InfallibleTArray<ImageCompositeNotification>&& aNotifications) override; // Create an ImageClient from any thread. RefPtr<ImageClient> CreateImageClient( CompositableType aType, - ImageContainer* aImageContainer, - ImageContainerChild* aContainerChild); + ImageContainer* aImageContainer); // Create an ImageClient from the ImageBridge thread. RefPtr<ImageClient> CreateImageClientNow( CompositableType aType, - ImageContainer* aImageContainer, - ImageContainerChild* aContainerChild); + ImageContainer* aImageContainer); already_AddRefed<CanvasClient> CreateCanvasClient(CanvasClient::CanvasClientType aType, TextureFlags aFlag); - void ReleaseImageContainer(RefPtr<ImageContainerChild> aChild); void UpdateAsyncCanvasRenderer(AsyncCanvasRenderer* aClient); void UpdateImageClient(RefPtr<ImageClient> aClient, RefPtr<ImageContainer> aContainer); static void DispatchReleaseTextureClient(TextureClient* aClient); /** * Flush all Images sent to CompositableHost. */ void FlushAllImages(ImageClient* aClient, ImageContainer* aContainer); @@ -238,18 +229,17 @@ private: CanvasClient::CanvasClientType aType, TextureFlags aFlags, RefPtr<CanvasClient>* const outResult); void CreateImageClientSync( SynchronousTask* aTask, RefPtr<ImageClient>* result, CompositableType aType, - ImageContainer* aImageContainer, - ImageContainerChild* aContainerChild); + ImageContainer* aImageContainer); void ReleaseTextureClientNow(TextureClient* aClient); void UpdateAsyncCanvasRendererNow(AsyncCanvasRenderer* aClient); void UpdateAsyncCanvasRendererSync( SynchronousTask* aTask, AsyncCanvasRenderer* aWrapper); @@ -275,16 +265,18 @@ public: virtual void UseTextures(CompositableClient* aCompositable, const nsTArray<TimedTextureClient>& aTextures) override; virtual void UseComponentAlphaTextures(CompositableClient* aCompositable, TextureClient* aClientOnBlack, TextureClient* aClientOnWhite) override; void Destroy(CompositableChild* aCompositable) override; + void ForgetImageContainer(uint64_t aAsyncContainerID); + /** * Hold TextureClient ref until end of usage on host side if TextureFlags::RECYCLE is set. * Host side's usage is checked via CompositableRef. */ void HoldUntilCompositableRefReleasedIfNecessary(TextureClient* aClient); /** * Notify id of Texture When host side end its use. Transaction id is used to @@ -387,14 +379,20 @@ private: */ uint64_t mFwdTransactionId; /** * Hold TextureClients refs until end of their usages on host side. * It defer calling of TextureClient recycle callback. */ nsDataHashtable<nsUint64HashKey, RefPtr<TextureClient> > mTexturesWaitingRecycled; + + /** + * Mapping from async compositable IDs to image containers. + */ + Mutex mContainerMapLock; + nsDataHashtable<nsUint64HashKey, ImageContainer*> mImageContainers; }; } // namespace layers } // namespace mozilla #endif
--- a/gfx/layers/ipc/ImageBridgeParent.cpp +++ b/gfx/layers/ipc/ImageBridgeParent.cpp @@ -54,29 +54,22 @@ ImageBridgeParent::ImageBridgeParent(Mes , mSetChildThreadPriority(false) , mClosed(false) { MOZ_ASSERT(NS_IsMainThread()); sMainLoop = MessageLoop::current(); // creates the map only if it has not been created already, so it is safe // with several bridges - CompositableMap::Create(); sImageBridges[aChildProcessId] = this; SetOtherProcessId(aChildProcessId); } ImageBridgeParent::~ImageBridgeParent() { - nsTArray<PImageContainerParent*> parents; - ManagedPImageContainerParent(parents); - for (PImageContainerParent* p : parents) { - delete p; - } - sImageBridges.erase(OtherPid()); } static StaticRefPtr<ImageBridgeParent> sImageBridgeParentSingleton; void ReleaseImageBridgeParentSingleton() { sImageBridgeParentSingleton = nullptr; } @@ -234,35 +227,43 @@ mozilla::ipc::IPCResult ImageBridgeParen ManagedPTextureParent(textures); for (unsigned int i = 0; i < textures.Length(); ++i) { RefPtr<TextureHost> tex = TextureHost::AsTextureHost(textures[i]); tex->DeallocateDeviceData(); } return IPC_OK(); } -static uint64_t GenImageContainerID() { - static uint64_t sNextImageID = 1; - - ++sNextImageID; - return sNextImageID; -} +PCompositableParent* +ImageBridgeParent::AllocPCompositableParent(const TextureInfo& aInfo, const uint64_t& aID) +{ + PCompositableParent* actor = CompositableHost::CreateIPDLActor(this, aInfo); + if (mCompositables.find(aID) != mCompositables.end()) { + NS_ERROR("Async compositable ID already exists"); + return actor; + } + if (!aID) { + NS_ERROR("Expected non-zero async compositable ID"); + return actor; + } -PCompositableParent* -ImageBridgeParent::AllocPCompositableParent(const TextureInfo& aInfo, - PImageContainerParent* aImageContainer, - uint64_t* aID) -{ - uint64_t id = GenImageContainerID(); - *aID = id; - return CompositableHost::CreateIPDLActor(this, aInfo, id, aImageContainer); + CompositableHost* host = CompositableHost::FromIPDLActor(actor); + + host->SetAsyncRef(AsyncCompositableRef(OtherPid(), aID)); + mCompositables[aID] = host; + + return actor; } bool ImageBridgeParent::DeallocPCompositableParent(PCompositableParent* aActor) { + if (CompositableHost* host = CompositableHost::FromIPDLActor(aActor)) { + const AsyncCompositableRef& ref = host->GetAsyncRef(); + mCompositables.erase(ref.mAsyncId); + } return CompositableHost::DestroyIPDLActor(aActor); } PTextureParent* ImageBridgeParent::AllocPTextureParent(const SurfaceDescriptor& aSharedData, const LayersBackend& aLayersBackend, const TextureFlags& aFlags, const uint64_t& aSerial) @@ -285,67 +286,54 @@ ImageBridgeParent::AllocPMediaSystemReso bool ImageBridgeParent::DeallocPMediaSystemResourceManagerParent(PMediaSystemResourceManagerParent* aActor) { MOZ_ASSERT(aActor); delete static_cast<mozilla::media::MediaSystemResourceManagerParent*>(aActor); return true; } -PImageContainerParent* -ImageBridgeParent::AllocPImageContainerParent() -{ - return new ImageContainerParent(); -} - -bool -ImageBridgeParent::DeallocPImageContainerParent(PImageContainerParent* actor) -{ - delete actor; - return true; -} - void ImageBridgeParent::SendAsyncMessage(const InfallibleTArray<AsyncParentMessageData>& aMessage) { mozilla::Unused << SendParentAsyncMessages(aMessage); } class ProcessIdComparator { public: - bool Equals(const ImageCompositeNotification& aA, - const ImageCompositeNotification& aB) const + bool Equals(const ImageCompositeNotificationInfo& aA, + const ImageCompositeNotificationInfo& aB) const { - return aA.imageContainerParent()->OtherPid() == aB.imageContainerParent()->OtherPid(); + return aA.mImageBridgeProcessId == aB.mImageBridgeProcessId; } - bool LessThan(const ImageCompositeNotification& aA, - const ImageCompositeNotification& aB) const + bool LessThan(const ImageCompositeNotificationInfo& aA, + const ImageCompositeNotificationInfo& aB) const { - return aA.imageContainerParent()->OtherPid() < aB.imageContainerParent()->OtherPid(); + return aA.mImageBridgeProcessId < aB.mImageBridgeProcessId; } }; /* static */ bool -ImageBridgeParent::NotifyImageComposites(nsTArray<ImageCompositeNotification>& aNotifications) +ImageBridgeParent::NotifyImageComposites(nsTArray<ImageCompositeNotificationInfo>& aNotifications) { // Group the notifications by destination process ID and then send the // notifications in one message per group. aNotifications.Sort(ProcessIdComparator()); uint32_t i = 0; bool ok = true; while (i < aNotifications.Length()) { AutoTArray<ImageCompositeNotification,1> notifications; - notifications.AppendElement(aNotifications[i]); + notifications.AppendElement(aNotifications[i].mNotification); uint32_t end = i + 1; - MOZ_ASSERT(aNotifications[i].imageContainerParent()); - ProcessId pid = aNotifications[i].imageContainerParent()->OtherPid(); + MOZ_ASSERT(aNotifications[i].mNotification.asyncCompositableID()); + ProcessId pid = aNotifications[i].mImageBridgeProcessId; while (end < aNotifications.Length() && - aNotifications[end].imageContainerParent()->OtherPid() == pid) { - notifications.AppendElement(aNotifications[end]); + aNotifications[end].mImageBridgeProcessId == pid) { + notifications.AppendElement(aNotifications[end].mNotification); ++end; } GetInstance(pid)->SendPendingAsyncMessages(); if (!GetInstance(pid)->SendDidComposite(notifications)) { ok = false; } i = end; } @@ -445,10 +433,20 @@ ImageBridgeParent::NotifyNotUsed(PTextur mPendingAsyncMessage.push_back( OpNotifyNotUsed(textureId, aTransactionId)); if (!IsAboutToSendAsyncMessages()) { SendPendingAsyncMessages(); } } +CompositableHost* +ImageBridgeParent::FindCompositable(uint64_t aId) +{ + auto iter = mCompositables.find(aId); + if (iter == mCompositables.end()) { + return nullptr; + } + return iter->second; +} + } // namespace layers } // namespace mozilla
--- a/gfx/layers/ipc/ImageBridgeParent.h +++ b/gfx/layers/ipc/ImageBridgeParent.h @@ -4,17 +4,16 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef gfx_layers_ipc_ImageBridgeParent_h_ #define gfx_layers_ipc_ImageBridgeParent_h_ #include <stddef.h> // for size_t #include <stdint.h> // for uint32_t, uint64_t #include "CompositableTransactionParent.h" -#include "ImageContainerParent.h" #include "mozilla/Assertions.h" // for MOZ_ASSERT_HELPER2 #include "mozilla/Attributes.h" // for override #include "mozilla/ipc/ProtocolUtils.h" #include "mozilla/ipc/SharedMemory.h" // for SharedMemory, etc #include "mozilla/layers/CompositorThread.h" #include "mozilla/layers/PImageBridgeParent.h" #include "nsISupportsImpl.h" #include "nsTArrayForwardDeclare.h" // for InfallibleTArray @@ -27,20 +26,20 @@ class Thread; namespace mozilla { namespace ipc { class Shmem; } // namespace ipc namespace layers { +struct ImageCompositeNotificationInfo; + /** - * ImageBridgeParent is the manager Protocol of ImageContainerParent. - * It's purpose is mainly to setup the IPDL connection. Most of the - * interesting stuff is in ImageContainerParent. + * ImageBridgeParent is the manager Protocol of async Compositables. */ class ImageBridgeParent final : public PImageBridgeParent, public CompositableParentManager, public ShmemAllocator { public: typedef InfallibleTArray<CompositableOperation> EditArray; typedef InfallibleTArray<OpDestroy> OpDestroyArray; @@ -74,30 +73,27 @@ public: virtual mozilla::ipc::IPCResult RecvImageBridgeThreadId(const PlatformThreadId& aThreadId) override; virtual mozilla::ipc::IPCResult RecvUpdate(EditArray&& aEdits, OpDestroyArray&& aToDestroy, const uint64_t& aFwdTransactionId, EditReplyArray* aReply) override; virtual mozilla::ipc::IPCResult RecvUpdateNoSwap(EditArray&& aEdits, OpDestroyArray&& aToDestroy, const uint64_t& aFwdTransactionId) override; PCompositableParent* AllocPCompositableParent(const TextureInfo& aInfo, - PImageContainerParent* aImageContainer, - uint64_t*) override; + const uint64_t& aID) override; bool DeallocPCompositableParent(PCompositableParent* aActor) override; virtual PTextureParent* AllocPTextureParent(const SurfaceDescriptor& aSharedData, const LayersBackend& aLayersBackend, const TextureFlags& aFlags, const uint64_t& aSerial) override; virtual bool DeallocPTextureParent(PTextureParent* actor) override; PMediaSystemResourceManagerParent* AllocPMediaSystemResourceManagerParent() override; bool DeallocPMediaSystemResourceManagerParent(PMediaSystemResourceManagerParent* aActor) override; - virtual PImageContainerParent* AllocPImageContainerParent() override; - virtual bool DeallocPImageContainerParent(PImageContainerParent* actor) override; // Shutdown step 1 virtual mozilla::ipc::IPCResult RecvWillClose() override; MessageLoop* GetMessageLoop() const { return mMessageLoop; } // ShmemAllocator @@ -116,22 +112,24 @@ public: using CompositableParentManager::SetAboutToSendAsyncMessages; static void SetAboutToSendAsyncMessages(base::ProcessId aChildProcessId); using CompositableParentManager::SendPendingAsyncMessages; static void SendPendingAsyncMessages(base::ProcessId aChildProcessId); static ImageBridgeParent* GetInstance(ProcessId aId); - static bool NotifyImageComposites(nsTArray<ImageCompositeNotification>& aNotifications); + static bool NotifyImageComposites(nsTArray<ImageCompositeNotificationInfo>& aNotifications); virtual bool UsesImageBridge() const override { return true; } virtual bool IPCOpen() const override { return !mClosed; } + CompositableHost* FindCompositable(uint64_t aId); + protected: void OnChannelConnected(int32_t pid) override; void Bind(Endpoint<PImageBridgeParent>&& aEndpoint); private: void DeferredDestroy(); MessageLoop* mMessageLoop; @@ -145,14 +143,41 @@ private: /** * Map of all living ImageBridgeParent instances */ static std::map<base::ProcessId, ImageBridgeParent*> sImageBridges; static MessageLoop* sMainLoop; RefPtr<CompositorThreadHolder> mCompositorThreadHolder; + + /** + * PCompositable and PLayer can, in the case of async textures, be managed by + * different top level protocols. In this case they don't share the same + * communication channel and we can't send an OpAttachCompositable (PCompositable, + * PLayer) message. + * + * In order to attach a layer and the right compositable if the the compositable + * is async, we store references to the async compositables in a CompositableMap + * that is accessed only on the compositor thread. During a layer transaction we + * send the message OpAttachAsyncCompositable(ID, PLayer), and on the compositor + * side we lookup the ID in the map and attach the corresponding compositable to + * the layer. + * + * CompositableMap must be global because the image bridge doesn't have any + * reference to whatever we have created with PLayerTransaction. So, the only way to + * actually connect these two worlds is to have something global that they can + * both query (in the same thread). The map is not allocated the map on the + * stack to avoid the badness of static initialization. + * + * Also, we have a compositor/PLayerTransaction protocol/etc. per layer manager, and the + * ImageBridge is used by all the existing compositors that have a video, so + * there isn't an instance or "something" that lives outside the boudaries of a + * given layer manager on the compositor thread except the image bridge and the + * thread itself. + */ + std::map<uint64_t, CompositableHost*> mCompositables; }; } // namespace layers } // namespace mozilla #endif // gfx_layers_ipc_ImageBridgeParent_h_
deleted file mode 100644 --- a/gfx/layers/ipc/ImageContainerChild.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * 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/. */ - -#include "ImageContainerChild.h" -#include "ImageContainer.h" -#include "mozilla/Assertions.h" -#include "mozilla/layers/ImageBridgeChild.h" - -namespace mozilla { -namespace layers { - -ImageContainerChild::ImageContainerChild(ImageContainer* aImageContainer) - : mLock("ImageContainerChild") - , mImageContainer(aImageContainer) - , mIPCOpen(false) -{ -} - -void -ImageContainerChild::ForgetImageContainer() -{ - MutexAutoLock lock(mLock); - mImageContainer = nullptr; -} - -void -ImageContainerChild::NotifyComposite(const ImageCompositeNotification& aNotification) -{ - MOZ_ASSERT(InImageBridgeChildThread()); - - MutexAutoLock lock(mLock); - if (mImageContainer) { - mImageContainer->NotifyCompositeInternal(aNotification); - } -} - -void -ImageContainerChild::RegisterWithIPDL() -{ - MOZ_ASSERT(!mIPCOpen); - MOZ_ASSERT(InImageBridgeChildThread()); - - AddRef(); - mIPCOpen = true; -} - -void -ImageContainerChild::UnregisterFromIPDL() -{ - MOZ_ASSERT(mIPCOpen); - MOZ_ASSERT(InImageBridgeChildThread()); - - mIPCOpen = false; - Release(); -} - -void -ImageContainerChild::SendAsyncDelete() -{ - MOZ_ASSERT(InImageBridgeChildThread()); - - if (mIPCOpen) { - PImageContainerChild::SendAsyncDelete(); - } -} - -} // namespace layers -} // namespace mozilla
deleted file mode 100644 --- a/gfx/layers/ipc/ImageContainerChild.h +++ /dev/null @@ -1,61 +0,0 @@ -/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * 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 mozilla_gfx_layers_ImageContainerChild_h -#define mozilla_gfx_layers_ImageContainerChild_h - -#include "mozilla/Mutex.h" -#include "mozilla/layers/PImageContainerChild.h" - -namespace mozilla { -namespace layers { - -class ImageContainer; -class ImageCompositeNotification; - -/** - * The child side of PImageContainer. It's best to avoid ImageContainer filling - * this role since IPDL objects should be associated with a single thread and - * ImageContainer definitely isn't. This object belongs to (and is always - * destroyed on) the ImageBridge thread, except when we need to destroy it - * during shutdown. - * An ImageContainer owns one of these; we have a weak reference to our - * ImageContainer. - */ -class ImageContainerChild final : public PImageContainerChild -{ -public: - explicit ImageContainerChild(ImageContainer* aImageContainer); - - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ImageContainerChild) - - void RegisterWithIPDL(); - void UnregisterFromIPDL(); - void SendAsyncDelete(); - - void NotifyComposite(const ImageCompositeNotification& aNotification); - void ForgetImageContainer(); - -private: - ~ImageContainerChild() - {} - -private: - Mutex mLock; - ImageContainer* mImageContainer; - - // If mIPCOpen is false, it means the IPDL code tried to deallocate the actor - // before the ImageContainer released it. When this happens we don't actually - // delete the actor right away because the ImageContainer has a reference to - // it. In this case the actor will be deleted when the ImageContainer lets go - // of it. - // mIPCOpen must not be accessed off the ImageBridgeChild thread. - bool mIPCOpen; -}; - -} // namespace layers -} // namespace mozilla - -#endif // mozilla_gfx_layers_ImageContainerChild_h
deleted file mode 100644 --- a/gfx/layers/ipc/ImageContainerParent.cpp +++ /dev/null @@ -1,31 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim: sw=2 ts=8 et : - */ -/* 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/. */ - -#include "ImageContainerParent.h" - -#include "nsThreadUtils.h" -#include "mozilla/layers/ImageHost.h" -#include "mozilla/Unused.h" - -namespace mozilla { -namespace layers { - -ImageContainerParent::~ImageContainerParent() -{ - while (!mImageHosts.IsEmpty()) { - mImageHosts[mImageHosts.Length() - 1]->SetImageContainer(nullptr); - } -} - -mozilla::ipc::IPCResult ImageContainerParent::RecvAsyncDelete() -{ - Unused << PImageContainerParent::Send__delete__(this); - return IPC_OK(); -} - -} // namespace layers -} // namespace mozilla
deleted file mode 100644 --- a/gfx/layers/ipc/ImageContainerParent.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim: sw=2 ts=8 et : - */ -/* 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 mozilla_layers_ImageContainerParent_h -#define mozilla_layers_ImageContainerParent_h - -#include "mozilla/Attributes.h" // for override -#include "mozilla/ipc/ProtocolUtils.h" -#include "mozilla/layers/PImageContainerParent.h" - -namespace mozilla { -namespace layers { - -class ImageHost; - -class ImageContainerParent : public PImageContainerParent -{