зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to mozilla-inbound
This commit is contained in:
Коммит
921626e7e1
|
@ -1186,3 +1186,5 @@ pref("image.mem.max_decoded_image_kb", 256000);
|
|||
// Example social provider
|
||||
pref("social.manifest.motown", "{\"origin\":\"https://motown-dev.mozillalabs.com\",\"name\":\"MoTown\",\"workerURL\":\"https://motown-dev.mozillalabs.com/social/worker.js\",\"iconURL\":\"https://motown-dev.mozillalabs.com/images/motown-icon.png\",\"sidebarURL\":\"https://motown-dev.mozillalabs.com/social/sidebar\"}");
|
||||
pref("social.sidebar.open", true);
|
||||
pref("browser.social.whitelist", "");
|
||||
pref("social.active", false);
|
||||
|
|
|
@ -332,6 +332,10 @@
|
|||
label="&preferencesCmd2.label;"
|
||||
#endif
|
||||
oncommand="openPreferences();">
|
||||
<menuitem id="appmenu_socialToggle"
|
||||
type="checkbox"
|
||||
autocheck="false"
|
||||
command="Social:Toggle"/>
|
||||
<menupopup id="appmenu_customizeMenu"
|
||||
onpopupshowing="onViewToolbarsPopupShowing(event, document.getElementById('appmenu_toggleToolbarsSeparator'));">
|
||||
<menuitem id="appmenu_preferences"
|
||||
|
|
|
@ -496,6 +496,10 @@
|
|||
accesskey="&addons.accesskey;"
|
||||
key="key_openAddons"
|
||||
command="Tools:Addons"/>
|
||||
<menuitem id="menu_socialToggle"
|
||||
type="checkbox"
|
||||
autocheck="false"
|
||||
command="Social:Toggle"/>
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
<!-- only one of sync-setup or sync-menu will be showing at once -->
|
||||
<menuitem id="sync-setup"
|
||||
|
|
|
@ -108,6 +108,7 @@
|
|||
<command id="Social:SharePage" oncommand="SocialShareButton.sharePage();"/>
|
||||
<command id="Social:UnsharePage" oncommand="SocialShareButton.unsharePage();"/>
|
||||
<command id="Social:ToggleSidebar" oncommand="Social.toggleSidebar();"/>
|
||||
<command id="Social:Toggle" oncommand="Social.toggle();" hidden="true"/>
|
||||
</commandset>
|
||||
|
||||
<commandset id="placesCommands">
|
||||
|
|
|
@ -11,6 +11,8 @@ let SocialUI = {
|
|||
|
||||
Services.prefs.addObserver("social.sidebar.open", this, false);
|
||||
|
||||
gBrowser.addEventListener("ActivateSocialFeature", this._activationEventHandler, true, true);
|
||||
|
||||
Social.init(this._providerReady.bind(this));
|
||||
},
|
||||
|
||||
|
@ -31,6 +33,7 @@ let SocialUI = {
|
|||
observe: function SocialUI_observe(subject, topic, data) {
|
||||
switch (topic) {
|
||||
case "social:pref-changed":
|
||||
this.updateToggleCommand();
|
||||
SocialShareButton.updateButtonHiddenState();
|
||||
SocialToolbar.updateButtonHiddenState();
|
||||
SocialSidebar.updateSidebar();
|
||||
|
@ -46,11 +49,103 @@ let SocialUI = {
|
|||
}
|
||||
},
|
||||
|
||||
get toggleCommand() {
|
||||
return document.getElementById("Social:Toggle");
|
||||
},
|
||||
|
||||
// Called once Social.jsm's provider has been set
|
||||
_providerReady: function SocialUI_providerReady() {
|
||||
// If we couldn't find a provider, nothing to do here.
|
||||
if (!Social.provider)
|
||||
return;
|
||||
|
||||
this.updateToggleCommand();
|
||||
|
||||
let toggleCommand = this.toggleCommand;
|
||||
let label = gNavigatorBundle.getFormattedString("social.enable.label",
|
||||
[Social.provider.name]);
|
||||
let accesskey = gNavigatorBundle.getString("social.enable.accesskey");
|
||||
toggleCommand.setAttribute("label", label);
|
||||
toggleCommand.setAttribute("accesskey", accesskey);
|
||||
|
||||
SocialToolbar.init();
|
||||
SocialShareButton.init();
|
||||
SocialSidebar.init();
|
||||
},
|
||||
|
||||
updateToggleCommand: function SocialUI_updateToggleCommand() {
|
||||
let toggleCommand = this.toggleCommand;
|
||||
toggleCommand.setAttribute("checked", 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"]) {
|
||||
let el = document.getElementById(id);
|
||||
if (!el)
|
||||
continue;
|
||||
|
||||
if (Social.active)
|
||||
el.removeAttribute("hidden");
|
||||
else
|
||||
el.setAttribute("hidden", "true");
|
||||
}
|
||||
},
|
||||
|
||||
// This handles "ActivateSocialFeature" events fired against content documents
|
||||
// in this window.
|
||||
_activationEventHandler: function SocialUI_activationHandler(e) {
|
||||
// Nothing to do if Social is already active, or we don't have a provider
|
||||
// to enable yet.
|
||||
if (Social.active || !Social.provider)
|
||||
return;
|
||||
|
||||
let targetDoc = e.target;
|
||||
|
||||
// Event must be fired against the document
|
||||
if (!(targetDoc instanceof HTMLDocument))
|
||||
return;
|
||||
|
||||
// Ignore events fired in background tabs
|
||||
if (targetDoc.defaultView.top != content)
|
||||
return;
|
||||
|
||||
// Check that the associated document's origin is in our whitelist
|
||||
let prePath = targetDoc.documentURIObject.prePath;
|
||||
let whitelist = Services.prefs.getCharPref("browser.social.whitelist");
|
||||
if (whitelist.split(",").indexOf(prePath) == -1)
|
||||
return;
|
||||
|
||||
// If the last event was received < 1s ago, ignore this one
|
||||
let now = Date.now();
|
||||
if (now - Social.lastEventReceived < 1000)
|
||||
return;
|
||||
Social.lastEventReceived = now;
|
||||
|
||||
// Enable the social functionality, and indicate that it was activated
|
||||
Social.active = true;
|
||||
|
||||
// Show a warning, allow undoing the activation
|
||||
let description = document.getElementById("social-activation-message");
|
||||
let brandShortName = document.getElementById("bundle_brand").getString("brandShortName");
|
||||
let message = gNavigatorBundle.getFormattedString("social.activated.message",
|
||||
[Social.provider.name, brandShortName]);
|
||||
description.value = message;
|
||||
|
||||
SocialUI.notificationPanel.hidden = false;
|
||||
|
||||
setTimeout(function () {
|
||||
SocialUI.notificationPanel.openPopup(SocialToolbar.button, "bottomcenter topright");
|
||||
}.bind(this), 0);
|
||||
},
|
||||
|
||||
get notificationPanel() {
|
||||
return document.getElementById("socialActivatedNotification")
|
||||
},
|
||||
|
||||
undoActivation: function SocialUI_undoActivation() {
|
||||
Social.active = false;
|
||||
this.notificationPanel.hidePopup();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -153,22 +248,33 @@ var SocialToolbar = {
|
|||
// Called once, after window load, when the Social.provider object is initialized
|
||||
init: function SocialToolbar_init() {
|
||||
document.getElementById("social-provider-image").setAttribute("image", Social.provider.iconURL);
|
||||
|
||||
// handle button state
|
||||
document.getElementById("social-statusarea-popup").addEventListener("popupshowing", function(e) {
|
||||
document.getElementById("social-toolbar-button").setAttribute("open", "true");
|
||||
}, false);
|
||||
document.getElementById("social-statusarea-popup").addEventListener("popuphiding", function(e) {
|
||||
document.getElementById("social-toolbar-button").removeAttribute("open");
|
||||
}, false);
|
||||
|
||||
let removeItem = document.getElementById("social-remove-menuitem");
|
||||
let brandShortName = document.getElementById("bundle_brand").getString("brandShortName");
|
||||
let label = gNavigatorBundle.getFormattedString("social.remove.label",
|
||||
[brandShortName]);
|
||||
let accesskey = gNavigatorBundle.getString("social.remove.accesskey");
|
||||
removeItem.setAttribute("label", label);
|
||||
removeItem.setAttribute("accesskey", accesskey);
|
||||
|
||||
let statusAreaPopup = document.getElementById("social-statusarea-popup");
|
||||
statusAreaPopup.addEventListener("popupshowing", function(e) {
|
||||
this.button.setAttribute("open", "true");
|
||||
}.bind(this));
|
||||
statusAreaPopup.addEventListener("popuphidden", function(e) {
|
||||
this.button.removeAttribute("open");
|
||||
}.bind(this));
|
||||
|
||||
this.updateButton();
|
||||
this.updateProfile();
|
||||
},
|
||||
|
||||
get button() {
|
||||
return document.getElementById("social-toolbar-button");
|
||||
},
|
||||
|
||||
updateButtonHiddenState: function SocialToolbar_updateButtonHiddenState() {
|
||||
let toolbarbutton = document.getElementById("social-toolbar-button");
|
||||
toolbarbutton.hidden = !Social.uiVisible;
|
||||
this.button.hidden = !Social.uiVisible;
|
||||
},
|
||||
|
||||
updateProfile: function SocialToolbar_updateProfile() {
|
||||
|
@ -233,10 +339,10 @@ var SocialToolbar = {
|
|||
panel.hidden = false;
|
||||
|
||||
function sizePanelToContent() {
|
||||
// XXX Maybe we can use nsIDOMWindowUtils.getRootBounds() here?
|
||||
// XXX need to handle dynamic sizing
|
||||
// FIXME: bug 764787: Maybe we can use nsIDOMWindowUtils.getRootBounds() here?
|
||||
// Need to handle dynamic sizing
|
||||
let doc = notifBrowser.contentDocument;
|
||||
// XXX "notif" is an implementation detail that we should get rid of
|
||||
// "notif" is an implementation detail that we should get rid of
|
||||
// eventually
|
||||
let body = doc.getElementById("notif") || doc.body.firstChild;
|
||||
if (!body)
|
||||
|
@ -254,13 +360,13 @@ var SocialToolbar = {
|
|||
panel.addEventListener("popuphiding", function onpopuphiding() {
|
||||
panel.removeEventListener("popuphiding", onpopuphiding);
|
||||
// unload the panel
|
||||
document.getElementById("social-toolbar-button").removeAttribute("open");
|
||||
SocialToolbar.button.removeAttribute("open");
|
||||
notifBrowser.setAttribute("src", "about:blank");
|
||||
});
|
||||
|
||||
notifBrowser.setAttribute("origin", Social.provider.origin);
|
||||
notifBrowser.setAttribute("src", iconImage.getAttribute("contentPanel"));
|
||||
document.getElementById("social-toolbar-button").setAttribute("open", "true");
|
||||
this.button.setAttribute("open", "true");
|
||||
panel.openPopup(iconImage, "bottomcenter topleft", 0, 0, false, false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -182,6 +182,44 @@
|
|||
</hbox>
|
||||
</panel>
|
||||
|
||||
<panel id="socialActivatedNotification"
|
||||
type="arrow"
|
||||
hidden="true"
|
||||
consumeoutsideclicks="true"
|
||||
align="start"
|
||||
role="alert">
|
||||
<hbox flex="1">
|
||||
<image src="chrome://browser/content/social-icon.png" class="popup-notification-icon"/>
|
||||
<vbox flex="1">
|
||||
<description id="social-activation-message" class="popup-notification-description"/>
|
||||
<spacer flex="1"/>
|
||||
<hbox pack="end" align="center" class="popup-notification-button-container">
|
||||
#ifdef XP_UNIX
|
||||
<button id="social-undoactivation-button"
|
||||
label="&social.activated.button.label;"
|
||||
accesskey="&social.activated.button.accesskey;"
|
||||
onclick="SocialUI.undoActivation();"/>
|
||||
<button default="true"
|
||||
autofocus="autofocus"
|
||||
label="&social.ok.label;"
|
||||
accesskey="&social.ok.accesskey;"
|
||||
oncommand="SocialUI.notificationPanel.hidePopup();"/>
|
||||
#else
|
||||
<button default="true"
|
||||
autofocus="autofocus"
|
||||
label="&social.ok.label;"
|
||||
accesskey="&social.ok.accesskey;"
|
||||
oncommand="SocialUI.notificationPanel.hidePopup();"/>
|
||||
<button id="social-undoactivation-button"
|
||||
label="&social.activated.button.label;"
|
||||
accesskey="&social.activated.button.accesskey;"
|
||||
onclick="SocialUI.undoActivation();"/>
|
||||
#endif
|
||||
</hbox>
|
||||
</vbox>
|
||||
</hbox>
|
||||
</panel>
|
||||
|
||||
<panel id="editSharePopup"
|
||||
type="arrow"
|
||||
orient="vertical"
|
||||
|
@ -214,16 +252,16 @@
|
|||
class="editSharePopupBottomButton"
|
||||
default="true"
|
||||
autofocus="autofocus"
|
||||
label="&social.sharePopup.ok.label;"
|
||||
accesskey="&social.sharePopup.ok.accesskey;"
|
||||
label="&social.ok.label;"
|
||||
accesskey="&social.ok.accesskey;"
|
||||
oncommand="SocialShareButton.dismissSharePopup();"/>
|
||||
#else
|
||||
<button id="editSharePopupOkButton"
|
||||
class="editSharePopupBottomButton"
|
||||
default="true"
|
||||
autofocus="autofocus"
|
||||
label="&social.sharePopup.ok.label;"
|
||||
accesskey="&social.sharePopup.ok.accesskey;"
|
||||
label="&social.ok.label;"
|
||||
accesskey="&social.ok.accesskey;"
|
||||
oncommand="SocialShareButton.dismissSharePopup();"/>
|
||||
<button id="editSharePopupUndoButton"
|
||||
class="editSharePopupBottomButton"
|
||||
|
@ -638,6 +676,8 @@
|
|||
oncommand="SocialUI.showProfile(); document.getElementById('social-statusarea-popup').hidePopup();"/>
|
||||
</vbox>
|
||||
</hbox>
|
||||
<menuitem id="social-remove-menuitem"
|
||||
oncommand="Social.active = false;"/>
|
||||
<menuitem id="social-toggle-sidebar-menuitem"
|
||||
type="checkbox"
|
||||
autocheck="false"
|
||||
|
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 2.1 KiB |
|
@ -258,6 +258,10 @@ _BROWSER_FILES = \
|
|||
browser_bug734076.js \
|
||||
browser_social_toolbar.js \
|
||||
browser_social_sidebar.js \
|
||||
browser_social_mozSocial_API.js \
|
||||
social_panel.html \
|
||||
social_sidebar.html \
|
||||
social_worker.js \
|
||||
$(NULL)
|
||||
|
||||
ifneq (cocoa,$(MOZ_WIDGET_TOOLKIT))
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
/* 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/. */
|
||||
|
||||
let SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).SocialService;
|
||||
|
||||
function test() {
|
||||
// XXX Bug 775779
|
||||
if (Cc["@mozilla.org/xpcom/debug;1"].getService(Ci.nsIDebug2).isDebugBuild) {
|
||||
ok(true, "can't run social sidebar test in debug builds because they falsely report leaks");
|
||||
return;
|
||||
}
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
let manifest = { // normal provider
|
||||
name: "provider 1",
|
||||
origin: "http://example.com",
|
||||
sidebarURL: "http://example.com/browser/browser/base/content/test/social_sidebar.html",
|
||||
workerURL: "http://example.com/browser/browser/base/content/test/social_worker.js",
|
||||
iconURL: "chrome://branding/content/icon48.png"
|
||||
};
|
||||
runSocialTestWithProvider(manifest, doTest);
|
||||
}
|
||||
|
||||
function doTest() {
|
||||
let iconsReady = false;
|
||||
let gotSidebarMessage = false;
|
||||
|
||||
function checkNext() {
|
||||
if (iconsReady && gotSidebarMessage)
|
||||
triggerIconPanel();
|
||||
}
|
||||
|
||||
function triggerIconPanel() {
|
||||
let statusIcons = document.getElementById("social-status-iconbox");
|
||||
ok(!statusIcons.firstChild.collapsed, "status icon is visible");
|
||||
// Click the button to trigger its contentPanel
|
||||
let panel = document.getElementById("social-notification-panel");
|
||||
EventUtils.synthesizeMouseAtCenter(statusIcons.firstChild, {});
|
||||
}
|
||||
|
||||
let port = Social.provider.port;
|
||||
ok(port, "provider has a port");
|
||||
port.postMessage({topic: "test-init"});
|
||||
Social.provider.port.onmessage = function (e) {
|
||||
let topic = e.data.topic;
|
||||
switch (topic) {
|
||||
case "got-panel-message":
|
||||
ok(true, "got panel message");
|
||||
// Wait for the panel to close before ending the test
|
||||
let panel = document.getElementById("social-notification-panel");
|
||||
panel.addEventListener("popuphidden", function hiddenListener() {
|
||||
panel.removeEventListener("popuphidden", hiddenListener);
|
||||
SocialService.removeProvider(Social.provider.origin, finish);
|
||||
});
|
||||
panel.hidePopup();
|
||||
break;
|
||||
case "got-sidebar-message":
|
||||
// The sidebar message will always come first, since it loads by default
|
||||
ok(true, "got sidebar message");
|
||||
info(topic);
|
||||
gotSidebarMessage = true;
|
||||
checkNext();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Our worker sets up ambient notification at the same time as it responds to
|
||||
// the workerAPI initialization. If it's already initialized, we can
|
||||
// immediately check the icons, otherwise wait for initialization by
|
||||
// observing the topic sent out by the social service.
|
||||
if (Social.provider.workerAPI.initialized) {
|
||||
iconsReady = true;
|
||||
checkNext();
|
||||
} else {
|
||||
Services.obs.addObserver(function obs() {
|
||||
Services.obs.removeObserver(obs, "social:ambient-notification-changed");
|
||||
// Let the other observers (like the one that updates the UI) run before
|
||||
// checking the icons.
|
||||
executeSoon(function () {
|
||||
iconsReady = true;
|
||||
checkNext();
|
||||
});
|
||||
}, "social:ambient-notification-changed", false);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script>
|
||||
function pingWorker() {
|
||||
var port = navigator.mozSocial.getWorker().port;
|
||||
port.postMessage({topic: "panel-message", result: "ok"});
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload="pingWorker();">
|
||||
<p>This is a test social panel.</p>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,14 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script>
|
||||
function pingWorker() {
|
||||
var port = navigator.mozSocial.getWorker().port;
|
||||
port.postMessage({topic: "sidebar-message", result: "ok"});
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload="pingWorker();">
|
||||
<p>This is a test social sidebar.</p>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,40 @@
|
|||
/* 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/. */
|
||||
|
||||
let testPort;
|
||||
|
||||
onconnect = function(e) {
|
||||
let port = e.ports[0];
|
||||
port.onmessage = function onMessage(event) {
|
||||
let topic = event.data.topic;
|
||||
switch (topic) {
|
||||
case "test-init":
|
||||
testPort = port;
|
||||
break;
|
||||
case "sidebar-message":
|
||||
if (testPort && event.data.result == "ok")
|
||||
testPort.postMessage({topic:"got-sidebar-message"});
|
||||
break;
|
||||
case "panel-message":
|
||||
if (testPort && event.data.result == "ok")
|
||||
testPort.postMessage({topic:"got-panel-message"});
|
||||
break;
|
||||
case "social.initialize":
|
||||
// This is the workerAPI port, respond and set up a notification icon.
|
||||
port.postMessage({topic: "social.initialize-response"});
|
||||
let profile = {
|
||||
userName: "foo"
|
||||
};
|
||||
port.postMessage({topic: "social.user-profile", data: profile});
|
||||
let icon = {
|
||||
name: "testIcon",
|
||||
iconURL: "chrome://branding/content/icon48.png",
|
||||
contentPanel: "http://example.com/browser/browser/base/content/test/social_panel.html",
|
||||
counter: 1
|
||||
};
|
||||
port.postMessage({topic: "social.ambient-notification", data: icon});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -101,6 +101,7 @@ browser.jar:
|
|||
#ifdef XP_WIN
|
||||
* content/browser/win6BrowserOverlay.xul (content/win6BrowserOverlay.xul)
|
||||
#endif
|
||||
content/browser/social-icon.png (content/social-icon.png)
|
||||
# the following files are browser-specific overrides
|
||||
* content/browser/license.html (/toolkit/content/license.html)
|
||||
% override chrome://global/content/license.html chrome://browser/content/license.html
|
||||
|
|
|
@ -657,11 +657,21 @@ toolbar button -->
|
|||
<!ENTITY socialToolbar.title "Social Toolbar Button">
|
||||
<!ENTITY social.notLoggedIn.label "Not logged in">
|
||||
|
||||
<!-- LOCALIZATION NOTE (social.ok.label, social.ok.accesskey): this string is
|
||||
used for the "OK" button for two different social panels. One appears when
|
||||
the feature is activated (social.activated.* below), and the other when
|
||||
the user clicks the "Share" button a second time (social.sharePopup.*
|
||||
below). -->
|
||||
<!ENTITY social.ok.label "OK">
|
||||
<!ENTITY social.ok.accesskey "O">
|
||||
|
||||
<!ENTITY social.sharePopup.undo.label "Unshare">
|
||||
<!ENTITY social.sharePopup.undo.accesskey "U">
|
||||
<!ENTITY social.sharePopup.ok.label "OK">
|
||||
<!ENTITY social.sharePopup.ok.accesskey "O">
|
||||
<!ENTITY social.sharePopup.shared.label "You shared this page.">
|
||||
<!ENTITY social.sharePopup.portrait.arialabel "User profile picture">
|
||||
|
||||
<!ENTITY social.toggleSidebar.label "Show sidebar">
|
||||
<!ENTITY social.toggleSidebar.accesskey "s">
|
||||
|
||||
<!ENTITY social.activated.button.label "Oops, undo">
|
||||
<!ENTITY social.activated.button.accesskey "u">
|
||||
|
|
|
@ -372,3 +372,14 @@ fullscreen.rememberDecision=Remember decision for %S
|
|||
social.shareButton.tooltip=Share this
|
||||
social.shareButton.sharedtooltip=You shared this
|
||||
social.pageShared.label=Page shared
|
||||
|
||||
# LOCALIZATION NOTE (social.enable.label): %S = Social networking provider
|
||||
social.enable.label=%S integration
|
||||
social.enable.accesskey=n
|
||||
|
||||
# LOCALIZATION NOTE (social.remove.label): %S = brandShortName
|
||||
social.remove.label=Remove from %S
|
||||
social.remove.accesskey=R
|
||||
|
||||
# LOCALIZATION NOTE (social.enabled.message): %1$S is the name of the social provider, %2$S is brandShortName (e.g. Firefox)
|
||||
social.activated.message=%1$S integration with %2$S has been activated.
|
||||
|
|
|
@ -17,6 +17,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "SocialService",
|
|||
"resource://gre/modules/SocialService.jsm");
|
||||
|
||||
let Social = {
|
||||
lastEventReceived: 0,
|
||||
provider: null,
|
||||
init: function Social_init(callback) {
|
||||
if (this.provider) {
|
||||
|
@ -38,6 +39,25 @@ let Social = {
|
|||
return this.provider && this.provider.enabled && this.provider.port;
|
||||
},
|
||||
|
||||
set enabled(val) {
|
||||
SocialService.enabled = val;
|
||||
},
|
||||
get enabled() {
|
||||
return SocialService.enabled;
|
||||
},
|
||||
|
||||
get active() {
|
||||
return Services.prefs.getBoolPref("social.active");
|
||||
},
|
||||
set active(val) {
|
||||
Services.prefs.setBoolPref("social.active", !!val);
|
||||
this.enabled = !!val;
|
||||
},
|
||||
|
||||
toggle: function Social_toggle() {
|
||||
this.enabled = !this.enabled;
|
||||
},
|
||||
|
||||
toggleSidebar: function SocialSidebar_toggle() {
|
||||
let prefValue = Services.prefs.getBoolPref("social.sidebar.open");
|
||||
Services.prefs.setBoolPref("social.sidebar.open", !prefValue);
|
||||
|
|
|
@ -228,8 +228,8 @@ let AlarmService = {
|
|||
|
||||
if (this._currentAlarm) {
|
||||
debug("Fire system intent: " + JSON.stringify(this._currentAlarm));
|
||||
if (this._currentAlarm.manifestURL)
|
||||
messenger.sendMessage("alarm", this._currentAlarm, this._currentAlarm.manifestURL);
|
||||
let manifestURI = Services.io.newURI(this._currentAlarm.manifestURL, null, null);
|
||||
messenger.sendMessage("alarm", this._currentAlarm, manifestURI);
|
||||
this._currentAlarm = null;
|
||||
}
|
||||
|
||||
|
@ -244,8 +244,8 @@ let AlarmService = {
|
|||
// fire system intent for it instead of setting it
|
||||
if (nextAlarmTime <= nowTime) {
|
||||
debug("Fire system intent: " + JSON.stringify(nextAlarm));
|
||||
if (nextAlarm.manifestURL)
|
||||
messenger.sendMessage("alarm", nextAlarm, nextAlarm.manifestURL);
|
||||
let manifestURI = Services.io.newURI(nextAlarm.manifestURL, null, null);
|
||||
messenger.sendMessage("alarm", nextAlarm, manifestURI);
|
||||
} else {
|
||||
this._currentAlarm = nextAlarm;
|
||||
break;
|
||||
|
|
|
@ -45,6 +45,11 @@ AlarmsManager.prototype = {
|
|||
add: function add(aDate, aRespectTimezone, aData) {
|
||||
debug("add()");
|
||||
|
||||
if (!this._manifestURL) {
|
||||
debug("Cannot add alarms for non-installed apps.");
|
||||
throw Components.results.NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
let isIgnoreTimezone = true;
|
||||
switch (aRespectTimezone) {
|
||||
case "honorTimezone":
|
||||
|
@ -150,8 +155,7 @@ AlarmsManager.prototype = {
|
|||
|
||||
// Get the manifest URL if this is an installed app
|
||||
this._manifestURL = null;
|
||||
let utils = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIDOMWindowUtils);
|
||||
let utils = aWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
|
||||
let app = utils.getApp();
|
||||
if (app)
|
||||
this._manifestURL = app.manifestURL;
|
||||
|
|
|
@ -60,6 +60,7 @@ let RILQUIRKS_DATACALLSTATE_DOWN_IS_UP = false;
|
|||
let RILQUIRKS_V5_LEGACY = true;
|
||||
let RILQUIRKS_REQUEST_USE_DIAL_EMERGENCY_CALL = false;
|
||||
let RILQUIRKS_MODEM_DEFAULTS_TO_EMERGENCY_MODE = false;
|
||||
let RILQUIRKS_SIM_APP_STATE_EXTRA_FIELDS = false;
|
||||
|
||||
/**
|
||||
* This object contains helpers buffering incoming data & deconstructing it
|
||||
|
@ -727,6 +728,10 @@ let RIL = {
|
|||
case "Qualcomm RIL 1.0":
|
||||
let product_model = libcutils.property_get("ro.product.model");
|
||||
if (DEBUG) debug("Detected product model " + product_model);
|
||||
if (product_model == "otoro1") {
|
||||
if (DEBUG) debug("Enabling RILQUIRKS_SIM_APP_STATE_EXTRA_FIELDS.");
|
||||
RILQUIRKS_SIM_APP_STATE_EXTRA_FIELDS = true;
|
||||
}
|
||||
if (DEBUG) {
|
||||
debug("Detected Qualcomm RIL 1.0, " +
|
||||
"disabling RILQUIRKS_V5_LEGACY and " +
|
||||
|
@ -2825,6 +2830,12 @@ RIL[REQUEST_GET_SIM_STATUS] = function REQUEST_GET_SIM_STATUS(length, options) {
|
|||
pin1: Buf.readUint32(),
|
||||
pin2: Buf.readUint32()
|
||||
});
|
||||
if (RILQUIRKS_SIM_APP_STATE_EXTRA_FIELDS) {
|
||||
Buf.readUint32();
|
||||
Buf.readUint32();
|
||||
Buf.readUint32();
|
||||
Buf.readUint32();
|
||||
}
|
||||
}
|
||||
|
||||
if (DEBUG) debug("iccStatus: " + JSON.stringify(iccStatus));
|
||||
|
|
|
@ -7,7 +7,9 @@
|
|||
#include "nsEditor.h"
|
||||
#include "IMETextTxn.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsISelection.h"
|
||||
#include "mozilla/Selection.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
PlaceholderTxn::PlaceholderTxn() : EditAggregateTxn(),
|
||||
mAbsorb(true),
|
||||
|
@ -42,7 +44,9 @@ NS_INTERFACE_MAP_END_INHERITING(EditAggregateTxn)
|
|||
NS_IMPL_ADDREF_INHERITED(PlaceholderTxn, EditAggregateTxn)
|
||||
NS_IMPL_RELEASE_INHERITED(PlaceholderTxn, EditAggregateTxn)
|
||||
|
||||
NS_IMETHODIMP PlaceholderTxn::Init(nsIAtom *aName, nsSelectionState *aSelState, nsIEditor *aEditor)
|
||||
NS_IMETHODIMP
|
||||
PlaceholderTxn::Init(nsIAtom* aName, nsSelectionState* aSelState,
|
||||
nsEditor* aEditor)
|
||||
{
|
||||
NS_ENSURE_TRUE(aEditor && aSelState, NS_ERROR_NULL_POINTER);
|
||||
|
||||
|
@ -256,10 +260,9 @@ NS_IMETHODIMP PlaceholderTxn::Commit()
|
|||
|
||||
NS_IMETHODIMP PlaceholderTxn::RememberEndingSelection()
|
||||
{
|
||||
nsCOMPtr<nsISelection> selection;
|
||||
nsresult res = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
nsRefPtr<Selection> selection = mEditor->GetSelection();
|
||||
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
|
||||
return mEndSel.SaveSelection(selection);
|
||||
mEndSel.SaveSelection(selection);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -44,7 +44,8 @@ public:
|
|||
|
||||
// ------------ nsIAbsorbingTransaction -----------------------
|
||||
|
||||
NS_IMETHOD Init(nsIAtom *aName, nsSelectionState *aSelState, nsIEditor *aEditor);
|
||||
NS_IMETHOD Init(nsIAtom* aName, nsSelectionState* aSelState,
|
||||
nsEditor* aEditor);
|
||||
|
||||
NS_IMETHOD GetTxnName(nsIAtom **aName);
|
||||
|
||||
|
@ -72,7 +73,7 @@ protected:
|
|||
// selection properly.
|
||||
nsAutoPtr<nsSelectionState> mStartSel; // use a pointer because this is constructed before we exist
|
||||
nsSelectionState mEndSel;
|
||||
nsIEditor* mEditor; /** the editor for this transaction */
|
||||
nsEditor* mEditor; /** the editor for this transaction */
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
<!DOCTYPE html>
|
||||
<html contenteditable="true">
|
||||
<head>
|
||||
<script>
|
||||
|
||||
function boom()
|
||||
{
|
||||
document.execCommand("inserthtml", false, "b");
|
||||
var myrange = document.createRange();
|
||||
myrange.selectNodeContents(document.getElementsByTagName("img")[0]);
|
||||
window.getSelection().addRange(myrange);
|
||||
document.execCommand("strikethrough", false, null);
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body onload="boom();"><img></body>
|
||||
</html>
|
|
@ -17,3 +17,4 @@ load 766845.xhtml
|
|||
load 768765.html
|
||||
needs-focus load 771749.html
|
||||
load 772282.html
|
||||
load 776323.html
|
||||
|
|
|
@ -904,9 +904,8 @@ nsEditor::BeginPlaceHolderTransaction(nsIAtom *aName)
|
|||
BeginUpdateViewBatch();
|
||||
mPlaceHolderTxn = nsnull;
|
||||
mPlaceHolderName = aName;
|
||||
nsCOMPtr<nsISelection> selection;
|
||||
nsresult res = GetSelection(getter_AddRefs(selection));
|
||||
if (NS_SUCCEEDED(res)) {
|
||||
nsRefPtr<Selection> selection = GetSelection();
|
||||
if (selection) {
|
||||
mSelState = new nsSelectionState();
|
||||
mSelState->SaveSelection(selection);
|
||||
}
|
||||
|
@ -1979,7 +1978,7 @@ nsEditor::ArePreservingSelection()
|
|||
}
|
||||
|
||||
void
|
||||
nsEditor::PreserveSelectionAcrossActions(nsISelection *aSel)
|
||||
nsEditor::PreserveSelectionAcrossActions(Selection* aSel)
|
||||
{
|
||||
mSavedSel.SaveSelection(aSel);
|
||||
mRangeUpdater.RegisterSelectionState(mSavedSel);
|
||||
|
|
|
@ -425,7 +425,7 @@ public:
|
|||
/** routines for managing the preservation of selection across
|
||||
* various editor actions */
|
||||
bool ArePreservingSelection();
|
||||
void PreserveSelectionAcrossActions(nsISelection *aSel);
|
||||
void PreserveSelectionAcrossActions(mozilla::Selection* aSel);
|
||||
nsresult RestorePreservedSelection(nsISelection *aSel);
|
||||
void StopPreservingSelection();
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
|
||||
#include "mozilla/Selection.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsEditorUtils.h"
|
||||
|
@ -18,24 +18,23 @@
|
|||
#include "nsIDocument.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsINode.h"
|
||||
#include "nsISelection.h"
|
||||
#include "nsISimpleEnumerator.h"
|
||||
|
||||
class nsIDOMRange;
|
||||
class nsISupports;
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
/******************************************************************************
|
||||
* nsAutoSelectionReset
|
||||
*****************************************************************************/
|
||||
|
||||
nsAutoSelectionReset::nsAutoSelectionReset(nsISelection *aSel, nsEditor *aEd) :
|
||||
mSel(nsnull)
|
||||
,mEd(nsnull)
|
||||
nsAutoSelectionReset::nsAutoSelectionReset(Selection* aSel, nsEditor* aEd)
|
||||
: mSel(nsnull), mEd(nsnull)
|
||||
{
|
||||
if (!aSel || !aEd) return; // not much we can do, bail.
|
||||
if (aEd->ArePreservingSelection()) return; // we already have initted mSavedSel, so this must be nested call.
|
||||
mSel = do_QueryInterface(aSel);
|
||||
mSel = aSel;
|
||||
mEd = aEd;
|
||||
if (mSel)
|
||||
{
|
||||
|
|
|
@ -57,12 +57,12 @@ class NS_STACK_CLASS nsAutoSelectionReset
|
|||
{
|
||||
private:
|
||||
/** ref-counted reference to the selection that we are supposed to restore */
|
||||
nsCOMPtr<nsISelection> mSel;
|
||||
nsRefPtr<mozilla::Selection> mSel;
|
||||
nsEditor *mEd; // non-owning ref to nsEditor
|
||||
|
||||
public:
|
||||
/** constructor responsible for remembering all state needed to restore aSel */
|
||||
nsAutoSelectionReset(nsISelection *aSel, nsEditor *aEd);
|
||||
nsAutoSelectionReset(mozilla::Selection* aSel, nsEditor* aEd);
|
||||
|
||||
/** destructor restores mSel to its former state */
|
||||
~nsAutoSelectionReset();
|
||||
|
|
|
@ -32,7 +32,8 @@ public:
|
|||
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IABSORBINGTRANSACTION_IID)
|
||||
|
||||
NS_IMETHOD Init(nsIAtom *aName, nsSelectionState *aSelState, nsIEditor *aEditor)=0;
|
||||
NS_IMETHOD Init(nsIAtom* aName, nsSelectionState* aSelState,
|
||||
nsEditor* aEditor) = 0;
|
||||
|
||||
NS_IMETHOD EndPlaceHolderBatch()=0;
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
|
||||
#include "mozilla/Selection.h" // for Selection
|
||||
#include "nsAString.h" // for nsAString_internal::Length
|
||||
#include "nsAutoPtr.h" // for nsRefPtr, getter_AddRefs, etc
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
|
@ -19,6 +20,7 @@
|
|||
#include "nsRange.h" // for nsRange
|
||||
#include "nsSelectionState.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
/***************************************************************************
|
||||
* class for recording selection info. stores selection as collection of
|
||||
|
@ -47,43 +49,30 @@ nsSelectionState::DoTraverse(nsCycleCollectionTraversalCallback &cb)
|
|||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsSelectionState::SaveSelection(nsISelection *aSel)
|
||||
void
|
||||
nsSelectionState::SaveSelection(Selection* aSel)
|
||||
{
|
||||
NS_ENSURE_TRUE(aSel, NS_ERROR_NULL_POINTER);
|
||||
PRInt32 i,rangeCount, arrayCount = mArray.Length();
|
||||
aSel->GetRangeCount(&rangeCount);
|
||||
|
||||
MOZ_ASSERT(aSel);
|
||||
PRInt32 arrayCount = mArray.Length();
|
||||
PRInt32 rangeCount = aSel->GetRangeCount();
|
||||
|
||||
// if we need more items in the array, new them
|
||||
if (arrayCount<rangeCount)
|
||||
{
|
||||
PRInt32 count = rangeCount-arrayCount;
|
||||
for (i=0; i<count; i++)
|
||||
{
|
||||
if (arrayCount < rangeCount) {
|
||||
for (PRInt32 i = arrayCount; i < rangeCount; i++) {
|
||||
mArray.AppendElement();
|
||||
mArray[i] = new nsRangeStore();
|
||||
}
|
||||
}
|
||||
|
||||
// else if we have too many, delete them
|
||||
else if (arrayCount>rangeCount)
|
||||
{
|
||||
for (i = arrayCount-1; i >= rangeCount; i--)
|
||||
{
|
||||
} else if (arrayCount > rangeCount) {
|
||||
// else if we have too many, delete them
|
||||
for (PRInt32 i = arrayCount - 1; i >= rangeCount; i--) {
|
||||
mArray.RemoveElementAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// now store the selection ranges
|
||||
nsresult res = NS_OK;
|
||||
for (i=0; i<rangeCount; i++)
|
||||
{
|
||||
nsCOMPtr<nsIDOMRange> range;
|
||||
res = aSel->GetRangeAt(i, getter_AddRefs(range));
|
||||
mArray[i]->StoreRange(range);
|
||||
for (PRInt32 i = 0; i < rangeCount; i++) {
|
||||
mArray[i]->StoreRange(aSel->GetRangeAt(i));
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
|
|
@ -18,6 +18,9 @@ class nsIDOMCharacterData;
|
|||
class nsIDOMRange;
|
||||
class nsISelection;
|
||||
class nsRange;
|
||||
namespace mozilla {
|
||||
class Selection;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* class for recording selection info. stores selection as collection of
|
||||
|
@ -52,7 +55,7 @@ class nsSelectionState
|
|||
void DoTraverse(nsCycleCollectionTraversalCallback &cb);
|
||||
void DoUnlink() { MakeEmpty(); }
|
||||
|
||||
nsresult SaveSelection(nsISelection *aSel);
|
||||
void SaveSelection(mozilla::Selection *aSel);
|
||||
nsresult RestoreSelection(nsISelection *aSel);
|
||||
bool IsCollapsed();
|
||||
bool IsEqual(nsSelectionState *aSelState);
|
||||
|
|
|
@ -2869,7 +2869,7 @@ nsHTMLEditRules::DidDeleteSelection(nsISelection *aSelection,
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLEditRules::WillMakeList(nsISelection* aSelection,
|
||||
nsHTMLEditRules::WillMakeList(Selection* aSelection,
|
||||
const nsAString* aListType,
|
||||
bool aEntireList,
|
||||
const nsAString* aBulletType,
|
||||
|
@ -3159,7 +3159,7 @@ nsHTMLEditRules::WillMakeList(nsISelection* aSelection,
|
|||
|
||||
|
||||
nsresult
|
||||
nsHTMLEditRules::WillRemoveList(nsISelection *aSelection,
|
||||
nsHTMLEditRules::WillRemoveList(Selection* aSelection,
|
||||
bool aOrdered,
|
||||
bool *aCancel,
|
||||
bool *aHandled)
|
||||
|
@ -3226,7 +3226,7 @@ nsHTMLEditRules::WillRemoveList(nsISelection *aSelection,
|
|||
|
||||
|
||||
nsresult
|
||||
nsHTMLEditRules::WillMakeDefListItem(nsISelection *aSelection,
|
||||
nsHTMLEditRules::WillMakeDefListItem(Selection* aSelection,
|
||||
const nsAString *aItemType,
|
||||
bool aEntireList,
|
||||
bool *aCancel,
|
||||
|
@ -3238,7 +3238,7 @@ nsHTMLEditRules::WillMakeDefListItem(nsISelection *aSelection,
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLEditRules::WillMakeBasicBlock(nsISelection *aSelection,
|
||||
nsHTMLEditRules::WillMakeBasicBlock(Selection* aSelection,
|
||||
const nsAString *aBlockType,
|
||||
bool *aCancel,
|
||||
bool *aHandled)
|
||||
|
@ -3395,7 +3395,8 @@ nsHTMLEditRules::DidMakeBasicBlock(nsISelection *aSelection,
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLEditRules::WillIndent(nsISelection *aSelection, bool *aCancel, bool * aHandled)
|
||||
nsHTMLEditRules::WillIndent(Selection* aSelection,
|
||||
bool* aCancel, bool* aHandled)
|
||||
{
|
||||
nsresult res;
|
||||
if (mHTMLEditor->IsCSSEnabled()) {
|
||||
|
@ -3408,7 +3409,8 @@ nsHTMLEditRules::WillIndent(nsISelection *aSelection, bool *aCancel, bool * aHan
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLEditRules::WillCSSIndent(nsISelection *aSelection, bool *aCancel, bool * aHandled)
|
||||
nsHTMLEditRules::WillCSSIndent(Selection* aSelection,
|
||||
bool* aCancel, bool* aHandled)
|
||||
{
|
||||
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
|
||||
|
||||
|
@ -3614,7 +3616,8 @@ nsHTMLEditRules::WillCSSIndent(nsISelection *aSelection, bool *aCancel, bool * a
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLEditRules::WillHTMLIndent(nsISelection *aSelection, bool *aCancel, bool * aHandled)
|
||||
nsHTMLEditRules::WillHTMLIndent(Selection* aSelection,
|
||||
bool* aCancel, bool* aHandled)
|
||||
{
|
||||
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
|
||||
nsresult res = WillInsert(aSelection, aCancel);
|
||||
|
@ -3842,7 +3845,8 @@ nsHTMLEditRules::WillHTMLIndent(nsISelection *aSelection, bool *aCancel, bool *
|
|||
|
||||
|
||||
nsresult
|
||||
nsHTMLEditRules::WillOutdent(nsISelection *aSelection, bool *aCancel, bool *aHandled)
|
||||
nsHTMLEditRules::WillOutdent(Selection* aSelection,
|
||||
bool* aCancel, bool* aHandled)
|
||||
{
|
||||
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
|
||||
// initialize out param
|
||||
|
@ -4412,7 +4416,7 @@ nsHTMLEditRules::IsEmptyBlock(nsIDOMNode *aNode,
|
|||
|
||||
|
||||
nsresult
|
||||
nsHTMLEditRules::WillAlign(nsISelection *aSelection,
|
||||
nsHTMLEditRules::WillAlign(Selection* aSelection,
|
||||
const nsAString *alignType,
|
||||
bool *aCancel,
|
||||
bool *aHandled)
|
||||
|
@ -8570,7 +8574,8 @@ nsHTMLEditRules::RelativeChangeIndentationOfElementNode(nsIDOMNode *aNode, PRInt
|
|||
//
|
||||
|
||||
nsresult
|
||||
nsHTMLEditRules::WillAbsolutePosition(nsISelection *aSelection, bool *aCancel, bool * aHandled)
|
||||
nsHTMLEditRules::WillAbsolutePosition(Selection* aSelection,
|
||||
bool* aCancel, bool* aHandled)
|
||||
{
|
||||
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
|
||||
nsresult res = WillInsert(aSelection, aCancel);
|
||||
|
@ -8786,8 +8791,8 @@ nsHTMLEditRules::DidAbsolutePosition()
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLEditRules::WillRemoveAbsolutePosition(nsISelection *aSelection, bool *aCancel, bool * aHandled)
|
||||
{
|
||||
nsHTMLEditRules::WillRemoveAbsolutePosition(Selection* aSelection,
|
||||
bool* aCancel, bool* aHandled) {
|
||||
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
|
||||
nsresult res = WillInsert(aSelection, aCancel);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
|
@ -8808,7 +8813,7 @@ nsHTMLEditRules::WillRemoveAbsolutePosition(nsISelection *aSelection, bool *aCan
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLEditRules::WillRelativeChangeZIndex(nsISelection *aSelection,
|
||||
nsHTMLEditRules::WillRelativeChangeZIndex(Selection* aSelection,
|
||||
PRInt32 aChange,
|
||||
bool *aCancel,
|
||||
bool * aHandled)
|
||||
|
|
|
@ -156,18 +156,38 @@ protected:
|
|||
nsresult MoveNodeSmart(nsIDOMNode *aSource, nsIDOMNode *aDest, PRInt32 *aOffset);
|
||||
nsresult MoveContents(nsIDOMNode *aSource, nsIDOMNode *aDest, PRInt32 *aOffset);
|
||||
nsresult DeleteNonTableElements(nsINode* aNode);
|
||||
nsresult WillMakeList(nsISelection *aSelection, const nsAString *aListType, bool aEntireList, const nsAString *aBulletType, bool *aCancel, bool *aHandled, const nsAString *aItemType=nsnull);
|
||||
nsresult WillRemoveList(nsISelection *aSelection, bool aOrderd, bool *aCancel, bool *aHandled);
|
||||
nsresult WillIndent(nsISelection *aSelection, bool *aCancel, bool *aHandled);
|
||||
nsresult WillCSSIndent(nsISelection *aSelection, bool *aCancel, bool *aHandled);
|
||||
nsresult WillHTMLIndent(nsISelection *aSelection, bool *aCancel, bool *aHandled);
|
||||
nsresult WillOutdent(nsISelection *aSelection, bool *aCancel, bool *aHandled);
|
||||
nsresult WillAlign(nsISelection *aSelection, const nsAString *alignType, bool *aCancel, bool *aHandled);
|
||||
nsresult WillAbsolutePosition(nsISelection *aSelection, bool *aCancel, bool * aHandled);
|
||||
nsresult WillRemoveAbsolutePosition(nsISelection *aSelection, bool *aCancel, bool * aHandled);
|
||||
nsresult WillRelativeChangeZIndex(nsISelection *aSelection, PRInt32 aChange, bool *aCancel, bool * aHandled);
|
||||
nsresult WillMakeDefListItem(nsISelection *aSelection, const nsAString *aBlockType, bool aEntireList, bool *aCancel, bool *aHandled);
|
||||
nsresult WillMakeBasicBlock(nsISelection *aSelection, const nsAString *aBlockType, bool *aCancel, bool *aHandled);
|
||||
nsresult WillMakeList(mozilla::Selection* aSelection,
|
||||
const nsAString* aListType,
|
||||
bool aEntireList,
|
||||
const nsAString* aBulletType,
|
||||
bool* aCancel, bool* aHandled,
|
||||
const nsAString* aItemType = nsnull);
|
||||
nsresult WillRemoveList(mozilla::Selection* aSelection,
|
||||
bool aOrdered, bool* aCancel, bool* aHandled);
|
||||
nsresult WillIndent(mozilla::Selection* aSelection,
|
||||
bool* aCancel, bool* aHandled);
|
||||
nsresult WillCSSIndent(mozilla::Selection* aSelection,
|
||||
bool* aCancel, bool* aHandled);
|
||||
nsresult WillHTMLIndent(mozilla::Selection* aSelection,
|
||||
bool* aCancel, bool* aHandled);
|
||||
nsresult WillOutdent(mozilla::Selection* aSelection,
|
||||
bool* aCancel, bool* aHandled);
|
||||
nsresult WillAlign(mozilla::Selection* aSelection,
|
||||
const nsAString* alignType,
|
||||
bool* aCancel, bool* aHandled);
|
||||
nsresult WillAbsolutePosition(mozilla::Selection* aSelection,
|
||||
bool* aCancel, bool* aHandled);
|
||||
nsresult WillRemoveAbsolutePosition(mozilla::Selection* aSelection,
|
||||
bool* aCancel, bool* aHandled);
|
||||
nsresult WillRelativeChangeZIndex(mozilla::Selection* aSelection,
|
||||
PRInt32 aChange,
|
||||
bool* aCancel, bool* aHandled);
|
||||
nsresult WillMakeDefListItem(mozilla::Selection* aSelection,
|
||||
const nsAString* aBlockType, bool aEntireList,
|
||||
bool* aCancel, bool* aHandled);
|
||||
nsresult WillMakeBasicBlock(mozilla::Selection* aSelection,
|
||||
const nsAString* aBlockType,
|
||||
bool* aCancel, bool* aHandled);
|
||||
nsresult DidMakeBasicBlock(nsISelection *aSelection, nsRulesInfo *aInfo, nsresult aResult);
|
||||
nsresult DidAbsolutePosition();
|
||||
nsresult AlignInnerBlocks(nsIDOMNode *aNode, const nsAString *alignType);
|
||||
|
|
|
@ -3379,15 +3379,13 @@ SetSelectionAroundHeadChildren(nsISelection* aSelection,
|
|||
NS_IMETHODIMP
|
||||
nsHTMLEditor::GetHeadContentsAsHTML(nsAString& aOutputString)
|
||||
{
|
||||
nsCOMPtr<nsISelection> selection;
|
||||
nsresult res = GetSelection(getter_AddRefs(selection));
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
nsRefPtr<Selection> selection = GetSelection();
|
||||
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
|
||||
|
||||
// Save current selection
|
||||
nsAutoSelectionReset selectionResetter(selection, this);
|
||||
|
||||
res = SetSelectionAroundHeadChildren(selection, mDocWeak);
|
||||
nsresult res = SetSelectionAroundHeadChildren(selection, mDocWeak);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
|
||||
res = OutputToString(NS_LITERAL_STRING("text/html"),
|
||||
|
|
|
@ -1535,11 +1535,8 @@ nsHTMLEditor::RelativeFontChange( PRInt32 aSizeChange)
|
|||
ForceCompositionEnd();
|
||||
|
||||
// Get the selection
|
||||
nsCOMPtr<nsISelection>selection;
|
||||
nsresult res = GetSelection(getter_AddRefs(selection));
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
nsRefPtr<Selection> selection = GetSelection();
|
||||
NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
|
||||
nsCOMPtr<nsISelectionPrivate> selPriv(do_QueryInterface(selection));
|
||||
// Is the selection collapsed?
|
||||
// if it's collapsed set typing state
|
||||
if (selection->Collapsed()) {
|
||||
|
@ -1554,7 +1551,7 @@ nsHTMLEditor::RelativeFontChange( PRInt32 aSizeChange)
|
|||
NS_ENSURE_TRUE(selectedNode, NS_OK);
|
||||
if (IsTextNode(selectedNode)) {
|
||||
nsCOMPtr<nsIDOMNode> parent;
|
||||
res = selectedNode->GetParentNode(getter_AddRefs(parent));
|
||||
nsresult res = selectedNode->GetParentNode(getter_AddRefs(parent));
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
selectedNode = parent;
|
||||
}
|
||||
|
@ -1575,7 +1572,7 @@ nsHTMLEditor::RelativeFontChange( PRInt32 aSizeChange)
|
|||
|
||||
// get selection range enumerator
|
||||
nsCOMPtr<nsIEnumerator> enumerator;
|
||||
res = selPriv->GetEnumerator(getter_AddRefs(enumerator));
|
||||
nsresult res = selection->GetEnumerator(getter_AddRefs(enumerator));
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
NS_ENSURE_TRUE(enumerator, NS_ERROR_FAILURE);
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Selection.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "nsAString.h"
|
||||
#include "nsAlgorithm.h"
|
||||
|
@ -28,8 +29,6 @@
|
|||
#include "nsIHTMLEditor.h"
|
||||
#include "nsINode.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsISelection.h"
|
||||
#include "nsISelectionPrivate.h" // For nsISelectionPrivate::TABLESELECTION_ defines
|
||||
#include "nsISupportsUtils.h"
|
||||
#include "nsITableCellLayout.h" // For efficient access to table cell
|
||||
#include "nsITableEditor.h"
|
||||
|
@ -1953,9 +1952,7 @@ nsHTMLEditor::SwitchTableCellHeaderType(nsIDOMElement *aSourceCell, nsIDOMElemen
|
|||
// Save current selection to restore when done
|
||||
// This is needed so ReplaceContainer can monitor selection
|
||||
// when replacing nodes
|
||||
nsCOMPtr<nsISelection>selection;
|
||||
nsresult res = GetSelection(getter_AddRefs(selection));
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
nsRefPtr<Selection> selection = GetSelection();
|
||||
NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
|
||||
nsAutoSelectionReset selectionResetter(selection, this);
|
||||
|
||||
|
@ -1965,7 +1962,8 @@ nsHTMLEditor::SwitchTableCellHeaderType(nsIDOMElement *aSourceCell, nsIDOMElemen
|
|||
|
||||
// This creates new node, moves children, copies attributes (true)
|
||||
// and manages the selection!
|
||||
res = ReplaceContainer(aSourceCell, address_of(newNode), newCellType, nsnull, nsnull, true);
|
||||
nsresult res = ReplaceContainer(aSourceCell, address_of(newNode),
|
||||
newCellType, nsnull, nsnull, true);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
NS_ENSURE_TRUE(newNode, NS_ERROR_FAILURE);
|
||||
|
||||
|
@ -2491,13 +2489,12 @@ nsHTMLEditor::FixBadColSpan(nsIDOMElement *aTable, PRInt32 aColIndex, PRInt32& a
|
|||
NS_IMETHODIMP
|
||||
nsHTMLEditor::NormalizeTable(nsIDOMElement *aTable)
|
||||
{
|
||||
nsCOMPtr<nsISelection>selection;
|
||||
nsresult res = GetSelection(getter_AddRefs(selection));
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
nsRefPtr<Selection> selection = GetSelection();
|
||||
NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIDOMElement> table;
|
||||
res = GetElementOrParentByTagName(NS_LITERAL_STRING("table"), aTable, getter_AddRefs(table));
|
||||
nsresult res = GetElementOrParentByTagName(NS_LITERAL_STRING("table"),
|
||||
aTable, getter_AddRefs(table));
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
// Don't fail if we didn't find a table
|
||||
NS_ENSURE_TRUE(table, NS_OK);
|
||||
|
|
|
@ -3641,6 +3641,29 @@ gfxFontGroup::InitScriptRun(gfxContext *aContext,
|
|||
}
|
||||
}
|
||||
|
||||
already_AddRefed<gfxFont>
|
||||
gfxFontGroup::TryOtherFamilyMembers(gfxFont* aFont, PRUint32 aCh)
|
||||
{
|
||||
gfxFontFamily *family = aFont->GetFontEntry()->Family();
|
||||
if (family && !aFont->GetFontEntry()->mIsProxy &&
|
||||
family->TestCharacterMap(aCh)) {
|
||||
// Note that we don't need the actual runScript in matchData for
|
||||
// gfxFontFamily::SearchAllFontsForChar, it's only used for the
|
||||
// system-fallback case. So we can just set it to 0 here.
|
||||
GlobalFontMatch matchData(aCh, 0, &mStyle);
|
||||
family->SearchAllFontsForChar(&matchData);
|
||||
gfxFontEntry *fe = matchData.mBestMatch;
|
||||
if (fe) {
|
||||
bool needsBold = aFont->GetStyle()->weight >= 600 && !fe->IsBold();
|
||||
nsRefPtr<gfxFont> font = fe->FindOrMakeFont(&mStyle, needsBold);
|
||||
if (font) {
|
||||
return font.forget();
|
||||
}
|
||||
}
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
already_AddRefed<gfxFont>
|
||||
gfxFontGroup::FindFontForChar(PRUint32 aCh, PRUint32 aPrevCh,
|
||||
PRInt32 aRunScript, gfxFont *aPrevMatchedFont,
|
||||
|
@ -3660,6 +3683,13 @@ gfxFontGroup::FindFontForChar(PRUint32 aCh, PRUint32 aPrevCh,
|
|||
firstFont->AddRef();
|
||||
return firstFont;
|
||||
}
|
||||
// It's possible that another font in the family (e.g. regular face,
|
||||
// where the requested style was italic) will support the character
|
||||
nsRefPtr<gfxFont> font = TryOtherFamilyMembers(firstFont, aCh);
|
||||
if (font) {
|
||||
*aMatchType = gfxTextRange::kFontGroup;
|
||||
return font.forget();
|
||||
}
|
||||
// we don't need to check the first font again below
|
||||
++nextIndex;
|
||||
}
|
||||
|
@ -3705,22 +3735,10 @@ gfxFontGroup::FindFontForChar(PRUint32 aCh, PRUint32 aPrevCh,
|
|||
return font.forget();
|
||||
}
|
||||
|
||||
// check other faces of the family
|
||||
gfxFontFamily *family = font->GetFontEntry()->Family();
|
||||
if (family && !font->GetFontEntry()->mIsProxy &&
|
||||
family->TestCharacterMap(aCh))
|
||||
{
|
||||
GlobalFontMatch matchData(aCh, aRunScript, &mStyle);
|
||||
family->SearchAllFontsForChar(&matchData);
|
||||
gfxFontEntry *fe = matchData.mBestMatch;
|
||||
if (fe) {
|
||||
bool needsBold =
|
||||
font->GetStyle()->weight >= 600 && !fe->IsBold();
|
||||
font = fe->FindOrMakeFont(font->GetStyle(), needsBold);
|
||||
if (font) {
|
||||
return font.forget();
|
||||
}
|
||||
}
|
||||
font = TryOtherFamilyMembers(font, aCh);
|
||||
if (font) {
|
||||
*aMatchType = gfxTextRange::kFontGroup;
|
||||
return font.forget();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3181,6 +3181,12 @@ protected:
|
|||
FontCreationCallback fc,
|
||||
void *closure);
|
||||
|
||||
// Helper for font-matching:
|
||||
// see if aCh is supported in any of the other faces from aFont's family;
|
||||
// if so return the best style match, else return null.
|
||||
already_AddRefed<gfxFont> TryOtherFamilyMembers(gfxFont* aFont,
|
||||
PRUint32 aCh);
|
||||
|
||||
static bool FontResolverProc(const nsAString& aName, void *aClosure);
|
||||
|
||||
static bool FindPlatformFont(const nsAString& aName,
|
||||
|
|
|
@ -85,6 +85,86 @@ GetBuildConfiguration(JSContext *cx, unsigned argc, jsval *vp)
|
|||
if (!JS_SetProperty(cx, info, "has-gczeal", &value))
|
||||
return false;
|
||||
|
||||
#ifdef JS_MORE_DETERMINISTIC
|
||||
value = BooleanValue(true);
|
||||
#else
|
||||
value = BooleanValue(false);
|
||||
#endif
|
||||
if (!JS_SetProperty(cx, info, "more-deterministic", &value))
|
||||
return false;
|
||||
|
||||
#ifdef MOZ_PROFILING
|
||||
value = BooleanValue(true);
|
||||
#else
|
||||
value = BooleanValue(false);
|
||||
#endif
|
||||
if (!JS_SetProperty(cx, info, "profiling", &value))
|
||||
return false;
|
||||
|
||||
#ifdef INCLUDE_MOZILLA_DTRACE
|
||||
value = BooleanValue(true);
|
||||
#else
|
||||
value = BooleanValue(false);
|
||||
#endif
|
||||
if (!JS_SetProperty(cx, info, "dtrace", &value))
|
||||
return false;
|
||||
|
||||
#ifdef MOZ_TRACE_JSCALLS
|
||||
value = BooleanValue(true);
|
||||
#else
|
||||
value = BooleanValue(false);
|
||||
#endif
|
||||
if (!JS_SetProperty(cx, info, "trace-jscalls-api", &value))
|
||||
return false;
|
||||
|
||||
#ifdef JSGC_INCREMENTAL
|
||||
value = BooleanValue(true);
|
||||
#else
|
||||
value = BooleanValue(false);
|
||||
#endif
|
||||
if (!JS_SetProperty(cx, info, "incremental-gc", &value))
|
||||
return false;
|
||||
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
value = BooleanValue(true);
|
||||
#else
|
||||
value = BooleanValue(false);
|
||||
#endif
|
||||
if (!JS_SetProperty(cx, info, "generational-gc", &value))
|
||||
return false;
|
||||
|
||||
#ifdef MOZ_VALGRIND
|
||||
value = BooleanValue(true);
|
||||
#else
|
||||
value = BooleanValue(false);
|
||||
#endif
|
||||
if (!JS_SetProperty(cx, info, "valgrind", &value))
|
||||
return false;
|
||||
|
||||
#ifdef JS_OOM_DO_BACKTRACES
|
||||
value = BooleanValue(true);
|
||||
#else
|
||||
value = BooleanValue(false);
|
||||
#endif
|
||||
if (!JS_SetProperty(cx, info, "oom-backtraces", &value))
|
||||
return false;
|
||||
|
||||
#ifdef JS_METHODJIT
|
||||
value = BooleanValue(true);
|
||||
#else
|
||||
value = BooleanValue(false);
|
||||
#endif
|
||||
if (!JS_SetProperty(cx, info, "methodjit", &value))
|
||||
return false;
|
||||
|
||||
#ifdef JS_HAS_XML_SUPPORT
|
||||
value = BooleanValue(true);
|
||||
#else
|
||||
value = BooleanValue(false);
|
||||
#endif
|
||||
if (!JS_SetProperty(cx, info, "e4x", &value))
|
||||
return false;
|
||||
|
||||
*vp = ObjectValue(*info);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style id="s"></style>
|
||||
<script>
|
||||
function boom() { document.getElementById("s").textContent = "div { opacity: 0.5; }"; }
|
||||
</script>
|
||||
</head>
|
||||
<body onload="document.documentElement.offsetHeight; boom();">
|
||||
<div><div>X</div></div>
|
||||
</body>
|
||||
</html>
|
|
@ -358,3 +358,4 @@ asserts-if(winWidget,0-2) load 736924-1.html # bug 738803
|
|||
load 749816-1.html
|
||||
load 763223-1.html
|
||||
test-pref(font.size.inflation.emPerLine,15) test-pref(font.size.inflation.lineThreshold,100) load 763702.xhtml
|
||||
load 770381-1.html
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Bug 769475 - test for italicized Arabic script in Arial</title>
|
||||
<style type="text/css">
|
||||
body {
|
||||
font-family: arial, serif;
|
||||
font-size: 36px;
|
||||
line-height: 72px;
|
||||
}
|
||||
span {
|
||||
color: white;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body lang="ar">
|
||||
<!-- the white span should have the same width whether it's italicized or not,
|
||||
-- as Arial does not have Arabic characters in the italic face but we should
|
||||
-- apply synthetic italic to the regular face, NOT fall back to a different
|
||||
-- family from prefs.
|
||||
-->
|
||||
<div>العربي <span>العربي</span> العربي</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,26 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Bug 769475 - test for italicized Arabic script in Arial</title>
|
||||
<style type="text/css">
|
||||
body {
|
||||
font-family: arial, serif;
|
||||
font-size: 36px;
|
||||
line-height: 72px;
|
||||
}
|
||||
span {
|
||||
font-style: italic;
|
||||
color: white;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body lang="ar">
|
||||
<!-- the white span should have the same width whether it's italicized or not,
|
||||
-- as Arial does not have Arabic characters in the italic face but we should
|
||||
-- apply synthetic italic to the regular face, NOT fall back to a different
|
||||
-- family from prefs.
|
||||
-->
|
||||
<div>العربي <span>العربي</span> العربي</div>
|
||||
</body>
|
||||
</html>
|
|
@ -81,3 +81,7 @@ HTTP(..) == font-stretch-1.html font-stretch-1-ref.html
|
|||
random-if(!(cocoaWidget||/^Windows\x20NT\x206\.1/.test(http.oscpu))) skip-if(gtk2Widget) != bold-system-fallback-1.html bold-system-fallback-1-notref.html
|
||||
# test 2 uses Chess symbols; expected to pass on Android
|
||||
random-if(!Android) skip-if(gtk2Widget) != bold-system-fallback-2.html bold-system-fallback-2-notref.html
|
||||
|
||||
# Bug 769475 - applying 'italic' to Arabic text in Arial should NOT change family or metrics.
|
||||
# Expected to pass on MacOSX and Windows; other platforms unknown, depending on font availability.
|
||||
random-if(!(cocoaWidget||winWidget)) == arial-arabic.html arial-arabic-ref.html
|
||||
|
|
|
@ -129,8 +129,7 @@ nsComputedDOMStyle::nsComputedDOMStyle(dom::Element* aElement,
|
|||
}
|
||||
}
|
||||
|
||||
nsPresContext *presCtx = aPresShell->GetPresContext();
|
||||
MOZ_ASSERT(presCtx);
|
||||
MOZ_ASSERT(aPresShell->GetPresContext());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ function getFrameWorkerHandle(url, clientWindow, name) {
|
|||
let existingWorker = workerCache[url];
|
||||
if (!existingWorker) {
|
||||
// setup the worker and add this connection to the pending queue
|
||||
let worker = new FrameWorker(url, clientWindow, name);
|
||||
let worker = new FrameWorker(url, name);
|
||||
worker.pendingPorts.push(clientPort);
|
||||
existingWorker = workerCache[url] = worker;
|
||||
} else {
|
||||
|
@ -253,11 +253,6 @@ function WorkerHandle(port, worker) {
|
|||
this._worker = worker;
|
||||
}
|
||||
WorkerHandle.prototype = {
|
||||
__exposedProps__: {
|
||||
port: "r",
|
||||
terminate: "r"
|
||||
},
|
||||
|
||||
// XXX - workers have no .close() method, but *do* have a .terminate()
|
||||
// method which we should implement. However, the worker spec doesn't define
|
||||
// a callback to be made in the worker when this happens - it all just dies.
|
||||
|
@ -329,7 +324,7 @@ function initClientMessageHandler(worker, workerWindow) {
|
|||
* @param {nsiDOMWindow} clientWindow, optional
|
||||
*/
|
||||
function ClientPort(portid, clientWindow) {
|
||||
this._clientWindow = clientWindow
|
||||
this._clientWindow = clientWindow;
|
||||
this._window = null;
|
||||
// messages posted to the worker before the worker has loaded.
|
||||
this._pendingMessagesOutgoing = [];
|
||||
|
@ -338,17 +333,17 @@ function ClientPort(portid, clientWindow) {
|
|||
|
||||
ClientPort.prototype = {
|
||||
__exposedProps__: {
|
||||
'port': 'r',
|
||||
'onmessage': 'rw',
|
||||
'postMessage': 'r',
|
||||
'close': 'r'
|
||||
onmessage: "rw",
|
||||
postMessage: "r",
|
||||
close: "r",
|
||||
toString: "r"
|
||||
},
|
||||
__proto__: AbstractPort.prototype,
|
||||
_portType: "client",
|
||||
|
||||
_JSONParse: function fw_ClientPort_JSONParse(data) {
|
||||
if (this._clientWindow) {
|
||||
return this._clientWindow.JSON.parse(data);
|
||||
return XPCNativeWrapper.unwrap(this._clientWindow).JSON.parse(data);
|
||||
}
|
||||
return JSON.parse(data);
|
||||
},
|
||||
|
@ -383,6 +378,7 @@ ClientPort.prototype = {
|
|||
this.postMessage({topic: "social.port-closing"});
|
||||
AbstractPort.prototype.close.call(this);
|
||||
this._window = null;
|
||||
this._clientWindow = null;
|
||||
this._pendingMessagesOutgoing = null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ EXTRA_JS_MODULES = \
|
|||
MessagePortWorker.js \
|
||||
SocialService.jsm \
|
||||
WorkerAPI.jsm \
|
||||
MozSocialAPI.jsm \
|
||||
$(NULL)
|
||||
|
||||
TEST_DIRS += \
|
||||
|
|
|
@ -29,17 +29,12 @@ AbstractPort.prototype = {
|
|||
_JSONParse: function fw_AbstractPort_JSONParse(data) JSON.parse(data),
|
||||
|
||||
_postControlMessage: function fw_AbstractPort_postControlMessage(topic, data) {
|
||||
let postData = {portTopic: topic,
|
||||
portId: this._portid,
|
||||
portFromType: this._portType,
|
||||
data: data,
|
||||
__exposedProps__: {
|
||||
portTopic: 'r',
|
||||
portId: 'r',
|
||||
portFromType: 'r',
|
||||
data: 'r'
|
||||
}
|
||||
};
|
||||
let postData = {
|
||||
portTopic: topic,
|
||||
portId: this._portid,
|
||||
portFromType: this._portType,
|
||||
data: data
|
||||
};
|
||||
this._dopost(postData);
|
||||
},
|
||||
|
||||
|
@ -52,14 +47,15 @@ AbstractPort.prototype = {
|
|||
data = this._JSONParse(data);
|
||||
if (!this._handler) {
|
||||
this._pendingMessagesIncoming.push(data);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
try {
|
||||
this._handler({data: data,
|
||||
__exposedProps__: {data: 'r'}
|
||||
});
|
||||
}
|
||||
catch (ex) {
|
||||
this._handler({
|
||||
data: data,
|
||||
__exposedProps__: {
|
||||
data: 'r'
|
||||
}
|
||||
});
|
||||
} catch (ex) {
|
||||
this._onerror(ex);
|
||||
}
|
||||
}
|
||||
|
@ -71,6 +67,9 @@ AbstractPort.prototype = {
|
|||
this._onmessage(this._pendingMessagesIncoming.shift());
|
||||
}
|
||||
},
|
||||
get onmessage() {
|
||||
return this._handler;
|
||||
},
|
||||
|
||||
/**
|
||||
* postMessage
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
/* 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/. */
|
||||
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "SocialService", "resource://gre/modules/SocialService.jsm");
|
||||
|
||||
const EXPORTED_SYMBOLS = ["MozSocialAPI"];
|
||||
|
||||
var MozSocialAPI = {
|
||||
_enabled: false,
|
||||
set enabled(val) {
|
||||
let enable = !!val;
|
||||
if (enable == this._enabled) {
|
||||
return;
|
||||
}
|
||||
this._enabled = enable;
|
||||
|
||||
if (enable) {
|
||||
Services.obs.addObserver(injectController, "document-element-inserted", false);
|
||||
} else {
|
||||
Services.obs.removeObserver(injectController, "document-element-inserted", false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Called on document-element-inserted, checks that the API should be injected,
|
||||
// and then calls attachToWindow as appropriate
|
||||
function injectController(doc, topic, data) {
|
||||
try {
|
||||
let window = doc.defaultView;
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
var containingBrowser = window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShell)
|
||||
.chromeEventHandler;
|
||||
|
||||
// If the containing browser isn't one of the social browsers, nothing to
|
||||
// do here.
|
||||
// XXX this is app-specific, might want some mechanism for consumers to
|
||||
// whitelist other IDs/windowtypes
|
||||
if (!(containingBrowser.id == "social-sidebar-browser" ||
|
||||
containingBrowser.id == "social-notification-browser")) {
|
||||
return;
|
||||
}
|
||||
|
||||
let origin = containingBrowser.getAttribute("origin");
|
||||
if (!origin) {
|
||||
return;
|
||||
}
|
||||
|
||||
SocialService.getProvider(origin, function(provider) {
|
||||
if (provider && provider.workerURL) {
|
||||
attachToWindow(provider, window);
|
||||
}
|
||||
});
|
||||
} catch(e) {
|
||||
Cu.reportError("MozSocialAPI injectController: unable to attachToWindow for " + doc.location + ": " + e);
|
||||
}
|
||||
}
|
||||
|
||||
// Loads mozSocial support functions associated with provider into targetWindow
|
||||
function attachToWindow(provider, targetWindow) {
|
||||
let origin = provider.origin;
|
||||
if (!provider.enabled) {
|
||||
throw new Error("MozSocialAPI: cannot attach disabled provider " + origin);
|
||||
}
|
||||
|
||||
let targetDocURI = targetWindow.document.documentURIObject;
|
||||
if (provider.origin != targetDocURI.prePath) {
|
||||
throw new Error("MozSocialAPI: cannot attach " + origin + " to " + targetDocURI.spec);
|
||||
}
|
||||
|
||||
var port = provider._getWorkerPort(targetWindow);
|
||||
|
||||
let mozSocialObj = {
|
||||
// Use a method for backwards compat with existing providers, but we
|
||||
// should deprecate this in favor of a simple .port getter.
|
||||
getWorker: function() {
|
||||
return {
|
||||
port: port,
|
||||
__exposedProps__: {
|
||||
port: "r"
|
||||
}
|
||||
};
|
||||
},
|
||||
hasBeenIdleFor: function () {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
let contentObj = Cu.createObjectIn(targetWindow);
|
||||
let propList = {};
|
||||
for (let prop in mozSocialObj) {
|
||||
propList[prop] = {
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: mozSocialObj[prop]
|
||||
};
|
||||
}
|
||||
Object.defineProperties(contentObj, propList);
|
||||
Cu.makeObjectPropsNormal(contentObj);
|
||||
|
||||
targetWindow.navigator.wrappedJSObject.__defineGetter__("mozSocial", function() {
|
||||
// We do this in a getter, so that we create these objects
|
||||
// only on demand (this is a potential concern, since
|
||||
// otherwise we might add one per iframe, and keep them
|
||||
// alive for as long as the window is alive).
|
||||
delete targetWindow.navigator.wrappedJSObject.mozSocial;
|
||||
return targetWindow.navigator.wrappedJSObject.mozSocial = contentObj;
|
||||
});
|
||||
|
||||
targetWindow.addEventListener("unload", function () {
|
||||
// We want to close the port, but also want the target window to be
|
||||
// able to use the port during an unload event they setup - so we
|
||||
// set a timer which will fire after the unload events have all fired.
|
||||
schedule(function () { port.close(); });
|
||||
});
|
||||
}
|
||||
|
||||
function schedule(callback) {
|
||||
Services.tm.mainThread.dispatch(callback, Ci.nsIThread.DISPATCH_NORMAL);
|
||||
}
|
|
@ -8,6 +8,7 @@ const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
|||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/MozSocialAPI.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "getFrameWorkerHandle", "resource://gre/modules/FrameWorker.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "WorkerAPI", "resource://gre/modules/WorkerAPI.jsm");
|
||||
|
@ -29,7 +30,7 @@ let SocialServiceInternal = {
|
|||
XPCOMUtils.defineLazyGetter(SocialServiceInternal, "providers", function () {
|
||||
// Initialize the service (add a pref observer)
|
||||
function prefObserver(subject, topic, data) {
|
||||
SocialService._setEnabled(Services.prefs.getBoolPref(data));
|
||||
SocialService._setEnabled(Services.prefs.getBoolPref("social.enabled"));
|
||||
}
|
||||
Services.prefs.addObserver("social.enabled", prefObserver, false);
|
||||
Services.obs.addObserver(function xpcomShutdown() {
|
||||
|
@ -37,6 +38,9 @@ XPCOMUtils.defineLazyGetter(SocialServiceInternal, "providers", function () {
|
|||
Services.prefs.removeObserver("social.enabled", prefObserver);
|
||||
}, "xpcom-shutdown", false);
|
||||
|
||||
// Initialize the MozSocialAPI
|
||||
MozSocialAPI.enabled = SocialServiceInternal.enabled;
|
||||
|
||||
// Now retrieve the providers
|
||||
let providers = {};
|
||||
let MANIFEST_PREFS = Services.prefs.getBranch("social.manifest.");
|
||||
|
@ -77,6 +81,7 @@ const SocialService = {
|
|||
_setEnabled: function _setEnabled(enable) {
|
||||
SocialServiceInternal.providerArray.forEach(function (p) p.enabled = enable);
|
||||
SocialServiceInternal.enabled = enable;
|
||||
MozSocialAPI.enabled = enable;
|
||||
Services.obs.notifyObservers(null, "social:pref-changed", enable ? "enabled" : "disabled");
|
||||
},
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ let tests = {
|
|||
ok(port, "should be able to get a port from the provider");
|
||||
|
||||
port.onmessage = function onMessage(event) {
|
||||
let {topic, data} = event.data;
|
||||
let topic = event.data.topic;
|
||||
if (topic == "test-initialization-complete") {
|
||||
is(provider.workerAPI.initialized, true, "workerAPI is now initialized");
|
||||
next();
|
||||
|
|
Загрузка…
Ссылка в новой задаче