mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-01 14:45:29 +00:00
Merge m-c to b2g-inbound
This commit is contained in:
commit
3887604616
@ -5,7 +5,7 @@
|
|||||||
malformedURI=The URL is not valid and cannot be loaded.
|
malformedURI=The URL is not valid and cannot be loaded.
|
||||||
fileNotFound=Firefox can't find the file at %S.
|
fileNotFound=Firefox can't find the file at %S.
|
||||||
dnsNotFound=Firefox can't find the server at %S.
|
dnsNotFound=Firefox can't find the server at %S.
|
||||||
protocolNotFound=Firefox doesn't know how to open this address, because the protocol (%S) isn't associated with any program.
|
unknownProtocolFound=Firefox doesn't know how to open this address, because one of the following protocols (%S) isn't associated with any program or is not allowed in this context.
|
||||||
connectionFailure=Firefox can't establish a connection to the server at %S.
|
connectionFailure=Firefox can't establish a connection to the server at %S.
|
||||||
netInterrupt=The connection to %S was interrupted while the page was loading.
|
netInterrupt=The connection to %S was interrupted while the page was loading.
|
||||||
netTimeout=The server at %S is taking too long to respond.
|
netTimeout=The server at %S is taking too long to respond.
|
||||||
|
@ -479,7 +479,7 @@ pref("browser.bookmarks.autoExportHTML", false);
|
|||||||
// keep in {PROFILEDIR}/bookmarkbackups. Special values:
|
// keep in {PROFILEDIR}/bookmarkbackups. Special values:
|
||||||
// -1: unlimited
|
// -1: unlimited
|
||||||
// 0: no backups created (and deletes all existing backups)
|
// 0: no backups created (and deletes all existing backups)
|
||||||
pref("browser.bookmarks.max_backups", 10);
|
pref("browser.bookmarks.max_backups", 15);
|
||||||
|
|
||||||
// Scripts & Windows prefs
|
// Scripts & Windows prefs
|
||||||
pref("dom.disable_open_during_load", true);
|
pref("dom.disable_open_during_load", true);
|
||||||
|
@ -249,6 +249,11 @@ toolbarpaletteitem > toolbaritem[sdkstylewidget="true"] > iframe {
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toolbarpaletteitem[removable="false"] {
|
||||||
|
opacity: 0.5;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
#bookmarks-toolbar-placeholder,
|
#bookmarks-toolbar-placeholder,
|
||||||
toolbarpaletteitem > #personal-bookmarks > #PlacesToolbar,
|
toolbarpaletteitem > #personal-bookmarks > #PlacesToolbar,
|
||||||
#personal-bookmarks[cui-areatype="menu-panel"] > #PlacesToolbar,
|
#personal-bookmarks[cui-areatype="menu-panel"] > #PlacesToolbar,
|
||||||
|
@ -660,6 +660,9 @@ CustomizeMode.prototype = {
|
|||||||
wrapper.setAttribute("flex", aNode.getAttribute("flex"));
|
wrapper.setAttribute("flex", aNode.getAttribute("flex"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let removable = aPlace == "palette" || CustomizableUI.isWidgetRemovable(aNode);
|
||||||
|
wrapper.setAttribute("removable", removable);
|
||||||
|
|
||||||
let contextMenuAttrName = aNode.getAttribute("context") ? "context" :
|
let contextMenuAttrName = aNode.getAttribute("context") ? "context" :
|
||||||
aNode.getAttribute("contextmenu") ? "contextmenu" : "";
|
aNode.getAttribute("contextmenu") ? "contextmenu" : "";
|
||||||
let currentContextMenu = aNode.getAttribute(contextMenuAttrName);
|
let currentContextMenu = aNode.getAttribute(contextMenuAttrName);
|
||||||
@ -1036,14 +1039,17 @@ CustomizeMode.prototype = {
|
|||||||
item = item.parentNode;
|
item = item.parentNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.classList.contains(kPlaceholderClass)) {
|
let draggedItem = item.firstChild;
|
||||||
|
let placeForItem = CustomizableUI.getPlaceForItem(item);
|
||||||
|
let isRemovable = placeForItem == "palette" ||
|
||||||
|
CustomizableUI.isWidgetRemovable(draggedItem);
|
||||||
|
if (item.classList.contains(kPlaceholderClass) || !isRemovable) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let dt = aEvent.dataTransfer;
|
let dt = aEvent.dataTransfer;
|
||||||
let documentId = aEvent.target.ownerDocument.documentElement.id;
|
let documentId = aEvent.target.ownerDocument.documentElement.id;
|
||||||
let draggedItem = item.firstChild;
|
let isInToolbar = placeForItem == "toolbar";
|
||||||
let isInToolbar = CustomizableUI.getPlaceForItem(item) == "toolbar";
|
|
||||||
|
|
||||||
dt.mozSetDataAt(kDragDataTypePrefix + documentId, draggedItem.id, 0);
|
dt.mozSetDataAt(kDragDataTypePrefix + documentId, draggedItem.id, 0);
|
||||||
dt.effectAllowed = "move";
|
dt.effectAllowed = "move";
|
||||||
@ -1618,7 +1624,8 @@ CustomizeMode.prototype = {
|
|||||||
let doc = aEvent.target.ownerDocument;
|
let doc = aEvent.target.ownerDocument;
|
||||||
doc.documentElement.setAttribute("customizing-movingItem", true);
|
doc.documentElement.setAttribute("customizing-movingItem", true);
|
||||||
let item = this._getWrapper(aEvent.target);
|
let item = this._getWrapper(aEvent.target);
|
||||||
if (item && !item.classList.contains(kPlaceholderClass)) {
|
if (item && !item.classList.contains(kPlaceholderClass) &&
|
||||||
|
item.getAttribute("removable") == "true") {
|
||||||
item.setAttribute("mousedown", "true");
|
item.setAttribute("mousedown", "true");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -14,6 +14,7 @@ add_task(function() {
|
|||||||
skippedItem.id = "test-skipintoolbarset-item";
|
skippedItem.id = "test-skipintoolbarset-item";
|
||||||
skippedItem.setAttribute("label", "Test");
|
skippedItem.setAttribute("label", "Test");
|
||||||
skippedItem.setAttribute("skipintoolbarset", "true");
|
skippedItem.setAttribute("skipintoolbarset", "true");
|
||||||
|
skippedItem.setAttribute("removable", "true");
|
||||||
navbar.customizationTarget.appendChild(skippedItem);
|
navbar.customizationTarget.appendChild(skippedItem);
|
||||||
let downloadsButton = document.getElementById("downloads-button");
|
let downloadsButton = document.getElementById("downloads-button");
|
||||||
yield startCustomizing();
|
yield startCustomizing();
|
||||||
|
@ -82,16 +82,20 @@ XPCOMUtils.defineLazyModuleGetter(this, "SessionStore",
|
|||||||
XPCOMUtils.defineLazyModuleGetter(this, "BrowserUITelemetry",
|
XPCOMUtils.defineLazyModuleGetter(this, "BrowserUITelemetry",
|
||||||
"resource:///modules/BrowserUITelemetry.jsm");
|
"resource:///modules/BrowserUITelemetry.jsm");
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyModuleGetter(this, "AsyncShutdown",
|
||||||
|
"resource:///modules/AsyncShutdown.jsm");
|
||||||
|
|
||||||
const PREF_PLUGINS_NOTIFYUSER = "plugins.update.notifyUser";
|
const PREF_PLUGINS_NOTIFYUSER = "plugins.update.notifyUser";
|
||||||
const PREF_PLUGINS_UPDATEURL = "plugins.update.url";
|
const PREF_PLUGINS_UPDATEURL = "plugins.update.url";
|
||||||
|
|
||||||
// We try to backup bookmarks at idle times, to avoid doing that at shutdown.
|
// Seconds of idle before trying to create a bookmarks backup.
|
||||||
// Number of idle seconds before trying to backup bookmarks. 10 minutes.
|
const BOOKMARKS_BACKUP_IDLE_TIME_SEC = 10 * 60;
|
||||||
const BOOKMARKS_BACKUP_IDLE_TIME = 10 * 60;
|
// Minimum interval between backups. We try to not create more than one backup
|
||||||
// Minimum interval in milliseconds between backups.
|
// per interval.
|
||||||
const BOOKMARKS_BACKUP_INTERVAL = 86400 * 1000;
|
const BOOKMARKS_BACKUP_MIN_INTERVAL_DAYS = 1;
|
||||||
// Maximum number of backups to create. Old ones will be purged.
|
// Maximum interval between backups. If the last backup is older than these
|
||||||
const BOOKMARKS_BACKUP_MAX_BACKUPS = 10;
|
// days we will try to create a new one more aggressively.
|
||||||
|
const BOOKMARKS_BACKUP_MAX_INTERVAL_DAYS = 5;
|
||||||
|
|
||||||
// Factory object
|
// Factory object
|
||||||
const BrowserGlueServiceFactory = {
|
const BrowserGlueServiceFactory = {
|
||||||
@ -134,7 +138,6 @@ function BrowserGlue() {
|
|||||||
|
|
||||||
BrowserGlue.prototype = {
|
BrowserGlue.prototype = {
|
||||||
_saveSession: false,
|
_saveSession: false,
|
||||||
_isIdleObserver: false,
|
|
||||||
_isPlacesInitObserver: false,
|
_isPlacesInitObserver: false,
|
||||||
_isPlacesLockedObserver: false,
|
_isPlacesLockedObserver: false,
|
||||||
_isPlacesShutdownObserver: false,
|
_isPlacesShutdownObserver: false,
|
||||||
@ -202,16 +205,7 @@ BrowserGlue.prototype = {
|
|||||||
this._onQuitRequest(subject, data);
|
this._onQuitRequest(subject, data);
|
||||||
break;
|
break;
|
||||||
case "quit-application-granted":
|
case "quit-application-granted":
|
||||||
// This pref must be set here because SessionStore will use its value
|
this._onQuitApplicationGranted();
|
||||||
// on quit-application.
|
|
||||||
this._setPrefToSaveSession();
|
|
||||||
try {
|
|
||||||
let appStartup = Cc["@mozilla.org/toolkit/app-startup;1"].
|
|
||||||
getService(Ci.nsIAppStartup);
|
|
||||||
appStartup.trackStartupCrashEnd();
|
|
||||||
} catch (e) {
|
|
||||||
Cu.reportError("Could not end startup crash tracking in quit-application-granted: " + e);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
#ifdef OBSERVE_LASTWINDOW_CLOSE_TOPICS
|
#ifdef OBSERVE_LASTWINDOW_CLOSE_TOPICS
|
||||||
case "browser-lastwindow-close-requested":
|
case "browser-lastwindow-close-requested":
|
||||||
@ -262,8 +256,7 @@ BrowserGlue.prototype = {
|
|||||||
this._onPlacesShutdown();
|
this._onPlacesShutdown();
|
||||||
break;
|
break;
|
||||||
case "idle":
|
case "idle":
|
||||||
if (this._idleService.idleTime > BOOKMARKS_BACKUP_IDLE_TIME * 1000)
|
this._backupBookmarks();
|
||||||
this._backupBookmarks();
|
|
||||||
break;
|
break;
|
||||||
case "distribution-customization-complete":
|
case "distribution-customization-complete":
|
||||||
Services.obs.removeObserver(this, "distribution-customization-complete");
|
Services.obs.removeObserver(this, "distribution-customization-complete");
|
||||||
@ -304,7 +297,10 @@ BrowserGlue.prototype = {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "profile-before-change":
|
case "profile-before-change":
|
||||||
this._onProfileShutdown();
|
// Any component depending on Places should be finalized in
|
||||||
|
// _onPlacesShutdown. Any component that doesn't need to act after
|
||||||
|
// the UI has gone should be finalized in _onQuitApplicationGranted.
|
||||||
|
this._dispose();
|
||||||
break;
|
break;
|
||||||
#ifdef MOZ_SERVICES_HEALTHREPORT
|
#ifdef MOZ_SERVICES_HEALTHREPORT
|
||||||
case "keyword-search":
|
case "keyword-search":
|
||||||
@ -422,8 +418,10 @@ BrowserGlue.prototype = {
|
|||||||
os.removeObserver(this, "weave:engine:clients:display-uri");
|
os.removeObserver(this, "weave:engine:clients:display-uri");
|
||||||
#endif
|
#endif
|
||||||
os.removeObserver(this, "session-save");
|
os.removeObserver(this, "session-save");
|
||||||
if (this._isIdleObserver)
|
if (this._bookmarksBackupIdleTime) {
|
||||||
this._idleService.removeIdleObserver(this, BOOKMARKS_BACKUP_IDLE_TIME);
|
this._idleService.removeIdleObserver(this, this._bookmarksBackupIdleTime);
|
||||||
|
delete this._bookmarksBackupIdleTime;
|
||||||
|
}
|
||||||
if (this._isPlacesInitObserver)
|
if (this._isPlacesInitObserver)
|
||||||
os.removeObserver(this, "places-init-complete");
|
os.removeObserver(this, "places-init-complete");
|
||||||
if (this._isPlacesLockedObserver)
|
if (this._isPlacesLockedObserver)
|
||||||
@ -634,16 +632,24 @@ BrowserGlue.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Profile shutdown handler (contains profile cleanup routines).
|
* Application shutdown handler.
|
||||||
* All components depending on Places should be shut down in
|
|
||||||
* _onPlacesShutdown() and not here.
|
|
||||||
*/
|
*/
|
||||||
_onProfileShutdown: function BG__onProfileShutdown() {
|
_onQuitApplicationGranted: function () {
|
||||||
|
// This pref must be set here because SessionStore will use its value
|
||||||
|
// on quit-application.
|
||||||
|
this._setPrefToSaveSession();
|
||||||
|
try {
|
||||||
|
let appStartup = Cc["@mozilla.org/toolkit/app-startup;1"]
|
||||||
|
.getService(Ci.nsIAppStartup);
|
||||||
|
appStartup.trackStartupCrashEnd();
|
||||||
|
} catch (e) {
|
||||||
|
Cu.reportError("Could not end startup crash tracking in quit-application-granted: " + e);
|
||||||
|
}
|
||||||
|
|
||||||
BrowserNewTabPreloader.uninit();
|
BrowserNewTabPreloader.uninit();
|
||||||
webappsUI.uninit();
|
webappsUI.uninit();
|
||||||
SignInToWebsiteUX.uninit();
|
SignInToWebsiteUX.uninit();
|
||||||
webrtcUI.uninit();
|
webrtcUI.uninit();
|
||||||
this._dispose();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// All initial windows have opened.
|
// All initial windows have opened.
|
||||||
@ -1060,14 +1066,18 @@ BrowserGlue.prototype = {
|
|||||||
}
|
}
|
||||||
} catch(ex) {}
|
} catch(ex) {}
|
||||||
|
|
||||||
|
// This may be reused later, check for "=== undefined" to see if it has
|
||||||
|
// been populated already.
|
||||||
|
let lastBackupFile;
|
||||||
|
|
||||||
// If the user did not require to restore default bookmarks, or import
|
// If the user did not require to restore default bookmarks, or import
|
||||||
// from bookmarks.html, we will try to restore from JSON
|
// from bookmarks.html, we will try to restore from JSON
|
||||||
if (importBookmarks && !restoreDefaultBookmarks && !importBookmarksHTML) {
|
if (importBookmarks && !restoreDefaultBookmarks && !importBookmarksHTML) {
|
||||||
// get latest JSON backup
|
// get latest JSON backup
|
||||||
var bookmarksBackupFile = yield PlacesBackups.getMostRecent("json");
|
lastBackupFile = yield PlacesBackups.getMostRecentBackup("json");
|
||||||
if (bookmarksBackupFile) {
|
if (lastBackupFile) {
|
||||||
// restore from JSON backup
|
// restore from JSON backup
|
||||||
yield BookmarkJSONUtils.importFromFile(bookmarksBackupFile, true);
|
yield BookmarkJSONUtils.importFromFile(lastBackupFile, true);
|
||||||
importBookmarks = false;
|
importBookmarks = false;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -1162,10 +1172,39 @@ BrowserGlue.prototype = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Initialize bookmark archiving on idle.
|
// Initialize bookmark archiving on idle.
|
||||||
// Once a day, either on idle or shutdown, bookmarks are backed up.
|
if (!this._bookmarksBackupIdleTime) {
|
||||||
if (!this._isIdleObserver) {
|
this._bookmarksBackupIdleTime = BOOKMARKS_BACKUP_IDLE_TIME_SEC;
|
||||||
this._idleService.addIdleObserver(this, BOOKMARKS_BACKUP_IDLE_TIME);
|
|
||||||
this._isIdleObserver = true;
|
// If there is no backup, or the last bookmarks backup is too old, use
|
||||||
|
// a more aggressive idle observer.
|
||||||
|
if (lastBackupFile === undefined)
|
||||||
|
lastBackupFile = yield PlacesBackups.getMostRecentBackup();
|
||||||
|
if (!lastBackupFile) {
|
||||||
|
this._bookmarksBackupIdleTime /= 2;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let lastBackupTime = PlacesBackups.getDateForFile(lastBackupFile);
|
||||||
|
let profileLastUse = Services.appinfo.replacedLockTime || Date.now();
|
||||||
|
|
||||||
|
// If there is a backup after the last profile usage date it's fine,
|
||||||
|
// regardless its age. Otherwise check how old is the last
|
||||||
|
// available backup compared to that session.
|
||||||
|
if (profileLastUse > lastBackupTime) {
|
||||||
|
let backupAge = Math.round((profileLastUse - lastBackupTime) / 86400000);
|
||||||
|
// Report the age of the last available backup.
|
||||||
|
try {
|
||||||
|
Services.telemetry
|
||||||
|
.getHistogramById("PLACES_BACKUPS_DAYSFROMLAST")
|
||||||
|
.add(backupAge);
|
||||||
|
} catch (ex) {
|
||||||
|
Components.utils.reportError("Unable to report telemetry.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (backupAge > BOOKMARKS_BACKUP_MAX_INTERVAL_DAYS)
|
||||||
|
this._bookmarksBackupIdleTime /= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this._idleService.addIdleObserver(this, this._bookmarksBackupIdleTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
Services.obs.notifyObservers(null, "places-browser-init-complete", "");
|
Services.obs.notifyObservers(null, "places-browser-init-complete", "");
|
||||||
@ -1174,63 +1213,34 @@ BrowserGlue.prototype = {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Places shut-down tasks
|
* Places shut-down tasks
|
||||||
* - back up bookmarks if needed.
|
|
||||||
* - export bookmarks as HTML, if so configured.
|
|
||||||
* - finalize components depending on Places.
|
* - finalize components depending on Places.
|
||||||
|
* - export bookmarks as HTML, if so configured.
|
||||||
*/
|
*/
|
||||||
_onPlacesShutdown: function BG__onPlacesShutdown() {
|
_onPlacesShutdown: function BG__onPlacesShutdown() {
|
||||||
this._sanitizer.onShutdown();
|
this._sanitizer.onShutdown();
|
||||||
PageThumbs.uninit();
|
PageThumbs.uninit();
|
||||||
|
|
||||||
if (this._isIdleObserver) {
|
if (this._bookmarksBackupIdleTime) {
|
||||||
this._idleService.removeIdleObserver(this, BOOKMARKS_BACKUP_IDLE_TIME);
|
this._idleService.removeIdleObserver(this, this._bookmarksBackupIdleTime);
|
||||||
this._isIdleObserver = false;
|
delete this._bookmarksBackupIdleTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
let waitingForBackupToComplete = true;
|
// Support legacy bookmarks.html format for apps that depend on that format.
|
||||||
this._backupBookmarks().then(
|
try {
|
||||||
function onSuccess() {
|
if (Services.prefs.getBoolPref("browser.bookmarks.autoExportHTML")) {
|
||||||
waitingForBackupToComplete = false;
|
// places-shutdown happens at profile-change-teardown, so here we
|
||||||
},
|
// can safely add a profile-before-change blocker.
|
||||||
function onFailure() {
|
AsyncShutdown.profileBeforeChange.addBlocker(
|
||||||
Cu.reportError("Unable to backup bookmarks.");
|
"Places: bookmarks.html",
|
||||||
waitingForBackupToComplete = false;
|
() => BookmarkHTMLUtils.exportToFile(Services.dirsvc.get("BMarks", Ci.nsIFile))
|
||||||
|
.then(null, Cu.reportError)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
);
|
} catch (ex) {} // Do not export.
|
||||||
|
|
||||||
// Backup bookmarks to bookmarks.html to support apps that depend
|
|
||||||
// on the legacy format.
|
|
||||||
let waitingForHTMLExportToComplete = false;
|
|
||||||
// If this fails to get the preference value, we don't export.
|
|
||||||
if (Services.prefs.getBoolPref("browser.bookmarks.autoExportHTML")) {
|
|
||||||
// Exceptionally, since this is a non-default setting and HTML format is
|
|
||||||
// discouraged in favor of the JSON backups, we spin the event loop on
|
|
||||||
// shutdown, to wait for the export to finish. We cannot safely spin
|
|
||||||
// the event loop on shutdown until we include a watchdog to prevent
|
|
||||||
// potential hangs (bug 518683). The asynchronous shutdown operations
|
|
||||||
// will then be handled by a shutdown service (bug 435058).
|
|
||||||
waitingForHTMLExportToComplete = true;
|
|
||||||
BookmarkHTMLUtils.exportToFile(Services.dirsvc.get("BMarks", Ci.nsIFile)).then(
|
|
||||||
function onSuccess() {
|
|
||||||
waitingForHTMLExportToComplete = false;
|
|
||||||
},
|
|
||||||
function onFailure() {
|
|
||||||
Cu.reportError("Unable to auto export html.");
|
|
||||||
waitingForHTMLExportToComplete = false;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// The events loop should spin at least once because waitingForBackupToComplete
|
|
||||||
// is true before checking whether backup should be made.
|
|
||||||
let thread = Services.tm.currentThread;
|
|
||||||
while (waitingForBackupToComplete || waitingForHTMLExportToComplete) {
|
|
||||||
thread.processNextEvent(true);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Backup bookmarks.
|
* If a backup for today doesn't exist, this creates one.
|
||||||
*/
|
*/
|
||||||
_backupBookmarks: function BG__backupBookmarks() {
|
_backupBookmarks: function BG__backupBookmarks() {
|
||||||
return Task.spawn(function() {
|
return Task.spawn(function() {
|
||||||
@ -1238,14 +1248,9 @@ BrowserGlue.prototype = {
|
|||||||
// Should backup bookmarks if there are no backups or the maximum
|
// Should backup bookmarks if there are no backups or the maximum
|
||||||
// interval between backups elapsed.
|
// interval between backups elapsed.
|
||||||
if (!lastBackupFile ||
|
if (!lastBackupFile ||
|
||||||
new Date() - PlacesBackups.getDateForFile(lastBackupFile) > BOOKMARKS_BACKUP_INTERVAL) {
|
new Date() - PlacesBackups.getDateForFile(lastBackupFile) > BOOKMARKS_BACKUP_MIN_INTERVAL_DAYS * 86400000) {
|
||||||
let maxBackups = BOOKMARKS_BACKUP_MAX_BACKUPS;
|
let maxBackups = Services.prefs.getIntPref("browser.bookmarks.max_backups");
|
||||||
try {
|
yield PlacesBackups.create(maxBackups);
|
||||||
maxBackups = Services.prefs.getIntPref("browser.bookmarks.max_backups");
|
|
||||||
}
|
|
||||||
catch(ex) { /* Use default. */ }
|
|
||||||
|
|
||||||
yield PlacesBackups.create(maxBackups); // Don't force creation.
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -540,7 +540,8 @@ var PlacesOrganizer = {
|
|||||||
let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
|
let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
|
||||||
let fpCallback = function fpCallback_done(aResult) {
|
let fpCallback = function fpCallback_done(aResult) {
|
||||||
if (aResult != Ci.nsIFilePicker.returnCancel) {
|
if (aResult != Ci.nsIFilePicker.returnCancel) {
|
||||||
PlacesBackups.saveBookmarksToJSONFile(fp.file);
|
// There is no OS.File version of the filepicker yet (Bug 937812).
|
||||||
|
PlacesBackups.saveBookmarksToJSONFile(fp.file.path);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4,91 +4,78 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
// Get bookmarks service
|
|
||||||
try {
|
|
||||||
var bmsvc = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
|
|
||||||
getService(Ci.nsINavBookmarksService);
|
|
||||||
} catch(ex) {
|
|
||||||
do_throw("Could not get Bookmarks service\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get annotation service
|
|
||||||
try {
|
|
||||||
var annosvc = Cc["@mozilla.org/browser/annotation-service;1"].
|
|
||||||
getService(Ci.nsIAnnotationService);
|
|
||||||
} catch(ex) {
|
|
||||||
do_throw("Could not get Annotation service\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get browser glue
|
|
||||||
try {
|
|
||||||
var gluesvc = Cc["@mozilla.org/browser/browserglue;1"].
|
|
||||||
getService(Ci.nsIBrowserGlue).
|
|
||||||
QueryInterface(Ci.nsIObserver);
|
|
||||||
// Avoid default bookmarks import.
|
|
||||||
gluesvc.observe(null, "initial-migration-will-import-default-bookmarks", "");
|
|
||||||
// gluesvc.observe(null, "initial-migration-did-import-default-bookmarks", "");
|
|
||||||
} catch(ex) {
|
|
||||||
do_throw("Could not get BrowserGlue service\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get pref service
|
|
||||||
try {
|
|
||||||
var pref = Cc["@mozilla.org/preferences-service;1"].
|
|
||||||
getService(Ci.nsIPrefBranch);
|
|
||||||
} catch(ex) {
|
|
||||||
do_throw("Could not get Preferences service\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
const SMART_BOOKMARKS_ANNO = "Places/SmartBookmark";
|
const SMART_BOOKMARKS_ANNO = "Places/SmartBookmark";
|
||||||
const SMART_BOOKMARKS_PREF = "browser.places.smartBookmarksVersion";
|
const SMART_BOOKMARKS_PREF = "browser.places.smartBookmarksVersion";
|
||||||
|
|
||||||
// main
|
let gluesvc = Cc["@mozilla.org/browser/browserglue;1"].
|
||||||
|
getService(Ci.nsIBrowserGlue).
|
||||||
|
QueryInterface(Ci.nsIObserver);
|
||||||
|
// Avoid default bookmarks import.
|
||||||
|
gluesvc.observe(null, "initial-migration-will-import-default-bookmarks", "");
|
||||||
|
|
||||||
function run_test() {
|
function run_test() {
|
||||||
// TEST 1: smart bookmarks disabled
|
run_next_test();
|
||||||
pref.setIntPref("browser.places.smartBookmarksVersion", -1);
|
|
||||||
gluesvc.ensurePlacesDefaultQueriesInitialized();
|
|
||||||
var smartBookmarkItemIds = annosvc.getItemsWithAnnotation(SMART_BOOKMARKS_ANNO);
|
|
||||||
do_check_eq(smartBookmarkItemIds.length, 0);
|
|
||||||
// check that pref has not been bumped up
|
|
||||||
do_check_eq(pref.getIntPref("browser.places.smartBookmarksVersion"), -1);
|
|
||||||
|
|
||||||
// TEST 2: create smart bookmarks
|
|
||||||
pref.setIntPref("browser.places.smartBookmarksVersion", 0);
|
|
||||||
gluesvc.ensurePlacesDefaultQueriesInitialized();
|
|
||||||
smartBookmarkItemIds = annosvc.getItemsWithAnnotation(SMART_BOOKMARKS_ANNO);
|
|
||||||
do_check_neq(smartBookmarkItemIds.length, 0);
|
|
||||||
// check that pref has been bumped up
|
|
||||||
do_check_true(pref.getIntPref("browser.places.smartBookmarksVersion") > 0);
|
|
||||||
|
|
||||||
var smartBookmarksCount = smartBookmarkItemIds.length;
|
|
||||||
|
|
||||||
// TEST 3: smart bookmarks restore
|
|
||||||
// remove one smart bookmark and restore
|
|
||||||
bmsvc.removeItem(smartBookmarkItemIds[0]);
|
|
||||||
pref.setIntPref("browser.places.smartBookmarksVersion", 0);
|
|
||||||
gluesvc.ensurePlacesDefaultQueriesInitialized();
|
|
||||||
smartBookmarkItemIds = annosvc.getItemsWithAnnotation(SMART_BOOKMARKS_ANNO);
|
|
||||||
do_check_eq(smartBookmarkItemIds.length, smartBookmarksCount);
|
|
||||||
// check that pref has been bumped up
|
|
||||||
do_check_true(pref.getIntPref("browser.places.smartBookmarksVersion") > 0);
|
|
||||||
|
|
||||||
// TEST 4: move a smart bookmark, change its title, then restore
|
|
||||||
// smart bookmark should be restored in place
|
|
||||||
var parent = bmsvc.getFolderIdForItem(smartBookmarkItemIds[0]);
|
|
||||||
var oldTitle = bmsvc.getItemTitle(smartBookmarkItemIds[0]);
|
|
||||||
// create a subfolder and move inside it
|
|
||||||
var newParent = bmsvc.createFolder(parent, "test", bmsvc.DEFAULT_INDEX);
|
|
||||||
bmsvc.moveItem(smartBookmarkItemIds[0], newParent, bmsvc.DEFAULT_INDEX);
|
|
||||||
// change title
|
|
||||||
bmsvc.setItemTitle(smartBookmarkItemIds[0], "new title");
|
|
||||||
// restore
|
|
||||||
pref.setIntPref("browser.places.smartBookmarksVersion", 0);
|
|
||||||
gluesvc.ensurePlacesDefaultQueriesInitialized();
|
|
||||||
smartBookmarkItemIds = annosvc.getItemsWithAnnotation(SMART_BOOKMARKS_ANNO);
|
|
||||||
do_check_eq(smartBookmarkItemIds.length, smartBookmarksCount);
|
|
||||||
do_check_eq(bmsvc.getFolderIdForItem(smartBookmarkItemIds[0]), newParent);
|
|
||||||
do_check_eq(bmsvc.getItemTitle(smartBookmarkItemIds[0]), oldTitle);
|
|
||||||
// check that pref has been bumped up
|
|
||||||
do_check_true(pref.getIntPref("browser.places.smartBookmarksVersion") > 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
add_task(function smart_bookmarks_disabled() {
|
||||||
|
Services.prefs.setIntPref("browser.places.smartBookmarksVersion", -1);
|
||||||
|
gluesvc.ensurePlacesDefaultQueriesInitialized();
|
||||||
|
let smartBookmarkItemIds =
|
||||||
|
PlacesUtils.annotations.getItemsWithAnnotation(SMART_BOOKMARKS_ANNO);
|
||||||
|
do_check_eq(smartBookmarkItemIds.length, 0);
|
||||||
|
do_log_info("check that pref has not been bumped up");
|
||||||
|
do_check_eq(Services.prefs.getIntPref("browser.places.smartBookmarksVersion"), -1);
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(function create_smart_bookmarks() {
|
||||||
|
Services.prefs.setIntPref("browser.places.smartBookmarksVersion", 0);
|
||||||
|
gluesvc.ensurePlacesDefaultQueriesInitialized();
|
||||||
|
let smartBookmarkItemIds =
|
||||||
|
PlacesUtils.annotations.getItemsWithAnnotation(SMART_BOOKMARKS_ANNO);
|
||||||
|
do_check_neq(smartBookmarkItemIds.length, 0);
|
||||||
|
do_log_info("check that pref has been bumped up");
|
||||||
|
do_check_true(Services.prefs.getIntPref("browser.places.smartBookmarksVersion") > 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(function remove_smart_bookmark_and_restore() {
|
||||||
|
let smartBookmarkItemIds =
|
||||||
|
PlacesUtils.annotations.getItemsWithAnnotation(SMART_BOOKMARKS_ANNO);
|
||||||
|
let smartBookmarksCount = smartBookmarkItemIds.length;
|
||||||
|
do_log_info("remove one smart bookmark and restore");
|
||||||
|
PlacesUtils.bookmarks.removeItem(smartBookmarkItemIds[0]);
|
||||||
|
Services.prefs.setIntPref("browser.places.smartBookmarksVersion", 0);
|
||||||
|
gluesvc.ensurePlacesDefaultQueriesInitialized();
|
||||||
|
let smartBookmarkItemIds =
|
||||||
|
PlacesUtils.annotations.getItemsWithAnnotation(SMART_BOOKMARKS_ANNO);
|
||||||
|
do_check_eq(smartBookmarkItemIds.length, smartBookmarksCount);
|
||||||
|
do_log_info("check that pref has been bumped up");
|
||||||
|
do_check_true(Services.prefs.getIntPref("browser.places.smartBookmarksVersion") > 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(function move_smart_bookmark_rename_and_restore() {
|
||||||
|
let smartBookmarkItemIds =
|
||||||
|
PlacesUtils.annotations.getItemsWithAnnotation(SMART_BOOKMARKS_ANNO);
|
||||||
|
let smartBookmarksCount = smartBookmarkItemIds.length;
|
||||||
|
do_log_info("smart bookmark should be restored in place");
|
||||||
|
let parent = PlacesUtils.bookmarks.getFolderIdForItem(smartBookmarkItemIds[0]);
|
||||||
|
let oldTitle = PlacesUtils.bookmarks.getItemTitle(smartBookmarkItemIds[0]);
|
||||||
|
// create a subfolder and move inside it
|
||||||
|
let newParent =
|
||||||
|
PlacesUtils.bookmarks.createFolder(parent, "test",
|
||||||
|
PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||||
|
PlacesUtils.bookmarks.moveItem(smartBookmarkItemIds[0], newParent,
|
||||||
|
PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||||
|
// change title
|
||||||
|
PlacesUtils.bookmarks.setItemTitle(smartBookmarkItemIds[0], "new title");
|
||||||
|
// restore
|
||||||
|
Services.prefs.setIntPref("browser.places.smartBookmarksVersion", 0);
|
||||||
|
gluesvc.ensurePlacesDefaultQueriesInitialized();
|
||||||
|
smartBookmarkItemIds =
|
||||||
|
PlacesUtils.annotations.getItemsWithAnnotation(SMART_BOOKMARKS_ANNO);
|
||||||
|
do_check_eq(smartBookmarkItemIds.length, smartBookmarksCount);
|
||||||
|
do_check_eq(PlacesUtils.bookmarks.getFolderIdForItem(smartBookmarkItemIds[0]), newParent);
|
||||||
|
do_check_eq(PlacesUtils.bookmarks.getItemTitle(smartBookmarkItemIds[0]), oldTitle);
|
||||||
|
do_log_info("check that pref has been bumped up");
|
||||||
|
do_check_true(Services.prefs.getIntPref("browser.places.smartBookmarksVersion") > 0);
|
||||||
|
});
|
||||||
|
@ -1,153 +0,0 @@
|
|||||||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* 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/. */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that nsBrowserGlue is correctly exporting based on preferences values,
|
|
||||||
* and creating bookmarks backup if one does not exist for today.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Initialize nsBrowserGlue after Places.
|
|
||||||
let bg = Cc["@mozilla.org/browser/browserglue;1"].
|
|
||||||
getService(Ci.nsIBrowserGlue);
|
|
||||||
|
|
||||||
// Initialize Places through Bookmarks Service.
|
|
||||||
let bs = PlacesUtils.bookmarks;
|
|
||||||
|
|
||||||
// Get other services.
|
|
||||||
let ps = Services.prefs;
|
|
||||||
let os = Services.obs;
|
|
||||||
|
|
||||||
const PREF_AUTO_EXPORT_HTML = "browser.bookmarks.autoExportHTML";
|
|
||||||
|
|
||||||
let tests = [];
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
tests.push({
|
|
||||||
description: "Export to bookmarks.html if autoExportHTML is true.",
|
|
||||||
exec: function() {
|
|
||||||
remove_all_JSON_backups();
|
|
||||||
|
|
||||||
// Sanity check: we should have bookmarks on the toolbar.
|
|
||||||
do_check_true(bs.getIdForItemAt(bs.toolbarFolder, 0) > 0);
|
|
||||||
|
|
||||||
// Set preferences.
|
|
||||||
ps.setBoolPref(PREF_AUTO_EXPORT_HTML, true);
|
|
||||||
|
|
||||||
// Force nsBrowserGlue::_shutdownPlaces().
|
|
||||||
bg.QueryInterface(Ci.nsIObserver).observe(null,
|
|
||||||
PlacesUtils.TOPIC_SHUTDOWN,
|
|
||||||
null);
|
|
||||||
|
|
||||||
// Check bookmarks.html has been created.
|
|
||||||
check_bookmarks_html();
|
|
||||||
// Check JSON backup has been created.
|
|
||||||
check_JSON_backup(true);
|
|
||||||
|
|
||||||
// Check preferences have not been reverted.
|
|
||||||
do_check_true(ps.getBoolPref(PREF_AUTO_EXPORT_HTML));
|
|
||||||
// Reset preferences.
|
|
||||||
ps.setBoolPref(PREF_AUTO_EXPORT_HTML, false);
|
|
||||||
|
|
||||||
next_test();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
tests.push({
|
|
||||||
description: "Export to bookmarks.html if autoExportHTML is true and a bookmarks.html exists.",
|
|
||||||
exec: function() {
|
|
||||||
// Sanity check: we should have bookmarks on the toolbar.
|
|
||||||
do_check_true(bs.getIdForItemAt(bs.toolbarFolder, 0) > 0);
|
|
||||||
|
|
||||||
// Set preferences.
|
|
||||||
ps.setBoolPref(PREF_AUTO_EXPORT_HTML, true);
|
|
||||||
|
|
||||||
// Create a bookmarks.html in the profile.
|
|
||||||
let profileBookmarksHTMLFile = create_bookmarks_html("bookmarks.glue.html");
|
|
||||||
|
|
||||||
// set the file's lastModifiedTime to one minute ago and get its size.
|
|
||||||
let lastMod = Date.now() - 60*1000;
|
|
||||||
profileBookmarksHTMLFile.lastModifiedTime = lastMod;
|
|
||||||
|
|
||||||
let fileSize = profileBookmarksHTMLFile.fileSize;
|
|
||||||
|
|
||||||
// Force nsBrowserGlue::_shutdownPlaces().
|
|
||||||
bg.QueryInterface(Ci.nsIObserver).observe(null,
|
|
||||||
PlacesUtils.TOPIC_SHUTDOWN,
|
|
||||||
null);
|
|
||||||
|
|
||||||
// Check a new bookmarks.html has been created.
|
|
||||||
let profileBookmarksHTMLFile = check_bookmarks_html();
|
|
||||||
do_check_true(profileBookmarksHTMLFile.lastModifiedTime > lastMod);
|
|
||||||
do_check_neq(profileBookmarksHTMLFile.fileSize, fileSize);
|
|
||||||
|
|
||||||
// Check preferences have not been reverted.
|
|
||||||
do_check_true(ps.getBoolPref(PREF_AUTO_EXPORT_HTML));
|
|
||||||
// Reset preferences.
|
|
||||||
ps.setBoolPref(PREF_AUTO_EXPORT_HTML, false);
|
|
||||||
|
|
||||||
next_test();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
tests.push({
|
|
||||||
description: "Backup to JSON should be a no-op if a backup for today already exists.",
|
|
||||||
exec: function() {
|
|
||||||
// Sanity check: we should have bookmarks on the toolbar.
|
|
||||||
do_check_true(bs.getIdForItemAt(bs.toolbarFolder, 0) > 0);
|
|
||||||
|
|
||||||
// Create a JSON backup in the profile.
|
|
||||||
let profileBookmarksJSONFile = create_JSON_backup("bookmarks.glue.json");
|
|
||||||
// Get file lastModified and size.
|
|
||||||
let lastMod = profileBookmarksJSONFile.lastModifiedTime;
|
|
||||||
let fileSize = profileBookmarksJSONFile.fileSize;
|
|
||||||
|
|
||||||
// Force nsBrowserGlue::_shutdownPlaces().
|
|
||||||
bg.QueryInterface(Ci.nsIObserver).observe(null,
|
|
||||||
PlacesUtils.TOPIC_SHUTDOWN,
|
|
||||||
null);
|
|
||||||
|
|
||||||
// Check a new JSON backup has not been created.
|
|
||||||
do_check_true(profileBookmarksJSONFile.exists());
|
|
||||||
do_check_eq(profileBookmarksJSONFile.lastModifiedTime, lastMod);
|
|
||||||
do_check_eq(profileBookmarksJSONFile.fileSize, fileSize);
|
|
||||||
|
|
||||||
do_test_finished();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
var testIndex = 0;
|
|
||||||
function next_test() {
|
|
||||||
// Remove bookmarks.html from profile.
|
|
||||||
remove_bookmarks_html();
|
|
||||||
|
|
||||||
// Execute next test.
|
|
||||||
let test = tests.shift();
|
|
||||||
dump("\nTEST " + (++testIndex) + ": " + test.description);
|
|
||||||
test.exec();
|
|
||||||
}
|
|
||||||
|
|
||||||
function run_test() {
|
|
||||||
do_test_pending();
|
|
||||||
|
|
||||||
// Clean up bookmarks.
|
|
||||||
remove_all_bookmarks();
|
|
||||||
|
|
||||||
// Create some bookmarks.
|
|
||||||
bs.insertBookmark(bs.bookmarksMenuFolder, uri("http://mozilla.org/"),
|
|
||||||
bs.DEFAULT_INDEX, "bookmark-on-menu");
|
|
||||||
bs.insertBookmark(bs.toolbarFolder, uri("http://mozilla.org/"),
|
|
||||||
bs.DEFAULT_INDEX, "bookmark-on-toolbar");
|
|
||||||
|
|
||||||
// Kick-off tests.
|
|
||||||
next_test();
|
|
||||||
}
|
|
@ -19,8 +19,8 @@ const TOPIC_CONNECTION_CLOSED = "places-connection-closed";
|
|||||||
|
|
||||||
let EXPECTED_NOTIFICATIONS = [
|
let EXPECTED_NOTIFICATIONS = [
|
||||||
"places-shutdown"
|
"places-shutdown"
|
||||||
, "places-expiration-finished"
|
|
||||||
, "places-will-close-connection"
|
, "places-will-close-connection"
|
||||||
|
, "places-expiration-finished"
|
||||||
, "places-connection-closed"
|
, "places-connection-closed"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -16,7 +16,6 @@ support-files =
|
|||||||
[test_browserGlue_migrate.js]
|
[test_browserGlue_migrate.js]
|
||||||
[test_browserGlue_prefs.js]
|
[test_browserGlue_prefs.js]
|
||||||
[test_browserGlue_restore.js]
|
[test_browserGlue_restore.js]
|
||||||
[test_browserGlue_shutdown.js]
|
|
||||||
[test_browserGlue_smartBookmarks.js]
|
[test_browserGlue_smartBookmarks.js]
|
||||||
[test_clearHistory_shutdown.js]
|
[test_clearHistory_shutdown.js]
|
||||||
[test_leftpane_corruption_handling.js]
|
[test_leftpane_corruption_handling.js]
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
malformedURI=The URL is not valid and cannot be loaded.
|
malformedURI=The URL is not valid and cannot be loaded.
|
||||||
fileNotFound=Firefox can't find the file at %S.
|
fileNotFound=Firefox can't find the file at %S.
|
||||||
dnsNotFound=Firefox can't find the server at %S.
|
dnsNotFound=Firefox can't find the server at %S.
|
||||||
protocolNotFound=Firefox doesn't know how to open this address, because the protocol (%S) isn't associated with any program.
|
unknownProtocolFound=Firefox doesn't know how to open this address, because one of the following protocols (%S) isn't associated with any program or is not allowed in this context.
|
||||||
connectionFailure=Firefox can't establish a connection to the server at %S.
|
connectionFailure=Firefox can't establish a connection to the server at %S.
|
||||||
netInterrupt=The connection to %S was interrupted while the page was loading.
|
netInterrupt=The connection to %S was interrupted while the page was loading.
|
||||||
netTimeout=The server at %S is taking too long to respond.
|
netTimeout=The server at %S is taking too long to respond.
|
||||||
|
@ -86,8 +86,8 @@
|
|||||||
<!ENTITY netTimeout.title "The connection has timed out">
|
<!ENTITY netTimeout.title "The connection has timed out">
|
||||||
<!ENTITY netTimeout.longDesc "&sharedLongDesc;">
|
<!ENTITY netTimeout.longDesc "&sharedLongDesc;">
|
||||||
|
|
||||||
<!ENTITY protocolNotFound.title "The address wasn't understood">
|
<!ENTITY unknownProtocolFound.title "The address wasn't understood">
|
||||||
<!ENTITY protocolNotFound.longDesc "
|
<!ENTITY unknownProtocolFound.longDesc "
|
||||||
<ul>
|
<ul>
|
||||||
<li>You might need to install other software to open this address.</li>
|
<li>You might need to install other software to open this address.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -48,6 +48,7 @@ let Elements = {};
|
|||||||
["contentViewport", "content-viewport"],
|
["contentViewport", "content-viewport"],
|
||||||
["progress", "progress-control"],
|
["progress", "progress-control"],
|
||||||
["progressContainer", "progress-container"],
|
["progressContainer", "progress-container"],
|
||||||
|
["feedbackLabel", "feedback-label"],
|
||||||
].forEach(function (aElementGlobal) {
|
].forEach(function (aElementGlobal) {
|
||||||
let [name, id] = aElementGlobal;
|
let [name, id] = aElementGlobal;
|
||||||
XPCOMUtils.defineLazyGetter(Elements, name, function() {
|
XPCOMUtils.defineLazyGetter(Elements, name, function() {
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -52,6 +52,17 @@ var SettingsCharm = {
|
|||||||
onselected: function() FlyoutPanelsUI.show('AboutFlyoutPanel')
|
onselected: function() FlyoutPanelsUI.show('AboutFlyoutPanel')
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Feedback
|
||||||
|
this.addEntry({
|
||||||
|
// feedbackLabel is a temporary measure to expose this string
|
||||||
|
// from the baseMenuOverlay.dtd
|
||||||
|
label: Elements.feedbackLabel.value,
|
||||||
|
onselected: function() {
|
||||||
|
let url = Elements.feedbackLabel.getAttribute("href");
|
||||||
|
BrowserUI.addAndShowTab(url, Browser.selectedTab);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Help
|
// Help
|
||||||
this.addEntry({
|
this.addEntry({
|
||||||
label: Strings.browser.GetStringFromName("helpOnlineCharm"),
|
label: Strings.browser.GetStringFromName("helpOnlineCharm"),
|
||||||
|
@ -275,7 +275,7 @@
|
|||||||
<h1 id="et_dnsNotFound">&dnsNotFound.title;</h1>
|
<h1 id="et_dnsNotFound">&dnsNotFound.title;</h1>
|
||||||
<h1 id="et_fileNotFound">&fileNotFound.title;</h1>
|
<h1 id="et_fileNotFound">&fileNotFound.title;</h1>
|
||||||
<h1 id="et_malformedURI">&malformedURI.title;</h1>
|
<h1 id="et_malformedURI">&malformedURI.title;</h1>
|
||||||
<h1 id="et_protocolNotFound">&protocolNotFound.title;</h1>
|
<h1 id="et_unknownProtocolFound">&unknownProtocolFound.title;</h1>
|
||||||
<h1 id="et_connectionFailure">&connectionFailure.title;</h1>
|
<h1 id="et_connectionFailure">&connectionFailure.title;</h1>
|
||||||
<h1 id="et_netTimeout">&netTimeout.title;</h1>
|
<h1 id="et_netTimeout">&netTimeout.title;</h1>
|
||||||
<h1 id="et_redirectLoop">&redirectLoop.title;</h1>
|
<h1 id="et_redirectLoop">&redirectLoop.title;</h1>
|
||||||
@ -300,7 +300,7 @@
|
|||||||
<div id="ed_dnsNotFound">&dnsNotFound.longDesc;</div>
|
<div id="ed_dnsNotFound">&dnsNotFound.longDesc;</div>
|
||||||
<div id="ed_fileNotFound">&fileNotFound.longDesc;</div>
|
<div id="ed_fileNotFound">&fileNotFound.longDesc;</div>
|
||||||
<div id="ed_malformedURI">&malformedURI.longDesc;</div>
|
<div id="ed_malformedURI">&malformedURI.longDesc;</div>
|
||||||
<div id="ed_protocolNotFound">&protocolNotFound.longDesc;</div>
|
<div id="ed_unknownProtocolFound">&unknownProtocolFound.longDesc;</div>
|
||||||
<div id="ed_connectionFailure">&connectionFailure.longDesc;</div>
|
<div id="ed_connectionFailure">&connectionFailure.longDesc;</div>
|
||||||
<div id="ed_netTimeout">&netTimeout.longDesc;</div>
|
<div id="ed_netTimeout">&netTimeout.longDesc;</div>
|
||||||
<div id="ed_redirectLoop">&redirectLoop.longDesc;</div>
|
<div id="ed_redirectLoop">&redirectLoop.longDesc;</div>
|
||||||
|
@ -109,7 +109,7 @@ HelperAppLauncherDialog.prototype = {
|
|||||||
let chromeWin = this._getChromeWindow(window).wrappedJSObject;
|
let chromeWin = this._getChromeWindow(window).wrappedJSObject;
|
||||||
let notificationBox = chromeWin.Browser.getNotificationBox();
|
let notificationBox = chromeWin.Browser.getNotificationBox();
|
||||||
let document = notificationBox.ownerDocument;
|
let document = notificationBox.ownerDocument;
|
||||||
downloadSize = this._getDownloadSize(aLauncher.contentLength);
|
let downloadSize = this._getDownloadSize(aLauncher.contentLength);
|
||||||
|
|
||||||
let msg = browserBundle.GetStringFromName("alertDownloadSave2");
|
let msg = browserBundle.GetStringFromName("alertDownloadSave2");
|
||||||
|
|
||||||
|
@ -39,6 +39,8 @@
|
|||||||
@AB_CD@.jar:
|
@AB_CD@.jar:
|
||||||
relativesrcdir browser/locales:
|
relativesrcdir browser/locales:
|
||||||
locale/browser/syncBrand.dtd (%chrome/browser/syncBrand.dtd)
|
locale/browser/syncBrand.dtd (%chrome/browser/syncBrand.dtd)
|
||||||
|
# Temporary hack to provide a 'feedback' string
|
||||||
|
locale/browser/baseMenuOverlay.dtd (%chrome/browser/baseMenuOverlay.dtd)
|
||||||
locale/browser/netError.dtd (%chrome/overrides/netError.dtd)
|
locale/browser/netError.dtd (%chrome/overrides/netError.dtd)
|
||||||
% override chrome://global/locale/netError.dtd chrome://browser/locale/netError.dtd
|
% override chrome://global/locale/netError.dtd chrome://browser/locale/netError.dtd
|
||||||
locale/browser/appstrings.properties (%chrome/overrides/appstrings.properties)
|
locale/browser/appstrings.properties (%chrome/overrides/appstrings.properties)
|
||||||
|
@ -298,6 +298,7 @@ toolbarpaletteitem[place="palette"] > toolbaritem > toolbarbutton {
|
|||||||
|
|
||||||
#PanelUI-footer {
|
#PanelUI-footer {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-shrink: 0;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
background-color: rgba(0, 0, 0, 0.05);
|
background-color: rgba(0, 0, 0, 0.05);
|
||||||
box-shadow: 0 -1px 0 rgba(0,0,0,.15);
|
box-shadow: 0 -1px 0 rgba(0,0,0,.15);
|
||||||
|
@ -15,9 +15,6 @@
|
|||||||
<tt> aa_block: /* innermost frame denies a */</tt><br/>
|
<tt> aa_block: /* innermost frame denies a */</tt><br/>
|
||||||
<iframe id='aa_block'></iframe><br/>
|
<iframe id='aa_block'></iframe><br/>
|
||||||
|
|
||||||
<tt> aa2_block: /* innermost frame (view-source: URL) denies a */</tt><br/>
|
|
||||||
<iframe id='aa2_block'></iframe><br/>
|
|
||||||
|
|
||||||
<tt> ab_allow: /* innermost frame allows a */</tt><br/>
|
<tt> ab_allow: /* innermost frame allows a */</tt><br/>
|
||||||
<iframe id='ab_allow'></iframe><br/>
|
<iframe id='ab_allow'></iframe><br/>
|
||||||
|
|
||||||
|
@ -22,10 +22,6 @@ function setupFrames() {
|
|||||||
elt.src = base.a + "?testid=aa_block&internalframe=aa_b&csp=" +
|
elt.src = base.a + "?testid=aa_block&internalframe=aa_b&csp=" +
|
||||||
escape("allow 'none'; frame-ancestors 'none'; script-src 'self'");
|
escape("allow 'none'; frame-ancestors 'none'; script-src 'self'");
|
||||||
|
|
||||||
elt = $('aa2_block');
|
|
||||||
elt.src = "view-source:" + base.a + "?testid=aa2_block&internalframe=aa_b&csp=" +
|
|
||||||
escape("allow 'none'; frame-ancestors 'none'; script-src 'self'");
|
|
||||||
|
|
||||||
elt = $('ab_allow');
|
elt = $('ab_allow');
|
||||||
elt.src = base.b + "?testid=ab_allow&internalframe=ab_a&csp=" +
|
elt.src = base.b + "?testid=ab_allow&internalframe=ab_a&csp=" +
|
||||||
escape("allow 'none'; frame-ancestors " + host.a + "; script-src 'self'");
|
escape("allow 'none'; frame-ancestors " + host.a + "; script-src 'self'");
|
||||||
|
@ -15,9 +15,6 @@
|
|||||||
<tt> aa_block: /* innermost frame denies a */</tt><br/>
|
<tt> aa_block: /* innermost frame denies a */</tt><br/>
|
||||||
<iframe id='aa_block_spec_compliant'></iframe><br/>
|
<iframe id='aa_block_spec_compliant'></iframe><br/>
|
||||||
|
|
||||||
<tt> aa2_block: /* innermost frame (view-source: URL) denies a */</tt><br/>
|
|
||||||
<iframe id='aa2_block_spec_compliant'></iframe><br/>
|
|
||||||
|
|
||||||
<tt> ab_allow: /* innermost frame allows a */</tt><br/>
|
<tt> ab_allow: /* innermost frame allows a */</tt><br/>
|
||||||
<iframe id='ab_allow_spec_compliant'></iframe><br/>
|
<iframe id='ab_allow_spec_compliant'></iframe><br/>
|
||||||
|
|
||||||
|
@ -22,10 +22,6 @@ function setupFrames() {
|
|||||||
elt.src = base.a + "?testid=aa_block_spec_compliant&internalframe=aa_b&csp=" +
|
elt.src = base.a + "?testid=aa_block_spec_compliant&internalframe=aa_b&csp=" +
|
||||||
escape("default-src 'none'; frame-ancestors 'none'; script-src 'self'");
|
escape("default-src 'none'; frame-ancestors 'none'; script-src 'self'");
|
||||||
|
|
||||||
elt = $('aa2_block_spec_compliant');
|
|
||||||
elt.src = "view-source:" + base.a + "?testid=aa2_block_spec_compliant&internalframe=aa_b&csp=" +
|
|
||||||
escape("default-src 'none'; frame-ancestors 'none'; script-src 'self'");
|
|
||||||
|
|
||||||
elt = $('ab_allow_spec_compliant');
|
elt = $('ab_allow_spec_compliant');
|
||||||
elt.src = base.b + "?testid=ab_allow_spec_compliant&internalframe=ab_a&csp=" +
|
elt.src = base.b + "?testid=ab_allow_spec_compliant&internalframe=ab_a&csp=" +
|
||||||
escape("default-src 'none'; frame-ancestors " + host.a + "; script-src 'self'");
|
escape("default-src 'none'; frame-ancestors " + host.a + "; script-src 'self'");
|
||||||
|
@ -20,7 +20,6 @@ var path = "/tests/content/base/test/csp/";
|
|||||||
var framesThatShouldLoad = {
|
var framesThatShouldLoad = {
|
||||||
aa_allow: -1, /* innermost frame allows a */
|
aa_allow: -1, /* innermost frame allows a */
|
||||||
//aa_block: -1, /* innermost frame denies a */
|
//aa_block: -1, /* innermost frame denies a */
|
||||||
//aa2_block: -1, /* innermost frame denies a */
|
|
||||||
ab_allow: -1, /* innermost frame allows a */
|
ab_allow: -1, /* innermost frame allows a */
|
||||||
//ab_block: -1, /* innermost frame denies a */
|
//ab_block: -1, /* innermost frame denies a */
|
||||||
aba_allow: -1, /* innermost frame allows b,a */
|
aba_allow: -1, /* innermost frame allows b,a */
|
||||||
@ -31,7 +30,6 @@ var framesThatShouldLoad = {
|
|||||||
//abb2_block: -1, /* innermost frame denies a */
|
//abb2_block: -1, /* innermost frame denies a */
|
||||||
aa_allow_spec_compliant: -1, /* innermost frame allows a *
|
aa_allow_spec_compliant: -1, /* innermost frame allows a *
|
||||||
//aa_block_spec_compliant: -1, /* innermost frame denies a */
|
//aa_block_spec_compliant: -1, /* innermost frame denies a */
|
||||||
//aa2_block_spec_compliant: -1, /* innermost frame denies a */
|
|
||||||
ab_allow_spec_compliant: -1, /* innermost frame allows a */
|
ab_allow_spec_compliant: -1, /* innermost frame allows a */
|
||||||
//ab_block_spec_compliant: -1, /* innermost frame denies a */
|
//ab_block_spec_compliant: -1, /* innermost frame denies a */
|
||||||
aba_allow_spec_compliant: -1, /* innermost frame allows b,a */
|
aba_allow_spec_compliant: -1, /* innermost frame allows b,a */
|
||||||
@ -42,7 +40,7 @@ var framesThatShouldLoad = {
|
|||||||
//abb2_block_spec_compliant: -1, /* innermost frame denies a */
|
//abb2_block_spec_compliant: -1, /* innermost frame denies a */
|
||||||
};
|
};
|
||||||
|
|
||||||
var expectedViolationsLeft = 14;
|
var expectedViolationsLeft = 12;
|
||||||
|
|
||||||
// This is used to watch the blocked data bounce off CSP and allowed data
|
// This is used to watch the blocked data bounce off CSP and allowed data
|
||||||
// get sent out to the wire.
|
// get sent out to the wire.
|
||||||
|
@ -4386,12 +4386,25 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI *aURI,
|
|||||||
// Turn the error code into a human readable error message.
|
// Turn the error code into a human readable error message.
|
||||||
if (NS_ERROR_UNKNOWN_PROTOCOL == aError) {
|
if (NS_ERROR_UNKNOWN_PROTOCOL == aError) {
|
||||||
NS_ENSURE_ARG_POINTER(aURI);
|
NS_ENSURE_ARG_POINTER(aURI);
|
||||||
// extract the scheme
|
|
||||||
|
// Extract the schemes into a comma delimited list.
|
||||||
nsAutoCString scheme;
|
nsAutoCString scheme;
|
||||||
aURI->GetScheme(scheme);
|
aURI->GetScheme(scheme);
|
||||||
CopyASCIItoUTF16(scheme, formatStrs[0]);
|
CopyASCIItoUTF16(scheme, formatStrs[0]);
|
||||||
|
nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(aURI);
|
||||||
|
while (nestedURI) {
|
||||||
|
nsCOMPtr<nsIURI> tempURI;
|
||||||
|
nsresult rv2;
|
||||||
|
rv2 = nestedURI->GetInnerURI(getter_AddRefs(tempURI));
|
||||||
|
if (NS_SUCCEEDED(rv2) && tempURI) {
|
||||||
|
tempURI->GetScheme(scheme);
|
||||||
|
formatStrs[0].Append(NS_LITERAL_STRING(", "));
|
||||||
|
AppendASCIItoUTF16(scheme, formatStrs[0]);
|
||||||
|
}
|
||||||
|
nestedURI = do_QueryInterface(tempURI);
|
||||||
|
}
|
||||||
formatStrCount = 1;
|
formatStrCount = 1;
|
||||||
error.AssignLiteral("protocolNotFound");
|
error.AssignLiteral("unknownProtocolFound");
|
||||||
}
|
}
|
||||||
else if (NS_ERROR_FILE_NOT_FOUND == aError) {
|
else if (NS_ERROR_FILE_NOT_FOUND == aError) {
|
||||||
NS_ENSURE_ARG_POINTER(aURI);
|
NS_ENSURE_ARG_POINTER(aURI);
|
||||||
@ -9682,6 +9695,25 @@ nsDocShell::DoURILoad(nsIURI * aURI,
|
|||||||
channelPolicy->SetLoadType(nsIContentPolicy::TYPE_SUBDOCUMENT);
|
channelPolicy->SetLoadType(nsIContentPolicy::TYPE_SUBDOCUMENT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Only allow view-source scheme in top-level docshells. view-source is
|
||||||
|
// the only scheme to which this applies at the moment due to potential
|
||||||
|
// timing attacks to read data from cross-origin iframes. If this widens
|
||||||
|
// we should add a protocol flag for whether the scheme is allowed in
|
||||||
|
// frames and use something like nsNetUtil::NS_URIChainHasFlags.
|
||||||
|
nsCOMPtr<nsIURI> tempURI = aURI;
|
||||||
|
nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(tempURI);
|
||||||
|
while (nestedURI) {
|
||||||
|
// view-source should always be an nsINestedURI, loop and check the
|
||||||
|
// scheme on this and all inner URIs that are also nested URIs.
|
||||||
|
bool isViewSource = false;
|
||||||
|
rv = tempURI->SchemeIs("view-source", &isViewSource);
|
||||||
|
if (NS_FAILED(rv) || isViewSource) {
|
||||||
|
return NS_ERROR_UNKNOWN_PROTOCOL;
|
||||||
|
}
|
||||||
|
nestedURI->GetInnerURI(getter_AddRefs(tempURI));
|
||||||
|
nestedURI = do_QueryInterface(tempURI);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// open a channel for the url
|
// open a channel for the url
|
||||||
|
@ -274,7 +274,7 @@
|
|||||||
<h1 id="et_dnsNotFound">&dnsNotFound.title;</h1>
|
<h1 id="et_dnsNotFound">&dnsNotFound.title;</h1>
|
||||||
<h1 id="et_fileNotFound">&fileNotFound.title;</h1>
|
<h1 id="et_fileNotFound">&fileNotFound.title;</h1>
|
||||||
<h1 id="et_malformedURI">&malformedURI.title;</h1>
|
<h1 id="et_malformedURI">&malformedURI.title;</h1>
|
||||||
<h1 id="et_protocolNotFound">&protocolNotFound.title;</h1>
|
<h1 id="et_unknownProtocolFound">&unknownProtocolFound.title;</h1>
|
||||||
<h1 id="et_connectionFailure">&connectionFailure.title;</h1>
|
<h1 id="et_connectionFailure">&connectionFailure.title;</h1>
|
||||||
<h1 id="et_netTimeout">&netTimeout.title;</h1>
|
<h1 id="et_netTimeout">&netTimeout.title;</h1>
|
||||||
<h1 id="et_redirectLoop">&redirectLoop.title;</h1>
|
<h1 id="et_redirectLoop">&redirectLoop.title;</h1>
|
||||||
@ -300,7 +300,7 @@
|
|||||||
<div id="ed_dnsNotFound">&dnsNotFound.longDesc;</div>
|
<div id="ed_dnsNotFound">&dnsNotFound.longDesc;</div>
|
||||||
<div id="ed_fileNotFound">&fileNotFound.longDesc;</div>
|
<div id="ed_fileNotFound">&fileNotFound.longDesc;</div>
|
||||||
<div id="ed_malformedURI">&malformedURI.longDesc;</div>
|
<div id="ed_malformedURI">&malformedURI.longDesc;</div>
|
||||||
<div id="ed_protocolNotFound">&protocolNotFound.longDesc;</div>
|
<div id="ed_unknownProtocolFound">&unknownProtocolFound.longDesc;</div>
|
||||||
<div id="ed_connectionFailure">&connectionFailure.longDesc;</div>
|
<div id="ed_connectionFailure">&connectionFailure.longDesc;</div>
|
||||||
<div id="ed_netTimeout">&netTimeout.longDesc;</div>
|
<div id="ed_netTimeout">&netTimeout.longDesc;</div>
|
||||||
<div id="ed_redirectLoop">&redirectLoop.longDesc;</div>
|
<div id="ed_redirectLoop">&redirectLoop.longDesc;</div>
|
||||||
|
@ -42,6 +42,7 @@ support-files =
|
|||||||
bug909218.js
|
bug909218.js
|
||||||
bug92598_window.xul
|
bug92598_window.xul
|
||||||
docshell_helpers.js
|
docshell_helpers.js
|
||||||
|
file_viewsource_forbidden_in_iframe.html
|
||||||
generic.html
|
generic.html
|
||||||
mozFrameType_window.xul
|
mozFrameType_window.xul
|
||||||
|
|
||||||
@ -78,3 +79,4 @@ support-files =
|
|||||||
[test_mozFrameType.xul]
|
[test_mozFrameType.xul]
|
||||||
[test_principalInherit.xul]
|
[test_principalInherit.xul]
|
||||||
[test_private_hidden_window.html]
|
[test_private_hidden_window.html]
|
||||||
|
[test_viewsource_forbidden_in_iframe.xul]
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Test ifranes for view-source forbidden in iframe tests</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<iframe id="testIframe"></iframe>
|
||||||
|
<iframe id="refIframe"></iframe>
|
||||||
|
</body>
|
||||||
|
</html>
|
180
docshell/test/chrome/test_viewsource_forbidden_in_iframe.xul
Normal file
180
docshell/test/chrome/test_viewsource_forbidden_in_iframe.xul
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<?xml-stylesheet type="text/css" href="chrome://global/skin/"?>
|
||||||
|
<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
|
||||||
|
<!--
|
||||||
|
https://bugzilla.mozilla.org/show_bug.cgi?id=624883
|
||||||
|
-->
|
||||||
|
<window title="Mozilla Bug 624883"
|
||||||
|
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||||
|
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
|
||||||
|
|
||||||
|
<!-- test results are displayed in the html:body -->
|
||||||
|
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=624883"
|
||||||
|
target="_blank">Mozilla Bug 624883</a>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
<!-- test code goes here -->
|
||||||
|
<iframe type="content" onload="startTest()" src="file_viewsource_forbidden_in_iframe.html"></iframe>
|
||||||
|
|
||||||
|
<script type="application/javascript">
|
||||||
|
<![CDATA[
|
||||||
|
|
||||||
|
const Ci = Components.interfaces;
|
||||||
|
const Cu = Components.utils;
|
||||||
|
|
||||||
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
|
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
|
||||||
|
// We create a promise that will resolve with the error message
|
||||||
|
// on a network error page load and reject on any other load.
|
||||||
|
function createNetworkErrorMessagePromise(frame) {
|
||||||
|
return new Promise(function(resolve, reject) {
|
||||||
|
|
||||||
|
// Error pages do not fire "load" events, so use a progressListener.
|
||||||
|
var originalDocumentURI = frame.contentDocument.documentURI;
|
||||||
|
var progressListener = {
|
||||||
|
onLocationChange: function(aWebProgress, aRequest, aLocation, aFlags) {
|
||||||
|
// Make sure nothing other than an error page is loaded.
|
||||||
|
if (!(aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_ERROR_PAGE)) {
|
||||||
|
reject("location change was not to an error page");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus) {
|
||||||
|
// Wait until the documentURI changes (from about:blank) this should
|
||||||
|
// be the error page URI.
|
||||||
|
var documentURI = frame.contentDocument.documentURI;
|
||||||
|
if (documentURI == originalDocumentURI) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
aWebProgress.removeProgressListener(progressListener,
|
||||||
|
Ci.nsIWebProgress.NOTIFY_ALL);
|
||||||
|
var matchArray = /about:neterror\?.*&d=([^&]*)/.exec(documentURI);
|
||||||
|
if (!matchArray) {
|
||||||
|
reject("no network error message found in URI")
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var errorMsg = matchArray[1];
|
||||||
|
resolve(decodeURIComponent(errorMsg));
|
||||||
|
},
|
||||||
|
|
||||||
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
|
||||||
|
Ci.nsISupportsWeakReference])
|
||||||
|
};
|
||||||
|
|
||||||
|
frame.contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||||
|
.getInterface(Ci.nsIWebNavigation)
|
||||||
|
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||||
|
.getInterface(Ci.nsIWebProgress)
|
||||||
|
.addProgressListener(progressListener,
|
||||||
|
Ci.nsIWebProgress.NOTIFY_LOCATION |
|
||||||
|
Ci.nsIWebProgress.NOTIFY_STATE_REQUEST);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function startTest() {
|
||||||
|
// Get a reference message that we know will be an unknown protocol message,
|
||||||
|
// so we can use it for comparisons in the test cases.
|
||||||
|
var refIframe = window[0].document.getElementById("refIframe");
|
||||||
|
var refErrorPromise = createNetworkErrorMessagePromise(refIframe);
|
||||||
|
|
||||||
|
refErrorPromise.then(
|
||||||
|
function(msg) {
|
||||||
|
window.refErrorMsg = msg;
|
||||||
|
var testIframe = window[0].document.getElementById("testIframe");
|
||||||
|
|
||||||
|
// Run test cases on load of "about:blank", so that the URI always changes
|
||||||
|
// and we can detect this in our Promise.
|
||||||
|
testIframe.onload = runNextTestCase;
|
||||||
|
testIframe.src = "about:blank";
|
||||||
|
},
|
||||||
|
function(reason) {
|
||||||
|
ok(false, "Could not get reference error message", reason);
|
||||||
|
SimpleTest.finish();
|
||||||
|
})
|
||||||
|
.catch(function(e) {
|
||||||
|
ok(false, "Unexpected exception thrown getting reference error message", exception);
|
||||||
|
});
|
||||||
|
|
||||||
|
refIframe.src = "wibble://example.com";
|
||||||
|
}
|
||||||
|
|
||||||
|
function runTestCase(testCase) {
|
||||||
|
var testIframe = window[0].document.getElementById("testIframe");
|
||||||
|
var expectedErrorMsg = window.refErrorMsg.replace("wibble", testCase.expectedProtocolList);
|
||||||
|
|
||||||
|
var testErrorPromise = createNetworkErrorMessagePromise(testIframe);
|
||||||
|
testErrorPromise.then(
|
||||||
|
function(actualErrorMsg) {
|
||||||
|
is(actualErrorMsg, expectedErrorMsg, testCase.desc);
|
||||||
|
testIframe.src = "about:blank";
|
||||||
|
},
|
||||||
|
function(reason) {
|
||||||
|
ok(false, testCase.desc, reason);
|
||||||
|
testIframe.src = "about:blank";
|
||||||
|
})
|
||||||
|
.catch(function(e) {
|
||||||
|
ok(false, testCase.desc + " - unexpected exception thrown", exception);
|
||||||
|
});
|
||||||
|
|
||||||
|
testIframe.src = testCase.protocols + "://example.com/!/";
|
||||||
|
}
|
||||||
|
|
||||||
|
var testCaseIndex = -1;
|
||||||
|
testCases = [
|
||||||
|
{
|
||||||
|
desc: "Test 1: view-source should not be allowed in an iframe",
|
||||||
|
protocols: "view-source:http",
|
||||||
|
expectedProtocolList: "view-source, http"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "Test 2: feed:view-source should not be allowed in an iframe",
|
||||||
|
protocols: "feed:view-source:http",
|
||||||
|
expectedProtocolList: "feed, view-source, http"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "Test 3: jar:view-source should not be allowed in an iframe",
|
||||||
|
protocols: "jar:view-source:http",
|
||||||
|
expectedProtocolList: "jar, view-source, http"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "Test 4: pcast:view-source should not be allowed in an iframe",
|
||||||
|
protocols: "pcast:view-source:http",
|
||||||
|
expectedProtocolList: "pcast, view-source, http"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "Test 5: pcast:feed:view-source should not be allowed in an iframe",
|
||||||
|
protocols: "pcast:feed:view-source:http",
|
||||||
|
expectedProtocolList: "pcast, feed, view-source, http"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "Test 6: if invalid protocol first should report before view-source",
|
||||||
|
protocols: "wibble:view-source:http",
|
||||||
|
// Nothing after the invalid protocol gets set as a proper nested URI,
|
||||||
|
// so the list stops there.
|
||||||
|
expectedProtocolList: "wibble"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "Test 7: if view-source first should report before invalid protocol",
|
||||||
|
protocols: "view-source:wibble:http",
|
||||||
|
expectedProtocolList: "view-source, wibble"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
function runNextTestCase() {
|
||||||
|
++testCaseIndex;
|
||||||
|
if (testCaseIndex == testCases.length) {
|
||||||
|
SimpleTest.finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
runTestCase(testCases[testCaseIndex]);
|
||||||
|
}
|
||||||
|
|
||||||
|
]]>
|
||||||
|
</script>
|
||||||
|
</window>
|
@ -1926,11 +1926,6 @@ Navigator::HasDataStoreSupport(JSContext* cx, JSObject* aGlobal)
|
|||||||
{
|
{
|
||||||
JS::Rooted<JSObject*> global(cx, aGlobal);
|
JS::Rooted<JSObject*> global(cx, aGlobal);
|
||||||
|
|
||||||
// DataStore is enabled by default for chrome code.
|
|
||||||
if (nsContentUtils::IsCallerChrome()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// First of all, the general pref has to be turned on.
|
// First of all, the general pref has to be turned on.
|
||||||
bool enabled = false;
|
bool enabled = false;
|
||||||
Preferences::GetBool("dom.datastore.enabled", &enabled);
|
Preferences::GetBool("dom.datastore.enabled", &enabled);
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
malformedURI=The URL is not valid and cannot be loaded.
|
malformedURI=The URL is not valid and cannot be loaded.
|
||||||
fileNotFound=The file %S cannot be found. Please check the location and try again.
|
fileNotFound=The file %S cannot be found. Please check the location and try again.
|
||||||
dnsNotFound=%S could not be found. Please check the name and try again.
|
dnsNotFound=%S could not be found. Please check the name and try again.
|
||||||
protocolNotFound=%S is not a registered protocol.
|
unknownProtocolFound=One of the following %S is not a registered protocol or is not allowed in this context.
|
||||||
connectionFailure=The connection was refused when attempting to contact %S.
|
connectionFailure=The connection was refused when attempting to contact %S.
|
||||||
netInterrupt=The connection to %S has terminated unexpectedly. Some data may have been transferred.
|
netInterrupt=The connection to %S has terminated unexpectedly. Some data may have been transferred.
|
||||||
netTimeout=The operation timed out when attempting to contact %S.
|
netTimeout=The operation timed out when attempting to contact %S.
|
||||||
|
@ -50,8 +50,8 @@
|
|||||||
<!ENTITY netTimeout.title "Network Timeout">
|
<!ENTITY netTimeout.title "Network Timeout">
|
||||||
<!ENTITY netTimeout.longDesc "<p>The requested site did not respond to a connection request and the browser has stopped waiting for a reply.</p><ul><li>Could the server be experiencing high demand or a temporary outage? Try again later.</li><li>Are you unable to browse other sites? Check the computer's network connection.</li><li>Is your computer or network protected by a firewall or proxy? Incorrect settings can interfere with Web browsing.</li><li>Still having trouble? Consult your network administrator or Internet provider for assistance.</li></ul>">
|
<!ENTITY netTimeout.longDesc "<p>The requested site did not respond to a connection request and the browser has stopped waiting for a reply.</p><ul><li>Could the server be experiencing high demand or a temporary outage? Try again later.</li><li>Are you unable to browse other sites? Check the computer's network connection.</li><li>Is your computer or network protected by a firewall or proxy? Incorrect settings can interfere with Web browsing.</li><li>Still having trouble? Consult your network administrator or Internet provider for assistance.</li></ul>">
|
||||||
|
|
||||||
<!ENTITY protocolNotFound.title "Unknown Protocol">
|
<!ENTITY unknownProtocolFound.title "Unknown Protocol">
|
||||||
<!ENTITY protocolNotFound.longDesc "<p>The address specifies a protocol (e.g. <q>wxyz://</q>) the browser does not recognize, so the browser cannot properly connect to the site.</p><ul><li>Are you trying to access multimedia or other non-text services? Check the site for extra requirements.</li><li>Some protocols may require third-party software or plugins before the browser can recognize them.</li></ul>">
|
<!ENTITY unknownProtocolFound.longDesc "<p>The address specifies a protocol (e.g. <q>wxyz://</q>) the browser does not recognize, so the browser cannot properly connect to the site.</p><ul><li>Are you trying to access multimedia or other non-text services? Check the site for extra requirements.</li><li>Some protocols may require third-party software or plugins before the browser can recognize them.</li></ul>">
|
||||||
|
|
||||||
<!ENTITY proxyConnectFailure.title "Proxy Server Refused Connection">
|
<!ENTITY proxyConnectFailure.title "Proxy Server Refused Connection">
|
||||||
<!ENTITY proxyConnectFailure.longDesc "<p>The browser is configured to use a proxy server, but the proxy refused a connection.</p><ul><li>Is the browser's proxy configuration correct? Check the settings and try again.</li><li>Does the proxy service allow connections from this network?</li><li>Still having trouble? Consult your network administrator or Internet provider for assistance.</li></ul>">
|
<!ENTITY proxyConnectFailure.longDesc "<p>The browser is configured to use a proxy server, but the proxy refused a connection.</p><ul><li>Is the browser's proxy configuration correct? Check the settings and try again.</li><li>Does the proxy service allow connections from this network?</li><li>Still having trouble? Consult your network administrator or Internet provider for assistance.</li></ul>">
|
||||||
|
@ -716,6 +716,21 @@ APZCTreeManager::DispatchScroll(AsyncPanZoomController* aPrev, ScreenPoint aStar
|
|||||||
next->AttemptScroll(aStartPoint, aEndPoint, aOverscrollHandoffChainIndex);
|
next->AttemptScroll(aStartPoint, aEndPoint, aOverscrollHandoffChainIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
APZCTreeManager::FlushRepaintsForOverscrollHandoffChain()
|
||||||
|
{
|
||||||
|
if (mOverscrollHandoffChain.length() == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (uint32_t i = 0; i < mOverscrollHandoffChain.length(); i++) {
|
||||||
|
nsRefPtr<AsyncPanZoomController> item = mOverscrollHandoffChain[i];
|
||||||
|
if (item) {
|
||||||
|
item->FlushRepaintForOverscrollHandoff();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
APZCTreeManager::HitTestAPZC(const ScreenIntPoint& aPoint)
|
APZCTreeManager::HitTestAPZC(const ScreenIntPoint& aPoint)
|
||||||
{
|
{
|
||||||
|
@ -256,6 +256,8 @@ public:
|
|||||||
void DispatchScroll(AsyncPanZoomController* aAPZC, ScreenPoint aStartPoint, ScreenPoint aEndPoint,
|
void DispatchScroll(AsyncPanZoomController* aAPZC, ScreenPoint aStartPoint, ScreenPoint aEndPoint,
|
||||||
uint32_t aOverscrollHandoffChainIndex);
|
uint32_t aOverscrollHandoffChainIndex);
|
||||||
|
|
||||||
|
bool FlushRepaintsForOverscrollHandoffChain();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* Debug-build assertion that can be called to ensure code is running on the
|
* Debug-build assertion that can be called to ensure code is running on the
|
||||||
|
@ -575,16 +575,18 @@ nsEventStatus AsyncPanZoomController::ReceiveInputEvent(const InputData& aEvent)
|
|||||||
nsEventStatus AsyncPanZoomController::HandleInputEvent(const InputData& aEvent) {
|
nsEventStatus AsyncPanZoomController::HandleInputEvent(const InputData& aEvent) {
|
||||||
nsEventStatus rv = nsEventStatus_eIgnore;
|
nsEventStatus rv = nsEventStatus_eIgnore;
|
||||||
|
|
||||||
nsRefPtr<GestureEventListener> listener = GetGestureEventListener();
|
|
||||||
if (listener) {
|
|
||||||
rv = listener->HandleInputEvent(aEvent);
|
|
||||||
if (rv == nsEventStatus_eConsumeNoDefault)
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (aEvent.mInputType) {
|
switch (aEvent.mInputType) {
|
||||||
case MULTITOUCH_INPUT: {
|
case MULTITOUCH_INPUT: {
|
||||||
const MultiTouchInput& multiTouchInput = aEvent.AsMultiTouchInput();
|
const MultiTouchInput& multiTouchInput = aEvent.AsMultiTouchInput();
|
||||||
|
|
||||||
|
nsRefPtr<GestureEventListener> listener = GetGestureEventListener();
|
||||||
|
if (listener) {
|
||||||
|
rv = listener->HandleInputEvent(multiTouchInput);
|
||||||
|
if (rv == nsEventStatus_eConsumeNoDefault) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (multiTouchInput.mType) {
|
switch (multiTouchInput.mType) {
|
||||||
case MultiTouchInput::MULTITOUCH_START: rv = OnTouchStart(multiTouchInput); break;
|
case MultiTouchInput::MULTITOUCH_START: rv = OnTouchStart(multiTouchInput); break;
|
||||||
case MultiTouchInput::MULTITOUCH_MOVE: rv = OnTouchMove(multiTouchInput); break;
|
case MultiTouchInput::MULTITOUCH_MOVE: rv = OnTouchMove(multiTouchInput); break;
|
||||||
@ -757,9 +759,17 @@ nsEventStatus AsyncPanZoomController::OnTouchEnd(const MultiTouchInput& aEvent)
|
|||||||
case PANNING_LOCKED_X:
|
case PANNING_LOCKED_X:
|
||||||
case PANNING_LOCKED_Y:
|
case PANNING_LOCKED_Y:
|
||||||
{
|
{
|
||||||
ReentrantMonitorAutoEnter lock(mMonitor);
|
// Make a local copy of the tree manager pointer and check if it's not
|
||||||
RequestContentRepaint();
|
// null before calling HandleOverscroll(). This is necessary because
|
||||||
UpdateSharedCompositorFrameMetrics();
|
// Destroy(), which nulls out mTreeManager, could be called concurrently.
|
||||||
|
APZCTreeManager* treeManagerLocal = mTreeManager;
|
||||||
|
if (treeManagerLocal) {
|
||||||
|
if (!treeManagerLocal->FlushRepaintsForOverscrollHandoffChain()) {
|
||||||
|
NS_WARNING("Overscroll handoff chain was empty during panning! This should not be the case.");
|
||||||
|
// Graceful handling of error condition
|
||||||
|
FlushRepaintForOverscrollHandoff();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mX.EndTouch();
|
mX.EndTouch();
|
||||||
mY.EndTouch();
|
mY.EndTouch();
|
||||||
@ -1389,6 +1399,12 @@ void AsyncPanZoomController::ScheduleComposite() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AsyncPanZoomController::FlushRepaintForOverscrollHandoff() {
|
||||||
|
ReentrantMonitorAutoEnter lock(mMonitor);
|
||||||
|
RequestContentRepaint();
|
||||||
|
UpdateSharedCompositorFrameMetrics();
|
||||||
|
}
|
||||||
|
|
||||||
void AsyncPanZoomController::RequestContentRepaint() {
|
void AsyncPanZoomController::RequestContentRepaint() {
|
||||||
RequestContentRepaint(mFrameMetrics);
|
RequestContentRepaint(mFrameMetrics);
|
||||||
}
|
}
|
||||||
|
@ -333,6 +333,8 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool HasScrollgrab() const { return mFrameMetrics.mHasScrollgrab; }
|
bool HasScrollgrab() const { return mFrameMetrics.mHasScrollgrab; }
|
||||||
|
|
||||||
|
void FlushRepaintForOverscrollHandoff();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* Helper method for touches beginning. Sets everything up for panning and any
|
* Helper method for touches beginning. Sets everything up for panning and any
|
||||||
|
@ -48,26 +48,20 @@ GestureEventListener::~GestureEventListener()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
nsEventStatus GestureEventListener::HandleInputEvent(const InputData& aEvent)
|
nsEventStatus GestureEventListener::HandleInputEvent(const MultiTouchInput& aEvent)
|
||||||
{
|
{
|
||||||
if (aEvent.mInputType != MULTITOUCH_INPUT) {
|
|
||||||
return nsEventStatus_eIgnore;
|
|
||||||
}
|
|
||||||
|
|
||||||
const MultiTouchInput& event = static_cast<const MultiTouchInput&>(aEvent);
|
|
||||||
|
|
||||||
// Cache the current event since it may become the single or long tap that we
|
// Cache the current event since it may become the single or long tap that we
|
||||||
// send.
|
// send.
|
||||||
mLastTouchInput = event;
|
mLastTouchInput = aEvent;
|
||||||
|
|
||||||
switch (event.mType)
|
switch (aEvent.mType)
|
||||||
{
|
{
|
||||||
case MultiTouchInput::MULTITOUCH_START:
|
case MultiTouchInput::MULTITOUCH_START:
|
||||||
case MultiTouchInput::MULTITOUCH_ENTER: {
|
case MultiTouchInput::MULTITOUCH_ENTER: {
|
||||||
for (size_t i = 0; i < event.mTouches.Length(); i++) {
|
for (size_t i = 0; i < aEvent.mTouches.Length(); i++) {
|
||||||
bool foundAlreadyExistingTouch = false;
|
bool foundAlreadyExistingTouch = false;
|
||||||
for (size_t j = 0; j < mTouches.Length(); j++) {
|
for (size_t j = 0; j < mTouches.Length(); j++) {
|
||||||
if (mTouches[j].mIdentifier == event.mTouches[i].mIdentifier) {
|
if (mTouches[j].mIdentifier == aEvent.mTouches[i].mIdentifier) {
|
||||||
foundAlreadyExistingTouch = true;
|
foundAlreadyExistingTouch = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -75,14 +69,14 @@ nsEventStatus GestureEventListener::HandleInputEvent(const InputData& aEvent)
|
|||||||
|
|
||||||
// If we didn't find a touch in our list that matches this, then add it.
|
// If we didn't find a touch in our list that matches this, then add it.
|
||||||
if (!foundAlreadyExistingTouch) {
|
if (!foundAlreadyExistingTouch) {
|
||||||
mTouches.AppendElement(event.mTouches[i]);
|
mTouches.AppendElement(aEvent.mTouches[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t length = mTouches.Length();
|
size_t length = mTouches.Length();
|
||||||
if (length == 1) {
|
if (length == 1) {
|
||||||
mTapStartTime = event.mTime;
|
mTapStartTime = aEvent.mTime;
|
||||||
mTouchStartPosition = event.mTouches[0].mScreenPoint;
|
mTouchStartPosition = aEvent.mTouches[0].mScreenPoint;
|
||||||
if (mState == GESTURE_NONE) {
|
if (mState == GESTURE_NONE) {
|
||||||
mState = GESTURE_WAITING_SINGLE_TAP;
|
mState = GESTURE_WAITING_SINGLE_TAP;
|
||||||
|
|
||||||
@ -95,28 +89,28 @@ nsEventStatus GestureEventListener::HandleInputEvent(const InputData& aEvent)
|
|||||||
}
|
}
|
||||||
} else if (length == 2) {
|
} else if (length == 2) {
|
||||||
// Another finger has been added; it can't be a tap anymore.
|
// Another finger has been added; it can't be a tap anymore.
|
||||||
HandleTapCancel(event);
|
HandleTapCancel(aEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MultiTouchInput::MULTITOUCH_MOVE: {
|
case MultiTouchInput::MULTITOUCH_MOVE: {
|
||||||
// If we move too much, bail out of the tap.
|
// If we move too much, bail out of the tap.
|
||||||
ScreenIntPoint delta = event.mTouches[0].mScreenPoint - mTouchStartPosition;
|
ScreenIntPoint delta = aEvent.mTouches[0].mScreenPoint - mTouchStartPosition;
|
||||||
if (mTouches.Length() == 1 &&
|
if (mTouches.Length() == 1 &&
|
||||||
NS_hypot(delta.x, delta.y) > AsyncPanZoomController::GetTouchStartTolerance())
|
NS_hypot(delta.x, delta.y) > AsyncPanZoomController::GetTouchStartTolerance())
|
||||||
{
|
{
|
||||||
HandleTapCancel(event);
|
HandleTapCancel(aEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t eventTouchesMatched = 0;
|
size_t eventTouchesMatched = 0;
|
||||||
for (size_t i = 0; i < mTouches.Length(); i++) {
|
for (size_t i = 0; i < mTouches.Length(); i++) {
|
||||||
bool isTouchRemoved = true;
|
bool isTouchRemoved = true;
|
||||||
for (size_t j = 0; j < event.mTouches.Length(); j++) {
|
for (size_t j = 0; j < aEvent.mTouches.Length(); j++) {
|
||||||
if (mTouches[i].mIdentifier == event.mTouches[j].mIdentifier) {
|
if (mTouches[i].mIdentifier == aEvent.mTouches[j].mIdentifier) {
|
||||||
eventTouchesMatched++;
|
eventTouchesMatched++;
|
||||||
isTouchRemoved = false;
|
isTouchRemoved = false;
|
||||||
mTouches[i] = event.mTouches[j];
|
mTouches[i] = aEvent.mTouches[j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isTouchRemoved) {
|
if (isTouchRemoved) {
|
||||||
@ -126,16 +120,16 @@ nsEventStatus GestureEventListener::HandleInputEvent(const InputData& aEvent)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_WARN_IF_FALSE(eventTouchesMatched == event.mTouches.Length(), "Touch moved, but not in list");
|
NS_WARN_IF_FALSE(eventTouchesMatched == aEvent.mTouches.Length(), "Touch moved, but not in list");
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MultiTouchInput::MULTITOUCH_END:
|
case MultiTouchInput::MULTITOUCH_END:
|
||||||
case MultiTouchInput::MULTITOUCH_LEAVE: {
|
case MultiTouchInput::MULTITOUCH_LEAVE: {
|
||||||
for (size_t i = 0; i < event.mTouches.Length(); i++) {
|
for (size_t i = 0; i < aEvent.mTouches.Length(); i++) {
|
||||||
bool foundAlreadyExistingTouch = false;
|
bool foundAlreadyExistingTouch = false;
|
||||||
for (size_t j = 0; j < mTouches.Length() && !foundAlreadyExistingTouch; j++) {
|
for (size_t j = 0; j < mTouches.Length() && !foundAlreadyExistingTouch; j++) {
|
||||||
if (event.mTouches[i].mIdentifier == mTouches[j].mIdentifier) {
|
if (aEvent.mTouches[i].mIdentifier == mTouches[j].mIdentifier) {
|
||||||
foundAlreadyExistingTouch = true;
|
foundAlreadyExistingTouch = true;
|
||||||
mTouches.RemoveElementAt(j);
|
mTouches.RemoveElementAt(j);
|
||||||
}
|
}
|
||||||
@ -146,30 +140,30 @@ nsEventStatus GestureEventListener::HandleInputEvent(const InputData& aEvent)
|
|||||||
if (mState == GESTURE_WAITING_DOUBLE_TAP) {
|
if (mState == GESTURE_WAITING_DOUBLE_TAP) {
|
||||||
CancelDoubleTapTimeoutTask();
|
CancelDoubleTapTimeoutTask();
|
||||||
if (mTapStartTime - mLastTapEndTime > MAX_TAP_TIME ||
|
if (mTapStartTime - mLastTapEndTime > MAX_TAP_TIME ||
|
||||||
event.mTime - mTapStartTime > MAX_TAP_TIME) {
|
aEvent.mTime - mTapStartTime > MAX_TAP_TIME) {
|
||||||
// Either the time between taps or the last tap took too long
|
// Either the time between taps or the last tap took too long
|
||||||
// confirm previous tap and handle current tap seperately
|
// confirm previous tap and handle current tap seperately
|
||||||
TimeoutDoubleTap();
|
TimeoutDoubleTap();
|
||||||
mState = GESTURE_WAITING_SINGLE_TAP;
|
mState = GESTURE_WAITING_SINGLE_TAP;
|
||||||
} else {
|
} else {
|
||||||
// We were waiting for a double tap and it has arrived.
|
// We were waiting for a double tap and it has arrived.
|
||||||
HandleDoubleTap(event);
|
HandleDoubleTap(aEvent);
|
||||||
mState = GESTURE_NONE;
|
mState = GESTURE_NONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mState == GESTURE_LONG_TAP_UP) {
|
if (mState == GESTURE_LONG_TAP_UP) {
|
||||||
HandleLongTapUpEvent(event);
|
HandleLongTapUpEvent(aEvent);
|
||||||
mState = GESTURE_NONE;
|
mState = GESTURE_NONE;
|
||||||
} else if (mState == GESTURE_WAITING_SINGLE_TAP &&
|
} else if (mState == GESTURE_WAITING_SINGLE_TAP &&
|
||||||
event.mTime - mTapStartTime > MAX_TAP_TIME) {
|
aEvent.mTime - mTapStartTime > MAX_TAP_TIME) {
|
||||||
// Extended taps are immediately dispatched as single taps
|
// Extended taps are immediately dispatched as single taps
|
||||||
CancelLongTapTimeoutTask();
|
CancelLongTapTimeoutTask();
|
||||||
HandleSingleTapConfirmedEvent(event);
|
HandleSingleTapConfirmedEvent(aEvent);
|
||||||
mState = GESTURE_NONE;
|
mState = GESTURE_NONE;
|
||||||
} else if (mState == GESTURE_WAITING_SINGLE_TAP) {
|
} else if (mState == GESTURE_WAITING_SINGLE_TAP) {
|
||||||
CancelLongTapTimeoutTask();
|
CancelLongTapTimeoutTask();
|
||||||
nsEventStatus tapupEvent = HandleSingleTapUpEvent(event);
|
nsEventStatus tapupEvent = HandleSingleTapUpEvent(aEvent);
|
||||||
|
|
||||||
if (tapupEvent == nsEventStatus_eIgnore) {
|
if (tapupEvent == nsEventStatus_eIgnore) {
|
||||||
// We were not waiting for anything but a single tap has happened that
|
// We were not waiting for anything but a single tap has happened that
|
||||||
@ -190,7 +184,7 @@ nsEventStatus GestureEventListener::HandleInputEvent(const InputData& aEvent)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mLastTapEndTime = event.mTime;
|
mLastTapEndTime = aEvent.mTime;
|
||||||
|
|
||||||
if (!mTouches.Length()) {
|
if (!mTouches.Length()) {
|
||||||
mSpanChange = 0.0f;
|
mSpanChange = 0.0f;
|
||||||
@ -199,20 +193,24 @@ nsEventStatus GestureEventListener::HandleInputEvent(const InputData& aEvent)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MultiTouchInput::MULTITOUCH_CANCEL:
|
case MultiTouchInput::MULTITOUCH_CANCEL:
|
||||||
// This gets called if there's a touch that has to bail for weird reasons
|
// FIXME: we should probably clear a bunch of gesture state here
|
||||||
// like pinching and then moving away from the window that the pinch was
|
break;
|
||||||
// started in without letting go of the screen.
|
|
||||||
return HandlePinchGestureEvent(event, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return HandlePinchGestureEvent(event, false);
|
return HandlePinchGestureEvent(aEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsEventStatus GestureEventListener::HandlePinchGestureEvent(const MultiTouchInput& aEvent, bool aClearTouches)
|
nsEventStatus GestureEventListener::HandlePinchGestureEvent(const MultiTouchInput& aEvent)
|
||||||
{
|
{
|
||||||
nsEventStatus rv = nsEventStatus_eIgnore;
|
nsEventStatus rv = nsEventStatus_eIgnore;
|
||||||
|
|
||||||
if (mTouches.Length() > 1 && !aClearTouches) {
|
if (aEvent.mType == MultiTouchInput::MULTITOUCH_CANCEL) {
|
||||||
|
mTouches.Clear();
|
||||||
|
mState = GESTURE_NONE;
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mTouches.Length() > 1) {
|
||||||
const ScreenIntPoint& firstTouch = mTouches[0].mScreenPoint,
|
const ScreenIntPoint& firstTouch = mTouches[0].mScreenPoint,
|
||||||
secondTouch = mTouches[1].mScreenPoint;
|
secondTouch = mTouches[1].mScreenPoint;
|
||||||
ScreenPoint focusPoint = ScreenPoint(firstTouch + secondTouch) / 2;
|
ScreenPoint focusPoint = ScreenPoint(firstTouch + secondTouch) / 2;
|
||||||
@ -289,10 +287,6 @@ nsEventStatus GestureEventListener::HandlePinchGestureEvent(const MultiTouchInpu
|
|||||||
mState = GESTURE_NONE;
|
mState = GESTURE_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aClearTouches) {
|
|
||||||
mTouches.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ public:
|
|||||||
* of a gesture, then we pass it along to AsyncPanZoomController. Otherwise,
|
* of a gesture, then we pass it along to AsyncPanZoomController. Otherwise,
|
||||||
* it gets consumed here and never forwarded along.
|
* it gets consumed here and never forwarded along.
|
||||||
*/
|
*/
|
||||||
nsEventStatus HandleInputEvent(const InputData& aEvent);
|
nsEventStatus HandleInputEvent(const MultiTouchInput& aEvent);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cancels any currently active gesture. May not properly handle situations
|
* Cancels any currently active gesture. May not properly handle situations
|
||||||
@ -94,11 +94,8 @@ protected:
|
|||||||
/**
|
/**
|
||||||
* Attempts to handle the event as a pinch event. If it is not a pinch event,
|
* Attempts to handle the event as a pinch event. If it is not a pinch event,
|
||||||
* then we simply tell the next consumer to consume the event instead.
|
* then we simply tell the next consumer to consume the event instead.
|
||||||
*
|
|
||||||
* |aClearTouches| marks whether or not to terminate any pinch currently
|
|
||||||
* happening.
|
|
||||||
*/
|
*/
|
||||||
nsEventStatus HandlePinchGestureEvent(const MultiTouchInput& aEvent, bool aClearTouches);
|
nsEventStatus HandlePinchGestureEvent(const MultiTouchInput& aEvent);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempts to handle the event as a single tap event, which highlights links
|
* Attempts to handle the event as a single tap event, which highlights links
|
||||||
|
@ -170,10 +170,10 @@ SetScriptSourceFilename(ExclusiveContext *cx, ScriptSource *ss,
|
|||||||
{
|
{
|
||||||
if (options.hasIntroductionInfo) {
|
if (options.hasIntroductionInfo) {
|
||||||
const char *filename = options.filename() ? options.filename() : "<unknown>";
|
const char *filename = options.filename() ? options.filename() : "<unknown>";
|
||||||
JS_ASSERT(options.introducer != nullptr);
|
JS_ASSERT(options.introductionType != nullptr);
|
||||||
|
|
||||||
if (!ss->setIntroducedFilename(cx, filename, options.introductionLineno,
|
if (!ss->setIntroducedFilename(cx, filename, options.introductionLineno,
|
||||||
options.introducer, options.introducerFilename()))
|
options.introductionType, options.introducerFilename()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
ss->setIntroductionOffset(options.introductionOffset);
|
ss->setIntroductionOffset(options.introductionOffset);
|
||||||
|
38
js/src/jit-test/tests/debug/Source-introductionType.js
Normal file
38
js/src/jit-test/tests/debug/Source-introductionType.js
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
// Check that scripts' introduction types are properly marked.
|
||||||
|
|
||||||
|
var g = newGlobal();
|
||||||
|
var dbg = new Debugger(g);
|
||||||
|
var log;
|
||||||
|
|
||||||
|
dbg.onDebuggerStatement = function (frame) {
|
||||||
|
log += 'd';
|
||||||
|
assertEq(frame.script.source.introductionType, 'eval');
|
||||||
|
};
|
||||||
|
log = '';
|
||||||
|
g.eval('debugger;');
|
||||||
|
assertEq(log, 'd');
|
||||||
|
|
||||||
|
dbg.onDebuggerStatement = function (frame) {
|
||||||
|
log += 'd';
|
||||||
|
assertEq(frame.script.source.introductionType, 'Function');
|
||||||
|
};
|
||||||
|
log = '';
|
||||||
|
g.Function('debugger;')();
|
||||||
|
assertEq(log, 'd');
|
||||||
|
|
||||||
|
dbg.onDebuggerStatement = function (frame) {
|
||||||
|
log += 'd';
|
||||||
|
assertEq(frame.script.source.introductionType, 'GeneratorFunction');
|
||||||
|
};
|
||||||
|
log = '';
|
||||||
|
g.eval('(function*() {})').constructor('debugger;')().next();
|
||||||
|
assertEq(log, 'd');
|
||||||
|
|
||||||
|
dbg.onDebuggerStatement = function (frame) {
|
||||||
|
log += 'd';
|
||||||
|
assertEq(frame.script.source.introductionType, undefined);
|
||||||
|
};
|
||||||
|
log = '';
|
||||||
|
g.evaluate('debugger;');
|
||||||
|
assertEq(log, 'd');
|
||||||
|
|
17
js/src/jit-test/tests/parallel/bug944975.js
Normal file
17
js/src/jit-test/tests/parallel/bug944975.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
if (getBuildConfiguration().parallelJS) {
|
||||||
|
var map_toSource_called = false;
|
||||||
|
var mapPar_toSource_called = false;
|
||||||
|
|
||||||
|
Array.prototype.mapPar.toSource = function() {
|
||||||
|
mapPar_toSource_called = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
Array.prototype.map.toSource = function() {
|
||||||
|
map_toSource_called = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
try { new Array.prototype.mapPar; } catch (e) {}
|
||||||
|
try { new Array.prototype.map; } catch (e) {}
|
||||||
|
|
||||||
|
assertEq(map_toSource_called, mapPar_toSource_called);
|
||||||
|
}
|
@ -236,17 +236,25 @@ DynamicallyLinkModule(JSContext *cx, CallArgs args, AsmJSModule &module)
|
|||||||
heap = &bufferVal.toObject().as<ArrayBufferObject>();
|
heap = &bufferVal.toObject().as<ArrayBufferObject>();
|
||||||
|
|
||||||
if (!IsValidAsmJSHeapLength(heap->byteLength())) {
|
if (!IsValidAsmJSHeapLength(heap->byteLength())) {
|
||||||
return LinkFail(cx, JS_smprintf("ArrayBuffer byteLength 0x%x is not a valid heap length. The next valid length is 0x%x",
|
ScopedJSFreePtr<char> msg(
|
||||||
heap->byteLength(),
|
JS_smprintf("ArrayBuffer byteLength 0x%x is not a valid heap length. The next "
|
||||||
RoundUpToNextValidAsmJSHeapLength(heap->byteLength())));
|
"valid length is 0x%x",
|
||||||
|
heap->byteLength(),
|
||||||
|
RoundUpToNextValidAsmJSHeapLength(heap->byteLength())));
|
||||||
|
return LinkFail(cx, msg.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
// This check is sufficient without considering the size of the loaded datum because heap
|
// This check is sufficient without considering the size of the loaded datum because heap
|
||||||
// loads and stores start on an aligned boundary and the heap byteLength has larger alignment.
|
// loads and stores start on an aligned boundary and the heap byteLength has larger alignment.
|
||||||
JS_ASSERT((module.minHeapLength() - 1) <= INT32_MAX);
|
JS_ASSERT((module.minHeapLength() - 1) <= INT32_MAX);
|
||||||
if (heap->byteLength() < module.minHeapLength()) {
|
if (heap->byteLength() < module.minHeapLength()) {
|
||||||
return LinkFail(cx, JS_smprintf("ArrayBuffer byteLength of 0x%x is less than 0x%x (which is the largest constant heap access offset rounded up to the next valid heap size).",
|
ScopedJSFreePtr<char> msg(
|
||||||
heap->byteLength(), module.minHeapLength()));
|
JS_smprintf("ArrayBuffer byteLength of 0x%x is less than 0x%x (which is the"
|
||||||
|
"largest constant heap access offset rounded up to the next valid "
|
||||||
|
"heap size).",
|
||||||
|
heap->byteLength(),
|
||||||
|
module.minHeapLength()));
|
||||||
|
return LinkFail(cx, msg.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ArrayBufferObject::prepareForAsmJS(cx, heap))
|
if (!ArrayBufferObject::prepareForAsmJS(cx, heap))
|
||||||
|
@ -285,7 +285,7 @@ CanEnterBaselineJIT(JSContext *cx, HandleScript script, bool osr)
|
|||||||
if (script->isCallsiteClone()) {
|
if (script->isCallsiteClone()) {
|
||||||
// Ensure the original function is compiled too, so that bailouts from
|
// Ensure the original function is compiled too, so that bailouts from
|
||||||
// Ion code have a BaselineScript to resume into.
|
// Ion code have a BaselineScript to resume into.
|
||||||
RootedScript original(cx, script->originalFunction()->nonLazyScript());
|
RootedScript original(cx, script->donorFunction()->nonLazyScript());
|
||||||
JS_ASSERT(original != script);
|
JS_ASSERT(original != script);
|
||||||
|
|
||||||
if (!original->canBaselineCompile())
|
if (!original->canBaselineCompile())
|
||||||
|
@ -23,10 +23,13 @@ BEGIN_TEST(testGCStoreBufferRemoval)
|
|||||||
CHECK(!js::gc::IsInsideNursery(rt, obj.get()));
|
CHECK(!js::gc::IsInsideNursery(rt, obj.get()));
|
||||||
JS::RootedObject tenuredObject(cx, obj);
|
JS::RootedObject tenuredObject(cx, obj);
|
||||||
|
|
||||||
|
// Hide the horrors herein from the static rooting analysis.
|
||||||
|
typedef JSObject *ObjectPtr;
|
||||||
|
|
||||||
// Test removal of store buffer entries added by RelocatablePtr<T>.
|
// Test removal of store buffer entries added by RelocatablePtr<T>.
|
||||||
{
|
{
|
||||||
JSObject *badObject = reinterpret_cast<JSObject*>(1);
|
ObjectPtr badObject = reinterpret_cast<JSObject*>(1);
|
||||||
JSObject *punnedPtr = nullptr;
|
ObjectPtr punnedPtr = nullptr;
|
||||||
RelocatablePtrObject* relocPtr =
|
RelocatablePtrObject* relocPtr =
|
||||||
reinterpret_cast<RelocatablePtrObject*>(&punnedPtr);
|
reinterpret_cast<RelocatablePtrObject*>(&punnedPtr);
|
||||||
new (relocPtr) RelocatablePtrObject;
|
new (relocPtr) RelocatablePtrObject;
|
||||||
@ -77,8 +80,8 @@ BEGIN_TEST(testGCStoreBufferRemoval)
|
|||||||
|
|
||||||
// Test removal of store buffer entries added by Heap<T>.
|
// Test removal of store buffer entries added by Heap<T>.
|
||||||
{
|
{
|
||||||
JSObject *badObject = reinterpret_cast<JSObject*>(1);
|
ObjectPtr badObject = reinterpret_cast<JSObject*>(1);
|
||||||
JSObject *punnedPtr = nullptr;
|
ObjectPtr punnedPtr = nullptr;
|
||||||
Heap<JSObject*>* heapPtr =
|
Heap<JSObject*>* heapPtr =
|
||||||
reinterpret_cast<Heap<JSObject*>*>(&punnedPtr);
|
reinterpret_cast<Heap<JSObject*>*>(&punnedPtr);
|
||||||
new (heapPtr) Heap<JSObject*>;
|
new (heapPtr) Heap<JSObject*>;
|
||||||
|
@ -4312,7 +4312,7 @@ JS::ReadOnlyCompileOptions::copyPODOptions(const ReadOnlyCompileOptions &rhs)
|
|||||||
werrorOption = rhs.werrorOption;
|
werrorOption = rhs.werrorOption;
|
||||||
asmJSOption = rhs.asmJSOption;
|
asmJSOption = rhs.asmJSOption;
|
||||||
sourcePolicy = rhs.sourcePolicy;
|
sourcePolicy = rhs.sourcePolicy;
|
||||||
introducer = rhs.introducer;
|
introductionType = rhs.introductionType;
|
||||||
introductionLineno = rhs.introductionLineno;
|
introductionLineno = rhs.introductionLineno;
|
||||||
introductionOffset = rhs.introductionOffset;
|
introductionOffset = rhs.introductionOffset;
|
||||||
hasIntroductionInfo = rhs.hasIntroductionInfo;
|
hasIntroductionInfo = rhs.hasIntroductionInfo;
|
||||||
|
@ -3478,7 +3478,7 @@ class JS_FRIEND_API(ReadOnlyCompileOptions)
|
|||||||
asmJSOption(false),
|
asmJSOption(false),
|
||||||
forceAsync(false),
|
forceAsync(false),
|
||||||
sourcePolicy(SAVE_SOURCE),
|
sourcePolicy(SAVE_SOURCE),
|
||||||
introducer(nullptr),
|
introductionType(nullptr),
|
||||||
introductionLineno(0),
|
introductionLineno(0),
|
||||||
introductionOffset(0),
|
introductionOffset(0),
|
||||||
hasIntroductionInfo(false)
|
hasIntroductionInfo(false)
|
||||||
@ -3521,9 +3521,9 @@ class JS_FRIEND_API(ReadOnlyCompileOptions)
|
|||||||
SAVE_SOURCE
|
SAVE_SOURCE
|
||||||
} sourcePolicy;
|
} sourcePolicy;
|
||||||
|
|
||||||
// |introducer| is a statically allocated C string:
|
// |introductionType| is a statically allocated C string:
|
||||||
// one of "eval", "Function", or "GeneratorFunction".
|
// one of "eval", "Function", or "GeneratorFunction".
|
||||||
const char *introducer;
|
const char *introductionType;
|
||||||
unsigned introductionLineno;
|
unsigned introductionLineno;
|
||||||
uint32_t introductionOffset;
|
uint32_t introductionOffset;
|
||||||
bool hasIntroductionInfo;
|
bool hasIntroductionInfo;
|
||||||
@ -3616,7 +3616,7 @@ class JS_FRIEND_API(OwningCompileOptions) : public ReadOnlyCompileOptions
|
|||||||
{
|
{
|
||||||
if (!setIntroducerFilename(cx, introducerFn))
|
if (!setIntroducerFilename(cx, introducerFn))
|
||||||
return false;
|
return false;
|
||||||
introducer = intro;
|
introductionType = intro;
|
||||||
introductionLineno = line;
|
introductionLineno = line;
|
||||||
introductionOffset = offset;
|
introductionOffset = offset;
|
||||||
hasIntroductionInfo = true;
|
hasIntroductionInfo = true;
|
||||||
@ -3692,7 +3692,7 @@ class MOZ_STACK_CLASS JS_FRIEND_API(CompileOptions) : public ReadOnlyCompileOpti
|
|||||||
unsigned line, uint32_t offset)
|
unsigned line, uint32_t offset)
|
||||||
{
|
{
|
||||||
introducerFilename_ = introducerFn;
|
introducerFilename_ = introducerFn;
|
||||||
introducer = intro;
|
introductionType = intro;
|
||||||
introductionLineno = line;
|
introductionLineno = line;
|
||||||
introductionOffset = offset;
|
introductionOffset = offset;
|
||||||
hasIntroductionInfo = true;
|
hasIntroductionInfo = true;
|
||||||
|
@ -118,8 +118,8 @@ fun_getProperty(JSContext *cx, HandleObject obj_, HandleId id, MutableHandleValu
|
|||||||
|
|
||||||
/* Callsite clones should never escape to script. */
|
/* Callsite clones should never escape to script. */
|
||||||
JSObject &maybeClone = iter.calleev().toObject();
|
JSObject &maybeClone = iter.calleev().toObject();
|
||||||
if (maybeClone.is<JSFunction>() && maybeClone.as<JSFunction>().nonLazyScript()->isCallsiteClone())
|
if (maybeClone.is<JSFunction>())
|
||||||
vp.setObject(*maybeClone.as<JSFunction>().nonLazyScript()->originalFunction());
|
vp.setObject(*maybeClone.as<JSFunction>().originalFunction());
|
||||||
else
|
else
|
||||||
vp.set(iter.calleev());
|
vp.set(iter.calleev());
|
||||||
|
|
||||||
@ -1486,9 +1486,9 @@ FunctionConstructor(JSContext *cx, unsigned argc, Value *vp, GeneratorKind gener
|
|||||||
CurrentScriptFileLineOrigin(cx, &script, &filename, &lineno, &pcOffset, &originPrincipals);
|
CurrentScriptFileLineOrigin(cx, &script, &filename, &lineno, &pcOffset, &originPrincipals);
|
||||||
JSPrincipals *principals = PrincipalsForCompiledCode(args, cx);
|
JSPrincipals *principals = PrincipalsForCompiledCode(args, cx);
|
||||||
|
|
||||||
const char *introducer = "Function";
|
const char *introductionType = "Function";
|
||||||
if (generatorKind != NotGenerator)
|
if (generatorKind != NotGenerator)
|
||||||
introducer = "GeneratorFunction";
|
introductionType = "GeneratorFunction";
|
||||||
|
|
||||||
const char *introducerFilename = filename;
|
const char *introducerFilename = filename;
|
||||||
if (script && script->scriptSource()->introducerFilename())
|
if (script && script->scriptSource()->introducerFilename())
|
||||||
@ -1500,7 +1500,7 @@ FunctionConstructor(JSContext *cx, unsigned argc, Value *vp, GeneratorKind gener
|
|||||||
.setFileAndLine(filename, 1)
|
.setFileAndLine(filename, 1)
|
||||||
.setNoScriptRval(false)
|
.setNoScriptRval(false)
|
||||||
.setCompileAndGo(true)
|
.setCompileAndGo(true)
|
||||||
.setIntroductionInfo(introducerFilename, introducer, lineno, pcOffset);
|
.setIntroductionInfo(introducerFilename, introductionType, lineno, pcOffset);
|
||||||
|
|
||||||
unsigned n = args.length() ? args.length() - 1 : 0;
|
unsigned n = args.length() ? args.length() - 1 : 0;
|
||||||
if (n > 0) {
|
if (n > 0) {
|
||||||
|
@ -339,6 +339,16 @@ class JSFunction : public JSObject
|
|||||||
return u.i.s.script_;
|
return u.i.s.script_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns non-callsited-clone version of this. Use when return
|
||||||
|
// value can flow to arbitrary JS (see Bug 944975).
|
||||||
|
JSFunction* originalFunction() {
|
||||||
|
if (this->hasScript() && this->nonLazyScript()->isCallsiteClone()) {
|
||||||
|
return this->nonLazyScript()->donorFunction();
|
||||||
|
} else {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
js::HeapPtrScript &mutableScript() {
|
js::HeapPtrScript &mutableScript() {
|
||||||
JS_ASSERT(isInterpreted());
|
JS_ASSERT(isInterpreted());
|
||||||
return *(js::HeapPtrScript *)&u.i.s.script_;
|
return *(js::HeapPtrScript *)&u.i.s.script_;
|
||||||
|
@ -1599,12 +1599,12 @@ ScriptSource::displayURL()
|
|||||||
bool
|
bool
|
||||||
ScriptSource::setIntroducedFilename(ExclusiveContext *cx,
|
ScriptSource::setIntroducedFilename(ExclusiveContext *cx,
|
||||||
const char *callerFilename, unsigned callerLineno,
|
const char *callerFilename, unsigned callerLineno,
|
||||||
const char *introducer, const char *introducerFilename)
|
const char *introductionType, const char *introducerFilename)
|
||||||
{
|
{
|
||||||
JS_ASSERT(!filename_);
|
JS_ASSERT(!filename_);
|
||||||
JS_ASSERT(!introducerFilename_);
|
JS_ASSERT(!introducerFilename_);
|
||||||
|
|
||||||
introducerType_ = introducer;
|
introductionType_ = introductionType;
|
||||||
|
|
||||||
if (introducerFilename) {
|
if (introducerFilename) {
|
||||||
introducerFilename_ = js_strdup(cx, introducerFilename);
|
introducerFilename_ = js_strdup(cx, introducerFilename);
|
||||||
@ -1612,24 +1612,24 @@ ScriptSource::setIntroducedFilename(ExclusiveContext *cx,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Final format: "{callerFilename} line {callerLineno} > {introducer}"
|
// Final format: "{callerFilename} line {callerLineno} > {introductionType}"
|
||||||
// Len = strlen(callerFilename) + strlen(" line ") +
|
// Len = strlen(callerFilename) + strlen(" line ") +
|
||||||
// strlen(toStr(callerLineno)) + strlen(" > ") + strlen(introducer);
|
// strlen(toStr(callerLineno)) + strlen(" > ") + strlen(introductionType);
|
||||||
char linenoBuf[15];
|
char linenoBuf[15];
|
||||||
size_t filenameLen = strlen(callerFilename);
|
size_t filenameLen = strlen(callerFilename);
|
||||||
size_t linenoLen = JS_snprintf(linenoBuf, 15, "%u", callerLineno);
|
size_t linenoLen = JS_snprintf(linenoBuf, 15, "%u", callerLineno);
|
||||||
size_t introducerLen = strlen(introducer);
|
size_t introductionTypeLen = strlen(introductionType);
|
||||||
size_t len = filenameLen +
|
size_t len = filenameLen +
|
||||||
6 /* == strlen(" line ") */ +
|
6 /* == strlen(" line ") */ +
|
||||||
linenoLen +
|
linenoLen +
|
||||||
3 /* == strlen(" > ") */ +
|
3 /* == strlen(" > ") */ +
|
||||||
introducerLen +
|
introductionTypeLen +
|
||||||
1 /* \0 */;
|
1 /* \0 */;
|
||||||
filename_ = cx->pod_malloc<char>(len);
|
filename_ = cx->pod_malloc<char>(len);
|
||||||
if (!filename_)
|
if (!filename_)
|
||||||
return false;
|
return false;
|
||||||
mozilla::DebugOnly<int> checkLen = JS_snprintf(filename_, len, "%s line %s > %s",
|
mozilla::DebugOnly<int> checkLen = JS_snprintf(filename_, len, "%s line %s > %s",
|
||||||
callerFilename, linenoBuf, introducer);
|
callerFilename, linenoBuf, introductionType);
|
||||||
JS_ASSERT(checkLen == len - 1);
|
JS_ASSERT(checkLen == len - 1);
|
||||||
|
|
||||||
if (!introducerFilename_)
|
if (!introducerFilename_)
|
||||||
|
@ -405,7 +405,7 @@ class ScriptSource
|
|||||||
// undefined if the implementation doesn't know how the code was introduced.
|
// undefined if the implementation doesn't know how the code was introduced.
|
||||||
// This is a constant, statically allocated C string, so does not need
|
// This is a constant, statically allocated C string, so does not need
|
||||||
// memory management.
|
// memory management.
|
||||||
const char *introducerType_;
|
const char *introductionType_;
|
||||||
|
|
||||||
// True if we can call JSRuntime::sourceHook to load the source on
|
// True if we can call JSRuntime::sourceHook to load the source on
|
||||||
// demand. If sourceRetrievable_ and hasSourceData() are false, it is not
|
// demand. If sourceRetrievable_ and hasSourceData() are false, it is not
|
||||||
@ -426,7 +426,7 @@ class ScriptSource
|
|||||||
originPrincipals_(originPrincipals),
|
originPrincipals_(originPrincipals),
|
||||||
introductionOffset_(0),
|
introductionOffset_(0),
|
||||||
introducerFilename_(nullptr),
|
introducerFilename_(nullptr),
|
||||||
introducerType_(nullptr),
|
introductionType_(nullptr),
|
||||||
sourceRetrievable_(false),
|
sourceRetrievable_(false),
|
||||||
argumentsNotIncluded_(false),
|
argumentsNotIncluded_(false),
|
||||||
ready_(true),
|
ready_(true),
|
||||||
@ -471,16 +471,16 @@ class ScriptSource
|
|||||||
bool setFilename(ExclusiveContext *cx, const char *filename);
|
bool setFilename(ExclusiveContext *cx, const char *filename);
|
||||||
bool setIntroducedFilename(ExclusiveContext *cx,
|
bool setIntroducedFilename(ExclusiveContext *cx,
|
||||||
const char *callerFilename, unsigned callerLineno,
|
const char *callerFilename, unsigned callerLineno,
|
||||||
const char *introducer, const char *introducerFilename);
|
const char *introductionType, const char *introducerFilename);
|
||||||
const char *introducerFilename() const {
|
const char *introducerFilename() const {
|
||||||
return introducerFilename_;
|
return introducerFilename_;
|
||||||
}
|
}
|
||||||
bool hasIntroducerType() const {
|
bool hasIntroductionType() const {
|
||||||
return introducerType_;
|
return introductionType_;
|
||||||
}
|
}
|
||||||
const char *introducerType() const {
|
const char *introductionType() const {
|
||||||
JS_ASSERT(hasIntroducerType());
|
JS_ASSERT(hasIntroductionType());
|
||||||
return introducerType_;
|
return introductionType_;
|
||||||
}
|
}
|
||||||
const char *filename() const {
|
const char *filename() const {
|
||||||
return filename_;
|
return filename_;
|
||||||
@ -1273,7 +1273,10 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
|||||||
*/
|
*/
|
||||||
inline void ensureNonLazyCanonicalFunction(JSContext *cx);
|
inline void ensureNonLazyCanonicalFunction(JSContext *cx);
|
||||||
|
|
||||||
JSFunction *originalFunction() const;
|
/*
|
||||||
|
* Donor provided itself to callsite clone; null if this is non-clone.
|
||||||
|
*/
|
||||||
|
JSFunction *donorFunction() const;
|
||||||
void setIsCallsiteClone(JSObject *fun);
|
void setIsCallsiteClone(JSObject *fun);
|
||||||
|
|
||||||
JSFlatString *sourceData(JSContext *cx);
|
JSFlatString *sourceData(JSContext *cx);
|
||||||
|
@ -149,7 +149,7 @@ JSScript::principals()
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline JSFunction *
|
inline JSFunction *
|
||||||
JSScript::originalFunction() const {
|
JSScript::donorFunction() const {
|
||||||
if (!isCallsiteClone())
|
if (!isCallsiteClone())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return &enclosingScopeOrOriginalFunction_->as<JSFunction>();
|
return &enclosingScopeOrOriginalFunction_->as<JSFunction>();
|
||||||
|
@ -3937,8 +3937,8 @@ DebuggerSource_getIntroductionType(JSContext *cx, unsigned argc, Value *vp)
|
|||||||
THIS_DEBUGSOURCE_REFERENT(cx, argc, vp, "(get introductionOffset)", args, obj, sourceObject);
|
THIS_DEBUGSOURCE_REFERENT(cx, argc, vp, "(get introductionOffset)", args, obj, sourceObject);
|
||||||
|
|
||||||
ScriptSource *ss = sourceObject->source();
|
ScriptSource *ss = sourceObject->source();
|
||||||
if (ss->hasIntroducerType()) {
|
if (ss->hasIntroductionType()) {
|
||||||
JSString *str = js_NewStringCopyZ<CanGC>(cx, ss->introducerType());
|
JSString *str = js_NewStringCopyZ<CanGC>(cx, ss->introductionType());
|
||||||
if (!str)
|
if (!str)
|
||||||
return false;
|
return false;
|
||||||
args.rval().setString(str);
|
args.rval().setString(str);
|
||||||
|
@ -555,9 +555,10 @@ js::InvokeConstructor(JSContext *cx, CallArgs args)
|
|||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fun->isInterpretedConstructor())
|
if (!fun->isInterpretedConstructor()) {
|
||||||
return ReportIsNotFunction(cx, args.calleev(), args.length() + 1, CONSTRUCT);
|
RootedValue orig(cx, ObjectValue(*fun->originalFunction()));
|
||||||
|
return ReportIsNotFunction(cx, orig, args.length() + 1, CONSTRUCT);
|
||||||
|
}
|
||||||
if (!Invoke(cx, args, CONSTRUCT))
|
if (!Invoke(cx, args, CONSTRUCT))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -203,101 +203,6 @@ nsSVGFilterFrame::AttributeChanged(int32_t aNameSpaceID,
|
|||||||
aAttribute, aModType);
|
aAttribute, aModType);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
|
||||||
nsSVGFilterFrame::PaintFilteredFrame(nsRenderingContext *aContext,
|
|
||||||
nsIFrame *aFilteredFrame,
|
|
||||||
nsSVGFilterPaintCallback *aPaintCallback,
|
|
||||||
const nsRect *aDirtyArea,
|
|
||||||
nsIFrame* aTransformRoot)
|
|
||||||
{
|
|
||||||
nsSVGFilterInstance instance(aFilteredFrame, this, aPaintCallback,
|
|
||||||
aDirtyArea, nullptr, nullptr, nullptr,
|
|
||||||
aTransformRoot);
|
|
||||||
if (!instance.IsInitialized()) {
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
return instance.Render(aContext->ThebesContext());
|
|
||||||
}
|
|
||||||
|
|
||||||
static nsRect
|
|
||||||
TransformFilterSpaceToFrameSpace(nsSVGFilterInstance *aInstance,
|
|
||||||
nsIntRect *aRect)
|
|
||||||
{
|
|
||||||
if (aRect->IsEmpty()) {
|
|
||||||
return nsRect();
|
|
||||||
}
|
|
||||||
gfxMatrix m = aInstance->GetFilterSpaceToFrameSpaceInCSSPxTransform();
|
|
||||||
gfxRect r(aRect->x, aRect->y, aRect->width, aRect->height);
|
|
||||||
r = m.TransformBounds(r);
|
|
||||||
return nsLayoutUtils::RoundGfxRectToAppRect(r, aInstance->AppUnitsPerCSSPixel());
|
|
||||||
}
|
|
||||||
|
|
||||||
nsRect
|
|
||||||
nsSVGFilterFrame::GetPostFilterDirtyArea(nsIFrame *aFilteredFrame,
|
|
||||||
const nsRect& aPreFilterDirtyRect)
|
|
||||||
{
|
|
||||||
if (aPreFilterDirtyRect.IsEmpty()) {
|
|
||||||
return nsRect();
|
|
||||||
}
|
|
||||||
|
|
||||||
nsSVGFilterInstance instance(aFilteredFrame, this, nullptr, nullptr,
|
|
||||||
&aPreFilterDirtyRect);
|
|
||||||
if (!instance.IsInitialized()) {
|
|
||||||
return nsRect();
|
|
||||||
}
|
|
||||||
// We've passed in the source's dirty area so the instance knows about it.
|
|
||||||
// Now we can ask the instance to compute the area of the filter output
|
|
||||||
// that's dirty.
|
|
||||||
nsIntRect dirtyRect;
|
|
||||||
nsresult rv = instance.ComputePostFilterDirtyRect(&dirtyRect);
|
|
||||||
if (NS_SUCCEEDED(rv)) {
|
|
||||||
return TransformFilterSpaceToFrameSpace(&instance, &dirtyRect);
|
|
||||||
}
|
|
||||||
return nsRect();
|
|
||||||
}
|
|
||||||
|
|
||||||
nsRect
|
|
||||||
nsSVGFilterFrame::GetPreFilterNeededArea(nsIFrame *aFilteredFrame,
|
|
||||||
const nsRect& aPostFilterDirtyRect)
|
|
||||||
{
|
|
||||||
nsSVGFilterInstance instance(aFilteredFrame, this, nullptr,
|
|
||||||
&aPostFilterDirtyRect);
|
|
||||||
if (!instance.IsInitialized()) {
|
|
||||||
return nsRect();
|
|
||||||
}
|
|
||||||
// Now we can ask the instance to compute the area of the source
|
|
||||||
// that's needed.
|
|
||||||
nsIntRect neededRect;
|
|
||||||
nsresult rv = instance.ComputeSourceNeededRect(&neededRect);
|
|
||||||
if (NS_SUCCEEDED(rv)) {
|
|
||||||
return TransformFilterSpaceToFrameSpace(&instance, &neededRect);
|
|
||||||
}
|
|
||||||
return nsRect();
|
|
||||||
}
|
|
||||||
|
|
||||||
nsRect
|
|
||||||
nsSVGFilterFrame::GetPostFilterBounds(nsIFrame *aFilteredFrame,
|
|
||||||
const gfxRect *aOverrideBBox,
|
|
||||||
const nsRect *aPreFilterBounds)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(!(aFilteredFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT) ||
|
|
||||||
!(aFilteredFrame->GetStateBits() & NS_FRAME_IS_NONDISPLAY),
|
|
||||||
"Non-display SVG do not maintain visual overflow rects");
|
|
||||||
|
|
||||||
nsSVGFilterInstance instance(aFilteredFrame, this, nullptr, nullptr,
|
|
||||||
aPreFilterBounds, aPreFilterBounds,
|
|
||||||
aOverrideBBox);
|
|
||||||
if (!instance.IsInitialized()) {
|
|
||||||
return nsRect();
|
|
||||||
}
|
|
||||||
nsIntRect bbox;
|
|
||||||
nsresult rv = instance.ComputePostFilterExtents(&bbox);
|
|
||||||
if (NS_SUCCEEDED(rv)) {
|
|
||||||
return TransformFilterSpaceToFrameSpace(&instance, &bbox);
|
|
||||||
}
|
|
||||||
return nsRect();
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
void
|
void
|
||||||
nsSVGFilterFrame::Init(nsIContent* aContent,
|
nsSVGFilterFrame::Init(nsIContent* aContent,
|
||||||
|
@ -57,48 +57,6 @@ public:
|
|||||||
nsIAtom* aAttribute,
|
nsIAtom* aAttribute,
|
||||||
int32_t aModType) MOZ_OVERRIDE;
|
int32_t aModType) MOZ_OVERRIDE;
|
||||||
|
|
||||||
/**
|
|
||||||
* Paint the given filtered frame.
|
|
||||||
* @param aDirtyArea The area than needs to be painted, in aFilteredFrame's
|
|
||||||
* frame space (i.e. relative to its origin, the top-left corner of its
|
|
||||||
* border box).
|
|
||||||
*/
|
|
||||||
nsresult PaintFilteredFrame(nsRenderingContext *aContext,
|
|
||||||
nsIFrame *aFilteredFrame,
|
|
||||||
nsSVGFilterPaintCallback *aPaintCallback,
|
|
||||||
const nsRect* aDirtyArea,
|
|
||||||
nsIFrame* aTransformRoot);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the post-filter area that could be dirtied when the given
|
|
||||||
* pre-filter area of aFilteredFrame changes.
|
|
||||||
* @param aPreFilterDirtyRect The pre-filter area of aFilteredFrame that has
|
|
||||||
* changed, relative to aFilteredFrame, in app units.
|
|
||||||
*/
|
|
||||||
nsRect GetPostFilterDirtyArea(nsIFrame *aFilteredFrame,
|
|
||||||
const nsRect& aPreFilterDirtyRect);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the pre-filter area that is needed from aFilteredFrame when the
|
|
||||||
* given post-filter area needs to be repainted.
|
|
||||||
* @param aPostFilterDirtyRect The post-filter area that is dirty, relative
|
|
||||||
* to aFilteredFrame, in app units.
|
|
||||||
*/
|
|
||||||
nsRect GetPreFilterNeededArea(nsIFrame *aFilteredFrame,
|
|
||||||
const nsRect& aPostFilterDirtyRect);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the post-filter visual overflow rect (paint bounds) of
|
|
||||||
* aFilteredFrame.
|
|
||||||
* @param aOverrideBBox A user space rect, in user units, that should be used
|
|
||||||
* as aFilteredFrame's bbox ('bbox' is a specific SVG term), if non-null.
|
|
||||||
* @param aPreFilterBounds The pre-filter visual overflow rect of
|
|
||||||
* aFilteredFrame, if non-null.
|
|
||||||
*/
|
|
||||||
nsRect GetPostFilterBounds(nsIFrame *aFilteredFrame,
|
|
||||||
const gfxRect *aOverrideBBox = nullptr,
|
|
||||||
const nsRect *aPreFilterBounds = nullptr);
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
virtual void Init(nsIContent* aContent,
|
virtual void Init(nsIContent* aContent,
|
||||||
nsIFrame* aParent,
|
nsIFrame* aParent,
|
||||||
|
@ -23,6 +23,92 @@ using namespace mozilla;
|
|||||||
using namespace mozilla::dom;
|
using namespace mozilla::dom;
|
||||||
using namespace mozilla::gfx;
|
using namespace mozilla::gfx;
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsSVGFilterInstance::PaintFilteredFrame(nsSVGFilterFrame* aFilterFrame,
|
||||||
|
nsRenderingContext *aContext,
|
||||||
|
nsIFrame *aFilteredFrame,
|
||||||
|
nsSVGFilterPaintCallback *aPaintCallback,
|
||||||
|
const nsRect *aDirtyArea,
|
||||||
|
nsIFrame* aTransformRoot)
|
||||||
|
{
|
||||||
|
nsSVGFilterInstance instance(aFilteredFrame, aFilterFrame, aPaintCallback,
|
||||||
|
aDirtyArea, nullptr, nullptr, nullptr,
|
||||||
|
aTransformRoot);
|
||||||
|
if (!instance.IsInitialized()) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
return instance.Render(aContext->ThebesContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
nsRect
|
||||||
|
nsSVGFilterInstance::GetPostFilterDirtyArea(nsSVGFilterFrame* aFilterFrame,
|
||||||
|
nsIFrame *aFilteredFrame,
|
||||||
|
const nsRect& aPreFilterDirtyRect)
|
||||||
|
{
|
||||||
|
if (aPreFilterDirtyRect.IsEmpty()) {
|
||||||
|
return nsRect();
|
||||||
|
}
|
||||||
|
|
||||||
|
nsSVGFilterInstance instance(aFilteredFrame, aFilterFrame, nullptr, nullptr,
|
||||||
|
&aPreFilterDirtyRect);
|
||||||
|
if (!instance.IsInitialized()) {
|
||||||
|
return nsRect();
|
||||||
|
}
|
||||||
|
// We've passed in the source's dirty area so the instance knows about it.
|
||||||
|
// Now we can ask the instance to compute the area of the filter output
|
||||||
|
// that's dirty.
|
||||||
|
nsRect dirtyRect;
|
||||||
|
nsresult rv = instance.ComputePostFilterDirtyRect(&dirtyRect);
|
||||||
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
return dirtyRect;
|
||||||
|
}
|
||||||
|
return nsRect();
|
||||||
|
}
|
||||||
|
|
||||||
|
nsRect
|
||||||
|
nsSVGFilterInstance::GetPreFilterNeededArea(nsSVGFilterFrame* aFilterFrame,
|
||||||
|
nsIFrame *aFilteredFrame,
|
||||||
|
const nsRect& aPostFilterDirtyRect)
|
||||||
|
{
|
||||||
|
nsSVGFilterInstance instance(aFilteredFrame, aFilterFrame, nullptr,
|
||||||
|
&aPostFilterDirtyRect);
|
||||||
|
if (!instance.IsInitialized()) {
|
||||||
|
return nsRect();
|
||||||
|
}
|
||||||
|
// Now we can ask the instance to compute the area of the source
|
||||||
|
// that's needed.
|
||||||
|
nsRect neededRect;
|
||||||
|
nsresult rv = instance.ComputeSourceNeededRect(&neededRect);
|
||||||
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
return neededRect;
|
||||||
|
}
|
||||||
|
return nsRect();
|
||||||
|
}
|
||||||
|
|
||||||
|
nsRect
|
||||||
|
nsSVGFilterInstance::GetPostFilterBounds(nsSVGFilterFrame* aFilterFrame,
|
||||||
|
nsIFrame *aFilteredFrame,
|
||||||
|
const gfxRect *aOverrideBBox,
|
||||||
|
const nsRect *aPreFilterBounds)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(!(aFilteredFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT) ||
|
||||||
|
!(aFilteredFrame->GetStateBits() & NS_FRAME_IS_NONDISPLAY),
|
||||||
|
"Non-display SVG do not maintain visual overflow rects");
|
||||||
|
|
||||||
|
nsSVGFilterInstance instance(aFilteredFrame, aFilterFrame, nullptr, nullptr,
|
||||||
|
aPreFilterBounds, aPreFilterBounds,
|
||||||
|
aOverrideBBox);
|
||||||
|
if (!instance.IsInitialized()) {
|
||||||
|
return nsRect();
|
||||||
|
}
|
||||||
|
nsRect bbox;
|
||||||
|
nsresult rv = instance.ComputePostFilterExtents(&bbox);
|
||||||
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
return bbox;
|
||||||
|
}
|
||||||
|
return nsRect();
|
||||||
|
}
|
||||||
|
|
||||||
nsSVGFilterInstance::nsSVGFilterInstance(nsIFrame *aTargetFrame,
|
nsSVGFilterInstance::nsSVGFilterInstance(nsIFrame *aTargetFrame,
|
||||||
nsSVGFilterFrame *aFilterFrame,
|
nsSVGFilterFrame *aFilterFrame,
|
||||||
nsSVGFilterPaintCallback *aPaintCallback,
|
nsSVGFilterPaintCallback *aPaintCallback,
|
||||||
@ -664,9 +750,9 @@ nsSVGFilterInstance::Render(gfxContext* aContext)
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsSVGFilterInstance::ComputePostFilterDirtyRect(nsIntRect* aPostFilterDirtyRect)
|
nsSVGFilterInstance::ComputePostFilterDirtyRect(nsRect* aPostFilterDirtyRect)
|
||||||
{
|
{
|
||||||
*aPostFilterDirtyRect = nsIntRect();
|
*aPostFilterDirtyRect = nsRect();
|
||||||
if (mPreFilterDirtyRect.IsEmpty()) {
|
if (mPreFilterDirtyRect.IsEmpty()) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
@ -685,14 +771,15 @@ nsSVGFilterInstance::ComputePostFilterDirtyRect(nsIntRect* aPostFilterDirtyRect)
|
|||||||
nsIntRegion resultChangeRegion =
|
nsIntRegion resultChangeRegion =
|
||||||
FilterSupport::ComputeResultChangeRegion(filter,
|
FilterSupport::ComputeResultChangeRegion(filter,
|
||||||
mPreFilterDirtyRect, nsIntRegion(), nsIntRegion());
|
mPreFilterDirtyRect, nsIntRegion(), nsIntRegion());
|
||||||
*aPostFilterDirtyRect = resultChangeRegion.GetBounds();
|
*aPostFilterDirtyRect =
|
||||||
|
FilterSpaceToFrameSpace(resultChangeRegion.GetBounds());
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsSVGFilterInstance::ComputePostFilterExtents(nsIntRect* aPostFilterExtents)
|
nsSVGFilterInstance::ComputePostFilterExtents(nsRect* aPostFilterExtents)
|
||||||
{
|
{
|
||||||
*aPostFilterExtents = nsIntRect();
|
*aPostFilterExtents = nsRect();
|
||||||
|
|
||||||
nsresult rv = BuildPrimitives();
|
nsresult rv = BuildPrimitives();
|
||||||
if (NS_FAILED(rv))
|
if (NS_FAILED(rv))
|
||||||
@ -714,12 +801,12 @@ nsSVGFilterInstance::ComputePostFilterExtents(nsIntRect* aPostFilterExtents)
|
|||||||
FilterDescription filter(mPrimitiveDescriptions, filterSpaceBounds);
|
FilterDescription filter(mPrimitiveDescriptions, filterSpaceBounds);
|
||||||
nsIntRegion postFilterExtents =
|
nsIntRegion postFilterExtents =
|
||||||
FilterSupport::ComputePostFilterExtents(filter, sourceBoundsInt);
|
FilterSupport::ComputePostFilterExtents(filter, sourceBoundsInt);
|
||||||
*aPostFilterExtents = postFilterExtents.GetBounds();
|
*aPostFilterExtents = FilterSpaceToFrameSpace(postFilterExtents.GetBounds());
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsSVGFilterInstance::ComputeSourceNeededRect(nsIntRect* aDirty)
|
nsSVGFilterInstance::ComputeSourceNeededRect(nsRect* aDirty)
|
||||||
{
|
{
|
||||||
nsresult rv = BuildPrimitives();
|
nsresult rv = BuildPrimitives();
|
||||||
if (NS_FAILED(rv))
|
if (NS_FAILED(rv))
|
||||||
@ -731,7 +818,7 @@ nsSVGFilterInstance::ComputeSourceNeededRect(nsIntRect* aDirty)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ComputeNeededBoxes();
|
ComputeNeededBoxes();
|
||||||
*aDirty = mSourceGraphic.mNeededBounds;
|
*aDirty = FilterSpaceToFrameSpace(mSourceGraphic.mNeededBounds);
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
@ -757,6 +844,17 @@ nsSVGFilterInstance::FrameSpaceToFilterSpace(const nsRect* aRect) const
|
|||||||
return rect;
|
return rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsRect
|
||||||
|
nsSVGFilterInstance::FilterSpaceToFrameSpace(const nsIntRect& aRect) const
|
||||||
|
{
|
||||||
|
if (aRect.IsEmpty()) {
|
||||||
|
return nsRect();
|
||||||
|
}
|
||||||
|
gfxRect r(aRect.x, aRect.y, aRect.width, aRect.height);
|
||||||
|
r = mFilterSpaceToFrameSpaceInCSSPxTransform.TransformBounds(r);
|
||||||
|
return nsLayoutUtils::RoundGfxRectToAppRect(r, mAppUnitsPerCSSPx);
|
||||||
|
}
|
||||||
|
|
||||||
gfxMatrix
|
gfxMatrix
|
||||||
nsSVGFilterInstance::GetUserSpaceToFrameSpaceInCSSPxTransform() const
|
nsSVGFilterInstance::GetUserSpaceToFrameSpaceInCSSPxTransform() const
|
||||||
{
|
{
|
||||||
|
@ -59,6 +59,52 @@ class nsSVGFilterInstance
|
|||||||
typedef mozilla::gfx::FilterPrimitiveDescription FilterPrimitiveDescription;
|
typedef mozilla::gfx::FilterPrimitiveDescription FilterPrimitiveDescription;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* Paint the given filtered frame.
|
||||||
|
* @param aDirtyArea The area than needs to be painted, in aFilteredFrame's
|
||||||
|
* frame space (i.e. relative to its origin, the top-left corner of its
|
||||||
|
* border box).
|
||||||
|
*/
|
||||||
|
static nsresult PaintFilteredFrame(nsSVGFilterFrame* aFilterFrame,
|
||||||
|
nsRenderingContext *aContext,
|
||||||
|
nsIFrame *aFilteredFrame,
|
||||||
|
nsSVGFilterPaintCallback *aPaintCallback,
|
||||||
|
const nsRect* aDirtyArea,
|
||||||
|
nsIFrame* aTransformRoot = nullptr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the post-filter area that could be dirtied when the given
|
||||||
|
* pre-filter area of aFilteredFrame changes.
|
||||||
|
* @param aPreFilterDirtyRect The pre-filter area of aFilteredFrame that has
|
||||||
|
* changed, relative to aFilteredFrame, in app units.
|
||||||
|
*/
|
||||||
|
static nsRect GetPostFilterDirtyArea(nsSVGFilterFrame* aFilterFrame,
|
||||||
|
nsIFrame *aFilteredFrame,
|
||||||
|
const nsRect& aPreFilterDirtyRect);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the pre-filter area that is needed from aFilteredFrame when the
|
||||||
|
* given post-filter area needs to be repainted.
|
||||||
|
* @param aPostFilterDirtyRect The post-filter area that is dirty, relative
|
||||||
|
* to aFilteredFrame, in app units.
|
||||||
|
*/
|
||||||
|
static nsRect GetPreFilterNeededArea(nsSVGFilterFrame* aFilterFrame,
|
||||||
|
nsIFrame *aFilteredFrame,
|
||||||
|
const nsRect& aPostFilterDirtyRect);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the post-filter visual overflow rect (paint bounds) of
|
||||||
|
* aFilteredFrame.
|
||||||
|
* @param aOverrideBBox A user space rect, in user units, that should be used
|
||||||
|
* as aFilteredFrame's bbox ('bbox' is a specific SVG term), if non-null.
|
||||||
|
* @param aPreFilterBounds The pre-filter visual overflow rect of
|
||||||
|
* aFilteredFrame, if non-null.
|
||||||
|
*/
|
||||||
|
static nsRect GetPostFilterBounds(nsSVGFilterFrame* aFilterFrame,
|
||||||
|
nsIFrame *aFilteredFrame,
|
||||||
|
const gfxRect *aOverrideBBox = nullptr,
|
||||||
|
const nsRect *aPreFilterBounds = nullptr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param aTargetFrame The frame of the filtered element under consideration.
|
* @param aTargetFrame The frame of the filtered element under consideration.
|
||||||
* @param aFilterFrame The frame of the SVG filter element.
|
* @param aFilterFrame The frame of the SVG filter element.
|
||||||
@ -118,31 +164,31 @@ public:
|
|||||||
nsresult Render(gfxContext* aContext);
|
nsresult Render(gfxContext* aContext);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the aPostFilterDirtyRect outparam to the post-filter bounds in filter
|
* Sets the aPostFilterDirtyRect outparam to the post-filter bounds in frame
|
||||||
* space of the area that would be dirtied by mTargetFrame when a given
|
* space of the area that would be dirtied by mTargetFrame when a given
|
||||||
* pre-filter area of mTargetFrame is dirtied. The pre-filter area must have
|
* pre-filter area of mTargetFrame is dirtied. The pre-filter area must have
|
||||||
* been specified before calling this method by passing it as the
|
* been specified before calling this method by passing it as the
|
||||||
* aPreFilterDirtyRect argument to the nsSVGFilterInstance constructor.
|
* aPreFilterDirtyRect argument to the nsSVGFilterInstance constructor.
|
||||||
*/
|
*/
|
||||||
nsresult ComputePostFilterDirtyRect(nsIntRect* aPostFilterDirtyRect);
|
nsresult ComputePostFilterDirtyRect(nsRect* aPostFilterDirtyRect);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the aPostFilterExtents outparam to the post-filter bounds in filter
|
* Sets the aPostFilterExtents outparam to the post-filter bounds in frame
|
||||||
* space for the whole filter output. This is not necessarily equivalent to
|
* space for the whole filter output. This is not necessarily equivalent to
|
||||||
* the area that would be dirtied in the result when the entire pre-filter
|
* the area that would be dirtied in the result when the entire pre-filter
|
||||||
* area is dirtied, because some filter primitives can generate output
|
* area is dirtied, because some filter primitives can generate output
|
||||||
* without any input.
|
* without any input.
|
||||||
*/
|
*/
|
||||||
nsresult ComputePostFilterExtents(nsIntRect* aPostFilterExtents);
|
nsresult ComputePostFilterExtents(nsRect* aPostFilterExtents);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the aDirty outparam to the pre-filter bounds in filter space of the
|
* Sets the aDirty outparam to the pre-filter bounds in frame space of the
|
||||||
* area of mTargetFrame that is needed in order to paint the filtered output
|
* area of mTargetFrame that is needed in order to paint the filtered output
|
||||||
* for a given post-filter dirtied area. The post-filter area must have been
|
* for a given post-filter dirtied area. The post-filter area must have been
|
||||||
* specified before calling this method by passing it as the aPostFilterDirtyRect
|
* specified before calling this method by passing it as the aPostFilterDirtyRect
|
||||||
* argument to the nsSVGFilterInstance constructor.
|
* argument to the nsSVGFilterInstance constructor.
|
||||||
*/
|
*/
|
||||||
nsresult ComputeSourceNeededRect(nsIntRect* aDirty);
|
nsresult ComputeSourceNeededRect(nsRect* aDirty);
|
||||||
|
|
||||||
float GetPrimitiveNumber(uint8_t aCtxType, const nsSVGNumber2 *aNumber) const
|
float GetPrimitiveNumber(uint8_t aCtxType, const nsSVGNumber2 *aNumber) const
|
||||||
{
|
{
|
||||||
@ -269,6 +315,7 @@ private:
|
|||||||
* large to be stored in an nsIntRect.
|
* large to be stored in an nsIntRect.
|
||||||
*/
|
*/
|
||||||
nsIntRect FrameSpaceToFilterSpace(const nsRect* aRect) const;
|
nsIntRect FrameSpaceToFilterSpace(const nsRect* aRect) const;
|
||||||
|
nsRect FilterSpaceToFrameSpace(const nsIntRect& aRect) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the transform from frame space to the coordinate space that
|
* Returns the transform from frame space to the coordinate space that
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "nsSVGEffects.h"
|
#include "nsSVGEffects.h"
|
||||||
#include "nsSVGElement.h"
|
#include "nsSVGElement.h"
|
||||||
#include "nsSVGFilterFrame.h"
|
#include "nsSVGFilterFrame.h"
|
||||||
|
#include "nsSVGFilterInstance.h"
|
||||||
#include "nsSVGFilterPaintCallback.h"
|
#include "nsSVGFilterPaintCallback.h"
|
||||||
#include "nsSVGMaskFrame.h"
|
#include "nsSVGMaskFrame.h"
|
||||||
#include "nsSVGPaintServerFrame.h"
|
#include "nsSVGPaintServerFrame.h"
|
||||||
@ -276,7 +277,7 @@ nsRect
|
|||||||
overrideBBox.RoundOut();
|
overrideBBox.RoundOut();
|
||||||
|
|
||||||
nsRect overflowRect =
|
nsRect overflowRect =
|
||||||
filterFrame->GetPostFilterBounds(firstFrame, &overrideBBox);
|
nsSVGFilterInstance::GetPostFilterBounds(filterFrame, firstFrame, &overrideBBox);
|
||||||
|
|
||||||
// Return overflowRect relative to aFrame, rather than "user space":
|
// Return overflowRect relative to aFrame, rather than "user space":
|
||||||
return overflowRect - (aFrame->GetOffsetTo(firstFrame) + firstFrameToUserSpace);
|
return overflowRect - (aFrame->GetOffsetTo(firstFrame) + firstFrameToUserSpace);
|
||||||
@ -327,8 +328,8 @@ nsSVGIntegrationUtils::AdjustInvalidAreaForSVGEffects(nsIFrame* aFrame,
|
|||||||
|
|
||||||
// Adjust the dirty area for effects, and shift it back to being relative to
|
// Adjust the dirty area for effects, and shift it back to being relative to
|
||||||
// the reference frame.
|
// the reference frame.
|
||||||
nsRect result = filterFrame->GetPostFilterDirtyArea(firstFrame, preEffectsRect) -
|
nsRect result = nsSVGFilterInstance::GetPostFilterDirtyArea(filterFrame,
|
||||||
toUserSpace;
|
firstFrame, preEffectsRect) - toUserSpace;
|
||||||
// Return the result, in pixels relative to the reference frame.
|
// Return the result, in pixels relative to the reference frame.
|
||||||
return result.ToOutsidePixels(appUnitsPerDevPixel);
|
return result.ToOutsidePixels(appUnitsPerDevPixel);
|
||||||
}
|
}
|
||||||
@ -352,8 +353,8 @@ nsSVGIntegrationUtils::GetRequiredSourceForInvalidArea(nsIFrame* aFrame,
|
|||||||
nsRect postEffectsRect = aDirtyRect + toUserSpace;
|
nsRect postEffectsRect = aDirtyRect + toUserSpace;
|
||||||
|
|
||||||
// Return ther result, relative to aFrame, not in user space:
|
// Return ther result, relative to aFrame, not in user space:
|
||||||
return filterFrame->GetPreFilterNeededArea(firstFrame, postEffectsRect) -
|
return nsSVGFilterInstance::GetPreFilterNeededArea(filterFrame, firstFrame,
|
||||||
toUserSpace;
|
postEffectsRect) - toUserSpace;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -517,7 +518,8 @@ nsSVGIntegrationUtils::PaintFramesWithEffects(nsRenderingContext* aCtx,
|
|||||||
RegularFramePaintCallback callback(aBuilder, aLayerManager,
|
RegularFramePaintCallback callback(aBuilder, aLayerManager,
|
||||||
offsetWithoutSVGGeomFramePos);
|
offsetWithoutSVGGeomFramePos);
|
||||||
nsRect dirtyRect = aDirtyRect - offset;
|
nsRect dirtyRect = aDirtyRect - offset;
|
||||||
filterFrame->PaintFilteredFrame(aCtx, aFrame, &callback, &dirtyRect, nullptr);
|
nsSVGFilterInstance::PaintFilteredFrame(filterFrame, aCtx, aFrame,
|
||||||
|
&callback, &dirtyRect);
|
||||||
} else {
|
} else {
|
||||||
gfx->SetMatrix(matrixAutoSaveRestore.Matrix());
|
gfx->SetMatrix(matrixAutoSaveRestore.Matrix());
|
||||||
aLayerManager->EndTransaction(FrameLayerBuilder::DrawThebesLayer, aBuilder);
|
aLayerManager->EndTransaction(FrameLayerBuilder::DrawThebesLayer, aBuilder);
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
#include "nsSVGContainerFrame.h"
|
#include "nsSVGContainerFrame.h"
|
||||||
#include "nsSVGEffects.h"
|
#include "nsSVGEffects.h"
|
||||||
#include "nsSVGFilterFrame.h"
|
#include "nsSVGFilterFrame.h"
|
||||||
|
#include "nsSVGFilterInstance.h"
|
||||||
#include "nsSVGFilterPaintCallback.h"
|
#include "nsSVGFilterPaintCallback.h"
|
||||||
#include "nsSVGForeignObjectFrame.h"
|
#include "nsSVGForeignObjectFrame.h"
|
||||||
#include "gfxSVGGlyphs.h"
|
#include "gfxSVGGlyphs.h"
|
||||||
@ -159,12 +160,13 @@ nsSVGUtils::GetPostFilterVisualOverflowRect(nsIFrame *aFrame,
|
|||||||
NS_ABORT_IF_FALSE(aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT,
|
NS_ABORT_IF_FALSE(aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT,
|
||||||
"Called on invalid frame type");
|
"Called on invalid frame type");
|
||||||
|
|
||||||
nsSVGFilterFrame *filter = nsSVGEffects::GetFilterFrame(aFrame);
|
nsSVGFilterFrame *filterFrame = nsSVGEffects::GetFilterFrame(aFrame);
|
||||||
if (!filter) {
|
if (!filterFrame) {
|
||||||
return aPreFilterRect;
|
return aPreFilterRect;
|
||||||
}
|
}
|
||||||
|
|
||||||
return filter->GetPostFilterBounds(aFrame, nullptr, &aPreFilterRect);
|
return nsSVGFilterInstance::GetPostFilterBounds(filterFrame, aFrame, nullptr,
|
||||||
|
&aPreFilterRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -621,7 +623,9 @@ nsSVGUtils::PaintFrameWithEffects(nsRenderingContext *aContext,
|
|||||||
dirtyRect = &tmpDirtyRect;
|
dirtyRect = &tmpDirtyRect;
|
||||||
}
|
}
|
||||||
SVGPaintCallback paintCallback;
|
SVGPaintCallback paintCallback;
|
||||||
filterFrame->PaintFilteredFrame(aContext, aFrame, &paintCallback, dirtyRect, aTransformRoot);
|
nsSVGFilterInstance::PaintFilteredFrame(filterFrame, aContext, aFrame,
|
||||||
|
&paintCallback, dirtyRect,
|
||||||
|
aTransformRoot);
|
||||||
} else {
|
} else {
|
||||||
svgChildFrame->PaintSVG(aContext, aDirtyRect, aTransformRoot);
|
svgChildFrame->PaintSVG(aContext, aDirtyRect, aTransformRoot);
|
||||||
}
|
}
|
||||||
|
@ -1198,6 +1198,9 @@ nsMenuPopupFrame::SetPopupPosition(nsIFrame* aAnchorFrame, bool aIsMove, bool aS
|
|||||||
nsDeviceContext* devContext = presContext->DeviceContext();
|
nsDeviceContext* devContext = presContext->DeviceContext();
|
||||||
nscoord offsetForContextMenu = 0;
|
nscoord offsetForContextMenu = 0;
|
||||||
|
|
||||||
|
bool isNoAutoHide = IsNoAutoHide();
|
||||||
|
nsPopupLevel popupLevel = PopupLevel(isNoAutoHide);
|
||||||
|
|
||||||
if (IsAnchored()) {
|
if (IsAnchored()) {
|
||||||
// if we are anchored, there are certain things we don't want to do when
|
// if we are anchored, there are certain things we don't want to do when
|
||||||
// repositioning the popup to fit on the screen, such as end up positioned
|
// repositioning the popup to fit on the screen, such as end up positioned
|
||||||
@ -1238,7 +1241,7 @@ nsMenuPopupFrame::SetPopupPosition(nsIFrame* aAnchorFrame, bool aIsMove, bool aS
|
|||||||
// the window is moved. Popups at the parent level follow the parent
|
// the window is moved. Popups at the parent level follow the parent
|
||||||
// window as it is moved and remained anchored, so we want to maintain the
|
// window as it is moved and remained anchored, so we want to maintain the
|
||||||
// anchoring instead.
|
// anchoring instead.
|
||||||
if (IsNoAutoHide() && PopupLevel(true) != ePopupLevelParent) {
|
if (isNoAutoHide && popupLevel != ePopupLevelParent) {
|
||||||
// Account for the margin that will end up being added to the screen coordinate
|
// Account for the margin that will end up being added to the screen coordinate
|
||||||
// the next time SetPopupPosition is called.
|
// the next time SetPopupPosition is called.
|
||||||
mScreenXPos = presContext->AppUnitsToIntCSSPixels(screenPoint.x - margin.left);
|
mScreenXPos = presContext->AppUnitsToIntCSSPixels(screenPoint.x - margin.left);
|
||||||
@ -1279,7 +1282,7 @@ nsMenuPopupFrame::SetPopupPosition(nsIFrame* aAnchorFrame, bool aIsMove, bool aS
|
|||||||
// If a panel is being moved or has flip="none", don't constrain or flip it. But always do this for
|
// If a panel is being moved or has flip="none", don't constrain or flip it. But always do this for
|
||||||
// content shells, so that the popup doesn't extend outside the containing frame.
|
// content shells, so that the popup doesn't extend outside the containing frame.
|
||||||
if (mInContentShell || (mFlip != FlipType_None && (!aIsMove || mPopupType != ePopupTypePanel))) {
|
if (mInContentShell || (mFlip != FlipType_None && (!aIsMove || mPopupType != ePopupTypePanel))) {
|
||||||
nsRect screenRect = GetConstraintRect(anchorRect, rootScreenRect);
|
nsRect screenRect = GetConstraintRect(anchorRect, rootScreenRect, popupLevel);
|
||||||
|
|
||||||
// Ensure that anchorRect is on screen.
|
// Ensure that anchorRect is on screen.
|
||||||
anchorRect = anchorRect.Intersect(screenRect);
|
anchorRect = anchorRect.Intersect(screenRect);
|
||||||
@ -1378,7 +1381,8 @@ nsMenuPopupFrame::GetCurrentMenuItem()
|
|||||||
|
|
||||||
nsRect
|
nsRect
|
||||||
nsMenuPopupFrame::GetConstraintRect(const nsRect& aAnchorRect,
|
nsMenuPopupFrame::GetConstraintRect(const nsRect& aAnchorRect,
|
||||||
const nsRect& aRootScreenRect)
|
const nsRect& aRootScreenRect,
|
||||||
|
nsPopupLevel aPopupLevel)
|
||||||
{
|
{
|
||||||
nsIntRect screenRectPixels;
|
nsIntRect screenRectPixels;
|
||||||
nsPresContext* presContext = PresContext();
|
nsPresContext* presContext = PresContext();
|
||||||
@ -1401,8 +1405,11 @@ nsMenuPopupFrame::GetConstraintRect(const nsRect& aAnchorRect,
|
|||||||
nsPresContext::AppUnitsToIntCSSPixels(rect.y),
|
nsPresContext::AppUnitsToIntCSSPixels(rect.y),
|
||||||
width, height, getter_AddRefs(screen));
|
width, height, getter_AddRefs(screen));
|
||||||
if (screen) {
|
if (screen) {
|
||||||
|
// Non-top-level popups (which will always be panels)
|
||||||
|
// should never overlap the OS bar:
|
||||||
|
bool dontOverlapOSBar = aPopupLevel != ePopupLevelTop;
|
||||||
// get the total screen area if the popup is allowed to overlap it.
|
// get the total screen area if the popup is allowed to overlap it.
|
||||||
if (mMenuCanOverlapOSBar && !mInContentShell)
|
if (!dontOverlapOSBar && mMenuCanOverlapOSBar && !mInContentShell)
|
||||||
screen->GetRect(&screenRectPixels.x, &screenRectPixels.y,
|
screen->GetRect(&screenRectPixels.x, &screenRectPixels.y,
|
||||||
&screenRectPixels.width, &screenRectPixels.height);
|
&screenRectPixels.width, &screenRectPixels.height);
|
||||||
else
|
else
|
||||||
|
@ -310,7 +310,11 @@ public:
|
|||||||
// area of the screen the popup should be displayed on. Content popups,
|
// area of the screen the popup should be displayed on. Content popups,
|
||||||
// however, will also be constrained by the content area, given by
|
// however, will also be constrained by the content area, given by
|
||||||
// aRootScreenRect. All coordinates are in app units.
|
// aRootScreenRect. All coordinates are in app units.
|
||||||
nsRect GetConstraintRect(const nsRect& aAnchorRect, const nsRect& aRootScreenRect);
|
// For non-toplevel popups (which will always be panels), we will also
|
||||||
|
// constrain them to the available screen rect, ie they will not fall
|
||||||
|
// underneath the taskbar, dock or other fixed OS elements.
|
||||||
|
nsRect GetConstraintRect(const nsRect& aAnchorRect, const nsRect& aRootScreenRect,
|
||||||
|
nsPopupLevel aPopupLevel);
|
||||||
|
|
||||||
// Determines whether the given edges of the popup may be moved, where
|
// Determines whether the given edges of the popup may be moved, where
|
||||||
// aHorizontalSide and aVerticalSide are one of the NS_SIDE_* constants, or
|
// aHorizontalSide and aVerticalSide are one of the NS_SIDE_* constants, or
|
||||||
|
@ -224,7 +224,8 @@ nsResizerFrame::HandleEvent(nsPresContext* aPresContext,
|
|||||||
nsIFrame* rootFrame = aPresContext->PresShell()->FrameManager()->GetRootFrame();
|
nsIFrame* rootFrame = aPresContext->PresShell()->FrameManager()->GetRootFrame();
|
||||||
nsRect rootScreenRect = rootFrame->GetScreenRectInAppUnits();
|
nsRect rootScreenRect = rootFrame->GetScreenRectInAppUnits();
|
||||||
|
|
||||||
nsRect screenRect = menuPopupFrame->GetConstraintRect(frameRect, rootScreenRect);
|
nsPopupLevel popupLevel = menuPopupFrame->PopupLevel();
|
||||||
|
nsRect screenRect = menuPopupFrame->GetConstraintRect(frameRect, rootScreenRect, popupLevel);
|
||||||
// round using ToInsidePixels as it's better to be a pixel too small
|
// round using ToInsidePixels as it's better to be a pixel too small
|
||||||
// than be too large. If the popup is too large it could get flipped
|
// than be too large. If the popup is too large it could get flipped
|
||||||
// to the opposite side of the anchor point while resizing.
|
// to the opposite side of the anchor point while resizing.
|
||||||
|
@ -73,8 +73,10 @@ WebrtcAudioConduit::~WebrtcAudioConduit()
|
|||||||
{
|
{
|
||||||
delete mRecvCodecList[i];
|
delete mRecvCodecList[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
delete mCurSendCodecConfig;
|
delete mCurSendCodecConfig;
|
||||||
|
if (mPtrVoERTP_RTCP) {
|
||||||
|
mPtrVoERTP_RTCP->Release();
|
||||||
|
}
|
||||||
|
|
||||||
// The first one of a pair to be deleted shuts down media for both
|
// The first one of a pair to be deleted shuts down media for both
|
||||||
if(mPtrVoEXmedia)
|
if(mPtrVoEXmedia)
|
||||||
@ -278,19 +280,22 @@ MediaConduitErrorCode WebrtcAudioConduit::Init(WebrtcAudioConduit *other)
|
|||||||
CSFLogError(logTag, "%s Unable to initialize VoEProcessing", __FUNCTION__);
|
CSFLogError(logTag, "%s Unable to initialize VoEProcessing", __FUNCTION__);
|
||||||
return kMediaConduitSessionNotInited;
|
return kMediaConduitSessionNotInited;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!(mPtrVoEXmedia = VoEExternalMedia::GetInterface(mVoiceEngine)))
|
if(!(mPtrVoEXmedia = VoEExternalMedia::GetInterface(mVoiceEngine)))
|
||||||
{
|
{
|
||||||
CSFLogError(logTag, "%s Unable to initialize VoEExternalMedia", __FUNCTION__);
|
CSFLogError(logTag, "%s Unable to initialize VoEExternalMedia", __FUNCTION__);
|
||||||
return kMediaConduitSessionNotInited;
|
return kMediaConduitSessionNotInited;
|
||||||
}
|
}
|
||||||
|
if(!(mPtrVoERTP_RTCP = VoERTP_RTCP::GetInterface(mVoiceEngine)))
|
||||||
|
{
|
||||||
|
CSFLogError(logTag, "%s Unable to initialize VoERTP_RTCP", __FUNCTION__);
|
||||||
|
return kMediaConduitSessionNotInited;
|
||||||
|
}
|
||||||
|
|
||||||
if(!(mPtrVoEVideoSync = VoEVideoSync::GetInterface(mVoiceEngine)))
|
if(!(mPtrVoEVideoSync = VoEVideoSync::GetInterface(mVoiceEngine)))
|
||||||
{
|
{
|
||||||
CSFLogError(logTag, "%s Unable to initialize VoEVideoSync", __FUNCTION__);
|
CSFLogError(logTag, "%s Unable to initialize VoEVideoSync", __FUNCTION__);
|
||||||
return kMediaConduitSessionNotInited;
|
return kMediaConduitSessionNotInited;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(mPtrRTP = webrtc::VoERTP_RTCP::GetInterface(mVoiceEngine)))
|
if (!(mPtrRTP = webrtc::VoERTP_RTCP::GetInterface(mVoiceEngine)))
|
||||||
{
|
{
|
||||||
CSFLogError(logTag, "%s Unable to get audio RTP/RTCP interface ",
|
CSFLogError(logTag, "%s Unable to get audio RTP/RTCP interface ",
|
||||||
@ -556,12 +561,24 @@ WebrtcAudioConduit::ConfigureRecvMediaCodecs(
|
|||||||
CSFLogError(logTag, "%s Starting playout Failed", __FUNCTION__);
|
CSFLogError(logTag, "%s Starting playout Failed", __FUNCTION__);
|
||||||
return kMediaConduitPlayoutError;
|
return kMediaConduitPlayoutError;
|
||||||
}
|
}
|
||||||
|
|
||||||
//we should be good here for setting this.
|
//we should be good here for setting this.
|
||||||
mEngineReceiving = true;
|
mEngineReceiving = true;
|
||||||
DumpCodecDB();
|
DumpCodecDB();
|
||||||
return kMediaConduitNoError;
|
return kMediaConduitNoError;
|
||||||
}
|
}
|
||||||
|
MediaConduitErrorCode
|
||||||
|
WebrtcAudioConduit::EnableAudioLevelExtension(bool enabled, uint8_t id)
|
||||||
|
{
|
||||||
|
CSFLogDebug(logTag, "%s %d %d ", __FUNCTION__, enabled, id);
|
||||||
|
|
||||||
|
if (mPtrVoERTP_RTCP->SetRTPAudioLevelIndicationStatus(mChannel, enabled, id) == -1)
|
||||||
|
{
|
||||||
|
CSFLogError(logTag, "%s SetRTPAudioLevelIndicationStatus Failed", __FUNCTION__);
|
||||||
|
return kMediaConduitUnknownError;
|
||||||
|
}
|
||||||
|
|
||||||
|
return kMediaConduitNoError;
|
||||||
|
}
|
||||||
|
|
||||||
MediaConduitErrorCode
|
MediaConduitErrorCode
|
||||||
WebrtcAudioConduit::SendAudioFrame(const int16_t audio_data[],
|
WebrtcAudioConduit::SendAudioFrame(const int16_t audio_data[],
|
||||||
@ -570,7 +587,6 @@ WebrtcAudioConduit::SendAudioFrame(const int16_t audio_data[],
|
|||||||
int32_t capture_delay)
|
int32_t capture_delay)
|
||||||
{
|
{
|
||||||
CSFLogDebug(logTag, "%s ", __FUNCTION__);
|
CSFLogDebug(logTag, "%s ", __FUNCTION__);
|
||||||
|
|
||||||
// Following checks need to be performed
|
// Following checks need to be performed
|
||||||
// 1. Non null audio buffer pointer,
|
// 1. Non null audio buffer pointer,
|
||||||
// 2. invalid sampling frequency - less than 0 or unsupported ones
|
// 2. invalid sampling frequency - less than 0 or unsupported ones
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
#include "webrtc/voice_engine/include/voe_audio_processing.h"
|
#include "webrtc/voice_engine/include/voe_audio_processing.h"
|
||||||
#include "webrtc/voice_engine/include/voe_video_sync.h"
|
#include "webrtc/voice_engine/include/voe_video_sync.h"
|
||||||
#include "webrtc/voice_engine/include/voe_rtp_rtcp.h"
|
#include "webrtc/voice_engine/include/voe_rtp_rtcp.h"
|
||||||
|
|
||||||
//Some WebRTC types for short notations
|
//Some WebRTC types for short notations
|
||||||
using webrtc::VoEBase;
|
using webrtc::VoEBase;
|
||||||
using webrtc::VoENetwork;
|
using webrtc::VoENetwork;
|
||||||
@ -31,13 +30,11 @@
|
|||||||
using webrtc::VoEExternalMedia;
|
using webrtc::VoEExternalMedia;
|
||||||
using webrtc::VoEAudioProcessing;
|
using webrtc::VoEAudioProcessing;
|
||||||
using webrtc::VoEVideoSync;
|
using webrtc::VoEVideoSync;
|
||||||
|
using webrtc::VoERTP_RTCP;
|
||||||
/** This file hosts several structures identifying different aspects
|
/** This file hosts several structures identifying different aspects
|
||||||
* of a RTP Session.
|
* of a RTP Session.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
// Helper function
|
// Helper function
|
||||||
|
|
||||||
DOMHighResTimeStamp
|
DOMHighResTimeStamp
|
||||||
@ -86,13 +83,17 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual MediaConduitErrorCode ConfigureRecvMediaCodecs(
|
virtual MediaConduitErrorCode ConfigureRecvMediaCodecs(
|
||||||
const std::vector<AudioCodecConfig* >& codecConfigList);
|
const std::vector<AudioCodecConfig* >& codecConfigList);
|
||||||
|
/**
|
||||||
|
* Function to enable the audio level extension
|
||||||
|
* @param enabled: enable extension
|
||||||
|
*/
|
||||||
|
virtual MediaConduitErrorCode EnableAudioLevelExtension(bool enabled, uint8_t id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register External Transport to this Conduit. RTP and RTCP frames from the VoiceEngine
|
* Register External Transport to this Conduit. RTP and RTCP frames from the VoiceEngine
|
||||||
* shall be passed to the registered transport for transporting externally.
|
* shall be passed to the registered transport for transporting externally.
|
||||||
*/
|
*/
|
||||||
virtual MediaConduitErrorCode AttachTransport(mozilla::RefPtr<TransportInterface> aTransport);
|
virtual MediaConduitErrorCode AttachTransport(mozilla::RefPtr<TransportInterface> aTransport);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function to deliver externally captured audio sample for encoding and transport
|
* Function to deliver externally captured audio sample for encoding and transport
|
||||||
* @param audioData [in]: Pointer to array containing a frame of audio
|
* @param audioData [in]: Pointer to array containing a frame of audio
|
||||||
@ -234,13 +235,12 @@ private:
|
|||||||
webrtc::VoEExternalMedia* mPtrVoEXmedia;
|
webrtc::VoEExternalMedia* mPtrVoEXmedia;
|
||||||
webrtc::VoEAudioProcessing* mPtrVoEProcessing;
|
webrtc::VoEAudioProcessing* mPtrVoEProcessing;
|
||||||
webrtc::VoEVideoSync* mPtrVoEVideoSync;
|
webrtc::VoEVideoSync* mPtrVoEVideoSync;
|
||||||
|
webrtc::VoERTP_RTCP* mPtrVoERTP_RTCP;
|
||||||
webrtc::VoERTP_RTCP* mPtrRTP;
|
webrtc::VoERTP_RTCP* mPtrRTP;
|
||||||
|
|
||||||
//engine states of our interets
|
//engine states of our interets
|
||||||
bool mEngineTransmitting; // If true => VoiceEngine Send-subsystem is up
|
bool mEngineTransmitting; // If true => VoiceEngine Send-subsystem is up
|
||||||
bool mEngineReceiving; // If true => VoiceEngine Receive-subsystem is up
|
bool mEngineReceiving; // If true => VoiceEngine Receive-subsystem is up
|
||||||
// and playout is enabled
|
// and playout is enabled
|
||||||
|
|
||||||
// Keep track of each inserted RTP block and the time it was inserted
|
// Keep track of each inserted RTP block and the time it was inserted
|
||||||
// so we can estimate the clock time for a specific TimeStamp coming out
|
// so we can estimate the clock time for a specific TimeStamp coming out
|
||||||
// (for when we send data to MediaStreamTracks). Blocks are aged out as needed.
|
// (for when we send data to MediaStreamTracks). Blocks are aged out as needed.
|
||||||
|
@ -344,16 +344,18 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual MediaConduitErrorCode ConfigureRecvMediaCodecs(
|
virtual MediaConduitErrorCode ConfigureRecvMediaCodecs(
|
||||||
const std::vector<AudioCodecConfig* >& recvCodecConfigList) = 0;
|
const std::vector<AudioCodecConfig* >& recvCodecConfigList) = 0;
|
||||||
|
/**
|
||||||
|
* Function to enable the audio level extension
|
||||||
|
* @param enabled: enable extension
|
||||||
|
* @param id: id to be used for this rtp header extension
|
||||||
|
* NOTE: See AudioConduit for more information
|
||||||
|
*/
|
||||||
|
virtual MediaConduitErrorCode EnableAudioLevelExtension(bool enabled, uint8_t id) = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -2230,12 +2230,15 @@ static int vcmTxStartICE_m(cc_mcapid_t mcap_id,
|
|||||||
// and are responsible for cleanly shutting down.
|
// and are responsible for cleanly shutting down.
|
||||||
mozilla::RefPtr<mozilla::AudioSessionConduit> conduit =
|
mozilla::RefPtr<mozilla::AudioSessionConduit> conduit =
|
||||||
mozilla::AudioSessionConduit::Create(static_cast<AudioSessionConduit *>(rx_conduit.get()));
|
mozilla::AudioSessionConduit::Create(static_cast<AudioSessionConduit *>(rx_conduit.get()));
|
||||||
|
|
||||||
if (!conduit || conduit->ConfigureSendMediaCodec(config))
|
if (!conduit || conduit->ConfigureSendMediaCodec(config))
|
||||||
return VCM_ERROR;
|
return VCM_ERROR;
|
||||||
|
CSFLogError(logTag, "Created audio pipeline audio level %d %d",
|
||||||
|
attrs->audio_level, attrs->audio_level_id);
|
||||||
|
|
||||||
|
if (!conduit || conduit->EnableAudioLevelExtension(attrs->audio_level, attrs->audio_level_id))
|
||||||
|
return VCM_ERROR;
|
||||||
|
|
||||||
pc.impl()->media()->AddConduit(level, false, conduit);
|
pc.impl()->media()->AddConduit(level, false, conduit);
|
||||||
|
|
||||||
mozilla::RefPtr<mozilla::MediaPipeline> pipeline =
|
mozilla::RefPtr<mozilla::MediaPipeline> pipeline =
|
||||||
new mozilla::MediaPipelineTransmit(
|
new mozilla::MediaPipelineTransmit(
|
||||||
pc.impl()->GetHandle(),
|
pc.impl()->GetHandle(),
|
||||||
|
@ -514,17 +514,16 @@ gsmsdp_init_media (fsmdef_media_t *media)
|
|||||||
media->previous_sdp.num_payloads = 0;
|
media->previous_sdp.num_payloads = 0;
|
||||||
media->previous_sdp.tias_bw = SDP_INVALID_VALUE;
|
media->previous_sdp.tias_bw = SDP_INVALID_VALUE;
|
||||||
media->previous_sdp.profile_level = 0;
|
media->previous_sdp.profile_level = 0;
|
||||||
|
|
||||||
media->hold = FSM_HOLD_NONE;
|
media->hold = FSM_HOLD_NONE;
|
||||||
media->flags = 0; /* clear all flags */
|
media->flags = 0; /* clear all flags */
|
||||||
media->cap_index = CC_MAX_MEDIA_CAP; /* max is invalid value */
|
media->cap_index = CC_MAX_MEDIA_CAP; /* max is invalid value */
|
||||||
media->video = NULL;
|
media->video = NULL;
|
||||||
media->candidate_ct = 0;
|
media->candidate_ct = 0;
|
||||||
media->rtcp_mux = FALSE;
|
media->rtcp_mux = FALSE;
|
||||||
|
media->audio_level = TRUE;
|
||||||
|
media->audio_level_id = 1;
|
||||||
/* ACTPASS is the value we put in every offer */
|
/* ACTPASS is the value we put in every offer */
|
||||||
media->setup = SDP_SETUP_ACTPASS;
|
media->setup = SDP_SETUP_ACTPASS;
|
||||||
|
|
||||||
media->local_datachannel_port = 0;
|
media->local_datachannel_port = 0;
|
||||||
media->remote_datachannel_port = 0;
|
media->remote_datachannel_port = 0;
|
||||||
media->datachannel_streams = WEBRTC_DATACHANNEL_STREAMS_DEFAULT;
|
media->datachannel_streams = WEBRTC_DATACHANNEL_STREAMS_DEFAULT;
|
||||||
@ -1702,7 +1701,6 @@ gsmsdp_set_rtcp_fb_ack_attribute (uint16_t level,
|
|||||||
GSM_ERR_MSG("Failed to add attribute");
|
GSM_ERR_MSG("Failed to add attribute");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = sdp_attr_set_rtcp_fb_ack(sdp_p, level, payload_type,
|
result = sdp_attr_set_rtcp_fb_ack(sdp_p, level, payload_type,
|
||||||
a_instance, ack_type);
|
a_instance, ack_type);
|
||||||
if (result != SDP_SUCCESS) {
|
if (result != SDP_SUCCESS) {
|
||||||
@ -1710,6 +1708,39 @@ gsmsdp_set_rtcp_fb_ack_attribute (uint16_t level,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* gsmsdp_set_audio_level_attribute
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
*
|
||||||
|
* Adds an audio level extension attributesto the specified SDP.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
*
|
||||||
|
* level - The media level of the SDP where the media attribute exists.
|
||||||
|
* sdp_p - Pointer to the SDP to set the attribute against.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
gsmsdp_set_extmap_attribute (uint16_t level,
|
||||||
|
void *sdp_p,
|
||||||
|
u16 id,
|
||||||
|
const char* uri)
|
||||||
|
{
|
||||||
|
uint16_t a_instance = 0;
|
||||||
|
sdp_result_e result;
|
||||||
|
|
||||||
|
result = sdp_add_new_attr(sdp_p, level, 0, SDP_ATTR_EXTMAP, &a_instance);
|
||||||
|
if (result != SDP_SUCCESS) {
|
||||||
|
GSM_ERR_MSG("Failed to add attribute");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = sdp_attr_set_extmap(sdp_p, level, id, uri, a_instance);
|
||||||
|
if (result != SDP_SUCCESS) {
|
||||||
|
GSM_ERR_MSG("Failed to set attribute");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* gsmsdp_set_rtcp_fb_nack_attribute
|
* gsmsdp_set_rtcp_fb_nack_attribute
|
||||||
*
|
*
|
||||||
@ -4629,6 +4660,66 @@ gsmsdp_negotiate_rtcp_fb (cc_sdp_t *cc_sdp_p,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return CC_CAUSE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* gsmsdp_negotiate_extmap
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Negotiates extmaps header extension to local SDP for supported audio codecs
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* cc_sdp_p - local and remote SDP
|
||||||
|
* media - The media structure for the current level to be negotiated
|
||||||
|
* offer - True if the remote SDP is an offer
|
||||||
|
*
|
||||||
|
* returns
|
||||||
|
* CC_CAUSE_OK - success
|
||||||
|
* any other code - failure
|
||||||
|
*/
|
||||||
|
cc_causes_t
|
||||||
|
gsmsdp_negotiate_extmap (cc_sdp_t *cc_sdp_p,
|
||||||
|
fsmdef_media_t *media,
|
||||||
|
boolean offer)
|
||||||
|
{
|
||||||
|
boolean audio_level = FALSE;
|
||||||
|
u16 audio_level_id = 0xFFFF;
|
||||||
|
int level = media->level;
|
||||||
|
int i;
|
||||||
|
const char* uri;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remove any previously negotiated extmap attributes from the
|
||||||
|
* local SDP
|
||||||
|
*/
|
||||||
|
sdp_result_e result = SDP_SUCCESS;
|
||||||
|
while (result == SDP_SUCCESS) {
|
||||||
|
result = sdp_delete_attr (cc_sdp_p->src_sdp, level, 0,
|
||||||
|
SDP_ATTR_EXTMAP, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
i = 1;
|
||||||
|
do {
|
||||||
|
uri = sdp_attr_get_extmap_uri(cc_sdp_p->dest_sdp, level, i);
|
||||||
|
|
||||||
|
if (uri != NULL && strcmp(uri, SDP_EXTMAP_AUDIO_LEVEL) == 0) {
|
||||||
|
audio_level = TRUE;
|
||||||
|
audio_level_id = sdp_attr_get_extmap_id(cc_sdp_p->dest_sdp, level, i);
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
} while (uri != NULL);
|
||||||
|
|
||||||
|
media->audio_level = audio_level;
|
||||||
|
media->audio_level_id = audio_level_id;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now, in our local SDP, set extmap types that both we and the
|
||||||
|
* remote party support
|
||||||
|
*/
|
||||||
|
if (media->audio_level) {
|
||||||
|
gsmsdp_set_extmap_attribute (level, cc_sdp_p->src_sdp, audio_level_id, SDP_EXTMAP_AUDIO_LEVEL);
|
||||||
|
}
|
||||||
|
|
||||||
return CC_CAUSE_OK;
|
return CC_CAUSE_OK;
|
||||||
}
|
}
|
||||||
@ -4980,11 +5071,14 @@ gsmsdp_negotiate_media_lines (fsm_fcb_t *fcb_p, cc_sdp_t *sdp_p, boolean initial
|
|||||||
unsupported_line = TRUE;
|
unsupported_line = TRUE;
|
||||||
update_local_ret_value = TRUE;
|
update_local_ret_value = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Negotiate rtcp feedback mechanisms */
|
/* Negotiate rtcp feedback mechanisms */
|
||||||
if (media && media_type == SDP_MEDIA_VIDEO) {
|
if (media && media_type == SDP_MEDIA_VIDEO) {
|
||||||
gsmsdp_negotiate_rtcp_fb (dcb_p->sdp, media, offer);
|
gsmsdp_negotiate_rtcp_fb (dcb_p->sdp, media, offer);
|
||||||
}
|
}
|
||||||
|
/* Negotiate redundancy mechanisms */
|
||||||
|
if (media && media_type == SDP_MEDIA_AUDIO) {
|
||||||
|
gsmsdp_negotiate_extmap (dcb_p->sdp, media, offer);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Negotiate rtcp-mux
|
* Negotiate rtcp-mux
|
||||||
@ -4993,7 +5087,6 @@ gsmsdp_negotiate_media_lines (fsm_fcb_t *fcb_p, cc_sdp_t *sdp_p, boolean initial
|
|||||||
sdp_res = sdp_attr_get_rtcp_mux_attribute(sdp_p->dest_sdp, i,
|
sdp_res = sdp_attr_get_rtcp_mux_attribute(sdp_p->dest_sdp, i,
|
||||||
0, SDP_ATTR_RTCP_MUX,
|
0, SDP_ATTR_RTCP_MUX,
|
||||||
1, &rtcp_mux);
|
1, &rtcp_mux);
|
||||||
|
|
||||||
if (SDP_SUCCESS == sdp_res) {
|
if (SDP_SUCCESS == sdp_res) {
|
||||||
media->rtcp_mux = TRUE;
|
media->rtcp_mux = TRUE;
|
||||||
}
|
}
|
||||||
@ -5597,10 +5690,14 @@ gsmsdp_add_media_line (fsmdef_dcb_t *dcb_p, const cc_media_cap_t *media_cap,
|
|||||||
sdp_rtcp_fb_nack_to_bitmap(SDP_RTCP_FB_NACK_PLI) |
|
sdp_rtcp_fb_nack_to_bitmap(SDP_RTCP_FB_NACK_PLI) |
|
||||||
sdp_rtcp_fb_ccm_to_bitmap(SDP_RTCP_FB_CCM_FIR));
|
sdp_rtcp_fb_ccm_to_bitmap(SDP_RTCP_FB_CCM_FIR));
|
||||||
}
|
}
|
||||||
|
/* Add supported audio level rtp extension */
|
||||||
|
if (media_cap->type == SDP_MEDIA_AUDIO) {
|
||||||
|
gsmsdp_set_extmap_attribute(level, dcb_p->sdp->src_sdp, 1,
|
||||||
|
SDP_EXTMAP_AUDIO_LEVEL);
|
||||||
|
}
|
||||||
|
|
||||||
/* Add a=setup attribute */
|
/* Add a=setup attribute */
|
||||||
gsmsdp_set_setup_attribute(level, dcb_p->sdp->src_sdp, media->setup);
|
gsmsdp_set_setup_attribute(level, dcb_p->sdp->src_sdp, media->setup);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* wait until here to set ICE candidates as SDP is now initialized
|
* wait until here to set ICE candidates as SDP is now initialized
|
||||||
*/
|
*/
|
||||||
|
@ -201,17 +201,21 @@ typedef struct fsmdef_media_t_ {
|
|||||||
/* ICE Candidates */
|
/* ICE Candidates */
|
||||||
char **candidatesp;
|
char **candidatesp;
|
||||||
int candidate_ct;
|
int candidate_ct;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* rtcp-mux indicates media stream is muxed for RTP and RTCP
|
* rtcp-mux indicates media stream is muxed for RTP and RTCP
|
||||||
*/
|
*/
|
||||||
boolean rtcp_mux;
|
boolean rtcp_mux;
|
||||||
|
/*
|
||||||
|
* Flag to indicate if RTP Header extension for audio level is used
|
||||||
|
* and the id to be used for it
|
||||||
|
*/
|
||||||
|
boolean audio_level;
|
||||||
|
uint8_t audio_level_id;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The value of the a=setup line
|
* The value of the a=setup line
|
||||||
*/
|
*/
|
||||||
sdp_setup_type_e setup;
|
sdp_setup_type_e setup;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* port number used in m= data channel line
|
* port number used in m= data channel line
|
||||||
*/
|
*/
|
||||||
|
@ -1230,13 +1230,11 @@ lsm_tx_start (lsm_lcb_t *lcb, const char *fname, fsmdef_media_t *media)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
media->xmit_chan = TRUE;
|
media->xmit_chan = TRUE;
|
||||||
|
|
||||||
attrs.mute = FALSE;
|
attrs.mute = FALSE;
|
||||||
|
|
||||||
attrs.rtcp_mux = media->rtcp_mux;
|
attrs.rtcp_mux = media->rtcp_mux;
|
||||||
|
attrs.audio_level = media->audio_level;
|
||||||
|
attrs.audio_level_id = (uint8_t)media->audio_level_id;
|
||||||
attrs.is_video = FALSE;
|
attrs.is_video = FALSE;
|
||||||
attrs.bundle_level = 0;
|
attrs.bundle_level = 0;
|
||||||
attrs.bundle_stream_correlator = 0;
|
attrs.bundle_stream_correlator = 0;
|
||||||
|
@ -67,15 +67,14 @@
|
|||||||
#define SDP_SRTP_CONTEXT_SET_ENCRYPT_AUTHENTICATE(cw) \
|
#define SDP_SRTP_CONTEXT_SET_ENCRYPT_AUTHENTICATE(cw) \
|
||||||
((cw) |= (SDP_SRTP_ENCRYPT_MASK | SDP_SRTP_AUTHENTICATE_MASK | \
|
((cw) |= (SDP_SRTP_ENCRYPT_MASK | SDP_SRTP_AUTHENTICATE_MASK | \
|
||||||
SDP_SRTCP_ENCRYPT_MASK))
|
SDP_SRTCP_ENCRYPT_MASK))
|
||||||
|
|
||||||
#define SDP_SRTP_CONTEXT_RESET_SSRC(cw) ((cw) &= ~(SDP_SRTCP_SSRC_MASK))
|
#define SDP_SRTP_CONTEXT_RESET_SSRC(cw) ((cw) &= ~(SDP_SRTCP_SSRC_MASK))
|
||||||
#define SDP_SRTP_CONTEXT_RESET_ROC(cw) ((cw) &= ~(SDP_SRTCP_ROC_MASK))
|
#define SDP_SRTP_CONTEXT_RESET_ROC(cw) ((cw) &= ~(SDP_SRTCP_ROC_MASK))
|
||||||
#define SDP_SRTP_CONTEXT_RESET_KDR(cw) ((cw) &= ~(SDP_SRTCP_KDR_MASK))
|
#define SDP_SRTP_CONTEXT_RESET_KDR(cw) ((cw) &= ~(SDP_SRTCP_KDR_MASK))
|
||||||
#define SDP_CONTEXT_RESET_MASTER_KEY(cw) ((cw) &= ~(SDP_SRTCP_KEY_MASK))
|
#define SDP_CONTEXT_RESET_MASTER_KEY(cw) ((cw) &= ~(SDP_SRTCP_KEY_MASK))
|
||||||
#define SDP_CONTEXT_RESET_MASTER_SALT(cw) ((cw) &= ~(SDP_SRTCP_SALT_MASK))
|
#define SDP_CONTEXT_RESET_MASTER_SALT(cw) ((cw) &= ~(SDP_SRTCP_SALT_MASK))
|
||||||
|
#define SDP_EXTMAP_AUDIO_LEVEL "urn:ietf:params:rtp-hdrext:ssrc-audio-level"
|
||||||
|
|
||||||
/* SDP Enum Types */
|
/* SDP Enum Types */
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SDP_DEBUG_TRACE,
|
SDP_DEBUG_TRACE,
|
||||||
SDP_DEBUG_WARNINGS,
|
SDP_DEBUG_WARNINGS,
|
||||||
@ -892,6 +891,16 @@ typedef struct sdp_media_profiles {
|
|||||||
sdp_payload_ind_e payload_indicator[SDP_MAX_PROFILES][SDP_MAX_PAYLOAD_TYPES];
|
sdp_payload_ind_e payload_indicator[SDP_MAX_PROFILES][SDP_MAX_PAYLOAD_TYPES];
|
||||||
u16 payload_type[SDP_MAX_PROFILES][SDP_MAX_PAYLOAD_TYPES];
|
u16 payload_type[SDP_MAX_PROFILES][SDP_MAX_PAYLOAD_TYPES];
|
||||||
} sdp_media_profiles_t;
|
} sdp_media_profiles_t;
|
||||||
|
/*
|
||||||
|
* a=extmap:<value>["/"<direction>] <URI> <extensionattributes>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
typedef struct sdp_extmap {
|
||||||
|
u16 id;
|
||||||
|
sdp_direction_e media_direction;
|
||||||
|
char uri[SDP_MAX_STRING_LEN+1];
|
||||||
|
char extension_attributes[SDP_MAX_STRING_LEN+1];
|
||||||
|
} sdp_extmap_t;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -899,7 +908,6 @@ typedef struct sdp_media_profiles {
|
|||||||
* This type is used to hold cryptographic context information.
|
* This type is used to hold cryptographic context information.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct sdp_srtp_crypto_context_t_ {
|
typedef struct sdp_srtp_crypto_context_t_ {
|
||||||
int32 tag;
|
int32 tag;
|
||||||
unsigned long selection_flags;
|
unsigned long selection_flags;
|
||||||
@ -982,10 +990,10 @@ typedef struct sdp_attr {
|
|||||||
sdp_fmtp_fb_t rtcp_fb;
|
sdp_fmtp_fb_t rtcp_fb;
|
||||||
sdp_setup_type_e setup;
|
sdp_setup_type_e setup;
|
||||||
sdp_connection_type_e connection;
|
sdp_connection_type_e connection;
|
||||||
|
sdp_extmap_t extmap;
|
||||||
} attr;
|
} attr;
|
||||||
struct sdp_attr *next_p;
|
struct sdp_attr *next_p;
|
||||||
} sdp_attr_t;
|
} sdp_attr_t;
|
||||||
|
|
||||||
typedef struct sdp_srtp_crypto_suite_list_ {
|
typedef struct sdp_srtp_crypto_suite_list_ {
|
||||||
sdp_srtp_crypto_suite_t crypto_suite_val;
|
sdp_srtp_crypto_suite_t crypto_suite_val;
|
||||||
char * crypto_suite_str;
|
char * crypto_suite_str;
|
||||||
@ -2099,9 +2107,16 @@ sdp_attr_set_rtcp_fb_nack(void *sdp_ptr, u16 level, u16 payload_type, u16 inst,
|
|||||||
sdp_result_e
|
sdp_result_e
|
||||||
sdp_attr_set_rtcp_fb_trr_int(void *sdp_ptr, u16 level, u16 payload_type,
|
sdp_attr_set_rtcp_fb_trr_int(void *sdp_ptr, u16 level, u16 payload_type,
|
||||||
u16 inst, u32 interval);
|
u16 inst, u32 interval);
|
||||||
|
|
||||||
sdp_result_e
|
sdp_result_e
|
||||||
sdp_attr_set_rtcp_fb_ccm(void *sdp_ptr, u16 level, u16 payload_type, u16 inst,
|
sdp_attr_set_rtcp_fb_ccm(void *sdp_ptr, u16 level, u16 payload_type, u16 inst,
|
||||||
sdp_rtcp_fb_ccm_type_e);
|
sdp_rtcp_fb_ccm_type_e);
|
||||||
|
const char *
|
||||||
|
sdp_attr_get_extmap_uri(void *sdp_ptr, u16 level, u16 inst);
|
||||||
|
|
||||||
|
u16
|
||||||
|
sdp_attr_get_extmap_id(void *sdp_ptr, u16 level, u16 inst);
|
||||||
|
|
||||||
|
sdp_result_e
|
||||||
|
sdp_attr_set_extmap(void *sdp_ptr, u16 level, u16 id, const char* uri, u16 inst);
|
||||||
|
|
||||||
#endif /* _SDP_H_ */
|
#endif /* _SDP_H_ */
|
||||||
|
@ -5145,6 +5145,79 @@ sdp_result_e sdp_parse_attr_connection(sdp_t *sdp_p,
|
|||||||
return SDP_FAILURE;
|
return SDP_FAILURE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
return SDP_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
sdp_result_e sdp_build_attr_extmap(sdp_t *sdp_p,
|
||||||
|
sdp_attr_t *attr_p,
|
||||||
|
flex_string *fs)
|
||||||
|
{
|
||||||
|
flex_string_sprintf(fs, "a=extmap:%d %s\r\n",
|
||||||
|
attr_p->attr.extmap.id,
|
||||||
|
attr_p->attr.extmap.uri);
|
||||||
|
|
||||||
return SDP_SUCCESS;
|
return SDP_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sdp_result_e sdp_parse_attr_extmap(sdp_t *sdp_p,
|
||||||
|
sdp_attr_t *attr_p,
|
||||||
|
const char *ptr)
|
||||||
|
{
|
||||||
|
sdp_result_e result;
|
||||||
|
|
||||||
|
attr_p->attr.extmap.id = 0;
|
||||||
|
attr_p->attr.extmap.media_direction = SDP_DIRECTION_SENDRECV;
|
||||||
|
attr_p->attr.extmap.uri[0] = '\0';
|
||||||
|
attr_p->attr.extmap.extension_attributes[0] = '\0';
|
||||||
|
|
||||||
|
/* Find the payload type number. */
|
||||||
|
attr_p->attr.extmap.id =
|
||||||
|
(u16)sdp_getnextnumtok(ptr, &ptr, "/ \t", &result);
|
||||||
|
if (result != SDP_SUCCESS) {
|
||||||
|
sdp_parse_error(sdp_p->peerconnection,
|
||||||
|
"%s Warning: Invalid extmap id specified for %s attribute.",
|
||||||
|
sdp_p->debug_str, sdp_get_attr_name(attr_p->type));
|
||||||
|
sdp_p->conf_p->num_invalid_param++;
|
||||||
|
return (SDP_INVALID_PARAMETER);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*ptr == '/') {
|
||||||
|
char direction[SDP_MAX_STRING_LEN+1];
|
||||||
|
/* Find the encoding name. */
|
||||||
|
ptr = sdp_getnextstrtok(ptr, direction,
|
||||||
|
sizeof(direction), " \t", &result);
|
||||||
|
if (result != SDP_SUCCESS) {
|
||||||
|
sdp_parse_error(sdp_p->peerconnection,
|
||||||
|
"%s Warning: No uri specified in %s attribute.",
|
||||||
|
sdp_p->debug_str, sdp_get_attr_name(attr_p->type));
|
||||||
|
sdp_p->conf_p->num_invalid_param++;
|
||||||
|
return (SDP_INVALID_PARAMETER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr = sdp_getnextstrtok(ptr, attr_p->attr.extmap.uri,
|
||||||
|
sizeof(attr_p->attr.extmap.uri), " \t", &result);
|
||||||
|
if (result != SDP_SUCCESS) {
|
||||||
|
sdp_parse_error(sdp_p->peerconnection,
|
||||||
|
"%s Warning: No uri specified in %s attribute.",
|
||||||
|
sdp_p->debug_str, sdp_get_attr_name(attr_p->type));
|
||||||
|
sdp_p->conf_p->num_invalid_param++;
|
||||||
|
return (SDP_INVALID_PARAMETER);
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr = sdp_getnextstrtok(ptr, attr_p->attr.extmap.extension_attributes,
|
||||||
|
sizeof(attr_p->attr.extmap.extension_attributes), "\r\n", &result);
|
||||||
|
|
||||||
|
if (sdp_p->debug_flag[SDP_DEBUG_TRACE]) {
|
||||||
|
SDP_PRINT("%s Parsed a=%s, id %u, direction %s, "
|
||||||
|
"uri %s, extension %s", sdp_p->debug_str,
|
||||||
|
sdp_get_attr_name(attr_p->type),
|
||||||
|
attr_p->attr.extmap.id,
|
||||||
|
SDP_DIRECTION_PRINT(attr_p->attr.extmap.media_direction),
|
||||||
|
attr_p->attr.extmap.uri,
|
||||||
|
attr_p->attr.extmap.extension_attributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (SDP_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -12477,10 +12477,112 @@ sdp_attr_set_rtcp_fb_ccm(void *sdp_ptr, u16 level, u16 payload_type, u16 inst,
|
|||||||
sdp_p->conf_p->num_invalid_param++;
|
sdp_p->conf_p->num_invalid_param++;
|
||||||
return (SDP_INVALID_PARAMETER);
|
return (SDP_INVALID_PARAMETER);
|
||||||
}
|
}
|
||||||
|
|
||||||
attr_p->attr.rtcp_fb.payload_num = payload_type;
|
attr_p->attr.rtcp_fb.payload_num = payload_type;
|
||||||
attr_p->attr.rtcp_fb.feedback_type = SDP_RTCP_FB_CCM;
|
attr_p->attr.rtcp_fb.feedback_type = SDP_RTCP_FB_CCM;
|
||||||
attr_p->attr.rtcp_fb.param.ccm = type;
|
attr_p->attr.rtcp_fb.param.ccm = type;
|
||||||
attr_p->attr.rtcp_fb.extra[0] = '\0';
|
attr_p->attr.rtcp_fb.extra[0] = '\0';
|
||||||
return (SDP_SUCCESS);
|
return (SDP_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Function: sdp_attr_get_extmap_uri
|
||||||
|
* Description: Returns a pointer to the value of the encoding name
|
||||||
|
* parameter specified for the given attribute. Value is
|
||||||
|
* returned as a const ptr and so cannot be modified by the
|
||||||
|
* application. If the given attribute is not defined, NULL
|
||||||
|
* will be returned.
|
||||||
|
* Parameters: sdp_ptr The SDP handle returned by sdp_init_description.
|
||||||
|
* level The level to check for the attribute.
|
||||||
|
* inst_num The attribute instance number to check.
|
||||||
|
* Returns: Codec value or SDP_CODEC_INVALID.
|
||||||
|
*/
|
||||||
|
const char *sdp_attr_get_extmap_uri(void *sdp_ptr, u16 level,
|
||||||
|
u16 inst_num)
|
||||||
|
{
|
||||||
|
sdp_t *sdp_p = (sdp_t *)sdp_ptr;
|
||||||
|
sdp_attr_t *attr_p;
|
||||||
|
|
||||||
|
if (sdp_verify_sdp_ptr(sdp_p) == FALSE) {
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
attr_p = sdp_find_attr(sdp_p, level, 0, SDP_ATTR_EXTMAP, inst_num);
|
||||||
|
if (attr_p == NULL) {
|
||||||
|
if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
|
||||||
|
CSFLogError(logTag, "%s extmap attribute, level %u instance %u "
|
||||||
|
"not found.", sdp_p->debug_str, level, inst_num);
|
||||||
|
}
|
||||||
|
sdp_p->conf_p->num_invalid_param++;
|
||||||
|
return (NULL);
|
||||||
|
} else {
|
||||||
|
return (attr_p->attr.extmap.uri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Function: sdp_attr_get_extmap_id
|
||||||
|
* Description: Returns the id of the extmap specified for the given
|
||||||
|
* attribute. If the given attribute is not defined, 0xFFFF
|
||||||
|
* will be returned.
|
||||||
|
* Parameters: sdp_ptr The SDP handle returned by sdp_init_description.
|
||||||
|
* level The level to check for the attribute.
|
||||||
|
* inst_num The attribute instance number to check.
|
||||||
|
* Returns: The id of the extmap attribute.
|
||||||
|
*/
|
||||||
|
u16 sdp_attr_get_extmap_id(void *sdp_ptr, u16 level,
|
||||||
|
u16 inst_num)
|
||||||
|
{
|
||||||
|
sdp_t *sdp_p = (sdp_t *)sdp_ptr;
|
||||||
|
sdp_attr_t *attr_p;
|
||||||
|
|
||||||
|
if (sdp_verify_sdp_ptr(sdp_p) == FALSE) {
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
attr_p = sdp_find_attr(sdp_p, level, 0, SDP_ATTR_EXTMAP, inst_num);
|
||||||
|
if (attr_p == NULL) {
|
||||||
|
if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
|
||||||
|
CSFLogError(logTag, "%s extmap attribute, level %u instance %u "
|
||||||
|
"not found.", sdp_p->debug_str, level, inst_num);
|
||||||
|
}
|
||||||
|
sdp_p->conf_p->num_invalid_param++;
|
||||||
|
return 0xFFFF;
|
||||||
|
} else {
|
||||||
|
return (attr_p->attr.extmap.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Function: sdp_attr_set_extmap
|
||||||
|
* Description: Sets the value of an rtcp-fb:...ccm attribute
|
||||||
|
* Parameters: sdp_ptr The SDP handle returned by sdp_init_description.
|
||||||
|
* level The level to set the attribute.
|
||||||
|
* id The id to set the attribute.
|
||||||
|
* uri The uri to set the attribute.
|
||||||
|
* inst The attribute instance number to check.
|
||||||
|
* Returns: SDP_SUCCESS Attribute param was set successfully.
|
||||||
|
* SDP_INVALID_PARAMETER Specified attribute is not defined.
|
||||||
|
*/
|
||||||
|
sdp_result_e
|
||||||
|
sdp_attr_set_extmap(void *sdp_ptr, u16 level, u16 id, const char* uri, u16 inst)
|
||||||
|
{
|
||||||
|
sdp_t *sdp_p = (sdp_t *)sdp_ptr;
|
||||||
|
sdp_attr_t *attr_p;
|
||||||
|
|
||||||
|
if (!sdp_verify_sdp_ptr(sdp_p)) {
|
||||||
|
return (SDP_INVALID_SDP_PTR);
|
||||||
|
}
|
||||||
|
|
||||||
|
attr_p = sdp_find_attr(sdp_p, level, 0, SDP_ATTR_EXTMAP, inst);
|
||||||
|
if (!attr_p) {
|
||||||
|
if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
|
||||||
|
CSFLogError(logTag, "%s extmap attribute, level %u "
|
||||||
|
"instance %u not found.", sdp_p->debug_str, level,
|
||||||
|
inst);
|
||||||
|
}
|
||||||
|
sdp_p->conf_p->num_invalid_param++;
|
||||||
|
return (SDP_INVALID_PARAMETER);
|
||||||
|
}
|
||||||
|
|
||||||
|
attr_p->attr.extmap.id = id;
|
||||||
|
sstrncpy(attr_p->attr.extmap.uri, uri, SDP_MAX_STRING_LEN+1);
|
||||||
|
return (SDP_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -176,8 +176,9 @@ const sdp_attrarray_t sdp_attr[SDP_MAX_ATTR_TYPES] =
|
|||||||
sdp_parse_attr_setup, sdp_build_attr_setup},
|
sdp_parse_attr_setup, sdp_build_attr_setup},
|
||||||
{"connection", sizeof("connection"),
|
{"connection", sizeof("connection"),
|
||||||
sdp_parse_attr_connection, sdp_build_attr_connection},
|
sdp_parse_attr_connection, sdp_build_attr_connection},
|
||||||
|
{"extmap", sizeof("extmap"),
|
||||||
|
sdp_parse_attr_extmap, sdp_build_attr_extmap},
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Note: These *must* be in the same order as the enum types. */
|
/* Note: These *must* be in the same order as the enum types. */
|
||||||
const sdp_namearray_t sdp_media[SDP_MAX_MEDIA_TYPES] =
|
const sdp_namearray_t sdp_media[SDP_MAX_MEDIA_TYPES] =
|
||||||
{
|
{
|
||||||
|
@ -167,11 +167,16 @@ extern sdp_result_e sdp_parse_attr_connection(sdp_t *sdp_p,
|
|||||||
extern sdp_result_e sdp_build_attr_connection(sdp_t *sdp_p,
|
extern sdp_result_e sdp_build_attr_connection(sdp_t *sdp_p,
|
||||||
sdp_attr_t *attr_p,
|
sdp_attr_t *attr_p,
|
||||||
flex_string *fs);
|
flex_string *fs);
|
||||||
|
extern sdp_result_e sdp_parse_attr_extmap(sdp_t *sdp_p,
|
||||||
|
sdp_attr_t *attr_p,
|
||||||
|
const char *ptr);
|
||||||
|
extern sdp_result_e sdp_build_attr_extmap(sdp_t *sdp_p,
|
||||||
|
sdp_attr_t *attr_p,
|
||||||
|
flex_string *fs);
|
||||||
extern sdp_result_e sdp_parse_attr_mptime(
|
extern sdp_result_e sdp_parse_attr_mptime(
|
||||||
sdp_t *sdp_p, sdp_attr_t *attr_p, const char *ptr);
|
sdp_t *sdp_p, sdp_attr_t *attr_p, const char *ptr);
|
||||||
extern sdp_result_e sdp_build_attr_mptime(
|
extern sdp_result_e sdp_build_attr_mptime(
|
||||||
sdp_t *sdp_p, sdp_attr_t *attr_p, flex_string *fs);
|
sdp_t *sdp_p, sdp_attr_t *attr_p, flex_string *fs);
|
||||||
|
|
||||||
extern sdp_result_e sdp_parse_attr_x_sidin(
|
extern sdp_result_e sdp_parse_attr_x_sidin(
|
||||||
sdp_t *sdp_p, sdp_attr_t *attr_p, const char *ptr);
|
sdp_t *sdp_p, sdp_attr_t *attr_p, const char *ptr);
|
||||||
extern sdp_result_e sdp_build_attr_x_sidin(
|
extern sdp_result_e sdp_build_attr_x_sidin(
|
||||||
|
@ -246,10 +246,10 @@ typedef enum {
|
|||||||
SDP_ATTR_RTCP_FB, /* RFC 4585 */
|
SDP_ATTR_RTCP_FB, /* RFC 4585 */
|
||||||
SDP_ATTR_SETUP,
|
SDP_ATTR_SETUP,
|
||||||
SDP_ATTR_CONNECTION,
|
SDP_ATTR_CONNECTION,
|
||||||
|
SDP_ATTR_EXTMAP, /* RFC 5285 */
|
||||||
SDP_MAX_ATTR_TYPES,
|
SDP_MAX_ATTR_TYPES,
|
||||||
SDP_ATTR_INVALID
|
SDP_ATTR_INVALID
|
||||||
} sdp_attr_e;
|
} sdp_attr_e;
|
||||||
|
|
||||||
/* This is here so that it can be used in the VcmSIPCCBinding interface */
|
/* This is here so that it can be used in the VcmSIPCCBinding interface */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SDP_SETUP_NOT_FOUND = -1,
|
SDP_SETUP_NOT_FOUND = -1,
|
||||||
|
@ -338,6 +338,8 @@ typedef struct vcm_attrs_t_ {
|
|||||||
cc_boolean mute;
|
cc_boolean mute;
|
||||||
cc_boolean is_video;
|
cc_boolean is_video;
|
||||||
cc_boolean rtcp_mux;
|
cc_boolean rtcp_mux;
|
||||||
|
cc_boolean audio_level;
|
||||||
|
uint8_t audio_level_id;
|
||||||
vcm_audioAttrs_t audio; /**< audio line attribs */
|
vcm_audioAttrs_t audio; /**< audio line attribs */
|
||||||
vcm_videoAttrs_t video; /**< Video Atrribs */
|
vcm_videoAttrs_t video; /**< Video Atrribs */
|
||||||
uint32_t bundle_level; /**< Where bundle transport info lives, if any */
|
uint32_t bundle_level; /**< Where bundle transport info lives, if any */
|
||||||
|
@ -191,6 +191,14 @@ class SdpTest : public ::testing::Test {
|
|||||||
type), SDP_SUCCESS);
|
type), SDP_SUCCESS);
|
||||||
return inst_num;
|
return inst_num;
|
||||||
}
|
}
|
||||||
|
u16 AddNewExtMap(int level, const char* uri) {
|
||||||
|
u16 inst_num = 0;
|
||||||
|
EXPECT_EQ(sdp_add_new_attr(sdp_ptr_, level, 0, SDP_ATTR_EXTMAP,
|
||||||
|
&inst_num), SDP_SUCCESS);
|
||||||
|
EXPECT_EQ(sdp_attr_set_extmap(sdp_ptr_, level, inst_num,
|
||||||
|
uri, inst_num), SDP_SUCCESS);
|
||||||
|
return inst_num;
|
||||||
|
}
|
||||||
|
|
||||||
u16 AddNewFmtpMaxFs(int level, u32 max_fs) {
|
u16 AddNewFmtpMaxFs(int level, u32 max_fs) {
|
||||||
u16 inst_num = 0;
|
u16 inst_num = 0;
|
||||||
@ -725,6 +733,23 @@ TEST_F(SdpTest, parseRtcpFbAllPayloads) {
|
|||||||
SDP_RTCP_FB_ACK_RPSI);
|
SDP_RTCP_FB_ACK_RPSI);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
TEST_F(SdpTest, addExtMap) {
|
||||||
|
InitLocalSdp();
|
||||||
|
int level = AddNewMedia(SDP_MEDIA_VIDEO);
|
||||||
|
AddNewExtMap(level, SDP_EXTMAP_AUDIO_LEVEL);
|
||||||
|
std::string body = SerializeSdp();
|
||||||
|
ASSERT_NE(body.find("a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\n"), std::string::npos);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SdpTest, parseExtMap) {
|
||||||
|
ParseSdp(kVideoSdp +
|
||||||
|
"a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\n");
|
||||||
|
ASSERT_STREQ(sdp_attr_get_extmap_uri(sdp_ptr_, 1, 1),
|
||||||
|
SDP_EXTMAP_AUDIO_LEVEL);
|
||||||
|
ASSERT_EQ(sdp_attr_get_extmap_id(sdp_ptr_, 1, 1),
|
||||||
|
1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(SdpTest, parseFmtpMaxFs) {
|
TEST_F(SdpTest, parseFmtpMaxFs) {
|
||||||
u32 val = 0;
|
u32 val = 0;
|
||||||
@ -732,7 +757,6 @@ TEST_F(SdpTest, parseFmtpMaxFs) {
|
|||||||
ASSERT_EQ(sdp_attr_get_fmtp_max_fs(sdp_ptr_, 1, 0, 1, &val), SDP_SUCCESS);
|
ASSERT_EQ(sdp_attr_get_fmtp_max_fs(sdp_ptr_, 1, 0, 1, &val), SDP_SUCCESS);
|
||||||
ASSERT_EQ(val, 300);
|
ASSERT_EQ(val, 300);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SdpTest, parseFmtpMaxFr) {
|
TEST_F(SdpTest, parseFmtpMaxFr) {
|
||||||
u32 val = 0;
|
u32 val = 0;
|
||||||
ParseSdp(kVideoSdp + "a=fmtp:120 max-fs=300;max-fr=30\r\n");
|
ParseSdp(kVideoSdp + "a=fmtp:120 max-fs=300;max-fr=30\r\n");
|
||||||
|
@ -52,6 +52,10 @@ public class AboutPages {
|
|||||||
return url.startsWith(READER);
|
return url.startsWith(READER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static final boolean isAboutPrivateBrowsing(final String url) {
|
||||||
|
return PRIVATEBROWSING.equals(url);
|
||||||
|
}
|
||||||
|
|
||||||
private static final String[] DEFAULT_ICON_PAGES = new String[] {
|
private static final String[] DEFAULT_ICON_PAGES = new String[] {
|
||||||
HOME,
|
HOME,
|
||||||
|
|
||||||
|
@ -34,6 +34,7 @@ import org.mozilla.gecko.util.Clipboard;
|
|||||||
import org.mozilla.gecko.util.EventDispatcher;
|
import org.mozilla.gecko.util.EventDispatcher;
|
||||||
import org.mozilla.gecko.util.GamepadUtils;
|
import org.mozilla.gecko.util.GamepadUtils;
|
||||||
import org.mozilla.gecko.util.HardwareUtils;
|
import org.mozilla.gecko.util.HardwareUtils;
|
||||||
|
import org.mozilla.gecko.util.MenuUtils;
|
||||||
import org.mozilla.gecko.util.StringUtils;
|
import org.mozilla.gecko.util.StringUtils;
|
||||||
import org.mozilla.gecko.util.ThreadUtils;
|
import org.mozilla.gecko.util.ThreadUtils;
|
||||||
import org.mozilla.gecko.util.UiAsyncTask;
|
import org.mozilla.gecko.util.UiAsyncTask;
|
||||||
@ -2132,6 +2133,15 @@ abstract public class BrowserApp extends GeckoApp
|
|||||||
share.setEnabled(false);
|
share.setEnabled(false);
|
||||||
saveAsPDF.setEnabled(false);
|
saveAsPDF.setEnabled(false);
|
||||||
findInPage.setEnabled(false);
|
findInPage.setEnabled(false);
|
||||||
|
|
||||||
|
// NOTE: Use MenuUtils.safeSetEnabled because some actions might
|
||||||
|
// be on the BrowserToolbar context menu
|
||||||
|
MenuUtils.safeSetEnabled(aMenu, R.id.page, false);
|
||||||
|
MenuUtils.safeSetEnabled(aMenu, R.id.subscribe, false);
|
||||||
|
MenuUtils.safeSetEnabled(aMenu, R.id.add_search_engine, false);
|
||||||
|
MenuUtils.safeSetEnabled(aMenu, R.id.site_settings, false);
|
||||||
|
MenuUtils.safeSetEnabled(aMenu, R.id.add_to_launcher, false);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2159,6 +2169,14 @@ abstract public class BrowserApp extends GeckoApp
|
|||||||
share.setEnabled(!(scheme.equals("about") || scheme.equals("chrome") ||
|
share.setEnabled(!(scheme.equals("about") || scheme.equals("chrome") ||
|
||||||
scheme.equals("file") || scheme.equals("resource")));
|
scheme.equals("file") || scheme.equals("resource")));
|
||||||
|
|
||||||
|
// NOTE: Use MenuUtils.safeSetEnabled because some actions might
|
||||||
|
// be on the BrowserToolbar context menu
|
||||||
|
MenuUtils.safeSetEnabled(aMenu, R.id.page, !isAboutHome(tab));
|
||||||
|
MenuUtils.safeSetEnabled(aMenu, R.id.subscribe, tab.hasFeeds());
|
||||||
|
MenuUtils.safeSetEnabled(aMenu, R.id.add_search_engine, tab.hasOpenSearch());
|
||||||
|
MenuUtils.safeSetEnabled(aMenu, R.id.site_settings, !isAboutHome(tab));
|
||||||
|
MenuUtils.safeSetEnabled(aMenu, R.id.add_to_launcher, !isAboutHome(tab));
|
||||||
|
|
||||||
// Action providers are available only ICS+.
|
// Action providers are available only ICS+.
|
||||||
if (Build.VERSION.SDK_INT >= 14) {
|
if (Build.VERSION.SDK_INT >= 14) {
|
||||||
GeckoActionProvider provider = (GeckoActionProvider) share.getActionProvider();
|
GeckoActionProvider provider = (GeckoActionProvider) share.getActionProvider();
|
||||||
@ -2355,6 +2373,13 @@ abstract public class BrowserApp extends GeckoApp
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We have a few menu items that can also be in the context menu. If
|
||||||
|
// we have not already handled the item, give the context menu handler
|
||||||
|
// a chance.
|
||||||
|
if (onContextItemSelected(item)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -648,7 +648,8 @@ public class Tab {
|
|||||||
|
|
||||||
private static boolean shouldShowProgress(final String url) {
|
private static boolean shouldShowProgress(final String url) {
|
||||||
return AboutPages.isAboutHome(url) ||
|
return AboutPages.isAboutHome(url) ||
|
||||||
AboutPages.isAboutReader(url);
|
AboutPages.isAboutReader(url) ||
|
||||||
|
AboutPages.isAboutPrivateBrowsing(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleDocumentStart(boolean showProgress, String url) {
|
void handleDocumentStart(boolean showProgress, String url) {
|
||||||
|
@ -43,9 +43,9 @@ public class PanelListRow extends TwoLineRow {
|
|||||||
final String title = cursor.getString(titleIndex);
|
final String title = cursor.getString(titleIndex);
|
||||||
setTitle(title);
|
setTitle(title);
|
||||||
|
|
||||||
int urlIndex = cursor.getColumnIndexOrThrow(HomeItems.URL);
|
int descriptionIndex = cursor.getColumnIndexOrThrow(HomeItems.DESCRIPTION);
|
||||||
final String url = cursor.getString(urlIndex);
|
final String description = cursor.getString(descriptionIndex);
|
||||||
setDescription(url);
|
setDescription(description);
|
||||||
|
|
||||||
int imageIndex = cursor.getColumnIndexOrThrow(HomeItems.IMAGE_URL);
|
int imageIndex = cursor.getColumnIndexOrThrow(HomeItems.IMAGE_URL);
|
||||||
final String imageUrl = cursor.getString(imageIndex);
|
final String imageUrl = cursor.getString(imageIndex);
|
||||||
|
@ -210,6 +210,7 @@ size. -->
|
|||||||
<!ENTITY save_as_pdf "Save as PDF">
|
<!ENTITY save_as_pdf "Save as PDF">
|
||||||
<!ENTITY find_in_page "Find in Page">
|
<!ENTITY find_in_page "Find in Page">
|
||||||
<!ENTITY desktop_mode "Request Desktop Site">
|
<!ENTITY desktop_mode "Request Desktop Site">
|
||||||
|
<!ENTITY page "Page">
|
||||||
<!ENTITY tools "Tools">
|
<!ENTITY tools "Tools">
|
||||||
<!ENTITY new_tab "New Tab">
|
<!ENTITY new_tab "New Tab">
|
||||||
<!ENTITY new_private_tab "New Private Tab">
|
<!ENTITY new_private_tab "New Private Tab">
|
||||||
|
@ -52,6 +52,7 @@ gujar.sources += [
|
|||||||
'util/INIParser.java',
|
'util/INIParser.java',
|
||||||
'util/INISection.java',
|
'util/INISection.java',
|
||||||
'util/JSONUtils.java',
|
'util/JSONUtils.java',
|
||||||
|
'util/MenuUtils.java',
|
||||||
'util/NonEvictingLruCache.java',
|
'util/NonEvictingLruCache.java',
|
||||||
'util/ProxySelector.java',
|
'util/ProxySelector.java',
|
||||||
'util/StringUtils.java',
|
'util/StringUtils.java',
|
||||||
|
@ -47,6 +47,28 @@
|
|||||||
android:title="@string/desktop_mode"
|
android:title="@string/desktop_mode"
|
||||||
android:checkable="true" />
|
android:checkable="true" />
|
||||||
|
|
||||||
|
<item android:id="@+id/page"
|
||||||
|
android:title="@string/page"
|
||||||
|
android:icon="@drawable/ic_menu_tools">
|
||||||
|
|
||||||
|
<menu>
|
||||||
|
|
||||||
|
<item android:id="@+id/subscribe"
|
||||||
|
android:title="@string/contextmenu_subscribe"/>
|
||||||
|
|
||||||
|
<item android:id="@+id/add_search_engine"
|
||||||
|
android:title="@string/contextmenu_add_search_engine"/>
|
||||||
|
|
||||||
|
<item android:id="@+id/site_settings"
|
||||||
|
android:title="@string/contextmenu_site_settings" />
|
||||||
|
|
||||||
|
<item android:id="@+id/add_to_launcher"
|
||||||
|
android:title="@string/contextmenu_add_to_launcher"/>
|
||||||
|
|
||||||
|
</menu>
|
||||||
|
|
||||||
|
</item>
|
||||||
|
|
||||||
<item android:id="@+id/tools"
|
<item android:id="@+id/tools"
|
||||||
android:title="@string/tools"
|
android:title="@string/tools"
|
||||||
android:icon="@drawable/ic_menu_tools">
|
android:icon="@drawable/ic_menu_tools">
|
||||||
|
@ -47,6 +47,28 @@
|
|||||||
android:title="@string/desktop_mode"
|
android:title="@string/desktop_mode"
|
||||||
android:checkable="true" />
|
android:checkable="true" />
|
||||||
|
|
||||||
|
<item android:id="@+id/page"
|
||||||
|
android:title="@string/page"
|
||||||
|
android:icon="@drawable/ic_menu_tools">
|
||||||
|
|
||||||
|
<menu>
|
||||||
|
|
||||||
|
<item android:id="@+id/subscribe"
|
||||||
|
android:title="@string/contextmenu_subscribe"/>
|
||||||
|
|
||||||
|
<item android:id="@+id/add_search_engine"
|
||||||
|
android:title="@string/contextmenu_add_search_engine"/>
|
||||||
|
|
||||||
|
<item android:id="@+id/site_settings"
|
||||||
|
android:title="@string/contextmenu_site_settings" />
|
||||||
|
|
||||||
|
<item android:id="@+id/add_to_launcher"
|
||||||
|
android:title="@string/contextmenu_add_to_launcher"/>
|
||||||
|
|
||||||
|
</menu>
|
||||||
|
|
||||||
|
</item>
|
||||||
|
|
||||||
<item android:id="@+id/tools"
|
<item android:id="@+id/tools"
|
||||||
android:title="@string/tools"
|
android:title="@string/tools"
|
||||||
android:icon="@drawable/ic_menu_tools">
|
android:icon="@drawable/ic_menu_tools">
|
||||||
|
@ -0,0 +1,20 @@
|
|||||||
|
<?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/. -->
|
||||||
|
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<item android:id="@+id/pasteandgo"
|
||||||
|
android:title="@string/contextmenu_pasteandgo"/>
|
||||||
|
|
||||||
|
<item android:id="@+id/paste"
|
||||||
|
android:title="@string/contextmenu_paste"/>
|
||||||
|
|
||||||
|
<item android:id="@+id/copyurl"
|
||||||
|
android:title="@string/contextmenu_copyurl"/>
|
||||||
|
|
||||||
|
<item android:id="@+id/add_to_launcher"
|
||||||
|
android:title="@string/contextmenu_add_to_launcher"/>
|
||||||
|
|
||||||
|
</menu>
|
@ -47,6 +47,29 @@
|
|||||||
android:title="@string/desktop_mode"
|
android:title="@string/desktop_mode"
|
||||||
android:checkable="true" />
|
android:checkable="true" />
|
||||||
|
|
||||||
|
|
||||||
|
<item android:id="@+id/page"
|
||||||
|
android:title="@string/page"
|
||||||
|
android:icon="@drawable/ic_menu_tools">
|
||||||
|
|
||||||
|
<menu>
|
||||||
|
|
||||||
|
<item android:id="@+id/subscribe"
|
||||||
|
android:title="@string/contextmenu_subscribe"/>
|
||||||
|
|
||||||
|
<item android:id="@+id/add_search_engine"
|
||||||
|
android:title="@string/contextmenu_add_search_engine"/>
|
||||||
|
|
||||||
|
<item android:id="@+id/site_settings"
|
||||||
|
android:title="@string/contextmenu_site_settings" />
|
||||||
|
|
||||||
|
<item android:id="@+id/add_to_launcher"
|
||||||
|
android:title="@string/contextmenu_add_to_launcher"/>
|
||||||
|
|
||||||
|
</menu>
|
||||||
|
|
||||||
|
</item>
|
||||||
|
|
||||||
<item android:id="@+id/tools"
|
<item android:id="@+id/tools"
|
||||||
android:title="@string/tools"
|
android:title="@string/tools"
|
||||||
android:icon="@drawable/ic_menu_tools">
|
android:icon="@drawable/ic_menu_tools">
|
||||||
|
@ -77,6 +77,7 @@
|
|||||||
<string name="save_as_pdf">&save_as_pdf;</string>
|
<string name="save_as_pdf">&save_as_pdf;</string>
|
||||||
<string name="find_in_page">&find_in_page;</string>
|
<string name="find_in_page">&find_in_page;</string>
|
||||||
<string name="desktop_mode">&desktop_mode;</string>
|
<string name="desktop_mode">&desktop_mode;</string>
|
||||||
|
<string name="page">&page;</string>
|
||||||
<string name="tools">&tools;</string>
|
<string name="tools">&tools;</string>
|
||||||
|
|
||||||
<string name="find_text">&find_text;</string>
|
<string name="find_text">&find_text;</string>
|
||||||
|
@ -166,6 +166,7 @@ public class StringHelper {
|
|||||||
|
|
||||||
// Android 3.0+
|
// Android 3.0+
|
||||||
public static final String TOOLS_LABEL = "Tools";
|
public static final String TOOLS_LABEL = "Tools";
|
||||||
|
public static final String PAGE_LABEL = "Page";
|
||||||
|
|
||||||
// Android 2.3 and lower only
|
// Android 2.3 and lower only
|
||||||
public static final String MORE_LABEL = "More";
|
public static final String MORE_LABEL = "More";
|
||||||
|
@ -107,9 +107,16 @@ public class testClearPrivateData extends PixelTest {
|
|||||||
|
|
||||||
//Verify if there are settings to be clear if so clear them from the URL bar context menu
|
//Verify if there are settings to be clear if so clear them from the URL bar context menu
|
||||||
public void checkOption(String option, String button) {
|
public void checkOption(String option, String button) {
|
||||||
final View toolbarView = mSolo.getView("browser_toolbar");
|
if (mDevice.version.equals("2.x")) {
|
||||||
mSolo.clickLongOnView(toolbarView);
|
// Use the context menu in pre-11
|
||||||
mAsserter.ok(waitForText(StringHelper.CONTEXT_MENU_ITEMS_IN_URL_BAR[2]), "Waiting for the pop-up to open", "Pop up was openend");
|
final View toolbarView = mSolo.getView("browser_toolbar");
|
||||||
|
mSolo.clickLongOnView(toolbarView);
|
||||||
|
mAsserter.ok(waitForText(StringHelper.CONTEXT_MENU_ITEMS_IN_URL_BAR[2]), "Waiting for the pop-up to open", "Pop up was opened");
|
||||||
|
} else {
|
||||||
|
// Use the Page menu in 11+
|
||||||
|
selectMenuItem(StringHelper.PAGE_LABEL);
|
||||||
|
mAsserter.ok(waitForText(StringHelper.CONTEXT_MENU_ITEMS_IN_URL_BAR[2]), "Waiting for the submenu to open", "Submenu was opened");
|
||||||
|
}
|
||||||
mSolo.clickOnText(StringHelper.CONTEXT_MENU_ITEMS_IN_URL_BAR[2]);
|
mSolo.clickOnText(StringHelper.CONTEXT_MENU_ITEMS_IN_URL_BAR[2]);
|
||||||
mAsserter.ok(waitForText(option), "Verify that the option: " + option + " is in the list", "The option is in the list. There are settings to clear");
|
mAsserter.ok(waitForText(option), "Verify that the option: " + option + " is in the list", "The option is in the list. There are settings to clear");
|
||||||
mSolo.clickOnButton(button);
|
mSolo.clickOnButton(button);
|
||||||
|
@ -24,6 +24,7 @@ import org.mozilla.gecko.toolbar.ToolbarDisplayLayout.OnTitleChangeListener;
|
|||||||
import org.mozilla.gecko.toolbar.ToolbarDisplayLayout.UpdateFlags;
|
import org.mozilla.gecko.toolbar.ToolbarDisplayLayout.UpdateFlags;
|
||||||
import org.mozilla.gecko.util.Clipboard;
|
import org.mozilla.gecko.util.Clipboard;
|
||||||
import org.mozilla.gecko.util.HardwareUtils;
|
import org.mozilla.gecko.util.HardwareUtils;
|
||||||
|
import org.mozilla.gecko.util.MenuUtils;
|
||||||
import org.mozilla.gecko.util.ThreadUtils;
|
import org.mozilla.gecko.util.ThreadUtils;
|
||||||
import org.mozilla.gecko.util.GeckoEventListener;
|
import org.mozilla.gecko.util.GeckoEventListener;
|
||||||
import org.mozilla.gecko.widget.GeckoImageButton;
|
import org.mozilla.gecko.widget.GeckoImageButton;
|
||||||
@ -249,6 +250,9 @@ public class BrowserToolbar extends GeckoRelativeLayout
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: Use MenuUtils.safeSetVisible because some actions might
|
||||||
|
// be on the Page menu
|
||||||
|
|
||||||
MenuInflater inflater = mActivity.getMenuInflater();
|
MenuInflater inflater = mActivity.getMenuInflater();
|
||||||
inflater.inflate(R.menu.titlebar_contextmenu, menu);
|
inflater.inflate(R.menu.titlebar_contextmenu, menu);
|
||||||
|
|
||||||
@ -263,22 +267,22 @@ public class BrowserToolbar extends GeckoRelativeLayout
|
|||||||
String url = tab.getURL();
|
String url = tab.getURL();
|
||||||
if (url == null) {
|
if (url == null) {
|
||||||
menu.findItem(R.id.copyurl).setVisible(false);
|
menu.findItem(R.id.copyurl).setVisible(false);
|
||||||
menu.findItem(R.id.share).setVisible(false);
|
|
||||||
menu.findItem(R.id.add_to_launcher).setVisible(false);
|
menu.findItem(R.id.add_to_launcher).setVisible(false);
|
||||||
|
MenuUtils.safeSetVisible(menu, R.id.share, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
menu.findItem(R.id.subscribe).setVisible(tab.hasFeeds());
|
MenuUtils.safeSetVisible(menu, R.id.subscribe, tab.hasFeeds());
|
||||||
menu.findItem(R.id.add_search_engine).setVisible(tab.hasOpenSearch());
|
MenuUtils.safeSetVisible(menu, R.id.add_search_engine, tab.hasOpenSearch());
|
||||||
} else {
|
} else {
|
||||||
// if there is no tab, remove anything tab dependent
|
// if there is no tab, remove anything tab dependent
|
||||||
menu.findItem(R.id.copyurl).setVisible(false);
|
menu.findItem(R.id.copyurl).setVisible(false);
|
||||||
menu.findItem(R.id.share).setVisible(false);
|
|
||||||
menu.findItem(R.id.add_to_launcher).setVisible(false);
|
menu.findItem(R.id.add_to_launcher).setVisible(false);
|
||||||
menu.findItem(R.id.subscribe).setVisible(false);
|
MenuUtils.safeSetVisible(menu, R.id.share, false);
|
||||||
menu.findItem(R.id.add_search_engine).setVisible(false);
|
MenuUtils.safeSetVisible(menu, R.id.subscribe, false);
|
||||||
|
MenuUtils.safeSetVisible(menu, R.id.add_search_engine, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
menu.findItem(R.id.share).setVisible(!GeckoProfile.get(getContext()).inGuestMode());
|
MenuUtils.safeSetVisible(menu, R.id.share, !GeckoProfile.get(getContext()).inGuestMode());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -79,7 +79,8 @@ public class SiteIdentityPopup extends ArrowPopup {
|
|||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mSiteIdentity.getSecurityMode() == SecurityMode.MIXED_CONTENT_LOADED) {
|
if (mSiteIdentity.getSecurityMode() == SecurityMode.MIXED_CONTENT_LOADED ||
|
||||||
|
mSiteIdentity.getSecurityMode() == SecurityMode.MIXED_CONTENT_BLOCKED) {
|
||||||
// Hide the identity data if there isn't valid site identity data.
|
// Hide the identity data if there isn't valid site identity data.
|
||||||
// Set some top padding on the popup content to create a of light blue
|
// Set some top padding on the popup content to create a of light blue
|
||||||
// between the popup arrow and the mixed content notification.
|
// between the popup arrow and the mixed content notification.
|
||||||
|
@ -150,11 +150,8 @@ public class ToolbarDisplayLayout extends GeckoLinearLayout
|
|||||||
mPrivateDomainColor = new ForegroundColorSpan(res.getColor(R.color.url_bar_domaintext_private));
|
mPrivateDomainColor = new ForegroundColorSpan(res.getColor(R.color.url_bar_domaintext_private));
|
||||||
|
|
||||||
mFavicon = (ImageButton) findViewById(R.id.favicon);
|
mFavicon = (ImageButton) findViewById(R.id.favicon);
|
||||||
if (Build.VERSION.SDK_INT >= 11) {
|
if (Build.VERSION.SDK_INT >= 16) {
|
||||||
if (Build.VERSION.SDK_INT >= 16) {
|
mFavicon.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
|
||||||
mFavicon.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
|
|
||||||
}
|
|
||||||
mFavicon.setLayerType(View.LAYER_TYPE_HARDWARE, null);
|
|
||||||
}
|
}
|
||||||
mFaviconSize = Math.round(res.getDimension(R.dimen.browser_toolbar_favicon_size));
|
mFaviconSize = Math.round(res.getDimension(R.dimen.browser_toolbar_favicon_size));
|
||||||
|
|
||||||
|
33
mobile/android/base/util/MenuUtils.java
Normal file
33
mobile/android/base/util/MenuUtils.java
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||||
|
* 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/. */
|
||||||
|
|
||||||
|
package org.mozilla.gecko.util;
|
||||||
|
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
|
||||||
|
public class MenuUtils {
|
||||||
|
/*
|
||||||
|
* This method looks for a menuitem and sets it's visible state, if
|
||||||
|
* it exists.
|
||||||
|
*/
|
||||||
|
public static void safeSetVisible(Menu menu, int id, boolean visible) {
|
||||||
|
MenuItem item = menu.findItem(id);
|
||||||
|
if (item != null) {
|
||||||
|
item.setVisible(visible);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This method looks for a menuitem and sets it's enabled state, if
|
||||||
|
* it exists.
|
||||||
|
*/
|
||||||
|
public static void safeSetEnabled(Menu menu, int id, boolean enabled) {
|
||||||
|
MenuItem item = menu.findItem(id);
|
||||||
|
if (item != null) {
|
||||||
|
item.setEnabled(enabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -240,7 +240,9 @@ function resolveGeckoURI(aURI) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function shouldShowProgress(url) {
|
function shouldShowProgress(url) {
|
||||||
return (url != "about:home" && !url.startsWith("about:reader"));
|
return (url != "about:home" &&
|
||||||
|
url != "about:privatebrowsing" &&
|
||||||
|
!url.startsWith("about:reader"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -275,7 +275,7 @@
|
|||||||
<h1 id="et_dnsNotFound">&dnsNotFound.title;</h1>
|
<h1 id="et_dnsNotFound">&dnsNotFound.title;</h1>
|
||||||
<h1 id="et_fileNotFound">&fileNotFound.title;</h1>
|
<h1 id="et_fileNotFound">&fileNotFound.title;</h1>
|
||||||
<h1 id="et_malformedURI">&malformedURI.title;</h1>
|
<h1 id="et_malformedURI">&malformedURI.title;</h1>
|
||||||
<h1 id="et_protocolNotFound">&protocolNotFound.title;</h1>
|
<h1 id="et_unknownProtocolFound">&unknownProtocolFound.title;</h1>
|
||||||
<h1 id="et_connectionFailure">&connectionFailure.title;</h1>
|
<h1 id="et_connectionFailure">&connectionFailure.title;</h1>
|
||||||
<h1 id="et_netTimeout">&netTimeout.title;</h1>
|
<h1 id="et_netTimeout">&netTimeout.title;</h1>
|
||||||
<h1 id="et_redirectLoop">&redirectLoop.title;</h1>
|
<h1 id="et_redirectLoop">&redirectLoop.title;</h1>
|
||||||
@ -304,7 +304,7 @@
|
|||||||
<div id="ed_dnsNotFound">&dnsNotFound.longDesc2;</div>
|
<div id="ed_dnsNotFound">&dnsNotFound.longDesc2;</div>
|
||||||
<div id="ed_fileNotFound">&fileNotFound.longDesc;</div>
|
<div id="ed_fileNotFound">&fileNotFound.longDesc;</div>
|
||||||
<div id="ed_malformedURI">&malformedURI.longDesc;</div>
|
<div id="ed_malformedURI">&malformedURI.longDesc;</div>
|
||||||
<div id="ed_protocolNotFound">&protocolNotFound.longDesc;</div>
|
<div id="ed_unknownProtocolFound">&unknownProtocolFound.longDesc;</div>
|
||||||
<div id="ed_connectionFailure">&connectionFailure.longDesc;</div>
|
<div id="ed_connectionFailure">&connectionFailure.longDesc;</div>
|
||||||
<div id="ed_netTimeout">&netTimeout.longDesc;</div>
|
<div id="ed_netTimeout">&netTimeout.longDesc;</div>
|
||||||
<div id="ed_redirectLoop">&redirectLoop.longDesc;</div>
|
<div id="ed_redirectLoop">&redirectLoop.longDesc;</div>
|
||||||
|
@ -178,7 +178,8 @@ function updateBanner(response) {
|
|||||||
text: message.text,
|
text: message.text,
|
||||||
icon: message.icon,
|
icon: message.icon,
|
||||||
onclick: function() {
|
onclick: function() {
|
||||||
gChromeWin.BrowserApp.addTab(message.url);
|
let parentId = gChromeWin.BrowserApp.selectedTab.id;
|
||||||
|
gChromeWin.BrowserApp.addTab(message.url, { parentId: parentId });
|
||||||
},
|
},
|
||||||
onshown: function() {
|
onshown: function() {
|
||||||
// 10% of the time, record the snippet id and a timestamp
|
// 10% of the time, record the snippet id and a timestamp
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
malformedURI=The URL is not valid and cannot be loaded.
|
malformedURI=The URL is not valid and cannot be loaded.
|
||||||
fileNotFound=Firefox can't find the file at %S.
|
fileNotFound=Firefox can't find the file at %S.
|
||||||
dnsNotFound=Firefox can't find the server at %S.
|
dnsNotFound=Firefox can't find the server at %S.
|
||||||
protocolNotFound=Firefox doesn't know how to open this address, because the protocol (%S) isn't associated with any program.
|
unknownProtocolFound=Firefox doesn't know how to open this address, because one of the following protocols (%S) isn't associated with any program or is not allowed in this context.
|
||||||
connectionFailure=Firefox can't establish a connection to the server at %S.
|
connectionFailure=Firefox can't establish a connection to the server at %S.
|
||||||
netInterrupt=The connection to %S was interrupted while the page was loading.
|
netInterrupt=The connection to %S was interrupted while the page was loading.
|
||||||
netTimeout=The server at %S is taking too long to respond.
|
netTimeout=The server at %S is taking too long to respond.
|
||||||
|
@ -83,8 +83,8 @@
|
|||||||
<!ENTITY netTimeout.title "The connection has timed out">
|
<!ENTITY netTimeout.title "The connection has timed out">
|
||||||
<!ENTITY netTimeout.longDesc "&sharedLongDesc2;">
|
<!ENTITY netTimeout.longDesc "&sharedLongDesc2;">
|
||||||
|
|
||||||
<!ENTITY protocolNotFound.title "The address wasn't understood">
|
<!ENTITY unknownProtocolFound.title "The address wasn't understood">
|
||||||
<!ENTITY protocolNotFound.longDesc "
|
<!ENTITY unknownProtocolFound.longDesc "
|
||||||
<ul>
|
<ul>
|
||||||
<li>You might need to install other software to open this address.</li>
|
<li>You might need to install other software to open this address.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user