author | Benjamin Smedberg <benjamin@smedbergs.us> |
Thu, 01 Jul 2010 11:55:57 -0400 | |
changeset 47092 | e90cbf73a8be1a3803ffb1c907388b3c8dfde8bf |
parent 47091 | ea142ed538fc02e587a18c8db4655f36cec8e54e (current diff) |
parent 46969 | d9253109fd884143e362b2f23b02281e6d0944b5 (diff) |
child 47093 | 2ad039920033d9fe2960153a79584b2e8c02a3ef |
push id | 14223 |
push user | bsmedberg@mozilla.com |
push date | Thu, 01 Jul 2010 18:30:48 +0000 |
treeherder | mozilla-central@836fd3f8feba [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
bugs | 568691 |
milestone | 2.0b2pre |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/.hgtags +++ b/.hgtags @@ -30,14 +30,25 @@ 8a601ed6bc4c7b3d1e35aa9e81f257512d984bd5 d7d64f68423b68a671f623f123e90057ebc49dac UPDATE_PACKAGING_R7 fb32f6e1859c07846a01b4478a7b1678019e0b45 UPDATE_PACKAGING_R7 f817a4378f32b1ad0a7c4b5a9949586dba816da5 FENNEC_M11 5c1e7c779b6edc8ff912001990edc579f80597f4 FENNEC_B1 fe9cc55b8db7f56f7e68a246acba363743854979 UPDATE_PACKAGING_R8 6fd4bb500d425c406c1b52f66e5b195b20ae5e0a chromium-import-r15462 6fd4bb500d425c406c1b52f66e5b195b20ae5e0a chromium-import-latest 376b78fc72230aaf2ca4e279a8f4ef1efd4a1d9f GECKO_1_9_2_BASE +941ad9d7d079246481f365c3cfbfc75a5bbefc94 last-mozilla-central +2bae3bbf866e7de2a4b2377e7c2f52cc9ac14a22 last-mozilla-central +2bae3bbf866e7de2a4b2377e7c2f52cc9ac14a22 last-mozilla-central +65c1582465efe99899189519fccaf7b2826fcb2e last-mozilla-central +65c1582465efe99899189519fccaf7b2826fcb2e last-mozilla-central +27937722da69ad0e8fd140a00671413068226a5b last-mozilla-central +27937722da69ad0e8fd140a00671413068226a5b last-mozilla-central +a732c6d3c078f80635255c78bfaadffa5828a8a5 last-mozilla-central +a732c6d3c078f80635255c78bfaadffa5828a8a5 last-mozilla-central +925595f3c08634cc42e33158ea6858bb55623ef7 last-mozilla-central +dba2abb7db57078c5a4810884834d3056a5d56c2 last-mozilla-central 138f593553b66c9f815e8f57870c19d6347f7702 UPDATE_PACKAGING_R9 138f593553b66c9f815e8f57870c19d6347f7702 UPDATE_PACKAGING_R10 138f593553b66c9f815e8f57870c19d6347f7702 UPDATE_PACKAGING_R11 0327e126ea245112c0aa7283fee154e084866fb5 bsmedberg-static-xpcom-registration-base 0327e126ea245112c0aa7283fee154e084866fb5 bsmedberg-static-xpcom-registration-base 2f83edbbeef0de7dd901411d270da61106c8afae bsmedberg-static-xpcom-registration-base
--- a/accessible/public/nsIAccessibleRetrieval.idl +++ b/accessible/public/nsIAccessibleRetrieval.idl @@ -51,57 +51,33 @@ interface nsIDOMDOMStringList; * An interface for in-process accessibility clients * wishing to get an nsIAccessible or nsIAccessNode for * a given DOM node. * More documentation at: * http://www.mozilla.org/projects/ui/accessibility * * @status UNDER_REVIEW */ -[scriptable, uuid(420f0f49-27c1-4ac1-b509-5aba4353909b)] +[scriptable, uuid(310ce77d-c92b-4761-82e8-77e1a728e8d4)] interface nsIAccessibleRetrieval : nsISupports { /** * Return application accessible. */ nsIAccessible getApplicationAccessible(); /** * Return an nsIAccessible for a DOM node in pres shell 0. * Create a new accessible of the appropriate type if necessary, * or use one from the accessibility cache if it already exists. * @param aNode The DOM node to get an accessible for. * @return The nsIAccessible for the given DOM node. */ nsIAccessible getAccessibleFor(in nsIDOMNode aNode); - /** - * The same like getAccessibleFor method except it returns accessible only if - * it is attached, i.e. accessible is certified to be a descendent of the root - * accessible. - * - * @param aNode - the DOM node to get an accessible for. - * - * @return - the accessible for the given DOM node. - */ - nsIAccessible getAttachedAccessibleFor(in nsIDOMNode aNode); - - /** - * Return an DOM node that is relevant to attached accesible check. This - * node is either from bindings chain if given node is anonymous and owner - * binding denies accessible in anonymous content or given node (it's not - * important whether it is accessible or not). This method doesn't create - * accessible object for returned node. - * - * @param aNode - the DOM node to get relevant content node. - * - * @return - the DOM node for parent attached accessible - */ - nsIDOMNode getRelevantContentNodeFor(in nsIDOMNode aNode); - /** * Returns accessible role as a string. * * @param aRole - the accessible role constants. */ AString getStringRole(in unsigned long aRole); /**
--- a/accessible/src/base/nsAccTreeWalker.cpp +++ b/accessible/src/base/nsAccTreeWalker.cpp @@ -108,18 +108,18 @@ nsAccTreeWalker::GetNextChildInternal(PR mState->childList->GetLength(&length); while (mState->childIdx < length) { nsIContent* childNode = mState->childList->GetNodeAt(mState->childIdx); mState->childIdx++; PRBool isHidden = PR_FALSE; nsRefPtr<nsAccessible> accessible = - GetAccService()->GetAccessible(childNode, presShell, mWeakShell, - &isHidden); + GetAccService()->GetOrCreateAccessible(childNode, presShell, mWeakShell, + &isHidden); if (accessible) return accessible.forget(); // Walk down into subtree to find accessibles. if (!isHidden) { if (!PushState(childNode)) break;
--- a/accessible/src/base/nsAccUtils.cpp +++ b/accessible/src/base/nsAccUtils.cpp @@ -522,41 +522,38 @@ nsAccUtils::GetTextAccessibleFromSelecti return nsnull; PRInt32 focusOffset = 0; aSelection->GetFocusOffset(&focusOffset); nsCOMPtr<nsINode> focusNode(do_QueryInterface(focusDOMNode)); nsCOMPtr<nsINode> resultNode = nsCoreUtils::GetDOMNodeFromDOMPoint(focusNode, focusOffset); + nsCOMPtr<nsIWeakReference> weakShell(nsCoreUtils::GetWeakShellFor(resultNode)); // Get text accessible containing the result node. - while (resultNode) { - // Make sure to get the correct starting node for selection events inside - // XBL content trees. - resultNode = GetAccService()->GetRelevantContentNodeFor(resultNode); - if (!resultNode->IsNodeOfType(nsINode::eTEXT)) { - nsAccessible *accessible = GetAccService()->GetAccessible(resultNode); - if (accessible) { - nsHyperTextAccessible *textAcc = nsnull; - CallQueryInterface(accessible, &textAcc); - if (textAcc) { - if (aNode) - NS_ADDREF(*aNode = resultNode); - - return textAcc; - } - } - } - - resultNode = resultNode->GetNodeParent(); + nsAccessible* accessible = + GetAccService()->GetAccessibleOrContainer(resultNode, weakShell); + if (!accessible) { + NS_NOTREACHED("No nsIAccessibleText for selection change event!"); + return nsnull; } - NS_NOTREACHED("No nsIAccessibleText for selection change event!"); + do { + nsHyperTextAccessible* textAcc = nsnull; + CallQueryInterface(accessible, &textAcc); + if (textAcc) { + if (aNode) + NS_ADDREF(*aNode = accessible->GetNode()); + return textAcc; + } + } while (accessible = accessible->GetParent()); + + NS_NOTREACHED("We must reach document accessible implementing nsIAccessibleText!"); return nsnull; } nsresult nsAccUtils::ConvertToScreenCoords(PRInt32 aX, PRInt32 aY, PRUint32 aCoordinateType, nsAccessNode *aAccessNode, nsIntPoint *aCoords) @@ -629,17 +626,18 @@ nsAccUtils::GetScreenCoordsForWindow(nsA { return nsCoreUtils::GetScreenCoordsForWindow(aAccessNode->GetNode()); } nsIntPoint nsAccUtils::GetScreenCoordsForParent(nsAccessNode *aAccessNode) { nsAccessible *parent = - GetAccService()->GetContainerAccessible(aAccessNode->GetNode(), PR_TRUE); + GetAccService()->GetContainerAccessible(aAccessNode->GetNode(), + aAccessNode->GetWeakShell()); if (!parent) return nsIntPoint(0, 0); nsIFrame *parentFrame = parent->GetFrame(); if (!parentFrame) return nsIntPoint(0, 0); nsIntRect parentRect = parentFrame->GetScreenRectExternal(); @@ -810,22 +808,16 @@ nsAccUtils::MustPrune(nsIAccessible *aAc role == nsIAccessibleRole::ROLE_PASSWORD_TEXT || role == nsIAccessibleRole::ROLE_TOGGLE_BUTTON || role == nsIAccessibleRole::ROLE_GRAPHIC || role == nsIAccessibleRole::ROLE_SLIDER || role == nsIAccessibleRole::ROLE_PROGRESSBAR || role == nsIAccessibleRole::ROLE_SEPARATOR; } -PRBool -nsAccUtils::IsNodeRelevant(nsINode *aNode) -{ - return aNode == GetAccService()->GetRelevantContentNodeFor(aNode); -} - nsresult nsAccUtils::GetHeaderCellsFor(nsIAccessibleTable *aTable, nsIAccessibleTableCell *aCell, PRInt32 aRowOrColHeaderCells, nsIArray **aCells) { nsresult rv = NS_OK; nsCOMPtr<nsIMutableArray> cells = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv);
--- a/accessible/src/base/nsAccUtils.h +++ b/accessible/src/base/nsAccUtils.h @@ -406,22 +406,16 @@ public: /** * Return true if the given accessible can't have children. Used when exposing * to platform accessibility APIs, should the children be pruned off? */ static PRBool MustPrune(nsIAccessible *aAccessible); /** - * Return true if the given node can be accessible and attached to - * the document's accessible tree. - */ - static PRBool IsNodeRelevant(nsINode *aNode); - - /** * Search hint enum constants. Used by GetHeaderCellsFor() method. */ enum { // search for row header cells, left direction eRowHeaderCells, // search for column header cells, top direction eColumnHeaderCells };
--- a/accessible/src/base/nsAccessNode.h +++ b/accessible/src/base/nsAccessNode.h @@ -171,16 +171,21 @@ public: return GetNode() && GetNode()->IsNodeOfType(nsINode::eDOCUMENT); } /** * Return the corresponding press shell for this accessible. */ already_AddRefed<nsIPresShell> GetPresShell(); + /** + * Return presentation shell for the accessible. + */ + nsIWeakReference* GetWeakShell() const { return mWeakShell; } + protected: nsPresContext* GetPresContext(); void LastRelease(); nsCOMPtr<nsIContent> mContent; nsCOMPtr<nsIWeakReference> mWeakShell;
--- a/accessible/src/base/nsAccessibilityService.cpp +++ b/accessible/src/base/nsAccessibilityService.cpp @@ -143,40 +143,28 @@ nsAccessibilityService::Observe(nsISuppo // nsIAccessibilityService void nsAccessibilityService::NotifyOfAnchorJumpTo(nsIContent *aTarget) { nsIDocument *document = aTarget->GetCurrentDoc(); if (!document) return; - nsINode *targetNode = aTarget; - nsAccessible *targetAcc = GetAccessible(targetNode); - - // Getting the targetAcc above will have ensured accessible doc creation. - // XXX Bug 561683 - nsDocAccessible *docAccessible = GetDocAccessible(document); - if (!docAccessible) + // If the jump target is not accessible then fire an event for nearest + // accessible in parent chain. + nsCOMPtr<nsIWeakReference> weakShell(nsCoreUtils::GetWeakShellFor(aTarget)); + nsAccessible* targetAcc = GetAccessibleOrContainer(aTarget, weakShell); + if (!targetAcc) return; - // If the jump target is not accessible then fire an event for nearest - // accessible in parent chain. - if (!targetAcc) { - targetAcc = GetContainerAccessible(targetNode, PR_TRUE); - targetNode = targetAcc->GetNode(); - } - - NS_ASSERTION(targetNode, - "No accessible in parent chain!? Expect at least a document accessible."); - if (!targetNode) - return; + nsINode* targetNode = targetAcc->GetNode(); // XXX note in rare cases the node could go away before we flush the queue, // for example if the node becomes inaccessible, or is removed from the DOM. - docAccessible-> + GetDocAccessible(document)-> FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_SCROLLING_START, targetNode); } // nsIAccessibilityService nsresult nsAccessibilityService::FireAccessibleEvent(PRUint32 aEvent, nsIAccessible *aTarget) @@ -509,41 +497,16 @@ nsAccessibilityService::GetAccessibleFor NS_ENSURE_ARG_POINTER(aAccessible); nsCOMPtr<nsINode> node(do_QueryInterface(aNode)); NS_IF_ADDREF(*aAccessible = GetAccessible(node)); return NS_OK; } NS_IMETHODIMP -nsAccessibilityService::GetAttachedAccessibleFor(nsIDOMNode *aDOMNode, - nsIAccessible **aAccessible) -{ - NS_ENSURE_ARG(aDOMNode); - NS_ENSURE_ARG_POINTER(aAccessible); - - nsCOMPtr<nsINode> node(do_QueryInterface(aDOMNode)); - NS_IF_ADDREF(*aAccessible = GetAttachedAccessibleFor(node)); - return NS_OK; -} - -NS_IMETHODIMP -nsAccessibilityService::GetRelevantContentNodeFor(nsIDOMNode *aNode, - nsIDOMNode **aRelevantNode) -{ - NS_ENSURE_ARG(aNode); - NS_ENSURE_ARG_POINTER(aRelevantNode); - - nsCOMPtr<nsINode> node(do_QueryInterface(aNode)); - nsINode *relevantNode = GetRelevantContentNodeFor(node); - CallQueryInterface(relevantNode, aRelevantNode); - return NS_OK; -} - -NS_IMETHODIMP nsAccessibilityService::GetStringRole(PRUint32 aRole, nsAString& aString) { if ( aRole >= NS_ARRAY_LENGTH(kRoleNames)) { aString.AssignLiteral("unknown"); return NS_OK; } CopyUTF8toUTF16(kRoleNames[aRole], aString); @@ -725,98 +688,57 @@ nsAccessibilityService::GetAccessibleFro nsAccessible* nsAccessibilityService::GetAccessibleInShell(nsINode* aNode, nsIPresShell* aPresShell) { if (!aNode || !aPresShell) return nsnull; nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(aPresShell)); - nsRefPtr<nsAccessible> accessible = - GetAccessible(aNode, aPresShell, weakShell); - return accessible; + return GetAccessibleByRule(aNode, weakShell, eGetAccForNode); } //////////////////////////////////////////////////////////////////////////////// // nsAccessibilityService public -nsAccessible * -nsAccessibilityService::GetAccessible(nsINode *aNode) +nsAccessible* +nsAccessibilityService::GetAccessible(nsINode* aNode) { - if (!aNode) - return nsnull; - - nsIPresShell *presShell = nsCoreUtils::GetPresShellFor(aNode); - if (!presShell) - return nsnull; - - nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(presShell)); - nsRefPtr<nsAccessible> accessible = GetAccessible(aNode, presShell, - weakShell); - return accessible; + if (aNode) { + nsCOMPtr<nsIWeakReference> weakShell(nsCoreUtils::GetWeakShellFor(aNode)); + if (weakShell) + return GetAccessibleByRule(aNode, weakShell, eGetAccForNode); + } + return nsnull; } -nsAccessible * -nsAccessibilityService::GetAccessibleInWeakShell(nsINode *aNode, - nsIWeakReference *aWeakShell) -{ - if (!aNode || !aWeakShell) - return nsnull; - - nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(aWeakShell)); - nsRefPtr<nsAccessible> accessible = GetAccessible(aNode, presShell, - aWeakShell); - return accessible; -} - -nsAccessible * -nsAccessibilityService::GetContainerAccessible(nsINode *aNode, - PRBool aCanCreate) +nsAccessible* +nsAccessibilityService::GetCachedContainerAccessible(nsINode* aNode) { if (!aNode) return nsnull; nsIDocument *document = aNode->GetCurrentDoc(); if (!document) return nsnull; nsIPresShell *presShell = document->GetShell(); if (!presShell) return nsnull; nsINode *currNode = aNode; nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(presShell)); nsAccessible *accessible = nsnull; - while (!accessible && (currNode = currNode->GetNodeParent())) { - currNode = GetAccService()->GetRelevantContentNodeFor(currNode); - - if (aCanCreate) { - accessible = GetAccService()->GetAccessibleInWeakShell(currNode, - weakShell); - - } else { - // Only return cached accessible, don't create anything. - accessible = GetCachedAccessible(currNode, weakShell); - } - } + while ((currNode = currNode->GetNodeParent()) && + !(accessible = GetCachedAccessible(currNode, weakShell))); return accessible; } -nsAccessible * -nsAccessibilityService::GetAttachedAccessibleFor(nsINode *aNode) -{ - nsINode *relevantNode = GetRelevantContentNodeFor(aNode); - if (relevantNode != aNode) - return nsnull; - - return GetAccessible(relevantNode); -} - PRBool nsAccessibilityService::InitAccessible(nsAccessible *aAccessible, nsRoleMapEntry *aRoleMapEntry) { if (!aAccessible) return PR_FALSE; // Add to cache an accessible, etc. @@ -858,20 +780,20 @@ static PRBool HasRelatedContent(nsIConte return PR_TRUE; } } return PR_FALSE; } already_AddRefed<nsAccessible> -nsAccessibilityService::GetAccessible(nsINode *aNode, - nsIPresShell *aPresShell, - nsIWeakReference *aWeakShell, - PRBool *aIsHidden) +nsAccessibilityService::GetOrCreateAccessible(nsINode* aNode, + nsIPresShell* aPresShell, + nsIWeakReference* aWeakShell, + PRBool* aIsHidden) { if (!aPresShell || !aWeakShell || !aNode || gIsShutdown) return nsnull; if (aIsHidden) *aIsHidden = PR_FALSE; // Check to see if we already have an accessible for this node in the cache. @@ -1239,81 +1161,83 @@ nsAccessibilityService::HasUniversalAria nsAccUtils::HasDefinedARIAToken(aContent, nsAccessibilityAtoms::aria_invalid) || aContent->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_label) || aContent->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_labelledby) || nsAccUtils::HasDefinedARIAToken(aContent, nsAccessibilityAtoms::aria_live) || nsAccUtils::HasDefinedARIAToken(aContent, nsAccessibilityAtoms::aria_owns) || nsAccUtils::HasDefinedARIAToken(aContent, nsAccessibilityAtoms::aria_relevant); } -nsINode * -nsAccessibilityService::GetRelevantContentNodeFor(nsINode *aNode) +nsAccessible* +nsAccessibilityService::GetAccessibleByRule(nsINode* aNode, + nsIWeakReference* aWeakShell, + EWhatAccToGet aWhatToGet) { - // The method returns node that is relevant for attached accessible check. - // Sometimes element that is XBL widget hasn't accessible children in - // anonymous content. This method check whether given node can be accessible - // by looking through all nested bindings that given node is anonymous for. If - // there is XBL widget that deniedes to be accessible for given node then the - // method returns that XBL widget otherwise it returns given node. - - // For example, the algorithm allows us to handle following cases: - // 1. xul:dialog element has buttons (like 'ok' and 'cancel') in anonymous - // content. When node is dialog's button then we dialog's button since button - // of xul:dialog is accessible anonymous node. - // 2. xul:texbox has html:input in anonymous content. When given node is - // html:input elmement then we return xul:textbox since xul:textbox doesn't - // allow accessible nodes in anonymous content. - // 3. xforms:input that is hosted in xul document contains xul:textbox - // element. When given node is html:input or xul:textbox then we return - // xforms:input element since xforms:input hasn't accessible anonymous - // children. - - if (!aNode) + if (!aNode || !aWeakShell) return nsnull; - nsCOMPtr<nsIContent> content(do_QueryInterface(aNode)); - if (content) { - // Build stack of binding parents so we can walk it in reverse. - nsIContent *bindingParent; - nsCOMArray<nsIContent> bindingsStack; + nsAccessible* cachedAcc = GetCachedAccessible(aNode, aWeakShell); + if (cachedAcc) { + if (aWhatToGet & eGetAccForNode) + return cachedAcc; - for (bindingParent = content->GetBindingParent(); bindingParent != nsnull && - bindingParent != bindingParent->GetBindingParent(); - bindingParent = bindingParent->GetBindingParent()) { - bindingsStack.AppendObject(bindingParent); - } + // XXX: while nsAccessible::GetParent() tries to repair broken tree and + // may not return cached parent then we use GetAccessibleOrContainer(). + return GetAccessibleByRule(aNode->GetNodeParent(), aWeakShell, + eGetAccForNodeOrContainer); + } - PRInt32 bindingsCount = bindingsStack.Count(); - for (PRInt32 index = bindingsCount - 1; index >= 0 ; index--) { - bindingParent = bindingsStack[index]; + // Go up looking for the nearest accessible container stored in cache. + nsTArray<nsINode*> nodes; + nsINode* node = aNode; + while ((node = node->GetNodeParent()) && + !(cachedAcc = GetCachedAccessible(node, aWeakShell))) + nodes.AppendElement(node); - // Try to get an accessible by type since XBL widget can be accessible - // only if it implements nsIAccessibleProvider interface. - nsCOMPtr<nsIWeakReference> weakShell = - nsCoreUtils::GetWeakShellFor(bindingParent); + // Node is not in accessible document. + if (!cachedAcc) + return nsnull; - // XXX: it's a hack we should try the cache before, otherwise to cache - // the accessible. - nsRefPtr<nsAccessible> accessible = - CreateAccessibleByType(bindingParent, weakShell); - - if (accessible) { - if (!accessible->GetAllowsAnonChildAccessibles()) - return bindingParent; + // If children of the cached accessible weren't initialized then go down to + // the given node and create accessible tree. + nsAccessible* containerAcc = cachedAcc; + if (!cachedAcc->AreChildrenCached()) { + cachedAcc->EnsureChildren(); + for (PRInt32 idx = nodes.Length() - 1; idx >= 0; idx--) { + cachedAcc = GetCachedAccessible(nodes[idx], aWeakShell); + if (cachedAcc) { + cachedAcc->EnsureChildren(); + containerAcc = cachedAcc; } } } - return aNode; + // If the given node is accessible then it should be cached at this point. + // Exception is an area element because area and imagemap nodes aren't in + // the same parent chain. + cachedAcc = GetCachedAccessible(aNode, aWeakShell); + if (!cachedAcc && aNode->IsElement()) { + nsIFrame* frame = aNode->AsElement()->GetPrimaryFrame(); + if (frame && frame->GetContent() != aNode) + cachedAcc = GetAreaAccessible(frame, aNode, aWeakShell, &containerAcc); + } + + if ((aWhatToGet & eGetAccForNode) && cachedAcc) + return cachedAcc; + else if (aWhatToGet & eGetAccForContainer) + return containerAcc; + + return nsnull; } nsAccessible* -nsAccessibilityService::GetAreaAccessible(nsIFrame *aImageFrame, - nsINode *aAreaNode, - nsIWeakReference *aWeakShell) +nsAccessibilityService::GetAreaAccessible(nsIFrame* aImageFrame, + nsINode* aAreaNode, + nsIWeakReference* aWeakShell, + nsAccessible** aImageAccessible) { // Check if frame is an image frame, and content is <area>. nsIImageFrame *imageFrame = do_QueryFrame(aImageFrame); if (!imageFrame) return nsnull; nsCOMPtr<nsIDOMHTMLAreaElement> areaElmt = do_QueryInterface(aAreaNode); if (!areaElmt) @@ -1326,16 +1250,19 @@ nsAccessibilityService::GetAreaAccessibl if (!imageAcc) { imageAcc = CreateHTMLImageAccessible(aImageFrame->GetContent(), aImageFrame->PresContext()->PresShell()); if (!InitAccessible(imageAcc, nsnull)) return nsnull; } + if (aImageAccessible) + *aImageAccessible = imageAcc; + // Make sure <area> accessible children of the image map are cached so // that they should be available in global cache. imageAcc->EnsureChildren(); return GetCachedAccessible(aAreaNode, aWeakShell); } already_AddRefed<nsAccessible>
--- a/accessible/src/base/nsAccessibilityService.h +++ b/accessible/src/base/nsAccessibilityService.h @@ -122,76 +122,72 @@ public: // nsAccessibiltiyService /** * Return true if accessibility service has been shutdown. */ static PRBool IsShutdown() { return gIsShutdown; } /** - * Return an accessible for the given DOM node. + * Return an accessible for the given DOM node from the cache or create new + * one. * * @param aNode [in] the given node * @param aPresShell [in] the pres shell of the node * @param aWeakShell [in] the weak shell for the pres shell * @param aIsHidden [out, optional] indicates whether the node's frame is * hidden */ already_AddRefed<nsAccessible> - GetAccessible(nsINode *aNode, nsIPresShell *aPresShell, - nsIWeakReference *aWeakShell, PRBool *aIsHidden = nsnull); + GetOrCreateAccessible(nsINode* aNode, nsIPresShell* aPresShell, + nsIWeakReference* aWeakShell, + PRBool* aIsHidden = nsnull); /** * Return an accessible for the given DOM node. */ - nsAccessible *GetAccessible(nsINode *aNode); + nsAccessible* GetAccessible(nsINode* aNode); /** - * Return an accessible for a DOM node in the given pres shell. - * - * @param aNode [in] the given node. - * @param aPresShell [in] the presentation shell of the given node. + * Return an accessible for a DOM node in the given presshell. + * + * @param aNode [in] the given node + * @param aWeakShell [in] the presentation shell for the given node */ - nsAccessible *GetAccessibleInWeakShell(nsINode *aNode, - nsIWeakReference *aPresShell); - - /** - * Return the first accessible parent of a DOM node. - * - * @param aDOMNode [in] the DOM node to get an accessible for - * @param aCanCreate [in] specifies if accessible can be created if it didn't - * exist - */ - nsAccessible *GetContainerAccessible(nsINode *aNode, PRBool aCanCreate); + inline nsAccessible* GetAccessibleInWeakShell(nsINode* aNode, + nsIWeakReference* aWeakShell) + { + return GetAccessibleByRule(aNode, aWeakShell, eGetAccForNode); + } /** - * The same as getAccessibleFor method except it returns accessible only if - * it is attached, i.e. accessible is certified to be a descendant of the root - * accessible. - * - * XXX: this method must go away once we'll implement correct accessible tree. - * - * @param aNode [in] the DOM node to get an accessible for - * @return the accessible for the given DOM node + * Return an accessible for the given DOM node or container accessible if + * the node is not accessible. */ - nsAccessible *GetAttachedAccessibleFor(nsINode *aNode); + inline nsAccessible* GetAccessibleOrContainer(nsINode* aNode, + nsIWeakReference* aWeakShell) + { + return GetAccessibleByRule(aNode, aWeakShell, eGetAccForNodeOrContainer); + } /** - * Return an DOM node that is relevant to attached accessible check. This - * node is either from bindings chain if given node is anonymous and owner - * binding denies accessible in anonymous content or given node (it's not - * important whether it is accessible or not). This method doesn't create - * accessible object for returned node. + * Return a container accessible for the given DOM node. + */ + inline nsAccessible* GetContainerAccessible(nsINode* aNode, + nsIWeakReference* aWeakShell) + { + return GetAccessibleByRule(aNode, aWeakShell, eGetAccForContainer); + } + + /** + * Return the first cached accessible parent of a DOM node. * - * XXX: this method must go away once we'll implement correct accessible tree. - * - * @param aNode [in] the DOM node to get relevant content node - * @return the DOM node for parent attached accessible + * @param aDOMNode [in] the DOM node to get an accessible for */ - nsINode *GetRelevantContentNodeFor(nsINode *aNode); + nsAccessible* GetCachedContainerAccessible(nsINode *aNode); /** * Initialize an accessible and cache it. The method should be called for * every created accessible. * * @param aAccessible [in] accessible to initialize. * @param aRoleMapEntry [in] the role map entry role the ARIA role or nsnull * if none @@ -226,21 +222,40 @@ private: */ PRBool Init(); /** * Shutdowns accessibility service. */ void Shutdown(); + enum EWhatAccToGet { + eGetAccForNode = 0x1, + eGetAccForContainer = 0x2, + eGetAccForNodeOrContainer = eGetAccForNode | eGetAccForContainer + }; + + /** + * Return accessible or accessible container for the given node in presshell. + */ + nsAccessible* GetAccessibleByRule(nsINode* aNode, + nsIWeakReference* aWeakShell, + EWhatAccToGet aWhatToGet); + /** * Return accessible for HTML area element associated with an image map. + * + * @param aImageFrame [in] image frame + * @param aAreaNode [in] area node + * @param aWeakShell [in] presshell of image frame + * @param aImageAccessible [out, optional] image accessible, isn't addrefed */ nsAccessible* GetAreaAccessible(nsIFrame* aImageFrame, nsINode* aAreaNode, - nsIWeakReference* aWeakShell); + nsIWeakReference* aWeakShell, + nsAccessible** aImageAccessible = nsnull); /** * Create accessible for the element implementing nsIAccessibleProvider * interface. */ already_AddRefed<nsAccessible> CreateAccessibleByType(nsIContent* aContent, nsIWeakReference* aWeakShell);
--- a/accessible/src/base/nsAccessible.cpp +++ b/accessible/src/base/nsAccessible.cpp @@ -808,26 +808,23 @@ nsAccessible::GetChildAtPoint(PRInt32 aX nsIFrame *foundFrame = presShell->GetFrameForPoint(frame, offset); nsIContent* content = nsnull; if (!foundFrame || !(content = foundFrame->GetContent())) { NS_IF_ADDREF(*aChild = fallbackAnswer); return NS_OK; } - nsINode *relevantNode = GetAccService()->GetRelevantContentNodeFor(content); - nsAccessible *accessible = GetAccService()->GetAccessible(relevantNode); + // Get accessible for the node with the point or the first accessible in + // the DOM parent chain. + nsAccessible* accessible = + GetAccService()->GetAccessibleOrContainer(content, mWeakShell); if (!accessible) { - // No accessible for the node with the point, so find the first - // accessible in the DOM parent chain - accessible = GetAccService()->GetContainerAccessible(relevantNode, PR_TRUE); - if (!accessible) { - NS_IF_ADDREF(*aChild = fallbackAnswer); - return NS_OK; - } + NS_IF_ADDREF(*aChild = fallbackAnswer); + return NS_OK; } if (accessible == this) { // Manually walk through accessible children and see if the are within this // point. Skip offscreen or invisible accessibles. This takes care of cases // where layout won't walk into things for us, such as image map areas and // sub documents (XXX: subdocuments should be handled by methods of // nsOuterDocAccessibles). @@ -1237,18 +1234,16 @@ nsAccessible::GetXULName(nsAString& aLab return nsTextEquivUtils::GetNameFromSubtree(this, aLabel); } nsresult nsAccessible::HandleAccEvent(nsAccEvent *aEvent) { NS_ENSURE_ARG_POINTER(aEvent); - NS_ENSURE_TRUE(nsAccUtils::IsNodeRelevant(aEvent->GetNode()), - NS_ERROR_FAILURE); nsCOMPtr<nsIObserverService> obsService = mozilla::services::GetObserverService(); NS_ENSURE_TRUE(obsService, NS_ERROR_FAILURE); return obsService->NotifyObservers(aEvent, NS_ACCESSIBLE_EVENT_TOPIC, nsnull); } @@ -2670,32 +2665,17 @@ nsAccessible::Init() GetAccService()->GetDocAccessible(mContent->GetOwnerDoc()); NS_ASSERTION(docAcc, "Cannot cache new nsAccessible!"); if (!docAcc) return PR_FALSE; void *uniqueID = nsnull; GetUniqueID(&uniqueID); - if (!docAcc->CacheAccessible(uniqueID, this)) - return PR_FALSE; - - // Make sure an ancestor in real content is cached so that - // nsDocAccessible::RefreshNodes() can find the anonymous subtree to release - // when the root node goes away. /Specific examples of where this is used: - // <input type="file"> and <xul:findbar>. - // XXX: remove this once we create correct accessible tree. - if (mContent && mContent->IsInAnonymousSubtree()) { - nsAccessible *parent = GetAccService()->GetContainerAccessible(mContent, - PR_TRUE); - if (parent) - parent->EnsureChildren(); - } - - return PR_TRUE; + return docAcc->CacheAccessible(uniqueID, this); } void nsAccessible::Shutdown() { // Invalidate the child count and pointers to other accessibles, also make // sure none of its children point to this parent InvalidateChildren(); @@ -2774,41 +2754,43 @@ nsAccessible::InvalidateChildren() mChildren.Clear(); mAreChildrenInitialized = PR_FALSE; } nsAccessible* nsAccessible::GetParent() { + if (mParent) + return mParent; + if (IsDefunct()) return nsnull; - if (mParent) - return mParent; + // XXX: mParent can be null randomly because supposedly we get layout + // notification and invalidate parent-child relations, this accessible stays + // unattached. This should gone after bug 572951. Other reason is bug 574588 + // since CacheChildren() implementation calls nsAccessible::GetRole() what + // can need to get a parent and we are here as result. + NS_WARNING("Bad accessible tree!"); #ifdef DEBUG nsDocAccessible *docAccessible = GetDocAccessible(); NS_ASSERTION(docAccessible, "No document accessible for valid accessible!"); #endif - nsAccessible *parent = GetAccService()->GetContainerAccessible(mContent, - PR_TRUE); + nsAccessible* parent = GetAccService()->GetContainerAccessible(mContent, + mWeakShell); NS_ASSERTION(parent, "No accessible parent for valid accessible!"); if (!parent) return nsnull; -#ifdef DEBUG - NS_ASSERTION(!parent->IsDefunct(), "Defunct parent!"); - + // Repair parent-child relations. parent->EnsureChildren(); - if (parent != mParent) - NS_WARNING("Bad accessible tree!"); -#endif - + NS_ASSERTION(parent == mParent, "Wrong children repair!"); return parent; } nsAccessible* nsAccessible::GetChildAt(PRUint32 aIndex) { if (EnsureChildren()) return nsnull; @@ -2840,35 +2822,16 @@ nsAccessible::GetIndexOf(nsIAccessible * PRInt32 nsAccessible::GetIndexInParent() { nsAccessible *parent = GetParent(); return parent ? parent->GetIndexOf(this) : -1; } -nsAccessible* -nsAccessible::GetCachedParent() -{ - if (IsDefunct()) - return nsnull; - - return mParent; -} - -nsAccessible* -nsAccessible::GetCachedFirstChild() -{ - if (IsDefunct()) - return nsnull; - - return mChildren.SafeElementAt(0, nsnull); -} - - #ifdef DEBUG PRBool nsAccessible::IsInCache() { nsDocAccessible *docAccessible = GetAccService()->GetDocAccessible(mContent->GetOwnerDoc()); if (!docAccessible) return nsnull;
--- a/accessible/src/base/nsAccessible.h +++ b/accessible/src/base/nsAccessible.h @@ -230,17 +230,17 @@ public: virtual PRBool RemoveChild(nsAccessible *aAccessible) { return PR_FALSE; } ////////////////////////////////////////////////////////////////////////////// // Accessible tree traverse methods /** * Return parent accessible. */ - virtual nsAccessible* GetParent(); + nsAccessible* GetParent(); /** * Return child accessible at the given index. */ virtual nsAccessible* GetChildAt(PRUint32 aIndex); /** * Return child accessible count. @@ -258,24 +258,23 @@ public: PRInt32 GetIndexInParent(); /** * Return true if accessible has children; */ PRBool HasChildren() { return !!GetChildAt(0); } /** - * Return parent accessible only if cached. + * Return cached accessible of parent-child relatives. */ - nsAccessible* GetCachedParent(); + nsAccessible* GetCachedParent() const { return mParent; } + nsAccessible* GetCachedFirstChild() const + { return mChildren.SafeElementAt(0, nsnull); } - /** - * Return first child accessible only if cached. - */ - nsAccessible* GetCachedFirstChild(); + PRBool AreChildrenCached() const { return mAreChildrenInitialized; } #ifdef DEBUG /** * Return true if the access node is cached. */ PRBool IsInCache(); #endif
--- a/accessible/src/base/nsApplicationAccessible.cpp +++ b/accessible/src/base/nsApplicationAccessible.cpp @@ -400,22 +400,16 @@ nsApplicationAccessible::GetStateInterna } if (aExtraState) *aExtraState = 0; return NS_OK; } -nsAccessible* -nsApplicationAccessible::GetParent() -{ - return nsnull; -} - void nsApplicationAccessible::InvalidateChildren() { // Do nothing because application children are kept updated by AppendChild() // and RemoveChild() method calls. } ////////////////////////////////////////////////////////////////////////////////
--- a/accessible/src/base/nsApplicationAccessible.h +++ b/accessible/src/base/nsApplicationAccessible.h @@ -108,17 +108,16 @@ public: virtual PRBool IsDefunct(); virtual PRBool Init(); virtual void Shutdown(); // nsAccessible virtual nsresult GetARIAState(PRUint32 *aState, PRUint32 *aExtraState); virtual nsresult GetRoleInternal(PRUint32 *aRole); virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState); - virtual nsAccessible* GetParent(); virtual void InvalidateChildren(); virtual PRBool AppendChild(nsAccessible* aChild); virtual PRBool RemoveChild(nsAccessible* aChild); protected: // nsAccessible
--- a/accessible/src/base/nsDocAccessible.cpp +++ b/accessible/src/base/nsDocAccessible.cpp @@ -950,18 +950,16 @@ nsDocAccessible::AttributeChangedImpl(ns return; // Still loading, ignore setting of initial attributes nsCOMPtr<nsIPresShell> shell = GetPresShell(); if (!shell) { return; // Document has been shut down } NS_ASSERTION(aContent, "No node for attr modified"); - if (!aContent || !nsAccUtils::IsNodeRelevant(aContent)) - return; // Universal boolean properties that don't require a role. Fire the state // change when disabled or aria-disabled attribute is set. if (aAttribute == nsAccessibilityAtoms::disabled || aAttribute == nsAccessibilityAtoms::aria_disabled) { // Note. Checking the XUL or HTML namespace would not seem to gain us // anything, because disabled attribute really is going to mean the same @@ -1267,22 +1265,16 @@ void nsDocAccessible::ParentChainChanged(nsIContent *aContent) { } //////////////////////////////////////////////////////////////////////////////// // nsAccessible -nsAccessible* -nsDocAccessible::GetParent() -{ - return IsDefunct() ? nsnull : mParent.get(); -} - #ifdef DEBUG_ACCDOCMGR nsresult nsDocAccessible::HandleAccEvent(nsAccEvent *aAccEvent) { NS_LOG_ACCDOCLOAD_HANDLEEVENT(aAccEvent) return nsHyperTextAccessible::HandleAccEvent(aAccEvent); @@ -1508,26 +1500,27 @@ nsDocAccessible::ProcessPendingEvent(nsA return; } gLastFocusedFrameType = newFrameType; } } if (eventType == nsIAccessibleEvent::EVENT_SHOW) { - nsAccessible *containerAccessible = nsnull; - if (accessible) + nsAccessible* containerAccessible = nsnull; + if (accessible) { containerAccessible = accessible->GetParent(); + } else { + nsCOMPtr<nsIWeakReference> weakShell(nsCoreUtils::GetWeakShellFor(node)); + containerAccessible = GetAccService()->GetContainerAccessible(node, + weakShell); + } - if (!containerAccessible) { - containerAccessible = GetAccService()->GetContainerAccessible(node, - PR_TRUE); - if (!containerAccessible) - containerAccessible = this; - } + if (!containerAccessible) + containerAccessible = this; if (isAsync) { // For asynch show, delayed invalidatation of parent's children containerAccessible->InvalidateChildren(); // Some show events in the subtree may have been removed to // avoid firing redundant events. But, we still need to make sure any // accessibles parenting those shown nodes lose their child references. @@ -1764,17 +1757,17 @@ nsDocAccessible::InvalidateCacheSubtree( nsIEventStateManager *esm = presShell->GetPresContext()->EventStateManager(); NS_ENSURE_TRUE(esm,); if (!esm->IsHandlingUserInputExternal()) { // Changes during page load, but not caused by user input // Just invalidate accessible hierarchy and return, // otherwise the page load time slows down way too much nsAccessible *containerAccessible = - GetAccService()->GetContainerAccessible(childNode, PR_FALSE); + GetAccService()->GetCachedContainerAccessible(childNode); if (!containerAccessible) { containerAccessible = this; } containerAccessible->InvalidateChildren(); return; } // else: user input, so we must fall through and for full handling, @@ -1800,17 +1793,17 @@ nsDocAccessible::InvalidateCacheSubtree( printf("[Create %s %s]\n", NS_ConvertUTF16toUTF8(localName).get(), hasAccessible); else if (aChangeType == nsIAccessibilityService::NODE_REMOVE) printf("[Destroy %s %s]\n", NS_ConvertUTF16toUTF8(localName).get(), hasAccessible); else if (aChangeType == nsIAccessibilityService::NODE_SIGNIFICANT_CHANGE) printf("[Type change %s %s]\n", NS_ConvertUTF16toUTF8(localName).get(), hasAccessible); #endif nsAccessible *containerAccessible = - GetAccService()->GetContainerAccessible(childNode, PR_TRUE); + GetAccService()->GetCachedContainerAccessible(childNode); if (!containerAccessible) { containerAccessible = this; } if (!isShowing) { // Fire EVENT_HIDE. if (isHiding) { if (aChild) { @@ -1945,17 +1938,17 @@ nsDocAccessible::FireShowHideEvents(nsIN nsAccessible *accessible = nsnull; if (!aAvoidOnThisNode) { if (aEventType == nsIAccessibleEvent::EVENT_HIDE) { // Don't allow creation for accessibles when nodes going away accessible = GetCachedAccessible(aNode); } else { // Allow creation of new accessibles for show events - accessible = GetAccService()->GetAttachedAccessibleFor(aNode); + accessible = GetAccService()->GetAccessible(aNode); } } if (accessible) { // Found an accessible, so fire the show/hide on it and don't look further // into this subtree. nsRefPtr<nsAccEvent> event = new nsAccEvent(aEventType, accessible, aIsAsyncChange, aIsFromUserInput,
--- a/accessible/src/base/nsDocAccessible.h +++ b/accessible/src/base/nsDocAccessible.h @@ -108,17 +108,16 @@ public: virtual nsINode* GetNode() const { return mDocument; } // nsAccessible virtual nsresult GetRoleInternal(PRUint32 *aRole); virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState); virtual nsresult GetARIAState(PRUint32 *aState, PRUint32 *aExtraState); virtual void SetRoleMapEntry(nsRoleMapEntry* aRoleMapEntry); - virtual nsAccessible* GetParent(); #ifdef DEBUG_ACCDOCMGR virtual nsresult HandleAccEvent(nsAccEvent *aAccEvent); #endif // nsIAccessibleText NS_IMETHOD GetAssociatedEditor(nsIEditor **aEditor);
--- a/accessible/src/base/nsRootAccessible.cpp +++ b/accessible/src/base/nsRootAccessible.cpp @@ -453,109 +453,77 @@ nsRootAccessible::FireAccessibleFocusEve } void nsRootAccessible::FireCurrentFocusEvent() { if (IsDefunct()) return; + // Simulate a focus event so that we can reuse code that fires focus for + // container children like treeitems. nsCOMPtr<nsINode> focusedNode = GetCurrentFocus(); if (!focusedNode) { return; // No current focus } - // Simulate a focus event so that we can reuse code that fires focus for container children like treeitems nsCOMPtr<nsIDOMDocumentEvent> docEvent = do_QueryInterface(mDocument); if (docEvent) { nsCOMPtr<nsIDOMEvent> event; if (NS_SUCCEEDED(docEvent->CreateEvent(NS_LITERAL_STRING("Events"), getter_AddRefs(event))) && NS_SUCCEEDED(event->InitEvent(NS_LITERAL_STRING("focus"), PR_TRUE, PR_TRUE))) { - // Get the target node we really want for the event. - nsINode *targetNode = - GetAccService()->GetRelevantContentNodeFor(focusedNode); - if (targetNode) { - // If the focused element is document element or HTML body element - // then simulate the focus event for the document. - nsINode *document = targetNode->GetOwnerDoc(); - if (targetNode == nsCoreUtils::GetRoleContent(document)) { - HandleEventWithTarget(event, document); - return; - } - - // Otherwise simulate the focus event for currently focused node. - nsCOMPtr<nsIPrivateDOMEvent> privateEvent(do_QueryInterface(event)); - nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(focusedNode)); - privateEvent->SetTarget(target); - HandleEventWithTarget(event, targetNode); - } + nsCOMPtr<nsIPrivateDOMEvent> privateEvent(do_QueryInterface(event)); + nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(focusedNode)); + privateEvent->SetTarget(target); + HandleEvent(event); } } } //////////////////////////////////////////////////////////////////////////////// // nsIDOMEventListener -NS_IMETHODIMP nsRootAccessible::HandleEvent(nsIDOMEvent* aEvent) +NS_IMETHODIMP +nsRootAccessible::HandleEvent(nsIDOMEvent* aEvent) { - // Turn DOM events in accessibility events - // Get info about event and target - nsCOMPtr<nsIDOMNode> targetNode; - GetTargetNode(aEvent, getter_AddRefs(targetNode)); - if (!targetNode) - return NS_ERROR_FAILURE; + nsCOMPtr<nsIDOMNSEvent> nsevent(do_QueryInterface(aEvent)); + NS_ENSURE_STATE(nsevent); - nsCOMPtr<nsINode> node(do_QueryInterface(targetNode)); - return HandleEventWithTarget(aEvent, node); -} - + nsCOMPtr<nsIDOMEventTarget> domEventTarget; + nsevent->GetOriginalTarget(getter_AddRefs(domEventTarget)); + nsCOMPtr<nsINode> origTarget(do_QueryInterface(domEventTarget)); + NS_ENSURE_STATE(origTarget); -// nsRootAccessible protected member -nsresult nsRootAccessible::HandleEventWithTarget(nsIDOMEvent* aEvent, - nsINode* aTargetNode) -{ nsAutoString eventType; aEvent->GetType(eventType); - nsAutoString localName; - nsCOMPtr<nsIContent> targetContent(do_QueryInterface(aTargetNode)); - if (targetContent) - targetContent->NodeInfo()->GetName(localName); -#ifdef MOZ_XUL - PRBool isTree = localName.EqualsLiteral("tree"); -#endif -#ifdef DEBUG_A11Y - // Very useful for debugging, please leave this here. - if (eventType.EqualsLiteral("AlertActive")) { - printf("\ndebugging %s events for %s", NS_ConvertUTF16toUTF8(eventType).get(), NS_ConvertUTF16toUTF8(localName).get()); - } - if (localName.LowerCaseEqualsLiteral("textbox")) { - printf("\ndebugging %s events for %s", NS_ConvertUTF16toUTF8(eventType).get(), NS_ConvertUTF16toUTF8(localName).get()); - } -#endif - - nsAccessibilityService *accService = GetAccService(); - NS_ENSURE_TRUE(accService, NS_ERROR_FAILURE); nsCOMPtr<nsIWeakReference> weakShell = - nsCoreUtils::GetWeakShellFor(aTargetNode); + nsCoreUtils::GetWeakShellFor(origTarget); if (!weakShell) return NS_OK; - nsAccessible *accessible = - accService->GetAccessibleInWeakShell(aTargetNode, weakShell); + nsAccessible* accessible = + GetAccService()->GetAccessibleOrContainer(origTarget, weakShell); if (eventType.EqualsLiteral("popuphiding")) - return HandlePopupHidingEvent(aTargetNode, accessible); + return HandlePopupHidingEvent(origTarget, accessible); if (!accessible) return NS_OK; + nsINode* targetNode = accessible->GetNode(); + nsIContent* targetContent = targetNode->IsElement() ? + targetNode->AsElement() : nsnull; #ifdef MOZ_XUL + PRBool isTree = targetContent ? + targetContent->NodeInfo()->Equals(nsAccessibilityAtoms::tree, + kNameSpaceID_XUL) : PR_FALSE; + if (isTree) { nsRefPtr<nsXULTreeAccessible> treeAcc = do_QueryObject(accessible); NS_ASSERTION(treeAcc, "Accessible for xul:tree isn't nsXULTreeAccessible."); if (treeAcc) { if (eventType.EqualsLiteral("TreeViewChanged")) { treeAcc->TreeViewChanged(); @@ -582,17 +550,17 @@ nsresult nsRootAccessible::HandleEventWi nsIAccessibleStates::STATE_SELECTED)) != 0; nsRefPtr<nsAccEvent> accEvent = new nsAccStateChangeEvent(accessible, nsIAccessibleStates::STATE_CHECKED, PR_FALSE, isEnabled); nsEventShell::FireEvent(accEvent); if (isEnabled) - FireAccessibleFocusEvent(accessible, aTargetNode, aEvent); + FireAccessibleFocusEvent(accessible, targetNode, aEvent); return NS_OK; } if (eventType.EqualsLiteral("CheckboxStateChange")) { PRUint32 state = nsAccUtils::State(accessible); PRBool isEnabled = !!(state & nsIAccessibleStates::STATE_CHECKED); @@ -606,17 +574,17 @@ nsresult nsRootAccessible::HandleEventWi return NS_OK; } nsAccessible *treeItemAccessible = nsnull; #ifdef MOZ_XUL // If it's a tree element, need the currently selected item if (isTree) { nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelect = - do_QueryInterface(aTargetNode); + do_QueryInterface(targetNode); if (multiSelect) { PRInt32 treeIndex = -1; multiSelect->GetCurrentIndex(&treeIndex); if (treeIndex >= 0) { nsRefPtr<nsXULTreeAccessible> treeAcc = do_QueryObject(accessible); if (treeAcc) { treeItemAccessible = treeAcc->GetTreeItemAccessible(treeIndex); if (treeItemAccessible) @@ -636,19 +604,19 @@ nsresult nsRootAccessible::HandleEventWi new nsAccStateChangeEvent(accessible, nsIAccessibleStates::STATE_EXPANDED, PR_FALSE, isEnabled); nsEventShell::FireEvent(accEvent); return NS_OK; } if (treeItemAccessible && eventType.EqualsLiteral("select")) { // If multiselect tree, we should fire selectionadd or selection removed - if (gLastFocusedNode == aTargetNode) { + if (gLastFocusedNode == targetNode) { nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSel = - do_QueryInterface(aTargetNode); + do_QueryInterface(targetNode); nsAutoString selType; multiSel->GetSelType(selType); if (selType.IsEmpty() || !selType.EqualsLiteral("single")) { // XXX: We need to fire EVENT_SELECTION_ADD and EVENT_SELECTION_REMOVE // for each tree item. Perhaps each tree item will need to cache its // selection state and fire an event after a DOM "select" event when // that state changes. nsXULTreeAccessible::UpdateTreeSelection(); nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_SELECTION_WITHIN, @@ -659,47 +627,46 @@ nsresult nsRootAccessible::HandleEventWi nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_SELECTION, treeItemAccessible); return NS_OK; } } else #endif if (eventType.EqualsLiteral("focus")) { - if (aTargetNode == mDocument && mDocument != gLastFocusedNode) { + if (targetNode == mDocument && mDocument != gLastFocusedNode) { // Got focus event for the window, we will make sure that an accessible // focus event for initial focus is fired. We do this on a short timer // because the initial focus may not have been set yet. NS_DISPATCH_RUNNABLEMETHOD(FireCurrentFocusEvent, this) } // Keep a reference to the target node. We might want to change // it to the individual radio button or selected item, and send // the focus event to that. - nsCOMPtr<nsINode> focusedItem(aTargetNode); - + nsCOMPtr<nsINode> focusedItem = targetNode; if (!treeItemAccessible) { nsCOMPtr<nsIDOMXULSelectControlElement> selectControl = - do_QueryInterface(aTargetNode); + do_QueryInterface(targetNode); if (selectControl) { nsCOMPtr<nsIDOMXULMenuListElement> menuList = - do_QueryInterface(aTargetNode); + do_QueryInterface(targetNode); if (!menuList) { // Don't do this for menu lists, the items only get focused // when the list is open, based on DOMMenuitemActive events nsCOMPtr<nsIDOMXULSelectControlItemElement> selectedItem; selectControl->GetSelectedItem(getter_AddRefs(selectedItem)); if (selectedItem) focusedItem = do_QueryInterface(selectedItem); if (!focusedItem) return NS_OK; - accessible = accService->GetAccessibleInWeakShell(focusedItem, - weakShell); + accessible = GetAccService()->GetAccessibleInWeakShell(focusedItem, + weakShell); if (!accessible) return NS_OK; } } } FireAccessibleFocusEvent(accessible, focusedItem, aEvent); } else if (eventType.EqualsLiteral("blur")) { @@ -751,83 +718,57 @@ nsresult nsRootAccessible::HandleEventWi if (nsAccUtils::Role(containerParent) != nsIAccessibleRole::ROLE_COMBOBOX) { return NS_OK; } } } } if (!fireFocus) { nsCOMPtr<nsINode> realFocusedNode = GetCurrentFocus(); - nsCOMPtr<nsIContent> realFocusedContent = do_QueryInterface(realFocusedNode); - nsCOMPtr<nsIContent> targetContent = do_QueryInterface(aTargetNode); - nsIContent *containerContent = targetContent; + nsIContent* realFocusedContent = realFocusedNode->AsElement(); + nsIContent* containerContent = targetContent; while (containerContent) { nsCOMPtr<nsIDOMXULPopupElement> popup = do_QueryInterface(containerContent); if (popup || containerContent == realFocusedContent) { // If we're inside the focus or a popup we can fire focus events // for the changed active item fireFocus = PR_TRUE; break; } containerContent = containerContent->GetParent(); } } if (fireFocus) { // Always asynch, always from user input. - FireAccessibleFocusEvent(accessible, aTargetNode, aEvent, PR_TRUE, + FireAccessibleFocusEvent(accessible, targetNode, aEvent, PR_TRUE, PR_TRUE, eFromUserInput); } } else if (eventType.EqualsLiteral("DOMMenuBarActive")) { // Always asynch, always from user input nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_MENU_START, accessible, PR_TRUE, eFromUserInput); } else if (eventType.EqualsLiteral("DOMMenuBarInactive")) { // Always asynch, always from user input nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_MENU_END, accessible, PR_TRUE, eFromUserInput); FireCurrentFocusEvent(); } else if (eventType.EqualsLiteral("ValueChange")) { FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE, - aTargetNode, nsAccEvent::eRemoveDupes); + targetNode, nsAccEvent::eRemoveDupes); } #ifdef DEBUG else if (eventType.EqualsLiteral("mouseover")) { nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_DRAGDROP_START, accessible); } #endif return NS_OK; } -void nsRootAccessible::GetTargetNode(nsIDOMEvent *aEvent, nsIDOMNode **aTargetNode) -{ - *aTargetNode = nsnull; - - nsCOMPtr<nsIDOMNSEvent> nsevent(do_QueryInterface(aEvent)); - - if (!nsevent) - return; - - nsCOMPtr<nsIDOMEventTarget> domEventTarget; - nsevent->GetOriginalTarget(getter_AddRefs(domEventTarget)); - nsCOMPtr<nsIDOMNode> eventTarget(do_QueryInterface(domEventTarget)); - if (!eventTarget) - return; - - nsIAccessibilityService* accService = GetAccService(); - if (accService) { - nsresult rv = accService->GetRelevantContentNodeFor(eventTarget, - aTargetNode); - if (NS_SUCCEEDED(rv) && *aTargetNode) - return; - } - - NS_ADDREF(*aTargetNode = eventTarget); -} //////////////////////////////////////////////////////////////////////////////// // nsAccessNode PRBool nsRootAccessible::Init() { nsApplicationAccessible *applicationAcc = GetApplicationAccessible(); @@ -928,27 +869,16 @@ nsRootAccessible::GetRelationByType(PRUi nsDocAccessible *accDoc = nsAccUtils::GetDocAccessibleFor(contentTreeItem); return nsRelUtils::AddTarget(aRelationType, aRelation, accDoc); } return NS_OK; } //////////////////////////////////////////////////////////////////////////////// -// nsAccessible - -nsAccessible* -nsRootAccessible::GetParent() -{ - // Parent has been set in nsApplicationAccesible::AppendChild() when root - // accessible was initialized. - return mParent; -} - -//////////////////////////////////////////////////////////////////////////////// // Protected members nsresult nsRootAccessible::HandlePopupShownEvent(nsAccessible *aAccessible) { PRUint32 role = nsAccUtils::Role(aAccessible); if (role == nsIAccessibleRole::ROLE_MENUPOPUP) {
--- a/accessible/src/base/nsRootAccessible.h +++ b/accessible/src/base/nsRootAccessible.h @@ -82,17 +82,16 @@ public: // nsAccessNode virtual PRBool Init(); virtual void Shutdown(); // nsAccessible virtual nsresult GetRoleInternal(PRUint32 *aRole); virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState); - virtual nsAccessible* GetParent(); // nsRootAccessible NS_DECLARE_STATIC_IID_ACCESSOR(NS_ROOTACCESSIBLE_IMPL_CID) /** * Fire an accessible focus event for the current focusAccssible * and attach a new selection listener, if necessary. * @@ -121,29 +120,22 @@ public: protected: NS_DECL_RUNNABLEMETHOD(nsRootAccessible, FireCurrentFocusEvent) nsresult AddEventListeners(); nsresult RemoveEventListeners(); /** - * Process DOM events. - */ - nsresult HandleEventWithTarget(nsIDOMEvent* aEvent, nsINode* aTargetNode); - - static void GetTargetNode(nsIDOMEvent *aEvent, nsIDOMNode **aTargetNode); - - /** - * Process "popupshown" event. Used by HandleEventWithTarget(). + * Process "popupshown" event. Used by HandleEvent(). */ nsresult HandlePopupShownEvent(nsAccessible *aAccessible); /* - * Process "popuphiding" event. Used by HandleEventWithTarget(). + * Process "popuphiding" event. Used by HandleEvent(). */ nsresult HandlePopupHidingEvent(nsINode *aNode, nsAccessible *aAccessible); #ifdef MOZ_XUL nsresult HandleTreeRowCountChangedEvent(nsIDOMEvent *aEvent, nsXULTreeAccessible *aAccessible); nsresult HandleTreeInvalidatedEvent(nsIDOMEvent *aEvent, nsXULTreeAccessible *aAccessible);
--- a/accessible/src/html/nsHTMLSelectAccessible.cpp +++ b/accessible/src/html/nsHTMLSelectAccessible.cpp @@ -366,30 +366,32 @@ nsHTMLSelectListAccessible::CacheChildre } //////////////////////////////////////////////////////////////////////////////// // nsHTMLSelectListAccessible protected void nsHTMLSelectListAccessible::CacheOptSiblings(nsIContent *aParentContent) { + nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(mWeakShell)); PRUint32 numChildren = aParentContent->GetChildCount(); for (PRUint32 count = 0; count < numChildren; count ++) { nsIContent *childContent = aParentContent->GetChildAt(count); if (!childContent->IsHTML()) { continue; } nsCOMPtr<nsIAtom> tag = childContent->Tag(); if (tag == nsAccessibilityAtoms::option || tag == nsAccessibilityAtoms::optgroup) { // Get an accessible for option or optgroup and cache it. - nsAccessible *accessible = - GetAccService()->GetAccessibleInWeakShell(childContent, mWeakShell); + nsRefPtr<nsAccessible> accessible = + GetAccService()->GetOrCreateAccessible(childContent, presShell, + mWeakShell); if (accessible) { mChildren.AppendElement(accessible); accessible->SetParent(this); } // Deep down into optgroup element. if (tag == nsAccessibilityAtoms::optgroup) CacheOptSiblings(childContent); @@ -927,21 +929,29 @@ nsHTMLComboboxAccessible::CacheChildren( return; if (!mListAccessible) { mListAccessible = new nsHTMLComboboxListAccessible(mParent, mContent, mWeakShell); if (!mListAccessible) return; - mListAccessible->Init(); + // Initialize and put into cache. + if (!mListAccessible->Init()) { + mListAccessible->Shutdown(); + return; + } } mChildren.AppendElement(mListAccessible); mListAccessible->SetParent(this); + + // Cache combobox option accessibles so that we build complete accessible tree + // for combobox. + mListAccessible->EnsureChildren(); } void nsHTMLComboboxAccessible::Shutdown() { nsAccessibleWrap::Shutdown(); if (mListAccessible) { @@ -1166,15 +1176,8 @@ void nsHTMLComboboxListAccessible::GetBo if (!frame) { *aBoundingFrame = nsnull; return; } *aBoundingFrame = frame->GetParent(); aBounds = (*aBoundingFrame)->GetRect(); } - -// nsHTMLComboboxListAccessible. nsAccessible public mehtod -nsAccessible* -nsHTMLComboboxListAccessible::GetParent() -{ - return mParent; -}
--- a/accessible/src/html/nsHTMLSelectAccessible.h +++ b/accessible/src/html/nsHTMLSelectAccessible.h @@ -271,12 +271,11 @@ public: NS_IMETHOD GetUniqueID(void **aUniqueID); // nsAccessNode virtual nsIFrame* GetFrame(); // nsAccessible virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState); virtual void GetBoundsRect(nsRect& aBounds, nsIFrame** aBoundingFrame); - virtual nsAccessible* GetParent(); }; #endif
--- a/accessible/src/html/nsHTMLTextAccessible.cpp +++ b/accessible/src/html/nsHTMLTextAccessible.cpp @@ -342,22 +342,16 @@ nsHTMLListBulletAccessible::AppendTextTo PRUint32 maxLength = mBulletText.Length() - aStartOffset; if (aLength > maxLength) { aLength = maxLength; } aText += Substring(mBulletText, aStartOffset, aLength); return NS_OK; } -nsAccessible* -nsHTMLListBulletAccessible::GetParent() -{ - return mParent; -} - //////////////////////////////////////////////////////////////////////////////// // nsHTMLListAccessible //////////////////////////////////////////////////////////////////////////////// nsHTMLListAccessible:: nsHTMLListAccessible(nsIContent *aContent, nsIWeakReference *aShell) : nsHyperTextAccessibleWrap(aContent, aShell) {
--- a/accessible/src/html/nsHTMLTextAccessible.h +++ b/accessible/src/html/nsHTMLTextAccessible.h @@ -124,18 +124,16 @@ public: virtual void Shutdown(); // nsAccessible virtual nsresult GetRoleInternal(PRUint32 *aRole); virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState); virtual nsresult AppendTextTo(nsAString& aText, PRUint32 aStartOffset, PRUint32 aLength); - virtual nsAccessible* GetParent(); - 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;
--- a/accessible/src/msaa/nsAccessibleWrap.cpp +++ b/accessible/src/msaa/nsAccessibleWrap.cpp @@ -1676,17 +1676,17 @@ nsAccessibleWrap::FirePlatformEvent(nsAc if (!childID) return NS_OK; // Can't fire an event without a child ID // See if we're in a scrollable area with its own window nsAccessible *newAccessible = nsnull; if (eventType == nsIAccessibleEvent::EVENT_HIDE) { // Don't use frame from current accessible when we're hiding that // accessible. - newAccessible = accessible->GetParent(); + newAccessible = accessible->GetCachedParent(); } else { newAccessible = accessible; } HWND hWnd = GetHWNDFor(newAccessible); NS_ENSURE_TRUE(hWnd, NS_ERROR_FAILURE); // Gecko uses two windows for every scrollable area. One window contains
--- a/accessible/src/xforms/nsXFormsAccessible.cpp +++ b/accessible/src/xforms/nsXFormsAccessible.cpp @@ -113,27 +113,30 @@ nsXFormsAccessible::CacheSelectChildren( container = do_QueryInterface(mContent); nsCOMPtr<nsIDOMNodeList> children; sXFormsService->GetSelectChildrenFor(container, getter_AddRefs(children)); if (!children) return; + nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(mWeakShell)); + PRUint32 length = 0; children->GetLength(&length); for (PRUint32 index = 0; index < length; index++) { nsCOMPtr<nsIDOMNode> DOMChild; children->Item(index, getter_AddRefs(DOMChild)); if (!DOMChild) continue; nsCOMPtr<nsIContent> child(do_QueryInterface(DOMChild)); - nsAccessible *accessible = GetAccService()->GetAttachedAccessibleFor(child); + nsRefPtr<nsAccessible> accessible = + GetAccService()->GetOrCreateAccessible(child, presShell, mWeakShell); if (!accessible) continue; mChildren.AppendElement(accessible); accessible->SetParent(this); } }
--- a/accessible/src/xul/nsXULColorPickerAccessible.cpp +++ b/accessible/src/xul/nsXULColorPickerAccessible.cpp @@ -161,16 +161,18 @@ nsXULColorPickerAccessible::GetRoleInter void nsXULColorPickerAccessible::CacheChildren() { nsAccTreeWalker walker(mWeakShell, mContent, PR_TRUE); nsRefPtr<nsAccessible> child; while ((child = walker.GetNextChild())) { + // XXX: do not call nsAccessible::GetRole() while accessible not in tree + // (bug 574588). PRUint32 role = nsAccUtils::Role(child); // Get an accessbile for menupopup or panel elements. if (role == nsIAccessibleRole::ROLE_ALERT) { mChildren.AppendElement(child); child->SetParent(this); return;
--- a/accessible/src/xul/nsXULFormControlAccessible.cpp +++ b/accessible/src/xul/nsXULFormControlAccessible.cpp @@ -207,16 +207,18 @@ nsXULButtonAccessible::CacheChildren() nsRefPtr<nsAccessible> menupopupAccessible; nsRefPtr<nsAccessible> buttonAccessible; nsAccTreeWalker walker(mWeakShell, mContent, PR_TRUE); nsRefPtr<nsAccessible> child; while ((child = walker.GetNextChild())) { + // XXX: do not call nsAccessible::GetRole() while accessible not in tree + // (bug 574588). PRUint32 role = nsAccUtils::Role(child); if (role == nsIAccessibleRole::ROLE_MENUPOPUP) { // Get an accessbile for menupopup or panel elements. menupopupAccessible.swap(child); } else if (isMenuButton && role == nsIAccessibleRole::ROLE_PUSHBUTTON) { // Button type="menu-button" contains a real button. Get an accessible
--- a/accessible/src/xul/nsXULTreeAccessible.cpp +++ b/accessible/src/xul/nsXULTreeAccessible.cpp @@ -1035,22 +1035,16 @@ nsXULTreeItemAccessibleBase::GetStateInt mTree->GetFirstVisibleRow(&firstVisibleRow); mTree->GetLastVisibleRow(&lastVisibleRow); if (mRow < firstVisibleRow || mRow > lastVisibleRow) *aState |= nsIAccessibleStates::STATE_INVISIBLE; return NS_OK; } -nsAccessible* -nsXULTreeItemAccessibleBase::GetParent() -{ - return IsDefunct() ? nsnull : mParent.get(); -} - //////////////////////////////////////////////////////////////////////////////// // nsXULTreeItemAccessibleBase: nsAccessible protected methods void nsXULTreeItemAccessibleBase::DispatchClickEvent(nsIContent *aContent, PRUint32 aActionIndex) { if (IsDefunct())
--- a/accessible/src/xul/nsXULTreeAccessible.h +++ b/accessible/src/xul/nsXULTreeAccessible.h @@ -194,17 +194,16 @@ public: NS_IMETHOD DoAction(PRUint8 aIndex); // nsAccessNode virtual PRBool IsDefunct(); virtual void Shutdown(); // nsAccessible virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState); - virtual nsAccessible* GetParent(); // nsXULTreeItemAccessibleBase NS_DECLARE_STATIC_IID_ACCESSOR(NS_XULTREEITEMBASEACCESSIBLE_IMPL_CID) /** * Return row index associated with the accessible. */ PRInt32 GetRowIndex() const { return mRow; }
--- a/accessible/src/xul/nsXULTreeGridAccessible.cpp +++ b/accessible/src/xul/nsXULTreeGridAccessible.cpp @@ -1197,22 +1197,16 @@ nsXULTreeGridCellAccessible::GetStateInt mTreeView->GetCellValue(mRow, mColumn, checked); if (checked.EqualsIgnoreCase("true")) *aStates |= nsIAccessibleStates::STATE_CHECKED; } return NS_OK; } -nsAccessible* -nsXULTreeGridCellAccessible::GetParent() -{ - return IsDefunct() ? nsnull : mParent.get(); -} - //////////////////////////////////////////////////////////////////////////////// // nsXULTreeGridCellAccessible: public implementation PRInt32 nsXULTreeGridCellAccessible::GetColumnIndex() const { PRInt32 index = 0; nsCOMPtr<nsITreeColumn> column = mColumn;
--- a/accessible/src/xul/nsXULTreeGridAccessible.h +++ b/accessible/src/xul/nsXULTreeGridAccessible.h @@ -157,18 +157,16 @@ public: virtual PRBool IsDefunct(); virtual PRBool Init(); // nsAccessible virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes); virtual nsresult GetRoleInternal(PRUint32 *aRole); virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState); - virtual nsAccessible* GetParent(); - // nsXULTreeGridCellAccessible NS_DECLARE_STATIC_IID_ACCESSOR(NS_XULTREEGRIDCELLACCESSIBLE_IMPL_CID) /** * Return index of the column. */ PRInt32 GetColumnIndex() const;
--- a/accessible/tests/mochitest/events/test_docload.html +++ b/accessible/tests/mochitest/events/test_docload.html @@ -122,16 +122,21 @@ { // Get application root accessible. var docAcc = getAccessible(document); while (docAcc) { this.mRootAcc = docAcc; try { docAcc = docAcc.parent; } catch (e) { + // XXX: it may randomaly fail on propertypage accessible of browser's + // tabbbrowser if nsIAccessible::parent returns cached parent only. + // This should gone after bug 572951. + // Error: failed | Can't get parent for [ 'panel1277435313424' , + // role: propertypage] ok(false, "Can't get parent for " + prettyName(docAcc)); throw e; } } this.eventSeq = [ new invokerChecker(EVENT_REORDER, this.mRootAcc) ];
--- a/accessible/tests/mochitest/events/test_text.html +++ b/accessible/tests/mochitest/events/test_text.html @@ -56,16 +56,17 @@ */ function removeChildSpan(aID) { this.__proto__ = new textRemoveInvoker(aID, 0, 5, "33322"); this.invoke = function removeChildSpan_invoke() { // remove HTML span, a first child of the node + ensureAccessibleTree(this.DOMNode); this.DOMNode.removeChild(this.DOMNode.firstChild); } this.getID = function removeChildSpan_getID() { return "Remove inaccessible span containing accessible nodes" + prettyName(aID); } }
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/setup.js +++ b/browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/setup.js @@ -57,17 +57,17 @@ const POPUP_REMINDER_INTERVAL = "extensi const ALWAYS_SUBMIT_DATA = "extensions.testpilot.alwaysSubmitData"; const LOG_FILE_NAME = "TestPilotErrorLog.log"; let TestPilotSetup = { didReminderAfterStartup: false, startupComplete: false, _shortTimer: null, _longTimer: null, - _remoteExperimentLoader: null, + _remoteExperimentLoader: null, // TODO make this a lazy initializer too? taskList: [], version: "", // Lazy initializers: __application: null, get _application() { if (this.__application == null) { this.__application = Cc["@mozilla.org/fuel/application;1"] @@ -367,20 +367,26 @@ let TestPilotSetup = { // exists. No excuse to ever be running two copies of the same task. this.taskList.push(testPilotTask); }, _showNotification: function TPS__showNotification(task, fragile, text, title, iconClass, showSubmit, showAlwaysSubmitCheckbox, linkText, linkUrl, - isExtensionUpdate) { + isExtensionUpdate, + onCloseCallback) { + /* TODO: Refactor the arguments of this function, it's getting really + * unweildly.... maybe pass in an object, or even make a notification an + * object that you create and then call .show() on. */ + // If there are multiple windows, show notifications in the frontmost // window. - let doc = this._getFrontBrowserWindow().document; + let window = this._getFrontBrowserWindow(); + let doc = window.document; let popup = doc.getElementById("pilot-notification-popup"); let anchor; if (this._isFfx4BetaVersion()) { /* If we're in the Ffx4Beta version, popups come down from feedback * button, but if we're in the standalone extension version, they * come up from status bar icon. */ anchor = doc.getElementById("feedback-menu-button"); @@ -417,24 +423,24 @@ let TestPilotSetup = { alwaysSubmitCheckbox.setAttribute("hidden", !showAlwaysSubmitCheckbox); if (showSubmit) { if (isExtensionUpdate) { submitBtn.setAttribute("label", this._stringBundle.GetStringFromName( "testpilot.notification.update")); submitBtn.onclick = function() { this._extensionUpdater.check(EXTENSION_ID); - self._hideNotification(); + self._hideNotification(window, onCloseCallback); }; } else { submitBtn.setAttribute("label", this._stringBundle.GetStringFromName("testpilot.submit")); // Functionality for submit button: submitBtn.onclick = function() { - self._hideNotification(); + self._hideNotification(window, onCloseCallback); if (showAlwaysSubmitCheckbox && alwaysSubmitCheckbox.checked) { self._prefs.setValue(ALWAYS_SUBMIT_DATA, true); } task.upload( function(success) { if (success) { self._showNotification( task, true, self._stringBundle.GetStringFromName( @@ -459,46 +465,52 @@ let TestPilotSetup = { link.setAttribute("class", "notification-link"); link.onclick = function(event) { if (event.button == 0) { if (task) { task.loadPage(); } else { self._openChromeless(linkUrl); } - self._hideNotification(); + self._hideNotification(window, onCloseCallback); } }; link.setAttribute("hidden", false); } else { link.setAttribute("hidden", true); } closeBtn.onclick = function() { - self._hideNotification(); + self._hideNotification(window, onCloseCallback); }; // Show the popup: popup.hidden = false; popup.setAttribute("open", "true"); popup.openPopup( anchor, "after_end"); }, _openChromeless: function TPS__openChromeless(url) { let window = this._getFrontBrowserWindow(); window.TestPilotWindowUtils.openChromeless(url); }, - _hideNotification: function TPS__hideNotification() { - let window = this._getFrontBrowserWindow(); + _hideNotification: function TPS__hideNotification(window, onCloseCallback) { + /* Note - we take window as an argument instead of just using the frontmost + * window because the window order might have changed since the notification + * appeared and we want to be sure we close the notification in the same + * window as we opened it in! */ let popup = window.document.getElementById("pilot-notification-popup"); popup.hidden = true; popup.setAttribute("open", "false"); popup.removeAttribute("tpisextensionupdate"); popup.hidePopup(); + if (onCloseCallback) { + onCloseCallback(); + } }, _isShowingUpdateNotification : function() { let window = this._getFrontBrowserWindow(); let popup = window.document.getElementById("pilot-notification-popup"); return popup.hasAttribute("tpisextensionupdate"); }, @@ -538,36 +550,38 @@ let TestPilotSetup = { } } // If there's no finished test, next highest priority is new tests that // are starting... if (this._prefs.getValue(POPUP_SHOW_ON_NEW, false)) { for (i = 0; i < this.taskList.length; i++) { task = this.taskList[i]; - if (task.status == TaskConstants.STATUS_STARTING || + if (task.status == TaskConstants.STATUS_PENDING || task.status == TaskConstants.STATUS_NEW) { if (task.taskType == TaskConstants.TYPE_EXPERIMENT) { this._showNotification( - task, true, + task, false, this._stringBundle.formatStringFromName( "testpilot.notification.newTestPilotStudy.message", [task.title], 1), this._stringBundle.GetStringFromName( "testpilot.notification.newTestPilotStudy"), "new-study", false, false, this._stringBundle.GetStringFromName("testpilot.moreInfo"), - task.defaultUrl); - // Having shown the notification, update task status so that this - // notification won't be shown again. - task.changeStatus(TaskConstants.STATUS_IN_PROGRESS, true); + task.defaultUrl, false, function() { + /* on close callback (Bug 575767) -- when the "new study + * starting" popup is dismissed, then the study can start. */ + task.changeStatus(TaskConstants.STATUS_IN_PROGRESS, true); + TestPilotSetup.reloadRemoteExperiments(); + }); return; } else if (task.taskType == TaskConstants.TYPE_SURVEY) { this._showNotification( - task, true, + task, false, this._stringBundle.formatStringFromName( "testpilot.notification.newTestPilotSurvey.message", [task.title], 1), this._stringBundle.GetStringFromName( "testpilot.notification.newTestPilotSurvey"), "new-study", false, false, this._stringBundle.GetStringFromName("testpilot.moreInfo"), task.defaultUrl);
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/tasks.js +++ b/browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/tasks.js @@ -198,16 +198,17 @@ var TestPilotTask = { onWindowClosed: function TestPilotTask_onWindowClosed(window) { }, onUrlLoad: function TestPilotTask_onUrlLoad(url) { }, onDetailPageOpened: function TestPilotTask_onDetailPageOpened(){ + // TODO fold this into loadPage()? }, checkDate: function TestPilotTask_checkDate() { }, changeStatus: function TPS_changeStatus(newStatus, suppressNotification) { // TODO we always suppress notifications except when new status is // "finished"; maybe remove that argument and only fire notification @@ -439,24 +440,19 @@ TestPilotExperiment.prototype = { break; } if (!waitForData) { callback(content); } }, experimentIsRunning: function TestPilotExperiment_isRunning() { - if (this._optInRequired) { - return (this._status == TaskConstants.STATUS_STARTING || - this._status == TaskConstants.STATUS_IN_PROGRESS); - } else { - // Tests that don't require extra opt-in should start running even - // if you haven't seen them yet. - return (this._status < TaskConstants.STATUS_FINISHED); - } + // bug 575767 + return (this._status == TaskConstants.STATUS_STARTING || + this._status == TaskConstants.STATUS_IN_PROGRESS); }, // Pass events along to handlers: onNewWindow: function TestPilotExperiment_onNewWindow(window) { this._logger.trace("Experiment.onNewWindow called."); if (this.experimentIsRunning()) { this._handlers.onNewWindow(window); } @@ -594,21 +590,33 @@ TestPilotExperiment.prototype = { numTimesRun++; this._logger.trace("Test recurring... incrementing " + RECUR_TIMES_PREF_PREFIX + this._id + " to " + numTimesRun); Application.prefs.setValue( RECUR_TIMES_PREF_PREFIX + this._id, numTimesRun ); this._logger.trace("Incremented it."); } } - // No-opt-in required tests skip PENDING and go straight to STARTING. + // If the notify-on-new-study pref is turned off, and the test doesn't + // require opt-in, then it can jump straight ahead to STARTING. if (!this._optInRequired && - this._status < TaskConstants.STATUS_STARTING && + !Application.prefs.getValue("extensions.testpilot.popup.showOnNewStudy", + false) && + (this._status == TaskConstants.STATUS_NEW || + this._status == TaskConstants.STATUS_PENDING)) { + this._logger.info("Skipping pending and going straight to starting."); + this.changeStatus(TaskConstants.STATUS_STARTING, true); + } + + // If a study is STARTING, and we're in the right date range, + // then start it, and move it to IN_PROGRESS. + if ( this._status == TaskConstants.STATUS_STARTING && currentDate >= this._startDate && currentDate <= this._endDate) { + this._logger.info("Study now starting."); let uuidGenerator = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator); let uuid = uuidGenerator.generateUUID().toString(); // remove the brackets from the generated UUID if (uuid.indexOf("{") == 0) { uuid = uuid.substring(1, (uuid.length - 1)); } // clear the data before starting.
--- a/browser/base/content/browser.css +++ b/browser/base/content/browser.css @@ -247,26 +247,22 @@ window[chromehidden~="toolbar"] toolbar: #identity-popup-content-box.unknownIdentity > #identity-popup-content-host , #identity-popup-content-box.unknownIdentity > #identity-popup-content-owner , #identity-popup-content-box.verifiedIdentity > #identity-popup-connectedToLabel2 , #identity-popup-content-box.verifiedDomain > #identity-popup-connectedToLabel2 { display: none; } /* Full Screen UI */ + #fullscr-toggler { - display: none; - min-height: 1px; height: 1px; background: black; - border-style: none; - -moz-appearance: none; } -#navigator-toolbox[inFullscreen="true"] > #fullscr-toggler, #nav-bar[mode="text"] > #window-controls > toolbarbutton > .toolbarbutton-icon { display: -moz-box; } #nav-bar[mode="text"] > #window-controls > toolbarbutton > .toolbarbutton-text { display: none; }
--- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -3513,22 +3513,20 @@ var FullScreen = document.getElementById("View:FullScreen").setAttribute("checked", !window.fullScreen); if (!window.fullScreen) { // Add a tiny toolbar to receive mouseover and dragenter events, and provide affordance. // This will help simulate the "collapse" metaphor while also requiring less code and // events than raw listening of mouse coords. let fullScrToggler = document.getElementById("fullscr-toggler"); if (!fullScrToggler) { - fullScrToggler = document.createElement("toolbar"); + fullScrToggler = document.createElement("hbox"); fullScrToggler.id = "fullscr-toggler"; - fullScrToggler.setAttribute("customizable", "false"); - fullScrToggler.setAttribute("moz-collapsed", "true"); - var navBar = document.getElementById("nav-bar"); - navBar.parentNode.insertBefore(fullScrToggler, navBar); + fullScrToggler.collapsed = true; + gNavToolbox.parentNode.insertBefore(fullScrToggler, gNavToolbox.nextSibling); } fullScrToggler.addEventListener("mouseover", this._expandCallback, false); fullScrToggler.addEventListener("dragenter", this._expandCallback, false); if (gPrefService.getBoolPref("browser.fullscreen.autohide")) gBrowser.mPanelContainer.addEventListener("mousemove", this._collapseCallback, false); @@ -3719,22 +3717,21 @@ var FullScreen = gBrowser.mPanelContainer.addEventListener("mousemove", this._collapseCallback, false); } else { gBrowser.mPanelContainer.removeEventListener("mousemove", this._collapseCallback, false); } - var allFSToolbars = document.getElementsByTagNameNS(this._XULNS, "toolbar"); - for (var i = 0; i < allFSToolbars.length; i++) { - if (allFSToolbars[i].getAttribute("fullscreentoolbar") == "true") - allFSToolbars[i].setAttribute("moz-collapsed", !aShow); - } - document.getElementById("fullscr-toggler").setAttribute("moz-collapsed", aShow); + // Hiding/collapsing the toolbox interferes with the tab bar's scrollbox, + // so we just move it off-screen instead. See bug 430687. + gNavToolbox.style.marginTop = aShow ? "" : -gNavToolbox.clientHeight + "px"; + + document.getElementById("fullscr-toggler").collapsed = aShow; this._isChromeCollapsed = !aShow; if (gPrefService.getIntPref("browser.fullscreen.animateUp") == 2) this._shouldAnimate = true; }, showXULChrome: function(aTag, aShow) { var els = document.getElementsByTagNameNS(this._XULNS, aTag);
--- a/browser/base/content/safeMode.js +++ b/browser/base/content/safeMode.js @@ -16,32 +16,34 @@ # # The Initial Developer of the Original Code is # Mike Connor. # Portions created by the Initial Developer are Copyright (C) 2005 # the Initial Developer. All Rights Reserved. # # Contributor(s): # Mike Connor <mconnor@steelgryphon.com> -# Asaf Romano <mozilla.mano@sent.com> +# Asaf Romano <mano@mozilla.com> # # 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 ***** +Components.utils.import("resource://gre/modules/AddonManager.jsm"); + function restartApp() { var appStartup = Components.classes["@mozilla.org/toolkit/app-startup;1"] .getService(Components.interfaces.nsIAppStartup); appStartup.quit(appStartup.eForceQuit | appStartup.eRestart); } function clearAllPrefs() { var prefService = Components.classes["@mozilla.org/preferences-service;1"] @@ -73,37 +75,31 @@ function deleteLocalstore() { var directoryService = Components.classes[nsIDirectoryServiceContractID] .getService(nsIProperties); var localstoreFile = directoryService.get("LStoreS", Components.interfaces.nsIFile); if (localstoreFile.exists()) localstoreFile.remove(false); } function disableAddons() { - // Disable addons - const nsIUpdateItem = Components.interfaces.nsIUpdateItem; - var em = Components.classes["@mozilla.org/extensions/manager;1"] - .getService(Components.interfaces.nsIExtensionManager); - var type = nsIUpdateItem.TYPE_EXTENSION + nsIUpdateItem.TYPE_LOCALE; - var items = em.getItemList(type); - for (var i = 0; i < items.length; ++i) - em.disableItem(items[i].id); - - // Select the default theme - var prefB = Components.classes["@mozilla.org/preferences-service;1"] - .getService(Components.interfaces.nsIPrefBranch); - if (prefB.prefHasUserValue("general.skins.selectedSkin")) - prefB.clearUserPref("general.skins.selectedSkin"); - - // Disable plugins - var phs = Components.classes["@mozilla.org/plugin/host;1"] - .getService(Components.interfaces.nsIPluginHost); - var plugins = phs.getPluginTags(); - for (i = 0; i < plugins.length; ++i) - plugins[i].disabled = true; + AddonManager.getAllAddons(function(aAddons) { + aAddons.forEach(function(aAddon) { + if (aAddon.type == "theme") { + // Setting userDisabled to false on the default theme activates it, + // disables all other themes and deactivates the applied persona, if + // any. + const DEFAULT_THEME_ID = "{972ce4c6-7e08-4474-a285-3208198ce6fd}"; + if (aAddon.id == DEFAULT_THEME_ID) + aAddon.userDisabled = false; + } + else { + aAddon.userDisabled = true; + } + }); + }); } function restoreDefaultSearchEngines() { var searchService = Components.classes["@mozilla.org/browser/search-service;1"] .getService(Components.interfaces.nsIBrowserSearchService); searchService.restoreDefaultEngines(); }
--- a/browser/components/places/Makefile.in +++ b/browser/components/places/Makefile.in @@ -38,17 +38,17 @@ DEPTH = ../../.. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(DEPTH)/config/autoconf.mk -DIRS = public src +DIRS = src ifdef ENABLE_TESTS DIRS += tests endif include $(topsrcdir)/config/rules.mk XPIDL_FLAGS += -I$(topsrcdir)/browser/components/
--- a/browser/components/places/content/browserPlacesViews.js +++ b/browser/components/places/content/browserPlacesViews.js @@ -490,17 +490,25 @@ PlacesViewBase.prototype = { // nothing to be done when the title changes. if (elt == this._rootElt) return; // Here we need the <menu>. if (elt.localName == "menupopup") elt = elt.parentNode; - elt.label = aNewTitle || PlacesUIUtils.getBestTitle(aPlacesNode); + if (!aNewTitle && elt.localName != "toolbarbutton") { + // Many users consider toolbars as shortcuts containers, so explicitly + // allow empty labels on toolbarbuttons. For any other element try to be + // smarter, guessing a title from the uri. + elt.label = PlacesUIUtils.getBestTitle(aPlacesNode); + } + else { + elt.label = aNewTitle; + } }, nodeRemoved: function PVB_nodeRemoved(aParentPlacesNode, aPlacesNode, aIndex) { let parentElt = aParentPlacesNode._DOMElement; let elt = aPlacesNode._DOMElement; if (!parentElt)
deleted file mode 100644 --- a/browser/components/places/public/Makefile.in +++ /dev/null @@ -1,52 +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 Places code. -# -# The Initial Developer of the Original Code is -# Google Inc. -# Portions created by the Initial Developer are Copyright (C) 2005 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Brett Wilson <brettw@gmail.com> -# -# 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 ***** - -DEPTH = ../../../.. -topsrcdir = @top_srcdir@ -srcdir = @srcdir@ -VPATH = @srcdir@ - -include $(DEPTH)/config/autoconf.mk - -MODULE = browserplaces -XPIDL_MODULE = browserplaces - -XPIDLSRCS = nsIPlacesTransactionsService.idl \ - $(NULL) - -include $(topsrcdir)/config/rules.mk
deleted file mode 100644 --- a/browser/components/places/public/nsIPlacesTransactionsService.idl +++ /dev/null @@ -1,381 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Places. - * - * The Initial Developer of the Original Code is Mozilla Foundation - * - * Portions created by the Initial Developer are Copyright (C) 2007 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Sungjoon Steve Won <stevewon@gmail.com> (Original Author) - * Asaf Romano <mano@mozilla.com> - * - * 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 "nsISupports.idl" -#include "nsITransactionManager.idl" - -interface nsIVariant; -interface nsIURI; -interface nsIMicrosummary; -interface nsITransaction; - -/** - * nsIPlacesTransactionService is a service designed to handle - * nsITransactions that correspond to changes in Places. It is here as a - * service so that we can keep the transactions around without holding onto - * the global scope of a js window. - * - * NOTE: If you are interacting directly with the Places back-end, and you - * need to transactionalize a large amount of changes, look at - * nsINavBookmarksService.runInBatchMode. - */ - -[scriptable, uuid(32eee5da-2bc7-4d18-8a54-a8ff0dec4d2a)] -interface nsIPlacesTransactionsService : nsITransactionManager -{ - /** - * Transaction for performing several Places Transactions in a single batch. - * - * @param aName - * title of the aggregate transactions - * @param aTransactions - * an array of transactions to perform - * @returns nsITransaction object - */ - nsITransaction aggregateTransactions(in AString aName, - in nsIVariant aTransactions); - - /** - * Transaction for creating a new folder item. - * - * @param aName - * the name of the new folder - * @param aContainerId - * the identifier of the folder in which the new folder should be - * added. - * @param [optional] aIndex - * the index of the item in aContainer, pass -1 or nothing to create - * the item at the end of aContainer. - * @param [optional] aAnnotations - * the annotations to set for the new folder. - * @param [optional] aChildItemsTransactions - * array of transactions for items to be created under the new folder. - * @returns nsITransaction object - */ - nsITransaction createFolder(in AString aName, in long long aContainerId, - [optional] in long long aIndex, - [optional] in nsIVariant aAnnotations, - [optional] in nsIVariant aChildItemsTransactions); - - /** - * Transaction for creating a new bookmark item - * - * @param aURI - * the uri of the new bookmark (nsIURI) - * @param aContainerId - * the identifier of the folder in which the bookmark should be added. - * @param [optional] aIndex - * the index of the item in aContainer, pass -1 or nothing to create - * the item at the end of aContainer. - * @param [optional] aTitle - * the title of the new bookmark. - * @param [optional] aKeyword - * the keyword of the new bookmark. - * @param [optional] aAnnotations - * the annotations to set for the new bookmark. - * @param [optional] aChildTransactions - * child transactions to commit after creating the bookmark. Prefer - * using any of the arguments above if possible. In general, a child - * transations should be used only if the change it does has to be - * reverted manually when removing the bookmark item. - * a child transaction must support setting its bookmark-item - * identifier via an "id" js setter. - * @returns nsITransaction object - */ - nsITransaction createItem(in nsIURI aURI, in long long aContainerId, - [optional] in long long aIndex, - [optional] in AString aTitle, - [optional] in AString aKeyword, - [optional] in nsIVariant aAnnotations, - [optional] in nsIVariant aChildTransactions); - - /** - * Transaction for creating a new separator item - * - * @param aContainerId - * the identifier of the folder in which the separator should be - * added. - * @param [optional] aIndex - * the index of the item in aContainer, pass -1 or nothing to create - * the separator at the end of aContainer. - * @returns nsITransaction object - */ - nsITransaction createSeparator(in long long aContainerId, - [optional] in long long aIndex); - - /** - * Transaction for creating a new live-bookmark item. - * - * @see nsILivemarksService::createLivemark for documentation regarding the - * first three arguments. - * - * @param aContainerId - * the identifier of the folder in which the live-bookmark should be - * added. - * @param [optional] aIndex - * the index of the item in aContainer, pass -1 or nothing to create - * the item at the end of aContainer. - * @param [optional] aAnnotations - * the annotations to set for the new live-bookmark. - * @returns nsITransaction object - */ - nsITransaction createLivemark(in nsIURI aFeedURI, - in nsIURI aSiteURI, - in AString aName, - in long long aContainerId, - [optional] in long long aIndex, - [optional] in nsIVariant aAnnotations); - - /** - * Transaction for moving an Item. - * - * @param aItemId - * the id of the item to move - * @param aNewContainerId - * id of the new container to move to - * @param aNewIndex - * index of the new position to move to - * @returns nsITransaction object - */ - nsITransaction moveItem(in long long aItemId, - in long long aNewContainerId, - in long long aNewIndex); - - /** - * Transaction for removing an Item - * - * @param aItemId - * id of the item to remove - * @returns nsITransaction object - */ - nsITransaction removeItem(in long long aItemId); - - /** - * Transaction for editting a bookmark's title. - * - * @param aItemId - * id of the item to edit - * @param aNewTitle - * new title for the item to edit - * @returns nsITransaction object - */ - nsITransaction editItemTitle(in long long aItemId, in AString aNewTitle); - - /** - * Transaction for editing a bookmark's uri. - * - * @param aBookmarkId - * id of the bookmark to edit - * @param aNewURI - * new uri for the bookmark - * @returns nsITransaction object - */ - nsITransaction editBookmarkURI(in long long aBookmarkId, in nsIURI aNewURI); - - /** - * Transaction for setting/unsetting an item annotation - * - * @param aItemId - * id of the item where to set annotation - * @param aAnnotationObject - * Object representing an annotation, containing the following - * properties: name, flags, expires, type, mimeType (only used for - * binary annotations), value. - * If value is null the annotation will be removed - * @returns nsITransaction object - */ - nsITransaction setItemAnnotation(in nsIVariant aItemId, - in nsIVariant aAnnotationObject); - - /** - * Transaction for setting/unsetting a page annotation - * - * @param aURI - * URI of the page where to set annotation - * @param aAnnotationObject - * Object representing an annotation, containing the following - * properties: name, flags, expires, type, mimeType (only used for - * binary annotations), value. - * If value is null the annotation will be removed - * @returns nsITransaction object - */ - nsITransaction setPageAnnotation(in nsIURI aURI, - in nsIVariant aAnnotationObject); - - /** - * Transaction for setting/unsetting Load-in-sidebar annotation - * - * @param aBookmarkId - * id of the bookmark where to set Load-in-sidebar annotation - * @param aLoadInSidebar - * boolean value - * @returns nsITransaction object - */ - nsITransaction setLoadInSidebar(in long long aBookmarkId, - in boolean aLoadInSidebar); - - /** - * Transaction for editing a the description of a bookmark or a folder - * - * @param aItemId - * id of the item to edit - * @param aDescription - * new description - * @returns nsITransaction object - */ - nsITransaction editItemDescription(in long long aItemId, - in AString aDescription); - - /** - * Transaction for editing a bookmark's keyword. - * - * @param aBookmarkId - * id of the bookmark to edit - * @param aNewKeyword - * new keyword for the bookmark - * @returns nsITransaction object - */ - nsITransaction editBookmarkKeyword(in long long aBookmarkId, - in AString aNewKeyword); - - /** - * Transaction for editing the post data associated with a bookmark. - * - * @param aBookmarkId - * id of the bookmark to edit - * @param aPostData - * post data - * @returns nsITransaction object - */ - nsITransaction editBookmarkPostData(in long long aBookmarkId, - in AString aPostData); - - /** - * Transaction for editing a live bookmark's site URI. - * - * @param aLivemarkId - * id of the livemark - * @param aURI - * new site uri - * @returns nsITransaction object - */ - nsITransaction editLivemarkSiteURI(in long long aLivemarkId, in nsIURI aURI); - - /** - * Transaction for editting a live bookmark's feed URI. - * - * @param aLivemarkId - * id of the livemark - * @param aURI - * new feed uri - * @returns nsITransaction object - */ - nsITransaction editLivemarkFeedURI(in long long aLivemarkId, in nsIURI aURI); - - /** - * Transaction for editing a bookmark's microsummary. - * - * @param aBookmarkId - * id of the bookmark to edit - * @param aNewMicrosummary - * new microsummary for the bookmark - * @returns nsITransaction object - */ - nsITransaction editBookmarkMicrosummary(in long long aBookmarkId, - in nsIMicrosummary aNewMicrosummary); - - /** - * Transaction for editing an item's date added property. - * - * @param aItemId - * id of the item to edit - * @param aNewDateAdded - * new date added for the item - * @returns nsITransaction object - */ - nsITransaction editItemDateAdded(in long long aItemId, - in PRTime aNewDateAdded); - - /** - * Transaction for editing an item's last modified time. - * - * @param aItemId - * id of the item to edit - * @param aNewLastModified - * new last modified date for the item - * @returns nsITransaction object - */ - nsITransaction editItemLastModified(in long long aItemId, - in PRTime aNewLastModified); - - /** - * Transaction for sorting a folder by name - * - * @param aFolderId - * id of the folder to sort - * @returns nsITransaction object - */ - nsITransaction sortFolderByName(in long long aFolderId); - - /** - * Transaction for tagging a URL with the given set of tags. Current tags set - * for the URL persist. It's the caller's job to check whether or not aURI - * was already tagged by any of the tags in aTags, undoing this tags - * transaction removes them all from aURL! - * - * @param aURI - * the URL to tag. - * @param aTags - * Array of tags to set for the given URL. - */ - nsITransaction tagURI(in nsIURI aURI, in nsIVariant aTags); - - /** - * Transaction for removing tags from a URL. It's the caller's job to check - * whether or not aURI isn't tagged by any of the tags in aTags, undoing this - * tags transaction adds them all to aURL! - * - * @param aURI - * the URL to un-tag. - * @param aTags - * Array of tags to unset. pass null to remove all tags from the given - * url. - */ - nsITransaction untagURI(in nsIURI aURI, in nsIVariant aTags); -};
--- a/browser/components/places/src/BrowserPlaces.manifest +++ b/browser/components/places/src/BrowserPlaces.manifest @@ -1,4 +1,2 @@ -component {c0844a84-5a12-4808-80a8-809cb002bb4f} nsPlacesTransactionsService.js -contract @mozilla.org/browser/placesTransactionsService;1 {c0844a84-5a12-4808-80a8-809cb002bb4f} component {6bcb9bde-9018-4443-a071-c32653469597} PlacesProtocolHandler.js contract @mozilla.org/network/protocol;1?name=place {6bcb9bde-9018-4443-a071-c32653469597}
--- a/browser/components/places/src/Makefile.in +++ b/browser/components/places/src/Makefile.in @@ -41,17 +41,16 @@ DEPTH = ../../../.. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(DEPTH)/config/autoconf.mk EXTRA_COMPONENTS = \ BrowserPlaces.manifest \ - nsPlacesTransactionsService.js \ PlacesProtocolHandler.js \ $(NULL) EXTRA_JS_MODULES = \ PlacesUIUtils.jsm \ $(NULL) include $(topsrcdir)/config/rules.mk
--- a/browser/components/places/src/PlacesUIUtils.jsm +++ b/browser/components/places/src/PlacesUIUtils.jsm @@ -67,38 +67,38 @@ var PlacesUIUtils = { /** * Makes a URI from a spec, and do fixup * @param aSpec * The string spec of the URI * @returns A URI object for the spec. */ createFixedURI: function PUIU_createFixedURI(aSpec) { - return this.URIFixup.createFixupURI(aSpec, 0); + return URIFixup.createFixupURI(aSpec, 0); }, /** * Wraps a string in a nsISupportsString wrapper * @param aString * The string to wrap * @returns A nsISupportsString object containing a string. */ _wrapString: function PUIU__wrapString(aString) { var s = Cc["@mozilla.org/supports-string;1"]. createInstance(Ci.nsISupportsString); s.data = aString; return s; }, getFormattedString: function PUIU_getFormattedString(key, params) { - return this._bundle.formatStringFromName(key, params, params.length); + return bundle.formatStringFromName(key, params, params.length); }, getString: function PUIU_getString(key) { - return this._bundle.GetStringFromName(key); + return bundle.GetStringFromName(key); }, /** * Get a transaction for copying a uri item from one container to another * as a bookmark. * @param aData * JSON object of dropped or pasted item properties * @param aContainer @@ -655,17 +655,17 @@ var PlacesUIUtils = { return ("performed" in aInfo && aInfo.performed); }, _getTopBrowserWin: function PUIU__getTopBrowserWin() { return Services.wm.getMostRecentWindow("navigator:browser"); }, _getCurrentActiveWin: function PUIU__getCurrentActiveWin() { - return this.fm.activeWindow; + return focusManager.activeWindow; }, /** * Returns the closet ancestor places view for the given DOM node * @param aNode * a DOM node * @return the closet ancestor places view if exists, null otherwsie. */ @@ -1216,17 +1216,17 @@ var PlacesUIUtils = { * * @param aItemId id of a container * @returns the name of the query, or empty string if not a left-pane query */ getLeftPaneQueryNameFromId: function PUIU_getLeftPaneQueryNameFromId(aItemId) { var queryName = ""; // If the let pane hasn't been built, use the annotation service // directly, to avoid building the left pane too early. - if (this.__lookupGetter__("leftPaneFolderId")) { + if (Object.getOwnPropertyDescriptor(this, "leftPaneFolderId").value === undefined) { try { queryName = PlacesUtils.annotations. getItemAnnotation(aItemId, this.ORGANIZER_QUERY_ANNO); } catch (ex) { // doesn't have the annotation queryName = ""; } @@ -1235,48 +1235,214 @@ var PlacesUIUtils = { // If the left pane has already been built, use the name->id map // cached in PlacesUIUtils. for (let [name, id] in Iterator(this.leftPaneQueries)) { if (aItemId == id) queryName = name; } } return queryName; - }, - + } }; XPCOMUtils.defineLazyServiceGetter(PlacesUIUtils, "RDF", "@mozilla.org/rdf/rdf-service;1", "nsIRDFService"); XPCOMUtils.defineLazyGetter(PlacesUIUtils, "localStore", function() { return PlacesUIUtils.RDF.GetDataSource("rdf:local-store"); }); -XPCOMUtils.defineLazyServiceGetter(PlacesUIUtils, "ptm", - "@mozilla.org/browser/placesTransactionsService;1", - "nsIPlacesTransactionsService"); - -XPCOMUtils.defineLazyServiceGetter(PlacesUIUtils, "URIFixup", - "@mozilla.org/docshell/urifixup;1", - "nsIURIFixup"); - XPCOMUtils.defineLazyGetter(PlacesUIUtils, "ellipsis", function() { return Services.prefs.getComplexValue("intl.ellipsis", Ci.nsIPrefLocalizedString).data; }); XPCOMUtils.defineLazyServiceGetter(PlacesUIUtils, "privateBrowsing", "@mozilla.org/privatebrowsing;1", "nsIPrivateBrowsingService"); -XPCOMUtils.defineLazyGetter(PlacesUIUtils, "_bundle", function() { +XPCOMUtils.defineLazyServiceGetter(this, "URIFixup", + "@mozilla.org/docshell/urifixup;1", + "nsIURIFixup"); + +XPCOMUtils.defineLazyGetter(this, "bundle", function() { const PLACES_STRING_BUNDLE_URI = "chrome://browser/locale/places/places.properties"; return Cc["@mozilla.org/intl/stringbundle;1"]. getService(Ci.nsIStringBundleService). createBundle(PLACES_STRING_BUNDLE_URI); }); -XPCOMUtils.defineLazyServiceGetter(PlacesUIUtils, "fm", +XPCOMUtils.defineLazyServiceGetter(this, "focusManager", "@mozilla.org/focus-manager;1", "nsIFocusManager"); + +/** + * This is a compatibility shim for old PUIU.ptm users. + * + * If you're looking for transactions and writing new code using them, directly + * use the transactions objects exported by the PlacesUtils.jsm module. + * + * This object will be removed once enough users are converted to the new API. + */ +XPCOMUtils.defineLazyGetter(PlacesUIUtils, "ptm", function() { + // Ensure PlacesUtils is imported in scope. + PlacesUtils; + + return { + aggregateTransactions: function(aName, aTransactions) + new PlacesAggregatedTransaction(aName, aTransactions), + + createFolder: function(aName, aContainer, aIndex, aAnnotations, + aChildItemsTransactions) + new PlacesCreateFolderTransaction(aName, aContainer, aIndex, aAnnotations, + aChildItemsTransactions), + + createItem: function(aURI, aContainer, aIndex, aTitle, aKeyword, + aAnnotations, aChildTransactions) + new PlacesCreateBookmarkTransaction(aURI, aContainer, aIndex, aTitle, + aKeyword, aAnnotations, + aChildTransactions), + + createSeparator: function(aContainer, aIndex) + new PlacesCreateSeparatorTransaction(aContainer, aIndex), + + createLivemark: function(aFeedURI, aSiteURI, aName, aContainer, aIndex, + aAnnotations) + new PlacesCreateLivemarkTransaction(aFeedURI, aSiteURI, aName, aContainer, + aIndex, aAnnotations), + + moveItem: function(aItemId, aNewContainer, aNewIndex) + new PlacesMoveItemTransaction(aItemId, aNewContainer, aNewIndex), + + removeItem: function(aItemId) + new PlacesRemoveItemTransaction(aItemId), + + editItemTitle: function(aItemId, aNewTitle) + new PlacesEditItemTitleTransaction(aItemId, aNewTitle), + + editBookmarkURI: function(aItemId, aNewURI) + new PlacesEditBookmarkURITransaction(aItemId, aNewURI), + + setItemAnnotation: function(aItemId, aAnnotationObject) + new PlacesSetItemAnnotationTransaction(aItemId, aAnnotationObject), + + setPageAnnotation: function(aURI, aAnnotationObject) + new PlacesSetPageAnnotationTransaction(aURI, aAnnotationObject), + + editBookmarkKeyword: function(aItemId, aNewKeyword) + new PlacesEditBookmarkKeywordTransaction(aItemId, aNewKeyword), + + editBookmarkPostData: function(aItemId, aPostData) + new PlacesEditBookmarkPostDataTransaction(aItemId, aPostData), + + editLivemarkSiteURI: function(aLivemarkId, aSiteURI) + new PlacesEditLivemarkSiteURITransaction(aLivemarkId, aSiteURI), + + editLivemarkFeedURI: function(aLivemarkId, aFeedURI) + new PlacesEditLivemarkFeedURITransaction(aLivemarkId, aFeedURI), + + editBookmarkMicrosummary: function(aItemId, aNewMicrosummary) + new PlacesEditBookmarkMicrosummaryTransaction(aItemId, aNewMicrosummary), + + editItemDateAdded: function(aItemId, aNewDateAdded) + new PlacesEditItemDateAddedTransaction(aItemId, aNewDateAdded), + + editItemLastModified: function(aItemId, aNewLastModified) + new PlacesEditItemLastModifiedTransaction(aItemId, aNewLastModified), + + sortFolderByName: function(aFolderId) + new PlacesSortFolderByNameTransaction(aFolderId), + + tagURI: function(aURI, aTags) + new PlacesTagURITransaction(aURI, aTags), + + untagURI: function(aURI, aTags) + new PlacesUntagURITransaction(aURI, aTags), + + /** + * Transaction for setting/unsetting Load-in-sidebar annotation. + * + * @param aBookmarkId + * id of the bookmark where to set Load-in-sidebar annotation. + * @param aLoadInSidebar + * boolean value. + * @returns nsITransaction object. + */ + setLoadInSidebar: function(aItemId, aLoadInSidebar) + { + let annoObj = { name: PlacesUIUtils.LOAD_IN_SIDEBAR_ANNO, + type: Ci.nsIAnnotationService.TYPE_INT32, + flags: 0, + value: aLoadInSidebar, + expires: Ci.nsIAnnotationService.EXPIRE_NEVER }; + return new PlacesSetItemAnnotationTransaction(aItemId, annoObj); + }, + + /** + * Transaction for editing a the description of a bookmark or a folder. + * + * @param aItemId + * id of the item to edit. + * @param aDescription + * new description. + * @returns nsITransaction object. + */ + editItemDescription: function(aItemId, aDescription) + { + let annoObj = { name: PlacesUIUtils.DESCRIPTION_ANNO, + type: Ci.nsIAnnotationService.TYPE_STRING, + flags: 0, + value: aDescription, + expires: Ci.nsIAnnotationService.EXPIRE_NEVER }; + return new PlacesSetItemAnnotationTransaction(aItemId, annoObj); + }, + + //////////////////////////////////////////////////////////////////////////// + //// nsITransactionManager forwarders. + + beginBatch: function() + PlacesUtils.transactionManager.beginBatch(), + + endBatch: function() + PlacesUtils.transactionManager.endBatch(), + + doTransaction: function(txn) + PlacesUtils.transactionManager.doTransaction(txn), + + undoTransaction: function() + PlacesUtils.transactionManager.undoTransaction(), + + redoTransaction: function() + PlacesUtils.transactionManager.redoTransaction(), + + get numberOfUndoItems() + PlacesUtils.transactionManager.numberOfUndoItems, + get numberOfRedoItems() + PlacesUtils.transactionManager.numberOfRedoItems, + get maxTransactionCount() + PlacesUtils.transactionManager.maxTransactionCount, + set maxTransactionCount(val) + PlacesUtils.transactionManager.maxTransactionCount = val, + + clear: function() + PlacesUtils.transactionManager.clear(), + + peekUndoStack: function() + PlacesUtils.transactionManager.peekUndoStack(), + + peekRedoStack: function() + PlacesUtils.transactionManager.peekRedoStack(), + + getUndoStack: function() + PlacesUtils.transactionManager.getUndoStack(), + + getRedoStack: function() + PlacesUtils.transactionManager.getRedoStack(), + + AddListener: function(aListener) + PlacesUtils.transactionManager.AddListener(aListener), + + RemoveListener: function(aListener) + PlacesUtils.transactionManager.RemoveListener(aListener) + } +});
deleted file mode 100644 --- a/browser/components/places/src/nsPlacesTransactionsService.js +++ /dev/null @@ -1,1187 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is the Places Command Controller. - * - * The Initial Developer of the Original Code is Google Inc. - * - * Portions created by the Initial Developer are Copyright (C) 2005 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Sungjoon Steve Won <stevewon@gmail.com> (Original Author) - * Asaf Romano <mano@mozilla.com> - * Marco Bonarco <mak77@bonardo.net> - * - * 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 ***** */ - -let Ci = Components.interfaces; -let Cc = Components.classes; -let Cr = Components.results; -let Cu = Components.utils; - -const LOAD_IN_SIDEBAR_ANNO = "bookmarkProperties/loadInSidebar"; -const DESCRIPTION_ANNO = "bookmarkProperties/description"; - -const CLASS_ID = Components.ID("c0844a84-5a12-4808-80a8-809cb002bb4f"); - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); - -XPCOMUtils.defineLazyGetter(this, "Services", function() { - Cu.import("resource://gre/modules/Services.jsm"); - return Services; -}); - -XPCOMUtils.defineLazyGetter(this, "PlacesUtils", function() { - Cu.import("resource://gre/modules/PlacesUtils.jsm"); - return PlacesUtils; -}); - -// The minimum amount of transactions we should tell our observers to begin -// batching (rather than letting them do incremental drawing). -const MIN_TRANSACTIONS_FOR_BATCH = 5; - -function placesTransactionsService() { - Services.obs.addObserver(this, PlacesUtils.TOPIC_SHUTDOWN, false); - this.mTransactionManager = Cc["@mozilla.org/transactionmanager;1"]. - createInstance(Ci.nsITransactionManager); -} - -placesTransactionsService.prototype = { - classID: CLASS_ID, - - QueryInterface: XPCOMUtils.generateQI([ - Ci.nsIPlacesTransactionsService, - Ci.nsITransactionManager, - Ci.nsIObserver, - ]), - - // nsIObserver - observe: function PlacesTxn_observe(aSubject, aTopic, aData) { - if (aTopic == PlacesUtils.TOPIC_SHUTDOWN) { - Services.obs.removeObserver(this, PlacesUtils.TOPIC_SHUTDOWN); - delete this.mTransactionManager; - } - }, - - aggregateTransactions: - function placesTxn_aggregateTransactions(aName, aTransactions) { - return new placesAggregateTransactions(aName, aTransactions); - }, - - createFolder: - function placesTxn_createFolder(aName, aContainer, aIndex, - aAnnotations, aChildItemsTransactions) { - return new placesCreateFolderTransactions(aName, aContainer, aIndex, - aAnnotations, aChildItemsTransactions); - }, - - createItem: - function placesTxn_createItem(aURI, aContainer, aIndex, aTitle, - aKeyword, aAnnotations, aChildTransactions) { - return new placesCreateItemTransactions(aURI, aContainer, aIndex, aTitle, - aKeyword, aAnnotations, aChildTransactions); - }, - - createSeparator: - function placesTxn_createSeparator(aContainer, aIndex) { - return new placesCreateSeparatorTransactions(aContainer, aIndex); - }, - - createLivemark: - function placesTxn_createLivemark(aFeedURI, aSiteURI, aName, - aContainer, aIndex, aAnnotations) { - return new placesCreateLivemarkTransactions(aFeedURI, aSiteURI, aName, - aContainer, aIndex, aAnnotations); - }, - - moveItem: - function placesTxn_moveItem(aItemId, aNewContainer, aNewIndex) { - return new placesMoveItemTransactions(aItemId, aNewContainer, aNewIndex); - }, - - removeItem: - function placesTxn_removeItem(aItemId) { - if (aItemId == PlacesUtils.tagsFolderId || - aItemId == PlacesUtils.placesRootId || - aItemId == PlacesUtils.bookmarksMenuFolderId || - aItemId == PlacesUtils.toolbarFolderId) - throw Cr.NS_ERROR_INVALID_ARG; - - // if the item lives within a tag container, use the tagging transactions - var parent = PlacesUtils.bookmarks.getFolderIdForItem(aItemId); - var grandparent = PlacesUtils.bookmarks.getFolderIdForItem(parent); - if (grandparent == PlacesUtils.tagsFolderId) { - var uri = PlacesUtils.bookmarks.getBookmarkURI(aItemId); - return this.untagURI(uri, [parent]); - } - - // if the item is a livemark container we will not save its children and - // will use createLivemark to undo. - if (PlacesUtils.itemIsLivemark(aItemId)) - return new placesRemoveLivemarkTransaction(aItemId); - - return new placesRemoveItemTransaction(aItemId); - }, - - editItemTitle: - function placesTxn_editItemTitle(aItemId, aNewTitle) { - return new placesEditItemTitleTransactions(aItemId, aNewTitle); - }, - - editBookmarkURI: - function placesTxn_editBookmarkURI(aItemId, aNewURI) { - return new placesEditBookmarkURITransactions(aItemId, aNewURI); - }, - - setItemAnnotation: - function placesTxn_setItemAnnotation(aItemId, aAnnotationObject) { - return new placesSetItemAnnotationTransactions(aItemId, aAnnotationObject); - }, - - setPageAnnotation: - function placesTxn_setPageAnnotation(aURI, aAnnotationObject) { - return new placesSetPageAnnotationTransactions(aURI, aAnnotationObject); - }, - - setLoadInSidebar: - function placesTxn_setLoadInSidebar(aItemId, aLoadInSidebar) { - var annoObj = { name: LOAD_IN_SIDEBAR_ANNO, - type: Ci.nsIAnnotationService.TYPE_INT32, - flags: 0, - value: aLoadInSidebar, - expires: Ci.nsIAnnotationService.EXPIRE_NEVER }; - return this.setItemAnnotation(aItemId, annoObj); - }, - - editItemDescription: - function placesTxn_editItemDescription(aItemId, aDescription) { - var annoObj = { name: DESCRIPTION_ANNO, - type: Ci.nsIAnnotationService.TYPE_STRING, - flags: 0, - value: aDescription, - expires: Ci.nsIAnnotationService.EXPIRE_NEVER }; - return this.setItemAnnotation(aItemId, annoObj); - }, - - editBookmarkKeyword: - function placesTxn_editBookmarkKeyword(aItemId, aNewKeyword) { - return new placesEditBookmarkKeywordTransactions(aItemId, aNewKeyword); - }, - - editBookmarkPostData: - function placesTxn_editBookmarkPostdata(aItemId, aPostData) { - return new placesEditBookmarkPostDataTransactions(aItemId, aPostData); - }, - - editLivemarkSiteURI: - function placesTxn_editLivemarkSiteURI(aLivemarkId, aSiteURI) { - return new placesEditLivemarkSiteURITransactions(aLivemarkId, aSiteURI); - }, - - editLivemarkFeedURI: - function placesTxn_editLivemarkFeedURI(aLivemarkId, aFeedURI) { - return new placesEditLivemarkFeedURITransactions(aLivemarkId, aFeedURI); - }, - - editBookmarkMicrosummary: - function placesTxn_editBookmarkMicrosummary(aItemId, aNewMicrosummary) { - return new placesEditBookmarkMicrosummaryTransactions(aItemId, aNewMicrosummary); - }, - - editItemDateAdded: - function placesTxn_editItemDateAdded(aItemId, aNewDateAdded) { - return new placesEditItemDateAddedTransaction(aItemId, aNewDateAdded); - }, - - editItemLastModified: - function placesTxn_editItemLastModified(aItemId, aNewLastModified) { - return new placesEditItemLastModifiedTransaction(aItemId, aNewLastModified); - }, - - sortFolderByName: - function placesTxn_sortFolderByName(aFolderId) { - return new placesSortFolderByNameTransactions(aFolderId); - }, - - tagURI: - function placesTxn_tagURI(aURI, aTags) { - return new placesTagURITransaction(aURI, aTags); - }, - - untagURI: - function placesTxn_untagURI(aURI, aTags) { - return new placesUntagURITransaction(aURI, aTags); - }, - - // Update commands in the undo group of the active window - // commands in inactive windows will are updated on-focus - _updateCommands: function placesTxn__updateCommands() { - var win = Services.wm.getMostRecentWindow(null); - if (win) - win.updateCommands("undo"); - }, - - // nsITransactionManager - beginBatch: function() { - this.mTransactionManager.beginBatch(); - - // A no-op transaction is pushed to the stack, in order to make safe and - // easy to implement "Undo" an unknown number of transactions (including 0), - // "above" beginBatch and endBatch. Otherwise,implementing Undo that way - // head to dataloss: for example, if no changes were done in the - // edit-item panel, the last transaction on the undo stack would be the - // initial createItem transaction, or even worse, the batched editing of - // some other item. - // DO NOT MOVE this to the window scope, that would leak (bug 490068)! - this.doTransaction({ doTransaction: function() { }, - undoTransaction: function() { }, - redoTransaction: function() { }, - isTransient: false, - merge: function() { return false; } }); - }, - - endBatch: function() this.mTransactionManager.endBatch(), - - doTransaction: function placesTxn_doTransaction(txn) { - this.mTransactionManager.doTransaction(txn); - this._updateCommands(); - }, - - undoTransaction: function placesTxn_undoTransaction() { - this.mTransactionManager.undoTransaction(); - this._updateCommands(); - }, - - redoTransaction: function placesTxn_redoTransaction() { - this.mTransactionManager.redoTransaction(); - this._updateCommands(); - }, - - clear: function() this.mTransactionManager.clear(), - - get numberOfUndoItems() { - return this.mTransactionManager.numberOfUndoItems; - }, - - get numberOfRedoItems() { - return this.mTransactionManager.numberOfRedoItems; - }, - - get maxTransactionCount() { - return this.mTransactionManager.maxTransactionCount; - }, - set maxTransactionCount(val) { - return this.mTransactionManager.maxTransactionCount = val; - }, - - peekUndoStack: function() this.mTransactionManager.peekUndoStack(), - peekRedoStack: function() this.mTransactionManager.peekRedoStack(), - getUndoStack: function() this.mTransactionManager.getUndoStack(), - getRedoStack: function() this.mTransactionManager.getRedoStack(), - AddListener: function(l) this.mTransactionManager.AddListener(l), - RemoveListener: function(l) this.mTransactionManager.RemoveListener(l) -}; - -/** - * Method and utility stubs for Places Edit Transactions - */ -function placesBaseTransaction() { -} - -placesBaseTransaction.prototype = { - // for child-transactions - get wrappedJSObject() { - return this; - }, - - // nsITransaction - redoTransaction: function PBT_redoTransaction() { - throw Cr.NS_ERROR_NOT_IMPLEMENTED; - }, - - get isTransient() { - return false; - }, - - merge: function mergeFunc(transaction) { - return false; - }, - - // nsISupports - QueryInterface: XPCOMUtils.generateQI([Ci.nsITransaction]), -}; - -function placesAggregateTransactions(name, transactions) { - this._transactions = transactions; - this._name = name; - this.container = -1; - this.redoTransaction = this.doTransaction; - - // Check child transactions number. We will batch if we have more than - // MIN_TRANSACTIONS_FOR_BATCH total number of transactions. - var countTransactions = function(aTransactions, aTxnCount) { - for (let i = 0; - i < aTransactions.length && aTxnCount < MIN_TRANSACTIONS_FOR_BATCH; - i++, aTxnCount++) { - let txn = aTransactions[i].wrappedJSObject; - if (txn && txn.childTransactions && txn.childTransactions.length) - aTxnCount = countTransactions(txn.childTransactions, aTxnCount); - } - return aTxnCount; - } - - var txnCount = countTransactions(transactions, 0); - this._useBatch = txnCount >= MIN_TRANSACTIONS_FOR_BATCH; -} - -placesAggregateTransactions.prototype = { - __proto__: placesBaseTransaction.prototype, - - doTransaction: function PAT_doTransaction() { - if (this._useBatch) { - var callback = { - _self: this, - runBatched: function() { - this._self.commit(false); - } - }; - PlacesUtils.bookmarks.runInBatchMode(callback, null); - } - else - this.commit(false); - }, - - undoTransaction: function PAT_undoTransaction() { - if (this._useBatch) { - var callback = { - _self: this, - runBatched: function() { - this._self.commit(true); - } - }; - PlacesUtils.bookmarks.runInBatchMode(callback, null); - } - else - this.commit(true); - }, - - commit: function PAT_commit(aUndo) { - // Use a copy of the transactions array, so we won't reverse the original - // one on undoing. - var transactions = this._transactions.slice(0); - if (aUndo) - transactions.reverse(); - for (var i = 0; i < transactions.length; i++) { - var txn = transactions[i]; - if (this.container > -1) - txn.wrappedJSObject.container = this.container; - if (aUndo) - txn.undoTransaction(); - else - txn.doTransaction(); - } - } -}; - -function placesCreateFolderTransactions(aName, aContainer, aIndex, - aAnnotations, - aChildItemsTransactions) { - this._name = aName; - this._container = aContainer; - this._index = typeof(aIndex) == "number" ? aIndex : -1; - this._annotations = aAnnotations; - this._id = null; - this.childTransactions = aChildItemsTransactions || []; - this.redoTransaction = this.doTransaction; -} - -placesCreateFolderTransactions.prototype = { - __proto__: placesBaseTransaction.prototype, - - // childItemsTransaction support - get container() { return this._container; }, - set container(val) { return this._container = val; }, - - doTransaction: function PCFT_doTransaction() { - this._id = PlacesUtils.bookmarks.createFolder(this._container, - this._name, this._index); - if (this._annotations && this._annotations.length > 0) - PlacesUtils.setAnnotationsForItem(this._id, this._annotations); - - if (this.childTransactions.length) { - // Set the new container id into child transactions. - for (var i = 0; i < this.childTransactions.length; ++i) { - this.childTransactions[i].wrappedJSObject.container = this._id; - } - - let aggregateTxn = new placesAggregateTransactions("Create folder childTxn", - this.childTransactions); - aggregateTxn.doTransaction(); - } - - if (this._GUID) - PlacesUtils.bookmarks.setItemGUID(this._id, this._GUID); - }, - - undoTransaction: function PCFT_undoTransaction() { - if (this.childTransactions.length) { - let aggregateTxn = new placesAggregateTransactions("Create folder childTxn", - this.childTransactions); - aggregateTxn.undoTransaction(); - } - - // If a GUID exists for this item, preserve it before removing the item. - if (PlacesUtils.annotations.itemHasAnnotation(this._id, PlacesUtils.GUID_ANNO)) - this._GUID = PlacesUtils.bookmarks.getItemGUID(this._id); - - // Remove item only after all child transactions have been reverted. - PlacesUtils.bookmarks.removeItem(this._id); - } -}; - -function placesCreateItemTransactions(aURI, aContainer, aIndex, aTitle, - aKeyword, aAnnotations, - aChildTransactions) { - this._uri = aURI; - this._container = aContainer; - this._index = typeof(aIndex) == "number" ? aIndex : -1; - this._title = aTitle; - this._keyword = aKeyword; - this._annotations = aAnnotations; - this.childTransactions = aChildTransactions || []; - this.redoTransaction = this.doTransaction; -} - -placesCreateItemTransactions.prototype = { - __proto__: placesBaseTransaction.prototype, - - // childItemsTransactions support for the create-folder transaction - get container() { return this._container; }, - set container(val) { return this._container = val; }, - - doTransaction: function PCIT_doTransaction() { - this._id = PlacesUtils.bookmarks.insertBookmark(this.container, this._uri, - this._index, this._title); - if (this._keyword) - PlacesUtils.bookmarks.setKeywordForBookmark(this._id, this._keyword); - if (this._annotations && this._annotations.length > 0) - PlacesUtils.setAnnotationsForItem(this._id, this._annotations); - - if (this.childTransactions.length) { - // Set the new item id into child transactions. - for (var i = 0; i < this.childTransactions.length; ++i) { - this.childTransactions[i].wrappedJSObject.id = this._id; - } - let aggregateTxn = new placesAggregateTransactions("Create item childTxn", - this.childTransactions); - aggregateTxn.doTransaction(); - } - if (this._GUID) - PlacesUtils.bookmarks.setItemGUID(this._id, this._GUID); - }, - - undoTransaction: function PCIT_undoTransaction() { - if (this.childTransactions.length) { - // Undo transactions should always be done in reverse order. - let aggregateTxn = new placesAggregateTransactions("Create item childTxn", - this.childTransactions); - aggregateTxn.undoTransaction(); - } - - // If a GUID exists for this item, preserve it before removing the item. - if (PlacesUtils.annotations.itemHasAnnotation(this._id, PlacesUtils.GUID_ANNO)) - this._GUID = PlacesUtils.bookmarks.getItemGUID(this._id); - - // Remove item only after all child transactions have been reverted. - PlacesUtils.bookmarks.removeItem(this._id); - } -}; - -function placesCreateSeparatorTransactions(aContainer, aIndex) { - this._container = aContainer; - this._index = typeof(aIndex) == "number" ? aIndex : -1; - this._id = null; - this.redoTransaction = this.doTransaction; -} - -placesCreateSeparatorTransactions.prototype = { - __proto__: placesBaseTransaction.prototype, - - // childItemsTransaction support - get container() { return this._container; }, - set container(val) { return this._container = val; }, - - doTransaction: function PCST_doTransaction() { - this._id = PlacesUtils.bookmarks - .insertSeparator(this.container, this._index); - if (this._GUID) - PlacesUtils.bookmarks.setItemGUID(this._id, this._GUID); - }, - - undoTransaction: function PCST_undoTransaction() { - // If a GUID exists for this item, preserve it before removing the item. - if (PlacesUtils.annotations.itemHasAnnotation(this._id, PlacesUtils.GUID_ANNO)) - this._GUID = PlacesUtils.bookmarks.getItemGUID(this._id); - - PlacesUtils.bookmarks.removeItem(this._id); - } -}; - -function placesCreateLivemarkTransactions(aFeedURI, aSiteURI, aName, - aContainer, aIndex, - aAnnotations) { - this.redoTransaction = this.doTransaction; - this._feedURI = aFeedURI; - this._siteURI = aSiteURI; - this._name = aName; - this._container = aContainer; - this._index = typeof(aIndex) == "number" ? aIndex : -1; - this._annotations = aAnnotations; -} - -placesCreateLivemarkTransactions.prototype = { - __proto__: placesBaseTransaction.prototype, - - // childItemsTransaction support - get container() { return this._container; }, - set container(val) { return this._container = val; }, - - doTransaction: function PCLT_doTransaction() { - this._id = PlacesUtils.livemarks.createLivemark(this._container, this._name, - this._siteURI, this._feedURI, - this._index); - if (this._annotations && this._annotations.length > 0) - PlacesUtils.setAnnotationsForItem(this._id, this._annotations); - if (this._GUID) - PlacesUtils.bookmarks.setItemGUID(this._id, this._GUID); - }, - - undoTransaction: function PCLT_undoTransaction() { - // If a GUID exists for this item, preserve it before removing the item. - if (PlacesUtils.annotations.itemHasAnnotation(this._id, PlacesUtils.GUID_ANNO)) - this._GUID = PlacesUtils.bookmarks.getItemGUID(this._id); - - PlacesUtils.bookmarks.removeItem(this._id); - } -}; - -function placesRemoveLivemarkTransaction(aFolderId) { - this.redoTransaction = this.doTransaction; - this._id = aFolderId; - this._title = PlacesUtils.bookmarks.getItemTitle(this._id); - this._container = PlacesUtils.bookmarks.getFolderIdForItem(this._id); - var annos = PlacesUtils.getAnnotationsForItem(this._id); - // Exclude livemark service annotations, those will be recreated automatically - var annosToExclude = ["livemark/feedURI", - "livemark/siteURI", - "livemark/expiration", - "livemark/loadfailed", - "livemark/loading"]; - this._annotations = annos.filter(function(aValue, aIndex, aArray) { - return annosToExclude.indexOf(aValue.name) == -1; - }); - this._feedURI = PlacesUtils.livemarks.getFeedURI(this._id); - this._siteURI = PlacesUtils.livemarks.getSiteURI(this._id); - this._dateAdded = PlacesUtils.bookmarks.getItemDateAdded(this._id); - this._lastModified = PlacesUtils.bookmarks.getItemLastModified(this._id); -} - -placesRemoveLivemarkTransaction.prototype = { - __proto__: placesBaseTransaction.prototype, - - doTransaction: function PRLT_doTransaction() { - this._index = PlacesUtils.bookmarks.getItemIndex(this._id); - PlacesUtils.bookmarks.removeItem(this._id); - }, - - undoTransaction: function PRLT_undoTransaction() { - this._id = PlacesUtils.livemarks.createLivemark(this._container, - this._title, - this._siteURI, - this._feedURI, - this._index); - PlacesUtils.bookmarks.setItemDateAdded(this._id, this._dateAdded); - PlacesUtils.bookmarks.setItemLastModified(this._id, this._lastModified); - // Restore annotations - PlacesUtils.setAnnotationsForItem(this._id, this._annotations); - } -}; - -function placesMoveItemTransactions(aItemId, aNewContainer, aNewIndex) { - this._id = aItemId; - this._oldContainer = PlacesUtils.bookmarks.getFolderIdForItem(this._id); - this._newContainer = aNewContainer; - this._newIndex = aNewIndex; - this.redoTransaction = this.doTransaction; -} - -placesMoveItemTransactions.prototype = { - __proto__: placesBaseTransaction.prototype, - - doTransaction: function PMIT_doTransaction() { - this._oldIndex = PlacesUtils.bookmarks.getItemIndex(this._id); - PlacesUtils.bookmarks.moveItem(this._id, this._newContainer, this._newIndex); - this._undoIndex = PlacesUtils.bookmarks.getItemIndex(this._id); - }, - - undoTransaction: function PMIT_undoTransaction() { - // moving down in the same container takes in count removal of the item - // so to revert positions we must move to oldIndex + 1 - if (this._newContainer == this._oldContainer && - this._oldIndex > this._undoIndex) - PlacesUtils.bookmarks.moveItem(this._id, this._oldContainer, this._oldIndex + 1); - else - PlacesUtils.bookmarks.moveItem(this._id, this._oldContainer, this._oldIndex); - } -}; - -function placesRemoveItemTransaction(aItemId) { - this.redoTransaction = this.doTransaction; - this._id = aItemId; - this._itemType = PlacesUtils.bookmarks.getItemType(this._id); - if (this._itemType == Ci.nsINavBookmarksService.TYPE_FOLDER) { - this.childTransactions = this._getFolderContentsTransactions(); - // Remove this folder itself. - let txn = PlacesUtils.bookmarks.getRemoveFolderTransaction(this._id); - this.childTransactions.push(txn); - } - else if (this._itemType == Ci.nsINavBookmarksService.TYPE_BOOKMARK) { - this._uri = PlacesUtils.bookmarks.getBookmarkURI(this._id); - this._keyword = PlacesUtils.bookmarks.getKeywordForBookmark(this._id); - } - - if (this._itemType != Ci.nsINavBookmarksService.TYPE_SEPARATOR) - this._title = PlacesUtils.bookmarks.getItemTitle(this._id); - - this._oldContainer = PlacesUtils.bookmarks.getFolderIdForItem(this._id); - this._annotations = PlacesUtils.getAnnotationsForItem(this._id); - this._dateAdded = PlacesUtils.bookmarks.getItemDateAdded(this._id); - this._lastModified = PlacesUtils.bookmarks.getItemLastModified(this._id); -} - -placesRemoveItemTransaction.prototype = { - __proto__: placesBaseTransaction.prototype, - - doTransaction: function PRIT_doTransaction() { - this._oldIndex = PlacesUtils.bookmarks.getItemIndex(this._id); - - if (this._itemType == Ci.nsINavBookmarksService.TYPE_FOLDER) { - let aggregateTxn = new placesAggregateTransactions("Remove item childTxn", - this.childTransactions); - aggregateTxn.doTransaction(); - } - else { - PlacesUtils.bookmarks.removeItem(this._id); - if (this._uri) { - // if this was the last bookmark (excluding tag-items and livemark - // children, see getMostRecentBookmarkForURI) for the bookmark's url, - // remove the url from tag containers as well. - if (PlacesUtils.getMostRecentBookmarkForURI(this._uri) == -1) { - this._tags = PlacesUtils.tagging.getTagsForURI(this._uri); - PlacesUtils.tagging.untagURI(this._uri, this._tags); - } - } - } - }, - - undoTransaction: function PRIT_undoTransaction() { - if (this._itemType == Ci.nsINavBookmarksService.TYPE_BOOKMARK) { - this._id = PlacesUtils.bookmarks.insertBookmark(this._oldContainer, - this._uri, - this._oldIndex, - this._title); - if (this._tags && this._tags.length > 0) - PlacesUtils.tagging.tagURI(this._uri, this._tags); - if (this._keyword) - PlacesUtils.bookmarks.setKeywordForBookmark(this._id, this._keyword); - } - else if (this._itemType == Ci.nsINavBookmarksService.TYPE_FOLDER) { - let aggregateTxn = new placesAggregateTransactions("Remove item childTxn", - this.childTransactions); - aggregateTxn.undoTransaction(); - } - else // TYPE_SEPARATOR - this._id = PlacesUtils.bookmarks.insertSeparator(this._oldContainer, this._oldIndex); - - if (this._annotations.length > 0) - PlacesUtils.setAnnotationsForItem(this._id, this._annotations); - - PlacesUtils.bookmarks.setItemDateAdded(this._id, this._dateAdded); - PlacesUtils.bookmarks.setItemLastModified(this._id, this._lastModified); - }, - - /** - * Returns a flat, ordered list of transactions for a depth-first recreation - * of items within this folder. - */ - _getFolderContentsTransactions: - function PRIT__getFolderContentsTransactions() { - var transactions = []; - var contents = - PlacesUtils.getFolderContents(this._id, false, false).root; - for (var i = 0; i < contents.childCount; ++i) { - let txn = new placesRemoveItemTransaction(contents.getChild(i).itemId); - transactions.push(txn); - } - contents.containerOpen = false; - // Reverse transactions to preserve parent-child relationship. - return transactions.reverse(); - } -}; - -function placesEditItemTitleTransactions(id, newTitle) { - this._id = id; - this._newTitle = newTitle; - this._oldTitle = ""; - this.redoTransaction = this.doTransaction; -} - -placesEditItemTitleTransactions.prototype = { - __proto__: placesBaseTransaction.prototype, - - doTransaction: function PEITT_doTransaction() { - this._oldTitle = PlacesUtils.bookmarks.getItemTitle(this._id); - PlacesUtils.bookmarks.setItemTitle(this._id, this._newTitle); - }, - - undoTransaction: function PEITT_undoTransaction() { - PlacesUtils.bookmarks.setItemTitle(this._id, this._oldTitle); - } -}; - -function placesEditBookmarkURITransactions(aBookmarkId, aNewURI) { - this._id = aBookmarkId; - this._newURI = aNewURI; - this.redoTransaction = this.doTransaction; -} - -placesEditBookmarkURITransactions.prototype = { - __proto__: placesBaseTransaction.prototype, - - doTransaction: function PEBUT_doTransaction() { - this._oldURI = PlacesUtils.bookmarks.getBookmarkURI(this._id); - PlacesUtils.bookmarks.changeBookmarkURI(this._id, this._newURI); - // move tags from old URI to new URI - this._tags = PlacesUtils.tagging.getTagsForURI(this._oldURI); - if (this._tags.length != 0) { - // only untag the old URI if this is the only bookmark - if (PlacesUtils.getBookmarksForURI(this._oldURI, {}).length == 0) - PlacesUtils.tagging.untagURI(this._oldURI, this._tags); - PlacesUtils.tagging.tagURI(this._newURI, this._tags); - } - }, - - undoTransaction: function PEBUT_undoTransaction() { - PlacesUtils.bookmarks.changeBookmarkURI(this._id, this._oldURI); - // move tags from new URI to old URI - if (this._tags.length != 0) { - // only untag the new URI if this is the only bookmark - if (PlacesUtils.getBookmarksForURI(this._newURI, {}).length == 0) - PlacesUtils.tagging.untagURI(this._newURI, this._tags); - PlacesUtils.tagging.tagURI(this._oldURI, this._tags); - } - } -}; - -function placesSetItemAnnotationTransactions(aItemId, aAnnotationObject) { - this.id = aItemId; - this._anno = aAnnotationObject; - // create an empty old anno - this._oldAnno = { name: this._anno.name, - type: Ci.nsIAnnotationService.TYPE_STRING, - flags: 0, - value: null, - expires: Ci.nsIAnnotationService.EXPIRE_NEVER }; - this.redoTransaction = this.doTransaction; -} - -placesSetItemAnnotationTransactions.prototype = { - __proto__: placesBaseTransaction.prototype, - - doTransaction: function PSIAT_doTransaction() { - // Since this can be used as a child transaction this.id will be known - // only at this point, after the external caller has set it. - if (PlacesUtils.annotations.itemHasAnnotation(this.id, this._anno.name)) { - // Save the old annotation if it is set. - var flags = {}, expires = {}, mimeType = {}, type = {}; - PlacesUtils.annotations.getItemAnnotationInfo(this.id, this._anno.name, - flags, expires, mimeType, - type); - this._oldAnno.flags = flags.value; - this._oldAnno.expires = expires.value; - this._oldAnno.mimeType = mimeType.value; - this._oldAnno.type = type.value; - this._oldAnno.value = PlacesUtils.annotations - .getItemAnnotation(this.id, - this._anno.name); - } - - PlacesUtils.setAnnotationsForItem(this.id, [this._anno]); - }, - - undoTransaction: function PSIAT_undoTransaction() { - PlacesUtils.setAnnotationsForItem(this.id, [this._oldAnno]); - } -}; - -function placesSetPageAnnotationTransactions(aURI, aAnnotationObject) { - this._uri = aURI; - this._anno = aAnnotationObject; - // create an empty old anno - this._oldAnno = { name: this._anno.name, - type: Ci.nsIAnnotationService.TYPE_STRING, - flags: 0, - value: null, - expires: Ci.nsIAnnotationService.EXPIRE_NEVER }; - - if (PlacesUtils.annotations.pageHasAnnotation(this._uri, this._anno.name)) { - // fill the old anno if it is set - var flags = {}, expires = {}, mimeType = {}, type = {}; - PlacesUtils.annotations.getPageAnnotationInfo(this._uri, this._anno.name, - flags, expires, mimeType, type); - this._oldAnno.flags = flags.value; - this._oldAnno.expires = expires.value; - this._oldAnno.mimeType = mimeType.value; - this._oldAnno.type = type.value; - this._oldAnno.value = PlacesUtils.annotations - .getPageAnnotation(this._uri, this._anno.name); - } - - this.redoTransaction = this.doTransaction; -} - -placesSetPageAnnotationTransactions.prototype = { - __proto__: placesBaseTransaction.prototype, - - doTransaction: function PSPAT_doTransaction() { - PlacesUtils.setAnnotationsForURI(this._uri, [this._anno]); - }, - - undoTransaction: function PSPAT_undoTransaction() { - PlacesUtils.setAnnotationsForURI(this._uri, [this._oldAnno]); - } -}; - -function placesEditBookmarkKeywordTransactions(id, newKeyword) { - this.id = id; - this._newKeyword = newKeyword; - this._oldKeyword = ""; - this.redoTransaction = this.doTransaction; -} - -placesEditBookmarkKeywordTransactions.prototype = { - __proto__: placesBaseTransaction.prototype, - - doTransaction: function PEBKT_doTransaction() { - this._oldKeyword = PlacesUtils.bookmarks.getKeywordForBookmark(this.id); - PlacesUtils.bookmarks.setKeywordForBookmark(this.id, this._newKeyword); - }, - - undoTransaction: function PEBKT_undoTransaction() { - PlacesUtils.bookmarks.setKeywordForBookmark(this.id, this._oldKeyword); - } -}; - -function placesEditBookmarkPostDataTransactions(aItemId, aPostData) { - this.id = aItemId; - this._newPostData = aPostData; - this._oldPostData = null; - this.redoTransaction = this.doTransaction; -} - -placesEditBookmarkPostDataTransactions.prototype = { - __proto__: placesBaseTransaction.prototype, - - doTransaction: function PEUPDT_doTransaction() { - this._oldPostData = PlacesUtils.getPostDataForBookmark(this.id); - PlacesUtils.setPostDataForBookmark(this.id, this._newPostData); - }, - - undoTransaction: function PEUPDT_undoTransaction() { - PlacesUtils.setPostDataForBookmark(this.id, this._oldPostData); - } -}; - -function placesEditLivemarkSiteURITransactions(folderId, uri) { - this._folderId = folderId; - this._newURI = uri; - this._oldURI = null; - this.redoTransaction = this.doTransaction; -} - -placesEditLivemarkSiteURITransactions.prototype = { - __proto__: placesBaseTransaction.prototype, - - doTransaction: function PELSUT_doTransaction() { - this._oldURI = PlacesUtils.livemarks.getSiteURI(this._folderId); - PlacesUtils.livemarks.setSiteURI(this._folderId, this._newURI); - }, - - undoTransaction: function PELSUT_undoTransaction() { - PlacesUtils.livemarks.setSiteURI(this._folderId, this._oldURI); - } -}; - -function placesEditLivemarkFeedURITransactions(folderId, uri) { - this._folderId = folderId; - this._newURI = uri; - this._oldURI = null; - this.redoTransaction = this.doTransaction; -} - -placesEditLivemarkFeedURITransactions.prototype = { - __proto__: placesBaseTransaction.prototype, - - doTransaction: function PELFUT_doTransaction() { - this._oldURI = PlacesUtils.livemarks.getFeedURI(this._folderId); - PlacesUtils.livemarks.setFeedURI(this._folderId, this._newURI); - PlacesUtils.livemarks.reloadLivemarkFolder(this._folderId); - }, - - undoTransaction: function PELFUT_undoTransaction() { - PlacesUtils.livemarks.setFeedURI(this._folderId, this._oldURI); - PlacesUtils.livemarks.reloadLivemarkFolder(this._folderId); - } -}; - -function placesEditBookmarkMicrosummaryTransactions(aItemId, newMicrosummary) { - this.id = aItemId; - this._mss = Cc["@mozilla.org/microsummary/service;1"]. - getService(Ci.nsIMicrosummaryService); - this._newMicrosummary = newMicrosummary; - this._oldMicrosummary = null; - this.redoTransaction = this.doTransaction; -} - -placesEditBookmarkMicrosummaryTransactions.prototype = { - __proto__: placesBaseTransaction.prototype, - - doTransaction: function PEBMT_doTransaction() { - this._oldMicrosummary = this._mss.getMicrosummary(this.id); - if (this._newMicrosummary) - this._mss.setMicrosummary(this.id, this._newMicrosummary); - else - this._mss.removeMicrosummary(this.id); - }, - - undoTransaction: function PEBMT_undoTransaction() { - if (this._oldMicrosummary) - this._mss.setMicrosummary(this.id, this._oldMicrosummary); - else - this._mss.removeMicrosummary(this.id); - } -}; - -function placesEditItemDateAddedTransaction(id, newDateAdded) { - this.id = id; - this._newDateAdded = newDateAdded; - this._oldDateAdded = null; - this.redoTransaction = this.doTransaction; -} - -placesEditItemDateAddedTransaction.prototype = { - __proto__: placesBaseTransaction.prototype, - - // to support folders as well - get container() { return this.id; }, - set container(val) { return this.id = val; }, - - doTransaction: function PEIDA_doTransaction() { - this._oldDateAdded = PlacesUtils.bookmarks.getItemDateAdded(this.id); - PlacesUtils.bookmarks.setItemDateAdded(this.id, this._newDateAdded); - }, - - undoTransaction: function PEIDA_undoTransaction() { - PlacesUtils.bookmarks.setItemDateAdded(this.id, this._oldDateAdded); - } -}; - -function placesEditItemLastModifiedTransaction(id, newLastModified) { - this.id = id; - this._newLastModified = newLastModified; - this._oldLastModified = null; - this.redoTransaction = this.doTransaction; -} - -placesEditItemLastModifiedTransaction.prototype = { - __proto__: placesBaseTransaction.prototype, - - // to support folders as well - get container() { return this.id; }, - set container(val) { return this.id = val; }, - - doTransaction: function PEILM_doTransaction() { - this._oldLastModified = PlacesUtils.bookmarks.getItemLastModified(this.id); - PlacesUtils.bookmarks.setItemLastModified(this.id, this._newLastModified); - }, - - undoTransaction: function PEILM_undoTransaction() { - PlacesUtils.bookmarks.setItemLastModified(this.id, this._oldLastModified); - } -}; - -function placesSortFolderByNameTransactions(aFolderId) { - this._folderId = aFolderId; - this._oldOrder = null, - this.redoTransaction = this.doTransaction; -} - -placesSortFolderByNameTransactions.prototype = { - __proto__: placesBaseTransaction.prototype, - - doTransaction: function PSSFBN_doTransaction() { - this._oldOrder = []; - - var contents = - PlacesUtils.getFolderContents(this._folderId, false, false).root; - var count = contents.childCount; - - // sort between separators - var newOrder = []; - var preSep = []; // temporary array for sorting each group of items - var sortingMethod = - function (a, b) { - if (PlacesUtils.nodeIsContainer(a) && !PlacesUtils.nodeIsContainer(b)) - return -1; - if (!PlacesUtils.nodeIsContainer(a) && PlacesUtils.nodeIsContainer(b)) - return 1; - return a.title.localeCompare(b.title); - }; - - for (var i = 0; i < count; ++i) { - var item = contents.getChild(i); - this._oldOrder[item.itemId] = i; - if (PlacesUtils.nodeIsSeparator(item)) { - if (preSep.length > 0) { - preSep.sort(sortingMethod); - newOrder = newOrder.concat(preSep); - preSep.splice(0); - } - newOrder.push(item); - } - else - preSep.push(item); - } - contents.containerOpen = false; - - if (preSep.length > 0) { - preSep.sort(sortingMethod); - newOrder = newOrder.concat(preSep); - } - - // set the nex indexes - var callback = { - runBatched: function() { - for (var i = 0; i < newOrder.length; ++i) { - PlacesUtils.bookmarks.setItemIndex(newOrder[i].itemId, i); - } - } - }; - PlacesUtils.bookmarks.runInBatchMode(callback, null); - }, - - undoTransaction: function PSSFBN_undoTransaction() { - var callback = { - _self: this, - runBatched: function() { - for (item in this._self._oldOrder) - PlacesUtils.bookmarks.setItemIndex(item, this._self._oldOrder[item]); - } - }; - PlacesUtils.bookmarks.runInBatchMode(callback, null); - } -}; - -function placesTagURITransaction(aURI, aTags) { - this._uri = aURI; - this._tags = aTags; - this._unfiledItemId = -1; - this.redoTransaction = this.doTransaction; -} - -placesTagURITransaction.prototype = { - __proto__: placesBaseTransaction.prototype, - - doTransaction: function PTU_doTransaction() { - if (PlacesUtils.getMostRecentBookmarkForURI(this._uri) == -1) { - // Force an unfiled bookmark first - this._unfiledItemId = - PlacesUtils.bookmarks - .insertBookmark(PlacesUtils.unfiledBookmarksFolderId, - this._uri, - PlacesUtils.bookmarks.DEFAULT_INDEX, - PlacesUtils.history.getPageTitle(this._uri)); - if (this._GUID) - PlacesUtils.bookmarks.setItemGUID(this._unfiledItemId, this._GUID); - } - PlacesUtils.tagging.tagURI(this._uri, this._tags); - }, - - undoTransaction: function PTU_undoTransaction() { - if (this._unfiledItemId != -1) { - // If a GUID exists for this item, preserve it before removing the item. - if (PlacesUtils.annotations.itemHasAnnotation(this._unfiledItemId, PlacesUtils.GUID_ANNO)) { - this._GUID = PlacesUtils.bookmarks.getItemGUID(this._unfiledItemId); - } - PlacesUtils.bookmarks.removeItem(this._unfiledItemId); - this._unfiledItemId = -1; - } - PlacesUtils.tagging.untagURI(this._uri, this._tags); - } -}; - -function placesUntagURITransaction(aURI, aTags) { - this._uri = aURI; - if (aTags) { - // Within this transaction, we cannot rely on tags given by itemId - // since the tag containers may be gone after we call untagURI. - // Thus, we convert each tag given by its itemId to name. - this._tags = aTags; - for (var i=0; i < aTags.length; i++) { - if (typeof(this._tags[i]) == "number") - this._tags[i] = PlacesUtils.bookmarks.getItemTitle(this._tags[i]); - } - } - else - this._tags = PlacesUtils.tagging.getTagsForURI(this._uri); - - this.redoTransaction = this.doTransaction; -} - -placesUntagURITransaction.prototype = { - __proto__: placesBaseTransaction.prototype, - - doTransaction: function PUTU_doTransaction() { - PlacesUtils.tagging.untagURI(this._uri, this._tags); - }, - - undoTransaction: function PUTU_undoTransaction() { - PlacesUtils.tagging.tagURI(this._uri, this._tags); - } -}; - -var NSGetFactory = XPCOMUtils.generateNSGetFactory([placesTransactionsService]);
--- a/browser/components/places/tests/browser/browser_views_liveupdate.js +++ b/browser/components/places/tests/browser/browser_views_liveupdate.js @@ -99,17 +99,17 @@ function startTest() { bs.DEFAULT_INDEX, "bm1"); bs.setItemTitle(id, "bm1_edited"); addedBookmarks.push(id); id = bs.insertBookmark(bs.bookmarksMenuFolder, PlacesUtils._uri("place:"), bs.DEFAULT_INDEX, "bm2"); - bs.setItemTitle(id, "bm2_edited"); + bs.setItemTitle(id, ""); addedBookmarks.push(id); id = bs.insertSeparator(bs.bookmarksMenuFolder, bs.DEFAULT_INDEX); addedBookmarks.push(id); id = bs.createFolder(bs.bookmarksMenuFolder, "bmf", bs.DEFAULT_INDEX); bs.setItemTitle(id, "bmf_edited"); addedBookmarks.push(id); @@ -130,17 +130,17 @@ function startTest() { bs.setItemTitle(id, "tb1_edited"); addedBookmarks.push(id); // Test live update of title. bs.setItemTitle(id, "tb1_edited"); id = bs.insertBookmark(bs.toolbarFolder, PlacesUtils._uri("place:"), bs.DEFAULT_INDEX, "tb2"); - bs.setItemTitle(id, "tb2_edited"); + bs.setItemTitle(id, ""); addedBookmarks.push(id); id = bs.insertSeparator(bs.toolbarFolder, bs.DEFAULT_INDEX); addedBookmarks.push(id); id = bs.createFolder(bs.toolbarFolder, "tbf", bs.DEFAULT_INDEX); bs.setItemTitle(id, "tbf_edited"); addedBookmarks.push(id); @@ -280,19 +280,23 @@ var bookmarksObserver = { // Check that item has been moved in the correct position. let validator = function(aElementOrTreeIndex) { if (typeof(aElementOrTreeIndex) == "number") { var sidebar = document.getElementById("sidebar"); var tree = sidebar.contentDocument.getElementById("bookmarks-view"); let cellText = tree.view.getCellText(aElementOrTreeIndex, tree.columns.getColumnAt(0)); + if (!aNewValue) + return cellText == PlacesUIUtils.getBestTitle(tree.view.nodeForTreeIndex(aElementOrTreeIndex)); return cellText == aNewValue; } else { + if (!aNewValue && aElementOrTreeIndex.localName != "toolbarbutton") + return aElementOrTreeIndex.label == PlacesUIUtils.getBestTitle(aElementOrTreeIndex._placesNode); return aElementOrTreeIndex.label == aNewValue; } }; for (var i = 0; i < views.length; i++) { var [node, index, valid] = searchItemInView(aItemId, views[i], validator); isnot(node, null, "Found changed Places node in " + views[i]); is(node.title, aNewValue, "Node has correct title: " + aNewValue);
--- a/browser/components/places/tests/unit/test_placesTxn.js +++ b/browser/components/places/tests/unit/test_placesTxn.js @@ -33,60 +33,22 @@ * 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 ***** */ -// Get bookmark service -try { - var bmsvc = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].getService(Ci.nsINavBookmarksService); -} catch(ex) { - do_throw("Could not get nav-bookmarks-service\n"); -} - -// Get livemark service -try { - var lmsvc = Cc["@mozilla.org/browser/livemark-service;2"].getService(Ci.nsILivemarkService); -} catch(ex) { - do_throw("Could not get livemark-service\n"); -} - -// Get microsummary service -try { - var mss = Cc["@mozilla.org/microsummary/service;1"].getService(Ci.nsIMicrosummaryService); -} catch(ex) { - do_throw("Could not get microsummary-service\n"); -} - -// Get Places Transaction Manager Service -try { - var ptSvc = Cc["@mozilla.org/browser/placesTransactionsService;1"]. - getService(Ci.nsIPlacesTransactionsService); -} catch(ex) { - do_throw("Could not get Places Transactions Service\n"); -} - -// Get tagging service -try { - var tagssvc = Cc["@mozilla.org/browser/tagging-service;1"]. - getService(Ci.nsITaggingService); -} catch(ex) { - do_throw("Could not get tagging service\n"); -} - -// Get annotations service -try { - var annosvc = Cc["@mozilla.org/browser/annotation-service;1"]. - getService(Ci.nsIAnnotationService); -} catch(ex) { - do_throw("Could not get annotations service\n"); -} +var bmsvc = PlacesUtils.bookmarks; +var lmsvc = PlacesUtils.livemarks; +var mss = PlacesUtils.microsummaries; +var ptSvc = PlacesUIUtils.ptm; +var tagssvc = PlacesUtils.tagging; +var annosvc = PlacesUtils.annotations; // create and add bookmarks observer var observer = { onBeginUpdateBatch: function() { this._beginUpdateBatch = true; }, onEndUpdateBatch: function() { this._endUpdateBatch = true; @@ -138,19 +100,18 @@ bmsvc.addObserver(observer, false); var bmStartIndex = 0; // main function run_test() { // get bookmarks root index var root = bmsvc.bookmarksMenuFolder; //Test creating a folder with a description - const DESCRIPTION_ANNO = "bookmarkProperties/description"; const TEST_DESCRIPTION = "this is my test description"; - var annos = [{ name: DESCRIPTION_ANNO, + var annos = [{ name: PlacesUIUtils.DESCRIPTION_ANNO, type: annosvc.TYPE_STRING, flags: 0, value: TEST_DESCRIPTION, expires: annosvc.EXPIRE_NEVER }]; var txn1 = ptSvc.createFolder("Testing folder", root, bmStartIndex, annos); ptSvc.doTransaction(txn1); // This checks that calling undoTransaction on an "empty batch" doesn't @@ -160,17 +121,17 @@ function run_test() { ptSvc.undoTransaction(); var folderId = observer._itemAddedId; do_check_eq(bmsvc.getItemTitle(folderId), "Testing folder"); do_check_eq(observer._itemAddedIndex, bmStartIndex); do_check_eq(observer._itemAddedParent, root); do_check_eq(observer._itemAddedId, folderId); do_check_eq(TEST_DESCRIPTION, - annosvc.getItemAnnotation(folderId, DESCRIPTION_ANNO)); + annosvc.getItemAnnotation(folderId, PlacesUIUtils.DESCRIPTION_ANNO)); txn1.undoTransaction(); do_check_eq(observer._itemRemovedId, folderId); do_check_eq(observer._itemRemovedFolder, root); do_check_eq(observer._itemRemovedIndex, bmStartIndex); txn1.redoTransaction(); do_check_eq(observer._itemAddedIndex, bmStartIndex); do_check_eq(observer._itemAddedParent, root); @@ -410,21 +371,21 @@ function run_test() { do_check_eq(observer._itemChangedId, bkmk1Id); do_check_eq(observer._itemChangedProperty, "uri"); do_check_eq(observer._itemChangedValue, "http://newuri.com/"); txn9.undoTransaction(); do_check_eq(observer._itemChangedId, bkmk1Id); do_check_eq(observer._itemChangedProperty, "uri"); do_check_eq(observer._itemChangedValue, "http://www.example3.com/"); - // Test edit item description + // Test edit description transaction. var txn10 = ptSvc.editItemDescription(bkmk1Id, "Description1"); txn10.doTransaction(); do_check_eq(observer._itemChangedId, bkmk1Id); - do_check_eq(observer._itemChangedProperty, "bookmarkProperties/description"); + do_check_eq(observer._itemChangedProperty, PlacesUIUtils.DESCRIPTION_ANNO); // Testing edit keyword var txn11 = ptSvc.editBookmarkKeyword(bkmk1Id, "kw1"); txn11.doTransaction(); do_check_eq(observer._itemChangedId, bkmk1Id); do_check_eq(observer._itemChangedProperty, "keyword"); do_check_eq(observer._itemChangedValue, "kw1"); txn11.undoTransaction(); @@ -505,26 +466,25 @@ function run_test() { do_check_true(lmsvc.isLivemark(lvmkId)); do_check_eq(lmsvc.getSiteURI(lvmkId).spec, "http://siteuri.com/"); do_check_eq(lmsvc.getFeedURI(lvmkId).spec, "http://feeduri.com/"); do_check_eq(annosvc.getItemAnnotation(lvmkId, "livemark/testAnno"), "testAnno"); txn15.redoTransaction(); do_check_false(lmsvc.isLivemark(lvmkId)); do_check_eq(observer._itemRemovedId, lvmkId); - // Test setLoadInSidebar - const LOAD_IN_SIDEBAR_ANNO = "bookmarkProperties/loadInSidebar"; + // Test LoadInSidebar transaction. var txn16 = ptSvc.setLoadInSidebar(bkmk1Id, true); txn16.doTransaction(); do_check_eq(observer._itemChangedId, bkmk1Id); - do_check_eq(observer._itemChangedProperty, LOAD_IN_SIDEBAR_ANNO); + do_check_eq(observer._itemChangedProperty, PlacesUIUtils.LOAD_IN_SIDEBAR_ANNO); do_check_eq(observer._itemChanged_isAnnotationProperty, true); txn16.undoTransaction(); do_check_eq(observer._itemChangedId, bkmk1Id); - do_check_eq(observer._itemChangedProperty, LOAD_IN_SIDEBAR_ANNO); + do_check_eq(observer._itemChangedProperty, PlacesUIUtils.LOAD_IN_SIDEBAR_ANNO); do_check_eq(observer._itemChanged_isAnnotationProperty, true); // Test generic item annotation var itemAnnoObj = { name: "testAnno/testInt", type: Ci.nsIAnnotationService.TYPE_INT32, flags: 0, value: 123, expires: Ci.nsIAnnotationService.EXPIRE_NEVER };
--- a/browser/components/places/tests/unit/test_txnGUIDs.js +++ b/browser/components/places/tests/unit/test_txnGUIDs.js @@ -1,89 +1,87 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ : - * ***** 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 - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2009 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Marco Bonardo <mak77@bonardo.net> - * - * 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 ***** */ - -/** - * This test will ensure any transactions service that is going to create - * a new item, won't replace the GUID when undoing and redoing the action. - */ -var bmsvc = Cc["@mozilla.org/browser/nav-bookmarks-service;1"]. - getService(Ci.nsINavBookmarksService); -var txnsvc = Cc["@mozilla.org/browser/placesTransactionsService;1"]. - getService(Ci.nsIPlacesTransactionsService); - -function test_GUID_persistance(aTxn) { - aTxn.doTransaction(); - var itemId = bmsvc.getIdForItemAt(bmsvc.unfiledBookmarksFolder, 0); - var GUID = bmsvc.getItemGUID(itemId); - aTxn.undoTransaction(); - aTxn.redoTransaction(); - do_check_eq(GUID, bmsvc.getItemGUID(itemId)); - aTxn.undoTransaction(); -} - -function run_test() { - // Create folder. - var createFolderTxn = txnsvc.createFolder("Test folder", - bmsvc.unfiledBookmarksFolder, - bmsvc.DEFAULT_INDEX); - test_GUID_persistance(createFolderTxn); - - // Create bookmark. - var createBookmarkTxn = txnsvc.createItem(uri("http://www.example.com"), - bmsvc.unfiledBookmarksFolder, - bmsvc.DEFAULT_INDEX, - "Test bookmark"); - test_GUID_persistance(createBookmarkTxn); - - // Create separator. - var createSeparatorTxn = txnsvc.createSeparator(bmsvc.unfiledBookmarksFolder, - bmsvc.DEFAULT_INDEX); - test_GUID_persistance(createFolderTxn); - - // Create livemark. - var createLivemarkTxn = txnsvc.createLivemark(uri("http://feeduri.com"), - uri("http://siteuri.com"), - "Test livemark", - bmsvc.unfiledBookmarksFolder, - bmsvc.DEFAULT_INDEX); - test_GUID_persistance(createLivemarkTxn); - - // Tag URI. - var tagURITxn = txnsvc.tagURI(uri("http://www.example.com"), ["foo"]); - test_GUID_persistance(tagURITxn); -} +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ : + * ***** 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 + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2009 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Marco Bonardo <mak77@bonardo.net> + * + * 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 ***** */ + +/** + * This test will ensure any transactions service that is going to create + * a new item, won't replace the GUID when undoing and redoing the action. + */ +var bmsvc = PlacesUtils.bookmarks; +var txnsvc = PlacesUIUtils.ptm; + +function test_GUID_persistance(aTxn) { + aTxn.doTransaction(); + var itemId = bmsvc.getIdForItemAt(bmsvc.unfiledBookmarksFolder, 0); + var GUID = bmsvc.getItemGUID(itemId); + aTxn.undoTransaction(); + aTxn.redoTransaction(); + do_check_eq(GUID, bmsvc.getItemGUID(itemId)); + aTxn.undoTransaction(); +} + +function run_test() { + // Create folder. + var createFolderTxn = txnsvc.createFolder("Test folder", + bmsvc.unfiledBookmarksFolder, + bmsvc.DEFAULT_INDEX); + test_GUID_persistance(createFolderTxn); + + // Create bookmark. + var createBookmarkTxn = txnsvc.createItem(uri("http://www.example.com"), + bmsvc.unfiledBookmarksFolder, + bmsvc.DEFAULT_INDEX, + "Test bookmark"); + test_GUID_persistance(createBookmarkTxn); + + // Create separator. + var createSeparatorTxn = txnsvc.createSeparator(bmsvc.unfiledBookmarksFolder, + bmsvc.DEFAULT_INDEX); + test_GUID_persistance(createFolderTxn); + + // Create livemark. + var createLivemarkTxn = txnsvc.createLivemark(uri("http://feeduri.com"), + uri("http://siteuri.com"), + "Test livemark", + bmsvc.unfiledBookmarksFolder, + bmsvc.DEFAULT_INDEX); + test_GUID_persistance(createLivemarkTxn); + + // Tag URI. + var tagURITxn = txnsvc.tagURI(uri("http://www.example.com"), ["foo"]); + test_GUID_persistance(tagURITxn); +}
--- a/browser/installer/package-manifest.in +++ b/browser/installer/package-manifest.in @@ -114,17 +114,16 @@ #endif @BINPATH@/components/accessibility.xpt #endif @BINPATH@/components/appshell.xpt @BINPATH@/components/appstartup.xpt @BINPATH@/components/autocomplete.xpt @BINPATH@/components/autoconfig.xpt @BINPATH@/components/browsercompsbase.xpt -@BINPATH@/components/browserplaces.xpt @BINPATH@/components/browser-feeds.xpt @BINPATH@/components/caps.xpt @BINPATH@/components/chardet.xpt @BINPATH@/components/chrome.xpt @BINPATH@/components/commandhandler.xpt @BINPATH@/components/commandlines.xpt @BINPATH@/components/composer.xpt @BINPATH@/components/content_base.xpt @@ -275,17 +274,16 @@ @BINPATH@/components/WebContentConverter.js @BINPATH@/components/BrowserComponents.manifest @BINPATH@/components/nsBrowserContentHandler.js @BINPATH@/components/nsBrowserGlue.js @BINPATH@/components/nsSetDefaultBrowser.manifest @BINPATH@/components/nsSetDefaultBrowser.js @BINPATH@/components/nsMicrosummaryService.js @BINPATH@/components/BrowserPlaces.manifest -@BINPATH@/components/nsPlacesTransactionsService.js @BINPATH@/components/nsPrivateBrowsingService.manifest @BINPATH@/components/nsPrivateBrowsingService.js @BINPATH@/components/toolkitsearch.manifest @BINPATH@/components/nsSearchService.js @BINPATH@/components/nsSearchSuggestions.js @BINPATH@/components/nsTryToClose.manifest @BINPATH@/components/nsTryToClose.js @BINPATH@/components/passwordmgr.manifest
--- a/browser/installer/removed-files.in +++ b/browser/installer/removed-files.in @@ -550,17 +550,16 @@ xpicleanup@BIN_SUFFIX@ ../Resources/firefox-bin.rsrc components/accessibility.xpt components/alerts.xpt components/appshell.xpt components/appstartup.xpt components/autoconfig.xpt components/browser-feeds.xpt components/browsercompsbase.xpt - components/browserplaces.xpt components/browsersearch.xpt components/caps.xpt components/chardet.xpt components/chrome.xpt components/commandhandler.xpt components/commandlines.xpt components/composer.xpt components/content.xpt @@ -856,8 +855,10 @@ extensions/inspector@mozilla.org/install extensions/inspector@mozilla.org/components/inspector-cmdline.js extensions/inspector@mozilla.org/chrome.manifest extensions/inspector@mozilla.org/chrome/inspector.jar extensions/inspector@mozilla.org/defaults/preferences/inspector.js extensions/inspector@mozilla.org/platform/WINNT/chrome/icons/default/winInspectorMain.ico extensions/inspector@mozilla.org/components/inspector.xpt extensions/inspector@mozilla.org/components/@DLL_PREFIX@inspector@DLL_SUFFIX@ extensions/inspector@mozilla.org/chrome/icons/default/winInspectorMain.ico +components/nsPlacesTransactionsService.js +components/browserplaces.xpt
deleted file mode 100644 index 8503bc31498fab300e93acdf732dc91d03c7f3b7..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@<O00001
new file mode 100644 index 0000000000000000000000000000000000000000..082b177811eb58303ee74b744e924adaf7223ade GIT binary patch literal 606 zc$@)V0-^nhP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV0006dNkl<ZILn2T z-)mBF7{(6>yNDu!h-y^WT4$vu1#K<dtOkxvn`sG~UUboqMYteyQF<{qGz&5hoQiJx zN!w^aFcv6X8H28jF=7yO(Z3J`gMsk$J_nW4k?7)s&-1*``{j7_s{l~Ube(^y3I(Am z)aq30nQHC-Wz>+K5Z2@RXH32Oh6m-J2Gq<rW2fbS&Y;#Nl*TekxIMdy@h4w!dSc%A zG;7Y-VV67213Cf^wNUB<l5bbxODsTqMHuP3_6CHS8E5RUE52YHU>~~g5^57KzT(V{ zIf%|T9#1qqOg_&}{CSmmO*pLV^JTTc<a-2Cix6EAY>frc%wY01Vfk!&5x!dsoE4Nk z15@9_Gi5k06d~GUealv)<8?+fgr-aEuPN=`)JACL6TI<R^h7m?H?S@?^4^$cbc2~P z{V!#wXL4gW^%1>SUgCg13-Jcl0~&c}AcvDzUt#F(68&#w$BCOi`s4Gk`!W#y->)DY zuYGVDp6he$uPNJ)$8~3<2=|x{(G{Wj5=AqE$=ifwcl0qFkw=_q%C=+UE}_<Q`8Ay9 zauD788Aa2><nxYT4&Bn_4tI^g)+3kny#r~uW6y9jl!f?;FtV#J2|~?`Gj`Y&uQmUP zTO1eLgwpQ*Npyt^=#CcQ@~6?^zh^+rj5BuF<xb0G+I%RM5Z2pI-NF9h9Mo{pfSMU+ s?ELdKl1&FkRiPlP2&l7C&swhYA1K2vaguu^HUIzs07*qoM6N<$f{UggX8-^I
new file mode 100644 index 0000000000000000000000000000000000000000..6e09ab9c32d021d9f1f4c937943b31be08cb87c8 GIT binary patch literal 8056 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 GLSTZxlG)Ax
--- a/browser/themes/gnomestripe/browser/browser.css +++ b/browser/themes/gnomestripe/browser/browser.css @@ -980,26 +980,26 @@ toolbar[iconsize="small"] #fullscreen-bu .popup-notification-icon { width: 64px; height: 64px; -moz-margin-end: 10px; } .popup-notification-icon[popupid="geolocation"] { - list-style-image: url(chrome://browser/skin/Geo.png); + list-style-image: url(chrome://browser/skin/Geolocation-64.png); } /* Notification icon box */ #notification-popup-box { margin: 0 3px; } #geo-notification-icon { - list-style-image: url(chrome://browser/skin/Geo.png); + list-style-image: url(chrome://browser/skin/Geolocation-16.png); width: 16px; height: 16px; } /* Feed icon */ #feed-button, #feed-button > .button-box, #feed-button:hover:active > .button-box {
--- a/browser/themes/gnomestripe/browser/jar.mn +++ b/browser/themes/gnomestripe/browser/jar.mn @@ -5,17 +5,18 @@ browser.jar: * skin/classic/browser/aboutPrivateBrowsing.css (aboutPrivateBrowsing.css) * skin/classic/browser/aboutSessionRestore.css (aboutSessionRestore.css) skin/classic/browser/aboutSessionRestore-window-icon.png skin/classic/browser/aboutCertError.css (aboutCertError.css) skin/classic/browser/actionicon-tab.png * skin/classic/browser/browser.css (browser.css) * skin/classic/browser/engineManager.css (engineManager.css) skin/classic/browser/fullscreen-video.css - skin/classic/browser/Geo.png + skin/classic/browser/Geolocation-16.png + skin/classic/browser/Geolocation-64.png skin/classic/browser/Go-arrow.png skin/classic/browser/identity.png skin/classic/browser/Info.png skin/classic/browser/KUI-close.png skin/classic/browser/monitor.png skin/classic/browser/monitor_16-10.png * skin/classic/browser/pageInfo.css skin/classic/browser/pageInfo.png
deleted file mode 100644 index 566a8ae74d6c94305b125883d9592fc292b6e9bf..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@<O00001
new file mode 100644 index 0000000000000000000000000000000000000000..a40cc1bb9ab74689fc3b7fdcffb3c9258387e4f4 GIT binary patch literal 416 zc$@*C0bl-!P)<h;3K|Lk000e1NJLTq000mG000mO1ONa4wfZ;e0004JNkl<ZC{t}w z%WA?<6g(>z^&JtTCTjCA(s=QKfd<962)2Stzr_Ct1o932071x41cZVhbn6EM3V{oO z=|W?>D6=@joZ&ne0^RUr6ueSYPRnU2DtJ#urr%3(FC-1LAwxzR4G2kb|1jipl~6>7 z_X5SyV?9=!UeMtpDq%hcB9P!qP_N1u1X3^RCkUjB)vE--15uU9X`id?Hc&Y}A8t%# zeJ-cf7i#(g41(+=xh@MC9|Q)P9;p`wZIOw8p)DAcGnsq}gSVo3Sk<ytRjVIck&#Sc z#x&t`SSgFNP<$9fO*^t^md-KxChKbj+x~BbZLeUR$qJSj`I%Vj)WnRB{3T{SjhT~9 zxpaS1I!GUP#-@Ckjv0ZRU<LEqVjvJZvl9r^V&-)P#|IH;mUBY~L*DguXCBXEebM!Y z+<_a;a*wdqdpEIR;~j5!g$*}Z|AuvgYizvjX@?!Qr;X=6;{E{z2IkOF7ucEr0000< KMNUMnLSTaTC#<6Y
new file mode 100644 index 0000000000000000000000000000000000000000..099b9c76f355237c3ae163f5c17845bb2cf36c6c GIT binary patch literal 8490 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 Y57q13Is`|s(f|Me07*qoM6N<$g6Am5R{#J2
--- a/browser/themes/pinstripe/browser/browser.css +++ b/browser/themes/pinstripe/browser/browser.css @@ -1805,47 +1805,47 @@ toolbarbutton.chevron > .toolbarbutton-m #identity-popup, #notification-popup { -moz-appearance: none; -moz-window-shadow: none; background-color: transparent; margin-top: -3px; margin-left: -23px; min-width: 280px; - -moz-border-image: url(chrome://browser/skin/hud-panel.png) 26 18 22 50 / 26px 18px 22px 50px repeat; + -moz-border-image: url(chrome://browser/skin/hud-panel.png) 26 18 22 50 / 26px 18px 22px 50px repeat; } #notification-popup { margin-top: -1px; margin-left: -27px; } #notification-popup-box { margin: 0 3px; } #geo-notification-icon { - list-style-image: url(chrome://browser/skin/Geo.png); + list-style-image: url(chrome://browser/skin/Geolocation-16.png); width: 16px; height: 16px; margin: 0 2px; } .popup-notification-description { color: #fff; } .popup-notification-icon { width: 64px; height: 64px; -moz-margin-end: 10px; } .popup-notification-icon[popupid="geolocation"] { - list-style-image: url(chrome://browser/skin/Geo.png); + list-style-image: url(chrome://browser/skin/Geolocation-64.png); } #identity-popup-container, #identity-popup-notification-container { margin: 4px 3px 2px -30px; color: #fff; }
--- a/browser/themes/pinstripe/browser/jar.mn +++ b/browser/themes/pinstripe/browser/jar.mn @@ -5,17 +5,18 @@ browser.jar: * skin/classic/browser/aboutSessionRestore.css (aboutSessionRestore.css) skin/classic/browser/aboutSessionRestore-window-icon.png skin/classic/browser/aboutCertError.css (aboutCertError.css) skin/classic/browser/actionicon-tab.png * skin/classic/browser/browser.css (browser.css) * skin/classic/browser/engineManager.css (engineManager.css) skin/classic/browser/feed-icons.png skin/classic/browser/fullscreen-video.css - skin/classic/browser/Geo.png + skin/classic/browser/Geolocation-16.png + skin/classic/browser/Geolocation-64.png skin/classic/browser/Go-arrow.png skin/classic/browser/home.png skin/classic/browser/hud-panel.png skin/classic/browser/hud-style-button-middle-background.png skin/classic/browser/hud-style-check-box-checked.png skin/classic/browser/hud-style-check-box-empty.png skin/classic/browser/hud-style-dropmarker-double-arrows.png skin/classic/browser/hud-style-expander-closed.png
deleted file mode 100644 index d81f056341e85dbede3ca5b02d35c2469969dde0..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@<O00001
deleted file mode 100644 index 9ae4c5a25748e66d9298b971b9fdbc5a45bf4669..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@<O00001
new file mode 100644 index 0000000000000000000000000000000000000000..d710e7336dbc445d36ee4868257d9139c50f8919 GIT binary patch literal 704 zc$@*i0zdtUP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV0007qNkl<ZILl-B z|NlP&G6n(_AZ}z}VBf~TC3F{zL2R%Xg9?UvG|d^TyrMV66*O<F=$hRyuyMNt!XP$C z3?v6qgJA#=umSNhQ8~3cidu%(BotJeWK=XQjI5ncfiQ>-5(CMB)PU52^dKA1ETy7* zTUpEKsECw;Hq3MtZKJ(PS_V5{d|^p>Z6!^^qad|FJq=L344R^{YPU5FEw2el$Y~-w zPgqiJv9N^P0%S2kaam1uL-VV`QYs)r)Ict2(loZZC9SB@j2=Lo{G!4fe4+yA;!+Cg z&1(7<HyIdM8W=>Rl=hk0xm_2QQZz$Xhzkpd$(k8iIbY|OklW3mqGNKy)j#s8j+y-p zUJ;p{3=FI*85kH9u|%&T(8gt4LXtZ)jjXTQdj?-t(9plYplxh@(?2p9C=hr{)6jgo zu(bS2Mos}t12}jU`Nd?Hs_U3+w|4fq;Sn5tSxv|E3WJ7$`2o+s=v&&xmd3<-K||Nn z*vUKOhO)NdZU$*Z^;So(pnGy^+AWy23dk_9^NXX4ODkzM+qih&5tmhNVi1&&*R*!= zzGrIZexHR;SPNMpzl8j9UNPC(sD|=u8Cp5tHM4WO!zV1I2^Lh-Hf(bXh<vDHVSk>5 zR}^lDslC@RLtEDaaLt^2TIxpD=N!C3?klS6G{aM(n4B`3p{3n2&%l@`macwJfa$(n zQOnpmJgwkXNMi0y8C5+CVHu@16FZMbPQIa!bc`*R0aGO#MrP7Awaj$&kGSt0k?=eu zDerlHUH9YM+Rn#;@tIHEf?}RJcn9CrG&IY^nHxb^%g92-*vhflGbCznL{j#%@T9C~ m?g0^d49)GE)D289vNHgKsnY3}7pKGk0000<MNUMnLSTYaut7oq
new file mode 100644 index 0000000000000000000000000000000000000000..1bd46ba5e146737f93c1ec1dfb1c80a6e203a59a GIT binary patch literal 8424 zc$@*~AQ#_>P)<h;3K|Lk000e1NJLTq002M$002M;1^@s6s%dfF001DbNkl<Zc-rNg zd6Zsdo##K#bGLV`Emf6NQk7KpKmvq4?2CvfB7z$@?qI9vj7@86JMEmtaoW~trR{0E zvGv$0ih?4jxUjf@0RoXF5V9|oq*AG>q}F%6_deVF@xDa@f<)S$an8Kw{LXXV`_?&i zf8XEt`EAed3g;aEKY#o`nI~B-T7WZvRW6{9K+G34w-Fcw?q-AA{~z&h#s5hL3{-yi zUjNzh3?bZGT!(xs9iC5w#NkjlA|X-EF=mvQus899`<wr#0J!t1X^eHk_k{GNkU|QH zb6zIQ??I<IZVgP&uzJeOJ0XWAN978_m7f7n`Y5ZpdLsVygRXVLAQORMzRp&k>l zyOIsA^d}3zKm~>;V)h=a1)0DLav9Ih1kwwA>HD7Wq!j+jw=I5eXhuKC!XRYa7@c(f zxP0Oz-`Vrwf7xWM)7m(bYO51vwRNbA-`;t$$g6MA?adO~)i>GTuK$w*V4wm!hbo?w zBJe#CMS+Ymp_d)@yhYPetf?7yteF^Jamkn7xx7nkE!w(cI6RJTz2-A?FI&u_qNHTJ zvJ_(5q!L>ZVsn@09_jbZZev~b_;)Wq-WP-4!{Hb<uM<zXb$=273{>EmJtaT%Wtfe; zOfK>=)xev5z>{w}R2sN4Nqd%?ksr`EG{9v)`YPE44l|tP&?O%sdBq#~{)Q=>gEybl zj_><qGZ9iqHXcmaJS`ZC{cW?`f;(0g-1jbgYxf6bZ{<yF*T35HEAs}xEiC+B1mM1H zRZ&fJ)Lsa(`HY_(i@arf)zpV~46S|rp4~r3)E98<taIoXxr=u^@NM#Qp)%IT$U8p8 z@SNkAQ;fLgjv-ni$#rLR(UlKa(v`>e1M2lU<#L&)_g4A#qcIDX&E;5cblp`yxMF4d z$ZnmqoxEoFU)Svh%)bW&|K(bJ_i$AzW3%0@QC8=JzRglz|J3duzJ2Yw8>mc=k_#dh zbuK~fw_Np`+sU<R_6{!MiU0fsg2G%@wfNjU7!wpDvVn&uCEa-sVGPa~d~3)AJ}dk3 zoU^~o#`TZ0wYBYxFTU<UP9D51IpeoKyaKohhzBa@m&=Afm;p^E=hah_YsvbBXYA<Z z>vrD!xkopAttBZ{kyvt3Krxr&G&75jK0HXKE##i)BEE6KpCj@`)^vihJ`Ws7amL}a z<+yf_^Jj;g+gF4jz#&Lg!mfjL9^QP2f!&j2>M?n17!_TxVp(a`ik6RDxk%grQ~?Fp zKNN&N2!MeK42{)2ZC$Y?>lYsrr7!;Y{`XzEZQE~<Mw1N#3b_oqOvnjofsd^nq;O20 z9b-$l{hAxd_&J7DJ3FcoMmw+$t281>K^Z(R;J>ZuW>&_dJtG;OPWiig_K=oivRaW< z3csFGE2r!{1mWUiIsN>Fw}0qV|3g3tNd8a|jv9c03TR{f$%<;LhyMI0>iciG^PV@Z z7#`e3AO-nMNHL!w6Z&*{A)i>M=xfpJs`T^yYyX<#a?el*i$uXP{&{o>Wn&>pAx^Ot zobYi5oOT@F9@3qWJTp|`;6$B3D?+95lN4D`Nh>Mi<1u@N6Ea=>TzKV)TdrP{eaoUE zdx09Dj}`>^2V`)v7Mqqh^80^2c*}S0`1z$P#z%ILi#%F$89G`E6tW@hEd{Q5c$fw4 zLyV5K^60e}vafv^X^_VTS-w(VMm-XEE=39hxeVm95c-I~Lj;niCsXd-S7oSf(Y{aO z`BbGx#q*f<e9FQ@1p$js*g|FONq%<oeaGDVo00GBuFwzU0Qo{$=gVTijPi-HnNjUl z{CMC?-+AQ8&n{0(bpkJ>r{;0aK|_mign>_Q#j-|DQ%@p3{oZ@%?OacrP_&9N#h{n3 zq_3l1NpY#c$N=XARyF*9Qx>N!D2G!9qYO6DxKtxj4T-|WDY~2zPbajt?V#BE12*0N zT9%x(h2A-TxAk2Y^t^dto}EX#9gZdn2xDBBDAV!q)cRXCZvFi7$R?~vJ>LCvh2uSi z*C7!CWGaYyQm|0jndR8@XJGab`Yl*dBz03<ES}*me>o=1Aq=1_!dY+vtN<r))`1lW zE5VmI<DsR+Nr{mjD)2}HkBL$j?Lm!Y=iW?dWEH!T8&=%1_6xUt@{+;@z!Z=Izt_Uv z4L98IQq~VDb=~%$E`8~@Pkrzl^bkv@1vfldrhksbP6(d%TX|+y7mJ^oMtB0dO%N`T z9QWYEjJM{g_O#*42;v%ZMM_s8!**uloTEWN0nRlZwYkh(<C;G?FxFwLMH`FJj=1XM znND&o1Gs1xm2?|ZmF-=_ZcYDb^9uI>dMd@Xhc5$wfeQ4#bwzvO_Ai|=s`VRo4gLHB z*`c4)8#_LF|1>R&1iSY~-1w>`JbCgQmLI6ID5z4eX1L=oE+W6BMti2t+$RpQ{j>#0 zJUnd>k<Z-7QWG5v>s(XGCJ-}X4=av!IP0E!-4v@W6Qk`M+I1#jpwRv%rfOSAZ0*=I ze8tXVXUT1VnM!dl2Ey<9fYqV}$$MQ<UQJQ<yOuCWXU!_;cvwo`;Z+>rX%_papqBa! z<+2<s7U(Q#`b%XVe(ebioUs6e;L<PtnpxQjk1SZm=mjS-mb;YM(E)xfFK0*<QK`iw z7TetWGpkcaiov8!Ni;fE=z5B(rKF{VwA5Im-~e4KZ)U2#n`|-9F+F#e-v8>AXD-S! z0Mr*2UU(}!mjSEAN>>oSVqx%Ve9=Z72Irh@c2=kIhbmPjT|lvH2<ng=khn<F78vI3 zsj>dD6)gGf2n&V}F=xj(`Qa*QE>EYiaLDJtn&Ww@_;$AW$5VDWqyuN0^fnEP;u^Vu zYpxA>p5=|j8H+WIYpV=aS?Z;T>4DXB&YdE)LyT<dkL0YC`P1eHzXsHcZ3X{G%e$=j z28)7jcId}VVeUWO^PPR;_w642&F*I|roE`iL>b=yvr(4TV*cq>{Y>{3ICFcIi>LN- z{*SgWHNTB^Q=x}RdP>u{y#ZlYiNf9j$)+<<=VtJnBPSe*5IEToD+TsNUGQNM0)!9< zDG^d2Jc;ln!V?6c&*C+|Bo-401C#rwdF<gm?|f|8F<(8UOKgBfy8Qd{fHUa!7P4RO zjF+DM=D|A$*KR4<>ksU>pS)Kg5CKk0YR*Hp2$mnH;k9I0F))Q(88EuChjkx+1rJ>J zYBsDskpa0JIaP;wmX0M8yz%~z@~OW(g{%Md<E-4eo~#grLf{LKqM_rnkLP|D1tFSf z{0<lbDFqfsX`%z`@5fq=0Jc54nFlvl{sPDV-V5ahM*^^lyzrQC-yQjv2Wo=}JwwBl zE5hm)@}5K*4`)1{o?8SXIB#TvGk$xB`L==^vJAcE7>a%l+0o9yHH)Zp7f5HfQ@g)| zU(J3elWsPJSuv+^FYo>KyZOXlU&y6D`V!saL(e`$BPu*kd-pp~AVd=Z*#H5r0mPwQ zC$qe($kI-q)6W`b$pXpNjR&sWTXj7^@KSleAR0$O90!C?PrJ8F>>6fS$1+CiJ|=Z& zD|oEGl{0pgSus22k|%c~`aDK-FBDoZ)4jyIBxkI>nRYXR^+Rrb-QV!U#c$)GFk;2v zR*t>@2P~-FNmu6>uN(V1m;T#VSl@m&KRM|tHuj$MY*ctQEY6^CBoNLWxig*>qce25 zmGpP+qA+KS!f~5ezjczeyB54<!SR{T1M%}AJsbsAi(c0ypCFL3bnb^Qx$(mP{;fj~ zKel4toV5(szC|h}i51{UI)&icUktILXA(ltqdBMxG+As*MATZt?l*k%oKNxK#qT0- zG_AfzTNsc9O2*Om>)Tni?oO6YK7rR4VJn8=@eXc1<r?l^d1)gWG{q>3O${d1jYyCv zbX}oqDXP+p2IUl~9CO+yxa|A~v1vqa_fFzuB|D=}Z2ic^eHQ|Uo?j;%-U1ukelcc$ zLaX$WEsuOQK2%=OnTgTfBWNJC4vocmP|r&abZ1a;NNH0mCE0})J|NiXmU4Uc-Tapi zKFqxrz5`RPph_ib(`6<qbw*;vq_V7A^LqZ_Ltp2k*Zzbb`Il1~3z^$J&h>l#CpUfP zO3vH(lg5^4MuEeuaL>sd+z|;>5-WD>%(8jgGCDdok?0E9Xe)EVCsu4OyTyR_dsAU2 zgBuw)myMk{|BP^af+*U<M0GFPIFODY%oBtW1+7^<GKKX$9)Ih(e0R|&m=Ym^*;I`~ zScA)E@U;Wyf%C8il1dE$XyK6vpTtQ@Ej`@)nvZg8=~~Wv{Kvd@+xM8)Il)KA{()<6 z`6s@*>N<Y0<W<cu$l-7}<1g$C2#xR7TISB(M@`oV1SnggJ##-h554-#V~gPv&E4W& zuo~R+K)TsgvNsMES9xk`3N5Bcjllwb*oABT3=_rgGJoGiWM{QAlrHCM^FPPFbRmiB zp=>17>JTTmxIxj>3hH5wN|dJ*<R}qPNi=b}f|@E}DpgFPs0Mj{dg@iY|EeGG`Od#! z|4<vPJqdp~{YAcZ=ha-e{cfDKO#m7z#yuC1CR=1sA$18#SYoS?Y$8h5u521yykHb) zh6u6u-txb$Tk?+GrRgfwWDW+2vfzb1)KojQ#Bj{M0jvnPYt>bZ$1PZ6i4%d<4yzpo zAL~4{5u`?tC`Uat)U>0DPu0s%6A`HfU5%k!ZUCn=&RXt2_BFikP2c15v#w|8Ks&v? zQ~c%rFY=AM-p=u(Pc;%J(*(jaL1}&u0uQ9XNJs1xsnAqZh4E@|%nSfWhC}}a(hmQS z%J!D3DW<jnuVWt0?8TTty2D!tlGk(c#6xHckDPfPT3fIJ=YcdDXTU~bv$As-<FH4- zE*#A)PGDt(3p_9hLMhM*0uL*FoE7|X*(Lm9(ZyV_`DeU${9l;gU*dlqyn#ozF5zz% zet<#S`fNt%tfQl?M$ha?^0Njo&R~r|3P;Vx)MK&Yg&5$!KwjWaPu7d2x<*ws+59_* zvbRxk*O97)T(aZicp2DM>gQl#HbUD*CS!p#!3u%1qLJr{XQNiLxM?^n*GzL~%3kM3 z;CwJKB2h?_VvsoDV~yj!g|Fnn?$fz^)9t)r;wP->*~OiEKFm$xGQKnKd?w2go)En4 z+OHEQ)09;WPk`_w&I+`u5#;t3;T-?@+x~?ZAWBm)<+?%DH08-&T=GehFu(*U{W~Qt z68w7ktFhW590*S!u((v?G8xdWVd`hWcFzIeu=0nU8V;Nn;liNNDobKy8snV6;Zydq zd~^BL{B-I(uG{ogF3fD;gW*qk+sOC%Z0B1TKYN^!(lBY7kjqMp5O~tVSc?RlnL0AD ze({#r5ANF5S}mtk>V`^9Q>_~+u_8${sWO~?=wV#R@@W6r&xzG8Q8?|eR${fqY4@Dp zpL?&lXHByMbmTqju);%o8I168X$sW}E{?I<a3Gk)Csurf>-`ThIU3M4zs_eTzs8%k z+(ShrXf%m680oN{L7~x}Au*b-{%CveQFVmsiKSdOn3_R`8sT|3AvylwMntQ}i0NV^ z+l^GV8G{8PO|eqq3=R6v04-(+a5#QH8@jB+cQNyV2dRrztaZe$jY+eh354J96Q%}9 z9kjz4iAfE=&adVX`x(A`@MD~m9pMscEW0b_<}-5~>XjI20I;3~&meHT_wr>!FWD4* z!)42-jgi!9hH6byuPN$vMVe?<4Q;^hkUZG72CHVQYH_K-DT8zJIlaB-TtD0QJCYfW zRE12Y$5LP`bLGFWF!};3TW&<!8de*O1ua9g^RTIcY86*c$VF2`-D7-u)p>koPL9%q zVCfReM;@wj>XsNI9r%tQ+lUB8yl|QId<Hb^=?7Hn23OMrfyVPae9z<fiKlVCV`s}k ztTI4@vQjvNwm4savLL}dTfrUa2#?6(?9A$zNIDs}Z>H#9OxByEE4YQ67^1HFu*zVR z#W;x}z^N2hOXyzwTUz>lN+mAyP*yT9E62wkth21s@~*u#`lby(eMJsWf-(Y+?jsv* zFUkN5=xiY>Cv`);W=QH9RnzELbCTYStywm7tZd}vslh6POHz!sIOCf2eoSw67pvRv z;}tzOu_*r-p#y1;w7zLJGYq!b4f5SMS#bbK6|KW&{%<f!H@iX(Wqpj1<gx>djg=@> zV-n*S%EHGk%kfJafP;(Tgg5`ZN}O7Z2r<d2<z`R7z7zv=v5?uCB;r(A*N9L;;ITX% zL_~t=T80CD2VSbdfiDDsGtA0urn7Aut<e)?!!pjLq(-5XU}0e`i(3MuXlL*AE7>^m z%IEd>8sHsDdKt6xSl01fW*6>eZ0xFMiy#|oOsp}n!CH^8kyFUedz`ph$7Kb=7kCD~ zazT!ryA*%6qsE!DQ|8=i_`>Vv<7bLnU#KbaEC34&Fi>d#FuNza#q*+5RUG4m1{o;2 z+z28g*&g?y<3_`wknuUDUEtEs;=HZs6eg4*6M9JD2m{ax5DI5g0&g~p+keR1!bX0v z_0LFEgtL~MKSeG(jY<vUrCvPWLnH#18gx3Nctdoo(REE~Qaqv27QDK}Ne=>nHSo~V z5YNFiyJ{@%vt0j!D&Km4v}Fc>Bdfs|WWd7t*-b68TA3WFq5_Q!BukP3WQ$-+y%!xT z0$&gq$7tm~y!dhaEO;U!@+^sTc(T#62m(;n5qdtJTun{YDTJG73->czUBJBdE%bNZ zOXQ89(jw33cM>OOv2n)*s90f=MhR?UgNYR;*5r!^X<v3Lqmv0vI-~=UItT>9cOV4o z76%L#@_c-2%#yj&eEg<Yc9hpVu3yRrIKZsz^&aj&wg;;%DsCi1`J{sIU|L70N=j`y zAtONYGiphS!J)OrSc5SJ>l{`ze2z8-Aq|O&sMMG6z?P3Pbg+*QSk-qI(%*uzb$qW* zF+9Z6ThAk{Cg{4t)OAx7y53+w$DEzir~2^I#RyLlwPeYPKC&*v*B&BqxVqs$d%zv@ z`>|sY9og;Y_Fs^B`%3`;V2*DWyH=bqcWV$zbZk&{%?bvwHN&HF3A&=t)s(5}n0maQ z)IcrKXk)0S24gMCI+Qjf#$uc$(Fwx4mA3pZS=99?Em4AJ9h2pL^1&QDS>)j4LJl1Y zNUABit}(S{<D;%nP329Z*}iTyPv7~U@YA`p71}93^#S($>MzOE&LY_VHrg_6WMxQO zu8qw-f5lyW*J)8o4ek1W^q(zzU(^XU{eS^#OP99Z-m|FZlY`s#qv{&#HBN3_YG}!i zl4~mwM2|CFtst!f4MG`wU*M&NNI+~2LP(r*_<le&oyJCw(b@SF%j1-%wqC#^PrQ~S zc~z5bx)~W#Ollj>FEN;;;RtooJR3+XT0s<KDQ~%g@!bn3WE^|fU%_eT-;Eu<oMP)R znUVLAx*|ibTl!hI_HP%7UiWGy%|8Nf_<am;KzjC~@V4X5TuQFs<BX+U){#+4TjySi z^S(`z{T$Qjy;N&;>aikLmU=T?uBR5I4XL)&Q$sa2)Dner5Gze3snOPP2g?@Sfpk?C z^*u#gO3<|wT~nx<I(&U31L}vBw-)wqIF$oWuObQr*^Ea^E9hh{h1RuXN*58O9<3c& zPFa}0EnU3&1}fIj>7C1J(fd-z<Ep<XhF7ebbH|+iZla9f*k}lsRM~UFdP?dUYPCAG zYD%g!Ds5znsWK$W5T}|-tkK3&PYg+_Dc4debwxEc#EGG%$0)Yn&Uxp4m_>`f%;JR) zp{fd1Rp{yr2#tL|Lw}uGRO+zS5d=^=*hUyhGFgwFg<~u`=VmD0i{~=r(goy9LeHGc z9Sd6g;o+Me9AMnuLYwq~OI{R!W{5CAeEPEdjmuA6!mK$3geTGE0z;2nO;&c`;gDFQ zvtUglZB>o1l_rhisTLcmv8EPVsx?iil9D8fdSWP5Q%d!igQaOkOVi{s1E^}_$ZJM< zRo9K{xM}&c;lF}V5M~5n)+3Yk$>u_&$Wx!_L%KRyb2S+h?X9q4Y3q&6Zm<!F8zd3} zXniRLI3PW#OKw|r!n|*G&F^m9G=kwBos4g|hSpp+Q6TYz!^h#Y#-s|PG*&l(NDXOf zNVKJ%SgLi)WLYsWof0Re!47RnQbUkG(6D^d`l{B<K$C{mwFV&}hy-Cq66SoOd`PAk zktsxYevu$EOfftQU!8z2Vb=WOH~V@zx6K@ryO2KQ?{A14=?pbcd*#af-|yYG^oo%k zT`fKNapwEu92n@t>T8(2<SG1FzrfTL7Kd=6QPK)<SPTwp3@((&K%lfksD>i4c@*RT zAtdHd4{1#`(qiqfrXj{O+f;$T4+VbY5oA1~tWPE%l5MrL&C;}X>?X=(2-3GUI#3Jd zl;)qh^zVUM-xYm%e`5bNZjt{E26Y15eKZ3S4oDUj<-U_w&;Cg5SBt*tn<<tRs|?pW zm^d(--u`a#q95h&#z=>djedhL4b?0TYb?rIgc1l3taIRr=N$VKvIXWW8RVGL*7NlJ zC!>|cHZyk5Ybfr8vZ=g}pYaKE0hwaR{NrvR@)I)h7-af!l#MWX$t(8%{3j>9<)YV1 zTRMe2XS?Nr&y+RdkiCfwZqreX$jl5#0L8AW`+wxx_1V|Of6fE-d89SP^5eFkjG?># z+oV=uT%$c^T|;>%9Kr|dY=afTHGUTkV-IH}p<c=4rpq|_HMdf(*Lmt^m$7H#3j6?M z;Ngc7Kl1T29ziz1&-!$9PceJ`eaQIjWc)c4vpyjX%NQrN)z^LCzBkVoN*73-qwWl2 zW<b>3C)wccIqDIaBep^{H!-~~UDR^M$$NKr&-AP$t|pYH`#ApOd(b8#otbiR4l8J6 zhSoM%AWUPWG36ly2<K4RVV!_z2bHp5$L1xd{I6Je{%y4OypkR3&%+NryvW1P`1sj? zAR7>50{l#l>4^`K&qd@i0m|P`)qR!T-uG;K&p%)P4RO%4k)}on27!lP?0tiynGte; zvN|0IC&y~5!qHrijXclyh^xIkvHmK~UQ<Ks-K0+Aq{BLk28`!W&Z3YgXK-301UPv_ zqtrSom4sQRf1U(KwPpxCi&6843L$>R$IJNmnTGOy6cA)WTo95iX2|6Nw5Va^KjMdT zcXyQX@BifKAAY8-H9z^bYu@#eW3)##CwS=_-@`X{-**12etl=jcGj=EVr{Z>!@hou z!fK5$j?2#ZG^67O5rM#AiM7T`fpV7AT2g07j6pfm0L5BT<Iv8bEEogUIy^5RUw<FN z+fKxbe7sE1uznOaK!`#zxscXYXm8y@A$vDTEO8>YFWPz5UyW?tvUTgGEeEE@ho@{h zm5hyS`}fZZKl0!sa%FVV6GO#yQ-$`ij&s(2{>#BdAG>z@ll%Kb9Fxflg775f&U%De zlA@F%7X@f%iJc`j8lf7;R>lgX6-Xq)9_jHR)lg{7;dDPyYZfo^@uPrD-q1b!NxHkr zB>GG`+P2YJe2_S<VoesW<$?nTe__6`eaj<L2S-Mk8lMcUcA<x-p5Fj@nZwdfrfK3$ zPs?An_44NPp8npcw~j@hT6X1o-oJNW_7qX8lJTJ>(@wpfpsXU%np%<&SWO@#9s*wq z0wbv?-N+j(q}m~yzCj8}-am#^Eg@5+2|&og1)J&bzn^?~9DevsjI#(Q(c)~z51jDZ zZQr@~*0F<QV^dR8O2u`Y(VoD~oB{m%0T5V(OWc!5?k5+FSKhFsZTg(~dmq1h<2Nhc zT6DoByKVommp`!m^60{a->1bJKwFQtf{!X{sw$zJ#FW#RK>2uSigON63WU-)pr$M$ z5VT|qMDc$`XF`gZfG8UhWqkZ_8STaSAP*o#mX5HUL-CpE&Ik0pyYKtq`svBZYOPX9 zRFY_%w!&#ATxtd8k25RWIcK@&5Lru99O&8f_52cf=FoP3)0xTnUoN(`cFkS9c>b(Y zFFL=sYwEa@^4}#;Qy8Ujksy(V1VzoIRBTEqjVY^ys!pjHLt+gn0x!&v;jL5;y#+6j zw6<-dqx}hr`6{i&G5jDT?-j6OH9I!X-nQ|sb?b(A?b%-`m&ek$K5le6fi;uDsVU*o zDM?Zmxcb=0HuJ{-Kmd`0+&{ODo_NKA>eoe4v^}#uTKm5Gs-KP*x^u;rmd>ulOXv5T zeA?-Yx<?i*Vm&QlFC|r@N=ntGR9!;VDeBIkrHA!aFi|-U=X{hpnYcO+(>P{ecK46T z<nG1yC7CcoYwj2(M;7kebocazL%VhkRm<h^YNb4`({$1rH3?=)Iz1&^IxWy;(HNRe z#zwZeKL!9ahYK>`a=)In?@cQf=)WZ^z0y7oK2mLY?0(ldVl%lG5#?G=E!q_=^ZS=Q zwEALyken!*t+Z!%k<aa*q<nTyokg5<Gdgt&NQsaVCmVA=UJw)Io+e+s4Z<!$yQC}* z^zIv8zjNpK!O^jLtu__cs*_5kQ%0#NoSp_VEuEeg=#s!yLDXgnpqGjQM?Egz1i=TF z0kYq1A3E#ouH@4}w_M;r*cfc;ASWdmAu)p5v`p^ggk5)@c#YLTTZfi~HW#%PQzZhe zY~$>}lZe2>k9=}jp>uM5*;EdeTy^ebdDoWFseOCKtCdPAN#ar($7Q9`X=`)|XUaHT z64-J>s5VFC>mXu4zm)QS@Cy@1Fd>=&;@(+<S9WL2X;I{QjTD|v@%GmI0}sW8!5eko zem@BFeh}n>Ak2Dxknw##@_j!PQhGuNX~XucNG9smTC25ITC3D3ohX&YTC2KNs%Dg` zT5D=JTLD{bh^sbeE^6YripPLG8s%U1OH)msFvErnka3Wm0cGYMh>Q>-Bc#koDI+0e z=t&t!=><YcuNkI9W4gs!Ypu4{C~K{9#-`TU1m_Zmi$z1R8L5Ma1=J7Ud)DfIkU}r} zt+6H>W`KwqtRQmDwRtZ*LV{-4^%0H9z9WvS8zWE6a-rG3*UdU!HP;kG0wkjGE<jU6 zGSlxrTC4xjUz|K*Yxv-TBNPr@L+PgS&TsymoU#7%YK|EIEQlEplxTpU4uc_7^EdNy zl>QHWb+!q{jDp?~N_#J$yf|WN>&RjG86cV>^kHC*et#d$=YIonccN)MAIhfy0000< KMNUMnLSTaD2x3+M
--- a/browser/themes/winstripe/browser/browser-aero.css +++ b/browser/themes/winstripe/browser/browser-aero.css @@ -24,16 +24,20 @@ background: transparent; } /* the new titlebar requires this, or content will be clipped at the top of the screen. */ #main-window[sizemode="maximized"][chromemargin^="0,"] { margin-top: 8px; } + #main-window[sizemode="normal"][chromemargin^="0,"] { + margin-top: 2px; + } + #main-window:not(:-moz-lwtheme)[inFullscreen="true"] { -moz-appearance: none; background-color: #556; } #toolbar-menubar:not(:-moz-lwtheme), #navigator-toolbox[tabsontop="true"] > #TabsToolbar:not(:-moz-lwtheme), #navigator-toolbox:not([tabsontop="true"]) > #nav-bar:not(:-moz-lwtheme), @@ -48,17 +52,17 @@ border-right: 1px solid ThreeDShadow; } /* Make the window draggable by glassed toolbars (bug 555081) */ #toolbar-menubar:not([autohide="true"]), #navigator-toolbox[tabsontop="true"] > #TabsToolbar, #navigator-toolbox:not([tabsontop="true"]) > #nav-bar, #navigator-toolbox:not([tabsontop="true"]) > #nav-bar + #customToolbars + #PersonalToolbar[collapsed="true"] + #TabsToolbar:last-child, - #navigator-toolbox > toolbar:not(#toolbar-menubar):not(#fullscr-toggler):-moz-lwtheme { + #navigator-toolbox > toolbar:not(#toolbar-menubar):-moz-lwtheme { -moz-binding: url("chrome://global/content/bindings/toolbar.xml#toolbar-drag"); } #browser:not(:-moz-lwtheme), #browser-bottombox:not(:-moz-lwtheme) { background-color: -moz-dialog; }
--- a/browser/themes/winstripe/browser/browser.css +++ b/browser/themes/winstripe/browser/browser.css @@ -1598,26 +1598,26 @@ toolbarbutton.bookmark-item[dragover="tr .popup-notification-icon { width: 64px; height: 64px; -moz-margin-end: 10px; } .popup-notification-icon[popupid="geolocation"] { - list-style-image: url(chrome://browser/skin/Geo.png); + list-style-image: url(chrome://browser/skin/Geolocation-64.png); } /* Notification icon box */ #notification-popup-box { margin: 0 3px; } #geo-notification-icon { - list-style-image: url(chrome://browser/skin/Geo.png); + list-style-image: url(chrome://browser/skin/Geolocation-16.png); width: 16px; height: 16px; } #identity-popup-container { min-width: 280px; padding: 9px; }
--- a/browser/themes/winstripe/browser/jar.mn +++ b/browser/themes/winstripe/browser/jar.mn @@ -8,17 +8,18 @@ browser.jar: * skin/classic/browser/aboutSessionRestore.css (aboutSessionRestore.css) skin/classic/browser/aboutSessionRestore-window-icon.png (aboutSessionRestore-window-icon.png) skin/classic/browser/aboutCertError.css (aboutCertError.css) skin/classic/browser/actionicon-tab.png skin/classic/browser/appmenu-dropmarker.png * skin/classic/browser/browser.css (browser.css) * skin/classic/browser/engineManager.css (engineManager.css) skin/classic/browser/fullscreen-video.css - skin/classic/browser/Geo.png (Geo.png) + skin/classic/browser/Geolocation-16.png + skin/classic/browser/Geolocation-64.png skin/classic/browser/Info.png (Info.png) skin/classic/browser/identity.png (identity.png) skin/classic/browser/keyhole-forward-mask.svg skin/classic/browser/KUI-background.png skin/classic/browser/KUI-close.png skin/classic/browser/mainwindow-dropdown-arrow.png skin/classic/browser/pageInfo.css skin/classic/browser/pageInfo.png (pageInfo.png) @@ -93,17 +94,18 @@ browser.jar: * skin/classic/aero/browser/aboutSessionRestore.css (aboutSessionRestore.css) skin/classic/aero/browser/aboutSessionRestore-window-icon.png (aboutSessionRestore-window-icon-aero.png) skin/classic/aero/browser/aboutCertError.css (aboutCertError.css) skin/classic/aero/browser/actionicon-tab.png (actionicon-tab.png) skin/classic/aero/browser/appmenu-dropmarker.png * skin/classic/aero/browser/browser.css (browser-aero.css) * skin/classic/aero/browser/engineManager.css (engineManager.css) skin/classic/aero/browser/fullscreen-video.css - skin/classic/aero/browser/Geo.png (Geo-aero.png) + skin/classic/aero/browser/Geolocation-16.png + skin/classic/aero/browser/Geolocation-64.png skin/classic/aero/browser/Info.png (Info-aero.png) skin/classic/aero/browser/identity.png (identity-aero.png) skin/classic/aero/browser/keyhole-forward-mask.svg skin/classic/aero/browser/KUI-background.png skin/classic/aero/browser/KUI-close.png skin/classic/aero/browser/mainwindow-dropdown-arrow.png (mainwindow-dropdown-arrow-aero.png) skin/classic/aero/browser/pageInfo.css skin/classic/aero/browser/pageInfo.png (pageInfo-aero.png)
--- a/chrome/src/Makefile.in +++ b/chrome/src/Makefile.in @@ -42,37 +42,54 @@ VPATH = @srcdir@ include $(DEPTH)/config/autoconf.mk MODULE = chrome LIBRARY_NAME = chrome_s LIBXUL_LIBRARY = 1 FORCE_STATIC_LIB = 1 +EXPORTS_NAMESPACES = mozilla/chrome + +EXPORTS_mozilla/chrome = \ + RegistryMessageUtils.h \ + $(NULL) CPPSRCS = \ nsChromeRegistry.cpp \ + nsChromeRegistryChrome.cpp \ nsChromeProtocolHandler.cpp \ $(NULL) +ifdef MOZ_IPC +CPPSRCS += nsChromeRegistryContent.cpp +endif + EXTRA_DSO_LDOPTS = \ $(MOZ_UNICHARUTIL_LIBS) \ $(MOZ_COMPONENT_LIBS) \ $(NULL) ifneq (,$(filter gtk2,$(MOZ_WIDGET_TOOLKIT))) EXTRA_DSO_LDOPTS += $(MOZ_GTK2_LIBS) endif ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT)) EXTRA_DSO_LDOPTS += $(TK_LIBS) endif +include $(topsrcdir)/config/config.mk +include $(topsrcdir)/ipc/chromium/chromium-config.mk include $(topsrcdir)/config/rules.mk +LOCAL_INCLUDES += \ + -I$(topsrcdir)/netwerk/protocol/res \ + -I$(topsrcdir)/netwerk/base/src \ + $(NULL) + ifneq (,$(filter gtk2,$(MOZ_WIDGET_TOOLKIT))) CXXFLAGS += $(MOZ_GTK2_CFLAGS) endif LOCAL_INCLUDES += \ -I$(topsrcdir)/xpcom/components \ -I$(DEPTH)/xpcom \ $(NULL)
new file mode 100644 --- /dev/null +++ b/chrome/src/RegistryMessageUtils.h @@ -0,0 +1,208 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Josh Matthews <josh@joshmatthews.net> (Initial Developer) + * + * 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 ***** */ + +#ifndef mozilla_RegistryMessageUtils_h +#define mozilla_RegistryMessageUtils_h + +#include "IPC/IPCMessageUtils.h" +#include "nsStringGlue.h" + +struct SerializedURI +{ + nsCString spec; + nsCString charset; +}; + +struct ChromePackage +{ + nsCString package; + SerializedURI contentBaseURI; + SerializedURI localeBaseURI; + SerializedURI skinBaseURI; + PRUint32 flags; +}; + +struct ResourceMapping +{ + nsCString resource; + SerializedURI resolvedURI; +}; + +struct OverrideMapping +{ + SerializedURI originalURI; + SerializedURI overrideURI; +}; + +namespace IPC { + +template<> +struct ParamTraits<SerializedURI> +{ + typedef SerializedURI paramType; + + static void Write(Message* aMsg, const paramType& aParam) + { + WriteParam(aMsg, aParam.spec); + WriteParam(aMsg, aParam.charset); + } + + static bool Read(const Message* aMsg, void** aIter, paramType* aResult) + { + nsCString spec, charset; + if (ReadParam(aMsg, aIter, &spec) && + ReadParam(aMsg, aIter, &charset)) { + aResult->spec = spec; + aResult->charset = charset; + return true; + } + return false; + } +}; + +template <> +struct ParamTraits<ChromePackage> +{ + typedef ChromePackage paramType; + + static void Write(Message* aMsg, const paramType& aParam) + { + WriteParam(aMsg, aParam.package); + WriteParam(aMsg, aParam.contentBaseURI); + WriteParam(aMsg, aParam.localeBaseURI); + WriteParam(aMsg, aParam.skinBaseURI); + WriteParam(aMsg, aParam.flags); + } + + static bool Read(const Message* aMsg, void** aIter, paramType* aResult) + { + nsCString package; + SerializedURI contentBaseURI, localeBaseURI, skinBaseURI; + PRUint32 flags; + + if (ReadParam(aMsg, aIter, &package) && + ReadParam(aMsg, aIter, &contentBaseURI) && + ReadParam(aMsg, aIter, &localeBaseURI) && + ReadParam(aMsg, aIter, &skinBaseURI) && + ReadParam(aMsg, aIter, &flags)) { + aResult->package = package; + aResult->contentBaseURI = contentBaseURI; + aResult->localeBaseURI = localeBaseURI; + aResult->skinBaseURI = skinBaseURI; + aResult->flags = flags; + return true; + } + return false; + } + + static void Log(const paramType& aParam, std::wstring* aLog) + { + aLog->append(StringPrintf(L"[%s, %s, %s, %s, %u]", aParam.package.get(), + aParam.contentBaseURI.spec.get(), + aParam.localeBaseURI.spec.get(), + aParam.skinBaseURI.spec.get(), aParam.flags)); + } +}; + +template <> +struct ParamTraits<ResourceMapping> +{ + typedef ResourceMapping paramType; + + static void Write(Message* aMsg, const paramType& aParam) + { + WriteParam(aMsg, aParam.resource); + WriteParam(aMsg, aParam.resolvedURI); + } + + static bool Read(const Message* aMsg, void** aIter, paramType* aResult) + { + nsCString resource; + SerializedURI resolvedURI; + + if (ReadParam(aMsg, aIter, &resource) && + ReadParam(aMsg, aIter, &resolvedURI)) { + aResult->resource = resource; + aResult->resolvedURI = resolvedURI; + return true; + } + return false; + } + + static void Log(const paramType& aParam, std::wstring* aLog) + { + aLog->append(StringPrintf(L"[%s, %s, %u]", aParam.resource.get(), + aParam.resolvedURI.spec.get())); + } +}; + +template <> +struct ParamTraits<OverrideMapping> +{ + typedef OverrideMapping paramType; + + static void Write(Message* aMsg, const paramType& aParam) + { + WriteParam(aMsg, aParam.originalURI); + WriteParam(aMsg, aParam.overrideURI); + } + + static bool Read(const Message* aMsg, void** aIter, paramType* aResult) + { + SerializedURI originalURI; + SerializedURI overrideURI; + + if (ReadParam(aMsg, aIter, &originalURI) && + ReadParam(aMsg, aIter, &overrideURI)) { + aResult->originalURI = originalURI; + aResult->overrideURI = overrideURI; + return true; + } + return false; + } + + static void Log(const paramType& aParam, std::wstring* aLog) + { + aLog->append(StringPrintf(L"[%s, %s, %u]", aParam.originalURI.spec.get(), + aParam.overrideURI.spec.get())); + } +}; + +} + +#endif // RegistryMessageUtils_h
--- a/chrome/src/nsChromeRegistry.cpp +++ b/chrome/src/nsChromeRegistry.cpp @@ -35,106 +35,57 @@ * 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 "nsChromeRegistry.h" +#include "nsChromeRegistryChrome.h" +#ifdef MOZ_IPC +#include "nsChromeRegistryContent.h" +#endif #include <string.h> #include "prio.h" #include "prprf.h" -#if defined(XP_WIN) -#include <windows.h> -#elif defined(XP_MACOSX) -#include <CoreServices/CoreServices.h> -#elif defined(MOZ_WIDGET_GTK2) -#include <gtk/gtk.h> -#endif -#include "nsAppDirectoryServiceDefs.h" -#include "nsArrayEnumerator.h" -#include "nsComponentManager.h" -#include "nsStringEnumerator.h" -#include "nsEnumeratorUtils.h" #include "nsCOMPtr.h" #include "nsDOMError.h" #include "nsEscape.h" -#include "nsInt64.h" #include "nsLayoutCID.h" -#include "nsNetCID.h" #include "nsNetUtil.h" -#include "nsReadableUtils.h" #include "nsString.h" #include "nsUnicharUtils.h" -#include "nsWidgetsCID.h" -#include "nsXPCOMCIDInternal.h" -#include "nsXPIDLString.h" -#include "nsXULAppAPI.h" -#include "nsTextFormatter.h" -#include "nsZipArchive.h" -#include "nsIAtom.h" -#include "nsICommandLine.h" #include "nsCSSStyleSheet.h" #include "nsIConsoleService.h" -#include "nsIDirectoryService.h" #include "nsIDocument.h" #include "nsIDOMDocument.h" #include "nsIDocShell.h" -#include "nsIDocumentObserver.h" #include "nsIDOMElement.h" #include "nsIDOMLocation.h" #include "nsIDOMWindowCollection.h" #include "nsIDOMWindowInternal.h" -#include "nsIFileChannel.h" -#include "nsIFileURL.h" #include "nsIIOService.h" #include "nsIJARProtocolHandler.h" -#include "nsIJARURI.h" -#include "nsILocalFile.h" -#include "nsILocaleService.h" -#include "nsILookAndFeel.h" #include "nsIObserverService.h" -#include "nsIPrefService.h" -#include "nsIPrefBranch.h" -#include "nsIPrefBranch2.h" #include "nsIPresShell.h" #include "nsIProtocolHandler.h" -#include "nsIResProtocolHandler.h" #include "nsIScriptError.h" -#include "nsIServiceManager.h" -#include "nsISimpleEnumerator.h" -#include "nsIStyleSheet.h" -#include "nsISupportsArray.h" -#include "nsIVersionComparator.h" #include "nsIWindowMediator.h" -#include "nsIXPConnect.h" -#include "nsIXULAppInfo.h" -#include "nsIXULRuntime.h" - -#include "mozilla/Omnijar.h" - -#define UILOCALE_CMD_LINE_ARG "UILocale" - -#define MATCH_OS_LOCALE_PREF "intl.locale.matchOS" -#define SELECTED_LOCALE_PREF "general.useragent.locale" -#define SELECTED_SKIN_PREF "general.skins.selectedSkin" - -static NS_DEFINE_CID(kLookAndFeelCID, NS_LOOKANDFEEL_CID); nsChromeRegistry* nsChromeRegistry::gChromeRegistry; //////////////////////////////////////////////////////////////////////////////// -static void -LogMessage(const char* aMsg, ...) +void +nsChromeRegistry::LogMessage(const char* aMsg, ...) { nsCOMPtr<nsIConsoleService> console (do_GetService(NS_CONSOLESERVICE_CONTRACTID)); if (!console) return; va_list args; va_start(args, aMsg); @@ -142,19 +93,19 @@ LogMessage(const char* aMsg, ...) va_end(args); if (!formatted) return; console->LogStringMessage(NS_ConvertUTF8toUTF16(formatted).get()); PR_smprintf_free(formatted); } -static void -LogMessageWithContext(nsIURI* aURL, PRUint32 aLineNumber, PRUint32 flags, - const char* aMsg, ...) +void +nsChromeRegistry::LogMessageWithContext(nsIURI* aURL, PRUint32 aLineNumber, PRUint32 flags, + const char* aMsg, ...) { nsresult rv; nsCOMPtr<nsIConsoleService> console (do_GetService(NS_CONSOLESERVICE_CONTRACTID)); nsCOMPtr<nsIScriptError> error (do_CreateInstance(NS_SCRIPTERROR_CONTRACTID)); @@ -179,252 +130,18 @@ LogMessageWithContext(nsIURI* aURL, PRUi PR_smprintf_free(formatted); if (NS_FAILED(rv)) return; console->LogMessage(error); } -// We use a "best-fit" algorithm for matching locales and themes. -// 1) the exact selected locale/theme -// 2) (locales only) same language, different country -// e.g. en-GB is the selected locale, only en-US is available -// 3) any available locale/theme - -/** - * Match the language-part of two lang-COUNTRY codes, hopefully but - * not guaranteed to be in the form ab-CD or abz-CD. "ab" should also - * work, any other garbage-in will produce undefined results as long - * as it does not crash. - */ -static PRBool -LanguagesMatch(const nsACString& a, const nsACString& b) -{ - if (a.Length() < 2 || b.Length() < 2) - return PR_FALSE; - - nsACString::const_iterator as, ae, bs, be; - a.BeginReading(as); - a.EndReading(ae); - b.BeginReading(bs); - b.EndReading(be); - - while (*as == *bs) { - if (*as == '-') - return PR_TRUE; - - ++as; ++bs; - - // reached the end - if (as == ae && bs == be) - return PR_TRUE; - - // "a" is short - if (as == ae) - return (*bs == '-'); - - // "b" is short - if (bs == be) - return (*as == '-'); - } - - return PR_FALSE; -} - -static PRBool -CanLoadResource(nsIURI* aResourceURI) -{ - PRBool isLocalResource = PR_FALSE; - (void)NS_URIChainHasFlags(aResourceURI, - nsIProtocolHandler::URI_IS_LOCAL_RESOURCE, - &isLocalResource); - return isLocalResource; -} - -nsChromeRegistry::ProviderEntry* -nsChromeRegistry::nsProviderArray::GetProvider(const nsACString& aPreferred, MatchType aType) -{ - PRInt32 i = mArray.Count(); - if (!i) - return nsnull; - - ProviderEntry* found = nsnull; // Only set if we find a partial-match locale - ProviderEntry* entry; - - while (i--) { - entry = reinterpret_cast<ProviderEntry*>(mArray[i]); - if (aPreferred.Equals(entry->provider)) - return entry; - - if (aType != LOCALE) - continue; - - if (LanguagesMatch(aPreferred, entry->provider)) { - found = entry; - continue; - } - - if (!found && entry->provider.EqualsLiteral("en-US")) - found = entry; - } - - if (!found && aType != EXACT) - return entry; - - return found; -} - -nsIURI* -nsChromeRegistry::nsProviderArray::GetBase(const nsACString& aPreferred, MatchType aType) -{ - ProviderEntry* provider = GetProvider(aPreferred, aType); - - if (!provider) - return nsnull; - - return provider->baseURI; -} - -const nsACString& -nsChromeRegistry::nsProviderArray::GetSelected(const nsACString& aPreferred, MatchType aType) -{ - ProviderEntry* entry = GetProvider(aPreferred, aType); - - if (entry) - return entry->provider; - - return EmptyCString(); -} - -void -nsChromeRegistry::nsProviderArray::SetBase(const nsACString& aProvider, nsIURI* aBaseURL) -{ - ProviderEntry* provider = GetProvider(aProvider, EXACT); - - if (provider) { - provider->baseURI = aBaseURL; - return; - } - - // no existing entries, add a new one - provider = new ProviderEntry(aProvider, aBaseURL); - if (!provider) - return; // It's safe to silently fail on OOM - - mArray.AppendElement(provider); -} - -void -nsChromeRegistry::nsProviderArray::EnumerateToArray(nsTArray<nsCString> *a) -{ - PRInt32 i = mArray.Count(); - while (i--) { - ProviderEntry *entry = reinterpret_cast<ProviderEntry*>(mArray[i]); - a->AppendElement(entry->provider); - } -} - -void -nsChromeRegistry::nsProviderArray::Clear() -{ - PRInt32 i = mArray.Count(); - while (i--) { - ProviderEntry* entry = reinterpret_cast<ProviderEntry*>(mArray[i]); - delete entry; - } - - mArray.Clear(); -} - -nsChromeRegistry::PackageEntry::PackageEntry(const nsACString& aPackage) : - package(aPackage), flags(0) -{ -} - -PLHashNumber -nsChromeRegistry::HashKey(PLDHashTable *table, const void *key) -{ - const nsACString& str = *reinterpret_cast<const nsACString*>(key); - return HashString(str); -} - -PRBool -nsChromeRegistry::MatchKey(PLDHashTable *table, const PLDHashEntryHdr *entry, - const void *key) -{ - const nsACString& str = *reinterpret_cast<const nsACString*>(key); - const PackageEntry* pentry = static_cast<const PackageEntry*>(entry); - return str.Equals(pentry->package); -} - -void -nsChromeRegistry::ClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry) -{ - PackageEntry* pentry = static_cast<PackageEntry*>(entry); - pentry->~PackageEntry(); -} - -PRBool -nsChromeRegistry::InitEntry(PLDHashTable *table, PLDHashEntryHdr *entry, - const void *key) -{ - const nsACString& str = *reinterpret_cast<const nsACString*>(key); - - new (entry) PackageEntry(str); - return PR_TRUE; -} - -const PLDHashTableOps -nsChromeRegistry::kTableOps = { - PL_DHashAllocTable, - PL_DHashFreeTable, - HashKey, - MatchKey, - PL_DHashMoveEntryStub, - ClearEntry, - PL_DHashFinalizeStub, - InitEntry -}; - -void -nsChromeRegistry::OverlayListEntry::AddURI(nsIURI* aURI) -{ - PRInt32 i = mArray.Count(); - while (i--) { - PRBool equals; - if (NS_SUCCEEDED(aURI->Equals(mArray[i], &equals)) && equals) - return; - } - - mArray.AppendObject(aURI); -} - -void -nsChromeRegistry::OverlayListHash::Add(nsIURI* aBase, nsIURI* aOverlay) -{ - OverlayListEntry* entry = mTable.PutEntry(aBase); - if (entry) - entry->AddURI(aOverlay); -} - -const nsCOMArray<nsIURI>* -nsChromeRegistry::OverlayListHash::GetArray(nsIURI* aBase) -{ - OverlayListEntry* entry = mTable.GetEntry(aBase); - if (!entry) - return nsnull; - - return &entry->mArray; -} - nsChromeRegistry::~nsChromeRegistry() { - if (mPackagesHash.ops) - PL_DHashTableFinish(&mPackagesHash); gChromeRegistry = nsnull; } NS_INTERFACE_MAP_BEGIN(nsChromeRegistry) NS_INTERFACE_MAP_ENTRY(nsIChromeRegistry) NS_INTERFACE_MAP_ENTRY(nsIXULChromeRegistry) NS_INTERFACE_MAP_ENTRY(nsIToolkitChromeRegistry) #ifdef MOZ_XUL @@ -436,135 +153,56 @@ NS_INTERFACE_MAP_BEGIN(nsChromeRegistry) NS_INTERFACE_MAP_END NS_IMPL_ADDREF(nsChromeRegistry) NS_IMPL_RELEASE(nsChromeRegistry) //////////////////////////////////////////////////////////////////////////////// // nsIChromeRegistry methods: -static nsresult -getUILangCountry(nsACString& aUILang) +already_AddRefed<nsIChromeRegistry> +nsChromeRegistry::GetService() { - nsresult rv; - - nsCOMPtr<nsILocaleService> localeService = do_GetService(NS_LOCALESERVICE_CONTRACTID, &rv); - NS_ENSURE_SUCCESS(rv, rv); - - nsAutoString uiLang; - rv = localeService->GetLocaleComponentForUserAgent(uiLang); - NS_ENSURE_SUCCESS(rv, rv); - - CopyUTF16toUTF8(uiLang, aUILang); - return NS_OK; + if (!nsChromeRegistry::gChromeRegistry) + { + // We don't actually want this ref, we just want the service to + // initialize if it hasn't already. + nsCOMPtr<nsIChromeRegistry> reg( + do_GetService(NS_CHROMEREGISTRY_CONTRACTID)); + if (!gChromeRegistry) + return NULL; + } + NS_IF_ADDREF(gChromeRegistry); + return gChromeRegistry; } nsresult nsChromeRegistry::Init() { - nsresult rv; - // Check to see if necko and the JAR protocol handler are registered yet // if not, somebody is doing work during XPCOM registration that they // shouldn't be doing. See bug 292549, where JS components are trying // to call Components.utils.import("chrome:///") early in registration NS_ASSERTION(nsCOMPtr<nsIIOService>(mozilla::services::GetIOService()), "I/O service not registered or available early enough?"); - if (!PL_DHashTableInit(&mPackagesHash, &kTableOps, - nsnull, sizeof(PackageEntry), 16)) + if (!mOverrideTable.Init()) return NS_ERROR_FAILURE; - if (!mOverlayHash.Init() || - !mStyleHash.Init() || - !mOverrideTable.Init()) - return NS_ERROR_FAILURE; - - mSelectedLocale = NS_LITERAL_CSTRING("en-US"); - mSelectedSkin = NS_LITERAL_CSTRING("classic/1.0"); - // This initialization process is fairly complicated and may cause reentrant // getservice calls to resolve chrome URIs (especially locale files). We // don't want that, so we inform the protocol handler about our existence // before we are actually fully initialized. gChromeRegistry = this; - PRBool safeMode = PR_FALSE; - nsCOMPtr<nsIXULRuntime> xulrun (do_GetService(XULAPPINFO_SERVICE_CONTRACTID)); - if (xulrun) - xulrun->GetInSafeMode(&safeMode); - - nsCOMPtr<nsIPrefService> prefserv (do_GetService(NS_PREFSERVICE_CONTRACTID)); - nsCOMPtr<nsIPrefBranch> prefs; - - if (safeMode) - prefserv->GetDefaultBranch(nsnull, getter_AddRefs(prefs)); - else - prefs = do_QueryInterface(prefserv); - - if (!prefs) { - NS_WARNING("Could not get pref service!"); - } - else { - nsXPIDLCString provider; - rv = prefs->GetCharPref(SELECTED_SKIN_PREF, getter_Copies(provider)); - if (NS_SUCCEEDED(rv)) - mSelectedSkin = provider; - - SelectLocaleFromPref(prefs); - - nsCOMPtr<nsIPrefBranch2> prefs2 (do_QueryInterface(prefs)); - if (prefs2) { - rv = prefs2->AddObserver(MATCH_OS_LOCALE_PREF, this, PR_TRUE); - rv = prefs2->AddObserver(SELECTED_LOCALE_PREF, this, PR_TRUE); - rv = prefs2->AddObserver(SELECTED_SKIN_PREF, this, PR_TRUE); - } - } - - nsCOMPtr<nsIObserverService> obsService = - mozilla::services::GetObserverService(); - if (obsService) { - obsService->AddObserver(this, "command-line-startup", PR_TRUE); - obsService->AddObserver(this, "profile-initial-state", PR_TRUE); - } - mInitialized = PR_TRUE; return NS_OK; } -NS_IMETHODIMP -nsChromeRegistry::CheckForOSAccessibility() -{ - nsresult rv; - - nsCOMPtr<nsILookAndFeel> lookAndFeel (do_GetService(kLookAndFeelCID)); - if (lookAndFeel) { - PRInt32 useAccessibilityTheme = 0; - - rv = lookAndFeel->GetMetric(nsILookAndFeel::eMetric_UseAccessibilityTheme, - useAccessibilityTheme); - - if (NS_SUCCEEDED(rv) && useAccessibilityTheme) { - /* Set the skin to classic and remove pref observers */ - if (!mSelectedSkin.EqualsLiteral("classic/1.0")) { - mSelectedSkin.AssignLiteral("classic/1.0"); - RefreshSkins(); - } - - nsCOMPtr<nsIPrefBranch2> prefs (do_GetService(NS_PREFSERVICE_CONTRACTID)); - if (prefs) { - prefs->RemoveObserver(SELECTED_SKIN_PREF, this); - } - } - } - - return NS_OK; -} - nsresult nsChromeRegistry::GetProviderAndPath(nsIURL* aChromeURL, nsACString& aProvider, nsACString& aPath) { nsresult rv; #ifdef DEBUG PRBool isChrome; @@ -686,157 +324,44 @@ nsChromeRegistry::ConvertChromeURL(nsIUR nsCAutoString package, provider, path; rv = chromeURL->GetHostPort(package); NS_ENSURE_SUCCESS(rv, rv); rv = GetProviderAndPath(chromeURL, provider, path); NS_ENSURE_SUCCESS(rv, rv); - PackageEntry* entry = - static_cast<PackageEntry*>(PL_DHashTableOperate(&mPackagesHash, - & (nsACString&) package, - PL_DHASH_LOOKUP)); + nsIURI* baseURI; + rv = GetBaseURIFromPackage(package, provider, path, &baseURI); + NS_ENSURE_SUCCESS(rv, rv); - if (PL_DHASH_ENTRY_IS_FREE(entry)) { - if (!mInitialized) - return NS_ERROR_NOT_INITIALIZED; + PRUint32 flags; + rv = GetFlagsFromPackage(package, &flags); + if (NS_FAILED(rv)) + return rv; - LogMessage("No chrome package registered for chrome://%s/%s/%s", - package.get(), provider.get(), path.get()); - - return NS_ERROR_FAILURE; - } - - if (entry->flags & PackageEntry::PLATFORM_PACKAGE) { + if (flags & PLATFORM_PACKAGE) { #if defined(XP_WIN) || defined(XP_OS2) path.Insert("win/", 0); #elif defined(XP_MACOSX) path.Insert("mac/", 0); #else path.Insert("unix/", 0); #endif } - nsIURI* baseURI = nsnull; - if (provider.EqualsLiteral("locale")) { - baseURI = entry->locales.GetBase(mSelectedLocale, nsProviderArray::LOCALE); - } - else if (provider.EqualsLiteral("skin")) { - baseURI = entry->skins.GetBase(mSelectedSkin, nsProviderArray::ANY); - } - else if (provider.EqualsLiteral("content")) { - baseURI = entry->baseURI; - } - if (!baseURI) { LogMessage("No chrome package registered for chrome://%s/%s/%s", package.get(), provider.get(), path.get()); return NS_ERROR_FAILURE; } return NS_NewURI(aResult, path, nsnull, baseURI); } -nsresult -nsChromeRegistry::GetSelectedLocale(const nsACString& aPackage, nsACString& aLocale) -{ - PackageEntry* entry = - static_cast<PackageEntry*>(PL_DHashTableOperate(&mPackagesHash, - & aPackage, - PL_DHASH_LOOKUP)); - - if (PL_DHASH_ENTRY_IS_FREE(entry)) - return NS_ERROR_FAILURE; - - aLocale = entry->locales.GetSelected(mSelectedLocale, nsProviderArray::LOCALE); - if (aLocale.IsEmpty()) - return NS_ERROR_FAILURE; - - return NS_OK; -} - -NS_IMETHODIMP -nsChromeRegistry::IsLocaleRTL(const nsACString& package, PRBool *aResult) -{ - *aResult = PR_FALSE; - - nsCAutoString locale; - GetSelectedLocale(package, locale); - if (locale.Length() < 2) - return NS_OK; - - // first check the intl.uidirection.<locale> preference, and if that is not - // set, check the same preference but with just the first two characters of - // the locale. If that isn't set, default to left-to-right. - nsCAutoString prefString = NS_LITERAL_CSTRING("intl.uidirection.") + locale; - nsCOMPtr<nsIPrefBranch> prefBranch (do_GetService(NS_PREFSERVICE_CONTRACTID)); - if (!prefBranch) - return NS_OK; - - nsXPIDLCString dir; - prefBranch->GetCharPref(prefString.get(), getter_Copies(dir)); - if (dir.IsEmpty()) { - PRInt32 hyphen = prefString.FindChar('-'); - if (hyphen >= 1) { - nsCAutoString shortPref(Substring(prefString, 0, hyphen)); - prefBranch->GetCharPref(shortPref.get(), getter_Copies(dir)); - } - } - *aResult = dir.EqualsLiteral("rtl"); - return NS_OK; -} - -NS_IMETHODIMP -nsChromeRegistry::GetLocalesForPackage(const nsACString& aPackage, - nsIUTF8StringEnumerator* *aResult) -{ - nsTArray<nsCString> *a = new nsTArray<nsCString>; - if (!a) - return NS_ERROR_OUT_OF_MEMORY; - - PackageEntry* entry = - static_cast<PackageEntry*>(PL_DHashTableOperate(&mPackagesHash, - & aPackage, - PL_DHASH_LOOKUP)); - - if (PL_DHASH_ENTRY_IS_BUSY(entry)) { - entry->locales.EnumerateToArray(a); - } - - nsresult rv = NS_NewAdoptingUTF8StringEnumerator(aResult, a); - if (NS_FAILED(rv)) - delete a; - - return rv; -} - -#ifdef MOZ_XUL -NS_IMETHODIMP -nsChromeRegistry::GetStyleOverlays(nsIURI *aChromeURL, - nsISimpleEnumerator **aResult) -{ - const nsCOMArray<nsIURI>* parray = mStyleHash.GetArray(aChromeURL); - if (!parray) - return NS_NewEmptyEnumerator(aResult); - - return NS_NewArrayEnumerator(aResult, *parray); -} - -NS_IMETHODIMP -nsChromeRegistry::GetXULOverlays(nsIURI *aChromeURL, nsISimpleEnumerator **aResult) -{ - const nsCOMArray<nsIURI>* parray = mOverlayHash.GetArray(aChromeURL); - if (!parray) - return NS_NewEmptyEnumerator(aResult); - - return NS_NewArrayEnumerator(aResult, *parray); -} -#endif // MOZ_XUL - //////////////////////////////////////////////////////////////////////// // theme stuff static void FlushSkinBindingsForWindow(nsIDOMWindowInternal* aWindow) { // Get the DOM document. @@ -1115,84 +640,22 @@ nsChromeRegistry::AllowContentToAccess(n NS_ERROR("Chrome URL doesn't implement nsIURL."); return NS_ERROR_UNEXPECTED; } nsCAutoString package; rv = url->GetHostPort(package); NS_ENSURE_SUCCESS(rv, rv); - PackageEntry *entry = - static_cast<PackageEntry*>(PL_DHashTableOperate(&mPackagesHash, - & (nsACString&) package, - PL_DHASH_LOOKUP)); - - if (PL_DHASH_ENTRY_IS_BUSY(entry)) { - *aResult = !!(entry->flags & PackageEntry::CONTENT_ACCESSIBLE); - } - return NS_OK; -} - -static PLDHashOperator -RemoveAll(PLDHashTable *table, PLDHashEntryHdr *entry, PRUint32 number, void *arg) -{ - return (PLDHashOperator) (PL_DHASH_NEXT | PL_DHASH_REMOVE); -} - -#ifdef MOZ_OMNIJAR -nsresult -nsChromeRegistry::CheckOmnijarChrome() -{ - nsresult rv; - - nsZipArchive* jarReader = mozilla::OmnijarReader(); - // just proceed normally if there is no omnijar - if (!jarReader) - return NS_OK; - - nsZipItem* manifest = jarReader->GetItem("chrome/chrome.manifest"); - NS_ENSURE_TRUE(manifest, NS_ERROR_NOT_AVAILABLE); + PRUint32 flags; + rv = GetFlagsFromPackage(package, &flags); - nsCAutoString omniJarSpec; - rv = NS_GetURLSpecFromActualFile(mozilla::OmnijarPath(), omniJarSpec); - NS_ENSURE_SUCCESS(rv, rv); - - PRUint32 len = manifest->RealSize(); - nsAutoArrayPtr<PRUint8> outbuf(new PRUint8[len]); - NS_ENSURE_TRUE(outbuf, NS_ERROR_OUT_OF_MEMORY); - - nsZipCursor cursor(manifest, jarReader, outbuf, len); - PRUint32 readlen; - PRUint8* buf = cursor.Read(&readlen); - NS_ENSURE_TRUE(buf, NS_ERROR_FILE_CORRUPTED); - - nsAutoString jarString(NS_LITERAL_STRING("jar:")); - AppendUTF8toUTF16(omniJarSpec, jarString); - jarString += NS_LITERAL_STRING("!/chrome/chrome.manifest"); - - nsCOMPtr<nsIURI> manifestURI; - rv = NS_NewURI(getter_AddRefs(manifestURI), jarString); - NS_ENSURE_SUCCESS(rv, rv); - - rv = ProcessManifestBuffer((char *)buf, readlen, manifestURI, PR_FALSE); - NS_ENSURE_SUCCESS(rv, rv); - - return rv; -} -#endif /* MOZ_OMNIJAR */ - -NS_IMETHODIMP -nsChromeRegistry::CheckForNewChrome() -{ - PL_DHashTableEnumerate(&mPackagesHash, RemoveAll, nsnull); - mOverlayHash.Clear(); - mStyleHash.Clear(); - mOverrideTable.Clear(); - - nsComponentManagerImpl::gComponentManager->RereadChromeManifests(); + if (NS_SUCCEEDED(rv)) { + *aResult = !!(flags & CONTENT_ACCESSIBLE); + } return NS_OK; } NS_IMETHODIMP_(PRBool) nsChromeRegistry::WrappersEnabled(nsIURI *aURI) { nsCOMPtr<nsIURL> chromeURL (do_QueryInterface(aURI)); if (!chromeURL) @@ -1203,377 +666,34 @@ nsChromeRegistry::WrappersEnabled(nsIURI if (NS_FAILED(rv) || !isChrome) return PR_FALSE; nsCAutoString package; rv = chromeURL->GetHostPort(package); if (NS_FAILED(rv)) return PR_FALSE; - PackageEntry* entry = - static_cast<PackageEntry*>(PL_DHashTableOperate(&mPackagesHash, - & (nsACString&) package, - PL_DHASH_LOOKUP)); - - return PL_DHASH_ENTRY_IS_LIVE(entry); -} - -nsresult -nsChromeRegistry::SelectLocaleFromPref(nsIPrefBranch* prefs) -{ - nsresult rv; - PRBool matchOSLocale = PR_FALSE, userLocaleOverride = PR_FALSE; - prefs->PrefHasUserValue(SELECTED_LOCALE_PREF, &userLocaleOverride); - rv = prefs->GetBoolPref(MATCH_OS_LOCALE_PREF, &matchOSLocale); - - if (NS_SUCCEEDED(rv) && matchOSLocale && !userLocaleOverride) { - // compute lang and region code only when needed! - nsCAutoString uiLocale; - rv = getUILangCountry(uiLocale); - if (NS_SUCCEEDED(rv)) - mSelectedLocale = uiLocale; - } - else { - nsXPIDLCString provider; - rv = prefs->GetCharPref(SELECTED_LOCALE_PREF, getter_Copies(provider)); - if (NS_SUCCEEDED(rv)) { - mSelectedLocale = provider; - } - } - - return rv; -} - -NS_IMETHODIMP nsChromeRegistry::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *someData) -{ - nsresult rv = NS_OK; - - if (!strcmp(NS_PREFBRANCH_PREFCHANGE_TOPIC_ID, aTopic)) { - nsCOMPtr<nsIPrefBranch> prefs (do_QueryInterface(aSubject)); - NS_ASSERTION(prefs, "Bad observer call!"); - - NS_ConvertUTF16toUTF8 pref(someData); - - if (pref.EqualsLiteral(MATCH_OS_LOCALE_PREF) || - pref.EqualsLiteral(SELECTED_LOCALE_PREF)) { - rv = SelectLocaleFromPref(prefs); - if (NS_SUCCEEDED(rv) && mProfileLoaded) - FlushAllCaches(); - } - else if (pref.EqualsLiteral(SELECTED_SKIN_PREF)) { - nsXPIDLCString provider; - rv = prefs->GetCharPref(pref.get(), getter_Copies(provider)); - if (NS_FAILED(rv)) { - NS_ERROR("Couldn't get new locale pref!"); - return rv; - } - - mSelectedSkin = provider; - RefreshSkins(); - } else { - NS_ERROR("Unexpected pref!"); - } - } - else if (!strcmp("command-line-startup", aTopic)) { - nsCOMPtr<nsICommandLine> cmdLine (do_QueryInterface(aSubject)); - if (cmdLine) { - nsAutoString uiLocale; - rv = cmdLine->HandleFlagWithParam(NS_LITERAL_STRING(UILOCALE_CMD_LINE_ARG), - PR_FALSE, uiLocale); - if (NS_SUCCEEDED(rv) && !uiLocale.IsEmpty()) { - CopyUTF16toUTF8(uiLocale, mSelectedLocale); - nsCOMPtr<nsIPrefBranch2> prefs (do_GetService(NS_PREFSERVICE_CONTRACTID)); - if (prefs) { - prefs->RemoveObserver(SELECTED_LOCALE_PREF, this); - } - } - } - } - else if (!strcmp("profile-initial-state", aTopic)) { - mProfileLoaded = PR_TRUE; - } - else { - NS_ERROR("Unexpected observer topic!"); - } - - return rv; -} - -nsIURI* -nsChromeRegistry::ManifestProcessingContext::GetManifestURI() -{ - if (!mManifestURI) { - nsCOMPtr<nsIIOService> io = mozilla::services::GetIOService(); - if (!io) { - NS_WARNING("No IO service trying to process chrome manifests"); - return NULL; - } - - io->NewFileURI(mFile, getter_AddRefs(mManifestURI)); - } - return mManifestURI; -} - -nsIXPConnect* -nsChromeRegistry::ManifestProcessingContext::GetXPConnect() -{ - if (!mXPConnect) - mXPConnect = do_GetService("@mozilla.org/js/xpc/XPConnect;1"); - - return mXPConnect; -} - -already_AddRefed<nsIURI> -nsChromeRegistry::ManifestProcessingContext::ResolveURI(const char* uri) -{ - nsIURI* baseuri = GetManifestURI(); - if (!baseuri) - return NULL; - - nsCOMPtr<nsIURI> resolved; - nsresult rv = NS_NewURI(getter_AddRefs(resolved), uri, baseuri); - if (NS_FAILED(rv)) - return NULL; - - return resolved.forget(); -} - -static void -EnsureLowerCase(char *aBuf) -{ - for (; *aBuf; ++aBuf) { - char ch = *aBuf; - if (ch >= 'A' && ch <= 'Z') - *aBuf = ch + 'a' - 'A'; - } -} - -void -nsChromeRegistry::ManifestContent(ManifestProcessingContext& cx, int lineno, - char *const * argv, bool platform, bool contentaccessible) -{ - char* package = argv[0]; - char* uri = argv[1]; - - EnsureLowerCase(package); - - nsCOMPtr<nsIURI> resolved = cx.ResolveURI(uri); - if (!resolved) { - LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, - "During chrome registration, unable to create URI '%s'.", uri); - return; - } - - if (!CanLoadResource(resolved)) { - LogMessageWithContext(resolved, lineno, nsIScriptError::warningFlag, - "During chrome registration, cannot register non-local URI '%s' as content.", - uri); - return; - } - - PackageEntry* entry = - static_cast<PackageEntry*>(PL_DHashTableOperate(&mPackagesHash, - & (const nsACString&) nsDependentCString(package), - PL_DHASH_ADD)); - if (!entry) - return; - - entry->baseURI = resolved; - - if (platform) - entry->flags |= PackageEntry::PLATFORM_PACKAGE; - if (contentaccessible) - entry->flags |= PackageEntry::CONTENT_ACCESSIBLE; - if (cx.GetXPConnect()) { - nsCAutoString urlp("chrome://"); - urlp.Append(package); - urlp.Append('/'); - - cx.GetXPConnect()->FlagSystemFilenamePrefix(urlp.get(), true); - } + PRUint32 flags; + rv = GetFlagsFromPackage(package, &flags); + return NS_SUCCEEDED(rv) && (flags & XPCNATIVEWRAPPERS); } -void -nsChromeRegistry::ManifestLocale(ManifestProcessingContext& cx, int lineno, - char *const * argv, bool platform, bool contentaccessible) -{ - char* package = argv[0]; - char* provider = argv[1]; - char* uri = argv[2]; - - EnsureLowerCase(package); - - nsCOMPtr<nsIURI> resolved = cx.ResolveURI(uri); - if (!resolved) { - LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, - "During chrome registration, unable to create URI '%s'.", uri); - return; - } - - if (!CanLoadResource(resolved)) { - LogMessageWithContext(resolved, lineno, nsIScriptError::warningFlag, - "During chrome registration, cannot register non-local URI '%s' as content.", - uri); - return; - } - - PackageEntry* entry = - static_cast<PackageEntry*>(PL_DHashTableOperate(&mPackagesHash, - & (const nsACString&) nsDependentCString(package), - PL_DHASH_ADD)); - if (!entry) - return; - - entry->locales.SetBase(nsDependentCString(provider), resolved); -} - -void -nsChromeRegistry::ManifestSkin(ManifestProcessingContext& cx, int lineno, - char *const * argv, bool platform, bool contentaccessible) +already_AddRefed<nsChromeRegistry> +nsChromeRegistry::GetSingleton() { - char* package = argv[0]; - char* provider = argv[1]; - char* uri = argv[2]; - - EnsureLowerCase(package); - - nsCOMPtr<nsIURI> resolved = cx.ResolveURI(uri); - if (!resolved) { - LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, - "During chrome registration, unable to create URI '%s'.", uri); - return; - } - - if (!CanLoadResource(resolved)) { - LogMessageWithContext(resolved, lineno, nsIScriptError::warningFlag, - "During chrome registration, cannot register non-local URI '%s' as content.", - uri); - return; - } - - PackageEntry* entry = - static_cast<PackageEntry*>(PL_DHashTableOperate(&mPackagesHash, - & (const nsACString&) nsDependentCString(package), - PL_DHASH_ADD)); - if (!entry) - return; - - entry->skins.SetBase(nsDependentCString(provider), resolved); -} - -void -nsChromeRegistry::ManifestOverlay(ManifestProcessingContext& cx, int lineno, - char *const * argv, bool platform, bool contentaccessible) -{ - char* base = argv[0]; - char* overlay = argv[1]; - - nsCOMPtr<nsIURI> baseuri = cx.ResolveURI(base); - nsCOMPtr<nsIURI> overlayuri = cx.ResolveURI(overlay); - if (!baseuri || !overlayuri) { - LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, - "During chrome registration, unable to create URI."); - return; - } - - if (!CanLoadResource(overlayuri)) { - LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, - "Cannot register non-local URI '%s' as an overlay.", overlay); - return; + if (gChromeRegistry) { + NS_ADDREF(gChromeRegistry); + return gChromeRegistry; } - mOverlayHash.Add(baseuri, overlayuri); -} - -void -nsChromeRegistry::ManifestStyle(ManifestProcessingContext& cx, int lineno, - char *const * argv, bool platform, bool contentaccessible) -{ - char* base = argv[0]; - char* overlay = argv[1]; - - nsCOMPtr<nsIURI> baseuri = cx.ResolveURI(base); - nsCOMPtr<nsIURI> overlayuri = cx.ResolveURI(overlay); - if (!baseuri || !overlayuri) { - LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, - "During chrome registration, unable to create URI."); - return; - } - - if (!CanLoadResource(overlayuri)) { - LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, - "Cannot register non-local URI '%s' as a style overlay.", overlay); - return; - } + nsRefPtr<nsChromeRegistry> cr; +#ifdef MOZ_IPC + if (GeckoProcessType_Content == XRE_GetProcessType()) + cr = new nsChromeRegistryContent(); + else +#endif + cr = new nsChromeRegistryChrome(); - mStyleHash.Add(baseuri, overlayuri); -} - -void -nsChromeRegistry::ManifestOverride(ManifestProcessingContext& cx, int lineno, - char *const * argv, bool platform, bool contentaccessible) -{ - char* chrome = argv[0]; - char* resolved = argv[1]; + if (NS_FAILED(cr->Init())) + return NULL; - nsCOMPtr<nsIURI> chromeuri = cx.ResolveURI(chrome); - nsCOMPtr<nsIURI> resolveduri = cx.ResolveURI(resolved); - if (!chromeuri || !resolveduri) { - LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, - "During chrome registration, unable to create URI."); - return; - } - - if (!CanLoadResource(resolveduri)) { - LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, - "Cannot register non-local URI '%s' for an override.", resolved); - return; - } - mOverrideTable.Put(chromeuri, resolveduri); + return cr.forget(); } - -void -nsChromeRegistry::ManifestResource(ManifestProcessingContext& cx, int lineno, - char *const * argv, bool platform, bool contentaccessible) -{ - char* package = argv[0]; - char* uri = argv[1]; - - EnsureLowerCase(package); - nsDependentCString host(package); - - nsCOMPtr<nsIIOService> io = mozilla::services::GetIOService(); - if (!io) { - NS_WARNING("No IO service trying to process chrome manifests"); - return; - } - - nsCOMPtr<nsIProtocolHandler> ph; - nsresult rv = io->GetProtocolHandler("resource", getter_AddRefs(ph)); - if (NS_FAILED(rv)) - return; - - nsCOMPtr<nsIResProtocolHandler> rph = do_QueryInterface(ph); - - PRBool exists = PR_FALSE; - rv = rph->HasSubstitution(host, &exists); - if (exists) { - LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, - "Duplicate resource declaration for '%s' ignored.", package); - return; - } - - nsCOMPtr<nsIURI> resolved = cx.ResolveURI(uri); - if (!resolved) { - LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, - "During chrome registration, unable to create URI '%s'.", uri); - return; - } - - if (!CanLoadResource(resolved)) { - LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, - "Warning: cannot register non-local URI '%s' as a resource.", - uri); - return; - } - - rph->SetSubstitution(host, resolved); -}
--- a/chrome/src/nsChromeRegistry.h +++ b/chrome/src/nsChromeRegistry.h @@ -32,107 +32,111 @@ * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ +#ifndef nsChromeRegistry_h +#define nsChromeRegistry_h + #include "nsIChromeRegistry.h" #include "nsIToolkitChromeRegistry.h" #include "nsIObserver.h" #include "nsWeakReference.h" +#include "nsIPrefBranch.h" #ifdef MOZ_XUL #include "nsIXULOverlayProvider.h" #endif #include "pldhash.h" #include "nsCOMArray.h" #include "nsString.h" #include "nsTHashtable.h" #include "nsURIHashKey.h" -#include "nsVoidArray.h" -#include "nsTArray.h" #include "nsInterfaceHashtable.h" #include "nsXULAppAPI.h" #include "nsIResProtocolHandler.h" #include "nsIXPConnect.h" -struct PRFileDesc; -class nsIAtom; class nsIDOMWindowInternal; -class nsILocalFile; -class nsIPrefBranch; -class nsIRDFDataSource; -class nsIRDFResource; -class nsIRDFService; -class nsISimpleEnumerator; class nsIURL; +// The chrome registry is actually split between nsChromeRegistryChrome and +// nsChromeRegistryContent. The work/data that is common to both resides in +// the shared nsChromeRegistry implementation, with operations that only make +// sense for one side erroring out in the other. + // for component registration // {47049e42-1d87-482a-984d-56ae185e367a} #define NS_CHROMEREGISTRY_CID \ { 0x47049e42, 0x1d87, 0x482a, { 0x98, 0x4d, 0x56, 0xae, 0x18, 0x5e, 0x36, 0x7a } } class nsChromeRegistry : public nsIToolkitChromeRegistry, #ifdef MOZ_XUL public nsIXULOverlayProvider, #endif public nsIObserver, public nsSupportsWeakReference { public: NS_DECL_ISUPPORTS - // nsIChromeRegistry methods: - NS_DECL_NSICHROMEREGISTRY - NS_DECL_NSIXULCHROMEREGISTRY - NS_DECL_NSITOOLKITCHROMEREGISTRY + // nsIXULChromeRegistry methods: + NS_IMETHOD ReloadChrome(); + NS_IMETHOD RefreshSkins(); + NS_IMETHOD AllowScriptsForPackage(nsIURI* url, + PRBool* _retval NS_OUTPARAM); + NS_IMETHOD AllowContentToAccess(nsIURI* url, + PRBool* _retval NS_OUTPARAM); -#ifdef MOZ_XUL - NS_DECL_NSIXULOVERLAYPROVIDER -#endif - - NS_DECL_NSIOBSERVER + // nsIChromeRegistry methods: + NS_IMETHOD_(PRBool) WrappersEnabled(nsIURI *aURI); + NS_IMETHOD ConvertChromeURL(nsIURI* aChromeURI, nsIURI* *aResult); // nsChromeRegistry methods: - nsChromeRegistry() : mInitialized(PR_FALSE), mProfileLoaded(PR_FALSE) { - mPackagesHash.ops = nsnull; - } - ~nsChromeRegistry(); + nsChromeRegistry() : mInitialized(PR_FALSE) { } + virtual ~nsChromeRegistry(); - nsresult Init(); + virtual nsresult Init(); + + static already_AddRefed<nsIChromeRegistry> GetService(); static nsChromeRegistry* gChromeRegistry; static nsresult Canonify(nsIURL* aChromeURL); protected: - nsresult GetDynamicInfo(nsIURI *aChromeURL, PRBool aIsOverlay, nsISimpleEnumerator **aResult); - - nsresult LoadInstallDataSource(); - nsresult LoadProfileDataSource(); - void FlushSkinCaches(); void FlushAllCaches(); -private: + static void LogMessage(const char* aMsg, ...); + static void LogMessageWithContext(nsIURI* aURL, PRUint32 aLineNumber, PRUint32 flags, + const char* aMsg, ...); + + virtual nsresult GetBaseURIFromPackage(const nsCString& aPackage, + const nsCString& aProvider, + const nsCString& aPath, + nsIURI* *aResult) = 0; + virtual nsresult GetFlagsFromPackage(const nsCString& aPackage, + PRUint32* aFlags) = 0; + nsresult SelectLocaleFromPref(nsIPrefBranch* prefs); -#ifdef MOZ_OMNIJAR - nsresult CheckOmnijarChrome(); -#endif static nsresult RefreshWindow(nsIDOMWindowInternal* aWindow); static nsresult GetProviderAndPath(nsIURL* aChromeURL, nsACString& aProvider, nsACString& aPath); public: + static already_AddRefed<nsChromeRegistry> GetSingleton(); + struct ManifestProcessingContext { ManifestProcessingContext(NSLocationType aType, nsILocalFile* aFile) : mType(aType) , mFile(aFile) { } ~ManifestProcessingContext() { } @@ -143,144 +147,52 @@ public: already_AddRefed<nsIURI> ResolveURI(const char* uri); NSLocationType mType; nsCOMPtr<nsILocalFile> mFile; nsCOMPtr<nsIURI> mManifestURI; nsCOMPtr<nsIXPConnect> mXPConnect; }; - void ManifestContent(ManifestProcessingContext& cx, int lineno, - char *const * argv, bool platform, bool contentaccessible); - void ManifestLocale(ManifestProcessingContext& cx, int lineno, - char *const * argv, bool platform, bool contentaccessible); - void ManifestSkin(ManifestProcessingContext& cx, int lineno, - char *const * argv, bool platform, bool contentaccessible); - void ManifestOverlay(ManifestProcessingContext& cx, int lineno, - char *const * argv, bool platform, bool contentaccessible); - void ManifestStyle(ManifestProcessingContext& cx, int lineno, - char *const * argv, bool platform, bool contentaccessible); - void ManifestOverride(ManifestProcessingContext& cx, int lineno, - char *const * argv, bool platform, bool contentaccessible); - void ManifestResource(ManifestProcessingContext& cx, int lineno, - char *const * argv, bool platform, bool contentaccessible); - -public: - struct ProviderEntry - { - ProviderEntry(const nsACString& aProvider, nsIURI* aBase) : - provider(aProvider), - baseURI(aBase) { } - - nsCString provider; - nsCOMPtr<nsIURI> baseURI; - }; + virtual void ManifestContent(ManifestProcessingContext& cx, int lineno, + char *const * argv, bool platform, + bool contentaccessible) = 0; + virtual void ManifestLocale(ManifestProcessingContext& cx, int lineno, + char *const * argv, bool platform, + bool contentaccessible) = 0; + virtual void ManifestSkin(ManifestProcessingContext& cx, int lineno, + char *const * argv, bool platform, + bool contentaccessible) = 0; + virtual void ManifestOverlay(ManifestProcessingContext& cx, int lineno, + char *const * argv, bool platform, + bool contentaccessible) = 0; + virtual void ManifestStyle(ManifestProcessingContext& cx, int lineno, + char *const * argv, bool platform, + bool contentaccessible) = 0; + virtual void ManifestOverride(ManifestProcessingContext& cx, int lineno, + char *const * argv, bool platform, + bool contentaccessible) = 0; + virtual void ManifestResource(ManifestProcessingContext& cx, int lineno, + char *const * argv, bool platform, + bool contentaccessible) = 0; - class nsProviderArray - { - public: - nsProviderArray() : - mArray(1) { } - ~nsProviderArray() - { Clear(); } + // Available flags + enum { + // This is a "platform" package (e.g. chrome://global-platform/). + // Appends one of win/ unix/ mac/ to the base URI. + PLATFORM_PACKAGE = 1 << 0, - // When looking up locales and skins, the "selected" locale is not always - // available. This enum identifies what kind of match is desired/found. - enum MatchType { - EXACT = 0, - LOCALE = 1, // "en-GB" is selected, we found "en-US" - ANY = 2 - }; + // This package should use the new XPCNativeWrappers to separate + // content from chrome. This flag is currently unused (because we call + // into xpconnect at registration time). + XPCNATIVEWRAPPERS = 1 << 1, - nsIURI* GetBase(const nsACString& aPreferred, MatchType aType); - const nsACString& GetSelected(const nsACString& aPreferred, MatchType aType); - void SetBase(const nsACString& aProvider, nsIURI* base); - void EnumerateToArray(nsTArray<nsCString> *a); - void Clear(); - - private: - ProviderEntry* GetProvider(const nsACString& aPreferred, MatchType aType); - - nsVoidArray mArray; + // Content script may access files in this package + CONTENT_ACCESSIBLE = 1 << 2 }; - struct PackageEntry : public PLDHashEntryHdr - { - PackageEntry(const nsACString& package); - ~PackageEntry() { } - - // Available flags - enum { - // This is a "platform" package (e.g. chrome://global-platform/). - // Appends one of win/ unix/ mac/ to the base URI. - PLATFORM_PACKAGE = 1 << 0, - - // Content script may access files in this package - CONTENT_ACCESSIBLE = 1 << 1 - }; - - nsCString package; - nsCOMPtr<nsIURI> baseURI; - PRUint32 flags; - nsProviderArray locales; - nsProviderArray skins; - }; - -private: - static PLDHashNumber HashKey(PLDHashTable *table, const void *key); - static PRBool MatchKey(PLDHashTable *table, const PLDHashEntryHdr *entry, - const void *key); - static void ClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry); - static PRBool InitEntry(PLDHashTable *table, PLDHashEntryHdr *entry, - const void *key); - - static const PLDHashTableOps kTableOps; - -public: - class OverlayListEntry : public nsURIHashKey - { - public: - typedef nsURIHashKey::KeyType KeyType; - typedef nsURIHashKey::KeyTypePointer KeyTypePointer; - - OverlayListEntry(KeyTypePointer aKey) : nsURIHashKey(aKey) { } - OverlayListEntry(OverlayListEntry& toCopy) : nsURIHashKey(toCopy), - mArray(toCopy.mArray) { } - ~OverlayListEntry() { } - - void AddURI(nsIURI* aURI); - - nsCOMArray<nsIURI> mArray; - }; - - class OverlayListHash - { - public: - OverlayListHash() { } - ~OverlayListHash() { } - - PRBool Init() { return mTable.Init(); } - void Add(nsIURI* aBase, nsIURI* aOverlay); - void Clear() { mTable.Clear(); } - const nsCOMArray<nsIURI>* GetArray(nsIURI* aBase); - - private: - nsTHashtable<OverlayListEntry> mTable; - }; - -private: PRBool mInitialized; - PRBool mProfileLoaded; - - // Hash of package names ("global") to PackageEntry objects - PLDHashTable mPackagesHash; - - // Hashes on the file to be overlaid (chrome://browser/content/browser.xul) - // to a list of overlays/stylesheets - OverlayListHash mOverlayHash; - OverlayListHash mStyleHash; // "Override" table (chrome URI string -> real URI) nsInterfaceHashtable<nsURIHashKey, nsIURI> mOverrideTable; +}; - nsCString mSelectedLocale; - nsCString mSelectedSkin; -}; +#endif // nsChromeRegistry_h
new file mode 100644 --- /dev/null +++ b/chrome/src/nsChromeRegistryChrome.cpp @@ -0,0 +1,1109 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Josh Matthews <josh@joshmatthews.net> (Initial Developer) + * + * 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 ***** */ + +#ifdef MOZ_IPC +#include "mozilla/dom/PContentProcessParent.h" +#include "RegistryMessageUtils.h" +#include "nsResProtocolHandler.h" +#endif + +#include "nsChromeRegistryChrome.h" + +#if defined(XP_WIN) +#include <windows.h> +#elif defined(XP_MACOSX) +#include <CoreServices/CoreServices.h> +#elif defined(MOZ_WIDGET_GTK2) +#include <gtk/gtk.h> +#endif + +#include "nsArrayEnumerator.h" +#include "nsAppDirectoryServiceDefs.h" +#include "nsComponentManager.h" +#include "nsEnumeratorUtils.h" +#include "nsNetUtil.h" +#include "nsStringEnumerator.h" +#include "nsTextFormatter.h" +#include "nsUnicharUtils.h" +#include "nsWidgetsCID.h" +#include "nsXPCOMCIDInternal.h" +#include "nsZipArchive.h" + +#include "nsICommandLine.h" +#include "nsILocaleService.h" +#include "nsILocalFile.h" +#include "nsILookAndFeel.h" +#include "nsIObserverService.h" +#include "nsIPrefBranch2.h" +#include "nsIPrefService.h" +#include "nsIResProtocolHandler.h" +#include "nsIScriptError.h" +#include "nsIVersionComparator.h" +#include "nsIXPConnect.h" +#include "nsIXULAppInfo.h" +#include "nsIXULRuntime.h" + +#include "mozilla/Omnijar.h" + +#define UILOCALE_CMD_LINE_ARG "UILocale" + +#define MATCH_OS_LOCALE_PREF "intl.locale.matchOS" +#define SELECTED_LOCALE_PREF "general.useragent.locale" +#define SELECTED_SKIN_PREF "general.skins.selectedSkin" + +static NS_DEFINE_CID(kLookAndFeelCID, NS_LOOKANDFEEL_CID); + +static PLDHashOperator +RemoveAll(PLDHashTable *table, PLDHashEntryHdr *entry, PRUint32 number, void *arg) +{ + return (PLDHashOperator) (PL_DHASH_NEXT | PL_DHASH_REMOVE); +} + +// We use a "best-fit" algorithm for matching locales and themes. +// 1) the exact selected locale/theme +// 2) (locales only) same language, different country +// e.g. en-GB is the selected locale, only en-US is available +// 3) any available locale/theme + +/** + * Match the language-part of two lang-COUNTRY codes, hopefully but + * not guaranteed to be in the form ab-CD or abz-CD. "ab" should also + * work, any other garbage-in will produce undefined results as long + * as it does not crash. + */ +static PRBool +LanguagesMatch(const nsACString& a, const nsACString& b) +{ + if (a.Length() < 2 || b.Length() < 2) + return PR_FALSE; + + nsACString::const_iterator as, ae, bs, be; + a.BeginReading(as); + a.EndReading(ae); + b.BeginReading(bs); + b.EndReading(be); + + while (*as == *bs) { + if (*as == '-') + return PR_TRUE; + + ++as; ++bs; + + // reached the end + if (as == ae && bs == be) + return PR_TRUE; + + // "a" is short + if (as == ae) + return (*bs == '-'); + + // "b" is short + if (bs == be) + return (*as == '-'); + } + + return PR_FALSE; +} + +nsChromeRegistryChrome::nsChromeRegistryChrome() + : mProfileLoaded(PR_FALSE) +{ + mPackagesHash.ops = nsnull; +} + +nsChromeRegistryChrome::~nsChromeRegistryChrome() +{ + if (mPackagesHash.ops) + PL_DHashTableFinish(&mPackagesHash); +} + +nsresult +nsChromeRegistryChrome::Init() +{ + nsresult rv = nsChromeRegistry::Init(); + if (NS_FAILED(rv)) + return rv; + + if (!mOverlayHash.Init() || + !mStyleHash.Init()) + return NS_ERROR_FAILURE; + + mSelectedLocale = NS_LITERAL_CSTRING("en-US"); + mSelectedSkin = NS_LITERAL_CSTRING("classic/1.0"); + + if (!PL_DHashTableInit(&mPackagesHash, &kTableOps, + nsnull, sizeof(PackageEntry), 16)) + return NS_ERROR_FAILURE; + + PRBool safeMode = PR_FALSE; + nsCOMPtr<nsIXULRuntime> xulrun (do_GetService(XULAPPINFO_SERVICE_CONTRACTID)); + if (xulrun) + xulrun->GetInSafeMode(&safeMode); + + nsCOMPtr<nsIPrefService> prefserv (do_GetService(NS_PREFSERVICE_CONTRACTID)); + nsCOMPtr<nsIPrefBranch> prefs; + + if (safeMode) + prefserv->GetDefaultBranch(nsnull, getter_AddRefs(prefs)); + else + prefs = do_QueryInterface(prefserv); + + if (!prefs) { + NS_WARNING("Could not get pref service!"); + } + else { + nsXPIDLCString provider; + rv = prefs->GetCharPref(SELECTED_SKIN_PREF, getter_Copies(provider)); + if (NS_SUCCEEDED(rv)) + mSelectedSkin = provider; + + SelectLocaleFromPref(prefs); + + nsCOMPtr<nsIPrefBranch2> prefs2 (do_QueryInterface(prefs)); + if (prefs2) { + rv = prefs2->AddObserver(MATCH_OS_LOCALE_PREF, this, PR_TRUE); + rv = prefs2->AddObserver(SELECTED_LOCALE_PREF, this, PR_TRUE); + rv = prefs2->AddObserver(SELECTED_SKIN_PREF, this, PR_TRUE); + } + } + + nsCOMPtr<nsIObserverService> obsService = mozilla::services::GetObserverService(); + if (obsService) { + obsService->AddObserver(this, "command-line-startup", PR_TRUE); + obsService->AddObserver(this, "profile-initial-state", PR_TRUE); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsChromeRegistryChrome::CheckForOSAccessibility() +{ + nsresult rv; + + nsCOMPtr<nsILookAndFeel> lookAndFeel (do_GetService(kLookAndFeelCID)); + if (lookAndFeel) { + PRInt32 useAccessibilityTheme = 0; + + rv = lookAndFeel->GetMetric(nsILookAndFeel::eMetric_UseAccessibilityTheme, + useAccessibilityTheme); + + if (NS_SUCCEEDED(rv) && useAccessibilityTheme) { + /* Set the skin to classic and remove pref observers */ + if (!mSelectedSkin.EqualsLiteral("classic/1.0")) { + mSelectedSkin.AssignLiteral("classic/1.0"); + RefreshSkins(); + } + + nsCOMPtr<nsIPrefBranch2> prefs (do_GetService(NS_PREFSERVICE_CONTRACTID)); + if (prefs) { + prefs->RemoveObserver(SELECTED_SKIN_PREF, this); + } + } + } + + return NS_OK; +} + +NS_IMETHODIMP +nsChromeRegistryChrome::GetLocalesForPackage(const nsACString& aPackage, + nsIUTF8StringEnumerator* *aResult) +{ + nsTArray<nsCString> *a = new nsTArray<nsCString>; + if (!a) + return NS_ERROR_OUT_OF_MEMORY; + + PackageEntry* entry = + static_cast<PackageEntry*>(PL_DHashTableOperate(&mPackagesHash, + & aPackage, + PL_DHASH_LOOKUP)); + + if (PL_DHASH_ENTRY_IS_BUSY(entry)) { + entry->locales.EnumerateToArray(a); + } + + nsresult rv = NS_NewAdoptingUTF8StringEnumerator(aResult, a); + if (NS_FAILED(rv)) + delete a; + + return rv; +} + +static nsresult +getUILangCountry(nsACString& aUILang) +{ + nsresult rv; + + nsCOMPtr<nsILocaleService> localeService = do_GetService(NS_LOCALESERVICE_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoString uiLang; + rv = localeService->GetLocaleComponentForUserAgent(uiLang); + NS_ENSURE_SUCCESS(rv, rv); + + CopyUTF16toUTF8(uiLang, aUILang); + return NS_OK; +} + +NS_IMETHODIMP +nsChromeRegistryChrome::IsLocaleRTL(const nsACString& package, PRBool *aResult) +{ + *aResult = PR_FALSE; + + nsCAutoString locale; + GetSelectedLocale(package, locale); + if (locale.Length() < 2) + return NS_OK; + + // first check the intl.uidirection.<locale> preference, and if that is not + // set, check the same preference but with just the first two characters of + // the locale. If that isn't set, default to left-to-right. + nsCAutoString prefString = NS_LITERAL_CSTRING("intl.uidirection.") + locale; + nsCOMPtr<nsIPrefBranch> prefBranch (do_GetService(NS_PREFSERVICE_CONTRACTID)); + if (!prefBranch) + return NS_OK; + + nsXPIDLCString dir; + prefBranch->GetCharPref(prefString.get(), getter_Copies(dir)); + if (dir.IsEmpty()) { + PRInt32 hyphen = prefString.FindChar('-'); + if (hyphen >= 1) { + nsCAutoString shortPref(Substring(prefString, 0, hyphen)); + prefBranch->GetCharPref(shortPref.get(), getter_Copies(dir)); + } + } + *aResult = dir.EqualsLiteral("rtl"); + return NS_OK; +} + +nsresult +nsChromeRegistryChrome::GetSelectedLocale(const nsACString& aPackage, + nsACString& aLocale) +{ + PackageEntry* entry = + static_cast<PackageEntry*>(PL_DHashTableOperate(&mPackagesHash, + & aPackage, + PL_DHASH_LOOKUP)); + + if (PL_DHASH_ENTRY_IS_FREE(entry)) + return NS_ERROR_FAILURE; + + aLocale = entry->locales.GetSelected(mSelectedLocale, nsProviderArray::LOCALE); + if (aLocale.IsEmpty()) + return NS_ERROR_FAILURE; + + return NS_OK; +} + +nsresult +nsChromeRegistryChrome::SelectLocaleFromPref(nsIPrefBranch* prefs) +{ + nsresult rv; + PRBool matchOSLocale = PR_FALSE, userLocaleOverride = PR_FALSE; + prefs->PrefHasUserValue(SELECTED_LOCALE_PREF, &userLocaleOverride); + rv = prefs->GetBoolPref(MATCH_OS_LOCALE_PREF, &matchOSLocale); + + if (NS_SUCCEEDED(rv) && matchOSLocale && !userLocaleOverride) { + // compute lang and region code only when needed! + nsCAutoString uiLocale; + rv = getUILangCountry(uiLocale); + if (NS_SUCCEEDED(rv)) + mSelectedLocale = uiLocale; + } + else { + nsXPIDLCString provider; + rv = prefs->GetCharPref(SELECTED_LOCALE_PREF, getter_Copies(provider)); + if (NS_SUCCEEDED(rv)) { + mSelectedLocale = provider; + } + } + + return rv; +} + +NS_IMETHODIMP +nsChromeRegistryChrome::Observe(nsISupports *aSubject, const char *aTopic, + const PRUnichar *someData) +{ + nsresult rv = NS_OK; + + if (!strcmp(NS_PREFBRANCH_PREFCHANGE_TOPIC_ID, aTopic)) { + nsCOMPtr<nsIPrefBranch> prefs (do_QueryInterface(aSubject)); + NS_ASSERTION(prefs, "Bad observer call!"); + + NS_ConvertUTF16toUTF8 pref(someData); + + if (pref.EqualsLiteral(MATCH_OS_LOCALE_PREF) || + pref.EqualsLiteral(SELECTED_LOCALE_PREF)) { + rv = SelectLocaleFromPref(prefs); + if (NS_SUCCEEDED(rv) && mProfileLoaded) + FlushAllCaches(); + } + else if (pref.EqualsLiteral(SELECTED_SKIN_PREF)) { + nsXPIDLCString provider; + rv = prefs->GetCharPref(pref.get(), getter_Copies(provider)); + if (NS_FAILED(rv)) { + NS_ERROR("Couldn't get new locale pref!"); + return rv; + } + + mSelectedSkin = provider; + RefreshSkins(); + } else { + NS_ERROR("Unexpected pref!"); + } + } + else if (!strcmp("command-line-startup", aTopic)) { + nsCOMPtr<nsICommandLine> cmdLine (do_QueryInterface(aSubject)); + if (cmdLine) { + nsAutoString uiLocale; + rv = cmdLine->HandleFlagWithParam(NS_LITERAL_STRING(UILOCALE_CMD_LINE_ARG), + PR_FALSE, uiLocale); + if (NS_SUCCEEDED(rv) && !uiLocale.IsEmpty()) { + CopyUTF16toUTF8(uiLocale, mSelectedLocale); + nsCOMPtr<nsIPrefBranch2> prefs (do_GetService(NS_PREFSERVICE_CONTRACTID)); + if (prefs) { + prefs->RemoveObserver(SELECTED_LOCALE_PREF, this); + } + } + } + } + else if (!strcmp("profile-initial-state", aTopic)) { + mProfileLoaded = PR_TRUE; + } + else { + NS_ERROR("Unexpected observer topic!"); + } + + return rv; +} + +#ifdef MOZ_OMNIJAR +nsresult +nsChromeRegistryChrome::CheckOmnijarChrome() +{ + nsresult rv; + + nsZipArchive* jarReader = mozilla::OmnijarReader(); + // just proceed normally if there is no omnijar + if (!jarReader) + return NS_OK; + + nsZipItem* manifest = jarReader->GetItem("chrome/chrome.manifest"); + NS_ENSURE_TRUE(manifest, NS_ERROR_NOT_AVAILABLE); + + nsCAutoString omniJarSpec; + rv = NS_GetURLSpecFromActualFile(mozilla::OmnijarPath(), omniJarSpec); + NS_ENSURE_SUCCESS(rv, rv); + + PRUint32 len = manifest->RealSize(); + nsAutoArrayPtr<PRUint8> outbuf(new PRUint8[len]); + NS_ENSURE_TRUE(outbuf, NS_ERROR_OUT_OF_MEMORY); + + nsZipCursor cursor(manifest, jarReader, outbuf, len); + PRUint32 readlen; + PRUint8* buf = cursor.Read(&readlen); + NS_ENSURE_TRUE(buf, NS_ERROR_FILE_CORRUPTED); + + nsAutoString jarString(NS_LITERAL_STRING("jar:")); + AppendUTF8toUTF16(omniJarSpec, jarString); + jarString += NS_LITERAL_STRING("!/chrome/chrome.manifest"); + + nsCOMPtr<nsIURI> manifestURI; + rv = NS_NewURI(getter_AddRefs(manifestURI), jarString); + NS_ENSURE_SUCCESS(rv, rv); + + rv = ProcessManifestBuffer((char *)buf, readlen, manifestURI, PR_FALSE); + NS_ENSURE_SUCCESS(rv, rv); + + return rv; +} +#endif /* MOZ_OMNIJAR */ + +NS_IMETHODIMP +nsChromeRegistryChrome::CheckForNewChrome() +{ + PL_DHashTableEnumerate(&mPackagesHash, RemoveAll, nsnull); + mOverlayHash.Clear(); + mStyleHash.Clear(); + mOverrideTable.Clear(); + + nsComponentManagerImpl::gComponentManager->RereadChromeManifests(); + return NS_OK; +} + +#ifdef MOZ_IPC +static void +SerializeURI(nsIURI* aURI, + SerializedURI& aSerializedURI) +{ + if (!aURI) + return; + + aURI->GetSpec(aSerializedURI.spec); + aURI->GetOriginCharset(aSerializedURI.charset); +} + +static PLDHashOperator +EnumerateOverride(nsIURI* aURIKey, + nsIURI* aURI, + void* aArg) +{ + nsTArray<OverrideMapping>* overrides = + static_cast<nsTArray<OverrideMapping>*>(aArg); + + SerializedURI chromeURI, overrideURI; + + SerializeURI(aURIKey, chromeURI); + SerializeURI(aURI, overrideURI); + + OverrideMapping override = { + chromeURI, overrideURI + }; + overrides->AppendElement(override); + return (PLDHashOperator)PL_DHASH_NEXT; +} + +struct EnumerationArgs +{ + nsTArray<ChromePackage>& packages; + const nsCString& selectedLocale; + const nsCString& selectedSkin; +}; + +void +nsChromeRegistryChrome::SendRegisteredChrome( + mozilla::dom::PContentProcessParent* aParent) +{ + nsTArray<ChromePackage> packages; + nsTArray<ResourceMapping> resources; + nsTArray<OverrideMapping> overrides; + + EnumerationArgs args = { + packages, mSelectedLocale, mSelectedSkin + }; + PL_DHashTableEnumerate(&mPackagesHash, CollectPackages, &args); + + nsCOMPtr<nsIIOService> io (do_GetIOService()); + NS_ENSURE_TRUE(io, ); + + nsCOMPtr<nsIProtocolHandler> ph; + nsresult rv = io->GetProtocolHandler("resource", getter_AddRefs(ph)); + NS_ENSURE_SUCCESS(rv, ); + + //FIXME: Some substitutions are set up lazily and might not exist yet + nsCOMPtr<nsIResProtocolHandler> irph (do_QueryInterface(ph)); + nsResProtocolHandler* rph = static_cast<nsResProtocolHandler*>(irph.get()); + rph->CollectSubstitutions(resources); + + mOverrideTable.EnumerateRead(&EnumerateOverride, &overrides); + + bool success = aParent->SendRegisterChrome(packages, resources, overrides); + NS_ENSURE_TRUE(success, ); +} + +PLDHashOperator +nsChromeRegistryChrome::CollectPackages(PLDHashTable *table, + PLDHashEntryHdr *entry, + PRUint32 number, + void *arg) +{ + EnumerationArgs* args = static_cast<EnumerationArgs*>(arg); + PackageEntry* package = static_cast<PackageEntry*>(entry); + + SerializedURI contentURI, localeURI, skinURI; + + SerializeURI(package->baseURI, contentURI); + SerializeURI(package->locales.GetBase(args->selectedLocale, + nsProviderArray::LOCALE), localeURI); + SerializeURI(package->skins.GetBase(args->selectedSkin, nsProviderArray::ANY), + skinURI); + + ChromePackage chromePackage = { + package->package, + contentURI, + localeURI, + skinURI, + package->flags + }; + args->packages.AppendElement(chromePackage); + return (PLDHashOperator)PL_DHASH_NEXT; +} +#endif + +static PRBool +CanLoadResource(nsIURI* aResourceURI) +{ + PRBool isLocalResource = PR_FALSE; + (void)NS_URIChainHasFlags(aResourceURI, + nsIProtocolHandler::URI_IS_LOCAL_RESOURCE, + &isLocalResource); + return isLocalResource; +} + +nsresult +nsChromeRegistryChrome::GetBaseURIFromPackage(const nsCString& aPackage, + const nsCString& aProvider, + const nsCString& aPath, + nsIURI* *aResult) +{ + PackageEntry* entry = + static_cast<PackageEntry*>(PL_DHashTableOperate(&mPackagesHash, + &aPackage, + PL_DHASH_LOOKUP)); + + if (PL_DHASH_ENTRY_IS_FREE(entry)) { + if (!mInitialized) + return NS_ERROR_NOT_INITIALIZED; + + LogMessage("No chrome package registered for chrome://%s/%s/%s", + aPackage.get(), aProvider.get(), aPath.get()); + + return NS_ERROR_FAILURE; + } + + *aResult = nsnull; + if (aProvider.EqualsLiteral("locale")) { + *aResult = entry->locales.GetBase(mSelectedLocale, nsProviderArray::LOCALE); + } + else if (aProvider.EqualsLiteral("skin")) { + *aResult = entry->skins.GetBase(mSelectedSkin, nsProviderArray::ANY); + } + else if (aProvider.EqualsLiteral("content")) { + *aResult = entry->baseURI; + } + return NS_OK; +} + +nsresult +nsChromeRegistryChrome::GetFlagsFromPackage(const nsCString& aPackage, + PRUint32* aFlags) +{ + PackageEntry* entry = + static_cast<PackageEntry*>(PL_DHashTableOperate(&mPackagesHash, + & (nsACString&) aPackage, + PL_DHASH_LOOKUP)); + if (PL_DHASH_ENTRY_IS_FREE(entry)) + return NS_ERROR_NOT_AVAILABLE; + + *aFlags = entry->flags; + return NS_OK; +} + +PLHashNumber +nsChromeRegistryChrome::HashKey(PLDHashTable *table, const void *key) +{ + const nsACString& str = *reinterpret_cast<const nsACString*>(key); + return HashString(str); +} + +PRBool +nsChromeRegistryChrome::MatchKey(PLDHashTable *table, const PLDHashEntryHdr *entry, + const void *key) +{ + const nsACString& str = *reinterpret_cast<const nsACString*>(key); + const PackageEntry* pentry = static_cast<const PackageEntry*>(entry); + return str.Equals(pentry->package); +} + +void +nsChromeRegistryChrome::ClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry) +{ + PackageEntry* pentry = static_cast<PackageEntry*>(entry); + pentry->~PackageEntry(); +} + +PRBool +nsChromeRegistryChrome::InitEntry(PLDHashTable *table, PLDHashEntryHdr *entry, + const void *key) +{ + const nsACString& str = *reinterpret_cast<const nsACString*>(key); + + new (entry) PackageEntry(str); + return PR_TRUE; +} + +const PLDHashTableOps +nsChromeRegistryChrome::kTableOps = { + PL_DHashAllocTable, + PL_DHashFreeTable, + HashKey, + MatchKey, + PL_DHashMoveEntryStub, + ClearEntry, + PL_DHashFinalizeStub, + InitEntry +}; + +nsChromeRegistryChrome::ProviderEntry* +nsChromeRegistryChrome::nsProviderArray::GetProvider(const nsACString& aPreferred, MatchType aType) +{ + PRInt32 i = mArray.Count(); + if (!i) + return nsnull; + + ProviderEntry* found = nsnull; // Only set if we find a partial-match locale + ProviderEntry* entry; + + while (i--) { + entry = reinterpret_cast<ProviderEntry*>(mArray[i]); + if (aPreferred.Equals(entry->provider)) + return entry; + + if (aType != LOCALE) + continue; + + if (LanguagesMatch(aPreferred, entry->provider)) { + found = entry; + continue; + } + + if (!found && entry->provider.EqualsLiteral("en-US")) + found = entry; + } + + if (!found && aType != EXACT) + return entry; + + return found; +} + +nsIURI* +nsChromeRegistryChrome::nsProviderArray::GetBase(const nsACString& aPreferred, MatchType aType) +{ + ProviderEntry* provider = GetProvider(aPreferred, aType); + + if (!provider) + return nsnull; + + return provider->baseURI; +} + +const nsACString& +nsChromeRegistryChrome::nsProviderArray::GetSelected(const nsACString& aPreferred, MatchType aType) +{ + ProviderEntry* entry = GetProvider(aPreferred, aType); + + if (entry) + return entry->provider; + + return EmptyCString(); +} + +void +nsChromeRegistryChrome::nsProviderArray::SetBase(const nsACString& aProvider, nsIURI* aBaseURL) +{ + ProviderEntry* provider = GetProvider(aProvider, EXACT); + + if (provider) { + provider->baseURI = aBaseURL; + return; + } + + // no existing entries, add a new one + provider = new ProviderEntry(aProvider, aBaseURL); + if (!provider) + return; // It's safe to silently fail on OOM + + mArray.AppendElement(provider); +} + +void +nsChromeRegistryChrome::nsProviderArray::EnumerateToArray(nsTArray<nsCString> *a) +{ + PRInt32 i = mArray.Count(); + while (i--) { + ProviderEntry *entry = reinterpret_cast<ProviderEntry*>(mArray[i]); + a->AppendElement(entry->provider); + } +} + +void +nsChromeRegistryChrome::nsProviderArray::Clear() +{ + PRInt32 i = mArray.Count(); + while (i--) { + ProviderEntry* entry = reinterpret_cast<ProviderEntry*>(mArray[i]); + delete entry; + } + + mArray.Clear(); +} + +void +nsChromeRegistryChrome::OverlayListEntry::AddURI(nsIURI* aURI) +{ + PRInt32 i = mArray.Count(); + while (i--) { + PRBool equals; + if (NS_SUCCEEDED(aURI->Equals(mArray[i], &equals)) && equals) + return; + } + + mArray.AppendObject(aURI); +} + +void +nsChromeRegistryChrome::OverlayListHash::Add(nsIURI* aBase, nsIURI* aOverlay) +{ + OverlayListEntry* entry = mTable.PutEntry(aBase); + if (entry) + entry->AddURI(aOverlay); +} + +const nsCOMArray<nsIURI>* +nsChromeRegistryChrome::OverlayListHash::GetArray(nsIURI* aBase) +{ + OverlayListEntry* entry = mTable.GetEntry(aBase); + if (!entry) + return nsnull; + + return &entry->mArray; +} + +#ifdef MOZ_XUL +NS_IMETHODIMP +nsChromeRegistryChrome::GetStyleOverlays(nsIURI *aChromeURL, + nsISimpleEnumerator **aResult) +{ + const nsCOMArray<nsIURI>* parray = mStyleHash.GetArray(aChromeURL); + if (!parray) + return NS_NewEmptyEnumerator(aResult); + + return NS_NewArrayEnumerator(aResult, *parray); +} + +NS_IMETHODIMP +nsChromeRegistryChrome::GetXULOverlays(nsIURI *aChromeURL, + nsISimpleEnumerator **aResult) +{ + const nsCOMArray<nsIURI>* parray = mOverlayHash.GetArray(aChromeURL); + if (!parray) + return NS_NewEmptyEnumerator(aResult); + + return NS_NewArrayEnumerator(aResult, *parray); +} +#endif // MOZ_XUL + +nsIURI* +nsChromeRegistry::ManifestProcessingContext::GetManifestURI() +{ + if (!mManifestURI) { + nsCOMPtr<nsIIOService> io = mozilla::services::GetIOService(); + if (!io) { + NS_WARNING("No IO service trying to process chrome manifests"); + return NULL; + } + + io->NewFileURI(mFile, getter_AddRefs(mManifestURI)); + } + return mManifestURI; +} + +nsIXPConnect* +nsChromeRegistry::ManifestProcessingContext::GetXPConnect() +{ + if (!mXPConnect) + mXPConnect = do_GetService("@mozilla.org/js/xpc/XPConnect;1"); + + return mXPConnect; +} + +already_AddRefed<nsIURI> +nsChromeRegistry::ManifestProcessingContext::ResolveURI(const char* uri) +{ + nsIURI* baseuri = GetManifestURI(); + if (!baseuri) + return NULL; + + nsCOMPtr<nsIURI> resolved; + nsresult rv = NS_NewURI(getter_AddRefs(resolved), uri, baseuri); + if (NS_FAILED(rv)) + return NULL; + + return resolved.forget(); +} + +static void +EnsureLowerCase(char *aBuf) +{ + for (; *aBuf; ++aBuf) { + char ch = *aBuf; + if (ch >= 'A' && ch <= 'Z') + *aBuf = ch + 'a' - 'A'; + } +} + +void +nsChromeRegistryChrome::ManifestContent(ManifestProcessingContext& cx, int lineno, + char *const * argv, bool platform, + bool contentaccessible) +{ + char* package = argv[0]; + char* uri = argv[1]; + + EnsureLowerCase(package); + + nsCOMPtr<nsIURI> resolved = cx.ResolveURI(uri); + if (!resolved) { + LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, + "During chrome registration, unable to create URI '%s'.", uri); + return; + } + + if (!CanLoadResource(resolved)) { + LogMessageWithContext(resolved, lineno, nsIScriptError::warningFlag, + "During chrome registration, cannot register non-local URI '%s' as content.", + uri); + return; + } + + PackageEntry* entry = + static_cast<PackageEntry*>(PL_DHashTableOperate(&mPackagesHash, + & (const nsACString&) nsDependentCString(package), + PL_DHASH_ADD)); + if (!entry) + return; + + entry->baseURI = resolved; + + if (platform) + entry->flags |= PLATFORM_PACKAGE; + if (contentaccessible) + entry->flags |= CONTENT_ACCESSIBLE; + if (cx.GetXPConnect()) { + nsCAutoString urlp("chrome://"); + urlp.Append(package); + urlp.Append('/'); + + cx.GetXPConnect()->FlagSystemFilenamePrefix(urlp.get(), true); + } +} + +void +nsChromeRegistryChrome::ManifestLocale(ManifestProcessingContext& cx, int lineno, + char *const * argv, bool platform, + bool contentaccessible) +{ + char* package = argv[0]; + char* provider = argv[1]; + char* uri = argv[2]; + + EnsureLowerCase(package); + + nsCOMPtr<nsIURI> resolved = cx.ResolveURI(uri); + if (!resolved) { + LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, + "During chrome registration, unable to create URI '%s'.", uri); + return; + } + + if (!CanLoadResource(resolved)) { + LogMessageWithContext(resolved, lineno, nsIScriptError::warningFlag, + "During chrome registration, cannot register non-local URI '%s' as content.", + uri); + return; + } + + PackageEntry* entry = + static_cast<PackageEntry*>(PL_DHashTableOperate(&mPackagesHash, + & (const nsACString&) nsDependentCString(package), + PL_DHASH_ADD)); + if (!entry) + return; + + entry->locales.SetBase(nsDependentCString(provider), resolved); +} + +void +nsChromeRegistryChrome::ManifestSkin(ManifestProcessingContext& cx, int lineno, + char *const * argv, bool platform, + bool contentaccessible) +{ + char* package = argv[0]; + char* provider = argv[1]; + char* uri = argv[2]; + + EnsureLowerCase(package); + + nsCOMPtr<nsIURI> resolved = cx.ResolveURI(uri); + if (!resolved) { + LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, + "During chrome registration, unable to create URI '%s'.", uri); + return; + } + + if (!CanLoadResource(resolved)) { + LogMessageWithContext(resolved, lineno, nsIScriptError::warningFlag, + "During chrome registration, cannot register non-local URI '%s' as content.", + uri); + return; + } + + PackageEntry* entry = + static_cast<PackageEntry*>(PL_DHashTableOperate(&mPackagesHash, + & (const nsACString&) nsDependentCString(package), + PL_DHASH_ADD)); + if (!entry) + return; + + entry->skins.SetBase(nsDependentCString(provider), resolved); +} + +void +nsChromeRegistryChrome::ManifestOverlay(ManifestProcessingContext& cx, int lineno, + char *const * argv, bool platform, + bool contentaccessible) +{ + char* base = argv[0]; + char* overlay = argv[1]; + + nsCOMPtr<nsIURI> baseuri = cx.ResolveURI(base); + nsCOMPtr<nsIURI> overlayuri = cx.ResolveURI(overlay); + if (!baseuri || !overlayuri) { + LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, + "During chrome registration, unable to create URI."); + return; + } + + if (!CanLoadResource(overlayuri)) { + LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, + "Cannot register non-local URI '%s' as an overlay.", overlay); + return; + } + + mOverlayHash.Add(baseuri, overlayuri); +} + +void +nsChromeRegistryChrome::ManifestStyle(ManifestProcessingContext& cx, int lineno, + char *const * argv, bool platform, + bool contentaccessible) +{ + char* base = argv[0]; + char* overlay = argv[1]; + + nsCOMPtr<nsIURI> baseuri = cx.ResolveURI(base); + nsCOMPtr<nsIURI> overlayuri = cx.ResolveURI(overlay); + if (!baseuri || !overlayuri) { + LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, + "During chrome registration, unable to create URI."); + return; + } + + if (!CanLoadResource(overlayuri)) { + LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, + "Cannot register non-local URI '%s' as a style overlay.", overlay); + return; + } + + mStyleHash.Add(baseuri, overlayuri); +} + +void +nsChromeRegistryChrome::ManifestOverride(ManifestProcessingContext& cx, int lineno, + char *const * argv, bool platform, + bool contentaccessible) +{ + char* chrome = argv[0]; + char* resolved = argv[1]; + + nsCOMPtr<nsIURI> chromeuri = cx.ResolveURI(chrome); + nsCOMPtr<nsIURI> resolveduri = cx.ResolveURI(resolved); + if (!chromeuri || !resolveduri) { + LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, + "During chrome registration, unable to create URI."); + return; + } + + if (!CanLoadResource(resolveduri)) { + LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, + "Cannot register non-local URI '%s' for an override.", resolved); + return; + } + mOverrideTable.Put(chromeuri, resolveduri); +} + +void +nsChromeRegistryChrome::ManifestResource(ManifestProcessingContext& cx, int lineno, + char *const * argv, bool platform, + bool contentaccessible) +{ + char* package = argv[0]; + char* uri = argv[1]; + + EnsureLowerCase(package); + nsDependentCString host(package); + + nsCOMPtr<nsIIOService> io = mozilla::services::GetIOService(); + if (!io) { + NS_WARNING("No IO service trying to process chrome manifests"); + return; + } + + nsCOMPtr<nsIProtocolHandler> ph; + nsresult rv = io->GetProtocolHandler("resource", getter_AddRefs(ph)); + if (NS_FAILED(rv)) + return; + + nsCOMPtr<nsIResProtocolHandler> rph = do_QueryInterface(ph); + + PRBool exists = PR_FALSE; + rv = rph->HasSubstitution(host, &exists); + if (exists) { + LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, + "Duplicate resource declaration for '%s' ignored.", package); + return; + } + + nsCOMPtr<nsIURI> resolved = cx.ResolveURI(uri); + if (!resolved) { + LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, + "During chrome registration, unable to create URI '%s'.", uri); + return; + } + + if (!CanLoadResource(resolved)) { + LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, + "Warning: cannot register non-local URI '%s' as a resource.", + uri); + return; + } + + rph->SetSubstitution(host, resolved); +}
new file mode 100644 --- /dev/null +++ b/chrome/src/nsChromeRegistryChrome.h @@ -0,0 +1,223 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Josh Matthews <josh@joshmatthews.net> (Initial Developer) + * + * 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 ***** */ + +#ifndef nsChromeRegistryChrome_h +#define nsChromeRegistryChrome_h + +#include "nsChromeRegistry.h" + +namespace mozilla { +namespace dom { +class PContentProcessParent; +} +} + +class nsIPrefBranch; + +class nsChromeRegistryChrome : public nsChromeRegistry +{ + public: + nsChromeRegistryChrome(); + ~nsChromeRegistryChrome(); + + NS_OVERRIDE nsresult Init(); + + NS_OVERRIDE NS_IMETHOD CheckForNewChrome(); + NS_OVERRIDE NS_IMETHOD CheckForOSAccessibility(); + NS_OVERRIDE NS_IMETHOD GetLocalesForPackage(const nsACString& aPackage, + nsIUTF8StringEnumerator* *aResult); + NS_OVERRIDE NS_IMETHOD IsLocaleRTL(const nsACString& package, + PRBool *aResult); + NS_OVERRIDE NS_IMETHOD GetSelectedLocale(const nsACString& aPackage, + nsACString& aLocale); + NS_OVERRIDE NS_IMETHOD Observe(nsISupports *aSubject, const char *aTopic, + const PRUnichar *someData); + +#ifdef MOZ_XUL + NS_OVERRIDE NS_IMETHOD GetXULOverlays(nsIURI *aURI, + nsISimpleEnumerator **_retval); + NS_OVERRIDE NS_IMETHOD GetStyleOverlays(nsIURI *aURI, + nsISimpleEnumerator **_retval); +#endif + +#ifdef MOZ_IPC + void SendRegisteredChrome(mozilla::dom::PContentProcessParent* aChild); +#endif + + private: +#ifdef MOZ_IPC + static PLDHashOperator CollectPackages(PLDHashTable *table, + PLDHashEntryHdr *entry, + PRUint32 number, void *arg); +#endif + + nsresult SelectLocaleFromPref(nsIPrefBranch* prefs); + NS_OVERRIDE nsresult GetBaseURIFromPackage(const nsCString& aPackage, + const nsCString& aProvider, + const nsCString& aPath, + nsIURI* *aResult); + NS_OVERRIDE nsresult GetFlagsFromPackage(const nsCString& aPackage, + PRUint32* aFlags); + + static const PLDHashTableOps kTableOps; + static PLDHashNumber HashKey(PLDHashTable *table, const void *key); + static PRBool MatchKey(PLDHashTable *table, const PLDHashEntryHdr *entry, + const void *key); + static void ClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry); + static PRBool InitEntry(PLDHashTable *table, PLDHashEntryHdr *entry, + const void *key); + + struct ProviderEntry + { + ProviderEntry(const nsACString& aProvider, nsIURI* aBase) : + provider(aProvider), + baseURI(aBase) { } + + nsCString provider; + nsCOMPtr<nsIURI> baseURI; + }; + + class nsProviderArray + { + public: + nsProviderArray() : + mArray(1) { } + ~nsProviderArray() + { Clear(); } + + // When looking up locales and skins, the "selected" locale is not always + // available. This enum identifies what kind of match is desired/found. + enum MatchType { + EXACT = 0, + LOCALE = 1, // "en-GB" is selected, we found "en-US" + ANY = 2 + }; + + nsIURI* GetBase(const nsACString& aPreferred, MatchType aType); + const nsACString& GetSelected(const nsACString& aPreferred, MatchType aType); + void SetBase(const nsACString& aProvider, nsIURI* base); + void EnumerateToArray(nsTArray<nsCString> *a); + void Clear(); + + private: + ProviderEntry* GetProvider(const nsACString& aPreferred, MatchType aType); + + nsVoidArray mArray; + }; + + struct PackageEntry : public PLDHashEntryHdr + { + PackageEntry(const nsACString& package) + : package(package), flags(0) { } + ~PackageEntry() { } + + nsCString package; + nsCOMPtr<nsIURI> baseURI; + PRUint32 flags; + nsProviderArray locales; + nsProviderArray skins; + }; + + class OverlayListEntry : public nsURIHashKey + { + public: + typedef nsURIHashKey::KeyType KeyType; + typedef nsURIHashKey::KeyTypePointer KeyTypePointer; + + OverlayListEntry(KeyTypePointer aKey) : nsURIHashKey(aKey) { } + OverlayListEntry(OverlayListEntry& toCopy) : nsURIHashKey(toCopy), + mArray(toCopy.mArray) { } + ~OverlayListEntry() { } + + void AddURI(nsIURI* aURI); + + nsCOMArray<nsIURI> mArray; + }; + + class OverlayListHash + { + public: + OverlayListHash() { } + ~OverlayListHash() { } + + PRBool Init() { return mTable.Init(); } + void Add(nsIURI* aBase, nsIURI* aOverlay); + void Clear() { mTable.Clear(); } + const nsCOMArray<nsIURI>* GetArray(nsIURI* aBase); + + private: + nsTHashtable<OverlayListEntry> mTable; + }; + + // Hashes on the file to be overlaid (chrome://browser/content/browser.xul) + // to a list of overlays/stylesheets + OverlayListHash mOverlayHash; + OverlayListHash mStyleHash; + + PRBool mProfileLoaded; + + nsCString mSelectedLocale; + nsCString mSelectedSkin; + + // Hash of package names ("global") to PackageEntry objects + PLDHashTable mPackagesHash; + + virtual void ManifestContent(ManifestProcessingContext& cx, int lineno, + char *const * argv, bool platform, + bool contentaccessible); + virtual void ManifestLocale(ManifestProcessingContext& cx, int lineno, + char *const * argv, bool platform, + bool contentaccessible); + virtual void ManifestSkin(ManifestProcessingContext& cx, int lineno, + char *const * argv, bool platform, + bool contentaccessible); + virtual void ManifestOverlay(ManifestProcessingContext& cx, int lineno, + char *const * argv, bool platform, + bool contentaccessible); + virtual void ManifestStyle(ManifestProcessingContext& cx, int lineno, + char *const * argv, bool platform, + bool contentaccessible); + virtual void ManifestOverride(ManifestProcessingContext& cx, int lineno, + char *const * argv, bool platform, + bool contentaccessible); + virtual void ManifestResource(ManifestProcessingContext& cx, int lineno, + char *const * argv, bool platform, + bool contentaccessible); +}; + +#endif // nsChromeRegistryChrome_h
new file mode 100644 --- /dev/null +++ b/chrome/src/nsChromeRegistryContent.cpp @@ -0,0 +1,331 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Josh Matthews <josh@joshmatthews.net> (Initial Developer) + * + * 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 "RegistryMessageUtils.h" +#include "nsChromeRegistry.h" +#include "nsChromeRegistryContent.h" +#include "nsString.h" +#include "nsNetUtil.h" +#include "nsResProtocolHandler.h" + +nsChromeRegistryContent::nsChromeRegistryContent() +{ + mPackagesHash.Init(); +} + +void +nsChromeRegistryContent::RegisterRemoteChrome( + const nsTArray<ChromePackage>& aPackages, + const nsTArray<ResourceMapping>& aResources, + const nsTArray<OverrideMapping>& aOverrides) +{ + for (PRUint32 i = aPackages.Length(); i > 0; ) { + --i; + RegisterPackage(aPackages[i]); + } + + for (PRUint32 i = aResources.Length(); i > 0; ) { + --i; + RegisterResource(aResources[i]); + } + + for (PRUint32 i = aOverrides.Length(); i > 0; ) { + --i; + RegisterOverride(aOverrides[i]); + } +} + +void +nsChromeRegistryContent::RegisterPackage(const ChromePackage& aPackage) +{ + nsCOMPtr<nsIIOService> io (do_GetIOService()); + if (!io) + return; + + nsCOMPtr<nsIURI> content, locale, skin; + + if (aPackage.contentBaseURI.spec.Length()) { + nsresult rv = NS_NewURI(getter_AddRefs(content), + aPackage.contentBaseURI.spec, + aPackage.contentBaseURI.charset.get(), + nsnull, io); + if (NS_FAILED(rv)) + return; + } + if (aPackage.localeBaseURI.spec.Length()) { + nsresult rv = NS_NewURI(getter_AddRefs(locale), + aPackage.localeBaseURI.spec, + aPackage.localeBaseURI.charset.get(), + nsnull, io); + if (NS_FAILED(rv)) + return; + } + if (aPackage.skinBaseURI.spec.Length()) { + nsCOMPtr<nsIURI> skinBaseURI; + nsresult rv = NS_NewURI(getter_AddRefs(skin), + aPackage.skinBaseURI.spec, + aPackage.skinBaseURI.charset.get(), + nsnull, io); + if (NS_FAILED(rv)) + return; + } + + PackageEntry* entry = new PackageEntry; + entry->flags = aPackage.flags; + entry->contentBaseURI = content; + entry->localeBaseURI = locale; + entry->skinBaseURI = skin; + + nsresult rv = mPackagesHash.Put(aPackage.package, entry); + if (NS_FAILED(rv)) + return; +} + +void +nsChromeRegistryContent::RegisterResource(const ResourceMapping& aResource) +{ + nsCOMPtr<nsIIOService> io (do_GetIOService()); + if (!io) + return; + + nsCOMPtr<nsIProtocolHandler> ph; + nsresult rv = io->GetProtocolHandler("resource", getter_AddRefs(ph)); + if (NS_FAILED(rv)) + return; + + nsCOMPtr<nsIResProtocolHandler> rph (do_QueryInterface(ph)); + if (!rph) + return; + + nsCOMPtr<nsIURI> resolvedURI; + if (aResource.resolvedURI.spec.Length()) { + nsresult rv = NS_NewURI(getter_AddRefs(resolvedURI), + aResource.resolvedURI.spec, + aResource.resolvedURI.charset.get(), + nsnull, io); + if (NS_FAILED(rv)) + return; + } + + rv = rph->SetSubstitution(aResource.resource, resolvedURI); + if (NS_FAILED(rv)) + return; +} + +void +nsChromeRegistryContent::RegisterOverride(const OverrideMapping& aOverride) +{ + nsCOMPtr<nsIIOService> io (do_GetIOService()); + if (!io) + return; + + nsCOMPtr<nsIURI> chromeURI, overrideURI; + nsresult rv = NS_NewURI(getter_AddRefs(chromeURI), + aOverride.originalURI.spec, + aOverride.originalURI.charset.get(), + nsnull, io); + if (NS_FAILED(rv)) + return; + + rv = NS_NewURI(getter_AddRefs(overrideURI), aOverride.overrideURI.spec, + aOverride.overrideURI.charset.get(), nsnull, io); + if (NS_FAILED(rv)) + return; + + mOverrideTable.Put(chromeURI, overrideURI); +} + +nsresult +nsChromeRegistryContent::GetBaseURIFromPackage(const nsCString& aPackage, + const nsCString& aProvider, + const nsCString& aPath, + nsIURI* *aResult) +{ + PackageEntry* entry; + if (!mPackagesHash.Get(aPackage, &entry)) { + return NS_ERROR_FAILURE; + } + + *aResult = nsnull; + if (aProvider.EqualsLiteral("locale")) { + *aResult = entry->localeBaseURI; + } + else if (aProvider.EqualsLiteral("skin")) { + *aResult = entry->skinBaseURI; + } + else if (aProvider.EqualsLiteral("content")) { + *aResult = entry->contentBaseURI; + } + return NS_OK; +} + +nsresult +nsChromeRegistryContent::GetFlagsFromPackage(const nsCString& aPackage, + PRUint32* aFlags) +{ + PackageEntry* entry; + if (!mPackagesHash.Get(aPackage, &entry)) { + return NS_ERROR_FAILURE; + } + *aFlags = entry->flags; + return NS_OK; +} + +// All functions following only make sense in chrome, and therefore assert + +#define CONTENT_NOTREACHED() \ + NS_NOTREACHED("Content should not be calling this") + +#define CONTENT_NOT_IMPLEMENTED() \ + CONTENT_NOTREACHED(); \ + return NS_ERROR_NOT_IMPLEMENTED; + +NS_IMETHODIMP +nsChromeRegistryContent::GetLocalesForPackage(const nsACString& aPackage, + nsIUTF8StringEnumerator* *aResult) +{ + CONTENT_NOT_IMPLEMENTED(); +} + +NS_IMETHODIMP +nsChromeRegistryContent::CheckForOSAccessibility() +{ + CONTENT_NOT_IMPLEMENTED(); +} + +NS_IMETHODIMP +nsChromeRegistryContent::CheckForNewChrome() +{ + CONTENT_NOT_IMPLEMENTED(); +} + +NS_IMETHODIMP +nsChromeRegistryContent::IsLocaleRTL(const nsACString& package, + PRBool *aResult) +{ + CONTENT_NOT_IMPLEMENTED(); +} + +NS_IMETHODIMP +nsChromeRegistryContent::GetSelectedLocale(const nsACString& aPackage, + nsACString& aLocale) +{ + CONTENT_NOT_IMPLEMENTED(); +} + +NS_IMETHODIMP +nsChromeRegistryContent::Observe(nsISupports* aSubject, const char* aTopic, + const PRUnichar* aData) +{ + CONTENT_NOT_IMPLEMENTED(); +} + +NS_IMETHODIMP +nsChromeRegistryContent::GetStyleOverlays(nsIURI *aChromeURL, + nsISimpleEnumerator **aResult) +{ + CONTENT_NOT_IMPLEMENTED(); +} + +NS_IMETHODIMP +nsChromeRegistryContent::GetXULOverlays(nsIURI *aChromeURL, + nsISimpleEnumerator **aResult) +{ + CONTENT_NOT_IMPLEMENTED(); +} + +void +nsChromeRegistryContent::ManifestContent(ManifestProcessingContext& cx, + int lineno, char *const * argv, + bool platform, bool contentaccessible) +{ + CONTENT_NOTREACHED(); +} + +void +nsChromeRegistryContent::ManifestLocale(ManifestProcessingContext& cx, + int lineno, + char *const * argv, bool platform, + bool contentaccessible) +{ + CONTENT_NOTREACHED(); +} + +void +nsChromeRegistryContent::ManifestSkin(ManifestProcessingContext& cx, + int lineno, + char *const * argv, bool platform, + bool contentaccessible) +{ + CONTENT_NOTREACHED(); +} + +void +nsChromeRegistryContent::ManifestOverlay(ManifestProcessingContext& cx, int lineno, + char *const * argv, bool platform, + bool contentaccessible) +{ + CONTENT_NOTREACHED(); +} + +void +nsChromeRegistryContent::ManifestStyle(ManifestProcessingContext& cx, + int lineno, + char *const * argv, bool platform, + bool contentaccessible) +{ + CONTENT_NOTREACHED(); +} + +void +nsChromeRegistryContent::ManifestOverride(ManifestProcessingContext& cx, + int lineno, + char *const * argv, bool platform, + bool contentaccessible) +{ + CONTENT_NOTREACHED(); +} + +void +nsChromeRegistryContent::ManifestResource(ManifestProcessingContext& cx, + int lineno, + char *const * argv, bool platform, + bool contentaccessible) +{ + CONTENT_NOTREACHED(); +}
new file mode 100644 --- /dev/null +++ b/chrome/src/nsChromeRegistryContent.h @@ -0,0 +1,122 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Josh Matthews <josh@joshmatthews.net> (Initial Developer) + * + * 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 ***** */ + +#ifndef nsChromeRegistryContent_h +#define nsChromeRegistryContent_h + +#include "nsChromeRegistry.h" +#include "nsTArray.h" +#include "nsClassHashtable.h" + +class nsCString; +struct ChromePackage; +struct ResourceMapping; +struct OverrideMapping; + +class nsChromeRegistryContent : public nsChromeRegistry +{ + public: + nsChromeRegistryContent(); + + void RegisterRemoteChrome(const nsTArray<ChromePackage>& aPackages, + const nsTArray<ResourceMapping>& aResources, + const nsTArray<OverrideMapping>& aOverrides); + + NS_OVERRIDE NS_IMETHOD GetLocalesForPackage(const nsACString& aPackage, + nsIUTF8StringEnumerator* *aResult); + NS_OVERRIDE NS_IMETHOD CheckForNewChrome(); + NS_OVERRIDE NS_IMETHOD CheckForOSAccessibility(); + NS_OVERRIDE NS_IMETHOD Observe(nsISupports* aSubject, const char* aTopic, + const PRUnichar* aData); + NS_OVERRIDE NS_IMETHOD IsLocaleRTL(const nsACString& package, + PRBool *aResult); + NS_OVERRIDE NS_IMETHOD GetSelectedLocale(const nsACString& aPackage, + nsACString& aLocale); + NS_OVERRIDE NS_IMETHOD GetStyleOverlays(nsIURI *aChromeURL, + nsISimpleEnumerator **aResult); + NS_OVERRIDE NS_IMETHOD GetXULOverlays(nsIURI *aChromeURL, + nsISimpleEnumerator **aResult); + + private: + struct PackageEntry + { + PackageEntry() : flags(0) { } + ~PackageEntry() { } + + nsCOMPtr<nsIURI> contentBaseURI; + nsCOMPtr<nsIURI> localeBaseURI; + nsCOMPtr<nsIURI> skinBaseURI; + PRUint32 flags; + }; + + void RegisterPackage(const ChromePackage& aPackage); + void RegisterResource(const ResourceMapping& aResource); + void RegisterOverride(const OverrideMapping& aOverride); + + NS_OVERRIDE nsresult GetBaseURIFromPackage(const nsCString& aPackage, + const nsCString& aProvider, + const nsCString& aPath, + nsIURI* *aResult); + NS_OVERRIDE nsresult GetFlagsFromPackage(const nsCString& aPackage, PRUint32* aFlags); + + nsClassHashtable<nsCStringHashKey, PackageEntry> mPackagesHash; + + virtual void ManifestContent(ManifestProcessingContext& cx, int lineno, + char *const * argv, bool platform, + bool contentaccessible); + virtual void ManifestLocale(ManifestProcessingContext& cx, int lineno, + char *const * argv, bool platform, + bool contentaccessible); + virtual void ManifestSkin(ManifestProcessingContext& cx, int lineno, + char *const * argv, bool platform, + bool contentaccessible); + virtual void ManifestOverlay(ManifestProcessingContext& cx, int lineno, + char *const * argv, bool platform, + bool contentaccessible); + virtual void ManifestStyle(ManifestProcessingContext& cx, int lineno, + char *const * argv, bool platform, + bool contentaccessible); + virtual void ManifestOverride(ManifestProcessingContext& cx, int lineno, + char *const * argv, bool platform, + bool contentaccessible); + virtual void ManifestResource(ManifestProcessingContext& cx, int lineno, + char *const * argv, bool platform, + bool contentaccessible); +}; + +#endif // nsChromeRegistryContent_h
--- a/chrome/test/Makefile.in +++ b/chrome/test/Makefile.in @@ -41,10 +41,16 @@ srcdir = @srcdir@ VPATH = @srcdir@ include $(DEPTH)/config/autoconf.mk MODULE = test_chrome XPCSHELL_TESTS = unit \ $(NULL) +ifdef MOZ_IPC +# FIXME/bug 575918: out-of-process xpcshell is broken on OS X +ifneq ($(OS_ARCH),Darwin) +XPCSHELL_TESTS += unit_ipc +endif +endif include $(topsrcdir)/config/rules.mk
new file mode 100644 --- /dev/null +++ b/chrome/test/unit/data/test_resolve_uris.manifest @@ -0,0 +1,5 @@ +resource foo resource://foo/foo-resource/ +content foo resource://foo/foo-content/ +locale foo foo resource://foo/foo-locale/ +skin foo foo resource://foo/foo-skin/ +override chrome://good-package/content/override-me.xul resource://foo/foo-override/override-me.xul
new file mode 100644 --- /dev/null +++ b/chrome/test/unit/test_resolve_uris.js @@ -0,0 +1,122 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Chrome Registration Test Code. + * + * The Initial Developer of the Original Code is + * Mozilla Corporation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Josh Matthews <josh@joshmatthews.net> (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 ***** */ + +// head_crtestutils.js doesn't get included in the child by default +if (typeof registerManifests === "undefined") { + load("../unit/head_crtestutils.js"); +} + +let manifests = [ + do_get_file("../unit/data/test_resolve_uris.manifest"), +]; +registerManifests(manifests); + +function do_run_test() +{ + let cr = Cc["@mozilla.org/chrome/chrome-registry;1"]. + getService(Ci.nsIChromeRegistry); + + var runtime = Components.classes["@mozilla.org/xre/app-info;1"] + .getService(Components.interfaces.nsIXULRuntime); + if (runtime.processType == + Components.interfaces.nsIXULRuntime.PROCESS_TYPE_DEFAULT) { + cr.checkForNewChrome(); + } + + // See if our various things were able to register + let registrationTypes = [ + "content", + "locale", + "skin", + "override", + "resource", + ]; + + for (let j = 0; j < registrationTypes.length; j++) { + let type = registrationTypes[j]; + dump("Testing type '" + type + "'\n"); + let expectedURI = "resource://foo/foo-" + type + "/"; + let sourceURI = "chrome://foo/" + type + "/"; + switch (type) { + case "content": + expectedURI += "foo.xul"; + break; + case "locale": + expectedURI += "foo.dtd"; + break; + case "skin": + expectedURI += "foo.css"; + break; + case "override": + sourceURI = "chrome://good-package/content/override-me.xul"; + expectedURI += "override-me.xul"; + break; + case "resource": + sourceURI = "resource://foo/"; + break; + }; + try { + let ios = Cc["@mozilla.org/network/io-service;1"]. + getService(Ci.nsIIOService); + sourceURI = ios.newURI(sourceURI, null, null); + let uri; + if (type == "resource") { + // resources go about a slightly different way than everything else + let rph = ios.getProtocolHandler("resource"). + QueryInterface(Ci.nsIResProtocolHandler); + uri = rph.resolveURI(sourceURI); + } + else { + uri = cr.convertChromeURL(sourceURI).spec; + } + + do_check_eq(expectedURI, uri); + } + catch (e) { + dump(e + "\n"); + do_throw("Should have registered a handler for type '" + + type + "'\n"); + } + } +} + +if (typeof run_test === "undefined") { + run_test = function() { + do_run_test(); + }; +}
new file mode 100644 --- /dev/null +++ b/chrome/test/unit_ipc/test_resolve_uris_ipc.js @@ -0,0 +1,9 @@ +// +// Run test script in content process instead of chrome (xpcshell's default) +// + +function run_test() { + load("../unit/test_resolve_uris.js"); + do_run_test(); + run_test_in_child("../unit/test_resolve_uris.js"); +}
--- a/configure.in +++ b/configure.in @@ -4980,17 +4980,16 @@ esac case "${target}" in arm-android-eabi) NSS_DISABLE_DBM=1 USE_ARM_KUSER=1 MOZ_INSTALLER= MOZ_CRASHREPORTER= NS_PRINTING= NECKO_WIFI= - MOZ_PLUGINS= MOZ_THUMB2=1 MOZ_THEME_FASTSTRIPE=1 MOZ_TREE_FREETYPE=1 MOZ_MEMORY=1 ;; esac MOZ_ARG_ENABLE_STRING(application, @@ -5695,17 +5694,17 @@ MOZ_ARG_DISABLE_BOOL(jsd, MOZ_JSDEBUGGER=, MOZ_JSDEBUGGER=1) dnl ======================================================== dnl = Disable IPC support for tabs and plugins dnl ======================================================== case "${target}" in -*-wince*|*-android*) +*-wince*) MOZ_IPC= ;; esac MOZ_ARG_DISABLE_BOOL(ipc, [ --disable-ipc Disable IPC supports for tabs and plugins], MOZ_IPC=, MOZ_IPC=1)
--- a/content/base/public/nsIFrameLoader.idl +++ b/content/base/public/nsIFrameLoader.idl @@ -36,27 +36,35 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "nsISupports.idl" interface nsIDocShell; interface nsIURI; +interface nsIWebProgress; +interface nsIFrame; interface nsIChromeFrameMessageManager; +interface nsIVariant; -[scriptable, uuid(3b256c12-20e1-4fd3-8edb-b9c793919f15)] +[scriptable, uuid(65d2c9e2-852c-48cf-a95d-9b82f1273c15)] interface nsIFrameLoader : nsISupports { /** * Get the docshell from the frame loader. */ readonly attribute nsIDocShell docShell; /** + * Get the nsIWebProgress from the frame loader, allowing listener registration. + */ + readonly attribute nsIWebProgress webProgress; + + /** * Start loading the frame. This method figures out what to load * from the owner content in the frame loader. */ void loadFrame(); /** * Loads the specified URI in this frame. Behaves identically to loadFrame, * except that this method allows specifying the URI to load. @@ -71,23 +79,64 @@ interface nsIFrameLoader : nsISupports /** * Find out whether the loader's frame is at too great a depth in * the frame tree. This can be used to decide what operations may * or may not be allowed on the loader's docshell. */ readonly attribute boolean depthTooGreat; + /** + * Updates the position and size of the subdocument loaded by this frameloader. + * + * @param aIFrame The nsIFrame for the content node that owns this frameloader + */ + [noscript] void updatePositionAndSize(in nsIFrame aIFrame); + + /** + * Activate remote frame. + * Throws an exception with non-remote frames. + */ + void activateRemoteFrame(); + + /** + * @see nsIDOMWindowUtils sendMouseEvent. + */ + void sendCrossProcessMouseEvent(in AString aType, + in float aX, + in float aY, + in long aButton, + in long aClickCount, + in long aModifiers, + [optional] in boolean aIgnoreRootScrollFrame); + + /** + * Activate event forwarding from client (remote frame) to parent. + */ + void activateFrameEvent(in AString aType, in boolean capture); + // Note, when frameloaders are swapped, also messageManagers are swapped. readonly attribute nsIChromeFrameMessageManager messageManager; + + /** + * @see nsIDOMWindowUtils sendKeyEvent. + */ + void sendCrossProcessKeyEvent(in AString aType, + in long aKeyCode, + in long aCharCode, + in long aModifiers, + [optional] in boolean aPreventDefault); + + attribute boolean delayRemoteDialogs; + }; native alreadyAddRefed_nsFrameLoader(already_AddRefed<nsFrameLoader>); -[scriptable, uuid(8f3b12a0-35ae-4e0d-9152-8e0d7e49d446)] +[scriptable, uuid(5879040e-83e9-40e3-b2bb-5ddf43b76e47)] interface nsIFrameLoaderOwner : nsISupports { /** * The frame loader owned by this nsIFrameLoaderOwner */ readonly attribute nsIFrameLoader frameLoader; [noscript, notxpcom] alreadyAddRefed_nsFrameLoader GetFrameLoader();
--- a/content/base/public/nsIFrameMessageManager.idl +++ b/content/base/public/nsIFrameMessageManager.idl @@ -47,17 +47,17 @@ interface nsIFrameMessageListener : nsIS /** * This is for JS only. * receiveMessage is called with one parameter, which has the following * properties: * { * name: %message name%, * sync: %true or false%. * json: %json object or null%, - * objects: %array of cpow or null, always null if sync is false% + * objects: %array of handles or null, always null if sync is false% * } * @note objects property isn't implemented yet. * * if the message is synchronous, possible return value is sent back * as JSON. * * When the listener is called, 'this' value is the target of the message. */
--- a/content/base/src/Makefile.in +++ b/content/base/src/Makefile.in @@ -164,28 +164,33 @@ EXTRA_COMPONENTS = \ contentAreaDropListener.js \ contentAreaDropListener.manifest \ $(NULL) EXTRA_JS_MODULES = \ CSPUtils.jsm \ $(NULL) +include $(topsrcdir)/config/config.mk +include $(topsrcdir)/ipc/chromium/chromium-config.mk include $(topsrcdir)/config/rules.mk INCLUDES += \ -I$(srcdir)/../../events/src \ -I$(srcdir)/../../xml/content/src \ -I$(srcdir)/../../../layout/xul/base/src \ -I$(srcdir)/../../xul/content/src \ -I$(srcdir)/../../html/content/src \ -I$(srcdir)/../../base/src \ -I$(srcdir)/../../xbl/src \ -I$(srcdir)/../../../layout/generic \ -I$(srcdir)/../../../layout/style \ -I$(srcdir)/../../../dom/base \ -I$(srcdir)/../../xml/document/src \ -I$(topsrcdir)/xpcom/io \ + -I$(topsrcdir)/dom/ipc \ -I$(topsrcdir)/js/src/xpconnect/src \ -I$(topsrcdir)/caps/include \ $(NULL) +CXXFLAGS += $(TK_CFLAGS) + DEFINES += -D_IMPL_NS_LAYOUT
--- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -84,16 +84,17 @@ #include "nsGenericHTMLElement.h" #include "nsIDOMEventGroup.h" #include "nsIDOMCDATASection.h" #include "nsIDOMProcessingInstruction.h" #include "nsDOMString.h" #include "nsNodeUtils.h" #include "nsLayoutUtils.h" // for GetFrameForPoint #include "nsIFrame.h" +#include "nsITabChild.h" #include "nsRange.h" #include "nsIDOMText.h" #include "nsIDOMComment.h" #include "nsDOMDocumentType.h" #include "nsNodeIterator.h" #include "nsTreeWalker.h" @@ -1079,17 +1080,18 @@ IMPL_SHIM(nsIApplicationCacheContainer) } \ PR_END_MACRO NS_IMETHODIMP nsExternalResourceMap::LoadgroupCallbacks::GetInterface(const nsIID & aIID, void **aSink) { if (mCallbacks && - (IID_IS(nsIPrompt) || IID_IS(nsIAuthPrompt) || IID_IS(nsIAuthPrompt2))) { + (IID_IS(nsIPrompt) || IID_IS(nsIAuthPrompt) || IID_IS(nsIAuthPrompt2) || + IID_IS(nsITabChild))) { return mCallbacks->GetInterface(aIID, aSink); } *aSink = nsnull; TRY_SHIM(nsILoadContext); TRY_SHIM(nsIProgressEventSink); TRY_SHIM(nsIChannelEventSink);
--- a/content/base/src/nsFrameLoader.cpp +++ b/content/base/src/nsFrameLoader.cpp @@ -18,16 +18,17 @@ * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Johnny Stenback <jst@netscape.com> (original author) * Boris Zbarsky <bzbarsky@mit.edu> + * Frederic Plourde <frederic.plourde@polymtl.ca> * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your @@ -38,64 +39,100 @@ * * ***** END LICENSE BLOCK ***** */ /* * Class for managing loading of a subframe (creation of the docshell, * handling of loads in it, recursion-checking). */ +#ifdef MOZ_WIDGET_QT +#include <QtGui/QX11EmbedWidget> +#include <QGraphicsWidget> +#include <QGraphicsProxyWidget> +#endif + +#ifdef MOZ_IPC +# include "base/basictypes.h" +#endif + +#include "prenv.h" + #include "nsIDOMHTMLIFrameElement.h" #include "nsIDOMHTMLFrameElement.h" #include "nsIDOMWindow.h" #include "nsIPresShell.h" #include "nsIContent.h" #include "nsIContentViewer.h" #include "nsIDocument.h" #include "nsIDOMDocument.h" #include "nsIDOMWindow.h" #include "nsPIDOMWindow.h" #include "nsIWebNavigation.h" +#include "nsIWebProgress.h" #include "nsIDocShell.h" #include "nsIDocShellTreeItem.h" #include "nsIDocShellTreeNode.h" #include "nsIDocShellTreeOwner.h" #include "nsIDocShellLoadInfo.h" #include "nsIBaseWindow.h" #include "nsContentUtils.h" +#include "nsIXPConnect.h" +#include "nsIJSContextStack.h" #include "nsUnicharUtils.h" #include "nsIScriptGlobalObject.h" #include "nsIScriptSecurityManager.h" #include "nsIScrollable.h" #include "nsFrameLoader.h" #include "nsIDOMEventTarget.h" #include "nsIFrame.h" #include "nsIFrameFrame.h" #include "nsDOMError.h" #include "nsGUIEvent.h" #include "nsEventDispatcher.h" #include "nsISHistory.h" #include "nsISHistoryInternal.h" #include "nsIDOMNSHTMLDocument.h" + +#include "nsLayoutUtils.h" #include "nsIView.h" #include "nsPLDOMEvent.h" #include "nsIURI.h" #include "nsIURL.h" #include "nsNetUtil.h" #include "nsGkAtoms.h" #include "nsINameSpaceManager.h" #include "nsThreadUtils.h" #include "nsIContentViewer.h" +#include "nsIView.h" + #include "nsIDOMChromeWindow.h" #include "nsInProcessTabChildGlobal.h" #include "mozilla/AutoRestore.h" +#ifdef MOZ_WIDGET_GTK2 +#include "mozcontainer.h" + +#include <gdk/gdkx.h> +#include <gtk/gtk.h> +#endif + +#ifdef MOZ_IPC +#include "ContentProcessParent.h" +#include "TabParent.h" + +using namespace mozilla; +using namespace mozilla::dom; +#endif + +#include "jsapi.h" + class nsAsyncDocShellDestroyer : public nsRunnable { public: nsAsyncDocShellDestroyer(nsIDocShell* aDocShell) : mDocShell(aDocShell) { } @@ -252,21 +289,44 @@ nsFrameLoader::ReallyStartLoading() return rv; } nsresult nsFrameLoader::ReallyStartLoadingInternal() { NS_ENSURE_STATE(mURIToLoad && mOwnerContent && mOwnerContent->IsInDoc()); + + nsresult rv = MaybeCreateDocShell(); + if (NS_FAILED(rv)) { + return rv; + } + +#ifdef MOZ_IPC + if (mRemoteFrame) { + if (!mChildProcess) { + TryNewProcess(); + } + + if (!mChildProcess) { + NS_WARNING("Couldn't create child process for iframe."); + return NS_ERROR_FAILURE; + } + + // FIXME get error codes from child + mChildProcess->LoadURL(mURIToLoad); + return NS_OK; + } +#endif + + NS_ASSERTION(mDocShell, + "MaybeCreateDocShell succeeded with a null mDocShell"); + // Just to be safe, recheck uri. - nsresult rv = CheckURILoad(mURIToLoad); - NS_ENSURE_SUCCESS(rv, rv); - - rv = EnsureDocShell(); + rv = CheckURILoad(mURIToLoad); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIDocShellLoadInfo> loadInfo; mDocShell->CreateLoadInfo(getter_AddRefs(loadInfo)); NS_ENSURE_TRUE(loadInfo, NS_ERROR_FAILURE); // We'll use our principal, not that of the document loaded inside us. This // is very important; needed to prevent XSS attacks on documents loaded in @@ -317,38 +377,84 @@ nsFrameLoader::CheckURILoad(nsIURI* aURI nsresult rv = secMan->CheckLoadURIWithPrincipal(principal, aURI, nsIScriptSecurityManager::STANDARD); if (NS_FAILED(rv)) { return rv; // We're not } // Bail out if this is an infinite recursion scenario + rv = MaybeCreateDocShell(); + if (NS_FAILED(rv)) { + return rv; + } +#ifdef MOZ_IPC + if (mRemoteFrame) { + return NS_OK; + } +#endif return CheckForRecursiveLoad(aURI); } NS_IMETHODIMP nsFrameLoader::GetDocShell(nsIDocShell **aDocShell) { *aDocShell = nsnull; // If we have an owner, make sure we have a docshell and return // that. If not, we're most likely in the middle of being torn down, // then we just return null. if (mOwnerContent) { - nsresult rv = EnsureDocShell(); - NS_ENSURE_SUCCESS(rv, rv); + nsresult rv = MaybeCreateDocShell(); + if (NS_FAILED(rv)) + return rv; +#ifdef MOZ_IPC + if (mRemoteFrame) { + NS_WARNING("No docshells for remote frames!"); + return NS_ERROR_NOT_AVAILABLE; + } +#endif + NS_ASSERTION(mDocShell, + "MaybeCreateDocShell succeeded, but null mDocShell"); } *aDocShell = mDocShell; NS_IF_ADDREF(*aDocShell); return NS_OK; } +NS_IMETHODIMP +nsFrameLoader::GetWebProgress(nsIWebProgress **aWebProgress) +{ + nsresult rv; + *aWebProgress = nsnull; +#ifdef MOZ_IPC + if (mRemoteFrame) { + if (!mChildProcess) { + TryNewProcess(); + } + if (!mChildProcess) { + return NS_ERROR_UNEXPECTED; + } + *aWebProgress = mChildProcess; + NS_ADDREF(*aWebProgress); + return NS_OK; + } +#endif + + nsCOMPtr<nsIDocShell> shell; + rv = GetDocShell(getter_AddRefs(shell)); + if (NS_SUCCEEDED(rv)) { + nsCOMPtr<nsIWebProgress> progress(do_QueryInterface(shell)); + progress.swap(*aWebProgress); + } + return rv; +} + void nsFrameLoader::Finalize() { nsCOMPtr<nsIBaseWindow> base_win(do_QueryInterface(mDocShell)); if (base_win) { base_win->Destroy(); } mDocShell = nsnull; @@ -542,73 +648,87 @@ nsFrameLoader::Show(PRInt32 marginWidth, return PR_FALSE; } // Reset mInShow if we exit early. AutoResetInShow resetInShow(this); mInShow = PR_TRUE; nsContentType contentType; - nsresult rv = EnsureDocShell(); + nsresult rv = MaybeCreateDocShell(); if (NS_FAILED(rv)) { return PR_FALSE; } - if (!mDocShell) - return PR_FALSE; - - nsCOMPtr<nsIPresShell> presShell; - mDocShell->GetPresShell(getter_AddRefs(presShell)); - if (presShell) - return PR_TRUE; +#ifdef MOZ_IPC + if (mRemoteFrame) { + contentType = eContentTypeUI; + } + else +#endif + { + if (!mDocShell) + return false; + nsCOMPtr<nsIPresShell> presShell; + mDocShell->GetPresShell(getter_AddRefs(presShell)); + if (presShell) + return true; - mDocShell->SetMarginWidth(marginWidth); - mDocShell->SetMarginHeight(marginHeight); + mDocShell->SetMarginWidth(marginWidth); + mDocShell->SetMarginHeight(marginHeight); - nsCOMPtr<nsIScrollable> sc = do_QueryInterface(mDocShell); - if (sc) { - sc->SetDefaultScrollbarPreferences(nsIScrollable::ScrollOrientation_X, - scrollbarPrefX); - sc->SetDefaultScrollbarPreferences(nsIScrollable::ScrollOrientation_Y, - scrollbarPrefY); - } + nsCOMPtr<nsIScrollable> sc = do_QueryInterface(mDocShell); + if (sc) { + sc->SetDefaultScrollbarPreferences(nsIScrollable::ScrollOrientation_X, + scrollbarPrefX); + sc->SetDefaultScrollbarPreferences(nsIScrollable::ScrollOrientation_Y, + scrollbarPrefY); + } - nsCOMPtr<nsIDocShellTreeItem> treeItem = do_QueryInterface(mDocShell); - NS_ASSERTION(treeItem, - "Found a nsIDocShell that isn't a nsIDocShellTreeItem."); + nsCOMPtr<nsIDocShellTreeItem> treeItem = do_QueryInterface(mDocShell); + NS_ASSERTION(treeItem, + "Found a nsIDocShell that isn't a nsIDocShellTreeItem."); - PRInt32 itemType; - treeItem->GetItemType(&itemType); + PRInt32 itemType; + treeItem->GetItemType(&itemType); - if (itemType == nsIDocShellTreeItem::typeChrome) - contentType = eContentTypeUI; - else { - nsCOMPtr<nsIDocShellTreeItem> sameTypeParent; - treeItem->GetSameTypeParent(getter_AddRefs(sameTypeParent)); - contentType = sameTypeParent ? eContentTypeContentFrame : eContentTypeContent; + if (itemType == nsIDocShellTreeItem::typeChrome) + contentType = eContentTypeUI; + else { + nsCOMPtr<nsIDocShellTreeItem> sameTypeParent; + treeItem->GetSameTypeParent(getter_AddRefs(sameTypeParent)); + contentType = sameTypeParent ? eContentTypeContentFrame : eContentTypeContent; + } } nsIView* view = frame->CreateViewAndWidget(contentType); if (!view) return PR_FALSE; +#ifdef MOZ_IPC + if (mRemoteFrame) { + return ShowRemoteFrame(frame, view); + } +#endif + nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(mDocShell); NS_ASSERTION(baseWindow, "Found a nsIDocShell that isn't a nsIBaseWindow."); baseWindow->InitWindow(nsnull, view->GetWidget(), 0, 0, 10, 10); // This is kinda whacky, this "Create()" call doesn't really // create anything, one starts to wonder why this was named // "Create"... baseWindow->Create(); baseWindow->SetVisibility(PR_TRUE); // Trigger editor re-initialization if midas is turned on in the // sub-document. This shouldn't be necessary, but given the way our // editor works, it is. See // https://bugzilla.mozilla.org/show_bug.cgi?id=284245 + nsCOMPtr<nsIPresShell> presShell; mDocShell->GetPresShell(getter_AddRefs(presShell)); if (presShell) { nsCOMPtr<nsIDOMNSHTMLDocument> doc = do_QueryInterface(presShell->GetDocument()); if (doc) { nsAutoString designMode; doc->GetDesignMode(designMode); @@ -624,16 +744,104 @@ nsFrameLoader::Show(PRInt32 marginWidth, if (mHideCalled) { mHideCalled = PR_FALSE; Hide(); return PR_FALSE; } return PR_TRUE; } +#ifdef MOZ_IPC +bool