зеркало из https://github.com/mozilla/pjs.git
Merge mozilla-central into electrolysis.
This commit is contained in:
Коммит
8411a08769
|
@ -44,7 +44,7 @@ interface nsIFrame;
|
|||
interface nsObjectFrame;
|
||||
interface nsIContent;
|
||||
|
||||
[uuid(e0498def-1552-4763-8c47-6c6cc36c7aa0)]
|
||||
[uuid(84a3ab70-8f7e-4610-9cd8-bd69308b76c5)]
|
||||
interface nsIAccessibilityService : nsIAccessibleRetrieval
|
||||
{
|
||||
nsIAccessible createOuterDocAccessible(in nsIDOMNode aNode);
|
||||
|
@ -74,19 +74,6 @@ interface nsIAccessibilityService : nsIAccessibleRetrieval
|
|||
nsIAccessible createHTMLTextFieldAccessible(in nsIFrame aFrame);
|
||||
nsIAccessible createHTMLCaptionAccessible(in nsIFrame aFrame);
|
||||
|
||||
/**
|
||||
* Return an accessible for the given DOM node.
|
||||
*
|
||||
* @param aNode [in] the given node
|
||||
* @param aPresShell [in] the pres shell of the node
|
||||
* @param aWeakShell [in] the weak shell for the pres shell
|
||||
* @param aFrameHint [in] the frame of the given node
|
||||
* @param aIsHidden [out] indicates whether the node's frame is hidden
|
||||
*/
|
||||
nsIAccessible getAccessible(in nsIDOMNode aNode, in nsIPresShell aPresShell,
|
||||
in nsIWeakReference aWeakShell,
|
||||
in nsIFrame aFrameHint, out boolean aIsHidden);
|
||||
|
||||
// For gtk+ native window accessible
|
||||
nsIAccessible addNativeRootAccessible(in voidPtr aAtkAccessible);
|
||||
void removeNativeRootAccessible(in nsIAccessible aRootAccessible);
|
||||
|
|
|
@ -56,7 +56,7 @@ interface nsIDOMDOMStringList;
|
|||
*
|
||||
* @status UNDER_REVIEW
|
||||
*/
|
||||
[scriptable, uuid(244e4c67-a1d3-44f2-9cab-cdaa31b68046)]
|
||||
[scriptable, uuid(7eb49afb-6298-4ce6-816f-9615936540f4)]
|
||||
interface nsIAccessibleRetrieval : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -92,26 +92,6 @@ interface nsIAccessibleRetrieval : nsISupports
|
|||
*/
|
||||
nsIDOMNode getRelevantContentNodeFor(in nsIDOMNode aNode);
|
||||
|
||||
/**
|
||||
* Return an nsIAccessible for a DOM node in pres shell for this DOM window.
|
||||
* Create a new accessible of the appropriate type if necessary,
|
||||
* or use one from the accessibility cache if it already exists.
|
||||
* @param aNode The DOM node to get an accessible for.
|
||||
* @param aDOMWin The DOM window containing the node.
|
||||
* @return The nsIAccessible for the given DOM node.
|
||||
*/
|
||||
nsIAccessible getAccessibleInWindow(in nsIDOMNode aNode, in nsIDOMWindow aDOMWin);
|
||||
|
||||
/**
|
||||
* Return an nsIAccessible for a DOM node in the given weak shell.
|
||||
* Create a new accessible of the appropriate type if necessary,
|
||||
* or use one from the accessibility cache if it already exists.
|
||||
* @param aNode The DOM node to get an accessible for.
|
||||
* @param aPresShell The presentation shell which contains layout info for the DOM node.
|
||||
* @return The nsIAccessible for the given DOM node.
|
||||
*/
|
||||
nsIAccessible getAccessibleInWeakShell(in nsIDOMNode aNode, in nsIWeakReference aPresShell);
|
||||
|
||||
/**
|
||||
* Return an nsIAccessible for a DOM node in the given pres shell.
|
||||
* Create a new accessible of the appropriate type if necessary,
|
||||
|
|
|
@ -295,8 +295,7 @@ nsAccReorderEvent::HasAccessibleInReasonSubtree()
|
|||
return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIAccessible> accessible;
|
||||
nsAccessNode::GetAccService()->GetAccessibleFor(mReasonNode,
|
||||
getter_AddRefs(accessible));
|
||||
GetAccService()->GetAccessibleFor(mReasonNode, getter_AddRefs(accessible));
|
||||
|
||||
return accessible || nsAccUtils::HasAccessibleChildren(mReasonNode);
|
||||
}
|
||||
|
|
|
@ -172,8 +172,7 @@ nsAccUtils::GetPositionAndSizeForXULSelectControlItem(nsIDOMNode *aNode,
|
|||
nsCOMPtr<nsIDOMNode> currNode(do_QueryInterface(currItem));
|
||||
|
||||
nsCOMPtr<nsIAccessible> itemAcc;
|
||||
nsAccessNode::GetAccService()->GetAccessibleFor(currNode,
|
||||
getter_AddRefs(itemAcc));
|
||||
GetAccService()->GetAccessibleFor(currNode, getter_AddRefs(itemAcc));
|
||||
if (!itemAcc ||
|
||||
State(itemAcc) & nsIAccessibleStates::STATE_INVISIBLE) {
|
||||
(*aSetSize)--;
|
||||
|
@ -214,8 +213,7 @@ nsAccUtils::GetPositionAndSizeForXULContainerItem(nsIDOMNode *aNode,
|
|||
container->GetItemAtIndex(index, getter_AddRefs(item));
|
||||
|
||||
nsCOMPtr<nsIAccessible> itemAcc;
|
||||
nsAccessNode::GetAccService()->GetAccessibleFor(item,
|
||||
getter_AddRefs(itemAcc));
|
||||
GetAccService()->GetAccessibleFor(item, getter_AddRefs(itemAcc));
|
||||
|
||||
if (itemAcc) {
|
||||
PRUint32 itemRole = Role(itemAcc);
|
||||
|
@ -236,8 +234,7 @@ nsAccUtils::GetPositionAndSizeForXULContainerItem(nsIDOMNode *aNode,
|
|||
container->GetItemAtIndex(index, getter_AddRefs(item));
|
||||
|
||||
nsCOMPtr<nsIAccessible> itemAcc;
|
||||
nsAccessNode::GetAccService()->GetAccessibleFor(item,
|
||||
getter_AddRefs(itemAcc));
|
||||
GetAccService()->GetAccessibleFor(item, getter_AddRefs(itemAcc));
|
||||
|
||||
if (itemAcc) {
|
||||
PRUint32 itemRole = Role(itemAcc);
|
||||
|
@ -524,8 +521,7 @@ already_AddRefed<nsIAccessible>
|
|||
nsAccUtils::GetMultiSelectableContainer(nsIDOMNode *aNode)
|
||||
{
|
||||
nsCOMPtr<nsIAccessible> accessible;
|
||||
nsAccessNode::GetAccService()->GetAccessibleFor(aNode,
|
||||
getter_AddRefs(accessible));
|
||||
GetAccService()->GetAccessibleFor(aNode, getter_AddRefs(accessible));
|
||||
|
||||
nsCOMPtr<nsIAccessible> container =
|
||||
GetSelectableContainer(accessible, State(accessible));
|
||||
|
@ -573,25 +569,20 @@ nsAccUtils::GetTextAccessibleFromSelection(nsISelection *aSelection,
|
|||
nsCOMPtr<nsIDOMNode> resultNode =
|
||||
nsCoreUtils::GetDOMNodeFromDOMPoint(focusNode, focusOffset);
|
||||
|
||||
nsIAccessibilityService *accService = nsAccessNode::GetAccService();
|
||||
|
||||
// Get text accessible containing the result node.
|
||||
while (resultNode) {
|
||||
// Make sure to get the correct starting node for selection events inside
|
||||
// XBL content trees.
|
||||
nsCOMPtr<nsIDOMNode> relevantNode;
|
||||
nsresult rv = accService->
|
||||
GetRelevantContentNodeFor(resultNode, getter_AddRefs(relevantNode));
|
||||
if (NS_FAILED(rv))
|
||||
return nsnull;
|
||||
|
||||
GetAccService()->GetRelevantContentNodeFor(resultNode,
|
||||
getter_AddRefs(relevantNode));
|
||||
if (relevantNode)
|
||||
resultNode.swap(relevantNode);
|
||||
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(resultNode);
|
||||
if (!content || !content->IsNodeOfType(nsINode::eTEXT)) {
|
||||
nsCOMPtr<nsIAccessible> accessible;
|
||||
accService->GetAccessibleFor(resultNode, getter_AddRefs(accessible));
|
||||
GetAccService()->GetAccessibleFor(resultNode, getter_AddRefs(accessible));
|
||||
if (accessible) {
|
||||
nsIAccessibleText *textAcc = nsnull;
|
||||
CallQueryInterface(accessible, &textAcc);
|
||||
|
@ -956,8 +947,7 @@ PRBool
|
|||
nsAccUtils::IsNodeRelevant(nsIDOMNode *aNode)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> relevantNode;
|
||||
nsAccessNode::GetAccService()->GetRelevantContentNodeFor(aNode,
|
||||
getter_AddRefs(relevantNode));
|
||||
GetAccService()->GetRelevantContentNodeFor(aNode, getter_AddRefs(relevantNode));
|
||||
return aNode == relevantNode;
|
||||
}
|
||||
|
||||
|
|
|
@ -82,12 +82,6 @@ nsAccessNodeHashtable nsAccessNode::gGlobalDocAccessibleCache;
|
|||
|
||||
nsApplicationAccessibleWrap *nsAccessNode::gApplicationAccessible = nsnull;
|
||||
|
||||
nsIAccessibilityService*
|
||||
nsAccessNode::GetAccService()
|
||||
{
|
||||
return nsAccessibilityService::GetAccessibilityService();
|
||||
}
|
||||
|
||||
/*
|
||||
* Class nsAccessNode
|
||||
*/
|
||||
|
@ -157,15 +151,12 @@ nsAccessNode::Init()
|
|||
if (presShell) {
|
||||
nsCOMPtr<nsIDOMNode> docNode(do_QueryInterface(presShell->GetDocument()));
|
||||
if (docNode) {
|
||||
nsIAccessibilityService *accService = GetAccService();
|
||||
if (accService) {
|
||||
nsCOMPtr<nsIAccessible> accessible;
|
||||
accService->GetAccessibleInShell(docNode, presShell,
|
||||
GetAccService()->GetAccessibleInShell(docNode, presShell,
|
||||
getter_AddRefs(accessible));
|
||||
docAccessible = do_QueryInterface(accessible);
|
||||
}
|
||||
}
|
||||
}
|
||||
NS_ASSERTION(docAccessible, "Cannot cache new nsAccessNode");
|
||||
if (!docAccessible) {
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -473,15 +464,13 @@ nsAccessNode::MakeAccessNode(nsIDOMNode *aNode, nsIAccessNode **aAccessNode)
|
|||
{
|
||||
*aAccessNode = nsnull;
|
||||
|
||||
nsIAccessibilityService *accService = GetAccService();
|
||||
NS_ENSURE_TRUE(accService, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIAccessNode> accessNode;
|
||||
accService->GetCachedAccessNode(aNode, mWeakShell, getter_AddRefs(accessNode));
|
||||
GetAccService()->GetCachedAccessNode(aNode, mWeakShell,
|
||||
getter_AddRefs(accessNode));
|
||||
|
||||
if (!accessNode) {
|
||||
nsCOMPtr<nsIAccessible> accessible;
|
||||
accService->GetAccessibleInWeakShell(aNode, mWeakShell,
|
||||
GetAccService()->GetAccessibleInWeakShell(aNode, mWeakShell,
|
||||
getter_AddRefs(accessible));
|
||||
|
||||
accessNode = do_QueryInterface(accessible);
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
#include "nsIStringBundle.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "nsInterfaceHashtable.h"
|
||||
#include "nsIAccessibilityService.h"
|
||||
#include "nsAccessibilityService.h"
|
||||
|
||||
class nsIPresShell;
|
||||
class nsPresContext;
|
||||
|
@ -145,7 +145,7 @@ class nsAccessNode: public nsIAccessNode
|
|||
already_AddRefed<nsRootAccessible> GetRootAccessible();
|
||||
|
||||
static nsIDOMNode *gLastFocusedNode;
|
||||
static nsIAccessibilityService* GetAccService();
|
||||
|
||||
already_AddRefed<nsIDOMNode> GetCurrentFocus();
|
||||
|
||||
/**
|
||||
|
|
|
@ -1173,26 +1173,6 @@ nsAccessibilityService::GetAttachedAccessibleFor(nsIDOMNode *aNode,
|
|||
return GetAccessibleFor(aNode, aAccessible);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAccessibilityService::GetAccessibleInWindow(nsIDOMNode *aNode,
|
||||
nsIDOMWindow *aWin,
|
||||
nsIAccessible **aAccessible)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aAccessible);
|
||||
*aAccessible = nsnull;
|
||||
|
||||
NS_ENSURE_ARG(aNode);
|
||||
NS_ENSURE_ARG(aWin);
|
||||
|
||||
nsCOMPtr<nsIWebNavigation> webNav(do_GetInterface(aWin));
|
||||
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(webNav));
|
||||
if (!docShell)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIPresShell> presShell;
|
||||
docShell->GetPresShell(getter_AddRefs(presShell));
|
||||
return GetAccessibleInShell(aNode, presShell, aAccessible);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAccessibilityService::GetAccessibleInShell(nsIDOMNode *aNode,
|
||||
nsIPresShell *aPresShell,
|
||||
nsIAccessible **aAccessible)
|
||||
|
@ -1209,7 +1189,8 @@ NS_IMETHODIMP nsAccessibilityService::GetAccessibleInShell(nsIDOMNode *aNode,
|
|||
nsnull, &isHiddenUnused, aAccessible);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAccessibilityService::GetAccessibleInWeakShell(nsIDOMNode *aNode,
|
||||
nsresult
|
||||
nsAccessibilityService::GetAccessibleInWeakShell(nsIDOMNode *aNode,
|
||||
nsIWeakReference *aWeakShell,
|
||||
nsIAccessible **aAccessible)
|
||||
{
|
||||
|
@ -1272,7 +1253,8 @@ static PRBool HasRelatedContent(nsIContent *aContent)
|
|||
return PR_FALSE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAccessibilityService::GetAccessible(nsIDOMNode *aNode,
|
||||
nsresult
|
||||
nsAccessibilityService::GetAccessible(nsIDOMNode *aNode,
|
||||
nsIPresShell *aPresShell,
|
||||
nsIWeakReference *aWeakShell,
|
||||
nsIFrame *aFrameHint,
|
||||
|
@ -2054,37 +2036,26 @@ nsAccessibilityService::InvalidateSubtreeFor(nsIPresShell *aShell,
|
|||
//////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Return accessibility service; creating one if necessary.
|
||||
*/
|
||||
nsresult
|
||||
nsAccessibilityService::GetAccessibilityService(nsIAccessibilityService** aResult)
|
||||
NS_GetAccessibilityService(nsIAccessibilityService** aResult)
|
||||
{
|
||||
NS_ENSURE_TRUE(aResult, NS_ERROR_NULL_POINTER);
|
||||
*aResult = nsnull;
|
||||
|
||||
if (!gAccessibilityService) {
|
||||
gAccessibilityService = new nsAccessibilityService();
|
||||
NS_ENSURE_TRUE(gAccessibilityService, NS_ERROR_OUT_OF_MEMORY);
|
||||
if (!nsAccessibilityService::gAccessibilityService) {
|
||||
nsAccessibilityService::gAccessibilityService = new nsAccessibilityService();
|
||||
NS_ENSURE_TRUE(nsAccessibilityService::gAccessibilityService, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
gIsShutdown = PR_FALSE;
|
||||
nsAccessibilityService::gIsShutdown = PR_FALSE;
|
||||
}
|
||||
|
||||
NS_ADDREF(*aResult = gAccessibilityService);
|
||||
NS_ADDREF(*aResult = nsAccessibilityService::gAccessibilityService);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIAccessibilityService*
|
||||
nsAccessibilityService::GetAccessibilityService()
|
||||
{
|
||||
NS_ASSERTION(!gIsShutdown,
|
||||
"Going to deal with shutdown accessibility service!");
|
||||
return gAccessibilityService;
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_GetAccessibilityService(nsIAccessibilityService** aResult)
|
||||
{
|
||||
return nsAccessibilityService::GetAccessibilityService(aResult);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsAccessibilityService::GetAccessibleForDeckChildren(nsIDOMNode *aNode, nsIAccessible** aAccessible)
|
||||
{
|
||||
|
|
|
@ -81,21 +81,35 @@ public:
|
|||
static nsresult GetShellFromNode(nsIDOMNode *aNode,
|
||||
nsIWeakReference **weakShell);
|
||||
|
||||
/**
|
||||
* Return accessibility service (static instance of this class).
|
||||
*/
|
||||
static nsresult GetAccessibilityService(nsIAccessibilityService** aResult);
|
||||
|
||||
/**
|
||||
* Return cached accessibility service.
|
||||
*/
|
||||
static nsIAccessibilityService* GetAccessibilityService();
|
||||
|
||||
/**
|
||||
* Indicates whether accessibility service was shutdown.
|
||||
*/
|
||||
static PRBool gIsShutdown;
|
||||
|
||||
/**
|
||||
* Return an accessible for the given DOM node.
|
||||
*
|
||||
* @param aNode [in] the given node
|
||||
* @param aPresShell [in] the pres shell of the node
|
||||
* @param aWeakShell [in] the weak shell for the pres shell
|
||||
* @param aFrameHint [in] the frame of the given node
|
||||
* @param aIsHidden [out] indicates whether the node's frame is hidden
|
||||
*/
|
||||
nsresult GetAccessible(nsIDOMNode *aNode, nsIPresShell *aPresShell,
|
||||
nsIWeakReference *aWeakShell, nsIFrame *aFrameHint,
|
||||
PRBool *aIsHidden, nsIAccessible **aAccessible);
|
||||
|
||||
/**
|
||||
* Return an accessible for a DOM node in the given pres shell.
|
||||
*
|
||||
* @param aNode [in] the given node.
|
||||
* @param aPresShell [in] the presentation shell of the given node.
|
||||
* @param aAccessible [out] the nsIAccessible for the given node.
|
||||
*/
|
||||
nsresult GetAccessibleInWeakShell(nsIDOMNode *aNode,
|
||||
nsIWeakReference *aPresShell,
|
||||
nsIAccessible **aAccessible);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Return presentation shell, DOM node for the given frame.
|
||||
|
@ -170,10 +184,24 @@ private:
|
|||
*/
|
||||
void ProcessDocLoadEvent(nsIWebProgress *aWebProgress, PRUint32 aEventType);
|
||||
|
||||
friend nsAccessibilityService* GetAccService();
|
||||
|
||||
friend nsresult NS_GetAccessibilityService(nsIAccessibilityService** aResult);
|
||||
|
||||
|
||||
NS_DECL_RUNNABLEMETHOD_ARG2(nsAccessibilityService, ProcessDocLoadEvent,
|
||||
nsCOMPtr<nsIWebProgress>, PRUint32)
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the accessibility service instance. (Handy global function)
|
||||
*/
|
||||
inline nsAccessibilityService*
|
||||
GetAccService()
|
||||
{
|
||||
return nsAccessibilityService::gAccessibilityService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map nsIAccessibleRole constants to strings. Used by
|
||||
* nsIAccessibleRetrieval::getStringRole() method.
|
||||
|
|
|
@ -3096,13 +3096,13 @@ nsAccessible::GetSiblingAtOffset(PRInt32 aOffset, nsresult* aError)
|
|||
already_AddRefed<nsIAccessible>
|
||||
nsAccessible::GetFirstAvailableAccessible(nsIDOMNode *aStartNode)
|
||||
{
|
||||
nsIAccessibilityService *accService = GetAccService();
|
||||
nsCOMPtr<nsIAccessible> accessible;
|
||||
nsCOMPtr<nsIDOMTreeWalker> walker;
|
||||
nsCOMPtr<nsIDOMNode> currentNode(aStartNode);
|
||||
|
||||
while (currentNode) {
|
||||
accService->GetAccessibleInWeakShell(currentNode, mWeakShell, getter_AddRefs(accessible)); // AddRef'd
|
||||
GetAccService()->GetAccessibleInWeakShell(currentNode, mWeakShell,
|
||||
getter_AddRefs(accessible));
|
||||
if (accessible)
|
||||
return accessible.forget();
|
||||
|
||||
|
|
|
@ -46,11 +46,11 @@
|
|||
#include "nsIContent.h"
|
||||
#include "nsIDOMXULElement.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsAccessibilityService.h"
|
||||
#include "nsWeakReference.h"
|
||||
|
||||
nsAccessibleTreeWalker::nsAccessibleTreeWalker(nsIWeakReference* aPresShell, nsIDOMNode* aNode, PRBool aWalkAnonContent):
|
||||
mWeakShell(aPresShell),
|
||||
mAccService(do_GetService("@mozilla.org/accessibilityService;1")),
|
||||
mWalkAnonContent(aWalkAnonContent)
|
||||
{
|
||||
mState.domNode = aNode;
|
||||
|
@ -294,14 +294,10 @@ nsAccessibleTreeWalker::WalkFrames()
|
|||
*/
|
||||
PRBool nsAccessibleTreeWalker::GetAccessible()
|
||||
{
|
||||
if (!mAccService) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
mState.accessible = nsnull;
|
||||
nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(mWeakShell));
|
||||
|
||||
mAccService->GetAccessible(mState.domNode, presShell, mWeakShell,
|
||||
GetAccService()->GetAccessible(mState.domNode, presShell, mWeakShell,
|
||||
mState.frame.GetFrame(), &mState.isHidden,
|
||||
getter_AddRefs(mState.accessible));
|
||||
|
||||
|
|
|
@ -48,7 +48,6 @@
|
|||
#include "nsIAccessible.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIDOMNodeList.h"
|
||||
#include "nsIAccessibilityService.h"
|
||||
#include "nsIWeakReference.h"
|
||||
#include "nsIFrame.h"
|
||||
|
||||
|
@ -132,7 +131,6 @@ protected:
|
|||
void GetNextDOMNode();
|
||||
|
||||
nsCOMPtr<nsIWeakReference> mWeakShell;
|
||||
nsCOMPtr<nsIAccessibilityService> mAccService;
|
||||
PRBool mWalkAnonContent;
|
||||
};
|
||||
|
||||
|
|
|
@ -2113,9 +2113,6 @@ nsDocAccessible::GetAccessibleInParentChain(nsIDOMNode *aNode,
|
|||
nsCOMPtr<nsIDOMNode> currentNode(aNode), parentNode;
|
||||
nsCOMPtr<nsIAccessNode> accessNode;
|
||||
|
||||
nsIAccessibilityService *accService = GetAccService();
|
||||
NS_ENSURE_TRUE(accService, NS_ERROR_FAILURE);
|
||||
|
||||
do {
|
||||
currentNode->GetParentNode(getter_AddRefs(parentNode));
|
||||
currentNode = parentNode;
|
||||
|
@ -2126,11 +2123,12 @@ nsDocAccessible::GetAccessibleInParentChain(nsIDOMNode *aNode,
|
|||
}
|
||||
|
||||
nsCOMPtr<nsIDOMNode> relevantNode;
|
||||
if (NS_SUCCEEDED(accService->GetRelevantContentNodeFor(currentNode, getter_AddRefs(relevantNode))) && relevantNode) {
|
||||
if (NS_SUCCEEDED(GetAccService()->GetRelevantContentNodeFor(currentNode, getter_AddRefs(relevantNode))) && relevantNode) {
|
||||
currentNode = relevantNode;
|
||||
}
|
||||
if (aCanCreate) {
|
||||
accService->GetAccessibleInWeakShell(currentNode, mWeakShell, aAccessible);
|
||||
GetAccService()->GetAccessibleInWeakShell(currentNode, mWeakShell,
|
||||
aAccessible);
|
||||
}
|
||||
else { // Only return cached accessibles, don't create anything
|
||||
nsCOMPtr<nsIAccessNode> accessNode;
|
||||
|
|
|
@ -89,11 +89,10 @@ nsRelUtils::AddTargetFromContent(PRUint32 aRelationType,
|
|||
if (!aContent)
|
||||
return NS_OK_NO_RELATION_TARGET;
|
||||
|
||||
nsCOMPtr<nsIAccessibilityService> accService = nsAccessNode::GetAccService();
|
||||
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(aContent));
|
||||
|
||||
nsCOMPtr<nsIAccessible> accessible;
|
||||
accService->GetAccessibleFor(node, getter_AddRefs(accessible));
|
||||
GetAccService()->GetAccessibleFor(node, getter_AddRefs(accessible));
|
||||
return AddTarget(aRelationType, aRelation, accessible);
|
||||
}
|
||||
|
||||
|
|
|
@ -152,14 +152,14 @@ nsTextEquivUtils::AppendTextEquivFromContent(nsIAccessible *aInitiatorAcc,
|
|||
nsIFrame *frame = aContent->GetPrimaryFrame();
|
||||
PRBool isVisible = frame && frame->GetStyleVisibility()->IsVisible();
|
||||
|
||||
nsresult rv;
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
PRBool goThroughDOMSubtree = PR_TRUE;
|
||||
|
||||
if (isVisible) {
|
||||
nsCOMPtr<nsIAccessible> accessible;
|
||||
rv = nsAccessNode::GetAccService()->
|
||||
GetAccessibleInShell(DOMNode, shell, getter_AddRefs(accessible));
|
||||
if (NS_SUCCEEDED(rv) && accessible) {
|
||||
GetAccService()->GetAccessibleInShell(DOMNode, shell,
|
||||
getter_AddRefs(accessible));
|
||||
if (accessible) {
|
||||
rv = AppendFromAccessible(accessible, aString);
|
||||
goThroughDOMSubtree = PR_FALSE;
|
||||
}
|
||||
|
|
|
@ -110,8 +110,8 @@ void nsHTMLSelectableAccessible::iterator::CalcSelectionCount(PRInt32 *aSelectio
|
|||
(*aSelectionCount)++;
|
||||
}
|
||||
|
||||
void nsHTMLSelectableAccessible::iterator::AddAccessibleIfSelected(nsIAccessibilityService *aAccService,
|
||||
nsIMutableArray *aSelectedAccessibles,
|
||||
void
|
||||
nsHTMLSelectableAccessible::iterator::AddAccessibleIfSelected(nsIMutableArray *aSelectedAccessibles,
|
||||
nsPresContext *aContext)
|
||||
{
|
||||
PRBool isSelected = PR_FALSE;
|
||||
|
@ -121,7 +121,8 @@ void nsHTMLSelectableAccessible::iterator::AddAccessibleIfSelected(nsIAccessibil
|
|||
mOption->GetSelected(&isSelected);
|
||||
if (isSelected) {
|
||||
nsCOMPtr<nsIDOMNode> optionNode(do_QueryInterface(mOption));
|
||||
aAccService->GetAccessibleInWeakShell(optionNode, mWeakShell, getter_AddRefs(tempAccess));
|
||||
GetAccService()->GetAccessibleInWeakShell(optionNode, mWeakShell,
|
||||
getter_AddRefs(tempAccess));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -129,8 +130,8 @@ void nsHTMLSelectableAccessible::iterator::AddAccessibleIfSelected(nsIAccessibil
|
|||
aSelectedAccessibles->AppendElement(static_cast<nsISupports*>(tempAccess), PR_FALSE);
|
||||
}
|
||||
|
||||
PRBool nsHTMLSelectableAccessible::iterator::GetAccessibleIfSelected(PRInt32 aIndex,
|
||||
nsIAccessibilityService *aAccService,
|
||||
PRBool
|
||||
nsHTMLSelectableAccessible::iterator::GetAccessibleIfSelected(PRInt32 aIndex,
|
||||
nsPresContext *aContext,
|
||||
nsIAccessible **aAccessible)
|
||||
{
|
||||
|
@ -143,7 +144,7 @@ PRBool nsHTMLSelectableAccessible::iterator::GetAccessibleIfSelected(PRInt32 aIn
|
|||
if (isSelected) {
|
||||
if (mSelCount == aIndex) {
|
||||
nsCOMPtr<nsIDOMNode> optionNode(do_QueryInterface(mOption));
|
||||
aAccService->GetAccessibleInWeakShell(optionNode, mWeakShell, aAccessible);
|
||||
GetAccService()->GetAccessibleInWeakShell(optionNode, mWeakShell, aAccessible);
|
||||
return PR_TRUE;
|
||||
}
|
||||
mSelCount++;
|
||||
|
@ -201,10 +202,6 @@ NS_IMETHODIMP nsHTMLSelectableAccessible::GetSelectedChildren(nsIArray **_retval
|
|||
{
|
||||
*_retval = nsnull;
|
||||
|
||||
nsCOMPtr<nsIAccessibilityService> accService(do_GetService("@mozilla.org/accessibilityService;1"));
|
||||
if (!accService)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIMutableArray> selectedAccessibles =
|
||||
do_CreateInstance(NS_ARRAY_CONTRACTID);
|
||||
NS_ENSURE_STATE(selectedAccessibles);
|
||||
|
@ -215,7 +212,7 @@ NS_IMETHODIMP nsHTMLSelectableAccessible::GetSelectedChildren(nsIArray **_retval
|
|||
|
||||
nsHTMLSelectableAccessible::iterator iter(this, mWeakShell);
|
||||
while (iter.Advance())
|
||||
iter.AddAccessibleIfSelected(accService, selectedAccessibles, context);
|
||||
iter.AddAccessibleIfSelected(selectedAccessibles, context);
|
||||
|
||||
PRUint32 uLength = 0;
|
||||
selectedAccessibles->GetLength(&uLength);
|
||||
|
@ -231,17 +228,13 @@ NS_IMETHODIMP nsHTMLSelectableAccessible::RefSelection(PRInt32 aIndex, nsIAccess
|
|||
{
|
||||
*_retval = nsnull;
|
||||
|
||||
nsCOMPtr<nsIAccessibilityService> accService(do_GetService("@mozilla.org/accessibilityService;1"));
|
||||
if (!accService)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsPresContext *context = GetPresContext();
|
||||
if (!context)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsHTMLSelectableAccessible::iterator iter(this, mWeakShell);
|
||||
while (iter.Advance())
|
||||
if (iter.GetAccessibleIfSelected(aIndex, accService, context, _retval))
|
||||
if (iter.GetAccessibleIfSelected(aIndex, context, _retval))
|
||||
return NS_OK;
|
||||
|
||||
// No matched item found
|
||||
|
@ -426,7 +419,6 @@ nsHTMLSelectListAccessible::CacheOptSiblings(nsIContent *aParentContent)
|
|||
nsHTMLSelectOptionAccessible::nsHTMLSelectOptionAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell):
|
||||
nsHyperTextAccessibleWrap(aDOMNode, aShell)
|
||||
{
|
||||
nsCOMPtr<nsIAccessibilityService> accService(do_GetService("@mozilla.org/accessibilityService;1"));
|
||||
nsCOMPtr<nsIDOMNode> parentNode;
|
||||
aDOMNode->GetParentNode(getter_AddRefs(parentNode));
|
||||
nsCOMPtr<nsIAccessible> parentAccessible;
|
||||
|
@ -436,7 +428,8 @@ nsHyperTextAccessibleWrap(aDOMNode, aShell)
|
|||
// GetParent would normally return. This is because the
|
||||
// nsHTMLComboboxListAccessible is inserted into the accessible hierarchy
|
||||
// where there is no DOM node for it.
|
||||
accService->GetAccessibleInWeakShell(parentNode, mWeakShell, getter_AddRefs(parentAccessible));
|
||||
GetAccService()->GetAccessibleInWeakShell(parentNode, mWeakShell,
|
||||
getter_AddRefs(parentAccessible));
|
||||
if (parentAccessible) {
|
||||
if (nsAccUtils::RoleInternal(parentAccessible) ==
|
||||
nsIAccessibleRole::ROLE_COMBOBOX) {
|
||||
|
@ -839,16 +832,13 @@ nsIContent* nsHTMLSelectOptionAccessible::GetSelectState(PRUint32* aState,
|
|||
|
||||
nsCOMPtr<nsIDOMNode> selectNode(do_QueryInterface(content));
|
||||
if (selectNode) {
|
||||
nsCOMPtr<nsIAccessibilityService> accService = GetAccService();
|
||||
if (accService) {
|
||||
nsCOMPtr<nsIAccessible> selAcc;
|
||||
accService->GetAccessibleFor(selectNode, getter_AddRefs(selAcc));
|
||||
GetAccService()->GetAccessibleFor(selectNode, getter_AddRefs(selAcc));
|
||||
if (selAcc) {
|
||||
selAcc->GetState(aState, aExtraState);
|
||||
return content;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
|
@ -1026,13 +1016,12 @@ nsHTMLComboboxAccessible::GetFocusedOptionAccessible()
|
|||
}
|
||||
nsCOMPtr<nsIDOMNode> focusedOptionNode;
|
||||
nsHTMLSelectOptionAccessible::GetFocusedOptionNode(mDOMNode, getter_AddRefs(focusedOptionNode));
|
||||
nsIAccessibilityService *accService = GetAccService();
|
||||
if (!focusedOptionNode || !accService) {
|
||||
if (!focusedOptionNode) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsIAccessible *optionAccessible;
|
||||
accService->GetAccessibleInWeakShell(focusedOptionNode, mWeakShell,
|
||||
GetAccService()->GetAccessibleInWeakShell(focusedOptionNode, mWeakShell,
|
||||
&optionAccessible);
|
||||
return optionAccessible;
|
||||
}
|
||||
|
|
|
@ -45,7 +45,6 @@
|
|||
#include "nsIDOMHTMLOptionsCollection.h"
|
||||
#include "nsIDOMHTMLOptionElement.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIAccessibilityService.h"
|
||||
#include "nsAccessibleTreeWalker.h"
|
||||
|
||||
class nsIMutableArray;
|
||||
|
@ -104,10 +103,10 @@ protected:
|
|||
|
||||
void CalcSelectionCount(PRInt32 *aSelectionCount);
|
||||
void Select(PRBool aSelect);
|
||||
void AddAccessibleIfSelected(nsIAccessibilityService *aAccService,
|
||||
nsIMutableArray *aSelectedAccessibles,
|
||||
void AddAccessibleIfSelected(nsIMutableArray *aSelectedAccessibles,
|
||||
nsPresContext *aContext);
|
||||
PRBool GetAccessibleIfSelected(PRInt32 aIndex, nsIAccessibilityService *aAccService, nsPresContext *aContext, nsIAccessible **_retval);
|
||||
PRBool GetAccessibleIfSelected(PRInt32 aIndex, nsPresContext *aContext,
|
||||
nsIAccessible **aAccessible);
|
||||
|
||||
PRBool Advance();
|
||||
};
|
||||
|
|
|
@ -39,7 +39,6 @@
|
|||
#include "nsAccessNodeWrap.h"
|
||||
#include "ISimpleDOMNode_i.c"
|
||||
#include "nsAccessibilityAtoms.h"
|
||||
#include "nsIAccessibilityService.h"
|
||||
#include "nsIAccessible.h"
|
||||
#include "nsAttrName.h"
|
||||
#include "nsIDocument.h"
|
||||
|
@ -411,13 +410,10 @@ ISimpleDOMNode* nsAccessNodeWrap::MakeAccessNode(nsIDOMNode *node)
|
|||
if (!doc)
|
||||
return NULL;
|
||||
|
||||
nsCOMPtr<nsIAccessibilityService> accService(do_GetService("@mozilla.org/accessibilityService;1"));
|
||||
if (!accService)
|
||||
return NULL;
|
||||
|
||||
ISimpleDOMNode *iNode = NULL;
|
||||
nsCOMPtr<nsIAccessible> nsAcc;
|
||||
accService->GetAccessibleInWeakShell(node, mWeakShell, getter_AddRefs(nsAcc));
|
||||
GetAccService()->GetAccessibleInWeakShell(node, mWeakShell,
|
||||
getter_AddRefs(nsAcc));
|
||||
if (nsAcc) {
|
||||
nsCOMPtr<nsIAccessNode> accessNode(do_QueryInterface(nsAcc));
|
||||
NS_ASSERTION(accessNode, "nsIAccessible impl does not inherit from nsIAccessNode");
|
||||
|
|
|
@ -125,7 +125,6 @@ nsXFormsAccessible::CacheSelectChildren(nsIDOMNode *aContainerNode)
|
|||
nsCOMPtr<nsIAccessible> accessible;
|
||||
nsRefPtr<nsAccessible> acc;
|
||||
|
||||
PRUint32 childLength = 0;
|
||||
for (PRUint32 index = 0; index < length; index++) {
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
children->Item(index, getter_AddRefs(child));
|
||||
|
|
|
@ -120,9 +120,6 @@ NS_IMETHODIMP nsXULSelectableAccessible::GetSelectedChildren(nsIArray **aChildre
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAccessibilityService> accService = GetAccService();
|
||||
NS_ENSURE_TRUE(accService, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIMutableArray> selectedAccessibles =
|
||||
do_CreateInstance(NS_ARRAY_CONTRACTID);
|
||||
NS_ENSURE_STATE(selectedAccessibles);
|
||||
|
@ -138,7 +135,7 @@ NS_IMETHODIMP nsXULSelectableAccessible::GetSelectedChildren(nsIArray **aChildre
|
|||
nsCOMPtr<nsIDOMXULSelectControlItemElement> selectedItem;
|
||||
xulMultiSelect->GetSelectedItem(index, getter_AddRefs(selectedItem));
|
||||
nsCOMPtr<nsIDOMNode> selectedNode(do_QueryInterface(selectedItem));
|
||||
accService->GetAccessibleInWeakShell(selectedNode, mWeakShell,
|
||||
GetAccService()->GetAccessibleInWeakShell(selectedNode, mWeakShell,
|
||||
getter_AddRefs(selectedAccessible));
|
||||
if (selectedAccessible)
|
||||
selectedAccessibles->AppendElement(selectedAccessible, PR_FALSE);
|
||||
|
@ -149,7 +146,7 @@ NS_IMETHODIMP nsXULSelectableAccessible::GetSelectedChildren(nsIArray **aChildre
|
|||
mSelectControl->GetSelectedItem(getter_AddRefs(selectedItem));
|
||||
nsCOMPtr<nsIDOMNode> selectedNode(do_QueryInterface(selectedItem));
|
||||
if(selectedNode) {
|
||||
accService->GetAccessibleInWeakShell(selectedNode, mWeakShell,
|
||||
GetAccService()->GetAccessibleInWeakShell(selectedNode, mWeakShell,
|
||||
getter_AddRefs(selectedAccessible));
|
||||
if (selectedAccessible)
|
||||
selectedAccessibles->AppendElement(selectedAccessible, PR_FALSE);
|
||||
|
@ -183,15 +180,13 @@ NS_IMETHODIMP nsXULSelectableAccessible::RefSelection(PRInt32 aIndex, nsIAccessi
|
|||
mSelectControl->GetSelectedItem(getter_AddRefs(selectedItem));
|
||||
|
||||
if (selectedItem) {
|
||||
nsCOMPtr<nsIAccessibilityService> accService = GetAccService();
|
||||
if (accService) {
|
||||
accService->GetAccessibleInWeakShell(selectedItem, mWeakShell, aAccessible);
|
||||
GetAccService()->GetAccessibleInWeakShell(selectedItem, mWeakShell,
|
||||
aAccessible);
|
||||
if (*aAccessible) {
|
||||
NS_ADDREF(*aAccessible);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -354,8 +349,8 @@ nsXULMenuitemAccessible::GetStateInternal(PRUint32 *aState,
|
|||
grandParentAcc->GetState(&grandParentState, &grandParentExtState);
|
||||
*aState &= ~(nsIAccessibleStates::STATE_OFFSCREEN |
|
||||
nsIAccessibleStates::STATE_INVISIBLE);
|
||||
*aState |= grandParentState & nsIAccessibleStates::STATE_OFFSCREEN |
|
||||
grandParentState & nsIAccessibleStates::STATE_INVISIBLE;
|
||||
*aState |= (grandParentState & nsIAccessibleStates::STATE_OFFSCREEN) |
|
||||
(grandParentState & nsIAccessibleStates::STATE_INVISIBLE);
|
||||
if (aExtraState) {
|
||||
*aExtraState |=
|
||||
grandParentExtState & nsIAccessibleStates::EXT_STATE_OPAQUE;
|
||||
|
|
|
@ -40,6 +40,10 @@
|
|||
display: none;
|
||||
}
|
||||
|
||||
tabpanels {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
%ifdef MOZ_WIDGET_GTK2
|
||||
/* Favicons override the "images-in-menus" metric in xul.css */
|
||||
.alltabs-item > .menu-iconic-left {
|
||||
|
|
|
@ -1335,6 +1335,14 @@ SessionStoreService.prototype = {
|
|||
catch (ex) { debug(ex); }
|
||||
}
|
||||
|
||||
if (aEntry.docIdentifier) {
|
||||
entry.docIdentifier = aEntry.docIdentifier;
|
||||
}
|
||||
|
||||
if (aEntry.stateData) {
|
||||
entry.stateData = aEntry.stateData;
|
||||
}
|
||||
|
||||
if (!(aEntry instanceof Ci.nsISHContainer)) {
|
||||
return entry;
|
||||
}
|
||||
|
@ -2038,9 +2046,11 @@ SessionStoreService.prototype = {
|
|||
delete this._windows[aWindow.__SSi]._restoring;
|
||||
}
|
||||
|
||||
// helper hash for ensuring unique frame IDs
|
||||
// helper hashes for ensuring unique frame IDs and unique document
|
||||
// identifiers.
|
||||
var idMap = { used: {} };
|
||||
this.restoreHistory(aWindow, aTabs, aTabData, idMap);
|
||||
var docIdentMap = {};
|
||||
this.restoreHistory(aWindow, aTabs, aTabData, idMap, docIdentMap);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -2054,7 +2064,8 @@ SessionStoreService.prototype = {
|
|||
* @param aIdMap
|
||||
* Hash for ensuring unique frame IDs
|
||||
*/
|
||||
restoreHistory: function sss_restoreHistory(aWindow, aTabs, aTabData, aIdMap) {
|
||||
restoreHistory:
|
||||
function sss_restoreHistory(aWindow, aTabs, aTabData, aIdMap, aDocIdentMap) {
|
||||
var _this = this;
|
||||
while (aTabs.length > 0 && (!aTabData[0]._tabStillLoading || !aTabs[0].parentNode)) {
|
||||
aTabs.shift(); // this tab got removed before being completely restored
|
||||
|
@ -2090,7 +2101,8 @@ SessionStoreService.prototype = {
|
|||
//XXXzpao Wallpaper patch for bug 514751
|
||||
if (!tabData.entries[i].url)
|
||||
continue;
|
||||
history.addEntry(this._deserializeHistoryEntry(tabData.entries[i], aIdMap), true);
|
||||
history.addEntry(this._deserializeHistoryEntry(tabData.entries[i],
|
||||
aIdMap, aDocIdentMap), true);
|
||||
}
|
||||
|
||||
// make sure to reset the capabilities and attributes, in case this tab gets reused
|
||||
|
@ -2152,7 +2164,9 @@ SessionStoreService.prototype = {
|
|||
browser.loadURI(tabData.userTypedValue, null, null, true);
|
||||
}
|
||||
|
||||
aWindow.setTimeout(function(){ _this.restoreHistory(aWindow, aTabs, aTabData, aIdMap); }, 0);
|
||||
aWindow.setTimeout(function(){
|
||||
_this.restoreHistory(aWindow, aTabs, aTabData, aIdMap, aDocIdentMap);
|
||||
}, 0);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -2163,7 +2177,9 @@ SessionStoreService.prototype = {
|
|||
* Hash for ensuring unique frame IDs
|
||||
* @returns nsISHEntry
|
||||
*/
|
||||
_deserializeHistoryEntry: function sss_deserializeHistoryEntry(aEntry, aIdMap) {
|
||||
_deserializeHistoryEntry:
|
||||
function sss_deserializeHistoryEntry(aEntry, aIdMap, aDocIdentMap) {
|
||||
|
||||
var shEntry = Cc["@mozilla.org/browser/session-history-entry;1"].
|
||||
createInstance(Ci.nsISHEntry);
|
||||
|
||||
|
@ -2196,6 +2212,10 @@ SessionStoreService.prototype = {
|
|||
shEntry.ID = id;
|
||||
}
|
||||
|
||||
if (aEntry.stateData) {
|
||||
shEntry.stateData = aEntry.stateData;
|
||||
}
|
||||
|
||||
if (aEntry.scroll) {
|
||||
var scrollPos = (aEntry.scroll || "0,0").split(",");
|
||||
scrollPos = [parseInt(scrollPos[0]) || 0, parseInt(scrollPos[1]) || 0];
|
||||
|
@ -2216,6 +2236,28 @@ SessionStoreService.prototype = {
|
|||
shEntry.postData = stream;
|
||||
}
|
||||
|
||||
if (aEntry.docIdentifier) {
|
||||
// Get a new document identifier for this entry to ensure that history
|
||||
// entries after a session restore are considered to have different
|
||||
// documents from the history entries before the session restore.
|
||||
// Document identifiers are 64-bit ints, so JS will loose precision and
|
||||
// start assigning all entries the same doc identifier if these ever get
|
||||
// large enough.
|
||||
//
|
||||
// It's a potential security issue if document identifiers aren't
|
||||
// globally unique, but shEntry.setUniqueDocIdentifier() below guarantees
|
||||
// that we won't re-use a doc identifier within a given instance of the
|
||||
// application.
|
||||
let ident = aDocIdentMap[aEntry.docIdentifier];
|
||||
if (!ident) {
|
||||
shEntry.setUniqueDocIdentifier();
|
||||
aDocIdentMap[aEntry.docIdentifier] = shEntry.docIdentifier;
|
||||
}
|
||||
else {
|
||||
shEntry.docIdentifier = ident;
|
||||
}
|
||||
}
|
||||
|
||||
if (aEntry.owner_b64) { // Firefox 3
|
||||
var ownerInput = Cc["@mozilla.org/io/string-input-stream;1"].
|
||||
createInstance(Ci.nsIStringInputStream);
|
||||
|
@ -2237,7 +2279,8 @@ SessionStoreService.prototype = {
|
|||
//XXXzpao Wallpaper patch for bug 514751
|
||||
if (!aEntry.children[i].url)
|
||||
continue;
|
||||
shEntry.AddChild(this._deserializeHistoryEntry(aEntry.children[i], aIdMap), i);
|
||||
shEntry.AddChild(this._deserializeHistoryEntry(aEntry.children[i], aIdMap,
|
||||
aDocIdentMap), i);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -108,6 +108,7 @@ _BROWSER_TEST_FILES = \
|
|||
browser_491577.js \
|
||||
browser_493467.js \
|
||||
browser_495495.js \
|
||||
browser_500328.js \
|
||||
browser_506482.js \
|
||||
browser_514751.js \
|
||||
browser_522545.js \
|
||||
|
|
|
@ -0,0 +1,135 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is sessionstore test code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Justin Lebar <justin.lebar@gmail.com>
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
function checkState(tab) {
|
||||
// Go back and then forward, and make sure that the state objects received
|
||||
// from the popState event are as we expect them to be.
|
||||
//
|
||||
// We also add a node to the document's body when after going back and make
|
||||
// sure it's still there after we go forward -- this is to test that the two
|
||||
// history entries correspond to the same document.
|
||||
|
||||
let popStateCount = 0;
|
||||
|
||||
tab.linkedBrowser.addEventListener("popstate", function(aEvent) {
|
||||
let contentWindow = tab.linkedBrowser.contentWindow;
|
||||
if (popStateCount == 0) {
|
||||
popStateCount++;
|
||||
ok(aEvent.state, "Event should have a state property.");
|
||||
is(JSON.stringify(aEvent.state), JSON.stringify({obj1:1}),
|
||||
"first popstate object.");
|
||||
|
||||
// Add a node with id "new-elem" to the document.
|
||||
let doc = contentWindow.document;
|
||||
ok(!doc.getElementById("new-elem"),
|
||||
"doc shouldn't contain new-elem before we add it.");
|
||||
let elem = doc.createElement("div");
|
||||
elem.id = "new-elem";
|
||||
doc.body.appendChild(elem);
|
||||
|
||||
contentWindow.history.forward();
|
||||
}
|
||||
else if (popStateCount == 1) {
|
||||
popStateCount++;
|
||||
is(JSON.stringify(aEvent.state), JSON.stringify({obj3:3}),
|
||||
"second popstate object.");
|
||||
|
||||
// Make sure that the new-elem node is present in the document. If it's
|
||||
// not, then this history entry has a different doc identifier than the
|
||||
// previous entry, which is bad.
|
||||
let doc = contentWindow.document;
|
||||
let newElem = doc.getElementById("new-elem");
|
||||
ok(newElem, "doc should contain new-elem.");
|
||||
newElem.parentNode.removeChild(newElem);
|
||||
ok(!doc.getElementById("new-elem"), "new-elem should be removed.");
|
||||
|
||||
// Clean up after ourselves and finish the test.
|
||||
tab.linkedBrowser.removeEventListener("popstate", arguments.callee, false);
|
||||
gBrowser.removeTab(tab);
|
||||
finish();
|
||||
}
|
||||
}, true);
|
||||
|
||||
tab.linkedBrowser.contentWindow.history.back();
|
||||
}
|
||||
|
||||
function test() {
|
||||
// Tests session restore functionality of history.pushState and
|
||||
// history.replaceState(). (Bug 500328)
|
||||
|
||||
let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
|
||||
waitForExplicitFinish();
|
||||
|
||||
// We open a new blank window, let it load, and then load in
|
||||
// http://example.com. We need to load the blank window first, otherwise the
|
||||
// docshell gets confused and doesn't have a current history entry.
|
||||
let tab = gBrowser.addTab("about:blank");
|
||||
let tabBrowser = tab.linkedBrowser;
|
||||
|
||||
tabBrowser.addEventListener("load", function(aEvent) {
|
||||
tabBrowser.removeEventListener("load", arguments.callee, true);
|
||||
|
||||
tabBrowser.loadURI("http://example.com", null, null);
|
||||
|
||||
tabBrowser.addEventListener("load", function(aEvent) {
|
||||
tabBrowser.removeEventListener("load", arguments.callee, true);
|
||||
|
||||
// After these push/replaceState calls, the window should have three
|
||||
// history entries:
|
||||
// testURL (state object: null) <-- oldest
|
||||
// testURL (state object: {obj1:1})
|
||||
// page2 (state object: {obj3:3}) <-- newest
|
||||
let contentWindow = tab.linkedBrowser.contentWindow;
|
||||
let history = contentWindow.history;
|
||||
history.pushState({obj1:1}, "title-obj1");
|
||||
history.pushState({obj2:2}, "title-obj2", "page2");
|
||||
history.replaceState({obj3:3}, "title-obj3");
|
||||
|
||||
let state = ss.getTabState(tab);
|
||||
|
||||
// In order to make sure that setWindowState actually modifies the
|
||||
// window's state, we modify the state here. checkState will fail if
|
||||
// this change isn't overwritten by setWindowState.
|
||||
history.replaceState({should_be_overwritten:true}, "title-overwritten");
|
||||
|
||||
// Restore the state and make sure it looks right, after giving the event
|
||||
// loop a chance to flush.
|
||||
ss.setTabState(tab, state, true);
|
||||
executeSoon(function() { checkState(tab); });
|
||||
|
||||
}, true);
|
||||
}, true);
|
||||
}
|
|
@ -1111,11 +1111,6 @@ statusbarpanel#statusbar-display {
|
|||
list-style-image: url("chrome://global/skin/icons/notloading_16.png");
|
||||
}
|
||||
|
||||
|
||||
tabpanels {
|
||||
-moz-appearance: none;
|
||||
}
|
||||
|
||||
/* Tabs */
|
||||
.tabbrowser-tab {
|
||||
border: none !important;
|
||||
|
|
|
@ -399,7 +399,6 @@ menubutton:not([disabled="true"]):hover:active {
|
|||
-moz-image-region: rect(23px, 36px, 46px, 0px);
|
||||
}
|
||||
#back-button:hover:active:not([disabled]),
|
||||
#back-button[buttondown="true"]:not([disabled]),
|
||||
#back-button[open="true"] {
|
||||
-moz-image-region: rect(46px, 36px, 69px, 0px);
|
||||
}
|
||||
|
@ -414,7 +413,6 @@ menubutton:not([disabled="true"]):hover:active {
|
|||
-moz-image-region: rect(23px, 72px, 46px, 36px);
|
||||
}
|
||||
#forward-button:hover:active:not([disabled]),
|
||||
#forward-button[buttondown="true"]:not([disabled]),
|
||||
#forward-button[open="true"] {
|
||||
-moz-image-region: rect(46px, 72px, 69px, 36px);
|
||||
}
|
||||
|
@ -1591,10 +1589,6 @@ tabbrowser > tabbox {
|
|||
display: none;
|
||||
}
|
||||
|
||||
tabbrowser > tabbox > tabpanels {
|
||||
-moz-appearance: none !important;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tab Drag and Drop
|
||||
*/
|
||||
|
@ -1782,10 +1776,6 @@ tabbrowser > tabbox > tabpanels {
|
|||
list-style-image: url("chrome://global/skin/icons/closetab-active.png");
|
||||
}
|
||||
|
||||
tabpanels.plain {
|
||||
background-color: #fff !important;
|
||||
}
|
||||
|
||||
/* Bookmarks toolbar */
|
||||
.toolbar-drop-indicator {
|
||||
list-style-image: url(chrome://browser/skin/places/toolbarDropMarker.png);
|
||||
|
|
|
@ -1177,10 +1177,6 @@ statusbarpanel#statusbar-display {
|
|||
border-bottom: 1px solid threedshadow;
|
||||
}
|
||||
|
||||
tabpanels {
|
||||
-moz-appearance: none;
|
||||
}
|
||||
|
||||
/* tabbrowser-tab focus ring */
|
||||
.tabbrowser-tab > .tab-text {
|
||||
border: 1px dotted transparent;
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
interface nsIURI;
|
||||
interface nsIChannel;
|
||||
|
||||
[scriptable, uuid(c0dbfd5e-b7ae-4c18-8674-82492f35d715)]
|
||||
[scriptable, uuid(50eda256-4dd2-4c7c-baed-96983910af9f)]
|
||||
interface nsIScriptSecurityManager : nsIXPCSecurityManager
|
||||
{
|
||||
///////////////// Security Checks //////////////////
|
||||
|
@ -54,14 +54,6 @@ interface nsIScriptSecurityManager : nsIXPCSecurityManager
|
|||
in JSVal aProperty,
|
||||
in PRUint32 aAction);
|
||||
|
||||
/**
|
||||
* Checks whether the running script is allowed to connect to aTargetURI
|
||||
*/
|
||||
[noscript] void checkConnect(in JSContextPtr aJSContext,
|
||||
in nsIURI aTargetURI,
|
||||
in string aClassName,
|
||||
in string aProperty);
|
||||
|
||||
/**
|
||||
* Check that the script currently running in context "cx" can load "uri".
|
||||
*
|
||||
|
|
|
@ -410,8 +410,7 @@ public:
|
|||
|
||||
static nsresult
|
||||
CheckSameOriginPrincipal(nsIPrincipal* aSubject,
|
||||
nsIPrincipal* aObject,
|
||||
PRBool aIsCheckConnect);
|
||||
nsIPrincipal* aObject);
|
||||
static PRUint32
|
||||
HashPrincipalByOrigin(nsIPrincipal* aPrincipal);
|
||||
|
||||
|
@ -458,8 +457,7 @@ private:
|
|||
nsresult
|
||||
CheckSameOriginDOMProp(nsIPrincipal* aSubject,
|
||||
nsIPrincipal* aObject,
|
||||
PRUint32 aAction,
|
||||
PRBool aIsCheckConnect);
|
||||
PRUint32 aAction);
|
||||
|
||||
nsresult
|
||||
LookupPolicy(nsIPrincipal* principal,
|
||||
|
|
|
@ -363,8 +363,7 @@ nsPrincipal::Equals(nsIPrincipal *aOther, PRBool *aResult)
|
|||
// Codebases are equal if they have the same origin.
|
||||
*aResult =
|
||||
NS_SUCCEEDED(nsScriptSecurityManager::CheckSameOriginPrincipal(this,
|
||||
aOther,
|
||||
PR_FALSE));
|
||||
aOther));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -563,34 +563,6 @@ nsScriptSecurityManager::CheckPropertyAccess(JSContext* cx,
|
|||
aClassName, aProperty, nsnull);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptSecurityManager::CheckConnect(JSContext* cx,
|
||||
nsIURI* aTargetURI,
|
||||
const char* aClassName,
|
||||
const char* aPropertyName)
|
||||
{
|
||||
// Get a context if necessary
|
||||
if (!cx)
|
||||
{
|
||||
cx = GetCurrentJSContext();
|
||||
if (!cx)
|
||||
return NS_OK; // No JS context, so allow the load
|
||||
}
|
||||
|
||||
nsresult rv = CheckLoadURIFromScript(cx, aTargetURI);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
JSAutoRequest ar(cx);
|
||||
|
||||
JSString* propertyName = ::JS_InternString(cx, aPropertyName);
|
||||
if (!propertyName)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
return CheckPropertyAccessImpl(nsIXPCSecurityManager::ACCESS_CALL_METHOD, nsnull,
|
||||
cx, nsnull, nsnull, aTargetURI,
|
||||
nsnull, aClassName, STRING_TO_JSVAL(propertyName), nsnull);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptSecurityManager::CheckSameOrigin(JSContext* cx,
|
||||
nsIURI* aTargetURI)
|
||||
|
@ -750,7 +722,7 @@ nsScriptSecurityManager::CheckPropertyAccessImpl(PRUint32 aAction,
|
|||
}
|
||||
if(NS_SUCCEEDED(rv))
|
||||
rv = CheckSameOriginDOMProp(subjectPrincipal, objectPrincipal,
|
||||
aAction, aTargetURI != nsnull);
|
||||
aAction);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -943,8 +915,7 @@ nsScriptSecurityManager::CheckPropertyAccessImpl(PRUint32 aAction,
|
|||
/* static */
|
||||
nsresult
|
||||
nsScriptSecurityManager::CheckSameOriginPrincipal(nsIPrincipal* aSubject,
|
||||
nsIPrincipal* aObject,
|
||||
PRBool aIsCheckConnect)
|
||||
nsIPrincipal* aObject)
|
||||
{
|
||||
/*
|
||||
** Get origin of subject and object and compare.
|
||||
|
@ -952,23 +923,13 @@ nsScriptSecurityManager::CheckSameOriginPrincipal(nsIPrincipal* aSubject,
|
|||
if (aSubject == aObject)
|
||||
return NS_OK;
|
||||
|
||||
// These booleans are only used when !aIsCheckConnect. Default
|
||||
// them to false, and change if that turns out wrong.
|
||||
// Default to false, and change if that turns out wrong.
|
||||
PRBool subjectSetDomain = PR_FALSE;
|
||||
PRBool objectSetDomain = PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIURI> subjectURI;
|
||||
nsCOMPtr<nsIURI> objectURI;
|
||||
|
||||
if (aIsCheckConnect)
|
||||
{
|
||||
// Don't use domain for CheckConnect calls, since that's called for
|
||||
// data-only load checks like XMLHTTPRequest (bug 290100).
|
||||
aSubject->GetURI(getter_AddRefs(subjectURI));
|
||||
aObject->GetURI(getter_AddRefs(objectURI));
|
||||
}
|
||||
else
|
||||
{
|
||||
aSubject->GetDomain(getter_AddRefs(subjectURI));
|
||||
if (!subjectURI) {
|
||||
aSubject->GetURI(getter_AddRefs(subjectURI));
|
||||
|
@ -982,7 +943,6 @@ nsScriptSecurityManager::CheckSameOriginPrincipal(nsIPrincipal* aSubject,
|
|||
} else {
|
||||
objectSetDomain = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (SecurityCompareURIs(subjectURI, objectURI))
|
||||
{ // If either the subject or the object has changed its principal by
|
||||
|
@ -990,12 +950,6 @@ nsScriptSecurityManager::CheckSameOriginPrincipal(nsIPrincipal* aSubject,
|
|||
// done so in order to be considered the same origin. This prevents
|
||||
// DNS spoofing based on document.domain (154930)
|
||||
|
||||
// But this restriction does not apply to CheckConnect calls, since
|
||||
// that's called for data-only load checks like XMLHTTPRequest where
|
||||
// we ignore domain (bug 290100).
|
||||
if (aIsCheckConnect)
|
||||
return NS_OK;
|
||||
|
||||
// If both or neither explicitly set their domain, allow the access
|
||||
if (subjectSetDomain == objectSetDomain)
|
||||
return NS_OK;
|
||||
|
@ -1009,7 +963,7 @@ nsScriptSecurityManager::CheckSameOriginPrincipal(nsIPrincipal* aSubject,
|
|||
|
||||
// It's important that
|
||||
//
|
||||
// CheckSameOriginPrincipal(A, B, PR_FALSE) == NS_OK
|
||||
// CheckSameOriginPrincipal(A, B) == NS_OK
|
||||
//
|
||||
// imply
|
||||
//
|
||||
|
@ -1032,22 +986,14 @@ nsScriptSecurityManager::HashPrincipalByOrigin(nsIPrincipal* aPrincipal)
|
|||
nsresult
|
||||
nsScriptSecurityManager::CheckSameOriginDOMProp(nsIPrincipal* aSubject,
|
||||
nsIPrincipal* aObject,
|
||||
PRUint32 aAction,
|
||||
PRBool aIsCheckConnect)
|
||||
PRUint32 aAction)
|
||||
{
|
||||
nsresult rv;
|
||||
if (aIsCheckConnect) {
|
||||
// Don't do equality compares, just do a same-origin compare,
|
||||
// since the object principal isn't a real principal, just a
|
||||
// GetCodebasePrincipal() on whatever URI we started with.
|
||||
rv = CheckSameOriginPrincipal(aSubject, aObject, aIsCheckConnect);
|
||||
} else {
|
||||
PRBool subsumes;
|
||||
rv = aSubject->Subsumes(aObject, &subsumes);
|
||||
if (NS_SUCCEEDED(rv) && !subsumes) {
|
||||
rv = NS_ERROR_DOM_PROP_ACCESS_DENIED;
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv))
|
||||
return NS_OK;
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
|
||||
interface nsIDOMFileError;
|
||||
|
||||
[scriptable, uuid(0845E8AE-56BD-4F0E-962A-3B3E92638A0B)]
|
||||
[scriptable, uuid(16753172-6890-4e6a-8c10-a7ff30c5ef22)]
|
||||
interface nsIDOMFile : nsISupports
|
||||
{
|
||||
//fileName and fileSize are now deprecated attributes
|
||||
|
@ -47,6 +47,7 @@ interface nsIDOMFile : nsISupports
|
|||
readonly attribute unsigned long long fileSize;
|
||||
|
||||
readonly attribute DOMString name;
|
||||
readonly attribute DOMString mozFullPath;
|
||||
readonly attribute unsigned long long size;
|
||||
readonly attribute DOMString type;
|
||||
|
||||
|
|
|
@ -106,8 +106,8 @@ class nsIBoxObject;
|
|||
|
||||
// IID for the nsIDocument interface
|
||||
#define NS_IDOCUMENT_IID \
|
||||
{ 0xb04d9176, 0xf087, 0x4d3c, \
|
||||
{ 0x87, 0x11, 0x13, 0x9d, 0x19, 0x95, 0x43, 0x55 } }
|
||||
{ 0x6b2f1996, 0x95d4, 0x48db, \
|
||||
{0xaf, 0xd1, 0xfd, 0xaa, 0x75, 0x4c, 0x79, 0x92 } }
|
||||
|
||||
// Flag for AddStyleSheet().
|
||||
#define NS_STYLESHEET_FROM_CATALOG (1 << 0)
|
||||
|
@ -1225,6 +1225,28 @@ public:
|
|||
Doc_Theme_Bright
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the document's pending state object (serialized to JSON), or the
|
||||
* empty string if one doesn't exist.
|
||||
*
|
||||
* This field serves as a waiting place for the history entry's state object:
|
||||
* We set the field's value to the history entry's state object early on in
|
||||
* the load, then after we fire onload we deserialize the field's value and
|
||||
* fire a popstate event containing the resulting object.
|
||||
*/
|
||||
nsAString& GetPendingStateObject()
|
||||
{
|
||||
return mPendingStateObject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the document's pending state object (as serialized to JSON).
|
||||
*/
|
||||
void SetPendingStateObject(nsAString &obj)
|
||||
{
|
||||
mPendingStateObject.Assign(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Doc_Theme_None if there is no lightweight theme specified,
|
||||
* Doc_Theme_Dark for a dark theme, Doc_Theme_Bright for a light theme, and
|
||||
|
@ -1388,6 +1410,8 @@ protected:
|
|||
nsCOMPtr<nsIDocument> mDisplayDocument;
|
||||
|
||||
PRUint32 mEventsSuppressed;
|
||||
|
||||
nsString mPendingStateObject;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocument, NS_IDOCUMENT_IID)
|
||||
|
|
|
@ -407,6 +407,7 @@ nsContentUtils::InitializeEventTable() {
|
|||
{ &nsGkAtoms::onchange, { NS_FORM_CHANGE, EventNameType_HTMLXUL }},
|
||||
{ &nsGkAtoms::onselect, { NS_FORM_SELECTED, EventNameType_HTMLXUL }},
|
||||
{ &nsGkAtoms::onload, { NS_LOAD, EventNameType_All }},
|
||||
{ &nsGkAtoms::onpopstate, { NS_POPSTATE, EventNameType_HTMLXUL }},
|
||||
{ &nsGkAtoms::onunload, { NS_PAGE_UNLOAD,
|
||||
(EventNameType_HTMLXUL | EventNameType_SVGSVG) }},
|
||||
{ &nsGkAtoms::onhashchange, { NS_HASHCHANGE, EventNameType_HTMLXUL }},
|
||||
|
|
|
@ -108,6 +108,16 @@ nsDOMFile::GetName(nsAString &aFileName)
|
|||
return mFile->GetLeafName(aFileName);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMFile::GetMozFullPath(nsAString &aFileName)
|
||||
{
|
||||
if (nsContentUtils::IsCallerTrustedForCapability("UniversalFileRead")) {
|
||||
return mFile->GetPath(aFileName);
|
||||
}
|
||||
aFileName.Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMFile::GetSize(PRUint64 *aFileSize)
|
||||
{
|
||||
|
|
|
@ -46,6 +46,11 @@
|
|||
* Base class for all our document implementations.
|
||||
*/
|
||||
|
||||
#ifdef MOZ_LOGGING
|
||||
// so we can get logging even in release builds
|
||||
#define FORCE_PR_LOG 1
|
||||
#endif
|
||||
#include "prlog.h"
|
||||
#include "plstr.h"
|
||||
#include "prprf.h"
|
||||
|
||||
|
@ -184,13 +189,6 @@ static NS_DEFINE_CID(kDOMEventGroupCID, NS_DOMEVENTGROUP_CID);
|
|||
// FOR CSP (autogenerated by xpidl)
|
||||
#include "nsIContentSecurityPolicy.h"
|
||||
|
||||
|
||||
#ifdef MOZ_LOGGING
|
||||
// so we can get logging even in release builds
|
||||
#define FORCE_PR_LOG 1
|
||||
#endif
|
||||
#include "prlog.h"
|
||||
|
||||
/* Keeps track of whether or not CSP is enabled */
|
||||
static PRBool gCSPEnabled = PR_TRUE;
|
||||
|
||||
|
|
|
@ -650,6 +650,7 @@ GK_ATOM(onkeypress, "onkeypress")
|
|||
GK_ATOM(onkeyup, "onkeyup")
|
||||
GK_ATOM(onLoad, "onLoad")
|
||||
GK_ATOM(onload, "onload")
|
||||
GK_ATOM(onpopstate, "onpopstate")
|
||||
GK_ATOM(only, "only") // this one is not an event
|
||||
GK_ATOM(onmousedown, "onmousedown")
|
||||
GK_ATOM(onmousemove, "onmousemove")
|
||||
|
|
|
@ -2402,9 +2402,13 @@ WebGLContext::ValidateGL()
|
|||
|
||||
//fprintf(stderr, "GL_MAX_VERTEX_ATTRIBS: %d\n", val);
|
||||
|
||||
gl->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_UNITS, &val);
|
||||
// Note: GL_MAX_TEXTURE_UNITS is fixed at 4 for most desktop hardware,
|
||||
// even though the hardware supports much more. The
|
||||
// GL_MAX_{COMBINED_}TEXTURE_IMAGE_UNITS value is the accurate
|
||||
// value. For GLES2, GL_MAX_TEXTURE_UNITS is still correc.t
|
||||
gl->fGetIntegerv(LOCAL_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &val);
|
||||
if (val == 0) {
|
||||
LogMessage("GL_MAX_TEXTURE_UNITS is 0!");
|
||||
LogMessage("GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS is 0!");
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
|
|
@ -82,6 +82,7 @@ CPPSRCS = \
|
|||
nsDOMEventTargetHelper.cpp \
|
||||
nsDOMScrollAreaEvent.cpp \
|
||||
nsDOMTransitionEvent.cpp \
|
||||
nsDOMPopStateEvent.cpp \
|
||||
$(NULL)
|
||||
|
||||
# we don't want the shared lib, but we want to force the creation of a static lib.
|
||||
|
|
|
@ -59,12 +59,13 @@
|
|||
#include "nsIURI.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsIScriptError.h"
|
||||
#include "nsDOMPopStateEvent.h"
|
||||
|
||||
static const char* const sEventNames[] = {
|
||||
"mousedown", "mouseup", "click", "dblclick", "mouseover",
|
||||
"mouseout", "mousemove", "contextmenu", "keydown", "keyup", "keypress",
|
||||
"focus", "blur", "load", "beforeunload", "unload", "hashchange", "abort", "error",
|
||||
"submit", "reset", "change", "select", "input" ,"text",
|
||||
"focus", "blur", "load", "popstate", "beforeunload", "unload", "hashchange",
|
||||
"abort", "error", "submit", "reset", "change", "select", "input", "text",
|
||||
"compositionstart", "compositionend", "popupshowing", "popupshown",
|
||||
"popuphiding", "popuphidden", "close", "command", "broadcast", "commandupdate",
|
||||
"dragenter", "dragover", "dragexit", "dragdrop", "draggesture",
|
||||
|
@ -1328,6 +1329,8 @@ const char* nsDOMEvent::GetEventName(PRUint32 aEventType)
|
|||
return sEventNames[eDOMEvents_close];
|
||||
case NS_LOAD:
|
||||
return sEventNames[eDOMEvents_load];
|
||||
case NS_POPSTATE:
|
||||
return sEventNames[eDOMEvents_popstate];
|
||||
case NS_BEFORE_PAGE_UNLOAD:
|
||||
return sEventNames[eDOMEvents_beforeunload];
|
||||
case NS_PAGE_UNLOAD:
|
||||
|
|
|
@ -58,7 +58,7 @@ class nsDOMEvent : public nsIDOMEvent,
|
|||
{
|
||||
public:
|
||||
|
||||
// Note: this enum must be kept in sync with mEventNames in nsDOMEvent.cpp
|
||||
// Note: this enum must be kept in sync with sEventNames in nsDOMEvent.cpp
|
||||
enum nsDOMEvents {
|
||||
eDOMEvents_mousedown=0,
|
||||
eDOMEvents_mouseup,
|
||||
|
@ -74,6 +74,7 @@ public:
|
|||
eDOMEvents_focus,
|
||||
eDOMEvents_blur,
|
||||
eDOMEvents_load,
|
||||
eDOMEvents_popstate,
|
||||
eDOMEvents_beforeunload,
|
||||
eDOMEvents_unload,
|
||||
eDOMEvents_hashchange,
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is the Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsDOMPopStateEvent.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMPopStateEvent)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(nsDOMPopStateEvent, nsDOMEvent)
|
||||
NS_IMPL_RELEASE_INHERITED(nsDOMPopStateEvent, nsDOMEvent)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMPopStateEvent, nsDOMEvent)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mState)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMPopStateEvent, nsDOMEvent)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mState)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsDOMPopStateEvent)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMPopStateEvent)
|
||||
NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(PopStateEvent)
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent)
|
||||
|
||||
nsDOMPopStateEvent::~nsDOMPopStateEvent()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMPopStateEvent::GetState(nsIVariant **aState)
|
||||
{
|
||||
NS_PRECONDITION(aState, "null state arg");
|
||||
NS_IF_ADDREF(*aState = mState);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMPopStateEvent::InitPopStateEvent(const nsAString &aTypeArg,
|
||||
PRBool aCanBubbleArg,
|
||||
PRBool aCancelableArg,
|
||||
nsIVariant *aStateArg)
|
||||
{
|
||||
nsresult rv = nsDOMEvent::InitEvent(aTypeArg, aCanBubbleArg, aCancelableArg);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mState = aStateArg;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult NS_NewDOMPopStateEvent(nsIDOMEvent** aInstancePtrResult,
|
||||
nsPresContext* aPresContext,
|
||||
nsEvent* aEvent)
|
||||
{
|
||||
nsDOMPopStateEvent* event =
|
||||
new nsDOMPopStateEvent(aPresContext, aEvent);
|
||||
|
||||
if (!event) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
return CallQueryInterface(event, aInstancePtrResult);
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is the Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef nsDOMPopStateEvent_h__
|
||||
#define nsDOMPopStateEvent_h__
|
||||
|
||||
class nsEvent;
|
||||
|
||||
#include "nsIDOMPopStateEvent.h"
|
||||
#include "nsDOMEvent.h"
|
||||
#include "nsIVariant.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
|
||||
class nsDOMPopStateEvent : public nsDOMEvent,
|
||||
public nsIDOMPopStateEvent
|
||||
{
|
||||
public:
|
||||
nsDOMPopStateEvent(nsPresContext* aPresContext, nsEvent* aEvent)
|
||||
: nsDOMEvent(aPresContext, aEvent) // state
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~nsDOMPopStateEvent();
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsDOMPopStateEvent, nsDOMEvent)
|
||||
|
||||
NS_DECL_NSIDOMPOPSTATEEVENT
|
||||
|
||||
NS_FORWARD_TO_NSDOMEVENT
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsIVariant> mState;
|
||||
};
|
||||
|
||||
nsresult NS_NewDOMPopStateEvent(nsIDOMEvent** aInstancePtrResult,
|
||||
nsPresContext* aPresContext,
|
||||
nsEvent* aEvent);
|
||||
|
||||
#endif // nsDOMPopStateEvent_h__
|
|
@ -48,6 +48,7 @@
|
|||
#include "nsFixedSizeAllocator.h"
|
||||
#include "nsINode.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsDOMPopStateEvent.h"
|
||||
|
||||
#define NS_TARGET_CHAIN_FORCE_CONTENT_DISPATCH (1 << 0)
|
||||
#define NS_TARGET_CHAIN_WANTS_WILL_HANDLE_EVENT (1 << 1)
|
||||
|
@ -796,6 +797,8 @@ nsEventDispatcher::CreateEvent(nsPresContext* aPresContext,
|
|||
// is probably wrong!
|
||||
if (aEventType.LowerCaseEqualsLiteral("transitionevent"))
|
||||
return NS_NewDOMTransitionEvent(aDOMEvent, aPresContext, nsnull);
|
||||
if (aEventType.LowerCaseEqualsLiteral("popstateevent"))
|
||||
return NS_NewDOMPopStateEvent(aDOMEvent, aPresContext, nsnull);
|
||||
|
||||
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
|
||||
}
|
||||
|
|
|
@ -692,9 +692,30 @@ nsHTMLDocument::StartDocumentLoad(const char* aCommand,
|
|||
loadAsHtml5 = PR_FALSE;
|
||||
}
|
||||
|
||||
if (!(contentType.EqualsLiteral("text/html") && aCommand && !nsCRT::strcmp(aCommand, "view"))) {
|
||||
if (loadAsHtml5 &&
|
||||
!(contentType.EqualsLiteral("text/html") &&
|
||||
aCommand &&
|
||||
!nsCRT::strcmp(aCommand, "view"))) {
|
||||
loadAsHtml5 = PR_FALSE;
|
||||
}
|
||||
|
||||
// TODO: Proper about:blank treatment is bug 543435
|
||||
if (loadAsHtml5) {
|
||||
// mDocumentURI hasn't been set, yet, so get the URI from the channel
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
aChannel->GetOriginalURI(getter_AddRefs(uri));
|
||||
// Adapted from nsDocShell:
|
||||
// GetSpec can be expensive for some URIs, so check the scheme first.
|
||||
PRBool isAbout = PR_FALSE;
|
||||
if (uri && NS_SUCCEEDED(uri->SchemeIs("about", &isAbout)) && isAbout) {
|
||||
nsCAutoString str;
|
||||
uri->GetSpec(str);
|
||||
if (str.EqualsLiteral("about:blank")) {
|
||||
loadAsHtml5 = PR_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
else {
|
||||
NS_ASSERTION(mIsRegularHTML,
|
||||
|
|
|
@ -44,6 +44,12 @@ namespace mozilla {
|
|||
class SMILBoolType : public nsISMILType
|
||||
{
|
||||
public:
|
||||
// Singleton for nsSMILValue objects to hold onto.
|
||||
static SMILBoolType sSingleton;
|
||||
|
||||
protected:
|
||||
// nsISMILType Methods
|
||||
// -------------------
|
||||
virtual nsresult Init(nsSMILValue& aValue) const;
|
||||
virtual void Destroy(nsSMILValue&) const;
|
||||
virtual nsresult Assign(nsSMILValue& aDest, const nsSMILValue& aSrc) const;
|
||||
|
@ -57,10 +63,11 @@ public:
|
|||
double aUnitDistance,
|
||||
nsSMILValue& aResult) const;
|
||||
|
||||
static SMILBoolType sSingleton;
|
||||
|
||||
private:
|
||||
// Private constructor & destructor: prevent instances beyond my singleton,
|
||||
// and prevent others from deleting my singleton.
|
||||
SMILBoolType() {}
|
||||
~SMILBoolType() {}
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -44,6 +44,12 @@ namespace mozilla {
|
|||
class SMILEnumType : public nsISMILType
|
||||
{
|
||||
public:
|
||||
// Singleton for nsSMILValue objects to hold onto.
|
||||
static SMILEnumType sSingleton;
|
||||
|
||||
protected:
|
||||
// nsISMILType Methods
|
||||
// -------------------
|
||||
virtual nsresult Init(nsSMILValue& aValue) const;
|
||||
virtual void Destroy(nsSMILValue&) const;
|
||||
virtual nsresult Assign(nsSMILValue& aDest, const nsSMILValue& aSrc) const;
|
||||
|
@ -57,10 +63,11 @@ public:
|
|||
double aUnitDistance,
|
||||
nsSMILValue& aResult) const;
|
||||
|
||||
static SMILEnumType sSingleton;
|
||||
|
||||
private:
|
||||
// Private constructor & destructor: prevent instances beyond my singleton,
|
||||
// and prevent others from deleting my singleton.
|
||||
SMILEnumType() {}
|
||||
~SMILEnumType() {}
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -75,7 +75,12 @@ class nsSMILValue;
|
|||
|
||||
class nsISMILType
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Only give the nsSMILValue class access to this interface.
|
||||
*/
|
||||
friend class nsSMILValue;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Initialises aValue and sets it to some identity value such that adding
|
||||
* aValue to another value of the same type has no effect.
|
||||
|
@ -211,11 +216,12 @@ public:
|
|||
double aUnitDistance,
|
||||
nsSMILValue& aResult) const = 0;
|
||||
|
||||
/*
|
||||
* Virtual destructor: Nothing to do here, but subclasses
|
||||
* may need it.
|
||||
/**
|
||||
* Protected destructor, to ensure that no one accidentally deletes an
|
||||
* instance of this class.
|
||||
* (The only instances in existence should be singletons - one per subclass.)
|
||||
*/
|
||||
virtual ~nsISMILType() {};
|
||||
~nsISMILType() {}
|
||||
};
|
||||
|
||||
#endif // NS_ISMILTYPE_H_
|
||||
|
|
|
@ -46,13 +46,16 @@
|
|||
#include "nsIContent.h"
|
||||
#include "nsIDOMElement.h"
|
||||
|
||||
// Helper function
|
||||
static PRBool
|
||||
GetCSSComputedValue(nsIContent* aElem,
|
||||
nsCSSProperty aPropID,
|
||||
nsAString& aResult)
|
||||
{
|
||||
NS_ENSURE_TRUE(nsSMILCSSProperty::IsPropertyAnimatable(aPropID),
|
||||
PR_FALSE);
|
||||
NS_ABORT_IF_FALSE(!nsCSSProps::IsShorthand(aPropID),
|
||||
"Can't look up computed value of shorthand property");
|
||||
NS_ABORT_IF_FALSE(nsSMILCSSProperty::IsPropertyAnimatable(aPropID),
|
||||
"Shouldn't get here for non-animatable properties");
|
||||
|
||||
nsIDocument* doc = aElem->GetCurrentDoc();
|
||||
if (!doc) {
|
||||
|
@ -73,8 +76,7 @@ GetCSSComputedValue(nsIContent* aElem,
|
|||
nsresult rv = NS_NewComputedDOMStyle(domElement, EmptyString(), shell,
|
||||
getter_AddRefs(computedStyle));
|
||||
|
||||
if (NS_SUCCEEDED(rv) && computedStyle) {
|
||||
// NOTE: This will produce an empty string for shorthand values
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
computedStyle->GetPropertyValue(aPropID, aResult);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
@ -94,6 +96,20 @@ nsSMILCSSProperty::nsSMILCSSProperty(nsCSSProperty aPropID,
|
|||
nsSMILValue
|
||||
nsSMILCSSProperty::GetBaseValue() const
|
||||
{
|
||||
// SPECIAL CASE: Shorthands
|
||||
if (nsCSSProps::IsShorthand(mPropID)) {
|
||||
// We can't look up the base (computed-style) value of shorthand
|
||||
// properties, because they aren't guaranteed to have a consistent computed
|
||||
// value. However, that's not a problem, because it turns out the caller
|
||||
// isn't going to end up using the value we return anyway. Base values only
|
||||
// get used when there's interpolation or addition, and the shorthand
|
||||
// properties we know about don't support those operations. So, we can just
|
||||
// return a dummy value (initialized with the right type, so as not to
|
||||
// indicate failure).
|
||||
return nsSMILValue(&nsSMILCSSValueType::sSingleton);
|
||||
}
|
||||
|
||||
// GENERAL CASE: Non-Shorthands
|
||||
// (1) Put empty string in override style for property mPropID
|
||||
// (saving old override style value, so we can set it again when we're done)
|
||||
nsCOMPtr<nsIDOMCSSStyleDeclaration> overrideStyle;
|
||||
|
@ -118,18 +134,11 @@ nsSMILCSSProperty::GetBaseValue() const
|
|||
overrideDecl->SetPropertyValue(mPropID, cachedOverrideStyleVal);
|
||||
}
|
||||
|
||||
// (4) Create a nsSMILValue from the computed style
|
||||
nsSMILValue baseValue;
|
||||
if (didGetComputedVal) {
|
||||
// (4) Create the nsSMILValue from the computed style value
|
||||
nsSMILCSSValueType::sSingleton.Init(baseValue);
|
||||
if (!nsCSSProps::IsShorthand(mPropID) &&
|
||||
!nsSMILCSSValueType::sSingleton.ValueFromString(mPropID, mElement,
|
||||
computedStyleVal,
|
||||
baseValue)) {
|
||||
nsSMILCSSValueType::sSingleton.Destroy(baseValue);
|
||||
NS_ABORT_IF_FALSE(baseValue.IsNull(),
|
||||
"Destroy should leave us with null-typed value");
|
||||
}
|
||||
nsSMILCSSValueType::ValueFromString(mPropID, mElement,
|
||||
computedStyleVal, baseValue);
|
||||
}
|
||||
return baseValue;
|
||||
}
|
||||
|
@ -140,14 +149,9 @@ nsSMILCSSProperty::ValueFromString(const nsAString& aStr,
|
|||
nsSMILValue& aValue) const
|
||||
{
|
||||
NS_ENSURE_TRUE(IsPropertyAnimatable(mPropID), NS_ERROR_FAILURE);
|
||||
nsSMILCSSValueType::sSingleton.Init(aValue);
|
||||
PRBool success =
|
||||
nsSMILCSSValueType::sSingleton.ValueFromString(mPropID, mElement,
|
||||
aStr, aValue);
|
||||
if (!success) {
|
||||
nsSMILCSSValueType::sSingleton.Destroy(aValue);
|
||||
}
|
||||
return success ? NS_OK : NS_ERROR_FAILURE;
|
||||
|
||||
nsSMILCSSValueType::ValueFromString(mPropID, mElement, aStr, aValue);
|
||||
return aValue.IsNull() ? NS_ERROR_FAILURE : NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -155,32 +159,29 @@ nsSMILCSSProperty::SetAnimValue(const nsSMILValue& aValue)
|
|||
{
|
||||
NS_ENSURE_TRUE(IsPropertyAnimatable(mPropID), NS_ERROR_FAILURE);
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
// Convert nsSMILValue to string
|
||||
nsAutoString valStr;
|
||||
if (!nsSMILCSSValueType::ValueToString(aValue, valStr)) {
|
||||
NS_WARNING("Failed to convert nsSMILValue for CSS property into a string");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (nsSMILCSSValueType::sSingleton.ValueToString(aValue, valStr)) {
|
||||
// Apply the style to the target element
|
||||
// Use string value to style the target element
|
||||
nsCOMPtr<nsIDOMCSSStyleDeclaration> overrideStyle;
|
||||
mElement->GetSMILOverrideStyle(getter_AddRefs(overrideStyle));
|
||||
NS_ABORT_IF_FALSE(overrideStyle, "Need a non-null overrideStyle");
|
||||
|
||||
nsCOMPtr<nsICSSDeclaration> overrideDecl =
|
||||
do_QueryInterface(overrideStyle);
|
||||
nsCOMPtr<nsICSSDeclaration> overrideDecl = do_QueryInterface(overrideStyle);
|
||||
if (overrideDecl) {
|
||||
overrideDecl->SetPropertyValue(mPropID, valStr);
|
||||
}
|
||||
} else {
|
||||
NS_WARNING("Failed to convert nsSMILValue for CSS property into a string");
|
||||
rv = NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return rv;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsSMILCSSProperty::ClearAnimValue()
|
||||
{
|
||||
// Put empty string in override style for property propID
|
||||
// Put empty string in override style for our property
|
||||
nsCOMPtr<nsIDOMCSSStyleDeclaration> overrideStyle;
|
||||
mElement->GetSMILOverrideStyle(getter_AddRefs(overrideStyle));
|
||||
nsCOMPtr<nsICSSDeclaration> overrideDecl = do_QueryInterface(overrideStyle);
|
||||
|
|
|
@ -303,59 +303,79 @@ GetPresContextForElement(nsIContent* aElem)
|
|||
return shell ? shell->GetPresContext() : nsnull;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsSMILCSSValueType::ValueFromString(nsCSSProperty aPropID,
|
||||
// Helper function to parse a string into a nsStyleAnimation::Value
|
||||
static PRBool
|
||||
ValueFromStringHelper(nsCSSProperty aPropID,
|
||||
nsIContent* aTargetElement,
|
||||
nsPresContext* aPresContext,
|
||||
const nsAString& aString,
|
||||
nsSMILValue& aValue) const
|
||||
nsStyleAnimation::Value& aStyleAnimValue)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(aValue.mType == &nsSMILCSSValueType::sSingleton,
|
||||
"Passed-in value is wrong type");
|
||||
NS_ABORT_IF_FALSE(!aValue.mU.mPtr, "expecting barely-initialized outparam");
|
||||
|
||||
nsPresContext* presContext = GetPresContextForElement(aTargetElement);
|
||||
if (!presContext) {
|
||||
NS_WARNING("Not parsing animation value; unable to get PresContext");
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// If value is negative, we'll strip off the "-" so the CSS parser won't
|
||||
// barf, and then manually make the parsed value negative. (This is a partial
|
||||
// solution to let us accept some otherwise out-of-bounds CSS values -- bug
|
||||
// 501188 will provide a more complete fix.)
|
||||
// barf, and then manually make the parsed value negative.
|
||||
// (This is a partial solution to let us accept some otherwise out-of-bounds
|
||||
// CSS values. Bug 501188 will provide a more complete fix.)
|
||||
PRBool isNegative = PR_FALSE;
|
||||
PRUint32 subStringBegin = 0;
|
||||
PRInt32 absValuePos = nsSMILParserUtils::CheckForNegativeNumber(aString);
|
||||
if (absValuePos > 0) {
|
||||
subStringBegin = (PRUint32)absValuePos;
|
||||
isNegative = PR_TRUE;
|
||||
subStringBegin = (PRUint32)absValuePos; // Start parsing after '-' sign
|
||||
}
|
||||
nsDependentSubstring subString(aString, subStringBegin);
|
||||
nsStyleAnimation::Value parsedValue;
|
||||
if (nsStyleAnimation::ComputeValue(aPropID, aTargetElement,
|
||||
subString, parsedValue)) {
|
||||
if (isNegative) {
|
||||
InvertSign(parsedValue);
|
||||
}
|
||||
if (aPropID == eCSSProperty_font_size) {
|
||||
// Divide out text-zoom, since SVG is supposed to ignore it
|
||||
NS_ABORT_IF_FALSE(parsedValue.GetUnit() == nsStyleAnimation::eUnit_Coord,
|
||||
"'font-size' value with unexpected style unit");
|
||||
parsedValue.SetCoordValue(parsedValue.GetCoordValue() /
|
||||
presContext->TextZoom());
|
||||
}
|
||||
aValue.mU.mPtr = new ValueWrapper(aPropID, parsedValue, presContext);
|
||||
return aValue.mU.mPtr != nsnull;
|
||||
}
|
||||
if (!nsStyleAnimation::ComputeValue(aPropID, aTargetElement,
|
||||
subString, aStyleAnimValue)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
if (isNegative) {
|
||||
InvertSign(aStyleAnimValue);
|
||||
}
|
||||
|
||||
if (aPropID == eCSSProperty_font_size) {
|
||||
// Divide out text-zoom, since SVG is supposed to ignore it
|
||||
NS_ABORT_IF_FALSE(aStyleAnimValue.GetUnit() ==
|
||||
nsStyleAnimation::eUnit_Coord,
|
||||
"'font-size' value with unexpected style unit");
|
||||
aStyleAnimValue.SetCoordValue(aStyleAnimValue.GetCoordValue() /
|
||||
aPresContext->TextZoom());
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
nsSMILCSSValueType::ValueFromString(nsCSSProperty aPropID,
|
||||
nsIContent* aTargetElement,
|
||||
const nsAString& aString,
|
||||
nsSMILValue& aValue)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(aValue.IsNull(), "Outparam should be null-typed");
|
||||
nsPresContext* presContext = GetPresContextForElement(aTargetElement);
|
||||
if (!presContext) {
|
||||
NS_WARNING("Not parsing animation value; unable to get PresContext");
|
||||
return;
|
||||
}
|
||||
|
||||
nsStyleAnimation::Value parsedValue;
|
||||
if (ValueFromStringHelper(aPropID, aTargetElement, presContext,
|
||||
aString, parsedValue)) {
|
||||
sSingleton.Init(aValue);
|
||||
aValue.mU.mPtr = new ValueWrapper(aPropID, parsedValue, presContext);
|
||||
if (!aValue.mU.mPtr) {
|
||||
// Out of memory! Destroy outparam, to leave it as nsSMILNullType,
|
||||
// which indicates to our caller that we failed.
|
||||
sSingleton.Destroy(aValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
PRBool
|
||||
nsSMILCSSValueType::ValueToString(const nsSMILValue& aValue,
|
||||
nsAString& aString) const
|
||||
nsAString& aString)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(aValue.mType == &nsSMILCSSValueType::sSingleton,
|
||||
"Passed-in value is wrong type");
|
||||
"Unexpected SMIL value type");
|
||||
const ValueWrapper* wrapper = ExtractValueWrapper(aValue);
|
||||
return !wrapper ||
|
||||
nsStyleAnimation::UncomputeValue(wrapper->mPropID, wrapper->mPresContext,
|
||||
|
|
|
@ -54,8 +54,12 @@ class nsAString;
|
|||
class nsSMILCSSValueType : public nsISMILType
|
||||
{
|
||||
public:
|
||||
// nsISMILValueType Methods
|
||||
// ------------------------
|
||||
// Singleton for nsSMILValue objects to hold onto.
|
||||
static nsSMILCSSValueType sSingleton;
|
||||
|
||||
protected:
|
||||
// nsISMILType Methods
|
||||
// -------------------
|
||||
NS_OVERRIDE virtual nsresult Init(nsSMILValue& aValue) const;
|
||||
NS_OVERRIDE virtual void Destroy(nsSMILValue&) const;
|
||||
NS_OVERRIDE virtual nsresult Assign(nsSMILValue& aDest,
|
||||
|
@ -71,24 +75,29 @@ public:
|
|||
double aUnitDistance,
|
||||
nsSMILValue& aResult) const;
|
||||
|
||||
public:
|
||||
// Helper Methods
|
||||
// --------------
|
||||
/**
|
||||
* Sets up the given nsSMILValue to represent the given string value. The
|
||||
* string is interpreted as a value for the given property on the given
|
||||
* element.
|
||||
*
|
||||
* Note: aValue is expected to be freshly initialized (i.e. it should already
|
||||
* have been passed into nsSMILCSSValueType::Init(), and it should not have
|
||||
* been set up further via e.g. Assign() or another ValueFromString() call.)
|
||||
* On failure, this method leaves aValue.mType == nsSMILNullType::sSingleton.
|
||||
* Otherwise, this method leaves aValue.mType == this class's singleton.
|
||||
*
|
||||
* @param aPropID The property for which we're parsing a value.
|
||||
* @param aTargetElement The target element to whom the property/value
|
||||
* setting applies.
|
||||
* @param aString The string to be parsed as a CSS value.
|
||||
* @param [out] aValue The nsSMILValue to be populated.
|
||||
* @return PR_TRUE on success, PR_FALSE on failure.
|
||||
* @param [out] aValue The nsSMILValue to be populated. Should
|
||||
* initially be null-typed.
|
||||
* @pre aValue.IsNull()
|
||||
* @post aValue.IsNull() || aValue.mType == nsSMILCSSValueType::sSingleton
|
||||
*/
|
||||
PRBool ValueFromString(nsCSSProperty aPropID, nsIContent* aTargetElement,
|
||||
const nsAString& aString, nsSMILValue& aValue) const;
|
||||
static void ValueFromString(nsCSSProperty aPropID,
|
||||
nsIContent* aTargetElement,
|
||||
const nsAString& aString, nsSMILValue& aValue);
|
||||
|
||||
/**
|
||||
* Creates a string representation of the given nsSMILValue.
|
||||
|
@ -102,13 +111,13 @@ public:
|
|||
* @param [out] aString The string to be populated with the given value.
|
||||
* @return PR_TRUE on success, PR_FALSE on failure.
|
||||
*/
|
||||
PRBool ValueToString(const nsSMILValue& aValue, nsAString& aString) const;
|
||||
|
||||
// Singleton for nsSMILValue objects to hold onto.
|
||||
static nsSMILCSSValueType sSingleton;
|
||||
static PRBool ValueToString(const nsSMILValue& aValue, nsAString& aString);
|
||||
|
||||
private:
|
||||
// Private constructor & destructor: prevent instances beyond my singleton,
|
||||
// and prevent others from deleting my singleton.
|
||||
nsSMILCSSValueType() {}
|
||||
~nsSMILCSSValueType() {}
|
||||
};
|
||||
|
||||
#endif // NS_SMILCSSVALUETYPE_H_
|
||||
|
|
|
@ -44,6 +44,12 @@
|
|||
class nsSMILFloatType : public nsISMILType
|
||||
{
|
||||
public:
|
||||
// Singleton for nsSMILValue objects to hold onto.
|
||||
static nsSMILFloatType sSingleton;
|
||||
|
||||
protected:
|
||||
// nsISMILType Methods
|
||||
// -------------------
|
||||
virtual nsresult Init(nsSMILValue& aValue) const;
|
||||
virtual void Destroy(nsSMILValue&) const;
|
||||
virtual nsresult Assign(nsSMILValue& aDest, const nsSMILValue& aSrc) const;
|
||||
|
@ -57,10 +63,11 @@ public:
|
|||
double aUnitDistance,
|
||||
nsSMILValue& aResult) const;
|
||||
|
||||
static nsSMILFloatType sSingleton;
|
||||
|
||||
private:
|
||||
// Private constructor & destructor: prevent instances beyond my singleton,
|
||||
// and prevent others from deleting my singleton.
|
||||
nsSMILFloatType() {}
|
||||
~nsSMILFloatType() {}
|
||||
};
|
||||
|
||||
#endif // NS_SMILFLOATTYPE_H_
|
||||
|
|
|
@ -44,6 +44,12 @@
|
|||
class nsSMILNullType : public nsISMILType
|
||||
{
|
||||
public:
|
||||
// Singleton for nsSMILValue objects to hold onto.
|
||||
static nsSMILNullType sSingleton;
|
||||
|
||||
protected:
|
||||
// nsISMILType Methods
|
||||
// -------------------
|
||||
virtual nsresult Init(nsSMILValue& aValue) const { return NS_OK; }
|
||||
virtual void Destroy(nsSMILValue& aValue) const {}
|
||||
virtual nsresult Assign(nsSMILValue& aDest, const nsSMILValue& aSrc) const;
|
||||
|
@ -60,7 +66,11 @@ public:
|
|||
double aUnitDistance,
|
||||
nsSMILValue& aResult) const;
|
||||
|
||||
static nsSMILNullType sSingleton;
|
||||
private:
|
||||
// Private constructor & destructor: prevent instances beyond my singleton,
|
||||
// and prevent others from deleting my singleton.
|
||||
nsSMILNullType() {}
|
||||
~nsSMILNullType() {}
|
||||
};
|
||||
|
||||
#endif // NS_SMILNULLTYPE_H_
|
||||
|
|
|
@ -50,12 +50,6 @@
|
|||
#include "nsISVGValue.h"
|
||||
#include "prdtoa.h"
|
||||
|
||||
nsISMILType*
|
||||
nsSVGTransformSMILAttr::GetSMILType() const
|
||||
{
|
||||
return &nsSVGTransformSMILType::sSingleton;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsSVGTransformSMILAttr::ValueFromString(const nsAString& aStr,
|
||||
const nsISMILAnimationElement* aSrcElement,
|
||||
|
@ -65,32 +59,21 @@ nsSVGTransformSMILAttr::ValueFromString(const nsAString& aStr,
|
|||
NS_ASSERTION(aValue.IsNull(),
|
||||
"aValue should have been cleared before calling ValueFromString");
|
||||
|
||||
nsSMILValue val(&nsSVGTransformSMILType::sSingleton);
|
||||
if (val.IsNull())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
const nsAttrValue* typeAttr = aSrcElement->GetAnimAttr(nsGkAtoms::type);
|
||||
|
||||
const nsIAtom* transformType = typeAttr
|
||||
? typeAttr->GetAtomValue()
|
||||
: nsGkAtoms::translate;
|
||||
|
||||
nsresult rv = ParseValue(aStr, transformType, val);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
aValue = val;
|
||||
|
||||
return NS_OK;
|
||||
ParseValue(aStr, transformType, aValue);
|
||||
return aValue.IsNull() ? NS_ERROR_FAILURE : NS_OK;
|
||||
}
|
||||
|
||||
nsSMILValue
|
||||
nsSVGTransformSMILAttr::GetBaseValue() const
|
||||
{
|
||||
nsSVGTransformSMILType *type = &nsSVGTransformSMILType::sSingleton;
|
||||
nsSMILValue val(type);
|
||||
nsSMILValue val(&nsSVGTransformSMILType::sSingleton);
|
||||
if (val.IsNull())
|
||||
return val;
|
||||
return val; // Initialization failed
|
||||
|
||||
nsIDOMSVGTransformList *list = mVal->mBaseVal.get();
|
||||
|
||||
|
@ -149,19 +132,12 @@ nsSVGTransformSMILAttr::SetAnimValue(const nsSMILValue& aValue)
|
|||
//----------------------------------------------------------------------
|
||||
// Implementation helpers
|
||||
|
||||
nsresult
|
||||
void
|
||||
nsSVGTransformSMILAttr::ParseValue(const nsAString& aSpec,
|
||||
const nsIAtom* aTransformType,
|
||||
nsSMILValue& aResult) const
|
||||
nsSMILValue& aResult)
|
||||
{
|
||||
nsSVGTransformSMILType* type = &nsSVGTransformSMILType::sSingleton;
|
||||
NS_ASSERTION(
|
||||
type == static_cast<nsSVGTransformSMILType const *>(aResult.mType),
|
||||
"Unexpected type for SMIL value result");
|
||||
|
||||
// Reset the result so we can just append to it
|
||||
nsresult rv = type->Init(aResult);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
NS_ASSERTION(aResult.IsNull(), "Unexpected type for SMIL value");
|
||||
|
||||
float params[3] = { 0.f };
|
||||
PRInt32 numParsed = ParseParameterList(aSpec, params, 3);
|
||||
|
@ -170,12 +146,12 @@ nsSVGTransformSMILAttr::ParseValue(const nsAString& aSpec,
|
|||
if (aTransformType == nsGkAtoms::translate) {
|
||||
// tx [ty=0]
|
||||
if (numParsed != 1 && numParsed != 2)
|
||||
return NS_ERROR_FAILURE;
|
||||
return;
|
||||
transformType = nsSVGSMILTransform::TRANSFORM_TRANSLATE;
|
||||
} else if (aTransformType == nsGkAtoms::scale) {
|
||||
// sx [sy=sx]
|
||||
if (numParsed != 1 && numParsed != 2)
|
||||
return NS_ERROR_FAILURE;
|
||||
return;
|
||||
if (numParsed == 1) {
|
||||
params[1] = params[0];
|
||||
}
|
||||
|
@ -183,35 +159,41 @@ nsSVGTransformSMILAttr::ParseValue(const nsAString& aSpec,
|
|||
} else if (aTransformType == nsGkAtoms::rotate) {
|
||||
// r [cx=0 cy=0]
|
||||
if (numParsed != 1 && numParsed != 3)
|
||||
return NS_ERROR_FAILURE;
|
||||
return;
|
||||
transformType = nsSVGSMILTransform::TRANSFORM_ROTATE;
|
||||
} else if (aTransformType == nsGkAtoms::skewX) {
|
||||
// x-angle
|
||||
if (numParsed != 1)
|
||||
return NS_ERROR_FAILURE;
|
||||
return;
|
||||
transformType = nsSVGSMILTransform::TRANSFORM_SKEWX;
|
||||
} else if (aTransformType == nsGkAtoms::skewY) {
|
||||
// y-angle
|
||||
if (numParsed != 1)
|
||||
return NS_ERROR_FAILURE;
|
||||
return;
|
||||
transformType = nsSVGSMILTransform::TRANSFORM_SKEWY;
|
||||
} else {
|
||||
return NS_ERROR_FAILURE;
|
||||
return;
|
||||
}
|
||||
|
||||
return type->AppendTransform(nsSVGSMILTransform(transformType, params),
|
||||
aResult);
|
||||
nsSMILValue val(&nsSVGTransformSMILType::sSingleton);
|
||||
nsSVGSMILTransform transform(transformType, params);
|
||||
if (NS_FAILED(nsSVGTransformSMILType::AppendTransform(transform, val))) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Success! Initialize our outparam with parsed value.
|
||||
aResult = val;
|
||||
}
|
||||
|
||||
inline PRBool
|
||||
nsSVGTransformSMILAttr::IsSpace(const char c) const
|
||||
IsSpace(const char c)
|
||||
{
|
||||
return (c == 0x9 || c == 0xA || c == 0xD || c == 0x20);
|
||||
}
|
||||
|
||||
inline void
|
||||
nsSVGTransformSMILAttr::SkipWsp(nsACString::const_iterator& aIter,
|
||||
const nsACString::const_iterator& aIterEnd) const
|
||||
SkipWsp(nsACString::const_iterator& aIter,
|
||||
const nsACString::const_iterator& aIterEnd)
|
||||
{
|
||||
while (aIter != aIterEnd && IsSpace(*aIter))
|
||||
++aIter;
|
||||
|
@ -220,7 +202,7 @@ nsSVGTransformSMILAttr::SkipWsp(nsACString::const_iterator& aIter,
|
|||
PRInt32
|
||||
nsSVGTransformSMILAttr::ParseParameterList(const nsAString& aSpec,
|
||||
float* aVars,
|
||||
PRInt32 aNVars) const
|
||||
PRInt32 aNVars)
|
||||
{
|
||||
NS_ConvertUTF16toUTF8 spec(aSpec);
|
||||
|
||||
|
@ -258,9 +240,10 @@ nsSVGTransformSMILAttr::ParseParameterList(const nsAString& aSpec,
|
|||
|
||||
nsresult
|
||||
nsSVGTransformSMILAttr::AppendSVGTransformToSMILValue(
|
||||
nsIDOMSVGTransform* aTransform, nsSMILValue& aValue) const
|
||||
nsIDOMSVGTransform* aTransform, nsSMILValue& aValue)
|
||||
{
|
||||
nsSVGTransformSMILType* type = &nsSVGTransformSMILType::sSingleton;
|
||||
NS_ASSERTION(aValue.mType == &nsSVGTransformSMILType::sSingleton,
|
||||
"Unexpected type for SMIL value");
|
||||
|
||||
PRUint16 svgTransformType = nsIDOMSVGTransform::SVG_TRANSFORM_MATRIX;
|
||||
aTransform->GetType(&svgTransformType);
|
||||
|
@ -328,10 +311,9 @@ nsSVGTransformSMILAttr::AppendSVGTransformToSMILValue(
|
|||
matrix->GetD(&mx[3]);
|
||||
matrix->GetE(&mx[4]);
|
||||
matrix->GetF(&mx[5]);
|
||||
rv = type->AppendTransform(nsSVGSMILTransform(mx), aValue);
|
||||
transformType = nsSVGSMILTransform::TRANSFORM_MATRIX;
|
||||
return nsSVGTransformSMILType::AppendTransform(nsSVGSMILTransform(mx),
|
||||
aValue);
|
||||
}
|
||||
break;
|
||||
|
||||
case nsIDOMSVGTransform::SVG_TRANSFORM_UNKNOWN:
|
||||
// If it's 'unknown', it's probably not initialised, so just skip it.
|
||||
|
@ -342,12 +324,11 @@ nsSVGTransformSMILAttr::AppendSVGTransformToSMILValue(
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (transformType != nsSVGSMILTransform::TRANSFORM_MATRIX) {
|
||||
rv =
|
||||
type->AppendTransform(nsSVGSMILTransform(transformType, params), aValue);
|
||||
}
|
||||
NS_ABORT_IF_FALSE(transformType != nsSVGSMILTransform::TRANSFORM_MATRIX,
|
||||
"generalized matrix case should have returned above");
|
||||
|
||||
return rv;
|
||||
return nsSVGTransformSMILType::
|
||||
AppendTransform(nsSVGSMILTransform(transformType, params), aValue);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -396,40 +377,34 @@ nsSVGTransformSMILAttr::UpdateFromSMILValue(
|
|||
nsresult
|
||||
nsSVGTransformSMILAttr::GetSVGTransformFromSMILValue(
|
||||
const nsSVGSMILTransform& aSMILTransform,
|
||||
nsIDOMSVGTransform* aSVGTransform) const
|
||||
nsIDOMSVGTransform* aSVGTransform)
|
||||
{
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
|
||||
switch (aSMILTransform.mTransformType)
|
||||
{
|
||||
case nsSVGSMILTransform::TRANSFORM_TRANSLATE:
|
||||
rv = aSVGTransform->SetTranslate(aSMILTransform.mParams[0],
|
||||
return aSVGTransform->SetTranslate(aSMILTransform.mParams[0],
|
||||
aSMILTransform.mParams[1]);
|
||||
break;
|
||||
|
||||
case nsSVGSMILTransform::TRANSFORM_SCALE:
|
||||
rv = aSVGTransform->SetScale(aSMILTransform.mParams[0],
|
||||
return aSVGTransform->SetScale(aSMILTransform.mParams[0],
|
||||
aSMILTransform.mParams[1]);
|
||||
break;
|
||||
|
||||
case nsSVGSMILTransform::TRANSFORM_ROTATE:
|
||||
rv = aSVGTransform->SetRotate(aSMILTransform.mParams[0],
|
||||
return aSVGTransform->SetRotate(aSMILTransform.mParams[0],
|
||||
aSMILTransform.mParams[1],
|
||||
aSMILTransform.mParams[2]);
|
||||
break;
|
||||
|
||||
case nsSVGSMILTransform::TRANSFORM_SKEWX:
|
||||
rv = aSVGTransform->SetSkewX(aSMILTransform.mParams[0]);
|
||||
break;
|
||||
return aSVGTransform->SetSkewX(aSMILTransform.mParams[0]);
|
||||
|
||||
case nsSVGSMILTransform::TRANSFORM_SKEWY:
|
||||
rv = aSVGTransform->SetSkewY(aSMILTransform.mParams[0]);
|
||||
break;
|
||||
return aSVGTransform->SetSkewY(aSMILTransform.mParams[0]);
|
||||
|
||||
case nsSVGSMILTransform::TRANSFORM_MATRIX:
|
||||
{
|
||||
nsCOMPtr<nsIDOMSVGMatrix> svgMatrix;
|
||||
rv = NS_NewSVGMatrix(getter_AddRefs(svgMatrix),
|
||||
nsresult rv =
|
||||
NS_NewSVGMatrix(getter_AddRefs(svgMatrix),
|
||||
aSMILTransform.mParams[0],
|
||||
aSMILTransform.mParams[1],
|
||||
aSMILTransform.mParams[2],
|
||||
|
@ -437,11 +412,13 @@ nsSVGTransformSMILAttr::GetSVGTransformFromSMILValue(
|
|||
aSMILTransform.mParams[4],
|
||||
aSMILTransform.mParams[5]);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(svgMatrix,NS_ERROR_FAILURE);
|
||||
rv = aSVGTransform->SetMatrix(svgMatrix);
|
||||
NS_ABORT_IF_FALSE(svgMatrix,
|
||||
"NS_NewSVGMatrix succeeded, so it should have "
|
||||
"given us a non-null result");
|
||||
return aSVGTransform->SetMatrix(svgMatrix);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
NS_WARNING("Unexpected transform type");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
|
|
@ -54,11 +54,9 @@ class nsSVGTransformSMILAttr : public nsISMILAttr
|
|||
public:
|
||||
nsSVGTransformSMILAttr(nsSVGAnimatedTransformList* aTransform,
|
||||
nsSVGElement* aSVGElement)
|
||||
: mVal(aTransform),
|
||||
mSVGElement(aSVGElement) {}
|
||||
: mVal(aTransform) {}
|
||||
|
||||
// nsISMILAttr methods
|
||||
virtual nsISMILType* GetSMILType() const;
|
||||
virtual nsresult ValueFromString(const nsAString& aStr,
|
||||
const nsISMILAnimationElement* aSrcElement,
|
||||
nsSMILValue& aValue) const;
|
||||
|
@ -67,30 +65,24 @@ public:
|
|||
virtual nsresult SetAnimValue(const nsSMILValue& aValue);
|
||||
|
||||
protected:
|
||||
nsresult ParseValue(const nsAString& aSpec,
|
||||
static void ParseValue(const nsAString& aSpec,
|
||||
const nsIAtom* aTransformType,
|
||||
nsSMILValue& aResult) const;
|
||||
PRInt32 ParseParameterList(const nsAString& aSpec, float* aVars,
|
||||
PRInt32 aNVars) const;
|
||||
PRBool IsSpace(const char c) const;
|
||||
void SkipWsp(nsACString::const_iterator& aIter,
|
||||
const nsACString::const_iterator& aIterEnd) const;
|
||||
nsresult AppendSVGTransformToSMILValue(nsIDOMSVGTransform* transform,
|
||||
nsSMILValue& aValue) const;
|
||||
nsresult UpdateFromSMILValue(nsIDOMSVGTransformList* aTransformList,
|
||||
nsSMILValue& aResult);
|
||||
static PRInt32 ParseParameterList(const nsAString& aSpec, float* aVars,
|
||||
PRInt32 aNVars);
|
||||
static nsresult AppendSVGTransformToSMILValue(nsIDOMSVGTransform* transform,
|
||||
nsSMILValue& aValue);
|
||||
static nsresult UpdateFromSMILValue(nsIDOMSVGTransformList* aTransformList,
|
||||
const nsSMILValue& aValue);
|
||||
nsresult GetSVGTransformFromSMILValue(
|
||||
static nsresult GetSVGTransformFromSMILValue(
|
||||
const nsSVGSMILTransform& aSMILTransform,
|
||||
nsIDOMSVGTransform* aSVGTransform) const;
|
||||
already_AddRefed<nsIDOMSVGTransform> GetSVGTransformFromSMILValue(
|
||||
const nsSMILValue& aValue) const;
|
||||
nsIDOMSVGTransform* aSVGTransform);
|
||||
|
||||
private:
|
||||
// Raw pointers are OK here because this nsSVGTransformSMILAttr is both
|
||||
// created & destroyed during a SMIL sample-step, during which time the DOM
|
||||
// isn't modified.
|
||||
nsSVGAnimatedTransformList* mVal;
|
||||
nsSVGElement* mSVGElement;
|
||||
};
|
||||
|
||||
#endif // NS_SVGTRANSFORMSMILATTR_H_
|
||||
|
|
|
@ -42,28 +42,20 @@
|
|||
|
||||
/*static*/ nsSVGTransformSMILType nsSVGTransformSMILType::sSingleton;
|
||||
|
||||
typedef nsTArray<nsSVGSMILTransform> TransformArray;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// nsISMILType implementation
|
||||
|
||||
nsresult
|
||||
nsSVGTransformSMILType::Init(nsSMILValue &aValue) const
|
||||
{
|
||||
NS_PRECONDITION(aValue.mType == this || aValue.IsNull(),
|
||||
"Unexpected value type");
|
||||
NS_ASSERTION(aValue.mType != this || aValue.mU.mPtr,
|
||||
"Invalid nsSMILValue of SVG transform type: NULL data member");
|
||||
NS_PRECONDITION(aValue.IsNull(), "Unexpected value type");
|
||||
|
||||
if (aValue.mType != this || !aValue.mU.mPtr) {
|
||||
// Different type, or no data member: allocate memory and set type
|
||||
TransformArray* transforms = new TransformArray(1);
|
||||
NS_ENSURE_TRUE(transforms, NS_ERROR_OUT_OF_MEMORY);
|
||||
aValue.mU.mPtr = transforms;
|
||||
aValue.mType = this;
|
||||
} else {
|
||||
// Same type, just set clear
|
||||
TransformArray* transforms = static_cast<TransformArray*>(aValue.mU.mPtr);
|
||||
transforms->Clear();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -313,10 +305,11 @@ nsSVGTransformSMILType::Interpolate(const nsSMILValue& aStartVal,
|
|||
//----------------------------------------------------------------------
|
||||
// Transform array accessors
|
||||
|
||||
// static
|
||||
PRUint32
|
||||
nsSVGTransformSMILType::GetNumTransforms(const nsSMILValue& aValue) const
|
||||
nsSVGTransformSMILType::GetNumTransforms(const nsSMILValue& aValue)
|
||||
{
|
||||
NS_PRECONDITION(aValue.mType == this, "Unexpected SMIL value");
|
||||
NS_PRECONDITION(aValue.mType == &sSingleton, "Unexpected SMIL value type");
|
||||
|
||||
const TransformArray& transforms =
|
||||
*static_cast<const TransformArray*>(aValue.mU.mPtr);
|
||||
|
@ -324,11 +317,12 @@ nsSVGTransformSMILType::GetNumTransforms(const nsSMILValue& aValue) const
|
|||
return transforms.Length();
|
||||
}
|
||||
|
||||
// static
|
||||
const nsSVGSMILTransform*
|
||||
nsSVGTransformSMILType::GetTransformAt(PRUint32 aIndex,
|
||||
const nsSMILValue& aValue) const
|
||||
const nsSMILValue& aValue)
|
||||
{
|
||||
NS_PRECONDITION(aValue.mType == this, "Unexpected SMIL value");
|
||||
NS_PRECONDITION(aValue.mType == &sSingleton, "Unexpected SMIL value type");
|
||||
|
||||
const TransformArray& transforms =
|
||||
*static_cast<const TransformArray*>(aValue.mU.mPtr);
|
||||
|
@ -341,16 +335,14 @@ nsSVGTransformSMILType::GetTransformAt(PRUint32 aIndex,
|
|||
return &transforms[aIndex];
|
||||
}
|
||||
|
||||
// static
|
||||
nsresult
|
||||
nsSVGTransformSMILType::AppendTransform(const nsSVGSMILTransform& aTransform,
|
||||
nsSMILValue& aValue) const
|
||||
nsSMILValue& aValue)
|
||||
{
|
||||
NS_PRECONDITION(aValue.mType == this, "Unexpected SMIL value");
|
||||
NS_PRECONDITION(aValue.mType == &sSingleton, "Unexpected SMIL value type");
|
||||
|
||||
TransformArray& transforms = *static_cast<TransformArray*>(aValue.mU.mPtr);
|
||||
|
||||
nsSVGSMILTransform* transform = transforms.AppendElement(aTransform);
|
||||
NS_ENSURE_TRUE(transform,NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
return NS_OK;
|
||||
return transforms.AppendElement(aTransform) ?
|
||||
NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
|
|
@ -106,7 +106,12 @@ class nsSMILValue;
|
|||
class nsSVGTransformSMILType : public nsISMILType
|
||||
{
|
||||
public:
|
||||
// nsISMILType
|
||||
// Singleton for nsSMILValue objects to hold onto.
|
||||
static nsSVGTransformSMILType sSingleton;
|
||||
|
||||
protected:
|
||||
// nsISMILType Methods
|
||||
// -------------------
|
||||
virtual nsresult Init(nsSMILValue& aValue) const;
|
||||
virtual void Destroy(nsSMILValue& aValue) const;
|
||||
virtual nsresult Assign(nsSMILValue& aDest, const nsSMILValue& aSrc) const;
|
||||
|
@ -122,20 +127,22 @@ public:
|
|||
const nsSMILValue& aEndVal,
|
||||
double aUnitDistance,
|
||||
nsSMILValue& aResult) const;
|
||||
|
||||
public:
|
||||
// Transform array accessors
|
||||
PRUint32 GetNumTransforms(const nsSMILValue& aValue) const;
|
||||
const nsSVGSMILTransform* GetTransformAt(PRUint32 aIndex,
|
||||
const nsSMILValue& aValue) const;
|
||||
nsresult AppendTransform(const nsSVGSMILTransform& aTransform,
|
||||
nsSMILValue& aValue) const;
|
||||
// -------------------------
|
||||
static PRUint32 GetNumTransforms(const nsSMILValue& aValue);
|
||||
static const nsSVGSMILTransform* GetTransformAt(PRUint32 aIndex,
|
||||
const nsSMILValue& aValue);
|
||||
static nsresult AppendTransform(const nsSVGSMILTransform& aTransform,
|
||||
nsSMILValue& aValue);
|
||||
|
||||
static nsSVGTransformSMILType sSingleton;
|
||||
|
||||
protected:
|
||||
typedef nsTArray<nsSVGSMILTransform> TransformArray;
|
||||
|
||||
private:
|
||||
// Private constructor & destructor: prevent instances beyond my singleton,
|
||||
// and prevent others from deleting my singleton.
|
||||
nsSVGTransformSMILType() {}
|
||||
~nsSVGTransformSMILType() {}
|
||||
};
|
||||
|
||||
#endif // NS_SVGTRANSFORMSMILTYPE_H_
|
||||
|
|
|
@ -52,6 +52,7 @@ const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
|||
const debug = false;
|
||||
|
||||
var expectedConsoleMessages = [];
|
||||
var expectLoggedMessages = null;
|
||||
|
||||
try {
|
||||
const RDF = Components.classes["@mozilla.org/rdf/rdf-service;1"].
|
||||
|
@ -88,6 +89,9 @@ function test_template()
|
|||
if (needsOpen)
|
||||
root.open = true;
|
||||
|
||||
if (expectLoggedMessages)
|
||||
expectLoggedMessages();
|
||||
|
||||
checkResults(root, 0);
|
||||
|
||||
if (changes.length) {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
-->
|
||||
|
||||
<window title="XUL Template Tests" width="500" height="600"
|
||||
onload="expectLoggedMessages(); test_template();"
|
||||
onload="test_template();"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/MochiKit/packed.js"></script>
|
||||
|
@ -37,7 +37,7 @@ var expectedOutput =
|
|||
Components.classes["@mozilla.org/consoleservice;1"].
|
||||
getService(Components.interfaces.nsIConsoleService).reset();
|
||||
|
||||
function expectLoggedMessages()
|
||||
expectLoggedMessages = function()
|
||||
{
|
||||
// check log to ensure that two rows have been added
|
||||
var initialNumber = Number(document.getElementById("root").firstChild.nextSibling.id.substring(3));
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<body onload="test();">
|
||||
<script>
|
||||
function test() {
|
||||
// Test that calling pushState() with a state object which calls
|
||||
// history.back() doesn't crash. We need to make sure that there's at least
|
||||
// one entry in the history before we do anything else.
|
||||
history.pushState(null, "");
|
||||
|
||||
x = {};
|
||||
x.toJSON = { history.back(); return "{a:1}"; };
|
||||
history.pushState(x, "");
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -6,3 +6,4 @@ load 430628-1.html
|
|||
load 432114-1.html
|
||||
load 432114-2.html
|
||||
load 436900-1.html
|
||||
load 500328-1.html
|
||||
|
|
|
@ -109,6 +109,7 @@
|
|||
#include "nsIURIClassifier.h"
|
||||
#include "nsIOfflineCacheUpdate.h"
|
||||
#include "nsCPrefetchService.h"
|
||||
#include "nsJSON.h"
|
||||
|
||||
// we want to explore making the document own the load group
|
||||
// so we can associate the document URI with the load group.
|
||||
|
@ -655,6 +656,8 @@ DispatchPings(nsIContent *content, nsIURI *referrer)
|
|||
ForEachPing(content, SendPing, &info);
|
||||
}
|
||||
|
||||
static nsISHEntry* GetRootSHEntry(nsISHEntry *entry);
|
||||
|
||||
//*****************************************************************************
|
||||
//*** nsDocShell: Object Management
|
||||
//*****************************************************************************
|
||||
|
@ -863,6 +866,14 @@ NS_IMETHODIMP nsDocShell::GetInterface(const nsIID & aIID, void **aSink)
|
|||
mContentViewer->GetDOMDocument((nsIDOMDocument **) aSink);
|
||||
return *aSink ? NS_OK : NS_NOINTERFACE;
|
||||
}
|
||||
else if (aIID.Equals(NS_GET_IID(nsIDocument)) &&
|
||||
NS_SUCCEEDED(EnsureContentViewer())) {
|
||||
nsCOMPtr<nsIDOMDocument> domDoc;
|
||||
mContentViewer->GetDOMDocument(getter_AddRefs(domDoc));
|
||||
if (!domDoc)
|
||||
return NS_NOINTERFACE;
|
||||
return domDoc->QueryInterface(aIID, aSink);
|
||||
}
|
||||
else if (aIID.Equals(NS_GET_IID(nsIApplicationCacheContainer))) {
|
||||
*aSink = nsnull;
|
||||
|
||||
|
@ -1196,7 +1207,7 @@ nsDocShell::LoadURI(nsIURI * aURI,
|
|||
// The parent was loaded normally. In this case, this *brand new* child really shouldn't
|
||||
// have a SHEntry. If it does, it could be because the parent is replacing an
|
||||
// existing frame with a new frame, in the onLoadHandler. We don't want this
|
||||
// url to get into session history. Clear off shEntry, and set laod type to
|
||||
// url to get into session history. Clear off shEntry, and set load type to
|
||||
// LOAD_BYPASS_HISTORY.
|
||||
PRBool inOnLoadHandler=PR_FALSE;
|
||||
parentDS->GetIsExecutingOnLoadHandler(&inOnLoadHandler);
|
||||
|
@ -3226,11 +3237,11 @@ nsDocShell::GetChildSHEntry(PRInt32 aChildOffset, nsISHEntry ** aResult)
|
|||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::AddChildSHEntry(nsISHEntry * aCloneRef, nsISHEntry * aNewEntry,
|
||||
PRInt32 aChildOffset)
|
||||
PRInt32 aChildOffset, PRUint32 loadType)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
if (mLSHE) {
|
||||
if (mLSHE && loadType != LOAD_PUSHSTATE) {
|
||||
/* You get here if you are currently building a
|
||||
* hierarchy ie.,you just visited a frameset page
|
||||
*/
|
||||
|
@ -3285,7 +3296,8 @@ nsDocShell::AddChildSHEntry(nsISHEntry * aCloneRef, nsISHEntry * aNewEntry,
|
|||
nsCOMPtr<nsIDocShellHistory> parent =
|
||||
do_QueryInterface(GetAsSupports(mParent), &rv);
|
||||
if (parent) {
|
||||
rv = parent->AddChildSHEntry(aCloneRef, aNewEntry, aChildOffset);
|
||||
rv = parent->AddChildSHEntry(aCloneRef, aNewEntry, aChildOffset,
|
||||
loadType);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
|
@ -3313,7 +3325,7 @@ nsDocShell::DoAddChildSHEntry(nsISHEntry* aNewEntry, PRInt32 aChildOffset)
|
|||
nsCOMPtr<nsIDocShellHistory> parent =
|
||||
do_QueryInterface(GetAsSupports(mParent), &rv);
|
||||
if (parent) {
|
||||
rv = parent->AddChildSHEntry(mOSHE, aNewEntry, aChildOffset);
|
||||
rv = parent->AddChildSHEntry(mOSHE, aNewEntry, aChildOffset, mLoadType);
|
||||
}
|
||||
|
||||
|
||||
|
@ -3457,7 +3469,6 @@ NS_IMETHODIMP nsDocShell::GotoIndex(PRInt32 aIndex)
|
|||
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::LoadURI(const PRUnichar * aURI,
|
||||
PRUint32 aLoadFlags,
|
||||
|
@ -3846,6 +3857,13 @@ nsDocShell::LoadErrorPage(nsIURI *aURI, const PRUnichar *aURL,
|
|||
mFailedURI = aURI;
|
||||
mFailedLoadType = mLoadType;
|
||||
|
||||
if (mLSHE) {
|
||||
// If we don't give mLSHE a new doc identifier here, when we go back or
|
||||
// forward to another SHEntry with the same doc identifier, the error
|
||||
// page will persist.
|
||||
mLSHE->SetUniqueDocIdentifier();
|
||||
}
|
||||
|
||||
nsCAutoString url;
|
||||
nsCAutoString charset;
|
||||
if (aURI)
|
||||
|
@ -5714,13 +5732,13 @@ nsDocShell::EndPageLoad(nsIWebProgress * aProgress,
|
|||
// We're done with the URI classifier for this channel
|
||||
mClassifier = nsnull;
|
||||
|
||||
//
|
||||
// Notify the ContentViewer that the Document has finished loading...
|
||||
//
|
||||
// This will cause any OnLoad(...) handlers to fire, if it is a HTML
|
||||
// document...
|
||||
//
|
||||
// Notify the ContentViewer that the Document has finished loading. This
|
||||
// will cause any OnLoad(...) and PopState(...) handlers to fire.
|
||||
if (!mEODForCurrentDocument && mContentViewer) {
|
||||
// Set the pending state object which will be returned to the page in
|
||||
// the popstate event.
|
||||
SetDocPendingStateObj(mLSHE);
|
||||
|
||||
mIsExecutingOnLoadHandler = PR_TRUE;
|
||||
mContentViewer->LoadComplete(aStatus);
|
||||
mIsExecutingOnLoadHandler = PR_FALSE;
|
||||
|
@ -7368,6 +7386,26 @@ nsDocShell::SetupNewViewer(nsIContentViewer * aNewViewer)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDocShell::SetDocPendingStateObj(nsISHEntry *shEntry)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIDocument> document = do_GetInterface(GetAsSupports(this));
|
||||
NS_ENSURE_TRUE(document, NS_ERROR_FAILURE);
|
||||
|
||||
nsAutoString stateData;
|
||||
if (shEntry) {
|
||||
rv = shEntry->GetStateData(stateData);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// if shEntry is null, we just set the pending state object to the
|
||||
// empty string.
|
||||
}
|
||||
|
||||
document->SetPendingStateObject(stateData);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDocShell::CheckLoadingPermissions()
|
||||
|
@ -7845,19 +7883,42 @@ nsDocShell::InternalLoad(nsIURI * aURI,
|
|||
#endif
|
||||
}
|
||||
|
||||
if ((aLoadType == LOAD_NORMAL ||
|
||||
if (aLoadType == LOAD_NORMAL ||
|
||||
aLoadType == LOAD_STOP_CONTENT ||
|
||||
LOAD_TYPE_HAS_FLAGS(aLoadType, LOAD_FLAGS_REPLACE_HISTORY) ||
|
||||
aLoadType == LOAD_HISTORY ||
|
||||
aLoadType == LOAD_LINK) && allowScroll) {
|
||||
aLoadType == LOAD_LINK) {
|
||||
|
||||
PRBool wasAnchor = PR_FALSE;
|
||||
PRBool doHashchange = PR_FALSE;
|
||||
nscoord cx, cy;
|
||||
NS_ENSURE_SUCCESS(ScrollIfAnchor(aURI, &wasAnchor, aLoadType, &cx, &cy,
|
||||
&doHashchange),
|
||||
NS_ERROR_FAILURE);
|
||||
|
||||
if (wasAnchor) {
|
||||
if (allowScroll) {
|
||||
NS_ENSURE_SUCCESS(ScrollIfAnchor(aURI, &wasAnchor, aLoadType, &cx,
|
||||
&cy, &doHashchange),
|
||||
NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
// If this is a history load, aSHEntry will have document identifier X
|
||||
// if it was created as a result of a History.pushState() from a
|
||||
// SHEntry with doc ident X, or if it was created by changing the hash
|
||||
// of the URI corresponding to a SHEntry with doc ident X.
|
||||
PRBool sameDocIdent = PR_FALSE;
|
||||
if (mOSHE && aSHEntry) {
|
||||
PRUint64 ourDocIdent, otherDocIdent;
|
||||
mOSHE->GetDocIdentifier(&ourDocIdent);
|
||||
aSHEntry->GetDocIdentifier(&otherDocIdent);
|
||||
sameDocIdent = (ourDocIdent == otherDocIdent);
|
||||
}
|
||||
|
||||
// Do a short-circuited load if the new URI differs from the current
|
||||
// URI only in the hash, or if the two entries belong to the same
|
||||
// document and don't point to the same object.
|
||||
//
|
||||
// (If we didn't check that the SHEntries are different objects,
|
||||
// history.go(0) would short-circuit instead of triggering a true
|
||||
// load, and we wouldn't dispatch an onload event to the page.)
|
||||
if (wasAnchor || (sameDocIdent && (mOSHE != aSHEntry))) {
|
||||
mLoadType = aLoadType;
|
||||
mURIResultedInDocument = PR_TRUE;
|
||||
|
||||
|
@ -7877,6 +7938,7 @@ nsDocShell::InternalLoad(nsIURI * aURI,
|
|||
mOSHE->GetOwner(getter_AddRefs(owner));
|
||||
}
|
||||
OnNewURI(aURI, nsnull, owner, mLoadType, PR_TRUE);
|
||||
|
||||
nsCOMPtr<nsIInputStream> postData;
|
||||
PRUint32 pageIdent = PR_UINT32_MAX;
|
||||
nsCOMPtr<nsISupports> cacheKey;
|
||||
|
@ -7895,6 +7957,17 @@ nsDocShell::InternalLoad(nsIURI * aURI,
|
|||
mOSHE->GetPageIdentifier(&pageIdent);
|
||||
mOSHE->GetCacheKey(getter_AddRefs(cacheKey));
|
||||
}
|
||||
|
||||
if (mLSHE && wasAnchor) {
|
||||
// If it's an anchor load, set mLSHE's doc identifier to
|
||||
// mOSHE's doc identifier -- These are the same documents,
|
||||
// as far as HTML5 is concerned.
|
||||
PRUint64 docIdent;
|
||||
rv = mOSHE->GetDocIdentifier(&docIdent);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mLSHE->SetDocIdentifier(docIdent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Assign mOSHE to mLSHE. This will either be a new entry created
|
||||
|
@ -7949,11 +8022,26 @@ nsDocShell::InternalLoad(nsIURI * aURI,
|
|||
shEntry->SetTitle(mTitle);
|
||||
}
|
||||
|
||||
if (doHashchange) {
|
||||
nsCOMPtr<nsPIDOMWindow> window =
|
||||
do_QueryInterface(mScriptGlobal);
|
||||
if (sameDocIdent) {
|
||||
// Set the doc's URI according to the new history entry's URI
|
||||
nsCOMPtr<nsIURI> newURI;
|
||||
mOSHE->GetURI(getter_AddRefs(newURI));
|
||||
NS_ENSURE_TRUE(newURI, NS_ERROR_FAILURE);
|
||||
nsCOMPtr<nsIDocument> doc =
|
||||
do_GetInterface(GetAsSupports(this));
|
||||
NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
|
||||
|
||||
if (window)
|
||||
doc->SetDocumentURI(newURI);
|
||||
}
|
||||
|
||||
SetDocPendingStateObj(mOSHE);
|
||||
|
||||
// Dispatch the popstate and hashchange events, as appropriate
|
||||
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(mScriptGlobal);
|
||||
if (window) {
|
||||
window->DispatchSyncPopState();
|
||||
|
||||
if (doHashchange)
|
||||
window->DispatchSyncHashchange();
|
||||
}
|
||||
|
||||
|
@ -8837,6 +8925,14 @@ nsDocShell::OnNewURI(nsIURI * aURI, nsIChannel * aChannel, nsISupports* aOwner,
|
|||
if (uploadChannel) {
|
||||
uploadChannel->GetUploadStream(getter_AddRefs(inputStream));
|
||||
}
|
||||
|
||||
// If the response status indicates an error, unlink this session
|
||||
// history entry from any entries sharing its doc ident.
|
||||
PRUint32 responseStatus;
|
||||
nsresult rv = httpChannel->GetResponseStatus(&responseStatus);
|
||||
if (mLSHE && NS_SUCCEEDED(rv) && responseStatus >= 400) {
|
||||
mLSHE->SetUniqueDocIdentifier();
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Create SH Entry (mLSHE) only if there is a SessionHistory object (mSessionHistory) in
|
||||
|
@ -8895,7 +8991,6 @@ nsDocShell::OnNewURI(nsIURI * aURI, nsIChannel * aChannel, nsISupports* aOwner,
|
|||
SetHistoryEntry(&mLSHE, mOSHE);
|
||||
}
|
||||
|
||||
|
||||
/* If the user pressed shift-reload, cache will create a new cache key
|
||||
* for the page. Save the new cacheKey in Session History.
|
||||
* see bug 90098
|
||||
|
@ -8986,6 +9081,282 @@ nsDocShell::SetReferrerURI(nsIURI * aURI)
|
|||
//*****************************************************************************
|
||||
// nsDocShell: Session History
|
||||
//*****************************************************************************
|
||||
|
||||
nsresult
|
||||
nsDocShell::StringifyJSValVariant(nsIVariant *aData, nsAString &aResult)
|
||||
{
|
||||
nsresult rv;
|
||||
aResult.Truncate();
|
||||
|
||||
// First, try to extract a jsval from the variant |aData|. This works only
|
||||
// if the variant implements GetAsJSVal.
|
||||
jsval jsData;
|
||||
rv = aData->GetAsJSVal(&jsData);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_UNEXPECTED);
|
||||
|
||||
// Now get the JSContext associated with the current document.
|
||||
// First get the current document.
|
||||
nsCOMPtr<nsIDocument> document = do_GetInterface(GetAsSupports(this));
|
||||
NS_ENSURE_TRUE(document, NS_ERROR_FAILURE);
|
||||
|
||||
// Get the JSContext from the document, like we do in
|
||||
// nsContentUtils::GetContextFromDocument().
|
||||
nsIScriptGlobalObject *sgo = document->GetScopeObject();
|
||||
NS_ENSURE_TRUE(sgo, NS_ERROR_FAILURE);
|
||||
|
||||
nsIScriptContext *scx = sgo->GetContext();
|
||||
NS_ENSURE_TRUE(scx, NS_ERROR_FAILURE);
|
||||
|
||||
JSContext *cx = (JSContext *)scx->GetNativeContext();
|
||||
|
||||
// If our json call triggers a JS-to-C++ call, we want that call to use cx
|
||||
// as the context. So we push cx onto the context stack.
|
||||
nsCOMPtr<nsIJSContextStack> contextStack =
|
||||
do_GetService("@mozilla.org/js/xpc/ContextStack;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
contextStack->Push(cx);
|
||||
|
||||
nsCOMPtr<nsIJSON> json = do_GetService("@mozilla.org/dom/json;1");
|
||||
if(json) {
|
||||
// Do the encoding
|
||||
rv = json->EncodeFromJSVal(&jsData, cx, aResult);
|
||||
}
|
||||
else {
|
||||
rv = NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Always pop the stack!
|
||||
contextStack->Pop(&cx);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::AddState(nsIVariant *aData, const nsAString& aTitle,
|
||||
const nsAString& aURL, PRBool aReplace)
|
||||
{
|
||||
// Implements History.pushState and History.replaceState
|
||||
|
||||
// Here's what we do, roughly in the order specified by HTML5:
|
||||
// 1. Serialize aData to JSON.
|
||||
// 2. If the third argument is present,
|
||||
// a. Resolve the url, relative to the first script's base URL
|
||||
// b. If (a) fails, raise a SECURITY_ERR
|
||||
// c. Compare the resulting absolute URL to the document's address. If
|
||||
// any part of the URLs difer other than the <path>, <query>, and
|
||||
// <fragment> components, raise a SECURITY_ERR and abort.
|
||||
// 3. If !aReplace:
|
||||
// Remove from the session history all entries after the current entry,
|
||||
// as we would after a regular navigation.
|
||||
// 4. As apropriate, either add a state object entry to the session history
|
||||
// after the current entry with the following properties, or modify the
|
||||
// current session history entry to set
|
||||
// a. cloned data as the state object,
|
||||
// b. the given title as the title, and,
|
||||
// c. if the third argument was present, the absolute URL found in
|
||||
// step 2
|
||||
// 5. If aReplace is false (i.e. we're doing a pushState instead of a
|
||||
// replaceState), notify bfcache that we've navigated to a new page.
|
||||
// 6. If the third argument is present, set the document's current address
|
||||
// to the absolute URL found in step 2.
|
||||
//
|
||||
// It's important that this function not run arbitrary scripts after step 1
|
||||
// and before completing step 5. For example, if a script called
|
||||
// history.back() before we completed step 5, bfcache might destroy an
|
||||
// active content viewer. Since EvictContentViewers at the end of step 5
|
||||
// might run script, we can't just put a script blocker around the critical
|
||||
// section.
|
||||
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIDocument> document = do_GetInterface(GetAsSupports(this));
|
||||
NS_ENSURE_TRUE(document, NS_ERROR_FAILURE);
|
||||
|
||||
mLoadType = LOAD_PUSHSTATE;
|
||||
|
||||
// Step 1: Clone aData by getting its JSON representation
|
||||
nsString dataStr;
|
||||
rv = StringifyJSValVariant(aData, dataStr);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Check that the state object isn't too long.
|
||||
// Default max length: 640k chars.
|
||||
PRInt32 maxStateObjSize = 0xA0000;
|
||||
if (mPrefs) {
|
||||
mPrefs->GetIntPref("browser.history.maxStateObjectSize",
|
||||
&maxStateObjSize);
|
||||
}
|
||||
if (maxStateObjSize < 0)
|
||||
maxStateObjSize = 0;
|
||||
NS_ENSURE_TRUE(dataStr.Length() <= (PRUint32)maxStateObjSize,
|
||||
NS_ERROR_ILLEGAL_VALUE);
|
||||
|
||||
// Step 2: Resolve aURL
|
||||
PRBool equalURIs = PR_TRUE;
|
||||
nsCOMPtr<nsIURI> oldURI = mCurrentURI;
|
||||
nsCOMPtr<nsIURI> newURI;
|
||||
if (aURL.Length() == 0) {
|
||||
newURI = mCurrentURI;
|
||||
}
|
||||
else {
|
||||
// 2a: Resolve aURL relative to mURI
|
||||
|
||||
nsIURI* docBaseURI = document->GetBaseURI();
|
||||
if (!docBaseURI)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCAutoString spec;
|
||||
docBaseURI->GetSpec(spec);
|
||||
|
||||
nsCAutoString charset;
|
||||
rv = docBaseURI->GetOriginCharset(charset);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
|
||||
|
||||
rv = NS_NewURI(getter_AddRefs(newURI), aURL,
|
||||
charset.get(), docBaseURI);
|
||||
|
||||
// 2b: If 2a fails, raise a SECURITY_ERR
|
||||
if (NS_FAILED(rv)) {
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
|
||||
// 2c: Same-origin check.
|
||||
if (!URIIsLocalFile(newURI)) {
|
||||
// In addition to checking that the security manager says that
|
||||
// the new URI has the same origin as our current URI, we also
|
||||
// check that the two URIs have the same userpass. (The
|
||||
// security manager says that |http://foo.com| and
|
||||
// |http://me@foo.com| have the same origin.) mCurrentURI
|
||||
// won't contain the password part of the userpass, so this
|
||||
// means that it's never valid to specify a password in a
|
||||
// pushState or replaceState URI.
|
||||
|
||||
nsCOMPtr<nsIScriptSecurityManager> secMan =
|
||||
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
|
||||
NS_ENSURE_TRUE(secMan, NS_ERROR_FAILURE);
|
||||
|
||||
// It's very important that we check that newURI is of the same
|
||||
// origin as mCurrentURI, not docBaseURI, because a page can
|
||||
// set docBaseURI arbitrarily to any domain.
|
||||
nsCAutoString currentUserPass, newUserPass;
|
||||
NS_ENSURE_SUCCESS(mCurrentURI->GetUserPass(currentUserPass),
|
||||
NS_ERROR_FAILURE);
|
||||
NS_ENSURE_SUCCESS(newURI->GetUserPass(newUserPass),
|
||||
NS_ERROR_FAILURE);
|
||||
if (NS_FAILED(secMan->CheckSameOriginURI(mCurrentURI,
|
||||
newURI, PR_TRUE)) ||
|
||||
!currentUserPass.Equals(newUserPass)) {
|
||||
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// It's a file:// URI
|
||||
nsCOMPtr<nsIScriptObjectPrincipal> docScriptObj =
|
||||
do_QueryInterface(document);
|
||||
|
||||
if (!docScriptObj) {
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal = docScriptObj->GetPrincipal();
|
||||
|
||||
if (!principal ||
|
||||
NS_FAILED(principal->CheckMayLoad(newURI, PR_TRUE))) {
|
||||
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
mCurrentURI->Equals(newURI, &equalURIs);
|
||||
|
||||
} // end of same-origin check
|
||||
|
||||
nsCOMPtr<nsISHistory> sessionHistory = mSessionHistory;
|
||||
if (!sessionHistory) {
|
||||
// Get the handle to SH from the root docshell
|
||||
GetRootSessionHistory(getter_AddRefs(sessionHistory));
|
||||
}
|
||||
NS_ENSURE_TRUE(sessionHistory, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsISHistoryInternal> shInternal =
|
||||
do_QueryInterface(sessionHistory, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Step 3: Create a new entry in the session history; this will erase
|
||||
// all SHEntries after the new entry and make this entry the current
|
||||
// one. This operation may modify mOSHE, which we need later, so we
|
||||
// keep a reference here.
|
||||
NS_ENSURE_TRUE(mOSHE, NS_ERROR_FAILURE);
|
||||
nsCOMPtr<nsISHEntry> oldOSHE = mOSHE;
|
||||
|
||||
nsCOMPtr<nsISHEntry> newSHEntry;
|
||||
if (!aReplace) {
|
||||
rv = AddToSessionHistory(newURI, nsnull, nsnull,
|
||||
getter_AddRefs(newSHEntry));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
NS_ENSURE_TRUE(newSHEntry, NS_ERROR_FAILURE);
|
||||
|
||||
// Set the new SHEntry's document identifier, if we can.
|
||||
PRUint64 ourDocIdent;
|
||||
NS_ENSURE_SUCCESS(oldOSHE->GetDocIdentifier(&ourDocIdent),
|
||||
NS_ERROR_FAILURE);
|
||||
NS_ENSURE_SUCCESS(newSHEntry->SetDocIdentifier(ourDocIdent),
|
||||
NS_ERROR_FAILURE);
|
||||
|
||||
// AddToSessionHistory may not modify mOSHE. In case it doesn't,
|
||||
// we'll just set mOSHE here.
|
||||
mOSHE = newSHEntry;
|
||||
|
||||
} else {
|
||||
newSHEntry = mOSHE;
|
||||
newSHEntry->SetURI(newURI);
|
||||
}
|
||||
|
||||
// Step 4: Modify new/original session history entry
|
||||
newSHEntry->SetStateData(dataStr);
|
||||
|
||||
// Step 5: If aReplace is false, indicating that we're doing a pushState
|
||||
// rather than a replaceState, notify bfcache that we've added a page to
|
||||
// the history so it can evict content viewers if appropriate.
|
||||
if (!aReplace) {
|
||||
nsCOMPtr<nsISHistory> rootSH;
|
||||
GetRootSessionHistory(getter_AddRefs(rootSH));
|
||||
NS_ENSURE_TRUE(rootSH, NS_ERROR_UNEXPECTED);
|
||||
|
||||
nsCOMPtr<nsISHistoryInternal> internalSH =
|
||||
do_QueryInterface(rootSH);
|
||||
NS_ENSURE_TRUE(internalSH, NS_ERROR_UNEXPECTED);
|
||||
|
||||
PRInt32 curIndex = -1;
|
||||
rv = rootSH->GetIndex(&curIndex);
|
||||
if (NS_SUCCEEDED(rv) && curIndex > -1) {
|
||||
internalSH->EvictContentViewers(curIndex - 1, curIndex);
|
||||
}
|
||||
}
|
||||
|
||||
// Step 6: If the document's URI changed, update document's URI and update
|
||||
// global history
|
||||
if (!equalURIs) {
|
||||
SetCurrentURI(newURI, nsnull, PR_TRUE);
|
||||
document->SetDocumentURI(newURI);
|
||||
|
||||
AddToGlobalHistory(newURI, PR_FALSE, oldURI);
|
||||
}
|
||||
|
||||
// Try to set the title of the current history element
|
||||
if (mOSHE)
|
||||
mOSHE->SetTitle(aTitle);
|
||||
|
||||
// We need this to ensure that the back button is enabled after a
|
||||
// pushState, if it wasn't already enabled.
|
||||
FireOnLocationChange(this, nsnull, mCurrentURI);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsDocShell::ShouldAddToSessionHistory(nsIURI * aURI)
|
||||
{
|
||||
|
@ -9428,7 +9799,6 @@ nsDocShell::CloneAndReplace(nsISHEntry *aSrcEntry,
|
|||
return rv;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nsDocShell::SwapHistoryEntries(nsISHEntry *aOldEntry, nsISHEntry *aNewEntry)
|
||||
{
|
||||
|
@ -9679,9 +10049,6 @@ nsresult
|
|||
nsDocShell::AddToGlobalHistory(nsIURI * aURI, PRBool aRedirect,
|
||||
nsIChannel * aChannel)
|
||||
{
|
||||
if (mItemType != typeContent || !mGlobalHistory)
|
||||
return NS_OK;
|
||||
|
||||
// If this is a POST request, we do not want to include this in global
|
||||
// history, so return early.
|
||||
nsCOMPtr<nsIHttpChannel> hchan(do_QueryInterface(aChannel));
|
||||
|
@ -9692,16 +10059,26 @@ nsDocShell::AddToGlobalHistory(nsIURI * aURI, PRBool aRedirect,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> referrer;
|
||||
if (aChannel)
|
||||
NS_GetReferrerFromChannel(aChannel, getter_AddRefs(referrer));
|
||||
|
||||
return AddToGlobalHistory(aURI, aRedirect, referrer);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDocShell::AddToGlobalHistory(nsIURI * aURI, PRBool aRedirect,
|
||||
nsIURI * aReferrer)
|
||||
{
|
||||
if (mItemType != typeContent || !mGlobalHistory)
|
||||
return NS_OK;
|
||||
|
||||
PRBool visited;
|
||||
nsresult rv = mGlobalHistory->IsVisited(aURI, &visited);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsCOMPtr<nsIURI> referrer;
|
||||
if (aChannel)
|
||||
NS_GetReferrerFromChannel(aChannel, getter_AddRefs(referrer));
|
||||
|
||||
rv = mGlobalHistory->AddURI(aURI, aRedirect, !IsFrame(), referrer);
|
||||
rv = mGlobalHistory->AddURI(aURI, aRedirect, !IsFrame(), aReferrer);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
|
@ -9714,6 +10091,7 @@ nsDocShell::AddToGlobalHistory(nsIURI * aURI, PRBool aRedirect,
|
|||
}
|
||||
|
||||
return NS_OK;
|
||||
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
|
|
|
@ -364,6 +364,10 @@ protected:
|
|||
PRUint32 aLoadType, nscoord *cx, nscoord *cy,
|
||||
PRBool * aDoHashchange);
|
||||
|
||||
// Tries to stringify a given variant by converting it to JSON. This only
|
||||
// works if the variant is backed by a JSVal.
|
||||
nsresult StringifyJSValVariant(nsIVariant *aData, nsAString &aResult);
|
||||
|
||||
// Returns PR_TRUE if would have called FireOnLocationChange,
|
||||
// but did not because aFireOnLocationChange was false on entry.
|
||||
// In this case it is the caller's responsibility to ensure
|
||||
|
@ -465,8 +469,11 @@ protected:
|
|||
PRUint32 aStateFlags);
|
||||
|
||||
// Global History
|
||||
|
||||
nsresult AddToGlobalHistory(nsIURI * aURI, PRBool aRedirect,
|
||||
nsIChannel * aChannel);
|
||||
nsresult AddToGlobalHistory(nsIURI * aURI, PRBool aRedirect,
|
||||
nsIURI * aReferrer);
|
||||
|
||||
// Helper Routines
|
||||
nsresult ConfirmRepost(PRBool * aRepost);
|
||||
|
@ -515,6 +522,11 @@ protected:
|
|||
nsIChannel * aChannel,
|
||||
nsresult aResult);
|
||||
|
||||
// Sets the current document's pending state object to the given SHEntry's
|
||||
// state object. The pending state object is eventually given to the page
|
||||
// in the PopState event.
|
||||
nsresult SetDocPendingStateObj(nsISHEntry *shEntry);
|
||||
|
||||
nsresult CheckLoadingPermissions();
|
||||
|
||||
// Security checks to prevent frameset spoofing. See comments at
|
||||
|
|
|
@ -92,6 +92,7 @@ enum LoadType {
|
|||
LOAD_BYPASS_HISTORY = MAKE_LOAD_TYPE(nsIDocShell::LOAD_CMD_NORMAL, nsIWebNavigation::LOAD_FLAGS_BYPASS_HISTORY),
|
||||
LOAD_STOP_CONTENT = MAKE_LOAD_TYPE(nsIDocShell::LOAD_CMD_NORMAL, nsIWebNavigation::LOAD_FLAGS_STOP_CONTENT),
|
||||
LOAD_STOP_CONTENT_AND_REPLACE = MAKE_LOAD_TYPE(nsIDocShell::LOAD_CMD_NORMAL, nsIWebNavigation::LOAD_FLAGS_STOP_CONTENT | nsIWebNavigation::LOAD_FLAGS_REPLACE_HISTORY),
|
||||
LOAD_PUSHSTATE = MAKE_LOAD_TYPE(nsIDocShell::LOAD_CMD_PUSHSTATE, nsIWebNavigation::LOAD_FLAGS_NONE),
|
||||
/**
|
||||
* Load type for an error page. These loads are never triggered by users of
|
||||
* Docshell. Instead, Docshell triggers the load itself when a
|
||||
|
@ -122,6 +123,7 @@ static inline PRBool IsValidLoadType(PRUint32 aLoadType)
|
|||
case LOAD_BYPASS_HISTORY:
|
||||
case LOAD_STOP_CONTENT:
|
||||
case LOAD_STOP_CONTENT_AND_REPLACE:
|
||||
case LOAD_PUSHSTATE:
|
||||
case LOAD_ERROR_PAGE:
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
|
|
@ -69,8 +69,9 @@ interface nsISecureBrowserUI;
|
|||
interface nsIDOMStorage;
|
||||
interface nsIPrincipal;
|
||||
interface nsIWebBrowserPrint;
|
||||
interface nsIVariant;
|
||||
|
||||
[scriptable, uuid(c95eaff1-14e6-4db1-a806-46be97d5a9b6)]
|
||||
[scriptable, uuid(3adde256-05a9-43a7-a190-f8fe75eecfd6)]
|
||||
interface nsIDocShell : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -169,6 +170,13 @@ interface nsIDocShell : nsISupports
|
|||
out nsIDocShell aDocShell,
|
||||
out nsIRequest aRequest);
|
||||
|
||||
/**
|
||||
* Do either a history.pushState() or history.replaceState() operation,
|
||||
* depending on the value of aReplace.
|
||||
*/
|
||||
void addState(in nsIVariant aData, in DOMString aTitle,
|
||||
in DOMString aURL, in boolean aReplace);
|
||||
|
||||
/**
|
||||
* Creates a DocShellLoadInfo object that you can manipulate and then pass
|
||||
* to loadURI.
|
||||
|
@ -342,6 +350,7 @@ interface nsIDocShell : nsISupports
|
|||
const unsigned long LOAD_CMD_NORMAL = 0x1; // Normal load
|
||||
const unsigned long LOAD_CMD_RELOAD = 0x2; // Reload
|
||||
const unsigned long LOAD_CMD_HISTORY = 0x4; // Load from history
|
||||
const unsigned long LOAD_CMD_PUSHSTATE = 0x8; // History.pushState()
|
||||
|
||||
readonly attribute unsigned long busyFlags;
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
#include "nsISupports.idl"
|
||||
interface nsISHEntry;
|
||||
|
||||
[scriptable, uuid(89caa9f0-8b1c-47fb-b0d3-f0aef0bff749)]
|
||||
[scriptable, uuid(a89b80a8-3c44-4a25-9d2c-2fb42358b46e)]
|
||||
interface nsIDocShellHistory : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -48,11 +48,12 @@ interface nsIDocShellHistory : nsISupports
|
|||
nsISHEntry getChildSHEntry(in long aChildOffset);
|
||||
|
||||
/**
|
||||
* Add a Child SHEntry for a frameset page
|
||||
* Add a Child SHEntry for a frameset page, given the child's loadtype.
|
||||
*/
|
||||
void addChildSHEntry(in nsISHEntry aCloneReference,
|
||||
in nsISHEntry aHistoryEntry,
|
||||
in long aChildOffset);
|
||||
in long aChildOffset,
|
||||
in unsigned long aLoadType);
|
||||
|
||||
/*
|
||||
* Whether this docshell should save entries in global history.
|
||||
|
|
|
@ -58,7 +58,7 @@ class nsDocShellEditorData;
|
|||
[ptr] native nsDocShellEditorDataPtr(nsDocShellEditorData);
|
||||
|
||||
|
||||
[scriptable, uuid(09fecea6-5453-43ba-bf91-3ff32618f037)]
|
||||
[scriptable, uuid(62b0603f-57ca-439e-a0fb-6f6978500755)]
|
||||
interface nsISHEntry : nsIHistoryEntry
|
||||
{
|
||||
/** URI for the document */
|
||||
|
@ -149,6 +149,21 @@ interface nsISHEntry : nsIHistoryEntry
|
|||
*/
|
||||
attribute unsigned long pageIdentifier;
|
||||
|
||||
/**
|
||||
* docIdentifier is an integer that should be the same for two entries
|
||||
* attached to the same docshell if and only if the two entries are entries
|
||||
* for the same document. In practice, two entries A and B will have the
|
||||
* same docIdentifier if they have the same pageIdentifier or if B was
|
||||
* created by A calling history.pushState().
|
||||
*/
|
||||
attribute unsigned long long docIdentifier;
|
||||
|
||||
/**
|
||||
* Changes this entry's doc identifier to a new value which is unique
|
||||
* among those of all other entries.
|
||||
*/
|
||||
void setUniqueDocIdentifier();
|
||||
|
||||
/** attribute to set and get the cache key for the entry */
|
||||
attribute nsISupports cacheKey;
|
||||
|
||||
|
@ -192,6 +207,12 @@ interface nsISHEntry : nsIHistoryEntry
|
|||
*/
|
||||
attribute nsISupports owner;
|
||||
|
||||
/**
|
||||
* Get/set data associated with this history state via a pushState() call,
|
||||
* encoded as JSON.
|
||||
**/
|
||||
attribute AString stateData;
|
||||
|
||||
/**
|
||||
* Gets the owning pointer to the editor data assosicated with
|
||||
* this shistory entry. This forgets its pointer, so free it when
|
||||
|
|
|
@ -75,6 +75,7 @@ protected:
|
|||
|
||||
static HistoryTracker *gHistoryTracker = nsnull;
|
||||
static PRUint32 gEntryID = 0;
|
||||
static PRUint64 gEntryDocIdentifier = 0;
|
||||
|
||||
nsresult nsSHEntry::Startup()
|
||||
{
|
||||
|
@ -104,6 +105,7 @@ nsSHEntry::nsSHEntry()
|
|||
: mLoadType(0)
|
||||
, mID(gEntryID++)
|
||||
, mPageIdentifier(mID)
|
||||
, mDocIdentifier(gEntryDocIdentifier++)
|
||||
, mScrollPositionX(0)
|
||||
, mScrollPositionY(0)
|
||||
, mIsFrameNavigation(PR_FALSE)
|
||||
|
@ -125,6 +127,7 @@ nsSHEntry::nsSHEntry(const nsSHEntry &other)
|
|||
, mLoadType(0) // XXX why not copy?
|
||||
, mID(other.mID)
|
||||
, mPageIdentifier(other.mPageIdentifier)
|
||||
, mDocIdentifier(other.mDocIdentifier)
|
||||
, mScrollPositionX(0) // XXX why not copy?
|
||||
, mScrollPositionY(0) // XXX why not copy?
|
||||
, mIsFrameNavigation(other.mIsFrameNavigation)
|
||||
|
@ -393,6 +396,30 @@ NS_IMETHODIMP nsSHEntry::SetPageIdentifier(PRUint32 aPageIdentifier)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsSHEntry::GetDocIdentifier(PRUint64 * aResult)
|
||||
{
|
||||
*aResult = mDocIdentifier;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsSHEntry::SetDocIdentifier(PRUint64 aDocIdentifier)
|
||||
{
|
||||
// This ensures that after a session restore, gEntryDocIdentifier is greater
|
||||
// than all SHEntries' docIdentifiers, which ensures that we'll never repeat
|
||||
// a doc identifier.
|
||||
if (aDocIdentifier >= gEntryDocIdentifier)
|
||||
gEntryDocIdentifier = aDocIdentifier + 1;
|
||||
|
||||
mDocIdentifier = aDocIdentifier;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsSHEntry::SetUniqueDocIdentifier()
|
||||
{
|
||||
mDocIdentifier = gEntryDocIdentifier++;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsSHEntry::GetIsSubFrame(PRBool * aFlag)
|
||||
{
|
||||
*aFlag = mIsFrameNavigation;
|
||||
|
@ -866,3 +893,17 @@ nsSHEntry::HasDetachedEditor()
|
|||
return mEditorData != nsnull;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSHEntry::GetStateData(nsAString &aStateData)
|
||||
{
|
||||
aStateData.Assign(mStateData);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSHEntry::SetStateData(const nsAString &aDataStr)
|
||||
{
|
||||
mStateData.Assign(aDataStr);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -99,6 +99,7 @@ private:
|
|||
PRUint32 mLoadType;
|
||||
PRUint32 mID;
|
||||
PRUint32 mPageIdentifier;
|
||||
PRInt64 mDocIdentifier;
|
||||
PRInt32 mScrollPositionX;
|
||||
PRInt32 mScrollPositionY;
|
||||
PRPackedBool mIsFrameNavigation;
|
||||
|
@ -115,6 +116,7 @@ private:
|
|||
nsCOMPtr<nsISupports> mOwner;
|
||||
nsExpirationState mExpirationState;
|
||||
nsAutoPtr<nsDocShellEditorData> mEditorData;
|
||||
nsString mStateData;
|
||||
};
|
||||
|
||||
#endif /* nsSHEntry_h */
|
||||
|
|
|
@ -492,9 +492,10 @@ nsSHistory::PrintHistory()
|
|||
uri->GetSpec(url);
|
||||
|
||||
printf("**** SH Transaction #%d, Entry = %x\n", index, entry.get());
|
||||
printf("\t\t URL = %s\n", url);
|
||||
printf("\t\t URL = %s\n", url.get());
|
||||
|
||||
printf("\t\t Title = %s\n", NS_LossyConvertUTF16toASCII(title).get());
|
||||
printf("\t\t layout History Data = %x\n", layoutHistoryState);
|
||||
printf("\t\t layout History Data = %x\n", layoutHistoryState.get());
|
||||
#endif
|
||||
|
||||
nsCOMPtr<nsISHTransaction> next;
|
||||
|
@ -1223,7 +1224,6 @@ nsSHistory::LoadEntry(PRInt32 aIndex, long aLoadType, PRUint32 aHistCmd)
|
|||
docShell = mRootDocShell;
|
||||
}
|
||||
|
||||
|
||||
if (!docShell) {
|
||||
// we did not successfully go to the proper index.
|
||||
// return error.
|
||||
|
@ -1235,8 +1235,6 @@ nsSHistory::LoadEntry(PRInt32 aIndex, long aLoadType, PRUint32 aHistCmd)
|
|||
return InitiateLoad(nextEntry, docShell, aLoadType);
|
||||
}
|
||||
|
||||
|
||||
|
||||
nsresult
|
||||
nsSHistory::CompareFrames(nsISHEntry * aPrevEntry, nsISHEntry * aNextEntry, nsIDocShell * aParent, long aLoadType, PRBool * aIsFrameFound)
|
||||
{
|
||||
|
|
|
@ -82,6 +82,7 @@
|
|||
#include "nsIDOMNSEvent.h"
|
||||
#include "nsIDOMKeyEvent.h"
|
||||
#include "nsIDOMEventListener.h"
|
||||
#include "nsIDOMPopStateEvent.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsDOMWindowUtils.h"
|
||||
|
||||
|
@ -1330,13 +1331,15 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
|||
|
||||
NS_DEFINE_CLASSINFO_DATA(ScrollAreaEvent, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(PopStateEvent, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(EventListenerInfo, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(TransitionEvent, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
};
|
||||
|
||||
// Objects that shuld be constructable through |new Name();|
|
||||
// Objects that should be constructable through |new Name();|
|
||||
struct nsContractIDMapData
|
||||
{
|
||||
PRInt32 mDOMClassInfoID;
|
||||
|
@ -1420,6 +1423,7 @@ jsval nsDOMClassInfo::sOnreset_id = JSVAL_VOID;
|
|||
jsval nsDOMClassInfo::sOnchange_id = JSVAL_VOID;
|
||||
jsval nsDOMClassInfo::sOnselect_id = JSVAL_VOID;
|
||||
jsval nsDOMClassInfo::sOnload_id = JSVAL_VOID;
|
||||
jsval nsDOMClassInfo::sOnpopstate_id = JSVAL_VOID;
|
||||
jsval nsDOMClassInfo::sOnbeforeunload_id = JSVAL_VOID;
|
||||
jsval nsDOMClassInfo::sOnunload_id = JSVAL_VOID;
|
||||
jsval nsDOMClassInfo::sOnhashchange_id = JSVAL_VOID;
|
||||
|
@ -1614,6 +1618,7 @@ nsDOMClassInfo::DefineStaticJSVals(JSContext *cx)
|
|||
SET_JSVAL_TO_STRING(sOnchange_id, cx, "onchange");
|
||||
SET_JSVAL_TO_STRING(sOnselect_id, cx, "onselect");
|
||||
SET_JSVAL_TO_STRING(sOnload_id, cx, "onload");
|
||||
SET_JSVAL_TO_STRING(sOnpopstate_id, cx, "onpopstate");
|
||||
SET_JSVAL_TO_STRING(sOnbeforeunload_id, cx, "onbeforeunload");
|
||||
SET_JSVAL_TO_STRING(sOnunload_id, cx, "onunload");
|
||||
SET_JSVAL_TO_STRING(sOnhashchange_id, cx, "onhashchange");
|
||||
|
@ -2232,6 +2237,11 @@ nsDOMClassInfo::Init()
|
|||
DOM_CLASSINFO_UI_EVENT_MAP_ENTRIES
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(PopStateEvent, nsIDOMPopStateEvent)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMPopStateEvent)
|
||||
DOM_CLASSINFO_EVENT_MAP_ENTRIES
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(HTMLDocument, nsIDOMHTMLDocument)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMHTMLDocument)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSHTMLDocument)
|
||||
|
@ -7327,7 +7337,8 @@ nsEventReceiverSH::ReallyIsEventName(jsval id, jschar aFirstChar)
|
|||
return (id == sOnpaint_id ||
|
||||
id == sOnpageshow_id ||
|
||||
id == sOnpagehide_id ||
|
||||
id == sOnpaste_id);
|
||||
id == sOnpaste_id ||
|
||||
id == sOnpopstate_id);
|
||||
case 'k' :
|
||||
return (id == sOnkeydown_id ||
|
||||
id == sOnkeypress_id ||
|
||||
|
|
|
@ -327,6 +327,7 @@ protected:
|
|||
static jsval sOnchange_id;
|
||||
static jsval sOnselect_id;
|
||||
static jsval sOnload_id;
|
||||
static jsval sOnpopstate_id;
|
||||
static jsval sOnbeforeunload_id;
|
||||
static jsval sOnunload_id;
|
||||
static jsval sOnhashchange_id;
|
||||
|
|
|
@ -473,6 +473,7 @@ enum nsDOMClassInfoID {
|
|||
eDOMClassInfo_PaintRequestList_id,
|
||||
|
||||
eDOMClassInfo_ScrollAreaEvent_id,
|
||||
eDOMClassInfo_PopStateEvent_id,
|
||||
|
||||
eDOMClassInfo_EventListenerInfo_id,
|
||||
|
||||
|
|
|
@ -79,6 +79,7 @@
|
|||
#include "nsCycleCollector.h"
|
||||
#include "nsCCUncollectableMarker.h"
|
||||
#include "nsDOMThreadService.h"
|
||||
#include "nsAutoJSValHolder.h"
|
||||
|
||||
// Interfaces Needed
|
||||
#include "nsIFrame.h"
|
||||
|
@ -112,6 +113,7 @@
|
|||
#include "nsIDOMKeyEvent.h"
|
||||
#include "nsIDOMMessageEvent.h"
|
||||
#include "nsIDOMPopupBlockedEvent.h"
|
||||
#include "nsIDOMPopStateEvent.h"
|
||||
#include "nsIDOMOfflineResourceList.h"
|
||||
#include "nsIDOMGeoGeolocation.h"
|
||||
#include "nsPIDOMStorage.h"
|
||||
|
@ -169,6 +171,7 @@
|
|||
#include "nsIXULAppInfo.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsFocusManager.h"
|
||||
#include "nsIJSON.h"
|
||||
#ifdef MOZ_XUL
|
||||
#include "nsXULPopupManager.h"
|
||||
#include "nsIDOMXULControlElement.h"
|
||||
|
@ -361,6 +364,8 @@ static const char sJSStackContractID[] = "@mozilla.org/js/xpc/ContextStack;1";
|
|||
static const char kCryptoContractID[] = NS_CRYPTO_CONTRACTID;
|
||||
static const char kPkcs11ContractID[] = NS_PKCS11_CONTRACTID;
|
||||
|
||||
static const char sPopStatePrefStr[] = "browser.history.allowPopState";
|
||||
|
||||
static PRBool
|
||||
IsAboutBlank(nsIURI* aURI)
|
||||
{
|
||||
|
@ -655,9 +660,9 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow)
|
|||
mTimeoutPublicIdCounter(1),
|
||||
mTimeoutFiringDepth(0),
|
||||
mJSObject(nsnull),
|
||||
mPendingStorageEventsObsolete(nsnull),
|
||||
mTimeoutsSuspendDepth(0),
|
||||
mFocusMethod(0),
|
||||
mPendingStorageEventsObsolete(nsnull)
|
||||
mFocusMethod(0)
|
||||
#ifdef DEBUG
|
||||
, mSetOpenerWindowCalled(PR_FALSE)
|
||||
#endif
|
||||
|
@ -6987,7 +6992,119 @@ nsGlobalWindow::DispatchSyncHashchange()
|
|||
PR_FALSE, PR_FALSE);
|
||||
}
|
||||
|
||||
// Find an nsCanvasFrame under aFrame. Only search the principal
|
||||
nsresult
|
||||
nsGlobalWindow::DispatchSyncPopState()
|
||||
{
|
||||
FORWARD_TO_INNER(DispatchSyncPopState, (), NS_OK);
|
||||
|
||||
NS_ASSERTION(nsContentUtils::IsSafeToRunScript(),
|
||||
"Must be safe to run script here.");
|
||||
|
||||
// Check that PopState hasn't been pref'ed off.
|
||||
if (!nsContentUtils::GetBoolPref(sPopStatePrefStr, PR_FALSE))
|
||||
return NS_OK;
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
// Bail if the window is frozen.
|
||||
if (IsFrozen()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Bail if there's no document or the document's readystate isn't "complete".
|
||||
if (!mDoc) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIDocument::ReadyState readyState = mDoc->GetReadyStateEnum();
|
||||
if (readyState != nsIDocument::READYSTATE_COMPLETE) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Get the document's pending state object -- it contains the data we're
|
||||
// going to send along with the popstate event. The object is serialized as
|
||||
// JSON.
|
||||
nsAString& stateObjJSON = mDoc->GetPendingStateObject();
|
||||
|
||||
nsCOMPtr<nsIVariant> stateObj;
|
||||
// Parse the JSON, if there's any to parse.
|
||||
if (!stateObjJSON.IsEmpty()) {
|
||||
// Get the JSContext associated with our document. We need this for
|
||||
// deserialization.
|
||||
nsCOMPtr<nsIDocument> document = do_QueryInterface(mDocument);
|
||||
NS_ENSURE_TRUE(document, NS_ERROR_FAILURE);
|
||||
|
||||
// Get the JSContext from the document, like we do in
|
||||
// nsContentUtils::GetContextFromDocument().
|
||||
nsIScriptGlobalObject *sgo = document->GetScopeObject();
|
||||
NS_ENSURE_TRUE(sgo, NS_ERROR_FAILURE);
|
||||
|
||||
nsIScriptContext *scx = sgo->GetContext();
|
||||
NS_ENSURE_TRUE(scx, NS_ERROR_FAILURE);
|
||||
|
||||
JSContext *cx = (JSContext*) scx->GetNativeContext();
|
||||
|
||||
// If our json call triggers a JS-to-C++ call, we want that call to use cx
|
||||
// as the context. So we push cx onto the context stack.
|
||||
nsCxPusher cxPusher;
|
||||
|
||||
jsval jsStateObj = JSVAL_NULL;
|
||||
// Root the container which will hold our decoded state object.
|
||||
nsAutoGCRoot(&jsStateObj, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Deserialize the state object into an nsIVariant.
|
||||
nsCOMPtr<nsIJSON> json = do_GetService("@mozilla.org/dom/json;1");
|
||||
NS_ENSURE_TRUE(cxPusher.Push(cx), NS_ERROR_FAILURE);
|
||||
rv = json->DecodeToJSVal(stateObjJSON, cx, &jsStateObj);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
cxPusher.Pop();
|
||||
|
||||
nsCOMPtr<nsIXPConnect> xpconnect = do_GetService(nsIXPConnect::GetCID());
|
||||
NS_ENSURE_TRUE(xpconnect, NS_ERROR_FAILURE);
|
||||
rv = xpconnect->JSValToVariant(cx, &jsStateObj, getter_AddRefs(stateObj));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// Obtain a presentation shell for use in creating a popstate event.
|
||||
nsIPresShell *shell = mDoc->GetPrimaryShell();
|
||||
nsCOMPtr<nsPresContext> presContext;
|
||||
if (shell) {
|
||||
presContext = shell->GetPresContext();
|
||||
}
|
||||
|
||||
// Create a new popstate event
|
||||
nsCOMPtr<nsIDOMEvent> domEvent;
|
||||
rv = nsEventDispatcher::CreateEvent(presContext, nsnull,
|
||||
NS_LITERAL_STRING("popstateevent"),
|
||||
getter_AddRefs(domEvent));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIPrivateDOMEvent> privateEvent = do_QueryInterface(domEvent);
|
||||
NS_ENSURE_TRUE(privateEvent, NS_ERROR_FAILURE);
|
||||
|
||||
// Initialize the popstate event, which does bubble but isn't cancellable.
|
||||
nsCOMPtr<nsIDOMPopStateEvent> popstateEvent = do_QueryInterface(domEvent);
|
||||
rv = popstateEvent->InitPopStateEvent(NS_LITERAL_STRING("popstate"),
|
||||
PR_TRUE, PR_FALSE,
|
||||
stateObj);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = privateEvent->SetTrusted(PR_TRUE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDOMEventTarget> outerWindow =
|
||||
do_QueryInterface(GetOuterWindow());
|
||||
NS_ENSURE_TRUE(outerWindow, NS_ERROR_UNEXPECTED);
|
||||
|
||||
rv = privateEvent->SetTarget(outerWindow);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRBool dummy; // default action
|
||||
return DispatchEvent(popstateEvent, &dummy);
|
||||
}
|
||||
|
||||
// Find an nsICanvasFrame under aFrame. Only search the principal
|
||||
// child lists. aFrame must be non-null.
|
||||
static nsCanvasFrame* FindCanvasFrame(nsIFrame* aFrame)
|
||||
{
|
||||
|
|
|
@ -448,6 +448,8 @@ public:
|
|||
virtual void SetReadyForFocus();
|
||||
virtual void PageHidden();
|
||||
virtual nsresult DispatchSyncHashchange();
|
||||
virtual nsresult DispatchSyncPopState();
|
||||
|
||||
virtual nsresult SetArguments(nsIArray *aArguments, nsIPrincipal *aOrigin);
|
||||
|
||||
static PRBool DOMWindowDumpEnabled();
|
||||
|
|
|
@ -57,6 +57,13 @@
|
|||
#include "nsReadableUtils.h"
|
||||
#include "nsDOMClassInfo.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIDOMNSDocument.h"
|
||||
#include "nsISHistoryInternal.h"
|
||||
|
||||
static const char* sAllowPushStatePrefStr =
|
||||
"browser.history.allowPushState";
|
||||
static const char* sAllowReplaceStatePrefStr =
|
||||
"browser.history.allowReplaceState";
|
||||
|
||||
//
|
||||
// History class implementation
|
||||
|
@ -272,6 +279,47 @@ nsHistory::Go(PRInt32 aDelta)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHistory::PushState(nsIVariant *aData, const nsAString& aTitle,
|
||||
const nsAString& aURL)
|
||||
{
|
||||
// Check that PushState hasn't been pref'ed off.
|
||||
if (!nsContentUtils::GetBoolPref(sAllowPushStatePrefStr, PR_FALSE))
|
||||
return NS_OK;
|
||||
|
||||
NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
|
||||
|
||||
// AddState might run scripts, so we need to hold a strong reference to the
|
||||
// docShell here to keep it from going away.
|
||||
nsCOMPtr<nsIDocShell> docShell = mDocShell;
|
||||
|
||||
// PR_FALSE tells the docshell to add a new history entry instead of
|
||||
// modifying the current one.
|
||||
nsresult rv = mDocShell->AddState(aData, aTitle, aURL, PR_FALSE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHistory::ReplaceState(nsIVariant *aData, const nsAString& aTitle,
|
||||
const nsAString& aURL)
|
||||
{
|
||||
// Check that ReplaceState hasn't been pref'ed off
|
||||
if (!nsContentUtils::GetBoolPref(sAllowReplaceStatePrefStr, PR_FALSE))
|
||||
return NS_OK;
|
||||
|
||||
NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
|
||||
|
||||
// As in PushState(), we need to keep a strong reference to the docShell
|
||||
// here.
|
||||
nsCOMPtr<nsIDocShell> docShell = mDocShell;
|
||||
|
||||
// PR_TRUE tells the docshell to modify the current SHEntry, rather than
|
||||
// create a new one.
|
||||
return mDocShell->AddState(aData, aTitle, aURL, PR_TRUE);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHistory::Item(PRUint32 aIndex, nsAString& aReturn)
|
||||
{
|
||||
|
|
|
@ -194,7 +194,6 @@ nsLocation::CheckURL(nsIURI* aURI, nsIDocShellLoadInfo** aLoadInfo)
|
|||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsISupports> owner;
|
||||
nsCOMPtr<nsIURI> sourceURI;
|
||||
|
||||
if (cx) {
|
||||
// No cx means that there's no JS running, or at least no JS that
|
||||
|
@ -222,7 +221,6 @@ nsLocation::CheckURL(nsIURI* aURI, nsIDocShellLoadInfo** aLoadInfo)
|
|||
!principal)
|
||||
return NS_ERROR_FAILURE;
|
||||
owner = do_QueryInterface(principal);
|
||||
principal->GetURI(getter_AddRefs(sourceURI));
|
||||
}
|
||||
|
||||
// Create load info
|
||||
|
@ -232,10 +230,12 @@ nsLocation::CheckURL(nsIURI* aURI, nsIDocShellLoadInfo** aLoadInfo)
|
|||
|
||||
loadInfo->SetOwner(owner);
|
||||
|
||||
// now set the referrer on the loadinfo
|
||||
if (sourceURI) {
|
||||
// Now set the referrer on the loadinfo. We need to do this in order to get
|
||||
// the correct referrer URI from a document which was pushStated.
|
||||
nsCOMPtr<nsIURI> sourceURI;
|
||||
result = GetURI(getter_AddRefs(sourceURI));
|
||||
if (NS_SUCCEEDED(result))
|
||||
loadInfo->SetReferrer(sourceURI);
|
||||
}
|
||||
|
||||
loadInfo.swap(*aLoadInfo);
|
||||
|
||||
|
|
|
@ -461,6 +461,10 @@ public:
|
|||
*/
|
||||
virtual nsresult DispatchSyncHashchange() = 0;
|
||||
|
||||
/**
|
||||
* Instructs this window to synchronously dispatch a popState event.
|
||||
*/
|
||||
virtual nsresult DispatchSyncPopState() = 0;
|
||||
|
||||
/**
|
||||
* Tell this window that there is an observer for orientation changes
|
||||
|
|
|
@ -39,7 +39,9 @@
|
|||
|
||||
#include "domstubs.idl"
|
||||
|
||||
[scriptable, uuid(896d1d20-b4c4-11d2-bd93-00805f8ae3f4)]
|
||||
interface nsIVariant;
|
||||
|
||||
[scriptable, uuid(208f2af7-9f2e-497c-8a53-9e7803280898)]
|
||||
interface nsIDOMHistory : nsISupports
|
||||
{
|
||||
readonly attribute long length;
|
||||
|
@ -52,4 +54,10 @@ interface nsIDOMHistory : nsISupports
|
|||
|
||||
void go([optional] in long aDelta);
|
||||
DOMString item(in unsigned long index);
|
||||
void pushState(in nsIVariant aData,
|
||||
in DOMString aTitle,
|
||||
[optional] in DOMString aURL);
|
||||
void replaceState(in nsIVariant aData,
|
||||
in DOMString aTitle,
|
||||
[optional] in DOMString aURL);
|
||||
};
|
||||
|
|
|
@ -83,6 +83,7 @@ XPIDLSRCS = \
|
|||
nsIDOMOrientationEvent.idl \
|
||||
nsIDOMScrollAreaEvent.idl \
|
||||
nsIDOMTransitionEvent.idl \
|
||||
nsIDOMPopStateEvent.idl \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is the Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsIDOMEvent.idl"
|
||||
|
||||
interface nsIVariant;
|
||||
|
||||
[scriptable, uuid(f3834fd5-0ef5-4ccd-a741-0b6685414342)]
|
||||
interface nsIDOMPopStateEvent : nsIDOMEvent
|
||||
{
|
||||
/**
|
||||
* The state associated with this popstate event
|
||||
*/
|
||||
readonly attribute nsIVariant state;
|
||||
|
||||
void initPopStateEvent(in DOMString typeArg,
|
||||
in boolean canBubbleArg,
|
||||
in boolean cancelableArg,
|
||||
in nsIVariant stateArg);
|
||||
};
|
|
@ -42,10 +42,18 @@ interface nsIInputStream;
|
|||
interface nsIOutputStream;
|
||||
interface nsIScriptGlobalObject;
|
||||
|
||||
%{ C++
|
||||
#include "jspubtd.h"
|
||||
%}
|
||||
|
||||
native JSVal(jsval);
|
||||
[ptr] native JSValPtr(jsval);
|
||||
[ptr] native JSContext(JSContext);
|
||||
|
||||
/**
|
||||
* Encode and decode JSON text.
|
||||
*/
|
||||
[scriptable, uuid(45464c36-efde-4cb5-8e00-07480533ff35)]
|
||||
[scriptable, uuid(6fcf09ee-87d0-42ec-a72a-8d60114e974f)]
|
||||
interface nsIJSON : nsISupports
|
||||
{
|
||||
AString encode(/* in JSObject value */);
|
||||
|
@ -59,4 +67,9 @@ interface nsIJSON : nsISupports
|
|||
|
||||
void /* JSObject */ decodeFromStream(in nsIInputStream stream,
|
||||
in long contentLength);
|
||||
|
||||
[noscript] AString encodeFromJSVal(in JSValPtr value, in JSContext cx);
|
||||
|
||||
// Make sure you GCroot the result of this function before using it.
|
||||
[noscript] JSVal decodeToJSVal(in AString str, in JSContext cx);
|
||||
};
|
||||
|
|
|
@ -12,6 +12,5 @@ version_label=Version:
|
|||
mimetype_label=MIME Type
|
||||
description_label=Description
|
||||
suffixes_label=Suffixes
|
||||
enabled_label=Enabled
|
||||
yes_label=Yes
|
||||
no_label=No
|
||||
|
|
|
@ -235,6 +235,10 @@ PluginModuleChild::InitGraphics()
|
|||
{
|
||||
// FIXME/cjones: is this the place for this?
|
||||
#if defined(MOZ_WIDGET_GTK2)
|
||||
// Work around plugins that don't interact well with GDK
|
||||
// client-side windows.
|
||||
PR_SetEnv("GDK_NATIVE_WINDOWS=1");
|
||||
|
||||
gtk_init(0, 0);
|
||||
|
||||
// GtkPlug is a static class so will leak anyway but this ref makes sure.
|
||||
|
|
|
@ -149,6 +149,8 @@ PluginModuleParent::WriteExtraDataForMinidump(nsIFile* dumpFile)
|
|||
pluginFile.substr(filePos).c_str());
|
||||
//TODO: add plugin name and version: bug 539841
|
||||
// (as PluginName, PluginVersion)
|
||||
WriteExtraDataEntry(stream, "PluginName", "");
|
||||
WriteExtraDataEntry(stream, "PluginVersion", "");
|
||||
stream->Close();
|
||||
}
|
||||
|
||||
|
|
|
@ -51,6 +51,9 @@ CPPSRCS = \
|
|||
nsJSON.cpp \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS = nsJSON.h \
|
||||
$(NULL)
|
||||
|
||||
FORCE_STATIC_LIB = 1
|
||||
|
||||
LOCAL_INCLUDES = \
|
||||
|
|
|
@ -195,6 +195,27 @@ WriteCallback(const jschar *buf, uint32 len, void *data)
|
|||
return JS_TRUE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsJSON::EncodeFromJSVal(jsval *value, JSContext *cx, nsAString &result)
|
||||
{
|
||||
result.Truncate();
|
||||
|
||||
// Begin a new request
|
||||
JSAutoRequest ar(cx);
|
||||
|
||||
nsJSONWriter writer;
|
||||
JSBool ok = JS_Stringify(cx, value, NULL, JSVAL_NULL,
|
||||
WriteCallback, &writer);
|
||||
if (!ok) {
|
||||
return NS_ERROR_XPC_BAD_CONVERT_JS;
|
||||
}
|
||||
|
||||
NS_ENSURE_TRUE(writer.DidWrite(), NS_ERROR_UNEXPECTED);
|
||||
writer.FlushBuffer();
|
||||
result.Assign(writer.mOutputString);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsJSON::EncodeInternal(nsJSONWriter *writer)
|
||||
{
|
||||
|
@ -382,6 +403,30 @@ nsJSON::DecodeFromStream(nsIInputStream *aStream, PRInt32 aContentLength)
|
|||
return DecodeInternal(aStream, aContentLength, PR_TRUE);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsJSON::DecodeToJSVal(const nsAString &str, JSContext *cx, jsval *result)
|
||||
{
|
||||
JSAutoRequest ar(cx);
|
||||
|
||||
JSONParser *parser = JS_BeginJSONParse(cx, result);
|
||||
NS_ENSURE_TRUE(parser, NS_ERROR_UNEXPECTED);
|
||||
|
||||
JSBool ok = JS_ConsumeJSONText(cx, parser,
|
||||
(jschar*)PromiseFlatString(str).get(),
|
||||
(uint32)str.Length());
|
||||
|
||||
// Since we've called JS_BeginJSONParse, we have to call JS_FinishJSONParse,
|
||||
// even if JS_ConsumeJSONText fails. But if either fails, we'll report an
|
||||
// error.
|
||||
ok = ok && JS_FinishJSONParse(cx, parser, JSVAL_NULL);
|
||||
|
||||
if (!ok) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsJSON::DecodeInternal(nsIInputStream *aStream,
|
||||
PRInt32 aContentLength,
|
||||
|
|
|
@ -550,8 +550,8 @@ NS_NewDOMStorage2(nsISupports* aOuter, REFNSIID aIID, void** aResult)
|
|||
nsDOMStorage::nsDOMStorage()
|
||||
: mUseDB(PR_FALSE)
|
||||
, mSessionOnly(PR_TRUE)
|
||||
, mItemsCached(PR_FALSE)
|
||||
, mStorageType(nsPIDOMStorage::Unknown)
|
||||
, mItemsCached(PR_FALSE)
|
||||
, mEventBroadcaster(nsnull)
|
||||
{
|
||||
mSecurityChecker = this;
|
||||
|
@ -562,10 +562,10 @@ nsDOMStorage::nsDOMStorage()
|
|||
|
||||
nsDOMStorage::nsDOMStorage(nsDOMStorage& aThat)
|
||||
: mUseDB(PR_FALSE) // Any clone is not using the database
|
||||
, mSessionOnly(PR_TRUE)
|
||||
, mItemsCached(PR_FALSE)
|
||||
, mDomain(aThat.mDomain)
|
||||
, mSessionOnly(PR_TRUE)
|
||||
, mStorageType(aThat.mStorageType)
|
||||
, mItemsCached(PR_FALSE)
|
||||
#ifdef MOZ_STORAGE
|
||||
, mScopeDBKey(aThat.mScopeDBKey)
|
||||
#endif
|
||||
|
|
|
@ -77,6 +77,9 @@ _TEST_FILES = \
|
|||
postMessage.jar \
|
||||
postMessage.jar^headers^ \
|
||||
test_bug477323.html \
|
||||
test_bug500328.html \
|
||||
file_bug500328_1.html \
|
||||
file_bug500328_2.html \
|
||||
$(NULL)
|
||||
|
||||
_CHROME_FILES = \
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Inner frame for testing bug 500328.
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=500328
|
||||
-->
|
||||
<head>
|
||||
<title>test 1</title>
|
||||
</head>
|
||||
<body onload="load();" onpopstate="popstate(event);">
|
||||
<script type="application/javascript">
|
||||
function load() {
|
||||
if(parent && parent.onChildLoad)
|
||||
parent.onChildLoad();
|
||||
if(opener && opener.onChildLoad)
|
||||
opener.onChildLoad();
|
||||
}
|
||||
|
||||
function popstate(e) {
|
||||
if(parent && parent.onChildLoad)
|
||||
parent.onChildPopState(e);
|
||||
if(opener && opener.onChildLoad)
|
||||
opener.onChildPopState(e);
|
||||
}
|
||||
|
||||
function navigateTo(loc) {
|
||||
location = loc;
|
||||
}
|
||||
</script>
|
||||
|
||||
<a id="link-anchor1", href="#1">Link Anchor1</a>
|
||||
<a id="link-self" href="file_bug500328_1.html">Self</a>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,17 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Inner frame for testing bug 500328.
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=500328
|
||||
-->
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<!--
|
||||
Yes, this page is basically blank. But no, about:blank wouldn't do as a
|
||||
replacement, because we use this page to test that pushstate has correct
|
||||
same-origin checks.
|
||||
-->
|
||||
file_bug500328_2.html
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,740 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=500328
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 500328</title>
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=500328">Mozilla Bug 500328</a>
|
||||
<p id="display"></p>
|
||||
<div id="status"></div>
|
||||
<div id="content">
|
||||
<iframe id="iframe"></iframe>
|
||||
<iframe id="iframe2"></iframe>
|
||||
<a id="link">link</a>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
/** Test for Bug 500328 **/
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var iframe = document.getElementById("iframe");
|
||||
var iframeCw = iframe.contentWindow;
|
||||
|
||||
var iframe2 = document.getElementById("iframe2");
|
||||
var iframe2Cw = iframe2.contentWindow;
|
||||
|
||||
var unvisitedColor;
|
||||
var visitedColor;
|
||||
|
||||
var gCallbackOnIframeLoad = false;
|
||||
var gCallbackOnPopState = false;
|
||||
var gNumPopStates = 0;
|
||||
var gLastPopStateEvent;
|
||||
|
||||
var gGen;
|
||||
|
||||
function statusMsg(msg) {
|
||||
var msgElem = document.createElement("p");
|
||||
msgElem.appendChild(document.createTextNode(msg));
|
||||
|
||||
document.getElementById("status").appendChild(msgElem);
|
||||
}
|
||||
|
||||
function longWait() {
|
||||
setTimeout(function() { gGen.next(); }, 1000);
|
||||
}
|
||||
|
||||
function shortWait() {
|
||||
setTimeout(function() { gGen.next(); }, 0);
|
||||
}
|
||||
|
||||
function onChildPopState(e) {
|
||||
gNumPopStates++;
|
||||
gLastPopStateEvent = e;
|
||||
if (gCallbackOnPopState) {
|
||||
statusMsg("Popstate(" + JSON.stringify(e.state) + "). Calling gGen.next().");
|
||||
gCallbackOnPopState = false;
|
||||
gGen.next();
|
||||
}
|
||||
else {
|
||||
statusMsg("Popstate(" + JSON.stringify(e.state) + "). NOT calling gGen.next().");
|
||||
}
|
||||
}
|
||||
|
||||
function onChildLoad() {
|
||||
if(gCallbackOnIframeLoad) {
|
||||
statusMsg("Got load. About to call gGen.next().");
|
||||
gCallbackOnIframeLoad = false;
|
||||
gGen.next();
|
||||
}
|
||||
else {
|
||||
statusMsg("Got load, but not calling gGen.next() because gCallbackOnIframeLoad was false.");
|
||||
}
|
||||
}
|
||||
|
||||
function enableChildLoadCallback() {
|
||||
gCallbackOnIframeLoad = true;
|
||||
}
|
||||
|
||||
function enableChildPopStateCallback() {
|
||||
gCallbackOnPopState = true;
|
||||
}
|
||||
|
||||
function clearPopStateCounter() {
|
||||
gNumPopStates = 0;
|
||||
}
|
||||
|
||||
function noPopStateExpected(msg) {
|
||||
is(gNumPopStates, 0, msg);
|
||||
|
||||
// Even if there's an error, set gNumPopStates to 0 so other tests don't
|
||||
// fail.
|
||||
gNumPopStates = 0;
|
||||
}
|
||||
|
||||
function popstateExpected(msg) {
|
||||
is(gNumPopStates, 1, msg);
|
||||
gNumPopStates = 0;
|
||||
}
|
||||
|
||||
function getColor(elem) {
|
||||
return document.defaultView.getComputedStyle(elem, "").color;
|
||||
}
|
||||
|
||||
function getSHistory(theWindow)
|
||||
{
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
|
||||
const Ci = Components.interfaces;
|
||||
var sh = theWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.sessionHistory;
|
||||
if (!sh || sh == null)
|
||||
throw("Couldn't get shistory for window!");
|
||||
|
||||
return sh;
|
||||
}
|
||||
|
||||
function getChromeWin(theWindow)
|
||||
{
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
const Ci = Components.interfaces;
|
||||
return theWindow
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShellTreeItem)
|
||||
.rootTreeItem
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindow)
|
||||
.QueryInterface(Ci.nsIDOMChromeWindow);
|
||||
}
|
||||
|
||||
function getSHTitle(sh, offset)
|
||||
{
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
|
||||
if (!offset)
|
||||
offset = 0;
|
||||
|
||||
// False instructs the SHistory not to modify its current index.
|
||||
return sh.getEntryAtIndex(sh.index + offset, false).title;
|
||||
}
|
||||
|
||||
// Tests that win's location ends with str
|
||||
function locationEndsWith(win, str) {
|
||||
var exp = new RegExp(str + "$");
|
||||
ok(win.location.toString().match(exp),
|
||||
"Wrong window location. Expected it to end with " +
|
||||
str + ", but actuall was " + win.location);
|
||||
}
|
||||
|
||||
function expectException(func, msg) {
|
||||
var failed = false;
|
||||
try {
|
||||
func();
|
||||
} catch(ex) {
|
||||
failed = true;
|
||||
}
|
||||
|
||||
ok(failed, msg + " succeeded, but should have failed.");
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
// We can't enable universal XPConnect privleges in this function, because
|
||||
// test 5 needs to be running at normal privleges in order to test the
|
||||
// same-origin policy.
|
||||
|
||||
/**
|
||||
* PRELIMINARY:
|
||||
* 1. Clear the popstate counter
|
||||
* 2. Get the visited and unvisited link colors.
|
||||
*/
|
||||
|
||||
clearPopStateCounter();
|
||||
|
||||
// Set the link's href to somewhere we haven't been so we can get the
|
||||
// unvisited link color.
|
||||
var rand = Date.now() + "-" + Math.random();
|
||||
$("link").href = rand;
|
||||
unvisitedColor = getColor($("link"));
|
||||
statusMsg("Unvisited color is " + unvisitedColor);
|
||||
|
||||
// Set the link's href to our current location so we can get the visited link
|
||||
// color.
|
||||
$("link").href = document.location;
|
||||
visitedColor = getColor($("link"));
|
||||
statusMsg("Visited color is " + visitedColor);
|
||||
isnot(visitedColor, unvisitedColor, "visited/unvisited link colors are the same?");
|
||||
|
||||
// The URL of file_bug500328_1.html on http://localhost:8888
|
||||
var innerLoc;
|
||||
|
||||
// Now we can start the tests
|
||||
|
||||
/**
|
||||
* TEST 1 tests basic pushState functionality
|
||||
*/
|
||||
enableChildLoadCallback();
|
||||
iframeCw.location = "file_bug500328_1.html";
|
||||
yield;
|
||||
innerLoc = iframeCw.location.toString();
|
||||
// Load should be fired before popstate.
|
||||
enableChildPopStateCallback();
|
||||
yield;
|
||||
popstateExpected("Expected initial popstate.");
|
||||
statusMsg("Awake after first popstate.");
|
||||
|
||||
var testObj1 = 42;
|
||||
var testObj2 = 4.2;
|
||||
iframeCw.history.pushState(testObj1, "test 1");
|
||||
is(iframeCw.location.search, "",
|
||||
"First pushstate should leave us where we were.");
|
||||
|
||||
// Make sure that this pushstate doesn't trigger a hashchange.
|
||||
iframeCw.onhashchange = function() {
|
||||
ok(false, "Pushstate shouldn't trigger a hashchange.");
|
||||
};
|
||||
|
||||
iframeCw.history.pushState(testObj2, "test 1#foo", "?test1#foo");
|
||||
is(iframeCw.location.search, "?test1",
|
||||
"Second pushstate should push us to '?test1'.");
|
||||
is(iframeCw.location.hash, "#foo",
|
||||
"Second pushstate should push us to '#foo'");
|
||||
shortWait();
|
||||
yield;
|
||||
|
||||
// Let the hashchange event fire, if it's going to.
|
||||
longWait();
|
||||
yield;
|
||||
iframeCw.onhashchange = null;
|
||||
|
||||
statusMsg("About to go back to page 1.");
|
||||
// We don't have to yield here because this back() and the resulting popstate
|
||||
// are completely synchronous. In fact, if we did yield, JS would throw an
|
||||
// error because we'd be calling gGen.next from within gGen.next.
|
||||
iframeCw.history.back();
|
||||
|
||||
statusMsg("Awake after going back to page 1.");
|
||||
popstateExpected("Going back to page 1 should trigger a popstate.");
|
||||
is(JSON.stringify(gLastPopStateEvent.state), JSON.stringify(testObj1),
|
||||
"Wrong state object popped after going back to page 1.");
|
||||
ok(iframeCw.location.toString().match(/file_bug500328_1.html$/),
|
||||
"Going back to page 1 hould take us to original page.");
|
||||
|
||||
iframeCw.history.back();
|
||||
popstateExpected("Going back to page 0 should trigger a popstate.");
|
||||
is(gLastPopStateEvent.state, null,
|
||||
"Going back to page 0 should pop a null state.");
|
||||
is(iframeCw.location.search, "",
|
||||
"Going back to page 0 should clear the querystring.");
|
||||
|
||||
iframeCw.history.forward();
|
||||
popstateExpected("Going forward to page 1 should trigger a popstate.");
|
||||
is(JSON.stringify(gLastPopStateEvent.state), JSON.stringify(testObj1),
|
||||
"Wrong state object popped after going forward to page 1.");
|
||||
ok(iframeCw.location.toString().match(/file_bug500328_1.html$/),
|
||||
"Going forward to page 1 should leave us at original page.");
|
||||
|
||||
|
||||
statusMsg("About to go forward to page 2.");
|
||||
iframeCw.history.forward();
|
||||
statusMsg("Awake after going forward to page 2.");
|
||||
popstateExpected("Going forward to page 2 should trigger a popstate.");
|
||||
is(JSON.stringify(gLastPopStateEvent.state), JSON.stringify(testObj2),
|
||||
"Wrong state object popped after going forward to page 2.");
|
||||
ok(iframeCw.location.toString().match(/file_bug500328_1.html\?test1#foo$/),
|
||||
"Going forward to page 2 took us to " + iframeCw.location.toString());
|
||||
|
||||
// The iframe's current location is file_bug500328_1.html?test1#foo.
|
||||
// Clicking link1 should take us to file_bug500328_1.html?test1#1.
|
||||
|
||||
enableChildPopStateCallback();
|
||||
sendMouseEvent({type:'click'}, 'link-anchor1', iframeCw);
|
||||
yield;
|
||||
popstateExpected("Clicking on link-anchor1 should trigger a popstate.");
|
||||
is(iframeCw.location.search, "?test1",
|
||||
"search should be ?test1 after clicking link.");
|
||||
is(iframeCw.location.hash, "#1",
|
||||
"hash should be #1 after clicking link.");
|
||||
|
||||
/*
|
||||
* Reload file_bug500328_1.html; we're now going to test that link hrefs
|
||||
* and colors are updated correctly on push/popstates.
|
||||
*/
|
||||
|
||||
iframe.onload = onChildLoad;
|
||||
enableChildLoadCallback();
|
||||
iframeCw.location = "about:blank";
|
||||
yield;
|
||||
iframe.onload = null;
|
||||
iframeCw.location = "file_bug500328_1.html";
|
||||
enableChildPopStateCallback();
|
||||
yield;
|
||||
popstateExpected("No popstate after re-loading file_bug500328_1.html");
|
||||
statusMsg("Done loading file_bug500328_1.html for the second time.");
|
||||
|
||||
var ifLink = iframeCw.document.getElementById("link-anchor1");
|
||||
ifLink.href = rand;
|
||||
|
||||
// Poll the document until the link has the correct color, or this test times
|
||||
// out. Unfortunately I can't come up with a more elegant way to do this.
|
||||
// We could listen to MozAfterPaint, but that doesn't guarantee that we'll
|
||||
// observe the new color.
|
||||
while (getColor(ifLink) != unvisitedColor) {
|
||||
// Dump so something shows up in the mochitest logs if we spin here.
|
||||
dump("ifLink has wrong initial color. Spinning...\n");
|
||||
setTimeout(function() { gGen.next(); }, 10);
|
||||
yield;
|
||||
}
|
||||
|
||||
// Navigate iframe2 to dir/${rand}
|
||||
iframe2.onload = onChildLoad;
|
||||
enableChildLoadCallback();
|
||||
iframe2Cw.location = "mytestdir/" + rand;
|
||||
yield;
|
||||
|
||||
// PushState the iframe into the mytestdir directory. This should cause
|
||||
// ifLink to turn purple, since we just visited mytestdir/${rand} in iframe2.
|
||||
iframeCw.history.pushState(null, "foo", "mytestdir/foo");
|
||||
|
||||
// Check that the link's color is now visitedColor
|
||||
while (getColor(ifLink) != visitedColor) {
|
||||
dump("ifLink has wrong color after pushstate. Spinning...\n");
|
||||
setTimeout(function() { gGen.next(); }, 10);
|
||||
yield;
|
||||
}
|
||||
|
||||
ok(ifLink.href.match("mytestdir\\/" + rand + "$"),
|
||||
"inner frame's link should end with 'mytestdir/${rand}'");
|
||||
|
||||
// Navigate out of the mytestdir directory. This should cause ifLink to turn
|
||||
// blue again.
|
||||
iframeCw.history.pushState(null, "bar", "../file_bug500328_1.html");
|
||||
|
||||
// Check that the link's color is back to the unvisited color.
|
||||
while (getColor(ifLink) != unvisitedColor) {
|
||||
dump("ifLink has wrong color after pushstating out of dir. Spinning...\n");
|
||||
setTimeout(function() { gGen.next(); }, 10);
|
||||
yield;
|
||||
}
|
||||
|
||||
ok(!ifLink.href.match("mytestdir"),
|
||||
"inner frame's link shouldn't contain 'mytestdir'.");
|
||||
|
||||
/*
|
||||
* TEST 2 tests that pushstate's same-origin checks are correct.
|
||||
*/
|
||||
var filename = 'file_bug500328_2.html';
|
||||
// Get the directory we're currently in
|
||||
var dirname = document.location.pathname.replace(/[^\/]*$/, '');
|
||||
statusMsg("Dirname is: " + dirname);
|
||||
var loc = 'http://example.com' + dirname + filename;
|
||||
statusMsg("About to transfer iframe to " + loc);
|
||||
iframeCw.location = loc;
|
||||
// We have to register a listener like this because this file is hosted on a
|
||||
// different domain and can't notify us on load.
|
||||
iframe.onload = onChildLoad;
|
||||
enableChildLoadCallback();
|
||||
yield;
|
||||
|
||||
// This function tries to pushstate and replacestate to the given URL and
|
||||
// fails the test if the calls succeed.
|
||||
var tryBadPushAndReplaceState = function(url) {
|
||||
// XXX ex should be a SECURITY_ERR, not a plain Error.
|
||||
|
||||
var hist = iframeCw.history;
|
||||
var url2 = url + dirname + filename;
|
||||
|
||||
expectException(function() { hist.pushState({}, "foo", url); },
|
||||
'pushState to ' + url);
|
||||
|
||||
expectException(function() { hist.pushState({}, "foo", url2); },
|
||||
'pushState to ' + url2);
|
||||
|
||||
expectException(function() { hist.replaceState({}, "foo", url); },
|
||||
'replaceState to ' + url);
|
||||
|
||||
expectException(function() { hist.replaceState({}, "foo", url2); },
|
||||
'replaceState to ' + url2);
|
||||
}
|
||||
|
||||
// We're currently at http://example.com/[dirname]/[filename]
|
||||
tryBadPushAndReplaceState("https://example.com");
|
||||
tryBadPushAndReplaceState("http://foo.example.com");
|
||||
tryBadPushAndReplaceState("http://example.com:1234");
|
||||
tryBadPushAndReplaceState("http://example.com.a");
|
||||
tryBadPushAndReplaceState("http://example.con");
|
||||
tryBadPushAndReplaceState("http://eexample.com");
|
||||
tryBadPushAndReplaceState("http://me@example.com");
|
||||
|
||||
/**
|
||||
* TEST 3 tests that the session history entries' titles are properly sync'ed
|
||||
* after push/pop states.
|
||||
*
|
||||
* We have to run this test in a popup rather than an iframe because only the
|
||||
* root docshell has a session history object.
|
||||
*/
|
||||
statusMsg("About to open popup.");
|
||||
var popup = window.open("file_bug500328_1.html", "popup0",
|
||||
"height=200,width=200,location=yes," +
|
||||
"menubar=yes,status=yes,toolbar=yes,dependent=yes");
|
||||
|
||||
var shistory = getSHistory(popup);
|
||||
|
||||
enableChildPopStateCallback();
|
||||
yield;
|
||||
popstateExpected("Didn't get popstate after opening window.");
|
||||
|
||||
popup.history.pushState(null, "title 0");
|
||||
ok(!getChromeWin(popup).document
|
||||
.getElementById("Browser:Back").hasAttribute("disabled"),
|
||||
"Back button was not enabled after initial pushstate.");
|
||||
|
||||
popup.document.title = "title 1";
|
||||
|
||||
// Yield to the event loop so listeners will be notified of the title change
|
||||
// and so that the hash change we trigger below generates a new session
|
||||
// history entry.
|
||||
shortWait();
|
||||
yield;
|
||||
|
||||
// Check that the current session history entry's title has been updated to
|
||||
// reflect the new document title.
|
||||
is(getSHTitle(shistory), "title 1", "SHEntry title test 1");
|
||||
|
||||
// Change the page's hash to #1, which will trigger a popstate event.
|
||||
// We don't have to wait, because this happens synchronously.
|
||||
popup.location.hash = "#1";
|
||||
popstateExpected("Didn't get popstate after changing hash.");
|
||||
|
||||
popup.document.title = "title 2";
|
||||
|
||||
// Yield so listeners will be notified of the title change we just performed.
|
||||
shortWait();
|
||||
yield;
|
||||
|
||||
is(getSHTitle(shistory), "title 2", "SHEntry title test 2");
|
||||
|
||||
// Go back. Happens synchronously. We should get a popstate.
|
||||
statusMsg("About to go back.");
|
||||
popup.history.go(-1);
|
||||
popstateExpected("Didn't get a popstate after going back.");
|
||||
|
||||
// Even though we went back, we expect the SHEntry title to remain the same
|
||||
// because the document didn't change.
|
||||
is(getSHTitle(shistory), "title 2", "SHEntry title test 3");
|
||||
|
||||
popup.document.title = "Changed 1";
|
||||
shortWait();
|
||||
yield;
|
||||
|
||||
// This check is really a test of bug 509055.
|
||||
is(getSHTitle(shistory), "Changed 1", "SHEntry title test 4");
|
||||
|
||||
popup.close();
|
||||
|
||||
/**
|
||||
* TEST 4 tests replaceState and that we don't get double popstates on
|
||||
* window.open. It also stress-tests the system and its interaction with
|
||||
* bfcache by making many push/replace state calls.
|
||||
*/
|
||||
popup = window.open("file_bug500328_1.html", "popup1",
|
||||
"height=200,width=200,location=yes," +
|
||||
"menubar=yes,status=yes,toolbar=yes,dependent=yes");
|
||||
|
||||
// The initial about:blank load into the new window shouldn't result in us
|
||||
// seeing a popstate. Once file_bug500328_1.html is loaded, it'll overwrite
|
||||
// popup.onpopstate, and this assertion won't fire for that popstate and
|
||||
// others after.
|
||||
//
|
||||
// If we fired the popstate event asynchronously, we'd expect this assert to
|
||||
// fire.
|
||||
popup.onpopstate = function() {
|
||||
ok(false, "Initial load of popup shouldn't give us a popstate.");
|
||||
};
|
||||
|
||||
shistory = getSHistory(popup);
|
||||
|
||||
enableChildPopStateCallback();
|
||||
yield;
|
||||
statusMsg("Awake after loading content into popup.");
|
||||
|
||||
popup.history.replaceState({n:1, ok:true}, "state 1", "good1.html");
|
||||
locationEndsWith(popup, "good1.html");
|
||||
is(getSHTitle(shistory), "state 1", "SHEntry title 'state 1'");
|
||||
|
||||
// Flush the event loop so our next load creates a new session history entry.
|
||||
shortWait();
|
||||
yield;
|
||||
|
||||
enableChildPopStateCallback();
|
||||
popup.location = "file_bug500328_1.html";
|
||||
yield;
|
||||
|
||||
// Flush the event loop so nsDocShell::OnNewURI runs and our load is recorded
|
||||
// properly. OnNewURI is called after PopState fires, because OnNewURI
|
||||
// results from an async event, while PopState is sync. We'd have to do the
|
||||
// same thing if we were listening to onload here, so this isn't
|
||||
// unreasonable.
|
||||
shortWait();
|
||||
yield;
|
||||
|
||||
// Now go back and make sure everything is as it should be.
|
||||
enableChildPopStateCallback();
|
||||
popup.history.back();
|
||||
yield;
|
||||
|
||||
// Flush the event loop so the document's location is updated.
|
||||
shortWait();
|
||||
yield;
|
||||
|
||||
// We had some popstates above without corresponding popstateExpected()
|
||||
// calls, so we need to clear the counter.
|
||||
clearPopStateCounter();
|
||||
|
||||
locationEndsWith(popup, "good1.html");
|
||||
is(JSON.stringify(gLastPopStateEvent.state), '{"n":1,"ok":true}',
|
||||
"Wrong state popped after going back to initial state.");
|
||||
|
||||
// We're back at state 0, which was replaceState-ed to state1.html. Let's do
|
||||
// some push/pop/replaces to make sure everything works OK when we involve
|
||||
// large numbers of SHEntries.
|
||||
for(var i = 2; i <= 30; i++) {
|
||||
if (i % 3 == 0) {
|
||||
popup.history.pushState({n:i, ok:true}, "state " + i, "good" + i + ".html");
|
||||
}
|
||||
else {
|
||||
popup.history.pushState({n:i}, "state " + i, "state" + i + ".html");
|
||||
for(var j = 0; j < i % 4; j++) {
|
||||
popup.history.replaceState({n:i, nn:j}, "state " + i + ", " + j);
|
||||
}
|
||||
popup.history.replaceState({n:i, ok:true}, "state " + i, "good" + i + ".html");
|
||||
}
|
||||
}
|
||||
|
||||
for(var i = 29; i >= 1; i--) {
|
||||
popup.history.back();
|
||||
popstateExpected("Didn't get a popstate on iteration " + i);
|
||||
locationEndsWith(popup, "good" + i + ".html");
|
||||
is(gLastPopStateEvent.state.n, i, "Bad counter on last popstate event.");
|
||||
ok(gLastPopStateEvent.state.ok,
|
||||
"Last popstate event should have 'ok' set to true.");
|
||||
}
|
||||
|
||||
popup.close();
|
||||
|
||||
/**
|
||||
* TEST 5 tests misc security features and implementation details of
|
||||
* Push/ReplaceState
|
||||
*/
|
||||
|
||||
/*
|
||||
* Test that we can't push/replace an object with a large (over 640k
|
||||
* characters) JSON representation.
|
||||
*/
|
||||
|
||||
// (In case you're curious, this loop generates an object which serializes to
|
||||
// 694581 characters.)
|
||||
var bigObject = new Object();
|
||||
for(var i = 0; i < 51200; i++) {
|
||||
bigObject[i] = i;
|
||||
}
|
||||
// statusMsg("Big object has size " + JSON.stringify(bigObject).length);
|
||||
|
||||
// We shouldn't be able to pushstate this large object, due to space
|
||||
// constraints.
|
||||
expectException(
|
||||
function() { iframeCw.history.pushState(bigObject, "foo"); },
|
||||
"pushState-ing large object");
|
||||
|
||||
expectException(
|
||||
function() { iframeCw.history.replaceState(bigObject, "foo"); },
|
||||
"replaceState-ing large object");
|
||||
|
||||
/*
|
||||
* Make sure we can't push/replace state on an iframe of a different origin.
|
||||
* This will work if this function has requested Universal XPConnect
|
||||
* privileges, so any code which needs those privileges can't be in this
|
||||
* function.
|
||||
*/
|
||||
enableChildLoadCallback();
|
||||
iframeCw.location = "http://example.com";
|
||||
iframe.onload = onChildLoad;
|
||||
yield;
|
||||
iframe.onload = null;
|
||||
|
||||
expectException(
|
||||
function() { iframeCw.history.pushState({}, "foo"); },
|
||||
"pushState-ing in a different origin");
|
||||
|
||||
expectException(
|
||||
function() { iframeCw.history.replaceState({}, "foo"); },
|
||||
"replaceState-ing in a different origin");
|
||||
|
||||
/*
|
||||
* If we do the following:
|
||||
* * Start at page A.
|
||||
* * PushState to page B.
|
||||
* * Refresh. The server responds with a 404
|
||||
* * Go back.
|
||||
* Then at the end, page A should be displayed, not the 404 page.
|
||||
*/
|
||||
enableChildLoadCallback();
|
||||
iframe.onload = onChildLoad;
|
||||
iframeCw.location = "about:blank";
|
||||
yield;
|
||||
iframe.onload = null;
|
||||
|
||||
enableChildPopStateCallback();
|
||||
// navigate to http://localhost:8888/[...]/file_bug500328_1.html
|
||||
iframeCw.location = innerLoc;
|
||||
yield;
|
||||
|
||||
// Let the PopState handler finish. If we call refresh (below) from within
|
||||
// the handler, we get slightly confused and can't tell that we're at a 404
|
||||
// after the refresh.
|
||||
shortWait();
|
||||
yield;
|
||||
|
||||
// PushState to a URL which doesn't exist
|
||||
iframeCw.history.pushState({}, "", rand);
|
||||
|
||||
// Refresh. We'll end up a 404 page.
|
||||
iframe.onload = onChildLoad;
|
||||
enableChildLoadCallback();
|
||||
iframeCw.location.reload(true);
|
||||
yield;
|
||||
|
||||
// Since the last page was a 404, going back should actually show the
|
||||
// contents of the old page, instead of persisting the contents of the 404
|
||||
// page.
|
||||
clearPopStateCounter();
|
||||
enableChildPopStateCallback();
|
||||
iframeCw.history.back();
|
||||
yield;
|
||||
popstateExpected("Didn't get popstate after going back.");
|
||||
|
||||
// Make sure that we're actually showing the contents of
|
||||
// file_bug500328_1.html, as opposed to the 404 page.
|
||||
var identifierElem = iframeCw.document.getElementById("link-anchor1");
|
||||
ok(identifierElem != undefined && identifierElem != null,
|
||||
"iframe didn't contain file_bug500328_1.html's contents.");
|
||||
|
||||
/**
|
||||
* TEST 6 tests that the referrer is set properly after push/replace states.
|
||||
*/
|
||||
|
||||
/*
|
||||
* First, a simple test:
|
||||
* * Load file_bug500328_1.html into iframe
|
||||
* * PushState to newpage1.html#foo
|
||||
* * Instruct the iframe to load file_bug500328_1.html into itself.
|
||||
* The referer should be newpage1.html, without the hash.
|
||||
*
|
||||
* This also tests that we can call pushState from within the onload handler.
|
||||
*/
|
||||
enableChildLoadCallback();
|
||||
iframeCw.location = "file_bug500328_1.html";
|
||||
yield;
|
||||
|
||||
// Run within the onload handler. This should work without issue.
|
||||
iframeCw.history.pushState(null, "", "newpage1.html");
|
||||
|
||||
// iframeCw.navigateTo() causes the iframe to set its location on our
|
||||
// behalf. We can't just set its location ourselves, because then *we*
|
||||
// become the referrer.
|
||||
enableChildPopStateCallback();
|
||||
iframeCw.navigateTo("file_bug500328_1.html");
|
||||
yield;
|
||||
|
||||
ok(iframeCw.document.referrer.toString().match(/newpage1.html$/),
|
||||
"Wrong referrer after replaceState. Expected newpage1.html, but was " +
|
||||
iframeCw.document.referrer);
|
||||
|
||||
/*
|
||||
* We're back at file_bug500328_1.html. Now do the following:
|
||||
* * replaceState to newpage2.html#foo
|
||||
* * Click a link back to file_bug500328_1.html
|
||||
* The referrer should be newpage2.html, without the hash.
|
||||
*/
|
||||
iframeCw.history.replaceState(null, null, "newpage2.html#foo");
|
||||
enableChildPopStateCallback();
|
||||
sendMouseEvent({type:'click'}, 'link-self', iframeCw);
|
||||
yield;
|
||||
|
||||
ok(iframeCw.document.referrer.toString().match(/newpage2.html$/),
|
||||
"Wrong referrer after replaceState. Expected newpage2.html, but was " +
|
||||
iframeCw.document.referrer);
|
||||
|
||||
|
||||
/*
|
||||
* Set up a cycle with the popstate event to make sure it's properly
|
||||
* collected.
|
||||
*/
|
||||
var evt = document.createEvent("popstateevent");
|
||||
evt.initEvent("foo", false, false, evt);
|
||||
|
||||
/* */
|
||||
SimpleTest.finish();
|
||||
statusMsg("********** Finished tests ***********");
|
||||
while(true)
|
||||
{
|
||||
yield;
|
||||
|
||||
// I don't think this will actually make the mochitest fail, but there's
|
||||
// not much we can do about this. Realistically, though, regressions are
|
||||
// not likely to fire extra events -- this trap is here mostly to catch
|
||||
// errors made while wriring tests.
|
||||
ok(false, "Got extra event!");
|
||||
}
|
||||
|
||||
/*
|
||||
statusMsg("XXXXXXXXXXXXXX");
|
||||
while(true) {
|
||||
yield;
|
||||
statusMsg("Woken up.");
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
// Important: Wait to start the tests until the page has loaded. Otherwise,
|
||||
// the test will occasionally fail when it begins running before the iframes
|
||||
// have finished their initial load of about:blank.
|
||||
window.addEventListener('load', function() {
|
||||
gGen = runTest();
|
||||
gGen.next();
|
||||
}, false);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -135,9 +135,6 @@ nsresult nsDateTimeFormatMac::FormatTMTime(nsILocale* locale,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// set the default string, in case for API/conversion errors
|
||||
CopyASCIItoUTF16(nsDependentCString(asctime(tmTime)), stringOut);
|
||||
|
||||
NS_ASSERTION(tmTime->tm_mon >= 0, "tm is not set correctly");
|
||||
NS_ASSERTION(tmTime->tm_mday >= 1, "tm is not set correctly");
|
||||
NS_ASSERTION(tmTime->tm_hour >= 0, "tm is not set correctly");
|
||||
|
|
|
@ -57,7 +57,6 @@
|
|||
|
||||
native COMVARIANT(VARIANT);
|
||||
[ptr] native COMVARIANTPtr(VARIANT);
|
||||
native JSVal(jsval);
|
||||
[ptr] native JSContextPtr(JSContext);
|
||||
|
||||
interface IDispatch;
|
||||
|
|
|
@ -59,11 +59,12 @@
|
|||
|
||||
/***************************************************************************/
|
||||
|
||||
// NB: JSVal is declared in nsIVariant.idl
|
||||
|
||||
[ptr] native JSContextPtr(JSContext);
|
||||
[ptr] native JSClassPtr(JSClass);
|
||||
[ptr] native JSObjectPtr(JSObject);
|
||||
[ptr] native JSValPtr(jsval);
|
||||
native JSVal(jsval);
|
||||
native JSEqualityOp(JSEqualityOp);
|
||||
native JSID(jsid);
|
||||
[ptr] native voidPtrPtr(void*);
|
||||
|
@ -530,6 +531,12 @@ interface nsIXPConnect : nsISupports
|
|||
in nsIIDRef aIID,
|
||||
[iid_is(aIID),retval] out nsQIResult result);
|
||||
|
||||
/**
|
||||
* Wraps the given JSVal in a nsIVariant and returns the new variant.
|
||||
*/
|
||||
nsIVariant
|
||||
jSValToVariant(in JSContextPtr cx, in JSValPtr aJSVal);
|
||||
|
||||
/**
|
||||
* This only succeeds if the JSObject is a nsIXPConnectWrappedNative.
|
||||
* A new wrapper is *never* constructed.
|
||||
|
|
|
@ -1358,14 +1358,6 @@ FullTrustSecMan::CheckPropertyAccess(JSContext * aJSContext,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
/* [noscript] void checkConnect (in JSContextPtr aJSContext, in nsIURI aTargetURI, in string aClassName, in string aProperty); */
|
||||
NS_IMETHODIMP
|
||||
FullTrustSecMan::CheckConnect(JSContext * aJSContext, nsIURI *aTargetURI,
|
||||
const char *aClassName, const char *aProperty)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* [noscript] void checkLoadURIFromScript (in JSContextPtr cx, in nsIURI uri); */
|
||||
NS_IMETHODIMP
|
||||
FullTrustSecMan::CheckLoadURIFromScript(JSContext * cx, nsIURI *uri)
|
||||
|
|
|
@ -1051,7 +1051,7 @@ InitWebGLTypes(JSContext *aJSContext, JSObject *aGlobalJSObj)
|
|||
// Alias WebGLArrayBuffer -> ArrayBuffer
|
||||
if(!JS_GetProperty(aJSContext, aGlobalJSObj, "ArrayBuffer", &v) ||
|
||||
!JS_DefineProperty(aJSContext, aGlobalJSObj, "WebGLArrayBuffer", v,
|
||||
NULL, NULL, JSPROP_PERMANENT | JSPROP_ENUMERATE))
|
||||
NULL, NULL, JSPROP_PERMANENT))
|
||||
return PR_FALSE;
|
||||
|
||||
const int webglTypes[] = {
|
||||
|
@ -1080,7 +1080,7 @@ InitWebGLTypes(JSContext *aJSContext, JSObject *aGlobalJSObj)
|
|||
{
|
||||
if(!JS_GetProperty(aJSContext, aGlobalJSObj, js::TypedArray::slowClasses[webglTypes[i]].name, &v) ||
|
||||
!JS_DefineProperty(aJSContext, aGlobalJSObj, webglNames[i], v,
|
||||
NULL, NULL, JSPROP_PERMANENT | JSPROP_ENUMERATE))
|
||||
NULL, NULL, JSPROP_PERMANENT))
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
@ -1370,6 +1370,25 @@ nsXPConnect::WrapJS(JSContext * aJSContext,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXPConnect::JSValToVariant(JSContext *cx,
|
||||
jsval *aJSVal,
|
||||
nsIVariant ** aResult)
|
||||
{
|
||||
NS_PRECONDITION(aJSVal, "bad param");
|
||||
NS_PRECONDITION(aResult, "bad param");
|
||||
*aResult = nsnull;
|
||||
|
||||
XPCCallContext ccx(NATIVE_CALLER, cx);
|
||||
if(!ccx.IsValid())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
*aResult = XPCVariant::newVariant(ccx, *aJSVal);
|
||||
NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void wrapJSAggregatedToNative (in nsISupports aOuter, in JSContextPtr aJSContext, in JSObjectPtr aJSObj, in nsIIDRef aIID, [iid_is (aIID), retval] out nsQIResult result); */
|
||||
NS_IMETHODIMP
|
||||
nsXPConnect::WrapJSAggregatedToNative(nsISupports *aOuter,
|
||||
|
|
|
@ -4198,6 +4198,10 @@ public:
|
|||
|
||||
static XPCVariant* newVariant(XPCCallContext& ccx, jsval aJSVal);
|
||||
|
||||
/**
|
||||
* nsIVariant exposes a GetAsJSVal() method, which also returns mJSVal.
|
||||
* But if you can, you should call this one, since it can be inlined.
|
||||
*/
|
||||
jsval GetJSVal() const {return mJSVal;}
|
||||
|
||||
XPCVariant(XPCCallContext& ccx, jsval aJSVal);
|
||||
|
|
|
@ -390,6 +390,14 @@ JSBool XPCVariant::InitializeData(XPCCallContext& ccx)
|
|||
NS_SUCCEEDED(nsVariant::SetFromInterface(&mData, iid, wrapper));
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
XPCVariant::GetAsJSVal(jsval* result)
|
||||
{
|
||||
NS_PRECONDITION(result, "null result arg.");
|
||||
*result = GetJSVal();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// static
|
||||
JSBool
|
||||
XPCVariant::VariantDataToJS(XPCLazyCallContext& lccx,
|
||||
|
@ -402,30 +410,29 @@ XPCVariant::VariantDataToJS(XPCLazyCallContext& lccx,
|
|||
if (NS_FAILED(variant->GetDataType(&type)))
|
||||
return JS_FALSE;
|
||||
|
||||
nsCOMPtr<XPCVariant> xpcvariant = do_QueryInterface(variant);
|
||||
if(xpcvariant)
|
||||
{
|
||||
jsval realVal = xpcvariant->GetJSVal();
|
||||
if(JSVAL_IS_PRIMITIVE(realVal) ||
|
||||
jsval realVal;
|
||||
nsresult rv = variant->GetAsJSVal(&realVal);
|
||||
|
||||
if(NS_SUCCEEDED(rv) &&
|
||||
(JSVAL_IS_PRIMITIVE(realVal) ||
|
||||
type == nsIDataType::VTYPE_ARRAY ||
|
||||
type == nsIDataType::VTYPE_EMPTY_ARRAY ||
|
||||
type == nsIDataType::VTYPE_ID)
|
||||
type == nsIDataType::VTYPE_ID))
|
||||
{
|
||||
// Not a JSObject (or is a JSArray or is a JSObject representing
|
||||
// an nsID),.
|
||||
// So, just pass through the underlying data.
|
||||
// It's not a JSObject (or it's a JSArray or a JSObject representing an
|
||||
// nsID). Just pass through the underlying data.
|
||||
*pJSVal = realVal;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
if(xpcvariant->mReturnRawObject)
|
||||
nsCOMPtr<XPCVariant> xpcvariant = do_QueryInterface(variant);
|
||||
if(xpcvariant && xpcvariant->mReturnRawObject)
|
||||
{
|
||||
NS_ASSERTION(type == nsIDataType::VTYPE_INTERFACE ||
|
||||
type == nsIDataType::VTYPE_INTERFACE_IS,
|
||||
"Weird variant");
|
||||
*pJSVal = realVal;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
// else, it's an object and we really need to double wrap it if we've
|
||||
// already decided that its 'natural' type is as some sort of interface.
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче