Merge fx-team to m-c a=merge

This commit is contained in:
Wes Kocher 2014-10-28 19:02:36 -07:00
commit 895e881439
71 changed files with 2173 additions and 399 deletions

View File

@ -1766,3 +1766,10 @@ pref("browser.apps.URL", "https://marketplace.firefox.com/discovery/");
pref("browser.polaris.enabled", false);
pref("privacy.trackingprotection.ui.enabled", false);
// Temporary pref to allow printing in e10s windows on some platforms.
#ifdef UNIX_BUT_NOT_MAC
pref("print.enable_e10s_testing", false);
#else
pref("print.enable_e10s_testing", true);
#endif

View File

@ -28,7 +28,7 @@
oncommand="MailIntegration.sendLinkForWindow(window.content);"/>
<command id="cmd_pageSetup" oncommand="PrintUtils.showPageSetup();"/>
<command id="cmd_print" oncommand="PrintUtils.print();"/>
<command id="cmd_print" oncommand="PrintUtils.print(window.gBrowser.selectedBrowser.contentWindowAsCPOW, window.gBrowser.selectedBrowser);"/>
<command id="cmd_printPreview" oncommand="PrintUtils.printPreview(PrintPreviewListener);"/>
<command id="cmd_close" oncommand="BrowserCloseTabOrWindow()"/>
<command id="cmd_closeWindow" oncommand="BrowserTryToCloseWindow()"/>

View File

