зеркало из https://github.com/mozilla/pjs.git
merge mozilla-central to devtools
This commit is contained in:
Коммит
754165375c
|
@ -1272,6 +1272,27 @@ nsAccessibleWrap::FirePlatformEvent(AccEvent* aEvent)
|
|||
g_signal_emit(atkObj, id, 0);
|
||||
} break;
|
||||
|
||||
case nsIAccessibleEvent::EVENT_WINDOW_MAXIMIZE:
|
||||
{
|
||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_WINDOW_MAXIMIZE\n"));
|
||||
guint id = g_signal_lookup ("maximize", MAI_TYPE_ATK_OBJECT);
|
||||
g_signal_emit(atkObj, id, 0);
|
||||
} break;
|
||||
|
||||
case nsIAccessibleEvent::EVENT_WINDOW_MINIMIZE:
|
||||
{
|
||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_WINDOW_MINIMIZE\n"));
|
||||
guint id = g_signal_lookup ("minimize", MAI_TYPE_ATK_OBJECT);
|
||||
g_signal_emit(atkObj, id, 0);
|
||||
} break;
|
||||
|
||||
case nsIAccessibleEvent::EVENT_WINDOW_RESTORE:
|
||||
{
|
||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_WINDOW_RESTORE\n"));
|
||||
guint id = g_signal_lookup ("restore", MAI_TYPE_ATK_OBJECT);
|
||||
g_signal_emit(atkObj, id, 0);
|
||||
} break;
|
||||
|
||||
case nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE:
|
||||
{
|
||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_DOCUMENT_LOAD_COMPLETE\n"));
|
||||
|
|
|
@ -218,6 +218,24 @@ mai_util_get_type(void)
|
|||
return type;
|
||||
}
|
||||
|
||||
static void
|
||||
window_added (AtkObject *atk_obj,
|
||||
guint index,
|
||||
AtkObject *child)
|
||||
{
|
||||
guint id = g_signal_lookup ("create", MAI_TYPE_ATK_OBJECT);
|
||||
g_signal_emit (child, id, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
window_removed (AtkObject *atk_obj,
|
||||
guint index,
|
||||
AtkObject *child)
|
||||
{
|
||||
guint id = g_signal_lookup ("destroy", MAI_TYPE_ATK_OBJECT);
|
||||
g_signal_emit (child, id, 0);
|
||||
}
|
||||
|
||||
/* intialize the the atk interface (function pointers) with MAI implementation.
|
||||
* When atk bridge get loaded, these interface can be used.
|
||||
*/
|
||||
|
@ -248,6 +266,10 @@ mai_util_class_init(MaiUtilClass *klass)
|
|||
|
||||
listener_list = g_hash_table_new_full(g_int_hash, g_int_equal, NULL,
|
||||
_listener_info_destroy);
|
||||
// Keep track of added/removed windows.
|
||||
AtkObject *root = atk_get_root ();
|
||||
g_signal_connect (root, "children-changed::add", (GCallback) window_added, NULL);
|
||||
g_signal_connect (root, "children-changed::remove", (GCallback) window_removed, NULL);
|
||||
}
|
||||
|
||||
static guint
|
||||
|
|
|
@ -304,10 +304,10 @@ NotificationController::WillRefresh(mozilla::TimeStamp aTime)
|
|||
if (accEvent->mEventRule != AccEvent::eDoNotEmit) {
|
||||
mDocument->ProcessPendingEvent(accEvent);
|
||||
|
||||
AccMutationEvent* showOrhideEvent = downcast_accEvent(accEvent);
|
||||
if (showOrhideEvent) {
|
||||
if (showOrhideEvent->mTextChangeEvent)
|
||||
mDocument->ProcessPendingEvent(showOrhideEvent->mTextChangeEvent);
|
||||
AccMutationEvent* showOrHideEvent = downcast_accEvent(accEvent);
|
||||
if (showOrHideEvent) {
|
||||
if (showOrHideEvent->mTextChangeEvent)
|
||||
mDocument->ProcessPendingEvent(showOrHideEvent->mTextChangeEvent);
|
||||
}
|
||||
}
|
||||
if (!mDocument)
|
||||
|
|
|
@ -70,7 +70,10 @@ TextUpdater::DoUpdate(const nsAString& aNewText, const nsAString& aOldText,
|
|||
PRUint32 aSkipStart)
|
||||
{
|
||||
nsAccessible* parent = mTextLeaf->GetParent();
|
||||
NS_ASSERTION(parent, "No parent for text leaf!");
|
||||
if (!parent) {
|
||||
NS_ERROR("No parent for text leaf!");
|
||||
return;
|
||||
}
|
||||
|
||||
mHyperText = parent->AsHyperText();
|
||||
if (!mHyperText) {
|
||||
|
|
|
@ -537,6 +537,22 @@ nsAccessibilityService::UpdateText(nsIPresShell* aPresShell,
|
|||
document->UpdateText(aContent);
|
||||
}
|
||||
|
||||
void
|
||||
nsAccessibilityService::UpdateListBullet(nsIPresShell* aPresShell,
|
||||
nsIContent* aHTMLListItemContent,
|
||||
bool aHasBullet)
|
||||
{
|
||||
nsDocAccessible* document = GetDocAccessible(aPresShell->GetDocument());
|
||||
if (document) {
|
||||
nsAccessible* accessible = document->GetAccessible(aHTMLListItemContent);
|
||||
if (accessible) {
|
||||
nsHTMLLIAccessible* listItem = accessible->AsHTMLListItem();
|
||||
if (listItem)
|
||||
listItem->UpdateBullet(aHasBullet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsAccessibilityService::PresShellDestroyed(nsIPresShell *aPresShell)
|
||||
{
|
||||
|
|
|
@ -120,6 +120,13 @@ public:
|
|||
|
||||
virtual void UpdateText(nsIPresShell* aPresShell, nsIContent* aContent);
|
||||
|
||||
/**
|
||||
* Update list bullet accessible.
|
||||
*/
|
||||
virtual void UpdateListBullet(nsIPresShell* aPresShell,
|
||||
nsIContent* aHTMLListItemContent,
|
||||
bool aHasBullet);
|
||||
|
||||
virtual void NotifyOfAnchorJumpTo(nsIContent *aTarget);
|
||||
|
||||
virtual void PresShellDestroyed(nsIPresShell* aPresShell);
|
||||
|
|
|
@ -3228,15 +3228,37 @@ nsAccessible::GetSiblingAtOffset(PRInt32 aOffset, nsresult* aError)
|
|||
nsAccessible *
|
||||
nsAccessible::GetFirstAvailableAccessible(nsINode *aStartNode) const
|
||||
{
|
||||
nsAccessible *accessible =
|
||||
nsAccessible* accessible =
|
||||
GetAccService()->GetAccessibleInWeakShell(aStartNode, mWeakShell);
|
||||
if (accessible)
|
||||
return accessible;
|
||||
|
||||
nsIContent *content = nsCoreUtils::GetRoleContent(aStartNode);
|
||||
nsAccTreeWalker walker(mWeakShell, content, PR_FALSE);
|
||||
nsRefPtr<nsAccessible> childAccessible = walker.GetNextChild();
|
||||
return childAccessible;
|
||||
nsCOMPtr<nsIDOMDocumentTraversal> trav =
|
||||
do_QueryInterface(aStartNode->GetOwnerDoc());
|
||||
NS_ENSURE_TRUE(trav, nsnull);
|
||||
|
||||
nsCOMPtr<nsIDOMNode> currentNode = do_QueryInterface(aStartNode);
|
||||
nsCOMPtr<nsIDOMNode> rootNode(do_QueryInterface(GetNode()));
|
||||
nsCOMPtr<nsIDOMTreeWalker> walker;
|
||||
trav->CreateTreeWalker(rootNode,
|
||||
nsIDOMNodeFilter::SHOW_ELEMENT | nsIDOMNodeFilter::SHOW_TEXT,
|
||||
nsnull, PR_FALSE, getter_AddRefs(walker));
|
||||
NS_ENSURE_TRUE(walker, nsnull);
|
||||
|
||||
walker->SetCurrentNode(currentNode);
|
||||
while (true) {
|
||||
walker->NextNode(getter_AddRefs(currentNode));
|
||||
if (!currentNode)
|
||||
return nsnull;
|
||||
|
||||
nsCOMPtr<nsINode> node(do_QueryInterface(currentNode));
|
||||
nsAccessible* accessible =
|
||||
GetAccService()->GetAccessibleInWeakShell(node, mWeakShell);
|
||||
if (accessible)
|
||||
return accessible;
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
PRBool nsAccessible::CheckVisibilityInParentChain(nsIDocument* aDocument, nsIView* aView)
|
||||
|
|
|
@ -58,6 +58,7 @@ class AccGroupInfo;
|
|||
class EmbeddedObjCollector;
|
||||
class nsAccessible;
|
||||
class nsHyperTextAccessible;
|
||||
class nsHTMLLIAccessible;
|
||||
struct nsRoleMapEntry;
|
||||
class nsTextAccessible;
|
||||
|
||||
|
@ -364,6 +365,9 @@ public:
|
|||
inline bool IsHyperText() const { return mFlags & eHyperTextAccessible; }
|
||||
nsHyperTextAccessible* AsHyperText();
|
||||
|
||||
inline bool IsHTMLListItem() const { return mFlags & eHTMLListItemAccessible; }
|
||||
nsHTMLLIAccessible* AsHTMLListItem();
|
||||
|
||||
inline bool IsRoot() const { return mFlags & eRootAccessible; }
|
||||
nsRootAccessible* AsRoot();
|
||||
|
||||
|
@ -512,8 +516,9 @@ protected:
|
|||
enum AccessibleTypes {
|
||||
eApplicationAccessible = 1 << 2,
|
||||
eHyperTextAccessible = 1 << 3,
|
||||
eRootAccessible = 1 << 4,
|
||||
eTextLeafAccessible = 1 << 5
|
||||
eHTMLListItemAccessible = 1 << 4,
|
||||
eRootAccessible = 1 << 5,
|
||||
eTextLeafAccessible = 1 << 6
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -650,6 +650,11 @@ nsDocAccessible::Shutdown()
|
|||
|
||||
RemoveEventListeners();
|
||||
|
||||
// Mark the document as shutdown before AT is notified about the document
|
||||
// removal from its container (valid for root documents on ATK).
|
||||
nsCOMPtr<nsIDocument> kungFuDeathGripDoc = mDocument;
|
||||
mDocument = nsnull;
|
||||
|
||||
if (mParent) {
|
||||
nsDocAccessible* parentDocument = mParent->GetDocAccessible();
|
||||
if (parentDocument)
|
||||
|
@ -672,9 +677,6 @@ nsDocAccessible::Shutdown()
|
|||
mNodeToAccessibleMap.Clear();
|
||||
ClearCache(mAccessibleCache);
|
||||
|
||||
nsCOMPtr<nsIDocument> kungFuDeathGripDoc = mDocument;
|
||||
mDocument = nsnull;
|
||||
|
||||
nsHyperTextAccessibleWrap::Shutdown();
|
||||
|
||||
GetAccService()->NotifyOfDocumentShutdown(kungFuDeathGripDoc);
|
||||
|
@ -1472,7 +1474,10 @@ nsDocAccessible::NotifyOfCachingEnd(nsAccessible* aAccessible)
|
|||
// Make sure we keep children updated. While we're inside of caching
|
||||
// loop then we must exist it with cached children.
|
||||
nsAccessible* container = GetContainerAccessible(content);
|
||||
container->UpdateChildren();
|
||||
NS_ASSERTION(container,
|
||||
"Got a referenced element that is not in document!");
|
||||
if (container)
|
||||
container->UpdateChildren();
|
||||
}
|
||||
}
|
||||
mInvalidationList.Clear();
|
||||
|
@ -1950,8 +1955,9 @@ nsDocAccessible::CacheChildrenInSubtree(nsAccessible* aRoot)
|
|||
PRUint32 count = aRoot->GetChildCount();
|
||||
for (PRUint32 idx = 0; idx < count; idx++) {
|
||||
nsAccessible* child = aRoot->GetChildAt(idx);
|
||||
NS_ASSERTION(child, "Illicit tree change while tree is created!");
|
||||
// Don't cross document boundaries.
|
||||
if (child->IsContent())
|
||||
if (child && child->IsContent())
|
||||
CacheChildrenInSubtree(child);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -254,12 +254,15 @@ nsHTMLOutputAccessible::GetAttributesInternal(nsIPersistentProperties* aAttribut
|
|||
|
||||
nsHTMLLIAccessible::
|
||||
nsHTMLLIAccessible(nsIContent* aContent, nsIWeakReference* aShell) :
|
||||
nsHyperTextAccessibleWrap(aContent, aShell)
|
||||
nsHyperTextAccessibleWrap(aContent, aShell), mBullet(nsnull)
|
||||
{
|
||||
mFlags |= eHTMLListItemAccessible;
|
||||
|
||||
nsBlockFrame* blockFrame = do_QueryFrame(GetFrame());
|
||||
if (blockFrame && !blockFrame->BulletIsEmptyExternal()) {
|
||||
mBulletAccessible = new nsHTMLListBulletAccessible(mContent, mWeakShell);
|
||||
GetDocAccessible()->BindToDocument(mBulletAccessible, nsnull);
|
||||
if (blockFrame && blockFrame->HasBullet()) {
|
||||
mBullet = new nsHTMLListBulletAccessible(mContent, mWeakShell);
|
||||
if (!GetDocAccessible()->BindToDocument(mBullet, nsnull))
|
||||
mBullet = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -268,13 +271,9 @@ NS_IMPL_ISUPPORTS_INHERITED0(nsHTMLLIAccessible, nsHyperTextAccessible)
|
|||
void
|
||||
nsHTMLLIAccessible::Shutdown()
|
||||
{
|
||||
if (mBulletAccessible) {
|
||||
// Ensure that pointer to this is nulled out.
|
||||
mBulletAccessible->Shutdown();
|
||||
}
|
||||
mBullet = nsnull;
|
||||
|
||||
nsHyperTextAccessibleWrap::Shutdown();
|
||||
mBulletAccessible = nsnull;
|
||||
}
|
||||
|
||||
PRUint32
|
||||
|
@ -297,12 +296,11 @@ nsHTMLLIAccessible::GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState)
|
|||
NS_IMETHODIMP nsHTMLLIAccessible::GetBounds(PRInt32 *x, PRInt32 *y, PRInt32 *width, PRInt32 *height)
|
||||
{
|
||||
nsresult rv = nsAccessibleWrap::GetBounds(x, y, width, height);
|
||||
if (NS_FAILED(rv) || !mBulletAccessible) {
|
||||
if (NS_FAILED(rv) || !mBullet)
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRInt32 bulletX, bulletY, bulletWidth, bulletHeight;
|
||||
rv = mBulletAccessible->GetBounds(&bulletX, &bulletY, &bulletWidth, &bulletHeight);
|
||||
rv = mBullet->GetBounds(&bulletX, &bulletY, &bulletWidth, &bulletHeight);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
*x = bulletX; // Move x coordinate of list item over to cover bullet as well
|
||||
|
@ -310,14 +308,41 @@ NS_IMETHODIMP nsHTMLLIAccessible::GetBounds(PRInt32 *x, PRInt32 *y, PRInt32 *wid
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHTMLLIAccessible: public
|
||||
|
||||
void
|
||||
nsHTMLLIAccessible::UpdateBullet(bool aHasBullet)
|
||||
{
|
||||
if (aHasBullet == !!mBullet) {
|
||||
NS_NOTREACHED("Bullet and accessible are in sync already!");
|
||||
return;
|
||||
}
|
||||
|
||||
nsDocAccessible* document = GetDocAccessible();
|
||||
if (aHasBullet) {
|
||||
mBullet = new nsHTMLListBulletAccessible(mContent, mWeakShell);
|
||||
if (document->BindToDocument(mBullet, nsnull)) {
|
||||
InsertChildAt(0, mBullet);
|
||||
}
|
||||
} else {
|
||||
RemoveChild(mBullet);
|
||||
document->UnbindFromDocument(mBullet);
|
||||
mBullet = nsnull;
|
||||
}
|
||||
|
||||
// XXXtodo: fire show/hide and reorder events. That's hard to make it
|
||||
// right now because coalescence happens by DOM node.
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHTMLLIAccessible: nsAccessible protected
|
||||
|
||||
void
|
||||
nsHTMLLIAccessible::CacheChildren()
|
||||
{
|
||||
if (mBulletAccessible)
|
||||
AppendChild(mBulletAccessible);
|
||||
if (mBullet)
|
||||
AppendChild(mBullet);
|
||||
|
||||
// Cache children from subtree.
|
||||
nsAccessibleWrap::CacheChildren();
|
||||
|
@ -331,19 +356,11 @@ nsHTMLListBulletAccessible::
|
|||
nsHTMLListBulletAccessible(nsIContent* aContent, nsIWeakReference* aShell) :
|
||||
nsLeafAccessible(aContent, aShell)
|
||||
{
|
||||
mBulletText += ' '; // Otherwise bullets are jammed up against list text
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHTMLListBulletAccessible: nsAccessNode
|
||||
|
||||
void
|
||||
nsHTMLListBulletAccessible::Shutdown()
|
||||
{
|
||||
mBulletText.Truncate();
|
||||
nsLeafAccessible::Shutdown();
|
||||
}
|
||||
|
||||
bool
|
||||
nsHTMLListBulletAccessible::IsPrimaryForNode() const
|
||||
{
|
||||
|
@ -363,6 +380,7 @@ nsHTMLListBulletAccessible::GetName(nsAString &aName)
|
|||
|
||||
// Native anonymous content, ARIA can't be used. Get list bullet text.
|
||||
nsBlockFrame* blockFrame = do_QueryFrame(mContent->GetPrimaryFrame());
|
||||
NS_ASSERTION(blockFrame, "No frame for list item!");
|
||||
if (blockFrame) {
|
||||
blockFrame->GetBulletText(aName);
|
||||
|
||||
|
@ -394,17 +412,13 @@ void
|
|||
nsHTMLListBulletAccessible::AppendTextTo(nsAString& aText, PRUint32 aStartOffset,
|
||||
PRUint32 aLength)
|
||||
{
|
||||
nsAutoString bulletText;
|
||||
nsBlockFrame* blockFrame = do_QueryFrame(mContent->GetPrimaryFrame());
|
||||
if (blockFrame) {
|
||||
nsAutoString bulletText;
|
||||
NS_ASSERTION(blockFrame, "No frame for list item!");
|
||||
if (blockFrame)
|
||||
blockFrame->GetBulletText(bulletText);
|
||||
|
||||
PRUint32 maxLength = bulletText.Length() - aStartOffset;
|
||||
if (aLength > maxLength)
|
||||
aLength = maxLength;
|
||||
|
||||
aText += Substring(bulletText, aStartOffset, aLength);
|
||||
}
|
||||
aText.Append(Substring(bulletText, aStartOffset, aLength));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -136,7 +136,6 @@ public:
|
|||
NS_IMETHOD GetName(nsAString& aName);
|
||||
|
||||
// nsAccessNode
|
||||
virtual void Shutdown();
|
||||
virtual bool IsPrimaryForNode() const;
|
||||
|
||||
// nsAccessible
|
||||
|
@ -144,15 +143,6 @@ public:
|
|||
virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
|
||||
virtual void AppendTextTo(nsAString& aText, PRUint32 aStartOffset = 0,
|
||||
PRUint32 aLength = PR_UINT32_MAX);
|
||||
|
||||
protected:
|
||||
// XXX: Ideally we'd get the bullet text directly from the bullet frame via
|
||||
// nsBulletFrame::GetListItemText(), but we'd need an interface for getting
|
||||
// text from contentless anonymous frames. Perhaps something like
|
||||
// nsIAnonymousFrame::GetText() ? However, in practice storing the bullet text
|
||||
// here should not be a problem if we invalidate the right parts of
|
||||
// the accessibility cache when mutation events occur.
|
||||
nsString mBulletText;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -182,22 +172,32 @@ public:
|
|||
// nsISupports
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsIAccessible
|
||||
NS_IMETHOD GetBounds(PRInt32 *x, PRInt32 *y, PRInt32 *width, PRInt32 *height);
|
||||
|
||||
// nsAccessNode
|
||||
virtual void Shutdown();
|
||||
|
||||
// nsIAccessible
|
||||
NS_IMETHOD GetBounds(PRInt32 *x, PRInt32 *y, PRInt32 *width, PRInt32 *height);
|
||||
|
||||
// nsAccessible
|
||||
virtual PRUint32 NativeRole();
|
||||
virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
|
||||
|
||||
// nsHTMLLIAccessible
|
||||
void UpdateBullet(bool aHasBullet);
|
||||
|
||||
protected:
|
||||
// nsAccessible
|
||||
virtual void CacheChildren();
|
||||
|
||||
private:
|
||||
nsRefPtr<nsHTMLListBulletAccessible> mBulletAccessible;
|
||||
nsRefPtr<nsHTMLListBulletAccessible> mBullet;
|
||||
};
|
||||
|
||||
#endif
|
||||
inline nsHTMLLIAccessible*
|
||||
nsAccessible::AsHTMLListItem()
|
||||
{
|
||||
return mFlags & eHTMLListItemAccessible ?
|
||||
static_cast<nsHTMLLIAccessible*>(this) : nsnull;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -308,7 +308,7 @@ STDMETHODIMP nsAccessNodeWrap::get_attributesForNames(
|
|||
/* [length_is][size_is][retval] */ BSTR __RPC_FAR *aAttribValues)
|
||||
{
|
||||
__try {
|
||||
if (IsDefunct() || IsDocument())
|
||||
if (IsDefunct() || !IsElement())
|
||||
return E_FAIL;
|
||||
|
||||
nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(mContent));
|
||||
|
@ -616,12 +616,7 @@ void nsAccessNodeWrap::InitAccessibility()
|
|||
|
||||
DoATSpecificProcessing();
|
||||
|
||||
// Register window class that'll be used for document accessibles associated
|
||||
// with tabs.
|
||||
if (nsWinUtils::IsWindowEmulationEnabled()) {
|
||||
nsWinUtils::RegisterNativeWindow(kClassNameTabContent);
|
||||
sHWNDCache.Init(4);
|
||||
}
|
||||
nsWinUtils::MaybeStartWindowEmulation();
|
||||
|
||||
nsAccessNode::InitXPAccessibility();
|
||||
}
|
||||
|
@ -631,10 +626,7 @@ void nsAccessNodeWrap::ShutdownAccessibility()
|
|||
NS_IF_RELEASE(gTextEvent);
|
||||
::DestroyCaret();
|
||||
|
||||
// Unregister window call that's used for document accessibles associated
|
||||
// with tabs.
|
||||
if (nsWinUtils::IsWindowEmulationEnabled())
|
||||
::UnregisterClassW(kClassNameTabContent, GetModuleHandle(NULL));
|
||||
nsWinUtils::ShutdownWindowEmulation();
|
||||
|
||||
nsAccessNode::ShutdownXPAccessibility();
|
||||
}
|
||||
|
|
|
@ -203,7 +203,7 @@ __try {
|
|||
// Return window system accessible object for root document and tab document
|
||||
// accessibles.
|
||||
if (!doc->ParentDocument() ||
|
||||
nsWinUtils::IsWindowEmulationEnabled() &&
|
||||
nsWinUtils::IsWindowEmulationStarted() &&
|
||||
nsWinUtils::IsTabDocument(doc->GetDocumentNode())) {
|
||||
HWND hwnd = static_cast<HWND>(doc->GetNativeWindow());
|
||||
if (hwnd && SUCCEEDED(AccessibleObjectFromWindow(hwnd, OBJID_WINDOW,
|
||||
|
|
|
@ -255,10 +255,11 @@ STDMETHODIMP nsDocAccessibleWrap::get_accValue(
|
|||
void
|
||||
nsDocAccessibleWrap::Shutdown()
|
||||
{
|
||||
if (nsWinUtils::IsWindowEmulationEnabled()) {
|
||||
// Do window emulation specific shutdown if emulation was started.
|
||||
if (nsWinUtils::IsWindowEmulationStarted()) {
|
||||
// Destroy window created for root document.
|
||||
if (nsWinUtils::IsTabDocument(mDocument)) {
|
||||
nsAccessibleWrap::sHWNDCache.Remove(mHWND);
|
||||
sHWNDCache.Remove(mHWND);
|
||||
::DestroyWindow(static_cast<HWND>(mHWND));
|
||||
}
|
||||
|
||||
|
@ -285,14 +286,14 @@ nsDocAccessibleWrap::NotifyOfInitialUpdate()
|
|||
{
|
||||
nsDocAccessible::NotifyOfInitialUpdate();
|
||||
|
||||
if (nsWinUtils::IsWindowEmulationEnabled()) {
|
||||
if (nsWinUtils::IsWindowEmulationStarted()) {
|
||||
// Create window for tab document.
|
||||
if (nsWinUtils::IsTabDocument(mDocument)) {
|
||||
nsRootAccessible* rootDocument = RootAccessible();
|
||||
|
||||
PRBool isActive = PR_TRUE;
|
||||
PRInt32 x = CW_USEDEFAULT, y = CW_USEDEFAULT, width = 0, height = 0;
|
||||
if (nsWinUtils::IsWindowEmulationEnabled(kDolphinModuleHandle)) {
|
||||
if (nsWinUtils::IsWindowEmulationFor(kDolphinModuleHandle)) {
|
||||
GetBounds(&x, &y, &width, &height);
|
||||
PRInt32 rootX = 0, rootY = 0, rootWidth = 0, rootHeight = 0;
|
||||
rootDocument->GetBounds(&rootX, &rootY, &rootWidth, &rootHeight);
|
||||
|
@ -308,7 +309,7 @@ nsDocAccessibleWrap::NotifyOfInitialUpdate()
|
|||
mHWND = nsWinUtils::CreateNativeWindow(kClassNameTabContent, parentWnd,
|
||||
x, y, width, height, isActive);
|
||||
|
||||
nsAccessibleWrap::sHWNDCache.Put(mHWND, this);
|
||||
sHWNDCache.Put(mHWND, this);
|
||||
|
||||
} else {
|
||||
nsDocAccessible* parentDocument = ParentDocument();
|
||||
|
|
|
@ -63,7 +63,7 @@ nsRootAccessibleWrap::~nsRootAccessibleWrap()
|
|||
void
|
||||
nsRootAccessibleWrap::DocumentActivated(nsDocAccessible* aDocument)
|
||||
{
|
||||
if (nsWinUtils::IsWindowEmulationEnabled(kDolphinModuleHandle) &&
|
||||
if (nsWinUtils::IsWindowEmulationFor(kDolphinModuleHandle) &&
|
||||
nsWinUtils::IsTabDocument(aDocument->GetDocumentNode())) {
|
||||
PRUint32 count = mChildDocuments.Length();
|
||||
for (PRUint32 idx = 0; idx < count; idx++) {
|
||||
|
|
|
@ -99,6 +99,34 @@ nsWinUtils::ConvertToIA2Array(nsIArray *aGeckoArray, IUnknown ***aIA2Array,
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
nsWinUtils::MaybeStartWindowEmulation()
|
||||
{
|
||||
// Register window class that'll be used for document accessibles associated
|
||||
// with tabs.
|
||||
if (IsWindowEmulationFor(0)) {
|
||||
RegisterNativeWindow(kClassNameTabContent);
|
||||
nsAccessNodeWrap::sHWNDCache.Init(4);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
nsWinUtils::ShutdownWindowEmulation()
|
||||
{
|
||||
// Unregister window call that's used for document accessibles associated
|
||||
// with tabs.
|
||||
if (IsWindowEmulationFor(0))
|
||||
::UnregisterClassW(kClassNameTabContent, GetModuleHandle(NULL));
|
||||
}
|
||||
|
||||
bool
|
||||
nsWinUtils::IsWindowEmulationStarted()
|
||||
{
|
||||
return nsAccessNodeWrap::sHWNDCache.IsInitialized();
|
||||
}
|
||||
|
||||
void
|
||||
nsWinUtils::RegisterNativeWindow(LPCWSTR aWindowClass)
|
||||
{
|
||||
|
@ -146,7 +174,7 @@ nsWinUtils::HideNativeWindow(HWND aWnd)
|
|||
}
|
||||
|
||||
bool
|
||||
nsWinUtils::IsWindowEmulationEnabled(LPCWSTR kModuleHandle)
|
||||
nsWinUtils::IsWindowEmulationFor(LPCWSTR kModuleHandle)
|
||||
{
|
||||
return kModuleHandle ? ::GetModuleHandleW(kModuleHandle) :
|
||||
::GetModuleHandleW(kJAWSModuleHandle) ||
|
||||
|
|
|
@ -63,6 +63,21 @@ public:
|
|||
static HRESULT ConvertToIA2Array(nsIArray *aCollection,
|
||||
IUnknown ***aAccessibles, long *aCount);
|
||||
|
||||
/**
|
||||
* Start window emulation if presence of specific AT is detected.
|
||||
*/
|
||||
static bool MaybeStartWindowEmulation();
|
||||
|
||||
/**
|
||||
* Free resources used for window emulation.
|
||||
*/
|
||||
static void ShutdownWindowEmulation();
|
||||
|
||||
/**
|
||||
* Return true if window emulation is started.
|
||||
*/
|
||||
static bool IsWindowEmulationStarted();
|
||||
|
||||
/**
|
||||
* Helper to register window class.
|
||||
*/
|
||||
|
@ -88,7 +103,7 @@ public:
|
|||
/**
|
||||
* Return true if window emulation is enabled.
|
||||
*/
|
||||
static bool IsWindowEmulationEnabled(LPCWSTR kModuleHandle = 0);
|
||||
static bool IsWindowEmulationFor(LPCWSTR kModuleHandle);
|
||||
|
||||
/**
|
||||
* Return true if the given document node is for tab document accessible.
|
||||
|
|
|
@ -64,6 +64,10 @@ const STATE_BUSY = nsIAccessibleStates.STATE_BUSY;
|
|||
|
||||
const kEmbedChar = String.fromCharCode(0xfffc);
|
||||
|
||||
const kDiscBulletText = String.fromCharCode(0x2022) + " ";
|
||||
const kCircleBulletText = String.fromCharCode(0x25e6) + " ";
|
||||
const kSquareBulletText = String.fromCharCode(0x25aa) + " ";
|
||||
|
||||
/**
|
||||
* nsIAccessibleRetrieval, initialized when test is loaded.
|
||||
*/
|
||||
|
|
|
@ -54,6 +54,7 @@ _TEST_FILES =\
|
|||
test_general.html \
|
||||
test_general.xul \
|
||||
test_link.html \
|
||||
test_list.html \
|
||||
test_markup.html \
|
||||
test_nsRootAcc.xul \
|
||||
markuprules.xml \
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
<html>
|
||||
|
||||
<head>
|
||||
<title>nsIAccessible::name calculation for HTML li</title>
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
|
||||
<script type="application/javascript"
|
||||
src="../common.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../name.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../events.js"></script>
|
||||
|
||||
<script type="application/javascript">
|
||||
/**
|
||||
* Alter list item numbering and change list style type.
|
||||
*/
|
||||
function bulletUpdate()
|
||||
{
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_REORDER, getNode("list"))
|
||||
];
|
||||
|
||||
this.invoke = function bulletUpdate_invoke()
|
||||
{
|
||||
testName("li_end", "1. list end");
|
||||
|
||||
var li = document.createElement("li");
|
||||
li.setAttribute("id", "li_start");
|
||||
li.textContent = "list start";
|
||||
getNode("list").insertBefore(li, getNode("li_end"));
|
||||
}
|
||||
|
||||
this.finalCheck = function bulletUpdate_finalCheck()
|
||||
{
|
||||
testName("li_start", "1. list start");
|
||||
testName("li_end", "2. list end");
|
||||
|
||||
// change list style type
|
||||
var list = getNode("list");
|
||||
list.setAttribute("style", "list-style-type: disc;");
|
||||
getComputedStyle(list, "").color; // make style processing sync
|
||||
|
||||
testName("li_start", kDiscBulletText + "list start");
|
||||
testName("li_end", kDiscBulletText + "list end");
|
||||
}
|
||||
|
||||
this.getID = function bulletUpdate_getID()
|
||||
{
|
||||
return "Update bullet of list items";
|
||||
}
|
||||
}
|
||||
|
||||
var gQueue = null;
|
||||
function doTest()
|
||||
{
|
||||
gQueue = new eventQueue();
|
||||
gQueue.push(new bulletUpdate());
|
||||
gQueue.invoke(); // SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addA11yLoadEvent(doTest);
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=634200"
|
||||
title="crash [@ nsIFrame::GetStyleVisibility() ]">
|
||||
Mozilla Bug 634200
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<ol id="list">
|
||||
<li id="li_end">list end</li>
|
||||
</ol>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -5,6 +5,12 @@
|
|||
<link rel="stylesheet" type="text/css"
|
||||
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
|
||||
<style>
|
||||
h6.gencontent:before {
|
||||
content: "aga"
|
||||
}
|
||||
</style>
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript"
|
||||
|
@ -40,6 +46,16 @@
|
|||
testText(IDs, 10, 13, "e " + kEmbedChar);
|
||||
testText(IDs, 0, 13, "hello " + kEmbedChar + " see " + kEmbedChar);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// getTextAtOffset line boundary
|
||||
|
||||
testTextAtOffset(0, BOUNDARY_LINE_START, "line ", 0, 5,
|
||||
"hypertext3", kOk, kOk, kOk);
|
||||
|
||||
// XXX: see bug 638684.
|
||||
testTextAtOffset(0, BOUNDARY_LINE_START, "line ", 0, 5,
|
||||
"hypertext4", kTodo, kOk, kTodo);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// list
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
@ -63,7 +79,14 @@
|
|||
|
||||
<a target="_blank"
|
||||
title="Fix getText"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=630001">Mozilla Bug 630001, part3</a>
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=630001">
|
||||
Bug 630001, part3
|
||||
</a>
|
||||
<a target="_blank"
|
||||
title="getTextAtOffset line boundary may return more than one line"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=638326">
|
||||
Bug 638326
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
|
@ -73,5 +96,17 @@
|
|||
<div id="hypertext2">hello <a>friend</a> see <input></div>
|
||||
<ol id="list"><li id="listitem">foo</li></ol>
|
||||
|
||||
<div id="hypertext3">line
|
||||
<!-- haha -->
|
||||
<!-- hahaha -->
|
||||
<h6>heading</h6>
|
||||
</div>
|
||||
|
||||
<div id="hypertext4">line
|
||||
<!-- haha -->
|
||||
<!-- hahaha -->
|
||||
<h6 role="presentation" class="gencontent">heading</h6>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -40,17 +40,13 @@
|
|||
|
||||
function doTest()
|
||||
{
|
||||
const discBulletText = String.fromCharCode(0x2022) + " ";
|
||||
const circleBulletText = String.fromCharCode(0x25e6) + " ";
|
||||
const squareBulletText = String.fromCharCode(0x25aa) + " ";
|
||||
|
||||
// list1
|
||||
var discAccTree = {
|
||||
role: ROLE_LIST,
|
||||
children: [
|
||||
new listItemTree(discBulletText, "Oranges"),
|
||||
new listItemTree(discBulletText, "Apples"),
|
||||
new listItemTree(discBulletText, "Bananas")
|
||||
new listItemTree(kDiscBulletText, "Oranges"),
|
||||
new listItemTree(kDiscBulletText, "Apples"),
|
||||
new listItemTree(kDiscBulletText, "Bananas")
|
||||
]
|
||||
};
|
||||
|
||||
|
@ -60,9 +56,9 @@
|
|||
var circleAccTree = {
|
||||
role: ROLE_LIST,
|
||||
children: [
|
||||
new listItemTree(circleBulletText, "Oranges"),
|
||||
new listItemTree(circleBulletText, "Apples"),
|
||||
new listItemTree(circleBulletText, "Bananas")
|
||||
new listItemTree(kCircleBulletText, "Oranges"),
|
||||
new listItemTree(kCircleBulletText, "Apples"),
|
||||
new listItemTree(kCircleBulletText, "Bananas")
|
||||
]
|
||||
};
|
||||
|
||||
|
@ -72,9 +68,9 @@
|
|||
var squareAccTree = {
|
||||
role: ROLE_LIST,
|
||||
children: [
|
||||
new listItemTree(squareBulletText, "Oranges"),
|
||||
new listItemTree(squareBulletText, "Apples"),
|
||||
new listItemTree(squareBulletText, "Bananas")
|
||||
new listItemTree(kSquareBulletText, "Oranges"),
|
||||
new listItemTree(kSquareBulletText, "Apples"),
|
||||
new listItemTree(kSquareBulletText, "Bananas")
|
||||
]
|
||||
};
|
||||
|
||||
|
@ -92,6 +88,43 @@
|
|||
|
||||
testAccessibleTree("list4", nestedAccTree);
|
||||
|
||||
// dl list
|
||||
var tree =
|
||||
{ LIST: [ // dl
|
||||
{ LISTITEM: [ // dt
|
||||
{ TEXT_LEAF: [] },
|
||||
] },
|
||||
{ PARAGRAPH: [ // dd
|
||||
{ TEXT_LEAF: [] }
|
||||
] },
|
||||
{ LISTITEM: [ // dt
|
||||
{ TEXT_LEAF: [] }
|
||||
] },
|
||||
{ PARAGRAPH: [ // dd
|
||||
{ TEXT_LEAF: [] }
|
||||
] }
|
||||
] };
|
||||
|
||||
testAccessibleTree("list5", tree);
|
||||
|
||||
// dl list inside ordered list
|
||||
tree =
|
||||
{ LIST: [ // ol
|
||||
{ LISTITEM: [ // li
|
||||
{ STATICTEXT: [ ] },
|
||||
{ LIST: [ // dl
|
||||
{ LISTITEM: [ // dt
|
||||
{ TEXT_LEAF: [] }
|
||||
] },
|
||||
{ PARAGRAPH: [ // dd
|
||||
{ TEXT_LEAF: [] }
|
||||
] }
|
||||
] }
|
||||
] }
|
||||
] };
|
||||
|
||||
testAccessibleTree("list6", tree);
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
|
@ -111,6 +144,11 @@
|
|||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=604587">
|
||||
Mozilla Bug 604587
|
||||
</a>
|
||||
<a target="_blank"
|
||||
title="Fix list bullets for DL list (crash [@ nsBulletFrame::GetListItemText])"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=629114">
|
||||
Mozilla Bug 629114
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
|
@ -144,5 +182,18 @@
|
|||
</ul>
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<dl id="list5">
|
||||
<dt>item1</dt><dd>description</dd>
|
||||
<dt>item2</td><dd>description</dd>
|
||||
</dl>
|
||||
|
||||
<ol id="list6">
|
||||
<li>
|
||||
<dl id="dl">
|
||||
<dt>item1</dt><dd>description</dd>
|
||||
</dl>
|
||||
</li>
|
||||
</ol>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -48,8 +48,6 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
pref("general.startup.browser", true);
|
||||
|
||||
pref("browser.chromeURL","chrome://browser/content/");
|
||||
pref("browser.hiddenWindowChromeURL", "chrome://browser/content/hiddenWindow.xul");
|
||||
|
||||
|
@ -536,11 +534,6 @@ pref("mousewheel.withcontrolkey.action",3);
|
|||
pref("mousewheel.withcontrolkey.sysnumlines",false);
|
||||
pref("mousewheel.withcontrolkey.numlines",1);
|
||||
|
||||
pref("profile.allow_automigration", false); // setting to false bypasses automigration in the profile code
|
||||
|
||||
// Customizable toolbar stuff
|
||||
pref("custtoolbar.personal_toolbar_folder", "");
|
||||
|
||||
// pref to control the alert notification
|
||||
pref("alerts.slideIncrement", 1);
|
||||
pref("alerts.slideIncrementTime", 10);
|
||||
|
|
|
@ -5068,23 +5068,19 @@ var TabsInTitlebar = {
|
|||
let titlebar = $("titlebar");
|
||||
|
||||
if (allowed) {
|
||||
let availTop = screen.availTop;
|
||||
function top(ele) ele.boxObject.screenY - availTop;
|
||||
function bottom(ele) top(ele) + rect(ele).height;
|
||||
function rect(ele) ele.getBoundingClientRect();
|
||||
|
||||
let tabsToolbar = $("TabsToolbar");
|
||||
|
||||
let appmenuButtonBox = $("appmenu-button-container");
|
||||
let captionButtonsBox = $("titlebar-buttonbox");
|
||||
|
||||
this._sizePlaceholder("appmenu-button", rect(appmenuButtonBox).width);
|
||||
this._sizePlaceholder("caption-buttons", rect(captionButtonsBox).width);
|
||||
|
||||
let maxMargin = top(gNavToolbox);
|
||||
let tabsBottom = maxMargin + rect(tabsToolbar).height;
|
||||
let titlebarBottom = Math.max(bottom(appmenuButtonBox), bottom(captionButtonsBox));
|
||||
let distance = tabsBottom - titlebarBottom;
|
||||
titlebar.style.marginBottom = - Math.min(distance, maxMargin) + "px";
|
||||
let tabsToolbarRect = rect(tabsToolbar);
|
||||
let titlebarTop = rect($("titlebar-content")).top;
|
||||
titlebar.style.marginBottom = - Math.min(tabsToolbarRect.top - titlebarTop,
|
||||
tabsToolbarRect.height) + "px";
|
||||
|
||||
docElement.setAttribute("tabsintitlebar", "true");
|
||||
|
||||
|
|
|
@ -84,6 +84,7 @@ function GroupItem(listOfEls, options) {
|
|||
this.fadeAwayUndoButtonDuration = 300;
|
||||
|
||||
this.keepProportional = false;
|
||||
this._frozenItemSizeData = {};
|
||||
|
||||
// Double click tracker
|
||||
this._lastClick = 0;
|
||||
|
@ -194,6 +195,7 @@ function GroupItem(listOfEls, options) {
|
|||
gTabView.firstUseExperienced = true;
|
||||
})
|
||||
.focus(function() {
|
||||
self._unfreezeItemSize();
|
||||
if (!self._titleFocused) {
|
||||
(self.$title)[0].select();
|
||||
self._titleFocused = true;
|
||||
|
@ -644,6 +646,9 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
|||
this.removeAll({dontClose: true});
|
||||
GroupItems.unregister(this);
|
||||
|
||||
// remove unfreeze event handlers, if item size is frozen
|
||||
this._unfreezeItemSize({dontArrange: true});
|
||||
|
||||
let self = this;
|
||||
let destroyGroup = function () {
|
||||
iQ(self.container).remove();
|
||||
|
@ -677,6 +682,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
|||
// Closes the groupItem and all of its children.
|
||||
closeAll: function GroupItem_closeAll() {
|
||||
if (this._children.length > 0) {
|
||||
this._unfreezeItemSize();
|
||||
this._children.forEach(function(child) {
|
||||
iQ(child.container).hide();
|
||||
});
|
||||
|
@ -878,8 +884,10 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
|||
this.$undoContainer = iQ("<div/>")
|
||||
.addClass("undo")
|
||||
.attr("type", "button")
|
||||
.text(tabviewString("groupItem.undoCloseGroup"))
|
||||
.appendTo("body");
|
||||
iQ("<span/>")
|
||||
.text(tabviewString("groupItem.undoCloseGroup"))
|
||||
.appendTo(this.$undoContainer);
|
||||
let undoClose = iQ("<span/>")
|
||||
.addClass("close")
|
||||
.appendTo(this.$undoContainer);
|
||||
|
@ -1007,8 +1015,13 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
|||
item.groupItemData = {};
|
||||
|
||||
item.addSubscriber(this, "close", function() {
|
||||
let count = self._children.length;
|
||||
let dontArrange = self.expanded || !self.shouldStack(count);
|
||||
let dontClose = !item.closedManually && gBrowser._numPinnedTabs > 0;
|
||||
self.remove(item, { dontClose: dontClose });
|
||||
self.remove(item, {dontArrange: dontArrange, dontClose: dontClose});
|
||||
|
||||
if (dontArrange)
|
||||
self._freezeItemSize(count);
|
||||
|
||||
if (self._children.length > 0 && self._activeTab) {
|
||||
GroupItems.setActiveGroupItem(self);
|
||||
|
@ -1035,6 +1048,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
|||
if (!options.dontArrange)
|
||||
this.arrange({animate: !options.immediately});
|
||||
|
||||
this._unfreezeItemSize({dontArrange: true});
|
||||
this._sendToSubscribers("childAdded",{ groupItemId: this.id, item: item });
|
||||
|
||||
UI.setReorderTabsOnHide(this);
|
||||
|
@ -1105,8 +1119,10 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
|||
let closed = options.dontClose ? false : this.closeIfEmpty();
|
||||
if (closed)
|
||||
this._makeClosestTabActive();
|
||||
else if (!options.dontArrange)
|
||||
else if (!options.dontArrange) {
|
||||
this.arrange({animate: !options.immediately});
|
||||
this._unfreezeItemSize({dontArrange: true});
|
||||
}
|
||||
|
||||
this._sendToSubscribers("childRemoved",{ groupItemId: this.id, item: item });
|
||||
} catch(e) {
|
||||
|
@ -1237,6 +1253,66 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
|||
return shouldStack;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: _freezeItemSize
|
||||
// Freezes current item size (when removing a child).
|
||||
//
|
||||
// Parameters:
|
||||
// itemCount - the number of children before the last one was removed
|
||||
_freezeItemSize: function GroupItem__freezeItemSize(itemCount) {
|
||||
let data = this._frozenItemSizeData;
|
||||
|
||||
if (!data.lastItemCount) {
|
||||
let self = this;
|
||||
data.lastItemCount = itemCount;
|
||||
|
||||
// unfreeze item size when tabview is hidden
|
||||
data.onTabViewHidden = function () self._unfreezeItemSize();
|
||||
window.addEventListener('tabviewhidden', data.onTabViewHidden, false);
|
||||
|
||||
// we don't need to observe mouse movement when expanded because the
|
||||
// tray is closed when we leave it and collapse causes unfreezing
|
||||
if (self.expanded)
|
||||
return;
|
||||
|
||||
// unfreeze item size when cursor is moved out of group bounds
|
||||
data.onMouseMove = function (e) {
|
||||
let cursor = new Point(e.pageX, e.pageY);
|
||||
if (!self.bounds.contains(cursor))
|
||||
self._unfreezeItemSize();
|
||||
}
|
||||
iQ(window).mousemove(data.onMouseMove);
|
||||
}
|
||||
|
||||
this.arrange({animate: true, count: data.lastItemCount});
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: _unfreezeItemSize
|
||||
// Unfreezes and updates item size.
|
||||
//
|
||||
// Parameters:
|
||||
// options - various options (see below)
|
||||
//
|
||||
// Possible options:
|
||||
// dontArrange - do not arrange items when unfreezing
|
||||
_unfreezeItemSize: function GroupItem__unfreezeItemSize(options) {
|
||||
let data = this._frozenItemSizeData;
|
||||
if (!data.lastItemCount)
|
||||
return;
|
||||
|
||||
if (!options || !options.dontArrange)
|
||||
this.arrange({animate: true});
|
||||
|
||||
// unbind event listeners
|
||||
window.removeEventListener('tabviewhidden', data.onTabViewHidden, false);
|
||||
if (data.onMouseMove)
|
||||
iQ(window).unbind('mousemove', data.onMouseMove);
|
||||
|
||||
// reset freeze status
|
||||
this._frozenItemSizeData = {};
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: arrange
|
||||
// Lays out all of the children.
|
||||
|
@ -1561,6 +1637,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
|||
});
|
||||
|
||||
this.arrange({z: z + 2});
|
||||
this._unfreezeItemSize({dontArrange: true});
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -1688,8 +1765,11 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
|||
// Function: setResizable
|
||||
// Sets whether the groupItem is resizable and updates the UI accordingly.
|
||||
setResizable: function GroupItem_setResizable(value, immediately) {
|
||||
var self = this;
|
||||
|
||||
this.resizeOptions.minWidth = GroupItems.minGroupWidth;
|
||||
this.resizeOptions.minHeight = GroupItems.minGroupHeight;
|
||||
this.resizeOptions.start = function () self._unfreezeItemSize();
|
||||
|
||||
if (value) {
|
||||
immediately ? this.$resizer.show() : this.$resizer.fadeIn();
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
* Aza Raskin <aza@mozilla.com>
|
||||
* Michael Yoshitaka Erlewine <mitcho@mitcho.com>
|
||||
* Sean Dunn <seanedunn@yahoo.com>
|
||||
* Tim Taubert <tim.taubert@gmx.de>
|
||||
*
|
||||
* 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
|
||||
|
@ -169,8 +170,10 @@ Item.prototype = {
|
|||
this.dragOptions = {
|
||||
cancelClass: 'close stackExpander',
|
||||
start: function(e, ui) {
|
||||
if (this.isAGroupItem)
|
||||
if (this.isAGroupItem) {
|
||||
GroupItems.setActiveGroupItem(this);
|
||||
this._unfreezeItemSize();
|
||||
}
|
||||
// if we start dragging a tab within a group, start with dropSpace on.
|
||||
else if (this.parent != null)
|
||||
this.parent._dropSpaceActive = true;
|
||||
|
@ -598,6 +601,35 @@ Item.prototype = {
|
|||
var droppables;
|
||||
var dropTarget;
|
||||
|
||||
// determine the best drop target based on the current mouse coordinates
|
||||
let determineBestDropTarget = function (e, box) {
|
||||
// drop events
|
||||
var best = {
|
||||
dropTarget: null,
|
||||
score: 0
|
||||
};
|
||||
|
||||
droppables.forEach(function(droppable) {
|
||||
var intersection = box.intersection(droppable.bounds);
|
||||
if (intersection && intersection.area() > best.score) {
|
||||
var possibleDropTarget = droppable.item;
|
||||
var accept = true;
|
||||
if (possibleDropTarget != dropTarget) {
|
||||
var dropOptions = possibleDropTarget.dropOptions;
|
||||
if (dropOptions && typeof dropOptions.accept == "function")
|
||||
accept = dropOptions.accept.apply(possibleDropTarget, [self]);
|
||||
}
|
||||
|
||||
if (accept) {
|
||||
best.dropTarget = possibleDropTarget;
|
||||
best.score = intersection.area();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return best.dropTarget;
|
||||
}
|
||||
|
||||
// ___ mousemove
|
||||
var handleMouseMove = function(e) {
|
||||
// global drag tracking
|
||||
|
@ -624,31 +656,9 @@ Item.prototype = {
|
|||
if (typeof self.dragOptions.drag == "function")
|
||||
self.dragOptions.drag.apply(self, [e]);
|
||||
|
||||
// drop events
|
||||
var best = {
|
||||
dropTarget: null,
|
||||
score: 0
|
||||
};
|
||||
let bestDropTarget = determineBestDropTarget(e, box);
|
||||
|
||||
droppables.forEach(function(droppable) {
|
||||
var intersection = box.intersection(droppable.bounds);
|
||||
if (intersection && intersection.area() > best.score) {
|
||||
var possibleDropTarget = droppable.item;
|
||||
var accept = true;
|
||||
if (possibleDropTarget != dropTarget) {
|
||||
var dropOptions = possibleDropTarget.dropOptions;
|
||||
if (dropOptions && typeof dropOptions.accept == "function")
|
||||
accept = dropOptions.accept.apply(possibleDropTarget, [self]);
|
||||
}
|
||||
|
||||
if (accept) {
|
||||
best.dropTarget = possibleDropTarget;
|
||||
best.score = intersection.area();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (best.dropTarget != dropTarget) {
|
||||
if (bestDropTarget != dropTarget) {
|
||||
var dropOptions;
|
||||
if (dropTarget) {
|
||||
dropOptions = dropTarget.dropOptions;
|
||||
|
@ -656,7 +666,7 @@ Item.prototype = {
|
|||
dropOptions.out.apply(dropTarget, [e]);
|
||||
}
|
||||
|
||||
dropTarget = best.dropTarget;
|
||||
dropTarget = bestDropTarget;
|
||||
|
||||
if (dropTarget) {
|
||||
dropOptions = dropTarget.dropOptions;
|
||||
|
@ -710,10 +720,10 @@ Item.prototype = {
|
|||
}
|
||||
|
||||
startMouse = new Point(e.pageX, e.pageY);
|
||||
startPos = self.getBounds().position();
|
||||
let bounds = self.getBounds();
|
||||
startPos = bounds.position();
|
||||
startEvent = e;
|
||||
startSent = false;
|
||||
dropTarget = null;
|
||||
|
||||
droppables = [];
|
||||
iQ('.iq-droppable').each(function(elem) {
|
||||
|
@ -726,6 +736,8 @@ Item.prototype = {
|
|||
}
|
||||
});
|
||||
|
||||
dropTarget = determineBestDropTarget(e, bounds);
|
||||
|
||||
iQ(gWindow)
|
||||
.mousemove(handleMouseMove)
|
||||
.mouseup(handleMouseUp);
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
* Aza Raskin <aza@mozilla.com>
|
||||
* Ian Gilman <ian@iangilman.com>
|
||||
* Michael Yoshitaka Erlewine <mitcho@mitcho.com>
|
||||
* Tim Taubert <tim.taubert@gmx.de>
|
||||
*
|
||||
* This file incorporates work from:
|
||||
* jQuery JavaScript Library v1.4.2: http://code.jquery.com/jquery-1.4.2.js
|
||||
|
@ -170,16 +171,22 @@ Rect.prototype = {
|
|||
|
||||
// ----------
|
||||
// Function: contains
|
||||
// Returns a boolean denoting if the given <Rect> is contained within
|
||||
// Returns a boolean denoting if the <Rect> or <Point> is contained inside
|
||||
// this rectangle.
|
||||
//
|
||||
// Paramaters
|
||||
// - A <Rect>
|
||||
contains: function Rect_contains(rect) {
|
||||
return (rect.left >= this.left &&
|
||||
rect.right <= this.right &&
|
||||
rect.top >= this.top &&
|
||||
rect.bottom <= this.bottom);
|
||||
// Parameters
|
||||
// - A <Rect> or a <Point>
|
||||
contains: function Rect_contains(a) {
|
||||
if (Utils.isPoint(a))
|
||||
return (a.x > this.left &&
|
||||
a.x < this.right &&
|
||||
a.y > this.top &&
|
||||
a.y < this.bottom);
|
||||
|
||||
return (a.left >= this.left &&
|
||||
a.right <= this.right &&
|
||||
a.top >= this.top &&
|
||||
a.bottom <= this.bottom);
|
||||
},
|
||||
|
||||
// ----------
|
||||
|
|
|
@ -721,6 +721,7 @@ TabItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
|||
complete();
|
||||
};
|
||||
|
||||
UI.setActiveTab(this);
|
||||
TabItems._update(this.tab, {force: true});
|
||||
|
||||
$tab.addClass("front");
|
||||
|
|
|
@ -112,11 +112,6 @@ body {
|
|||
position: absolute;
|
||||
}
|
||||
|
||||
.undo .close {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
position: absolute;
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ function test() {
|
|||
waitForExplicitFinish();
|
||||
|
||||
is(getTopWin(), window, "got top window");
|
||||
is(getBoolPref("general.startup.browser", false), true, "getBoolPref");
|
||||
is(getBoolPref("browser.search.openintab", false), false, "getBoolPref");
|
||||
is(getBoolPref("this.pref.doesnt.exist", true), true, "getBoolPref fallback");
|
||||
is(getBoolPref("this.pref.doesnt.exist", false), false, "getBoolPref fallback #2");
|
||||
|
||||
|
|
|
@ -85,6 +85,7 @@ _BROWSER_FILES = \
|
|||
browser_tabview_bug608184.js \
|
||||
browser_tabview_bug608158.js \
|
||||
browser_tabview_bug608405.js \
|
||||
browser_tabview_bug610208.js \
|
||||
browser_tabview_bug610242.js \
|
||||
browser_tabview_bug612470.js \
|
||||
browser_tabview_bug613541.js \
|
||||
|
|
|
@ -4,10 +4,12 @@
|
|||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
newWindowWithTabView(onTabViewShown);
|
||||
newWindowWithTabView(part1);
|
||||
}
|
||||
|
||||
function onTabViewShown(win) {
|
||||
function part1(win) {
|
||||
registerCleanupFunction(function() win.close());
|
||||
|
||||
let contentWindow = win.document.getElementById("tab-view").contentWindow;
|
||||
is(contentWindow.GroupItems.groupItems.length, 1, "Has only one group");
|
||||
|
||||
|
@ -52,8 +54,32 @@ function onTabViewShown(win) {
|
|||
checkActive(function() {
|
||||
checkActive(function() {
|
||||
win.close();
|
||||
finish();
|
||||
newWindowWithTabView(part2);
|
||||
});
|
||||
}, 490);
|
||||
}, 10)
|
||||
}
|
||||
|
||||
function part2(win) {
|
||||
registerCleanupFunction(function() win.close());
|
||||
|
||||
let newTab = win.gBrowser.loadOneTab("about:blank", {inBackground: true});
|
||||
hideTabView(function() {
|
||||
let selectedTab = win.gBrowser.selectedTab;
|
||||
isnot(selectedTab, newTab, "They are different tabs");
|
||||
|
||||
// switch the selected tab to new tab
|
||||
win.gBrowser.selectedTab = newTab;
|
||||
|
||||
win.addEventListener("tabviewhidden", function () {
|
||||
win.removeEventListener("tabviewhidden", arguments.callee, false);
|
||||
is(win.gBrowser.selectedTab, newTab, "The seleted tab should be the same as before (new tab)");
|
||||
win.close();
|
||||
finish();
|
||||
}, false);
|
||||
// show tabview
|
||||
EventUtils.synthesizeKey("e", { accelKey: true, shiftKey: true }, win);
|
||||
// hide tabview
|
||||
EventUtils.synthesizeKey("e", { accelKey: true, shiftKey: true }, win);
|
||||
})
|
||||
}
|
||||
|
|
|
@ -15,8 +15,8 @@ function test() {
|
|||
}
|
||||
|
||||
let testVeryQuickDragAndDrop = function () {
|
||||
let sourceGroup = cw.GroupItems.groupItems[0];
|
||||
let targetGroup = createGroupItem();
|
||||
let sourceGroup = createGroupItem();
|
||||
let targetGroup = cw.GroupItems.groupItems[0];
|
||||
|
||||
sourceGroup.pushAway(true);
|
||||
targetGroup.pushAway(true);
|
||||
|
|
|
@ -0,0 +1,231 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function test() {
|
||||
let cw;
|
||||
let win;
|
||||
let groupItem;
|
||||
|
||||
let next = function () {
|
||||
let test = tests.shift();
|
||||
|
||||
if (test) {
|
||||
test();
|
||||
return;
|
||||
}
|
||||
|
||||
win.close();
|
||||
finish();
|
||||
}
|
||||
|
||||
let prepareTest = function (testName) {
|
||||
let originalBounds = groupItem.getChild(0).getBounds();
|
||||
|
||||
let tabItem = groupItem.getChild(1);
|
||||
let bounds = tabItem.getBounds();
|
||||
tabItem.close();
|
||||
|
||||
ok(originalBounds.equals(groupItem.getChild(0).getBounds()), testName + ': tabs did not change their size');
|
||||
ok(bounds.equals(groupItem.getChild(1).getBounds()), testName + ': third tab is now on second tab\'s previous position');
|
||||
|
||||
return originalBounds;
|
||||
}
|
||||
|
||||
let cleanUpTest = function (testName, originalBounds, callback) {
|
||||
// Use setTimeout here because the groupItem.arrange() call uses
|
||||
// animation to re-arrange the tabItems.
|
||||
win.setTimeout(function () {
|
||||
ok(!originalBounds.equals(groupItem.getChild(0).getBounds()), testName + ': tabs changed their size');
|
||||
|
||||
// cleanup
|
||||
cw.GroupItems.setActiveGroupItem(groupItem);
|
||||
win.gBrowser.loadOneTab('about:blank', {inBackground: true});
|
||||
afterAllTabsLoaded(callback, win);
|
||||
}, 500);
|
||||
}
|
||||
|
||||
let tests = [];
|
||||
|
||||
// focus group title's input field to cause item arrange
|
||||
let testFocusTitle = function () {
|
||||
let originalBounds = prepareTest('testFocusTitle');
|
||||
|
||||
let target = groupItem.$titleShield[0];
|
||||
EventUtils.synthesizeMouseAtCenter(target, {}, cw);
|
||||
|
||||
cleanUpTest('testFocusTitle', originalBounds, next);
|
||||
}
|
||||
|
||||
// hide tabview to cause item arrange
|
||||
let testHideTabView = function () {
|
||||
let originalBounds = prepareTest('testHideTabView');
|
||||
|
||||
hideTabView(function () {
|
||||
cleanUpTest('testHideTabView', originalBounds, function () {
|
||||
showTabView(next, win);
|
||||
});
|
||||
}, win);
|
||||
}
|
||||
|
||||
// (undo) close a group to cause item arrange
|
||||
let testCloseGroupUndo = function () {
|
||||
let originalBounds = prepareTest('testCloseGroupUndo');
|
||||
|
||||
hideGroupItem(groupItem, function () {
|
||||
unhideGroupItem(groupItem, function () {
|
||||
cleanUpTest('testCloseGroupUndo', originalBounds, next);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// leave the group's container with the mouse to cause item arrange
|
||||
let testMouseOut = function () {
|
||||
let originalBounds = prepareTest('testMouseOut');
|
||||
let doc = cw.document.documentElement;
|
||||
let bounds = groupItem.getBounds();
|
||||
|
||||
EventUtils.synthesizeMouse(doc, bounds.right - 5, bounds.bottom - 5, {type: 'mousemove'}, cw);
|
||||
ok(originalBounds.equals(groupItem.getChild(0).getBounds()), 'testMouseOut: tabs did not change their size');
|
||||
|
||||
EventUtils.synthesizeMouse(doc, bounds.right + 1, bounds.bottom + 1, {type: 'mousemove'}, cw);
|
||||
cleanUpTest('testMouseOut', originalBounds, next);
|
||||
}
|
||||
|
||||
// sort item (drag it around) in its group to cause item arrange
|
||||
let testSortInGroup = function () {
|
||||
let originalBounds = prepareTest('testSortInGroup');
|
||||
let target = groupItem.getChild(0).container;
|
||||
|
||||
// simulate drag/drop sorting
|
||||
EventUtils.synthesizeMouse(target, 20, 20, {type: 'mousedown'}, cw);
|
||||
EventUtils.synthesizeMouse(target, 40, 20, {type: 'mousemove'}, cw);
|
||||
EventUtils.synthesizeMouse(target, 20, 20, {type: 'mouseup'}, cw);
|
||||
|
||||
cleanUpTest('testSortInGroup', originalBounds, next);
|
||||
}
|
||||
|
||||
// arrange items when the containing group is resized
|
||||
let testResizeGroup = function () {
|
||||
let originalBounds = prepareTest('testResizeGroup');
|
||||
let oldBounds = groupItem.getBounds();
|
||||
let resizer = groupItem.$resizer[0];
|
||||
|
||||
// simulate drag/drop resizing
|
||||
EventUtils.synthesizeMouse(resizer, 5, 5, {type: 'mousedown'}, cw);
|
||||
EventUtils.synthesizeMouse(resizer, 40, 20, {type: 'mousemove'}, cw);
|
||||
EventUtils.synthesizeMouse(resizer, 20, 20, {type: 'mouseup'}, cw);
|
||||
|
||||
// reset group size
|
||||
groupItem.setBounds(oldBounds);
|
||||
groupItem.setUserSize();
|
||||
|
||||
cleanUpTest('testResizeGroup', originalBounds, next);
|
||||
}
|
||||
|
||||
// make sure we don't freeze item size when removing an item from a stack
|
||||
let testRemoveWhileStacked = function () {
|
||||
let oldBounds = groupItem.getBounds();
|
||||
groupItem.setSize(150, 200, true);
|
||||
groupItem.setUserSize();
|
||||
|
||||
let originalBounds = groupItem.getChild(0).getBounds();
|
||||
ok(!groupItem._isStacked, 'testRemoveWhileStacked: group is not stacked');
|
||||
|
||||
// add a new tab to let the group stack
|
||||
win.gBrowser.loadOneTab('about:blank', {inBackground: true});
|
||||
ok(groupItem._isStacked, 'testRemoveWhileStacked: group is now stacked');
|
||||
|
||||
afterAllTabsLoaded(function () {
|
||||
groupItem.getChild(0).close();
|
||||
let bounds = groupItem.getChild(0).getBounds();
|
||||
ok(originalBounds.equals(bounds), 'testRemoveWhileStacked: tabs did not change their size');
|
||||
|
||||
// reset group size
|
||||
groupItem.setBounds(oldBounds);
|
||||
groupItem.setUserSize();
|
||||
|
||||
next();
|
||||
}, win);
|
||||
}
|
||||
|
||||
// 1) make sure item size is frozen when removing an item in expanded mode
|
||||
// 2) make sure item size stays frozen while moving the mouse in the expanded
|
||||
// layer
|
||||
let testExpandedMode = function () {
|
||||
let oldBounds = groupItem.getBounds();
|
||||
groupItem.setSize(100, 100, true);
|
||||
groupItem.setUserSize();
|
||||
|
||||
ok(groupItem._isStacked, 'testExpandedMode: group is stacked');
|
||||
|
||||
groupItem.addSubscriber(groupItem, 'expanded', function () {
|
||||
groupItem.removeSubscriber(groupItem, 'expanded');
|
||||
onExpanded();
|
||||
});
|
||||
|
||||
groupItem.addSubscriber(groupItem, 'collapsed', function () {
|
||||
groupItem.removeSubscriber(groupItem, 'collapsed');
|
||||
onCollapsed();
|
||||
});
|
||||
|
||||
let onExpanded = function () {
|
||||
let originalBounds = groupItem.getChild(0).getBounds();
|
||||
let tabItem = groupItem.getChild(1);
|
||||
let bounds = tabItem.getBounds();
|
||||
|
||||
for (let i=0; i<3; i++)
|
||||
groupItem.getChild(1).close();
|
||||
|
||||
ok(originalBounds.equals(groupItem.getChild(0).getBounds()), 'testExpandedMode: tabs did not change their size');
|
||||
|
||||
// move the mouse over the expanded layer
|
||||
let trayBounds = groupItem.expanded.bounds;
|
||||
let target = groupItem.expanded.$tray[0];
|
||||
EventUtils.synthesizeMouse(target, trayBounds.right - 5, trayBounds.bottom -5, {type: 'mousemove'}, cw);
|
||||
|
||||
ok(originalBounds.equals(groupItem.getChild(0).getBounds()), 'testExpandedMode: tabs did not change their size');
|
||||
groupItem.collapse();
|
||||
}
|
||||
|
||||
let onCollapsed = function () {
|
||||
// reset group size
|
||||
groupItem.setBounds(oldBounds);
|
||||
groupItem.setUserSize();
|
||||
|
||||
next();
|
||||
}
|
||||
|
||||
groupItem.expand();
|
||||
}
|
||||
|
||||
tests.push(testFocusTitle);
|
||||
tests.push(testHideTabView);
|
||||
tests.push(testCloseGroupUndo);
|
||||
tests.push(testMouseOut);
|
||||
tests.push(testSortInGroup);
|
||||
tests.push(testResizeGroup);
|
||||
tests.push(testRemoveWhileStacked);
|
||||
tests.push(testExpandedMode);
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
newWindowWithTabView(function (tvwin) {
|
||||
win = tvwin;
|
||||
|
||||
registerCleanupFunction(function () {
|
||||
if (!win.closed)
|
||||
win.close();
|
||||
});
|
||||
|
||||
cw = win.TabView.getContentWindow();
|
||||
|
||||
groupItem = cw.GroupItems.groupItems[0];
|
||||
groupItem.setSize(400, 200, true);
|
||||
groupItem.setUserSize();
|
||||
|
||||
for (let i=0; i<3; i++)
|
||||
win.gBrowser.loadOneTab('about:blank', {inBackground: true});
|
||||
|
||||
afterAllTabsLoaded(next, win);
|
||||
});
|
||||
}
|
|
@ -81,8 +81,7 @@
|
|||
<stringbundle id="bundlePreferences" src="chrome://browser/locale/preferences/preferences.properties"/>
|
||||
|
||||
<!-- addons, forgery (phishing) UI -->
|
||||
<groupbox id="addonsPhishingGroup"
|
||||
xmlns:aaa="http://www.w3.org/2005/07/aaa">
|
||||
<groupbox id="addonsPhishingGroup">
|
||||
<hbox id="addonInstallBox">
|
||||
<checkbox id="warnAddonInstall" flex="1"
|
||||
label="&warnAddonInstall.label;"
|
||||
|
|
|
@ -299,9 +299,12 @@ html[dir=rtl] .appTabTrayContainer {
|
|||
|
||||
.undo {
|
||||
background-color: rgba(0,0,0,.2);
|
||||
width: 150px;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
padding-top: 3px;
|
||||
padding-bottom: 3px;
|
||||
-moz-padding-start: 5px;
|
||||
-moz-padding-end: 20px;
|
||||
width: 135px;
|
||||
line-height: 25px;
|
||||
box-shadow: 0 1px 0 rgba(255,255,255,.4), 0 1px 0 rgba(0,0,0,.3) inset;
|
||||
text-shadow: 0 1px 0 rgba(255,255,255,.2);
|
||||
color: WindowText;
|
||||
|
@ -316,14 +319,14 @@ html[dir=rtl] .appTabTrayContainer {
|
|||
}
|
||||
|
||||
.undo .close {
|
||||
top: 4px;
|
||||
left: 4px;
|
||||
top: 7px;
|
||||
right: 7px;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
html[dir=rtl] .undo .close {
|
||||
left: auto;
|
||||
right: 4px;
|
||||
right: auto;
|
||||
left: 7px;
|
||||
}
|
||||
|
||||
.undo .close:hover{
|
||||
|
|
|
@ -293,9 +293,12 @@ html[dir=rtl] .appTabTrayContainer {
|
|||
|
||||
.undo {
|
||||
background-color: #A0A0A0;
|
||||
width: 150px;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
padding-top: 3px;
|
||||
padding-bottom: 3px;
|
||||
-moz-padding-start: 5px;
|
||||
-moz-padding-end: 20px;
|
||||
width: 135px;
|
||||
line-height: 25px;
|
||||
box-shadow: 0px 1px 0px rgba(255,255,255,.5), 0px -1px 0px rgba(0,0,0,.24);
|
||||
text-shadow: 0px -1px 0px rgba(255,255,255,.2);
|
||||
color: rgba( 0,0,0, .8);
|
||||
|
@ -310,14 +313,14 @@ html[dir=rtl] .appTabTrayContainer {
|
|||
}
|
||||
|
||||
.undo .close {
|
||||
top: 4px;
|
||||
left: 4px;
|
||||
top: 7px;
|
||||
right: 7px;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
html[dir=rtl] .undo .close {
|
||||
left: auto;
|
||||
right: 4px;
|
||||
right: auto;
|
||||
left: 7px;
|
||||
}
|
||||
|
||||
.undo .close:hover{
|
||||
|
|
|
@ -318,9 +318,12 @@ html[dir=rtl] .appTabTrayContainer {
|
|||
|
||||
.undo {
|
||||
background-color: #A0A0A0;
|
||||
width: 150px;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
padding-top: 3px;
|
||||
padding-bottom: 3px;
|
||||
-moz-padding-start: 5px;
|
||||
-moz-padding-end: 20px;
|
||||
width: 135px;
|
||||
line-height: 25px;
|
||||
box-shadow: 0px 1px 0px rgba(255,255,255,.5), 0px -1px 0px rgba(0,0,0,.24);
|
||||
text-shadow: 0px -1px 0px rgba(255,255,255,.2);
|
||||
color: rgba( 0,0,0, .8);
|
||||
|
@ -335,14 +338,14 @@ html[dir=rtl] .appTabTrayContainer {
|
|||
}
|
||||
|
||||
.undo .close {
|
||||
top: 4px;
|
||||
left: 4px;
|
||||
top: 7px;
|
||||
right: 7px;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
html[dir=rtl] .undo .close {
|
||||
left: auto;
|
||||
right: 4px;
|
||||
right: auto;
|
||||
left: 7px;
|
||||
}
|
||||
|
||||
.undo .close:hover{
|
||||
|
|
|
@ -57,7 +57,7 @@ interface nsIScriptSecurityManager : nsIXPCSecurityManager
|
|||
/**
|
||||
* Check that the script currently running in context "cx" can load "uri".
|
||||
*
|
||||
* Will return error code NS_ERROR_DOM_BAD_URI if the load request
|
||||
* Will return error code NS_ERROR_DOM_BAD_URI if the load request
|
||||
* should be denied.
|
||||
*
|
||||
* @param cx the JSContext of the script causing the load
|
||||
|
@ -105,7 +105,7 @@ interface nsIScriptSecurityManager : nsIXPCSecurityManager
|
|||
/**
|
||||
* Check that content with principal aPrincipal can load "uri".
|
||||
*
|
||||
* Will return error code NS_ERROR_DOM_BAD_URI if the load request
|
||||
* Will return error code NS_ERROR_DOM_BAD_URI if the load request
|
||||
* should be denied.
|
||||
*
|
||||
* @param aPrincipal the principal identifying the actor causing the load
|
||||
|
@ -113,13 +113,13 @@ interface nsIScriptSecurityManager : nsIXPCSecurityManager
|
|||
* @param flags the permission set, see above
|
||||
*/
|
||||
void checkLoadURIWithPrincipal(in nsIPrincipal aPrincipal,
|
||||
in nsIURI uri,
|
||||
in nsIURI uri,
|
||||
in unsigned long flags);
|
||||
|
||||
/**
|
||||
* Check that content from "from" can load "uri".
|
||||
*
|
||||
* Will return error code NS_ERROR_DOM_BAD_URI if the load request
|
||||
* Will return error code NS_ERROR_DOM_BAD_URI if the load request
|
||||
* should be denied.
|
||||
*
|
||||
* @param from the URI causing the load
|
||||
|
@ -128,8 +128,8 @@ interface nsIScriptSecurityManager : nsIXPCSecurityManager
|
|||
*
|
||||
* @deprecated Use checkLoadURIWithPrincipal instead of this function.
|
||||
*/
|
||||
void checkLoadURI(in nsIURI from, in nsIURI uri,
|
||||
in unsigned long flags);
|
||||
[deprecated] void checkLoadURI(in nsIURI from, in nsIURI uri,
|
||||
in unsigned long flags);
|
||||
|
||||
/**
|
||||
* Similar to checkLoadURIWithPrincipal but there are two differences:
|
||||
|
@ -141,17 +141,17 @@ interface nsIScriptSecurityManager : nsIXPCSecurityManager
|
|||
* function will return error code NS_ERROR_DOM_BAD_URI.
|
||||
*/
|
||||
void checkLoadURIStrWithPrincipal(in nsIPrincipal aPrincipal,
|
||||
in AUTF8String uri,
|
||||
in unsigned long flags);
|
||||
|
||||
in AUTF8String uri,
|
||||
in unsigned long flags);
|
||||
|
||||
/**
|
||||
* Same as CheckLoadURI but takes string arguments for ease of use
|
||||
* by scripts
|
||||
*
|
||||
* @deprecated Use checkLoadURIStrWithPrincipal instead of this function.
|
||||
*/
|
||||
void checkLoadURIStr(in AUTF8String from, in AUTF8String uri,
|
||||
in unsigned long flags);
|
||||
[deprecated] void checkLoadURIStr(in AUTF8String from, in AUTF8String uri,
|
||||
in unsigned long flags);
|
||||
|
||||
/**
|
||||
* Check that the function 'funObj' is allowed to run on 'targetObj'
|
||||
|
@ -173,10 +173,10 @@ interface nsIScriptSecurityManager : nsIXPCSecurityManager
|
|||
[noscript] boolean canExecuteScripts(in JSContextPtr cx,
|
||||
in nsIPrincipal principal);
|
||||
|
||||
///////////////// Principals ///////////////////////
|
||||
///////////////// Principals ///////////////////////
|
||||
/**
|
||||
* Return the principal of the innermost frame of the currently
|
||||
* executing script. Will return null if there is no script
|
||||
* Return the principal of the innermost frame of the currently
|
||||
* executing script. Will return null if there is no script
|
||||
* currently executing.
|
||||
*/
|
||||
[noscript] nsIPrincipal getSubjectPrincipal();
|
||||
|
@ -215,12 +215,12 @@ interface nsIScriptSecurityManager : nsIXPCSecurityManager
|
|||
*/
|
||||
[noscript] short requestCapability(in nsIPrincipal principal,
|
||||
in string capability);
|
||||
|
||||
|
||||
/**
|
||||
* Return true if the currently executing script has 'capability' enabled.
|
||||
*/
|
||||
boolean isCapabilityEnabled(in string capability);
|
||||
|
||||
|
||||
/**
|
||||
* Enable 'capability' in the innermost frame of the currently executing
|
||||
* script.
|
||||
|
@ -249,7 +249,7 @@ interface nsIScriptSecurityManager : nsIXPCSecurityManager
|
|||
// XXXbz ideally we'd pass a subjectName here too, and the nsISupports
|
||||
// cert we're enabling for...
|
||||
void setCanEnableCapability(in AUTF8String certificateFingerprint,
|
||||
in string capability,
|
||||
in string capability,
|
||||
in short canEnable);
|
||||
|
||||
///////////////////////
|
||||
|
|
|
@ -385,6 +385,7 @@ GNU_LD = @GNU_LD@
|
|||
GNU_CC = @GNU_CC@
|
||||
GNU_CXX = @GNU_CXX@
|
||||
HAVE_GCC3_ABI = @HAVE_GCC3_ABI@
|
||||
HAVE_OLD_CLANG = @HAVE_OLD_CLANG@
|
||||
INTEL_CC = @INTEL_CC@
|
||||
INTEL_CXX = @INTEL_CXX@
|
||||
|
||||
|
|
29
configure.in
29
configure.in
|
@ -1167,6 +1167,28 @@ fi
|
|||
|
||||
fi # COMPILE_ENVIRONMENT
|
||||
|
||||
dnl clang prior to 2.9 (including Xcode 4) does not support all the
|
||||
dnl constructs required by the libtheora inline asm. This is used to
|
||||
dnl detect and disable it
|
||||
AC_LANG_SAVE
|
||||
AC_LANG_C
|
||||
AC_TRY_COMPILE([
|
||||
#if defined(__clang__)
|
||||
# if __clang_major__<2 || (__clang_major__==2 && __clang_minor__<9)
|
||||
# error "clang older than 2.9 detected"
|
||||
# endif
|
||||
#endif
|
||||
],
|
||||
[],
|
||||
result="yes",
|
||||
result="no")
|
||||
if test "$result" = "no"; then
|
||||
AC_DEFINE(HAVE_OLD_CLANG)
|
||||
HAVE_OLD_CLANG=1
|
||||
fi
|
||||
AC_LANG_RESTORE
|
||||
AC_SUBST(HAVE_OLD_CLANG)
|
||||
|
||||
if test -n "$MAKE"; then
|
||||
if test `echo $MAKE | grep -c make.py` != 1; then
|
||||
NOT_PYMAKE=$MAKE
|
||||
|
@ -5052,13 +5074,18 @@ if test -z "$XULRUNNER_STUB_NAME"; then
|
|||
fi
|
||||
AC_SUBST(XULRUNNER_STUB_NAME)
|
||||
|
||||
AC_MSG_CHECKING([for application to build])
|
||||
if test -z "$MOZ_BUILD_APP"; then
|
||||
AC_MSG_ERROR([--enable-application=APP was not specified and is required.])
|
||||
AC_MSG_RESULT([browser])
|
||||
MOZ_BUILD_APP=browser
|
||||
else
|
||||
# We have a valid application only if it has a build.mk file in its top
|
||||
# directory.
|
||||
if test ! -f "${srcdir}/${MOZ_BUILD_APP}/build.mk" ; then
|
||||
AC_MSG_RESULT([none])
|
||||
AC_MSG_ERROR([--enable-application value not recognized (${MOZ_BUILD_APP}/build.mk does not exist).])
|
||||
else
|
||||
AC_MSG_RESULT([$MOZ_BUILD_APP])
|
||||
fi
|
||||
fi
|
||||
|
||||
|
|
|
@ -109,7 +109,7 @@ interface nsIXMLHttpRequestUpload : nsIXMLHttpRequestEventTarget {
|
|||
* you're aware of all the security implications. And then think twice about
|
||||
* it.
|
||||
*/
|
||||
[scriptable, uuid(6bb91106-85f0-4d93-8cb4-e57b3d0624f2)]
|
||||
[scriptable, uuid(af62a870-820c-4981-96a3-28ab17b779e1)]
|
||||
interface nsIXMLHttpRequest : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -187,42 +187,19 @@ interface nsIXMLHttpRequest : nsISupports
|
|||
*/
|
||||
ACString getResponseHeader(in AUTF8String header);
|
||||
|
||||
/**
|
||||
* Native (non-script) method to initialize a request. Note that
|
||||
* the request is not sent until the <code>send</code> method
|
||||
* is invoked.
|
||||
*
|
||||
* If there is an "active" request (that is, if open() or openRequest() has
|
||||
* been called already), this is equivalent to calling abort().
|
||||
*
|
||||
* @param method The HTTP method, for example "POST" or "GET". Ignored
|
||||
* if the URL is not a HTTP(S) URL.
|
||||
* @param url The URL to which to send the request.
|
||||
* @param async Whether the request is synchronous or asynchronous
|
||||
* i.e. whether send returns only after the response
|
||||
* is received or if it returns immediately after
|
||||
* sending the request. In the latter case, notification
|
||||
* of completion is sent through the event listeners.
|
||||
* This argument must be true if the multipart
|
||||
* attribute has been set to true, or an exception will
|
||||
* be thrown.
|
||||
* @param user A username for authentication if necessary.
|
||||
* @param password A password for authentication if necessary.
|
||||
*/
|
||||
[noscript] void openRequest(in AUTF8String method,
|
||||
in AUTF8String url,
|
||||
in boolean async,
|
||||
in AString user,
|
||||
in AString password);
|
||||
|
||||
%{C++
|
||||
// note this is NOT virtual so this won't muck with the vtable!
|
||||
inline nsresult Open(const nsACString& method, const nsACString& url,
|
||||
PRBool async, const nsAString& user,
|
||||
const nsAString& password) {
|
||||
return Open(method, url, async, user, password, 3);
|
||||
}
|
||||
%}
|
||||
/**
|
||||
* Meant to be a script-only method for initializing a request.
|
||||
* The parameters are similar to the ones detailed in the
|
||||
* description of <code>openRequest</code>, but the last
|
||||
* 3 are optional.
|
||||
*
|
||||
* If there is an "active" request (that is, if open() or openRequest() has
|
||||
* been called already), this is equivalent to calling abort().
|
||||
* If there is an "active" request (that is, if open() has been called
|
||||
* already), this is equivalent to calling abort() and then open().
|
||||
*
|
||||
* @param method The HTTP method - either "POST" or "GET". Ignored
|
||||
* if the URL is not a HTTP URL.
|
||||
|
|
|
@ -448,6 +448,14 @@ nsContentList::nsContentList(nsINode* aRootNode,
|
|||
{
|
||||
NS_ASSERTION(mRootNode, "Must have root");
|
||||
mRootNode->AddMutationObserver(this);
|
||||
|
||||
// We only need to flush if we're in an non-HTML document, since the
|
||||
// HTML5 parser doesn't need flushing. Further, if we're not in a
|
||||
// document at all right now (in the GetCurrentDoc() sense), we're
|
||||
// not parser-created and don't need to be flushing stuff under us
|
||||
// to get our kids right.
|
||||
nsIDocument* doc = mRootNode->GetCurrentDoc();
|
||||
mFlushesNeeded = doc && !doc->IsHTML();
|
||||
}
|
||||
|
||||
nsContentList::~nsContentList()
|
||||
|
|
|
@ -54,52 +54,337 @@
|
|||
#include "nsIChannelEventSink.h"
|
||||
#include "nsIAsyncVerifyRedirectCallback.h"
|
||||
#include "nsCharSeparatedTokenizer.h"
|
||||
#include "nsXMLHttpRequest.h"
|
||||
#include "nsAsyncRedirectVerifyHelper.h"
|
||||
#include "prclist.h"
|
||||
#include "prtime.h"
|
||||
#include "nsClassHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
|
||||
#define PREFLIGHT_CACHE_SIZE 100
|
||||
|
||||
static PRBool gDisableCORS = PR_FALSE;
|
||||
static PRBool gDisableCORSPrivateData = PR_FALSE;
|
||||
|
||||
class nsChannelCanceller
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Preflight cache
|
||||
|
||||
class nsPreflightCache
|
||||
{
|
||||
public:
|
||||
nsChannelCanceller(nsIChannel* aChannel)
|
||||
: mChannel(aChannel)
|
||||
struct TokenTime
|
||||
{
|
||||
nsCString token;
|
||||
PRTime expirationTime;
|
||||
};
|
||||
|
||||
struct CacheEntry : public PRCList
|
||||
{
|
||||
CacheEntry(nsCString& aKey)
|
||||
: mKey(aKey)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsPreflightCache::CacheEntry);
|
||||
}
|
||||
|
||||
~CacheEntry()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsPreflightCache::CacheEntry);
|
||||
}
|
||||
|
||||
void PurgeExpired(PRTime now);
|
||||
PRBool CheckRequest(const nsCString& aMethod,
|
||||
const nsTArray<nsCString>& aCustomHeaders);
|
||||
|
||||
nsCString mKey;
|
||||
nsTArray<TokenTime> mMethods;
|
||||
nsTArray<TokenTime> mHeaders;
|
||||
};
|
||||
|
||||
nsPreflightCache()
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsPreflightCache);
|
||||
PR_INIT_CLIST(&mList);
|
||||
}
|
||||
~nsChannelCanceller()
|
||||
|
||||
~nsPreflightCache()
|
||||
{
|
||||
if (mChannel) {
|
||||
mChannel->Cancel(NS_ERROR_DOM_BAD_URI);
|
||||
Clear();
|
||||
MOZ_COUNT_DTOR(nsPreflightCache);
|
||||
}
|
||||
|
||||
PRBool Initialize()
|
||||
{
|
||||
return mTable.Init();
|
||||
}
|
||||
|
||||
CacheEntry* GetEntry(nsIURI* aURI, nsIPrincipal* aPrincipal,
|
||||
PRBool aWithCredentials, PRBool aCreate);
|
||||
void RemoveEntries(nsIURI* aURI, nsIPrincipal* aPrincipal);
|
||||
|
||||
void Clear();
|
||||
|
||||
private:
|
||||
static PLDHashOperator
|
||||
RemoveExpiredEntries(const nsACString& aKey, nsAutoPtr<CacheEntry>& aValue,
|
||||
void* aUserData);
|
||||
|
||||
static PRBool GetCacheKey(nsIURI* aURI, nsIPrincipal* aPrincipal,
|
||||
PRBool aWithCredentials, nsACString& _retval);
|
||||
|
||||
nsClassHashtable<nsCStringHashKey, CacheEntry> mTable;
|
||||
PRCList mList;
|
||||
};
|
||||
|
||||
// Will be initialized in EnsurePreflightCache.
|
||||
static nsPreflightCache* sPreflightCache = nsnull;
|
||||
|
||||
static PRBool EnsurePreflightCache()
|
||||
{
|
||||
if (sPreflightCache)
|
||||
return PR_TRUE;
|
||||
|
||||
nsAutoPtr<nsPreflightCache> newCache(new nsPreflightCache());
|
||||
|
||||
if (newCache->Initialize()) {
|
||||
sPreflightCache = newCache.forget();
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
nsPreflightCache::CacheEntry::PurgeExpired(PRTime now)
|
||||
{
|
||||
PRUint32 i;
|
||||
for (i = 0; i < mMethods.Length(); ++i) {
|
||||
if (now >= mMethods[i].expirationTime) {
|
||||
mMethods.RemoveElementAt(i--);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < mHeaders.Length(); ++i) {
|
||||
if (now >= mHeaders[i].expirationTime) {
|
||||
mHeaders.RemoveElementAt(i--);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsPreflightCache::CacheEntry::CheckRequest(const nsCString& aMethod,
|
||||
const nsTArray<nsCString>& aHeaders)
|
||||
{
|
||||
PurgeExpired(PR_Now());
|
||||
|
||||
if (!aMethod.EqualsLiteral("GET") && !aMethod.EqualsLiteral("POST")) {
|
||||
PRUint32 i;
|
||||
for (i = 0; i < mMethods.Length(); ++i) {
|
||||
if (aMethod.Equals(mMethods[i].token))
|
||||
break;
|
||||
}
|
||||
if (i == mMethods.Length()) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void DontCancel()
|
||||
{
|
||||
mChannel = nsnull;
|
||||
for (PRUint32 i = 0; i < aHeaders.Length(); ++i) {
|
||||
PRUint32 j;
|
||||
for (j = 0; j < mHeaders.Length(); ++j) {
|
||||
if (aHeaders[i].Equals(mHeaders[j].token,
|
||||
nsCaseInsensitiveCStringComparator())) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j == mHeaders.Length()) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
nsIChannel* mChannel;
|
||||
};
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS5(nsCrossSiteListenerProxy, nsIStreamListener,
|
||||
nsPreflightCache::CacheEntry*
|
||||
nsPreflightCache::GetEntry(nsIURI* aURI,
|
||||
nsIPrincipal* aPrincipal,
|
||||
PRBool aWithCredentials,
|
||||
PRBool aCreate)
|
||||
{
|
||||
nsCString key;
|
||||
if (!GetCacheKey(aURI, aPrincipal, aWithCredentials, key)) {
|
||||
NS_WARNING("Invalid cache key!");
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
CacheEntry* entry;
|
||||
|
||||
if (mTable.Get(key, &entry)) {
|
||||
// Entry already existed so just return it. Also update the LRU list.
|
||||
|
||||
// Move to the head of the list.
|
||||
PR_REMOVE_LINK(entry);
|
||||
PR_INSERT_LINK(entry, &mList);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
if (!aCreate) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
// This is a new entry, allocate and insert into the table now so that any
|
||||
// failures don't cause items to be removed from a full cache.
|
||||
entry = new CacheEntry(key);
|
||||
if (!entry) {
|
||||
NS_WARNING("Failed to allocate new cache entry!");
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
NS_ASSERTION(mTable.Count() <= PREFLIGHT_CACHE_SIZE,
|
||||
"Something is borked, too many entries in the cache!");
|
||||
|
||||
// Now enforce the max count.
|
||||
if (mTable.Count() == PREFLIGHT_CACHE_SIZE) {
|
||||
// Try to kick out all the expired entries.
|
||||
PRTime now = PR_Now();
|
||||
mTable.Enumerate(RemoveExpiredEntries, &now);
|
||||
|
||||
// If that didn't remove anything then kick out the least recently used
|
||||
// entry.
|
||||
if (mTable.Count() == PREFLIGHT_CACHE_SIZE) {
|
||||
CacheEntry* lruEntry = static_cast<CacheEntry*>(PR_LIST_TAIL(&mList));
|
||||
PR_REMOVE_LINK(lruEntry);
|
||||
|
||||
// This will delete 'lruEntry'.
|
||||
mTable.Remove(lruEntry->mKey);
|
||||
|
||||
NS_ASSERTION(mTable.Count() == PREFLIGHT_CACHE_SIZE - 1,
|
||||
"Somehow tried to remove an entry that was never added!");
|
||||
}
|
||||
}
|
||||
|
||||
if (!mTable.Put(key, entry)) {
|
||||
// Failed, clean up the new entry.
|
||||
delete entry;
|
||||
|
||||
NS_WARNING("Failed to add entry to the CORS preflight cache!");
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
PR_INSERT_LINK(entry, &mList);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
void
|
||||
nsPreflightCache::RemoveEntries(nsIURI* aURI, nsIPrincipal* aPrincipal)
|
||||
{
|
||||
CacheEntry* entry;
|
||||
nsCString key;
|
||||
if (GetCacheKey(aURI, aPrincipal, PR_TRUE, key) &&
|
||||
mTable.Get(key, &entry)) {
|
||||
PR_REMOVE_LINK(entry);
|
||||
mTable.Remove(key);
|
||||
}
|
||||
|
||||
if (GetCacheKey(aURI, aPrincipal, PR_FALSE, key) &&
|
||||
mTable.Get(key, &entry)) {
|
||||
PR_REMOVE_LINK(entry);
|
||||
mTable.Remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsPreflightCache::Clear()
|
||||
{
|
||||
PR_INIT_CLIST(&mList);
|
||||
mTable.Clear();
|
||||
}
|
||||
|
||||
/* static */ PLDHashOperator
|
||||
nsPreflightCache::RemoveExpiredEntries(const nsACString& aKey,
|
||||
nsAutoPtr<CacheEntry>& aValue,
|
||||
void* aUserData)
|
||||
{
|
||||
PRTime* now = static_cast<PRTime*>(aUserData);
|
||||
|
||||
aValue->PurgeExpired(*now);
|
||||
|
||||
if (aValue->mHeaders.IsEmpty() &&
|
||||
aValue->mMethods.IsEmpty()) {
|
||||
// Expired, remove from the list as well as the hash table.
|
||||
PR_REMOVE_LINK(aValue);
|
||||
return PL_DHASH_REMOVE;
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
/* static */ PRBool
|
||||
nsPreflightCache::GetCacheKey(nsIURI* aURI,
|
||||
nsIPrincipal* aPrincipal,
|
||||
PRBool aWithCredentials,
|
||||
nsACString& _retval)
|
||||
{
|
||||
NS_ASSERTION(aURI, "Null uri!");
|
||||
NS_ASSERTION(aPrincipal, "Null principal!");
|
||||
|
||||
NS_NAMED_LITERAL_CSTRING(space, " ");
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = aPrincipal->GetURI(getter_AddRefs(uri));
|
||||
NS_ENSURE_SUCCESS(rv, PR_FALSE);
|
||||
|
||||
nsCAutoString scheme, host, port;
|
||||
if (uri) {
|
||||
uri->GetScheme(scheme);
|
||||
uri->GetHost(host);
|
||||
port.AppendInt(NS_GetRealPort(uri));
|
||||
}
|
||||
|
||||
nsCAutoString cred;
|
||||
if (aWithCredentials) {
|
||||
_retval.AssignLiteral("cred");
|
||||
}
|
||||
else {
|
||||
_retval.AssignLiteral("nocred");
|
||||
}
|
||||
|
||||
nsCAutoString spec;
|
||||
rv = aURI->GetSpec(spec);
|
||||
NS_ENSURE_SUCCESS(rv, PR_FALSE);
|
||||
|
||||
_retval.Assign(cred + space + scheme + space + host + space + port + space +
|
||||
spec);
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// nsCORSListenerProxy
|
||||
|
||||
NS_IMPL_ISUPPORTS5(nsCORSListenerProxy, nsIStreamListener,
|
||||
nsIRequestObserver, nsIChannelEventSink,
|
||||
nsIInterfaceRequestor, nsIAsyncVerifyRedirectCallback)
|
||||
|
||||
/* static */
|
||||
void
|
||||
nsCrossSiteListenerProxy::Startup()
|
||||
nsCORSListenerProxy::Startup()
|
||||
{
|
||||
nsContentUtils::AddBoolPrefVarCache("content.cors.disable", &gDisableCORS);
|
||||
nsContentUtils::AddBoolPrefVarCache("content.cors.no_private_data", &gDisableCORSPrivateData);
|
||||
}
|
||||
|
||||
nsCrossSiteListenerProxy::nsCrossSiteListenerProxy(nsIStreamListener* aOuter,
|
||||
nsIPrincipal* aRequestingPrincipal,
|
||||
nsIChannel* aChannel,
|
||||
PRBool aWithCredentials,
|
||||
nsresult* aResult)
|
||||
/* static */
|
||||
void
|
||||
nsCORSListenerProxy::Shutdown()
|
||||
{
|
||||
delete sPreflightCache;
|
||||
sPreflightCache = nsnull;
|
||||
}
|
||||
|
||||
nsCORSListenerProxy::nsCORSListenerProxy(nsIStreamListener* aOuter,
|
||||
nsIPrincipal* aRequestingPrincipal,
|
||||
nsIChannel* aChannel,
|
||||
PRBool aWithCredentials,
|
||||
nsresult* aResult)
|
||||
: mOuterListener(aOuter),
|
||||
mRequestingPrincipal(aRequestingPrincipal),
|
||||
mWithCredentials(aWithCredentials && !gDisableCORSPrivateData),
|
||||
|
@ -118,14 +403,13 @@ nsCrossSiteListenerProxy::nsCrossSiteListenerProxy(nsIStreamListener* aOuter,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
nsCrossSiteListenerProxy::nsCrossSiteListenerProxy(nsIStreamListener* aOuter,
|
||||
nsIPrincipal* aRequestingPrincipal,
|
||||
nsIChannel* aChannel,
|
||||
PRBool aWithCredentials,
|
||||
const nsCString& aPreflightMethod,
|
||||
const nsTArray<nsCString>& aPreflightHeaders,
|
||||
nsresult* aResult)
|
||||
nsCORSListenerProxy::nsCORSListenerProxy(nsIStreamListener* aOuter,
|
||||
nsIPrincipal* aRequestingPrincipal,
|
||||
nsIChannel* aChannel,
|
||||
PRBool aWithCredentials,
|
||||
const nsCString& aPreflightMethod,
|
||||
const nsTArray<nsCString>& aPreflightHeaders,
|
||||
nsresult* aResult)
|
||||
: mOuterListener(aOuter),
|
||||
mRequestingPrincipal(aRequestingPrincipal),
|
||||
mWithCredentials(aWithCredentials && !gDisableCORSPrivateData),
|
||||
|
@ -152,19 +436,18 @@ nsCrossSiteListenerProxy::nsCrossSiteListenerProxy(nsIStreamListener* aOuter,
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCrossSiteListenerProxy::OnStartRequest(nsIRequest* aRequest,
|
||||
nsISupports* aContext)
|
||||
nsCORSListenerProxy::OnStartRequest(nsIRequest* aRequest,
|
||||
nsISupports* aContext)
|
||||
{
|
||||
mRequestApproved = NS_SUCCEEDED(CheckRequestApproved(aRequest));
|
||||
if (!mRequestApproved) {
|
||||
if (nsXMLHttpRequest::sAccessControlCache) {
|
||||
if (sPreflightCache) {
|
||||
nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
|
||||
if (channel) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
NS_GetFinalChannelURI(channel, getter_AddRefs(uri));
|
||||
if (uri) {
|
||||
nsXMLHttpRequest::sAccessControlCache->
|
||||
RemoveEntries(uri, mRequestingPrincipal);
|
||||
sPreflightCache->RemoveEntries(uri, mRequestingPrincipal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -219,7 +502,7 @@ IsValidHTTPToken(const nsCSubstring& aToken)
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsCrossSiteListenerProxy::CheckRequestApproved(nsIRequest* aRequest)
|
||||
nsCORSListenerProxy::CheckRequestApproved(nsIRequest* aRequest)
|
||||
{
|
||||
// Check if this was actually a cross domain request
|
||||
if (!mHasBeenCrossSite) {
|
||||
|
@ -326,19 +609,19 @@ nsCrossSiteListenerProxy::CheckRequestApproved(nsIRequest* aRequest)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCrossSiteListenerProxy::OnStopRequest(nsIRequest* aRequest,
|
||||
nsISupports* aContext,
|
||||
nsresult aStatusCode)
|
||||
nsCORSListenerProxy::OnStopRequest(nsIRequest* aRequest,
|
||||
nsISupports* aContext,
|
||||
nsresult aStatusCode)
|
||||
{
|
||||
return mOuterListener->OnStopRequest(aRequest, aContext, aStatusCode);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCrossSiteListenerProxy::OnDataAvailable(nsIRequest* aRequest,
|
||||
nsISupports* aContext,
|
||||
nsIInputStream* aInputStream,
|
||||
PRUint32 aOffset,
|
||||
PRUint32 aCount)
|
||||
nsCORSListenerProxy::OnDataAvailable(nsIRequest* aRequest,
|
||||
nsISupports* aContext,
|
||||
nsIInputStream* aInputStream,
|
||||
PRUint32 aOffset,
|
||||
PRUint32 aCount)
|
||||
{
|
||||
if (!mRequestApproved) {
|
||||
return NS_ERROR_DOM_BAD_URI;
|
||||
|
@ -348,7 +631,7 @@ nsCrossSiteListenerProxy::OnDataAvailable(nsIRequest* aRequest,
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCrossSiteListenerProxy::GetInterface(const nsIID & aIID, void **aResult)
|
||||
nsCORSListenerProxy::GetInterface(const nsIID & aIID, void **aResult)
|
||||
{
|
||||
if (aIID.Equals(NS_GET_IID(nsIChannelEventSink))) {
|
||||
*aResult = static_cast<nsIChannelEventSink*>(this);
|
||||
|
@ -363,21 +646,20 @@ nsCrossSiteListenerProxy::GetInterface(const nsIID & aIID, void **aResult)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCrossSiteListenerProxy::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
|
||||
nsIChannel *aNewChannel,
|
||||
PRUint32 aFlags,
|
||||
nsIAsyncVerifyRedirectCallback *cb)
|
||||
nsCORSListenerProxy::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
|
||||
nsIChannel *aNewChannel,
|
||||
PRUint32 aFlags,
|
||||
nsIAsyncVerifyRedirectCallback *cb)
|
||||
{
|
||||
nsresult rv;
|
||||
if (!NS_IsInternalSameURIRedirect(aOldChannel, aNewChannel, aFlags)) {
|
||||
rv = CheckRequestApproved(aOldChannel);
|
||||
if (NS_FAILED(rv)) {
|
||||
if (nsXMLHttpRequest::sAccessControlCache) {
|
||||
if (sPreflightCache) {
|
||||
nsCOMPtr<nsIURI> oldURI;
|
||||
NS_GetFinalChannelURI(aOldChannel, getter_AddRefs(oldURI));
|
||||
if (oldURI) {
|
||||
nsXMLHttpRequest::sAccessControlCache->
|
||||
RemoveEntries(oldURI, mRequestingPrincipal);
|
||||
sPreflightCache->RemoveEntries(oldURI, mRequestingPrincipal);
|
||||
}
|
||||
}
|
||||
aOldChannel->Cancel(NS_ERROR_DOM_BAD_URI);
|
||||
|
@ -408,7 +690,7 @@ nsCrossSiteListenerProxy::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCrossSiteListenerProxy::OnRedirectVerifyCallback(nsresult result)
|
||||
nsCORSListenerProxy::OnRedirectVerifyCallback(nsresult result)
|
||||
{
|
||||
NS_ASSERTION(mRedirectCallback, "mRedirectCallback not set in callback");
|
||||
NS_ASSERTION(mOldRedirectChannel, "mOldRedirectChannel not set in callback");
|
||||
|
@ -417,7 +699,7 @@ nsCrossSiteListenerProxy::OnRedirectVerifyCallback(nsresult result)
|
|||
if (NS_SUCCEEDED(result)) {
|
||||
nsresult rv = UpdateChannel(mNewRedirectChannel);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("nsCrossSiteListenerProxy::OnRedirectVerifyCallback: "
|
||||
NS_WARNING("nsCORSListenerProxy::OnRedirectVerifyCallback: "
|
||||
"UpdateChannel() returned failure");
|
||||
}
|
||||
result = rv;
|
||||
|
@ -435,7 +717,7 @@ nsCrossSiteListenerProxy::OnRedirectVerifyCallback(nsresult result)
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsCrossSiteListenerProxy::UpdateChannel(nsIChannel* aChannel)
|
||||
nsCORSListenerProxy::UpdateChannel(nsIChannel* aChannel)
|
||||
{
|
||||
nsCOMPtr<nsIURI> uri, originalURI;
|
||||
nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
|
||||
|
@ -517,3 +799,304 @@ nsCrossSiteListenerProxy::UpdateChannel(nsIChannel* aChannel)
|
|||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Preflight proxy
|
||||
|
||||
// Class used as streamlistener and notification callback when
|
||||
// doing the initial OPTIONS request for a CORS check
|
||||
class nsCORSPreflightListener : public nsIStreamListener,
|
||||
public nsIInterfaceRequestor,
|
||||
public nsIChannelEventSink
|
||||
{
|
||||
public:
|
||||
nsCORSPreflightListener(nsIChannel* aOuterChannel,
|
||||
nsIStreamListener* aOuterListener,
|
||||
nsISupports* aOuterContext,
|
||||
nsIPrincipal* aReferrerPrincipal,
|
||||
const nsACString& aRequestMethod,
|
||||
PRBool aWithCredentials)
|
||||
: mOuterChannel(aOuterChannel), mOuterListener(aOuterListener),
|
||||
mOuterContext(aOuterContext), mReferrerPrincipal(aReferrerPrincipal),
|
||||
mRequestMethod(aRequestMethod), mWithCredentials(aWithCredentials)
|
||||
{ }
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
NS_DECL_NSIREQUESTOBSERVER
|
||||
NS_DECL_NSIINTERFACEREQUESTOR
|
||||
NS_DECL_NSICHANNELEVENTSINK
|
||||
|
||||
private:
|
||||
void AddResultToCache(nsIRequest* aRequest);
|
||||
|
||||
nsCOMPtr<nsIChannel> mOuterChannel;
|
||||
nsCOMPtr<nsIStreamListener> mOuterListener;
|
||||
nsCOMPtr<nsISupports> mOuterContext;
|
||||
nsCOMPtr<nsIPrincipal> mReferrerPrincipal;
|
||||
nsCString mRequestMethod;
|
||||
PRBool mWithCredentials;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS4(nsCORSPreflightListener, nsIStreamListener,
|
||||
nsIRequestObserver, nsIInterfaceRequestor,
|
||||
nsIChannelEventSink)
|
||||
|
||||
void
|
||||
nsCORSPreflightListener::AddResultToCache(nsIRequest *aRequest)
|
||||
{
|
||||
nsCOMPtr<nsIHttpChannel> http = do_QueryInterface(aRequest);
|
||||
NS_ASSERTION(http, "Request was not http");
|
||||
|
||||
// The "Access-Control-Max-Age" header should return an age in seconds.
|
||||
nsCAutoString headerVal;
|
||||
http->GetResponseHeader(NS_LITERAL_CSTRING("Access-Control-Max-Age"),
|
||||
headerVal);
|
||||
if (headerVal.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Sanitize the string. We only allow 'delta-seconds' as specified by
|
||||
// http://dev.w3.org/2006/waf/access-control (digits 0-9 with no leading or
|
||||
// trailing non-whitespace characters).
|
||||
PRUint32 age = 0;
|
||||
nsCSubstring::const_char_iterator iter, end;
|
||||
headerVal.BeginReading(iter);
|
||||
headerVal.EndReading(end);
|
||||
while (iter != end) {
|
||||
if (*iter < '0' || *iter > '9') {
|
||||
return;
|
||||
}
|
||||
age = age * 10 + (*iter - '0');
|
||||
// Cap at 24 hours. This also avoids overflow
|
||||
age = NS_MIN(age, 86400U);
|
||||
++iter;
|
||||
}
|
||||
|
||||
if (!age || !EnsurePreflightCache()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// String seems fine, go ahead and cache.
|
||||
// Note that we have already checked that these headers follow the correct
|
||||
// syntax.
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
NS_GetFinalChannelURI(http, getter_AddRefs(uri));
|
||||
|
||||
// PR_Now gives microseconds
|
||||
PRTime expirationTime = PR_Now() + (PRUint64)age * PR_USEC_PER_SEC;
|
||||
|
||||
nsPreflightCache::CacheEntry* entry =
|
||||
sPreflightCache->GetEntry(uri, mReferrerPrincipal, mWithCredentials,
|
||||
PR_TRUE);
|
||||
if (!entry) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The "Access-Control-Allow-Methods" header contains a comma separated
|
||||
// list of method names.
|
||||
http->GetResponseHeader(NS_LITERAL_CSTRING("Access-Control-Allow-Methods"),
|
||||
headerVal);
|
||||
|
||||
nsCCharSeparatedTokenizer methods(headerVal, ',');
|
||||
while(methods.hasMoreTokens()) {
|
||||
const nsDependentCSubstring& method = methods.nextToken();
|
||||
if (method.IsEmpty()) {
|
||||
continue;
|
||||
}
|
||||
PRUint32 i;
|
||||
for (i = 0; i < entry->mMethods.Length(); ++i) {
|
||||
if (entry->mMethods[i].token.Equals(method)) {
|
||||
entry->mMethods[i].expirationTime = expirationTime;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == entry->mMethods.Length()) {
|
||||
nsPreflightCache::TokenTime* newMethod =
|
||||
entry->mMethods.AppendElement();
|
||||
if (!newMethod) {
|
||||
return;
|
||||
}
|
||||
|
||||
newMethod->token = method;
|
||||
newMethod->expirationTime = expirationTime;
|
||||
}
|
||||
}
|
||||
|
||||
// The "Access-Control-Allow-Headers" header contains a comma separated
|
||||
// list of method names.
|
||||
http->GetResponseHeader(NS_LITERAL_CSTRING("Access-Control-Allow-Headers"),
|
||||
headerVal);
|
||||
|
||||
nsCCharSeparatedTokenizer headers(headerVal, ',');
|
||||
while(headers.hasMoreTokens()) {
|
||||
const nsDependentCSubstring& header = headers.nextToken();
|
||||
if (header.IsEmpty()) {
|
||||
continue;
|
||||
}
|
||||
PRUint32 i;
|
||||
for (i = 0; i < entry->mHeaders.Length(); ++i) {
|
||||
if (entry->mHeaders[i].token.Equals(header)) {
|
||||
entry->mHeaders[i].expirationTime = expirationTime;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == entry->mHeaders.Length()) {
|
||||
nsPreflightCache::TokenTime* newHeader =
|
||||
entry->mHeaders.AppendElement();
|
||||
if (!newHeader) {
|
||||
return;
|
||||
}
|
||||
|
||||
newHeader->token = header;
|
||||
newHeader->expirationTime = expirationTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCORSPreflightListener::OnStartRequest(nsIRequest *aRequest,
|
||||
nsISupports *aContext)
|
||||
{
|
||||
nsresult status;
|
||||
nsresult rv = aRequest->GetStatus(&status);
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = status;
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// Everything worked, try to cache and then fire off the actual request.
|
||||
AddResultToCache(aRequest);
|
||||
|
||||
rv = mOuterChannel->AsyncOpen(mOuterListener, mOuterContext);
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
mOuterChannel->Cancel(rv);
|
||||
mOuterListener->OnStartRequest(mOuterChannel, mOuterContext);
|
||||
mOuterListener->OnStopRequest(mOuterChannel, mOuterContext, rv);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCORSPreflightListener::OnStopRequest(nsIRequest *aRequest,
|
||||
nsISupports *aContext,
|
||||
nsresult aStatus)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/** nsIStreamListener methods **/
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCORSPreflightListener::OnDataAvailable(nsIRequest *aRequest,
|
||||
nsISupports *ctxt,
|
||||
nsIInputStream *inStr,
|
||||
PRUint32 sourceOffset,
|
||||
PRUint32 count)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCORSPreflightListener::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
|
||||
nsIChannel *aNewChannel,
|
||||
PRUint32 aFlags,
|
||||
nsIAsyncVerifyRedirectCallback *callback)
|
||||
{
|
||||
// Only internal redirects allowed for now.
|
||||
if (!NS_IsInternalSameURIRedirect(aOldChannel, aNewChannel, aFlags))
|
||||
return NS_ERROR_DOM_BAD_URI;
|
||||
|
||||
callback->OnRedirectVerifyCallback(NS_OK);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCORSPreflightListener::GetInterface(const nsIID & aIID, void **aResult)
|
||||
{
|
||||
return QueryInterface(aIID, aResult);
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
NS_StartCORSPreflight(nsIChannel* aRequestChannel,
|
||||
nsIStreamListener* aListener,
|
||||
nsIPrincipal* aPrincipal,
|
||||
PRBool aWithCredentials,
|
||||
nsTArray<nsCString>& aUnsafeHeaders,
|
||||
nsIChannel** aPreflightChannel)
|
||||
{
|
||||
*aPreflightChannel = nsnull;
|
||||
|
||||
nsCAutoString method;
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aRequestChannel));
|
||||
NS_ENSURE_TRUE(httpChannel, NS_ERROR_UNEXPECTED);
|
||||
httpChannel->GetRequestMethod(method);
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = NS_GetFinalChannelURI(aRequestChannel, getter_AddRefs(uri));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsPreflightCache::CacheEntry* entry =
|
||||
sPreflightCache ?
|
||||
sPreflightCache->GetEntry(uri, aPrincipal, aWithCredentials, PR_FALSE) :
|
||||
nsnull;
|
||||
|
||||
if (entry && entry->CheckRequest(method, aUnsafeHeaders)) {
|
||||
// We have a cached preflight result, just start the original channel
|
||||
return aRequestChannel->AsyncOpen(aListener, nsnull);
|
||||
}
|
||||
|
||||
// Either it wasn't cached or the cached result has expired. Build a
|
||||
// channel for the OPTIONS request.
|
||||
|
||||
nsCOMPtr<nsILoadGroup> loadGroup;
|
||||
rv = aRequestChannel->GetLoadGroup(getter_AddRefs(loadGroup));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsLoadFlags loadFlags;
|
||||
rv = aRequestChannel->GetLoadFlags(&loadFlags);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIChannel> preflightChannel;
|
||||
rv = NS_NewChannel(getter_AddRefs(preflightChannel), uri, nsnull,
|
||||
loadGroup, nsnull, loadFlags);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> preHttp = do_QueryInterface(preflightChannel);
|
||||
NS_ASSERTION(preHttp, "Failed to QI to nsIHttpChannel!");
|
||||
|
||||
rv = preHttp->SetRequestMethod(NS_LITERAL_CSTRING("OPTIONS"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Set up listener which will start the original channel
|
||||
nsCOMPtr<nsIStreamListener> preflightListener =
|
||||
new nsCORSPreflightListener(aRequestChannel, aListener, nsnull, aPrincipal,
|
||||
method, aWithCredentials);
|
||||
NS_ENSURE_TRUE(preflightListener, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
preflightListener =
|
||||
new nsCORSListenerProxy(preflightListener, aPrincipal,
|
||||
preflightChannel, aWithCredentials,
|
||||
method, aUnsafeHeaders, &rv);
|
||||
NS_ENSURE_TRUE(preflightListener, NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Start preflight
|
||||
rv = preflightChannel->AsyncOpen(preflightListener, nsnull);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Return newly created preflight channel
|
||||
preflightChannel.forget(aPreflightChannel);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -35,8 +35,8 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef nsCrossSiteListenerProxy_h__
|
||||
#define nsCrossSiteListenerProxy_h__
|
||||
#ifndef nsCORSListenerProxy_h__
|
||||
#define nsCORSListenerProxy_h__
|
||||
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
|
@ -55,24 +55,32 @@ class nsIPrincipal;
|
|||
extern PRBool
|
||||
IsValidHTTPToken(const nsCSubstring& aToken);
|
||||
|
||||
class nsCrossSiteListenerProxy : public nsIStreamListener,
|
||||
public nsIInterfaceRequestor,
|
||||
public nsIChannelEventSink,
|
||||
public nsIAsyncVerifyRedirectCallback
|
||||
nsresult
|
||||
NS_StartCORSPreflight(nsIChannel* aRequestChannel,
|
||||
nsIStreamListener* aListener,
|
||||
nsIPrincipal* aPrincipal,
|
||||
PRBool aWithCredentials,
|
||||
nsTArray<nsCString>& aACUnsafeHeaders,
|
||||
nsIChannel** aPreflightChannel);
|
||||
|
||||
class nsCORSListenerProxy : public nsIStreamListener,
|
||||
public nsIInterfaceRequestor,
|
||||
public nsIChannelEventSink,
|
||||
public nsIAsyncVerifyRedirectCallback
|
||||
{
|
||||
public:
|
||||
nsCrossSiteListenerProxy(nsIStreamListener* aOuter,
|
||||
nsIPrincipal* aRequestingPrincipal,
|
||||
nsIChannel* aChannel,
|
||||
PRBool aWithCredentials,
|
||||
nsresult* aResult);
|
||||
nsCrossSiteListenerProxy(nsIStreamListener* aOuter,
|
||||
nsIPrincipal* aRequestingPrincipal,
|
||||
nsIChannel* aChannel,
|
||||
PRBool aWithCredentials,
|
||||
const nsCString& aPreflightMethod,
|
||||
const nsTArray<nsCString>& aPreflightHeaders,
|
||||
nsresult* aResult);
|
||||
nsCORSListenerProxy(nsIStreamListener* aOuter,
|
||||
nsIPrincipal* aRequestingPrincipal,
|
||||
nsIChannel* aChannel,
|
||||
PRBool aWithCredentials,
|
||||
nsresult* aResult);
|
||||
nsCORSListenerProxy(nsIStreamListener* aOuter,
|
||||
nsIPrincipal* aRequestingPrincipal,
|
||||
nsIChannel* aChannel,
|
||||
PRBool aWithCredentials,
|
||||
const nsCString& aPreflightMethod,
|
||||
const nsTArray<nsCString>& aPreflightHeaders,
|
||||
nsresult* aResult);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIREQUESTOBSERVER
|
||||
|
@ -84,6 +92,8 @@ public:
|
|||
// Must be called at startup.
|
||||
static void Startup();
|
||||
|
||||
static void Shutdown();
|
||||
|
||||
private:
|
||||
nsresult UpdateChannel(nsIChannel* aChannel);
|
||||
nsresult CheckRequestApproved(nsIRequest* aRequest);
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
|
||||
#include "nsDOMAttributeMap.h"
|
||||
#include "nsDOMAttribute.h"
|
||||
#include "nsIDOM3Document.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsGenericElement.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIDocument.h"
|
||||
|
@ -298,7 +298,7 @@ nsDOMAttributeMap::SetNamedItemInternal(nsIDOMNode *aNode,
|
|||
}
|
||||
|
||||
if (!mContent->HasSameOwnerDoc(iAttribute)) {
|
||||
nsCOMPtr<nsIDOM3Document> domDoc =
|
||||
nsCOMPtr<nsIDOMDocument> domDoc =
|
||||
do_QueryInterface(mContent->GetOwnerDoc(), &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
|
|
|
@ -52,7 +52,6 @@
|
|||
#include "nsTArray.h"
|
||||
#include "nsHashSets.h"
|
||||
#include "nsIDOMXMLDocument.h"
|
||||
#include "nsIDOM3Document.h"
|
||||
#include "nsIDOMDocumentView.h"
|
||||
#include "nsIDOMDocumentXBL.h"
|
||||
#include "nsIDOMNSDocument.h"
|
||||
|
@ -509,7 +508,6 @@ class nsDocument : public nsIDocument,
|
|||
public nsIDOMDocumentRange,
|
||||
public nsIDOMDocumentTraversal,
|
||||
public nsIDOMDocumentXBL,
|
||||
public nsIDOM3Document,
|
||||
public nsSupportsWeakReference,
|
||||
public nsIDOMEventTarget,
|
||||
public nsIDOM3EventTarget,
|
||||
|
@ -805,9 +803,6 @@ public:
|
|||
// nsIDOMDocument
|
||||
NS_DECL_NSIDOMDOCUMENT
|
||||
|
||||
// nsIDOM3Document
|
||||
NS_DECL_NSIDOM3DOCUMENT
|
||||
|
||||
// nsIDOMXMLDocument
|
||||
NS_DECL_NSIDOMXMLDOCUMENT
|
||||
|
||||
|
@ -1279,7 +1274,6 @@ protected:
|
|||
NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsIDOMDocumentTraversal, \
|
||||
nsDocument) \
|
||||
NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsIDOMEventTarget, nsDocument) \
|
||||
NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsIDOMNode, nsDocument) \
|
||||
NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsIDOM3Document, nsDocument)
|
||||
NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsIDOMNode, nsDocument)
|
||||
|
||||
#endif /* nsDocument_h___ */
|
||||
|
|
|
@ -3564,7 +3564,7 @@ nsINode::doInsertChildAt(nsIContent* aKid, PRUint32 aIndex,
|
|||
rv = kid->GetNodeType(&nodeType);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDOM3Document> domDoc = do_QueryInterface(GetOwnerDoc());
|
||||
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(GetOwnerDoc());
|
||||
|
||||
// DocumentType nodes are the only nodes that can have a null
|
||||
// ownerDocument according to the DOM spec, and we need to allow
|
||||
|
@ -4075,7 +4075,7 @@ nsINode::ReplaceOrInsertBefore(PRBool aReplace, nsINode* aNewChild,
|
|||
if (!HasSameOwnerDoc(newContent) &&
|
||||
(nodeType != nsIDOMNode::DOCUMENT_TYPE_NODE ||
|
||||
newContent->GetOwnerDoc())) {
|
||||
nsCOMPtr<nsIDOM3Document> domDoc = do_QueryInterface(doc);
|
||||
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(doc);
|
||||
|
||||
if (domDoc) {
|
||||
nsresult rv;
|
||||
|
|
|
@ -220,8 +220,8 @@ nsSyncLoader::LoadDocument(nsIChannel* aChannel,
|
|||
}
|
||||
|
||||
if (aLoaderPrincipal) {
|
||||
listener = new nsCrossSiteListenerProxy(listener, aLoaderPrincipal,
|
||||
mChannel, PR_FALSE, &rv);
|
||||
listener = new nsCORSListenerProxy(listener, aLoaderPrincipal,
|
||||
mChannel, PR_FALSE, &rv);
|
||||
NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
|
|
@ -227,9 +227,7 @@ nsTextFragment::SetTo(const PRUnichar* aBuffer, PRInt32 aLength)
|
|||
}
|
||||
|
||||
// Copy data
|
||||
// Use the same copying code we use elsewhere; it's likely to be
|
||||
// carefully tuned.
|
||||
LossyConvertEncoding<PRUnichar, char> converter(buff);
|
||||
LossyConvertEncoding16to8 converter(buff);
|
||||
copy_string(aBuffer, aBuffer+aLength, converter);
|
||||
m1b = buff;
|
||||
}
|
||||
|
@ -260,9 +258,8 @@ nsTextFragment::CopyTo(PRUnichar *aDest, PRInt32 aOffset, PRInt32 aCount)
|
|||
} else {
|
||||
const char *cp = m1b + aOffset;
|
||||
const char *end = cp + aCount;
|
||||
while (cp < end) {
|
||||
*aDest++ = (unsigned char)(*cp++);
|
||||
}
|
||||
LossyConvertEncoding8to16 converter(aDest);
|
||||
copy_string(cp, end, converter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -316,11 +313,10 @@ nsTextFragment::Append(const PRUnichar* aBuffer, PRUint32 aLength)
|
|||
return;
|
||||
}
|
||||
|
||||
// Copy data
|
||||
for (PRUint32 i = 0; i < mState.mLength; ++i) {
|
||||
buff[i] = (unsigned char)m1b[i];
|
||||
}
|
||||
|
||||
// Copy data into buff
|
||||
LossyConvertEncoding8to16 converter(buff);
|
||||
copy_string(m1b, m1b+mState.mLength, converter);
|
||||
|
||||
memcpy(buff + mState.mLength, aBuffer, aLength * sizeof(PRUnichar));
|
||||
|
||||
mState.mLength += aLength;
|
||||
|
@ -354,10 +350,10 @@ nsTextFragment::Append(const PRUnichar* aBuffer, PRUint32 aLength)
|
|||
memcpy(buff, m1b, mState.mLength);
|
||||
mState.mInHeap = PR_TRUE;
|
||||
}
|
||||
|
||||
for (PRUint32 i = 0; i < aLength; ++i) {
|
||||
buff[mState.mLength + i] = (char)aBuffer[i];
|
||||
}
|
||||
|
||||
// Copy aBuffer into buff.
|
||||
LossyConvertEncoding16to8 converter(buff + mState.mLength);
|
||||
copy_string(aBuffer, aBuffer + aLength, converter);
|
||||
|
||||
m1b = buff;
|
||||
mState.mLength += aLength;
|
||||
|
|
|
@ -87,7 +87,6 @@
|
|||
#include "nsCrossSiteListenerProxy.h"
|
||||
#include "nsDOMError.h"
|
||||
#include "nsIHTMLDocument.h"
|
||||
#include "nsIDOM3Document.h"
|
||||
#include "nsIMultiPartChannel.h"
|
||||
#include "nsIScriptObjectPrincipal.h"
|
||||
#include "nsIStorageStream.h"
|
||||
|
@ -146,8 +145,6 @@
|
|||
XML_HTTP_REQUEST_SENT | \
|
||||
XML_HTTP_REQUEST_STOPPED)
|
||||
|
||||
#define ACCESS_CONTROL_CACHE_SIZE 100
|
||||
|
||||
#define NS_BADCERTHANDLER_CONTRACTID \
|
||||
"@mozilla.org/content/xmlhttprequest-bad-cert-handler;1"
|
||||
|
||||
|
@ -286,225 +283,6 @@ nsMultipartProxyListener::OnDataAvailable(nsIRequest *aRequest,
|
|||
count);
|
||||
}
|
||||
|
||||
// Class used as streamlistener and notification callback when
|
||||
// doing the initial GET request for an access-control check
|
||||
class nsACProxyListener : public nsIStreamListener,
|
||||
public nsIInterfaceRequestor,
|
||||
public nsIChannelEventSink
|
||||
{
|
||||
public:
|
||||
nsACProxyListener(nsIChannel* aOuterChannel,
|
||||
nsIStreamListener* aOuterListener,
|
||||
nsISupports* aOuterContext,
|
||||
nsIPrincipal* aReferrerPrincipal,
|
||||
const nsACString& aRequestMethod,
|
||||
PRBool aWithCredentials)
|
||||
: mOuterChannel(aOuterChannel), mOuterListener(aOuterListener),
|
||||
mOuterContext(aOuterContext), mReferrerPrincipal(aReferrerPrincipal),
|
||||
mRequestMethod(aRequestMethod), mWithCredentials(aWithCredentials)
|
||||
{ }
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
NS_DECL_NSIREQUESTOBSERVER
|
||||
NS_DECL_NSIINTERFACEREQUESTOR
|
||||
NS_DECL_NSICHANNELEVENTSINK
|
||||
|
||||
private:
|
||||
void AddResultToCache(nsIRequest* aRequest);
|
||||
|
||||
nsCOMPtr<nsIChannel> mOuterChannel;
|
||||
nsCOMPtr<nsIStreamListener> mOuterListener;
|
||||
nsCOMPtr<nsISupports> mOuterContext;
|
||||
nsCOMPtr<nsIPrincipal> mReferrerPrincipal;
|
||||
nsCString mRequestMethod;
|
||||
PRBool mWithCredentials;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS4(nsACProxyListener, nsIStreamListener, nsIRequestObserver,
|
||||
nsIInterfaceRequestor, nsIChannelEventSink)
|
||||
|
||||
void
|
||||
nsACProxyListener::AddResultToCache(nsIRequest *aRequest)
|
||||
{
|
||||
nsCOMPtr<nsIHttpChannel> http = do_QueryInterface(aRequest);
|
||||
NS_ASSERTION(http, "Request was not http");
|
||||
|
||||
// The "Access-Control-Max-Age" header should return an age in seconds.
|
||||
nsCAutoString headerVal;
|
||||
http->GetResponseHeader(NS_LITERAL_CSTRING("Access-Control-Max-Age"),
|
||||
headerVal);
|
||||
if (headerVal.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Sanitize the string. We only allow 'delta-seconds' as specified by
|
||||
// http://dev.w3.org/2006/waf/access-control (digits 0-9 with no leading or
|
||||
// trailing non-whitespace characters).
|
||||
PRUint32 age = 0;
|
||||
nsCSubstring::const_char_iterator iter, end;
|
||||
headerVal.BeginReading(iter);
|
||||
headerVal.EndReading(end);
|
||||
while (iter != end) {
|
||||
if (*iter < '0' || *iter > '9') {
|
||||
return;
|
||||
}
|
||||
age = age * 10 + (*iter - '0');
|
||||
// Cap at 24 hours. This also avoids overflow
|
||||
age = NS_MIN(age, 86400U);
|
||||
++iter;
|
||||
}
|
||||
|
||||
if (!age || !nsXMLHttpRequest::EnsureACCache()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// String seems fine, go ahead and cache.
|
||||
// Note that we have already checked that these headers follow the correct
|
||||
// syntax.
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
NS_GetFinalChannelURI(http, getter_AddRefs(uri));
|
||||
|
||||
// PR_Now gives microseconds
|
||||
PRTime expirationTime = PR_Now() + (PRUint64)age * PR_USEC_PER_SEC;
|
||||
|
||||
nsAccessControlLRUCache::CacheEntry* entry =
|
||||
nsXMLHttpRequest::sAccessControlCache->
|
||||
GetEntry(uri, mReferrerPrincipal, mWithCredentials, PR_TRUE);
|
||||
if (!entry) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The "Access-Control-Allow-Methods" header contains a comma separated
|
||||
// list of method names.
|
||||
http->GetResponseHeader(NS_LITERAL_CSTRING("Access-Control-Allow-Methods"),
|
||||
headerVal);
|
||||
|
||||
nsCCharSeparatedTokenizer methods(headerVal, ',');
|
||||
while(methods.hasMoreTokens()) {
|
||||
const nsDependentCSubstring& method = methods.nextToken();
|
||||
if (method.IsEmpty()) {
|
||||
continue;
|
||||
}
|
||||
PRUint32 i;
|
||||
for (i = 0; i < entry->mMethods.Length(); ++i) {
|
||||
if (entry->mMethods[i].token.Equals(method)) {
|
||||
entry->mMethods[i].expirationTime = expirationTime;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == entry->mMethods.Length()) {
|
||||
nsAccessControlLRUCache::TokenTime* newMethod =
|
||||
entry->mMethods.AppendElement();
|
||||
if (!newMethod) {
|
||||
return;
|
||||
}
|
||||
|
||||
newMethod->token = method;
|
||||
newMethod->expirationTime = expirationTime;
|
||||
}
|
||||
}
|
||||
|
||||
// The "Access-Control-Allow-Headers" header contains a comma separated
|
||||
// list of method names.
|
||||
http->GetResponseHeader(NS_LITERAL_CSTRING("Access-Control-Allow-Headers"),
|
||||
headerVal);
|
||||
|
||||
nsCCharSeparatedTokenizer headers(headerVal, ',');
|
||||
while(headers.hasMoreTokens()) {
|
||||
const nsDependentCSubstring& header = headers.nextToken();
|
||||
if (header.IsEmpty()) {
|
||||
continue;
|
||||
}
|
||||
PRUint32 i;
|
||||
for (i = 0; i < entry->mHeaders.Length(); ++i) {
|
||||
if (entry->mHeaders[i].token.Equals(header)) {
|
||||
entry->mHeaders[i].expirationTime = expirationTime;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == entry->mHeaders.Length()) {
|
||||
nsAccessControlLRUCache::TokenTime* newHeader =
|
||||
entry->mHeaders.AppendElement();
|
||||
if (!newHeader) {
|
||||
return;
|
||||
}
|
||||
|
||||
newHeader->token = header;
|
||||
newHeader->expirationTime = expirationTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsACProxyListener::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
|
||||
{
|
||||
nsresult status;
|
||||
nsresult rv = aRequest->GetStatus(&status);
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = status;
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// Everything worked, try to cache and then fire off the actual request.
|
||||
AddResultToCache(aRequest);
|
||||
|
||||
rv = mOuterChannel->AsyncOpen(mOuterListener, mOuterContext);
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
mOuterChannel->Cancel(rv);
|
||||
mOuterListener->OnStartRequest(mOuterChannel, mOuterContext);
|
||||
mOuterListener->OnStopRequest(mOuterChannel, mOuterContext, rv);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsACProxyListener::OnStopRequest(nsIRequest *aRequest, nsISupports *aContext,
|
||||
nsresult aStatus)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/** nsIStreamListener methods **/
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsACProxyListener::OnDataAvailable(nsIRequest *aRequest,
|
||||
nsISupports *ctxt,
|
||||
nsIInputStream *inStr,
|
||||
PRUint32 sourceOffset,
|
||||
PRUint32 count)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsACProxyListener::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
|
||||
nsIChannel *aNewChannel,
|
||||
PRUint32 aFlags,
|
||||
nsIAsyncVerifyRedirectCallback *callback)
|
||||
{
|
||||
// Only internal redirects allowed for now.
|
||||
if (!NS_IsInternalSameURIRedirect(aOldChannel, aNewChannel, aFlags))
|
||||
return NS_ERROR_DOM_BAD_URI;
|
||||
|
||||
callback->OnRedirectVerifyCallback(NS_OK);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsACProxyListener::GetInterface(const nsIID & aIID, void **aResult)
|
||||
{
|
||||
return QueryInterface(aIID, aResult);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsXHREventTarget)
|
||||
|
@ -633,219 +411,11 @@ NS_INTERFACE_MAP_END_INHERITING(nsXHREventTarget)
|
|||
NS_IMPL_ADDREF_INHERITED(nsXMLHttpRequestUpload, nsXHREventTarget)
|
||||
NS_IMPL_RELEASE_INHERITED(nsXMLHttpRequestUpload, nsXHREventTarget)
|
||||
|
||||
void
|
||||
nsAccessControlLRUCache::CacheEntry::PurgeExpired(PRTime now)
|
||||
{
|
||||
PRUint32 i;
|
||||
for (i = 0; i < mMethods.Length(); ++i) {
|
||||
if (now >= mMethods[i].expirationTime) {
|
||||
mMethods.RemoveElementAt(i--);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < mHeaders.Length(); ++i) {
|
||||
if (now >= mHeaders[i].expirationTime) {
|
||||
mHeaders.RemoveElementAt(i--);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsAccessControlLRUCache::CacheEntry::CheckRequest(const nsCString& aMethod,
|
||||
const nsTArray<nsCString>& aHeaders)
|
||||
{
|
||||
PurgeExpired(PR_Now());
|
||||
|
||||
if (!aMethod.EqualsLiteral("GET") && !aMethod.EqualsLiteral("POST")) {
|
||||
PRUint32 i;
|
||||
for (i = 0; i < mMethods.Length(); ++i) {
|
||||
if (aMethod.Equals(mMethods[i].token))
|
||||
break;
|
||||
}
|
||||
if (i == mMethods.Length()) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
for (PRUint32 i = 0; i < aHeaders.Length(); ++i) {
|
||||
PRUint32 j;
|
||||
for (j = 0; j < mHeaders.Length(); ++j) {
|
||||
if (aHeaders[i].Equals(mHeaders[j].token,
|
||||
nsCaseInsensitiveCStringComparator())) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j == mHeaders.Length()) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
nsAccessControlLRUCache::CacheEntry*
|
||||
nsAccessControlLRUCache::GetEntry(nsIURI* aURI,
|
||||
nsIPrincipal* aPrincipal,
|
||||
PRBool aWithCredentials,
|
||||
PRBool aCreate)
|
||||
{
|
||||
nsCString key;
|
||||
if (!GetCacheKey(aURI, aPrincipal, aWithCredentials, key)) {
|
||||
NS_WARNING("Invalid cache key!");
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
CacheEntry* entry;
|
||||
|
||||
if (mTable.Get(key, &entry)) {
|
||||
// Entry already existed so just return it. Also update the LRU list.
|
||||
|
||||
// Move to the head of the list.
|
||||
PR_REMOVE_LINK(entry);
|
||||
PR_INSERT_LINK(entry, &mList);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
if (!aCreate) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
// This is a new entry, allocate and insert into the table now so that any
|
||||
// failures don't cause items to be removed from a full cache.
|
||||
entry = new CacheEntry(key);
|
||||
if (!entry) {
|
||||
NS_WARNING("Failed to allocate new cache entry!");
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
if (!mTable.Put(key, entry)) {
|
||||
// Failed, clean up the new entry.
|
||||
delete entry;
|
||||
|
||||
NS_WARNING("Failed to add entry to the access control cache!");
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
PR_INSERT_LINK(entry, &mList);
|
||||
|
||||
NS_ASSERTION(mTable.Count() <= ACCESS_CONTROL_CACHE_SIZE + 1,
|
||||
"Something is borked, too many entries in the cache!");
|
||||
|
||||
// Now enforce the max count.
|
||||
if (mTable.Count() > ACCESS_CONTROL_CACHE_SIZE) {
|
||||
// Try to kick out all the expired entries.
|
||||
PRTime now = PR_Now();
|
||||
mTable.Enumerate(RemoveExpiredEntries, &now);
|
||||
|
||||
// If that didn't remove anything then kick out the least recently used
|
||||
// entry.
|
||||
if (mTable.Count() > ACCESS_CONTROL_CACHE_SIZE) {
|
||||
CacheEntry* lruEntry = static_cast<CacheEntry*>(PR_LIST_TAIL(&mList));
|
||||
PR_REMOVE_LINK(lruEntry);
|
||||
|
||||
// This will delete 'lruEntry'.
|
||||
mTable.Remove(lruEntry->mKey);
|
||||
|
||||
NS_ASSERTION(mTable.Count() == ACCESS_CONTROL_CACHE_SIZE,
|
||||
"Somehow tried to remove an entry that was never added!");
|
||||
}
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
void
|
||||
nsAccessControlLRUCache::RemoveEntries(nsIURI* aURI, nsIPrincipal* aPrincipal)
|
||||
{
|
||||
CacheEntry* entry;
|
||||
nsCString key;
|
||||
if (GetCacheKey(aURI, aPrincipal, PR_TRUE, key) &&
|
||||
mTable.Get(key, &entry)) {
|
||||
PR_REMOVE_LINK(entry);
|
||||
mTable.Remove(key);
|
||||
}
|
||||
|
||||
if (GetCacheKey(aURI, aPrincipal, PR_FALSE, key) &&
|
||||
mTable.Get(key, &entry)) {
|
||||
PR_REMOVE_LINK(entry);
|
||||
mTable.Remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsAccessControlLRUCache::Clear()
|
||||
{
|
||||
PR_INIT_CLIST(&mList);
|
||||
mTable.Clear();
|
||||
}
|
||||
|
||||
/* static */ PLDHashOperator
|
||||
nsAccessControlLRUCache::RemoveExpiredEntries(const nsACString& aKey,
|
||||
nsAutoPtr<CacheEntry>& aValue,
|
||||
void* aUserData)
|
||||
{
|
||||
PRTime* now = static_cast<PRTime*>(aUserData);
|
||||
|
||||
aValue->PurgeExpired(*now);
|
||||
|
||||
if (aValue->mHeaders.IsEmpty() &&
|
||||
aValue->mHeaders.IsEmpty()) {
|
||||
// Expired, remove from the list as well as the hash table.
|
||||
PR_REMOVE_LINK(aValue);
|
||||
return PL_DHASH_REMOVE;
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
/* static */ PRBool
|
||||
nsAccessControlLRUCache::GetCacheKey(nsIURI* aURI,
|
||||
nsIPrincipal* aPrincipal,
|
||||
PRBool aWithCredentials,
|
||||
nsACString& _retval)
|
||||
{
|
||||
NS_ASSERTION(aURI, "Null uri!");
|
||||
NS_ASSERTION(aPrincipal, "Null principal!");
|
||||
|
||||
NS_NAMED_LITERAL_CSTRING(space, " ");
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = aPrincipal->GetURI(getter_AddRefs(uri));
|
||||
NS_ENSURE_SUCCESS(rv, PR_FALSE);
|
||||
|
||||
nsCAutoString scheme, host, port;
|
||||
if (uri) {
|
||||
uri->GetScheme(scheme);
|
||||
uri->GetHost(host);
|
||||
port.AppendInt(NS_GetRealPort(uri));
|
||||
}
|
||||
|
||||
nsCAutoString cred;
|
||||
if (aWithCredentials) {
|
||||
_retval.AssignLiteral("cred");
|
||||
}
|
||||
else {
|
||||
_retval.AssignLiteral("nocred");
|
||||
}
|
||||
|
||||
nsCAutoString spec;
|
||||
rv = aURI->GetSpec(spec);
|
||||
NS_ENSURE_SUCCESS(rv, PR_FALSE);
|
||||
|
||||
_retval.Assign(cred + space + scheme + space + host + space + port + space +
|
||||
spec);
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////
|
||||
//
|
||||
//
|
||||
/////////////////////////////////////////////
|
||||
|
||||
// Will be initialized in nsXMLHttpRequest::EnsureACCache.
|
||||
nsAccessControlLRUCache* nsXMLHttpRequest::sAccessControlCache = nsnull;
|
||||
|
||||
nsXMLHttpRequest::nsXMLHttpRequest()
|
||||
: mRequestObserver(nsnull), mState(XML_HTTP_REQUEST_UNINITIALIZED),
|
||||
mUploadTransferred(0), mUploadTotal(0), mUploadComplete(PR_TRUE),
|
||||
|
@ -985,7 +555,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXMLHttpRequest,
|
|||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mChannel)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mReadRequest)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mResponseXML)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mACGetChannel)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mCORSPreflightChannel)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnUploadProgressListener)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnReadystatechangeListener)
|
||||
|
@ -1006,7 +576,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsXMLHttpRequest,
|
|||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mChannel)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mReadRequest)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mResponseXML)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mACGetChannel)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCORSPreflightChannel)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnUploadProgressListener)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnReadystatechangeListener)
|
||||
|
@ -1363,8 +933,8 @@ nsXMLHttpRequest::Abort()
|
|||
if (mChannel) {
|
||||
mChannel->Cancel(NS_BINDING_ABORTED);
|
||||
}
|
||||
if (mACGetChannel) {
|
||||
mACGetChannel->Cancel(NS_BINDING_ABORTED);
|
||||
if (mCORSPreflightChannel) {
|
||||
mCORSPreflightChannel->Cancel(NS_BINDING_ABORTED);
|
||||
}
|
||||
mResponseXML = nsnull;
|
||||
PRUint32 responseLength = mResponseBody.Length();
|
||||
|
@ -1390,7 +960,7 @@ nsXMLHttpRequest::Abort()
|
|||
}
|
||||
|
||||
// The ChangeState call above calls onreadystatechange handlers which
|
||||
// if they load a new url will cause nsXMLHttpRequest::OpenRequest to clear
|
||||
// if they load a new url will cause nsXMLHttpRequest::Open to clear
|
||||
// the abort state bit. If this occurs we're not uninitialized (bug 361773).
|
||||
if (mState & XML_HTTP_REQUEST_ABORTED) {
|
||||
ChangeState(XML_HTTP_REQUEST_UNINITIALIZED, PR_FALSE); // IE seems to do it
|
||||
|
@ -1655,7 +1225,7 @@ nsXMLHttpRequest::CheckChannelForCrossSiteRequest(nsIChannel* aChannel)
|
|||
|
||||
nsCAutoString method;
|
||||
httpChannel->GetRequestMethod(method);
|
||||
if (!mACUnsafeHeaders.IsEmpty() ||
|
||||
if (!mCORSUnsafeHeaders.IsEmpty() ||
|
||||
HasListenersFor(NS_LITERAL_STRING(UPLOADPROGRESS_STR)) ||
|
||||
(mUpload && mUpload->HasListeners()) ||
|
||||
(!method.LowerCaseEqualsLiteral("get") &&
|
||||
|
@ -1667,16 +1237,18 @@ nsXMLHttpRequest::CheckChannelForCrossSiteRequest(nsIChannel* aChannel)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
/* noscript void openRequest (in AUTF8String method, in AUTF8String url, in boolean async, in AString user, in AString password); */
|
||||
NS_IMETHODIMP
|
||||
nsXMLHttpRequest::OpenRequest(const nsACString& method,
|
||||
const nsACString& url,
|
||||
PRBool async,
|
||||
const nsAString& user,
|
||||
const nsAString& password)
|
||||
nsXMLHttpRequest::Open(const nsACString& method, const nsACString& url,
|
||||
PRBool async, const nsAString& user,
|
||||
const nsAString& password, PRUint8 optional_argc)
|
||||
{
|
||||
NS_ENSURE_ARG(!method.IsEmpty());
|
||||
|
||||
if (!optional_argc) {
|
||||
// No optional arguments were passed in. Default async to true.
|
||||
async = PR_TRUE;
|
||||
}
|
||||
|
||||
NS_ENSURE_TRUE(mPrincipal, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
// Disallow HTTP/1.1 TRACE method (see bug 302489)
|
||||
|
@ -1806,20 +1378,6 @@ nsXMLHttpRequest::OpenRequest(const nsACString& method,
|
|||
return rv;
|
||||
}
|
||||
|
||||
/* void open (in AUTF8String method, in AUTF8String url); */
|
||||
NS_IMETHODIMP
|
||||
nsXMLHttpRequest::Open(const nsACString& method, const nsACString& url,
|
||||
PRBool async, const nsAString& user,
|
||||
const nsAString& password, PRUint8 optional_argc)
|
||||
{
|
||||
if (!optional_argc) {
|
||||
// No optional arguments were passed in. Default async to true.
|
||||
async = PR_TRUE;
|
||||
}
|
||||
|
||||
return OpenRequest(method, url, async, user, password);
|
||||
}
|
||||
|
||||
/*
|
||||
* "Copy" from a stream.
|
||||
*/
|
||||
|
@ -2279,13 +1837,10 @@ GetRequestBody(nsIVariant* aBody, nsIInputStream** aResult,
|
|||
nsCOMPtr<nsIDOMDocument> doc = do_QueryInterface(supports);
|
||||
if (doc) {
|
||||
aContentType.AssignLiteral("application/xml");
|
||||
nsCOMPtr<nsIDOM3Document> dom3doc = do_QueryInterface(doc);
|
||||
if (dom3doc) {
|
||||
nsAutoString inputEncoding;
|
||||
dom3doc->GetInputEncoding(inputEncoding);
|
||||
if (!DOMStringIsNull(inputEncoding)) {
|
||||
CopyUTF16toUTF8(inputEncoding, aCharset);
|
||||
}
|
||||
nsAutoString inputEncoding;
|
||||
doc->GetInputEncoding(inputEncoding);
|
||||
if (!DOMStringIsNull(inputEncoding)) {
|
||||
CopyUTF16toUTF8(inputEncoding, aCharset);
|
||||
}
|
||||
|
||||
// Serialize to a stream so that the encoding used will
|
||||
|
@ -2571,7 +2126,7 @@ nsXMLHttpRequest::Send(nsIVariant *aBody)
|
|||
if (!contentType.LowerCaseEqualsLiteral("text/plain") &&
|
||||
!contentType.LowerCaseEqualsLiteral("application/x-www-form-urlencoded") &&
|
||||
!contentType.LowerCaseEqualsLiteral("multipart/form-data")) {
|
||||
mACUnsafeHeaders.AppendElement(NS_LITERAL_CSTRING("Content-Type"));
|
||||
mCORSUnsafeHeaders.AppendElement(NS_LITERAL_CSTRING("Content-Type"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2588,41 +2143,6 @@ nsXMLHttpRequest::Send(nsIVariant *aBody)
|
|||
|
||||
PRBool withCredentials = !!(mState & XML_HTTP_REQUEST_AC_WITH_CREDENTIALS);
|
||||
|
||||
// If so, set up the preflight
|
||||
if (mState & XML_HTTP_REQUEST_NEED_AC_PREFLIGHT) {
|
||||
// Check to see if this initial OPTIONS request has already been cached
|
||||
// in our special Access Control Cache.
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
rv = NS_GetFinalChannelURI(mChannel, getter_AddRefs(uri));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAccessControlLRUCache::CacheEntry* entry =
|
||||
sAccessControlCache ?
|
||||
sAccessControlCache->GetEntry(uri, mPrincipal, withCredentials, PR_FALSE) :
|
||||
nsnull;
|
||||
|
||||
if (!entry || !entry->CheckRequest(method, mACUnsafeHeaders)) {
|
||||
// Either it wasn't cached or the cached result has expired. Build a
|
||||
// channel for the OPTIONS request.
|
||||
nsCOMPtr<nsILoadGroup> loadGroup;
|
||||
GetLoadGroup(getter_AddRefs(loadGroup));
|
||||
|
||||
nsLoadFlags loadFlags;
|
||||
rv = mChannel->GetLoadFlags(&loadFlags);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = NS_NewChannel(getter_AddRefs(mACGetChannel), uri, nsnull,
|
||||
loadGroup, nsnull, loadFlags);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> acHttp = do_QueryInterface(mACGetChannel);
|
||||
NS_ASSERTION(acHttp, "Failed to QI to nsIHttpChannel!");
|
||||
|
||||
rv = acHttp->SetRequestMethod(NS_LITERAL_CSTRING("OPTIONS"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
|
||||
// Hook us up to listen to redirects and the like
|
||||
mChannel->GetNotificationCallbacks(getter_AddRefs(mNotificationCallbacks));
|
||||
mChannel->SetNotificationCallbacks(this);
|
||||
|
@ -2637,10 +2157,10 @@ nsXMLHttpRequest::Send(nsIVariant *aBody)
|
|||
}
|
||||
|
||||
if (!IsSystemXHR()) {
|
||||
// Always create a nsCrossSiteListenerProxy here even if it's
|
||||
// Always create a nsCORSListenerProxy here even if it's
|
||||
// a same-origin request right now, since it could be redirected.
|
||||
listener = new nsCrossSiteListenerProxy(listener, mPrincipal, mChannel,
|
||||
withCredentials, &rv);
|
||||
listener = new nsCORSListenerProxy(listener, mPrincipal, mChannel,
|
||||
withCredentials, &rv);
|
||||
NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
@ -2661,10 +2181,6 @@ nsXMLHttpRequest::Send(nsIVariant *aBody)
|
|||
else if (!(mState & XML_HTTP_REQUEST_ASYNC)) {
|
||||
AddLoadFlags(mChannel,
|
||||
nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE_IF_BUSY);
|
||||
if (mACGetChannel) {
|
||||
AddLoadFlags(mACGetChannel,
|
||||
nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE_IF_BUSY);
|
||||
}
|
||||
}
|
||||
|
||||
// Since we expect XML data, set the type hint accordingly
|
||||
|
@ -2672,22 +2188,16 @@ nsXMLHttpRequest::Send(nsIVariant *aBody)
|
|||
// ignoring return value, as this is not critical
|
||||
mChannel->SetContentType(NS_LITERAL_CSTRING("application/xml"));
|
||||
|
||||
// If we're doing a cross-site non-GET request we need to first do
|
||||
// a GET request to the same URI. Set that up if needed
|
||||
if (mACGetChannel) {
|
||||
nsCOMPtr<nsIStreamListener> acProxyListener =
|
||||
new nsACProxyListener(mChannel, listener, nsnull, mPrincipal, method,
|
||||
withCredentials);
|
||||
NS_ENSURE_TRUE(acProxyListener, NS_ERROR_OUT_OF_MEMORY);
|
||||
// Set up the preflight if needed
|
||||
if (mState & XML_HTTP_REQUEST_NEED_AC_PREFLIGHT) {
|
||||
// Check to see if this initial OPTIONS request has already been cached
|
||||
// in our special Access Control Cache.
|
||||
|
||||
acProxyListener =
|
||||
new nsCrossSiteListenerProxy(acProxyListener, mPrincipal, mACGetChannel,
|
||||
withCredentials, method, mACUnsafeHeaders,
|
||||
&rv);
|
||||
NS_ENSURE_TRUE(acProxyListener, NS_ERROR_OUT_OF_MEMORY);
|
||||
rv = NS_StartCORSPreflight(mChannel, listener,
|
||||
mPrincipal, withCredentials,
|
||||
mCORSUnsafeHeaders,
|
||||
getter_AddRefs(mCORSPreflightChannel));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mACGetChannel->AsyncOpen(acProxyListener, nsnull);
|
||||
}
|
||||
else {
|
||||
// Start reading from the channel
|
||||
|
@ -2697,7 +2207,7 @@ nsXMLHttpRequest::Send(nsIVariant *aBody)
|
|||
if (NS_FAILED(rv)) {
|
||||
// Drop our ref to the channel to avoid cycles
|
||||
mChannel = nsnull;
|
||||
mACGetChannel = nsnull;
|
||||
mCORSPreflightChannel = nsnull;
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -2774,17 +2284,17 @@ nsXMLHttpRequest::SetRequestHeader(const nsACString& header,
|
|||
{
|
||||
nsresult rv;
|
||||
|
||||
// Make sure we don't store an invalid header name in mACUnsafeHeaders
|
||||
// Make sure we don't store an invalid header name in mCORSUnsafeHeaders
|
||||
if (!IsValidHTTPToken(header)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Check that we haven't already opened the channel. We can't rely on
|
||||
// the channel throwing from mChannel->SetRequestHeader since we might
|
||||
// still be waiting for mACGetChannel to actually open mChannel
|
||||
if (mACGetChannel) {
|
||||
// still be waiting for mCORSPreflightChannel to actually open mChannel
|
||||
if (mCORSPreflightChannel) {
|
||||
PRBool pending;
|
||||
rv = mACGetChannel->IsPending(&pending);
|
||||
rv = mCORSPreflightChannel->IsPending(&pending);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (pending) {
|
||||
|
@ -2849,7 +2359,7 @@ nsXMLHttpRequest::SetRequestHeader(const nsACString& header,
|
|||
}
|
||||
|
||||
if (!safeHeader) {
|
||||
mACUnsafeHeaders.AppendElement(header);
|
||||
mCORSUnsafeHeaders.AppendElement(header);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -60,10 +60,6 @@
|
|||
#include "nsTArray.h"
|
||||
#include "nsIJSNativeInitializer.h"
|
||||
#include "nsIDOMLSProgressEvent.h"
|
||||
#include "nsClassHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "prclist.h"
|
||||
#include "prtime.h"
|
||||
#include "nsIDOMNSEvent.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsIPrivateDOMEvent.h"
|
||||
|
@ -74,72 +70,6 @@
|
|||
class nsILoadGroup;
|
||||
class AsyncVerifyRedirectCallbackForwarder;
|
||||
|
||||
class nsAccessControlLRUCache
|
||||
{
|
||||
public:
|
||||
struct TokenTime
|
||||
{
|
||||
nsCString token;
|
||||
PRTime expirationTime;
|
||||
};
|
||||
|
||||
struct CacheEntry : public PRCList
|
||||
{
|
||||
CacheEntry(nsCString& aKey)
|
||||
: mKey(aKey)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsAccessControlLRUCache::CacheEntry);
|
||||
}
|
||||
|
||||
~CacheEntry()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsAccessControlLRUCache::CacheEntry);
|
||||
}
|
||||
|
||||
void PurgeExpired(PRTime now);
|
||||
PRBool CheckRequest(const nsCString& aMethod,
|
||||
const nsTArray<nsCString>& aCustomHeaders);
|
||||
|
||||
nsCString mKey;
|
||||
nsTArray<TokenTime> mMethods;
|
||||
nsTArray<TokenTime> mHeaders;
|
||||
};
|
||||
|
||||
nsAccessControlLRUCache()
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsAccessControlLRUCache);
|
||||
PR_INIT_CLIST(&mList);
|
||||
}
|
||||
|
||||
~nsAccessControlLRUCache()
|
||||
{
|
||||
Clear();
|
||||
MOZ_COUNT_DTOR(nsAccessControlLRUCache);
|
||||
}
|
||||
|
||||
PRBool Initialize()
|
||||
{
|
||||
return mTable.Init();
|
||||
}
|
||||
|
||||
CacheEntry* GetEntry(nsIURI* aURI, nsIPrincipal* aPrincipal,
|
||||
PRBool aWithCredentials, PRBool aCreate);
|
||||
void RemoveEntries(nsIURI* aURI, nsIPrincipal* aPrincipal);
|
||||
|
||||
void Clear();
|
||||
|
||||
private:
|
||||
static PLDHashOperator
|
||||
RemoveExpiredEntries(const nsACString& aKey, nsAutoPtr<CacheEntry>& aValue,
|
||||
void* aUserData);
|
||||
|
||||
static PRBool GetCacheKey(nsIURI* aURI, nsIPrincipal* aPrincipal,
|
||||
PRBool aWithCredentials, nsACString& _retval);
|
||||
|
||||
nsClassHashtable<nsCStringHashKey, CacheEntry> mTable;
|
||||
PRCList mList;
|
||||
};
|
||||
|
||||
class nsXHREventTarget : public nsDOMEventTargetWrapperCache,
|
||||
public nsIXMLHttpRequestEventTarget
|
||||
{
|
||||
|
@ -281,32 +211,8 @@ public:
|
|||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXMLHttpRequest,
|
||||
nsXHREventTarget)
|
||||
|
||||
static PRBool EnsureACCache()
|
||||
{
|
||||
if (sAccessControlCache)
|
||||
return PR_TRUE;
|
||||
|
||||
nsAutoPtr<nsAccessControlLRUCache> newCache(new nsAccessControlLRUCache());
|
||||
NS_ENSURE_TRUE(newCache, PR_FALSE);
|
||||
|
||||
if (newCache->Initialize()) {
|
||||
sAccessControlCache = newCache.forget();
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
static void ShutdownACCache()
|
||||
{
|
||||
delete sAccessControlCache;
|
||||
sAccessControlCache = nsnull;
|
||||
}
|
||||
|
||||
PRBool AllowUploadProgress();
|
||||
|
||||
static nsAccessControlLRUCache* sAccessControlCache;
|
||||
|
||||
protected:
|
||||
friend class nsMultipartProxyListener;
|
||||
|
||||
|
@ -357,8 +263,8 @@ protected:
|
|||
// mReadRequest is different from mChannel for multipart requests
|
||||
nsCOMPtr<nsIRequest> mReadRequest;
|
||||
nsCOMPtr<nsIDOMDocument> mResponseXML;
|
||||
nsCOMPtr<nsIChannel> mACGetChannel;
|
||||
nsTArray<nsCString> mACUnsafeHeaders;
|
||||
nsCOMPtr<nsIChannel> mCORSPreflightChannel;
|
||||
nsTArray<nsCString> mCORSUnsafeHeaders;
|
||||
|
||||
nsRefPtr<nsDOMEventListenerWrapper> mOnUploadProgressListener;
|
||||
nsRefPtr<nsDOMEventListenerWrapper> mOnReadystatechangeListener;
|
||||
|
|
|
@ -76,7 +76,7 @@ nsresult TestGetURL(const nsCString& aURL)
|
|||
rv = xhr->Init(systemPrincipal, nsnull, nsnull, nsnull);
|
||||
TEST_ENSURE_SUCCESS(rv, "Couldn't initialize the XHR!");
|
||||
|
||||
rv = xhr->OpenRequest(getString, aURL, PR_FALSE, empty, empty);
|
||||
rv = xhr->Open(getString, aURL, PR_FALSE, empty, empty);
|
||||
TEST_ENSURE_SUCCESS(rv, "OpenRequest failed!");
|
||||
|
||||
rv = xhr->Send(nsnull);
|
||||
|
|
|
@ -77,9 +77,9 @@ nsresult TestNativeXMLHttpRequest()
|
|||
const nsAString& empty = EmptyString();
|
||||
|
||||
printf("*** About to see an expected warning about mPrincipal:\n");
|
||||
rv = xhr->OpenRequest(getString, testURL, PR_FALSE, empty, empty);
|
||||
rv = xhr->Open(getString, testURL, PR_FALSE, empty, empty);
|
||||
printf("*** End of expected warning output.\n");
|
||||
TEST_ENSURE_FAILED(rv, "OpenRequest should have failed!");
|
||||
TEST_ENSURE_FAILED(rv, "Open should have failed!");
|
||||
|
||||
nsCOMPtr<nsIScriptSecurityManager> secman =
|
||||
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
|
||||
|
@ -92,8 +92,8 @@ nsresult TestNativeXMLHttpRequest()
|
|||
rv = xhr->Init(systemPrincipal, nsnull, nsnull, nsnull);
|
||||
TEST_ENSURE_SUCCESS(rv, "Couldn't initialize the XHR!");
|
||||
|
||||
rv = xhr->OpenRequest(getString, testURL, PR_FALSE, empty, empty);
|
||||
TEST_ENSURE_SUCCESS(rv, "OpenRequest failed!");
|
||||
rv = xhr->Open(getString, testURL, PR_FALSE, empty, empty);
|
||||
TEST_ENSURE_SUCCESS(rv, "Open failed!");
|
||||
|
||||
rv = xhr->Send(nsnull);
|
||||
TEST_ENSURE_SUCCESS(rv, "Send failed!");
|
||||
|
|
|
@ -25,7 +25,7 @@ window.addEventListener("message", function(e) {
|
|||
};
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
for each(type in ["load", "abort", "error", "loadstart"]) {
|
||||
for each(type in ["load", "abort", "error", "loadstart", "loadend"]) {
|
||||
xhr.addEventListener(type, function(e) {
|
||||
res.events.push(e.type);
|
||||
}, false);
|
||||
|
@ -48,10 +48,10 @@ window.addEventListener("message", function(e) {
|
|||
}, false);
|
||||
}
|
||||
}
|
||||
xhr.onload = xhr.onerror = function (event) {
|
||||
if (event.type == "error") {
|
||||
res.didFail = true;
|
||||
}
|
||||
xhr.onerror = function(e) {
|
||||
res.didFail = true;
|
||||
};
|
||||
xhr.onloadend = function (event) {
|
||||
res.status = xhr.status;
|
||||
try {
|
||||
res.statusText = xhr.statusText;
|
||||
|
|
Двоичные данные
content/base/test/file_CrossSiteXHR_inner.jar
Двоичные данные
content/base/test/file_CrossSiteXHR_inner.jar
Двоичный файл не отображается.
|
@ -14,7 +14,7 @@ window.addEventListener("message", function(e) {\n\
|
|||
};\n\
|
||||
\n\
|
||||
var xhr = new XMLHttpRequest();\n\
|
||||
for each(type in ["load", "abort", "error", "loadstart"]) {\n\
|
||||
for each(type in ["load", "abort", "error", "loadstart", "loadend"]) {\n\
|
||||
xhr.addEventListener(type, function(e) {\n\
|
||||
res.events.push(e.type);\n\
|
||||
}, false);\n\
|
||||
|
@ -37,26 +37,27 @@ window.addEventListener("message", function(e) {\n\
|
|||
}, false);\n\
|
||||
}\n\
|
||||
}\n\
|
||||
xhr.onload = function () {\n\
|
||||
res.status = xhr.status;\n\
|
||||
res.statusText = xhr.statusText;\n\
|
||||
res.responseXML = xhr.responseXML ?\n\
|
||||
(new XMLSerializer()).serializeToString(xhr.responseXML) :\n\
|
||||
null;\n\
|
||||
res.responseText = xhr.responseText;\n\
|
||||
post(e, res);\n\
|
||||
};\n\
|
||||
xhr.onerror = function () {\n\
|
||||
xhr.onerror = function(e) {\n\
|
||||
res.didFail = true;\n\
|
||||
};\n\
|
||||
xhr.onloadend = function (event) {\n\
|
||||
res.status = xhr.status;\n\
|
||||
try {\n\
|
||||
res.statusText = xhr.statusText;\n\
|
||||
} catch (e) {\n\
|
||||
delete(res.statusText);\n\
|
||||
}\n\
|
||||
res.responseXML = xhr.responseXML ?\n\
|
||||
(new XMLSerializer()).serializeToString(xhr.responseXML) :\n\
|
||||
null;\n\
|
||||
res.responseText = xhr.responseText;\n\
|
||||
\n\
|
||||
res.responseHeaders = {};\n\
|
||||
for (responseHeader in req.responseHeaders) {\n\
|
||||
res.responseHeaders[responseHeader] =\n\
|
||||
xhr.getResponseHeader(responseHeader);\n\
|
||||
}\n\
|
||||
\n\
|
||||
post(e, res);\n\
|
||||
}\n\
|
||||
\n\
|
||||
|
|
|
@ -656,7 +656,7 @@ function runTest() {
|
|||
is(res.responseText, "<res>hello pass</res>\n",
|
||||
"wrong responseText in test for " + test.toSource());
|
||||
is(res.events.join(","),
|
||||
"opening,rs1,sending,rs1,loadstart,rs2,rs3,rs4,load",
|
||||
"opening,rs1,sending,rs1,loadstart,rs2,rs3,rs4,load,loadend",
|
||||
"wrong responseText in test for " + test.toSource());
|
||||
}
|
||||
else {
|
||||
|
@ -665,7 +665,7 @@ function runTest() {
|
|||
is(res.responseText, "",
|
||||
"wrong responseText in test for " + test.toSource());
|
||||
is(res.events.join(","),
|
||||
"opening,rs1,sending,rs1,loadstart,rs2,rs4,load",
|
||||
"opening,rs1,sending,rs1,loadstart,rs2,rs4,load,loadend",
|
||||
"wrong responseText in test for " + test.toSource());
|
||||
}
|
||||
if (test.responseHeaders) {
|
||||
|
@ -694,7 +694,7 @@ function runTest() {
|
|||
"wrong responseText in test for " + test.toSource());
|
||||
if (!res.sendThrew) {
|
||||
is(res.events.join(","),
|
||||
"opening,rs1,sending,rs1,loadstart,rs2,rs4,error",
|
||||
"opening,rs1,sending,rs1,loadstart,rs2,rs4,error,loadend",
|
||||
"wrong events in test for " + test.toSource());
|
||||
}
|
||||
is(res.progressEvents, 0,
|
||||
|
@ -822,7 +822,7 @@ function runTest() {
|
|||
is(res.responseText, "<res>hello pass</res>\n",
|
||||
"wrong responseText in test for " + test.toSource());
|
||||
is(res.events.join(","),
|
||||
"opening,rs1,sending,rs1,loadstart,rs2,rs3,rs4,load",
|
||||
"opening,rs1,sending,rs1,loadstart,rs2,rs3,rs4,load,loadend",
|
||||
"wrong responseText in test for " + test.toSource());
|
||||
}
|
||||
else {
|
||||
|
@ -835,7 +835,7 @@ function runTest() {
|
|||
is(res.responseText, "",
|
||||
"wrong responseText in test for " + test.toSource());
|
||||
is(res.events.join(","),
|
||||
"opening,rs1,sending,rs1,loadstart,rs2,rs4,error",
|
||||
"opening,rs1,sending,rs1,loadstart,rs2,rs4,error,loadend",
|
||||
"wrong events in test for " + test.toSource());
|
||||
is(res.progressEvents, 0,
|
||||
"wrong events in test for " + test.toSource());
|
||||
|
@ -1091,7 +1091,7 @@ function runTest() {
|
|||
is(res.responseText, "<res>hello pass</res>\n",
|
||||
"wrong responseText in test for " + test.toSource());
|
||||
is(res.events.join(","),
|
||||
"opening,rs1,sending,rs1,loadstart,rs2,rs3,rs4,load",
|
||||
"opening,rs1,sending,rs1,loadstart,rs2,rs3,rs4,load,loadend",
|
||||
"wrong responseText in test for " + test.toSource());
|
||||
}
|
||||
else {
|
||||
|
@ -1104,7 +1104,7 @@ function runTest() {
|
|||
is(res.responseText, "",
|
||||
"wrong responseText in test for " + test.toSource());
|
||||
is(res.events.join(","),
|
||||
"opening,rs1,sending,rs1,loadstart,rs2,rs4,error",
|
||||
"opening,rs1,sending,rs1,loadstart,rs2,rs4,error,loadend",
|
||||
"wrong events in test for " + test.toSource());
|
||||
is(res.progressEvents, 0,
|
||||
"wrong progressevents in test for " + test.toSource());
|
||||
|
|
|
@ -464,7 +464,7 @@ function runTest() {
|
|||
is(res.responseText, "<res>hello pass</res>\n",
|
||||
"wrong responseText in test for " + testName);
|
||||
is(res.events.join(","),
|
||||
"opening,rs1,sending,rs1,loadstart,rs2,rs3,rs4,load",
|
||||
"opening,rs1,sending,rs1,loadstart,rs2,rs3,rs4,load,loadend",
|
||||
"wrong events in test for " + testName);
|
||||
}
|
||||
else {
|
||||
|
@ -476,15 +476,13 @@ function runTest() {
|
|||
is(res.responseText, "",
|
||||
"wrong responseText in test for " + testName);
|
||||
is(res.events.join(","),
|
||||
"opening,rs1,sending,rs1,loadstart,rs2,rs4,error",
|
||||
"opening,rs1,sending,rs1,loadstart,rs2,rs4,error,loadend",
|
||||
"wrong events in test for " + testName);
|
||||
is(res.progressEvents, 0,
|
||||
"wrong events in test for " + testName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
SimpleTest.finish();
|
||||
|
||||
yield;
|
||||
|
|
|
@ -133,7 +133,7 @@ function runTest() {
|
|||
is(res.responseText, "<res>hello pass</res>\n",
|
||||
"wrong responseText in test for " + allowOrigin);
|
||||
is(res.events.join(","),
|
||||
"opening,rs1,sending,rs1,loadstart,rs2,rs3,rs4,load",
|
||||
"opening,rs1,sending,rs1,loadstart,rs2,rs3,rs4,load,loadend",
|
||||
"wrong responseText in test for " + allowOrigin);
|
||||
}
|
||||
|
||||
|
@ -151,7 +151,7 @@ function runTest() {
|
|||
is(res.statusText, "", "wrong status text for " + allowOrigin);
|
||||
is(res.responseXML, null, "should have no XML for " + allowOrigin);
|
||||
is(res.events.join(","),
|
||||
"opening,rs1,sending,rs1,loadstart,rs2,rs4,error",
|
||||
"opening,rs1,sending,rs1,loadstart,rs2,rs4,error,loadend",
|
||||
"wrong events in test for " + allowOrigin);
|
||||
is(res.progressEvents, 0,
|
||||
"wrong events in test for " + allowOrigin);
|
||||
|
|
|
@ -42,7 +42,6 @@
|
|||
#include "nsIAtom.h"
|
||||
#include "nsIContentViewer.h"
|
||||
#include "mozilla/css/StyleRule.h"
|
||||
#include "nsCSSStruct.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDocumentEncoder.h"
|
||||
#include "nsIDOMHTMLBodyElement.h"
|
||||
|
|
|
@ -43,7 +43,6 @@
|
|||
#include "nsStyleConsts.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsMappedAttributes.h"
|
||||
#include "nsCSSStruct.h"
|
||||
#include "nsRuleData.h"
|
||||
#include "nsIDocument.h"
|
||||
|
||||
|
|
|
@ -974,11 +974,11 @@ nsresult nsHTMLMediaElement::LoadResource(nsIURI* aURI)
|
|||
nsCOMPtr<nsIStreamListener> listener;
|
||||
if (ShouldCheckAllowOrigin()) {
|
||||
listener =
|
||||
new nsCrossSiteListenerProxy(loadListener,
|
||||
NodePrincipal(),
|
||||
channel,
|
||||
PR_FALSE,
|
||||
&rv);
|
||||
new nsCORSListenerProxy(loadListener,
|
||||
NodePrincipal(),
|
||||
channel,
|
||||
PR_FALSE,
|
||||
&rv);
|
||||
} else {
|
||||
rv = nsContentUtils::GetSecurityManager()->
|
||||
CheckLoadURIWithPrincipal(NodePrincipal(),
|
||||
|
|
|
@ -41,7 +41,6 @@
|
|||
#include "nsStyleConsts.h"
|
||||
#include "nsMappedAttributes.h"
|
||||
#include "nsRuleData.h"
|
||||
#include "nsCSSStruct.h"
|
||||
|
||||
class nsHTMLPreElement : public nsGenericHTMLElement,
|
||||
public nsIDOMHTMLPreElement
|
||||
|
|
|
@ -1320,7 +1320,12 @@ nsHTMLDocument::GetElementsByTagName(const nsAString& aTagname,
|
|||
return nsDocument::GetElementsByTagName(aTagname, aReturn);
|
||||
}
|
||||
|
||||
// nsIDOM3Document interface implementation
|
||||
NS_IMETHODIMP
|
||||
nsHTMLDocument::GetInputEncoding(nsAString& aInputEncoding)
|
||||
{
|
||||
return nsDocument::GetInputEncoding(aInputEncoding);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLDocument::GetXmlEncoding(nsAString& aXmlEncoding)
|
||||
{
|
||||
|
@ -1334,7 +1339,7 @@ nsHTMLDocument::GetXmlEncoding(nsAString& aXmlEncoding)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLDocument::GetXmlStandalone(PRBool *aXmlStandalone)
|
||||
nsHTMLDocument::GetXmlStandalone(PRBool* aXmlStandalone)
|
||||
{
|
||||
if (!IsHTML()) {
|
||||
return nsDocument::GetXmlStandalone(aXmlStandalone);
|
||||
|
@ -1355,7 +1360,6 @@ nsHTMLDocument::SetXmlStandalone(PRBool aXmlStandalone)
|
|||
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLDocument::GetXmlVersion(nsAString& aXmlVersion)
|
||||
{
|
||||
|
@ -1378,6 +1382,57 @@ nsHTMLDocument::SetXmlVersion(const nsAString& aXmlVersion)
|
|||
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLDocument::GetStrictErrorChecking(PRBool* aStrictErrorChecking)
|
||||
{
|
||||
return nsDocument::GetStrictErrorChecking(aStrictErrorChecking);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLDocument::SetStrictErrorChecking(PRBool aStrictErrorChecking)
|
||||
{
|
||||
return nsDocument::SetStrictErrorChecking(aStrictErrorChecking);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLDocument::GetDocumentURI(nsAString& aDocumentURI)
|
||||
{
|
||||
return nsDocument::GetDocumentURI(aDocumentURI);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLDocument::SetDocumentURI(const nsAString& aDocumentURI)
|
||||
{
|
||||
return nsDocument::SetDocumentURI(aDocumentURI);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLDocument::AdoptNode(nsIDOMNode* aSource, nsIDOMNode** aRetval)
|
||||
{
|
||||
return nsDocument::AdoptNode(aSource, aRetval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLDocument::GetDomConfig(nsIDOMDOMConfiguration** aDomConfig)
|
||||
{
|
||||
return nsDocument::GetDomConfig(aDomConfig);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLDocument::NormalizeDocument()
|
||||
{
|
||||
return nsDocument::NormalizeDocument();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLDocument::RenameNode(nsIDOMNode* aNode,
|
||||
const nsAString& aNamespaceURI,
|
||||
const nsAString& aQualifiedName,
|
||||
nsIDOMNode** aRetval)
|
||||
{
|
||||
return nsDocument::RenameNode(aNode, aNamespaceURI, aQualifiedName, aRetval);
|
||||
}
|
||||
|
||||
//
|
||||
// nsIDOMHTMLDocument interface implementation
|
||||
//
|
||||
|
|
|
@ -74,6 +74,8 @@ class nsHTMLDocument : public nsDocument,
|
|||
public nsIDOMNSHTMLDocument
|
||||
{
|
||||
public:
|
||||
using nsDocument::SetDocumentURI;
|
||||
|
||||
nsHTMLDocument();
|
||||
virtual nsresult Init();
|
||||
|
||||
|
@ -123,13 +125,6 @@ public:
|
|||
// nsIDOMDocument interface
|
||||
NS_DECL_NSIDOMDOCUMENT
|
||||
|
||||
// nsIDOM3Document interface
|
||||
NS_IMETHOD GetXmlEncoding(nsAString& aXmlVersion);
|
||||
NS_IMETHOD GetXmlStandalone(PRBool *aXmlStandalone);
|
||||
NS_IMETHOD SetXmlStandalone(PRBool aXmlStandalone);
|
||||
NS_IMETHOD GetXmlVersion(nsAString& aXmlVersion);
|
||||
NS_IMETHOD SetXmlVersion(const nsAString& aXmlVersion);
|
||||
|
||||
// nsIDOMNode interface
|
||||
NS_FORWARD_NSIDOMNODE(nsDocument::)
|
||||
|
||||
|
|
|
@ -161,8 +161,8 @@ nsMediaChannelStream::OnStartRequest(nsIRequest* aRequest)
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (element->ShouldCheckAllowOrigin()) {
|
||||
// If the request was cancelled by nsCrossSiteListenerProxy due to failing
|
||||
// the Access Control check, send an error through to the media element.
|
||||
// If the request was cancelled by nsCORSListenerProxy due to failing
|
||||
// the CORS security check, send an error through to the media element.
|
||||
if (status == NS_ERROR_DOM_BAD_URI) {
|
||||
mDecoder->NetworkError();
|
||||
return NS_ERROR_DOM_BAD_URI;
|
||||
|
@ -457,12 +457,12 @@ nsresult nsMediaChannelStream::OpenChannel(nsIStreamListener** aStreamListener)
|
|||
NS_ENSURE_TRUE(element, NS_ERROR_FAILURE);
|
||||
if (element->ShouldCheckAllowOrigin()) {
|
||||
nsresult rv;
|
||||
nsCrossSiteListenerProxy* crossSiteListener =
|
||||
new nsCrossSiteListenerProxy(mListener,
|
||||
element->NodePrincipal(),
|
||||
mChannel,
|
||||
PR_FALSE,
|
||||
&rv);
|
||||
nsCORSListenerProxy* crossSiteListener =
|
||||
new nsCORSListenerProxy(mListener,
|
||||
element->NodePrincipal(),
|
||||
mChannel,
|
||||
PR_FALSE,
|
||||
&rv);
|
||||
listener = crossSiteListener;
|
||||
NS_ENSURE_TRUE(crossSiteListener, NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
|
|
@ -79,7 +79,10 @@ nsOggCodecState::nsOggCodecState(ogg_page* aBosPage) :
|
|||
|
||||
nsOggCodecState::~nsOggCodecState() {
|
||||
MOZ_COUNT_DTOR(nsOggCodecState);
|
||||
int ret = ogg_stream_clear(&mState);
|
||||
#ifdef DEBUG
|
||||
int ret =
|
||||
#endif
|
||||
ogg_stream_clear(&mState);
|
||||
NS_ASSERTION(ret == 0, "ogg_stream_clear failed");
|
||||
}
|
||||
|
||||
|
|
|
@ -204,7 +204,11 @@ nsresult nsOggReader::ReadMetadata(nsVideoInfo* aInfo)
|
|||
if (ogg_page_bos(&page)) {
|
||||
NS_ASSERTION(!readAllBOS, "We shouldn't encounter another BOS page");
|
||||
codecState = nsOggCodecState::Create(&page);
|
||||
PRBool r = mCodecStates.Put(serial, codecState);
|
||||
|
||||
#ifdef DEBUG
|
||||
PRBool r =
|
||||
#endif
|
||||
mCodecStates.Put(serial, codecState);
|
||||
NS_ASSERTION(r, "Failed to insert into mCodecStates");
|
||||
bitstreams.AppendElement(codecState);
|
||||
mKnownStreams.AppendElement(serial);
|
||||
|
|
|
@ -511,8 +511,7 @@ nsSMILTimedElement::DoSampleAt(nsSMILTime aContainerTime, PRBool aEndOnly)
|
|||
case STATE_STARTUP:
|
||||
{
|
||||
nsSMILInterval firstInterval;
|
||||
mElementState =
|
||||
NS_SUCCEEDED(GetNextInterval(nsnull, nsnull, firstInterval))
|
||||
mElementState = GetNextInterval(nsnull, nsnull, firstInterval)
|
||||
? STATE_WAITING
|
||||
: STATE_POSTACTIVE;
|
||||
stateChanged = PR_TRUE;
|
||||
|
@ -556,8 +555,7 @@ nsSMILTimedElement::DoSampleAt(nsSMILTime aContainerTime, PRBool aEndOnly)
|
|||
|
||||
if (mCurrentInterval->End()->Time() <= sampleTime) {
|
||||
nsSMILInterval newInterval;
|
||||
mElementState =
|
||||
NS_SUCCEEDED(GetNextInterval(mCurrentInterval, nsnull, newInterval))
|
||||
mElementState = GetNextInterval(mCurrentInterval, nsnull, newInterval)
|
||||
? STATE_WAITING
|
||||
: STATE_POSTACTIVE;
|
||||
if (mClient) {
|
||||
|
@ -1483,17 +1481,17 @@ nsSMILTimedElement::FilterInstanceTimes(InstanceTimeList& aList)
|
|||
// See:
|
||||
// http://www.w3.org/TR/2001/REC-smil-animation-20010904/#Timing-BeginEnd-LC-Start
|
||||
//
|
||||
nsresult
|
||||
PRBool
|
||||
nsSMILTimedElement::GetNextInterval(const nsSMILInterval* aPrevInterval,
|
||||
const nsSMILInstanceTime* aFixedBeginTime,
|
||||
nsSMILInterval& aResult) const
|
||||
{
|
||||
NS_ABORT_IF_FALSE(!aFixedBeginTime || aFixedBeginTime->Time().IsResolved(),
|
||||
"Unresolved begin time specified for interval start");
|
||||
static nsSMILTimeValue zeroTime(0L);
|
||||
static const nsSMILTimeValue zeroTime(0L);
|
||||
|
||||
if (mRestartMode == RESTART_NEVER && aPrevInterval)
|
||||
return NS_ERROR_FAILURE;
|
||||
return PR_FALSE;
|
||||
|
||||
// Calc starting point
|
||||
nsSMILTimeValue beginAfter;
|
||||
|
@ -1516,8 +1514,9 @@ nsSMILTimedElement::GetNextInterval(const nsSMILInterval* aPrevInterval,
|
|||
while (PR_TRUE) {
|
||||
// Calculate begin time
|
||||
if (aFixedBeginTime) {
|
||||
if (aFixedBeginTime->Time() < beginAfter)
|
||||
return NS_ERROR_FAILURE;
|
||||
if (aFixedBeginTime->Time() < beginAfter) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
// our ref-counting is not const-correct
|
||||
tempBegin = const_cast<nsSMILInstanceTime*>(aFixedBeginTime);
|
||||
} else if ((!mAnimationElement ||
|
||||
|
@ -1527,8 +1526,9 @@ nsSMILTimedElement::GetNextInterval(const nsSMILInterval* aPrevInterval,
|
|||
} else {
|
||||
PRInt32 beginPos = 0;
|
||||
tempBegin = GetNextGreaterOrEqual(mBeginInstances, beginAfter, beginPos);
|
||||
if (!tempBegin || !tempBegin->Time().IsResolved())
|
||||
return NS_ERROR_FAILURE;
|
||||
if (!tempBegin || !tempBegin->Time().IsResolved()) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
NS_ABORT_IF_FALSE(tempBegin && tempBegin->Time().IsResolved() &&
|
||||
tempBegin->Time() >= beginAfter,
|
||||
|
@ -1560,7 +1560,7 @@ nsSMILTimedElement::GetNextInterval(const nsSMILInterval* aPrevInterval,
|
|||
mEndInstances.IsEmpty() ||
|
||||
EndHasEventConditions();
|
||||
if (!tempEnd && !openEndedIntervalOk)
|
||||
return NS_ERROR_FAILURE; // Bad interval
|
||||
return PR_FALSE; // Bad interval
|
||||
|
||||
nsSMILTimeValue intervalEnd = tempEnd
|
||||
? tempEnd->Time() : nsSMILTimeValue();
|
||||
|
@ -1588,19 +1588,19 @@ nsSMILTimedElement::GetNextInterval(const nsSMILInterval* aPrevInterval,
|
|||
if (tempEnd->Time() > zeroTime ||
|
||||
(tempBegin->Time() == zeroTime && tempEnd->Time() == zeroTime)) {
|
||||
aResult.Set(*tempBegin, *tempEnd);
|
||||
return NS_OK;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
if (mRestartMode == RESTART_NEVER) {
|
||||
// tempEnd <= 0 so we're going to loop which effectively means restarting
|
||||
return NS_ERROR_FAILURE;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
beginAfter = tempEnd->Time();
|
||||
}
|
||||
NS_NOTREACHED("Hmm... we really shouldn't be here");
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsSMILInstanceTime*
|
||||
|
@ -1803,10 +1803,7 @@ nsSMILTimedElement::UpdateCurrentInterval(PRBool aForceChangeNotice)
|
|||
? mCurrentInterval->Begin()
|
||||
: nsnull;
|
||||
nsSMILInterval updatedInterval;
|
||||
nsresult rv =
|
||||
GetNextInterval(GetPreviousInterval(), beginTime, updatedInterval);
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (GetNextInterval(GetPreviousInterval(), beginTime, updatedInterval)) {
|
||||
|
||||
if (mElementState == STATE_POSTACTIVE) {
|
||||
|
||||
|
|
|
@ -475,12 +475,11 @@ protected:
|
|||
* should be updated such as when the animation is in
|
||||
* the ACTIVE state. May be nsnull.
|
||||
* @param[out] aResult The next interval. Will be unchanged if no suitable
|
||||
* interval was found (in which case NS_ERROR_FAILURE
|
||||
* will be returned).
|
||||
* @return NS_OK if a suitable interval was found, NS_ERROR_FAILURE
|
||||
* otherwise.
|
||||
* interval was found (in which case PR_FALSE will be
|
||||
* returned).
|
||||
* @return PR_TRUE if a suitable interval was found, PR_FALSE otherwise.
|
||||
*/
|
||||
nsresult GetNextInterval(const nsSMILInterval* aPrevInterval,
|
||||
PRBool GetNextInterval(const nsSMILInterval* aPrevInterval,
|
||||
const nsSMILInstanceTime* aFixedBeginTime,
|
||||
nsSMILInterval& aResult) const;
|
||||
nsSMILInstanceTime* GetNextGreater(const InstanceTimeList& aList,
|
||||
|
|
|
@ -45,7 +45,9 @@
|
|||
class nsSVGDocument : public nsXMLDocument,
|
||||
public nsIDOMSVGDocument
|
||||
{
|
||||
public:
|
||||
public:
|
||||
using nsDocument::GetElementById;
|
||||
using nsDocument::SetDocumentURI;
|
||||
nsSVGDocument();
|
||||
virtual ~nsSVGDocument();
|
||||
|
||||
|
|
|
@ -522,8 +522,8 @@ txCompileObserver::startLoad(nsIURI* aUri, txStylesheetCompiler* aCompiler,
|
|||
|
||||
// Always install in case of redirects
|
||||
nsCOMPtr<nsIStreamListener> listener =
|
||||
new nsCrossSiteListenerProxy(sink, aReferrerPrincipal, channel,
|
||||
PR_FALSE, &rv);
|
||||
new nsCORSListenerProxy(sink, aReferrerPrincipal, channel,
|
||||
PR_FALSE, &rv);
|
||||
NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
|
|
|
@ -217,8 +217,8 @@ nsXULTemplateQueryProcessorXML::GetDatasource(nsIArray* aDataSources,
|
|||
nsCOMPtr<nsPIDOMWindow> owner = do_QueryInterface(scriptObject);
|
||||
req->Init(docPrincipal, context, owner, nsnull);
|
||||
|
||||
rv = req->OpenRequest(NS_LITERAL_CSTRING("GET"), uriStr, PR_TRUE,
|
||||
EmptyString(), EmptyString());
|
||||
rv = req->Open(NS_LITERAL_CSTRING("GET"), uriStr, PR_TRUE,
|
||||
EmptyString(), EmptyString());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(req));
|
||||
|
|
|
@ -53,7 +53,6 @@
|
|||
#include "mozilla/dom/Element.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOM3Document.h"
|
||||
#include "nsIDOMNSDocument.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIDOMStorageObsolete.h"
|
||||
|
|
|
@ -80,7 +80,6 @@
|
|||
#include "nsIAttribute.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOM3Document.h"
|
||||
#include "nsIDOMXMLDocument.h"
|
||||
#include "nsIDOMNSDocument.h"
|
||||
#include "nsIDOMEvent.h"
|
||||
|
@ -2194,7 +2193,6 @@ nsDOMClassInfo::WrapNativeParent(JSContext *cx, JSObject *scope,
|
|||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMDocumentXBL) \
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSEventTarget) \
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget) \
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOM3Document) \
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOM3Node) \
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMXPathEvaluator) \
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMNodeSelector)
|
||||
|
|
|
@ -108,7 +108,6 @@
|
|||
#include "nsIDOMCrypto.h"
|
||||
#endif
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOM3Document.h"
|
||||
#include "nsIDOMNSDocument.h"
|
||||
#include "nsIDOMDocumentView.h"
|
||||
#include "nsIDOMElement.h"
|
||||
|
@ -4408,19 +4407,8 @@ nsGlobalWindow::SetFullScreen(PRBool aFullScreen)
|
|||
mFullScreen = aFullScreen;
|
||||
|
||||
nsCOMPtr<nsIWidget> widget = GetMainWidget();
|
||||
if (widget) {
|
||||
PRBool visible;
|
||||
widget->IsVisible(visible);
|
||||
if (visible && aFullScreen)
|
||||
widget->Show(PR_FALSE);
|
||||
if (widget)
|
||||
widget->MakeFullScreen(aFullScreen);
|
||||
if (visible && aFullScreen) {
|
||||
widget->Show(PR_TRUE);
|
||||
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
|
||||
if (fm)
|
||||
fm->SetActiveWindow(this);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -7967,9 +7955,7 @@ nsGlobalWindow::GetSessionStorage(nsIDOMStorage ** aSessionStorage)
|
|||
*aSessionStorage = nsnull;
|
||||
|
||||
nsString documentURI;
|
||||
nsCOMPtr<nsIDOM3Document> document3 = do_QueryInterface(mDoc);
|
||||
if (document3)
|
||||
document3->GetDocumentURI(documentURI);
|
||||
mDocument->GetDocumentURI(documentURI);
|
||||
|
||||
nsresult rv = docShell->GetSessionStorageForPrincipal(principal,
|
||||
documentURI,
|
||||
|
@ -8053,9 +8039,7 @@ nsGlobalWindow::GetLocalStorage(nsIDOMStorage ** aLocalStorage)
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsString documentURI;
|
||||
nsCOMPtr<nsIDOM3Document> document3 = do_QueryInterface(mDoc);
|
||||
if (document3)
|
||||
document3->GetDocumentURI(documentURI);
|
||||
mDocument->GetDocumentURI(documentURI);
|
||||
|
||||
rv = storageManager->GetLocalStorageForPrincipal(principal,
|
||||
documentURI,
|
||||
|
|
|
@ -67,7 +67,6 @@ SDK_XPIDLSRCS = \
|
|||
nsIDOMText.idl \
|
||||
$(NULL)
|
||||
XPIDLSRCS = \
|
||||
nsIDOM3Document.idl \
|
||||
nsIDOM3Node.idl \
|
||||
nsIDOM3Text.idl \
|
||||
nsIDOM3TypeInfo.idl \
|
||||
|
|
|
@ -1,75 +0,0 @@
|
|||
/* ***** 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
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Christopher A. Aillon <christopher@aillon.com> (Original Author)
|
||||
*
|
||||
* 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 ***** */
|
||||
|
||||
#include "domstubs.idl"
|
||||
|
||||
interface nsIDOMDOMConfiguration;
|
||||
|
||||
/**
|
||||
* For more information on this interface, please see
|
||||
* http://www.w3.org/TR/DOM-Level-3-Core/
|
||||
*/
|
||||
[scriptable, uuid(c0568f22-b9d5-427a-9642-b6a797edc5cd)]
|
||||
interface nsIDOM3Document : nsISupports
|
||||
{
|
||||
// Introduced in DOM Level 3:
|
||||
readonly attribute DOMString inputEncoding;
|
||||
// Introduced in DOM Level 3:
|
||||
readonly attribute DOMString xmlEncoding;
|
||||
// Introduced in DOM Level 3:
|
||||
attribute boolean xmlStandalone;
|
||||
// raises(DOMException) on setting
|
||||
// Introduced in DOM Level 3:
|
||||
attribute DOMString xmlVersion;
|
||||
// raises(DOMException) on setting
|
||||
// Introduced in DOM Level 3:
|
||||
attribute boolean strictErrorChecking;
|
||||
// Introduced in DOM Level 3:
|
||||
attribute DOMString documentURI;
|
||||
// Introduced in DOM Level 3:
|
||||
nsIDOMNode adoptNode(in nsIDOMNode source)
|
||||
raises(DOMException);
|
||||
// Introduced in DOM Level 3:
|
||||
readonly attribute nsIDOMDOMConfiguration domConfig;
|
||||
// Introduced in DOM Level 3:
|
||||
void normalizeDocument();
|
||||
// Introduced in DOM Level 3:
|
||||
nsIDOMNode renameNode(in nsIDOMNode node,
|
||||
in DOMString namespaceURI,
|
||||
in DOMString qualifiedName)
|
||||
raises(DOMException);
|
||||
};
|
|
@ -39,6 +39,8 @@
|
|||
|
||||
#include "nsIDOMNode.idl"
|
||||
|
||||
interface nsIDOMDOMConfiguration;
|
||||
|
||||
/**
|
||||
* The nsIDOMDocument interface represents the entire HTML or XML document.
|
||||
* Conceptually, it is the root of the document tree, and provides the
|
||||
|
@ -49,10 +51,10 @@
|
|||
* objects.
|
||||
*
|
||||
* For more information on this interface please see
|
||||
* http://www.w3.org/TR/DOM-Level-2-Core/
|
||||
* http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html
|
||||
*/
|
||||
|
||||
[scriptable, uuid(a6cf9075-15b3-11d2-932e-00805f8add32)]
|
||||
[scriptable, uuid(fde1a53b-cf60-4997-a0b2-1aa1dc55492e)]
|
||||
interface nsIDOMDocument : nsIDOMNode
|
||||
{
|
||||
readonly attribute nsIDOMDocumentType doctype;
|
||||
|
@ -91,4 +93,30 @@ interface nsIDOMDocument : nsIDOMNode
|
|||
in DOMString localName);
|
||||
// Introduced in DOM Level 2:
|
||||
nsIDOMElement getElementById(in DOMString elementId);
|
||||
// Introduced in DOM Level 3:
|
||||
readonly attribute DOMString inputEncoding;
|
||||
// Introduced in DOM Level 3:
|
||||
readonly attribute DOMString xmlEncoding;
|
||||
// Introduced in DOM Level 3:
|
||||
attribute boolean xmlStandalone;
|
||||
// raises(DOMException) on setting
|
||||
// Introduced in DOM Level 3:
|
||||
attribute DOMString xmlVersion;
|
||||
// raises(DOMException) on setting
|
||||
// Introduced in DOM Level 3:
|
||||
attribute boolean strictErrorChecking;
|
||||
// Introduced in DOM Level 3:
|
||||
attribute DOMString documentURI;
|
||||
// Introduced in DOM Level 3:
|
||||
nsIDOMNode adoptNode(in nsIDOMNode source)
|
||||
raises(DOMException);
|
||||
// Introduced in DOM Level 3:
|
||||
readonly attribute nsIDOMDOMConfiguration domConfig;
|
||||
// Introduced in DOM Level 3:
|
||||
void normalizeDocument();
|
||||
// Introduced in DOM Level 3:
|
||||
nsIDOMNode renameNode(in nsIDOMNode node,
|
||||
in DOMString namespaceURI,
|
||||
in DOMString qualifiedName)
|
||||
raises(DOMException);
|
||||
};
|
||||
|
|
|
@ -639,25 +639,6 @@ nsDOMWorkerXHR::GetResponseHeader(const nsACString& aHeader,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::OpenRequest(const nsACString& aMethod,
|
||||
const nsACString& aUrl,
|
||||
PRBool aAsync,
|
||||
const nsAString& aUser,
|
||||
const nsAString& aPassword)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
nsresult rv = mXHRProxy->OpenRequest(aMethod, aUrl, aAsync, aUser, aPassword);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::Open(const nsACString& aMethod, const nsACString& aUrl,
|
||||
PRBool aAsync, const nsAString& aUser,
|
||||
|
@ -673,7 +654,10 @@ nsDOMWorkerXHR::Open(const nsACString& aMethod, const nsACString& aUrl,
|
|||
aAsync = PR_TRUE;
|
||||
}
|
||||
|
||||
return OpenRequest(aMethod, aUrl, aAsync, aUser, aPassword);
|
||||
nsresult rv = mXHRProxy->Open(aMethod, aUrl, aAsync, aUser, aPassword);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -136,17 +136,17 @@ namespace nsDOMWorkerProxiedXHRFunctions
|
|||
}
|
||||
};
|
||||
|
||||
class OpenRequest : public SyncEventCapturingRunnable
|
||||
class Open : public SyncEventCapturingRunnable
|
||||
{
|
||||
public:
|
||||
OpenRequest(const nsACString& aMethod, const nsACString& aUrl,
|
||||
PRBool aAsync, const nsAString& aUser,
|
||||
const nsAString& aPassword)
|
||||
Open(const nsACString& aMethod, const nsACString& aUrl,
|
||||
PRBool aAsync, const nsAString& aUser,
|
||||
const nsAString& aPassword)
|
||||
: mMethod(aMethod), mUrl(aUrl), mAsync(aAsync), mUser(aUser),
|
||||
mPassword(aPassword) { }
|
||||
|
||||
virtual nsresult RunInternal() {
|
||||
return mXHR->OpenRequest(mMethod, mUrl, mAsync, mUser, mPassword);
|
||||
return mXHR->Open(mMethod, mUrl, mAsync, mUser, mPassword);
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
@ -683,7 +683,7 @@ nsDOMWorkerXHRProxy::DispatchPrematureAbortEvents(PRUint32 aType,
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerXHRProxy::MaybeDispatchPrematureAbortEvents(PRBool aFromOpenRequest)
|
||||
nsDOMWorkerXHRProxy::MaybeDispatchPrematureAbortEvents(PRBool aFromOpen)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
|
@ -698,7 +698,7 @@ nsDOMWorkerXHRProxy::MaybeDispatchPrematureAbortEvents(PRBool aFromOpenRequest)
|
|||
nsnull);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (aFromOpenRequest) {
|
||||
if (aFromOpen) {
|
||||
rv = DispatchPrematureAbortEvents(LISTENER_TYPE_ABORT, target,
|
||||
mDownloadProgressInfo);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -866,17 +866,17 @@ nsDOMWorkerXHRProxy::HandleEventRunnable(nsIRunnable* aRunnable)
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerXHRProxy::OpenRequest(const nsACString& aMethod,
|
||||
const nsACString& aUrl,
|
||||
PRBool aAsync,
|
||||
const nsAString& aUser,
|
||||
const nsAString& aPassword)
|
||||
nsDOMWorkerXHRProxy::Open(const nsACString& aMethod,
|
||||
const nsACString& aUrl,
|
||||
PRBool aAsync,
|
||||
const nsAString& aUser,
|
||||
const nsAString& aPassword)
|
||||
{
|
||||
if (!NS_IsMainThread()) {
|
||||
mSyncRequest = !aAsync;
|
||||
|
||||
// Always do async behind the scenes!
|
||||
RUN_PROXIED_FUNCTION(OpenRequest,
|
||||
RUN_PROXIED_FUNCTION(Open,
|
||||
(aMethod, aUrl, PR_TRUE, aUser, aPassword));
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -888,12 +888,12 @@ nsDOMWorkerXHRProxy::OpenRequest(const nsACString& aMethod,
|
|||
nsresult rv = MaybeDispatchPrematureAbortEvents(PR_TRUE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mXHR->OpenRequest(aMethod, aUrl, aAsync, aUser, aPassword);
|
||||
rv = mXHR->Open(aMethod, aUrl, aAsync, aUser, aPassword);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Do this after OpenRequest is called so that we will continue to run events
|
||||
// from the old channel if OpenRequest fails. Any events generated by the
|
||||
// OpenRequest method will always run regardless of channel ID.
|
||||
// Do this after Open is called so that we will continue to run events
|
||||
// from the old channel if Open fails. Any events generated by the
|
||||
// Open method will always run regardless of channel ID.
|
||||
mChannelID++;
|
||||
|
||||
return NS_OK;
|
||||
|
|
|
@ -92,11 +92,11 @@ public:
|
|||
|
||||
nsIXMLHttpRequest* GetXMLHttpRequest();
|
||||
|
||||
nsresult OpenRequest(const nsACString& aMethod,
|
||||
const nsACString& aUrl,
|
||||
PRBool aAsync,
|
||||
const nsAString& aUser,
|
||||
const nsAString& aPassword);
|
||||
nsresult Open(const nsACString& aMethod,
|
||||
const nsACString& aUrl,
|
||||
PRBool aAsync,
|
||||
const nsAString& aUser,
|
||||
const nsAString& aPassword);
|
||||
|
||||
nsresult Abort();
|
||||
|
||||
|
|
|
@ -178,13 +178,8 @@ GPSDProvider.prototype = {
|
|||
watch: function(c) {
|
||||
LOG("watch called\n");
|
||||
try {
|
||||
// Turn GPSD buffer on, results in smoother data points which I think we want.
|
||||
// Required due to the way that different data arrives in different NMEA sentences.
|
||||
var bufferOption = "J=1\n";
|
||||
this.outputStream.write(bufferOption, bufferOption.length);
|
||||
|
||||
// Go into "watcher" mode
|
||||
var mode = "w\n";
|
||||
var mode = '?WATCH={"enable":true,"json":true}';
|
||||
this.outputStream.write(mode, mode.length);
|
||||
} catch (e) { return; }
|
||||
|
||||
|
@ -196,54 +191,57 @@ GPSDProvider.prototype = {
|
|||
var sInputStream = Cc["@mozilla.org/scriptableinputstream;1"].createInstance(Ci.nsIScriptableInputStream);
|
||||
sInputStream.init(inputStream);
|
||||
|
||||
var s = sInputStream.read(count);
|
||||
var responseSentence = sInputStream.read(count);
|
||||
|
||||
var response = s.split('=');
|
||||
var response = null;
|
||||
try {
|
||||
response = JSON.parse(responseSentence);
|
||||
} catch (e) { return; }
|
||||
|
||||
var header = response[0];
|
||||
var info = response[1];
|
||||
|
||||
// is this location information?
|
||||
if (header != 'GPSD,O') {
|
||||
// don't do anything
|
||||
// is the right kind of sentence?
|
||||
if (response.class != 'TPV') {
|
||||
//don't do anything
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// is there a fix?
|
||||
if (info == '?') {
|
||||
if (response.mode == '1') {
|
||||
// don't do anything
|
||||
return;
|
||||
}
|
||||
|
||||
// get the info from the string
|
||||
var fields = info.split(' ');
|
||||
|
||||
// we'll only use RMC data as it seems to make sense
|
||||
if (fields[0] != 'RMC') {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG("Got info: " + info);
|
||||
|
||||
for (var i = 0; i < fields.length; i++) {
|
||||
if (fields[i] == '?') {
|
||||
fields[i] = null;
|
||||
}
|
||||
}
|
||||
LOG("Got info: " + responseSentence);
|
||||
|
||||
// The API requires these values, if one is missing
|
||||
// we return without updating the position.
|
||||
if (response.time && response.lat && response.lon
|
||||
&& response.epx && response.epy) {
|
||||
var timestamp = response.time; // UTC
|
||||
var latitude = response.lat; // degrees
|
||||
var longitude = response.lon; // degrees
|
||||
var horizontalError = Math.max(response.epx,response.epy); } // meters
|
||||
else { return; }
|
||||
|
||||
var timestamp = fields[1]; // UTC
|
||||
var timeError = fields[2]; // seconds
|
||||
var latitude = fields[3]; // degrees
|
||||
var longitude = fields[4]; // degrees
|
||||
var altitude = fields[5]; // meters
|
||||
var horizontalError = fields[6]; // meters
|
||||
var verticalError = fields[7]; // meters
|
||||
var course = fields[8]; // degrees;
|
||||
var speed = fields[9]; // meters/sec maybe knots depending on GPSD version TODO: figure this out
|
||||
// Altitude is optional, but if it's present, so must be vertical precision.
|
||||
var altitude = null;
|
||||
var verticalError = null;
|
||||
if (response.alt && response.epv) {
|
||||
altitude = response.alt; // meters
|
||||
verticalError = response.epv; // meters
|
||||
}
|
||||
|
||||
var speed = null;
|
||||
if (response.speed) { var speed = response.speed; } // meters/sec
|
||||
|
||||
var course = null;
|
||||
if (response.track) { var course = response.track; } // degrees
|
||||
|
||||
var geoPos = new GeoPositionObject(latitude, longitude, altitude, horizontalError, verticalError, course, speed, timestamp);
|
||||
|
||||
c.update(geoPos);
|
||||
LOG("Position updated:" + timestamp + "," + latitude + "," + longitude + ","
|
||||
+ horizontalError + "," + altitude + "," + verticalError + "," + course
|
||||
+ "," + speed);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -39,333 +39,6 @@
|
|||
#include "nsIServiceManager.h"
|
||||
#include "windows.h"
|
||||
|
||||
#ifdef WINCE_WINDOWS_MOBILE
|
||||
|
||||
////////////////////////////
|
||||
// HTC
|
||||
////////////////////////////
|
||||
|
||||
|
||||
typedef struct _SENSORDATA
|
||||
{
|
||||
SHORT TiltX; // From -1000 to 1000 (about), 0 is flat
|
||||
SHORT TiltY; // From -1000 to 1000 (about), 0 is flat
|
||||
SHORT Orientation; // From -1000 to 1000 (about)
|
||||
|
||||
WORD Unknown1; // Always zero
|
||||
DWORD AngleY; // From 0 to 359
|
||||
DWORD AngleX; // From 0 to 359
|
||||
DWORD Unknown2; // Bit field?
|
||||
} SENSORDATA, *PSENSORDATA;
|
||||
|
||||
typedef HANDLE (WINAPI * HTCSensorOpen)(DWORD);
|
||||
typedef void (WINAPI * HTCSensorClose)(HANDLE);
|
||||
typedef DWORD (WINAPI * HTCSensorGetDataOutput)(HANDLE, PSENSORDATA);
|
||||
|
||||
HTCSensorOpen gHTCSensorOpen = nsnull;
|
||||
HTCSensorClose gHTCSensorClose = nsnull;
|
||||
HTCSensorGetDataOutput gHTCSensorGetDataOutput = nsnull;
|
||||
|
||||
class HTCSensor : public Sensor
|
||||
{
|
||||
public:
|
||||
HTCSensor();
|
||||
~HTCSensor();
|
||||
PRBool Startup();
|
||||
void Shutdown();
|
||||
void GetValues(double *x, double *y, double *z);
|
||||
private:
|
||||
HMODULE mLibrary;
|
||||
HANDLE mHTCHandle;
|
||||
};
|
||||
|
||||
HTCSensor::HTCSensor()
|
||||
{
|
||||
}
|
||||
|
||||
HTCSensor::~HTCSensor()
|
||||
{
|
||||
}
|
||||
|
||||
PRBool
|
||||
HTCSensor::Startup()
|
||||
{
|
||||
HMODULE hSensorLib = LoadLibraryW(L"HTCSensorSDK.dll");
|
||||
|
||||
if (!hSensorLib)
|
||||
return PR_FALSE;
|
||||
|
||||
gHTCSensorOpen = (HTCSensorOpen) GetProcAddressW(hSensorLib, L"HTCSensorOpen");
|
||||
gHTCSensorClose = (HTCSensorClose) GetProcAddressW(hSensorLib, L"HTCSensorClose");
|
||||
gHTCSensorGetDataOutput = (HTCSensorGetDataOutput) GetProcAddressW(hSensorLib,
|
||||
L"HTCSensorGetDataOutput");
|
||||
|
||||
if (gHTCSensorOpen != nsnull && gHTCSensorClose != nsnull &&
|
||||
gHTCSensorGetDataOutput != nsnull) {
|
||||
mHTCHandle = gHTCSensorOpen(1);
|
||||
if (mHTCHandle)
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
FreeLibrary(hSensorLib);
|
||||
mLibrary = nsnull;
|
||||
gHTCSensorOpen = nsnull;
|
||||
gHTCSensorClose = nsnull;
|
||||
gHTCSensorGetDataOutput = nsnull;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
HTCSensor::Shutdown()
|
||||
{
|
||||
NS_ASSERTION(mHTCHandle, "mHTCHandle should not be null at shutdown!");
|
||||
gHTCSensorClose(mHTCHandle);
|
||||
|
||||
NS_ASSERTION(mLibrary, "Shutdown called when mLibrary is null?");
|
||||
FreeLibrary(mLibrary);
|
||||
mLibrary = nsnull;
|
||||
gHTCSensorOpen = nsnull;
|
||||
gHTCSensorClose = nsnull;
|
||||
gHTCSensorGetDataOutput = nsnull;
|
||||
}
|
||||
|
||||
void
|
||||
HTCSensor::GetValues(double *x, double *y, double *z)
|
||||
{
|
||||
if (!mHTCHandle)
|
||||
return;
|
||||
|
||||
static const double htcScalingFactor = 1.0 / 1000.0 * 9.8;
|
||||
|
||||
SENSORDATA sd;
|
||||
gHTCSensorGetDataOutput(mHTCHandle, &sd);
|
||||
|
||||
*x = ((double)sd.TiltX) / 980 ;
|
||||
*y = ((double)sd.TiltY) / 980 ;
|
||||
*z = ((double)sd.Orientation) / 1000;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////
|
||||
// Samsung
|
||||
////////////////////////////
|
||||
|
||||
/**
|
||||
* The result of an SMI SDK function call.
|
||||
*/
|
||||
typedef UINT SMI_RESULT;
|
||||
|
||||
/**
|
||||
* Common result codes.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
SMI_SUCCESS = 0x00000000,
|
||||
SMI_ERROR_UNKNOWN = 0x00000001,
|
||||
SMI_ERROR_DEVICE_NOT_FOUND = 0x00000002,
|
||||
SMI_ERROR_DEVICE_DISABLED = 0x00000003,
|
||||
SMI_ERROR_PERMISSION_DENIED = 0x00000004,
|
||||
SMI_ERROR_INVALID_PARAMETER = 0x00000005,
|
||||
SMI_ERROR_CANNOT_ACTIVATE_SERVER= 0x00000006,
|
||||
SMI_ACCELEROMETER_RESULT_BASE = 0x10010000,
|
||||
SMI_HAPTICS_RESULT_BASE = 0x10020000,
|
||||
SMI_LED_RESULT_BASE = 0x10030000
|
||||
} SmiResultCode;
|
||||
|
||||
/**
|
||||
* Accelerometer vector data.
|
||||
*
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
FLOAT x; /**< X-direction value */
|
||||
FLOAT y; /**< Y-direction value */
|
||||
FLOAT z; /**< Z-direction value */
|
||||
} SmiAccelerometerVector;
|
||||
|
||||
/**
|
||||
* Specifies the capabilities of the Accelerometer device.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
UINT callbackPeriod; /**<The unit of the vector sampling time, in milliseconds. */
|
||||
} SmiAccelerometerCapabilities;
|
||||
|
||||
typedef SMI_RESULT (WINAPI * SmiAccelerometerGetVector)(SmiAccelerometerVector *);
|
||||
typedef void (*SmiAccelerometerHandler)(SmiAccelerometerVector accel);
|
||||
|
||||
SmiAccelerometerGetVector gSmiAccelerometerGetVector = nsnull;
|
||||
|
||||
class SMISensor : public Sensor
|
||||
{
|
||||
public:
|
||||
SMISensor();
|
||||
~SMISensor();
|
||||
PRBool Startup();
|
||||
void Shutdown();
|
||||
void GetValues(double *x, double *y, double *z);
|
||||
private:
|
||||
HMODULE mLibrary;
|
||||
};
|
||||
|
||||
SMISensor::SMISensor()
|
||||
:mLibrary(nsnull)
|
||||
{
|
||||
}
|
||||
|
||||
SMISensor::~SMISensor()
|
||||
{
|
||||
}
|
||||
|
||||
PRBool
|
||||
SMISensor::Startup()
|
||||
{
|
||||
HMODULE hSensorLib = LoadLibraryW(L"SamsungMobileSDK_1.dll");
|
||||
|
||||
if (!hSensorLib)
|
||||
return PR_FALSE;
|
||||
|
||||
gSmiAccelerometerGetVector = (SmiAccelerometerGetVector)
|
||||
GetProcAddressW(hSensorLib, L"SmiAccelerometerGetVector");
|
||||
|
||||
if (gSmiAccelerometerGetVector == nsnull) {
|
||||
FreeLibrary(hSensorLib);
|
||||
mLibrary = nsnull;
|
||||
gSmiAccelerometerGetVector = nsnull;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
mLibrary = hSensorLib;
|
||||
return PR_TRUE;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
SMISensor::Shutdown()
|
||||
{
|
||||
NS_ASSERTION(mLibrary, "Shutdown called when mLibrary is null?");
|
||||
FreeLibrary(mLibrary);
|
||||
mLibrary = nsnull;
|
||||
gSmiAccelerometerGetVector = nsnull;
|
||||
}
|
||||
|
||||
void
|
||||
SMISensor::GetValues(double *x, double *y, double *z)
|
||||
{
|
||||
NS_ASSERTION(mLibrary, "mLibrary should not be null when GetValues is called");
|
||||
|
||||
SmiAccelerometerVector vector;
|
||||
vector.x = vector.y = vector.z = 0;
|
||||
SMI_RESULT result = gSmiAccelerometerGetVector(&vector);
|
||||
|
||||
// don't we have to adjust
|
||||
*x = vector.x;
|
||||
*y = vector.y;
|
||||
*z = vector.z;
|
||||
}
|
||||
|
||||
////////////////////////////
|
||||
// Toshiba TG01 / T-01A
|
||||
////////////////////////////
|
||||
|
||||
typedef struct _TS_ACCELERATION
|
||||
{
|
||||
SHORT x;
|
||||
SHORT y;
|
||||
SHORT z;
|
||||
FILETIME time;
|
||||
} TS_ACCELERATION;
|
||||
|
||||
typedef DWORD (WINAPI *TSRegisterAcceleration)(HANDLE,DWORD,DWORD*);
|
||||
typedef DWORD (WINAPI *TSDeregisterAcceleration)(DWORD);
|
||||
typedef DWORD (WINAPI *TSGetAcceleration)(DWORD,TS_ACCELERATION*);
|
||||
|
||||
TSRegisterAcceleration gTSRegisterAcceleration = nsnull;
|
||||
TSDeregisterAcceleration gTSDeregisterAcceleration = nsnull;
|
||||
TSGetAcceleration gTSGetAcceleration = nsnull;
|
||||
|
||||
class TsSensor : public Sensor
|
||||
{
|
||||
public:
|
||||
TsSensor();
|
||||
~TsSensor();
|
||||
PRBool Startup();
|
||||
void Shutdown();
|
||||
void GetValues(double *x, double *y, double *z);
|
||||
private:
|
||||
HMODULE mLibrary;
|
||||
DWORD mId;
|
||||
};
|
||||
|
||||
TsSensor::TsSensor() : mLibrary(nsnull), mId(0)
|
||||
{
|
||||
}
|
||||
|
||||
TsSensor::~TsSensor()
|
||||
{
|
||||
}
|
||||
|
||||
PRBool
|
||||
TsSensor::Startup()
|
||||
{
|
||||
HMODULE hSensorLib = LoadLibraryW(L"axcon.dll");
|
||||
|
||||
if (!hSensorLib)
|
||||
return PR_FALSE;
|
||||
|
||||
gTSRegisterAcceleration = (TSRegisterAcceleration) GetProcAddressW(hSensorLib, L"TSRegisterAcceleration");
|
||||
gTSDeregisterAcceleration = (TSDeregisterAcceleration) GetProcAddressW(hSensorLib, L"TSDeregisterAcceleration");
|
||||
gTSGetAcceleration = (TSGetAcceleration) GetProcAddressW(hSensorLib, L"TSGetAcceleration");
|
||||
|
||||
if (gTSRegisterAcceleration && gTSDeregisterAcceleration && gTSGetAcceleration) {
|
||||
if (!gTSRegisterAcceleration(GetModuleHandle(NULL), 100, &mId)) {
|
||||
mLibrary = hSensorLib;
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
FreeLibrary(hSensorLib);
|
||||
|
||||
mLibrary = nsnull;
|
||||
mId = 0;
|
||||
gTSRegisterAcceleration = nsnull;
|
||||
gTSDeregisterAcceleration = nsnull;
|
||||
gTSGetAcceleration = nsnull;
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
TsSensor::Shutdown()
|
||||
{
|
||||
NS_ASSERTION(mLibrary, "Shutdown called when mLibrary is null?");
|
||||
|
||||
gTSDeregisterAcceleration(mId);
|
||||
FreeLibrary(mLibrary);
|
||||
|
||||
mLibrary = nsnull;
|
||||
mId = 0;
|
||||
gTSRegisterAcceleration = nsnull;
|
||||
gTSDeregisterAcceleration = nsnull;
|
||||
gTSGetAcceleration = nsnull;
|
||||
}
|
||||
|
||||
void
|
||||
TsSensor::GetValues(double *x, double *y, double *z)
|
||||
{
|
||||
NS_ASSERTION(mLibrary, "mLibrary should not be null when GetValues is called");
|
||||
|
||||
TS_ACCELERATION data;
|
||||
gTSGetAcceleration(mId, &data);
|
||||
|
||||
// Value for TG-01 is landscaped
|
||||
*x = ((double)data.y) / 1000;
|
||||
*y = ((double)data.x) / 1000;
|
||||
*z = ((double)data.z) / 1000;
|
||||
}
|
||||
|
||||
#endif // WINCE_WINDOWS_MOBILE
|
||||
|
||||
#if !defined(WINCE) && !defined(WINCE_WINDOWS_MOBILE) // normal windows.
|
||||
|
||||
////////////////////////////
|
||||
|
@ -472,26 +145,6 @@ void nsAccelerometerSystem::Startup()
|
|||
|
||||
PRBool started = PR_FALSE;
|
||||
|
||||
#ifdef WINCE_WINDOWS_MOBILE
|
||||
|
||||
mSensor = new SMISensor();
|
||||
if (mSensor)
|
||||
started = mSensor->Startup();
|
||||
|
||||
if (!started) {
|
||||
mSensor = new HTCSensor();
|
||||
if (mSensor)
|
||||
started = mSensor->Startup();
|
||||
}
|
||||
|
||||
if (!started) {
|
||||
mSensor = new TsSensor();
|
||||
if (mSensor)
|
||||
started = mSensor->Startup();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(WINCE) && !defined(WINCE_WINDOWS_MOBILE) // normal windows.
|
||||
|
||||
mSensor = new ThinkPadSensor();
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script>
|
||||
|
||||
function boom()
|
||||
{
|
||||
var f = document.getElementById("f");
|
||||
var fw = f.contentWindow;
|
||||
fw.document.designMode = 'on';
|
||||
f.style.content = "'m'";
|
||||
fw.document.removeChild(fw.document.documentElement)
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body onload="boom();"><iframe id="f" src="data:text/html,"></iframe></body>
|
||||
</html>
|
|
@ -21,3 +21,4 @@ load 582138-1.xhtml
|
|||
load 612565-1.html
|
||||
asserts(6) load 615015-1.html # Bug 439258
|
||||
load 615450-1.html
|
||||
load 643786-1.html
|
||||
|
|
|
@ -9205,6 +9205,10 @@ nsHTMLEditRules::DocumentModifiedWorker()
|
|||
if (!mHTMLEditor) {
|
||||
return;
|
||||
}
|
||||
|
||||
// DeleteNode below may cause a flush, which could destroy the editor
|
||||
nsAutoRemovableScriptBlocker scriptBlocker;
|
||||
|
||||
nsCOMPtr<nsIHTMLEditor> kungFuDeathGrip(mHTMLEditor);
|
||||
nsCOMPtr<nsISelection> selection;
|
||||
nsresult res = mHTMLEditor->GetSelection(getter_AddRefs(selection));
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 tw=80 et cindent: */
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
/* ***** 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
|
||||
|
@ -61,7 +60,6 @@
|
|||
#include "nsIDOMWindow.h"
|
||||
#include "nsIDOMWindowCollection.h"
|
||||
#include "nsIWebBrowser.h"
|
||||
#include "nsIDOM3Document.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsIFormControl.h"
|
||||
|
@ -555,8 +553,7 @@ EmbedContextMenuInfo::UpdateContextData(nsIDOMEvent *aDOMEvent)
|
|||
if (NS_SUCCEEDED(rv) && domDoc && mCtxDocument != domDoc) {
|
||||
mCtxDocument = domDoc;
|
||||
mNSHHTMLElementSc = nsnull;
|
||||
nsCOMPtr<nsIDOM3Document> docuri = do_QueryInterface(mCtxDocument);
|
||||
docuri->GetDocumentURI(mCtxURI);
|
||||
mCtxDocument->GetDocumentURI(mCtxURI);
|
||||
NS_ENSURE_ARG_POINTER(mOwner);
|
||||
nsCOMPtr<nsIWebBrowser> webBrowser;
|
||||
mOwner->mWindow->GetWebBrowser(getter_AddRefs(webBrowser));
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** 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
|
||||
|
@ -49,7 +48,6 @@
|
|||
#include "nsIComponentManager.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOM3Document.h"
|
||||
#include "nsIDOMXULDocument.h"
|
||||
#include "nsIDOMWindow.h"
|
||||
#include "nsIDOMElement.h"
|
||||
|
@ -1747,10 +1745,7 @@ nsEventStatus nsWebBrowser::HandleEvent(nsGUIEvent *aEvent)
|
|||
#if defined(DEBUG_smaug)
|
||||
nsCOMPtr<nsIDOMDocument> domDocument = do_GetInterface(browser->mDocShell);
|
||||
nsAutoString documentURI;
|
||||
if (domDocument) {
|
||||
nsCOMPtr<nsIDOM3Document> d3 = do_QueryInterface(domDocument);
|
||||
d3->GetDocumentURI(documentURI);
|
||||
}
|
||||
domDocument->GetDocumentURI(documentURI);
|
||||
printf("nsWebBrowser::NS_ACTIVATE %p %s\n", (void*)browser,
|
||||
NS_ConvertUTF16toUTF8(documentURI).get());
|
||||
#endif
|
||||
|
@ -1762,10 +1757,7 @@ nsEventStatus nsWebBrowser::HandleEvent(nsGUIEvent *aEvent)
|
|||
#if defined(DEBUG_smaug)
|
||||
nsCOMPtr<nsIDOMDocument> domDocument = do_GetInterface(browser->mDocShell);
|
||||
nsAutoString documentURI;
|
||||
if (domDocument) {
|
||||
nsCOMPtr<nsIDOM3Document> d3 = do_QueryInterface(domDocument);
|
||||
d3->GetDocumentURI(documentURI);
|
||||
}
|
||||
domDocument->GetDocumentURI(documentURI);
|
||||
printf("nsWebBrowser::NS_DEACTIVATE %p %s\n", (void*)browser,
|
||||
NS_ConvertUTF16toUTF8(documentURI).get());
|
||||
#endif
|
||||
|
|
|
@ -68,8 +68,10 @@ class OTSStream {
|
|||
}
|
||||
|
||||
while (length >= 4) {
|
||||
chksum_ += ntohl(*reinterpret_cast<const uint32_t*>(
|
||||
reinterpret_cast<const uint8_t*>(data) + offset));
|
||||
uint32_t tmp;
|
||||
std::memcpy(&tmp, reinterpret_cast<const uint8_t *>(data) + offset,
|
||||
sizeof(uint32_t));
|
||||
chksum_ += ntohl(tmp);
|
||||
length -= 4;
|
||||
offset += 4;
|
||||
}
|
||||
|
|
|
@ -1011,7 +1011,7 @@ gfxDWriteFontList::GetFontSubstitutes()
|
|||
|
||||
for (i = 0, rv = ERROR_SUCCESS; rv != ERROR_NO_MORE_ITEMS; i++) {
|
||||
aliasName[0] = 0;
|
||||
lenAlias = sizeof(aliasName);
|
||||
lenAlias = NS_ARRAY_LENGTH(aliasName);
|
||||
actualName[0] = 0;
|
||||
lenActual = sizeof(actualName);
|
||||
rv = RegEnumValueW(hKey, i, aliasName, &lenAlias, NULL, &valueType,
|
||||
|
|
|
@ -626,7 +626,7 @@ gfxGDIFontList::GetFontSubstitutes()
|
|||
|
||||
for (i = 0, rv = ERROR_SUCCESS; rv != ERROR_NO_MORE_ITEMS; i++) {
|
||||
aliasName[0] = 0;
|
||||
lenAlias = sizeof(aliasName);
|
||||
lenAlias = NS_ARRAY_LENGTH(aliasName);
|
||||
actualName[0] = 0;
|
||||
lenActual = sizeof(actualName);
|
||||
rv = RegEnumValueW(hKey, i, aliasName, &lenAlias, NULL, &valueType,
|
||||
|
|
|
@ -57,7 +57,10 @@ nsCollationMacUC::nsCollationMacUC()
|
|||
nsCollationMacUC::~nsCollationMacUC()
|
||||
{
|
||||
if (mHasCollator) {
|
||||
OSStatus err = ::UCDisposeCollator(&mCollator);
|
||||
#ifdef DEBUG
|
||||
OSStatus err =
|
||||
#endif
|
||||
::UCDisposeCollator(&mCollator);
|
||||
mHasCollator = PR_FALSE;
|
||||
NS_ASSERTION((err == noErr), "UCDisposeCollator failed");
|
||||
}
|
||||
|
|
|
@ -147,7 +147,6 @@ geostd8=GEOSTD8
|
|||
armscii-8=armscii-8
|
||||
x-viet-tcvn5712=x-viet-tcvn5712
|
||||
x-viet-vps=x-viet-vps
|
||||
x-viet-vni=x-viet-vni
|
||||
iso-10646-ucs-2=UTF-16BE
|
||||
x-iso-10646-ucs-2-be=UTF-16BE
|
||||
x-iso-10646-ucs-2-le=UTF-16LE
|
||||
|
@ -474,10 +473,6 @@ csiso2022kr=ISO-2022-KR
|
|||
#
|
||||
csviscii=VISCII
|
||||
#
|
||||
# Aliases for VIQR
|
||||
#
|
||||
csviqr=VIQR
|
||||
#
|
||||
# Aliases for x-euc-tw
|
||||
#
|
||||
zh_tw-euc=x-euc-tw
|
||||
|
|
|
@ -279,9 +279,6 @@
|
|||
#include "nsUnicodeToISO2022CN.h"
|
||||
#include "gbku.h"
|
||||
|
||||
#define DECODER_NAME_BASE "Unicode Decoder-"
|
||||
#define ENCODER_NAME_BASE "Unicode Encoder-"
|
||||
|
||||
NS_CONVERTER_REGISTRY_START
|
||||
NS_UCONV_REG_UNREG("ISO-8859-1", NS_ISO88591TOUNICODE_CID, NS_UNICODETOISO88591_CID)
|
||||
NS_UCONV_REG_UNREG("windows-1252", NS_CP1252TOUNICODE_CID, NS_UNICODETOCP1252_CID)
|
||||
|
@ -460,9 +457,6 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsISO2022CNToUnicode)
|
|||
//----------------------------------------------------------------------------
|
||||
// Global functions and data [declaration]
|
||||
|
||||
#define DECODER_NAME_BASE "Unicode Decoder-"
|
||||
#define ENCODER_NAME_BASE "Unicode Encoder-"
|
||||
|
||||
// ucvja
|
||||
const PRUint16 g_uf0201Mapping[] = {
|
||||
#include "jis0201.uf"
|
||||
|
@ -480,10 +474,6 @@ const PRUint16 g_uf0208extMapping[] = {
|
|||
#include "jis0208ext.uf"
|
||||
};
|
||||
|
||||
const PRUint16 g_uf0212Mapping[] = {
|
||||
#include "jis0212.uf"
|
||||
};
|
||||
|
||||
// ucvtw2
|
||||
const PRUint16 g_ufCNS1MappingTable[] = {
|
||||
#include "cns_1.uf"
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче