зеркало из https://github.com/mozilla/gecko-dev.git
Merge the last PGO-green inbound changeset to m-c.
This commit is contained in:
Коммит
7d0be33071
|
@ -83,6 +83,8 @@ const kDiscBulletText = String.fromCharCode(0x2022) + " ";
|
|||
const kCircleBulletText = String.fromCharCode(0x25e6) + " ";
|
||||
const kSquareBulletText = String.fromCharCode(0x25aa) + " ";
|
||||
|
||||
const MAX_TRIM_LENGTH = 100;
|
||||
|
||||
/**
|
||||
* nsIAccessibleRetrieval service.
|
||||
*/
|
||||
|
@ -607,7 +609,7 @@ function prettyName(aIdentifier)
|
|||
try {
|
||||
msg += ", role: " + roleToString(acc.role);
|
||||
if (acc.name)
|
||||
msg += ", name: '" + acc.name + "'";
|
||||
msg += ", name: '" + shortenString(acc.name) + "'";
|
||||
} catch (e) {
|
||||
msg += "defunct";
|
||||
}
|
||||
|
@ -625,6 +627,21 @@ function prettyName(aIdentifier)
|
|||
return " '" + aIdentifier + "' ";
|
||||
}
|
||||
|
||||
/**
|
||||
* Shorten a long string if it exceeds MAX_TRIM_LENGTH.
|
||||
* @param aString the string to shorten.
|
||||
* @returns the shortened string.
|
||||
*/
|
||||
function shortenString(aString, aMaxLength)
|
||||
{
|
||||
if (aString.length <= MAX_TRIM_LENGTH)
|
||||
return aString;
|
||||
|
||||
// Trim the string if its length is > MAX_TRIM_LENGTH characters.
|
||||
var trimOffset = MAX_TRIM_LENGTH / 2;
|
||||
return aString.substring(0, trimOffset - 1) + "..." +
|
||||
aString.substring(aString.length - trimOffset, aString.length);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Private
|
||||
|
|
|
@ -56,8 +56,9 @@
|
|||
|
||||
this.getID = function changeText_getID()
|
||||
{
|
||||
return "change text '" + this.textData + "' -> " + this.textNode.data +
|
||||
"for " + prettyName(this.containerNode);
|
||||
return "change text '" + shortenString(this.textData) + "' -> '" +
|
||||
shortenString(this.textNode.data) + "' for " +
|
||||
prettyName(this.containerNode);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@ Cu.import('resource://gre/modules/DOMFMRadioParent.jsm');
|
|||
Cu.import('resource://gre/modules/AlarmService.jsm');
|
||||
Cu.import('resource://gre/modules/ActivitiesService.jsm');
|
||||
Cu.import('resource://gre/modules/PermissionPromptHelper.jsm');
|
||||
Cu.import('resource://gre/modules/PermissionSettings.jsm');
|
||||
Cu.import('resource://gre/modules/ObjectWrapper.jsm');
|
||||
Cu.import('resource://gre/modules/accessibility/AccessFu.jsm');
|
||||
Cu.import('resource://gre/modules/Payment.jsm');
|
||||
|
|
|
@ -44,8 +44,53 @@ XPCOMUtils.defineLazyServiceGetter(Services, "settings",
|
|||
"@mozilla.org/settingsService;1",
|
||||
"nsISettingsService");
|
||||
|
||||
function UpdateCheckListener(updatePrompt) {
|
||||
this._updatePrompt = updatePrompt;
|
||||
}
|
||||
|
||||
UpdateCheckListener.prototype = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIUpdateCheckListener]),
|
||||
|
||||
_updatePrompt: null,
|
||||
|
||||
onCheckComplete: function UCL_onCheckComplete(request, updates, updateCount) {
|
||||
if (Services.um.activeUpdate) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (updateCount == 0) {
|
||||
this._updatePrompt.setUpdateStatus("no-updates");
|
||||
return;
|
||||
}
|
||||
|
||||
let update = Services.aus.selectUpdate(updates, updateCount);
|
||||
if (!update) {
|
||||
this._updatePrompt.setUpdateStatus("already-latest-version");
|
||||
return;
|
||||
}
|
||||
|
||||
this._updatePrompt.setUpdateStatus("check-complete");
|
||||
this._updatePrompt.showUpdateAvailable(update);
|
||||
},
|
||||
|
||||
onError: function UCL_onError(request, update) {
|
||||
if (update.errorCode == NETWORK_ERROR_OFFLINE) {
|
||||
this._updatePrompt.setUpdateStatus("retry-when-online");
|
||||
}
|
||||
|
||||
Services.aus.QueryInterface(Ci.nsIUpdateCheckListener);
|
||||
Services.aus.onError(request, update);
|
||||
},
|
||||
|
||||
onProgress: function UCL_onProgress(request, position, totalSize) {
|
||||
Services.aus.QueryInterface(Ci.nsIUpdateCheckListener);
|
||||
Services.aus.onProgress(request, position, totalSize);
|
||||
}
|
||||
};
|
||||
|
||||
function UpdatePrompt() {
|
||||
this.wrappedJSObject = this;
|
||||
this._updateCheckListener = new UpdateCheckListener(this);
|
||||
}
|
||||
|
||||
UpdatePrompt.prototype = {
|
||||
|
@ -60,6 +105,7 @@ UpdatePrompt.prototype = {
|
|||
_update: null,
|
||||
_applyPromptTimer: null,
|
||||
_waitingForIdle: false,
|
||||
_updateCheckListner: null,
|
||||
|
||||
// nsIUpdatePrompt
|
||||
|
||||
|
@ -107,42 +153,6 @@ UpdatePrompt.prototype = {
|
|||
showUpdateHistory: function UP_showUpdateHistory(aParent) { },
|
||||
showUpdateInstalled: function UP_showUpdateInstalled() { },
|
||||
|
||||
// nsIUpdateCheckListener
|
||||
|
||||
onCheckComplete: function UP_onCheckComplete(request, updates, updateCount) {
|
||||
if (Services.um.activeUpdate) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (updateCount == 0) {
|
||||
this.setUpdateStatus("no-updates");
|
||||
return;
|
||||
}
|
||||
|
||||
let update = Services.aus.selectUpdate(updates, updateCount);
|
||||
if (!update) {
|
||||
this.setUpdateStatus("already-latest-version");
|
||||
return;
|
||||
}
|
||||
|
||||
this.setUpdateStatus("check-complete");
|
||||
this.showUpdateAvailable(update);
|
||||
},
|
||||
|
||||
onError: function UP_onError(request, update) {
|
||||
if (update.errorCode == NETWORK_ERROR_OFFLINE) {
|
||||
this.setUpdateStatus("retry-when-online");
|
||||
}
|
||||
|
||||
Services.aus.QueryInterface(Ci.nsIUpdateCheckListener);
|
||||
Services.aus.onError(request, update);
|
||||
},
|
||||
|
||||
onProgress: function UP_onProgress(request, position, totalSize) {
|
||||
Services.aus.QueryInterface(Ci.nsIUpdateCheckListener);
|
||||
Services.aus.onProgress(request, position, totalSize);
|
||||
},
|
||||
|
||||
// Custom functions
|
||||
|
||||
waitForIdle: function UP_waitForIdle() {
|
||||
|
@ -320,7 +330,7 @@ UpdatePrompt.prototype = {
|
|||
|
||||
let checker = Cc["@mozilla.org/updates/update-checker;1"]
|
||||
.createInstance(Ci.nsIUpdateChecker);
|
||||
checker.checkForUpdates(this, true);
|
||||
checker.checkForUpdates(this._updateCheckListener, true);
|
||||
},
|
||||
|
||||
handleEvent: function UP_handleEvent(evt) {
|
||||
|
|
|
@ -482,9 +482,7 @@
|
|||
accesskey="&toolsMenu.accesskey;">
|
||||
<menupopup id="menu_ToolsPopup"
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
onpopupshowing="gSyncUI.updateUI(); SocialMenu.populate();"
|
||||
#else
|
||||
onpopupshowing="SocialMenu.populate();"
|
||||
onpopupshowing="gSyncUI.updateUI();"
|
||||
#endif
|
||||
>
|
||||
<menuitem id="menu_search"
|
||||
|
@ -510,9 +508,23 @@
|
|||
autocheck="false"
|
||||
command="Social:Toggle"/>
|
||||
<menu id="menu_socialAmbientMenu"
|
||||
class="show-only-for-keyboard"
|
||||
command="Social:Toggle">
|
||||
<menupopup id="menu_socialAmbientMenuPopup"/>
|
||||
class="show-only-for-keyboard">
|
||||
<menupopup id="menu_socialAmbientMenuPopup">
|
||||
<menuseparator id="socialAmbientMenuSeparator"
|
||||
hidden="true"/>
|
||||
<menuitem id="social-toggle-sidebar-keyboardmenuitem"
|
||||
type="checkbox"
|
||||
autocheck="false"
|
||||
command="Social:ToggleSidebar"
|
||||
label="&social.toggleSidebar.label;"
|
||||
accesskey="&social.toggleSidebar.accesskey;"/>
|
||||
<menuitem id="social-toggle-notifications-keyboardmenuitem"
|
||||
type="checkbox"
|
||||
autocheck="false"
|
||||
command="Social:ToggleNotifications"
|
||||
label="&social.toggleNotifications.label;"
|
||||
accesskey="&social.toggleNotifications.accesskey;"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
<!-- only one of sync-setup or sync-menu will be showing at once -->
|
||||
|
|
|
@ -62,7 +62,7 @@ let SocialUI = {
|
|||
break;
|
||||
case "social:ambient-notification-changed":
|
||||
SocialToolbar.updateButton();
|
||||
SocialMenu.updateMenu();
|
||||
SocialMenu.populate();
|
||||
break;
|
||||
case "social:profile-changed":
|
||||
SocialToolbar.updateProfile();
|
||||
|
@ -72,6 +72,8 @@ let SocialUI = {
|
|||
case "nsPref:changed":
|
||||
SocialSidebar.updateSidebar();
|
||||
SocialToolbar.updateButton();
|
||||
SocialMenu.populate();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -99,25 +101,14 @@ let SocialUI = {
|
|||
SocialToolbar.init();
|
||||
SocialShareButton.init();
|
||||
SocialSidebar.init();
|
||||
SocialMenu.populate();
|
||||
},
|
||||
|
||||
updateToggleCommand: function SocialUI_updateToggleCommand() {
|
||||
let toggleCommand = this.toggleCommand;
|
||||
// We only need to update the command itself - all our menu items use it.
|
||||
toggleCommand.setAttribute("checked", Services.prefs.getBoolPref("social.enabled"));
|
||||
|
||||
// FIXME: bug 772808: menu items don't inherit the "hidden" state properly,
|
||||
// need to update them manually.
|
||||
// This should just be: toggleCommand.hidden = !Social.active;
|
||||
for (let id of ["appmenu_socialToggle", "menu_socialToggle", "menu_socialAmbientMenu"]) {
|
||||
let el = document.getElementById(id);
|
||||
if (!el)
|
||||
continue;
|
||||
|
||||
if (Social.active)
|
||||
el.removeAttribute("hidden");
|
||||
else
|
||||
el.setAttribute("hidden", "true");
|
||||
}
|
||||
toggleCommand.setAttribute("hidden", Social.active ? "false" : "true");
|
||||
},
|
||||
|
||||
// This handles "ActivateSocialFeature" events fired against content documents
|
||||
|
@ -610,24 +601,28 @@ var SocialMenu = {
|
|||
populate: function SocialMenu_populate() {
|
||||
// This menu is only accessible through keyboard navigation.
|
||||
let submenu = document.getElementById("menu_socialAmbientMenuPopup");
|
||||
while (submenu.hasChildNodes())
|
||||
submenu.removeChild(submenu.firstChild);
|
||||
let ambientMenuItems = submenu.getElementsByClassName("ambient-menuitem");
|
||||
for (let ambientMenuItem of ambientMenuItems)
|
||||
submenu.removeChild(ambientMenuItem);
|
||||
let provider = Social.provider;
|
||||
if (Social.active && provider) {
|
||||
let iconNames = Object.keys(provider.ambientNotificationIcons);
|
||||
let separator = document.getElementById("socialAmbientMenuSeparator");
|
||||
for (let name of iconNames) {
|
||||
let icon = provider.ambientNotificationIcons[name];
|
||||
if (!icon.label || !icon.menuURL)
|
||||
continue;
|
||||
let menuitem = document.createElement("menuitem");
|
||||
menuitem.setAttribute("label", icon.label);
|
||||
menuitem.classList.add("ambient-menuitem");
|
||||
menuitem.addEventListener("command", function() {
|
||||
openUILinkIn(icon.menuURL, "tab");
|
||||
}, false);
|
||||
submenu.appendChild(menuitem);
|
||||
submenu.insertBefore(menuitem, separator);
|
||||
}
|
||||
separator.hidden = !iconNames.length;
|
||||
}
|
||||
document.getElementById("menu_socialAmbientMenu").hidden = !submenu.querySelector("menuitem");
|
||||
document.getElementById("menu_socialAmbientMenu").hidden = !Social.enabled;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -692,11 +687,12 @@ var SocialToolbar = {
|
|||
const CACHE_PREF_NAME = "social.cached.notificationIcons";
|
||||
// provider.profile == undefined means no response yet from the provider
|
||||
// to tell us whether the user is logged in or not.
|
||||
if (!SocialUI.haveLoggedInUser() && provider.profile !== undefined) {
|
||||
// The provider has responded with a profile and the user isn't logged
|
||||
// in. The icons etc have already been removed by
|
||||
// updateButtonHiddenState, so we want to nuke any cached icons we
|
||||
// have and get out of here!
|
||||
if (!Social.provider || !Social.provider.enabled ||
|
||||
(!SocialUI.haveLoggedInUser() && provider.profile !== undefined)) {
|
||||
// Either no enabled provider, or there is a provider and it has
|
||||
// responded with a profile and the user isn't loggedin. The icons
|
||||
// etc have already been removed by updateButtonHiddenState, so we want
|
||||
// to nuke any cached icons we have and get out of here!
|
||||
Services.prefs.clearUserPref(CACHE_PREF_NAME);
|
||||
return;
|
||||
}
|
||||
|
@ -923,7 +919,7 @@ var SocialSidebar = {
|
|||
updateSidebar: function SocialSidebar_updateSidebar() {
|
||||
// Hide the toggle menu item if the sidebar cannot appear
|
||||
let command = document.getElementById("Social:ToggleSidebar");
|
||||
command.hidden = !this.canShow;
|
||||
command.setAttribute("hidden", this.canShow ? "false" : "true");
|
||||
|
||||
// Hide the sidebar if it cannot appear, or has been toggled off.
|
||||
// Also set the command "checked" state accordingly.
|
||||
|
|
|
@ -46,7 +46,8 @@ var tests = {
|
|||
toolsPopup.removeEventListener("popupshown", ontoolspopupshownNoAmbient);
|
||||
let socialToggleMore = document.getElementById("menu_socialAmbientMenu");
|
||||
ok(socialToggleMore, "Keyboard accessible social menu should exist");
|
||||
is(socialToggleMore.hidden, true, "Menu should be hidden when no ambient notifications.");
|
||||
is(socialToggleMore.querySelectorAll("menuitem").length, 2, "The minimum number of menuitems is two when there are no ambient notifications.");
|
||||
is(socialToggleMore.hidden, false, "Menu should be visible since we show some non-ambient notifications in the menu.");
|
||||
toolsPopup.hidePopup();
|
||||
next();
|
||||
}, false);
|
||||
|
@ -85,6 +86,7 @@ var tests = {
|
|||
toolsPopup.removeEventListener("popupshown", ontoolspopupshownAmbient);
|
||||
let socialToggleMore = document.getElementById("menu_socialAmbientMenu");
|
||||
ok(socialToggleMore, "Keyboard accessible social menu should exist");
|
||||
is(socialToggleMore.querySelectorAll("menuitem").length, 3, "The number of menuitems is minimum plus one ambient notification menuitem.");
|
||||
is(socialToggleMore.hidden, false, "Menu is visible when ambient notifications have label & menuURL");
|
||||
let menuitem = socialToggleMore.querySelector("menuitem");
|
||||
is(menuitem.getAttribute("label"), "Test Ambient 1", "Keyboard accessible ambient menuitem should have specified label");
|
||||
|
@ -109,11 +111,15 @@ var tests = {
|
|||
testShowSidebarMenuitemExists: function(next) {
|
||||
let toggleSidebarMenuitem = document.getElementById("social-toggle-sidebar-menuitem");
|
||||
ok(toggleSidebarMenuitem, "Toggle Sidebar menuitem exists");
|
||||
let toggleSidebarKeyboardMenuitem = document.getElementById("social-toggle-sidebar-keyboardmenuitem");
|
||||
ok(toggleSidebarKeyboardMenuitem, "Toggle Sidebar keyboard menuitem exists");
|
||||
next();
|
||||
},
|
||||
testShowDesktopNotificationsMenuitemExists: function(next) {
|
||||
let toggleDesktopNotificationsMenuitem = document.getElementById("social-toggle-notifications-menuitem");
|
||||
ok(toggleDesktopNotificationsMenuitem, "Toggle notifications menuitem exists");
|
||||
let toggleDesktopNotificationsKeyboardMenuitem = document.getElementById("social-toggle-notifications-keyboardmenuitem");
|
||||
ok(toggleDesktopNotificationsKeyboardMenuitem, "Toggle notifications keyboard menuitem exists");
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
%filter substitution
|
||||
|
||||
%define primaryToolbarButtons #back-button, #forward-button, #reload-button, #stop-button, #home-button, #print-button, #downloads-button, #history-button, #bookmarks-button, #bookmarks-menu-button, #new-tab-button, #new-window-button, #cut-button, #copy-button, #paste-button, #fullscreen-button, #zoom-out-button, #zoom-in-button, #sync-button, #feed-button, #alltabs-button, #tabview-button
|
||||
%define primaryToolbarButtons #back-button, #forward-button, #reload-button, #stop-button, #home-button, #print-button, #downloads-button, #downloads-indicator, #history-button, #bookmarks-button, #bookmarks-menu-button, #new-tab-button, #new-window-button, #cut-button, #copy-button, #paste-button, #fullscreen-button, #zoom-out-button, #zoom-in-button, #sync-button, #feed-button, #alltabs-button, #tabview-button
|
||||
|
|
|
@ -2734,6 +2734,7 @@ html|*#gcli-output-frame {
|
|||
|
||||
.chat-titlebar {
|
||||
background-color: #d9d9d9;
|
||||
background-image: linear-gradient(@toolbarHighlight@, rgba(255,255,255,0));
|
||||
height: 20px;
|
||||
min-height: 20px;
|
||||
width: 100%;
|
||||
|
@ -2754,7 +2755,10 @@ html|*#gcli-output-frame {
|
|||
}
|
||||
|
||||
.chat-titlebar[activity] {
|
||||
background-color: #ceeaff;
|
||||
background-image: radial-gradient(ellipse closest-side at center, rgb(255,255,255), rgba(255,255,255,0));
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 20px;
|
||||
background-position: 0 -10px;
|
||||
}
|
||||
|
||||
.chat-frame {
|
||||
|
@ -2764,6 +2768,7 @@ html|*#gcli-output-frame {
|
|||
}
|
||||
|
||||
.chatbar-button {
|
||||
-moz-appearance: none;
|
||||
background-color: #d9d9d9;
|
||||
list-style-image: url("chrome://browser/skin/social/social.png");
|
||||
border: none;
|
||||
|
@ -2775,8 +2780,16 @@ html|*#gcli-output-frame {
|
|||
-moz-border-end: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.chatbar-button[open="true"],
|
||||
.chatbar-button:active:hover {
|
||||
.chatbar-button > .toolbarbutton-icon {
|
||||
opacity: .6;
|
||||
-moz-margin-end: 0;
|
||||
}
|
||||
.chatbar-button:hover > .toolbarbutton-icon,
|
||||
.chatbar-button[open="true"] > .toolbarbutton-icon {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.chatbar-button[open="true"] {
|
||||
background-color: #f0f0f0;
|
||||
box-shadow: inset 0 2px 5px rgba(0,0,0,0.6), 0 1px rgba(255,255,255,0.2);
|
||||
}
|
||||
|
@ -2787,7 +2800,7 @@ html|*#gcli-output-frame {
|
|||
}
|
||||
|
||||
.chatbar-button[activity] {
|
||||
background-color: #ceeaff;
|
||||
background-image: radial-gradient(circle farthest-corner at center 3px, rgb(233,242,252) 3%, rgba(172,206,255,0.75) 40%, rgba(87,151,201,0.5) 80%, rgba(87,151,201,0));
|
||||
}
|
||||
|
||||
.chatbar-button > menupopup > menuitem[activity] {
|
||||
|
@ -2811,6 +2824,8 @@ chatbox {
|
|||
background-color: white;
|
||||
border: 1px solid #ccc;
|
||||
border-bottom: none;
|
||||
border-top-left-radius: 2.5px;
|
||||
border-top-right-radius: 2.5px;
|
||||
}
|
||||
|
||||
chatbox[minimized="true"] {
|
||||
|
|
|
@ -61,7 +61,6 @@ richlistitem[type="download"]:last-child {
|
|||
#downloadsListBox:-moz-focusring > richlistitem[type="download"][selected] {
|
||||
outline: 1px -moz-dialogtext dotted;
|
||||
outline-offset: -1px;
|
||||
-moz-outline-radius: 3px;
|
||||
}
|
||||
|
||||
.downloadTypeIcon {
|
||||
|
|
|
@ -4156,6 +4156,7 @@ html|*#gcli-output-frame {
|
|||
|
||||
.chat-titlebar {
|
||||
background-color: #d9d9d9;
|
||||
background-image: linear-gradient(rgba(255,255,255,.43), rgba(255,255,255,0));
|
||||
height: 20px;
|
||||
min-height: 20px;
|
||||
width: 100%;
|
||||
|
@ -4172,7 +4173,10 @@ html|*#gcli-output-frame {
|
|||
}
|
||||
|
||||
.chat-titlebar[activity] {
|
||||
background-color: #ceeaff;
|
||||
background-image: radial-gradient(ellipse closest-side at center, rgb(255,255,255), rgba(255,255,255,0));
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 20px;
|
||||
background-position: 0 -10px;
|
||||
}
|
||||
|
||||
.chat-titlebar[selected] {
|
||||
|
@ -4197,8 +4201,15 @@ html|*#gcli-output-frame {
|
|||
-moz-border-end: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.chatbar-button[open="true"],
|
||||
.chatbar-button:active:hover {
|
||||
.chatbar-button > .toolbarbutton-icon {
|
||||
opacity: .6;
|
||||
}
|
||||
.chatbar-button:hover > .toolbarbutton-icon,
|
||||
.chatbar-button[open="true"] > .toolbarbutton-icon {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.chatbar-button[open="true"] {
|
||||
background-color: #f0f0f0;
|
||||
box-shadow: inset 0 2px 5px rgba(0,0,0,0.6), 0 1px rgba(255,255,255,0.2);
|
||||
}
|
||||
|
@ -4209,7 +4220,7 @@ html|*#gcli-output-frame {
|
|||
}
|
||||
|
||||
.chatbar-button[activity] {
|
||||
background-color: #ceeaff;
|
||||
background-image: radial-gradient(circle farthest-corner at center 2px, rgb(254,254,255) 3%, rgba(210,235,255,0.9) 12%, rgba(148,205,253,0.6) 30%, rgba(148,205,253,0.2) 70%);
|
||||
}
|
||||
|
||||
.chatbar-button > menupopup > menuitem[activity] {
|
||||
|
@ -4218,7 +4229,7 @@ html|*#gcli-output-frame {
|
|||
|
||||
.chatbar-innerbox {
|
||||
background: transparent;
|
||||
margin: -285px -1px 0 -1px;
|
||||
margin: -285px 0 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
|
@ -4233,6 +4244,8 @@ chatbox {
|
|||
background-color: white;
|
||||
border: 1px solid #ccc;
|
||||
border-bottom: none;
|
||||
border-top-left-radius: @toolbarbuttonCornerRadius@;
|
||||
border-top-right-radius: @toolbarbuttonCornerRadius@;
|
||||
}
|
||||
|
||||
chatbox[minimized="true"] {
|
||||
|
|
|
@ -77,7 +77,6 @@ richlistitem[type="download"]:last-child {
|
|||
#downloadsListBox:-moz-focusring > richlistitem[type="download"][selected] {
|
||||
outline: 1px -moz-dialogtext dotted;
|
||||
outline-offset: -1px;
|
||||
-moz-outline-radius: 3px;
|
||||
}
|
||||
|
||||
.downloadTypeIcon {
|
||||
|
|
|
@ -3438,6 +3438,7 @@ html|*#gcli-output-frame {
|
|||
|
||||
.chat-titlebar {
|
||||
background-color: #c4cfde;
|
||||
background-image: linear-gradient(rgba(255,255,255,.5), rgba(255,255,255,0));
|
||||
height: 20px;
|
||||
min-height: 20px;
|
||||
width: 100%;
|
||||
|
@ -3458,7 +3459,10 @@ html|*#gcli-output-frame {
|
|||
}
|
||||
|
||||
.chat-titlebar[activity] {
|
||||
background-color: #ceeaff;
|
||||
background-image: radial-gradient(ellipse closest-side at center, rgb(255,255,255), rgba(255,255,255,0));
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 20px;
|
||||
background-position: 0 -10px;
|
||||
}
|
||||
|
||||
.chat-frame {
|
||||
|
@ -3487,9 +3491,16 @@ html|*#gcli-output-frame {
|
|||
padding: 2px;
|
||||
}
|
||||
|
||||
.chatbar-button[open="true"],
|
||||
.chatbar-button:hover,
|
||||
.chatbar-button:active:hover {
|
||||
.chatbar-button > .toolbarbutton-icon {
|
||||
opacity: .6;
|
||||
-moz-margin-end: 0;
|
||||
}
|
||||
.chatbar-button:hover > .toolbarbutton-icon,
|
||||
.chatbar-button[open="true"] > .toolbarbutton-icon {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.chatbar-button[open="true"] {
|
||||
background-color: #dae3f0;
|
||||
box-shadow: inset 0 2px 5px rgba(0,0,0,0.6), 0 1px rgba(255,255,255,0.2);
|
||||
}
|
||||
|
@ -3499,8 +3510,8 @@ html|*#gcli-output-frame {
|
|||
display: none;
|
||||
}
|
||||
|
||||
.chatbar-button[activity] {
|
||||
background-color: #ceeaff;
|
||||
.chatbar-button[activity]:not([open="true"]) {
|
||||
background-image: radial-gradient(circle farthest-corner at center 3px, rgb(255,255,255) 3%, rgba(186,221,251,0.75) 40%, rgba(127,179,255,0.5) 80%, rgba(127,179,255,0.25));
|
||||
}
|
||||
|
||||
.chatbar-button > menupopup > menuitem[activity] {
|
||||
|
@ -3509,7 +3520,7 @@ html|*#gcli-output-frame {
|
|||
|
||||
.chatbar-innerbox {
|
||||
background: transparent;
|
||||
margin: -285px -1px 0 -1px;
|
||||
margin: -285px 0 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
|
@ -3524,6 +3535,8 @@ chatbox {
|
|||
background-color: white;
|
||||
border: 1px solid #ccc;
|
||||
border-bottom: none;
|
||||
border-top-left-radius: 2.5px;
|
||||
border-top-right-radius: 2.5px;
|
||||
}
|
||||
|
||||
chatbox[minimized="true"] {
|
||||
|
|
|
@ -72,7 +72,6 @@ richlistitem[type="download"]:first-child {
|
|||
#downloadsListBox:-moz-focusring > richlistitem[type="download"][selected] {
|
||||
outline: 1px -moz-dialogtext dotted;
|
||||
outline-offset: -1px;
|
||||
-moz-outline-radius: 3px;
|
||||
}
|
||||
|
||||
.downloadTypeIcon {
|
||||
|
|
|
@ -21,7 +21,7 @@ interface nsIContentSecurityPolicy;
|
|||
[ptr] native JSPrincipals(JSPrincipals);
|
||||
[ptr] native PrincipalArray(nsTArray<nsCOMPtr<nsIPrincipal> >);
|
||||
|
||||
[scriptable, uuid(96a92f0c-adcb-44ac-a034-37627647ec97)]
|
||||
[scriptable, uuid(3a283dc9-f733-4618-a36f-e2b68c280ab7)]
|
||||
interface nsIPrincipal : nsISerializable
|
||||
{
|
||||
/**
|
||||
|
@ -195,6 +195,12 @@ interface nsIPrincipal : nsISerializable
|
|||
* appId everywhere where we construct principals.
|
||||
*/
|
||||
readonly attribute boolean unknownAppId;
|
||||
|
||||
/**
|
||||
* Returns true iff this principal is a null principal (corresponding to an
|
||||
* unknown, hence assumed minimally privileged, security context).
|
||||
*/
|
||||
readonly attribute boolean isNullPrincipal;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -217,4 +223,4 @@ interface nsIExpandedPrincipal : nsISupports
|
|||
* should not be changed and should only be used ephemerally.
|
||||
*/
|
||||
[noscript] readonly attribute PrincipalArray whiteList;
|
||||
};
|
||||
};
|
|
@ -71,6 +71,7 @@ public:
|
|||
NS_IMETHOD GetAppId(uint32_t* aAppStatus);
|
||||
NS_IMETHOD GetIsInBrowserElement(bool* aIsInBrowserElement);
|
||||
NS_IMETHOD GetUnknownAppId(bool* aUnknownAppId);
|
||||
NS_IMETHOD GetIsNullPrincipal(bool* aIsNullPrincipal);
|
||||
#ifdef DEBUG
|
||||
virtual void dumpImpl();
|
||||
#endif
|
||||
|
@ -152,6 +153,7 @@ public:
|
|||
NS_IMETHOD GetAppId(uint32_t* aAppStatus);
|
||||
NS_IMETHOD GetIsInBrowserElement(bool* aIsInBrowserElement);
|
||||
NS_IMETHOD GetUnknownAppId(bool* aUnknownAppId);
|
||||
NS_IMETHOD GetIsNullPrincipal(bool* aIsNullPrincipal);
|
||||
#ifdef DEBUG
|
||||
virtual void dumpImpl();
|
||||
#endif
|
||||
|
|
|
@ -291,6 +291,13 @@ nsNullPrincipal::GetUnknownAppId(bool* aUnknownAppId)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNullPrincipal::GetIsNullPrincipal(bool* aIsNullPrincipal)
|
||||
{
|
||||
*aIsNullPrincipal = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* nsISerializable implementation
|
||||
*/
|
||||
|
|
|
@ -541,6 +541,13 @@ nsPrincipal::GetUnknownAppId(bool* aUnknownAppId)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPrincipal::GetIsNullPrincipal(bool* aIsNullPrincipal)
|
||||
{
|
||||
*aIsNullPrincipal = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPrincipal::Read(nsIObjectInputStream* aStream)
|
||||
{
|
||||
|
@ -852,6 +859,13 @@ nsExpandedPrincipal::GetUnknownAppId(bool* aUnknownAppId)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsExpandedPrincipal::GetIsNullPrincipal(bool* aIsNullPrincipal)
|
||||
{
|
||||
*aIsNullPrincipal = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsExpandedPrincipal::GetScriptLocation(nsACString& aStr)
|
||||
{
|
||||
|
|
|
@ -2992,11 +2992,13 @@ GetExtendedOrigin(nsIURI* aURI, uint32_t aAppId, bool aInMozBrowser,
|
|||
return;
|
||||
}
|
||||
|
||||
// aExtendedOrigin = appId + "+" + origin + "+" + { 't', 'f' }
|
||||
// aExtendedOrigin = appId + "+" + { 't', 'f' } "+" + origin;
|
||||
aExtendedOrigin.Truncate();
|
||||
aExtendedOrigin.AppendInt(aAppId);
|
||||
aExtendedOrigin.Append(NS_LITERAL_CSTRING("+") + origin + NS_LITERAL_CSTRING("+"));
|
||||
aExtendedOrigin.Append('+');
|
||||
aExtendedOrigin.Append(aInMozBrowser ? 't' : 'f');
|
||||
aExtendedOrigin.Append('+');
|
||||
aExtendedOrigin.Append(origin);
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -198,6 +198,13 @@ nsSystemPrincipal::GetUnknownAppId(bool* aUnknownAppId)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSystemPrincipal::GetIsNullPrincipal(bool* aIsNullPrincipal)
|
||||
{
|
||||
*aIsNullPrincipal = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////
|
||||
// Methods implementing nsISerializable //
|
||||
//////////////////////////////////////////
|
||||
|
|
|
@ -1202,15 +1202,15 @@ WebGLContext::DummyFramebufferOperation(const char *info)
|
|||
// are met.
|
||||
// At a bare minimum, from context lost to context restores, it would take 3
|
||||
// full timer iterations: detection, webglcontextlost, webglcontextrestored.
|
||||
NS_IMETHODIMP
|
||||
WebGLContext::Notify(nsITimer* timer)
|
||||
void
|
||||
WebGLContext::RobustnessTimerCallback(nsITimer* timer)
|
||||
{
|
||||
TerminateContextLossTimer();
|
||||
|
||||
if (!mCanvasElement) {
|
||||
// the canvas is gone. That happens when the page was closed before we got
|
||||
// this timer event. In this case, there's nothing to do here, just don't crash.
|
||||
return NS_OK;
|
||||
return;
|
||||
}
|
||||
|
||||
// If the context has been lost and we're waiting for it to be restored, do
|
||||
|
@ -1243,7 +1243,7 @@ WebGLContext::Notify(nsITimer* timer)
|
|||
// Try to restore the context. If it fails, try again later.
|
||||
if (NS_FAILED(SetDimensions(mWidth, mHeight))) {
|
||||
SetupContextLossTimer();
|
||||
return NS_OK;
|
||||
return;
|
||||
}
|
||||
mContextStatus = ContextStable;
|
||||
nsContentUtils::DispatchTrustedEvent(mCanvasElement->OwnerDoc(),
|
||||
|
@ -1258,7 +1258,7 @@ WebGLContext::Notify(nsITimer* timer)
|
|||
}
|
||||
|
||||
MaybeRestoreContext();
|
||||
return NS_OK;
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1408,7 +1408,6 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WebGLContext)
|
|||
NS_INTERFACE_MAP_ENTRY(nsIDOMWebGLRenderingContext)
|
||||
NS_INTERFACE_MAP_ENTRY(nsICanvasRenderingContextInternal)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
||||
NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
|
||||
// If the exact way we cast to nsISupports here ever changes, fix our
|
||||
// PreCreate hook!
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports,
|
||||
|
|
|
@ -473,7 +473,6 @@ class WebGLContext :
|
|||
public nsIDOMWebGLRenderingContext,
|
||||
public nsICanvasRenderingContextInternal,
|
||||
public nsSupportsWeakReference,
|
||||
public nsITimerCallback,
|
||||
public WebGLRectangleObject,
|
||||
public nsWrapperCache
|
||||
{
|
||||
|
@ -510,8 +509,6 @@ public:
|
|||
|
||||
NS_DECL_NSIDOMWEBGLRENDERINGCONTEXT
|
||||
|
||||
NS_DECL_NSITIMERCALLBACK
|
||||
|
||||
// nsICanvasRenderingContextInternal
|
||||
NS_IMETHOD SetDimensions(int32_t width, int32_t height);
|
||||
NS_IMETHOD InitializeWithSurface(nsIDocShell *docShell, gfxASurface *surface, int32_t width, int32_t height)
|
||||
|
@ -607,6 +604,12 @@ public:
|
|||
return mMinCapability;
|
||||
}
|
||||
|
||||
void RobustnessTimerCallback(nsITimer* timer);
|
||||
|
||||
static void RobustnessTimerCallbackStatic(nsITimer* timer, void *thisPointer) {
|
||||
static_cast<WebGLContext*>(thisPointer)->RobustnessTimerCallback(timer);
|
||||
}
|
||||
|
||||
void SetupContextLossTimer() {
|
||||
// If the timer was already running, don't restart it here. Instead,
|
||||
// wait until the previous call is done, then fire it one more time.
|
||||
|
@ -616,10 +619,11 @@ public:
|
|||
mDrawSinceContextLossTimerSet = true;
|
||||
return;
|
||||
}
|
||||
|
||||
mContextRestorer->InitWithCallback(static_cast<nsITimerCallback*>(this),
|
||||
PR_MillisecondsToInterval(1000),
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
|
||||
mContextRestorer->InitWithFuncCallback(RobustnessTimerCallbackStatic,
|
||||
static_cast<void*>(this),
|
||||
PR_MillisecondsToInterval(1000),
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
mContextLossTimerRunning = true;
|
||||
mDrawSinceContextLossTimerSet = false;
|
||||
}
|
||||
|
|
|
@ -64,12 +64,6 @@ CPPSRCS = \
|
|||
TextComposition.cpp \
|
||||
$(NULL)
|
||||
|
||||
ifdef MOZ_B2G_RIL
|
||||
CPPSRCS += \
|
||||
nsDOMWifiEvent.cpp \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
# we don't want the shared lib, but we want to force the creation of a static lib.
|
||||
FORCE_STATIC_LIB = 1
|
||||
|
||||
|
|
|
@ -1,179 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsDOMWifiEvent.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "DictionaryHelpers.h"
|
||||
#include "nsDOMClassInfoID.h"
|
||||
|
||||
// nsDOMMozWifiStatusChangeEvent
|
||||
|
||||
DOMCI_DATA(MozWifiStatusChangeEvent, nsDOMMozWifiStatusChangeEvent)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMMozWifiStatusChangeEvent)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMMozWifiStatusChangeEvent, nsDOMEvent)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mNetwork)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMMozWifiStatusChangeEvent, nsDOMEvent)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mNetwork)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(nsDOMMozWifiStatusChangeEvent)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMMozWifiStatusChangeEvent)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozWifiStatusChangeEvent)
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(nsDOMMozWifiStatusChangeEvent, nsDOMEvent)
|
||||
NS_IMPL_RELEASE_INHERITED(nsDOMMozWifiStatusChangeEvent, nsDOMEvent)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMMozWifiStatusChangeEvent::GetNetwork(nsIVariant** aNetwork)
|
||||
{
|
||||
NS_IF_ADDREF(*aNetwork = mNetwork);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMMozWifiStatusChangeEvent::GetStatus(nsAString& aStatus)
|
||||
{
|
||||
aStatus = mStatus;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMMozWifiStatusChangeEvent::InitMozWifiStatusChangeEvent(const nsAString& aType,
|
||||
bool aCanBubble,
|
||||
bool aCancelable,
|
||||
nsIVariant* aNetwork,
|
||||
const nsAString& aStatus)
|
||||
{
|
||||
nsresult rv = nsDOMEvent::InitEvent(aType, aCanBubble, aCancelable);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mNetwork = aNetwork;
|
||||
mStatus = aStatus;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMMozWifiStatusChangeEvent::InitFromCtor(const nsAString& aType,
|
||||
JSContext* aCx, jsval* aVal)
|
||||
{
|
||||
mozilla::dom::MozWifiStatusChangeEventInit d;
|
||||
nsresult rv = d.Init(aCx, aVal);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return InitMozWifiStatusChangeEvent(aType, d.bubbles, d.cancelable, d.network, d.status);
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_NewDOMMozWifiStatusChangeEvent(nsIDOMEvent** aInstancePtrResult,
|
||||
nsPresContext* aPresContext,
|
||||
nsEvent* aEvent)
|
||||
{
|
||||
nsDOMMozWifiStatusChangeEvent* e = new nsDOMMozWifiStatusChangeEvent(aPresContext, aEvent);
|
||||
return CallQueryInterface(e, aInstancePtrResult);
|
||||
}
|
||||
|
||||
// nsDOMMozWifiConnectionInfoEvent
|
||||
DOMCI_DATA(MozWifiConnectionInfoEvent, nsDOMMozWifiConnectionInfoEvent)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMMozWifiConnectionInfoEvent)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMMozWifiConnectionInfoEvent, nsDOMEvent)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mNetwork)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMMozWifiConnectionInfoEvent, nsDOMEvent)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mNetwork)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(nsDOMMozWifiConnectionInfoEvent)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMMozWifiConnectionInfoEvent)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozWifiConnectionInfoEvent)
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(nsDOMMozWifiConnectionInfoEvent, nsDOMEvent)
|
||||
NS_IMPL_RELEASE_INHERITED(nsDOMMozWifiConnectionInfoEvent, nsDOMEvent)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMMozWifiConnectionInfoEvent::GetNetwork(nsIVariant** aNetwork)
|
||||
{
|
||||
NS_IF_ADDREF(*aNetwork = mNetwork);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMMozWifiConnectionInfoEvent::GetSignalStrength(int16_t* aSignalStrength)
|
||||
{
|
||||
*aSignalStrength = mSignalStrength;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMMozWifiConnectionInfoEvent::GetRelSignalStrength(int16_t* aRelSignalStrength)
|
||||
{
|
||||
*aRelSignalStrength = mRelSignalStrength;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMMozWifiConnectionInfoEvent::GetLinkSpeed(int32_t* aLinkSpeed)
|
||||
{
|
||||
*aLinkSpeed = mLinkSpeed;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMMozWifiConnectionInfoEvent::GetIpAddress(nsAString& aIpAddress)
|
||||
{
|
||||
aIpAddress = mIpAddress;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMMozWifiConnectionInfoEvent::InitMozWifiConnectionInfoEvent(const nsAString& aType,
|
||||
bool aCanBubble,
|
||||
bool aCancelable,
|
||||
nsIVariant *aNetwork,
|
||||
int16_t aSignalStrength,
|
||||
int16_t aRelSignalStrength,
|
||||
int32_t aLinkSpeed,
|
||||
const nsAString &aIpAddress)
|
||||
{
|
||||
nsresult rv = nsDOMEvent::InitEvent(aType, aCanBubble, aCancelable);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mNetwork = aNetwork;
|
||||
mSignalStrength = aSignalStrength;
|
||||
mRelSignalStrength = aRelSignalStrength;
|
||||
mLinkSpeed = aLinkSpeed;
|
||||
mIpAddress = aIpAddress;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMMozWifiConnectionInfoEvent::InitFromCtor(const nsAString& aType,
|
||||
JSContext* aCx, jsval* aVal)
|
||||
{
|
||||
mozilla::dom::MozWifiConnectionInfoEventInit d;
|
||||
nsresult rv = d.Init(aCx, aVal);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return InitMozWifiConnectionInfoEvent(aType, d.bubbles, d.cancelable, d.network,
|
||||
d.signalStrength, d.relSignalStrength, d.linkSpeed,
|
||||
d.ipAddress);
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_NewDOMMozWifiConnectionInfoEvent(nsIDOMEvent** aInstancePtrResult,
|
||||
nsPresContext* aPresContext,
|
||||
nsEvent* aEvent)
|
||||
{
|
||||
nsDOMMozWifiConnectionInfoEvent* e = new nsDOMMozWifiConnectionInfoEvent(aPresContext, aEvent);
|
||||
return CallQueryInterface(e, aInstancePtrResult);
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsDOMWifiEvent_h__
|
||||
#define nsDOMWifiEvent_h__
|
||||
|
||||
#include "nsIWifi.h"
|
||||
#include "nsIWifiEventInits.h"
|
||||
#include "nsDOMEvent.h"
|
||||
|
||||
class nsDOMMozWifiStatusChangeEvent : public nsDOMEvent,
|
||||
public nsIDOMMozWifiStatusChangeEvent
|
||||
{
|
||||
public:
|
||||
nsDOMMozWifiStatusChangeEvent(nsPresContext* aPresContext, nsEvent* aEvent)
|
||||
: nsDOMEvent(aPresContext, aEvent) {}
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsDOMMozWifiStatusChangeEvent, nsDOMEvent)
|
||||
// Forward to base class
|
||||
NS_FORWARD_TO_NSDOMEVENT
|
||||
|
||||
NS_DECL_NSIDOMMOZWIFISTATUSCHANGEEVENT
|
||||
|
||||
virtual nsresult InitFromCtor(const nsAString& aType,
|
||||
JSContext* aCx, jsval* aVal);
|
||||
private:
|
||||
nsCOMPtr<nsIVariant> mNetwork;
|
||||
nsString mStatus;
|
||||
};
|
||||
|
||||
class nsDOMMozWifiConnectionInfoEvent : public nsDOMEvent,
|
||||
public nsIDOMMozWifiConnectionInfoEvent
|
||||
{
|
||||
public:
|
||||
nsDOMMozWifiConnectionInfoEvent(nsPresContext* aPresContext, nsEvent* aEvent)
|
||||
: nsDOMEvent(aPresContext, aEvent) {}
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsDOMMozWifiConnectionInfoEvent, nsDOMEvent)
|
||||
// Forward to base class
|
||||
NS_FORWARD_TO_NSDOMEVENT
|
||||
|
||||
NS_DECL_NSIDOMMOZWIFICONNECTIONINFOEVENT
|
||||
|
||||
virtual nsresult InitFromCtor(const nsAString& aType,
|
||||
JSContext* aCx, jsval* aVal);
|
||||
private:
|
||||
nsCOMPtr<nsIVariant> mNetwork;
|
||||
int16_t mSignalStrength;
|
||||
int16_t mRelSignalStrength;
|
||||
int32_t mLinkSpeed;
|
||||
nsString mIpAddress;
|
||||
};
|
||||
|
||||
#endif // nsDOMWifiEvent_h__
|
|
@ -167,7 +167,9 @@ nsSVGSVGElement::nsSVGSVGElement(already_AddRefed<nsINodeInfo> aNodeInfo,
|
|||
mCurrentScale(1.0f),
|
||||
mPreviousTranslate(0.0f, 0.0f),
|
||||
mPreviousScale(1.0f),
|
||||
mStartAnimationOnBindToTree(!aFromParser),
|
||||
mStartAnimationOnBindToTree(aFromParser == NOT_FROM_PARSER ||
|
||||
aFromParser == FROM_PARSER_FRAGMENT ||
|
||||
aFromParser == FROM_PARSER_XSLT),
|
||||
mImageNeedsTransformInvalidation(false),
|
||||
mIsPaintingSVGImageElement(false),
|
||||
mHasChildrenOnlyTransform(false),
|
||||
|
|
|
@ -19,20 +19,20 @@ AlarmHalService::Init()
|
|||
if (!mAlarmEnabled) {
|
||||
return;
|
||||
}
|
||||
RegisterSystemTimeChangeObserver(this);
|
||||
RegisterSystemTimezoneChangeObserver(this);
|
||||
}
|
||||
|
||||
/* virtual */ AlarmHalService::~AlarmHalService()
|
||||
{
|
||||
if (mAlarmEnabled) {
|
||||
UnregisterTheOneAlarmObserver();
|
||||
UnregisterSystemTimeChangeObserver(this);
|
||||
UnregisterSystemTimezoneChangeObserver(this);
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ StaticRefPtr<AlarmHalService> AlarmHalService::sSingleton;
|
||||
|
||||
/* static */ already_AddRefed<nsIAlarmHalService>
|
||||
/* static */ already_AddRefed<AlarmHalService>
|
||||
AlarmHalService::GetInstance()
|
||||
{
|
||||
if (!sSingleton) {
|
||||
|
@ -41,7 +41,7 @@ AlarmHalService::GetInstance()
|
|||
ClearOnShutdown(&sSingleton);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAlarmHalService> service(do_QueryInterface(sSingleton));
|
||||
nsRefPtr<AlarmHalService> service = sSingleton.get();
|
||||
return service.forget();
|
||||
}
|
||||
|
||||
|
@ -76,7 +76,7 @@ AlarmHalService::SetTimezoneChangedCb(nsITimezoneChangedCb* aTimeZoneChangedCb)
|
|||
}
|
||||
|
||||
void
|
||||
AlarmHalService::Notify(const mozilla::void_t& aVoid)
|
||||
AlarmHalService::Notify(const void_t& aVoid)
|
||||
{
|
||||
if (!mAlarmFiredCb) {
|
||||
return;
|
||||
|
@ -85,26 +85,14 @@ AlarmHalService::Notify(const mozilla::void_t& aVoid)
|
|||
}
|
||||
|
||||
void
|
||||
AlarmHalService::Notify(const SystemTimeChange& aReason)
|
||||
AlarmHalService::Notify(
|
||||
const SystemTimezoneChangeInformation& aSystemTimezoneChangeInfo)
|
||||
{
|
||||
if (aReason != SYS_TIME_CHANGE_TZ || !mTimezoneChangedCb) {
|
||||
if (!mTimezoneChangedCb) {
|
||||
return;
|
||||
}
|
||||
mTimezoneChangedCb->OnTimezoneChanged(GetTimezoneOffset(false));
|
||||
}
|
||||
|
||||
int32_t
|
||||
AlarmHalService::GetTimezoneOffset(bool aIgnoreDST)
|
||||
{
|
||||
PRExplodedTime prTime;
|
||||
PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &prTime);
|
||||
|
||||
int32_t offset = prTime.tm_params.tp_gmt_offset;
|
||||
if (!aIgnoreDST) {
|
||||
offset += prTime.tm_params.tp_dst_offset;
|
||||
}
|
||||
|
||||
return -(offset / 60);
|
||||
mTimezoneChangedCb->OnTimezoneChanged(
|
||||
aSystemTimezoneChangeInfo.newTimezoneOffsetMinutes());
|
||||
}
|
||||
|
||||
} // alarm
|
||||
|
|
|
@ -13,17 +13,17 @@
|
|||
#include "nsIAlarmHalService.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "prtime.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace alarm {
|
||||
|
||||
using namespace hal;
|
||||
|
||||
typedef Observer<void_t> AlarmObserver;
|
||||
typedef Observer<hal::SystemTimezoneChangeInformation> SystemTimezoneChangeObserver;
|
||||
|
||||
class AlarmHalService : public nsIAlarmHalService,
|
||||
public AlarmObserver,
|
||||
public SystemTimeObserver
|
||||
public SystemTimezoneChangeObserver
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
@ -32,13 +32,13 @@ public:
|
|||
void Init();
|
||||
virtual ~AlarmHalService();
|
||||
|
||||
static already_AddRefed<nsIAlarmHalService> GetInstance();
|
||||
static already_AddRefed<AlarmHalService> GetInstance();
|
||||
|
||||
// Implementing hal::AlarmObserver
|
||||
void Notify(const mozilla::void_t& aVoid);
|
||||
void Notify(const void_t& aVoid);
|
||||
|
||||
// Implementing hal::SystemTimeObserver
|
||||
void Notify(const SystemTimeChange& aReason);
|
||||
// Implementing hal::SystemTimezoneChangeObserver
|
||||
void Notify(const hal::SystemTimezoneChangeInformation& aSystemTimezoneChangeInfo);
|
||||
|
||||
private:
|
||||
bool mAlarmEnabled;
|
||||
|
@ -46,8 +46,6 @@ private:
|
|||
|
||||
nsCOMPtr<nsIAlarmFiredCb> mAlarmFiredCb;
|
||||
nsCOMPtr<nsITimezoneChangedCb> mTimezoneChangedCb;
|
||||
|
||||
int32_t GetTimezoneOffset(bool aIgnoreDST);
|
||||
};
|
||||
|
||||
} // namespace alarm
|
||||
|
|
|
@ -26,6 +26,7 @@ EXTRA_PP_JS_MODULES += \
|
|||
EXTRA_JS_MODULES += \
|
||||
AppsServiceChild.jsm \
|
||||
AppsUtils.jsm \
|
||||
OfflineCacheInstaller.jsm \
|
||||
PermissionsInstaller.jsm \
|
||||
$(NULL)
|
||||
|
||||
|
|
|
@ -0,0 +1,174 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const Cu = Components.utils;
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const CC = Components.Constructor;
|
||||
|
||||
let EXPORTED_SYMBOLS = ["OfflineCacheInstaller"];
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/AppsUtils.jsm");
|
||||
Cu.import("resource://gre/modules/NetUtil.jsm");
|
||||
|
||||
let Namespace = CC('@mozilla.org/network/application-cache-namespace;1',
|
||||
'nsIApplicationCacheNamespace',
|
||||
'init');
|
||||
let makeFile = CC('@mozilla.org/file/local;1',
|
||||
'nsIFile',
|
||||
'initWithPath');
|
||||
const nsICache = Ci.nsICache;
|
||||
const nsIApplicationCache = Ci.nsIApplicationCache;
|
||||
const applicationCacheService =
|
||||
Cc['@mozilla.org/network/application-cache-service;1']
|
||||
.getService(Ci.nsIApplicationCacheService);
|
||||
|
||||
|
||||
function debug(aMsg) {
|
||||
//dump("-*-*- OfflineCacheInstaller.jsm : " + aMsg + "\n");
|
||||
}
|
||||
|
||||
|
||||
function enableOfflineCacheForApp(origin, appId) {
|
||||
let originURI = Services.io.newURI(origin, null, null);
|
||||
let principal = Services.scriptSecurityManager.getAppCodebasePrincipal(
|
||||
originURI, appId, false);
|
||||
Services.perms.addFromPrincipal(principal, 'offline-app',
|
||||
Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||
// Prevent cache from being evicted:
|
||||
Services.perms.addFromPrincipal(principal, 'pin-app',
|
||||
Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||
}
|
||||
|
||||
|
||||
function storeCache(applicationCache, url, file, itemType) {
|
||||
let session = Services.cache.createSession(applicationCache.clientID,
|
||||
nsICache.STORE_OFFLINE, true);
|
||||
session.asyncOpenCacheEntry(url, nsICache.ACCESS_WRITE, {
|
||||
onCacheEntryAvailable: function (cacheEntry, accessGranted, status) {
|
||||
cacheEntry.setMetaDataElement('request-method', 'GET');
|
||||
cacheEntry.setMetaDataElement('response-head', 'HTTP/1.1 200 OK\r\n');
|
||||
|
||||
let outputStream = cacheEntry.openOutputStream(0);
|
||||
|
||||
// Input-Output stream machinery in order to push nsIFile content into cache
|
||||
let inputStream = Cc['@mozilla.org/network/file-input-stream;1']
|
||||
.createInstance(Ci.nsIFileInputStream);
|
||||
inputStream.init(file, 1, -1, null);
|
||||
let bufferedOutputStream = Cc['@mozilla.org/network/buffered-output-stream;1']
|
||||
.createInstance(Ci.nsIBufferedOutputStream);
|
||||
bufferedOutputStream.init(outputStream, 1024);
|
||||
bufferedOutputStream.writeFrom(inputStream, inputStream.available());
|
||||
bufferedOutputStream.flush();
|
||||
bufferedOutputStream.close();
|
||||
outputStream.close();
|
||||
inputStream.close();
|
||||
|
||||
cacheEntry.markValid();
|
||||
debug (file.path + ' -> ' + url + ' (' + itemType + ')');
|
||||
applicationCache.markEntry(url, itemType);
|
||||
cacheEntry.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function readFile(aFile, aCallback) {
|
||||
let channel = NetUtil.newChannel(aFile);
|
||||
channel.contentType = "pain/text";
|
||||
NetUtil.asyncFetch(channel, function(aStream, aResult) {
|
||||
if (!Components.isSuccessCode(aResult)) {
|
||||
Cu.reportError("OfflineCacheInstaller: Could not read file " + aFile.path);
|
||||
if (aCallback)
|
||||
aCallback(null);
|
||||
return;
|
||||
}
|
||||
|
||||
// Obtain a converter to read from a UTF-8 encoded input stream.
|
||||
let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
|
||||
.createInstance(Ci.nsIScriptableUnicodeConverter);
|
||||
converter.charset = "UTF-8";
|
||||
|
||||
let data = NetUtil.readInputStreamToString(aStream,
|
||||
aStream.available());
|
||||
aCallback(converter.ConvertToUnicode(data));
|
||||
});
|
||||
}
|
||||
|
||||
const OfflineCacheInstaller = {
|
||||
installCache: function installCache(app) {
|
||||
let cacheDir = makeFile(app.basePath)
|
||||
cacheDir.append(app.appId);
|
||||
cacheDir.append("cache");
|
||||
if (!cacheDir.exists())
|
||||
return;
|
||||
|
||||
let cacheManifest = cacheDir.clone();
|
||||
cacheManifest.append("manifest.appcache");
|
||||
if (!cacheManifest.exists())
|
||||
return;
|
||||
|
||||
enableOfflineCacheForApp(app.origin, app.localId);
|
||||
|
||||
// Get the url for the manifest.
|
||||
let appcacheURL = app.origin + "cache/manifest.appcache";
|
||||
|
||||
// The group ID contains application id and 'f' for not being hosted in
|
||||
// a browser element, but a mozbrowser iframe.
|
||||
// See netwerk/cache/nsDiskCacheDeviceSQL.cpp: AppendJARIdentifier
|
||||
let groupID = appcacheURL + '#' + app.localId+ '+f';
|
||||
let applicationCache = applicationCacheService.createApplicationCache(groupID);
|
||||
applicationCache.activate();
|
||||
|
||||
readFile(cacheManifest, function (content) {
|
||||
let lines = content.split(/\r?\n/);
|
||||
// Process each manifest line, read only CACHE entries
|
||||
// (ignore NETWORK entries) and compute absolute URL for each entry
|
||||
let urls = [];
|
||||
for(let i = 0; i < lines.length; i++) {
|
||||
let line = lines[i];
|
||||
// Ignore comments
|
||||
if (/^#/.test(line) || !line.length)
|
||||
continue;
|
||||
if (line == 'CACHE MANIFEST')
|
||||
continue;
|
||||
if (line == 'CACHE:')
|
||||
continue;
|
||||
// Ignore network entries and everything that comes after
|
||||
if (line == 'NETWORK:')
|
||||
break;
|
||||
|
||||
// Prepend webapp origin in case of absolute path
|
||||
if (line[0] == '/') {
|
||||
urls.push(app.origin + line.substring(1));
|
||||
// Just pass along the url, if we have one
|
||||
} else if (line.substr(0, 4) == 'http') {
|
||||
urls.push(line);
|
||||
} else {
|
||||
throw new Error('Invalid line in appcache manifest:\n' + line +
|
||||
'\nFrom: ' + cacheManifest.path);
|
||||
}
|
||||
}
|
||||
urls.forEach(function processCachedFile(url) {
|
||||
// Get this nsIFile from cache folder for this URL
|
||||
let path = url.replace(/https?:\/\//, '');
|
||||
let file = cacheDir.clone();
|
||||
let paths = path.split('/');
|
||||
paths.forEach(file.append);
|
||||
|
||||
if (!file.exists()) {
|
||||
let msg = 'File ' + file.path + ' exists in the manifest but does ' +
|
||||
'not points to a real file.';
|
||||
throw new Error(msg);
|
||||
}
|
||||
|
||||
let itemType = nsIApplicationCache.ITEM_EXPLICIT;
|
||||
storeCache(applicationCache, url, file, itemType);
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -9,6 +9,7 @@ const Cu = Components.utils;
|
|||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/AppsUtils.jsm");
|
||||
Cu.import("resource://gre/modules/PermissionSettings.jsm");
|
||||
|
||||
var EXPORTED_SYMBOLS = ["PermissionsInstaller"];
|
||||
|
||||
|
@ -25,16 +26,6 @@ const READWRITE = "readwrite";
|
|||
|
||||
const PERM_TO_STRING = ["unknown", "allow", "deny", "prompt"];
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this,
|
||||
"PermSettings",
|
||||
"@mozilla.org/permissionSettings;1",
|
||||
"nsIDOMPermissionSettings");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this,
|
||||
"permissionManager",
|
||||
"@mozilla.org/permissionmanager;1",
|
||||
"nsIPermissionManager");
|
||||
|
||||
function debug(aMsg) {
|
||||
//dump("-*-*- PermissionsInstaller.jsm : " + aMsg + "\n");
|
||||
}
|
||||
|
@ -344,7 +335,7 @@ let PermissionsInstaller = {
|
|||
let index = newPerms.indexOf(AllPossiblePermissions[idx]);
|
||||
if (index == -1) {
|
||||
// See if the permission was installed previously
|
||||
let _perm = PermSettings.get(AllPossiblePermissions[idx],
|
||||
let _perm = PermissionSettingsModule.getPermission(AllPossiblePermissions[idx],
|
||||
aApp.manifestURL,
|
||||
aApp.origin,
|
||||
false);
|
||||
|
@ -415,13 +406,25 @@ let PermissionsInstaller = {
|
|||
**/
|
||||
_setPermission: function setPermission(aPerm, aValue, aApp) {
|
||||
if (aPerm != "storage") {
|
||||
PermSettings.set(aPerm, aValue, aApp.manifestURL, aApp.origin, false);
|
||||
PermissionSettingsModule.addPermission({
|
||||
type: aPerm,
|
||||
origin: aApp.origin,
|
||||
manifestURL: aApp.manifestURL,
|
||||
value: aValue,
|
||||
browserFlag: false
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
["indexedDB-unlimited", "offline-app", "pin-app"].forEach(
|
||||
function(aName) {
|
||||
PermSettings.set(aName, aValue, aApp.manifestURL, aApp.origin, false);
|
||||
PermissionSettingsModule.addPermission({
|
||||
type: aName,
|
||||
origin: aApp.origin,
|
||||
manifestURL: aApp.manifestURL,
|
||||
value: aValue,
|
||||
browserFlag: false
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ Cu.import("resource://gre/modules/FileUtils.jsm");
|
|||
Cu.import('resource://gre/modules/ActivitiesService.jsm');
|
||||
Cu.import("resource://gre/modules/AppsUtils.jsm");
|
||||
Cu.import("resource://gre/modules/PermissionsInstaller.jsm");
|
||||
Cu.import("resource://gre/modules/OfflineCacheInstaller.jsm");
|
||||
|
||||
function debug(aMsg) {
|
||||
//dump("-*-*- Webapps.jsm : " + aMsg + "\n");
|
||||
|
@ -92,7 +93,7 @@ let DOMApplicationRegistry = {
|
|||
// aNext() is called after we load the current webapps list.
|
||||
loadCurrentRegistry: function loadCurrentRegistry(aNext) {
|
||||
let file = FileUtils.getFile(DIRECTORY_NAME, ["webapps", "webapps.json"], false);
|
||||
if (file && file.exists) {
|
||||
if (file && file.exists()) {
|
||||
this._loadJSONAsync(file, (function loadRegistry(aData) {
|
||||
if (aData) {
|
||||
this.webapps = aData;
|
||||
|
@ -175,89 +176,99 @@ let DOMApplicationRegistry = {
|
|||
}).bind(this));
|
||||
},
|
||||
|
||||
updateOfflineCacheForApp: function updateOfflineCacheForApp(aId) {
|
||||
let app = this.webapps[aId];
|
||||
OfflineCacheInstaller.installCache({
|
||||
basePath: app.basePath,
|
||||
appId: aId,
|
||||
origin: app.origin,
|
||||
localId: app.localId
|
||||
});
|
||||
},
|
||||
|
||||
// Implements the core of bug 787439
|
||||
// 1. load the apps from the current registry.
|
||||
// 2. if at first run, go through these steps:
|
||||
// if at first run, go through these steps:
|
||||
// a. load the core apps registry.
|
||||
// b. uninstall any core app from the current registry but not in the
|
||||
// new core apps registry.
|
||||
// c. for all apps in the new core registry, install them if they are not
|
||||
// yet in the current registry, and run installPermissions()
|
||||
installSystemApps: function installSystemApps(aNext) {
|
||||
let file;
|
||||
try {
|
||||
file = FileUtils.getFile("coreAppsDir", ["webapps", "webapps.json"], false);
|
||||
} catch(e) { }
|
||||
|
||||
if (file && file.exists()) {
|
||||
// a
|
||||
this._loadJSONAsync(file, (function loadCoreRegistry(aData) {
|
||||
if (!aData) {
|
||||
aNext();
|
||||
return;
|
||||
}
|
||||
|
||||
// b : core apps are not removable.
|
||||
for (let id in this.webapps) {
|
||||
if (id in aData || this.webapps[id].removable)
|
||||
continue;
|
||||
delete this.webapps[id];
|
||||
// Remove the permissions, cookies and private data for this app.
|
||||
let localId = this.webapps[id].localId;
|
||||
let permMgr = Cc["@mozilla.org/permissionmanager;1"]
|
||||
.getService(Ci.nsIPermissionManager);
|
||||
permMgr.RemovePermissionsForApp(localId);
|
||||
Services.cookies.removeCookiesForApp(localId, false);
|
||||
this._clearPrivateData(localId, false);
|
||||
}
|
||||
|
||||
let appDir = FileUtils.getDir("coreAppsDir", ["webapps"], false);
|
||||
// c
|
||||
for (let id in aData) {
|
||||
// Core apps have ids matching their domain name (eg: dialer.gaiamobile.org)
|
||||
// Use that property to check if they are new or not.
|
||||
if (!(id in this.webapps)) {
|
||||
this.webapps[id] = aData[id];
|
||||
this.webapps[id].basePath = appDir.path;
|
||||
|
||||
// Create a new localId.
|
||||
this.webapps[id].localId = this._nextLocalId();
|
||||
|
||||
// Core apps are not removable.
|
||||
if (this.webapps[id].removable === undefined) {
|
||||
this.webapps[id].removable = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
aNext();
|
||||
}).bind(this));
|
||||
} else {
|
||||
aNext();
|
||||
}
|
||||
},
|
||||
|
||||
loadAndUpdateApps: function loadAndUpdateApps() {
|
||||
let runUpdate = AppsUtils.isFirstRun(Services.prefs);
|
||||
|
||||
// 1.
|
||||
this.loadCurrentRegistry((function() {
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
// if first run, merge the system apps.
|
||||
if (runUpdate) {
|
||||
let file;
|
||||
try {
|
||||
file = FileUtils.getFile("coreAppsDir", ["webapps", "webapps.json"], false);
|
||||
} catch(e) { }
|
||||
|
||||
if (file && file.exists) {
|
||||
// 2.a
|
||||
this._loadJSONAsync(file, (function loadCoreRegistry(aData) {
|
||||
if (!aData) {
|
||||
this.registerAppsHandlers();
|
||||
return;
|
||||
}
|
||||
|
||||
// 2.b : core apps are not removable.
|
||||
for (let id in this.webapps) {
|
||||
if (id in aData || this.webapps[id].removable)
|
||||
continue;
|
||||
delete this.webapps[id];
|
||||
// Remove the permissions, cookies and private data for this app.
|
||||
let localId = this.webapps[id].localId;
|
||||
let permMgr = Cc["@mozilla.org/permissionmanager;1"]
|
||||
.getService(Ci.nsIPermissionManager);
|
||||
permMgr.RemovePermissionsForApp(localId);
|
||||
Services.cookies.removeCookiesForApp(localId, false);
|
||||
this._clearPrivateData(localId, false);
|
||||
}
|
||||
|
||||
let appDir = FileUtils.getDir("coreAppsDir", ["webapps"], false);
|
||||
// 2.c
|
||||
for (let id in aData) {
|
||||
// Core apps have ids matching their domain name (eg: dialer.gaiamobile.org)
|
||||
// Use that property to check if they are new or not.
|
||||
if (!(id in this.webapps)) {
|
||||
this.webapps[id] = aData[id];
|
||||
this.webapps[id].basePath = appDir.path;
|
||||
|
||||
// Create a new localId.
|
||||
this.webapps[id].localId = this._nextLocalId();
|
||||
|
||||
// Core apps are not removable.
|
||||
if (this.webapps[id].removable === undefined) {
|
||||
this.webapps[id].removable = false;
|
||||
}
|
||||
}
|
||||
|
||||
this.updatePermissionsForApp(id);
|
||||
}
|
||||
this.registerAppsHandlers();
|
||||
}).bind(this));
|
||||
} else {
|
||||
// At first run, set up the permissions for eng builds.
|
||||
let onAppsLoaded = (function onAppsLoaded() {
|
||||
if (runUpdate) {
|
||||
// At first run, set up the permissions
|
||||
for (let id in this.webapps) {
|
||||
this.updatePermissionsForApp(id);
|
||||
this.updateOfflineCacheForApp(id);
|
||||
}
|
||||
this.registerAppsHandlers();
|
||||
}
|
||||
} else {
|
||||
this.registerAppsHandlers();
|
||||
}
|
||||
}).bind(this);
|
||||
|
||||
this.loadCurrentRegistry((function() {
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
// if first run, merge the system apps.
|
||||
if (runUpdate)
|
||||
this.installSystemApps(onAppsLoaded);
|
||||
else
|
||||
onAppsLoaded();
|
||||
#else
|
||||
if (runUpdate) {
|
||||
// At first run, set up the permissions for desktop builds.
|
||||
for (let id in this.webapps) {
|
||||
this.updatePermissionsForApp(id);
|
||||
}
|
||||
}
|
||||
this.registerAppsHandlers();
|
||||
onAppsLoaded();
|
||||
#endif
|
||||
}).bind(this));
|
||||
},
|
||||
|
@ -475,14 +486,14 @@ let DOMApplicationRegistry = {
|
|||
aCallback(data);
|
||||
} catch (ex) {
|
||||
Cu.reportError("DOMApplicationRegistry: Could not parse JSON: " +
|
||||
aFile.path + " " + ex);
|
||||
aFile.path + " " + ex + "\n" + ex.stack);
|
||||
if (aCallback)
|
||||
aCallback(null);
|
||||
}
|
||||
});
|
||||
} catch (ex) {
|
||||
Cu.reportError("DOMApplicationRegistry: Could not read from " +
|
||||
aFile.path + " : " + ex);
|
||||
aFile.path + " : " + ex + "\n" + ex.stack);
|
||||
if (aCallback)
|
||||
aCallback(null);
|
||||
}
|
||||
|
@ -1725,6 +1736,10 @@ let DOMApplicationRegistry = {
|
|||
switch (message.name) {
|
||||
case "Webapps:ClearBrowserData":
|
||||
this._clearPrivateData(appId, true);
|
||||
// XXXbent This is a hack until bug 802366 is fixed. Currently all data
|
||||
// loaded in mozbrowser frames within an app believe that their
|
||||
// appId is 0.
|
||||
this._clearPrivateData(0, true);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
|
|
@ -179,7 +179,6 @@
|
|||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
#include "nsIWifi.h"
|
||||
#include "nsIWifiEventInits.h"
|
||||
#endif
|
||||
|
||||
// includes needed for the prototype chain interfaces
|
||||
|
@ -1619,10 +1618,6 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
|||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
NS_DEFINE_CLASSINFO_DATA(MozWifiStatusChangeEvent, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(MozWifiConnectionInfoEvent, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(Telephony, nsEventTargetSH,
|
||||
EVENTTARGET_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(TelephonyCall, nsEventTargetSH,
|
||||
|
@ -1733,10 +1728,6 @@ NS_DEFINE_EVENT_CTOR(Event)
|
|||
NS_DEFINE_EVENT_CTOR(UIEvent)
|
||||
NS_DEFINE_EVENT_CTOR(MouseEvent)
|
||||
NS_DEFINE_EVENT_CTOR(WheelEvent)
|
||||
#ifdef MOZ_B2G_RIL
|
||||
NS_DEFINE_EVENT_CTOR(MozWifiStatusChangeEvent)
|
||||
NS_DEFINE_EVENT_CTOR(MozWifiConnectionInfoEvent)
|
||||
#endif
|
||||
|
||||
#define MOZ_GENERATED_EVENT_LIST
|
||||
#define MOZ_GENERATED_EVENT(_event_interface) \
|
||||
|
|
|
@ -488,8 +488,6 @@ DOMCI_CLASS(MutationObserver)
|
|||
DOMCI_CLASS(MutationRecord)
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
DOMCI_CLASS(MozWifiStatusChangeEvent)
|
||||
DOMCI_CLASS(MozWifiConnectionInfoEvent)
|
||||
DOMCI_CLASS(Telephony)
|
||||
DOMCI_CLASS(TelephonyCall)
|
||||
DOMCI_CLASS(CallEvent)
|
||||
|
|
|
@ -181,31 +181,6 @@ DatabaseInfo::Remove(nsIAtom* aId)
|
|||
}
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
EnumerateDatabasesRemoveOrigin(nsISupports* aId,
|
||||
DatabaseInfo*& aDatabaseInfo,
|
||||
void* aUserArg)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
const nsACString* origin = static_cast<const nsACString*>(aUserArg);
|
||||
return aDatabaseInfo->origin.Equals(*origin) ?
|
||||
PL_DHASH_REMOVE :
|
||||
PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
DatabaseInfo::RemoveAllForOrigin(const nsACString& aOrigin)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (gDatabaseHash) {
|
||||
gDatabaseHash->Enumerate(EnumerateDatabasesRemoveOrigin,
|
||||
const_cast<nsACString*>(&aOrigin));
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
DatabaseInfo::GetObjectStoreNames(nsTArray<nsString>& aNames)
|
||||
{
|
||||
|
|
|
@ -62,8 +62,6 @@ struct DatabaseInfo : public DatabaseInfoGuts
|
|||
|
||||
static void Remove(nsIAtom* aId);
|
||||
|
||||
static void RemoveAllForOrigin(const nsACString& aOrigin);
|
||||
|
||||
bool GetObjectStoreNames(nsTArray<nsString>& aNames);
|
||||
bool ContainsStoreName(const nsAString& aName);
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "mozilla/storage.h"
|
||||
#include "mozilla/unused.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "nsDOMClassInfo.h"
|
||||
#include "nsDOMLists.h"
|
||||
|
@ -33,6 +34,7 @@
|
|||
#include "nsContentUtils.h"
|
||||
|
||||
#include "ipc/IndexedDBChild.h"
|
||||
#include "ipc/IndexedDBParent.h"
|
||||
|
||||
USING_INDEXEDDB_NAMESPACE
|
||||
using mozilla::dom::ContentParent;
|
||||
|
@ -269,12 +271,14 @@ IDBDatabase::Invalidate()
|
|||
if (owner) {
|
||||
IndexedDatabaseManager::CancelPromptsForWindow(owner);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
IDBDatabase::IsInvalidated()
|
||||
{
|
||||
return mInvalidated;
|
||||
DatabaseInfo::Remove(mDatabaseId);
|
||||
|
||||
// And let the child process know as well.
|
||||
if (mActorParent) {
|
||||
NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
|
||||
mozilla::unused << mActorParent->SendInvalidate();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -299,8 +303,9 @@ IDBDatabase::DisconnectFromActor()
|
|||
}
|
||||
|
||||
bool
|
||||
IDBDatabase::IsDisconnectedFromActor()
|
||||
IDBDatabase::IsDisconnectedFromActor() const
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
return mDisconnected;
|
||||
}
|
||||
|
||||
|
@ -330,7 +335,7 @@ IDBDatabase::CloseInternal(bool aIsDead)
|
|||
}
|
||||
|
||||
// And let the parent process know as well.
|
||||
if (mActorChild) {
|
||||
if (mActorChild && !IsInvalidated()) {
|
||||
NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
|
||||
mActorChild->SendClose(aIsDead);
|
||||
}
|
||||
|
@ -338,7 +343,7 @@ IDBDatabase::CloseInternal(bool aIsDead)
|
|||
}
|
||||
|
||||
bool
|
||||
IDBDatabase::IsClosed()
|
||||
IDBDatabase::IsClosed() const
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
return mClosed;
|
||||
|
|
|
@ -74,12 +74,12 @@ public:
|
|||
return mDatabaseInfo;
|
||||
}
|
||||
|
||||
const nsString& Name()
|
||||
const nsString& Name() const
|
||||
{
|
||||
return mName;
|
||||
}
|
||||
|
||||
const nsString& FilePath()
|
||||
const nsString& FilePath() const
|
||||
{
|
||||
return mFilePath;
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ public:
|
|||
return doc.forget();
|
||||
}
|
||||
|
||||
nsCString& Origin()
|
||||
const nsCString& Origin() const
|
||||
{
|
||||
return mASCIIOrigin;
|
||||
}
|
||||
|
@ -103,20 +103,24 @@ public:
|
|||
void Invalidate();
|
||||
|
||||
// Whether or not the database has been invalidated. If it has then no further
|
||||
// transactions for this database will be allowed to run.
|
||||
bool IsInvalidated();
|
||||
// transactions for this database will be allowed to run. This function may be
|
||||
// called on any thread.
|
||||
bool IsInvalidated() const
|
||||
{
|
||||
return mInvalidated;
|
||||
}
|
||||
|
||||
void DisconnectFromActor();
|
||||
|
||||
// Whether or not the database has been disconnected from its actor. If true
|
||||
// it is not safe to send any IPC messages to the actor representing this db
|
||||
// or any of its subactors.
|
||||
bool IsDisconnectedFromActor();
|
||||
bool IsDisconnectedFromActor() const;
|
||||
|
||||
void CloseInternal(bool aIsDead);
|
||||
|
||||
// Whether or not the database has had Close called on it.
|
||||
bool IsClosed();
|
||||
bool IsClosed() const;
|
||||
|
||||
void EnterSetVersionTransaction();
|
||||
void ExitSetVersionTransaction();
|
||||
|
|
|
@ -541,8 +541,9 @@ IDBFactory::OpenCommon(const nsAString& aName,
|
|||
IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
|
||||
NS_ASSERTION(mgr, "This should never be null!");
|
||||
|
||||
rv =
|
||||
mgr->WaitForOpenAllowed(mASCIIOrigin, openHelper->Id(), permissionHelper);
|
||||
rv =
|
||||
mgr->WaitForOpenAllowed(OriginOrPatternString::FromOrigin(mASCIIOrigin),
|
||||
openHelper->Id(), permissionHelper);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
}
|
||||
else if (aDeleting) {
|
||||
|
|
|
@ -175,6 +175,44 @@ struct SerializedStructuredCloneWriteInfo
|
|||
uint64_t offsetToKeyProp;
|
||||
};
|
||||
|
||||
class OriginOrPatternString : public nsCString
|
||||
{
|
||||
public:
|
||||
static OriginOrPatternString
|
||||
FromOrigin(const nsACString& aOrigin)
|
||||
{
|
||||
return OriginOrPatternString(aOrigin, true);
|
||||
}
|
||||
|
||||
static OriginOrPatternString
|
||||
FromPattern(const nsACString& aPattern)
|
||||
{
|
||||
return OriginOrPatternString(aPattern, false);
|
||||
}
|
||||
|
||||
bool
|
||||
IsOrigin() const
|
||||
{
|
||||
return mIsOrigin;
|
||||
}
|
||||
|
||||
bool
|
||||
IsPattern() const
|
||||
{
|
||||
return !mIsOrigin;
|
||||
}
|
||||
|
||||
private:
|
||||
OriginOrPatternString(const nsACString& aOriginOrPattern, bool aIsOrigin)
|
||||
: nsCString(aOriginOrPattern), mIsOrigin(aIsOrigin)
|
||||
{ }
|
||||
|
||||
bool
|
||||
operator==(const OriginOrPatternString& aOther) MOZ_DELETE;
|
||||
|
||||
bool mIsOrigin;
|
||||
};
|
||||
|
||||
END_INDEXEDDB_NAMESPACE
|
||||
|
||||
#endif // mozilla_dom_indexeddb_indexeddatabase_h__
|
||||
|
|
|
@ -5,14 +5,15 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "IndexedDatabaseManager.h"
|
||||
#include "DatabaseInfo.h"
|
||||
|
||||
#include "mozIApplicationClearPrivateDataParams.h"
|
||||
#include "nsIAtom.h"
|
||||
#include "nsIConsoleService.h"
|
||||
#include "nsIDOMScriptObjectFactory.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsIFileStorage.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsIScriptError.h"
|
||||
#include "nsIScriptObjectPrincipal.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
|
@ -27,8 +28,10 @@
|
|||
#include "mozilla/storage.h"
|
||||
#include "nsAppDirectoryServiceDefs.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsCRTGlue.h"
|
||||
#include "nsDirectoryServiceUtils.h"
|
||||
#include "nsEventDispatcher.h"
|
||||
#include "nsScriptSecurityManager.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsXPCOM.h"
|
||||
#include "nsXPCOMPrivate.h"
|
||||
|
@ -133,34 +136,247 @@ EnumerateToTArray(const nsACString& aKey,
|
|||
NS_ASSERTION(aValue, "Null pointer!");
|
||||
NS_ASSERTION(aUserArg, "Null pointer!");
|
||||
|
||||
nsTArray<T>* array =
|
||||
static_cast<nsTArray<T>*>(aUserArg);
|
||||
|
||||
if (!array->AppendElements(*aValue)) {
|
||||
NS_WARNING("Out of memory!");
|
||||
return PL_DHASH_STOP;
|
||||
}
|
||||
|
||||
static_cast<nsTArray<T>*>(aUserArg)->AppendElements(*aValue);
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
bool
|
||||
PatternMatchesOrigin(const nsACString& aPatternString, const nsACString& aOrigin)
|
||||
{
|
||||
// Aren't we smart!
|
||||
return StringBeginsWith(aOrigin, aPatternString);
|
||||
}
|
||||
|
||||
enum MozBrowserPatternFlag
|
||||
{
|
||||
MozBrowser = 0,
|
||||
NotMozBrowser,
|
||||
IgnoreMozBrowser
|
||||
};
|
||||
|
||||
// Use one of the friendly overloads below.
|
||||
void
|
||||
GetOriginPatternString(uint32_t aAppId, MozBrowserPatternFlag aBrowserFlag,
|
||||
const nsACString& aOrigin, nsAutoCString& _retval)
|
||||
{
|
||||
NS_ASSERTION(aAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID,
|
||||
"Bad appId!");
|
||||
NS_ASSERTION(aOrigin.IsEmpty() || aBrowserFlag != IgnoreMozBrowser,
|
||||
"Bad args!");
|
||||
|
||||
if (aOrigin.IsEmpty()) {
|
||||
_retval.Truncate();
|
||||
|
||||
_retval.AppendInt(aAppId);
|
||||
_retval.Append('+');
|
||||
|
||||
if (aBrowserFlag != IgnoreMozBrowser) {
|
||||
if (aBrowserFlag == MozBrowser) {
|
||||
_retval.Append('t');
|
||||
}
|
||||
else {
|
||||
_retval.Append('f');
|
||||
}
|
||||
_retval.Append('+');
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (aAppId != nsIScriptSecurityManager::NO_APP_ID ||
|
||||
aBrowserFlag == MozBrowser) {
|
||||
nsAutoCString pattern;
|
||||
GetOriginPatternString(aAppId, aBrowserFlag, EmptyCString(), pattern);
|
||||
NS_ASSERTION(PatternMatchesOrigin(pattern, aOrigin),
|
||||
"Origin doesn't match parameters!");
|
||||
}
|
||||
#endif
|
||||
|
||||
_retval = aOrigin;
|
||||
}
|
||||
|
||||
void
|
||||
GetOriginPatternString(uint32_t aAppId, nsAutoCString& _retval)
|
||||
{
|
||||
return GetOriginPatternString(aAppId, IgnoreMozBrowser, EmptyCString(),
|
||||
_retval);
|
||||
}
|
||||
|
||||
void
|
||||
GetOriginPatternString(uint32_t aAppId, bool aBrowserOnly,
|
||||
nsAutoCString& _retval)
|
||||
{
|
||||
return GetOriginPatternString(aAppId,
|
||||
aBrowserOnly ? MozBrowser : NotMozBrowser,
|
||||
EmptyCString(), _retval);
|
||||
}
|
||||
|
||||
void
|
||||
GetOriginPatternString(uint32_t aAppId, bool aBrowserOnly,
|
||||
const nsACString& aOrigin, nsAutoCString& _retval)
|
||||
{
|
||||
return GetOriginPatternString(aAppId,
|
||||
aBrowserOnly ? MozBrowser : NotMozBrowser,
|
||||
aOrigin, _retval);
|
||||
}
|
||||
|
||||
void
|
||||
GetOriginPatternStringMaybeIgnoreBrowser(uint32_t aAppId, bool aBrowserOnly,
|
||||
nsAutoCString& _retval)
|
||||
{
|
||||
return GetOriginPatternString(aAppId,
|
||||
aBrowserOnly ? MozBrowser : IgnoreMozBrowser,
|
||||
EmptyCString(), _retval);
|
||||
}
|
||||
|
||||
template <class ValueType>
|
||||
class PatternMatchArray : public nsAutoTArray<ValueType, 20>
|
||||
{
|
||||
typedef PatternMatchArray<ValueType> SelfType;
|
||||
|
||||
struct Closure
|
||||
{
|
||||
Closure(SelfType& aSelf, const nsACString& aPattern)
|
||||
: mSelf(aSelf), mPattern(aPattern)
|
||||
{ }
|
||||
|
||||
SelfType& mSelf;
|
||||
const nsACString& mPattern;
|
||||
};
|
||||
|
||||
public:
|
||||
template <class T>
|
||||
void
|
||||
Find(const T& aHashtable,
|
||||
const nsACString& aPattern)
|
||||
{
|
||||
SelfType::Clear();
|
||||
|
||||
Closure closure(*this, aPattern);
|
||||
aHashtable.EnumerateRead(SelfType::Enumerate, &closure);
|
||||
}
|
||||
|
||||
private:
|
||||
static PLDHashOperator
|
||||
Enumerate(const nsACString& aKey,
|
||||
nsTArray<ValueType>* aValue,
|
||||
void* aUserArg)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(!aKey.IsEmpty(), "Empty key!");
|
||||
NS_ASSERTION(aValue, "Null pointer!");
|
||||
NS_ASSERTION(aUserArg, "Null pointer!");
|
||||
|
||||
Closure* closure = static_cast<Closure*>(aUserArg);
|
||||
|
||||
if (PatternMatchesOrigin(closure->mPattern, aKey)) {
|
||||
closure->mSelf.AppendElements(*aValue);
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
};
|
||||
|
||||
typedef PatternMatchArray<IDBDatabase*> DatabasePatternMatchArray;
|
||||
|
||||
PLDHashOperator
|
||||
InvalidateAllFileManagers(const nsACString& aKey,
|
||||
nsTArray<nsRefPtr<FileManager> >* aValue,
|
||||
void* aUserArg)
|
||||
InvalidateAndRemoveFileManagers(
|
||||
const nsACString& aKey,
|
||||
nsAutoPtr<nsTArray<nsRefPtr<FileManager> > >& aValue,
|
||||
void* aUserArg)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(!aKey.IsEmpty(), "Empty key!");
|
||||
NS_ASSERTION(aValue, "Null pointer!");
|
||||
|
||||
for (uint32_t i = 0; i < aValue->Length(); i++) {
|
||||
nsRefPtr<FileManager> fileManager = aValue->ElementAt(i);
|
||||
fileManager->Invalidate();
|
||||
const nsACString* pattern =
|
||||
static_cast<const nsACString*>(aUserArg);
|
||||
|
||||
if (!pattern || PatternMatchesOrigin(*pattern, aKey)) {
|
||||
for (uint32_t i = 0; i < aValue->Length(); i++) {
|
||||
nsRefPtr<FileManager>& fileManager = aValue->ElementAt(i);
|
||||
fileManager->Invalidate();
|
||||
}
|
||||
return PL_DHASH_REMOVE;
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
SanitizeOriginString(nsCString& aOrigin)
|
||||
{
|
||||
// We want profiles to be platform-independent so we always need to replace
|
||||
// the same characters on every platform. Windows has the most extensive set
|
||||
// of illegal characters so we use its FILE_ILLEGAL_CHARACTERS and
|
||||
// FILE_PATH_SEPARATOR.
|
||||
static const char kReplaceChars[] = CONTROL_CHARACTERS "/:*?\"<>|\\";
|
||||
|
||||
#ifdef XP_WIN
|
||||
NS_ASSERTION(!strcmp(kReplaceChars,
|
||||
FILE_ILLEGAL_CHARACTERS FILE_PATH_SEPARATOR),
|
||||
"Illegal file characters have changed!");
|
||||
#endif
|
||||
|
||||
aOrigin.ReplaceChar(kReplaceChars, '+');
|
||||
}
|
||||
|
||||
nsresult
|
||||
GetASCIIOriginFromURI(nsIURI* aURI,
|
||||
uint32_t aAppId,
|
||||
bool aInMozBrowser,
|
||||
nsACString& aOrigin)
|
||||
{
|
||||
NS_ASSERTION(aURI, "Null uri!");
|
||||
|
||||
nsCString origin;
|
||||
mozilla::GetExtendedOrigin(aURI, aAppId, aInMozBrowser, origin);
|
||||
|
||||
if (origin.IsEmpty()) {
|
||||
NS_WARNING("GetExtendedOrigin returned empty string!");
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
||||
aOrigin.Assign(origin);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
GetASCIIOriginFromPrincipal(nsIPrincipal* aPrincipal,
|
||||
nsACString& aOrigin)
|
||||
{
|
||||
NS_ASSERTION(aPrincipal, "Don't hand me a null principal!");
|
||||
|
||||
static const char kChromeOrigin[] = "chrome";
|
||||
|
||||
nsCString origin;
|
||||
if (nsContentUtils::IsSystemPrincipal(aPrincipal)) {
|
||||
origin.AssignLiteral(kChromeOrigin);
|
||||
}
|
||||
else {
|
||||
bool isNullPrincipal;
|
||||
nsresult rv = aPrincipal->GetIsNullPrincipal(&isNullPrincipal);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
if (isNullPrincipal) {
|
||||
NS_WARNING("IndexedDB not supported from this principal!");
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
||||
rv = aPrincipal->GetExtendedOrigin(origin);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
if (origin.EqualsLiteral(kChromeOrigin)) {
|
||||
NS_WARNING("Non-chrome principal can't use chrome origin!");
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
aOrigin.Assign(origin);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
IndexedDatabaseManager::IndexedDatabaseManager()
|
||||
|
@ -297,10 +513,10 @@ IndexedDatabaseManager::GetDirectoryForOrigin(const nsACString& aASCIIOrigin,
|
|||
rv = directory->InitWithPath(GetBaseDirectory());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
NS_ConvertASCIItoUTF16 originSanitized(aASCIIOrigin);
|
||||
originSanitized.ReplaceChar(":/", '+');
|
||||
nsAutoCString originSanitized(aASCIIOrigin);
|
||||
SanitizeOriginString(originSanitized);
|
||||
|
||||
rv = directory->Append(originSanitized);
|
||||
rv = directory->Append(NS_ConvertASCIItoUTF16(originSanitized));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
directory.forget(aDirectory);
|
||||
|
@ -406,6 +622,37 @@ IndexedDatabaseManager::FireWindowOnError(nsPIDOMWindow* aOwner,
|
|||
return consoleService->LogMessage(scriptError);
|
||||
}
|
||||
|
||||
// static
|
||||
bool
|
||||
IndexedDatabaseManager::OriginMatchesApp(const nsACString& aOrigin,
|
||||
uint32_t aAppId)
|
||||
{
|
||||
NS_ASSERTION(!aOrigin.IsEmpty(), "Empty origin!");
|
||||
NS_ASSERTION(aAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID,
|
||||
"Bad appId!");
|
||||
|
||||
nsAutoCString pattern;
|
||||
GetOriginPatternString(aAppId, pattern);
|
||||
|
||||
return PatternMatchesOrigin(pattern, aOrigin);
|
||||
}
|
||||
|
||||
// static
|
||||
bool
|
||||
IndexedDatabaseManager::OriginMatchesApp(const nsACString& aOrigin,
|
||||
uint32_t aAppId,
|
||||
bool aInMozBrowser)
|
||||
{
|
||||
NS_ASSERTION(!aOrigin.IsEmpty(), "Empty origin!");
|
||||
NS_ASSERTION(aAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID,
|
||||
"Bad appId!");
|
||||
|
||||
nsAutoCString pattern;
|
||||
GetOriginPatternString(aAppId, aInMozBrowser, pattern);
|
||||
|
||||
return PatternMatchesOrigin(pattern, aOrigin);
|
||||
}
|
||||
|
||||
bool
|
||||
IndexedDatabaseManager::RegisterDatabase(IDBDatabase* aDatabase)
|
||||
{
|
||||
|
@ -466,15 +713,16 @@ IndexedDatabaseManager::OnUsageCheckComplete(AsyncUsageRunnable* aRunnable)
|
|||
}
|
||||
|
||||
nsresult
|
||||
IndexedDatabaseManager::WaitForOpenAllowed(const nsACString& aOrigin,
|
||||
nsIAtom* aId,
|
||||
nsIRunnable* aRunnable)
|
||||
IndexedDatabaseManager::WaitForOpenAllowed(
|
||||
const OriginOrPatternString& aOriginOrPattern,
|
||||
nsIAtom* aId,
|
||||
nsIRunnable* aRunnable)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(!aOrigin.IsEmpty(), "Empty origin!");
|
||||
NS_ASSERTION(!aOriginOrPattern.IsEmpty(), "Empty pattern!");
|
||||
NS_ASSERTION(aRunnable, "Null pointer!");
|
||||
|
||||
nsAutoPtr<SynchronizedOp> op(new SynchronizedOp(aOrigin, aId));
|
||||
nsAutoPtr<SynchronizedOp> op(new SynchronizedOp(aOriginOrPattern, aId));
|
||||
|
||||
// See if this runnable needs to wait.
|
||||
bool delayed = false;
|
||||
|
@ -501,16 +749,18 @@ IndexedDatabaseManager::WaitForOpenAllowed(const nsACString& aOrigin,
|
|||
}
|
||||
|
||||
void
|
||||
IndexedDatabaseManager::AllowNextSynchronizedOp(const nsACString& aOrigin,
|
||||
nsIAtom* aId)
|
||||
IndexedDatabaseManager::AllowNextSynchronizedOp(
|
||||
const OriginOrPatternString& aOriginOrPattern,
|
||||
nsIAtom* aId)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(!aOrigin.IsEmpty(), "Empty origin!");
|
||||
NS_ASSERTION(!aOriginOrPattern.IsEmpty(), "Empty origin/pattern!");
|
||||
|
||||
uint32_t count = mSynchronizedOps.Length();
|
||||
for (uint32_t index = 0; index < count; index++) {
|
||||
nsAutoPtr<SynchronizedOp>& op = mSynchronizedOps[index];
|
||||
if (op->mOrigin.Equals(aOrigin)) {
|
||||
if (op->mOriginOrPattern.IsOrigin() == aOriginOrPattern.IsOrigin() &&
|
||||
op->mOriginOrPattern == aOriginOrPattern) {
|
||||
if (op->mId == aId) {
|
||||
NS_ASSERTION(op->mDatabases.IsEmpty(), "How did this happen?");
|
||||
|
||||
|
@ -531,7 +781,7 @@ IndexedDatabaseManager::AllowNextSynchronizedOp(const nsACString& aOrigin,
|
|||
|
||||
nsresult
|
||||
IndexedDatabaseManager::AcquireExclusiveAccess(
|
||||
const nsACString& aOrigin,
|
||||
const nsACString& aPattern,
|
||||
IDBDatabase* aDatabase,
|
||||
AsyncConnectionHelper* aHelper,
|
||||
nsIRunnable* aRunnable,
|
||||
|
@ -544,26 +794,26 @@ IndexedDatabaseManager::AcquireExclusiveAccess(
|
|||
|
||||
// Find the right SynchronizedOp.
|
||||
SynchronizedOp* op =
|
||||
FindSynchronizedOp(aOrigin, aDatabase ? aDatabase->Id() : nullptr);
|
||||
FindSynchronizedOp(aPattern, aDatabase ? aDatabase->Id() : nullptr);
|
||||
|
||||
NS_ASSERTION(op, "We didn't find a SynchronizedOp?");
|
||||
NS_ASSERTION(!op->mHelper, "SynchronizedOp already has a helper?!?");
|
||||
NS_ASSERTION(!op->mRunnable, "SynchronizedOp already has a runnable?!?");
|
||||
|
||||
nsTArray<IDBDatabase*>* array;
|
||||
mLiveDatabases.Get(aOrigin, &array);
|
||||
DatabasePatternMatchArray matches;
|
||||
matches.Find(mLiveDatabases, aPattern);
|
||||
|
||||
// We need to wait for the databases to go away.
|
||||
// Hold on to all database objects that represent the same database file
|
||||
// (except the one that is requesting this version change).
|
||||
nsTArray<nsRefPtr<IDBDatabase> > liveDatabases;
|
||||
|
||||
if (array) {
|
||||
if (!matches.IsEmpty()) {
|
||||
if (aDatabase) {
|
||||
// Grab all databases that are not yet closed but whose database id match
|
||||
// the one we're looking for.
|
||||
for (uint32_t index = 0; index < array->Length(); index++) {
|
||||
IDBDatabase*& database = array->ElementAt(index);
|
||||
for (uint32_t index = 0; index < matches.Length(); index++) {
|
||||
IDBDatabase*& database = matches[index];
|
||||
if (!database->IsClosed() &&
|
||||
database != aDatabase &&
|
||||
database->Id() == aDatabase->Id()) {
|
||||
|
@ -574,7 +824,7 @@ IndexedDatabaseManager::AcquireExclusiveAccess(
|
|||
else {
|
||||
// We want *all* databases, even those that are closed, if we're going to
|
||||
// clear the origin.
|
||||
liveDatabases.AppendElements(*array);
|
||||
liveDatabases.AppendElements(matches);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -986,18 +1236,8 @@ IndexedDatabaseManager::GetASCIIOriginFromWindow(nsPIDOMWindow* aWindow,
|
|||
nsCOMPtr<nsIPrincipal> principal = sop->GetPrincipal();
|
||||
NS_ENSURE_TRUE(principal, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
if (nsContentUtils::IsSystemPrincipal(principal)) {
|
||||
aASCIIOrigin.AssignLiteral("chrome");
|
||||
}
|
||||
else {
|
||||
nsresult rv = principal->GetExtendedOrigin(aASCIIOrigin);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
if (aASCIIOrigin.EqualsLiteral("null")) {
|
||||
NS_WARNING("IndexedDB databases not allowed for this principal!");
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
}
|
||||
nsresult rv = GetASCIIOriginFromPrincipal(principal, aASCIIOrigin);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1053,17 +1293,12 @@ IndexedDatabaseManager::AddFileManager(const nsACString& aOrigin,
|
|||
}
|
||||
|
||||
void
|
||||
IndexedDatabaseManager::InvalidateFileManagersForOrigin(
|
||||
const nsACString& aOrigin)
|
||||
IndexedDatabaseManager::InvalidateFileManagersForPattern(
|
||||
const nsACString& aPattern)
|
||||
{
|
||||
nsTArray<nsRefPtr<FileManager> >* array;
|
||||
if (mFileManagers.Get(aOrigin, &array)) {
|
||||
for (uint32_t i = 0; i < array->Length(); i++) {
|
||||
nsRefPtr<FileManager> fileManager = array->ElementAt(i);
|
||||
fileManager->Invalidate();
|
||||
}
|
||||
mFileManagers.Remove(aOrigin);
|
||||
}
|
||||
NS_ASSERTION(!aPattern.IsEmpty(), "Empty pattern!");
|
||||
mFileManagers.Enumerate(InvalidateAndRemoveFileManagers,
|
||||
const_cast<nsACString*>(&aPattern));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1173,39 +1408,103 @@ IndexedDatabaseManager::RunSynchronizedOp(IDBDatabase* aDatabase,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
IndexedDatabaseManager::SynchronizedOp*
|
||||
IndexedDatabaseManager::FindSynchronizedOp(const nsACString& aPattern,
|
||||
nsIAtom* aId)
|
||||
{
|
||||
for (uint32_t index = 0; index < mSynchronizedOps.Length(); index++) {
|
||||
const nsAutoPtr<SynchronizedOp>& currentOp = mSynchronizedOps[index];
|
||||
if (PatternMatchesOrigin(aPattern, currentOp->mOriginOrPattern) &&
|
||||
(!currentOp->mId || currentOp->mId == aId)) {
|
||||
return currentOp;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsresult
|
||||
IndexedDatabaseManager::ClearDatabasesForApp(uint32_t aAppId, bool aBrowserOnly)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(aAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID,
|
||||
"Bad appId!");
|
||||
|
||||
// This only works from the main process.
|
||||
NS_ENSURE_TRUE(IsMainProcess(), NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
nsAutoCString pattern;
|
||||
GetOriginPatternStringMaybeIgnoreBrowser(aAppId, aBrowserOnly, pattern);
|
||||
|
||||
// If there is a pending or running clear operation for this app, return
|
||||
// immediately.
|
||||
if (IsClearOriginPending(pattern)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
OriginOrPatternString oops = OriginOrPatternString::FromPattern(pattern);
|
||||
|
||||
// Queue up the origin clear runnable.
|
||||
nsRefPtr<OriginClearRunnable> runnable = new OriginClearRunnable(oops);
|
||||
|
||||
nsresult rv = WaitForOpenAllowed(oops, nullptr, runnable);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
runnable->AdvanceState();
|
||||
|
||||
// Give the runnable some help by invalidating any databases in the way.
|
||||
DatabasePatternMatchArray matches;
|
||||
matches.Find(mLiveDatabases, pattern);
|
||||
|
||||
for (uint32_t index = 0; index < matches.Length(); index++) {
|
||||
// We need to grab references here to prevent the database from dying while
|
||||
// we invalidate it.
|
||||
nsRefPtr<IDBDatabase> database = matches[index];
|
||||
database->Invalidate();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS2(IndexedDatabaseManager, nsIIndexedDatabaseManager,
|
||||
nsIObserver)
|
||||
|
||||
NS_IMETHODIMP
|
||||
IndexedDatabaseManager::GetUsageForURI(
|
||||
nsIURI* aURI,
|
||||
nsIIndexedDatabaseUsageCallback* aCallback)
|
||||
nsIIndexedDatabaseUsageCallback* aCallback,
|
||||
uint32_t aAppId,
|
||||
bool aInMozBrowserOnly,
|
||||
uint8_t aOptionalArgCount)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aURI);
|
||||
NS_ENSURE_ARG_POINTER(aCallback);
|
||||
|
||||
// This only works from the main process.
|
||||
NS_ENSURE_TRUE(IsMainProcess(), NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
if (!aOptionalArgCount) {
|
||||
aAppId = nsIScriptSecurityManager::NO_APP_ID;
|
||||
}
|
||||
|
||||
// Figure out which origin we're dealing with.
|
||||
nsCString origin;
|
||||
nsresult rv = nsContentUtils::GetASCIIOrigin(aURI, origin);
|
||||
nsresult rv = GetASCIIOriginFromURI(aURI, aAppId, aInMozBrowserOnly, origin);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
OriginOrPatternString oops = OriginOrPatternString::FromOrigin(origin);
|
||||
|
||||
nsRefPtr<AsyncUsageRunnable> runnable =
|
||||
new AsyncUsageRunnable(aURI, origin, aCallback);
|
||||
new AsyncUsageRunnable(aAppId, aInMozBrowserOnly, oops, aURI, aCallback);
|
||||
|
||||
nsRefPtr<AsyncUsageRunnable>* newRunnable =
|
||||
mUsageRunnables.AppendElement(runnable);
|
||||
NS_ENSURE_TRUE(newRunnable, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
// Non-standard URIs can't create databases anyway so fire the callback
|
||||
// immediately.
|
||||
if (origin.EqualsLiteral("null")) {
|
||||
return runnable->TakeShortcut();
|
||||
}
|
||||
|
||||
// Otherwise put the computation runnable in the queue.
|
||||
rv = WaitForOpenAllowed(origin, nullptr, runnable);
|
||||
rv = WaitForOpenAllowed(oops, nullptr, runnable);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
runnable->AdvanceState();
|
||||
|
@ -1216,77 +1515,95 @@ IndexedDatabaseManager::GetUsageForURI(
|
|||
NS_IMETHODIMP
|
||||
IndexedDatabaseManager::CancelGetUsageForURI(
|
||||
nsIURI* aURI,
|
||||
nsIIndexedDatabaseUsageCallback* aCallback)
|
||||
nsIIndexedDatabaseUsageCallback* aCallback,
|
||||
uint32_t aAppId,
|
||||
bool aInMozBrowserOnly,
|
||||
uint8_t aOptionalArgCount)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aURI);
|
||||
NS_ENSURE_ARG_POINTER(aCallback);
|
||||
|
||||
// This only works from the main process.
|
||||
NS_ENSURE_TRUE(IsMainProcess(), NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
if (!aOptionalArgCount) {
|
||||
aAppId = nsIScriptSecurityManager::NO_APP_ID;
|
||||
}
|
||||
|
||||
// See if one of our pending callbacks matches both the URI and the callback
|
||||
// given. Cancel an remove it if so.
|
||||
for (uint32_t index = 0; index < mUsageRunnables.Length(); index++) {
|
||||
nsRefPtr<AsyncUsageRunnable>& runnable = mUsageRunnables[index];
|
||||
|
||||
bool equals;
|
||||
nsresult rv = runnable->mURI->Equals(aURI, &equals);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (runnable->mAppId == aAppId &&
|
||||
runnable->mInMozBrowserOnly == aInMozBrowserOnly) {
|
||||
bool equals;
|
||||
nsresult rv = runnable->mURI->Equals(aURI, &equals);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (equals && SameCOMIdentity(aCallback, runnable->mCallback)) {
|
||||
runnable->Cancel();
|
||||
break;
|
||||
if (equals && SameCOMIdentity(aCallback, runnable->mCallback)) {
|
||||
runnable->Cancel();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
IndexedDatabaseManager::ClearDatabasesForURI(nsIURI* aURI)
|
||||
IndexedDatabaseManager::ClearDatabasesForURI(nsIURI* aURI,
|
||||
uint32_t aAppId,
|
||||
bool aInMozBrowserOnly,
|
||||
uint8_t aOptionalArgCount)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aURI);
|
||||
|
||||
// This only works from the main process.
|
||||
NS_ENSURE_TRUE(IsMainProcess(), NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
if (!aOptionalArgCount) {
|
||||
aAppId = nsIScriptSecurityManager::NO_APP_ID;
|
||||
}
|
||||
|
||||
// Figure out which origin we're dealing with.
|
||||
nsCString origin;
|
||||
nsresult rv = nsContentUtils::GetASCIIOrigin(aURI, origin);
|
||||
nsresult rv = GetASCIIOriginFromURI(aURI, aAppId, aInMozBrowserOnly, origin);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Non-standard URIs can't create databases anyway, so return immediately.
|
||||
if (origin.EqualsLiteral("null")) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsAutoCString pattern;
|
||||
GetOriginPatternString(aAppId, aInMozBrowserOnly, origin, pattern);
|
||||
|
||||
// If there is a pending or running clear operation for this origin, return
|
||||
// immediately.
|
||||
if (IsClearOriginPending(origin)) {
|
||||
if (IsClearOriginPending(pattern)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Queue up the origin clear runnable.
|
||||
nsRefPtr<OriginClearRunnable> runnable = new OriginClearRunnable(origin);
|
||||
OriginOrPatternString oops = OriginOrPatternString::FromPattern(pattern);
|
||||
|
||||
rv = WaitForOpenAllowed(origin, nullptr, runnable);
|
||||
// Queue up the origin clear runnable.
|
||||
nsRefPtr<OriginClearRunnable> runnable = new OriginClearRunnable(oops);
|
||||
|
||||
rv = WaitForOpenAllowed(oops, nullptr, runnable);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
runnable->AdvanceState();
|
||||
|
||||
// Give the runnable some help by invalidating any databases in the way. We
|
||||
// need to grab references to any live databases here to prevent them from
|
||||
// dying while we invalidate them.
|
||||
nsTArray<nsRefPtr<IDBDatabase> > liveDatabases;
|
||||
// Give the runnable some help by invalidating any databases in the way.
|
||||
DatabasePatternMatchArray matches;
|
||||
matches.Find(mLiveDatabases, pattern);
|
||||
|
||||
nsTArray<IDBDatabase*>* array;
|
||||
if (mLiveDatabases.Get(origin, &array)) {
|
||||
liveDatabases.AppendElements(*array);
|
||||
for (uint32_t index = 0; index < matches.Length(); index++) {
|
||||
// We need to grab references to any live databases here to prevent them
|
||||
// from dying while we invalidate them.
|
||||
nsRefPtr<IDBDatabase> database = matches[index];
|
||||
database->Invalidate();
|
||||
}
|
||||
|
||||
for (uint32_t index = 0; index < liveDatabases.Length(); index++) {
|
||||
liveDatabases[index]->Invalidate();
|
||||
}
|
||||
|
||||
DatabaseInfo::RemoveAllForOrigin(origin);
|
||||
|
||||
// After everything has been invalidated the helper should be dispatched to
|
||||
// the end of the event queue.
|
||||
return NS_OK;
|
||||
|
@ -1361,7 +1678,7 @@ IndexedDatabaseManager::Observe(nsISupports* aSubject,
|
|||
}
|
||||
}
|
||||
|
||||
mFileManagers.EnumerateRead(InvalidateAllFileManagers, nullptr);
|
||||
mFileManagers.Enumerate(InvalidateAndRemoveFileManagers, nullptr);
|
||||
|
||||
if (PR_ATOMIC_SET(&gClosed, 1)) {
|
||||
NS_ERROR("Close more than once?!");
|
||||
|
@ -1392,6 +1709,25 @@ IndexedDatabaseManager::Observe(nsISupports* aSubject,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!strcmp(aTopic, TOPIC_WEB_APP_CLEAR_DATA)) {
|
||||
nsCOMPtr<mozIApplicationClearPrivateDataParams> params =
|
||||
do_QueryInterface(aSubject);
|
||||
NS_ENSURE_TRUE(params, NS_ERROR_UNEXPECTED);
|
||||
|
||||
uint32_t appId;
|
||||
nsresult rv = params->GetAppId(&appId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
bool browserOnly;
|
||||
rv = params->GetBrowserOnly(&browserOnly);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = ClearDatabasesForApp(appId, browserOnly);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_NOTREACHED("Unknown topic!");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
@ -1408,16 +1744,75 @@ OriginClearRunnable::InvalidateOpenedDatabases(
|
|||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
OriginClearRunnable* self = static_cast<OriginClearRunnable*>(aClosure);
|
||||
|
||||
nsTArray<nsRefPtr<IDBDatabase> > databases;
|
||||
databases.SwapElements(aDatabases);
|
||||
|
||||
for (uint32_t index = 0; index < databases.Length(); index++) {
|
||||
databases[index]->Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
DatabaseInfo::RemoveAllForOrigin(self->mOrigin);
|
||||
void
|
||||
IndexedDatabaseManager::
|
||||
OriginClearRunnable::DeleteFiles(IndexedDatabaseManager* aManager)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(aManager, "Don't pass me null!");
|
||||
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIFile> directory =
|
||||
do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
|
||||
rv = directory->InitWithPath(aManager->GetBaseDirectory());
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> entries;
|
||||
rv = directory->GetDirectoryEntries(getter_AddRefs(entries));
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
|
||||
if (!entries) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCString originSanitized(mOriginOrPattern);
|
||||
SanitizeOriginString(originSanitized);
|
||||
|
||||
bool hasMore;
|
||||
while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) && hasMore) {
|
||||
nsCOMPtr<nsISupports> entry;
|
||||
rv = entries->GetNext(getter_AddRefs(entry));
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
|
||||
nsCOMPtr<nsIFile> file = do_QueryInterface(entry);
|
||||
NS_ASSERTION(file, "Don't know what this is!");
|
||||
|
||||
bool isDirectory;
|
||||
rv = file->IsDirectory(&isDirectory);
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
|
||||
if (!isDirectory) {
|
||||
NS_WARNING("Something in the IndexedDB directory that doesn't belong!");
|
||||
continue;
|
||||
}
|
||||
|
||||
nsString leafName;
|
||||
rv = file->GetLeafName(leafName);
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
|
||||
// Skip databases for other apps.
|
||||
if (!PatternMatchesOrigin(originSanitized,
|
||||
NS_ConvertUTF16toUTF8(leafName))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (NS_FAILED(file->Remove(true))) {
|
||||
// This should never fail if we've closed all database connections
|
||||
// correctly...
|
||||
NS_ERROR("Failed to remove directory!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -1439,9 +1834,9 @@ IndexedDatabaseManager::OriginClearRunnable::Run()
|
|||
|
||||
// Now we have to wait until the thread pool is done with all of the
|
||||
// databases we care about.
|
||||
nsresult rv =
|
||||
mgr->AcquireExclusiveAccess(mOrigin, this, InvalidateOpenedDatabases,
|
||||
this);
|
||||
nsresult rv = mgr->AcquireExclusiveAccess(mOriginOrPattern, this,
|
||||
InvalidateOpenedDatabases,
|
||||
nullptr);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
|
@ -1452,24 +1847,7 @@ IndexedDatabaseManager::OriginClearRunnable::Run()
|
|||
|
||||
AdvanceState();
|
||||
|
||||
// Remove the directory that contains all our databases.
|
||||
nsCOMPtr<nsIFile> directory;
|
||||
nsresult rv =
|
||||
mgr->GetDirectoryForOrigin(mOrigin, getter_AddRefs(directory));
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed to get directory to remove!");
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
bool exists;
|
||||
rv = directory->Exists(&exists);
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
|
||||
"Failed to check that the directory exists!");
|
||||
|
||||
if (NS_SUCCEEDED(rv) && exists && NS_FAILED(directory->Remove(true))) {
|
||||
// This should never fail if we've closed all database connections
|
||||
// correctly...
|
||||
NS_ERROR("Failed to remove directory!");
|
||||
}
|
||||
}
|
||||
DeleteFiles(mgr);
|
||||
|
||||
// Now dispatch back to the main thread.
|
||||
if (NS_FAILED(NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL))) {
|
||||
|
@ -1483,10 +1861,10 @@ IndexedDatabaseManager::OriginClearRunnable::Run()
|
|||
case Complete: {
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
mgr->InvalidateFileManagersForOrigin(mOrigin);
|
||||
mgr->InvalidateFileManagersForPattern(mOriginOrPattern);
|
||||
|
||||
// Tell the IndexedDatabaseManager that we're done.
|
||||
mgr->AllowNextSynchronizedOp(mOrigin, nullptr);
|
||||
mgr->AllowNextSynchronizedOp(mOriginOrPattern, nullptr);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1501,19 +1879,24 @@ IndexedDatabaseManager::OriginClearRunnable::Run()
|
|||
}
|
||||
|
||||
IndexedDatabaseManager::AsyncUsageRunnable::AsyncUsageRunnable(
|
||||
uint32_t aAppId,
|
||||
bool aInMozBrowserOnly,
|
||||
const OriginOrPatternString& aOrigin,
|
||||
nsIURI* aURI,
|
||||
const nsACString& aOrigin,
|
||||
nsIIndexedDatabaseUsageCallback* aCallback)
|
||||
: mURI(aURI),
|
||||
mOrigin(aOrigin),
|
||||
mCallback(aCallback),
|
||||
mUsage(0),
|
||||
mFileUsage(0),
|
||||
mAppId(aAppId),
|
||||
mCanceled(0),
|
||||
mCallbackState(Pending)
|
||||
mOrigin(aOrigin),
|
||||
mCallbackState(Pending),
|
||||
mInMozBrowserOnly(aInMozBrowserOnly)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(aURI, "Null pointer!");
|
||||
NS_ASSERTION(aOrigin.IsOrigin(), "Expect origin only here!");
|
||||
NS_ASSERTION(!aOrigin.IsEmpty(), "Empty origin!");
|
||||
NS_ASSERTION(aCallback, "Null pointer!");
|
||||
}
|
||||
|
@ -1612,7 +1995,8 @@ IndexedDatabaseManager::AsyncUsageRunnable::RunInternal()
|
|||
if (!mCanceled) {
|
||||
uint64_t usage = mUsage;
|
||||
IncrementUsage(&usage, mFileUsage);
|
||||
mCallback->OnUsageResult(mURI, usage, mFileUsage);
|
||||
mCallback->OnUsageResult(mURI, usage, mFileUsage, mAppId,
|
||||
mInMozBrowserOnly);
|
||||
}
|
||||
|
||||
// Clean up.
|
||||
|
@ -1779,9 +2163,9 @@ IndexedDatabaseManager::WaitForLockedFilesToFinishRunnable::Run()
|
|||
}
|
||||
|
||||
IndexedDatabaseManager::
|
||||
SynchronizedOp::SynchronizedOp(const nsACString& aOrigin,
|
||||
SynchronizedOp::SynchronizedOp(const OriginOrPatternString& aOriginOrPattern,
|
||||
nsIAtom* aId)
|
||||
: mOrigin(aOrigin), mId(aId)
|
||||
: mOriginOrPattern(aOriginOrPattern), mId(aId)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
MOZ_COUNT_CTOR(IndexedDatabaseManager::SynchronizedOp);
|
||||
|
@ -1794,24 +2178,42 @@ IndexedDatabaseManager::SynchronizedOp::~SynchronizedOp()
|
|||
}
|
||||
|
||||
bool
|
||||
IndexedDatabaseManager::SynchronizedOp::MustWaitFor(const SynchronizedOp& aRhs)
|
||||
const
|
||||
IndexedDatabaseManager::
|
||||
SynchronizedOp::MustWaitFor(const SynchronizedOp& aExistingOp)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
bool match;
|
||||
|
||||
if (aExistingOp.mOriginOrPattern.IsOrigin()) {
|
||||
if (mOriginOrPattern.IsOrigin()) {
|
||||
match = aExistingOp.mOriginOrPattern.Equals(mOriginOrPattern);
|
||||
}
|
||||
else {
|
||||
match = PatternMatchesOrigin(mOriginOrPattern, aExistingOp.mOriginOrPattern);
|
||||
}
|
||||
}
|
||||
else if (mOriginOrPattern.IsOrigin()) {
|
||||
match = PatternMatchesOrigin(aExistingOp.mOriginOrPattern, mOriginOrPattern);
|
||||
}
|
||||
else {
|
||||
match = PatternMatchesOrigin(mOriginOrPattern, aExistingOp.mOriginOrPattern) ||
|
||||
PatternMatchesOrigin(aExistingOp.mOriginOrPattern, mOriginOrPattern);
|
||||
}
|
||||
|
||||
// If the origins don't match, the second can proceed.
|
||||
if (!aRhs.mOrigin.Equals(mOrigin)) {
|
||||
if (!match) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the origins and the ids match, the second must wait.
|
||||
if (aRhs.mId == mId) {
|
||||
if (aExistingOp.mId == mId) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Waiting is required if either one corresponds to an origin clearing
|
||||
// (a null Id).
|
||||
if (!aRhs.mId || !mId) {
|
||||
if (!aExistingOp.mId || !mId) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -57,11 +57,11 @@ public:
|
|||
|
||||
// Waits for databases to be cleared and for version change transactions to
|
||||
// complete before dispatching the given runnable.
|
||||
nsresult WaitForOpenAllowed(const nsACString& aOrigin,
|
||||
nsresult WaitForOpenAllowed(const OriginOrPatternString& aOriginOrPattern,
|
||||
nsIAtom* aId,
|
||||
nsIRunnable* aRunnable);
|
||||
|
||||
void AllowNextSynchronizedOp(const nsACString& aOrigin,
|
||||
void AllowNextSynchronizedOp(const OriginOrPatternString& aOriginOrPattern,
|
||||
nsIAtom* aId);
|
||||
|
||||
nsIThread* IOThread()
|
||||
|
@ -169,7 +169,7 @@ public:
|
|||
const nsAString& aDatabaseName,
|
||||
FileManager* aFileManager);
|
||||
|
||||
void InvalidateFileManagersForOrigin(const nsACString& aOrigin);
|
||||
void InvalidateFileManagersForPattern(const nsACString& aPattern);
|
||||
|
||||
void InvalidateFileManager(const nsACString& aOrigin,
|
||||
const nsAString& aDatabaseName);
|
||||
|
@ -200,7 +200,18 @@ public:
|
|||
const nsAString& aName);
|
||||
|
||||
static nsresult
|
||||
FireWindowOnError(nsPIDOMWindow* aOwner, nsEventChainPostVisitor& aVisitor);
|
||||
FireWindowOnError(nsPIDOMWindow* aOwner,
|
||||
nsEventChainPostVisitor& aVisitor);
|
||||
|
||||
static bool
|
||||
OriginMatchesApp(const nsACString& aOrigin,
|
||||
uint32_t aAppId);
|
||||
|
||||
static bool
|
||||
OriginMatchesApp(const nsACString& aOrigin,
|
||||
uint32_t aAppId,
|
||||
bool aInMozBrowser);
|
||||
|
||||
private:
|
||||
IndexedDatabaseManager();
|
||||
~IndexedDatabaseManager();
|
||||
|
@ -225,6 +236,8 @@ private:
|
|||
// Called when a database has been closed.
|
||||
void OnDatabaseClosed(IDBDatabase* aDatabase);
|
||||
|
||||
nsresult ClearDatabasesForApp(uint32_t aAppId, bool aBrowserOnly);
|
||||
|
||||
// Responsible for clearing the database files for a particular origin on the
|
||||
// IO thread. Created when nsIIDBIndexedDatabaseManager::ClearDatabasesForURI
|
||||
// is called. Runs three times, first on the main thread, next on the IO
|
||||
|
@ -253,8 +266,8 @@ private:
|
|||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIRUNNABLE
|
||||
|
||||
OriginClearRunnable(const nsACString& aOrigin)
|
||||
: mOrigin(aOrigin),
|
||||
OriginClearRunnable(const OriginOrPatternString& aOriginOrPattern)
|
||||
: mOriginOrPattern(aOriginOrPattern),
|
||||
mCallbackState(Pending)
|
||||
{ }
|
||||
|
||||
|
@ -279,8 +292,10 @@ private:
|
|||
nsTArray<nsRefPtr<IDBDatabase> >& aDatabases,
|
||||
void* aClosure);
|
||||
|
||||
void DeleteFiles(IndexedDatabaseManager* aManager);
|
||||
|
||||
private:
|
||||
nsCString mOrigin;
|
||||
OriginOrPatternString mOriginOrPattern;
|
||||
CallbackState mCallbackState;
|
||||
};
|
||||
|
||||
|
@ -311,12 +326,15 @@ private:
|
|||
// Running on the main thread after skipping the work
|
||||
Shortcut
|
||||
};
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIRUNNABLE
|
||||
|
||||
AsyncUsageRunnable(nsIURI* aURI,
|
||||
const nsACString& aOrigin,
|
||||
AsyncUsageRunnable(uint32_t aAppId,
|
||||
bool aInMozBrowserOnly,
|
||||
const OriginOrPatternString& aOrigin,
|
||||
nsIURI* aURI,
|
||||
nsIIndexedDatabaseUsageCallback* aCallback);
|
||||
|
||||
// Sets the canceled flag so that the callback is never called.
|
||||
|
@ -349,13 +367,14 @@ private:
|
|||
uint64_t* aUsage);
|
||||
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
nsCString mOrigin;
|
||||
|
||||
nsCOMPtr<nsIIndexedDatabaseUsageCallback> mCallback;
|
||||
uint64_t mUsage;
|
||||
uint64_t mFileUsage;
|
||||
uint32_t mAppId;
|
||||
int32_t mCanceled;
|
||||
OriginOrPatternString mOrigin;
|
||||
CallbackState mCallbackState;
|
||||
bool mInMozBrowserOnly;
|
||||
};
|
||||
|
||||
// Called when AsyncUsageRunnable has finished its Run() method.
|
||||
|
@ -366,16 +385,17 @@ private:
|
|||
// clearing dbs for an origin, etc).
|
||||
struct SynchronizedOp
|
||||
{
|
||||
SynchronizedOp(const nsACString& aOrigin, nsIAtom* aId);
|
||||
SynchronizedOp(const OriginOrPatternString& aOriginOrPattern,
|
||||
nsIAtom* aId);
|
||||
~SynchronizedOp();
|
||||
|
||||
// Test whether the second SynchronizedOp needs to get behind this one.
|
||||
bool MustWaitFor(const SynchronizedOp& aRhs) const;
|
||||
// Test whether this SynchronizedOp needs to wait for the given op.
|
||||
bool MustWaitFor(const SynchronizedOp& aOp);
|
||||
|
||||
void DelayRunnable(nsIRunnable* aRunnable);
|
||||
void DispatchDelayedRunnables();
|
||||
|
||||
const nsCString mOrigin;
|
||||
const OriginOrPatternString mOriginOrPattern;
|
||||
nsCOMPtr<nsIAtom> mId;
|
||||
nsRefPtr<AsyncConnectionHelper> mHelper;
|
||||
nsCOMPtr<nsIRunnable> mRunnable;
|
||||
|
@ -442,22 +462,12 @@ private:
|
|||
static nsresult RunSynchronizedOp(IDBDatabase* aDatabase,
|
||||
SynchronizedOp* aOp);
|
||||
|
||||
SynchronizedOp* FindSynchronizedOp(const nsACString& aOrigin,
|
||||
nsIAtom* aId)
|
||||
{
|
||||
for (uint32_t index = 0; index < mSynchronizedOps.Length(); index++) {
|
||||
const nsAutoPtr<SynchronizedOp>& currentOp = mSynchronizedOps[index];
|
||||
if (currentOp->mOrigin == aOrigin &&
|
||||
(!currentOp->mId || currentOp->mId == aId)) {
|
||||
return currentOp;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
SynchronizedOp* FindSynchronizedOp(const nsACString& aPattern,
|
||||
nsIAtom* aId);
|
||||
|
||||
bool IsClearOriginPending(const nsACString& aOrigin)
|
||||
bool IsClearOriginPending(const nsACString& aPattern)
|
||||
{
|
||||
return !!FindSynchronizedOp(aOrigin, nullptr);
|
||||
return !!FindSynchronizedOp(aPattern, nullptr);
|
||||
}
|
||||
|
||||
// Maintains a list of live databases per origin.
|
||||
|
|
|
@ -66,12 +66,13 @@ EXPORTS_mozilla/dom/indexedDB = \
|
|||
$(NULL)
|
||||
|
||||
LOCAL_INCLUDES = \
|
||||
-I$(topsrcdir)/db/sqlite3/src \
|
||||
-I$(topsrcdir)/xpcom/build \
|
||||
-I$(topsrcdir)/dom/base \
|
||||
-I$(topsrcdir)/dom/src/storage \
|
||||
-I$(topsrcdir)/caps/include \
|
||||
-I$(topsrcdir)/content/base/src \
|
||||
-I$(topsrcdir)/content/events/src \
|
||||
-I$(topsrcdir)/db/sqlite3/src \
|
||||
-I$(topsrcdir)/dom/base \
|
||||
-I$(topsrcdir)/dom/src/storage \
|
||||
-I$(topsrcdir)/xpcom/build \
|
||||
$(NULL)
|
||||
|
||||
DEFINES += -D_IMPL_NS_LAYOUT
|
||||
|
|
|
@ -2018,7 +2018,9 @@ OpenDatabaseHelper::Run()
|
|||
IndexedDatabaseManager* manager = IndexedDatabaseManager::Get();
|
||||
NS_ASSERTION(manager, "This should never be null!");
|
||||
|
||||
manager->AllowNextSynchronizedOp(mASCIIOrigin, mDatabaseId);
|
||||
manager->AllowNextSynchronizedOp(
|
||||
OriginOrPatternString::FromOrigin(mASCIIOrigin),
|
||||
mDatabaseId);
|
||||
|
||||
ReleaseMainThreadObjects();
|
||||
|
||||
|
|
|
@ -434,6 +434,15 @@ IndexedDBDatabaseChild::RecvVersionChange(const uint64_t& aOldVersion,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
IndexedDBDatabaseChild::RecvInvalidate()
|
||||
{
|
||||
if (mDatabase) {
|
||||
mDatabase->Invalidate();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
IndexedDBDatabaseChild::RecvPIndexedDBTransactionConstructor(
|
||||
PIndexedDBTransactionChild* aActor,
|
||||
|
@ -584,9 +593,30 @@ IndexedDBTransactionChild::ActorDestroy(ActorDestroyReason aWhy)
|
|||
}
|
||||
|
||||
bool
|
||||
IndexedDBTransactionChild::RecvComplete(const nsresult& aRv)
|
||||
IndexedDBTransactionChild::RecvComplete(const CompleteParams& aParams)
|
||||
{
|
||||
FireCompleteEvent(aRv);
|
||||
MOZ_ASSERT(mTransaction);
|
||||
MOZ_ASSERT(mStrongTransaction);
|
||||
|
||||
nsresult resultCode;
|
||||
|
||||
switch (aParams.type()) {
|
||||
case CompleteParams::TCompleteResult:
|
||||
resultCode = NS_OK;
|
||||
break;
|
||||
case CompleteParams::TAbortResult:
|
||||
resultCode = aParams.get_AbortResult().errorCode();
|
||||
if (NS_SUCCEEDED(resultCode)) {
|
||||
resultCode = NS_ERROR_DOM_INDEXEDDB_ABORT_ERR;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_NOT_REACHED("Unknown union type!");
|
||||
return false;
|
||||
}
|
||||
|
||||
FireCompleteEvent(resultCode);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -119,6 +119,9 @@ protected:
|
|||
RecvVersionChange(const uint64_t& aOldVersion, const uint64_t& aNewVersion)
|
||||
MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
RecvInvalidate() MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
RecvPIndexedDBTransactionConstructor(PIndexedDBTransactionChild* aActor,
|
||||
const TransactionParams& aParams)
|
||||
|
@ -163,7 +166,7 @@ protected:
|
|||
ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
RecvComplete(const nsresult& aRv) MOZ_OVERRIDE;
|
||||
RecvComplete(const CompleteParams& aParams) MOZ_OVERRIDE;
|
||||
|
||||
virtual PIndexedDBObjectStoreChild*
|
||||
AllocPIndexedDBObjectStore(const ObjectStoreConstructorParams& aParams)
|
||||
|
|
|
@ -355,7 +355,11 @@ IndexedDBDatabaseParent::HandleRequestEvent(nsIDOMEvent* aEvent,
|
|||
}
|
||||
|
||||
MOZ_ASSERT(!mDatabase || mDatabase == databaseConcrete);
|
||||
mDatabase = databaseConcrete;
|
||||
|
||||
if (!mDatabase) {
|
||||
databaseConcrete->SetActor(this);
|
||||
mDatabase = databaseConcrete;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -390,6 +394,7 @@ IndexedDBDatabaseParent::HandleRequestEvent(nsIDOMEvent* aEvent,
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
databaseConcrete->SetActor(this);
|
||||
mDatabase = databaseConcrete;
|
||||
|
||||
return NS_OK;
|
||||
|
@ -555,10 +560,10 @@ IndexedDBTransactionParent::HandleEvent(nsIDOMEvent* aEvent)
|
|||
nsresult rv = aEvent->GetType(type);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsresult transactionResult;
|
||||
CompleteParams params;
|
||||
|
||||
if (type.EqualsLiteral(COMPLETE_EVT_STR)) {
|
||||
transactionResult = NS_OK;
|
||||
params = CompleteResult();
|
||||
}
|
||||
else if (type.EqualsLiteral(ABORT_EVT_STR)) {
|
||||
#ifdef DEBUG
|
||||
|
@ -573,15 +578,14 @@ IndexedDBTransactionParent::HandleEvent(nsIDOMEvent* aEvent)
|
|||
}
|
||||
}
|
||||
#endif
|
||||
MOZ_ASSERT(NS_FAILED(mTransaction->GetAbortCode()));
|
||||
transactionResult = mTransaction->GetAbortCode();
|
||||
params = AbortResult(mTransaction->GetAbortCode());
|
||||
}
|
||||
else {
|
||||
NS_WARNING("Unknown message type!");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (!SendComplete(transactionResult)) {
|
||||
if (!SendComplete(params)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
|
|
@ -58,6 +58,8 @@ child:
|
|||
|
||||
VersionChange(uint64_t oldVersion, uint64_t newVersion);
|
||||
|
||||
Invalidate();
|
||||
|
||||
both:
|
||||
PIndexedDBTransaction(TransactionParams params);
|
||||
};
|
||||
|
|
|
@ -31,6 +31,20 @@ union ObjectStoreConstructorParams
|
|||
GetObjectStoreParams;
|
||||
};
|
||||
|
||||
struct CompleteResult
|
||||
{ };
|
||||
|
||||
struct AbortResult
|
||||
{
|
||||
nsresult errorCode;
|
||||
};
|
||||
|
||||
union CompleteParams
|
||||
{
|
||||
CompleteResult;
|
||||
AbortResult;
|
||||
};
|
||||
|
||||
} // namespace ipc
|
||||
|
||||
protocol PIndexedDBTransaction
|
||||
|
@ -51,7 +65,7 @@ parent:
|
|||
DeleteObjectStore(nsString name);
|
||||
|
||||
child:
|
||||
Complete(nsresult rv);
|
||||
Complete(CompleteParams params);
|
||||
};
|
||||
|
||||
} // namespace indexedDB
|
||||
|
|
|
@ -8,18 +8,17 @@
|
|||
|
||||
interface nsIURI;
|
||||
|
||||
[scriptable, function, uuid(ef1795ec-7050-4658-b80f-0e48cbe1d64b)]
|
||||
[scriptable, function, uuid(38f15cc7-2df0-4a90-8b7f-1606b2243522)]
|
||||
interface nsIIndexedDatabaseUsageCallback : nsISupports
|
||||
{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void onUsageResult(in nsIURI aURI,
|
||||
in unsigned long long aUsage,
|
||||
in unsigned long long aFileUsage);
|
||||
in unsigned long long aFileUsage,
|
||||
in unsigned long aAppId,
|
||||
in boolean aInMozBrowserOnly);
|
||||
};
|
||||
|
||||
[scriptable, builtinclass, uuid(02256aa7-70d8-473f-bf3b-8cb35d28fd75)]
|
||||
[scriptable, builtinclass, uuid(e5168115-baff-4559-887e-7c0405cc9e63)]
|
||||
interface nsIIndexedDatabaseManager : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -31,8 +30,11 @@ interface nsIIndexedDatabaseManager : nsISupports
|
|||
* @param aCallback
|
||||
* The callback that will be called when the usage is available.
|
||||
*/
|
||||
[optional_argc]
|
||||
void getUsageForURI(in nsIURI aURI,
|
||||
in nsIIndexedDatabaseUsageCallback aCallback);
|
||||
in nsIIndexedDatabaseUsageCallback aCallback,
|
||||
[optional] in unsigned long aAppId,
|
||||
[optional] in boolean aInMozBrowserOnly);
|
||||
|
||||
/**
|
||||
* Cancels an asynchronous usage check initiated by a previous call to
|
||||
|
@ -43,9 +45,11 @@ interface nsIIndexedDatabaseManager : nsISupports
|
|||
* @param aCallback
|
||||
* The callback that will be called when the usage is available.
|
||||
*/
|
||||
[optional_argc]
|
||||
void cancelGetUsageForURI(in nsIURI aURI,
|
||||
in nsIIndexedDatabaseUsageCallback aCallback);
|
||||
|
||||
in nsIIndexedDatabaseUsageCallback aCallback,
|
||||
[optional] in unsigned long aAppId,
|
||||
[optional] in boolean aInMozBrowserOnly);
|
||||
|
||||
/**
|
||||
* Removes all databases stored for the given URI. The files may not be
|
||||
|
@ -54,7 +58,10 @@ interface nsIIndexedDatabaseManager : nsISupports
|
|||
* @param aURI
|
||||
* The URI whose databases are to be cleared.
|
||||
*/
|
||||
void clearDatabasesForURI(in nsIURI aURI);
|
||||
[optional_argc]
|
||||
void clearDatabasesForURI(in nsIURI aURI,
|
||||
[optional] in unsigned long aAppId,
|
||||
[optional] in boolean aInMozBrowserOnly);
|
||||
|
||||
/**
|
||||
* Defines indexedDB and IDBKeyrange with its static functions on
|
||||
|
|
|
@ -21,6 +21,8 @@ MOCHITEST_FILES = \
|
|||
event_propagation_iframe.html \
|
||||
exceptions_in_events_iframe.html \
|
||||
file.js \
|
||||
file_app_isolation.html \
|
||||
file_app_isolation.js \
|
||||
helpers.js \
|
||||
leaving_page_iframe.html \
|
||||
test_add_put.html \
|
||||
|
@ -100,12 +102,13 @@ MOCHITEST_FILES = \
|
|||
test_setVersion_events.html \
|
||||
test_setVersion_exclusion.html \
|
||||
test_unique_index_update.html \
|
||||
test_webapp_clearBrowserData.html \
|
||||
third_party_iframe1.html \
|
||||
third_party_iframe2.html \
|
||||
test_app_isolation_inproc.html \
|
||||
test_app_isolation_oop.html \
|
||||
file_app_isolation.html \
|
||||
file_app_isolation.js \
|
||||
webapp_clearBrowserData_appFrame.html \
|
||||
webapp_clearBrowserData_browserFrame.html \
|
||||
$(NULL)
|
||||
|
||||
# test_writer_starvation.html disabled for infinite loops, bug 595368
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>Indexed Database Clear Browser Data Test</title>
|
||||
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
|
||||
<script type="text/javascript;version=1.7">
|
||||
"use strict";
|
||||
|
||||
const appDomain = "example.org";
|
||||
const manifestURL =
|
||||
location.protocol + "//" + appDomain + "/manifest.webapp";
|
||||
|
||||
function testSteps()
|
||||
{
|
||||
const objectStoreName = "foo";
|
||||
const testKey = 1;
|
||||
const testValue = objectStoreName;
|
||||
|
||||
let request = indexedDB.open(window.location.pathname, 1);
|
||||
request.onerror = errorHandler;
|
||||
request.onupgradeneeded = grabEventAndContinueHandler;
|
||||
request.onsuccess = unexpectedSuccessHandler;
|
||||
let event = yield;
|
||||
|
||||
let db = event.target.result;
|
||||
db.onerror = errorHandler;
|
||||
db.onversionchange = function(event) {
|
||||
event.target.close();
|
||||
}
|
||||
|
||||
let objectStore = db.createObjectStore(objectStoreName);
|
||||
objectStore.add(testValue, testKey);
|
||||
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
let srcURL =
|
||||
location.protocol + "//" + appDomain +
|
||||
location.pathname.replace("test_webapp_clearBrowserData.html",
|
||||
"webapp_clearBrowserData_appFrame.html");
|
||||
|
||||
let iframe = document.createElement("iframe");
|
||||
iframe.setAttribute("mozbrowser", "");
|
||||
iframe.setAttribute("mozapp", manifestURL);
|
||||
iframe.setAttribute("src", srcURL);
|
||||
iframe.setAttribute("remote", "true");
|
||||
iframe.addEventListener("mozbrowsershowmodalprompt", function(event) {
|
||||
let message = JSON.parse(event.detail.message);
|
||||
switch (message.type) {
|
||||
case "info":
|
||||
case "ok":
|
||||
window[message.type].apply(window, message.args);
|
||||
break;
|
||||
case "done":
|
||||
continueToNextStepSync();
|
||||
break;
|
||||
default:
|
||||
throw "unknown message";
|
||||
}
|
||||
});
|
||||
|
||||
info("loading app frame");
|
||||
|
||||
document.body.appendChild(iframe);
|
||||
yield;
|
||||
|
||||
request = indexedDB.open(window.location.pathname, 1);
|
||||
request.onerror = errorHandler;
|
||||
request.onupgradeneeded = unexpectedSuccessHandler;
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
db = event.target.result;
|
||||
db.onerror = errorHandler;
|
||||
|
||||
objectStore =
|
||||
db.transaction(objectStoreName).objectStore(objectStoreName);
|
||||
objectStore.get(testKey).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
ok(testValue == event.target.result, "data still exists");
|
||||
|
||||
finishTest();
|
||||
yield;
|
||||
}
|
||||
|
||||
function start()
|
||||
{
|
||||
if (!SpecialPowers.isMainProcess()) {
|
||||
todo(false, "Test disabled in child processes, for now");
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
SpecialPowers.addPermission("browser", true, document);
|
||||
SpecialPowers.addPermission("browser", true, { manifestURL: manifestURL,
|
||||
isInBrowserElement: false });
|
||||
SpecialPowers.addPermission("embed-apps", true, document);
|
||||
|
||||
let Webapps = {};
|
||||
SpecialPowers.wrap(Components)
|
||||
.utils.import("resource://gre/modules/Webapps.jsm", Webapps);
|
||||
let appRegistry = SpecialPowers.wrap(Webapps.DOMApplicationRegistry);
|
||||
|
||||
let originalAllAppsLaunchable = appRegistry.allAppsLaunchable;
|
||||
appRegistry.allAppsLaunchable = true;
|
||||
|
||||
window.addEventListener("unload", function cleanup(event) {
|
||||
if (event.target == document) {
|
||||
window.removeEventListener("unload", cleanup, false);
|
||||
|
||||
SpecialPowers.removePermission("browser", location.href);
|
||||
SpecialPowers.removePermission("browser",
|
||||
location.protocol + "//" + appDomain);
|
||||
SpecialPowers.removePermission("embed-apps", location.href);
|
||||
appRegistry.allAppsLaunchable = originalAllAppsLaunchable;
|
||||
}
|
||||
}, false);
|
||||
|
||||
SpecialPowers.pushPrefEnv({
|
||||
"set": [["dom.mozBrowserFramesEnabled", true]]
|
||||
}, runTest);
|
||||
}
|
||||
</script>
|
||||
|
||||
<script type="text/javascript;version=1.7" src="helpers.js"></script>
|
||||
</head>
|
||||
|
||||
<body onload="start();"></body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,126 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>Indexed Database Clear Browser Data Test</title>
|
||||
|
||||
<script type="text/javascript;version=1.7">
|
||||
"use strict";
|
||||
|
||||
function ok(cond, message)
|
||||
{
|
||||
alert(JSON.stringify({ type: "ok",
|
||||
args: [!!cond, "appFrame: " + message] }));
|
||||
}
|
||||
|
||||
function info(message)
|
||||
{
|
||||
alert(JSON.stringify({ type: "info",
|
||||
args: ["appFrame: " + message] }));
|
||||
}
|
||||
|
||||
function finish()
|
||||
{
|
||||
alert(JSON.stringify({ type: "done" }));
|
||||
}
|
||||
|
||||
window.onerror = ok.bind(window, false);
|
||||
|
||||
function testSteps()
|
||||
{
|
||||
const objectStoreName = "foo";
|
||||
const testKey = 1;
|
||||
const testValue = objectStoreName;
|
||||
|
||||
let request = indexedDB.open(window.location.pathname, 1);
|
||||
request.onerror = errorHandler;
|
||||
request.onupgradeneeded = grabEventAndContinueHandler;
|
||||
request.onsuccess = unexpectedSuccessHandler;
|
||||
let event = yield;
|
||||
|
||||
let db = event.target.result;
|
||||
db.onerror = errorHandler;
|
||||
db.onversionchange = function(event) {
|
||||
event.target.close();
|
||||
}
|
||||
|
||||
let objectStore = db.createObjectStore(objectStoreName);
|
||||
objectStore.add(testValue, testKey);
|
||||
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
ok(db === event.target.result, "created database");
|
||||
|
||||
objectStore =
|
||||
db.transaction(objectStoreName).objectStore(objectStoreName);
|
||||
objectStore.get(testKey).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
ok(testValue == event.target.result, "data exists");
|
||||
|
||||
let iframe = document.createElement("iframe");
|
||||
iframe.setAttribute("mozbrowser", "");
|
||||
iframe.setAttribute("src", "webapp_clearBrowserData_browserFrame.html");
|
||||
iframe.addEventListener("mozbrowsershowmodalprompt", function(event) {
|
||||
let message = JSON.parse(event.detail.message);
|
||||
switch (message.type) {
|
||||
case "block":
|
||||
info("blocking browserFrame");
|
||||
event.preventDefault();
|
||||
|
||||
let request = navigator.mozApps.getSelf();
|
||||
request.onsuccess = function() {
|
||||
let app = request.result;
|
||||
ok(app, "got app");
|
||||
|
||||
info("clearing browser data");
|
||||
app.clearBrowserData();
|
||||
|
||||
info("unblocking browserFrame");
|
||||
event.detail.unblock();
|
||||
}
|
||||
break;
|
||||
case "done":
|
||||
continueToNextStepSync();
|
||||
break;
|
||||
default:
|
||||
alert(event.detail.message);
|
||||
}
|
||||
});
|
||||
|
||||
info("loading browser frame");
|
||||
|
||||
document.body.appendChild(iframe);
|
||||
yield;
|
||||
|
||||
request = indexedDB.open(window.location.pathname, 1);
|
||||
request.onerror = errorHandler;
|
||||
request.onupgradeneeded = unexpectedSuccessHandler;
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
db = event.target.result;
|
||||
db.onerror = errorHandler;
|
||||
|
||||
objectStore =
|
||||
db.transaction(objectStoreName).objectStore(objectStoreName);
|
||||
objectStore.get(testKey).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
ok(testValue == event.target.result, "data still exists");
|
||||
|
||||
finish();
|
||||
yield;
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<script type="text/javascript;version=1.7" src="helpers.js"></script>
|
||||
</head>
|
||||
|
||||
<body onload="testGenerator.next();"></body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,103 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>Indexed Database Clear Browser Data Test</title>
|
||||
|
||||
<script type="text/javascript;version=1.7">
|
||||
"use strict";
|
||||
|
||||
function ok(cond, message)
|
||||
{
|
||||
alert(JSON.stringify({ type: "ok",
|
||||
args: [!!cond, "browserFrame: " + message] }));
|
||||
}
|
||||
|
||||
function info(message)
|
||||
{
|
||||
alert(JSON.stringify({ type: "info",
|
||||
args: ["browserFrame: " + message] }));
|
||||
}
|
||||
|
||||
function block()
|
||||
{
|
||||
info("about to block");
|
||||
|
||||
// This will block until the parent has cleared our database.
|
||||
alert(JSON.stringify({ type: "block" }));
|
||||
|
||||
info("unblocked");
|
||||
}
|
||||
|
||||
function finish()
|
||||
{
|
||||
alert(JSON.stringify({ type: "done" }));
|
||||
}
|
||||
|
||||
window.onerror = ok.bind(window, false);
|
||||
|
||||
function testSteps()
|
||||
{
|
||||
const objectStoreName = "foo";
|
||||
const testKey = 1;
|
||||
const testValue = objectStoreName;
|
||||
|
||||
let request = indexedDB.open(window.location.pathname, 1);
|
||||
request.onerror = errorHandler;
|
||||
request.onupgradeneeded = grabEventAndContinueHandler;
|
||||
request.onsuccess = unexpectedSuccessHandler;
|
||||
let event = yield;
|
||||
|
||||
let db = event.target.result;
|
||||
db.onerror = errorHandler;
|
||||
db.onversionchange = function(event) {
|
||||
event.target.close();
|
||||
}
|
||||
|
||||
let objectStore = db.createObjectStore(objectStoreName);
|
||||
objectStore.add(testValue, testKey);
|
||||
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
ok(db === event.target.result, "created database");
|
||||
|
||||
objectStore =
|
||||
db.transaction(objectStoreName).objectStore(objectStoreName);
|
||||
objectStore.get(testKey).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
ok(testValue == event.target.result, "data exists");
|
||||
|
||||
block();
|
||||
|
||||
request = indexedDB.open(window.location.pathname, 1);
|
||||
request.onerror = errorHandler;
|
||||
request.onupgradeneeded = grabEventAndContinueHandler;
|
||||
request.onsuccess = unexpectedSuccessHandler;
|
||||
event = yield;
|
||||
|
||||
ok(event.type == "upgradeneeded", "db doesn't exist");
|
||||
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
db = event.target.result;
|
||||
info(db.objectStoreNames.length);
|
||||
ok(!db.objectStoreNames.length, "no object stores");
|
||||
|
||||
finish();
|
||||
|
||||
yield;
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<script type="text/javascript;version=1.7" src="helpers.js"></script>
|
||||
</head>
|
||||
|
||||
<body onload="testGenerator.next();"></body>
|
||||
|
||||
</html>
|
|
@ -13,3 +13,7 @@ interface mozIApplicationClearPrivateDataParams : nsISupports
|
|||
readonly attribute unsigned long appId;
|
||||
readonly attribute boolean browserOnly;
|
||||
};
|
||||
|
||||
%{C++
|
||||
#define TOPIC_WEB_APP_CLEAR_DATA "webapps-clear-data"
|
||||
%}
|
||||
|
|
|
@ -57,7 +57,6 @@ XPIDLSRCS = \
|
|||
nsIDOMCustomEvent.idl \
|
||||
nsIDOMCompositionEvent.idl \
|
||||
nsIDOMWheelEvent.idl \
|
||||
nsIWifiEventInits.idl \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -329,9 +329,5 @@ NS_NewDOMSmsEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext,
|
|||
nsresult
|
||||
NS_NewDOMMozSettingsEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, nsEvent* aEvent);
|
||||
nsresult
|
||||
NS_NewDOMMozWifiStatusChangeEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, nsEvent* aEvent);
|
||||
nsresult
|
||||
NS_NewDOMMozWifiConnectionInfoEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, nsEvent* aEvent);
|
||||
nsresult
|
||||
NS_NewDOMMozApplicationEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, nsEvent* aEvent);
|
||||
%}
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
#include "nsIDOMEventTarget.idl"
|
||||
#include "nsIDOMEvent.idl"
|
||||
|
||||
interface nsIVariant;
|
||||
|
||||
dictionary MozWifiStatusChangeEventInit : EventInit
|
||||
{
|
||||
nsIVariant network;
|
||||
DOMString status;
|
||||
};
|
||||
|
||||
dictionary MozWifiConnectionInfoEventInit : EventInit
|
||||
{
|
||||
nsIVariant network;
|
||||
short signalStrength;
|
||||
short relSignalStrength;
|
||||
long linkSpeed;
|
||||
DOMString ipAddress;
|
||||
};
|
|
@ -884,6 +884,23 @@ TabParent::RecvPIndexedDBConstructor(PIndexedDBParent* aActor,
|
|||
NS_RUNTIMEABORT("Not supported yet!");
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
|
||||
// XXXbent Need to make sure we have a whitelist for chrome databases!
|
||||
|
||||
// Verify the appID in the origin first.
|
||||
if (mApp && !aASCIIOrigin.EqualsLiteral("chrome")) {
|
||||
uint32_t appId;
|
||||
rv = mApp->GetLocalId(&appId);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
if (!IndexedDatabaseManager::OriginMatchesApp(aASCIIOrigin, appId)) {
|
||||
NS_WARNING("App attempted to open databases that it does not have "
|
||||
"permission to access!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsINode> node = do_QueryInterface(GetOwnerElement());
|
||||
NS_ENSURE_TRUE(node, false);
|
||||
|
||||
|
@ -897,9 +914,8 @@ TabParent::RecvPIndexedDBConstructor(PIndexedDBParent* aActor,
|
|||
NS_ASSERTION(contentParent, "Null manager?!");
|
||||
|
||||
nsRefPtr<IDBFactory> factory;
|
||||
nsresult rv =
|
||||
IDBFactory::Create(window, aASCIIOrigin, contentParent,
|
||||
getter_AddRefs(factory));
|
||||
rv = IDBFactory::Create(window, aASCIIOrigin, contentParent,
|
||||
getter_AddRefs(factory));
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
if (!factory) {
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html class="reftest-wait">
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=791330
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>PeerConnection test - operate on closed connection</title>
|
||||
<script type="application/javascript">
|
||||
function finish() {
|
||||
document.documentElement.removeAttribute("class");
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
var pc = mozRTCPeerConnection();
|
||||
pc.close();
|
||||
|
||||
navigator.mozGetUserMedia({audio: true, fake: true}, function (stream) {
|
||||
pc.addStream(stream);
|
||||
pc.createOffer(function (offer) {
|
||||
}, finish);
|
||||
}, function () {});
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body onload="setTimeout(runTest, 100)">
|
||||
</body>
|
||||
</html>
|
|
@ -1,3 +1,4 @@
|
|||
pref(media.peerconnection.enabled,true) load 780790.html
|
||||
pref(media.peerconnection.enabled,true) load 791270.html
|
||||
pref(media.peerconnection.enabled,true) load 791278.html
|
||||
pref(media.peerconnection.enabled,true) load 791330.html
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
"use strict";
|
||||
|
||||
function debug(aMsg) {
|
||||
// dump("-*- PermissionSettings.js: " + aMsg + "\n");
|
||||
//dump("-*- PermissionSettings.js: " + aMsg + "\n");
|
||||
}
|
||||
|
||||
const Cc = Components.classes;
|
||||
|
@ -28,9 +28,20 @@ function PermissionSettings()
|
|||
debug("Constructor");
|
||||
}
|
||||
|
||||
var permissionManager = Cc["@mozilla.org/permissionmanager;1"].getService(Ci.nsIPermissionManager);
|
||||
var secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager);
|
||||
var appsService = Cc["@mozilla.org/AppsService;1"].getService(Ci.nsIAppsService);
|
||||
XPCOMUtils.defineLazyServiceGetter(this,
|
||||
"permissionManager",
|
||||
"@mozilla.org/permissionmanager;1",
|
||||
"nsIPermissionManager");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this,
|
||||
"secMan",
|
||||
"@mozilla.org/scriptsecuritymanager;1",
|
||||
"nsIScriptSecurityManager");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this,
|
||||
"appsService",
|
||||
"@mozilla.org/AppsService;1",
|
||||
"nsIAppsService");
|
||||
|
||||
PermissionSettings.prototype = {
|
||||
get: function get(aPermission, aManifestURL, aOrigin, aBrowserFlag) {
|
||||
|
|
|
@ -4,11 +4,9 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
let DEBUG = 0;
|
||||
if (DEBUG)
|
||||
debug = function (s) { dump("-*- PermissionSettings Module: " + s + "\n"); }
|
||||
else
|
||||
debug = function (s) {}
|
||||
function debug(s) {
|
||||
//dump("-*- PermissionSettings Module: " + s + "\n");
|
||||
}
|
||||
|
||||
const Cu = Components.utils;
|
||||
const Cc = Components.classes;
|
||||
|
@ -23,9 +21,20 @@ XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
|
|||
"@mozilla.org/parentprocessmessagemanager;1",
|
||||
"nsIMessageListenerManager");
|
||||
|
||||
var permissionManager = Cc["@mozilla.org/permissionmanager;1"].getService(Ci.nsIPermissionManager);
|
||||
var secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager);
|
||||
var appsService = Cc["@mozilla.org/AppsService;1"].getService(Ci.nsIAppsService);
|
||||
XPCOMUtils.defineLazyServiceGetter(this,
|
||||
"permissionManager",
|
||||
"@mozilla.org/permissionmanager;1",
|
||||
"nsIPermissionManager");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this,
|
||||
"secMan",
|
||||
"@mozilla.org/scriptsecuritymanager;1",
|
||||
"nsIScriptSecurityManager");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this,
|
||||
"appsService",
|
||||
"@mozilla.org/AppsService;1",
|
||||
"nsIAppsService");
|
||||
|
||||
let PermissionSettingsModule = {
|
||||
init: function() {
|
||||
|
@ -62,6 +71,29 @@ let PermissionSettingsModule = {
|
|||
permissionManager.addFromPrincipal(principal, aData.type, action);
|
||||
},
|
||||
|
||||
getPermission: function getPermission(aPermission, aManifestURL, aOrigin, aBrowserFlag) {
|
||||
debug("getPermission: " + aPermission + ", " + aManifestURL + ", " + aOrigin);
|
||||
let uri = Services.io.newURI(aOrigin, null, null);
|
||||
let appID = appsService.getAppLocalIdByManifestURL(aManifestURL);
|
||||
let principal = secMan.getAppCodebasePrincipal(uri, appID, aBrowserFlag);
|
||||
let result = permissionManager.testExactPermissionFromPrincipal(principal, aPermission);
|
||||
|
||||
switch (result)
|
||||
{
|
||||
case Ci.nsIPermissionManager.UNKNOWN_ACTION:
|
||||
return "unknown";
|
||||
case Ci.nsIPermissionManager.ALLOW_ACTION:
|
||||
return "allow";
|
||||
case Ci.nsIPermissionManager.DENY_ACTION:
|
||||
return "deny";
|
||||
case Ci.nsIPermissionManager.PROMPT_ACTION:
|
||||
return "prompt";
|
||||
default:
|
||||
dump("Unsupported PermissionSettings Action!\n");
|
||||
return "unknown";
|
||||
}
|
||||
},
|
||||
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
ppmm.removeMessageListener("PermissionSettings:AddPermission", this);
|
||||
Services.obs.removeObserver(this, "profile-before-change");
|
||||
|
|
|
@ -331,7 +331,7 @@ nsDOMStorageManager::Observe(nsISupports *aSubject,
|
|||
rv = params->GetBrowserOnly(&browserOnly);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
MOZ_ASSERT(appId != nsIScriptSecurityManager::NO_APP_ID);
|
||||
MOZ_ASSERT(appId != nsIScriptSecurityManager::UNKNOWN_APP_ID);
|
||||
|
||||
return DOMStorageImpl::gStorageDB->RemoveAllForApp(appId, browserOnly);
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "mozIStorageFunction.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
|
||||
#include "sampler.h"
|
||||
|
||||
|
@ -226,6 +227,8 @@ nsDOMStoragePersistentDB::EnsureLoadTemporaryTableForStorage(DOMStorageImpl* aSt
|
|||
if (!mTempTableLoads.Get(aStorage->GetScopeDBKey(), &timeStamp)) {
|
||||
nsresult rv;
|
||||
|
||||
Telemetry::AutoTimer<Telemetry::LOCALDOMSTORAGE_FETCH_DOMAIN_MS> timer;
|
||||
|
||||
rv = MaybeCommitInsertTransaction();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
|
@ -307,8 +310,23 @@ nsDOMStoragePersistentDB::FlushTemporaryTable(nsCStringHashKey::KeyType aKey,
|
|||
nsresult
|
||||
nsDOMStoragePersistentDB::FlushTemporaryTables(bool force)
|
||||
{
|
||||
mozStorageTransaction trans(mConnection, false);
|
||||
nsCOMPtr<mozIStorageStatement> stmt =
|
||||
mStatements.GetCachedStatement(
|
||||
"SELECT COUNT(*) FROM webappsstore2_temp WHERE modified = 1"
|
||||
);
|
||||
mozStorageStatementScoper scope(stmt);
|
||||
|
||||
TimeStamp startTime;
|
||||
bool exists;
|
||||
int32_t dirtyCount;
|
||||
if (stmt &&
|
||||
NS_SUCCEEDED(stmt->ExecuteStep(&exists)) && exists &&
|
||||
NS_SUCCEEDED(stmt->GetInt32(0, &dirtyCount)) && dirtyCount > 0) {
|
||||
// Time the operation if dirty entries will be flushed
|
||||
startTime = TimeStamp::Now();
|
||||
}
|
||||
|
||||
mozStorageTransaction trans(mConnection, false);
|
||||
nsresult rv;
|
||||
|
||||
FlushTemporaryTableData data;
|
||||
|
@ -325,6 +343,10 @@ nsDOMStoragePersistentDB::FlushTemporaryTables(bool force)
|
|||
rv = MaybeCommitInsertTransaction();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!startTime.IsNull()) {
|
||||
Telemetry::AutoTimer<Telemetry::LOCALDOMSTORAGE_TIMER_FLUSH_MS> timer(startTime);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -332,6 +354,7 @@ nsresult
|
|||
nsDOMStoragePersistentDB::GetAllKeys(DOMStorageImpl* aStorage,
|
||||
nsTHashtable<nsSessionStorageEntry>* aKeys)
|
||||
{
|
||||
Telemetry::AutoTimer<Telemetry::LOCALDOMSTORAGE_GETALLKEYS_MS> timer;
|
||||
nsresult rv;
|
||||
|
||||
rv = MaybeCommitInsertTransaction();
|
||||
|
@ -384,6 +407,7 @@ nsDOMStoragePersistentDB::GetKeyValue(DOMStorageImpl* aStorage,
|
|||
nsAString& aValue,
|
||||
bool* aSecure)
|
||||
{
|
||||
Telemetry::AutoTimer<Telemetry::LOCALDOMSTORAGE_GETVALUE_MS> timer;
|
||||
SAMPLE_LABEL("nsDOMStoragePersistentDB", "GetKeyValue");
|
||||
nsresult rv;
|
||||
|
||||
|
@ -435,6 +459,8 @@ nsDOMStoragePersistentDB::SetKey(DOMStorageImpl* aStorage,
|
|||
const nsAString& aValue,
|
||||
bool aSecure)
|
||||
{
|
||||
Telemetry::AutoTimer<Telemetry::LOCALDOMSTORAGE_SETVALUE_MS> timer;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
rv = EnsureLoadTemporaryTableForStorage(aStorage);
|
||||
|
@ -541,6 +567,7 @@ nsresult
|
|||
nsDOMStoragePersistentDB::RemoveKey(DOMStorageImpl* aStorage,
|
||||
const nsAString& aKey)
|
||||
{
|
||||
Telemetry::AutoTimer<Telemetry::LOCALDOMSTORAGE_REMOVEKEY_MS> timer;
|
||||
nsresult rv;
|
||||
|
||||
rv = MaybeCommitInsertTransaction();
|
||||
|
@ -645,6 +672,7 @@ nsDOMStoragePersistentDB::RemoveOwner(const nsACString& aOwner)
|
|||
nsresult
|
||||
nsDOMStoragePersistentDB::RemoveAll()
|
||||
{
|
||||
Telemetry::AutoTimer<Telemetry::LOCALDOMSTORAGE_REMOVEALL_MS> timer;
|
||||
nsresult rv;
|
||||
|
||||
rv = MaybeCommitInsertTransaction();
|
||||
|
@ -726,6 +754,8 @@ nsDOMStoragePersistentDB::GetUsageInternal(const nsACString& aQuotaDBKey,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
Telemetry::AutoTimer<Telemetry::LOCALDOMSTORAGE_FETCH_QUOTA_USE_MS> timer;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
rv = MaybeCommitInsertTransaction();
|
||||
|
|
|
@ -40,6 +40,7 @@ const kSmsSentObserverTopic = "sms-sent";
|
|||
const kSmsDeliveredObserverTopic = "sms-delivered";
|
||||
const kMozSettingsChangedObserverTopic = "mozsettings-changed";
|
||||
const kSysMsgListenerReadyObserverTopic = "system-message-listener-ready";
|
||||
const kSysClockChangeObserverTopic = "system-clock-change";
|
||||
const kTimeNitzAutomaticUpdateEnabled = "time.nitz.automatic-update.enabled";
|
||||
const DOM_SMS_DELIVERY_RECEIVED = "received";
|
||||
const DOM_SMS_DELIVERY_SENT = "sent";
|
||||
|
@ -274,6 +275,7 @@ function RadioInterfaceLayer() {
|
|||
Services.obs.addObserver(this, "xpcom-shutdown", false);
|
||||
Services.obs.addObserver(this, kMozSettingsChangedObserverTopic, false);
|
||||
Services.obs.addObserver(this, kSysMsgListenerReadyObserverTopic, false);
|
||||
Services.obs.addObserver(this, kSysClockChangeObserverTopic, false);
|
||||
|
||||
this._sentSmsEnvelopes = {};
|
||||
|
||||
|
@ -1366,12 +1368,9 @@ RadioInterfaceLayer.prototype = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Handle the NITZ message.
|
||||
* Set the NITZ message in our system time.
|
||||
*/
|
||||
handleNitzTime: function handleNitzTime(message) {
|
||||
if (!this._nitzAutomaticUpdateEnabled) {
|
||||
return;
|
||||
}
|
||||
setNitzTime: function setNitzTime(message) {
|
||||
// To set the system clock time. Note that there could be a time diff
|
||||
// between when the NITZ was received and when the time is actually set.
|
||||
gTimeService.set(
|
||||
|
@ -1394,6 +1393,19 @@ RadioInterfaceLayer.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle the NITZ message.
|
||||
*/
|
||||
handleNitzTime: function handleNitzTime(message) {
|
||||
// Cache the latest NITZ message whenever receiving it.
|
||||
this._lastNitzMessage = message;
|
||||
|
||||
// Set the received NITZ time if the setting is enabled.
|
||||
if (this._nitzAutomaticUpdateEnabled) {
|
||||
this.setNitzTime(message);
|
||||
}
|
||||
},
|
||||
|
||||
handleICCInfoChange: function handleICCInfoChange(message) {
|
||||
let oldIcc = this.rilContext.icc;
|
||||
this.rilContext.icc = message;
|
||||
|
@ -1418,7 +1430,7 @@ RadioInterfaceLayer.prototype = {
|
|||
|
||||
handleUSSDReceived: function handleUSSDReceived(ussd) {
|
||||
debug("handleUSSDReceived " + JSON.stringify(ussd));
|
||||
this._sendMobileConnectionMessage("RIL:UssdReceived", ussd);
|
||||
this._sendMobileConnectionMessage("RIL:USSDReceived", ussd);
|
||||
},
|
||||
|
||||
handleSendMMI: function handleSendMMI(message) {
|
||||
|
@ -1472,6 +1484,12 @@ RadioInterfaceLayer.prototype = {
|
|||
ppmm = null;
|
||||
Services.obs.removeObserver(this, "xpcom-shutdown");
|
||||
Services.obs.removeObserver(this, kMozSettingsChangedObserverTopic);
|
||||
Services.obs.removeObserver(this, kSysClockChangeObserverTopic);
|
||||
break;
|
||||
case kSysClockChangeObserverTopic:
|
||||
if (this._lastNitzMessage) {
|
||||
this._lastNitzMessage.receiveTimeInMS += parseInt(data, 10);
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
@ -1504,6 +1522,10 @@ RadioInterfaceLayer.prototype = {
|
|||
// 'time.nitz.automatic-update.enabled' setting from the UI.
|
||||
_nitzAutomaticUpdateEnabled: null,
|
||||
|
||||
// Remember the last NITZ message so that we can set the time based on
|
||||
// the network immediately when users enable network-based time.
|
||||
_lastNitzMessage: null,
|
||||
|
||||
// nsISettingsServiceCallback
|
||||
handle: function handle(aName, aResult) {
|
||||
switch(aName) {
|
||||
|
@ -1559,6 +1581,11 @@ RadioInterfaceLayer.prototype = {
|
|||
break;
|
||||
case kTimeNitzAutomaticUpdateEnabled:
|
||||
this._nitzAutomaticUpdateEnabled = aResult;
|
||||
|
||||
// Set the latest cached NITZ time if the setting is enabled.
|
||||
if (this._nitzAutomaticUpdateEnabled && this._lastNitzMessage) {
|
||||
this.setNitzTime(this._lastNitzMessage);
|
||||
}
|
||||
break;
|
||||
};
|
||||
},
|
||||
|
|
|
@ -16,24 +16,20 @@ namespace mozilla {
|
|||
namespace dom {
|
||||
namespace time {
|
||||
|
||||
class DateCacheCleaner : public SystemTimeChangeObserver
|
||||
class DateCacheCleaner : public SystemTimezoneChangeObserver
|
||||
{
|
||||
public:
|
||||
DateCacheCleaner()
|
||||
{
|
||||
RegisterSystemTimeChangeObserver(this);
|
||||
RegisterSystemTimezoneChangeObserver(this);
|
||||
}
|
||||
|
||||
~DateCacheCleaner()
|
||||
{
|
||||
UnregisterSystemTimeChangeObserver(this);
|
||||
UnregisterSystemTimezoneChangeObserver(this);
|
||||
}
|
||||
void Notify(const SystemTimeChange& aReason)
|
||||
void Notify(const SystemTimezoneChangeInformation& aSystemTimezoneChangeInfo)
|
||||
{
|
||||
if (aReason == SYS_TIME_CHANGE_CLOCK) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIThreadJSContextStack> stack =
|
||||
do_GetService("@mozilla.org/js/xpc/ContextStack;1");
|
||||
if (!stack) {
|
||||
|
|
|
@ -9,9 +9,11 @@
|
|||
#include "nsPIDOMWindow.h"
|
||||
#include "nsDOMEvent.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIObserverService.h"
|
||||
|
||||
using namespace mozilla::hal;
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::hal;
|
||||
using namespace mozilla::services;
|
||||
|
||||
StaticAutoPtr<nsSystemTimeChangeObserver> sObserver;
|
||||
|
||||
|
@ -27,11 +29,12 @@ nsSystemTimeChangeObserver* nsSystemTimeChangeObserver::GetInstance()
|
|||
nsSystemTimeChangeObserver::~nsSystemTimeChangeObserver()
|
||||
{
|
||||
mWindowListeners.Clear();
|
||||
UnregisterSystemTimeChangeObserver(this);
|
||||
UnregisterSystemClockChangeObserver(this);
|
||||
UnregisterSystemTimezoneChangeObserver(this);
|
||||
}
|
||||
|
||||
void
|
||||
nsSystemTimeChangeObserver::Notify(const SystemTimeChange& aReason)
|
||||
nsSystemTimeChangeObserver::FireMozTimeChangeEvent()
|
||||
{
|
||||
//Copy mWindowListeners and iterate over windowListeners instead because
|
||||
//mWindowListeners may be modified while we loop.
|
||||
|
@ -58,6 +61,28 @@ nsSystemTimeChangeObserver::Notify(const SystemTimeChange& aReason)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsSystemTimeChangeObserver::Notify(const int64_t& aClockDeltaMS)
|
||||
{
|
||||
// Notify observers that the system clock has been adjusted.
|
||||
nsCOMPtr<nsIObserverService> observerService = GetObserverService();
|
||||
if (observerService) {
|
||||
nsString dataStr;
|
||||
dataStr.AppendFloat(static_cast<double>(aClockDeltaMS));
|
||||
observerService->NotifyObservers(
|
||||
nullptr, "system-clock-change", dataStr.get());
|
||||
}
|
||||
|
||||
FireMozTimeChangeEvent();
|
||||
}
|
||||
|
||||
void
|
||||
nsSystemTimeChangeObserver::Notify(
|
||||
const SystemTimezoneChangeInformation& aSystemTimezoneChangeInfo)
|
||||
{
|
||||
FireMozTimeChangeEvent();
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsSystemTimeChangeObserver::AddWindowListener(nsIDOMWindow* aWindow)
|
||||
{
|
||||
|
@ -80,7 +105,8 @@ nsSystemTimeChangeObserver::AddWindowListenerImpl(nsIDOMWindow* aWindow)
|
|||
}
|
||||
|
||||
if (mWindowListeners.Length() == 0) {
|
||||
RegisterSystemTimeChangeObserver(sObserver);
|
||||
RegisterSystemClockChangeObserver(sObserver);
|
||||
RegisterSystemTimezoneChangeObserver(sObserver);
|
||||
}
|
||||
|
||||
mWindowListeners.AppendElement(windowWeakRef);
|
||||
|
@ -103,7 +129,8 @@ nsSystemTimeChangeObserver::RemoveWindowListenerImpl(nsIDOMWindow* aWindow)
|
|||
mWindowListeners.RemoveElement(NS_GetWeakReference(aWindow));
|
||||
|
||||
if (mWindowListeners.Length() == 0) {
|
||||
UnregisterSystemTimeChangeObserver(sObserver);
|
||||
UnregisterSystemClockChangeObserver(sObserver);
|
||||
UnregisterSystemTimezoneChangeObserver(sObserver);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
|
|
@ -12,14 +12,23 @@
|
|||
#include "nsPIDOMWindow.h"
|
||||
#include "nsWeakPtr.h"
|
||||
|
||||
typedef mozilla::Observer<mozilla::hal::SystemTimeChange> SystemTimeChangeObserver;
|
||||
typedef mozilla::Observer<int64_t> SystemClockChangeObserver;
|
||||
typedef mozilla::Observer<mozilla::hal::SystemTimezoneChangeInformation> SystemTimezoneChangeObserver;
|
||||
|
||||
class nsSystemTimeChangeObserver : public SystemTimeChangeObserver
|
||||
class nsSystemTimeChangeObserver : public SystemClockChangeObserver,
|
||||
public SystemTimezoneChangeObserver
|
||||
{
|
||||
public:
|
||||
static nsSystemTimeChangeObserver* GetInstance();
|
||||
virtual ~nsSystemTimeChangeObserver();
|
||||
void Notify(const mozilla::hal::SystemTimeChange& aReason);
|
||||
|
||||
// Implementing hal::SystemClockChangeObserver::Notify()
|
||||
void Notify(const int64_t& aClockDeltaMS);
|
||||
|
||||
// Implementing hal::SystemTimezoneChangeObserver::Notify()
|
||||
void Notify(
|
||||
const mozilla::hal::SystemTimezoneChangeInformation& aSystemTimezoneChangeInfo);
|
||||
|
||||
static nsresult AddWindowListener(nsIDOMWindow* aWindow);
|
||||
static nsresult RemoveWindowListener(nsIDOMWindow* aWindow);
|
||||
private:
|
||||
|
@ -27,6 +36,7 @@ private:
|
|||
nsresult RemoveWindowListenerImpl(nsIDOMWindow* aWindow);
|
||||
nsSystemTimeChangeObserver() { };
|
||||
nsTArray<nsWeakPtr> mWindowListeners;
|
||||
void FireMozTimeChangeEvent();
|
||||
};
|
||||
|
||||
#endif //_mozilla_time_change_observer_h_
|
||||
|
|
|
@ -19,6 +19,8 @@ include $(topsrcdir)/dom/dom-config.mk
|
|||
|
||||
XPIDLSRCS = \
|
||||
nsIWifi.idl \
|
||||
nsIDOMMozWifiStatusChangeEvent.idl \
|
||||
nsIDOMMozWifiConnectionInfoEvent.idl \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_COMPONENTS = \
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsIDOMEvent.idl"
|
||||
|
||||
interface nsIVariant;
|
||||
|
||||
[scriptable, builtinclass, uuid(1717f9d9-5fd8-43d8-a098-55924c6d37de)]
|
||||
interface nsIDOMMozWifiConnectionInfoEvent : nsIDOMEvent
|
||||
{
|
||||
/**
|
||||
* Network object with an SSID field.
|
||||
*/
|
||||
readonly attribute nsIVariant network;
|
||||
|
||||
/**
|
||||
* Strength of the signal to network, in dBm between -55 and -100 dBm.
|
||||
*/
|
||||
readonly attribute short signalStrength;
|
||||
|
||||
/**
|
||||
* Relative signal strength between 0 and 100.
|
||||
*/
|
||||
readonly attribute short relSignalStrength;
|
||||
|
||||
/**
|
||||
* Link speed in Mb/s.
|
||||
*/
|
||||
readonly attribute long linkSpeed;
|
||||
|
||||
/**
|
||||
* IP address in the dotted quad format.
|
||||
*/
|
||||
readonly attribute DOMString ipAddress;
|
||||
|
||||
[noscript] void initMozWifiConnectionInfoEvent(in DOMString aType,
|
||||
in boolean aCanBubble,
|
||||
in boolean aCancelable,
|
||||
in nsIVariant aNetwork,
|
||||
in short signalStrength,
|
||||
in short relSignalStrength,
|
||||
in long linkSpeed,
|
||||
in DOMString ipAddress);
|
||||
};
|
||||
|
||||
dictionary MozWifiConnectionInfoEventInit : EventInit
|
||||
{
|
||||
nsIVariant network;
|
||||
short signalStrength;
|
||||
short relSignalStrength;
|
||||
long linkSpeed;
|
||||
DOMString ipAddress;
|
||||
};
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsIDOMEvent.idl"
|
||||
|
||||
interface nsIVariant;
|
||||
|
||||
[scriptable, builtinclass, uuid(f3ef70b0-b2d3-4eb5-8ea4-008f8d330cd6)]
|
||||
interface nsIDOMMozWifiStatusChangeEvent : nsIDOMEvent
|
||||
{
|
||||
/**
|
||||
* Network object with a SSID field describing the network affected by
|
||||
* this change. This might be null.
|
||||
*/
|
||||
readonly attribute nsIVariant network;
|
||||
|
||||
/**
|
||||
* String describing the current status of the wifi manager. See above for
|
||||
* the possible values.
|
||||
*/
|
||||
readonly attribute DOMString status;
|
||||
|
||||
[noscript] void initMozWifiStatusChangeEvent(in DOMString aType,
|
||||
in boolean aCanBubble,
|
||||
in boolean aCancelable,
|
||||
in nsIVariant aNetwork,
|
||||
in DOMString aStatus);
|
||||
};
|
||||
|
||||
dictionary MozWifiStatusChangeEventInit : EventInit
|
||||
{
|
||||
nsIVariant network;
|
||||
DOMString status;
|
||||
};
|
|
@ -186,63 +186,3 @@ interface nsIDOMWifiManager : nsISupports
|
|||
attribute nsIDOMEventListener onenabled;
|
||||
attribute nsIDOMEventListener ondisabled;
|
||||
};
|
||||
|
||||
[scriptable, builtinclass, uuid(f3ef70b0-b2d3-4eb5-8ea4-008f8d330cd6)]
|
||||
interface nsIDOMMozWifiStatusChangeEvent : nsIDOMEvent
|
||||
{
|
||||
/**
|
||||
* Network object with a SSID field describing the network affected by
|
||||
* this change. This might be null.
|
||||
*/
|
||||
readonly attribute nsIVariant network;
|
||||
|
||||
/**
|
||||
* String describing the current status of the wifi manager. See above for
|
||||
* the possible values.
|
||||
*/
|
||||
readonly attribute DOMString status;
|
||||
|
||||
[noscript] void initMozWifiStatusChangeEvent(in DOMString aType,
|
||||
in boolean aCanBubble,
|
||||
in boolean aCancelable,
|
||||
in nsIVariant aNetwork,
|
||||
in DOMString status);
|
||||
};
|
||||
|
||||
[scriptable, builtinclass, uuid(1717f9d9-5fd8-43d8-a098-55924c6d37de)]
|
||||
interface nsIDOMMozWifiConnectionInfoEvent : nsIDOMEvent
|
||||
{
|
||||
/**
|
||||
* Network object with an SSID field.
|
||||
*/
|
||||
readonly attribute nsIVariant network;
|
||||
|
||||
/**
|
||||
* Strength of the signal to network, in dBm between -55 and -100 dBm.
|
||||
*/
|
||||
readonly attribute short signalStrength;
|
||||
|
||||
/**
|
||||
* Relative signal strength between 0 and 100.
|
||||
*/
|
||||
readonly attribute short relSignalStrength;
|
||||
|
||||
/**
|
||||
* Link speed in Mb/s.
|
||||
*/
|
||||
readonly attribute long linkSpeed;
|
||||
|
||||
/**
|
||||
* IP address in the dotted quad format.
|
||||
*/
|
||||
readonly attribute DOMString ipAddress;
|
||||
|
||||
[noscript] void initMozWifiConnectionInfoEvent(in DOMString aType,
|
||||
in boolean aCanBubble,
|
||||
in boolean aCancelable,
|
||||
in nsIVariant aNetwork,
|
||||
in short signalStrength,
|
||||
in short relSignalStrength,
|
||||
in long linkSpeed,
|
||||
in DOMString ipAddress);
|
||||
};
|
||||
|
|
|
@ -701,9 +701,7 @@ DrawTargetCG::FillGlyphs(ScaledFont *aFont, const GlyphBuffer &aBuffer, const Pa
|
|||
|
||||
CGContextConcatCTM(cg, GfxMatrixToCGAffineTransform(mTransform));
|
||||
|
||||
ScaledFontMac* cgFont = static_cast<ScaledFontMac*>(aFont);
|
||||
CGContextSetFont(cg, cgFont->mFont);
|
||||
CGContextSetFontSize(cg, cgFont->mSize);
|
||||
ScaledFontMac* macFont = static_cast<ScaledFontMac*>(aFont);
|
||||
|
||||
//XXX: we should use a stack vector here when we have a class like that
|
||||
std::vector<CGGlyph> glyphs;
|
||||
|
@ -729,14 +727,32 @@ DrawTargetCG::FillGlyphs(ScaledFont *aFont, const GlyphBuffer &aBuffer, const Pa
|
|||
//XXX: CGContextShowGlyphsAtPositions is 10.5+ for older versions use CGContextShowGlyphsWithAdvances
|
||||
if (isGradient(aPattern)) {
|
||||
CGContextSetTextDrawingMode(cg, kCGTextClip);
|
||||
CGContextShowGlyphsAtPositions(cg, &glyphs.front(), &positions.front(), aBuffer.mNumGlyphs);
|
||||
if (ScaledFontMac::CTFontDrawGlyphsPtr != nullptr) {
|
||||
ScaledFontMac::CTFontDrawGlyphsPtr(macFont->mCTFont, &glyphs.front(),
|
||||
&positions.front(),
|
||||
aBuffer.mNumGlyphs, cg);
|
||||
} else {
|
||||
CGContextSetFont(cg, macFont->mFont);
|
||||
CGContextSetFontSize(cg, macFont->mSize);
|
||||
CGContextShowGlyphsAtPositions(cg, &glyphs.front(), &positions.front(),
|
||||
aBuffer.mNumGlyphs);
|
||||
}
|
||||
DrawGradient(cg, aPattern);
|
||||
} else {
|
||||
//XXX: with CoreGraphics we can stroke text directly instead of going
|
||||
// through GetPath. It would be nice to add support for using that
|
||||
CGContextSetTextDrawingMode(cg, kCGTextFill);
|
||||
SetFillFromPattern(cg, mColorSpace, aPattern);
|
||||
CGContextShowGlyphsAtPositions(cg, &glyphs.front(), &positions.front(), aBuffer.mNumGlyphs);
|
||||
if (ScaledFontMac::CTFontDrawGlyphsPtr != nullptr) {
|
||||
ScaledFontMac::CTFontDrawGlyphsPtr(macFont->mCTFont, &glyphs.front(),
|
||||
&positions.front(),
|
||||
aBuffer.mNumGlyphs, cg);
|
||||
} else {
|
||||
CGContextSetFont(cg, macFont->mFont);
|
||||
CGContextSetFontSize(cg, macFont->mSize);
|
||||
CGContextShowGlyphsAtPositions(cg, &glyphs.front(), &positions.front(),
|
||||
aBuffer.mNumGlyphs);
|
||||
}
|
||||
}
|
||||
|
||||
fixer.Fix(mCg);
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#endif
|
||||
#include "DrawTargetCG.h"
|
||||
#include <vector>
|
||||
#include <dlfcn.h>
|
||||
|
||||
// prototype for private API
|
||||
extern "C" {
|
||||
|
@ -22,15 +23,33 @@ CGPathRef CGFontGetGlyphPath(CGFontRef fontRef, CGAffineTransform *textTransform
|
|||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
ScaledFontMac::CTFontDrawGlyphsFuncT* ScaledFontMac::CTFontDrawGlyphsPtr = nullptr;
|
||||
bool ScaledFontMac::sSymbolLookupDone = false;
|
||||
|
||||
ScaledFontMac::ScaledFontMac(CGFontRef aFont, Float aSize)
|
||||
: ScaledFontBase(aSize)
|
||||
{
|
||||
if (!sSymbolLookupDone) {
|
||||
CTFontDrawGlyphsPtr =
|
||||
(CTFontDrawGlyphsFuncT*)dlsym(RTLD_DEFAULT, "CTFontDrawGlyphs");
|
||||
sSymbolLookupDone = true;
|
||||
}
|
||||
|
||||
// XXX: should we be taking a reference
|
||||
mFont = CGFontRetain(aFont);
|
||||
if (CTFontDrawGlyphsPtr != nullptr) {
|
||||
// only create mCTFont if we're going to be using the CTFontDrawGlyphs API
|
||||
mCTFont = CTFontCreateWithGraphicsFont(aFont, aSize, nullptr, nullptr);
|
||||
} else {
|
||||
mCTFont = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ScaledFontMac::~ScaledFontMac()
|
||||
{
|
||||
if (mCTFont) {
|
||||
CFRelease(mCTFont);
|
||||
}
|
||||
CGFontRelease(mFont);
|
||||
}
|
||||
|
||||
|
@ -38,9 +57,13 @@ ScaledFontMac::~ScaledFontMac()
|
|||
SkTypeface* ScaledFontMac::GetSkTypeface()
|
||||
{
|
||||
if (!mTypeface) {
|
||||
CTFontRef fontFace = CTFontCreateWithGraphicsFont(mFont, mSize, nullptr, nullptr);
|
||||
mTypeface = SkCreateTypefaceFromCTFont(fontFace);
|
||||
CFRelease(fontFace);
|
||||
if (mCTFont) {
|
||||
mTypeface = SkCreateTypefaceFromCTFont(mCTFont);
|
||||
} else {
|
||||
CTFontRef fontFace = CTFontCreateWithGraphicsFont(mFont, mSize, nullptr, nullptr);
|
||||
mTypeface = SkCreateTypefaceFromCTFont(fontFace);
|
||||
CFRelease(fontFace);
|
||||
}
|
||||
}
|
||||
return mTypeface;
|
||||
}
|
||||
|
|
|
@ -25,9 +25,23 @@ public:
|
|||
virtual SkTypeface* GetSkTypeface();
|
||||
#endif
|
||||
virtual TemporaryRef<Path> GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget *aTarget);
|
||||
|
||||
private:
|
||||
friend class DrawTargetCG;
|
||||
CGFontRef mFont;
|
||||
CTFontRef mCTFont; // only created if CTFontDrawGlyphs is available, otherwise null
|
||||
|
||||
typedef void (CTFontDrawGlyphsFuncT)(CTFontRef,
|
||||
const CGGlyph[], const CGPoint[],
|
||||
size_t, CGContextRef);
|
||||
|
||||
static bool sSymbolLookupDone;
|
||||
|
||||
public:
|
||||
// function pointer for CTFontDrawGlyphs, if available;
|
||||
// initialized the first time a ScaledFontMac is created,
|
||||
// so it will be valid by the time DrawTargetCG wants to use it
|
||||
static CTFontDrawGlyphsFuncT* CTFontDrawGlyphsPtr;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -216,6 +216,10 @@ pixman-16-bit-pipeline.patch: 16 bit pipeline for dithering
|
|||
|
||||
pixman-dither.patch: Add dithering of 16 bit gradients
|
||||
|
||||
quartz-support-color-emoji-font.patch: support Apple Color Emoji font in cairo-quartz backend
|
||||
|
||||
use-show-text-glyphs-if-glyph-path-fails.patch: fall back to show_text_glyphs even at huge sizes if scaled_font_glyph_path didn't work
|
||||
|
||||
==== disable printing patch ====
|
||||
|
||||
disable-printing.patch: allows us to use NS_PRINTING to disable printing.
|
||||
|
|
|
@ -2007,13 +2007,24 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
|
|||
transformed_glyphs, num_glyphs,
|
||||
&path);
|
||||
|
||||
if (status == CAIRO_STATUS_SUCCESS) {
|
||||
if (status == CAIRO_STATUS_SUCCESS && !_cairo_path_fixed_fill_is_empty (&path)) {
|
||||
status = _cairo_surface_fill (gstate->target, op, pattern,
|
||||
&path,
|
||||
CAIRO_FILL_RULE_WINDING,
|
||||
gstate->tolerance,
|
||||
gstate->scaled_font->options.antialias,
|
||||
_gstate_get_clip (gstate, &clip));
|
||||
} else {
|
||||
/* if _cairo_scaled_font_glyph_path() failed, maybe the font doesn't support
|
||||
* returning paths, so try the _cairo_surface_show_text_glyphs() option
|
||||
*/
|
||||
status = _cairo_surface_show_text_glyphs (gstate->target, op, pattern,
|
||||
utf8, utf8_len,
|
||||
transformed_glyphs, num_glyphs,
|
||||
transformed_clusters, num_clusters,
|
||||
cluster_flags,
|
||||
gstate->scaled_font,
|
||||
_gstate_get_clip (gstate, &clip));
|
||||
}
|
||||
|
||||
_cairo_path_fixed_fini (&path);
|
||||
|
|
|
@ -90,6 +90,10 @@ static int (*CGFontGetAscentPtr) (CGFontRef fontRef) = NULL;
|
|||
static int (*CGFontGetDescentPtr) (CGFontRef fontRef) = NULL;
|
||||
static int (*CGFontGetLeadingPtr) (CGFontRef fontRef) = NULL;
|
||||
|
||||
/* CTFontCreateWithGraphicsFont is not public until 10.5. */
|
||||
typedef const struct __CTFontDescriptor *CTFontDescriptorRef;
|
||||
static CTFontRef (*CTFontCreateWithGraphicsFontPtr) (CGFontRef, CGFloat, const CGAffineTransform *, CTFontDescriptorRef) = NULL;
|
||||
|
||||
static cairo_bool_t _cairo_quartz_font_symbol_lookup_done = FALSE;
|
||||
static cairo_bool_t _cairo_quartz_font_symbols_present = FALSE;
|
||||
|
||||
|
@ -127,6 +131,8 @@ quartz_font_ensure_symbols(void)
|
|||
CGContextGetAllowsFontSmoothingPtr = dlsym(RTLD_DEFAULT, "CGContextGetAllowsFontSmoothing");
|
||||
CGContextSetAllowsFontSmoothingPtr = dlsym(RTLD_DEFAULT, "CGContextSetAllowsFontSmoothing");
|
||||
|
||||
CTFontCreateWithGraphicsFontPtr = dlsym(RTLD_DEFAULT, "CTFontCreateWithGraphicsFont");
|
||||
|
||||
if ((CGFontCreateWithFontNamePtr || CGFontCreateWithNamePtr) &&
|
||||
CGFontGetGlyphBBoxesPtr &&
|
||||
CGFontGetGlyphsForUnicharsPtr &&
|
||||
|
@ -150,6 +156,7 @@ struct _cairo_quartz_font_face {
|
|||
cairo_font_face_t base;
|
||||
|
||||
CGFontRef cgFont;
|
||||
CTFontRef ctFont;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -234,6 +241,10 @@ _cairo_quartz_font_face_destroy (void *abstract_face)
|
|||
{
|
||||
cairo_quartz_font_face_t *font_face = (cairo_quartz_font_face_t*) abstract_face;
|
||||
|
||||
if (font_face->ctFont) {
|
||||
CFRelease (font_face->ctFont);
|
||||
}
|
||||
|
||||
CGFontRelease (font_face->cgFont);
|
||||
}
|
||||
|
||||
|
@ -358,6 +369,12 @@ cairo_quartz_font_face_create_for_cgfont (CGFontRef font)
|
|||
|
||||
font_face->cgFont = CGFontRetain (font);
|
||||
|
||||
if (CTFontCreateWithGraphicsFontPtr) {
|
||||
font_face->ctFont = CTFontCreateWithGraphicsFontPtr (font, 1.0, NULL, NULL);
|
||||
} else {
|
||||
font_face->ctFont = NULL;
|
||||
}
|
||||
|
||||
_cairo_font_face_init (&font_face->base, &_cairo_quartz_font_face_backend);
|
||||
|
||||
return &font_face->base;
|
||||
|
@ -777,6 +794,14 @@ _cairo_quartz_scaled_font_get_cg_font_ref (cairo_scaled_font_t *abstract_font)
|
|||
return ffont->cgFont;
|
||||
}
|
||||
|
||||
CTFontRef
|
||||
_cairo_quartz_scaled_font_get_ct_font_ref (cairo_scaled_font_t *abstract_font)
|
||||
{
|
||||
cairo_quartz_font_face_t *ffont = _cairo_quartz_scaled_to_face(abstract_font);
|
||||
|
||||
return ffont->ctFont;
|
||||
}
|
||||
|
||||
#ifndef __LP64__
|
||||
/*
|
||||
* compat with old ATSUI backend
|
||||
|
|
|
@ -50,6 +50,9 @@ typedef CGFloat cairo_quartz_float_t;
|
|||
typedef float cairo_quartz_float_t;
|
||||
#endif
|
||||
|
||||
/* define CTFontRef for pre-10.5 SDKs */
|
||||
typedef const struct __CTFont *CTFontRef;
|
||||
|
||||
typedef struct cairo_quartz_surface {
|
||||
cairo_surface_t base;
|
||||
|
||||
|
@ -104,6 +107,9 @@ _cairo_quartz_create_cgimage (cairo_format_t format,
|
|||
CGFontRef
|
||||
_cairo_quartz_scaled_font_get_cg_font_ref (cairo_scaled_font_t *sfont);
|
||||
|
||||
CTFontRef
|
||||
_cairo_quartz_scaled_font_get_ct_font_ref (cairo_scaled_font_t *sfont);
|
||||
|
||||
#else
|
||||
|
||||
# error Cairo was not compiled with support for the quartz backend
|
||||
|
|
|
@ -135,6 +135,9 @@ static bool (*CGContextGetAllowsFontSmoothingPtr) (CGContextRef) = NULL;
|
|||
static CGPathRef (*CGContextCopyPathPtr) (CGContextRef) = NULL;
|
||||
static CGFloat (*CGContextGetAlphaPtr) (CGContextRef) = NULL;
|
||||
|
||||
/* CTFontDrawGlyphs is not available until 10.7 */
|
||||
static void (*CTFontDrawGlyphsPtr) (CTFontRef, const CGGlyph[], const CGPoint[], size_t, CGContextRef) = NULL;
|
||||
|
||||
static SInt32 _cairo_quartz_osx_version = 0x0;
|
||||
|
||||
static cairo_bool_t _cairo_quartz_symbol_lookup_done = FALSE;
|
||||
|
@ -172,6 +175,8 @@ static void quartz_ensure_symbols(void)
|
|||
CGContextSetAllowsFontSmoothingPtr = dlsym(RTLD_DEFAULT, "CGContextSetAllowsFontSmoothing");
|
||||
CGContextGetAlphaPtr = dlsym(RTLD_DEFAULT, "CGContextGetAlpha");
|
||||
|
||||
CTFontDrawGlyphsPtr = dlsym(RTLD_DEFAULT, "CTFontDrawGlyphs");
|
||||
|
||||
if (Gestalt(gestaltSystemVersion, &_cairo_quartz_osx_version) != noErr) {
|
||||
// assume 10.5
|
||||
_cairo_quartz_osx_version = 0x1050;
|
||||
|
@ -610,10 +615,13 @@ _cairo_quartz_cairo_matrix_to_quartz (const cairo_matrix_t *src,
|
|||
typedef struct {
|
||||
bool isClipping;
|
||||
CGGlyph *cg_glyphs;
|
||||
CGSize *cg_advances;
|
||||
union {
|
||||
CGSize *cg_advances;
|
||||
CGPoint *cg_positions;
|
||||
} u;
|
||||
size_t nglyphs;
|
||||
CGAffineTransform textTransform;
|
||||
CGFontRef font;
|
||||
cairo_scaled_font_t *scaled_font;
|
||||
CGPoint origin;
|
||||
} unbounded_show_glyphs_t;
|
||||
|
||||
|
@ -691,12 +699,6 @@ _cairo_quartz_fixup_unbounded_operation (cairo_quartz_surface_t *surface,
|
|||
else
|
||||
CGContextEOFillPath (cgc);
|
||||
} else if (op->op == UNBOUNDED_SHOW_GLYPHS) {
|
||||
CGContextSetFont (cgc, op->u.show_glyphs.font);
|
||||
CGContextSetFontSize (cgc, 1.0);
|
||||
CGContextSetTextMatrix (cgc, CGAffineTransformIdentity);
|
||||
CGContextTranslateCTM (cgc, op->u.show_glyphs.origin.x, op->u.show_glyphs.origin.y);
|
||||
CGContextConcatCTM (cgc, op->u.show_glyphs.textTransform);
|
||||
|
||||
if (op->u.show_glyphs.isClipping) {
|
||||
/* Note that the comment in show_glyphs about kCGTextClip
|
||||
* and the text transform still applies here; however, the
|
||||
|
@ -705,12 +707,25 @@ _cairo_quartz_fixup_unbounded_operation (cairo_quartz_surface_t *surface,
|
|||
CGContextSetTextDrawingMode (cgc, kCGTextClip);
|
||||
CGContextSaveGState (cgc);
|
||||
}
|
||||
CGContextTranslateCTM (cgc, op->u.show_glyphs.origin.x, op->u.show_glyphs.origin.y);
|
||||
CGContextConcatCTM (cgc, op->u.show_glyphs.textTransform);
|
||||
if (CTFontDrawGlyphsPtr) {
|
||||
CTFontDrawGlyphsPtr (_cairo_quartz_scaled_font_get_ct_font_ref (op->u.show_glyphs.scaled_font),
|
||||
op->u.show_glyphs.cg_glyphs,
|
||||
op->u.show_glyphs.u.cg_positions,
|
||||
op->u.show_glyphs.nglyphs,
|
||||
cgc);
|
||||
} else {
|
||||
CGContextSetFont (cgc, _cairo_quartz_scaled_font_get_cg_font_ref (op->u.show_glyphs.scaled_font));
|
||||
CGContextSetFontSize (cgc, 1.0);
|
||||
CGContextSetTextMatrix (cgc, CGAffineTransformIdentity);
|
||||
|
||||
CGContextShowGlyphsWithAdvances (cgc,
|
||||
op->u.show_glyphs.cg_glyphs,
|
||||
op->u.show_glyphs.cg_advances,
|
||||
op->u.show_glyphs.nglyphs);
|
||||
CGContextShowGlyphsWithAdvances (cgc,
|
||||
op->u.show_glyphs.cg_glyphs,
|
||||
op->u.show_glyphs.u.cg_advances,
|
||||
op->u.show_glyphs.nglyphs);
|
||||
|
||||
}
|
||||
if (op->u.show_glyphs.isClipping) {
|
||||
CGContextClearRect (cgc, clipBoxRound);
|
||||
CGContextRestoreGState (cgc);
|
||||
|
@ -2689,6 +2704,9 @@ _cairo_quartz_surface_show_glyphs_cg (void *abstract_surface,
|
|||
CGGlyph glyphs_static[STATIC_BUF_SIZE];
|
||||
CGSize cg_advances_static[STATIC_BUF_SIZE];
|
||||
CGGlyph *cg_glyphs = &glyphs_static[0];
|
||||
/* We'll use the cg_advances array for either advances or positions,
|
||||
depending which API we're using to actually draw. The types involved
|
||||
have the same size, so this is safe. */
|
||||
CGSize *cg_advances = &cg_advances_static[0];
|
||||
|
||||
cairo_rectangle_int_t glyph_extents;
|
||||
|
@ -2801,31 +2819,52 @@ _cairo_quartz_surface_show_glyphs_cg (void *abstract_surface,
|
|||
|
||||
CGContextSetTextMatrix (state.context, CGAffineTransformIdentity);
|
||||
|
||||
/* Convert our glyph positions to glyph advances. We need n-1 advances,
|
||||
* since the advance at index 0 is applied after glyph 0. */
|
||||
xprev = glyphs[0].x;
|
||||
yprev = glyphs[0].y;
|
||||
|
||||
cg_glyphs[0] = glyphs[0].index;
|
||||
|
||||
for (i = 1; i < num_glyphs; i++) {
|
||||
cairo_quartz_float_t xf = glyphs[i].x;
|
||||
cairo_quartz_float_t yf = glyphs[i].y;
|
||||
cg_glyphs[i] = glyphs[i].index;
|
||||
cg_advances[i - 1] = CGSizeApplyAffineTransform(CGSizeMake (xf - xprev, yf - yprev), invTextTransform);
|
||||
xprev = xf;
|
||||
yprev = yf;
|
||||
}
|
||||
|
||||
/* Translate to the first glyph's position before drawing */
|
||||
ctm = CGContextGetCTM (state.context);
|
||||
CGContextTranslateCTM (state.context, glyphs[0].x, glyphs[0].y);
|
||||
CGContextConcatCTM (state.context, textTransform);
|
||||
|
||||
CGContextShowGlyphsWithAdvances (state.context,
|
||||
cg_glyphs,
|
||||
cg_advances,
|
||||
num_glyphs);
|
||||
if (CTFontDrawGlyphsPtr) {
|
||||
/* If CTFontDrawGlyphs is available (i.e. OS X 10.7 or later), we want to use
|
||||
* that in preference to CGContextShowGlyphsWithAdvances so that colored-bitmap
|
||||
* fonts like Apple Color Emoji will render properly.
|
||||
* For this, we need to convert our glyph positions to Core Graphics's CGPoint.
|
||||
* We borrow the cg_advances array, as CGPoint and CGSize are the same size. */
|
||||
|
||||
CGPoint *cg_positions = (CGPoint*) cg_advances;
|
||||
cairo_quartz_float_t origin_x = glyphs[0].x;
|
||||
cairo_quartz_float_t origin_y = glyphs[0].y;
|
||||
|
||||
for (i = 0; i < num_glyphs; i++) {
|
||||
CGPoint pt = CGPointMake (glyphs[i].x - origin_x, glyphs[i].y - origin_y);
|
||||
cg_positions[i] = CGPointApplyAffineTransform (pt, invTextTransform);
|
||||
cg_glyphs[i] = glyphs[i].index;
|
||||
}
|
||||
|
||||
CTFontDrawGlyphsPtr (_cairo_quartz_scaled_font_get_ct_font_ref (scaled_font),
|
||||
cg_glyphs, cg_positions, num_glyphs, state.context);
|
||||
} else {
|
||||
/* Convert our glyph positions to glyph advances. We need n-1 advances,
|
||||
* since the advance at index 0 is applied after glyph 0. */
|
||||
xprev = glyphs[0].x;
|
||||
yprev = glyphs[0].y;
|
||||
|
||||
cg_glyphs[0] = glyphs[0].index;
|
||||
|
||||
for (i = 1; i < num_glyphs; i++) {
|
||||
cairo_quartz_float_t xf = glyphs[i].x;
|
||||
cairo_quartz_float_t yf = glyphs[i].y;
|
||||
cg_glyphs[i] = glyphs[i].index;
|
||||
cg_advances[i - 1] = CGSizeApplyAffineTransform(CGSizeMake (xf - xprev, yf - yprev), invTextTransform);
|
||||
xprev = xf;
|
||||
yprev = yf;
|
||||
}
|
||||
|
||||
CGContextShowGlyphsWithAdvances (state.context,
|
||||
cg_glyphs,
|
||||
cg_advances,
|
||||
num_glyphs);
|
||||
}
|
||||
|
||||
CGContextSetCTM (state.context, ctm);
|
||||
|
||||
|
@ -2852,10 +2891,17 @@ BAIL:
|
|||
|
||||
ub.u.show_glyphs.isClipping = isClipping;
|
||||
ub.u.show_glyphs.cg_glyphs = cg_glyphs;
|
||||
ub.u.show_glyphs.cg_advances = cg_advances;
|
||||
if (CTFontDrawGlyphsPtr) {
|
||||
/* we're using Core Text API: the cg_advances array was
|
||||
reused (above) for glyph positions */
|
||||
CGPoint *cg_positions = (CGPoint*) cg_advances;
|
||||
ub.u.show_glyphs.u.cg_positions = cg_positions;
|
||||
} else {
|
||||
ub.u.show_glyphs.u.cg_advances = cg_advances;
|
||||
}
|
||||
ub.u.show_glyphs.nglyphs = num_glyphs;
|
||||
ub.u.show_glyphs.textTransform = textTransform;
|
||||
ub.u.show_glyphs.font = cgfref;
|
||||
ub.u.show_glyphs.scaled_font = scaled_font;
|
||||
ub.u.show_glyphs.origin = CGPointMake (glyphs[0].x, glyphs[0].y);
|
||||
|
||||
_cairo_quartz_fixup_unbounded_operation (surface, &ub, scaled_font->options.antialias);
|
||||
|
|
|
@ -0,0 +1,432 @@
|
|||
From: Jonathan Kew <jkew@mozilla.com>
|
||||
bug 715798 pt 1 - support Apple Color Emoji font in cairo-quartz backend. r=jrmuizel
|
||||
|
||||
diff --git a/gfx/cairo/cairo/src/cairo-quartz-font.c b/gfx/cairo/cairo/src/cairo-quartz-font.c
|
||||
--- a/gfx/cairo/cairo/src/cairo-quartz-font.c
|
||||
+++ b/gfx/cairo/cairo/src/cairo-quartz-font.c
|
||||
@@ -85,16 +85,20 @@ typedef struct {
|
||||
int descent;
|
||||
int leading;
|
||||
} quartz_CGFontMetrics;
|
||||
static quartz_CGFontMetrics* (*CGFontGetHMetricsPtr) (CGFontRef fontRef) = NULL;
|
||||
static int (*CGFontGetAscentPtr) (CGFontRef fontRef) = NULL;
|
||||
static int (*CGFontGetDescentPtr) (CGFontRef fontRef) = NULL;
|
||||
static int (*CGFontGetLeadingPtr) (CGFontRef fontRef) = NULL;
|
||||
|
||||
+/* CTFontCreateWithGraphicsFont is not public until 10.5. */
|
||||
+typedef const struct __CTFontDescriptor *CTFontDescriptorRef;
|
||||
+static CTFontRef (*CTFontCreateWithGraphicsFontPtr) (CGFontRef, CGFloat, const CGAffineTransform *, CTFontDescriptorRef) = NULL;
|
||||
+
|
||||
static cairo_bool_t _cairo_quartz_font_symbol_lookup_done = FALSE;
|
||||
static cairo_bool_t _cairo_quartz_font_symbols_present = FALSE;
|
||||
|
||||
static void
|
||||
quartz_font_ensure_symbols(void)
|
||||
{
|
||||
if (_cairo_quartz_font_symbol_lookup_done)
|
||||
return;
|
||||
@@ -122,16 +126,18 @@ quartz_font_ensure_symbols(void)
|
||||
CGFontGetHMetricsPtr = dlsym(RTLD_DEFAULT, "CGFontGetHMetrics");
|
||||
CGFontGetAscentPtr = dlsym(RTLD_DEFAULT, "CGFontGetAscent");
|
||||
CGFontGetDescentPtr = dlsym(RTLD_DEFAULT, "CGFontGetDescent");
|
||||
CGFontGetLeadingPtr = dlsym(RTLD_DEFAULT, "CGFontGetLeading");
|
||||
|
||||
CGContextGetAllowsFontSmoothingPtr = dlsym(RTLD_DEFAULT, "CGContextGetAllowsFontSmoothing");
|
||||
CGContextSetAllowsFontSmoothingPtr = dlsym(RTLD_DEFAULT, "CGContextSetAllowsFontSmoothing");
|
||||
|
||||
+ CTFontCreateWithGraphicsFontPtr = dlsym(RTLD_DEFAULT, "CTFontCreateWithGraphicsFont");
|
||||
+
|
||||
if ((CGFontCreateWithFontNamePtr || CGFontCreateWithNamePtr) &&
|
||||
CGFontGetGlyphBBoxesPtr &&
|
||||
CGFontGetGlyphsForUnicharsPtr &&
|
||||
CGFontGetUnitsPerEmPtr &&
|
||||
CGFontGetGlyphAdvancesPtr &&
|
||||
CGFontGetGlyphPathPtr &&
|
||||
(CGFontGetHMetricsPtr || (CGFontGetAscentPtr && CGFontGetDescentPtr && CGFontGetLeadingPtr)))
|
||||
_cairo_quartz_font_symbols_present = TRUE;
|
||||
@@ -145,16 +151,17 @@ typedef struct _cairo_quartz_scaled_font
|
||||
struct _cairo_quartz_scaled_font {
|
||||
cairo_scaled_font_t base;
|
||||
};
|
||||
|
||||
struct _cairo_quartz_font_face {
|
||||
cairo_font_face_t base;
|
||||
|
||||
CGFontRef cgFont;
|
||||
+ CTFontRef ctFont;
|
||||
};
|
||||
|
||||
/*
|
||||
* font face backend
|
||||
*/
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_quartz_font_face_create_for_toy (cairo_toy_font_face_t *toy_face,
|
||||
@@ -229,16 +236,20 @@ static cairo_status_t
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_quartz_font_face_destroy (void *abstract_face)
|
||||
{
|
||||
cairo_quartz_font_face_t *font_face = (cairo_quartz_font_face_t*) abstract_face;
|
||||
|
||||
+ if (font_face->ctFont) {
|
||||
+ CFRelease (font_face->ctFont);
|
||||
+ }
|
||||
+
|
||||
CGFontRelease (font_face->cgFont);
|
||||
}
|
||||
|
||||
static const cairo_scaled_font_backend_t _cairo_quartz_scaled_font_backend;
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_quartz_font_face_scaled_font_create (void *abstract_face,
|
||||
const cairo_matrix_t *font_matrix,
|
||||
@@ -353,16 +364,22 @@ cairo_quartz_font_face_create_for_cgfont
|
||||
if (!font_face) {
|
||||
cairo_status_t ignore_status;
|
||||
ignore_status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return (cairo_font_face_t *)&_cairo_font_face_nil;
|
||||
}
|
||||
|
||||
font_face->cgFont = CGFontRetain (font);
|
||||
|
||||
+ if (CTFontCreateWithGraphicsFontPtr) {
|
||||
+ font_face->ctFont = CTFontCreateWithGraphicsFontPtr (font, 1.0, NULL, NULL);
|
||||
+ } else {
|
||||
+ font_face->ctFont = NULL;
|
||||
+ }
|
||||
+
|
||||
_cairo_font_face_init (&font_face->base, &_cairo_quartz_font_face_backend);
|
||||
|
||||
return &font_face->base;
|
||||
}
|
||||
|
||||
/*
|
||||
* scaled font backend
|
||||
*/
|
||||
@@ -772,16 +789,24 @@ static const cairo_scaled_font_backend_t
|
||||
CGFontRef
|
||||
_cairo_quartz_scaled_font_get_cg_font_ref (cairo_scaled_font_t *abstract_font)
|
||||
{
|
||||
cairo_quartz_font_face_t *ffont = _cairo_quartz_scaled_to_face(abstract_font);
|
||||
|
||||
return ffont->cgFont;
|
||||
}
|
||||
|
||||
+CTFontRef
|
||||
+_cairo_quartz_scaled_font_get_ct_font_ref (cairo_scaled_font_t *abstract_font)
|
||||
+{
|
||||
+ cairo_quartz_font_face_t *ffont = _cairo_quartz_scaled_to_face(abstract_font);
|
||||
+
|
||||
+ return ffont->ctFont;
|
||||
+}
|
||||
+
|
||||
#ifndef __LP64__
|
||||
/*
|
||||
* compat with old ATSUI backend
|
||||
*/
|
||||
|
||||
/**
|
||||
* cairo_quartz_font_face_create_for_atsu_font_id
|
||||
* @font_id: an ATSUFontID for the font.
|
||||
diff --git a/gfx/cairo/cairo/src/cairo-quartz-private.h b/gfx/cairo/cairo/src/cairo-quartz-private.h
|
||||
--- a/gfx/cairo/cairo/src/cairo-quartz-private.h
|
||||
+++ b/gfx/cairo/cairo/src/cairo-quartz-private.h
|
||||
@@ -45,16 +45,19 @@
|
||||
#include "cairo-surface-clipper-private.h"
|
||||
|
||||
#ifdef CGFLOAT_DEFINED
|
||||
typedef CGFloat cairo_quartz_float_t;
|
||||
#else
|
||||
typedef float cairo_quartz_float_t;
|
||||
#endif
|
||||
|
||||
+/* define CTFontRef for pre-10.5 SDKs */
|
||||
+typedef const struct __CTFont *CTFontRef;
|
||||
+
|
||||
typedef struct cairo_quartz_surface {
|
||||
cairo_surface_t base;
|
||||
|
||||
CGContextRef cgContext;
|
||||
CGAffineTransform cgContextBaseCTM;
|
||||
|
||||
void *imageData;
|
||||
cairo_surface_t *imageSurfaceEquiv;
|
||||
@@ -99,15 +102,18 @@ CGImageRef
|
||||
cairo_bool_t interpolate,
|
||||
CGColorSpaceRef colorSpaceOverride,
|
||||
CGDataProviderReleaseDataCallback releaseCallback,
|
||||
void *releaseInfo);
|
||||
|
||||
CGFontRef
|
||||
_cairo_quartz_scaled_font_get_cg_font_ref (cairo_scaled_font_t *sfont);
|
||||
|
||||
+CTFontRef
|
||||
+_cairo_quartz_scaled_font_get_ct_font_ref (cairo_scaled_font_t *sfont);
|
||||
+
|
||||
#else
|
||||
|
||||
# error Cairo was not compiled with support for the quartz backend
|
||||
|
||||
#endif /* CAIRO_HAS_QUARTZ_SURFACE */
|
||||
|
||||
#endif /* CAIRO_QUARTZ_PRIVATE_H */
|
||||
diff --git a/gfx/cairo/cairo/src/cairo-quartz-surface.c b/gfx/cairo/cairo/src/cairo-quartz-surface.c
|
||||
--- a/gfx/cairo/cairo/src/cairo-quartz-surface.c
|
||||
+++ b/gfx/cairo/cairo/src/cairo-quartz-surface.c
|
||||
@@ -130,16 +130,19 @@ static void (*CGContextClipToMaskPtr) (C
|
||||
static void (*CGContextDrawTiledImagePtr) (CGContextRef, CGRect, CGImageRef) = NULL;
|
||||
static unsigned int (*CGContextGetTypePtr) (CGContextRef) = NULL;
|
||||
static void (*CGContextSetShouldAntialiasFontsPtr) (CGContextRef, bool) = NULL;
|
||||
static void (*CGContextSetAllowsFontSmoothingPtr) (CGContextRef, bool) = NULL;
|
||||
static bool (*CGContextGetAllowsFontSmoothingPtr) (CGContextRef) = NULL;
|
||||
static CGPathRef (*CGContextCopyPathPtr) (CGContextRef) = NULL;
|
||||
static CGFloat (*CGContextGetAlphaPtr) (CGContextRef) = NULL;
|
||||
|
||||
+/* CTFontDrawGlyphs is not available until 10.7 */
|
||||
+static void (*CTFontDrawGlyphsPtr) (CTFontRef, const CGGlyph[], const CGPoint[], size_t, CGContextRef) = NULL;
|
||||
+
|
||||
static SInt32 _cairo_quartz_osx_version = 0x0;
|
||||
|
||||
static cairo_bool_t _cairo_quartz_symbol_lookup_done = FALSE;
|
||||
|
||||
/*
|
||||
* Utility functions
|
||||
*/
|
||||
|
||||
@@ -167,16 +170,18 @@ static void quartz_ensure_symbols(void)
|
||||
CGContextDrawTiledImagePtr = dlsym(RTLD_DEFAULT, "CGContextDrawTiledImage");
|
||||
CGContextGetTypePtr = dlsym(RTLD_DEFAULT, "CGContextGetType");
|
||||
CGContextSetShouldAntialiasFontsPtr = dlsym(RTLD_DEFAULT, "CGContextSetShouldAntialiasFonts");
|
||||
CGContextCopyPathPtr = dlsym(RTLD_DEFAULT, "CGContextCopyPath");
|
||||
CGContextGetAllowsFontSmoothingPtr = dlsym(RTLD_DEFAULT, "CGContextGetAllowsFontSmoothing");
|
||||
CGContextSetAllowsFontSmoothingPtr = dlsym(RTLD_DEFAULT, "CGContextSetAllowsFontSmoothing");
|
||||
CGContextGetAlphaPtr = dlsym(RTLD_DEFAULT, "CGContextGetAlpha");
|
||||
|
||||
+ CTFontDrawGlyphsPtr = dlsym(RTLD_DEFAULT, "CTFontDrawGlyphs");
|
||||
+
|
||||
if (Gestalt(gestaltSystemVersion, &_cairo_quartz_osx_version) != noErr) {
|
||||
// assume 10.5
|
||||
_cairo_quartz_osx_version = 0x1050;
|
||||
}
|
||||
|
||||
_cairo_quartz_symbol_lookup_done = TRUE;
|
||||
}
|
||||
|
||||
@@ -605,20 +610,23 @@ static inline void
|
||||
dst->d = src->yy;
|
||||
dst->tx = src->x0;
|
||||
dst->ty = src->y0;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
bool isClipping;
|
||||
CGGlyph *cg_glyphs;
|
||||
- CGSize *cg_advances;
|
||||
+ union {
|
||||
+ CGSize *cg_advances;
|
||||
+ CGPoint *cg_positions;
|
||||
+ } u;
|
||||
size_t nglyphs;
|
||||
CGAffineTransform textTransform;
|
||||
- CGFontRef font;
|
||||
+ cairo_scaled_font_t *scaled_font;
|
||||
CGPoint origin;
|
||||
} unbounded_show_glyphs_t;
|
||||
|
||||
typedef struct {
|
||||
CGPathRef cgPath;
|
||||
cairo_fill_rule_t fill_rule;
|
||||
} unbounded_stroke_fill_t;
|
||||
|
||||
@@ -686,36 +694,43 @@ static void
|
||||
CGContextBeginPath (cgc);
|
||||
CGContextAddPath (cgc, op->u.stroke_fill.cgPath);
|
||||
|
||||
if (op->u.stroke_fill.fill_rule == CAIRO_FILL_RULE_WINDING)
|
||||
CGContextFillPath (cgc);
|
||||
else
|
||||
CGContextEOFillPath (cgc);
|
||||
} else if (op->op == UNBOUNDED_SHOW_GLYPHS) {
|
||||
- CGContextSetFont (cgc, op->u.show_glyphs.font);
|
||||
- CGContextSetFontSize (cgc, 1.0);
|
||||
- CGContextSetTextMatrix (cgc, CGAffineTransformIdentity);
|
||||
- CGContextTranslateCTM (cgc, op->u.show_glyphs.origin.x, op->u.show_glyphs.origin.y);
|
||||
- CGContextConcatCTM (cgc, op->u.show_glyphs.textTransform);
|
||||
-
|
||||
if (op->u.show_glyphs.isClipping) {
|
||||
/* Note that the comment in show_glyphs about kCGTextClip
|
||||
* and the text transform still applies here; however, the
|
||||
* cg_advances we have were already transformed, so we
|
||||
* don't have to do anything. */
|
||||
CGContextSetTextDrawingMode (cgc, kCGTextClip);
|
||||
CGContextSaveGState (cgc);
|
||||
}
|
||||
-
|
||||
- CGContextShowGlyphsWithAdvances (cgc,
|
||||
- op->u.show_glyphs.cg_glyphs,
|
||||
- op->u.show_glyphs.cg_advances,
|
||||
- op->u.show_glyphs.nglyphs);
|
||||
-
|
||||
+ CGContextTranslateCTM (cgc, op->u.show_glyphs.origin.x, op->u.show_glyphs.origin.y);
|
||||
+ CGContextConcatCTM (cgc, op->u.show_glyphs.textTransform);
|
||||
+ if (CTFontDrawGlyphsPtr) {
|
||||
+ CTFontDrawGlyphsPtr (_cairo_quartz_scaled_font_get_ct_font_ref (op->u.show_glyphs.scaled_font),
|
||||
+ op->u.show_glyphs.cg_glyphs,
|
||||
+ op->u.show_glyphs.u.cg_positions,
|
||||
+ op->u.show_glyphs.nglyphs,
|
||||
+ cgc);
|
||||
+ } else {
|
||||
+ CGContextSetFont (cgc, _cairo_quartz_scaled_font_get_cg_font_ref (op->u.show_glyphs.scaled_font));
|
||||
+ CGContextSetFontSize (cgc, 1.0);
|
||||
+ CGContextSetTextMatrix (cgc, CGAffineTransformIdentity);
|
||||
+
|
||||
+ CGContextShowGlyphsWithAdvances (cgc,
|
||||
+ op->u.show_glyphs.cg_glyphs,
|
||||
+ op->u.show_glyphs.u.cg_advances,
|
||||
+ op->u.show_glyphs.nglyphs);
|
||||
+
|
||||
+ }
|
||||
if (op->u.show_glyphs.isClipping) {
|
||||
CGContextClearRect (cgc, clipBoxRound);
|
||||
CGContextRestoreGState (cgc);
|
||||
}
|
||||
} else if (op->op == UNBOUNDED_MASK) {
|
||||
CGAffineTransform ctm = CGContextGetCTM (cgc);
|
||||
CGContextSaveGState (cgc);
|
||||
CGContextConcatCTM (cgc, op->u.mask.maskTransform);
|
||||
@@ -2684,16 +2699,19 @@ static cairo_int_status_t
|
||||
cairo_clip_t *clip,
|
||||
int *remaining_glyphs)
|
||||
{
|
||||
CGAffineTransform textTransform, ctm, invTextTransform;
|
||||
#define STATIC_BUF_SIZE 64
|
||||
CGGlyph glyphs_static[STATIC_BUF_SIZE];
|
||||
CGSize cg_advances_static[STATIC_BUF_SIZE];
|
||||
CGGlyph *cg_glyphs = &glyphs_static[0];
|
||||
+ /* We'll use the cg_advances array for either advances or positions,
|
||||
+ depending which API we're using to actually draw. The types involved
|
||||
+ have the same size, so this is safe. */
|
||||
CGSize *cg_advances = &cg_advances_static[0];
|
||||
|
||||
cairo_rectangle_int_t glyph_extents;
|
||||
cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
|
||||
cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
|
||||
cairo_quartz_drawing_state_t state;
|
||||
cairo_quartz_float_t xprev, yprev;
|
||||
int i;
|
||||
@@ -2796,41 +2814,62 @@ static cairo_int_status_t
|
||||
invTextTransform = CGAffineTransformMake (scaled_font->scale_inverse.xx,
|
||||
-scaled_font->scale_inverse.yx,
|
||||
scaled_font->scale_inverse.xy,
|
||||
-scaled_font->scale_inverse.yy,
|
||||
0.0, 0.0);
|
||||
|
||||
CGContextSetTextMatrix (state.context, CGAffineTransformIdentity);
|
||||
|
||||
- /* Convert our glyph positions to glyph advances. We need n-1 advances,
|
||||
- * since the advance at index 0 is applied after glyph 0. */
|
||||
- xprev = glyphs[0].x;
|
||||
- yprev = glyphs[0].y;
|
||||
-
|
||||
- cg_glyphs[0] = glyphs[0].index;
|
||||
-
|
||||
- for (i = 1; i < num_glyphs; i++) {
|
||||
- cairo_quartz_float_t xf = glyphs[i].x;
|
||||
- cairo_quartz_float_t yf = glyphs[i].y;
|
||||
- cg_glyphs[i] = glyphs[i].index;
|
||||
- cg_advances[i - 1] = CGSizeApplyAffineTransform(CGSizeMake (xf - xprev, yf - yprev), invTextTransform);
|
||||
- xprev = xf;
|
||||
- yprev = yf;
|
||||
- }
|
||||
-
|
||||
/* Translate to the first glyph's position before drawing */
|
||||
ctm = CGContextGetCTM (state.context);
|
||||
CGContextTranslateCTM (state.context, glyphs[0].x, glyphs[0].y);
|
||||
CGContextConcatCTM (state.context, textTransform);
|
||||
|
||||
- CGContextShowGlyphsWithAdvances (state.context,
|
||||
- cg_glyphs,
|
||||
- cg_advances,
|
||||
- num_glyphs);
|
||||
+ if (CTFontDrawGlyphsPtr) {
|
||||
+ /* If CTFontDrawGlyphs is available (i.e. OS X 10.7 or later), we want to use
|
||||
+ * that in preference to CGContextShowGlyphsWithAdvances so that colored-bitmap
|
||||
+ * fonts like Apple Color Emoji will render properly.
|
||||
+ * For this, we need to convert our glyph positions to Core Graphics's CGPoint.
|
||||
+ * We borrow the cg_advances array, as CGPoint and CGSize are the same size. */
|
||||
+
|
||||
+ CGPoint *cg_positions = (CGPoint*) cg_advances;
|
||||
+ cairo_quartz_float_t origin_x = glyphs[0].x;
|
||||
+ cairo_quartz_float_t origin_y = glyphs[0].y;
|
||||
+
|
||||
+ for (i = 0; i < num_glyphs; i++) {
|
||||
+ CGPoint pt = CGPointMake (glyphs[i].x - origin_x, glyphs[i].y - origin_y);
|
||||
+ cg_positions[i] = CGPointApplyAffineTransform (pt, invTextTransform);
|
||||
+ cg_glyphs[i] = glyphs[i].index;
|
||||
+ }
|
||||
+
|
||||
+ CTFontDrawGlyphsPtr (_cairo_quartz_scaled_font_get_ct_font_ref (scaled_font),
|
||||
+ cg_glyphs, cg_positions, num_glyphs, state.context);
|
||||
+ } else {
|
||||
+ /* Convert our glyph positions to glyph advances. We need n-1 advances,
|
||||
+ * since the advance at index 0 is applied after glyph 0. */
|
||||
+ xprev = glyphs[0].x;
|
||||
+ yprev = glyphs[0].y;
|
||||
+
|
||||
+ cg_glyphs[0] = glyphs[0].index;
|
||||
+
|
||||
+ for (i = 1; i < num_glyphs; i++) {
|
||||
+ cairo_quartz_float_t xf = glyphs[i].x;
|
||||
+ cairo_quartz_float_t yf = glyphs[i].y;
|
||||
+ cg_glyphs[i] = glyphs[i].index;
|
||||
+ cg_advances[i - 1] = CGSizeApplyAffineTransform(CGSizeMake (xf - xprev, yf - yprev), invTextTransform);
|
||||
+ xprev = xf;
|
||||
+ yprev = yf;
|
||||
+ }
|
||||
+
|
||||
+ CGContextShowGlyphsWithAdvances (state.context,
|
||||
+ cg_glyphs,
|
||||
+ cg_advances,
|
||||
+ num_glyphs);
|
||||
+ }
|
||||
|
||||
CGContextSetCTM (state.context, ctm);
|
||||
|
||||
if (state.action == DO_IMAGE || state.action == DO_TILED_IMAGE ||
|
||||
state.action == DO_LAYER) {
|
||||
_cairo_quartz_draw_image (&state, op);
|
||||
} else if (state.action == DO_SHADING) {
|
||||
CGContextConcatCTM (state.context, state.transform);
|
||||
@@ -2847,20 +2886,27 @@ BAIL:
|
||||
cgfref &&
|
||||
!_cairo_operator_bounded_by_mask (op))
|
||||
{
|
||||
unbounded_op_data_t ub;
|
||||
ub.op = UNBOUNDED_SHOW_GLYPHS;
|
||||
|
||||
ub.u.show_glyphs.isClipping = isClipping;
|
||||
ub.u.show_glyphs.cg_glyphs = cg_glyphs;
|
||||
- ub.u.show_glyphs.cg_advances = cg_advances;
|
||||
+ if (CTFontDrawGlyphsPtr) {
|
||||
+ /* we're using Core Text API: the cg_advances array was
|
||||
+ reused (above) for glyph positions */
|
||||
+ CGPoint *cg_positions = (CGPoint*) cg_advances;
|
||||
+ ub.u.show_glyphs.u.cg_positions = cg_positions;
|
||||
+ } else {
|
||||
+ ub.u.show_glyphs.u.cg_advances = cg_advances;
|
||||
+ }
|
||||
ub.u.show_glyphs.nglyphs = num_glyphs;
|
||||
ub.u.show_glyphs.textTransform = textTransform;
|
||||
- ub.u.show_glyphs.font = cgfref;
|
||||
+ ub.u.show_glyphs.scaled_font = scaled_font;
|
||||
ub.u.show_glyphs.origin = CGPointMake (glyphs[0].x, glyphs[0].y);
|
||||
|
||||
_cairo_quartz_fixup_unbounded_operation (surface, &ub, scaled_font->options.antialias);
|
||||
}
|
||||
|
||||
|
||||
if (cg_advances != &cg_advances_static[0]) {
|
||||
free (cg_advances);
|
|
@ -0,0 +1,42 @@
|
|||
From: Jonathan Kew <jkew@mozilla.com>
|
||||
bug 715798 pt 2 - fall back to show_text_glyphs even at huge sizes if scaled_font_glyph_path didn't work. r=jrmuizel
|
||||
|
||||
diff --git a/gfx/cairo/cairo/src/cairo-gstate.c b/gfx/cairo/cairo/src/cairo-gstate.c
|
||||
--- a/gfx/cairo/cairo/src/cairo-gstate.c
|
||||
+++ b/gfx/cairo/cairo/src/cairo-gstate.c
|
||||
@@ -2002,23 +2002,34 @@ cairo_status_t
|
||||
cairo_path_fixed_t path;
|
||||
|
||||
_cairo_path_fixed_init (&path);
|
||||
|
||||
status = _cairo_scaled_font_glyph_path (gstate->scaled_font,
|
||||
transformed_glyphs, num_glyphs,
|
||||
&path);
|
||||
|
||||
- if (status == CAIRO_STATUS_SUCCESS) {
|
||||
+ if (status == CAIRO_STATUS_SUCCESS && !_cairo_path_fixed_fill_is_empty (&path)) {
|
||||
status = _cairo_surface_fill (gstate->target, op, pattern,
|
||||
&path,
|
||||
CAIRO_FILL_RULE_WINDING,
|
||||
gstate->tolerance,
|
||||
gstate->scaled_font->options.antialias,
|
||||
_gstate_get_clip (gstate, &clip));
|
||||
+ } else {
|
||||
+ /* if _cairo_scaled_font_glyph_path() failed, maybe the font doesn't support
|
||||
+ * returning paths, so try the _cairo_surface_show_text_glyphs() option
|
||||
+ */
|
||||
+ status = _cairo_surface_show_text_glyphs (gstate->target, op, pattern,
|
||||
+ utf8, utf8_len,
|
||||
+ transformed_glyphs, num_glyphs,
|
||||
+ transformed_clusters, num_clusters,
|
||||
+ cluster_flags,
|
||||
+ gstate->scaled_font,
|
||||
+ _gstate_get_clip (gstate, &clip));
|
||||
}
|
||||
|
||||
_cairo_path_fixed_fini (&path);
|
||||
}
|
||||
|
||||
_cairo_clip_fini (&clip);
|
||||
|
||||
CLEANUP_GLYPHS:
|
|
@ -410,7 +410,10 @@ BasicTiledThebesLayer::PaintThebes(gfxContext* aContext,
|
|||
transform.Invert();
|
||||
|
||||
// Store the old valid region, then clear it before painting.
|
||||
// We clip the old valid region to the visible region, as it only gets
|
||||
// used to decide stale content (currently valid and previously visible)
|
||||
nsIntRegion oldValidRegion = mTiledBuffer.GetValidRegion();
|
||||
oldValidRegion.And(oldValidRegion, mVisibleRegion);
|
||||
mTiledBuffer.ClearPaintedRegion();
|
||||
|
||||
// Make sure that tiles that fall outside of the visible region are
|
||||
|
@ -453,8 +456,14 @@ BasicTiledThebesLayer::PaintThebes(gfxContext* aContext,
|
|||
// Keep track of what we're about to refresh.
|
||||
mValidRegion.Or(mValidRegion, regionToPaint);
|
||||
|
||||
// mValidRegion would have been altered by InvalidateRegion, but we still
|
||||
// want to display stale content until it gets progressively updated.
|
||||
// Create a region that includes stale content.
|
||||
nsIntRegion validOrStale;
|
||||
validOrStale.Or(mValidRegion, oldValidRegion);
|
||||
|
||||
// Paint the computed region and subtract it from the invalid region.
|
||||
mTiledBuffer.PaintThebes(this, mValidRegion, regionToPaint, aCallback, aCallbackData);
|
||||
mTiledBuffer.PaintThebes(this, validOrStale, regionToPaint, aCallback, aCallbackData);
|
||||
invalidRegion.Sub(invalidRegion, regionToPaint);
|
||||
} while (repeat);
|
||||
} else {
|
||||
|
|
|
@ -444,22 +444,6 @@ inline nscoord NSIntPixelsToAppUnits(int32_t aPixels, int32_t aAppUnitsPerPixel)
|
|||
{
|
||||
// The cast to nscoord makes sure we don't overflow if we ever change
|
||||
// nscoord to float
|
||||
#ifndef NS_COORD_IS_FLOAT
|
||||
const int pixels_MAX = nscoord_MAX / aAppUnitsPerPixel;
|
||||
// Bounds-check before converting out of float, to avoid overflow
|
||||
NS_WARN_IF_FALSE(aPixels <= pixels_MAX,
|
||||
"Overflowed nscoord_MAX in conversion to nscoord");
|
||||
if (aPixels >= pixels_MAX) {
|
||||
aPixels = pixels_MAX;
|
||||
} else {
|
||||
const int pixels_MIN = nscoord_MIN / aAppUnitsPerPixel;
|
||||
NS_WARN_IF_FALSE(aPixels >= pixels_MIN,
|
||||
"Overflowed nscoord_MIN in conversion to nscoord");
|
||||
if (aPixels <= pixels_MIN) {
|
||||
aPixels = pixels_MIN;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
nscoord r = aPixels * (nscoord)aAppUnitsPerPixel;
|
||||
VERIFY_COORD(r);
|
||||
return r;
|
||||
|
|
78
hal/Hal.cpp
78
hal/Hal.cpp
|
@ -405,52 +405,86 @@ void SetScreenBrightness(double brightness)
|
|||
PROXY_IF_SANDBOXED(SetScreenBrightness(clamped(brightness, 0.0, 1.0)));
|
||||
}
|
||||
|
||||
bool SetLight(LightType light, const hal::LightConfiguration& aConfig)
|
||||
bool SetLight(LightType light, const LightConfiguration& aConfig)
|
||||
{
|
||||
AssertMainThread();
|
||||
RETURN_PROXY_IF_SANDBOXED(SetLight(light, aConfig), false);
|
||||
}
|
||||
|
||||
bool GetLight(LightType light, hal::LightConfiguration* aConfig)
|
||||
bool GetLight(LightType light, LightConfiguration* aConfig)
|
||||
{
|
||||
AssertMainThread();
|
||||
RETURN_PROXY_IF_SANDBOXED(GetLight(light, aConfig), false);
|
||||
}
|
||||
|
||||
class SystemTimeObserversManager : public ObserversManager<SystemTimeChange>
|
||||
class SystemClockChangeObserversManager : public ObserversManager<int64_t>
|
||||
{
|
||||
protected:
|
||||
void EnableNotifications() {
|
||||
PROXY_IF_SANDBOXED(EnableSystemTimeChangeNotifications());
|
||||
PROXY_IF_SANDBOXED(EnableSystemClockChangeNotifications());
|
||||
}
|
||||
|
||||
void DisableNotifications() {
|
||||
PROXY_IF_SANDBOXED(DisableSystemTimeChangeNotifications());
|
||||
PROXY_IF_SANDBOXED(DisableSystemClockChangeNotifications());
|
||||
}
|
||||
};
|
||||
|
||||
static SystemTimeObserversManager sSystemTimeObservers;
|
||||
static SystemClockChangeObserversManager sSystemClockChangeObservers;
|
||||
|
||||
void
|
||||
RegisterSystemTimeChangeObserver(SystemTimeObserver *aObserver)
|
||||
RegisterSystemClockChangeObserver(SystemClockChangeObserver* aObserver)
|
||||
{
|
||||
AssertMainThread();
|
||||
sSystemTimeObservers.AddObserver(aObserver);
|
||||
sSystemClockChangeObservers.AddObserver(aObserver);
|
||||
}
|
||||
|
||||
void
|
||||
UnregisterSystemTimeChangeObserver(SystemTimeObserver *aObserver)
|
||||
UnregisterSystemClockChangeObserver(SystemClockChangeObserver* aObserver)
|
||||
{
|
||||
AssertMainThread();
|
||||
sSystemTimeObservers.RemoveObserver(aObserver);
|
||||
sSystemClockChangeObservers.RemoveObserver(aObserver);
|
||||
}
|
||||
|
||||
void
|
||||
NotifySystemTimeChange(const hal::SystemTimeChange& aReason)
|
||||
NotifySystemClockChange(const int64_t& aClockDeltaMS)
|
||||
{
|
||||
sSystemTimeObservers.BroadcastInformation(aReason);
|
||||
sSystemClockChangeObservers.BroadcastInformation(aClockDeltaMS);
|
||||
}
|
||||
|
||||
|
||||
class SystemTimezoneChangeObserversManager : public ObserversManager<SystemTimezoneChangeInformation>
|
||||
{
|
||||
protected:
|
||||
void EnableNotifications() {
|
||||
PROXY_IF_SANDBOXED(EnableSystemTimezoneChangeNotifications());
|
||||
}
|
||||
|
||||
void DisableNotifications() {
|
||||
PROXY_IF_SANDBOXED(DisableSystemTimezoneChangeNotifications());
|
||||
}
|
||||
};
|
||||
|
||||
static SystemTimezoneChangeObserversManager sSystemTimezoneChangeObservers;
|
||||
|
||||
void
|
||||
RegisterSystemTimezoneChangeObserver(SystemTimezoneChangeObserver* aObserver)
|
||||
{
|
||||
AssertMainThread();
|
||||
sSystemTimezoneChangeObservers.AddObserver(aObserver);
|
||||
}
|
||||
|
||||
void
|
||||
UnregisterSystemTimezoneChangeObserver(SystemTimezoneChangeObserver* aObserver)
|
||||
{
|
||||
AssertMainThread();
|
||||
sSystemTimezoneChangeObservers.RemoveObserver(aObserver);
|
||||
}
|
||||
|
||||
void
|
||||
NotifySystemTimezoneChange(const SystemTimezoneChangeInformation& aSystemTimezoneChangeInfo)
|
||||
{
|
||||
sSystemTimezoneChangeObservers.BroadcastInformation(aSystemTimezoneChangeInfo);
|
||||
}
|
||||
|
||||
void
|
||||
AdjustSystemClock(int64_t aDeltaMilliseconds)
|
||||
{
|
||||
|
@ -607,8 +641,8 @@ UnregisterWakeLockObserver(WakeLockObserver* aObserver)
|
|||
|
||||
void
|
||||
ModifyWakeLock(const nsAString &aTopic,
|
||||
hal::WakeLockControl aLockAdjust,
|
||||
hal::WakeLockControl aHiddenAdjust)
|
||||
WakeLockControl aLockAdjust,
|
||||
WakeLockControl aHiddenAdjust)
|
||||
{
|
||||
AssertMainThread();
|
||||
PROXY_IF_SANDBOXED(ModifyWakeLock(aTopic, aLockAdjust, aHiddenAdjust));
|
||||
|
@ -671,18 +705,18 @@ UnlockScreenOrientation()
|
|||
}
|
||||
|
||||
void
|
||||
EnableSwitchNotifications(hal::SwitchDevice aDevice) {
|
||||
EnableSwitchNotifications(SwitchDevice aDevice) {
|
||||
AssertMainThread();
|
||||
PROXY_IF_SANDBOXED(EnableSwitchNotifications(aDevice));
|
||||
}
|
||||
|
||||
void
|
||||
DisableSwitchNotifications(hal::SwitchDevice aDevice) {
|
||||
DisableSwitchNotifications(SwitchDevice aDevice) {
|
||||
AssertMainThread();
|
||||
PROXY_IF_SANDBOXED(DisableSwitchNotifications(aDevice));
|
||||
}
|
||||
|
||||
hal::SwitchState GetCurrentSwitchState(hal::SwitchDevice aDevice)
|
||||
SwitchState GetCurrentSwitchState(SwitchDevice aDevice)
|
||||
{
|
||||
AssertMainThread();
|
||||
RETURN_PROXY_IF_SANDBOXED(GetCurrentSwitchState(aDevice), SWITCH_STATE_UNKNOWN);
|
||||
|
@ -693,7 +727,7 @@ typedef mozilla::ObserverList<SwitchEvent> SwitchObserverList;
|
|||
static SwitchObserverList *sSwitchObserverLists = NULL;
|
||||
|
||||
static SwitchObserverList&
|
||||
GetSwitchObserverList(hal::SwitchDevice aDevice) {
|
||||
GetSwitchObserverList(SwitchDevice aDevice) {
|
||||
MOZ_ASSERT(0 <= aDevice && aDevice < NUM_SWITCH_DEVICE);
|
||||
if (sSwitchObserverLists == NULL) {
|
||||
sSwitchObserverLists = new SwitchObserverList[NUM_SWITCH_DEVICE];
|
||||
|
@ -714,7 +748,7 @@ ReleaseObserversIfNeeded() {
|
|||
}
|
||||
|
||||
void
|
||||
RegisterSwitchObserver(hal::SwitchDevice aDevice, hal::SwitchObserver *aObserver)
|
||||
RegisterSwitchObserver(SwitchDevice aDevice, SwitchObserver *aObserver)
|
||||
{
|
||||
AssertMainThread();
|
||||
SwitchObserverList& observer = GetSwitchObserverList(aDevice);
|
||||
|
@ -725,7 +759,7 @@ RegisterSwitchObserver(hal::SwitchDevice aDevice, hal::SwitchObserver *aObserver
|
|||
}
|
||||
|
||||
void
|
||||
UnregisterSwitchObserver(hal::SwitchDevice aDevice, hal::SwitchObserver *aObserver)
|
||||
UnregisterSwitchObserver(SwitchDevice aDevice, SwitchObserver *aObserver)
|
||||
{
|
||||
AssertMainThread();
|
||||
|
||||
|
@ -743,7 +777,7 @@ UnregisterSwitchObserver(hal::SwitchDevice aDevice, hal::SwitchObserver *aObserv
|
|||
}
|
||||
|
||||
void
|
||||
NotifySwitchChange(const hal::SwitchEvent& aEvent)
|
||||
NotifySwitchChange(const SwitchEvent& aEvent)
|
||||
{
|
||||
// When callback this notification, main thread may call unregister function
|
||||
// first. We should check if this pointer is valid.
|
||||
|
|
40
hal/Hal.h
40
hal/Hal.h
|
@ -50,7 +50,8 @@ class WindowIdentifier;
|
|||
extern PRLogModuleInfo *sHalLog;
|
||||
#define HAL_LOG(msg) PR_LOG(mozilla::hal::sHalLog, PR_LOG_DEBUG, msg)
|
||||
|
||||
typedef Observer<SystemTimeChange> SystemTimeObserver;
|
||||
typedef Observer<int64_t> SystemClockChangeObserver;
|
||||
typedef Observer<SystemTimezoneChangeInformation> SystemTimezoneChangeObserver;
|
||||
|
||||
} // namespace hal
|
||||
|
||||
|
@ -258,22 +259,45 @@ void SetTimezone(const nsCString& aTimezoneSpec);
|
|||
nsCString GetTimezone();
|
||||
|
||||
/**
|
||||
* Register observer for system time changed notification.
|
||||
* Register observer for system clock changed notification.
|
||||
* @param aObserver The observer that should be added.
|
||||
*/
|
||||
void RegisterSystemTimeChangeObserver(hal::SystemTimeObserver* aObserver);
|
||||
void RegisterSystemClockChangeObserver(
|
||||
hal::SystemClockChangeObserver* aObserver);
|
||||
|
||||
/**
|
||||
* Unregister the observer for system time changed.
|
||||
* Unregister the observer for system clock changed.
|
||||
* @param aObserver The observer that should be removed.
|
||||
*/
|
||||
void UnregisterSystemTimeChangeObserver(hal::SystemTimeObserver* aObserver);
|
||||
void UnregisterSystemClockChangeObserver(
|
||||
hal::SystemClockChangeObserver* aObserver);
|
||||
|
||||
/**
|
||||
* Notify of a change in the system cloeck or time zone.
|
||||
* @param aReason
|
||||
* Notify of a change in the system clock.
|
||||
* @param aClockDeltaMS
|
||||
*/
|
||||
void NotifySystemTimeChange(const hal::SystemTimeChange& aReason);
|
||||
void NotifySystemClockChange(const int64_t& aClockDeltaMS);
|
||||
|
||||
/**
|
||||
* Register observer for system timezone changed notification.
|
||||
* @param aObserver The observer that should be added.
|
||||
*/
|
||||
void RegisterSystemTimezoneChangeObserver(
|
||||
hal::SystemTimezoneChangeObserver* aObserver);
|
||||
|
||||
/**
|
||||
* Unregister the observer for system timezone changed.
|
||||
* @param aObserver The observer that should be removed.
|
||||
*/
|
||||
void UnregisterSystemTimezoneChangeObserver(
|
||||
hal::SystemTimezoneChangeObserver* aObserver);
|
||||
|
||||
/**
|
||||
* Notify of a change in the system timezone.
|
||||
* @param aSystemTimezoneChangeInfo
|
||||
*/
|
||||
void NotifySystemTimezoneChange(
|
||||
const hal::SystemTimezoneChangeInformation& aSystemTimezoneChangeInfo);
|
||||
|
||||
/**
|
||||
* Reboot the device.
|
||||
|
|
|
@ -75,14 +75,24 @@ bool EnableAlarm();
|
|||
void DisableAlarm();
|
||||
|
||||
/**
|
||||
* Enable system time change notifications from the backend.
|
||||
* Enable system clock change notifications from the backend.
|
||||
*/
|
||||
void EnableSystemTimeChangeNotifications();
|
||||
void EnableSystemClockChangeNotifications();
|
||||
|
||||
/**
|
||||
* Disable system time change notifications from the backend.
|
||||
* Disable system clock change notifications from the backend.
|
||||
*/
|
||||
void DisableSystemTimeChangeNotifications();
|
||||
void DisableSystemClockChangeNotifications();
|
||||
|
||||
/**
|
||||
* Enable system timezone change notifications from the backend.
|
||||
*/
|
||||
void EnableSystemTimezoneChangeNotifications();
|
||||
|
||||
/**
|
||||
* Disable system timezone change notifications from the backend.
|
||||
*/
|
||||
void DisableSystemTimezoneChangeNotifications();
|
||||
|
||||
bool IsHalChildLive();
|
||||
} // namespace MOZ_HAL_NAMESPACE
|
||||
|
|
|
@ -84,13 +84,6 @@ enum WakeLockControl {
|
|||
NUM_WAKE_LOCK
|
||||
};
|
||||
|
||||
enum SystemTimeChange {
|
||||
SYS_TIME_CHANGE_UNKNOWN = -1,
|
||||
SYS_TIME_CHANGE_CLOCK,
|
||||
SYS_TIME_CHANGE_TZ,
|
||||
SYS_TIME_CHANGE_GUARD
|
||||
};
|
||||
|
||||
class FMRadioOperationInformation;
|
||||
|
||||
enum FMRadioOperation {
|
||||
|
@ -167,7 +160,6 @@ enum FMRadioCountry {
|
|||
};
|
||||
|
||||
typedef Observer<FMRadioOperationInformation> FMRadioObserver;
|
||||
typedef Observer<SystemTimeChange> SystemTimeChangeObserver;
|
||||
} // namespace hal
|
||||
} // namespace mozilla
|
||||
|
||||
|
@ -250,16 +242,6 @@ struct ParamTraits<mozilla::hal::ProcessPriority>:
|
|||
mozilla::hal::NUM_PROCESS_PRIORITY> {
|
||||
};
|
||||
|
||||
/**
|
||||
* SystemTimeChange serializer.
|
||||
*/
|
||||
template <>
|
||||
struct ParamTraits<mozilla::hal::SystemTimeChange>
|
||||
: public EnumSerializer<mozilla::hal::SystemTimeChange,
|
||||
mozilla::hal::SYS_TIME_CHANGE_UNKNOWN,
|
||||
mozilla::hal::SYS_TIME_CHANGE_GUARD>
|
||||
{};
|
||||
|
||||
/**
|
||||
* Serializer for FMRadioOperation
|
||||
*/
|
||||
|
|
|
@ -25,13 +25,24 @@ GetTimezone()
|
|||
}
|
||||
|
||||
void
|
||||
EnableSystemTimeChangeNotifications()
|
||||
EnableSystemClockChangeNotifications()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
DisableSystemTimeChangeNotifications()
|
||||
DisableSystemClockChangeNotifications()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
EnableSystemTimezoneChangeNotifications()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
DisableSystemTimezoneChangeNotifications()
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace hal_impl
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -83,6 +83,13 @@
|
|||
#define OOM_SCORE_ADJ_MAX 1000
|
||||
#endif
|
||||
|
||||
#ifndef BATTERY_CHARGING_ARGB
|
||||
#define BATTERY_CHARGING_ARGB 0x00FF0000
|
||||
#endif
|
||||
#ifndef BATTERY_FULL_ARGB
|
||||
#define BATTERY_FULL_ARGB 0x0000FF00
|
||||
#endif
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::hal;
|
||||
|
||||
|
@ -250,6 +257,26 @@ public:
|
|||
{
|
||||
hal::BatteryInformation info;
|
||||
hal_impl::GetCurrentBatteryInformation(&info);
|
||||
|
||||
// Control the battery indicator (led light) here using BatteryInformation
|
||||
// we just retrieved.
|
||||
uint32_t color = 0; // Format: 0x00rrggbb.
|
||||
if (info.charging() && (info.level() == 1)) {
|
||||
// Charging and battery full.
|
||||
color = BATTERY_FULL_ARGB;
|
||||
} else if (info.charging() && (info.level() < 1)) {
|
||||
// Charging but not full.
|
||||
color = BATTERY_CHARGING_ARGB;
|
||||
} // else turn off battery indicator.
|
||||
|
||||
hal::LightConfiguration aConfig(hal::eHalLightID_Battery,
|
||||
hal::eHalLightMode_User,
|
||||
hal::eHalLightFlash_None,
|
||||
0,
|
||||
0,
|
||||
color);
|
||||
hal_impl::SetLight(hal::eHalLightID_Battery, aConfig);
|
||||
|
||||
hal::NotifyBatteryChange(info);
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -643,7 +670,21 @@ AdjustSystemClock(int64_t aDeltaMilliseconds)
|
|||
return;
|
||||
}
|
||||
|
||||
hal::NotifySystemTimeChange(hal::SYS_TIME_CHANGE_CLOCK);
|
||||
hal::NotifySystemClockChange(aDeltaMilliseconds);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
GetTimezoneOffset()
|
||||
{
|
||||
PRExplodedTime prTime;
|
||||
PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &prTime);
|
||||
|
||||
// Daylight saving time (DST) will be taken into account.
|
||||
int32_t offset = prTime.tm_params.tp_gmt_offset;
|
||||
offset += prTime.tm_params.tp_dst_offset;
|
||||
|
||||
// Returns the timezone offset relative to UTC in minutes.
|
||||
return -(offset / 60);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -653,11 +694,15 @@ SetTimezone(const nsCString& aTimezoneSpec)
|
|||
return;
|
||||
}
|
||||
|
||||
int32_t oldTimezoneOffsetMinutes = GetTimezoneOffset();
|
||||
property_set("persist.sys.timezone", aTimezoneSpec.get());
|
||||
// this function is automatically called by the other time conversion
|
||||
// functions that depend on the timezone. To be safe, we call it manually.
|
||||
tzset();
|
||||
hal::NotifySystemTimeChange(hal::SYS_TIME_CHANGE_TZ);
|
||||
int32_t newTimezoneOffsetMinutes = GetTimezoneOffset();
|
||||
hal::NotifySystemTimezoneChange(
|
||||
hal::SystemTimezoneChangeInformation(
|
||||
oldTimezoneOffsetMinutes, newTimezoneOffsetMinutes));
|
||||
}
|
||||
|
||||
nsCString
|
||||
|
@ -669,12 +714,22 @@ GetTimezone()
|
|||
}
|
||||
|
||||
void
|
||||
EnableSystemTimeChangeNotifications()
|
||||
EnableSystemClockChangeNotifications()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
DisableSystemTimeChangeNotifications()
|
||||
DisableSystemClockChangeNotifications()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
EnableSystemTimezoneChangeNotifications()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
DisableSystemTimezoneChangeNotifications()
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@ using mozilla::hal::SwitchDevice;
|
|||
using mozilla::hal::ProcessPriority;
|
||||
using nsIntRect;
|
||||
using PRTime;
|
||||
using mozilla::hal::SystemTimeChange;
|
||||
using mozilla::hal::FMRadioCountry;
|
||||
using mozilla::hal::FMRadioOperation;
|
||||
using mozilla::hal::FMRadioOperationStatus;
|
||||
|
@ -92,6 +91,13 @@ struct FMRadioSettings {
|
|||
uint32_t preEmphasis;
|
||||
};
|
||||
|
||||
struct SystemTimezoneChangeInformation {
|
||||
// These timezone offsets are relative to UTC in minutes and
|
||||
// have already taken daylight saving time (DST) into account.
|
||||
int32_t oldTimezoneOffsetMinutes;
|
||||
int32_t newTimezoneOffsetMinutes;
|
||||
};
|
||||
|
||||
} // namespace hal
|
||||
|
||||
namespace hal_sandbox {
|
||||
|
@ -105,7 +111,8 @@ child:
|
|||
NotifyWakeLockChange(WakeLockInformation aWakeLockInfo);
|
||||
NotifyScreenConfigurationChange(ScreenConfiguration aScreenOrientation);
|
||||
NotifySwitchChange(SwitchEvent aEvent);
|
||||
NotifySystemTimeChange(SystemTimeChange aReason);
|
||||
NotifySystemClockChange(int64_t aClockDeltaMS);
|
||||
NotifySystemTimezoneChange(SystemTimezoneChangeInformation aSystemTimezoneChangeInfo);
|
||||
NotifyFMRadioStatus(FMRadioOperationInformation aInfo);
|
||||
|
||||
parent:
|
||||
|
@ -135,8 +142,10 @@ parent:
|
|||
SetTimezone(nsCString aTimezoneSpec);
|
||||
sync GetTimezone()
|
||||
returns (nsCString aTimezoneSpec);
|
||||
EnableSystemTimeChangeNotifications();
|
||||
DisableSystemTimeChangeNotifications();
|
||||
EnableSystemClockChangeNotifications();
|
||||
DisableSystemClockChangeNotifications();
|
||||
EnableSystemTimezoneChangeNotifications();
|
||||
DisableSystemTimezoneChangeNotifications();
|
||||
|
||||
sync SetLight(LightType light, LightConfiguration aConfig)
|
||||
returns (bool status);
|
||||
|
|
|
@ -212,15 +212,27 @@ GetTimezone()
|
|||
}
|
||||
|
||||
void
|
||||
EnableSystemTimeChangeNotifications()
|
||||
EnableSystemClockChangeNotifications()
|
||||
{
|
||||
Hal()->SendEnableSystemTimeChangeNotifications();
|
||||
Hal()->SendEnableSystemClockChangeNotifications();
|
||||
}
|
||||
|
||||
void
|
||||
DisableSystemTimeChangeNotifications()
|
||||
DisableSystemClockChangeNotifications()
|
||||
{
|
||||
Hal()->SendDisableSystemTimeChangeNotifications();
|
||||
Hal()->SendDisableSystemClockChangeNotifications();
|
||||
}
|
||||
|
||||
void
|
||||
EnableSystemTimezoneChangeNotifications()
|
||||
{
|
||||
Hal()->SendEnableSystemTimezoneChangeNotifications();
|
||||
}
|
||||
|
||||
void
|
||||
DisableSystemTimezoneChangeNotifications()
|
||||
{
|
||||
Hal()->SendDisableSystemTimezoneChangeNotifications();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -394,7 +406,8 @@ class HalParent : public PHalParent
|
|||
, public WakeLockObserver
|
||||
, public ScreenConfigurationObserver
|
||||
, public SwitchObserver
|
||||
, public SystemTimeObserver
|
||||
, public SystemClockChangeObserver
|
||||
, public SystemTimezoneChangeObserver
|
||||
{
|
||||
public:
|
||||
virtual void
|
||||
|
@ -410,7 +423,8 @@ public:
|
|||
hal::UnregisterSensorObserver(SensorType(sensor), this);
|
||||
}
|
||||
hal::UnregisterWakeLockObserver(this);
|
||||
hal::UnregisterSystemTimeChangeObserver(this);
|
||||
hal::UnregisterSystemClockChangeObserver(this);
|
||||
hal::UnregisterSystemTimezoneChangeObserver(this);
|
||||
}
|
||||
|
||||
virtual bool
|
||||
|
@ -643,16 +657,30 @@ public:
|
|||
}
|
||||
|
||||
virtual bool
|
||||
RecvEnableSystemTimeChangeNotifications() MOZ_OVERRIDE
|
||||
RecvEnableSystemClockChangeNotifications() MOZ_OVERRIDE
|
||||
{
|
||||
hal::RegisterSystemTimeChangeObserver(this);
|
||||
hal::RegisterSystemClockChangeObserver(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool
|
||||
RecvDisableSystemTimeChangeNotifications() MOZ_OVERRIDE
|
||||
RecvDisableSystemClockChangeNotifications() MOZ_OVERRIDE
|
||||
{
|
||||
hal::UnregisterSystemTimeChangeObserver(this);
|
||||
hal::UnregisterSystemClockChangeObserver(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool
|
||||
RecvEnableSystemTimezoneChangeNotifications() MOZ_OVERRIDE
|
||||
{
|
||||
hal::RegisterSystemTimezoneChangeObserver(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool
|
||||
RecvDisableSystemTimezoneChangeNotifications() MOZ_OVERRIDE
|
||||
{
|
||||
hal::UnregisterSystemTimezoneChangeObserver(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -749,9 +777,14 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
void Notify(const SystemTimeChange& aReason)
|
||||
void Notify(const int64_t& aClockDeltaMS)
|
||||
{
|
||||
unused << SendNotifySystemTimeChange(aReason);
|
||||
unused << SendNotifySystemClockChange(aClockDeltaMS);
|
||||
}
|
||||
|
||||
void Notify(const SystemTimezoneChangeInformation& aSystemTimezoneChangeInfo)
|
||||
{
|
||||
unused << SendNotifySystemTimezoneChange(aSystemTimezoneChangeInfo);
|
||||
}
|
||||
|
||||
virtual bool
|
||||
|
@ -902,8 +935,15 @@ public:
|
|||
}
|
||||
|
||||
virtual bool
|
||||
RecvNotifySystemTimeChange(const SystemTimeChange& aReason) {
|
||||
hal::NotifySystemTimeChange(aReason);
|
||||
RecvNotifySystemClockChange(const int64_t& aClockDeltaMS) {
|
||||
hal::NotifySystemClockChange(aClockDeltaMS);
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool
|
||||
RecvNotifySystemTimezoneChange(
|
||||
const SystemTimezoneChangeInformation& aSystemTimezoneChangeInfo) {
|
||||
hal::NotifySystemTimezoneChange(aSystemTimezoneChangeInfo);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ static const uint8_t gASCIIToLower [128] = {
|
|||
// We want ToLowerCase(uint32_t) and ToLowerCaseASCII(uint32_t) to be fast
|
||||
// when they're called from within the case-insensitive comparators, so we
|
||||
// define inlined versions.
|
||||
static NS_ALWAYS_INLINE uint32_t
|
||||
static MOZ_ALWAYS_INLINE uint32_t
|
||||
ToLowerCase_inline(uint32_t aChar)
|
||||
{
|
||||
if (IS_ASCII(aChar)) {
|
||||
|
@ -46,7 +46,7 @@ ToLowerCase_inline(uint32_t aChar)
|
|||
return mozilla::unicode::GetLowercase(aChar);
|
||||
}
|
||||
|
||||
static NS_ALWAYS_INLINE uint32_t
|
||||
static MOZ_ALWAYS_INLINE uint32_t
|
||||
ToLowerCaseASCII_inline(const uint32_t aChar)
|
||||
{
|
||||
if (IS_ASCII(aChar)) {
|
||||
|
@ -271,7 +271,7 @@ CaseInsensitiveCompare(const PRUnichar *a,
|
|||
// the end of the string (as marked by aEnd), returns -1 and does not set
|
||||
// aNext. Note that this function doesn't check that aStr < aEnd -- it assumes
|
||||
// you've done that already.
|
||||
static NS_ALWAYS_INLINE uint32_t
|
||||
static MOZ_ALWAYS_INLINE uint32_t
|
||||
GetLowerUTF8Codepoint(const char* aStr, const char* aEnd, const char **aNext)
|
||||
{
|
||||
// Convert to unsigned char so that stuffing chars into PRUint32s doesn't
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
// |jit-test| error:ReferenceError
|
||||
function e() {
|
||||
try {} catch (e) {
|
||||
return (actual = "FAIL");
|
||||
a.x + a.x + a.x + a.x + a.x + a.x + a.x + a.x
|
||||
a.x + a.x + a.x + a.x + a.x + a.x + a.x + a.x
|
||||
a.x + a.x + a.x + a.x + a.x + a.x + a.x + a.x
|
||||
a.x + a.x + a.x + a.x + a.x + a.x + a.x + a.x
|
||||
a.x + a.x + a.x + a.x + a.x + a.x + a.x + a.x
|
||||
a.x + a.x + a.x + a.x + a.x + a.x + a.x + a.x
|
||||
a.x + a.x + a.x + a.x + a.x + a.x + a.x + a.x
|
||||
a.x + a.x + a.x + a.x + a.x + a.x + a.x + a.x
|
||||
a.x + a.x + a.x + a.x + a.x + a.x + a.x + a.x
|
||||
a.x + a.x + a.x + a.x + a.x + a.x + a.x + a.x
|
||||
a.x + a.x + a.x + a.x + a.x + a.x + a.x + a.x
|
||||
a.x + a.x + a.x + a.x + a.x + a.x + a.x + a.x
|
||||
a.x + a.x + a.x + a.x + a.x + a.x + a.x + a.x
|
||||
a.x + a.x + a.x + a.x + a.x + a.x + a.x + a.x
|
||||
a.x + a.x + a.x + a.x + a.x + a.x + a.x + a.x
|
||||
a.x + a.x + a.x + a.x + a.x + a.x + a.x + a.x
|
||||
a.x + a.x + a.x + a.x + a.x + a.x + a.x + a.x
|
||||
}
|
||||
while (t) continue;
|
||||
}
|
||||
e();
|
|
@ -0,0 +1,9 @@
|
|||
mjitChunkLimit(42);
|
||||
Function("\
|
||||
switch (/x/) {\
|
||||
case 8:\
|
||||
break;\
|
||||
t(function(){})\
|
||||
}\
|
||||
while (false)(function(){})\
|
||||
")()
|
|
@ -0,0 +1,10 @@
|
|||
mjitChunkLimit(10);
|
||||
function e() {
|
||||
try {
|
||||
var t = undefined;
|
||||
} catch (e) { }
|
||||
while (t)
|
||||
continue;
|
||||
}
|
||||
for (var i = 0; i < 20; i++)
|
||||
e();
|
|
@ -2603,7 +2603,7 @@ MarkRuntime(JSTracer *trc, bool useSavedRoots = false)
|
|||
mjit::ExpandInlineFrames(c);
|
||||
#endif
|
||||
|
||||
rt->stackSpace.markAndClobber(trc);
|
||||
rt->stackSpace.mark(trc);
|
||||
rt->debugScopes->mark(trc);
|
||||
|
||||
#ifdef JS_ION
|
||||
|
@ -3851,13 +3851,6 @@ BeginSweepPhase(JSRuntime *rt)
|
|||
{
|
||||
gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_SWEEP_COMPARTMENTS);
|
||||
|
||||
/*
|
||||
* Eliminate any garbage values from the VM stack that may have been
|
||||
* left by the JIT in between incremental GC slices. We need to do this
|
||||
* before discarding analysis data during JSCompartment::sweep.
|
||||
*/
|
||||
rt->stackSpace.markAndClobber(NULL);
|
||||
|
||||
bool releaseTypes = ReleaseObservedTypes(rt);
|
||||
for (CompartmentsIter c(rt); !c.done(); c.next()) {
|
||||
gcstats::AutoSCC scc(rt->gcStats, partition.getSCC(c));
|
||||
|
|
|
@ -748,12 +748,7 @@ void
|
|||
StackTypeSet::addPropagateThis(JSContext *cx, HandleScript script, jsbytecode *pc,
|
||||
Type type, StackTypeSet *types)
|
||||
{
|
||||
/* Don't add constraints when the call will be 'new' (see addCallProperty). */
|
||||
jsbytecode *callpc = script->analysis()->getCallPC(pc);
|
||||
if (JSOp(*callpc) == JSOP_NEW)
|
||||
return;
|
||||
|
||||
add(cx, cx->analysisLifoAlloc().new_<TypeConstraintPropagateThis>(script, callpc, type, types));
|
||||
add(cx, cx->analysisLifoAlloc().new_<TypeConstraintPropagateThis>(script, pc, type, types));
|
||||
}
|
||||
|
||||
/* Subset constraint which filters out primitive types. */
|
||||
|
@ -1207,7 +1202,6 @@ TypeConstraintCallProp<access>::newType(JSContext *cx, TypeSet *source, Type typ
|
|||
return;
|
||||
if (!types->hasPropagatedProperty())
|
||||
object->getFromPrototypes(cx, id, types);
|
||||
/* Bypass addPropagateThis, we already have the callpc. */
|
||||
if (access == PROPERTY_READ) {
|
||||
types->add(cx, cx->typeLifoAlloc().new_<TypeConstraintPropagateThis>(
|
||||
script_, callpc, type, (StackTypeSet *) NULL));
|
||||
|
@ -3579,16 +3573,6 @@ GetInitializerType(JSContext *cx, HandleScript script, jsbytecode *pc)
|
|||
return TypeScript::InitObject(cx, script, pc, key);
|
||||
}
|
||||
|
||||
static inline Type
|
||||
GetCalleeThisType(jsbytecode *pc)
|
||||
{
|
||||
pc += GetBytecodeLength(pc);
|
||||
if (*pc == JSOP_UNDEFINED)
|
||||
return Type::UndefinedType();
|
||||
JS_ASSERT(*pc == JSOP_IMPLICITTHIS);
|
||||
return Type::UnknownType();
|
||||
}
|
||||
|
||||
/* Analyze type information for a single bytecode. */
|
||||
bool
|
||||
ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset, TypeInferenceState &state)
|
||||
|
@ -3823,9 +3807,6 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset, TypeInferen
|
|||
PropertyAccess<PROPERTY_READ_EXISTING>(cx, script, pc, global, seen, id);
|
||||
else
|
||||
PropertyAccess<PROPERTY_READ>(cx, script, pc, global, seen, id);
|
||||
|
||||
if (op == JSOP_CALLGNAME)
|
||||
pushed[0].addPropagateThis(cx, script, pc, GetCalleeThisType(pc));
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -3836,8 +3817,6 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset, TypeInferen
|
|||
StackTypeSet *seen = bytecodeTypes(pc);
|
||||
addTypeBarrier(cx, pc, seen, Type::UnknownType());
|
||||
seen->addSubset(cx, &pushed[0]);
|
||||
if (op == JSOP_CALLNAME || op == JSOP_CALLINTRINSIC)
|
||||
pushed[0].addPropagateThis(cx, script, pc, GetCalleeThisType(pc));
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -3885,8 +3864,6 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset, TypeInferen
|
|||
/* Local 'let' variable. Punt on types for these, for now. */
|
||||
pushed[0].addType(cx, Type::UnknownType());
|
||||
}
|
||||
if (op == JSOP_CALLARG || op == JSOP_CALLLOCAL)
|
||||
pushed[0].addPropagateThis(cx, script, pc, Type::UndefinedType());
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -3917,8 +3894,6 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset, TypeInferen
|
|||
* variable. Instead, we monitor/barrier all reads unconditionally.
|
||||
*/
|
||||
bytecodeTypes(pc)->addSubset(cx, &pushed[0]);
|
||||
if (op == JSOP_CALLALIASEDVAR)
|
||||
pushed[0].addPropagateThis(cx, script, pc, Type::UnknownType());
|
||||
break;
|
||||
|
||||
case JSOP_SETALIASEDVAR:
|
||||
|
@ -4035,8 +4010,6 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset, TypeInferen
|
|||
}
|
||||
|
||||
seen->addSubset(cx, &pushed[0]);
|
||||
if (op == JSOP_CALLELEM)
|
||||
pushed[0].addPropagateThis(cx, script, pc, Type::UndefinedType(), poppedTypes(pc, 1));
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -4133,7 +4106,24 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset, TypeInferen
|
|||
if (op == JSOP_FUNCALL || op == JSOP_FUNAPPLY)
|
||||
cx->compartment->types.monitorBytecode(cx, script, pc - script_->code);
|
||||
|
||||
poppedTypes(pc, argCount + 1)->addCall(cx, callsite);
|
||||
StackTypeSet *calleeTypes = poppedTypes(pc, argCount + 1);
|
||||
|
||||
/*
|
||||
* Propagate possible 'this' types to the callee except when the call
|
||||
* came through JSOP_CALLPROP (which uses TypeConstraintCallProperty)
|
||||
* or for JSOP_NEW (where the callee will construct the 'this' object).
|
||||
*/
|
||||
SSAValue calleeValue = poppedValue(pc, argCount + 1);
|
||||
if (*pc != JSOP_NEW &&
|
||||
(calleeValue.kind() != SSAValue::PUSHED ||
|
||||
script->code[calleeValue.pushedOffset()] != JSOP_CALLPROP))
|
||||
{
|
||||
HandleScript script_ = script;
|
||||
calleeTypes->add(cx, cx->analysisLifoAlloc().new_<TypeConstraintPropagateThis>
|
||||
(script_, pc, Type::UndefinedType(), callsite->thisTypes));
|
||||
}
|
||||
|
||||
calleeTypes->addCall(cx, callsite);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -704,7 +704,7 @@ MakeJITScript(JSContext *cx, JSScript *script)
|
|||
|
||||
Bytecode *code = analysis->maybeCode(offset);
|
||||
if (!code)
|
||||
continue;
|
||||
op = JSOP_NOP; /* Ignore edges from unreachable opcodes. */
|
||||
|
||||
/* Whether this should be the last opcode in the chunk. */
|
||||
bool finishChunk = false;
|
||||
|
@ -1292,17 +1292,7 @@ mjit::Compiler::markUndefinedLocal(uint32_t offset, uint32_t i)
|
|||
uint32_t depth = ssa.getFrame(a->inlineIndex).depth;
|
||||
uint32_t slot = LocalSlot(script_, i);
|
||||
Address local(JSFrameReg, sizeof(StackFrame) + (depth + i) * sizeof(Value));
|
||||
if (!cx->typeInferenceEnabled() || !analysis->trackSlot(slot)) {
|
||||
masm.storeValue(UndefinedValue(), local);
|
||||
} else {
|
||||
Lifetime *lifetime = analysis->liveness(slot).live(offset);
|
||||
if (lifetime)
|
||||
masm.storeValue(UndefinedValue(), local);
|
||||
#ifdef DEBUG
|
||||
else
|
||||
masm.storeValue(ObjectValueCrashOnTouch(), local);
|
||||
#endif
|
||||
}
|
||||
masm.storeValue(UndefinedValue(), local);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче