Bug 489224 - Printing doesn't print text field values, r+sr=roc
--- a/layout/base/nsIPresShell.h
+++ b/layout/base/nsIPresShell.h
@@ -96,20 +96,20 @@ class nsWeakFrame;
class nsIScrollableFrame;
class gfxASurface;
class gfxContext;
class nsPIDOMEventTarget;
typedef short SelectionType;
typedef PRUint32 nsFrameState;
-// fa7f090d-b19a-4ef8-9552-82992a3b4a83
+// b8ace28a-d3fa-46d8-a5a0-d7c35c12fd41
#define NS_IPRESSHELL_IID \
-{ 0xfa7f090d, 0xb19a, 0x4ef8, \
- { 0x95, 0x52, 0x82, 0x99, 0x2a, 0x3b, 0x4a, 0x83 } }
+{ 0xb8ace28a, 0xd3fa, 0x46d8, \
+ { 0xa5, 0xa0, 0xd7, 0xc3, 0x5c, 0x12, 0xfd, 0x41 } }
// Constants for ScrollContentIntoView() function
#define NS_PRESSHELL_SCROLL_TOP 0
#define NS_PRESSHELL_SCROLL_BOTTOM 100
#define NS_PRESSHELL_SCROLL_LEFT 0
#define NS_PRESSHELL_SCROLL_RIGHT 100
#define NS_PRESSHELL_SCROLL_CENTER 50
#define NS_PRESSHELL_SCROLL_ANYWHERE -1
@@ -788,16 +788,25 @@ public:
* This color is composited on top of the user's default background
* color whenever we need to provide an "ultimate" background color.
* See PresShell::Paint, PresShell::PaintDefaultBackground, and
* nsDocShell::SetupNewViewer; bug 476557 and other bugs mentioned there.
*/
void SetCanvasBackground(nscolor aColor) { mCanvasBackgroundColor = aColor; }
nscolor GetCanvasBackground() { return mCanvasBackgroundColor; }
+ void ObserveNativeAnonMutationsForPrint(PRBool aObserve)
+ {
+ mObservesMutationsForPrint = aObserve;
+ }
+ PRBool ObservesNativeAnonMutationsForPrint()
+ {
+ return mObservesMutationsForPrint;
+ }
+
protected:
// IMPORTANT: The ownership implicit in the following member variables
// has been explicitly checked. If you add any members to this class,
// please make the ownership explicit (pinkerton, scc).
// these are the same Document and PresContext owned by the DocViewer.
// we must share ownership.
nsIDocument* mDocument; // [STRONG]
@@ -824,16 +833,18 @@ protected:
*/
void InvalidateAccessibleSubtree(nsIContent *aContent);
#endif
// Set to true when the accessibility service is being used to mirror
// the dom/layout trees
PRPackedBool mIsAccessibilityActive;
+ PRPackedBool mObservesMutationsForPrint;
+
// A list of weak frames. This is a pointer to the last item in the list.
nsWeakFrame* mWeakFrames;
// Most recent canvas background color.
nscolor mCanvasBackgroundColor;
};
/**
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -761,129 +761,16 @@ FrameArena::FreeFrame(size_t aSize, void
}
struct nsCallbackEventRequest
{
nsIReflowCallback* callback;
nsCallbackEventRequest* next;
};
-
-class nsDocumentObserverForNonDynamicPresContext : public nsStubDocumentObserver
-{
-public:
- nsDocumentObserverForNonDynamicPresContext(nsIDocumentObserver* aBaseObserver)
- : mBaseObserver(aBaseObserver)
- {
- NS_ASSERTION(aBaseObserver, "Null document observer!");
- }
-
- NS_DECL_ISUPPORTS
-
- virtual void BeginUpdate(nsIDocument* aDocument, nsUpdateType aUpdateType)
- {
- mBaseObserver->BeginUpdate(aDocument, aUpdateType);
- }
- virtual void EndUpdate(nsIDocument* aDocument, nsUpdateType aUpdateType)
- {
- mBaseObserver->EndUpdate(aDocument, aUpdateType);
- }
- virtual void BeginLoad(nsIDocument* aDocument)
- {
- mBaseObserver->BeginLoad(aDocument);
- }
- virtual void EndLoad(nsIDocument* aDocument)
- {
- mBaseObserver->EndLoad(aDocument);
- }
- virtual void ContentStatesChanged(nsIDocument* aDocument,
- nsIContent* aContent1,
- nsIContent* aContent2,
- PRInt32 aStateMask)
- {
- if ((!aContent1 || IsInRootScrollbar(aContent1)) &&
- (!aContent2 || IsInRootScrollbar(aContent2))) {
- mBaseObserver->ContentStatesChanged(aDocument, aContent1, aContent2,
- aStateMask);
- }
- }
-
- // nsIMutationObserver
- virtual void CharacterDataChanged(nsIDocument* aDocument,
- nsIContent* aContent,
- CharacterDataChangeInfo* aInfo)
- {
- if (IsInRootScrollbar(aContent)) {
- mBaseObserver->CharacterDataChanged(aDocument, aContent, aInfo);
- }
- }
- virtual void AttributeChanged(nsIDocument* aDocument,
- nsIContent* aContent,
- PRInt32 aNameSpaceID,
- nsIAtom* aAttribute,
- PRInt32 aModType,
- PRUint32 aStateMask)
- {
- if (IsInRootScrollbar(aContent)) {
- mBaseObserver->AttributeChanged(aDocument, aContent, aNameSpaceID,
- aAttribute, aModType, aStateMask);
- }
- }
- virtual void ContentAppended(nsIDocument* aDocument,
- nsIContent* aContainer,
- PRInt32 aNewIndexInContainer)
- {
- if (IsInRootScrollbar(aContainer)) {
- mBaseObserver->ContentAppended(aDocument, aContainer,
- aNewIndexInContainer);
- }
- }
- virtual void ContentInserted(nsIDocument* aDocument,
- nsIContent* aContainer,
- nsIContent* aChild,
- PRInt32 aIndexInContainer)
- {
- if (IsInRootScrollbar(aContainer)) {
- mBaseObserver->ContentInserted(aDocument, aContainer, aChild,
- aIndexInContainer);
- }
- }
- virtual void ContentRemoved(nsIDocument* aDocument,
- nsIContent* aContainer,
- nsIContent* aChild,
- PRInt32 aIndexInContainer)
- {
- if (IsInRootScrollbar(aContainer)) {
- mBaseObserver->ContentRemoved(aDocument, aContainer, aChild,
- aIndexInContainer);
- }
- }
-
- PRBool IsInRootScrollbar(nsIContent* aContent) {
- if(aContent && aContent->IsInDoc()) {
- nsIContent* root = aContent->GetCurrentDoc()->GetRootContent();
- while (aContent && aContent->IsInNativeAnonymousSubtree()) {
- nsIContent* parent = aContent->GetParent();
- if (parent == root && aContent->IsNodeOfType(nsINode::eXUL)) {
- nsIAtom* tag = aContent->Tag();
- return tag == nsGkAtoms::scrollbar || tag == nsGkAtoms::scrollcorner;
- }
- aContent = parent;
- }
- }
- return PR_FALSE;
- }
-protected:
- nsCOMPtr<nsIDocumentObserver> mBaseObserver;
-};
-
-NS_IMPL_ISUPPORTS2(nsDocumentObserverForNonDynamicPresContext,
- nsIDocumentObserver,
- nsIMutationObserver)
-
// ----------------------------------------------------------------------------
class nsPresShellEventCB;
class PresShell : public nsIPresShell, public nsIViewObserver,
public nsStubDocumentObserver,
public nsISelectionController, public nsIObserver,
public nsSupportsWeakReference
{
@@ -1384,16 +1271,133 @@ public:
&aVisitor.mEventStatus);
}
}
}
nsRefPtr<PresShell> mPresShell;
};
+class nsDocumentObserverForNonDynamicPresContext : public nsStubDocumentObserver
+{
+public:
+ nsDocumentObserverForNonDynamicPresContext(PresShell* aBaseObserver)
+ : mBaseObserver(aBaseObserver)
+ {
+ NS_ASSERTION(aBaseObserver, "Null document observer!");
+ }
+
+ NS_DECL_ISUPPORTS
+
+ virtual void BeginUpdate(nsIDocument* aDocument, nsUpdateType aUpdateType)
+ {
+ mBaseObserver->BeginUpdate(aDocument, aUpdateType);
+ }
+ virtual void EndUpdate(nsIDocument* aDocument, nsUpdateType aUpdateType)
+ {
+ mBaseObserver->EndUpdate(aDocument, aUpdateType);
+ }
+ virtual void BeginLoad(nsIDocument* aDocument)
+ {
+ mBaseObserver->BeginLoad(aDocument);
+ }
+ virtual void EndLoad(nsIDocument* aDocument)
+ {
+ mBaseObserver->EndLoad(aDocument);
+ }
+ virtual void ContentStatesChanged(nsIDocument* aDocument,
+ nsIContent* aContent1,
+ nsIContent* aContent2,
+ PRInt32 aStateMask)
+ {
+ if ((!aContent1 || AllowMutation(aContent1)) &&
+ (!aContent2 || AllowMutation(aContent2))) {
+ mBaseObserver->ContentStatesChanged(aDocument, aContent1, aContent2,
+ aStateMask);
+ }
+ }
+
+ // nsIMutationObserver
+ virtual void CharacterDataChanged(nsIDocument* aDocument,
+ nsIContent* aContent,
+ CharacterDataChangeInfo* aInfo)
+ {
+ if (AllowMutation(aContent)) {
+ mBaseObserver->CharacterDataChanged(aDocument, aContent, aInfo);
+ }
+ }
+ virtual void AttributeChanged(nsIDocument* aDocument,
+ nsIContent* aContent,
+ PRInt32 aNameSpaceID,
+ nsIAtom* aAttribute,
+ PRInt32 aModType,
+ PRUint32 aStateMask)
+ {
+ if (AllowMutation(aContent)) {
+ mBaseObserver->AttributeChanged(aDocument, aContent, aNameSpaceID,
+ aAttribute, aModType, aStateMask);
+ }
+ }
+ virtual void ContentAppended(nsIDocument* aDocument,
+ nsIContent* aContainer,
+ PRInt32 aNewIndexInContainer)
+ {
+ if (AllowMutation(aContainer)) {
+ mBaseObserver->ContentAppended(aDocument, aContainer,
+ aNewIndexInContainer);
+ }
+ }
+ virtual void ContentInserted(nsIDocument* aDocument,
+ nsIContent* aContainer,
+ nsIContent* aChild,
+ PRInt32 aIndexInContainer)
+ {
+ if (AllowMutation(aContainer)) {
+ mBaseObserver->ContentInserted(aDocument, aContainer, aChild,
+ aIndexInContainer);
+ }
+ }
+ virtual void ContentRemoved(nsIDocument* aDocument,
+ nsIContent* aContainer,
+ nsIContent* aChild,
+ PRInt32 aIndexInContainer)
+ {
+ if (AllowMutation(aContainer)) {
+ mBaseObserver->ContentRemoved(aDocument, aContainer, aChild,
+ aIndexInContainer);
+ }
+ }
+
+ PRBool AllowMutation(nsIContent* aContent) {
+ if(aContent && aContent->IsInDoc()) {
+ if (mBaseObserver->ObservesNativeAnonMutationsForPrint() &&
+ aContent->IsInNativeAnonymousSubtree()) {
+ return PR_TRUE;
+ }
+ // Changes to scrollbar are always ok.
+ nsIContent* root = aContent->GetCurrentDoc()->GetRootContent();
+ while (aContent && aContent->IsInNativeAnonymousSubtree()) {
+ nsIContent* parent = aContent->GetParent();
+ if (parent == root && aContent->IsNodeOfType(nsINode::eXUL)) {
+ nsIAtom* tag = aContent->Tag();
+ return tag == nsGkAtoms::scrollbar || tag == nsGkAtoms::scrollcorner;
+ }
+ aContent = parent;
+ }
+ }
+ return PR_FALSE;
+ }
+protected:
+ nsRefPtr<PresShell> mBaseObserver;
+};
+
+NS_IMPL_ISUPPORTS2(nsDocumentObserverForNonDynamicPresContext,
+ nsIDocumentObserver,
+ nsIMutationObserver)
+
PRBool PresShell::sDisableNonTestMouseEvents = PR_FALSE;
#ifdef PR_LOGGING
PRLogModuleInfo* PresShell::gLog;
#endif
#ifdef NS_DEBUG
static void
--- a/layout/base/tests/test_printpreview.html
+++ b/layout/base/tests/test_printpreview.html
@@ -141,25 +141,92 @@ function finalizeTest1() {
setTimeout(runTest2, 1000);
}
function runTest2() {
isnot(window.frames[0].document.body.firstChild.nextSibling.textContent, "0 timers", "Timers should have run!");
isnot(window.frames[0].counter, 0, "Timers should have run!");
counter = window.frames[0].counter;
window.frames[0].counterTimeout = "";
+ setTimeout(runTest3, 0);
+}
+
+var elementIndex = 0;
+var compareEmptyElement = true;
+var emptyFormElements =
+ ["<input type='text'>",
+ "<input type='password'>",
+ "<input type='file'>",
+ "<input type='button'>",
+ "<input type='submit'>",
+ "<input type='reset'>",
+ "<input type='checkbox'>",
+ "<input type='radio'>",
+ "<select></select>",
+ "<select size='5'></select>",
+ "<textarea></textarea>"];
+
+var formElements =
+ ["<input type='text' value='text'>",
+ "<input type='password' value='password'>",
+ "<input type='file' value='file'>",
+ "<input type='button' value='button'>",
+ "<input type='submit' value='submit button'>",
+ "<input type='reset' value='reset button'>",
+ "<input type='checkbox' checked>",
+ "<input type='radio' checked>",
+ "<select><option>option1</option></select>",
+ "<select size='5'><option>1</option><option>2</option><option>3</option></select>",
+ "<textarea value='textarea'>textarea</textarea>"];
+
+function runTest3() {
+ if (compareEmptyElement) {
+ var currentIndex = elementIndex;
+ ++elementIndex;
+ if (elementIndex >= emptyFormElements.length) {
+ elementIndex = 0;
+ compareEmptyElement = false;
+ }
+ compareFormElementPrint(emptyFormElements[currentIndex], emptyFormElements[currentIndex], true);
+ return;
+ } else if (elementIndex < emptyFormElements.length) {
+ var currentIndex = elementIndex;
+ ++elementIndex;
+ compareFormElementPrint(emptyFormElements[currentIndex], formElements[currentIndex], false);
+ return;
+ }
+
SimpleTest.finish();
}
+function compareFormElementPrint(el1, el2, equals) {
+ netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+ window.frames[0].document.body.innerHTML = el1;
+ window.frames[0].document.body.firstChild.value =
+ window.frames[0].document.body.firstChild.getAttribute('value');
+ printpreview();
+ ctx1.drawWindow(window.frames[0], 0, 0, 300, 300, "rgb(256,256,256)");
+ exitprintpreview();
+ window.frames[0].document.body.innerHTML = el2;
+ window.frames[0].document.body.firstChild.value =
+ window.frames[0].document.body.firstChild.getAttribute('value');
+ printpreview();
+ ctx2.drawWindow(window.frames[0], 0, 0, 300, 300, "rgb(256,256,256)");
+ exitprintpreview();
+ is(compareCanvases(), equals,
+ "Comparing print preview didn't succeed [" + el1 + " : " + el2 + "]");
+ setTimeout(runTest3, 100);
+}
+
SimpleTest.waitForExplicitFinish();
</script>
<iframe height="200" width="600"></iframe>
<table>
-<tr><th>Print preview canvas before mutations</th><th>Print preview canvas after mutations</th></tr>
+<tr><th>Print preview canvas 1</th><th>Print preview canvas 2</th></tr>
<tr>
<td><canvas height="300" width="300"></canvas></td>
<td><canvas height="300" width="300"></canvas></td>
</tr></table>
</canvas>
</pre>
</body>
</html>
--- a/layout/forms/nsTextControlFrame.h
+++ b/layout/forms/nsTextControlFrame.h
@@ -218,17 +218,22 @@ protected:
class EditorInitializer : public nsRunnable {
public:
EditorInitializer(nsTextControlFrame* aFrame) :
mWeakFrame(aFrame),
mFrame(aFrame) {}
NS_IMETHOD Run() {
if (mWeakFrame) {
+ nsCOMPtr<nsIPresShell> shell =
+ mWeakFrame.GetFrame()->PresContext()->GetPresShell();
+ PRBool observes = shell->ObservesNativeAnonMutationsForPrint();
+ shell->ObserveNativeAnonMutationsForPrint(PR_TRUE);
mFrame->DelayedEditorInit();
+ shell->ObserveNativeAnonMutationsForPrint(observes);
}
return NS_OK;
}
private:
nsWeakFrame mWeakFrame;
nsTextControlFrame* mFrame;
};