@ -1663,7 +1663,8 @@ function HandleAppCommandEvent(evt) {
BrowserOpenFileWindow();
break;
case "Print":
PrintUtils.print();
PrintUtils.print(gBrowser.selectedBrowser.contentWindowAsCPOW,
gBrowser.selectedBrowser);
break;
case "Save":
saveDocument(window.content.document);

View File

@ -294,7 +294,8 @@ let LoopCallsInternal = {
var callData = {
contact: contact,
callType: callType,
callId: Math.floor((Math.random() * 10))
// XXX Really we shouldn't be using random numbers, bug 1090209 will fix this.
callId: Math.floor((Math.random() * 100000000))
};
this._startCall(callData, "outgoing");

View File

@ -571,18 +571,17 @@
background-color: rgba(0,0,0,.2)
}
/* Force full height on all parents up to the video elements
* this way we can ensure the aspect ratio and use height 100%
* on the video element
* */
html, .fx-embedded, #main,
.video-layout-wrapper,
.conversation {
height: 100%;
}
@media screen and (min-width:640px) {
/* Force full height on all parents up to the video elements
* this way we can ensure the aspect ratio and use height 100%
* on the video element
* */
html, body, #main,
.video-layout-wrapper,
.conversation {
height: 100%;
}
.standalone .conversation-toolbar {
position: absolute;
bottom: 0;

View File

@ -117,7 +117,7 @@ Tools.inspector = {
},
isTargetSupported: function(target) {
return !target.isAddon;
return !target.isAddon && target.hasActor("inspector");
},
build: function(iframeWindow, toolbox) {
@ -199,7 +199,8 @@ Tools.styleEditor = {
commands: "devtools/styleeditor/styleeditor-commands",
isTargetSupported: function(target) {
return !target.isAddon;
return !target.isAddon &&
(target.hasActor("styleEditor") || target.hasActor("styleSheets"));
},
build: function(iframeWindow, toolbox) {
@ -267,7 +268,7 @@ Tools.jsprofiler = {
isTargetSupported: function (target) {
// Hide the profiler when debugging devices pre bug 1046394,
// that don't expose profiler actor in content processes.
return !target.isAddon && (!target.isApp || target.form.profilerActor);
return !target.isAddon && target.hasActor("profiler");
},
build: function (frame, target) {
@ -291,9 +292,7 @@ Tools.performance = {
inMenu: true,
isTargetSupported: function (target) {
// Hide the profiler when debugging devices pre bug 1046394,
// that don't expose profiler actor in content processes.
return !target.isAddon && (!target.isApp || target.form.profilerActor);
return !target.isAddon && target.hasActor("profiler");
},
build: function (frame, target) {
@ -338,8 +337,7 @@ Tools.netMonitor = {
inMenu: true,
isTargetSupported: function(target) {
let root = target.client.mainRoot;
return !target.isAddon && (root.traits.networkMonitor || !target.isApp);
return !target.isAddon && target.getTrait("networkMonitor");
},
build: function(iframeWindow, toolbox) {

View File

@ -29,7 +29,7 @@ function test() {
is(container.childNodes[0].childNodes[0].getAttribute("type"), "duration",
"The root node in the tree has a duration cell.");
is(container.childNodes[0].childNodes[0].getAttribute("value"), "18",
is(container.childNodes[0].childNodes[0].getAttribute("value"), "15",
"The root node in the tree has the correct duration cell value.");
is(container.childNodes[0].childNodes[1].getAttribute("type"), "percentage",
@ -49,7 +49,7 @@ function test() {
is(container.childNodes[0].childNodes[4].getAttribute("type"), "samples",
"The root node in the tree has an samples cell.");
is(container.childNodes[0].childNodes[4].getAttribute("value"), "3",
is(container.childNodes[0].childNodes[4].getAttribute("value"), "4",
"The root node in the tree has the correct samples cell value.");
is(container.childNodes[0].childNodes[5].getAttribute("type"), "function",
@ -69,7 +69,7 @@ let gSamples = [{
{ category: 32, location: "C (http://foo/bar/baz:56)" }
]
}, {
time: 5 + 6,
time: 5 + 1,
frames: [
{ category: 8, location: "(root)" },
{ category: 8, location: "A (http://foo/bar/baz:12)" },
@ -77,7 +77,15 @@ let gSamples = [{
{ category: 64, location: "D (http://foo/bar/baz:78)" }
]
}, {
time: 5 + 6 + 7,
time: 5 + 1 + 2,
frames: [
{ category: 8, location: "(root)" },
{ category: 8, location: "A (http://foo/bar/baz:12)" },
{ category: 16, location: "B (http://foo/bar/baz:34)" },
{ category: 64, location: "D (http://foo/bar/baz:78)" }
]
}, {
time: 5 + 1 + 2 + 7,
frames: [
{ category: 8, location: "(root)" },
{ category: 8, location: "A (http://foo/bar/baz:12)" },

View File

@ -27,11 +27,11 @@ function test() {
is(container.childNodes[0].className, "call-tree-item",
"The root node in the tree has the correct class name.");
is($$dur(0).getAttribute("value"), "18",
is($$dur(0).getAttribute("value"), "15",
"The root's duration cell displays the correct value.");
is($$perc(0).getAttribute("value"), "100%",
"The root's percentage cell displays the correct value.");
is($$sampl(0).getAttribute("value"), "3",
is($$sampl(0).getAttribute("value"), "4",
"The root's samples cell displays the correct value.");
is($$fun(".call-tree-name")[0].getAttribute("value"), "(root)",
"The root's function cell displays the correct name.");
@ -53,11 +53,11 @@ function test() {
is(container.childNodes[1].className, "call-tree-item",
"The .A node in the tree has the correct class name.");
is($$dur(1).getAttribute("value"), "18",
is($$dur(1).getAttribute("value"), "15",
"The .A node's duration cell displays the correct value.");
is($$perc(1).getAttribute("value"), "100%",
"The .A node's percentage cell displays the correct value.");
is($$sampl(1).getAttribute("value"), "3",
is($$sampl(1).getAttribute("value"), "4",
"The .A node's samples cell displays the correct value.");
is($$fun(".call-tree-name")[1].getAttribute("value"), "A",
"The .A node's function cell displays the correct name.");
@ -82,11 +82,11 @@ function test() {
is(container.childNodes[3].className, "call-tree-item",
"The .E node in the tree has the correct class name.");
is($$dur(2).getAttribute("value"), "11",
is($$dur(2).getAttribute("value"), "8",
"The .A.B node's duration cell displays the correct value.");
is($$perc(2).getAttribute("value"), "66.66%",
is($$perc(2).getAttribute("value"), "75%",
"The .A.B node's percentage cell displays the correct value.");
is($$sampl(2).getAttribute("value"), "2",
is($$sampl(2).getAttribute("value"), "3",
"The .A.B node's samples cell displays the correct value.");
is($$fun(".call-tree-name")[2].getAttribute("value"), "B",
"The .A.B node's function cell displays the correct name.");
@ -103,7 +103,7 @@ function test() {
is($$dur(3).getAttribute("value"), "7",
"The .A.E node's duration cell displays the correct value.");
is($$perc(3).getAttribute("value"), "33.33%",
is($$perc(3).getAttribute("value"), "25%",
"The .A.E node's percentage cell displays the correct value.");
is($$sampl(3).getAttribute("value"), "1",
"The .A.E node's samples cell displays the correct value.");
@ -132,7 +132,7 @@ let gSamples = [{
{ category: 32, location: "C (http://foo/bar/baz:56)" }
]
}, {
time: 5 + 6,
time: 5 + 1,
frames: [
{ category: 8, location: "(root)" },
{ category: 8, location: "A (http://foo/bar/baz:12)" },
@ -140,7 +140,15 @@ let gSamples = [{
{ category: 64, location: "D (http://foo/bar/baz:78)" }
]
}, {
time: 5 + 6 + 7,
time: 5 + 1 + 2,
frames: [
{ category: 8, location: "(root)" },
{ category: 8, location: "A (http://foo/bar/baz:12)" },
{ category: 16, location: "B (http://foo/bar/baz:34)" },
{ category: 64, location: "D (http://foo/bar/baz:78)" }
]
}, {
time: 5 + 1 + 2 + 7,
frames: [
{ category: 8, location: "(root)" },
{ category: 8, location: "A (http://foo/bar/baz:12)" },

View File

@ -55,13 +55,13 @@ function test() {
is($$name(6).getAttribute("value"), "F",
"The .A.E.F node's function cell displays the correct name.");
is($$duration(0).getAttribute("value"), "18",
is($$duration(0).getAttribute("value"), "15",
"The root node's function cell displays the correct duration.");
is($$duration(1).getAttribute("value"), "18",
is($$duration(1).getAttribute("value"), "15",
"The .A node's function cell displays the correct duration.");
is($$duration(2).getAttribute("value"), "11",
is($$duration(2).getAttribute("value"), "8",
"The .A.B node's function cell displays the correct duration.");
is($$duration(3).getAttribute("value"), "6",
is($$duration(3).getAttribute("value"), "3",
"The .A.B.D node's function cell displays the correct duration.");
is($$duration(4).getAttribute("value"), "5",
"The .A.B.C node's function cell displays the correct duration.");
@ -82,7 +82,7 @@ let gSamples = [{
{ category: 32, location: "C (http://foo/bar/baz:56)" }
]
}, {
time: 5 + 6,
time: 5 + 1,
frames: [
{ category: 8, location: "(root)" },
{ category: 8, location: "A (http://foo/bar/baz:12)" },
@ -90,7 +90,15 @@ let gSamples = [{
{ category: 64, location: "D (http://foo/bar/baz:78)" }
]
}, {
time: 5 + 6 + 7,
time: 5 + 1 + 2,
frames: [
{ category: 8, location: "(root)" },
{ category: 8, location: "A (http://foo/bar/baz:12)" },
{ category: 16, location: "B (http://foo/bar/baz:34)" },
{ category: 64, location: "D (http://foo/bar/baz:78)" }
]
}, {
time: 5 + 1 + 2 + 7,
frames: [
{ category: 8, location: "(root)" },
{ category: 8, location: "A (http://foo/bar/baz:12)" },

View File

@ -29,35 +29,35 @@ function test() {
let A = treeRoot.getChild();
let B = A.getChild();
let C = B.getChild();
let D = B.getChild();
is(C.target.getAttribute("origin"), "chrome",
"The .A.B.C node's 'origin' attribute is correct.");
is(C.target.getAttribute("category"), "gc",
"The .A.B.C node's 'category' attribute is correct.");
is(C.target.getAttribute("tooltiptext"), "D (http://foo/bar/baz:78)",
"The .A.B.C node's 'tooltiptext' attribute is correct.");
is(D.target.getAttribute("origin"), "chrome",
"The .A.B.D node's 'origin' attribute is correct.");
is(D.target.getAttribute("category"), "gc",
"The .A.B.D node's 'category' attribute is correct.");
is(D.target.getAttribute("tooltiptext"), "D (http://foo/bar/baz:78)",
"The .A.B.D node's 'tooltiptext' attribute is correct.");
ok(!A.target.querySelector(".call-tree-zoom").hidden,
"The .A.B.C node's zoom button cell should not be hidden.");
"The .A.B.D node's zoom button cell should not be hidden.");
ok(!A.target.querySelector(".call-tree-category").hidden,
"The .A.B.C node's category label cell should not be hidden.");
"The .A.B.D node's category label cell should not be hidden.");
is(C.target.childNodes.length, 6,
is(D.target.childNodes.length, 6,
"The number of columns displayed for tree items is correct.");
is(C.target.childNodes[0].getAttribute("type"), "duration",
is(D.target.childNodes[0].getAttribute("type"), "duration",
"The first column displayed for tree items is correct.");
is(C.target.childNodes[1].getAttribute("type"), "percentage",
is(D.target.childNodes[1].getAttribute("type"), "percentage",
"The third column displayed for tree items is correct.");
is(C.target.childNodes[2].getAttribute("type"), "self-duration",
is(D.target.childNodes[2].getAttribute("type"), "self-duration",
"The second column displayed for tree items is correct.");
is(C.target.childNodes[3].getAttribute("type"), "self-percentage",
is(D.target.childNodes[3].getAttribute("type"), "self-percentage",
"The fourth column displayed for tree items is correct.");
is(C.target.childNodes[4].getAttribute("type"), "samples",
is(D.target.childNodes[4].getAttribute("type"), "samples",
"The fifth column displayed for tree items is correct.");
is(C.target.childNodes[5].getAttribute("type"), "function",
is(D.target.childNodes[5].getAttribute("type"), "function",
"The sixth column displayed for tree items is correct.");
let functionCell = C.target.childNodes[5];
let functionCell = D.target.childNodes[5];
is(functionCell.childNodes.length, 8,
"The number of columns displayed for function cells is correct.");
@ -90,7 +90,7 @@ let gSamples = [{
{ category: 32, location: "C (http://foo/bar/baz:56)" }
]
}, {
time: 5 + 6,
time: 5 + 1,
frames: [
{ category: 8, location: "(root)" },
{ category: 8, location: "A (http://foo/bar/baz:12)" },
@ -98,7 +98,15 @@ let gSamples = [{
{ category: 64, location: "D (http://foo/bar/baz:78)" }
]
}, {
time: 5 + 6 + 7,
time: 5 + 1 + 2,
frames: [
{ category: 8, location: "(root)" },
{ category: 8, location: "A (http://foo/bar/baz:12)" },
{ category: 16, location: "B (http://foo/bar/baz:34)" },
{ category: 64, location: "D (http://foo/bar/baz:78)" }
]
}, {
time: 5 + 1 + 2 + 7,
frames: [
{ category: 8, location: "(root)" },
{ category: 8, location: "A (http://foo/bar/baz:12)" },

View File

@ -40,7 +40,7 @@ let gSamples = [{
{ category: 32, location: "C (http://foo/bar/baz:56)" }
]
}, {
time: 5 + 6,
time: 5 + 1,
frames: [
{ category: 8, location: "(root)" },
{ category: 8, location: "A (http://foo/bar/baz:12)" },
@ -48,7 +48,15 @@ let gSamples = [{
{ category: 64, location: "D (http://foo/bar/baz:78)" }
]
}, {
time: 5 + 6 + 7,
time: 5 + 1 + 2,
frames: [
{ category: 8, location: "(root)" },
{ category: 8, location: "A (http://foo/bar/baz:12)" },
{ category: 16, location: "B (http://foo/bar/baz:34)" },
{ category: 64, location: "D (http://foo/bar/baz:78)" }
]
}, {
time: 5 + 1 + 2 + 7,
frames: [
{ category: 8, location: "(root)" },
{ category: 8, location: "A (http://foo/bar/baz:12)" },

View File

@ -18,19 +18,19 @@ let test = Task.async(function*() {
let A = treeRoot.getChild();
let B = A.getChild();
let C = B.getChild();
let D = B.getChild();
let receivedLinkEvent = treeRoot.once("link");
EventUtils.sendMouseEvent({ type: "mousedown" }, C.target.querySelector(".call-tree-url"));
EventUtils.sendMouseEvent({ type: "mousedown" }, D.target.querySelector(".call-tree-url"));
let eventItem = yield receivedLinkEvent;
is(eventItem, C, "The 'link' event target is correct.");
is(eventItem, D, "The 'link' event target is correct.");
let receivedZoomEvent = treeRoot.once("zoom");
EventUtils.sendMouseEvent({ type: "mousedown" }, C.target.querySelector(".call-tree-zoom"));
EventUtils.sendMouseEvent({ type: "mousedown" }, D.target.querySelector(".call-tree-zoom"));
eventItem = yield receivedZoomEvent;
is(eventItem, C, "The 'zoom' event target is correct.");
is(eventItem, D, "The 'zoom' event target is correct.");
finish();
});
@ -44,7 +44,7 @@ let gSamples = [{
{ category: 32, location: "C (http://foo/bar/baz:56)" }
]
}, {
time: 5 + 6,
time: 5 + 1,
frames: [
{ category: 8, location: "(root)" },
{ category: 8, location: "A (http://foo/bar/baz:12)" },
@ -52,7 +52,15 @@ let gSamples = [{
{ category: 64, location: "D (http://foo/bar/baz:78)" }
]
}, {
time: 5 + 6 + 7,
time: 5 + 1 + 2,
frames: [
{ category: 8, location: "(root)" },
{ category: 8, location: "A (http://foo/bar/baz:12)" },
{ category: 16, location: "B (http://foo/bar/baz:34)" },
{ category: 64, location: "D (http://foo/bar/baz:78)" }
]
}, {
time: 5 + 1 + 2 + 7,
frames: [
{ category: 8, location: "(root)" },
{ category: 8, location: "A (http://foo/bar/baz:12)" },

View File

@ -19,18 +19,18 @@ function test() {
let A = treeRoot.getChild();
let B = A.getChild();
let C = B.getChild();
let D = B.getChild();
is(C.root, treeRoot,
"The .A.B.C node has the correct root.");
is(C.parent, B,
"The .A.B.C node has the correct parent.");
is(C.level, 3,
"The .A.B.C node has the correct level.");
is(C.target.className, "call-tree-item",
"The .A.B.C node has the correct target node.");
is(C.container.id, "call-tree-container",
"The .A.B.C node has the correct container node.");
is(D.root, treeRoot,
"The .A.B.D node has the correct root.");
is(D.parent, B,
"The .A.B.D node has the correct parent.");
is(D.level, 3,
"The .A.B.D node has the correct level.");
is(D.target.className, "call-tree-item",
"The .A.B.D node has the correct target node.");
is(D.container.id, "call-tree-container",
"The .A.B.D node has the correct container node.");
finish();
}
@ -44,7 +44,7 @@ let gSamples = [{
{ category: 32, location: "C (http://foo/bar/baz:56)" }
]
}, {
time: 5 + 6,
time: 5 + 1,
frames: [
{ category: 8, location: "(root)" },
{ category: 8, location: "A (http://foo/bar/baz:12)" },
@ -52,7 +52,15 @@ let gSamples = [{
{ category: 64, location: "D (http://foo/bar/baz:78)" }
]
}, {
time: 5 + 6 + 7,
time: 5 + 1 + 2,
frames: [
{ category: 8, location: "(root)" },
{ category: 8, location: "A (http://foo/bar/baz:12)" },
{ category: 16, location: "B (http://foo/bar/baz:34)" },
{ category: 64, location: "D (http://foo/bar/baz:78)" }
]
}, {
time: 5 + 1 + 2 + 7,
frames: [
{ category: 8, location: "(root)" },
{ category: 8, location: "A (http://foo/bar/baz:12)" },

View File

@ -174,8 +174,8 @@ CallView.prototype = Heritage.extend(AbstractTreeItem.prototype, {
}));
}
// Sort the "callees" asc. by duration, before inserting them in the tree.
children.sort((a, b) => a.frame.duration < b.frame.duration ? 1 : -1);
// Sort the "callees" asc. by samples, before inserting them in the tree.
children.sort((a, b) => a.frame.samples < b.frame.samples ? 1 : -1);
},
/**

View File

@ -273,12 +273,14 @@ this.ContentSearch = {
}),
_onMessageAddFormHistoryEntry: function (msg, entry) {
// There are some tests that use about:home and newtab that trigger a search
// and then immediately close the tab. In those cases, the browser may have
// been destroyed by the time we receive this message, and as a result
// contentWindow is undefined.
if (!msg.target.contentWindow ||
PrivateBrowsingUtils.isBrowserPrivate(msg.target)) {
let isPrivate = true;
try {
// isBrowserPrivate assumes that the passed-in browser has all the normal
// properties, which won't be true if the browser has been destroyed.
// That may be the case here due to the asynchronous nature of messaging.
isPrivate = PrivateBrowsingUtils.isBrowserPrivate(msg.target);
} catch (err) {}
if (isPrivate || entry === "") {
return Promise.resolve();
}
let browserData = this._suggestionDataForBrowser(msg.target, true);

View File

@ -175,6 +175,7 @@ using namespace mozilla::dom::mobileconnection;
using namespace mozilla::dom::mobilemessage;
using namespace mozilla::dom::telephony;
using namespace mozilla::dom::voicemail;
using namespace mozilla::embedding;
using namespace mozilla::hal_sandbox;
using namespace mozilla::ipc;
using namespace mozilla::layers;
@ -1391,6 +1392,24 @@ ContentChild::DeallocPNeckoChild(PNeckoChild* necko)
return true;
}
PPrintingChild*
ContentChild::AllocPPrintingChild()
{
// The ContentParent should never attempt to allocate the
// nsPrintingPromptServiceProxy, which implements PPrintingChild. Instead,
// the nsPrintingPromptServiceProxy service is requested and instantiated
// via XPCOM, and the constructor of nsPrintingPromptServiceProxy sets up
// the IPC connection.
NS_NOTREACHED("Should never get here!");
return nullptr;
}
bool
ContentChild::DeallocPPrintingChild(PPrintingChild* printing)
{
return true;
}
PScreenManagerChild*
ContentChild::AllocPScreenManagerChild(uint32_t* aNumberOfScreens,
float* aSystemDefaultScale,

View File

@ -207,6 +207,9 @@ public:
virtual PNeckoChild* AllocPNeckoChild() MOZ_OVERRIDE;
virtual bool DeallocPNeckoChild(PNeckoChild*) MOZ_OVERRIDE;
virtual PPrintingChild* AllocPPrintingChild() MOZ_OVERRIDE;
virtual bool DeallocPPrintingChild(PPrintingChild*) MOZ_OVERRIDE;
virtual PScreenManagerChild*
AllocPScreenManagerChild(uint32_t* aNumberOfScreens,
float* aSystemDefaultScale,

View File

@ -57,6 +57,7 @@
#include "mozilla/dom/telephony/TelephonyParent.h"
#include "mozilla/dom/time/DateCacheCleaner.h"
#include "mozilla/dom/voicemail/VoicemailParent.h"
#include "mozilla/embedding/printingui/PrintingParent.h"
#include "mozilla/hal_sandbox/PHalParent.h"
#include "mozilla/ipc/BackgroundChild.h"
#include "mozilla/ipc/BackgroundParent.h"
@ -208,6 +209,7 @@ using namespace mozilla::dom::mobileconnection;
using namespace mozilla::dom::mobilemessage;
using namespace mozilla::dom::telephony;
using namespace mozilla::dom::voicemail;
using namespace mozilla::embedding;
using namespace mozilla::hal;
using namespace mozilla::ipc;
using namespace mozilla::layers;
@ -3116,6 +3118,25 @@ ContentParent::DeallocPNeckoParent(PNeckoParent* necko)
return true;
}
PPrintingParent*
ContentParent::AllocPPrintingParent()
{
return new PrintingParent();
}
bool
ContentParent::RecvPPrintingConstructor(PPrintingParent* aActor)
{
return true;
}
bool
ContentParent::DeallocPPrintingParent(PPrintingParent* printing)
{
delete printing;
return true;
}
PScreenManagerParent*
ContentParent::AllocPScreenManagerParent(uint32_t* aNumberOfScreens,
float* aSystemDefaultScale,

View File

@ -245,6 +245,10 @@ public:
return PContentParent::RecvPNeckoConstructor(aActor);
}
virtual PPrintingParent* AllocPPrintingParent() MOZ_OVERRIDE;
virtual bool RecvPPrintingConstructor(PPrintingParent* aActor) MOZ_OVERRIDE;
virtual bool DeallocPPrintingParent(PPrintingParent* aActor) MOZ_OVERRIDE;
virtual PScreenManagerParent*
AllocPScreenManagerParent(uint32_t* aNumberOfScreens,
float* aSystemDefaultScale,

View File

@ -25,6 +25,7 @@ include protocol PImageBridge;
include protocol PMemoryReportRequest;
include protocol PMobileConnection;
include protocol PNecko;
include protocol PPrinting;
include protocol PScreenManager;
include protocol PSharedBufferManager;
include protocol PSms;
@ -349,6 +350,7 @@ prio(normal upto high) intr protocol PContent
manages PMemoryReportRequest;
manages PMobileConnection;
manages PNecko;
manages PPrinting;
manages PScreenManager;
manages PSms;
manages PSpeechSynthesis;
@ -553,6 +555,8 @@ parent:
PNecko();
PPrinting();
prio(high) sync PScreenManager()
returns (uint32_t numberOfScreens,
float systemDefaultScale,

View File

@ -110,6 +110,7 @@ LOCAL_INCLUDES += [
'/dom/mobilemessage/ipc',
'/dom/storage',
'/editor/libeditor',
'/embedding/components/printingui/ipc',
'/extensions/cookie',
'/extensions/spellcheck/src',
'/hal/sandbox',

View File

@ -15,11 +15,13 @@ LOCAL_INCLUDES += [
'../appstartup',
'../commandhandler',
'../find',
'../printingui/ipc',
'../webbrowserpersist',
'../windowwatcher',
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
DEFINES['PROXY_PRINTING'] = 1
LOCAL_INCLUDES += [
'../printingui/win',
]
@ -29,7 +31,10 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
]
if CONFIG['MOZ_PDF_PRINTING']:
DEFINES['PROXY_PRINTING'] = 1
LOCAL_INCLUDES += [
'../printingui/unixshared',
]
include('/ipc/chromium/chromium-config.mozbuild')

View File

@ -20,6 +20,7 @@
#ifdef NS_PRINTING
#include "nsPrintingPromptService.h"
#include "nsPrintingPromptServiceProxy.h"
#endif
@ -38,6 +39,9 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsBaseCommandController)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsDialogParamBlock)
#ifdef NS_PRINTING
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPrintingPromptService, Init)
#ifdef PROXY_PRINTING
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPrintingPromptServiceProxy, Init)
#endif
#endif
#endif
@ -62,8 +66,16 @@ static const mozilla::Module::CIDEntry kEmbeddingCIDs[] = {
#ifdef MOZ_XUL
{ &kNS_DIALOGPARAMBLOCK_CID, false, nullptr, nsDialogParamBlockConstructor },
#ifdef NS_PRINTING
#ifdef PROXY_PRINTING
{ &kNS_PRINTINGPROMPTSERVICE_CID, false, nullptr, nsPrintingPromptServiceConstructor,
mozilla::Module::MAIN_PROCESS_ONLY },
{ &kNS_PRINTINGPROMPTSERVICE_CID, false, nullptr, nsPrintingPromptServiceProxyConstructor,
mozilla::Module::CONTENT_PROCESS_ONLY },
#else
{ &kNS_PRINTINGPROMPTSERVICE_CID, false, nullptr, nsPrintingPromptServiceConstructor },
#endif
#endif
#endif
{ &kNS_WINDOWWATCHER_CID, false, nullptr, nsWindowWatcherConstructor },
{ &kNS_FIND_CID, false, nullptr, nsFindConstructor },

View File

@ -0,0 +1,101 @@
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PContent;
include protocol PBrowser;
namespace mozilla {
namespace embedding {
struct PrintData {
int32_t startPageRange;
int32_t endPageRange;
double edgeTop;
double edgeLeft;
double edgeBottom;
double edgeRight;
double marginTop;
double marginLeft;
double marginBottom;
double marginRight;
double unwriteableMarginTop;
double unwriteableMarginLeft;
double unwriteableMarginBottom;
double unwriteableMarginRight;
double scaling;
bool printBGColors;
bool printBGImages;
short printRange;
nsString title;
nsString docURL;
nsString headerStrLeft;
nsString headerStrCenter;
nsString headerStrRight;
nsString footerStrLeft;
nsString footerStrCenter;
nsString footerStrRight;
short howToEnableFrameUI;
bool isCancelled;
short printFrameTypeUsage;
short printFrameType;
bool printSilent;
bool shrinkToFit;
bool showPrintProgress;
nsString paperName;
short paperSizeType;
short paperData;
double paperWidth;
double paperHeight;
short paperSizeUnit;
nsString plexName;
nsString colorspace;
nsString resolutionName;
bool downloadFonts;
bool printReversed;
bool printInColor;
int32_t orientation;
nsString printCommand;
int32_t numCopies;
nsString printerName;
bool printToFile;
nsString toFileName;
short outputFormat;
int32_t printPageDelay;
int32_t resolution;
int32_t duplex;
bool isInitializedFromPrinter;
bool isInitializedFromPrefs;
bool persistMarginBoxSettings;
/* Windows-specific things */
nsString driverName;
nsString deviceName;
bool isFramesetDocument;
bool isFramesetFrameSelected;
bool isIFrameSelected;
bool isRangeSelection;
/* TODO: OS X specific things - specifically, an array of names for the
* document to be supplied by nsIWebBrowserPrint::enumerateDocumentNames
*/
};
sync protocol PPrinting
{
manager PContent;
parent:
sync ShowProgress(PBrowser browser, bool isForPrinting);
sync ShowPrintDialog(PBrowser browser, PrintData settings)
returns(PrintData modifiedSettings, bool success);
child:
__delete__();
};
} // namespace embedding
} // namespace mozilla

View File

@ -0,0 +1,143 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set sw=4 ts=8 et tw=80 : */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "PrintDataUtils.h"
#include "nsIPrintOptions.h"
#include "nsIPrintSettings.h"
#include "nsIServiceManager.h"
#include "nsIWebBrowserPrint.h"
#include "nsXPIDLString.h"
namespace mozilla {
namespace embedding {
/**
* MockWebBrowserPrint is a mostly useless implementation of nsIWebBrowserPrint,
* but wraps a PrintData so that it's able to return information to print
* settings dialogs that need an nsIWebBrowserPrint to interrogate.
*/
NS_IMPL_ISUPPORTS(MockWebBrowserPrint, nsIWebBrowserPrint);
MockWebBrowserPrint::MockWebBrowserPrint(PrintData aData)
: mData(aData)
{
MOZ_COUNT_CTOR(MockWebBrowserPrint);
}
MockWebBrowserPrint::~MockWebBrowserPrint()
{
MOZ_COUNT_DTOR(MockWebBrowserPrint);
}
NS_IMETHODIMP
MockWebBrowserPrint::GetGlobalPrintSettings(nsIPrintSettings **aGlobalPrintSettings)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
MockWebBrowserPrint::GetCurrentPrintSettings(nsIPrintSettings **aCurrentPrintSettings)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
MockWebBrowserPrint::GetCurrentChildDOMWindow(nsIDOMWindow **aCurrentPrintSettings)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
MockWebBrowserPrint::GetDoingPrint(bool *aDoingPrint)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
MockWebBrowserPrint::GetDoingPrintPreview(bool *aDoingPrintPreview)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
MockWebBrowserPrint::GetIsFramesetDocument(bool *aIsFramesetDocument)
{
*aIsFramesetDocument = mData.isFramesetDocument();
return NS_OK;
}
NS_IMETHODIMP
MockWebBrowserPrint::GetIsFramesetFrameSelected(bool *aIsFramesetFrameSelected)
{
*aIsFramesetFrameSelected = mData.isFramesetFrameSelected();
return NS_OK;
}
NS_IMETHODIMP
MockWebBrowserPrint::GetIsIFrameSelected(bool *aIsIFrameSelected)
{
*aIsIFrameSelected = mData.isIFrameSelected();
return NS_OK;
}
NS_IMETHODIMP
MockWebBrowserPrint::GetIsRangeSelection(bool *aIsRangeSelection)
{
*aIsRangeSelection = mData.isRangeSelection();
return NS_OK;
}
NS_IMETHODIMP
MockWebBrowserPrint::GetPrintPreviewNumPages(int32_t *aPrintPreviewNumPages)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
MockWebBrowserPrint::Print(nsIPrintSettings* aThePrintSettings,
nsIWebProgressListener* aWPListener)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
MockWebBrowserPrint::PrintPreview(nsIPrintSettings* aThePrintSettings,
nsIDOMWindow* aChildDOMWin,
nsIWebProgressListener* aWPListener)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
MockWebBrowserPrint::PrintPreviewNavigate(int16_t aNavType,
int32_t aPageNum)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
MockWebBrowserPrint::Cancel()
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
MockWebBrowserPrint::EnumerateDocumentNames(uint32_t* aCount,
char16_t*** aResult)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
MockWebBrowserPrint::ExitPrintPreview()
{
return NS_ERROR_NOT_IMPLEMENTED;
}
} // namespace embedding
} // namespace mozilla

View File

@ -0,0 +1,39 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set sw=4 ts=8 et tw=80 : */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_embedding_PrintDataUtils_h
#define mozilla_embedding_PrintDataUtils_h
#include "mozilla/embedding/PPrinting.h"
#include "nsIWebBrowserPrint.h"
/**
* nsIPrintSettings and nsIWebBrowserPrint information is sent back and forth
* across PPrinting via the PrintData struct. These are utilities for
* manipulating PrintData that can be used on either side of the communications
* channel.
*/
namespace mozilla {
namespace embedding {
class MockWebBrowserPrint MOZ_FINAL : public nsIWebBrowserPrint
{
public:
MockWebBrowserPrint(PrintData aData);
NS_DECL_ISUPPORTS
NS_DECL_NSIWEBBROWSERPRINT
private:
~MockWebBrowserPrint();
PrintData mData;
};
} // namespace embedding
} // namespace mozilla
#endif

View File

@ -0,0 +1,150 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set sw=4 ts=8 et tw=80 : */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/Element.h"
#include "mozilla/dom/TabParent.h"
#include "nsIContent.h"
#include "nsIDocument.h"
#include "nsIDOMWindow.h"
#include "nsIPrintingPromptService.h"
#include "nsIPrintProgressParams.h"
#include "nsIServiceManager.h"
#include "nsIWebProgressListener.h"
#include "PrintingParent.h"
#include "nsIPrintOptions.h"
#include "PrintDataUtils.h"
using namespace mozilla;
using namespace mozilla::dom;
namespace mozilla {
namespace embedding {
bool
PrintingParent::RecvShowProgress(PBrowserParent* parent,
const bool& isForPrinting)
{
TabParent* tabParent = static_cast<TabParent*>(parent);
if (!tabParent) {
return true;
}
nsCOMPtr<Element> frameElement = tabParent->GetOwnerElement();
if (!frameElement) {
return true;
}
nsCOMPtr<nsIContent> frame(do_QueryInterface(frameElement));
if (!frame) {
return true;
}
nsCOMPtr<nsIDOMWindow> parentWin = do_QueryInterface(frame->OwnerDoc()->GetWindow());
if (!parentWin) {
return true;
}
nsCOMPtr<nsIPrintingPromptService> pps(do_GetService("@mozilla.org/embedcomp/printingprompt-service;1"));
if (!pps) {
return true;
}
nsCOMPtr<nsIWebProgressListener> printProgressListener;
nsCOMPtr<nsIPrintProgressParams> printProgressParams;
// TODO: What do I do with this thing?
bool doNotify = false;
pps->ShowProgress(parentWin, nullptr, nullptr, nullptr,
isForPrinting,
getter_AddRefs(printProgressListener),
getter_AddRefs(printProgressParams),
&doNotify);
return true;
}
bool
PrintingParent::RecvShowPrintDialog(PBrowserParent* parent,
const PrintData& data,
PrintData* retVal,
bool* success)
{
*success = false;
TabParent* tabParent = static_cast<TabParent*>(parent);
if (!tabParent) {
return true;
}
nsCOMPtr<Element> frameElement = tabParent->GetOwnerElement();
if (!frameElement) {
return true;
}
nsCOMPtr<nsIContent> frame(do_QueryInterface(frameElement));
if (!frame) {
return true;
}
nsCOMPtr<nsIDOMWindow> parentWin = do_QueryInterface(frame->OwnerDoc()->GetWindow());
if (!parentWin) {
return true;
}
nsCOMPtr<nsIPrintingPromptService> pps(do_GetService("@mozilla.org/embedcomp/printingprompt-service;1"));
if (!pps) {
return true;
}
// The initSettings we got can be wrapped using
// PrintDataUtils' MockWebBrowserPrint, which implements enough of
// nsIWebBrowserPrint to keep the dialogs happy.
nsCOMPtr<nsIWebBrowserPrint> wbp = new MockWebBrowserPrint(data);
nsresult rv;
nsCOMPtr<nsIPrintOptions> po = do_GetService("@mozilla.org/gfx/printsettings-service;1", &rv);
NS_ENSURE_SUCCESS(rv, true);
nsCOMPtr<nsIPrintSettings> settings;
rv = po->CreatePrintSettings(getter_AddRefs(settings));
NS_ENSURE_SUCCESS(rv, true);
rv = po->DeserializeToPrintSettings(data, settings);
NS_ENSURE_SUCCESS(rv, true);
rv = pps->ShowPrintDialog(parentWin, wbp, settings);
NS_ENSURE_SUCCESS(rv, true);
// And send it back.
PrintData result;
rv = po->SerializeToPrintData(settings, nullptr, &result);
NS_ENSURE_SUCCESS(rv, true);
*retVal = result;
*success = true;
return true;
}
void
PrintingParent::ActorDestroy(ActorDestroyReason aWhy)
{
}
MOZ_IMPLICIT PrintingParent::PrintingParent()
{
MOZ_COUNT_CTOR(PrintingParent);
}
MOZ_IMPLICIT PrintingParent::~PrintingParent()
{
MOZ_COUNT_DTOR(PrintingParent);
}
} // namespace embedding
} // namespace mozilla

View File

@ -0,0 +1,37 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set sw=4 ts=8 et tw=80 : */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_embedding_PrintingParent_h
#define mozilla_embedding_PrintingParent_h
#include "mozilla/embedding/PPrintingParent.h"
#include "mozilla/dom/PBrowserParent.h"
namespace mozilla {
namespace embedding {
class PrintingParent : public PPrintingParent
{
public:
virtual bool
RecvShowProgress(PBrowserParent* parent,
const bool& isForPrinting);
virtual bool
RecvShowPrintDialog(PBrowserParent* parent,
const PrintData& initSettings,
PrintData* retVal,
bool* success);
virtual void
ActorDestroy(ActorDestroyReason aWhy);
MOZ_IMPLICIT PrintingParent();
virtual ~PrintingParent();
};
} // namespace embedding
} // namespace mozilla
#endif

View File

@ -0,0 +1,25 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
EXPORTS.mozilla.embedding.printingui += [
'PrintingParent.h',
]
UNIFIED_SOURCES += [
'nsPrintingPromptServiceProxy.cpp',
'PrintDataUtils.cpp',
'PrintingParent.cpp',
]
IPDL_SOURCES += [
'PPrinting.ipdl',
]
include('/ipc/chromium/chromium-config.mozbuild')
FAIL_ON_WARNINGS = True
FINAL_LIBRARY = 'xul'

View File

@ -0,0 +1,135 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/TabChild.h"
#include "mozilla/unused.h"
#include "nsIDocShell.h"
#include "nsIDocShellTreeOwner.h"
#include "nsPIDOMWindow.h"
#include "nsPrintingPromptServiceProxy.h"
#include "nsIPrintingPromptService.h"
#include "PrintDataUtils.h"
#include "nsPrintOptionsImpl.h"
using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::embedding;
NS_IMPL_ISUPPORTS(nsPrintingPromptServiceProxy, nsIPrintingPromptService)
nsPrintingPromptServiceProxy::nsPrintingPromptServiceProxy()
{
}
nsPrintingPromptServiceProxy::~nsPrintingPromptServiceProxy()
{
}
nsresult
nsPrintingPromptServiceProxy::Init()
{
mozilla::unused << ContentChild::GetSingleton()->SendPPrintingConstructor(this);
return NS_OK;
}
NS_IMETHODIMP
nsPrintingPromptServiceProxy::ShowPrintDialog(nsIDOMWindow *parent,
nsIWebBrowserPrint *webBrowserPrint,
nsIPrintSettings *printSettings)
{
NS_ENSURE_ARG(parent);
NS_ENSURE_ARG(webBrowserPrint);
NS_ENSURE_ARG(printSettings);
// Get the root docshell owner of this nsIDOMWindow, which
// should map to a TabChild, which we can then pass up to
// the parent.
nsCOMPtr<nsPIDOMWindow> pwin = do_QueryInterface(parent);
NS_ENSURE_STATE(pwin);
nsCOMPtr<nsIDocShell> docShell = pwin->GetDocShell();
NS_ENSURE_STATE(docShell);
nsCOMPtr<nsIDocShellTreeOwner> owner;
nsresult rv = docShell->GetTreeOwner(getter_AddRefs(owner));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsITabChild> tabchild = do_GetInterface(owner);
NS_ENSURE_STATE(tabchild);
TabChild* pBrowser = static_cast<TabChild*>(tabchild.get());
// Next, serialize the nsIWebBrowserPrint and nsIPrintSettings we were given.
nsCOMPtr<nsIPrintOptions> po =
do_GetService("@mozilla.org/gfx/printsettings-service;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
PrintData inSettings;
rv = po->SerializeToPrintData(printSettings, webBrowserPrint, &inSettings);
NS_ENSURE_SUCCESS(rv, rv);
PrintData modifiedSettings;
bool success;
mozilla::unused << SendShowPrintDialog(pBrowser, inSettings, &modifiedSettings, &success);
if (!success) {
// Something failed in the parent.
return NS_ERROR_FAILURE;
}
rv = po->DeserializeToPrintSettings(modifiedSettings, printSettings);
return NS_OK;
}
NS_IMETHODIMP
nsPrintingPromptServiceProxy::ShowProgress(nsIDOMWindow* parent,
nsIWebBrowserPrint* webBrowserPrint, // ok to be null
nsIPrintSettings* printSettings, // ok to be null
nsIObserver* openDialogObserver, // ok to be null
bool isForPrinting,
nsIWebProgressListener** webProgressListener,
nsIPrintProgressParams** printProgressParams,
bool* notifyOnOpen)
{
NS_ENSURE_ARG(parent);
NS_ENSURE_ARG(webProgressListener);
NS_ENSURE_ARG(printProgressParams);
NS_ENSURE_ARG(notifyOnOpen);
// Get the root docshell owner of this nsIDOMWindow, which
// should map to a TabChild, which we can then pass up to
// the parent.
nsCOMPtr<nsPIDOMWindow> pwin = do_QueryInterface(parent);
NS_ENSURE_STATE(pwin);
nsCOMPtr<nsIDocShell> docShell = pwin->GetDocShell();
NS_ENSURE_STATE(docShell);
nsCOMPtr<nsIDocShellTreeOwner> owner;
nsresult rv = docShell->GetTreeOwner(getter_AddRefs(owner));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsITabChild> tabchild = do_GetInterface(owner);
TabChild* pBrowser = static_cast<TabChild*>(tabchild.get());
mozilla::unused << SendShowProgress(pBrowser, isForPrinting);
return NS_OK;
}
NS_IMETHODIMP
nsPrintingPromptServiceProxy::ShowPageSetup(nsIDOMWindow *parent,
nsIPrintSettings *printSettings,
nsIObserver *aObs)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsPrintingPromptServiceProxy::ShowPrinterProperties(nsIDOMWindow *parent,
const char16_t *printerName,
nsIPrintSettings *printSettings)
{
return NS_ERROR_NOT_IMPLEMENTED;
}

View File

@ -0,0 +1,27 @@
/* -*- 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 __nsPrintingPromptServiceProxy_h
#define __nsPrintingPromptServiceProxy_h
#include "nsIPrintingPromptService.h"
#include "mozilla/embedding/PPrintingChild.h"
class nsPrintingPromptServiceProxy: public nsIPrintingPromptService,
public mozilla::embedding::PPrintingChild
{
virtual ~nsPrintingPromptServiceProxy();
public:
nsPrintingPromptServiceProxy();
nsresult Init();
NS_DECL_ISUPPORTS
NS_DECL_NSIPRINTINGPROMPTSERVICE
};
#endif

View File

@ -6,6 +6,8 @@
toolkit = CONFIG['MOZ_WIDGET_TOOLKIT']
DIRS += ['ipc']
if toolkit == 'windows':
DIRS += ['win']
elif toolkit == 'cocoa':

View File

@ -11,6 +11,10 @@ UNIFIED_SOURCES += [
'nsPrintProgressParams.cpp',
]
EXPORTS += [
'nsPrintDialogUtil.h',
]
FAIL_ON_WARNINGS = True
FINAL_LIBRARY = 'xul'

View File

@ -682,7 +682,7 @@ static UINT CALLBACK PrintHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM
// This function assumes that aPrintName has already been converted from
// unicode
//
static HGLOBAL CreateGlobalDevModeAndInit(const nsXPIDLString& aPrintName, nsIPrintSettings* aPS)
HGLOBAL CreateGlobalDevModeAndInit(const nsXPIDLString& aPrintName, nsIPrintSettings* aPS)
{
HGLOBAL hGlobalDevMode = nullptr;

View File

@ -9,4 +9,6 @@ nsresult NativeShowPrintDialog(HWND aHWnd,
nsIWebBrowserPrint* aWebBrowserPrint,
nsIPrintSettings* aPrintSettings);
HGLOBAL CreateGlobalDevModeAndInit(const nsXPIDLString& aPrintName, nsIPrintSettings* aPS);
#endif /* nsFlyOwnDialog_h___ */

View File

@ -21,7 +21,6 @@ import org.mozilla.gecko.AppConstants.Versions;
import org.mozilla.gecko.DynamicToolbar.PinReason;
import org.mozilla.gecko.DynamicToolbar.VisibilityTransition;
import org.mozilla.gecko.GeckoProfileDirectories.NoMozillaDirectoryException;
import org.mozilla.gecko.ReadingListHelper;
import org.mozilla.gecko.animation.PropertyAnimator;
import org.mozilla.gecko.animation.ViewHelper;
import org.mozilla.gecko.db.BrowserContract.Combined;
@ -52,6 +51,7 @@ import org.mozilla.gecko.home.HomePanelsManager;
import org.mozilla.gecko.home.SearchEngine;
import org.mozilla.gecko.menu.GeckoMenu;
import org.mozilla.gecko.menu.GeckoMenuItem;
import org.mozilla.gecko.mozglue.ContextUtils;
import org.mozilla.gecko.preferences.ClearOnShutdownPref;
import org.mozilla.gecko.preferences.GeckoPreferences;
import org.mozilla.gecko.prompts.Prompt;
@ -684,7 +684,7 @@ public class BrowserApp extends GeckoApp
public void onResume() {
super.onResume();
final String args = StringUtils.getStringExtra(getIntent(), "args");
final String args = ContextUtils.getStringExtra(getIntent(), "args");
// If an external intent tries to start Fennec in guest mode, and it's not already
// in guest mode, this will change modes before opening the url.
// NOTE: OnResume is called twice sometimes when showing on the lock screen.
@ -2666,12 +2666,12 @@ public class BrowserApp extends GeckoApp
}
// Disable share menuitem for about:, chrome:, file:, and resource: URIs
final boolean shareEnabled = RestrictedProfiles.isAllowed(RestrictedProfiles.Restriction.DISALLOW_SHARE);
final boolean shareEnabled = RestrictedProfiles.isAllowed(this, RestrictedProfiles.Restriction.DISALLOW_SHARE);
share.setVisible(shareEnabled);
share.setEnabled(StringUtils.isShareableUrl(url) && shareEnabled);
MenuUtils.safeSetEnabled(aMenu, R.id.apps, RestrictedProfiles.isAllowed(RestrictedProfiles.Restriction.DISALLOW_INSTALL_APPS));
MenuUtils.safeSetEnabled(aMenu, R.id.addons, RestrictedProfiles.isAllowed(RestrictedProfiles.Restriction.DISALLOW_INSTALL_EXTENSION));
MenuUtils.safeSetEnabled(aMenu, R.id.downloads, RestrictedProfiles.isAllowed(RestrictedProfiles.Restriction.DISALLOW_DOWNLOADS));
MenuUtils.safeSetEnabled(aMenu, R.id.apps, RestrictedProfiles.isAllowed(this, RestrictedProfiles.Restriction.DISALLOW_INSTALL_APPS));
MenuUtils.safeSetEnabled(aMenu, R.id.addons, RestrictedProfiles.isAllowed(this, RestrictedProfiles.Restriction.DISALLOW_INSTALL_EXTENSION));
MenuUtils.safeSetEnabled(aMenu, R.id.downloads, RestrictedProfiles.isAllowed(this, RestrictedProfiles.Restriction.DISALLOW_DOWNLOADS));
// NOTE: Use MenuUtils.safeSetEnabled because some actions might
// be on the BrowserToolbar context menu.

View File

@ -40,6 +40,8 @@ import org.mozilla.gecko.health.StubbedHealthRecorder;
import org.mozilla.gecko.menu.GeckoMenu;
import org.mozilla.gecko.menu.GeckoMenuInflater;
import org.mozilla.gecko.menu.MenuPanel;
import org.mozilla.gecko.mozglue.ContextUtils;
import org.mozilla.gecko.mozglue.ContextUtils.SafeIntent;
import org.mozilla.gecko.mozglue.GeckoLoader;
import org.mozilla.gecko.preferences.ClearOnShutdownPref;
import org.mozilla.gecko.preferences.GeckoPreferences;
@ -55,7 +57,6 @@ import org.mozilla.gecko.util.HardwareUtils;
import org.mozilla.gecko.util.NativeEventListener;
import org.mozilla.gecko.util.NativeJSObject;
import org.mozilla.gecko.util.PrefUtils;
import org.mozilla.gecko.util.StringUtils;
import org.mozilla.gecko.util.ThreadUtils;
import org.mozilla.gecko.webapp.EventListener;
import org.mozilla.gecko.webapp.UninstallListener;
@ -1102,8 +1103,8 @@ public abstract class GeckoApp
/**
* Check and start the Java profiler if MOZ_PROFILER_STARTUP env var is specified.
**/
protected static void earlyStartJavaSampler(Intent intent) {
String env = StringUtils.getStringExtra(intent, "env0");
protected static void earlyStartJavaSampler(SafeIntent intent) {
String env = intent.getStringExtra("env0");
for (int i = 1; env != null; i++) {
if (env.startsWith("MOZ_PROFILER_STARTUP=")) {
if (!env.endsWith("=")) {
@ -1123,8 +1124,7 @@ public abstract class GeckoApp
* and other one-shot constructions.
**/
@Override
public void onCreate(Bundle savedInstanceState)
{
public void onCreate(Bundle savedInstanceState) {
GeckoAppShell.ensureCrashHandling();
// Enable Android Strict Mode for developers' local builds (the "default" channel).
@ -1136,9 +1136,9 @@ public abstract class GeckoApp
mJavaUiStartupTimer = new Telemetry.UptimeTimer("FENNEC_STARTUP_TIME_JAVAUI");
mGeckoReadyStartupTimer = new Telemetry.UptimeTimer("FENNEC_STARTUP_TIME_GECKOREADY");
final Intent intent = getIntent();
final SafeIntent intent = new SafeIntent(getIntent());
final String action = intent.getAction();
final String args = StringUtils.getStringExtra(intent, "args");
final String args = intent.getStringExtra("args");
earlyStartJavaSampler(intent);
@ -1254,7 +1254,7 @@ public abstract class GeckoApp
}, 1000 * 5 /* 5 seconds */);
}
Bundle stateBundle = getIntent().getBundleExtra(EXTRA_STATE_BUNDLE);
Bundle stateBundle = ContextUtils.getBundleExtra(getIntent(), EXTRA_STATE_BUNDLE);
if (stateBundle != null) {
// Use the state bundle if it was given as an intent extra. This is
// only intended to be used internally via Robocop, so a boolean
@ -1458,18 +1458,21 @@ public abstract class GeckoApp
private void initialize() {
mInitialized = true;
Intent intent = getIntent();
String action = intent.getAction();
final SafeIntent intent = new SafeIntent(getIntent());
final String action = intent.getAction();
String passedUri = null;
final String uri = getURIFromIntent(intent);
final String passedUri;
if (!TextUtils.isEmpty(uri)) {
passedUri = uri;
} else {
passedUri = null;
}
final boolean isExternalURL = passedUri != null &&
!AboutPages.isAboutHome(passedUri);
StartupAction startupAction;
final StartupAction startupAction;
if (isExternalURL) {
startupAction = StartupAction.URL;
} else {
@ -1532,7 +1535,7 @@ public abstract class GeckoApp
if (ACTION_LAUNCH_SETTINGS.equals(action)) {
Intent settingsIntent = new Intent(GeckoApp.this, GeckoPreferences.class);
// Copy extras.
settingsIntent.putExtras(intent);
settingsIntent.putExtras(intent.getUnsafe());
startActivity(settingsIntent);
}
@ -1732,7 +1735,7 @@ public abstract class GeckoApp
}
private boolean getRestartFromIntent() {
return getIntent().getBooleanExtra("didRestart", false);
return ContextUtils.getBooleanExtra(getIntent(), "didRestart", false);
}
/**
@ -1798,7 +1801,7 @@ public abstract class GeckoApp
AppConstants.USER_AGENT_FENNEC_MOBILE;
}
private void processAlertCallback(Intent intent) {
private void processAlertCallback(SafeIntent intent) {
String alertName = "";
String alertCookie = "";
Uri data = intent.getData();
@ -1814,7 +1817,9 @@ public abstract class GeckoApp
}
@Override
protected void onNewIntent(Intent intent) {
protected void onNewIntent(Intent externalIntent) {
final SafeIntent intent = new SafeIntent(externalIntent);
if (GeckoThread.checkLaunchState(GeckoThread.LaunchState.GeckoExiting)) {
// We're exiting and shouldn't try to do anything else. In the case
// where we are hung while exiting, we should force the process to exit.
@ -1825,7 +1830,7 @@ public abstract class GeckoApp
// if we were previously OOM killed, we can end up here when launching
// from external shortcuts, so set this as the intent for initialization
if (!mInitialized) {
setIntent(intent);
setIntent(externalIntent);
return;
}
@ -1859,7 +1864,7 @@ public abstract class GeckoApp
// Check if launched from data reporting notification.
Intent settingsIntent = new Intent(GeckoApp.this, GeckoPreferences.class);
// Copy extras.
settingsIntent.putExtras(intent);
settingsIntent.putExtras(intent.getUnsafe());
startActivity(settingsIntent);
}
}
@ -1868,7 +1873,7 @@ public abstract class GeckoApp
* Handles getting a URI from an intent in a way that is backwards-
* compatible with our previous implementations.
*/
protected String getURIFromIntent(Intent intent) {
protected String getURIFromIntent(SafeIntent intent) {
final String action = intent.getAction();
if (ACTION_ALERT_CALLBACK.equals(action) || NotificationHelper.HELPER_BROADCAST_ACTION.equals(action)) {
return null;

View File

@ -25,27 +25,24 @@ import java.util.Locale;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Queue;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import org.json.JSONException;
import org.json.JSONObject;
import org.mozilla.gecko.AppConstants.Versions;
import org.mozilla.gecko.favicons.OnFaviconLoadedListener;
import org.mozilla.gecko.favicons.decoders.FaviconDecoder;
import org.mozilla.gecko.gfx.BitmapUtils;
import org.mozilla.gecko.gfx.LayerView;
import org.mozilla.gecko.gfx.PanZoomController;
import org.mozilla.gecko.mozglue.ContextUtils;
import org.mozilla.gecko.mozglue.GeckoLoader;
import org.mozilla.gecko.mozglue.JNITarget;
import org.mozilla.gecko.mozglue.RobocopTarget;
import org.mozilla.gecko.mozglue.generatorannotations.OptionalGeneratedParameter;
import org.mozilla.gecko.mozglue.generatorannotations.WrapElementForJNI;
import org.mozilla.gecko.prompts.PromptService;
import org.mozilla.gecko.SmsManager;
import org.mozilla.gecko.util.EventCallback;
import org.mozilla.gecko.util.GeckoRequest;
import org.mozilla.gecko.util.HardwareUtils;
@ -53,7 +50,6 @@ import org.mozilla.gecko.util.NativeEventListener;
import org.mozilla.gecko.util.NativeJSContainer;
import org.mozilla.gecko.util.NativeJSObject;
import org.mozilla.gecko.util.ProxySelector;
import org.mozilla.gecko.util.StringUtils;
import org.mozilla.gecko.util.ThreadUtils;
import android.app.Activity;
@ -2519,7 +2515,7 @@ public class GeckoAppShell
/* Downloads the URI pointed to by a share intent, and alters the intent to point to the locally stored file.
*/
public static void downloadImageForIntent(final Intent intent) {
final String src = StringUtils.getStringExtra(intent, Intent.EXTRA_TEXT);
final String src = ContextUtils.getStringExtra(intent, Intent.EXTRA_TEXT);
if (src == null) {
showImageShareFailureToast();
return;

View File

@ -5,17 +5,17 @@
package org.mozilla.gecko;
import org.mozilla.gecko.gfx.BitmapUtils;
import org.mozilla.gecko.util.GeckoEventListener;
import org.mozilla.gecko.util.StringUtils;
import java.util.HashMap;
import java.util.Iterator;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.mozilla.gecko.gfx.BitmapUtils;
import org.mozilla.gecko.mozglue.ContextUtils.SafeIntent;
import org.mozilla.gecko.util.GeckoEventListener;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.IntentFilter;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
@ -23,9 +23,6 @@ import android.net.Uri;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import java.util.Iterator;
import java.util.HashMap;
public final class NotificationHelper implements GeckoEventListener {
public static final String HELPER_BROADCAST_ACTION = AppConstants.ANDROID_PACKAGE_NAME + ".helperBroadcastAction";
@ -110,7 +107,7 @@ public final class NotificationHelper implements GeckoEventListener {
return i.getBooleanExtra(HELPER_NOTIFICATION, false);
}
public void handleNotificationIntent(Intent i) {
public void handleNotificationIntent(SafeIntent i) {
final Uri data = i.getData();
if (data == null) {
Log.e(LOGTAG, "handleNotificationEvent: empty data");
@ -137,7 +134,7 @@ public final class NotificationHelper implements GeckoEventListener {
// The handler and cookie parameters are optional.
final String handler = data.getQueryParameter(HANDLER_ATTR);
final String cookie = StringUtils.getStringExtra(i, COOKIE_ATTR);
final String cookie = i.getStringExtra(COOKIE_ATTR);
try {
args.put(ID_ATTR, id);

View File

@ -25,7 +25,7 @@ import android.util.Log;
public class RestrictedProfiles {
private static final String LOGTAG = "GeckoRestrictedProfiles";
private static Boolean inGuest = null;
private static volatile Boolean inGuest = null;
@SuppressWarnings("serial")
private static final List<String> BANNED_SCHEMES = new ArrayList<String>() {{
@ -36,6 +36,16 @@ public class RestrictedProfiles {
add("wyciwyg");
}};
/**
* This is a hack to allow non-GeckoApp activities to safely call into
* RestrictedProfiles without reworking this class or GeckoProfile.
*
* It can be removed after Bug 1077590 lands.
*/
public static void initWithProfile(GeckoProfile profile) {
inGuest = profile.inGuestMode();
}
private static boolean getInGuest() {
if (inGuest == null) {
inGuest = GeckoAppShell.getGeckoInterface().getProfile().inGuestMode();
@ -86,9 +96,8 @@ public class RestrictedProfiles {
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
@RobocopTarget
private static Bundle getRestrictions() {
final UserManager mgr = (UserManager) GeckoAppShell.getContext().getSystemService(Context.USER_SERVICE);
private static Bundle getRestrictions(final Context context) {
final UserManager mgr = (UserManager) context.getSystemService(Context.USER_SERVICE);
return mgr.getUserRestrictions();
}
@ -101,17 +110,17 @@ public class RestrictedProfiles {
*
* Returns true otherwise.
*/
private static boolean getRestriction(final String name) {
private static boolean getRestriction(final Context context, final String name) {
// Early versions don't support restrictions at all,
// so no action can be restricted.
if (Versions.preJBMR2) {
return false;
}
return getRestrictions().getBoolean(name, false);
return getRestrictions(context).getBoolean(name, false);
}
private static boolean canLoadUrl(final String url) {
private static boolean canLoadUrl(final Context context, final String url) {
// Null URLs are always permitted.
if (url == null) {
return true;
@ -120,7 +129,7 @@ public class RestrictedProfiles {
try {
// If we're not in guest mode, and the system restriction isn't in place, everything is allowed.
if (!getInGuest() &&
!getRestriction(Restriction.DISALLOW_BROWSE_FILES.name)) {
!getRestriction(context, Restriction.DISALLOW_BROWSE_FILES.name)) {
return true;
}
} catch (IllegalArgumentException ex) {
@ -145,6 +154,10 @@ public class RestrictedProfiles {
@WrapElementForJNI
public static boolean isUserRestricted() {
return isUserRestricted(GeckoAppShell.getContext());
}
private static boolean isUserRestricted(final Context context) {
// Guest mode is supported in all Android versions.
if (getInGuest()) {
return true;
@ -154,15 +167,19 @@ public class RestrictedProfiles {
return false;
}
return !getRestrictions().isEmpty();
return !getRestrictions(context).isEmpty();
}
public static boolean isAllowed(Restriction action) {
return isAllowed(action.id, null);
public static boolean isAllowed(final Context context, final Restriction action) {
return isAllowed(context, action.id, null);
}
@WrapElementForJNI
public static boolean isAllowed(int action, String url) {
return isAllowed(GeckoAppShell.getContext(), action, url);
}
private static boolean isAllowed(final Context context, int action, String url) {
final Restriction restriction;
try {
restriction = geckoActionToRestriction(action);
@ -175,7 +192,7 @@ public class RestrictedProfiles {
if (getInGuest()) {
if (Restriction.DISALLOW_BROWSE_FILES == restriction) {
return canLoadUrl(url);
return canLoadUrl(context, url);
}
// Guest users can't do anything.
@ -183,11 +200,15 @@ public class RestrictedProfiles {
}
// NOTE: Restrictions hold the opposite intention, so we need to flip it.
return !getRestriction(restriction.name);
return !getRestriction(context, restriction.name);
}
@WrapElementForJNI
public static String getUserRestrictions() {
return getUserRestrictions(GeckoAppShell.getContext());
}
private static String getUserRestrictions(final Context context) {
// Guest mode is supported in all Android versions
if (getInGuest()) {
StringBuilder builder = new StringBuilder("{ ");
@ -205,7 +226,7 @@ public class RestrictedProfiles {
}
final JSONObject json = new JSONObject();
final Bundle restrictions = getRestrictions();
final Bundle restrictions = getRestrictions(context);
final Set<String> keys = restrictions.keySet();
for (String key : keys) {

View File

@ -338,9 +338,12 @@ public class LoadFaviconTask {
// Attempt to decode the favicon URL as a data URL. We don't bother storing such URIs in
// the database: the cost of decoding them here probably doesn't exceed the cost of mucking
// about with the DB.
LoadFaviconResult uriBitmaps = FaviconDecoder.decodeDataURI(faviconURL);
if (uriBitmaps != null) {
return pushToCacheAndGetResult(uriBitmaps);
final boolean isEmpty = TextUtils.isEmpty(faviconURL);
if (!isEmpty) {
LoadFaviconResult uriBitmaps = FaviconDecoder.decodeDataURI(faviconURL);
if (uriBitmaps != null) {
return pushToCacheAndGetResult(uriBitmaps);
}
}
String storedFaviconUrl;
@ -348,7 +351,7 @@ public class LoadFaviconTask {
// Handle the case of malformed favicon URL.
// If favicon is empty, fall back to the stored one.
if (TextUtils.isEmpty(faviconURL)) {
if (isEmpty) {
// Try to get the favicon URL from the memory cache.
storedFaviconUrl = Favicons.getFaviconURLForPageURLFromCache(pageUrl);

View File

@ -85,7 +85,7 @@ class HomeConfigPrefsBackend implements HomeConfigBackend {
// We disable Synced Tabs for guest mode profiles.
final PanelConfig remoteTabsEntry;
if (RestrictedProfiles.isAllowed(RestrictedProfiles.Restriction.DISALLOW_MODIFY_ACCOUNTS)) {
if (RestrictedProfiles.isAllowed(mContext, RestrictedProfiles.Restriction.DISALLOW_MODIFY_ACCOUNTS)) {
remoteTabsEntry = createBuiltinPanelConfig(mContext, PanelType.REMOTE_TABS);
} else {
remoteTabsEntry = null;

View File

@ -27,6 +27,7 @@ resjar.javac_flags += ['-Xlint:all']
mgjar = add_java_jar('gecko-mozglue')
mgjar.sources += [
'mozglue/ByteBufferInputStream.java',
'mozglue/ContextUtils.java',
'mozglue/DirectBufferAllocator.java',
'mozglue/generatorannotations/OptionalGeneratedParameter.java',
'mozglue/generatorannotations/WrapElementForJNI.java',

View File

@ -0,0 +1,102 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko.mozglue;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
public class ContextUtils {
private static final String LOGTAG = "GeckoContextUtils";
public static Bundle getBundleExtra(final Intent intent, final String name) {
return new SafeIntent(intent).getBundleExtra(name);
}
public static String getStringExtra(final Intent intent, final String name) {
return new SafeIntent(intent).getStringExtra(name);
}
public static boolean getBooleanExtra(Intent intent, String name, boolean defaultValue) {
return new SafeIntent(intent).getBooleanExtra(name, defaultValue);
}
public static class SafeIntent {
private final Intent intent;
public SafeIntent(final Intent intent) {
this.intent = intent;
}
public boolean getBooleanExtra(final String name, final boolean defaultValue) {
try {
return intent.getBooleanExtra(name, defaultValue);
} catch (OutOfMemoryError e) {
Log.w(LOGTAG, "Couldn't get intent extras: OOM. Malformed?");
return defaultValue;
} catch (RuntimeException e) {
Log.w(LOGTAG, "Couldn't get intent extras.", e);
return defaultValue;
}
}
public String getStringExtra(final String name) {
try {
return intent.getStringExtra(name);
} catch (OutOfMemoryError e) {
Log.w(LOGTAG, "Couldn't get intent extras: OOM. Malformed?");
return null;
} catch (RuntimeException e) {
Log.w(LOGTAG, "Couldn't get intent extras.", e);
return null;
}
}
public Bundle getBundleExtra(final String name) {
try {
return intent.getBundleExtra(name);
} catch (OutOfMemoryError e) {
Log.w(LOGTAG, "Couldn't get intent extras: OOM. Malformed?");
return null;
} catch (RuntimeException e) {
Log.w(LOGTAG, "Couldn't get intent extras.", e);
return null;
}
}
public String getAction() {
return intent.getAction();
}
public String getDataString() {
try {
return intent.getDataString();
} catch (OutOfMemoryError e) {
Log.w(LOGTAG, "Couldn't get intent data string: OOM. Malformed?");
return null;
} catch (RuntimeException e) {
Log.w(LOGTAG, "Couldn't get intent data string.", e);
return null;
}
}
public Uri getData() {
try {
return intent.getData();
} catch (OutOfMemoryError e) {
Log.w(LOGTAG, "Couldn't get intent data: OOM. Malformed?");
return null;
} catch (RuntimeException e) {
Log.w(LOGTAG, "Couldn't get intent data.", e);
return null;
}
}
public Intent getUnsafe() {
return intent;
}
}
}

View File

@ -22,6 +22,8 @@ import android.os.Build;
import android.os.Environment;
import android.util.Log;
import org.mozilla.gecko.mozglue.ContextUtils.SafeIntent;
public final class GeckoLoader {
private static final String LOGTAG = "GeckoLoader";
@ -29,7 +31,7 @@ public final class GeckoLoader {
private static final String ANDROID_PACKAGE_NAME = "@ANDROID_PACKAGE_NAME@";
private static final String MOZ_APP_ABI = "@MOZ_APP_ABI@";
private static volatile Intent sIntent;
private static volatile SafeIntent sIntent;
private static File sCacheFile;
private static File sGREDir;
@ -123,14 +125,14 @@ public final class GeckoLoader {
return tmpDir;
}
public static void setLastIntent(Intent intent) {
public static void setLastIntent(SafeIntent intent) {
sIntent = intent;
}
public static void setupGeckoEnvironment(Context context, String[] pluginDirs, String profilePath) {
// if we have an intent (we're being launched by an activity)
// read in any environmental variables from it here
final Intent intent = sIntent;
final SafeIntent intent = sIntent;
if (intent != null) {
String env = intent.getStringExtra("env0");
Log.d(LOGTAG, "Gecko environment env0: " + env);

View File

@ -19,8 +19,8 @@ import org.mozilla.gecko.overlays.service.sharemethods.ParcelableClientRecord;
import org.mozilla.gecko.overlays.service.sharemethods.SendTab;
import org.mozilla.gecko.overlays.service.sharemethods.ShareMethod;
import org.mozilla.gecko.sync.setup.activities.WebURLFinder;
import org.mozilla.gecko.mozglue.ContextUtils;
import org.mozilla.gecko.util.HardwareUtils;
import org.mozilla.gecko.util.StringUtils;
import org.mozilla.gecko.util.ThreadUtils;
import org.mozilla.gecko.util.UIAsyncTask;
@ -121,7 +121,7 @@ public class ShareDialog extends LocaleAware.LocaleAwareActivity implements Send
final Resources resources = getResources();
// The URL is usually hiding somewhere in the extra text. Extract it.
final String extraText = StringUtils.getStringExtra(intent, Intent.EXTRA_TEXT);
final String extraText = ContextUtils.getStringExtra(intent, Intent.EXTRA_TEXT);
if (TextUtils.isEmpty(extraText)) {
abortDueToNoURL();
return;

View File

@ -26,7 +26,7 @@ class AndroidImportPreference extends MultiPrefMultiChoicePreference {
public static class Handler implements GeckoPreferences.PrefHandler {
public boolean setupPref(Context context, Preference pref) {
return RestrictedProfiles.isAllowed(Restriction.DISALLOW_IMPORT_SETTINGS);
return RestrictedProfiles.isAllowed(context, Restriction.DISALLOW_IMPORT_SETTINGS);
}
public void onChange(Context context, Preference pref, Object newValue) { }

View File

@ -296,6 +296,9 @@ OnSharedPreferenceChangeListener
@Override
protected void onCreate(Bundle savedInstanceState) {
// Make sure RestrictedProfiles is ready.
RestrictedProfiles.initWithProfile(GeckoProfile.get(this));
if (GeckoProfile.get(this).inGuestMode()) {
GuestSession.configureWindow(getWindow());
}
@ -700,7 +703,7 @@ OnSharedPreferenceChangeListener
i--;
continue;
} else if (PREFS_DEVTOOLS_REMOTE_ENABLED.equals(key)) {
if (!RestrictedProfiles.isAllowed(RestrictedProfiles.Restriction.DISALLOW_REMOTE_DEBUGGING)) {
if (!RestrictedProfiles.isAllowed(this, RestrictedProfiles.Restriction.DISALLOW_REMOTE_DEBUGGING)) {
preferences.removePreference(pref);
i--;
continue;
@ -728,7 +731,7 @@ OnSharedPreferenceChangeListener
listPref.setSummary(selectedEntry);
continue;
} else if (PREFS_SYNC.equals(key) &&
!RestrictedProfiles.isAllowed(RestrictedProfiles.Restriction.DISALLOW_MODIFY_ACCOUNTS)) {
!RestrictedProfiles.isAllowed(this, RestrictedProfiles.Restriction.DISALLOW_MODIFY_ACCOUNTS)) {
// Don't show sync prefs while in guest mode.
preferences.removePreference(pref);
i--;

View File

@ -183,7 +183,7 @@ public class TabsPanel extends LinearLayout
mTabWidget.addTab(R.drawable.tabs_normal, R.string.tabs_normal);
mTabWidget.addTab(R.drawable.tabs_private, R.string.tabs_private);
if (RestrictedProfiles.isAllowed(RestrictedProfiles.Restriction.DISALLOW_MODIFY_ACCOUNTS)) {
if (RestrictedProfiles.isAllowed(mContext, RestrictedProfiles.Restriction.DISALLOW_MODIFY_ACCOUNTS)) {
// The initial icon is not the animated icon, because on Android
// 4.4.2, the animation starts immediately (and can start at other
// unpredictable times). See Bug 1015974.

View File

@ -104,6 +104,7 @@ skip-if = android_version == "10"
[testBrowserDiscovery]
[testDebuggerServer]
[testDeviceSearchEngine]
[testFilePicker]
[testJNI]
# [testMozPay] # see bug 945675
[testNetworkManager]

View File

@ -0,0 +1,52 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko.tests;
import static org.mozilla.gecko.tests.helpers.AssertionHelper.fFail;
import org.mozilla.gecko.EventDispatcher;
import org.mozilla.gecko.GeckoAppShell;
import org.mozilla.gecko.GeckoEvent;
import org.mozilla.gecko.util.GeckoEventListener;
import org.json.JSONException;
import org.json.JSONObject;
public class testFilePicker extends JavascriptTest implements GeckoEventListener {
private static final String TEST_FILENAME = "/mnt/sdcard/my-favorite-martian.png";
public testFilePicker() {
super("testFilePicker.js");
}
@Override
public void handleMessage(String event, final JSONObject message) {
// We handle the FilePicker message here so we can send back hard coded file information. We
// don't want to try to emulate "picking" a file using the Android intent chooser.
if (event.equals("FilePicker:Show")) {
try {
message.put("file", TEST_FILENAME);
} catch (JSONException ex) {
fFail("Can't add filename to message " + TEST_FILENAME);
}
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("FilePicker:Result", message.toString()));
}
}
@Override
public void setUp() throws Exception {
super.setUp();
EventDispatcher.getInstance().registerGeckoThreadListener(this, "FilePicker:Show");
}
@Override
public void tearDown() throws Exception {
super.tearDown();
EventDispatcher.getInstance().unregisterGeckoThreadListener(this, "FilePicker:Show");
}
}

View File

@ -0,0 +1,80 @@
// -*- indent-tabs-mode: nil; js-indent-level: 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/. */
"use strict";
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
Cu.import("resource://gre/modules/Services.jsm");
function ok(passed, text) {
do_report_result(passed, text, Components.stack.caller, false);
}
function is(lhs, rhs, text) {
do_report_result(lhs === rhs, text, Components.stack.caller, false);
}
add_test(function filepicker_open() {
let chromeWin = Services.wm.getMostRecentWindow("navigator:browser");
do_test_pending();
let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
fp.appendFilter("Martian files", "*.martian");
fp.appendFilters(Ci.nsIFilePicker.filterAll);
fp.filterIndex = 0;
let fpCallback = function(result) {
if (result == Ci.nsIFilePicker.returnOK || result == Ci.nsIFilePicker.returnReplace) {
do_print("File: " + fp.file.path);
is(fp.file.path, "/mnt/sdcard/my-favorite-martian.png", "Retrieve the right martian file!");
let files = fp.files;
while (files.hasMoreElements()) {
let file = files.getNext().QueryInterface(Ci.nsIFile);
do_print("File: " + file.path);
is(file.path, "/mnt/sdcard/my-favorite-martian.png", "Retrieve the right martian file from array!");
}
do_print("DOMFile: " + fp.domfile.mozFullPath);
is(fp.domfile.mozFullPath, "/mnt/sdcard/my-favorite-martian.png", "Retrieve the right martian domfile!");
let domfiles = fp.domfiles;
while (domfiles.hasMoreElements()) {
let domfile = domfiles.getNext();
do_print("DOMFile: " + domfile.mozFullPath);
is(domfile.mozFullPath, "/mnt/sdcard/my-favorite-martian.png", "Retrieve the right martian file from domfile array!");
}
do_test_finished();
run_next_test();
}
};
try {
fp.init(chromeWin, "Open", Ci.nsIFilePicker.modeOpen);
} catch(ex) {
ok(false, "Android should support FilePicker.modeOpen: " + ex);
}
fp.open(fpCallback);
});
add_test(function filepicker_save() {
let failed = false;
let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
try {
fp.init(null, "Save", Ci.nsIFilePicker.modeSave);
} catch(ex) {
failed = true;
}
ok(failed, "Android does not support FilePicker.modeSave");
run_next_test();
});
run_next_test();

View File

@ -5,10 +5,8 @@
package org.mozilla.gecko.util;
import android.content.Intent;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;
public class StringUtils {
private static final String LOGTAG = "GeckoStringUtils";
@ -189,16 +187,4 @@ public class StringUtils {
public static String encodeUserEnteredUrl(String url) {
return Uri.fromParts("user-entered", url, null).toString();
}
public static String getStringExtra(Intent intent, String name) {
try {
return intent.getStringExtra(name);
} catch (android.os.BadParcelableException ex) {
Log.w(LOGTAG, "Couldn't get string extra: malformed intent.");
return null;
} catch (RuntimeException re) {
Log.w(LOGTAG, "Couldn't get string extra.", re);
return null;
}
}
}

View File

@ -18,6 +18,7 @@ import org.mozilla.gecko.GeckoThread;
import org.mozilla.gecko.R;
import org.mozilla.gecko.Tab;
import org.mozilla.gecko.Tabs;
import org.mozilla.gecko.mozglue.ContextUtils.SafeIntent;
import org.mozilla.gecko.util.NativeJSObject;
import org.mozilla.gecko.webapp.InstallHelper.InstallCallback;
@ -157,7 +158,7 @@ public class WebappImpl extends GeckoApp implements InstallCallback {
}
@Override
protected String getURIFromIntent(Intent intent) {
protected String getURIFromIntent(SafeIntent intent) {
String uri = super.getURIFromIntent(intent);
if (uri != null) {
return uri;

View File

@ -76,7 +76,7 @@ var WebcompatReporter = {
},
reportIssue: function(url) {
let webcompatURL = new URL("http://webcompat.com/");
let webcompatURL = new URL("https://webcompat.com/");
webcompatURL.searchParams.append("open", "1");
webcompatURL.searchParams.append("url", url);
if (PrivateBrowsingUtils.isBrowserPrivate(BrowserApp.selectedTab.browser)) {

View File

@ -146,8 +146,10 @@ FilePicker.prototype = {
return null;
}
if (this._domWin) {
return new this._domWin.File(f);
let win = this._domWin;
if (win) {
let utils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
return utils.wrapDOMFile(f);
}
return new File(f);
@ -213,7 +215,6 @@ FilePicker.prototype = {
let msg = {
type: "FilePicker:Show",
guid: this.guid,
guid: this.guid,
title: this._title,
};

View File

@ -23,7 +23,7 @@
<content>
<xul:button label="&print.label;" accesskey="&print.accesskey;"
oncommand="PrintUtils.print();" icon="print"/>
oncommand="this.parentNode.print();" icon="print"/>
<xul:button label="&pageSetup.label;" accesskey="&pageSetup.accesskey;"
oncommand="this.parentNode.doPageSetup();"/>
@ -93,7 +93,7 @@
<xul:data value="&customPrompt.title;"/>
</content>
<implementation>
<implementation implements="nsIMessageListener">
<field name="mPrintButton">
document.getAnonymousNodes(this)[0]
</field>
@ -125,16 +125,24 @@
</field>
<field name="mWebProgress">
</field>
<constructor>
<![CDATA[
var print = PrintUtils.getPrintPreview();
this.mTotalPages.value = print.printPreviewNumPages;
this.mPageTextBox.max = print.printPreviewNumPages;
<field name="mPPBrowser">
null
</field>
<field name="mMessageManager">
null
</field>
this.updateToolbar();
]]>
</constructor>
<method name="initialize">
<parameter name="aPPBrowser"/>
<body>
<![CDATA[
this.mPPBrowser = aPPBrowser;
this.mMessageManager = aPPBrowser.messageManager;
this.mMessageManager.addMessageListener("Printing:Preview:UpdatePageCount", this);
this.updateToolbar();
]]>
</body>
</method>
<method name="doPageSetup">
<body>
@ -156,38 +164,47 @@
<parameter name="aPageNum"/>
<parameter name="aHomeOrEnd"/>
<body>
<![CDATA[
var print = PrintUtils.getPrintPreview();
<![CDATA[
const nsIWebBrowserPrint = Components.interfaces.nsIWebBrowserPrint;
let navType, pageNum;
// we use only one of aHomeOrEnd, aDirection, or aPageNum
if (aHomeOrEnd)
{
var homeOrEnd;
if (aHomeOrEnd == "home")
{
homeOrEnd = print.PRINTPREVIEW_HOME;
this.mPageTextBox.value = 1;
if (aHomeOrEnd) {
// We're going to either the very first page ("home"), or the
// very last page ("end").
if (aHomeOrEnd == "home") {
navType = nsIWebBrowserPrint.PRINTPREVIEW_HOME;
this.mPageTextBox.value = 1;
} else {
navType = nsIWebBrowserPrint.PRINTPREVIEW_END;
this.mPageTextBox.value = this.mPageTextBox.max;
}
else
{
homeOrEnd = print.PRINTPREVIEW_END;
this.mPageTextBox.value = print.printPreviewNumPages;
}
print.printPreviewNavigate(homeOrEnd, 0);
}
else if (aDirection)
{
pageNum = 0;
} else if (aDirection) {
// aDirection is either +1 or -1, and allows us to increment
// or decrement our currently viewed page.
this.mPageTextBox.valueNumber += aDirection;
print.printPreviewNavigate(
print.PRINTPREVIEW_GOTO_PAGENUM,
this.mPageTextBox.valueNumber);
}
else
{
print.printPreviewNavigate(
print.PRINTPREVIEW_GOTO_PAGENUM, aPageNum);
navType = nsIWebBrowserPrint.PRINTPREVIEW_GOTO_PAGENUM;
pageNum = this.mPageTextBox.value; // TODO: back to valueNumber?
} else {
// We're going to a specific page (aPageNum)
navType = nsIWebBrowserPrint.PRINTPREVIEW_GOTO_PAGENUM;
pageNum = aPageNum;
}
this.mMessageManager.sendAsyncMessage("Printing:Preview:Navigate", {
navType: navType,
pageNum: pageNum,
});
]]>
</body>
</method>
<method name="print">
<body>
<![CDATA[
let contentWindow = this.mPPBrowser.contentWindowAsCPOW;
PrintUtils.print(contentWindow, this.mPPBrowser);
]]>
</body>
</method>
@ -290,7 +307,6 @@
<method name="updateToolbar">
<body>
<![CDATA[
var print = PrintUtils.getPrintPreview();
var settings = PrintUtils.getPrintSettings();
var isPortrait = settings.orientation == Components.interfaces.nsIPrintSettings.kPortraitOrientation;
@ -304,9 +320,9 @@
this.setScaleCombobox(settings.scaling);
}
this.mTotalPages.value = print.printPreviewNumPages;
this.mPageTextBox.max = print.printPreviewNumPages;
this.mPageTextBox.value = 1;
this.mMessageManager.sendAsyncMessage("Printing:Preview:UpdatePageCount");
]]>
</body>
</method>
@ -320,6 +336,20 @@
PSSVC.savePrintSettingsToPrefs(settings, true, flags);
]]></body>
</method>
<!-- nsIMessageListener -->
<method name="receiveMessage">
<parameter name="message"/>
<body>
<![CDATA[
if (message.name == "Printing:Preview:UpdatePageCount") {
let numPages = message.data.numPages;
this.mTotalPages.value = numPages;
this.mPageTextBox.max = numPages;
}
]]>
</body>
</method>
</implementation>
</binding>

View File

@ -1,29 +1,93 @@
// -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 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/. */
/**
* PrintUtils is a utility for front-end code to trigger common print
* operations (printing, show print preview, show page settings).
*
* Unfortunately, likely due to inconsistencies in how different operating
* systems do printing natively, our XPCOM-level printing interfaces
* are a bit confusing and the method by which we do something basic
* like printing a page is quite circuitous.
*
* To compound that, we need to support remote browsers, and that means
* kicking off the print jobs in the content process. This means we send
* messages back and forth to that process. browser-content.js contains
* the object that listens and responds to the messages that PrintUtils
* sends.
*
* PrintUtils sends messages at different points in its implementation, but
* their documentation is consolidated here for ease-of-access.
*
*
* Messages sent:
*
* Printing:Print
* This message is sent to kick off a print job for a particular content
* window (which is passed along with the message). We also pass print
* settings with this message - though bug 1088070 will have us gather
* those settings from the content process instead.
*
* Printing:Preview:Enter
* This message is sent to put content into print preview mode. We pass
* the content window of the browser we're showing the preview of, and
* the target of the message is the browser that we'll be showing the
* preview in. We also pass print settings in this message, but
* bug 1088070 will have us gather those settings from the content process
* instead.
*
* Printing:Preview:Exit
* This message is sent to take content out of print preview mode.
*
*
* Messages Received
*
* Printing:Preview:Entered
* This message is sent by the content process once it has completed
* putting the content into print preview mode. We must wait for that to
* to complete before switching the chrome UI to print preview mode,
* otherwise we have layout issues.
*
* Printing:Preview:StateChange, Printing:Preview:ProgressChange
* Due to a timing issue resulting in a main-process crash, we have to
* manually open the progress dialog for print preview. The progress
* dialog is opened here in PrintUtils, and then we listen for update
* messages from the child. Bug 1088061 has been filed to investigate
* other solutions.
*
*/
var gPrintSettingsAreGlobal = false;
var gSavePrintSettings = false;
var gFocusedElement = null;
var PrintUtils = {
bailOut: function () {
let remote = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebNavigation)
.QueryInterface(Components.interfaces.nsILoadContext)
.useRemoteTabs;
if (remote) {
let pref = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
let allow_for_testing = false;
try {
allow_for_testing = pref.getBoolPref("print.enable_e10s_testing");
} catch(e) {
// The pref wasn't set, so I guess we're not overriding.
}
if (this.usingRemoteTabs && !allow_for_testing) {
alert("e10s printing is not implemented yet. Bug 927188.");
return true;
}
return false;
},
showPageSetup: function ()
{
/**
* Shows the page setup dialog, and saves any settings changed in
* that dialog if print.save_print_settings is set to true.
*
* @return true on success, false on failure
*/
showPageSetup: function () {
if (this.bailOut()) {
return;
}
@ -45,102 +109,261 @@ var PrintUtils = {
return true;
},
print: function (aWindow)
/**
* Starts printing the contents of aWindow.
*
* @param aWindow
* An nsIDOMWindow to initiate the printing of. If the chrome window
* is not running with remote tabs, this defaults to window.content if
* omitted. If running with remote tabs, the caller must pass in the
* content window to be printed. This function throws if that invariant
* is violated.
* @param aBrowser (optional for non-remote browsers)
* The remote <xul:browser> that contains aWindow. This argument is
* not necessary if aWindow came from a non-remote browser, but is
* strictly required otherwise. This function will throw if aWindow
* comes from a remote browser and aBrowser is not provided.
*/
print: function (aWindow, aBrowser)
{
if (this.bailOut()) {
return;
}
var webBrowserPrint = this.getWebBrowserPrint(aWindow);
var printSettings = this.getPrintSettings();
try {
webBrowserPrint.print(printSettings, null);
if (gPrintSettingsAreGlobal && gSavePrintSettings) {
var PSSVC = Components.classes["@mozilla.org/gfx/printsettings-service;1"]
.getService(Components.interfaces.nsIPrintSettingsService);
PSSVC.savePrintSettingsToPrefs(printSettings, true,
printSettings.kInitSaveAll);
PSSVC.savePrintSettingsToPrefs(printSettings, false,
printSettings.kInitSavePrinterName);
if (!aWindow) {
// If we're using remote browsers, chances are that window.content will
// not be defined.
if (this.usingRemoteTabs) {
throw new Error("Windows running with remote tabs must explicitly pass " +
"a content window to PrintUtils.print.");
}
} catch (e) {
// Pressing cancel is expressed as an NS_ERROR_ABORT return value,
// causing an exception to be thrown which we catch here.
// Unfortunately this will also consume helpful failures, so add a
// dump("print: "+e+"\n"); // if you need to debug
// Otherwise, we should have access to window.content.
aWindow = window.content;
}
if (Cu.isCrossProcessWrapper(aWindow)) {
if (!aBrowser) {
throw new Error("PrintUtils.print expects a remote browser passed as " +
"an argument if the content window is a CPOW.");
}
} else {
// For content windows coming from non-remote browsers, the browser can
// be resolved as the chromeEventHandler.
aBrowser = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell)
.chromeEventHandler;
}
if (!aBrowser) {
throw new Error("PrintUtils.print could not resolve content window " +
"to a browser.");
}
let printSettings = this.getPrintSettings();
let mm = aBrowser.messageManager;
mm.sendAsyncMessage("Printing:Print", null, {
printSettings: printSettings,
contentWindow: aWindow,
});
},
// If aCallback is not null, it must be an object which has the following methods:
// getPrintPreviewBrowser(), getSourceBrowser(),
// getNavToolbox(), onEnter() and onExit().
// If aCallback is null, then printPreview must previously have been called with
// non-null aCallback and that object will be reused.
printPreview: function (aCallback)
/**
* Initializes print preview.
*
* @param aListenerObj
* An object that defines the following functions:
*
* getPrintPreviewBrowser:
* Returns the <xul:browser> to display the print preview in.
*
* getSourceBrowser:
* Returns the <xul:browser> that contains the document being
* printed.
*
* getNavToolbox:
* Returns the primary toolbox for this window.
*
* onEnter:
* Called upon entering print preview.
*
* onExit:
* Called upon exiting print preview.
*
* These methods must be defined. printPreview can be called
* with aListenerObj as null iff this window is already displaying
* print preview (in which case, the previous aListenerObj passed
* to it will be used).
*/
printPreview: function (aListenerObj)
{
if (this.bailOut()) {
return;
}
// if we're already in PP mode, don't set the callback; chances
// if we're already in PP mode, don't set the listener; chances
// are it is null because someone is calling printPreview() to
// get us to refresh the display.
if (!document.getElementById("print-preview-toolbar")) {
this._callback = aCallback;
this._sourceBrowser = aCallback.getSourceBrowser();
this._originalTitle = this._sourceBrowser.contentDocument.title;
if (!this.inPrintPreview) {
this._listener = aListenerObj;
this._sourceBrowser = aListenerObj.getSourceBrowser();
this._originalTitle = this._sourceBrowser.contentTitle;
this._originalURL = this._sourceBrowser.currentURI.spec;
} else {
// collapse the browser here -- it will be shown in
// enterPrintPreview; this forces a reflow which fixes display
// issues in bug 267422.
this._sourceBrowser = this._callback.getPrintPreviewBrowser();
this._sourceBrowser = this._listener.getPrintPreviewBrowser();
this._sourceBrowser.collapsed = true;
}
this._webProgressPP = {};
var ppParams = {};
var notifyOnOpen = {};
var webBrowserPrint = this.getWebBrowserPrint();
var printSettings = this.getPrintSettings();
let ppParams = {};
let notifyOnOpen = {};
let printSettings = this.getPrintSettings();
// Here we get the PrintingPromptService so we can display the PP Progress from script
// For the browser implemented via XUL with the PP toolbar we cannot let it be
// automatically opened from the print engine because the XUL scrollbars in the PP window
// will layout before the content window and a crash will occur.
// Doing it all from script, means it lays out before hand and we can let printing do its own thing
var PPROMPTSVC = Components.classes["@mozilla.org/embedcomp/printingprompt-service;1"]
let PPROMPTSVC = Components.classes["@mozilla.org/embedcomp/printingprompt-service;1"]
.getService(Components.interfaces.nsIPrintingPromptService);
// just in case we are already printing,
// an error code could be returned if the Prgress Dialog is already displayed
// just in case we are already printing,
// an error code could be returned if the Progress Dialog is already displayed
try {
PPROMPTSVC.showProgress(window, webBrowserPrint, printSettings, this._obsPP, false,
PPROMPTSVC.showProgress(window, null, printSettings, this._obsPP, false,
this._webProgressPP, ppParams, notifyOnOpen);
if (ppParams.value) {
ppParams.value.docTitle = this._originalTitle;
ppParams.value.docURL = this._originalURL;
}
// this tells us whether we should continue on with PP or
// this tells us whether we should continue on with PP or
// wait for the callback via the observer
if (!notifyOnOpen.value.valueOf() || this._webProgressPP.value == null)
if (!notifyOnOpen.value.valueOf() || this._webProgressPP.value == null) {
this.enterPrintPreview();
}
} catch (e) {
this.enterPrintPreview();
}
},
/**
* Returns the nsIWebBrowserPrint associated with some content window.
* This method is being kept here for compatibility reasons, but should not
* be called by code hoping to support e10s / remote browsers.
*
* @param aWindow
* The window from which to get the nsIWebBrowserPrint from.
* @return nsIWebBrowserPrint
*/
getWebBrowserPrint: function (aWindow)
{
let Deprecated = Components.utils.import("resource://gre/modules/Deprecated.jsm", {}).Deprecated;
let text = "getWebBrowserPrint is now deprecated, and fully unsupported for " +
"multi-process browsers. Please use a frame script to get " +
"access to nsIWebBrowserPrint from content.";
let url = "https://developer.mozilla.org/en-US/docs/Printing_from_a_XUL_App";
Deprecated.warning(text, url);
if (this.usingRemoteTabs) {
return {};
}
var contentWindow = aWindow || window.content;
return contentWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebBrowserPrint);
},
/**
* Returns the nsIWebBrowserPrint from the print preview browser's docShell.
* This method is being kept here for compatibility reasons, but should not
* be called by code hoping to support e10s / remote browsers.
*
* @return nsIWebBrowserPrint
*/
getPrintPreview: function() {
return this._callback.getPrintPreviewBrowser().docShell.printPreview;
let Deprecated = Components.utils.import("resource://gre/modules/Deprecated.jsm", {}).Deprecated;
let text = "getPrintPreview is now deprecated, and fully unsupported for " +
"multi-process browsers. Please use a frame script to get " +
"access to nsIWebBrowserPrint from content.";
let url = "https://developer.mozilla.org/en-US/docs/Printing_from_a_XUL_App";
Deprecated.warning(text, url);
if (this.usingRemoteTabs) {
return {};
}
return this._listener.getPrintPreviewBrowser().docShell.printPreview;
},
////////////////////////////////////////
// "private" methods. Don't use them. //
////////////////////////////////////////
get inPrintPreview() {
return document.getElementById("print-preview-toolbar") != null;
},
////////////////////////////////////////////////////
// "private" methods and members. Don't use them. //
///////////////////////////////////////////////////
_listener: null,
_closeHandlerPP: null,
_webProgressPP: null,
_sourceBrowser: null,
_originalTitle: "",
_originalURL: "",
get usingRemoteTabs() {
// We memoize this, since it's highly unlikely to change over the lifetime
// of the window.
let usingRemoteTabs =
window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebNavigation)
.QueryInterface(Components.interfaces.nsILoadContext)
.useRemoteTabs;
delete this.usingRemoteTabs;
return this.usingRemoteTabs = usingRemoteTabs;
},
receiveMessage(aMessage) {
if (!this._webProgressPP.value) {
// We somehow didn't get a nsIWebProgressListener to be updated...
// I guess there's nothing to do.
return;
}
let listener = this._webProgressPP.value;
let mm = aMessage.target.messageManager;
let data = aMessage.data;
switch (aMessage.name) {
case "Printing:Preview:ProgressChange": {
return listener.onProgressChange(null, null,
data.curSelfProgress,
data.maxSelfProgress,
data.curTotalProgress,
data.maxTotalProgress);
break;
}
case "Printing:Preview:StateChange": {
if (data.stateFlags & Components.interfaces.nsIWebProgressListener.STATE_STOP) {
// Strangely, the printing engine sends 2 STATE_STOP messages when
// print preview is finishing. One has the STATE_IS_DOCUMENT flag,
// the other has the STATE_IS_NETWORK flag. However, the webProgressPP
// listener stops listening once the first STATE_STOP is sent.
// Any subsequent messages result in NS_ERROR_FAILURE errors getting
// thrown. This should all get torn out once bug 1088061 is fixed.
mm.removeMessageListener("Printing:Preview:StateChange", this);
mm.removeMessageListener("Printing:Preview:ProgressChange", this);
}
return listener.onStateChange(null, null,
data.stateFlags,
data.status);
break;
}
}
},
setPrinterDefaultsForSelectedPrinter: function (aPSSVC, aPrintSettings)
{
@ -178,15 +401,8 @@ var PrintUtils = {
return printSettings;
},
_closeHandlerPP: null,
_webProgressPP: null,
_callback: null,
_sourceBrowser: null,
_originalTitle: "",
_originalURL: "",
// This observer is called once the progress dialog has been "opened"
_obsPP:
_obsPP:
{
observe: function(aSubject, aTopic, aData)
{
@ -199,84 +415,87 @@ var PrintUtils = {
if (iid.equals(Components.interfaces.nsIObserver) ||
iid.equals(Components.interfaces.nsISupportsWeakReference) ||
iid.equals(Components.interfaces.nsISupports))
return this;
return this;
throw Components.results.NS_NOINTERFACE;
}
},
enterPrintPreview: function ()
{
gFocusedElement = document.commandDispatcher.focusedElement;
// Send a message to the print preview browser to initialize
// print preview. If we happen to have gotten a print preview
// progress listener from nsIPrintingPromptService.showProgress
// in printPreview, we add listeners to feed that progress
// listener.
let ppBrowser = this._listener.getPrintPreviewBrowser();
let mm = ppBrowser.messageManager;
let printSettings = this.getPrintSettings();
mm.sendAsyncMessage("Printing:Preview:Enter", null, {
printSettings: printSettings,
contentWindow: this._sourceBrowser.contentWindowAsCPOW,
});
var webBrowserPrint;
var printSettings = this.getPrintSettings();
var originalWindow = this._sourceBrowser.contentWindow;
try {
webBrowserPrint = this.getPrintPreview();
webBrowserPrint.printPreview(printSettings, originalWindow,
this._webProgressPP.value);
} catch (e) {
// Pressing cancel is expressed as an NS_ERROR_ABORT return value,
// causing an exception to be thrown which we catch here.
// Unfortunately this will also consume helpful failures, so add a
// dump(e); // if you need to debug
// Need to call enter and exit so that UI gets back to normal.
this._callback.onEnter();
this._callback.onExit();
return;
if (this._webProgressPP.value) {
mm.addMessageListener("Printing:Preview:StateChange", this);
mm.addMessageListener("Printing:Preview:ProgressChange", this);
}
var printPreviewTB = document.getElementById("print-preview-toolbar");
if (printPreviewTB) {
printPreviewTB.updateToolbar();
var browser = this._callback.getPrintPreviewBrowser();
browser.collapsed = false;
browser.contentWindow.focus();
return;
}
let onEntered = (message) => {
mm.removeMessageListener("Printing:PrintPreview:Entered", onEntered);
// Stash the focused element so that we can return to it after exiting
// print preview.
gFocusedElement = document.commandDispatcher.focusedElement;
// Set the original window as an active window so any mozPrintCallbacks can
// run without delayed setTimeouts.
var docShell = originalWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebNavigation)
.QueryInterface(Components.interfaces.nsIDocShell);
docShell.isActive = true;
let printPreviewTB = document.getElementById("print-preview-toolbar");
if (printPreviewTB) {
printPreviewTB.updateToolbar();
ppBrowser.collapsed = false;
ppBrowser.focus();
return;
}
// show the toolbar after we go into print preview mode so
// that we can initialize the toolbar with total num pages
var XUL_NS =
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
printPreviewTB = document.createElementNS(XUL_NS, "toolbar");
printPreviewTB.setAttribute("printpreview", true);
printPreviewTB.id = "print-preview-toolbar";
printPreviewTB.className = "toolbar-primary";
// Set the original window as an active window so any mozPrintCallbacks can
// run without delayed setTimeouts.
this._sourceBrowser.docShellIsActive = true;
var navToolbox = this._callback.getNavToolbox();
navToolbox.parentNode.insertBefore(printPreviewTB, navToolbox);
// show the toolbar after we go into print preview mode so
// that we can initialize the toolbar with total num pages
const XUL_NS =
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
printPreviewTB = document.createElementNS(XUL_NS, "toolbar");
printPreviewTB.setAttribute("printpreview", true);
printPreviewTB.id = "print-preview-toolbar";
printPreviewTB.className = "toolbar-primary";
// copy the window close handler
if (document.documentElement.hasAttribute("onclose"))
this._closeHandlerPP = document.documentElement.getAttribute("onclose");
else
this._closeHandlerPP = null;
document.documentElement.setAttribute("onclose", "PrintUtils.exitPrintPreview(); return false;");
let navToolbox = this._listener.getNavToolbox();
navToolbox.parentNode.insertBefore(printPreviewTB, navToolbox);
printPreviewTB.initialize(ppBrowser);
// disable chrome shortcuts...
window.addEventListener("keydown", this.onKeyDownPP, true);
window.addEventListener("keypress", this.onKeyPressPP, true);
// copy the window close handler
if (document.documentElement.hasAttribute("onclose"))
this._closeHandlerPP = document.documentElement.getAttribute("onclose");
else
this._closeHandlerPP = null;
document.documentElement.setAttribute("onclose", "PrintUtils.exitPrintPreview(); return false;");
var browser = this._callback.getPrintPreviewBrowser();
browser.collapsed = false;
browser.contentWindow.focus();
// disable chrome shortcuts...
window.addEventListener("keydown", this.onKeyDownPP, true);
window.addEventListener("keypress", this.onKeyPressPP, true);
// on Enter PP Call back
this._callback.onEnter();
ppBrowser.collapsed = false;
ppBrowser.focus();
// on Enter PP Call back
this._listener.onEnter();
};
mm.addMessageListener("Printing:Preview:Entered", onEntered);
},
exitPrintPreview: function ()
{
let ppBrowser = this._listener.getPrintPreviewBrowser();
let browserMM = ppBrowser.messageManager;
browserMM.sendAsyncMessage("Printing:Preview:Exit");
window.removeEventListener("keydown", this.onKeyDownPP, true);
window.removeEventListener("keypress", this.onKeyPressPP, true);
@ -284,14 +503,11 @@ var PrintUtils = {
document.documentElement.setAttribute("onclose", this._closeHandlerPP);
this._closeHandlerPP = null;
var webBrowserPrint = this.getPrintPreview();
webBrowserPrint.exitPrintPreview();
// remove the print preview toolbar
var printPreviewTB = document.getElementById("print-preview-toolbar");
this._callback.getNavToolbox().parentNode.removeChild(printPreviewTB);
let printPreviewTB = document.getElementById("print-preview-toolbar");
this._listener.getNavToolbox().parentNode.removeChild(printPreviewTB);
var fm = Components.classes["@mozilla.org/focus-manager;1"]
let fm = Components.classes["@mozilla.org/focus-manager;1"]
.getService(Components.interfaces.nsIFocusManager);
if (gFocusedElement)
fm.setFocus(gFocusedElement, fm.FLAG_NOSCROLL);
@ -299,7 +515,7 @@ var PrintUtils = {
window.content.focus();
gFocusedElement = null;
this._callback.onExit();
this._listener.onExit();
},
onKeyDownPP: function (aEvent)
@ -329,7 +545,7 @@ var PrintUtils = {
var printKey = document.getElementById("printKb").getAttribute("key").toUpperCase();
var pressedKey = String.fromCharCode(aEvent.charCode).toUpperCase();
if (printKey == pressedKey) {
PrintUtils.print();
printPreviewTB.print();
}
}
// cancel shortkeys

View File

@ -6,8 +6,10 @@
let Cc = Components.classes;
let Ci = Components.interfaces;
let Cu = Components.utils;
let Cr = Components.results;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
var global = this;
@ -353,3 +355,130 @@ PopupBlocking.init();
// Set up console.* for frame scripts.
let Console = Components.utils.import("resource://gre/modules/devtools/Console.jsm", {});
this.console = new Console.ConsoleAPI();
let Printing = {
// Bug 1088061: nsPrintEngine's DoCommonPrint currently expects the
// progress listener passed to it to QI to an nsIPrintingPromptService
// in order to know that a printing progress dialog has been shown. That's
// really all the interface is used for, hence the fact that I don't actually
// implement the interface here. Bug 1088061 has been filed to remove
// this hackery.
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
Ci.nsIPrintingPromptService]),
MESSAGES: [
"Printing:Preview:Enter",
"Printing:Preview:Exit",
"Printing:Preview:Navigate",
"Printing:Preview:UpdatePageCount",
"Printing:Print",
],
init() {
this.MESSAGES.forEach(msgName => addMessageListener(msgName, this));
},
receiveMessage(message) {
let objects = message.objects;
let data = message.data;
switch(message.name) {
case "Printing:Preview:Enter": {
this.enterPrintPreview(objects.printSettings, objects.contentWindow);
break;
}
case "Printing:Preview:Exit": {
this.exitPrintPreview();
break;
}
case "Printing:Preview:Navigate": {
this.navigate(data.navType, data.pageNum);
break;
}
case "Printing:Preview:UpdatePageCount": {
this.updatePageCount();
break;
}
case "Printing:Print": {
this.print(objects.printSettings, objects.contentWindow);
break;
}
}
},
enterPrintPreview(printSettings, contentWindow) {
// Bug 1088070 - we should instantiate nsIPrintSettings here in the
// content script instead of passing it down as a CPOW.
if (Cu.isCrossProcessWrapper(printSettings)) {
printSettings = null;
}
// We have to wait for the print engine to finish reflowing all of the
// documents and subdocuments before we can tell the parent to flip to
// the print preview UI - otherwise, the print preview UI might ask for
// information (like the number of pages in the document) before we have
// our PresShells set up.
addEventListener("printPreviewUpdate", function onPrintPreviewReady() {
removeEventListener("printPreviewUpdate", onPrintPreviewReady);
sendAsyncMessage("Printing:Preview:Entered");
});
docShell.printPreview.printPreview(printSettings, contentWindow, this);
},
exitPrintPreview() {
docShell.printPreview.exitPrintPreview();
},
print(printSettings, contentWindow) {
// Bug 1088070 - we should instantiate nsIPrintSettings here in the
// content script instead of passing it down as a CPOW.
if (Cu.isCrossProcessWrapper(printSettings)) {
printSettings = null;
}
let print = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebBrowserPrint);
print.print(printSettings, null);
},
updatePageCount() {
let numPages = docShell.printPreview.printPreviewNumPages;
sendAsyncMessage("Printing:Preview:UpdatePageCount", {
numPages: numPages,
});
},
navigate(navType, pageNum) {
docShell.printPreview.printPreviewNavigate(navType, pageNum);
},
/* nsIWebProgressListener for print preview */
onStateChange(aWebProgress, aRequest, aStateFlags, aStatus) {
sendAsyncMessage("Printing:Preview:StateChange", {
stateFlags: aStateFlags,
status: aStatus,
});
},
onProgressChange(aWebProgress, aRequest, aCurSelfProgress,
aMaxSelfProgress, aCurTotalProgress,
aMaxTotalProgress) {
sendAsyncMessage("Printing:Preview:ProgressChange", {
curSelfProgress: aCurSelfProgress,
maxSelfProgress: aMaxSelfProgress,
curTotalProgress: aCurTotalProgress,
maxTotalProgress: aMaxTotalProgress,
});
},
onLocationChange(aWebProgress, aRequest, aLocation, aFlags) {},
onStatusChange(aWebProgress, aRequest, aStatus, aMessage) {},
onSecurityChange(aWebProgress, aRequest, aState) {},
}
Printing.init();

View File

@ -37,7 +37,7 @@ function TouchEventHandler (window) {
let TouchEventHandler = {
enabled: false,
events: ['mousedown', 'mousemove', 'mouseup'],
events: ['mousedown', 'mousemove', 'mouseup', 'touchstart', 'touchend'],
start: function teh_start() {
if (this.enabled)
return false;
@ -61,18 +61,43 @@ function TouchEventHandler (window) {
}).bind(this));
},
handleEvent: function teh_handleEvent(evt) {
// Ignore all but real mouse event coming from physical mouse
// (especially ignore mouse event being dispatched from a touch event)
if (evt.button || evt.mozInputSource != Ci.nsIDOMMouseEvent.MOZ_SOURCE_MOUSE || evt.isSynthesized) {
return;
}
// The gaia system window use an hybrid system even on the device which is
// a mix of mouse/touch events. So let's not cancel *all* mouse events
// if it is the current target.
let content = this.getContent(evt.target);
let isSystemWindow = content.location.toString().indexOf("system.gaiamobile.org") != -1;
// App touchstart & touchend should also be dispatched on the system app
// to match on-device behavior.
if (evt.type.startsWith('touch') && !isSystemWindow) {
let sysFrame = content.realFrameElement;
let sysDocument = sysFrame.ownerDocument;
let sysWindow = sysDocument.defaultView;
let touchEvent = sysDocument.createEvent('touchevent');
let touch = evt.touches[0] || evt.changedTouches[0];
let point = sysDocument.createTouch(sysWindow, sysFrame, 0,
touch.pageX, touch.pageY,
touch.screenX, touch.screenY,
touch.clientX, touch.clientY,
1, 1, 0, 0);
let touches = sysDocument.createTouchList(point);
let targetTouches = touches;
let changedTouches = touches;
touchEvent.initTouchEvent(evt.type, true, true, sysWindow, 0,
false, false, false, false,
touches, targetTouches, changedTouches);
sysFrame.dispatchEvent(touchEvent);
return;
}
// Ignore all but real mouse event coming from physical mouse
// (especially ignore mouse event being dispatched from a touch event)
if (evt.button || evt.mozInputSource != Ci.nsIDOMMouseEvent.MOZ_SOURCE_MOUSE || evt.isSynthesized) {
return;
}
let eventTarget = this.target;
let type = '';
switch (evt.type) {

View File

@ -1066,13 +1066,14 @@ nsViewManager::ProcessPendingUpdates()
return;
}
mPresShell->GetPresContext()->RefreshDriver()->RevokeViewManagerFlush();
// Flush things like reflows by calling WillPaint on observer presShells.
if (mPresShell) {
mPresShell->GetPresContext()->RefreshDriver()->RevokeViewManagerFlush();
CallWillPaintOnObservers();
ProcessPendingUpdatesForView(mRootView, true);
}
ProcessPendingUpdatesForView(mRootView, true);
}
void

View File

@ -29,7 +29,7 @@ nsPrintOptionsX::ReadPrefs(nsIPrintSettings* aPS, const nsAString& aPrinterName,
return NS_ERROR_NO_INTERFACE;
rv = printSettingsX->ReadPageFormatFromPrefs();
return rv;
return NS_OK;
}
nsresult nsPrintOptionsX::_CreatePrintSettings(nsIPrintSettings **_retval)

View File

@ -140,13 +140,10 @@ static const mozilla::Module::CIDEntry kWidgetCIDs[] = {
{ &kNS_THEMERENDERER_CID, false, NULL, nsNativeThemeCocoaConstructor },
{ &kNS_SCREENMANAGER_CID, false, NULL, nsScreenManagerCocoaConstructor,
mozilla::Module::MAIN_PROCESS_ONLY },
{ &kNS_DEVICE_CONTEXT_SPEC_CID, false, NULL, nsDeviceContextSpecXConstructor,
mozilla::Module::MAIN_PROCESS_ONLY },
{ &kNS_PRINTSESSION_CID, false, NULL, nsPrintSessionConstructor,
mozilla::Module::MAIN_PROCESS_ONLY },
{ &kNS_DEVICE_CONTEXT_SPEC_CID, false, NULL, nsDeviceContextSpecXConstructor },
{ &kNS_PRINTSESSION_CID, false, NULL, nsPrintSessionConstructor },
{ &kNS_PRINTSETTINGSSERVICE_CID, false, NULL, nsPrintOptionsXConstructor },
{ &kNS_PRINTDIALOGSERVICE_CID, false, NULL, nsPrintDialogServiceXConstructor,
mozilla::Module::MAIN_PROCESS_ONLY },
{ &kNS_PRINTDIALOGSERVICE_CID, false, NULL, nsPrintDialogServiceXConstructor },
{ &kNS_IDLE_SERVICE_CID, false, NULL, nsIdleServiceXConstructor },
{ &kNS_SYSTEMALERTSSERVICE_CID, false, NULL, OSXNotificationCenterConstructor },
{ &kNS_NATIVEMENUSERVICE_CID, false, NULL, nsNativeMenuServiceXConstructor },
@ -180,13 +177,10 @@ static const mozilla::Module::ContractIDEntry kWidgetContracts[] = {
{ "@mozilla.org/chrome/chrome-native-theme;1", &kNS_THEMERENDERER_CID },
{ "@mozilla.org/gfx/screenmanager;1", &kNS_SCREENMANAGER_CID,
mozilla::Module::MAIN_PROCESS_ONLY },
{ "@mozilla.org/gfx/devicecontextspec;1", &kNS_DEVICE_CONTEXT_SPEC_CID,
mozilla::Module::MAIN_PROCESS_ONLY },
{ "@mozilla.org/gfx/printsession;1", &kNS_PRINTSESSION_CID,
mozilla::Module::MAIN_PROCESS_ONLY },
{ "@mozilla.org/gfx/devicecontextspec;1", &kNS_DEVICE_CONTEXT_SPEC_CID },
{ "@mozilla.org/gfx/printsession;1", &kNS_PRINTSESSION_CID },
{ "@mozilla.org/gfx/printsettings-service;1", &kNS_PRINTSETTINGSSERVICE_CID },
{ NS_PRINTDIALOGSERVICE_CONTRACTID, &kNS_PRINTDIALOGSERVICE_CID,
mozilla::Module::MAIN_PROCESS_ONLY },
{ NS_PRINTDIALOGSERVICE_CONTRACTID, &kNS_PRINTDIALOGSERVICE_CID },
{ "@mozilla.org/widget/idleservice;1", &kNS_IDLE_SERVICE_CID },
{ "@mozilla.org/system-alerts-service;1", &kNS_SYSTEMALERTSSERVICE_CID },
{ "@mozilla.org/widget/nativemenuservice;1", &kNS_NATIVEMENUSERVICE_CID },

View File

@ -219,14 +219,10 @@ static const mozilla::Module::CIDEntry kWidgetCIDs[] = {
{ &kNS_THEMERENDERER_CID, false, nullptr, nsNativeThemeGTKConstructor },
#ifdef NS_PRINTING
{ &kNS_PRINTSETTINGSSERVICE_CID, false, nullptr, nsPrintOptionsGTKConstructor },
{ &kNS_PRINTER_ENUMERATOR_CID, false, nullptr, nsPrinterEnumeratorGTKConstructor,
Module::MAIN_PROCESS_ONLY },
{ &kNS_PRINTSESSION_CID, false, nullptr, nsPrintSessionConstructor,
Module::MAIN_PROCESS_ONLY },
{ &kNS_DEVICE_CONTEXT_SPEC_CID, false, nullptr, nsDeviceContextSpecGTKConstructor,
Module::MAIN_PROCESS_ONLY },
{ &kNS_PRINTDIALOGSERVICE_CID, false, nullptr, nsPrintDialogServiceGTKConstructor,
Module::MAIN_PROCESS_ONLY },
{ &kNS_PRINTER_ENUMERATOR_CID, false, nullptr, nsPrinterEnumeratorGTKConstructor },
{ &kNS_PRINTSESSION_CID, false, nullptr, nsPrintSessionConstructor },
{ &kNS_DEVICE_CONTEXT_SPEC_CID, false, nullptr, nsDeviceContextSpecGTKConstructor },
{ &kNS_PRINTDIALOGSERVICE_CID, false, nullptr, nsPrintDialogServiceGTKConstructor },
#endif
{ &kNS_IMAGE_TO_PIXBUF_CID, false, nullptr, nsImageToPixbufConstructor },
#if defined(MOZ_X11)
@ -256,14 +252,10 @@ static const mozilla::Module::ContractIDEntry kWidgetContracts[] = {
{ "@mozilla.org/chrome/chrome-native-theme;1", &kNS_THEMERENDERER_CID },
#ifdef NS_PRINTING
{ "@mozilla.org/gfx/printsettings-service;1", &kNS_PRINTSETTINGSSERVICE_CID },
{ "@mozilla.org/gfx/printerenumerator;1", &kNS_PRINTER_ENUMERATOR_CID,
Module::MAIN_PROCESS_ONLY },
{ "@mozilla.org/gfx/printsession;1", &kNS_PRINTSESSION_CID,
Module::MAIN_PROCESS_ONLY },
{ "@mozilla.org/gfx/devicecontextspec;1", &kNS_DEVICE_CONTEXT_SPEC_CID,
Module::MAIN_PROCESS_ONLY },
{ NS_PRINTDIALOGSERVICE_CONTRACTID, &kNS_PRINTDIALOGSERVICE_CID,
Module::MAIN_PROCESS_ONLY },
{ "@mozilla.org/gfx/printerenumerator;1", &kNS_PRINTER_ENUMERATOR_CID },
{ "@mozilla.org/gfx/printsession;1", &kNS_PRINTSESSION_CID },
{ "@mozilla.org/gfx/devicecontextspec;1", &kNS_DEVICE_CONTEXT_SPEC_CID },
{ NS_PRINTDIALOGSERVICE_CONTRACTID, &kNS_PRINTDIALOGSERVICE_CID },
#endif
{ "@mozilla.org/widget/image-to-gdk-pixbuf;1", &kNS_IMAGE_TO_PIXBUF_CID },
#if defined(MOZ_X11)

View File

@ -102,6 +102,7 @@ EXPORTS += [
'nsIRollupListener.h',
'nsIWidget.h',
'nsIWidgetListener.h',
'nsPrintOptionsImpl.h',
'nsWidgetInitData.h',
'nsWidgetsCID.h',
]

View File

@ -8,14 +8,23 @@
%{ C++
struct nsFont;
namespace mozilla {
namespace embedding {
class PrintData;
}
}
%}
interface nsIStringEnumerator;
interface nsIWebBrowserPrint;
/**
* Native types
*/
[ref] native nsNativeFontRef(nsFont);
[ref] native PrintDataRef(const mozilla::embedding::PrintData);
[ptr] native PrintDataPtr(mozilla::embedding::PrintData);
/**
* Print options interface
@ -24,7 +33,7 @@ interface nsIStringEnumerator;
* John Keiser <jkeiser@netscape.com> and Roland Mainz
* <roland.mainz@informatik.med.uni-giessen.de> for futher details.
*/
[scriptable, uuid(92597c2b-109b-40bb-8f93-9b9acfa31de8)]
[scriptable, uuid(2ac74034-700e-40fd-8059-81d33223af58)]
interface nsIPrintOptions : nsISupports
{
@ -57,6 +66,39 @@ interface nsIPrintOptions : nsISupports
const short kNativeDataPrintRecord = 0;
[noscript] voidPtr GetNativeData(in short aDataType);
/**
* Given some nsIPrintSettings and (optionally) an nsIWebBrowserPrint, populates
* a PrintData representing them which can be sent over IPC. Values are only
* ever read from aSettings and aWBP.
*
* @param aSettings
* An nsIPrintSettings for a print job.
* @param aWBP (optional)
* The nsIWebBrowserPrint for the print job.
* @param data
* Pointer to a pre-existing PrintData to populate.
*
* @return nsresult
*/
[noscript] void SerializeToPrintData(in nsIPrintSettings aPrintSettings,
in nsIWebBrowserPrint aWebBrowserPrint,
in PrintDataPtr data);
/**
* This function is the opposite of SerializeToPrintData, in that it takes
* a PrintData, and populates a pre-existing nsIPrintSettings with the data
* from PrintData.
*
* @param PrintData
* Printing information sent through IPC.
* @param settings
* A pre-existing nsIPrintSettings to populate with the PrintData.
*
* @return nsresult
*/
[noscript] void DeserializeToPrintSettings(in PrintDataRef data,
in nsIPrintSettings aPrintSettings);
};
[scriptable, uuid(5e738fff-404c-4c94-9189-e8f2cce93e94)]

View File

@ -3,6 +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/embedding/PPrinting.h"
#include "nsPrintOptionsImpl.h"
#include "nsReadableUtils.h"
#include "nsPrintSettingsImpl.h"
@ -22,8 +23,10 @@
#include "nsAutoPtr.h"
#include "mozilla/Preferences.h"
#include "nsPrintfCString.h"
#include "nsIWebBrowserPrint.h"
using namespace mozilla;
using namespace mozilla::embedding;
NS_IMPL_ISUPPORTS(nsPrintOptions, nsIPrintOptions, nsIPrintSettingsService)
@ -97,6 +100,221 @@ nsPrintOptions::Init()
return NS_OK;
}
NS_IMETHODIMP
nsPrintOptions::SerializeToPrintData(nsIPrintSettings* aSettings,
nsIWebBrowserPrint* aWBP,
PrintData* data)
{
aSettings->GetStartPageRange(&data->startPageRange());
aSettings->GetEndPageRange(&data->endPageRange());
aSettings->GetEdgeTop(&data->edgeTop());
aSettings->GetEdgeLeft(&data->edgeLeft());
aSettings->GetEdgeBottom(&data->edgeBottom());
aSettings->GetEdgeRight(&data->edgeRight());
aSettings->GetMarginTop(&data->marginTop());
aSettings->GetMarginLeft(&data->marginLeft());
aSettings->GetMarginBottom(&data->marginBottom());
aSettings->GetMarginRight(&data->marginRight());
aSettings->GetUnwriteableMarginTop(&data->unwriteableMarginTop());
aSettings->GetUnwriteableMarginLeft(&data->unwriteableMarginLeft());
aSettings->GetUnwriteableMarginBottom(&data->unwriteableMarginBottom());
aSettings->GetUnwriteableMarginRight(&data->unwriteableMarginRight());
aSettings->GetScaling(&data->scaling());
aSettings->GetPrintBGColors(&data->printBGColors());
aSettings->GetPrintBGImages(&data->printBGImages());
aSettings->GetPrintRange(&data->printRange());
// I have no idea if I'm doing this string copying correctly...
nsXPIDLString title;
aSettings->GetTitle(getter_Copies(title));
data->title() = title;
nsXPIDLString docURL;
aSettings->GetDocURL(getter_Copies(docURL));
data->docURL() = docURL;
// Header strings...
nsXPIDLString headerStrLeft;
aSettings->GetHeaderStrLeft(getter_Copies(headerStrLeft));
data->headerStrLeft() = headerStrLeft;
nsXPIDLString headerStrCenter;
aSettings->GetHeaderStrCenter(getter_Copies(headerStrCenter));
data->headerStrCenter() = headerStrCenter;
nsXPIDLString headerStrRight;
aSettings->GetHeaderStrRight(getter_Copies(headerStrRight));
data->headerStrRight() = headerStrRight;
// Footer strings...
nsXPIDLString footerStrLeft;
aSettings->GetFooterStrLeft(getter_Copies(footerStrLeft));
data->footerStrLeft() = footerStrLeft;
nsXPIDLString footerStrCenter;
aSettings->GetFooterStrCenter(getter_Copies(footerStrCenter));
data->footerStrCenter() = footerStrCenter;
nsXPIDLString footerStrRight;
aSettings->GetFooterStrRight(getter_Copies(footerStrRight));
data->footerStrRight() = footerStrRight;
aSettings->GetHowToEnableFrameUI(&data->howToEnableFrameUI());
aSettings->GetIsCancelled(&data->isCancelled());
aSettings->GetPrintFrameTypeUsage(&data->printFrameTypeUsage());
aSettings->GetPrintFrameType(&data->printFrameType());
aSettings->GetPrintSilent(&data->printSilent());
aSettings->GetShrinkToFit(&data->shrinkToFit());
aSettings->GetShowPrintProgress(&data->showPrintProgress());
nsXPIDLString paperName;
aSettings->GetPaperName(getter_Copies(paperName));
data->paperName() = paperName;
aSettings->GetPaperSizeType(&data->paperSizeType());
aSettings->GetPaperData(&data->paperData());
aSettings->GetPaperWidth(&data->paperWidth());
aSettings->GetPaperHeight(&data->paperHeight());
aSettings->GetPaperSizeUnit(&data->paperSizeUnit());
nsXPIDLString plexName;
aSettings->GetPlexName(getter_Copies(plexName));
data->plexName() = plexName;
nsXPIDLString colorspace;
aSettings->GetColorspace(getter_Copies(colorspace));
data->colorspace() = colorspace;
nsXPIDLString resolutionName;
aSettings->GetResolutionName(getter_Copies(resolutionName));
data->resolutionName() = resolutionName;
aSettings->GetDownloadFonts(&data->downloadFonts());
aSettings->GetPrintReversed(&data->printReversed());
aSettings->GetPrintInColor(&data->printInColor());
aSettings->GetOrientation(&data->orientation());
nsXPIDLString printCommand;
aSettings->GetPrintCommand(getter_Copies(printCommand));
data->printCommand() = printCommand;
aSettings->GetNumCopies(&data->numCopies());
nsXPIDLString printerName;
aSettings->GetPrinterName(getter_Copies(printerName));
data->printerName() = printerName;
aSettings->GetPrintToFile(&data->printToFile());
nsXPIDLString toFileName;
aSettings->GetToFileName(getter_Copies(toFileName));
data->toFileName() = toFileName;
aSettings->GetOutputFormat(&data->outputFormat());
aSettings->GetPrintPageDelay(&data->printPageDelay());
aSettings->GetResolution(&data->resolution());
aSettings->GetDuplex(&data->duplex());
aSettings->GetIsInitializedFromPrinter(&data->isInitializedFromPrinter());
aSettings->GetIsInitializedFromPrefs(&data->isInitializedFromPrefs());
aSettings->GetPersistMarginBoxSettings(&data->persistMarginBoxSettings());
return NS_OK;
}
NS_IMETHODIMP
nsPrintOptions::DeserializeToPrintSettings(const PrintData& data,
nsIPrintSettings* settings)
{
settings->SetStartPageRange(data.startPageRange());
settings->SetEndPageRange(data.endPageRange());
settings->SetEdgeTop(data.edgeTop());
settings->SetEdgeLeft(data.edgeLeft());
settings->SetEdgeBottom(data.edgeBottom());
settings->SetEdgeRight(data.edgeRight());
settings->SetMarginTop(data.marginTop());
settings->SetMarginLeft(data.marginLeft());
settings->SetMarginBottom(data.marginBottom());
settings->SetMarginRight(data.marginRight());
settings->SetUnwriteableMarginTop(data.unwriteableMarginTop());
settings->SetUnwriteableMarginLeft(data.unwriteableMarginLeft());
settings->SetUnwriteableMarginBottom(data.unwriteableMarginBottom());
settings->SetUnwriteableMarginRight(data.unwriteableMarginRight());
settings->SetScaling(data.scaling());
settings->SetPrintBGColors(data.printBGColors());
settings->SetPrintBGImages(data.printBGImages());
settings->SetPrintRange(data.printRange());
// I have no idea if I'm doing this string copying correctly...
settings->SetTitle(data.title().get());
settings->SetDocURL(data.docURL().get());
// Header strings...
settings->SetHeaderStrLeft(data.headerStrLeft().get());
settings->SetHeaderStrCenter(data.headerStrCenter().get());
settings->SetHeaderStrRight(data.headerStrRight().get());
// Footer strings...
settings->SetFooterStrLeft(data.footerStrLeft().get());
settings->SetFooterStrCenter(data.footerStrCenter().get());
settings->SetFooterStrRight(data.footerStrRight().get());
settings->SetHowToEnableFrameUI(data.howToEnableFrameUI());
settings->SetIsCancelled(data.isCancelled());
settings->SetPrintFrameTypeUsage(data.printFrameTypeUsage());
settings->SetPrintFrameType(data.printFrameType());
settings->SetPrintSilent(data.printSilent());
settings->SetShrinkToFit(data.shrinkToFit());
settings->SetShowPrintProgress(data.showPrintProgress());
settings->SetPaperName(data.paperName().get());
settings->SetPaperSizeType(data.paperSizeType());
settings->SetPaperData(data.paperData());
settings->SetPaperWidth(data.paperWidth());
settings->SetPaperHeight(data.paperHeight());
settings->SetPaperSizeUnit(data.paperSizeUnit());
settings->SetPlexName(data.plexName().get());
settings->SetColorspace(data.colorspace().get());
settings->SetResolutionName(data.resolutionName().get());
settings->SetDownloadFonts(data.downloadFonts());
settings->SetPrintReversed(data.printReversed());
settings->SetPrintInColor(data.printInColor());
settings->SetOrientation(data.orientation());
settings->SetPrintCommand(data.printCommand().get());
settings->SetNumCopies(data.numCopies());
settings->SetPrinterName(data.printerName().get());
settings->SetPrintToFile(data.printToFile());
settings->SetToFileName(data.toFileName().get());
settings->SetOutputFormat(data.outputFormat());
settings->SetPrintPageDelay(data.printPageDelay());
settings->SetResolution(data.resolution());
settings->SetDuplex(data.duplex());
settings->SetIsInitializedFromPrinter(data.isInitializedFromPrinter());
settings->SetIsInitializedFromPrefs(data.isInitializedFromPrefs());
settings->SetPersistMarginBoxSettings(data.persistMarginBoxSettings());
return NS_OK;
}
NS_IMETHODIMP
nsPrintOptions::ShowPrintSetupDialog(nsIPrintSettings *aPS)
{

View File

@ -7,12 +7,16 @@
#ifndef nsPrintOptionsImpl_h__
#define nsPrintOptionsImpl_h__
#include "mozilla/embedding/PPrinting.h"
#include "nsCOMPtr.h"
#include "nsIPrintOptions.h"
#include "nsIPrintSettingsService.h"
#include "nsString.h"
#include "nsFont.h"
class nsIPrintSettings;
class nsIWebBrowserPrint;
/**
* Class nsPrintOptions
*/

View File

@ -5,11 +5,16 @@
#include "nsCOMPtr.h"
#include "nsPrintOptionsWin.h"
#include "nsPrintSettingsWin.h"
#include "nsPrintDialogUtil.h"
#include "nsGfxCIID.h"
#include "nsIServiceManager.h"
#include "nsIWebBrowserPrint.h"
const char kPrinterEnumeratorContractID[] = "@mozilla.org/gfx/printerenumerator;1";
using namespace mozilla::embedding;
/** ---------------------------------------------------
* See documentation in nsPrintOptionsWin.h
* @update 6/21/00 dwc
@ -27,6 +32,71 @@ nsPrintOptionsWin::~nsPrintOptionsWin()
{
}
NS_IMETHODIMP
nsPrintOptionsWin::SerializeToPrintData(nsIPrintSettings* aSettings,
nsIWebBrowserPrint* aWBP,
PrintData* data)
{
nsresult rv = nsPrintOptions::SerializeToPrintData(aSettings, aWBP, data);
NS_ENSURE_SUCCESS(rv, rv);
// Windows wants this information for its print dialogs
if (aWBP) {
aWBP->GetIsFramesetDocument(&data->isFramesetDocument());
aWBP->GetIsFramesetFrameSelected(&data->isFramesetFrameSelected());
aWBP->GetIsIFrameSelected(&data->isIFrameSelected());
aWBP->GetIsRangeSelection(&data->isRangeSelection());
}
nsCOMPtr<nsIPrintSettingsWin> psWin = do_QueryInterface(aSettings);
if (!psWin) {
return NS_ERROR_FAILURE;
}
char16_t* deviceName;
char16_t* driverName;
psWin->GetDeviceName(&deviceName);
psWin->GetDriverName(&driverName);
data->deviceName().Assign(deviceName);
data->driverName().Assign(driverName);
free(deviceName);
free(driverName);
return NS_OK;
}
NS_IMETHODIMP
nsPrintOptionsWin::DeserializeToPrintSettings(const PrintData& data,
nsIPrintSettings* settings)
{
nsresult rv = nsPrintOptions::DeserializeToPrintSettings(data, settings);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIPrintSettingsWin> psWin = do_QueryInterface(settings);
if (!settings) {
return NS_ERROR_FAILURE;
}
psWin->SetDeviceName(data.deviceName().get());
psWin->SetDriverName(data.driverName().get());
// We also need to prepare a DevMode and stuff it into our newly
// created nsIPrintSettings...
nsXPIDLString printerName;
settings->GetPrinterName(getter_Copies(printerName));
HGLOBAL gDevMode = CreateGlobalDevModeAndInit(printerName, settings);
LPDEVMODEW devMode = (LPDEVMODEW)::GlobalLock(gDevMode);
psWin->SetDevMode(devMode);
::GlobalUnlock(gDevMode);
::GlobalFree(gDevMode);
return NS_OK;
}
/* nsIPrintSettings CreatePrintSettings (); */
nsresult nsPrintOptionsWin::_CreatePrintSettings(nsIPrintSettings **_retval)
{

View File

@ -7,8 +7,11 @@
#ifndef nsPrintOptionsWin_h__
#define nsPrintOptionsWin_h__
#include "mozilla/embedding/PPrinting.h"
#include "nsPrintOptionsImpl.h"
class nsIPrintSettings;
class nsIWebBrowserPrint;
//*****************************************************************************
//*** nsPrintOptions
@ -19,6 +22,12 @@ public:
nsPrintOptionsWin();
virtual ~nsPrintOptionsWin();
NS_IMETHODIMP SerializeToPrintData(nsIPrintSettings* aSettings,
nsIWebBrowserPrint* aWBP,
mozilla::embedding::PrintData* data);
NS_IMETHODIMP DeserializeToPrintSettings(const mozilla::embedding::PrintData& data,
nsIPrintSettings* settings);
virtual nsresult _CreatePrintSettings(nsIPrintSettings **_retval);
};

View File

@ -244,12 +244,9 @@ static const mozilla::Module::CIDEntry kWidgetCIDs[] = {
#endif
#ifdef NS_PRINTING
{ &kNS_PRINTSETTINGSSERVICE_CID, false, nullptr, nsPrintOptionsWinConstructor },
{ &kNS_PRINTER_ENUMERATOR_CID, false, nullptr, nsPrinterEnumeratorWinConstructor,
Module::MAIN_PROCESS_ONLY },
{ &kNS_PRINTSESSION_CID, false, nullptr, nsPrintSessionConstructor,
Module::MAIN_PROCESS_ONLY },
{ &kNS_DEVICE_CONTEXT_SPEC_CID, false, nullptr, nsDeviceContextSpecWinConstructor,
Module::MAIN_PROCESS_ONLY },
{ &kNS_PRINTER_ENUMERATOR_CID, false, nullptr, nsPrinterEnumeratorWinConstructor },
{ &kNS_PRINTSESSION_CID, false, nullptr, nsPrintSessionConstructor },
{ &kNS_DEVICE_CONTEXT_SPEC_CID, false, nullptr, nsDeviceContextSpecWinConstructor },
#endif
{ nullptr }
};
@ -282,12 +279,9 @@ static const mozilla::Module::ContractIDEntry kWidgetContracts[] = {
#endif
#ifdef NS_PRINTING
{ "@mozilla.org/gfx/printsettings-service;1", &kNS_PRINTSETTINGSSERVICE_CID },
{ "@mozilla.org/gfx/printerenumerator;1", &kNS_PRINTER_ENUMERATOR_CID,
Module::MAIN_PROCESS_ONLY },
{ "@mozilla.org/gfx/printsession;1", &kNS_PRINTSESSION_CID,
Module::MAIN_PROCESS_ONLY },
{ "@mozilla.org/gfx/devicecontextspec;1", &kNS_DEVICE_CONTEXT_SPEC_CID,
Module::MAIN_PROCESS_ONLY },
{ "@mozilla.org/gfx/printerenumerator;1", &kNS_PRINTER_ENUMERATOR_CID },
{ "@mozilla.org/gfx/printsession;1", &kNS_PRINTSESSION_CID },
{ "@mozilla.org/gfx/devicecontextspec;1", &kNS_DEVICE_CONTEXT_SPEC_CID },
#endif
{ nullptr }
};