Merge from mozilla-central.
--HG-- rename : js/src/jsfun.cpp => js/src/vm/ArgumentsObject.cpp
@ -322,20 +322,6 @@ nsAccUtils::GetSelectableContainer(nsAccessible* aAccessible, PRUint64 aState)
|
||||
return parent;
|
||||
}
|
||||
|
||||
nsAccessible*
|
||||
nsAccUtils::GetMultiSelectableContainer(nsINode* aNode)
|
||||
{
|
||||
nsAccessible* accessible = GetAccService()->GetAccessible(aNode, nsnull);
|
||||
if (accessible) {
|
||||
nsAccessible* container = GetSelectableContainer(accessible,
|
||||
accessible->State());
|
||||
if (container && container->State() & states::MULTISELECTABLE)
|
||||
return container;
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
bool
|
||||
nsAccUtils::IsARIASelected(nsAccessible *aAccessible)
|
||||
{
|
||||
|
@ -196,11 +196,6 @@ public:
|
||||
static nsAccessible* GetSelectableContainer(nsAccessible* aAccessible,
|
||||
PRUint64 aState);
|
||||
|
||||
/**
|
||||
* Return multi selectable container for the given item.
|
||||
*/
|
||||
static nsAccessible *GetMultiSelectableContainer(nsINode *aNode);
|
||||
|
||||
/**
|
||||
* Return true if the DOM node of given accessible has aria-selected="true"
|
||||
* attribute.
|
||||
|
@ -298,23 +298,24 @@ already_AddRefed<nsAccessible>
|
||||
nsAccessibilityService::CreateHTMLImageAccessible(nsIContent* aContent,
|
||||
nsIPresShell* aPresShell)
|
||||
{
|
||||
nsAutoString mapElmName;
|
||||
aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::usemap, mapElmName);
|
||||
nsCOMPtr<nsIDOMHTMLMapElement> mapElm;
|
||||
if (nsIDocument* document = aContent->GetCurrentDoc()) {
|
||||
mapElm = do_QueryInterface(document->FindImageMap(mapElmName));
|
||||
}
|
||||
|
||||
nsAccessible* accessible = mapElm ?
|
||||
new nsHTMLImageMapAccessible(aContent,
|
||||
nsAccUtils::GetDocAccessibleFor(aPresShell),
|
||||
mapElm) :
|
||||
new nsHTMLImageAccessibleWrap(aContent,
|
||||
nsAccessible* accessible =
|
||||
new nsHTMLImageAccessibleWrap(aContent,
|
||||
nsAccUtils::GetDocAccessibleFor(aPresShell));
|
||||
NS_ADDREF(accessible);
|
||||
return accessible;
|
||||
}
|
||||
|
||||
already_AddRefed<nsAccessible>
|
||||
nsAccessibilityService::CreateHTMLImageMapAccessible(nsIContent* aContent,
|
||||
nsIPresShell* aPresShell)
|
||||
{
|
||||
nsAccessible* accessible =
|
||||
new nsHTMLImageMapAccessible(aContent,
|
||||
nsAccUtils::GetDocAccessibleFor(aPresShell));
|
||||
NS_ADDREF(accessible);
|
||||
return accessible;
|
||||
}
|
||||
|
||||
already_AddRefed<nsAccessible>
|
||||
nsAccessibilityService::CreateHTMLGroupboxAccessible(nsIContent* aContent,
|
||||
nsIPresShell* aPresShell)
|
||||
@ -611,6 +612,28 @@ nsAccessibilityService::UpdateListBullet(nsIPresShell* aPresShell,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsAccessibilityService::UpdateImageMap(nsImageFrame* aImageFrame)
|
||||
{
|
||||
nsIPresShell* presShell = aImageFrame->PresContext()->PresShell();
|
||||
nsDocAccessible* document = GetDocAccessible(presShell->GetDocument());
|
||||
if (document) {
|
||||
nsAccessible* accessible =
|
||||
document->GetAccessible(aImageFrame->GetContent());
|
||||
if (accessible) {
|
||||
nsHTMLImageMapAccessible* imageMap = accessible->AsImageMap();
|
||||
if (imageMap) {
|
||||
imageMap->UpdateChildAreas();
|
||||
return;
|
||||
}
|
||||
|
||||
// If image map was initialized after we created an accessible (that'll
|
||||
// be an image accessible) then recreate it.
|
||||
RecreateAccessible(presShell, aImageFrame->GetContent());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsAccessibilityService::PresShellDestroyed(nsIPresShell *aPresShell)
|
||||
{
|
||||
|
@ -48,6 +48,8 @@
|
||||
|
||||
#include "nsIObserver.h"
|
||||
|
||||
class nsImageFrame;
|
||||
|
||||
namespace mozilla {
|
||||
namespace a11y {
|
||||
|
||||
@ -109,6 +111,8 @@ public:
|
||||
CreateHTMLHRAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
|
||||
virtual already_AddRefed<nsAccessible>
|
||||
CreateHTMLImageAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
|
||||
already_AddRefed<nsAccessible>
|
||||
CreateHTMLImageMapAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
|
||||
virtual already_AddRefed<nsAccessible>
|
||||
CreateHTMLLabelAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
|
||||
virtual already_AddRefed<nsAccessible>
|
||||
@ -155,6 +159,11 @@ public:
|
||||
nsIContent* aHTMLListItemContent,
|
||||
bool aHasBullet);
|
||||
|
||||
/**
|
||||
* Update the image map.
|
||||
*/
|
||||
void UpdateImageMap(nsImageFrame* aImageFrame);
|
||||
|
||||
virtual void NotifyOfAnchorJumpTo(nsIContent *aTarget);
|
||||
|
||||
virtual void PresShellDestroyed(nsIPresShell* aPresShell);
|
||||
|
@ -1042,47 +1042,42 @@ nsIFrame* nsAccessible::GetBoundsFrame()
|
||||
return GetFrame();
|
||||
}
|
||||
|
||||
/* void removeSelection (); */
|
||||
NS_IMETHODIMP nsAccessible::SetSelected(bool aSelect)
|
||||
{
|
||||
// Add or remove selection
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (State() & states::SELECTABLE) {
|
||||
nsAccessible* multiSelect =
|
||||
nsAccUtils::GetMultiSelectableContainer(mContent);
|
||||
if (!multiSelect) {
|
||||
return aSelect ? TakeFocus() : NS_ERROR_FAILURE;
|
||||
nsAccessible* select = nsAccUtils::GetSelectableContainer(this, State());
|
||||
if (select) {
|
||||
if (select->State() & states::MULTISELECTABLE) {
|
||||
if (mRoleMapEntry) {
|
||||
if (aSelect) {
|
||||
return mContent->SetAttr(kNameSpaceID_None,
|
||||
nsGkAtoms::aria_selected,
|
||||
NS_LITERAL_STRING("true"), true);
|
||||
}
|
||||
return mContent->UnsetAttr(kNameSpaceID_None,
|
||||
nsGkAtoms::aria_selected, true);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mRoleMapEntry) {
|
||||
if (aSelect) {
|
||||
return mContent->SetAttr(kNameSpaceID_None,
|
||||
nsGkAtoms::aria_selected,
|
||||
NS_LITERAL_STRING("true"), true);
|
||||
}
|
||||
return mContent->UnsetAttr(kNameSpaceID_None,
|
||||
nsGkAtoms::aria_selected, true);
|
||||
}
|
||||
return aSelect ? TakeFocus() : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void takeSelection (); */
|
||||
NS_IMETHODIMP nsAccessible::TakeSelection()
|
||||
{
|
||||
// Select only this item
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (State() & states::SELECTABLE) {
|
||||
nsAccessible* multiSelect =
|
||||
nsAccUtils::GetMultiSelectableContainer(mContent);
|
||||
if (multiSelect)
|
||||
multiSelect->ClearSelection();
|
||||
|
||||
nsAccessible* select = nsAccUtils::GetSelectableContainer(this, State());
|
||||
if (select) {
|
||||
if (select->State() & states::MULTISELECTABLE)
|
||||
select->ClearSelection();
|
||||
return SetSelected(true);
|
||||
}
|
||||
|
||||
|
@ -62,6 +62,7 @@ class KeyBinding;
|
||||
class nsAccessible;
|
||||
class nsHyperTextAccessible;
|
||||
class nsHTMLImageAccessible;
|
||||
class nsHTMLImageMapAccessible;
|
||||
class nsHTMLLIAccessible;
|
||||
struct nsRoleMapEntry;
|
||||
class Relation;
|
||||
@ -454,10 +455,13 @@ public:
|
||||
|
||||
inline bool IsHTMLListItem() const { return mFlags & eHTMLListItemAccessible; }
|
||||
nsHTMLLIAccessible* AsHTMLListItem();
|
||||
|
||||
|
||||
inline bool IsImageAccessible() const { return mFlags & eImageAccessible; }
|
||||
nsHTMLImageAccessible* AsImage();
|
||||
|
||||
bool IsImageMapAccessible() const { return mFlags & eImageMapAccessible; }
|
||||
nsHTMLImageMapAccessible* AsImageMap();
|
||||
|
||||
inline bool IsListControl() const { return mFlags & eListControlAccessible; }
|
||||
|
||||
inline bool IsMenuButton() const { return mFlags & eMenuButtonAccessible; }
|
||||
@ -689,11 +693,12 @@ protected:
|
||||
eHTMLFileInputAccessible = 1 << 8,
|
||||
eHTMLListItemAccessible = 1 << 9,
|
||||
eImageAccessible = 1 << 10,
|
||||
eListControlAccessible = 1 << 11,
|
||||
eMenuButtonAccessible = 1 << 12,
|
||||
eMenuPopupAccessible = 1 << 13,
|
||||
eRootAccessible = 1 << 14,
|
||||
eTextLeafAccessible = 1 << 15
|
||||
eImageMapAccessible = 1 << 11,
|
||||
eListControlAccessible = 1 << 12,
|
||||
eMenuButtonAccessible = 1 << 13,
|
||||
eMenuPopupAccessible = 1 << 14,
|
||||
eRootAccessible = 1 << 15,
|
||||
eTextLeafAccessible = 1 << 16
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -52,15 +52,16 @@
|
||||
#include "nsImageMap.h"
|
||||
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHTMLImageMapAccessible
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsHTMLImageMapAccessible::
|
||||
nsHTMLImageMapAccessible(nsIContent* aContent, nsDocAccessible* aDoc,
|
||||
nsIDOMHTMLMapElement* aMapElm) :
|
||||
nsHTMLImageAccessibleWrap(aContent, aDoc), mMapElement(aMapElm)
|
||||
nsHTMLImageMapAccessible(nsIContent* aContent, nsDocAccessible* aDoc) :
|
||||
nsHTMLImageAccessibleWrap(aContent, aDoc)
|
||||
{
|
||||
mFlags |= eImageMapAccessible;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -104,39 +105,75 @@ nsHTMLImageMapAccessible::AnchorURIAt(PRUint32 aAnchorIndex)
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHTMLImageMapAccessible: nsAccessible protected
|
||||
// nsHTMLImageMapAccessible: public
|
||||
|
||||
void
|
||||
nsHTMLImageMapAccessible::CacheChildren()
|
||||
void
|
||||
nsHTMLImageMapAccessible::UpdateChildAreas(bool aDoFireEvents)
|
||||
{
|
||||
if (!mMapElement)
|
||||
nsImageFrame* imageFrame = do_QueryFrame(mContent->GetPrimaryFrame());
|
||||
|
||||
// If image map is not initialized yet then we trigger one time more later.
|
||||
nsImageMap* imageMapObj = imageFrame->GetExistingImageMap();
|
||||
if (!imageMapObj)
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsIDOMHTMLCollection> mapAreas;
|
||||
mMapElement->GetAreas(getter_AddRefs(mapAreas));
|
||||
if (!mapAreas)
|
||||
return;
|
||||
bool doReorderEvent = false;
|
||||
|
||||
nsDocAccessible* document = Document();
|
||||
// Remove areas that are not a valid part of the image map anymore.
|
||||
for (PRInt32 childIdx = mChildren.Length() - 1; childIdx >= 0; childIdx--) {
|
||||
nsAccessible* area = mChildren.ElementAt(childIdx);
|
||||
if (area->GetContent()->GetPrimaryFrame())
|
||||
continue;
|
||||
|
||||
PRUint32 areaCount = 0;
|
||||
mapAreas->GetLength(&areaCount);
|
||||
if (aDoFireEvents) {
|
||||
nsRefPtr<AccEvent> event = new AccHideEvent(area, area->GetContent());
|
||||
mDoc->FireDelayedAccessibleEvent(event);
|
||||
doReorderEvent = true;
|
||||
}
|
||||
|
||||
for (PRUint32 areaIdx = 0; areaIdx < areaCount; areaIdx++) {
|
||||
nsCOMPtr<nsIDOMNode> areaNode;
|
||||
mapAreas->Item(areaIdx, getter_AddRefs(areaNode));
|
||||
if (!areaNode)
|
||||
return;
|
||||
RemoveChild(area);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> areaContent(do_QueryInterface(areaNode));
|
||||
nsRefPtr<nsAccessible> area =
|
||||
new nsHTMLAreaAccessible(areaContent, mDoc);
|
||||
// Insert new areas into the tree.
|
||||
PRUint32 areaElmCount = imageMapObj->AreaCount();
|
||||
for (PRUint32 idx = 0; idx < areaElmCount; idx++) {
|
||||
nsIContent* areaContent = imageMapObj->GetAreaAt(idx);
|
||||
|
||||
if (!document->BindToDocument(area, nsAccUtils::GetRoleMapEntry(areaContent)) ||
|
||||
!AppendChild(area)) {
|
||||
return;
|
||||
nsAccessible* area = mChildren.SafeElementAt(idx);
|
||||
if (!area || area->GetContent() != areaContent) {
|
||||
nsRefPtr<nsAccessible> area = new nsHTMLAreaAccessible(areaContent, mDoc);
|
||||
if (!mDoc->BindToDocument(area, nsAccUtils::GetRoleMapEntry(areaContent)))
|
||||
break;
|
||||
|
||||
if (!InsertChildAt(idx, area)) {
|
||||
mDoc->UnbindFromDocument(area);
|
||||
break;
|
||||
}
|
||||
|
||||
if (aDoFireEvents) {
|
||||
nsRefPtr<AccEvent> event = new AccShowEvent(area, areaContent);
|
||||
mDoc->FireDelayedAccessibleEvent(event);
|
||||
doReorderEvent = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fire reorder event if needed.
|
||||
if (doReorderEvent) {
|
||||
nsRefPtr<AccEvent> reorderEvent =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_REORDER, mContent,
|
||||
eAutoDetect, AccEvent::eCoalesceFromSameSubtree);
|
||||
mDoc->FireDelayedAccessibleEvent(reorderEvent);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHTMLImageMapAccessible: nsAccessible protected
|
||||
|
||||
void
|
||||
nsHTMLImageMapAccessible::CacheChildren()
|
||||
{
|
||||
UpdateChildAreas(false);
|
||||
}
|
||||
|
||||
|
||||
@ -226,6 +263,17 @@ nsHTMLAreaAccessible::GetBounds(PRInt32 *aX, PRInt32 *aY,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHTMLAreaAccessible: nsAccessNode public
|
||||
|
||||
bool
|
||||
nsHTMLAreaAccessible::IsPrimaryForNode() const
|
||||
{
|
||||
// Make HTML area DOM element not accessible. HTML image map accessible
|
||||
// manages its tree itself.
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHTMLAreaAccessible: nsAccessible public
|
||||
|
||||
|
@ -51,8 +51,8 @@
|
||||
class nsHTMLImageMapAccessible : public nsHTMLImageAccessibleWrap
|
||||
{
|
||||
public:
|
||||
nsHTMLImageMapAccessible(nsIContent* aContent, nsDocAccessible* aDoc,
|
||||
nsIDOMHTMLMapElement* aMapElm);
|
||||
nsHTMLImageMapAccessible(nsIContent* aContent, nsDocAccessible* aDoc);
|
||||
virtual ~nsHTMLImageMapAccessible() { }
|
||||
|
||||
// nsISupports and cycle collector
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
@ -65,16 +65,27 @@ public:
|
||||
virtual nsAccessible* AnchorAt(PRUint32 aAnchorIndex);
|
||||
virtual already_AddRefed<nsIURI> AnchorURIAt(PRUint32 aAnchorIndex);
|
||||
|
||||
/**
|
||||
* Update area children of the image map.
|
||||
*/
|
||||
void UpdateChildAreas(bool aDoFireEvents = true);
|
||||
|
||||
protected:
|
||||
|
||||
// nsAccessible
|
||||
virtual void CacheChildren();
|
||||
|
||||
private:
|
||||
// Reference on linked map element if any.
|
||||
nsCOMPtr<nsIDOMHTMLMapElement> mMapElement;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsAccessible downcasting method
|
||||
|
||||
inline nsHTMLImageMapAccessible*
|
||||
nsAccessible::AsImageMap()
|
||||
{
|
||||
return IsImageMapAccessible() ?
|
||||
static_cast<nsHTMLImageMapAccessible*>(this) : nsnull;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Accessible for image map areas - must be child of image.
|
||||
@ -89,6 +100,9 @@ public:
|
||||
|
||||
NS_IMETHOD GetBounds(PRInt32 *x, PRInt32 *y, PRInt32 *width, PRInt32 *height);
|
||||
|
||||
// nsAccessNode
|
||||
virtual bool IsPrimaryForNode() const;
|
||||
|
||||
// nsAccessible
|
||||
virtual void Description(nsString& aDescription);
|
||||
virtual nsresult GetNameInternal(nsAString& aName);
|
||||
|
@ -486,6 +486,21 @@ function testDefunctAccessible(aAcc, aNodeOrId)
|
||||
ok(success, "parent" + msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that image map accessible tree is created.
|
||||
*/
|
||||
function ensureImageMapTree(aID)
|
||||
{
|
||||
// XXX: We send a useless mouse move to the image to force it to setup its
|
||||
// image map, because flushing layout won't do it. Hopefully bug 135040
|
||||
// will make this not suck.
|
||||
synthesizeMouse(getNode(aID), 10, 10, { type: "mousemove" });
|
||||
|
||||
// XXX This may affect a11y more than other code because imagemaps may not
|
||||
// get drawn or have an mouse event over them. Bug 570322 tracks a11y
|
||||
// dealing with this.
|
||||
todo(false, "Need to remove this image map workaround.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert role to human readable string.
|
||||
|
@ -9,6 +9,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=418368
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
|
||||
|
||||
<script type="application/javascript"
|
||||
src="../common.js"></script>
|
||||
@ -88,6 +90,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=418368
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// image map and its link children
|
||||
ensureImageMapTree("imgmap");
|
||||
|
||||
var imageMapHyperlinkAcc = getAccessible("imgmap",
|
||||
[nsIAccessibleHyperLink]);
|
||||
testThis("imgmap", imageMapHyperlinkAcc, ROLE_IMAGE_MAP, 2, "b", true,
|
||||
@ -268,7 +272,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=418368
|
||||
><img width="447" id="imgmap"
|
||||
height="15"
|
||||
usemap="#atoz_map"
|
||||
src="letters.gif"><br>Empty link:<br
|
||||
src="../letters.gif"><br>Empty link:<br
|
||||
><a id="emptyLink" href=""><img src=""></a
|
||||
><br>Link with embedded span<br
|
||||
><a id="LinkWithSpan" href="http://www.heise.de/"><span lang="de">Heise Online</span></a
|
||||
|
@ -9,6 +9,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=428248
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
|
||||
|
||||
<script type="application/javascript"
|
||||
src="../common.js"></script>
|
||||
@ -53,6 +55,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=428248
|
||||
testThis("InvalidAriaHyperlink", 63, 2, "Invalid link");
|
||||
|
||||
// image map, but not its link children. They are not part of hypertext.
|
||||
ensureImageMapTree("imgmap");
|
||||
testThis("imgmap", 76, 3, "b");
|
||||
|
||||
// empty hyperlink
|
||||
@ -131,7 +134,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=428248
|
||||
><img width="447" id="imgmap"
|
||||
height="15"
|
||||
usemap="#atoz_map"
|
||||
src="letters.gif"></img><br
|
||||
src="../letters.gif"></img><br
|
||||
>Empty link:<br
|
||||
><a id="emptyLink" href=""><img src=""></img></a><br
|
||||
>Link with embedded span<br
|
||||
|
@ -19,21 +19,22 @@
|
||||
<script type="application/javascript">
|
||||
function doTest()
|
||||
{
|
||||
//XXX We send a useless mouse move to the image to force it to setup its
|
||||
// image map, because flushing layout won't do it. Hopefully bug 135040
|
||||
// will make this not suck.
|
||||
synthesizeMouse($("imagemap"), 10, 10, { type: "mousemove" });
|
||||
//XXX This may affect a11y more than other code because imagemaps may not
|
||||
// get drawn or have an mouse event over them. Bug 570322 tracks a11y
|
||||
// dealing with this.
|
||||
todo(false, "Need to remove this image map workaround.");
|
||||
ensureImageMapTree("imagemap");
|
||||
|
||||
testStates("t1", 0, EXT_STATE_EDITABLE, STATE_LINKED);
|
||||
testStates("t2", 0, EXT_STATE_EDITABLE, STATE_LINKED);
|
||||
testStates("rb1", (STATE_CHECKABLE | STATE_CHECKED), 0, STATE_LINKED);
|
||||
testStates("rb2", STATE_CHECKABLE, 0, STATE_CHECKED, STATE_LINKED);
|
||||
testStates("cb1", (STATE_CHECKABLE | STATE_CHECKED), 0, STATE_LINKED);
|
||||
testStates("cbox", (STATE_HASPOPUP | STATE_COLLAPSED),
|
||||
var imageMap = getAccessible("imagemap");
|
||||
|
||||
var t1 = imageMap.getChildAt(0);
|
||||
testStates(t1, 0, EXT_STATE_EDITABLE, STATE_LINKED);
|
||||
var t2 = imageMap.getChildAt(1);
|
||||
testStates(t2, 0, EXT_STATE_EDITABLE, STATE_LINKED);
|
||||
var rb1 = imageMap.getChildAt(2);
|
||||
testStates(rb1, (STATE_CHECKABLE | STATE_CHECKED), 0, STATE_LINKED);
|
||||
var rb2 = imageMap.getChildAt(3);
|
||||
testStates(rb2, STATE_CHECKABLE, 0, STATE_CHECKED, STATE_LINKED);
|
||||
var cb1 = imageMap.getChildAt(4);
|
||||
testStates(cb1, (STATE_CHECKABLE | STATE_CHECKED), 0, STATE_LINKED);
|
||||
var cbox = imageMap.getChildAt(5);
|
||||
testStates(cbox, (STATE_HASPOPUP | STATE_COLLAPSED),
|
||||
EXT_STATE_EXPANDABLE, STATE_LINKED);
|
||||
|
||||
SimpleTest.finish();
|
||||
|
@ -19,14 +19,7 @@
|
||||
<script type="application/javascript">
|
||||
function doTest()
|
||||
{
|
||||
//XXX We send a useless mouse move to the image to force it to setup its
|
||||
// image map, because flushing layout won't do it. Hopefully bug 135040
|
||||
// will make this not suck.
|
||||
synthesizeMouse($("imagemap"), 10, 10, { type: "mousemove" });
|
||||
//XXX This may affect a11y more than other code because imagemaps may not
|
||||
// get drawn or have an mouse event over them. Bug 570322 tracks a11y
|
||||
// dealing with this.
|
||||
todo(false, "Need to remove this image map workaround.");
|
||||
ensureImageMapTree("imagemap");
|
||||
|
||||
var accTree = {
|
||||
role: ROLE_IMAGE_MAP,
|
||||
|
@ -54,6 +54,7 @@ _TEST_FILES =\
|
||||
test_doc.html \
|
||||
test_gencontent.html \
|
||||
test_hidden.html \
|
||||
test_imagemap.html \
|
||||
test_list_editabledoc.html \
|
||||
test_list.html \
|
||||
test_menu.xul \
|
||||
|
394
accessible/tests/mochitest/treeupdate/test_imagemap.html
Normal file
@ -0,0 +1,394 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>HTML img map accessible tree update tests</title>
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
|
||||
|
||||
<script type="application/javascript"
|
||||
src="../common.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../role.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../events.js"></script>
|
||||
|
||||
<script type="application/javascript">
|
||||
function insertArea(aImageMapID, aMapID)
|
||||
{
|
||||
this.imageMap = getAccessible(aImageMapID);
|
||||
this.mapNode = getNode(aMapID);
|
||||
|
||||
function getInsertedArea(aThisObj)
|
||||
{
|
||||
return aThisObj.imageMap.firstChild;
|
||||
}
|
||||
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_SHOW, getInsertedArea, this),
|
||||
new invokerChecker(EVENT_REORDER, this.imageMap)
|
||||
];
|
||||
|
||||
this.invoke = function insertArea_invoke()
|
||||
{
|
||||
var areaElm = document.createElement("area");
|
||||
areaElm.setAttribute("href",
|
||||
"http://www.bbc.co.uk/radio4/atoz/index.shtml#a");
|
||||
areaElm.setAttribute("coords", "0,0,13,14");
|
||||
areaElm.setAttribute("alt", "a");
|
||||
areaElm.setAttribute("shape", "rect");
|
||||
|
||||
this.mapNode.insertBefore(areaElm, this.mapNode.firstChild);
|
||||
}
|
||||
|
||||
this.finalCheck = function insertArea_finalCheck()
|
||||
{
|
||||
var accTree =
|
||||
{ IMAGE_MAP: [
|
||||
{
|
||||
role: ROLE_LINK,
|
||||
name: "a",
|
||||
children: [ ]
|
||||
},
|
||||
{
|
||||
role: ROLE_LINK,
|
||||
name: "b",
|
||||
children: [ ]
|
||||
},
|
||||
] };
|
||||
testAccessibleTree(this.imageMap, accTree);
|
||||
}
|
||||
|
||||
this.getID = function insertArea_getID()
|
||||
{
|
||||
return "insert area element";
|
||||
}
|
||||
}
|
||||
|
||||
function appendArea(aImageMapID, aMapID)
|
||||
{
|
||||
this.imageMap = getAccessible(aImageMapID);
|
||||
this.mapNode = getNode(aMapID);
|
||||
|
||||
function getAppendedArea(aThisObj)
|
||||
{
|
||||
return aThisObj.imageMap.lastChild;
|
||||
}
|
||||
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_SHOW, getAppendedArea, this),
|
||||
new invokerChecker(EVENT_REORDER, this.imageMap)
|
||||
];
|
||||
|
||||
this.invoke = function appendArea_invoke()
|
||||
{
|
||||
var areaElm = document.createElement("area");
|
||||
areaElm.setAttribute("href",
|
||||
"http://www.bbc.co.uk/radio4/atoz/index.shtml#c");
|
||||
areaElm.setAttribute("coords", "34,0,47,14");
|
||||
areaElm.setAttribute("alt", "c");
|
||||
areaElm.setAttribute("shape", "rect");
|
||||
|
||||
this.mapNode.appendChild(areaElm);
|
||||
}
|
||||
|
||||
this.finalCheck = function appendArea_finalCheck()
|
||||
{
|
||||
var accTree =
|
||||
{ IMAGE_MAP: [
|
||||
{
|
||||
role: ROLE_LINK,
|
||||
name: "a",
|
||||
children: [ ]
|
||||
},
|
||||
{
|
||||
role: ROLE_LINK,
|
||||
name: "b",
|
||||
children: [ ]
|
||||
},
|
||||
{
|
||||
role: ROLE_LINK,
|
||||
name: "c",
|
||||
children: [ ]
|
||||
}
|
||||
] };
|
||||
testAccessibleTree(this.imageMap, accTree);
|
||||
}
|
||||
|
||||
this.getID = function appendArea_getID()
|
||||
{
|
||||
return "append area element";
|
||||
}
|
||||
}
|
||||
|
||||
function removeArea(aImageMapID, aMapID)
|
||||
{
|
||||
this.imageMap = getAccessible(aImageMapID);
|
||||
this.area = null;
|
||||
this.mapNode = getNode(aMapID);
|
||||
|
||||
function getRemovedArea(aThisObj)
|
||||
{
|
||||
return aThisObj.area;
|
||||
}
|
||||
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_HIDE, getRemovedArea, this),
|
||||
new invokerChecker(EVENT_REORDER, this.imageMap)
|
||||
];
|
||||
|
||||
this.invoke = function removeArea_invoke()
|
||||
{
|
||||
this.area = this.imageMap.firstChild;
|
||||
this.mapNode.removeChild(this.mapNode.firstElementChild);
|
||||
}
|
||||
|
||||
this.finalCheck = function removeArea_finalCheck()
|
||||
{
|
||||
var accTree =
|
||||
{ IMAGE_MAP: [
|
||||
{
|
||||
role: ROLE_LINK,
|
||||
name: "b",
|
||||
children: [ ]
|
||||
},
|
||||
{
|
||||
role: ROLE_LINK,
|
||||
name: "c",
|
||||
children: [ ]
|
||||
}
|
||||
] };
|
||||
testAccessibleTree(this.imageMap, accTree);
|
||||
}
|
||||
|
||||
this.getID = function removeArea_getID()
|
||||
{
|
||||
return "remove area element";
|
||||
}
|
||||
}
|
||||
|
||||
function removeNameOnMap(aImageMapContainerID, aImageMapID, aMapID)
|
||||
{
|
||||
this.container = getAccessible(aImageMapContainerID);
|
||||
this.containerNode = this.container.DOMNode;
|
||||
this.imageMap = getAccessible(aImageMapID);
|
||||
this.imgNode = this.imageMap.DOMNode;
|
||||
this.mapNode = getNode(aMapID);
|
||||
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_HIDE, this.imageMap),
|
||||
new invokerChecker(EVENT_SHOW, this.imgNode),
|
||||
new invokerChecker(EVENT_REORDER, this.container)
|
||||
];
|
||||
|
||||
this.invoke = function removeNameOnMap_invoke()
|
||||
{
|
||||
this.mapNode.removeAttribute("name");
|
||||
}
|
||||
|
||||
this.finalCheck = function removeNameOnMap_finalCheck()
|
||||
{
|
||||
var accTree =
|
||||
{ SECTION: [
|
||||
{ GRAPHIC: [ ] }
|
||||
] };
|
||||
testAccessibleTree(this.container, accTree);
|
||||
}
|
||||
|
||||
this.getID = function removeNameOnMap_getID()
|
||||
{
|
||||
return "remove @name on map element";
|
||||
}
|
||||
}
|
||||
|
||||
function restoreNameOnMap(aImageMapContainerID, aImageMapID, aMapID)
|
||||
{
|
||||
this.container = getAccessible(aImageMapContainerID);
|
||||
this.containerNode = this.container.DOMNode;
|
||||
this.imageMap = null;
|
||||
this.imgNode = getNode(aImageMapID);
|
||||
this.mapNode = getNode(aMapID);
|
||||
|
||||
function getImageMap(aThisObj)
|
||||
{
|
||||
return aThisObj.imageMap;
|
||||
}
|
||||
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_HIDE, getImageMap, this),
|
||||
new invokerChecker(EVENT_SHOW, this.imgNode),
|
||||
new invokerChecker(EVENT_REORDER, this.container)
|
||||
];
|
||||
|
||||
this.invoke = function restoreNameOnMap_invoke()
|
||||
{
|
||||
this.imageMap = getAccessible(aImageMapID);
|
||||
this.mapNode.setAttribute("name", "atoz_map");
|
||||
}
|
||||
|
||||
this.finalCheck = function removeNameOnMap_finalCheck()
|
||||
{
|
||||
var accTree =
|
||||
{ SECTION: [
|
||||
{ IMAGE_MAP: [
|
||||
{ LINK: [ ] },
|
||||
{ LINK: [ ] }
|
||||
] }
|
||||
] };
|
||||
testAccessibleTree(this.container, accTree);
|
||||
}
|
||||
|
||||
this.getID = function removeNameOnMap_getID()
|
||||
{
|
||||
return "restore @name on map element";
|
||||
}
|
||||
}
|
||||
|
||||
function removeMap(aImageMapContainerID, aImageMapID, aMapID)
|
||||
{
|
||||
this.container = getAccessible(aImageMapContainerID);
|
||||
this.containerNode = this.container.DOMNode;
|
||||
this.imageMap = null;
|
||||
this.imgNode = getNode(aImageMapID);
|
||||
this.mapNode = getNode(aMapID);
|
||||
|
||||
function getImageMap(aThisObj)
|
||||
{
|
||||
return aThisObj.imageMap;
|
||||
}
|
||||
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_HIDE, getImageMap, this),
|
||||
new invokerChecker(EVENT_SHOW, this.imgNode),
|
||||
new invokerChecker(EVENT_REORDER, this.container)
|
||||
];
|
||||
|
||||
this.invoke = function removeMap_invoke()
|
||||
{
|
||||
this.imageMap = getAccessible(aImageMapID);
|
||||
this.mapNode.parentNode.removeChild(this.mapNode);
|
||||
}
|
||||
|
||||
this.finalCheck = function removeMap_finalCheck()
|
||||
{
|
||||
var accTree =
|
||||
{ SECTION: [
|
||||
{ GRAPHIC: [ ] }
|
||||
] };
|
||||
testAccessibleTree(this.container, accTree);
|
||||
}
|
||||
|
||||
this.getID = function removeMap_getID()
|
||||
{
|
||||
return "remove map element";
|
||||
}
|
||||
}
|
||||
|
||||
function insertMap(aImageMapContainerID, aImageID)
|
||||
{
|
||||
this.container = getAccessible(aImageMapContainerID);
|
||||
this.containerNode = this.container.DOMNode;
|
||||
this.image = null;
|
||||
this.imgMapNode = getNode(aImageID);
|
||||
|
||||
function getImage(aThisObj)
|
||||
{
|
||||
return aThisObj.image;
|
||||
}
|
||||
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_HIDE, getImage, this),
|
||||
new invokerChecker(EVENT_SHOW, this.imgMapNode),
|
||||
new invokerChecker(EVENT_REORDER, this.container)
|
||||
];
|
||||
|
||||
this.invoke = function insertMap_invoke()
|
||||
{
|
||||
this.image = getAccessible(aImageID);
|
||||
|
||||
var map = document.createElement("map");
|
||||
map.setAttribute("name", "atoz_map");
|
||||
map.setAttribute("id", "map");
|
||||
|
||||
var area = document.createElement("area")
|
||||
area.setAttribute("href",
|
||||
"http://www.bbc.co.uk/radio4/atoz/index.shtml#b");
|
||||
area.setAttribute("coords", "17,0,30,14");
|
||||
area.setAttribute("alt", "b");
|
||||
area.setAttribute("shape", "rect");
|
||||
|
||||
map.appendChild(area);
|
||||
|
||||
this.containerNode.appendChild(map);
|
||||
|
||||
ensureImageMapTree(aImageID);
|
||||
}
|
||||
|
||||
this.finalCheck = function insertMap_finalCheck()
|
||||
{
|
||||
var accTree =
|
||||
{ SECTION: [
|
||||
{ IMAGE_MAP: [
|
||||
{ LINK: [ ] }
|
||||
] }
|
||||
] };
|
||||
testAccessibleTree(this.container, accTree);
|
||||
}
|
||||
|
||||
this.getID = function insertMap_getID()
|
||||
{
|
||||
return "insert map element";
|
||||
}
|
||||
}
|
||||
|
||||
//gA11yEventDumpToConsole = true;
|
||||
|
||||
var gQueue = null;
|
||||
function doTest()
|
||||
{
|
||||
gQueue = new eventQueue();
|
||||
|
||||
gQueue.push(new insertArea("imgmap", "map"));
|
||||
gQueue.push(new appendArea("imgmap", "map"));
|
||||
gQueue.push(new removeArea("imgmap", "map"));
|
||||
gQueue.push(new removeNameOnMap("container", "imgmap", "map"));
|
||||
gQueue.push(new restoreNameOnMap("container", "imgmap", "map"));
|
||||
gQueue.push(new removeMap("container", "imgmap", "map"));
|
||||
gQueue.push(new insertMap("container", "imgmap"));
|
||||
|
||||
gQueue.invoke(); // Will call SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addA11yLoadEvent(doTest);
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<a target="_blank"
|
||||
title="Image map accessible tree is not updated when image map is changed"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=732389">
|
||||
Mozilla Bug 732389
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<map name="atoz_map" id="map">
|
||||
<area href="http://www.bbc.co.uk/radio4/atoz/index.shtml#b"
|
||||
coords="17,0,30,14" alt="b" shape="rect">
|
||||
</map>
|
||||
|
||||
<div id="container">
|
||||
<img id="imgmap" width="447" height="15"
|
||||
usemap="#atoz_map"
|
||||
src="../letters.gif">
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
1
aclocal.m4
vendored
@ -19,6 +19,7 @@ builtin(include, build/autoconf/gcc-pr49911.m4)dnl
|
||||
builtin(include, build/autoconf/frameptr.m4)dnl
|
||||
builtin(include, build/autoconf/compiler-opts.m4)dnl
|
||||
builtin(include, build/autoconf/expandlibs.m4)dnl
|
||||
builtin(include, build/autoconf/arch.m4)dnl
|
||||
|
||||
MOZ_PROG_CHECKMSYS()
|
||||
|
||||
|
@ -147,7 +147,7 @@ pref("dom.disable_open_during_load", true);
|
||||
pref("privacy.popups.showBrowserMessage", true);
|
||||
|
||||
pref("keyword.enabled", true);
|
||||
pref("keyword.URL", "http://www.google.com/m?ie=UTF-8&oe=UTF-8&sourceid=navclient&gfns=1&q=");
|
||||
pref("keyword.URL", "https://www.google.com/m?ie=UTF-8&oe=UTF-8&sourceid=navclient&gfns=1&q=");
|
||||
|
||||
pref("accessibility.typeaheadfind", false);
|
||||
pref("accessibility.typeaheadfind.timeout", 5000);
|
||||
|
@ -17,6 +17,7 @@ const LocalFile = CC('@mozilla.org/file/local;1',
|
||||
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
|
||||
Cu.import('resource://gre/modules/Services.jsm');
|
||||
Cu.import('resource://gre/modules/ContactService.jsm');
|
||||
Cu.import('resource://gre/modules/Webapps.jsm');
|
||||
|
||||
XPCOMUtils.defineLazyGetter(Services, 'env', function() {
|
||||
return Cc['@mozilla.org/process/environment;1']
|
||||
@ -66,7 +67,7 @@ function startupHttpd(baseDir, port) {
|
||||
function addPermissions(urls) {
|
||||
let permissions = [
|
||||
'indexedDB', 'indexedDB-unlimited', 'webapps-manage', 'offline-app',
|
||||
'content-camera', 'webcontacts-manage', 'wifi-manage'
|
||||
'content-camera', 'webcontacts-manage', 'wifi-manage', 'desktop-notification'
|
||||
];
|
||||
urls.forEach(function(url) {
|
||||
let uri = Services.io.newURI(url, null, null);
|
||||
@ -165,6 +166,10 @@ var shell = {
|
||||
dump('Error loading ' + frameScriptUrl + ' as a frame script: ' + e + '\n');
|
||||
}
|
||||
|
||||
CustomEventManager.init();
|
||||
|
||||
WebappsHelper.init();
|
||||
|
||||
let browser = this.contentBrowser;
|
||||
browser.homePage = homeURL;
|
||||
browser.goHome();
|
||||
@ -421,3 +426,70 @@ Services.obs.addObserver(function onConsoleAPILogEvent(subject, topic, data) {
|
||||
serverSocket.asyncListen(listener);
|
||||
})();
|
||||
|
||||
CustomEventManager = {
|
||||
init: function custevt_init() {
|
||||
window.addEventListener("ContentStart", (function(evt) {
|
||||
content.addEventListener("mozContentEvent", this, false, true);
|
||||
}).bind(this), false);
|
||||
},
|
||||
|
||||
handleEvent: function custevt_handleEvent(evt) {
|
||||
let detail = evt.detail;
|
||||
dump("XXX FIXME : Got a mozContentEvent: " + detail.type);
|
||||
|
||||
switch(detail.type) {
|
||||
case "desktop-notification-click":
|
||||
case "desktop-notification-close":
|
||||
AlertsHelper.handleEvent(detail);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AlertsHelper = {
|
||||
_listeners: {},
|
||||
_count: 0,
|
||||
|
||||
handleEvent: function alert_handleEvent(detail) {
|
||||
if (!detail || !detail.id)
|
||||
return;
|
||||
|
||||
let listener = this._listeners[detail.id];
|
||||
let topic = detail.type == "desktop-notification-click" ? "alertclickcallback" : "alertfinished";
|
||||
listener.observer.observe(null, topic, listener.cookie);
|
||||
|
||||
// we're done with this notification
|
||||
if (topic === "alertfinished")
|
||||
delete this._listeners[detail.id];
|
||||
},
|
||||
|
||||
registerListener: function alert_registerListener(cookie, alertListener) {
|
||||
let id = "alert" + this._count++;
|
||||
this._listeners[id] = { observer: alertListener, cookie: cookie };
|
||||
return id;
|
||||
},
|
||||
|
||||
showAlertNotification: function alert_showAlertNotification(imageUrl, title, text, textClickable,
|
||||
cookie, alertListener, name) {
|
||||
let id = this.registerListener(cookie, alertListener);
|
||||
shell.sendEvent(content, "mozChromeEvent", { type: "desktop-notification", id: id, icon: imageUrl,
|
||||
title: title, text: text } );
|
||||
}
|
||||
}
|
||||
|
||||
WebappsHelper = {
|
||||
init: function webapps_init() {
|
||||
Services.obs.addObserver(this, "webapps-launch", false);
|
||||
},
|
||||
|
||||
observe: function webapps_observe(subject, topic, data) {
|
||||
let json = JSON.parse(data);
|
||||
DOMApplicationRegistry.getManifestFor(json.origin, function(aManifest) {
|
||||
if (!aManifest)
|
||||
return;
|
||||
|
||||
let manifest = new DOMApplicationManifest(aManifest, json.origin);
|
||||
shell.sendEvent(content, "mozChromeEvent", { type: "webapps-launch", url: manifest.fullLaunchPath(), origin: json.origin });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
27
b2g/components/AlertsService.js
Normal file
@ -0,0 +1,27 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Alerts Service
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
function AlertsService() { }
|
||||
|
||||
AlertsService.prototype = {
|
||||
classID: Components.ID("{5dce03b2-8faa-4b6e-9242-6ddb0411750c}"),
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAlertsService]),
|
||||
|
||||
showAlertNotification: function(aImageUrl, aTitle, aText, aTextClickable, aCookie, aAlertListener, aName) {
|
||||
let browser = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
browser.AlertsHelper.showAlertNotification(aImageUrl, aTitle, aText, aTextClickable, aCookie, aAlertListener, aName);
|
||||
}
|
||||
};
|
||||
|
||||
const NSGetFactory = XPCOMUtils.generateNSGetFactory([AlertsService]);
|
@ -5,3 +5,11 @@ category agent-style-sheets browser-content-stylesheet chrome://browser/content/
|
||||
component {eff4231b-abce-4f7f-a40a-d646e8fde3ce} CameraContent.js
|
||||
contract @mozilla.org/b2g-camera-content;1 {eff4231b-abce-4f7f-a40a-d646e8fde3ce}
|
||||
category JavaScript-navigator-property mozCamera @mozilla.org/b2g-camera-content;1
|
||||
|
||||
# AlertsService.js
|
||||
component {5dce03b2-8faa-4b6e-9242-6ddb0411750c} AlertsService.js
|
||||
contract @mozilla.org/alerts-service;1 {5dce03b2-8faa-4b6e-9242-6ddb0411750c}
|
||||
|
||||
# ContentPermissionPrompt.js
|
||||
component {8c719f03-afe0-4aac-91ff-6c215895d467} ContentPermissionPrompt.js
|
||||
contract @mozilla.org/content-permission/prompt;1 {8c719f03-afe0-4aac-91ff-6c215895d467}
|
||||
|
@ -62,7 +62,7 @@ CameraContent.prototype = {
|
||||
let perm = principal == secMan.getSystemPrincipal() ? Ci.nsIPermissionManager.ALLOW_ACTION : Services.perms.testExactPermission(principal.URI, "content-camera");
|
||||
|
||||
//only pages with perm set and chrome pages can use the camera in content
|
||||
this.hasPrivileges = perm == Ci.nsIPermissionManager.ALLOW_ACTION || from.schemeIs("chrome");
|
||||
this.hasPrivileges = perm == Ci.nsIPermissionManager.ALLOW_ACTION;
|
||||
|
||||
Services.obs.addObserver(this, "inner-window-destroyed", false);
|
||||
let util = aWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
|
||||
|
45
b2g/components/ContentPermissionPrompt.js
Normal file
@ -0,0 +1,45 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const Ci = Components.interfaces;
|
||||
const Cr = Components.results;
|
||||
const Cu = Components.utils;
|
||||
const Cc = Components.classes;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
function ContentPermissionPrompt() {}
|
||||
|
||||
ContentPermissionPrompt.prototype = {
|
||||
|
||||
handleExistingPermission: function handleExistingPermission(request) {
|
||||
let result = Services.perms.testExactPermission(request.uri, request.type);
|
||||
if (result == Ci.nsIPermissionManager.ALLOW_ACTION) {
|
||||
request.allow();
|
||||
return true;
|
||||
}
|
||||
if (result == Ci.nsIPermissionManager.DENY_ACTION) {
|
||||
request.cancel();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
prompt: function(request) {
|
||||
// returns true if the request was handled
|
||||
if (this.handleExistingPermission(request))
|
||||
return;
|
||||
|
||||
// TODO : show UI to grant or deny permission
|
||||
},
|
||||
|
||||
classID: Components.ID("{8c719f03-afe0-4aac-91ff-6c215895d467}"),
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPermissionPrompt])
|
||||
};
|
||||
|
||||
|
||||
//module initialization
|
||||
const NSGetFactory = XPCOMUtils.generateNSGetFactory([ContentPermissionPrompt]);
|
@ -51,6 +51,8 @@ XPIDLSRCS = \
|
||||
EXTRA_PP_COMPONENTS = \
|
||||
B2GComponents.manifest \
|
||||
CameraContent.js \
|
||||
AlertsService.js \
|
||||
ContentPermissionPrompt.js \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
@ -2,9 +2,9 @@
|
||||
#export GONK_PRODUCT=generic
|
||||
#gonk="/home/cjones/mozilla/gonk-toolchain-$GONK_TOOLCHAIN_VERSION"
|
||||
|
||||
mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/objdir-prof-gonk
|
||||
mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/obj-b2g
|
||||
|
||||
mk_add_options MOZ_MAKE_FLAGS="-s -j16"
|
||||
mk_add_options MOZ_MAKE_FLAGS="-j8"
|
||||
|
||||
ac_add_options --enable-application=b2g
|
||||
|
||||
|
@ -144,6 +144,7 @@
|
||||
@BINPATH@/components/directory.xpt
|
||||
@BINPATH@/components/docshell.xpt
|
||||
@BINPATH@/components/dom.xpt
|
||||
@BINPATH@/components/dom_apps.xpt
|
||||
@BINPATH@/components/dom_base.xpt
|
||||
#ifdef MOZ_B2G_RIL
|
||||
@BINPATH@/components/dom_telephony.xpt
|
||||
@ -290,7 +291,6 @@
|
||||
@BINPATH@/components/xuldoc.xpt
|
||||
@BINPATH@/components/xultmpl.xpt
|
||||
@BINPATH@/components/zipwriter.xpt
|
||||
@BINPATH@/components/webapps.xpt
|
||||
|
||||
; JavaScript components
|
||||
@BINPATH@/components/ConsoleAPI.manifest
|
||||
@ -407,10 +407,10 @@
|
||||
@BINPATH@/components/RadioInterfaceLayer.js
|
||||
@BINPATH@/components/SmsDatabaseService.manifest
|
||||
@BINPATH@/components/SmsDatabaseService.js
|
||||
@BINPATH@/components/nsWifiWorker.js
|
||||
@BINPATH@/components/nsWifiWorker.manifest
|
||||
@BINPATH@/components/nsDOMWifiManager.js
|
||||
@BINPATH@/components/nsDOMWifiManager.manifest
|
||||
@BINPATH@/components/WifiWorker.js
|
||||
@BINPATH@/components/WifiWorker.manifest
|
||||
@BINPATH@/components/DOMWifiManager.js
|
||||
@BINPATH@/components/DOMWifiManager.manifest
|
||||
#endif
|
||||
#ifdef XP_MACOSX
|
||||
@BINPATH@/components/libalerts.dylib
|
||||
@ -430,6 +430,8 @@
|
||||
#endif
|
||||
@BINPATH@/components/TelemetryPing.js
|
||||
@BINPATH@/components/TelemetryPing.manifest
|
||||
@BINPATH@/components/Webapps.js
|
||||
@BINPATH@/components/Webapps.manifest
|
||||
|
||||
; Modules
|
||||
@BINPATH@/modules/*
|
||||
@ -615,3 +617,5 @@ bin/components/@DLL_PREFIX@nkgnomevfs@DLL_SUFFIX@
|
||||
@BINPATH@/components/B2GComponents.manifest
|
||||
@BINPATH@/components/B2GComponents.xpt
|
||||
@BINPATH@/components/CameraContent.js
|
||||
@BINPATH@/components/AlertsService.js
|
||||
@BINPATH@/components/ContentPermissionPrompt.js
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0"?>
|
||||
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1331241604000">
|
||||
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1331848989000">
|
||||
<emItems>
|
||||
<emItem blockID="i58" id="webmaster@buzzzzvideos.info">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
@ -65,8 +65,8 @@
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i72" id="{4ED1F68A-5463-4931-9384-8FFF5ED91D92}">
|
||||
<versionRange minVersion="0" maxVersion="3.4.1.194" severity="1">
|
||||
<emItem blockID="i72" os="WINNT" id="{4ED1F68A-5463-4931-9384-8FFF5ED91D92}">
|
||||
<versionRange minVersion="3.4.1" maxVersion="3.4.1.194" severity="1">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i40" id="{28387537-e3f9-4ed7-860c-11e69af4a8a0}">
|
||||
@ -153,6 +153,10 @@
|
||||
<versionRange minVersion="2.0" maxVersion="2.0">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i73" id="a1g0a9g219d@a1.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i51" id="admin@youtubeplayer.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
|
Before Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 4.4 KiB |
@ -1,384 +0,0 @@
|
||||
%if 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 aboutHome.xhtml.
|
||||
*
|
||||
* 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):
|
||||
* Marco Bonardo <mak77@bonardo.net> (original author)
|
||||
* Mihai Sucan <mihai.sucan@gmail.com>
|
||||
* Stephen Horlander <shorlander@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 ***** */
|
||||
%endif
|
||||
|
||||
html {
|
||||
font-family: sans-serif;
|
||||
background: -moz-Field;
|
||||
color: -moz-FieldText;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#brandStart {
|
||||
text-align: center;
|
||||
height: 19%;
|
||||
max-height: 256px;
|
||||
min-height: 92px;
|
||||
}
|
||||
|
||||
#brandStartSpacer {
|
||||
height: 6.5%;
|
||||
}
|
||||
|
||||
#brandStartLogo {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#searchContainer {
|
||||
height: 15%;
|
||||
min-height: 90px;
|
||||
}
|
||||
|
||||
#searchContainer::before {
|
||||
content: " ";
|
||||
display: block;
|
||||
height: 23%;
|
||||
}
|
||||
|
||||
#searchForm {
|
||||
display: table;
|
||||
width: 100%;
|
||||
max-width: 1830px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
@media all and (max-height: 700px) {
|
||||
#searchContainer { height: 20% }
|
||||
}
|
||||
|
||||
@media all and (max-height: 500px) {
|
||||
#searchContainer { height: 25% }
|
||||
}
|
||||
|
||||
@media all and (max-height: 370px) {
|
||||
#searchContainer { height: 30% }
|
||||
}
|
||||
|
||||
#searchLogoContainer {
|
||||
display: table-cell;
|
||||
width: 30%;
|
||||
text-align: end;
|
||||
line-height: 32px;
|
||||
}
|
||||
|
||||
#searchEngineLogo {
|
||||
-moz-margin-end: 2.5%;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
#searchInputContainer {
|
||||
display: table-cell;
|
||||
width: 38%;
|
||||
max-width: 700px;
|
||||
min-width: 150px;
|
||||
}
|
||||
|
||||
#searchText {
|
||||
width: 100%;
|
||||
height: 24px;
|
||||
padding: 3px 6px;
|
||||
border-radius: 2px;
|
||||
border: 1px solid rgb(150,150,150);
|
||||
border-top-color: rgb(100,100,100);
|
||||
box-shadow: 0 1px 0 rgba(255,255,255,0.5);
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
#searchButtons {
|
||||
display: table-cell;
|
||||
width: 31%;
|
||||
-moz-padding-start: 13px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
@media all and (max-width: 470px) {
|
||||
#searchLogoContainer { width: 10% }
|
||||
#searchButtons { width: 11% }
|
||||
#searchInputContainer { width: 40% }
|
||||
}
|
||||
|
||||
@media all and (min-width: 470px) and (max-width: 600px) {
|
||||
#searchLogoContainer { width: 15% }
|
||||
#searchButtons { width: 16%; white-space: nowrap }
|
||||
#searchInputContainer { width: 45% }
|
||||
}
|
||||
|
||||
@media all and (min-width: 600px) and (max-width: 850px) {
|
||||
#searchLogoContainer { width: 20% }
|
||||
#searchButtons { width: 21%; white-space: nowrap }
|
||||
#searchInputContainer { width: 49% }
|
||||
}
|
||||
|
||||
#searchSubmit {
|
||||
background: -moz-linear-gradient(#f1f1f1, #dfdfdf);
|
||||
padding: 4px 8px;
|
||||
height: 32px;
|
||||
border: 1px solid #ccc;
|
||||
border-top-color: #ccc;
|
||||
border-bottom-color: #999;
|
||||
-moz-border-start-color: #afafaf;
|
||||
-moz-border-end-color: #999;
|
||||
box-shadow: 1px 1px 0 #e7e7e7,
|
||||
0 1px 0 #fcfcfc inset,
|
||||
0 -1px 0 #d7d7d7 inset;
|
||||
font-size: 1em;
|
||||
color: #000;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
body[dir=rtl] #searchSubmit {
|
||||
box-shadow: -1px 1px 0 #e7e7e7,
|
||||
0 1px 0 #fcfcfc inset,
|
||||
0 -1px 0 #d7d7d7 inset;
|
||||
}
|
||||
|
||||
#searchSubmit:active {
|
||||
background: -moz-linear-gradient(#c5c5c5, #c5c5c5);
|
||||
box-shadow: 1px 1px 0 #e7e7e7;
|
||||
}
|
||||
|
||||
body[dir=rtl] #searchSubmit:active {
|
||||
box-shadow: -1px 1px 0 #e7e7e7;
|
||||
}
|
||||
|
||||
#contentContainer {
|
||||
height: 30%;
|
||||
background-image: -moz-radial-gradient(center top, ellipse farthest-side, rgba(16,83,130,.5), rgba(16,83,130,0) 75%),
|
||||
-moz-radial-gradient(center top, ellipse farthest-side, rgba(180,218,244,.5), rgba(180,218,244,0)),
|
||||
-moz-radial-gradient(center top, ellipse farthest-side, rgba(180,218,244,.3), rgba(180,218,244,0));
|
||||
background-size: 100% 5px,
|
||||
100% 50px,
|
||||
100% 100%;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
@media all and (max-height: 400px) {
|
||||
#contentContainer { height: 20% }
|
||||
}
|
||||
|
||||
#snippetContainer {
|
||||
position: relative;
|
||||
top: -24px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#snippets {
|
||||
display: inline-block;
|
||||
padding: 14px;
|
||||
width: 30%;
|
||||
max-width: 600px;
|
||||
background-image: -moz-linear-gradient(rgba(255,255,255,.8), rgba(255,255,255,.1));
|
||||
background-color: rgb(250,250,250);
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 1px 0 rgba(255,255,255,.8) inset,
|
||||
0 -2px 0 rgba(0,0,0,.1) inset,
|
||||
0 0 10px rgba(255,255,255,.5) inset,
|
||||
0 0 0 1px rgba(0,0,0,.1),
|
||||
0 2px 4px rgba(0,0,0,.2);
|
||||
color: rgb(60,60,60);
|
||||
font-size: .85em;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#snippets:empty {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
@media all and (max-width: 470px) {
|
||||
#snippets { width: 65% }
|
||||
}
|
||||
|
||||
@media all and (min-width: 470px) and (max-width: 850px) {
|
||||
#snippets { width: 45% }
|
||||
}
|
||||
|
||||
#snippets:hover {
|
||||
background-color: rgb(255,255,255);
|
||||
box-shadow: 0 1px 0 rgba(255,255,255,.8) inset,
|
||||
0 -2px 0 rgba(0,0,0,.1) inset,
|
||||
0 0 10px rgba(255,255,255,.5) inset,
|
||||
0 0 5px rgba(0,0,0,.1),
|
||||
0 0 0 1px rgba(0,0,0,.1),
|
||||
0 2px 4px rgba(0,0,0,.2);
|
||||
}
|
||||
|
||||
#snippets:hover:active {
|
||||
background-color: rgb(210,210,210);
|
||||
box-shadow: 0 2px 3px rgba(0,0,0,.3) inset,
|
||||
0 1px 0 rgba(255,255,255,.5);
|
||||
}
|
||||
|
||||
#defaultSnippet1,
|
||||
#defaultSnippet2 {
|
||||
display: table-row;
|
||||
text-align: start;
|
||||
}
|
||||
|
||||
#defaultSnippet1::before,
|
||||
#defaultSnippet2::before {
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
-moz-padding-end: 1em;
|
||||
}
|
||||
|
||||
#defaultSnippet1::before {
|
||||
content: url("chrome://browser/content/aboutHome-snippet1.png");
|
||||
}
|
||||
#defaultSnippet2::before {
|
||||
content: url("chrome://browser/content/aboutHome-snippet2.png");
|
||||
}
|
||||
|
||||
#sessionRestoreContainer {
|
||||
padding-top: 1.5%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@media all and (max-height: 500px) {
|
||||
#sessionRestoreContainer {
|
||||
position: relative;
|
||||
top: -15px;
|
||||
padding-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
#restorePreviousSession {
|
||||
padding: 10px;
|
||||
border: 0;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 0 0 1px rgba(9,37,59,0),
|
||||
0 1px 2px rgba(9,37,59,0),
|
||||
0 0 10px rgba(255,255,255,0),
|
||||
0 -3px 0 rgba(180,194,212,0) inset;
|
||||
-moz-transition-property: background-color, box-shadow;
|
||||
-moz-transition-duration: 0.25s;
|
||||
-moz-transition-timing-function: ease-out;
|
||||
background: transparent;
|
||||
color: rgb(50,50,50);
|
||||
font-weight: bold;
|
||||
font-size: 1em;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#restorePreviousSession::before {
|
||||
display: inline-block;
|
||||
content: url("chrome://browser/content/aboutHome-restore-icon.png");
|
||||
-moz-margin-end: 10px;
|
||||
vertical-align: middle;
|
||||
height: 66px; /* Needed to avoid a blank space under the image */
|
||||
}
|
||||
|
||||
body[dir=rtl] #restorePreviousSession::before {
|
||||
-moz-transform: scaleX(-1);
|
||||
}
|
||||
|
||||
@media all and (max-height: 500px) {
|
||||
#restorePreviousSession::before {
|
||||
content: url("chrome://browser/content/aboutHome-restore-icon-small.png");
|
||||
height: 41px;
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (max-width: 500px) {
|
||||
#restorePreviousSession::before {
|
||||
content: url("chrome://browser/content/aboutHome-restore-icon-small.png");
|
||||
height: 41px;
|
||||
}
|
||||
}
|
||||
|
||||
#restorePreviousSession:disabled {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#restorePreviousSession:hover {
|
||||
background-image: -moz-linear-gradient(rgba(255,255,255,.7), rgba(255,255,255,.2));
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 0 0 1px rgba(9,37,59,.2),
|
||||
0 1px 2px rgba(9,37,59,.2),
|
||||
0 0 10px rgba(255,255,255,.4),
|
||||
0 -3px 0 rgba(180,194,212,.3) inset;
|
||||
}
|
||||
|
||||
#restorePreviousSession:hover:active {
|
||||
background-image: -moz-linear-gradient(rgba(255,255,255,.0), rgba(255,255,255,.2));
|
||||
background-color: rgba(23,75,115,.1);
|
||||
box-shadow: 0 0 0 1px rgba(9,37,59,.2),
|
||||
0 1px 2px rgba(9,37,59,.4) inset,
|
||||
0 1px 5px rgba(9,37,59,.15) inset;
|
||||
}
|
||||
|
||||
#bottomSection {
|
||||
position: absolute;
|
||||
color: rgb(150,150,150);
|
||||
font-size: .8em;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
bottom: 2%;
|
||||
}
|
||||
|
||||
#syncLinksContainer {
|
||||
padding-top: 1em;
|
||||
}
|
||||
|
||||
.sync-link {
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
@media all and (max-height: 370px) {
|
||||
#bottomSection {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
362
browser/base/content/abouthome/aboutHome.css
Normal file
@ -0,0 +1,362 @@
|
||||
%if 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 aboutHome.xhtml.
|
||||
*
|
||||
* 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):
|
||||
* Marco Bonardo <mak77@bonardo.net> (original author)
|
||||
* Mihai Sucan <mihai.sucan@gmail.com>
|
||||
* Stephen Horlander <shorlander@mozilla.com>
|
||||
* Frank Yan <fyan@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 ***** */
|
||||
%endif
|
||||
|
||||
html {
|
||||
font: message-box;
|
||||
font-size: 100%;
|
||||
background-color: hsl(0,0%,90%);
|
||||
background-image: url(chrome://browser/content/abouthome/noise.png),
|
||||
-moz-linear-gradient(hsla(0,0%,100%,.7), hsla(0,0%,100%,.4));
|
||||
background-attachment: fixed;
|
||||
color: #000;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#container {
|
||||
display: -moz-box;
|
||||
-moz-box-orient: vertical;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
input,
|
||||
button {
|
||||
font-size: inherit;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
a {
|
||||
color: -moz-nativehyperlinktext;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.spacer {
|
||||
-moz-box-flex: 1;
|
||||
}
|
||||
|
||||
#topSection {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#brandLogo {
|
||||
height: 154px;
|
||||
margin: 22px 0 31px;
|
||||
}
|
||||
|
||||
#searchForm,
|
||||
#snippets {
|
||||
width: 470px;
|
||||
}
|
||||
|
||||
#searchForm {
|
||||
display: -moz-box;
|
||||
}
|
||||
|
||||
#searchLogoContainer {
|
||||
display: -moz-box;
|
||||
-moz-box-align: center;
|
||||
padding-top: 2px;
|
||||
-moz-padding-end: 8px;
|
||||
}
|
||||
|
||||
#searchEngineLogo {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
#searchText {
|
||||
-moz-box-flex: 1;
|
||||
padding: 6px 8px;
|
||||
background: hsla(0,0%,100%,.9) padding-box;
|
||||
border: 1px solid;
|
||||
border-color: hsla(210,54%,20%,.15) hsla(210,54%,20%,.17) hsla(210,54%,20%,.2);
|
||||
box-shadow: 0 1px 0 hsla(210,65%,9%,.02) inset,
|
||||
0 0 2px hsla(210,65%,9%,.1) inset,
|
||||
0 1px 0 hsla(0,0%,100%,.2);
|
||||
border-radius: 2.5px 0 0 2.5px;
|
||||
}
|
||||
|
||||
body[dir=rtl] #searchText {
|
||||
border-radius: 0 2.5px 2.5px 0;
|
||||
}
|
||||
|
||||
#searchText:focus {
|
||||
border-color: hsla(206,100%,60%,.6) hsla(206,76%,52%,.6) hsla(204,100%,40%,.6);
|
||||
}
|
||||
|
||||
#searchSubmit {
|
||||
-moz-margin-start: -1px;
|
||||
background: -moz-linear-gradient(hsla(0,0%,100%,.8), hsla(0,0%,100%,.1)) padding-box;
|
||||
padding: 0 9px;
|
||||
border: 1px solid;
|
||||
border-color: hsla(210,54%,20%,.15) hsla(210,54%,20%,.17) hsla(210,54%,20%,.2);
|
||||
-moz-border-start: 1px solid transparent;
|
||||
border-radius: 0 2.5px 2.5px 0;
|
||||
box-shadow: 0 0 2px hsla(0,0%,100%,.5) inset,
|
||||
0 1px 0 hsla(0,0%,100%,.2);
|
||||
cursor: pointer;
|
||||
-moz-transition-property: background-color, border-color, box-shadow;
|
||||
-moz-transition-duration: 150ms;
|
||||
}
|
||||
|
||||
body[dir=rtl] #searchSubmit {
|
||||
border-radius: 2.5px 0 0 2.5px;
|
||||
}
|
||||
|
||||
#searchText:focus + #searchSubmit,
|
||||
#searchText + #searchSubmit:hover {
|
||||
border-color: #59b5fc #45a3e7 #3294d5;
|
||||
color: white;
|
||||
}
|
||||
|
||||
#searchText:focus + #searchSubmit {
|
||||
background-image: -moz-linear-gradient(#4cb1ff, #1793e5);
|
||||
box-shadow: 0 1px 0 hsla(0,0%,100%,.2) inset,
|
||||
0 0 0 1px hsla(0,0%,100%,.1) inset,
|
||||
0 1px 0 hsla(210,54%,20%,.03);
|
||||
}
|
||||
|
||||
#searchText + #searchSubmit:hover {
|
||||
background-image: -moz-linear-gradient(#66bdff, #0d9eff);
|
||||
box-shadow: 0 1px 0 hsla(0,0%,100%,.2) inset,
|
||||
0 0 0 1px hsla(0,0%,100%,.1) inset,
|
||||
0 1px 0 hsla(210,54%,20%,.03),
|
||||
0 0 4px hsla(206,100%,20%,.2);
|
||||
}
|
||||
|
||||
#searchText + #searchSubmit:hover:active {
|
||||
box-shadow: 0 1px 1px hsla(211,79%,6%,.1) inset,
|
||||
0 0 1px hsla(211,79%,6%,.2) inset;
|
||||
-moz-transition-duration: 0ms;
|
||||
}
|
||||
|
||||
#defaultSnippet1,
|
||||
#defaultSnippet2 {
|
||||
display: block;
|
||||
min-height: 38px;
|
||||
background: 30px center no-repeat;
|
||||
padding: 6px 0;
|
||||
-moz-padding-start: 79px;
|
||||
}
|
||||
|
||||
body[dir=rtl] #defaultSnippet1,
|
||||
body[dir=rtl] #defaultSnippet2 {
|
||||
background-position: right 30px center;
|
||||
}
|
||||
|
||||
#defaultSnippet1 {
|
||||
background-image: url("chrome://browser/content/abouthome/snippet1.png");
|
||||
}
|
||||
|
||||
#defaultSnippet2 {
|
||||
background-image: url("chrome://browser/content/abouthome/snippet2.png");
|
||||
}
|
||||
|
||||
#snippets {
|
||||
display: inline-block;
|
||||
text-align: start;
|
||||
margin: 12px 0;
|
||||
color: #3c3c3c;
|
||||
font-size: 75%;
|
||||
}
|
||||
|
||||
#launcher {
|
||||
display: -moz-box;
|
||||
-moz-box-align: center;
|
||||
-moz-box-pack: center;
|
||||
width: 100%;
|
||||
background-color: hsla(0,0%,0%,.03);
|
||||
border-top: 1px solid hsla(0,0%,0%,.03);
|
||||
box-shadow: 0 1px 2px hsla(0,0%,0%,.02) inset,
|
||||
0 -1px 0 hsla(0,0%,100%,.25);
|
||||
}
|
||||
|
||||
#launcher:not([session]),
|
||||
body[narrow] #launcher[session] {
|
||||
display: block; /* display separator and restore button on separate lines */
|
||||
text-align: center;
|
||||
white-space: nowrap; /* prevent navigational buttons from wrapping */
|
||||
}
|
||||
|
||||
.launchButton {
|
||||
display: -moz-box;
|
||||
-moz-box-orient: vertical;
|
||||
margin: 16px 1px;
|
||||
padding: 14px 6px;
|
||||
min-width: 88px;
|
||||
max-width: 176px;
|
||||
max-height: 85px;
|
||||
vertical-align: top;
|
||||
white-space: normal;
|
||||
background: transparent padding-box;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 2.5px;
|
||||
color: #525c66;
|
||||
font-size: 75%;
|
||||
cursor: pointer;
|
||||
-moz-transition-property: background-color, border-color, box-shadow;
|
||||
-moz-transition-duration: 150ms;
|
||||
}
|
||||
|
||||
body[narrow] #launcher[session] > .launchButton {
|
||||
margin: 4px 1px;
|
||||
}
|
||||
|
||||
.launchButton:hover {
|
||||
background-color: hsla(211,79%,6%,.03);
|
||||
border-color: hsla(210,54%,20%,.15) hsla(210,54%,20%,.17) hsla(210,54%,20%,.2);
|
||||
}
|
||||
|
||||
.launchButton:hover:active {
|
||||
background-image: -moz-linear-gradient(hsla(211,79%,6%,.02), hsla(211,79%,6%,.05));
|
||||
border-color: hsla(210,54%,20%,.2) hsla(210,54%,20%,.23) hsla(210,54%,20%,.25);
|
||||
box-shadow: 0 1px 1px hsla(211,79%,6%,.05) inset,
|
||||
0 0 1px hsla(211,79%,6%,.1) inset;
|
||||
-moz-transition-duration: 0ms;
|
||||
}
|
||||
|
||||
#launcher:not([session]) > #restorePreviousSessionSeparator,
|
||||
#launcher:not([session]) > #restorePreviousSession {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#restorePreviousSessionSeparator {
|
||||
width: 3px;
|
||||
height: 116px;
|
||||
margin: 0 10px;
|
||||
background-image: -moz-linear-gradient(hsla(0,0%,100%,0), hsla(0,0%,100%,.35), hsla(0,0%,100%,0)),
|
||||
-moz-linear-gradient(hsla(211,79%,6%,0), hsla(211,79%,6%,.2), hsla(211,79%,6%,0)),
|
||||
-moz-linear-gradient(hsla(0,0%,100%,0), hsla(0,0%,100%,.35), hsla(0,0%,100%,0));
|
||||
background-position: left top, center, right bottom;
|
||||
background-size: 1px auto;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
body[narrow] #restorePreviousSessionSeparator {
|
||||
margin: 0 auto;
|
||||
width: 512px;
|
||||
height: 3px;
|
||||
background-image: -moz-linear-gradient(0, hsla(0,0%,100%,0), hsla(0,0%,100%,.35), hsla(0,0%,100%,0)),
|
||||
-moz-linear-gradient(0, hsla(211,79%,6%,0), hsla(211,79%,6%,.2), hsla(211,79%,6%,0)),
|
||||
-moz-linear-gradient(0, hsla(0,0%,100%,0), hsla(0,0%,100%,.35), hsla(0,0%,100%,0));
|
||||
background-size: auto 1px;
|
||||
}
|
||||
|
||||
#restorePreviousSession {
|
||||
max-width: none;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
body[narrow] #restorePreviousSession {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
.launchButton::before {
|
||||
display: block;
|
||||
margin-bottom: 6px;
|
||||
line-height: 0; /* remove extra vertical space due to non-zero font-size */
|
||||
}
|
||||
|
||||
#bookmarks::before {
|
||||
content: url("chrome://browser/content/abouthome/bookmarks.png");
|
||||
}
|
||||
|
||||
#history::before {
|
||||
content: url("chrome://browser/content/abouthome/history.png");
|
||||
}
|
||||
|
||||
#settings::before {
|
||||
content: url("chrome://browser/content/abouthome/settings.png");
|
||||
}
|
||||
|
||||
#addons::before {
|
||||
content: url("chrome://browser/content/abouthome/addons.png");
|
||||
}
|
||||
|
||||
#downloads::before {
|
||||
content: url("chrome://browser/content/abouthome/downloads.png");
|
||||
}
|
||||
|
||||
#sync::before {
|
||||
content: url("chrome://browser/content/abouthome/sync.png");
|
||||
}
|
||||
|
||||
#restorePreviousSession::before {
|
||||
content: url("chrome://browser/content/abouthome/restore-large.png");
|
||||
display: inline-block; /* display on same line as text label */
|
||||
vertical-align: middle;
|
||||
margin-bottom: 0;
|
||||
-moz-margin-end: 8px;
|
||||
}
|
||||
|
||||
body[dir=rtl] #restorePreviousSession::before {
|
||||
-moz-transform: scaleX(-1);
|
||||
}
|
||||
|
||||
body[narrow] #restorePreviousSession::before {
|
||||
content: url("chrome://browser/content/abouthome/restore.png");
|
||||
}
|
||||
|
||||
#aboutMozilla {
|
||||
display: block;
|
||||
position: relative; /* pin wordmark to edge of document, not of viewport */
|
||||
-moz-box-ordinal-group: 0;
|
||||
opacity: .5;
|
||||
-moz-transition: opacity 150ms;
|
||||
}
|
||||
|
||||
#aboutMozilla:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
#aboutMozilla::before {
|
||||
content: url("chrome://browser/content/abouthome/mozilla.png");
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 12px;
|
||||
right: 12px;
|
||||
}
|
@ -22,6 +22,7 @@
|
||||
* Contributor(s):
|
||||
* Marco Bonardo <mak77@bonardo.net> (original author)
|
||||
* Mihai Sucan <mihai.sucan@gmail.com>
|
||||
* Frank Yan <fyan@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
|
||||
@ -155,6 +156,9 @@ function onLoad(event)
|
||||
document.getElementById("searchText").focus();
|
||||
|
||||
loadSnippets();
|
||||
|
||||
fitToWidth();
|
||||
window.addEventListener("resize", fitToWidth);
|
||||
}
|
||||
|
||||
|
||||
@ -210,13 +214,17 @@ function loadSnippets()
|
||||
let updateURL = localStorage["snippets-update-url"];
|
||||
if (updateURL && (!lastUpdate ||
|
||||
Date.now() - lastUpdate > SNIPPETS_UPDATE_INTERVAL_MS)) {
|
||||
// Try to update from network.
|
||||
let xhr = new XMLHttpRequest();
|
||||
try {
|
||||
xhr.open("GET", updateURL, true);
|
||||
} catch (ex) {
|
||||
showSnippets();
|
||||
return;
|
||||
}
|
||||
// Even if fetching should fail we don't want to spam the server, thus
|
||||
// set the last update time regardless its results. Will retry tomorrow.
|
||||
localStorage["snippets-last-update"] = Date.now();
|
||||
|
||||
// Try to update from network.
|
||||
let xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', updateURL, true);
|
||||
xhr.onerror = function (event) {
|
||||
showSnippets();
|
||||
};
|
||||
@ -260,7 +268,7 @@ function showSnippets()
|
||||
let defaultSnippetsElt = document.getElementById("defaultSnippets");
|
||||
let entries = defaultSnippetsElt.querySelectorAll("span");
|
||||
// Choose a random snippet. Assume there is always at least one.
|
||||
let randIndex = Math.round(Math.random() * (entries.length - 1));
|
||||
let randIndex = Math.floor(Math.random() * entries.length);
|
||||
let entry = entries[randIndex];
|
||||
// Inject url in the eventual link.
|
||||
if (DEFAULT_SNIPPETS_URLS[randIndex]) {
|
||||
@ -269,27 +277,17 @@ function showSnippets()
|
||||
// up in the translation.
|
||||
if (links.length == 1) {
|
||||
links[0].href = DEFAULT_SNIPPETS_URLS[randIndex];
|
||||
activateSnippetsButtonClick(entry);
|
||||
}
|
||||
}
|
||||
// Move the default snippet to the snippets element.
|
||||
snippetsElt.appendChild(entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches a single link element in aElt and binds its href to the click
|
||||
* action of the snippets button.
|
||||
*
|
||||
* @param aElt
|
||||
* Element to search the link into.
|
||||
*/
|
||||
function activateSnippetsButtonClick(aElt) {
|
||||
let links = aElt.getElementsByTagName("a");
|
||||
if (links.length == 1) {
|
||||
document.getElementById("snippets")
|
||||
.addEventListener("click", function(aEvent) {
|
||||
if (aEvent.target.nodeName != "a")
|
||||
window.location = links[0].href;
|
||||
}, false);
|
||||
function fitToWidth() {
|
||||
if (window.scrollMaxX) {
|
||||
document.body.setAttribute("narrow", "true");
|
||||
} else if (document.body.hasAttribute("narrow")) {
|
||||
document.body.removeAttribute("narrow");
|
||||
fitToWidth();
|
||||
}
|
||||
}
|
@ -25,6 +25,7 @@
|
||||
# Marco Bonardo <mak77@bonardo.net> (original author)
|
||||
# Mihai Sucan <mihai.sucan@gmail.com>
|
||||
# Stephen Horlander <shorlander@mozilla.com>
|
||||
# Frank Yan <fyan@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
|
||||
@ -60,52 +61,48 @@
|
||||
<link rel="icon" type="image/png" id="favicon"
|
||||
href="chrome://branding/content/icon16.png"/>
|
||||
<link rel="stylesheet" type="text/css" media="all"
|
||||
href="chrome://browser/content/aboutHome.css"/>
|
||||
href="chrome://browser/content/abouthome/aboutHome.css"/>
|
||||
|
||||
<script type="text/javascript;version=1.8"
|
||||
src="chrome://browser/content/aboutHome.js"/>
|
||||
src="chrome://browser/content/abouthome/aboutHome.js"/>
|
||||
</head>
|
||||
|
||||
<body dir="&locale.dir;" onload="onLoad(event)">
|
||||
<div id="brandStartSpacer" />
|
||||
<div id="brandStart">
|
||||
<img id="brandStartLogo" src="chrome://branding/content/about-logo.png" alt="" />
|
||||
</div>
|
||||
<div id="container">
|
||||
<div class="spacer"/>
|
||||
<div id="topSection">
|
||||
<img id="brandLogo" src="chrome://branding/content/about-logo.png" alt=""/>
|
||||
|
||||
<div id="searchContainer">
|
||||
<form name="searchForm" id="searchForm" onsubmit="onSearchSubmit(event)">
|
||||
<div id="searchLogoContainer"><img id="searchEngineLogo" /></div>
|
||||
<div id="searchInputContainer">
|
||||
<input type="text" name="q" value="" id="searchText" maxlength="256" />
|
||||
<div id="searchContainer">
|
||||
<form name="searchForm" id="searchForm" onsubmit="onSearchSubmit(event)">
|
||||
<div id="searchLogoContainer"><img id="searchEngineLogo"/></div>
|
||||
<input type="text" name="q" value="" id="searchText" maxlength="256"/>
|
||||
<input id="searchSubmit" type="submit" value="&abouthome.searchEngineButton.label;"/>
|
||||
</form>
|
||||
</div>
|
||||
<div id="searchButtons">
|
||||
<input id="searchSubmit" type="submit" value="&abouthome.searchEngineButton.label;" />
|
||||
|
||||
<div id="snippetContainer">
|
||||
<div id="defaultSnippets" hidden="true">
|
||||
<span id="defaultSnippet1">&abouthome.defaultSnippet1.v1;</span>
|
||||
<span id="defaultSnippet2">&abouthome.defaultSnippet2.v1;</span>
|
||||
</div>
|
||||
<div id="snippets"/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="spacer"/>
|
||||
|
||||
<div id="contentContainer">
|
||||
<div id="snippetContainer">
|
||||
<div id="defaultSnippets" hidden="true">
|
||||
<span id="defaultSnippet1">&abouthome.defaultSnippet1.v1;</span>
|
||||
<span id="defaultSnippet2">&abouthome.defaultSnippet2.v1;</span>
|
||||
</div>
|
||||
<div id="snippets"/>
|
||||
<div id="launcher" session="true">
|
||||
<button class="launchButton" id="bookmarks">&abouthome.bookmarksButton.label;</button>
|
||||
<button class="launchButton" id="history">&abouthome.historyButton.label;</button>
|
||||
<button class="launchButton" id="settings">&abouthome.settingsButton.label;</button>
|
||||
<button class="launchButton" id="addons">&abouthome.addonsButton.label;</button>
|
||||
<button class="launchButton" id="downloads">&abouthome.downloadsButton.label;</button>
|
||||
<button class="launchButton" id="sync">&syncBrand.shortName.label;</button>
|
||||
<div id="restorePreviousSessionSeparator"/>
|
||||
<button class="launchButton" id="restorePreviousSession">&historyRestoreLastSession.label;</button>
|
||||
</div>
|
||||
|
||||
<div id="sessionRestoreContainer">
|
||||
<button id="restorePreviousSession">&historyRestoreLastSession.label;</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="bottomSection">
|
||||
<div id="aboutMozilla">
|
||||
<a href="http://www.mozilla.com/about/">&abouthome.aboutMozilla;</a>
|
||||
</div>
|
||||
<div id="syncLinksContainer">
|
||||
<a href="javascript:void(0);" class="sync-link" id="setupSyncLink">&abouthome.syncSetup.label;</a>
|
||||
<a href="javascript:void(0);" class="sync-link" id="pairDeviceLink">&abouthome.pairDevice.label;</a>
|
||||
</div>
|
||||
<a id="aboutMozilla" href="http://www.mozilla.com/about/"/>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
BIN
browser/base/content/abouthome/addons.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
browser/base/content/abouthome/bookmarks.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
browser/base/content/abouthome/downloads.png
Normal file
After Width: | Height: | Size: 898 B |
BIN
browser/base/content/abouthome/history.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
browser/base/content/abouthome/mozilla.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
browser/base/content/abouthome/noise.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
browser/base/content/abouthome/restore-large.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
browser/base/content/abouthome/restore.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
browser/base/content/abouthome/settings.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
BIN
browser/base/content/abouthome/sync.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
@ -175,21 +175,7 @@ let gSyncUI = {
|
||||
this.clearError(title);
|
||||
},
|
||||
|
||||
// Set visibility of "Setup Sync" link
|
||||
showSetupSyncAboutHome: function SUI_showSetupSyncAboutHome(toShow) {
|
||||
let browsers = gBrowser.browsers;
|
||||
for (let i = 0; i < browsers.length; i++) {
|
||||
let b = browsers[i];
|
||||
if ("about:home" == b.currentURI.spec) {
|
||||
b.contentDocument.getElementById("setupSyncLink").hidden = !toShow;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onSetupComplete: function SUI_onSetupComplete() {
|
||||
// Remove "setup sync" link in about:home if it is open.
|
||||
this.showSetupSyncAboutHome(false);
|
||||
|
||||
onLoginFinish();
|
||||
},
|
||||
|
||||
@ -237,8 +223,6 @@ let gSyncUI = {
|
||||
|
||||
onStartOver: function SUI_onStartOver() {
|
||||
this.clearError();
|
||||
// Make "setup sync" link visible in about:home if it is open.
|
||||
this.showSetupSyncAboutHome(true);
|
||||
},
|
||||
|
||||
onQuotaNotice: function onQuotaNotice(subject, data) {
|
||||
|
@ -110,6 +110,15 @@ let gBrowserThumbnails = {
|
||||
|
||||
let channel = aBrowser.docShell.currentDocumentChannel;
|
||||
|
||||
// No valid document channel. We shouldn't take a screenshot.
|
||||
if (!channel)
|
||||
return false;
|
||||
|
||||
// Don't take screenshots of internally redirecting about: pages.
|
||||
// This includes error pages.
|
||||
if (channel.originalURI.schemeIs("about"))
|
||||
return false;
|
||||
|
||||
try {
|
||||
// If the channel is a nsIHttpChannel get its http status code.
|
||||
let httpChannel = channel.QueryInterface(Ci.nsIHttpChannel);
|
||||
|
@ -56,6 +56,7 @@
|
||||
# Patrick Walton <pcwalton@mozilla.com>
|
||||
# Mihai Sucan <mihai.sucan@gmail.com>
|
||||
# Victor Porof <vporof@mozilla.com>
|
||||
# Frank Yan <fyan@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
|
||||
@ -2706,11 +2707,7 @@ function BrowserOnAboutPageLoad(document) {
|
||||
let ss = Components.classes["@mozilla.org/browser/sessionstore;1"].
|
||||
getService(Components.interfaces.nsISessionStore);
|
||||
if (!ss.canRestoreLastSession)
|
||||
document.getElementById("sessionRestoreContainer").hidden = true;
|
||||
// Sync-related links
|
||||
if (Services.prefs.prefHasUserValue("services.sync.username")) {
|
||||
document.getElementById("setupSyncLink").hidden = true;
|
||||
}
|
||||
document.getElementById("launcher").removeAttribute("session");
|
||||
}
|
||||
}
|
||||
|
||||
@ -2718,19 +2715,17 @@ function BrowserOnAboutPageLoad(document) {
|
||||
* Handle command events bubbling up from error page content
|
||||
*/
|
||||
function BrowserOnClick(event) {
|
||||
// Don't trust synthetic events
|
||||
if (!event.isTrusted ||
|
||||
(event.target.localName != "button" &&
|
||||
event.target.className != "sync-link"))
|
||||
if (!event.isTrusted || // Don't trust synthetic events
|
||||
event.button == 2 || event.target.localName != "button")
|
||||
return;
|
||||
|
||||
var ot = event.originalTarget;
|
||||
var errorDoc = ot.ownerDocument;
|
||||
var ownerDoc = ot.ownerDocument;
|
||||
|
||||
// If the event came from an ssl error page, it is probably either the "Add
|
||||
// Exception…" or "Get me out of here!" button
|
||||
if (/^about:certerror/.test(errorDoc.documentURI)) {
|
||||
if (ot == errorDoc.getElementById('exceptionDialogButton')) {
|
||||
if (/^about:certerror/.test(ownerDoc.documentURI)) {
|
||||
if (ot == ownerDoc.getElementById('exceptionDialogButton')) {
|
||||
var params = { exceptionAdded : false, handlePrivateBrowsing : true };
|
||||
|
||||
try {
|
||||
@ -2738,7 +2733,7 @@ function BrowserOnClick(event) {
|
||||
case 2 : // Pre-fetch & pre-populate
|
||||
params.prefetchCert = true;
|
||||
case 1 : // Pre-populate
|
||||
params.location = errorDoc.location.href;
|
||||
params.location = ownerDoc.location.href;
|
||||
}
|
||||
} catch (e) {
|
||||
Components.utils.reportError("Couldn't get ssl_override pref: " + e);
|
||||
@ -2749,22 +2744,22 @@ function BrowserOnClick(event) {
|
||||
|
||||
// If the user added the exception cert, attempt to reload the page
|
||||
if (params.exceptionAdded)
|
||||
errorDoc.location.reload();
|
||||
ownerDoc.location.reload();
|
||||
}
|
||||
else if (ot == errorDoc.getElementById('getMeOutOfHereButton')) {
|
||||
else if (ot == ownerDoc.getElementById('getMeOutOfHereButton')) {
|
||||
getMeOutOfHere();
|
||||
}
|
||||
}
|
||||
else if (/^about:blocked/.test(errorDoc.documentURI)) {
|
||||
else if (/^about:blocked/.test(ownerDoc.documentURI)) {
|
||||
// The event came from a button on a malware/phishing block page
|
||||
// First check whether it's malware or phishing, so that we can
|
||||
// use the right strings/links
|
||||
var isMalware = /e=malwareBlocked/.test(errorDoc.documentURI);
|
||||
var isMalware = /e=malwareBlocked/.test(ownerDoc.documentURI);
|
||||
|
||||
if (ot == errorDoc.getElementById('getMeOutButton')) {
|
||||
if (ot == ownerDoc.getElementById('getMeOutButton')) {
|
||||
getMeOutOfHere();
|
||||
}
|
||||
else if (ot == errorDoc.getElementById('reportButton')) {
|
||||
else if (ot == ownerDoc.getElementById('reportButton')) {
|
||||
// This is the "Why is this site blocked" button. For malware,
|
||||
// we can fetch a site-specific report, for phishing, we redirect
|
||||
// to the generic page describing phishing protection.
|
||||
@ -2774,7 +2769,7 @@ function BrowserOnClick(event) {
|
||||
// append the current url, and go there.
|
||||
try {
|
||||
let reportURL = formatURL("browser.safebrowsing.malware.reportURL", true);
|
||||
reportURL += errorDoc.location.href;
|
||||
reportURL += ownerDoc.location.href;
|
||||
content.location = reportURL;
|
||||
} catch (e) {
|
||||
Components.utils.reportError("Couldn't get malware report URL: " + e);
|
||||
@ -2788,7 +2783,7 @@ function BrowserOnClick(event) {
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ot == errorDoc.getElementById('ignoreWarningButton')) {
|
||||
else if (ot == ownerDoc.getElementById('ignoreWarningButton')) {
|
||||
// Allow users to override and continue through to the site,
|
||||
// but add a notify bar as a reminder, so that they don't lose
|
||||
// track after, e.g., tab switching.
|
||||
@ -2843,23 +2838,31 @@ function BrowserOnClick(event) {
|
||||
);
|
||||
}
|
||||
}
|
||||
else if (/^about:home$/i.test(errorDoc.documentURI)) {
|
||||
if (ot == errorDoc.getElementById("restorePreviousSession")) {
|
||||
else if (/^about:home$/i.test(ownerDoc.documentURI)) {
|
||||
if (ot == ownerDoc.getElementById("restorePreviousSession")) {
|
||||
let ss = Cc["@mozilla.org/browser/sessionstore;1"].
|
||||
getService(Ci.nsISessionStore);
|
||||
if (ss.canRestoreLastSession)
|
||||
ss.restoreLastSession();
|
||||
errorDoc.getElementById("sessionRestoreContainer").hidden = true;
|
||||
ownerDoc.getElementById("launcher").removeAttribute("session");
|
||||
}
|
||||
else if (ot == errorDoc.getElementById("pairDeviceLink")) {
|
||||
if (Services.prefs.prefHasUserValue("services.sync.username")) {
|
||||
gSyncUI.openAddDevice();
|
||||
} else {
|
||||
gSyncUI.openSetup("pair");
|
||||
}
|
||||
else if (ot == ownerDoc.getElementById("bookmarks")) {
|
||||
PlacesCommandHook.showPlacesOrganizer("AllBookmarks");
|
||||
}
|
||||
else if (ot == errorDoc.getElementById("setupSyncLink")) {
|
||||
gSyncUI.openSetup(null);
|
||||
else if (ot == ownerDoc.getElementById("history")) {
|
||||
PlacesCommandHook.showPlacesOrganizer("History");
|
||||
}
|
||||
else if (ot == ownerDoc.getElementById("settings")) {
|
||||
openPreferences();
|
||||
}
|
||||
else if (ot == ownerDoc.getElementById("addons")) {
|
||||
BrowserOpenAddonsMgr();
|
||||
}
|
||||
else if (ot == ownerDoc.getElementById("downloads")) {
|
||||
BrowserDownloadsUI();
|
||||
}
|
||||
else if (ot == ownerDoc.getElementById("sync")) {
|
||||
openPreferences("paneSync");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5120,6 +5123,7 @@ var TabsProgressListener = {
|
||||
// document URI is not yet the about:-uri of the error page.
|
||||
|
||||
if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP &&
|
||||
Components.isSuccessCode(aStatus) &&
|
||||
/^about:/.test(aWebProgress.DOMWindow.document.documentURI)) {
|
||||
aBrowser.addEventListener("click", BrowserOnClick, false);
|
||||
aBrowser.addEventListener("pagehide", function () {
|
||||
|
@ -94,7 +94,11 @@ let gDrop = {
|
||||
// A new link was dragged onto the grid. Create it by pinning its URL.
|
||||
let dt = aEvent.dataTransfer;
|
||||
let [url, title] = dt.getData("text/x-moz-url").split(/[\r\n]+/);
|
||||
gPinnedLinks.pin({url: url, title: title}, index);
|
||||
let link = {url: url, title: title};
|
||||
gPinnedLinks.pin(link, index);
|
||||
|
||||
// Make sure the newly added link is not blocked.
|
||||
gBlockedLinks.unblock(link);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -92,6 +92,7 @@ nsContextMenu.prototype = {
|
||||
} catch (e) { }
|
||||
this.isTextSelected = this.isTextSelection();
|
||||
this.isContentSelected = this.isContentSelection();
|
||||
this.onPlainTextLink = false;
|
||||
|
||||
// Initialize (disable/remove) menu items.
|
||||
this.initItems();
|
||||
@ -132,7 +133,6 @@ nsContextMenu.prototype = {
|
||||
|
||||
// Time to do some bad things and see if we've highlighted a URL that
|
||||
// isn't actually linked.
|
||||
var onPlainTextLink = false;
|
||||
if (this.isTextSelected && !this.onLink) {
|
||||
// Ok, we have some text, let's figure out if it looks like a URL.
|
||||
let selection = document.commandDispatcher.focusedWindow
|
||||
@ -190,14 +190,14 @@ nsContextMenu.prototype = {
|
||||
if (uri && uri.host) {
|
||||
this.linkURI = uri;
|
||||
this.linkURL = this.linkURI.spec;
|
||||
onPlainTextLink = true;
|
||||
this.onPlainTextLink = true;
|
||||
}
|
||||
}
|
||||
|
||||
var shouldShow = this.onSaveableLink || isMailtoInternal || onPlainTextLink;
|
||||
var shouldShow = this.onSaveableLink || isMailtoInternal || this.onPlainTextLink;
|
||||
this.showItem("context-openlink", shouldShow);
|
||||
this.showItem("context-openlinkintab", shouldShow);
|
||||
this.showItem("context-openlinkincurrent", onPlainTextLink);
|
||||
this.showItem("context-openlinkincurrent", this.onPlainTextLink);
|
||||
this.showItem("context-sep-open", shouldShow);
|
||||
},
|
||||
|
||||
@ -222,9 +222,9 @@ nsContextMenu.prototype = {
|
||||
this.showItem("context-savepage", shouldShow);
|
||||
this.showItem("context-sendpage", shouldShow);
|
||||
|
||||
// Save+Send link depends on whether we're in a link.
|
||||
this.showItem("context-savelink", this.onSaveableLink);
|
||||
this.showItem("context-sendlink", this.onSaveableLink);
|
||||
// Save+Send link depends on whether we're in a link, or selected text matches valid URL pattern.
|
||||
this.showItem("context-savelink", this.onSaveableLink || this.onPlainTextLink);
|
||||
this.showItem("context-sendlink", this.onSaveableLink || this.onPlainTextLink);
|
||||
|
||||
// Save image depends on having loaded its content, video and audio don't.
|
||||
this.showItem("context-saveimage", this.onLoadedImage || this.onCanvas);
|
||||
@ -310,7 +310,7 @@ nsContextMenu.prototype = {
|
||||
this.showItem("context-bookmarkpage",
|
||||
!(this.isContentSelected || this.onTextInput || this.onLink ||
|
||||
this.onImage || this.onVideo || this.onAudio));
|
||||
this.showItem("context-bookmarklink", this.onLink && !this.onMailtoLink);
|
||||
this.showItem("context-bookmarklink", (this.onLink && !this.onMailtoLink) || this.onPlainTextLink);
|
||||
this.showItem("context-searchselect", isTextSelected);
|
||||
this.showItem("context-keywordfield",
|
||||
this.onTextInput && this.onKeywordField);
|
||||
@ -1073,9 +1073,15 @@ nsContextMenu.prototype = {
|
||||
// Save URL of clicked-on link.
|
||||
saveLink: function() {
|
||||
var doc = this.target.ownerDocument;
|
||||
var linkText;
|
||||
// If selected text is found to match valid URL pattern.
|
||||
if (this.onPlainTextLink)
|
||||
linkText = document.commandDispatcher.focusedWindow.getSelection().toString().trim();
|
||||
else
|
||||
linkText = this.linkText();
|
||||
urlSecurityCheck(this.linkURL, doc.nodePrincipal);
|
||||
|
||||
this.saveHelper(this.linkURL, this.linkText(), null, true, doc);
|
||||
this.saveHelper(this.linkURL, linkText, null, true, doc);
|
||||
},
|
||||
|
||||
sendLink: function() {
|
||||
@ -1390,8 +1396,14 @@ nsContextMenu.prototype = {
|
||||
},
|
||||
|
||||
bookmarkLink: function CM_bookmarkLink() {
|
||||
var linkText;
|
||||
// If selected text is found to match valid URL pattern.
|
||||
if (this.onPlainTextLink)
|
||||
linkText = document.commandDispatcher.focusedWindow.getSelection().toString().trim();
|
||||
else
|
||||
linkText = this.linkText();
|
||||
window.top.PlacesCommandHook.bookmarkLink(PlacesUtils.bookmarksMenuFolderId, this.linkURL,
|
||||
this.linkText());
|
||||
linkText);
|
||||
},
|
||||
|
||||
addBookmarkForFrame: function CM_addBookmarkForFrame() {
|
||||
|
@ -10,9 +10,6 @@ registerCleanupFunction(function() {
|
||||
try {
|
||||
Services.prefs.clearUserPref("network.cookie.lifetimePolicy");
|
||||
} catch (ex) {}
|
||||
try {
|
||||
Services.prefs.clearUserPref("services.sync.username");
|
||||
} catch (ex) {}
|
||||
});
|
||||
|
||||
let gTests = [
|
||||
@ -112,121 +109,11 @@ let gTests = [
|
||||
ok(snippetsElt, "Found snippets element");
|
||||
is(snippetsElt.getElementsByTagName("span").length, 1,
|
||||
"A default snippet is visible.");
|
||||
|
||||
let storage = getStorage();
|
||||
storage.removeItem("snippets");
|
||||
executeSoon(runNextTest);
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
desc: "Check sync links visibility before and after Sync setup",
|
||||
setup: function ()
|
||||
{
|
||||
try {
|
||||
Services.prefs.clearUserPref("services.sync.username");
|
||||
} catch (ex) {}
|
||||
Services.obs.notifyObservers(null, "weave:service:ready", null);
|
||||
},
|
||||
run: function ()
|
||||
{
|
||||
let doc = gBrowser.selectedTab.linkedBrowser.contentDocument;
|
||||
let pairLink = doc.getElementById("pairDeviceLink");
|
||||
let setupLink = doc.getElementById("setupSyncLink");
|
||||
|
||||
ok(pairLink, "Found 'Pair Device' link");
|
||||
ok(setupLink, "Found 'Set Up Sync' link");
|
||||
ok(!pairLink.hidden, "'Pair' link is visible before setup");
|
||||
ok(!setupLink.hidden, "'Set Up' link is visible before setup");
|
||||
|
||||
Services.obs.notifyObservers(null, "weave:service:setup-complete", null);
|
||||
|
||||
executeSoon(function () {
|
||||
setupLink = doc.getElementById("setupSyncLink");
|
||||
ok(setupLink.hidden, "'Set Up' link is hidden after setup");
|
||||
ok(!pairLink.hidden, "'Pair' link is visible after setup");
|
||||
|
||||
executeSoon(runNextTest);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
desc: "Check sync links visibility before and after Sync unlink",
|
||||
setup: function ()
|
||||
{
|
||||
Services.prefs.setCharPref("services.sync.username", "someuser@domain.com");
|
||||
Services.obs.notifyObservers(null, "weave:service:ready", null);
|
||||
},
|
||||
run: function ()
|
||||
{
|
||||
let doc = gBrowser.selectedTab.linkedBrowser.contentDocument;
|
||||
let pairLink = doc.getElementById("pairDeviceLink");
|
||||
let setupLink = doc.getElementById("setupSyncLink");
|
||||
|
||||
ok(!pairLink.hidden, "'Pair' link is visible before unlink");
|
||||
ok(setupLink.hidden, "'Set Up' link is hidden before unlink");
|
||||
|
||||
Services.obs.notifyObservers(null, "weave:service:start-over", null);
|
||||
|
||||
executeSoon(function () {
|
||||
setupLink = doc.getElementById("setupSyncLink");
|
||||
ok(!setupLink.hidden, "'Set Up' link is visible after unlink");
|
||||
ok(!pairLink.hidden, "'Pair' link is visible after unlink");
|
||||
executeSoon(runNextTest);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
desc: "Check Pair Device link opens correct dialog with Sync account ",
|
||||
setup: function ()
|
||||
{
|
||||
Services.prefs.setCharPref("services.sync.username", "someuser@domain.com");
|
||||
Services.obs.notifyObservers(null, "weave:service:ready", null);
|
||||
},
|
||||
run: function ()
|
||||
{
|
||||
expectDialogWindow("Sync:AddDevice");
|
||||
let browser = gBrowser.selectedTab.linkedBrowser;
|
||||
let button = browser.contentDocument.getElementById("pairDeviceLink");
|
||||
EventUtils.sendMouseEvent({type: "click"}, button, browser.contentWindow);
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
desc: "Check Pair Device link opens correct dialog without Sync account",
|
||||
setup: function ()
|
||||
{
|
||||
try {
|
||||
Services.prefs.clearUserPref("services.sync.username");
|
||||
} catch (ex) {}
|
||||
Services.obs.notifyObservers(null, "weave:service:ready", null);
|
||||
},
|
||||
run: function ()
|
||||
{
|
||||
expectDialogWindow("Weave:AccountSetup");
|
||||
let browser = gBrowser.selectedTab.linkedBrowser;
|
||||
let button = browser.contentDocument.getElementById("pairDeviceLink");
|
||||
EventUtils.sendMouseEvent({type: "click"}, button, browser.contentWindow);
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
desc: "Check Sync Setup link opens correct dialog (without Sync account)",
|
||||
setup: function ()
|
||||
{
|
||||
try {
|
||||
Services.prefs.clearUserPref("services.sync.username");
|
||||
} catch (ex) {}
|
||||
Services.obs.notifyObservers(null, "weave:service:ready", null);
|
||||
},
|
||||
run: function ()
|
||||
{
|
||||
expectDialogWindow("Weave:AccountSetup");
|
||||
let browser = gBrowser.selectedTab.linkedBrowser;
|
||||
let button = browser.contentDocument.getElementById("setupSyncLink");
|
||||
EventUtils.sendMouseEvent({type: "click"}, button, browser.contentWindow);
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
function test()
|
||||
@ -272,22 +159,6 @@ function runNextTest()
|
||||
}
|
||||
}
|
||||
|
||||
function expectDialogWindow(expectedDialog) {
|
||||
Services.ww.registerNotification(function onWindow(subject, topic) {
|
||||
let win = subject.QueryInterface(Components.interfaces.nsIDOMWindow);
|
||||
win.addEventListener("load", function onLoad() {
|
||||
win.removeEventListener("load", onLoad, false);
|
||||
let wintype = win.document.documentElement.getAttribute("windowtype");
|
||||
if (topic == "domwindowopened" && wintype == expectedDialog) {
|
||||
Services.ww.unregisterNotification(onWindow);
|
||||
// Clean up dialog.
|
||||
win.close();
|
||||
executeSoon(runNextTest);
|
||||
}
|
||||
}, false);
|
||||
});
|
||||
}
|
||||
|
||||
function getStorage()
|
||||
{
|
||||
let aboutHomeURI = Services.io.newURI("moz-safe-about:home", null, null);
|
||||
|
@ -25,6 +25,7 @@ _BROWSER_FILES = \
|
||||
browser_newtab_bug723121.js \
|
||||
browser_newtab_bug725996.js \
|
||||
browser_newtab_bug734043.js \
|
||||
browser_newtab_bug735987.js \
|
||||
head.js \
|
||||
$(NULL)
|
||||
|
||||
|
@ -25,7 +25,7 @@ function runTests() {
|
||||
checkGrid("0,1,2,3,7,8,9,,");
|
||||
|
||||
// we removed a pinned site
|
||||
reset();
|
||||
yield restore();
|
||||
setLinks("0,1,2,3,4,5,6,7,8");
|
||||
setPinnedLinks(",1");
|
||||
|
||||
@ -37,7 +37,7 @@ function runTests() {
|
||||
|
||||
// we remove the last site on the grid (which is pinned) and expect the gap
|
||||
// to be re-filled and the new site to be unpinned
|
||||
reset();
|
||||
yield restore();
|
||||
setLinks("0,1,2,3,4,5,6,7,8,9");
|
||||
setPinnedLinks(",,,,,,,,8");
|
||||
|
||||
@ -49,7 +49,7 @@ function runTests() {
|
||||
|
||||
// we remove the first site on the grid with the last one pinned. all cells
|
||||
// but the last one should shift to the left and a new site fades in
|
||||
reset();
|
||||
yield restore();
|
||||
setLinks("0,1,2,3,4,5,6,7,8,9");
|
||||
setPinnedLinks(",,,,,,,,8");
|
||||
|
||||
|
@ -2,13 +2,11 @@
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function runTests() {
|
||||
// TODO Bug 735166 - Intermittent timeout in browser_newtab_bug734043.js
|
||||
return;
|
||||
|
||||
setLinks("0,1,2,3,4,5,6,7,8");
|
||||
setPinnedLinks("");
|
||||
|
||||
yield addNewTabPageTab();
|
||||
checkGrid("0,1,2,3,4,5,6,7,8");
|
||||
|
||||
let receivedError = false;
|
||||
let block = cw.document.querySelector(".newtab-control-block");
|
||||
@ -19,10 +17,8 @@ function runTests() {
|
||||
|
||||
cw.addEventListener("error", onError);
|
||||
|
||||
for (let i = 0; i < 3; i++) {
|
||||
for (let i = 0; i < 3; i++)
|
||||
EventUtils.synthesizeMouseAtCenter(block, {}, cw);
|
||||
yield executeSoon(TestRunner.next);
|
||||
}
|
||||
|
||||
yield whenPagesUpdated();
|
||||
ok(!receivedError, "we got here without any errors");
|
||||
|
22
browser/base/content/test/newtab/browser_newtab_bug735987.js
Normal file
@ -0,0 +1,22 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function runTests() {
|
||||
setLinks("0,1,2,3,4,5,6,7,8");
|
||||
setPinnedLinks("");
|
||||
|
||||
yield addNewTabPageTab();
|
||||
checkGrid("0,1,2,3,4,5,6,7,8");
|
||||
|
||||
yield simulateDrop(cells[1]);
|
||||
checkGrid("0,99p,1,2,3,4,5,6,7");
|
||||
|
||||
yield blockCell(cells[1]);
|
||||
checkGrid("0,1,2,3,4,5,6,7,8");
|
||||
|
||||
yield simulateDrop(cells[1]);
|
||||
checkGrid("0,99p,1,2,3,4,5,6,7");
|
||||
|
||||
yield blockCell(cells[1]);
|
||||
checkGrid("0,1,2,3,4,5,6,7,8");
|
||||
}
|
@ -10,8 +10,6 @@ Cu.import("resource:///modules/NewTabUtils.jsm", tmp);
|
||||
let NewTabUtils = tmp.NewTabUtils;
|
||||
|
||||
registerCleanupFunction(function () {
|
||||
reset();
|
||||
|
||||
while (gBrowser.tabs.length > 1)
|
||||
gBrowser.removeTab(gBrowser.tabs[1]);
|
||||
|
||||
@ -57,8 +55,29 @@ let TestRunner = {
|
||||
try {
|
||||
TestRunner._iter.next();
|
||||
} catch (e if e instanceof StopIteration) {
|
||||
finish();
|
||||
TestRunner.finish();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Finishes all tests and cleans up.
|
||||
*/
|
||||
finish: function () {
|
||||
function cleanupAndFinish() {
|
||||
// Restore the old provider.
|
||||
NewTabUtils.links._provider = originalProvider;
|
||||
|
||||
whenPagesUpdated(finish);
|
||||
NewTabUtils.restore();
|
||||
}
|
||||
|
||||
let callbacks = NewTabUtils.links._populateCallbacks;
|
||||
let numCallbacks = callbacks.length;
|
||||
|
||||
if (numCallbacks)
|
||||
callbacks.splice(0, numCallbacks, cleanupAndFinish);
|
||||
else
|
||||
cleanupAndFinish();
|
||||
}
|
||||
};
|
||||
|
||||
@ -106,13 +125,11 @@ function setPinnedLinks(aLinksPattern) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the lists of blocked and pinned links and clears the storage.
|
||||
* Restore the grid state.
|
||||
*/
|
||||
function reset() {
|
||||
NewTabUtils.reset();
|
||||
|
||||
// Restore the old provider to prevent memory leaks.
|
||||
NewTabUtils.links._provider = originalProvider;
|
||||
function restore() {
|
||||
whenPagesUpdated();
|
||||
NewTabUtils.restore();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -269,11 +286,11 @@ function simulateDrop(aDropTarget, aDragSource) {
|
||||
/**
|
||||
* Resumes testing when all pages have been updated.
|
||||
*/
|
||||
function whenPagesUpdated() {
|
||||
function whenPagesUpdated(aCallback) {
|
||||
let page = {
|
||||
update: function () {
|
||||
NewTabUtils.allPages.unregister(this);
|
||||
executeSoon(TestRunner.next);
|
||||
executeSoon(aCallback || TestRunner.next);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -58,6 +58,8 @@ Browser context menu subtest.
|
||||
<menuitem></menuitem>
|
||||
</menu>
|
||||
</div>
|
||||
<div id="test-select-text">Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</div>
|
||||
<div id="test-select-text-link">http://mozilla.com</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
@ -20,6 +20,7 @@ Browser context menu tests.
|
||||
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
Components.utils.import("resource://gre/modules/InlineSpellChecker.jsm");
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
@ -72,6 +73,16 @@ function invokeItemAction(generatedItemId)
|
||||
ok(!pagemenu.hasAttribute("hopeless"), "attribute got removed");
|
||||
}
|
||||
|
||||
function selectText(element) {
|
||||
// Clear any previous selections before selecting new element.
|
||||
subwindow.getSelection().removeAllRanges();
|
||||
|
||||
var div = subwindow.document.createRange();
|
||||
div.setStartBefore(element);
|
||||
div.setEndAfter(element);
|
||||
subwindow.getSelection().addRange(div);
|
||||
}
|
||||
|
||||
function getVisibleMenuItems(aMenu, aData) {
|
||||
var items = [];
|
||||
var accessKeys = {};
|
||||
@ -667,6 +678,45 @@ function runTest(testNum) {
|
||||
"context-viewinfo", true
|
||||
].concat(inspectItems));
|
||||
closeContextMenu();
|
||||
selectText(selecttext); // Select text prior to opening context menu.
|
||||
openContextMenuFor(selecttext); // Invoke context menu for next test.
|
||||
return;
|
||||
|
||||
case 22:
|
||||
// Context menu for selected text
|
||||
if (Services.appinfo.OS == "Darwin") {
|
||||
// This test is only enabled on Mac due to bug 736399.
|
||||
checkContextMenu(["context-copy", true,
|
||||
"context-selectall", true,
|
||||
"---", null,
|
||||
"context-searchselect", true,
|
||||
"context-viewpartialsource-selection", true
|
||||
].concat(inspectItems));
|
||||
}
|
||||
closeContextMenu();
|
||||
selectText(selecttextlink); // Select text prior to opening context menu.
|
||||
openContextMenuFor(selecttextlink); // Invoke context menu for next test.
|
||||
return;
|
||||
|
||||
case 23:
|
||||
// Context menu for selected text which matches valid URL pattern
|
||||
if (Services.appinfo.OS == "Darwin") {
|
||||
// This test is only enabled on Mac due to bug 736399.
|
||||
checkContextMenu(["context-openlinkincurrent", true,
|
||||
"context-openlinkintab", true,
|
||||
"context-openlink", true,
|
||||
"---", null,
|
||||
"context-bookmarklink", true,
|
||||
"context-savelink", true,
|
||||
"context-sendlink", true,
|
||||
"context-copy", true,
|
||||
"context-selectall", true,
|
||||
"---", null,
|
||||
"context-searchselect", true,
|
||||
"context-viewpartialsource-selection", true
|
||||
].concat(inspectItems));
|
||||
}
|
||||
closeContextMenu();
|
||||
|
||||
subwindow.close();
|
||||
SimpleTest.finish();
|
||||
@ -674,7 +724,6 @@ function runTest(testNum) {
|
||||
|
||||
/*
|
||||
* Other things that would be nice to test:
|
||||
* - selected text
|
||||
* - spelling / misspelled word (in text input?)
|
||||
* - check state of disabled items
|
||||
* - test execution of menu items (maybe as a separate test?)
|
||||
@ -734,6 +783,8 @@ function startTest() {
|
||||
contenteditable.focus(); // content editable needs to be focused to enable spellcheck
|
||||
inputspell = subwindow.document.getElementById("test-input-spellcheck");
|
||||
pagemenu = subwindow.document.getElementById("test-pagemenu");
|
||||
selecttext = subwindow.document.getElementById("test-select-text");
|
||||
selecttextlink = subwindow.document.getElementById("test-select-text-link");
|
||||
|
||||
contextMenu.addEventListener("popupshown", function() { runTest(++testNum); }, false);
|
||||
runTest(1);
|
||||
|
@ -110,11 +110,33 @@ function getBoolPref(prefname, def)
|
||||
}
|
||||
}
|
||||
|
||||
// openUILink handles clicks on UI elements that cause URLs to load.
|
||||
function openUILink( url, e, ignoreButton, ignoreAlt, allowKeywordFixup, postData, referrerUrl )
|
||||
{
|
||||
var where = whereToOpenLink(e, ignoreButton, ignoreAlt);
|
||||
openUILinkIn(url, where, allowKeywordFixup, postData, referrerUrl);
|
||||
/* openUILink handles clicks on UI elements that cause URLs to load.
|
||||
*
|
||||
* As the third argument, you may pass an object with the same properties as
|
||||
* accepted by openUILinkIn, plus "ignoreButton" and "ignoreAlt".
|
||||
*/
|
||||
function openUILink(url, event, aIgnoreButton, aIgnoreAlt, aAllowThirdPartyFixup,
|
||||
aPostData, aReferrerURI) {
|
||||
let params;
|
||||
|
||||
if (aIgnoreButton && typeof aIgnoreButton == "object") {
|
||||
params = aIgnoreButton;
|
||||
|
||||
// don't forward "ignoreButton" and "ignoreAlt" to openUILinkIn
|
||||
aIgnoreButton = params.ignoreButton;
|
||||
aIgnoreAlt = params.ignoreAlt;
|
||||
delete params.ignoreButton;
|
||||
delete params.ignoreAlt;
|
||||
} else {
|
||||
params = {
|
||||
allowThirdPartyFixup: aAllowThirdPartyFixup,
|
||||
postData: aPostData,
|
||||
referrerURI: aReferrerURI
|
||||
};
|
||||
}
|
||||
|
||||
let where = whereToOpenLink(event, aIgnoreButton, aIgnoreAlt);
|
||||
openUILinkIn(url, where, params);
|
||||
}
|
||||
|
||||
|
||||
|
@ -16,13 +16,21 @@ browser.jar:
|
||||
* content/browser/aboutDialog.js (content/aboutDialog.js)
|
||||
* content/browser/aboutDialog.css (content/aboutDialog.css)
|
||||
* content/browser/aboutRobots.xhtml (content/aboutRobots.xhtml)
|
||||
* content/browser/aboutHome.xhtml (content/aboutHome.xhtml)
|
||||
* content/browser/aboutHome.js (content/aboutHome.js)
|
||||
* content/browser/aboutHome.css (content/aboutHome.css)
|
||||
content/browser/aboutHome-restore-icon.png (content/aboutHome-restore-icon.png)
|
||||
content/browser/aboutHome-restore-icon-small.png (content/aboutHome-restore-icon-small.png)
|
||||
content/browser/aboutHome-snippet1.png (content/aboutHome-snippet1.png)
|
||||
content/browser/aboutHome-snippet2.png (content/aboutHome-snippet2.png)
|
||||
* content/browser/abouthome/aboutHome.xhtml (content/abouthome/aboutHome.xhtml)
|
||||
* content/browser/abouthome/aboutHome.js (content/abouthome/aboutHome.js)
|
||||
* content/browser/abouthome/aboutHome.css (content/abouthome/aboutHome.css)
|
||||
content/browser/abouthome/snippet1.png (content/abouthome/snippet1.png)
|
||||
content/browser/abouthome/snippet2.png (content/abouthome/snippet2.png)
|
||||
content/browser/abouthome/bookmarks.png (content/abouthome/bookmarks.png)
|
||||
content/browser/abouthome/history.png (content/abouthome/history.png)
|
||||
content/browser/abouthome/settings.png (content/abouthome/settings.png)
|
||||
content/browser/abouthome/addons.png (content/abouthome/addons.png)
|
||||
content/browser/abouthome/downloads.png (content/abouthome/downloads.png)
|
||||
content/browser/abouthome/sync.png (content/abouthome/sync.png)
|
||||
content/browser/abouthome/restore.png (content/abouthome/restore.png)
|
||||
content/browser/abouthome/restore-large.png (content/abouthome/restore-large.png)
|
||||
content/browser/abouthome/mozilla.png (content/abouthome/mozilla.png)
|
||||
content/browser/abouthome/noise.png (content/abouthome/noise.png)
|
||||
content/browser/aboutRobots-icon.png (content/aboutRobots-icon.png)
|
||||
content/browser/aboutRobots-widget-left.png (content/aboutRobots-widget-left.png)
|
||||
* content/browser/browser.css (content/browser.css)
|
||||
|
@ -102,7 +102,7 @@ static RedirEntry kRedirMap[] = {
|
||||
{ "sync-tabs", "chrome://browser/content/sync/aboutSyncTabs.xul",
|
||||
nsIAboutModule::ALLOW_SCRIPT },
|
||||
#endif
|
||||
{ "home", "chrome://browser/content/aboutHome.xhtml",
|
||||
{ "home", "chrome://browser/content/abouthome/aboutHome.xhtml",
|
||||
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
|
||||
nsIAboutModule::ALLOW_SCRIPT },
|
||||
{ "newtab", "chrome://browser/content/newtab/newTab.xul",
|
||||
|
@ -887,7 +887,7 @@ let AboutHomeUtils = {
|
||||
|
||||
loadSnippetsURL: function AHU_loadSnippetsURL()
|
||||
{
|
||||
const STARTPAGE_VERSION = 1;
|
||||
const STARTPAGE_VERSION = 2;
|
||||
let updateURL = Services.prefs
|
||||
.getCharPref(this.SNIPPETS_URL_PREF)
|
||||
.replace("%STARTPAGE_VERSION%", STARTPAGE_VERSION);
|
||||
|
@ -68,7 +68,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "KeywordURLResetPrompter",
|
||||
"resource:///modules/KeywordURLResetPrompter.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "webappsUI",
|
||||
"resource://gre/modules/webappsUI.jsm");
|
||||
"resource:///modules/webappsUI.jsm");
|
||||
|
||||
const PREF_PLUGINS_NOTIFYUSER = "plugins.update.notifyUser";
|
||||
const PREF_PLUGINS_UPDATEURL = "plugins.update.url";
|
||||
|
@ -231,73 +231,8 @@ var tests = [
|
||||
}
|
||||
catch (e) {}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
desc: "HTML restore into folder: normal restore should succeed",
|
||||
currTopic: NSIOBSERVER_TOPIC_BEGIN,
|
||||
finalTopic: NSIOBSERVER_TOPIC_SUCCESS,
|
||||
data: NSIOBSERVER_DATA_HTML,
|
||||
run: function () {
|
||||
this.file = createFile("bookmarks-test_restoreNotification.html");
|
||||
addBookmarks();
|
||||
importer.exportHTMLToFile(this.file);
|
||||
remove_all_bookmarks();
|
||||
this.folderId = bmsvc.createFolder(bmsvc.unfiledBookmarksFolder,
|
||||
"test folder",
|
||||
bmsvc.DEFAULT_INDEX);
|
||||
print(" Sanity check: createFolder() should have succeeded");
|
||||
do_check_true(this.folderId > 0);
|
||||
try {
|
||||
importer.importHTMLFromFileToFolder(this.file, this.folderId, false);
|
||||
}
|
||||
catch (e) {
|
||||
do_throw(" Restore should not have failed");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
desc: "HTML restore into folder: empty file should succeed",
|
||||
currTopic: NSIOBSERVER_TOPIC_BEGIN,
|
||||
finalTopic: NSIOBSERVER_TOPIC_SUCCESS,
|
||||
data: NSIOBSERVER_DATA_HTML,
|
||||
run: function () {
|
||||
this.file = createFile("bookmarks-test_restoreNotification.init.html");
|
||||
this.folderId = bmsvc.createFolder(bmsvc.unfiledBookmarksFolder,
|
||||
"test folder",
|
||||
bmsvc.DEFAULT_INDEX);
|
||||
print(" Sanity check: createFolder() should have succeeded");
|
||||
do_check_true(this.folderId > 0);
|
||||
try {
|
||||
importer.importHTMLFromFileToFolder(this.file, this.folderId, false);
|
||||
}
|
||||
catch (e) {
|
||||
do_throw(" Restore should not have failed");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
desc: "HTML restore into folder: nonexistent file should fail",
|
||||
currTopic: NSIOBSERVER_TOPIC_BEGIN,
|
||||
finalTopic: NSIOBSERVER_TOPIC_FAILED,
|
||||
data: NSIOBSERVER_DATA_HTML,
|
||||
run: function () {
|
||||
this.file = Services.dirsvc.get("ProfD", Ci.nsILocalFile);
|
||||
this.file.append("this file doesn't exist because nobody created it");
|
||||
this.folderId = bmsvc.createFolder(bmsvc.unfiledBookmarksFolder,
|
||||
"test folder",
|
||||
bmsvc.DEFAULT_INDEX);
|
||||
print(" Sanity check: createFolder() should have succeeded");
|
||||
do_check_true(this.folderId > 0);
|
||||
try {
|
||||
importer.importHTMLFromFileToFolder(this.file, this.folderId, false);
|
||||
do_throw(" Restore should have failed");
|
||||
}
|
||||
catch (e) {}
|
||||
}
|
||||
}
|
||||
|
||||
];
|
||||
|
||||
// nsIObserver that observes bookmarks-restore-begin.
|
||||
|
@ -218,58 +218,6 @@ add_test(function test_emptytitle_export()
|
||||
});
|
||||
});
|
||||
|
||||
add_test(function test_import_preplaces_to_folder()
|
||||
{
|
||||
// Test importing a pre-Places canonical bookmarks file to a specific folder.
|
||||
// 1. create a new folder
|
||||
// 2. import bookmarks.preplaces.html to that folder
|
||||
// 3. run the test-suite
|
||||
|
||||
let testFolder = PlacesUtils.bookmarks.createFolder(
|
||||
PlacesUtils.bookmarksMenuFolderId, "test-import",
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX
|
||||
);
|
||||
try {
|
||||
importer.importHTMLFromFileToFolder(gBookmarksFileOld, testFolder, false);
|
||||
} catch(ex) { do_throw("couldn't import the exported file to folder: " + ex); }
|
||||
|
||||
waitForAsyncUpdates(function () {
|
||||
// Import-to-folder creates subfolders for toolbar and unfiled.
|
||||
testImportedBookmarksToFolder(testFolder);
|
||||
|
||||
waitForAsyncUpdates(function () {
|
||||
remove_all_bookmarks();
|
||||
run_next_test();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
add_test(function test_import_to_folder()
|
||||
{
|
||||
// Test importing a Places canonical bookmarks file to a specific folder.
|
||||
// 1. create a new folder
|
||||
// 2. import bookmarks.exported.html to that folder
|
||||
// 3. run the test-suite
|
||||
|
||||
let testFolder = PlacesUtils.bookmarks.createFolder(
|
||||
PlacesUtils.bookmarksMenuFolderId, "test-import",
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX
|
||||
);
|
||||
try {
|
||||
importer.importHTMLFromFileToFolder(gBookmarksFileNew, testFolder, false);
|
||||
} catch(ex) { do_throw("couldn't import the exported file to folder: " + ex); }
|
||||
|
||||
waitForAsyncUpdates(function () {
|
||||
// Import-to-folder creates subfolders for toolbar and unfiled.
|
||||
testImportedBookmarksToFolder(testFolder);
|
||||
|
||||
waitForAsyncUpdates(function () {
|
||||
remove_all_bookmarks();
|
||||
run_next_test();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
add_test(function test_import_ontop()
|
||||
{
|
||||
// Test importing the exported bookmarks.html file *on top of* the existing
|
||||
|
@ -72,7 +72,7 @@ const Cr = Components.results;
|
||||
const Cu = Components.utils;
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource:///modules/TelemetryStopwatch.jsm");
|
||||
Cu.import("resource://gre/modules/TelemetryStopwatch.jsm");
|
||||
|
||||
const STATE_RUNNING_STR = "running";
|
||||
const MAX_FILE_SIZE = 100 * 1024 * 1024; // 100 megabytes
|
||||
|
@ -131,7 +131,7 @@ Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/debug.js");
|
||||
|
||||
Cu.import("resource:///modules/TelemetryTimestamps.jsm");
|
||||
Cu.import("resource:///modules/TelemetryStopwatch.jsm");
|
||||
Cu.import("resource://gre/modules/TelemetryStopwatch.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "NetUtil", function() {
|
||||
Cu.import("resource://gre/modules/NetUtil.jsm");
|
||||
|
@ -36,9 +36,8 @@
|
||||
|
||||
function test() {
|
||||
/** Test for Bug 484108 **/
|
||||
requestLongerTimeout(2);
|
||||
|
||||
waitForExplicitFinish();
|
||||
requestLongerTimeout(3);
|
||||
|
||||
// builds the tests state based on a few parameters
|
||||
function buildTestState(num, selected, hidden) {
|
||||
@ -54,109 +53,105 @@ function test() {
|
||||
return state;
|
||||
}
|
||||
|
||||
// builds an array of the indexs we expect to see in the order they get loaded
|
||||
function buildExpectedOrder(num, selected, shown) {
|
||||
// assume selected is 1-based index
|
||||
selected--;
|
||||
let expected = [selected];
|
||||
// fill left to selected if space
|
||||
for (let i = selected - (shown - expected.length); i >= 0 && i < selected; i++)
|
||||
expected.push(i);
|
||||
// fill from left to right until right length or end
|
||||
for (let i = selected + 1; expected.length < shown && i < num; i++)
|
||||
expected.push(i);
|
||||
// fill in the remaining
|
||||
for (let i = 0; i < num; i++) {
|
||||
if (expected.indexOf(i) == -1) {
|
||||
expected.push(i);
|
||||
}
|
||||
let tests = [
|
||||
{ testNum: 1,
|
||||
totalTabs: 13,
|
||||
selectedTab: 1,
|
||||
shownTabs: 6,
|
||||
hiddenTabs: [],
|
||||
order: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
|
||||
},
|
||||
{ testNum: 2,
|
||||
totalTabs: 13,
|
||||
selectedTab: 13,
|
||||
shownTabs: 6,
|
||||
hiddenTabs: [],
|
||||
order: [12, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6]
|
||||
},
|
||||
{ testNum: 3,
|
||||
totalTabs: 13,
|
||||
selectedTab: 4,
|
||||
shownTabs: 6,
|
||||
hiddenTabs: [],
|
||||
order: [3, 4, 5, 6, 7, 8, 0, 1, 2, 9, 10, 11, 12]
|
||||
},
|
||||
{ testNum: 4,
|
||||
totalTabs: 13,
|
||||
selectedTab: 11,
|
||||
shownTabs: 6,
|
||||
hiddenTabs: [],
|
||||
order: [10, 7, 8, 9, 11, 12, 0, 1, 2, 3, 4, 5, 6]
|
||||
},
|
||||
{ testNum: 5,
|
||||
totalTabs: 13,
|
||||
selectedTab: 13,
|
||||
shownTabs: 6,
|
||||
hiddenTabs: [0, 4, 9],
|
||||
order: [12, 6, 7, 8, 10, 11, 1, 2, 3, 5, 0, 4, 9]
|
||||
},
|
||||
{ testNum: 6,
|
||||
totalTabs: 13,
|
||||
selectedTab: 4,
|
||||
shownTabs: 6,
|
||||
hiddenTabs: [1, 7, 12],
|
||||
order: [3, 4, 5, 6, 8, 9, 0, 2, 10, 11, 1, 7, 12]
|
||||
},
|
||||
{ testNum: 7,
|
||||
totalTabs: 13,
|
||||
selectedTab: 4,
|
||||
shownTabs: 6,
|
||||
hiddenTabs: [0, 1, 2],
|
||||
order: [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 1, 2]
|
||||
}
|
||||
return expected;
|
||||
}
|
||||
|
||||
// the number of tests we're running
|
||||
let numTests = 7;
|
||||
let completedTests = 0;
|
||||
];
|
||||
|
||||
let tabMinWidth = parseInt(getComputedStyle(gBrowser.selectedTab, null).minWidth);
|
||||
let testIndex = 0;
|
||||
|
||||
function runTest(testNum, totalTabs, selectedTab, shownTabs, hiddenTabs, order) {
|
||||
let test = {
|
||||
state: buildTestState(totalTabs, selectedTab, hiddenTabs),
|
||||
numTabsToShow: shownTabs,
|
||||
expectedOrder: order,
|
||||
actualOrder: [],
|
||||
windowWidth: null,
|
||||
callback: null,
|
||||
window: null,
|
||||
function runNextTest() {
|
||||
if (tests.length == 0) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
handleSSTabRestoring: function (aEvent) {
|
||||
let tab = aEvent.originalTarget;
|
||||
let tabbrowser = this.window.gBrowser;
|
||||
let currentIndex = Array.indexOf(tabbrowser.tabs, tab);
|
||||
this.actualOrder.push(currentIndex);
|
||||
info ("Starting test " + (++testIndex));
|
||||
let test = tests.shift();
|
||||
let state = buildTestState(test.totalTabs, test.selectedTab, test.hiddenTabs);
|
||||
let tabbarWidth = Math.floor((test.shownTabs - 0.5) * tabMinWidth);
|
||||
let win = openDialog(location, "_blank", "chrome,all,dialog=no");
|
||||
let actualOrder = [];
|
||||
|
||||
if (this.actualOrder.length < this.state.windows[0].tabs.length)
|
||||
return;
|
||||
win.addEventListener("SSTabRestoring", function onSSTabRestoring(aEvent) {
|
||||
let tab = aEvent.originalTarget;
|
||||
let currentIndex = Array.indexOf(win.gBrowser.tabs, tab);
|
||||
actualOrder.push(currentIndex);
|
||||
|
||||
// all of the tabs should be restoring or restored by now
|
||||
is(this.actualOrder.length, this.state.windows[0].tabs.length,
|
||||
"Test #" + testNum + ": Number of restored tabs is as expected");
|
||||
if (actualOrder.length < state.windows[0].tabs.length)
|
||||
return;
|
||||
|
||||
is(this.actualOrder.join(" "), this.expectedOrder.join(" "),
|
||||
"Test #" + testNum + ": 'visible' tabs restored first");
|
||||
// all of the tabs should be restoring or restored by now
|
||||
is(actualOrder.length, state.windows[0].tabs.length,
|
||||
"Test #" + testIndex + ": Number of restored tabs is as expected");
|
||||
|
||||
// cleanup
|
||||
this.window.close();
|
||||
// if we're all done, explicitly finish
|
||||
if (++completedTests == numTests) {
|
||||
this.window.removeEventListener("load", this, false);
|
||||
this.window.removeEventListener("SSTabRestoring", this, false);
|
||||
finish();
|
||||
}
|
||||
},
|
||||
is(actualOrder.join(" "), test.order.join(" "),
|
||||
"Test #" + testIndex + ": 'visible' tabs restored first");
|
||||
|
||||
handleLoad: function (aEvent) {
|
||||
let _this = this;
|
||||
executeSoon(function () {
|
||||
let extent = _this.window.outerWidth - _this.window.gBrowser.tabContainer.mTabstrip.scrollClientSize;
|
||||
let windowWidth = _this.tabbarWidth + extent;
|
||||
_this.window.resizeTo(windowWidth, _this.window.outerHeight);
|
||||
ss.setWindowState(_this.window, JSON.stringify(_this.state), true);
|
||||
});
|
||||
},
|
||||
// Cleanup.
|
||||
win.removeEventListener("SSTabRestoring", onSSTabRestoring, false);
|
||||
win.close();
|
||||
executeSoon(runNextTest);
|
||||
}, false);
|
||||
|
||||
// Implement nsIDOMEventListener for handling various window and tab events
|
||||
handleEvent: function (aEvent) {
|
||||
switch (aEvent.type) {
|
||||
case "load":
|
||||
this.handleLoad(aEvent);
|
||||
break;
|
||||
case "SSTabRestoring":
|
||||
this.handleSSTabRestoring(aEvent);
|
||||
break;
|
||||
}
|
||||
},
|
||||
win.addEventListener("load", function onLoad(aEvent) {
|
||||
win.removeEventListener("load", onLoad, false);
|
||||
executeSoon(function () {
|
||||
let extent = win.outerWidth - win.gBrowser.tabContainer.mTabstrip.scrollClientSize;
|
||||
let windowWidth = tabbarWidth + extent;
|
||||
win.resizeTo(windowWidth, win.outerHeight);
|
||||
ss.setWindowState(win, JSON.stringify(state), true);
|
||||
});
|
||||
}, false);
|
||||
};
|
||||
|
||||
// setup and actually run the test
|
||||
run: function () {
|
||||
this.tabbarWidth = Math.floor((this.numTabsToShow - 0.5) * tabMinWidth);
|
||||
this.window = openDialog(location, "_blank", "chrome,all,dialog=no");
|
||||
this.window.addEventListener("SSTabRestoring", this, false);
|
||||
this.window.addEventListener("load", this, false);
|
||||
}
|
||||
};
|
||||
test.run();
|
||||
}
|
||||
|
||||
// actually create & run the tests
|
||||
runTest(1, 13, 1, 6, [], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
|
||||
runTest(2, 13, 13, 6, [], [12, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6]);
|
||||
runTest(3, 13, 4, 6, [], [3, 4, 5, 6, 7, 8, 0, 1, 2, 9, 10, 11, 12]);
|
||||
runTest(4, 13, 11, 6, [], [10, 7, 8, 9, 11, 12, 0, 1, 2, 3, 4, 5, 6]);
|
||||
runTest(5, 13, 13, 6, [0, 4, 9], [12, 6, 7, 8, 10, 11, 1, 2, 3, 5, 0, 4, 9]);
|
||||
runTest(6, 13, 4, 6, [1, 7, 12], [3, 4, 5, 6, 8, 9, 0, 2, 10, 11, 1, 7, 12]);
|
||||
runTest(7, 13, 4, 6, [0, 1, 2], [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 1, 2]);
|
||||
|
||||
// finish() is run by the last test to finish, so no cleanup down here
|
||||
runNextTest();
|
||||
}
|
||||
|
@ -2,6 +2,8 @@
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
let assertNumberOfTabs = function (num, msg) {
|
||||
is(gBrowser.tabs.length, num, msg);
|
||||
}
|
||||
@ -25,11 +27,13 @@ function test() {
|
||||
assertNumberOfPinnedTabs(2, "both tabs are now pinned");
|
||||
|
||||
// run the test
|
||||
ss.setBrowserState(JSON.stringify({ windows: [{ tabs: [{ url: "about:blank" }] }] }));
|
||||
assertNumberOfTabs(1, "one tab left after setBrowserState()");
|
||||
assertNumberOfPinnedTabs(0, "there are no pinned tabs");
|
||||
is(gBrowser.tabs[0].linkedBrowser, linkedBrowser, "first tab's browser got re-used");
|
||||
|
||||
waitForExplicitFinish();
|
||||
waitForSaveState(finish);
|
||||
waitForBrowserState(
|
||||
{ windows: [{ tabs: [{ url: "about:blank" }] }] },
|
||||
function () {
|
||||
assertNumberOfTabs(1, "one tab left after setBrowserState()");
|
||||
assertNumberOfPinnedTabs(0, "there are no pinned tabs");
|
||||
is(gBrowser.tabs[0].linkedBrowser, linkedBrowser, "first tab's browser got re-used");
|
||||
finish();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -14,10 +14,14 @@ function test() {
|
||||
// window is now in _closedWindows.
|
||||
|
||||
waitForExplicitFinish();
|
||||
requestLongerTimeout(2);
|
||||
|
||||
// We speed up the interval between session saves to ensure that the test
|
||||
// runs quickly.
|
||||
Services.prefs.setIntPref("browser.sessionstore.interval", 2000);
|
||||
Services.prefs.setIntPref("browser.sessionstore.interval", 4000);
|
||||
registerCleanupFunction(function () {
|
||||
Services.prefs.clearUserPref("browser.sessionstore.interval");
|
||||
});
|
||||
|
||||
// We'll clear all closed windows to make sure our state is clean
|
||||
// forgetClosedWindow doesn't trigger a delayed save
|
||||
@ -97,7 +101,6 @@ function openTab() {
|
||||
}
|
||||
|
||||
function done() {
|
||||
Services.prefs.clearUserPref("browser.sessionstore.interval");
|
||||
gBrowser.removeTab(newTab);
|
||||
// The API still represents the closed window as closed, so we can clear it
|
||||
// with the API, but just to make sure...
|
||||
|
@ -7,9 +7,14 @@ let tabState = {
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
requestLongerTimeout(2);
|
||||
|
||||
Services.prefs.setIntPref("browser.sessionstore.interval", 4000);
|
||||
registerCleanupFunction(function () {
|
||||
Services.prefs.clearUserPref("browser.sessionstore.interval");
|
||||
});
|
||||
|
||||
let tab = gBrowser.addTab("about:blank");
|
||||
registerCleanupFunction(function () gBrowser.removeTab(tab));
|
||||
|
||||
let browser = tab.linkedBrowser;
|
||||
|
||||
@ -26,7 +31,9 @@ function test() {
|
||||
is(entries.length, 1, "tab has one history entry");
|
||||
ok(!entries[0].children, "history entry has no subframes");
|
||||
|
||||
finish();
|
||||
// Make sure that we reset the state.
|
||||
let blankState = { windows: [{ tabs: [{ entries: [{ url: "about:blank" }] }]}]};
|
||||
waitForBrowserState(blankState, finish);
|
||||
});
|
||||
|
||||
// reload the browser to deprecate the subframes
|
||||
@ -36,8 +43,8 @@ function test() {
|
||||
// create a dynamic subframe
|
||||
let doc = browser.contentDocument;
|
||||
let iframe = doc.createElement("iframe");
|
||||
iframe.setAttribute("src", "about:mozilla");
|
||||
doc.body.appendChild(iframe);
|
||||
iframe.setAttribute("src", "about:mozilla");
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -53,5 +60,5 @@ function whenChildCount(aEntry, aChildCount, aCallback) {
|
||||
if (aEntry.childCount == aChildCount)
|
||||
aCallback();
|
||||
else
|
||||
executeSoon(function () whenChildCount(aEntry, aChildCount, aCallback));
|
||||
setTimeout(function () whenChildCount(aEntry, aChildCount, aCallback), 100);
|
||||
}
|
||||
|
@ -7,9 +7,14 @@ let tabState = {
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
requestLongerTimeout(2);
|
||||
|
||||
Services.prefs.setIntPref("browser.sessionstore.interval", 4000);
|
||||
registerCleanupFunction(function () {
|
||||
Services.prefs.clearUserPref("browser.sessionstore.interval");
|
||||
});
|
||||
|
||||
let tab = gBrowser.addTab("about:blank");
|
||||
registerCleanupFunction(function () gBrowser.removeTab(tab));
|
||||
|
||||
let browser = tab.linkedBrowser;
|
||||
|
||||
@ -25,7 +30,11 @@ function test() {
|
||||
let sessionHistory = browser.sessionHistory;
|
||||
let entry = sessionHistory.getEntryAtIndex(0, false);
|
||||
|
||||
whenChildCount(entry, 0, finish);
|
||||
whenChildCount(entry, 0, function () {
|
||||
// Make sure that we reset the state.
|
||||
let blankState = { windows: [{ tabs: [{ entries: [{ url: "about:blank" }] }]}]};
|
||||
waitForBrowserState(blankState, finish);
|
||||
});
|
||||
});
|
||||
|
||||
// reload the browser to deprecate the subframes
|
||||
@ -35,8 +44,8 @@ function test() {
|
||||
// create a dynamic subframe
|
||||
let doc = browser.contentDocument;
|
||||
let iframe = doc.createElement("iframe");
|
||||
iframe.setAttribute("src", "about:mozilla");
|
||||
doc.body.appendChild(iframe);
|
||||
iframe.setAttribute("src", "about:mozilla");
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -52,5 +61,5 @@ function whenChildCount(aEntry, aChildCount, aCallback) {
|
||||
if (aEntry.childCount == aChildCount)
|
||||
aCallback();
|
||||
else
|
||||
executeSoon(function () whenChildCount(aEntry, aChildCount, aCallback));
|
||||
setTimeout(function () whenChildCount(aEntry, aChildCount, aCallback), 100);
|
||||
}
|
||||
|
@ -94,11 +94,21 @@ let WindowMessageHandler = {
|
||||
!webProgress.isLoadingDocument);
|
||||
|
||||
sendAsyncMessage(cx.name, {isLoaded: isLoaded});
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: isImageDocument
|
||||
// Checks if the currently active document is an image document or not.
|
||||
isImageDocument: function WMH_isImageDocument(cx) {
|
||||
let isImageDocument = (content.document instanceof Ci.nsIImageDocument);
|
||||
|
||||
sendAsyncMessage(cx.name, {isImageDocument: isImageDocument});
|
||||
}
|
||||
};
|
||||
|
||||
// add message listeners
|
||||
addMessageListener("Panorama:isDocumentLoaded", WindowMessageHandler.isDocumentLoaded);
|
||||
addMessageListener("Panorama:isImageDocument", WindowMessageHandler.isImageDocument);
|
||||
|
||||
// ----------
|
||||
// WebProgressListener
|
||||
|
@ -234,10 +234,12 @@ function GroupItem(listOfEls, options) {
|
||||
.addClass("appTabTray")
|
||||
.appendTo(appTabTrayContainer);
|
||||
|
||||
AllTabs.tabs.forEach(function(xulTab) {
|
||||
let pinnedTabCount = gBrowser._numPinnedTabs;
|
||||
AllTabs.tabs.forEach(function (xulTab, index) {
|
||||
// only adjust tray when it's the last app tab.
|
||||
if (xulTab.pinned)
|
||||
self.addAppTab(xulTab, {dontAdjustTray: true});
|
||||
});
|
||||
this.addAppTab(xulTab, {dontAdjustTray: index + 1 < pinnedTabCount});
|
||||
}, this);
|
||||
|
||||
// ___ Undo Close
|
||||
this.$undoContainer = null;
|
||||
@ -758,7 +760,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
});
|
||||
|
||||
UI.setActive(self);
|
||||
self._sendToSubscribers("groupShown", { groupItemId: self.id });
|
||||
self._sendToSubscribers("groupShown");
|
||||
};
|
||||
|
||||
let $container = iQ(this.container).show();
|
||||
@ -927,7 +929,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
easing: "tabviewBounce",
|
||||
duration: 170,
|
||||
complete: function() {
|
||||
self._sendToSubscribers("groupHidden", { groupItemId: self.id });
|
||||
self._sendToSubscribers("groupHidden");
|
||||
}
|
||||
});
|
||||
}, 50);
|
||||
@ -1052,7 +1054,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
this.arrange({animate: !options.immediately});
|
||||
|
||||
this._unfreezeItemSize({dontArrange: true});
|
||||
this._sendToSubscribers("childAdded",{ groupItemId: this.id, item: item });
|
||||
this._sendToSubscribers("childAdded", { item: item });
|
||||
|
||||
UI.setReorderTabsOnHide(this);
|
||||
} catch(e) {
|
||||
@ -1155,7 +1157,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
this._unfreezeItemSize({dontArrange: true});
|
||||
}
|
||||
|
||||
this._sendToSubscribers("childRemoved",{ groupItemId: this.id, item: item });
|
||||
this._sendToSubscribers("childRemoved", { item: item });
|
||||
} catch(e) {
|
||||
Utils.log(e);
|
||||
}
|
||||
@ -1181,36 +1183,46 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
// Adds the given xul:tab as an app tab in this group's apptab tray
|
||||
//
|
||||
// Parameters:
|
||||
// xulTab - the xul:tab.
|
||||
// options - change how the app tab is added.
|
||||
//
|
||||
// Options:
|
||||
// dontAdjustTray - (boolean) if true, the $appTabTray size is not adjusted,
|
||||
// which means that the adjustAppTabTray() method is not
|
||||
// called.
|
||||
// position - the position of the app tab should be added to.
|
||||
// dontAdjustTray - (boolean) if true, do not adjust the tray.
|
||||
addAppTab: function GroupItem_addAppTab(xulTab, options) {
|
||||
let self = this;
|
||||
GroupItems.getAppTabFavIconUrl(xulTab, function(iconUrl) {
|
||||
let self = this;
|
||||
let $appTab = iQ("<img>")
|
||||
.addClass("appTabIcon")
|
||||
.attr("src", iconUrl)
|
||||
.data("xulTab", xulTab)
|
||||
.mousedown(function GroupItem_addAppTab_onAppTabMousedown(event) {
|
||||
// stop mousedown propagation to disable group dragging on app tabs
|
||||
event.stopPropagation();
|
||||
})
|
||||
.click(function GroupItem_addAppTab_onAppTabClick(event) {
|
||||
if (!Utils.isLeftClick(event))
|
||||
return;
|
||||
|
||||
let iconUrl = GroupItems.getAppTabFavIconUrl(xulTab);
|
||||
let $appTab = iQ("<img>")
|
||||
.addClass("appTabIcon")
|
||||
.attr("src", iconUrl)
|
||||
.data("xulTab", xulTab)
|
||||
.appendTo(this.$appTabTray)
|
||||
.mousedown(function onAppTabMousedown(event) {
|
||||
// stop mousedown propagation to disable group dragging on app tabs
|
||||
event.stopPropagation();
|
||||
})
|
||||
.click(function(event) {
|
||||
if (!Utils.isLeftClick(event))
|
||||
return;
|
||||
UI.setActive(self, { dontSetActiveTabInGroup: true });
|
||||
UI.goToTab(iQ(this).data("xulTab"));
|
||||
});
|
||||
|
||||
UI.setActive(self, { dontSetActiveTabInGroup: true });
|
||||
UI.goToTab(iQ(this).data("xulTab"));
|
||||
});
|
||||
if (options && "position" in options) {
|
||||
let children = this.$appTabTray[0].childNodes;
|
||||
|
||||
// adjust the tray, if needed.
|
||||
if (!options || !options.dontAdjustTray)
|
||||
this.adjustAppTabTray(true);
|
||||
if (options.position >= children.length)
|
||||
$appTab.appendTo(this.$appTabTray);
|
||||
else
|
||||
this.$appTabTray[0].insertBefore($appTab[0], children[options.position]);
|
||||
} else {
|
||||
$appTab.appendTo(this.$appTabTray);
|
||||
}
|
||||
if (!options || !options.dontAdjustTray)
|
||||
this.adjustAppTabTray(true);
|
||||
|
||||
this._sendToSubscribers("appTabIconAdded", { item: $appTab });
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
// ----------
|
||||
@ -2078,16 +2090,11 @@ let GroupItems = {
|
||||
if (!xulTab.pinned)
|
||||
return;
|
||||
|
||||
let iconUrl = this.getAppTabFavIconUrl(xulTab);
|
||||
this.groupItems.forEach(function(groupItem) {
|
||||
iQ(".appTabIcon", groupItem.$appTabTray).each(function(icon) {
|
||||
let $icon = iQ(icon);
|
||||
if ($icon.data("xulTab") != xulTab)
|
||||
return true;
|
||||
|
||||
if (iconUrl != $icon.attr("src"))
|
||||
$icon.attr("src", iconUrl);
|
||||
return false;
|
||||
this.getAppTabFavIconUrl(xulTab, function(iconUrl) {
|
||||
iQ(".appTabIcon").each(function GroupItems__updateAppTabIcons_forEach(icon) {
|
||||
let $icon = iQ(icon);
|
||||
if ($icon.data("xulTab") == xulTab && iconUrl != $icon.attr("src"))
|
||||
$icon.attr("src", iconUrl);
|
||||
});
|
||||
});
|
||||
},
|
||||
@ -2095,15 +2102,10 @@ let GroupItems = {
|
||||
// ----------
|
||||
// Function: getAppTabFavIconUrl
|
||||
// Gets the fav icon url for app tab.
|
||||
getAppTabFavIconUrl: function GroupItems_getAppTabFavIconUrl(xulTab) {
|
||||
let iconUrl;
|
||||
|
||||
if (UI.shouldLoadFavIcon(xulTab.linkedBrowser))
|
||||
iconUrl = UI.getFavIconUrlForTab(xulTab);
|
||||
else
|
||||
iconUrl = gFavIconService.defaultFavicon.spec;
|
||||
|
||||
return iconUrl;
|
||||
getAppTabFavIconUrl: function GroupItems_getAppTabFavIconUrl(xulTab, callback) {
|
||||
UI.getFavIconUrlForTab(xulTab, function GroupItems_getAppTabFavIconUrl_getFavIconUrlForTab(iconUrl) {
|
||||
callback(iconUrl || gFavIconService.defaultFavicon.spec);
|
||||
});
|
||||
},
|
||||
|
||||
// ----------
|
||||
|
@ -985,20 +985,21 @@ let TabItems = {
|
||||
let tabItem = tab._tabViewTabItem;
|
||||
|
||||
// Even if the page hasn't loaded, display the favicon and title
|
||||
|
||||
// ___ icon
|
||||
if (UI.shouldLoadFavIcon(tab.linkedBrowser)) {
|
||||
let iconUrl = UI.getFavIconUrlForTab(tab);
|
||||
|
||||
if (tabItem.$favImage[0].src != iconUrl)
|
||||
tabItem.$favImage[0].src = iconUrl;
|
||||
|
||||
iQ(tabItem.$fav[0]).show();
|
||||
} else {
|
||||
if (tabItem.$favImage[0].hasAttribute("src"))
|
||||
tabItem.$favImage[0].removeAttribute("src");
|
||||
iQ(tabItem.$fav[0]).hide();
|
||||
}
|
||||
UI.getFavIconUrlForTab(tab, function TabItems__update_getFavIconUrlCallback(iconUrl) {
|
||||
let favImage = tabItem.$favImage[0];
|
||||
let fav = tabItem.$fav;
|
||||
if (iconUrl) {
|
||||
if (favImage.src != iconUrl)
|
||||
favImage.src = iconUrl;
|
||||
fav.show();
|
||||
} else {
|
||||
if (favImage.hasAttribute("src"))
|
||||
favImage.removeAttribute("src");
|
||||
fav.hide();
|
||||
}
|
||||
tabItem._sendToSubscribers("iconUpdated");
|
||||
});
|
||||
|
||||
// ___ label
|
||||
let label = tab.label;
|
||||
|
@ -158,6 +158,7 @@ _BROWSER_FILES = \
|
||||
browser_tabview_bug673196.js \
|
||||
browser_tabview_bug673729.js \
|
||||
browser_tabview_bug677310.js \
|
||||
browser_tabview_bug678374.js \
|
||||
browser_tabview_bug679853.js \
|
||||
browser_tabview_bug681599.js \
|
||||
browser_tabview_bug685476.js \
|
||||
@ -192,6 +193,8 @@ _BROWSER_FILES = \
|
||||
search2.html \
|
||||
test_bug600645.html \
|
||||
test_bug644097.html \
|
||||
test_bug678374.html \
|
||||
test_bug678374_icon16.png \
|
||||
$(NULL)
|
||||
|
||||
# browser_tabview_bug597980.js is disabled for leaking, see bug 711907
|
||||
|
@ -4,15 +4,13 @@
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
window.addEventListener("tabviewshown", onTabViewWindowLoaded, false);
|
||||
TabView.toggle();
|
||||
showTabView(onTabViewWindowLoaded);
|
||||
}
|
||||
|
||||
function onTabViewWindowLoaded() {
|
||||
window.removeEventListener("tabviewshown", onTabViewWindowLoaded, false);
|
||||
ok(TabView.isVisible(), "Tab View is visible");
|
||||
|
||||
let contentWindow = document.getElementById("tab-view").contentWindow;
|
||||
let contentWindow = TabView.getContentWindow();
|
||||
|
||||
// establish initial state
|
||||
is(contentWindow.GroupItems.groupItems.length, 1,
|
||||
@ -36,60 +34,61 @@ function onTabViewWindowLoaded() {
|
||||
is(appTabCount(groupItemOne), 0, "there are no app tab icons");
|
||||
|
||||
// pin the tab, make sure the TabItem goes away and the icon comes on
|
||||
whenAppTabIconAdded(function() {
|
||||
is(groupItemOne._children.length, 0,
|
||||
"the app tab's TabItem was removed from the group");
|
||||
is(appTabCount(groupItemOne), 1, "there's now one app tab icon");
|
||||
|
||||
// create a second group and make sure it gets the icon too
|
||||
box.offset(box.width + 20, 0);
|
||||
let groupItemTwo = new contentWindow.GroupItem([],
|
||||
{ bounds: box, title: "test2" });
|
||||
whenAppTabIconAdded(function() {
|
||||
is(contentWindow.GroupItems.groupItems.length, 3, "we now have three groups");
|
||||
is(appTabCount(groupItemTwo), 1,
|
||||
"there's an app tab icon in the second group");
|
||||
|
||||
// When the tab was pinned, the last active group with an item got the focus.
|
||||
// Therefore, switching the focus back to group item one.
|
||||
contentWindow.UI.setActive(groupItemOne);
|
||||
|
||||
// unpin the tab, make sure the icon goes away and the TabItem comes on
|
||||
gBrowser.unpinTab(xulTab);
|
||||
is(groupItemOne._children.length, 1, "the app tab's TabItem is back");
|
||||
is(appTabCount(groupItemOne), 0, "the icon is gone from group one");
|
||||
is(appTabCount(groupItemTwo), 0, "the icon is gone from group two");
|
||||
|
||||
whenAppTabIconAdded(function() {
|
||||
// close the second group
|
||||
groupItemTwo.close();
|
||||
|
||||
// find app tab in group and hit it
|
||||
whenTabViewIsHidden(function() {
|
||||
ok(!TabView.isVisible(),
|
||||
"Tab View is hidden because we clicked on the app tab");
|
||||
|
||||
// delete the app tab and make sure its icon goes away
|
||||
gBrowser.removeTab(xulTab);
|
||||
is(appTabCount(groupItemOne), 0, "closing app tab removes its icon");
|
||||
|
||||
// clean up
|
||||
groupItemOne.close();
|
||||
|
||||
is(contentWindow.GroupItems.groupItems.length, 1,
|
||||
"we finish with one group");
|
||||
is(gBrowser.tabs.length, 1, "we finish with one tab");
|
||||
ok(!TabView.isVisible(), "we finish with Tab View not visible");
|
||||
|
||||
finish();
|
||||
});
|
||||
|
||||
let appTabIcons = groupItemOne.container.getElementsByClassName("appTabIcon");
|
||||
EventUtils.sendMouseEvent({ type: "click" }, appTabIcons[0], contentWindow);
|
||||
});
|
||||
gBrowser.pinTab(xulTab);
|
||||
});
|
||||
});
|
||||
gBrowser.pinTab(xulTab);
|
||||
is(groupItemOne._children.length, 0,
|
||||
"the app tab's TabItem was removed from the group");
|
||||
is(appTabCount(groupItemOne), 1, "there's now one app tab icon");
|
||||
|
||||
// create a second group and make sure it gets the icon too
|
||||
box.offset(box.width + 20, 0);
|
||||
let groupItemTwo = new contentWindow.GroupItem([],
|
||||
{ bounds: box, title: "test2" });
|
||||
is(contentWindow.GroupItems.groupItems.length, 3, "we now have three groups");
|
||||
is(appTabCount(groupItemTwo), 1,
|
||||
"there's an app tab icon in the second group");
|
||||
|
||||
// When the tab was pinned, the last active group with an item got the focus.
|
||||
// Therefore, switching the focus back to group item one.
|
||||
contentWindow.UI.setActive(groupItemOne);
|
||||
|
||||
// unpin the tab, make sure the icon goes away and the TabItem comes on
|
||||
gBrowser.unpinTab(xulTab);
|
||||
is(groupItemOne._children.length, 1, "the app tab's TabItem is back");
|
||||
is(appTabCount(groupItemOne), 0, "the icon is gone from group one");
|
||||
is(appTabCount(groupItemTwo), 0, "the icon is gone from group 2");
|
||||
|
||||
// pin the tab again
|
||||
gBrowser.pinTab(xulTab);
|
||||
|
||||
// close the second group
|
||||
groupItemTwo.close();
|
||||
|
||||
// find app tab in group and hit it
|
||||
let onTabViewHidden = function() {
|
||||
window.removeEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
ok(!TabView.isVisible(),
|
||||
"Tab View is hidden because we clicked on the app tab");
|
||||
|
||||
// delete the app tab and make sure its icon goes away
|
||||
gBrowser.removeTab(xulTab);
|
||||
is(appTabCount(groupItemOne), 0, "closing app tab removes its icon");
|
||||
|
||||
// clean up
|
||||
groupItemOne.close();
|
||||
|
||||
is(contentWindow.GroupItems.groupItems.length, 1,
|
||||
"we finish with one group");
|
||||
is(gBrowser.tabs.length, 1, "we finish with one tab");
|
||||
ok(!TabView.isVisible(), "we finish with Tab View not visible");
|
||||
|
||||
finish();
|
||||
};
|
||||
|
||||
window.addEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
|
||||
let appTabIcons = groupItemOne.container.getElementsByClassName("appTabIcon");
|
||||
EventUtils.sendMouseEvent({ type: "click" }, appTabIcons[0], contentWindow);
|
||||
}
|
||||
|
||||
function appTabCount(groupItem) {
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
requestLongerTimeout(2);
|
||||
|
||||
newWindowWithTabView(onTabViewWindowLoaded);
|
||||
}
|
||||
@ -105,8 +106,8 @@ function onTabViewWindowLoaded(win) {
|
||||
// Close the window and we're done!
|
||||
win.close();
|
||||
finish();
|
||||
}, 6000, false);
|
||||
},1000);
|
||||
}, 10000, false);
|
||||
}, 2000);
|
||||
|
||||
});
|
||||
|
||||
|
@ -53,87 +53,98 @@ function onTabViewShown(win) {
|
||||
"$appTabTray container is not visible");
|
||||
|
||||
// pin the tab, make sure the TabItem goes away and the icon comes on
|
||||
gBrowser.pinTab(xulTabs[0]);
|
||||
is(groupItem._children.length, 0,
|
||||
"the app tab's TabItem was removed from the group");
|
||||
is(appTabCount(groupItem), 1, "there's now one app tab icon");
|
||||
whenAppTabIconAdded(function() {
|
||||
is(groupItem._children.length, 0,
|
||||
"the app tab's TabItem was removed from the group");
|
||||
is(appTabCount(groupItem), 1, "there's now one app tab icon");
|
||||
|
||||
is(tray.css("-moz-column-count"), 1,
|
||||
"$appTabTray column count is 1");
|
||||
isnot(parseInt(trayContainer.css("width")), 0,
|
||||
"$appTabTray container is visible");
|
||||
is(tray.css("-moz-column-count"), 1,
|
||||
"$appTabTray column count is 1");
|
||||
isnot(parseInt(trayContainer.css("width")), 0,
|
||||
"$appTabTray container is visible");
|
||||
|
||||
let iconHeight = iQ(iQ(".appTabIcon", tray)[0]).height();
|
||||
let trayHeight = parseInt(trayContainer.css("height"));
|
||||
let rows = Math.floor(trayHeight / iconHeight);
|
||||
let icons = rows * 2;
|
||||
|
||||
// add enough tabs to have two columns
|
||||
for (let i = 1; i < icons; i++) {
|
||||
xulTabs.push(gBrowser.loadOneTab("about:blank"));
|
||||
gBrowser.pinTab(xulTabs[i]);
|
||||
}
|
||||
let iconHeight = iQ(iQ(".appTabIcon", tray)[0]).height();
|
||||
let trayHeight = parseInt(trayContainer.css("height"));
|
||||
let rows = Math.floor(trayHeight / iconHeight);
|
||||
let icons = rows * 2;
|
||||
|
||||
is(appTabCount(groupItem), icons, "number of app tab icons is correct");
|
||||
function pinnedSomeTabs() {
|
||||
is(appTabCount(groupItem), icons, "number of app tab icons is correct");
|
||||
|
||||
is(tray.css("-moz-column-count"), 2,
|
||||
"$appTabTray column count is 2");
|
||||
is(tray.css("-moz-column-count"), 2,
|
||||
"$appTabTray column count is 2");
|
||||
|
||||
ok(!trayContainer.hasClass("appTabTrayContainerTruncated"),
|
||||
"$appTabTray container does not have .appTabTrayContainerTruncated");
|
||||
ok(!trayContainer.hasClass("appTabTrayContainerTruncated"),
|
||||
"$appTabTray container does not have .appTabTrayContainerTruncated");
|
||||
|
||||
// add one more tab
|
||||
xulTabs.push(gBrowser.loadOneTab("about:blank"));
|
||||
gBrowser.pinTab(xulTabs[xulTabs.length-1]);
|
||||
// add one more tab
|
||||
xulTabs.push(gBrowser.loadOneTab("about:blank"));
|
||||
whenAppTabIconAdded(function() {
|
||||
is(tray.css("-moz-column-count"), 3,
|
||||
"$appTabTray column count is 3");
|
||||
|
||||
is(tray.css("-moz-column-count"), 3,
|
||||
"$appTabTray column count is 3");
|
||||
ok(trayContainer.hasClass("appTabTrayContainerTruncated"),
|
||||
"$appTabTray container hasClass .appTabTrayContainerTruncated");
|
||||
|
||||
ok(trayContainer.hasClass("appTabTrayContainerTruncated"),
|
||||
"$appTabTray container hasClass .appTabTrayContainerTruncated");
|
||||
// remove all but one app tabs
|
||||
for (let i = 1; i < xulTabs.length; i++)
|
||||
gBrowser.removeTab(xulTabs[i]);
|
||||
|
||||
// remove all but one app tabs
|
||||
for (let i = 1; i < xulTabs.length; i++)
|
||||
gBrowser.removeTab(xulTabs[i]);
|
||||
is(tray.css("-moz-column-count"), 1,
|
||||
"$appTabTray column count is 1");
|
||||
|
||||
is(tray.css("-moz-column-count"), 1,
|
||||
"$appTabTray column count is 1");
|
||||
is(appTabCount(groupItem), 1, "there's now one app tab icon");
|
||||
|
||||
is(appTabCount(groupItem), 1, "there's now one app tab icon");
|
||||
ok(!trayContainer.hasClass("appTabTrayContainerTruncated"),
|
||||
"$appTabTray container does not have .appTabTrayContainerTruncated");
|
||||
|
||||
ok(!trayContainer.hasClass("appTabTrayContainerTruncated"),
|
||||
"$appTabTray container does not have .appTabTrayContainerTruncated");
|
||||
// unpin the last remaining tab
|
||||
gBrowser.unpinTab(xulTabs[0]);
|
||||
|
||||
// When the tab was pinned, the last active group with an item got the focus.
|
||||
// Therefore, switching the focus back to group item one.
|
||||
contentWindow.UI.setActive(groupItem);
|
||||
is(parseInt(trayContainer.css("width")), 0,
|
||||
"$appTabTray container is not visible");
|
||||
|
||||
// unpin the last remaining tab
|
||||
gBrowser.unpinTab(xulTabs[0]);
|
||||
// When the tab was pinned, the last active group with an item got the focus.
|
||||
// Therefore, switching the focus back to group item one.
|
||||
contentWindow.UI.setActive(groupItem);
|
||||
|
||||
is(parseInt(trayContainer.css("width")), 0,
|
||||
"$appTabTray container is not visible");
|
||||
is(appTabCount(groupItem), 0, "there are no app tab icons");
|
||||
|
||||
is(appTabCount(groupItem), 0, "there are no app tab icons");
|
||||
is(groupItem._children.length, 1, "the normal tab shows in the group");
|
||||
|
||||
is(groupItem._children.length, 1, "the normal tab shows in the group");
|
||||
gBrowser.removeTab(xulTabs[0]);
|
||||
|
||||
gBrowser.removeTab(xulTabs[0]);
|
||||
// close the group
|
||||
groupItem.close();
|
||||
|
||||
// close the group
|
||||
groupItem.close();
|
||||
hideTabView(function() {
|
||||
ok(!TabView.isVisible(), "Tab View is hidden");
|
||||
|
||||
hideTabView(function() {
|
||||
ok(!TabView.isVisible(), "Tab View is hidden");
|
||||
is(contentWindow.GroupItems.groupItems.length, 1,
|
||||
"we finish with one group");
|
||||
is(gBrowser.tabs.length, 1, "we finish with one tab");
|
||||
|
||||
is(contentWindow.GroupItems.groupItems.length, 1,
|
||||
"we finish with one group");
|
||||
is(gBrowser.tabs.length, 1, "we finish with one tab");
|
||||
win.close();
|
||||
|
||||
win.close();
|
||||
executeSoon(finish);
|
||||
}, win);
|
||||
}, win);
|
||||
win.gBrowser.pinTab(xulTabs[xulTabs.length-1]);
|
||||
};
|
||||
|
||||
executeSoon(finish);
|
||||
// add enough tabs to have two columns
|
||||
let returnCount = 0;
|
||||
for (let i = 1; i < icons; i++) {
|
||||
xulTabs.push(gBrowser.loadOneTab("about:blank"));
|
||||
whenAppTabIconAdded(function() {
|
||||
if (++returnCount == (icons - 1))
|
||||
executeSoon(pinnedSomeTabs);
|
||||
}, win);
|
||||
win.gBrowser.pinTab(xulTabs[i]);
|
||||
}
|
||||
}, win);
|
||||
win.gBrowser.pinTab(xulTabs[0]);
|
||||
}
|
||||
|
||||
function appTabCount(groupItem) {
|
||||
|
@ -10,15 +10,14 @@ function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
newTab = gBrowser.addTab();
|
||||
gBrowser.pinTab(newTab);
|
||||
|
||||
window.addEventListener("tabviewshown", onTabViewWindowLoaded, false);
|
||||
TabView.toggle();
|
||||
showTabView(function() {
|
||||
whenAppTabIconAdded(onTabPinned);
|
||||
gBrowser.pinTab(newTab);
|
||||
})
|
||||
}
|
||||
|
||||
function onTabViewWindowLoaded() {
|
||||
window.removeEventListener("tabviewshown", onTabViewWindowLoaded, false);
|
||||
|
||||
function onTabPinned() {
|
||||
let contentWindow = document.getElementById("tab-view").contentWindow;
|
||||
is(contentWindow.GroupItems.groupItems.length, 1,
|
||||
"There is one group item on startup");
|
||||
|
@ -29,6 +29,7 @@ function onTabViewWindowLoaded(win) {
|
||||
let datatext = win.gBrowser.loadOneTab("data:text/plain,bug610242", bg);
|
||||
let datahtml = win.gBrowser.loadOneTab("data:text/html,<blink>don't blink!</blink>", bg);
|
||||
let mozilla = win.gBrowser.loadOneTab("about:mozilla", bg);
|
||||
let robots = win.gBrowser.loadOneTab("about:robots", bg);
|
||||
let html = win.gBrowser.loadOneTab("http://example.com", bg);
|
||||
let png = win.gBrowser.loadOneTab("http://mochi.test:8888/browser/browser/base/content/test/moz.png", bg);
|
||||
let svg = win.gBrowser.loadOneTab("http://mochi.test:8888/browser/browser/base/content/test/title_test.svg", bg);
|
||||
@ -46,13 +47,11 @@ function onTabViewWindowLoaded(win) {
|
||||
is(win.gBrowser.tabs.length, 1, "There is only one tab left");
|
||||
is(win.gBrowser.visibleTabs.length, 1, "There is also only one visible tab");
|
||||
|
||||
let onTabViewHidden = function() {
|
||||
win.removeEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
whenTabViewIsHidden(function() {
|
||||
win.close();
|
||||
ok(win.closed, "new window is closed");
|
||||
finish();
|
||||
};
|
||||
win.addEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
}, win);
|
||||
win.gBrowser.selectedTab = originalTab;
|
||||
|
||||
win.TabView.hide();
|
||||
@ -69,16 +68,33 @@ function onTabViewWindowLoaded(win) {
|
||||
|
||||
afterAllTabsLoaded(function() {
|
||||
afterAllTabItemsUpdated(function() {
|
||||
check(datatext, "datatext", false);
|
||||
check(datahtml, "datahtml", false);
|
||||
check(mozilla, "about:mozilla", true);
|
||||
check(html, "html", true);
|
||||
check(png, "png", false);
|
||||
check(svg, "svg", true);
|
||||
|
||||
// Get rid of the group and its children
|
||||
// The group close will trigger a finish().
|
||||
closeGroupItem(group);
|
||||
}, win);
|
||||
let children = group.getChildren();
|
||||
let len = children.length;
|
||||
let iconUpdateCounter = 0;
|
||||
|
||||
children.forEach(function(tabItem) {
|
||||
tabItem.addSubscriber("iconUpdated", function onIconUpdated() {
|
||||
// the tab is not loaded completely so ignore it.
|
||||
if (tabItem.tab.linkedBrowser.currentURI.spec == "about:blank")
|
||||
return;
|
||||
|
||||
tabItem.removeSubscriber("iconUpdated", onIconUpdated);
|
||||
|
||||
if (++iconUpdateCounter == len) {
|
||||
check(datatext, "datatext", false);
|
||||
check(datahtml, "datahtml", false);
|
||||
check(mozilla, "about:mozilla", false);
|
||||
check(robots, "about:robots", true);
|
||||
check(html, "html", true);
|
||||
check(png, "png", false);
|
||||
check(svg, "svg", true);
|
||||
|
||||
// Get rid of the group and its children
|
||||
// The group close will trigger a finish().
|
||||
closeGroupItem(group);
|
||||
}
|
||||
});
|
||||
});
|
||||
}, win);
|
||||
}, win);
|
||||
}
|
||||
|
@ -172,6 +172,7 @@ function test() {
|
||||
}
|
||||
|
||||
waitForExplicitFinish();
|
||||
requestLongerTimeout(2);
|
||||
|
||||
next();
|
||||
}
|
||||
|
@ -11,10 +11,6 @@ function test() {
|
||||
let newTabTwo = gBrowser.addTab();
|
||||
let newTabThree = gBrowser.addTab();
|
||||
|
||||
gBrowser.pinTab(newTabOne);
|
||||
gBrowser.pinTab(newTabTwo);
|
||||
gBrowser.pinTab(newTabThree);
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
TabView.hide();
|
||||
while (gBrowser.tabs.length > 1)
|
||||
@ -27,37 +23,47 @@ function test() {
|
||||
|
||||
groupItem = contentWindow.GroupItems.groupItems[0];
|
||||
|
||||
is(xulTabForAppTabIcon(0), newTabOne,
|
||||
"New tab one matches the first app tab icon in tabview");
|
||||
is(xulTabForAppTabIcon(1), newTabTwo,
|
||||
"New tab two matches the second app tab icon in tabview");
|
||||
is(xulTabForAppTabIcon(2), newTabThree,
|
||||
"New tab three matches the third app tab icon in tabview");
|
||||
whenAppTabIconAdded(function() {
|
||||
whenAppTabIconAdded(function() {
|
||||
whenAppTabIconAdded(function() {
|
||||
|
||||
// move the last tab to the first position
|
||||
gBrowser.moveTabTo(newTabThree, 0);
|
||||
is(xulTabForAppTabIcon(0), newTabThree,
|
||||
"New tab three matches the first app tab icon in tabview");
|
||||
is(xulTabForAppTabIcon(1), newTabOne,
|
||||
"New tab one matches the second app tab icon in tabview");
|
||||
is(xulTabForAppTabIcon(2), newTabTwo,
|
||||
"New tab two matches the third app tab icon in tabview");
|
||||
is(xulTabForAppTabIcon(0), newTabOne,
|
||||
"New tab one matches the first app tab icon in tabview");
|
||||
is(xulTabForAppTabIcon(1), newTabTwo,
|
||||
"New tab two matches the second app tab icon in tabview");
|
||||
is(xulTabForAppTabIcon(2), newTabThree,
|
||||
"New tab three matches the third app tab icon in tabview");
|
||||
|
||||
// move the first tab to the second position
|
||||
gBrowser.moveTabTo(newTabThree, 1);
|
||||
is(xulTabForAppTabIcon(0), newTabOne,
|
||||
"New tab one matches the first app tab icon in tabview");
|
||||
is(xulTabForAppTabIcon(1), newTabThree,
|
||||
"New tab three matches the second app tab icon in tabview");
|
||||
is(xulTabForAppTabIcon(2), newTabTwo,
|
||||
"New tab two matches the third app tab icon in tabview");
|
||||
// move the last tab to the first position
|
||||
gBrowser.moveTabTo(newTabThree, 0);
|
||||
is(xulTabForAppTabIcon(0), newTabThree,
|
||||
"New tab three matches the first app tab icon in tabview");
|
||||
is(xulTabForAppTabIcon(1), newTabOne,
|
||||
"New tab one matches the second app tab icon in tabview");
|
||||
is(xulTabForAppTabIcon(2), newTabTwo,
|
||||
"New tab two matches the third app tab icon in tabview");
|
||||
|
||||
hideTabView(function() {
|
||||
gBrowser.removeTab(newTabOne);
|
||||
gBrowser.removeTab(newTabTwo);
|
||||
gBrowser.removeTab(newTabThree);
|
||||
finish();
|
||||
// move the first tab to the second position
|
||||
gBrowser.moveTabTo(newTabThree, 1);
|
||||
is(xulTabForAppTabIcon(0), newTabOne,
|
||||
"New tab one matches the first app tab icon in tabview");
|
||||
is(xulTabForAppTabIcon(1), newTabThree,
|
||||
"New tab three matches the second app tab icon in tabview");
|
||||
is(xulTabForAppTabIcon(2), newTabTwo,
|
||||
"New tab two matches the third app tab icon in tabview");
|
||||
|
||||
hideTabView(function() {
|
||||
gBrowser.removeTab(newTabOne);
|
||||
gBrowser.removeTab(newTabTwo);
|
||||
gBrowser.removeTab(newTabThree);
|
||||
finish();
|
||||
});
|
||||
});
|
||||
gBrowser.pinTab(newTabThree);
|
||||
});
|
||||
gBrowser.pinTab(newTabTwo);
|
||||
});
|
||||
gBrowser.pinTab(newTabOne);
|
||||
});
|
||||
}
|
||||
|
||||
|
45
browser/components/tabview/test/browser_tabview_bug678374.js
Normal file
@ -0,0 +1,45 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const ICON_URL = "moz-anno:favicon:http://example.com/browser/browser/components/tabview/test/test_bug678374_icon16.png";
|
||||
const TEST_URL = "http://example.com/browser/browser/components/tabview/test/test_bug678374.html";
|
||||
|
||||
function test() {
|
||||
Services.prefs.setBoolPref("browser.chrome.favicons", false);
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
newWindowWithTabView(function(win) {
|
||||
is(win.gBrowser.tabs.length, 3, "There are 3 tabs")
|
||||
|
||||
let newTabOne = win.gBrowser.tabs[1];
|
||||
let newTabTwo = win.gBrowser.tabs[2];
|
||||
let cw = win.TabView.getContentWindow();
|
||||
let groupItem = cw.GroupItems.groupItems[0];
|
||||
|
||||
// test tab item
|
||||
let newTabItemOne = newTabOne._tabViewTabItem;
|
||||
|
||||
newTabItemOne.addSubscriber("iconUpdated", function onIconUpdated() {
|
||||
newTabItemOne.removeSubscriber("iconUpdated", onIconUpdated);
|
||||
is(newTabItemOne.$favImage[0].src, ICON_URL, "The tab item is showing the right icon.");
|
||||
|
||||
// test pin tab
|
||||
whenAppTabIconAdded(function() {
|
||||
let icon = cw.iQ(".appTabIcon", groupItem.$appTabTray)[0];
|
||||
is(icon.src, ICON_URL, "The app tab is showing the right icon");
|
||||
|
||||
finish();
|
||||
}, win);
|
||||
win.gBrowser.pinTab(newTabTwo);
|
||||
});
|
||||
}, function(win) {
|
||||
registerCleanupFunction(function() {
|
||||
Services.prefs.clearUserPref("browser.chrome.favicons");
|
||||
win.close();
|
||||
});
|
||||
|
||||
win.gBrowser.loadOneTab(TEST_URL);
|
||||
win.gBrowser.loadOneTab(TEST_URL);
|
||||
});
|
||||
}
|
@ -6,19 +6,21 @@ function test() {
|
||||
|
||||
showTabView(function () {
|
||||
let tab = gBrowser.addTab();
|
||||
gBrowser.pinTab(tab);
|
||||
registerCleanupFunction(function () gBrowser.removeTab(tab));
|
||||
|
||||
let cw = TabView.getContentWindow();
|
||||
let body = cw.document.body;
|
||||
let [appTabIcon] = cw.iQ(".appTabTray .appTabIcon");
|
||||
whenAppTabIconAdded(function() {
|
||||
let cw = TabView.getContentWindow();
|
||||
let body = cw.document.body;
|
||||
let [appTabIcon] = cw.iQ(".appTabTray .appTabIcon");
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(appTabIcon, {type: "mousedown"}, cw);
|
||||
EventUtils.synthesizeMouse(body, 500, 100, {type: "mousemove"}, cw);
|
||||
EventUtils.synthesizeMouse(body, 500, 100, {type: "mouseup"}, cw);
|
||||
EventUtils.synthesizeMouseAtCenter(appTabIcon, {type: "mousedown"}, cw);
|
||||
EventUtils.synthesizeMouse(body, 500, 100, {type: "mousemove"}, cw);
|
||||
EventUtils.synthesizeMouse(body, 500, 100, {type: "mouseup"}, cw);
|
||||
|
||||
ok(TabView.isVisible(), "tabview is still visible");
|
||||
ok(TabView.isVisible(), "tabview is still visible");
|
||||
|
||||
hideTabView(finish);
|
||||
hideTabView(finish);
|
||||
});
|
||||
gBrowser.pinTab(tab);
|
||||
});
|
||||
}
|
||||
|
@ -385,3 +385,17 @@ function togglePrivateBrowsing(callback) {
|
||||
|
||||
pb.privateBrowsingEnabled = !pb.privateBrowsingEnabled;
|
||||
}
|
||||
|
||||
// ----------
|
||||
function whenAppTabIconAdded(callback, win) {
|
||||
win = win || window;
|
||||
|
||||
let contentWindow = win.TabView.getContentWindow();
|
||||
let groupItems = contentWindow.GroupItems.groupItems;
|
||||
let groupItem = groupItems[(groupItems.length - 1)];
|
||||
|
||||
groupItem.addSubscriber("appTabIconAdded", function onAppTabIconAdded() {
|
||||
groupItem.removeSubscriber("appTabIconAdded", onAppTabIconAdded);
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
7
browser/components/tabview/test/test_bug678374.html
Normal file
@ -0,0 +1,7 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Bug 678374</title>
|
||||
<link rel="icon" type="image/png" id="favicon" href="test_bug678374_icon16.png" />
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
BIN
browser/components/tabview/test/test_bug678374_icon16.png
Normal file
After Width: | Height: | Size: 924 B |
@ -51,6 +51,12 @@ let Keys = { meta: false };
|
||||
// Class: UI
|
||||
// Singleton top-level UI manager.
|
||||
let UI = {
|
||||
// Pref that controls whether to display site icons
|
||||
PREF_CHROME_SITE_ICONS: "browser.chrome.site_icons",
|
||||
|
||||
// Pref that controls whether to display fav icons
|
||||
PREF_CHROME_FAVICONS: "browser.chrome.favicons",
|
||||
|
||||
// Variable: _frameInitialized
|
||||
// True if the Tab View UI frame has been initialized.
|
||||
_frameInitialized: false,
|
||||
@ -141,6 +147,12 @@ let UI = {
|
||||
// Used to keep track of the tab strip smooth scroll value.
|
||||
_originalSmoothScroll: null,
|
||||
|
||||
// Used to keep track of the browser.chrome.site_icons pref value.
|
||||
_prefSiteIcons: null,
|
||||
|
||||
// Used to keep track of the browser.chrome.favicons pref value.
|
||||
_prefFavicons: null,
|
||||
|
||||
// ----------
|
||||
// Function: toString
|
||||
// Prints [UI] for debug use
|
||||
@ -241,6 +253,10 @@ let UI = {
|
||||
// ___ add tab action handlers
|
||||
this._addTabActionHandlers();
|
||||
|
||||
// ___ add preference observers
|
||||
Services.prefs.addObserver(this.PREF_CHROME_SITE_ICONS, this, false);
|
||||
Services.prefs.addObserver(this.PREF_CHROME_FAVICONS, this, false);
|
||||
|
||||
// ___ groups
|
||||
GroupItems.init();
|
||||
GroupItems.pauseArrange();
|
||||
@ -292,6 +308,9 @@ let UI = {
|
||||
let event = document.createEvent("Events");
|
||||
event.initEvent("tabviewframeinitialized", true, false);
|
||||
dispatchEvent(event);
|
||||
|
||||
// XXX this can be removed when bug 731868 is fixed
|
||||
event = null;
|
||||
} catch(e) {
|
||||
Utils.log(e);
|
||||
} finally {
|
||||
@ -314,6 +333,9 @@ let UI = {
|
||||
Storage.uninit();
|
||||
StoragePolicy.uninit();
|
||||
|
||||
Services.prefs.removeObserver(this.PREF_CHROME_SITE_ICONS, this);
|
||||
Services.prefs.removeObserver(this.PREF_CHROME_FAVICONS, this);
|
||||
|
||||
this._removeTabActionHandlers();
|
||||
this._currentTab = null;
|
||||
this._pageBounds = null;
|
||||
@ -851,6 +873,19 @@ let UI = {
|
||||
AllTabs.unregister(name, this._eventListeners[name]);
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: observe
|
||||
// Observes different preference value changes.
|
||||
observe: function UI_observe(subject, topic, data) {
|
||||
if (data == this.PREF_CHROME_SITE_ICONS) {
|
||||
this._prefSiteIcons =
|
||||
Services.prefs.getBoolPref(this.PREF_CHROME_SITE_ICONS);
|
||||
} else if (data == this.PREF_CHROME_FAVICONS) {
|
||||
this._prefFavicons =
|
||||
Services.prefs.getBoolPref(this.PREF_CHROME_FAVICONS);
|
||||
}
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: goToTab
|
||||
// Selects the given xul:tab in the browser.
|
||||
@ -1604,7 +1639,6 @@ let UI = {
|
||||
// ----------
|
||||
// Function: _saveAll
|
||||
// Saves all data associated with TabView.
|
||||
// TODO: Save info items
|
||||
_saveAll: function UI__saveAll() {
|
||||
this._save();
|
||||
GroupItems.saveAll();
|
||||
@ -1612,31 +1646,68 @@ let UI = {
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: shouldLoadFavIcon
|
||||
// Takes a xul:browser and checks whether we should display a favicon for it.
|
||||
shouldLoadFavIcon: function UI_shouldLoadFavIcon(browser) {
|
||||
return !(browser.contentDocument instanceof window.ImageDocument) &&
|
||||
(browser.currentURI.schemeIs("about") ||
|
||||
gBrowser.shouldLoadFavIcon(browser.contentDocument.documentURIObject));
|
||||
// Function: _isImageDocument
|
||||
// Checks whether an image is loaded into the given tab.
|
||||
_isImageDocument: function UI__isImageDocument(tab, callback) {
|
||||
let mm = tab.linkedBrowser.messageManager;
|
||||
let message = "Panorama:isImageDocument";
|
||||
|
||||
mm.addMessageListener(message, function onMessage(cx) {
|
||||
mm.removeMessageListener(cx.name, onMessage);
|
||||
callback(cx.json.isImageDocument);
|
||||
});
|
||||
mm.sendAsyncMessage(message);
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: _shouldLoadFavIcon
|
||||
// Checks whether fav icon should be loaded for a given tab.
|
||||
_shouldLoadFavIcon: function UI__shouldLoadFavIcon(tab) {
|
||||
let uri = tab.linkedBrowser.currentURI;
|
||||
|
||||
if (!uri)
|
||||
return false;
|
||||
|
||||
if (this._prefSiteIcons == null)
|
||||
this._prefSiteIcons =
|
||||
Services.prefs.getBoolPref(this.PREF_CHROME_SITE_ICONS);
|
||||
|
||||
if (!this._prefSiteIcons)
|
||||
return false;
|
||||
|
||||
if (this._prefFavicons == null)
|
||||
this._prefFavicons =
|
||||
Services.prefs.getBoolPref(this.PREF_CHROME_FAVICONS);
|
||||
|
||||
return (this._prefFavicons && ("schemeIs" in uri) &&
|
||||
(uri.schemeIs("http") || uri.schemeIs("https")));
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: getFavIconUrlForTab
|
||||
// Gets fav icon url for the given xul:tab.
|
||||
getFavIconUrlForTab: function UI_getFavIconUrlForTab(tab) {
|
||||
let url;
|
||||
getFavIconUrlForTab: function UI_getFavIconUrlForTab(tab, callback) {
|
||||
this._isImageDocument(tab, function(isImageDoc) {
|
||||
if (isImageDoc) {
|
||||
callback(tab.pinned ? tab.image : null);
|
||||
} else {
|
||||
let tabImage = tab.image;
|
||||
if (tabImage) {
|
||||
// if starts with http/https, fetch icon from favicon service via the moz-anno protocal
|
||||
if (/^https?:/.test(tabImage))
|
||||
tabImage = gFavIconService.getFaviconLinkForIcon(gWindow.makeURI(tab.image)).spec;
|
||||
|
||||
if (tab.image) {
|
||||
// if starts with http/https, fetch icon from favicon service via the moz-anno protocal
|
||||
if (/^https?:/.test(tab.image))
|
||||
url = gFavIconService.getFaviconLinkForIcon(gWindow.makeURI(tab.image)).spec;
|
||||
else
|
||||
url = tab.image;
|
||||
} else {
|
||||
url = gFavIconService.getFaviconImageForPage(tab.linkedBrowser.currentURI).spec;
|
||||
}
|
||||
|
||||
return url;
|
||||
callback(tabImage);
|
||||
} else {
|
||||
// determine to load the default/cached icon or not and also ensure we don't show the default icon
|
||||
// for about:-style error pages
|
||||
let url = null;
|
||||
if (this._shouldLoadFavIcon(tab))
|
||||
url = gFavIconService.getFaviconImageForPage(tab.linkedBrowser.currentURI).spec;
|
||||
callback(url);
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
// ----------
|
||||
|
@ -109,6 +109,7 @@ let PageThumbs = {
|
||||
* @param aCallback The function to be called when finished (optional).
|
||||
*/
|
||||
captureAndStore: function PageThumbs_captureAndStore(aBrowser, aCallback) {
|
||||
let url = aBrowser.currentURI.spec;
|
||||
this.capture(aBrowser.contentWindow, function (aInputStream) {
|
||||
let telemetryStoreTime = new Date();
|
||||
|
||||
@ -123,7 +124,7 @@ let PageThumbs = {
|
||||
}
|
||||
|
||||
// Get a writeable cache entry.
|
||||
PageThumbsCache.getWriteEntry(aBrowser.currentURI.spec, function (aEntry) {
|
||||
PageThumbsCache.getWriteEntry(url, function (aEntry) {
|
||||
if (!aEntry) {
|
||||
finish(false);
|
||||
return;
|
||||
|
@ -13,6 +13,7 @@ include $(topsrcdir)/config/rules.mk
|
||||
|
||||
_BROWSER_FILES = \
|
||||
browser_thumbnails_capture.js \
|
||||
browser_thumbnails_bug726727.js \
|
||||
head.js \
|
||||
$(NULL)
|
||||
|
||||
|
@ -0,0 +1,19 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* These tests ensure that capturing a sites's thumbnail, saving it and
|
||||
* retrieving it from the cache works.
|
||||
*/
|
||||
function runTests() {
|
||||
// Create a tab that shows an error page.
|
||||
let tab = gBrowser.addTab("http://non-existant.url/");
|
||||
let browser = tab.linkedBrowser;
|
||||
|
||||
yield browser.addEventListener("DOMContentLoaded", function onLoad() {
|
||||
browser.removeEventListener("DOMContentLoaded", onLoad, false);
|
||||
executeSoon(next);
|
||||
}, false);
|
||||
|
||||
ok(!gBrowserThumbnails._shouldCapture(browser), "we're not going to capture an error page");
|
||||
}
|
@ -49,7 +49,7 @@ Cu.import("resource://gre/modules/NetUtil.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/devtools/dbg-server.jsm");
|
||||
Cu.import("resource://gre/modules/devtools/dbg-client.jsm");
|
||||
Cu.import("resource:///modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource:///modules/source-editor.jsm");
|
||||
|
||||
let EXPORTED_SYMBOLS = ["DebuggerUI"];
|
||||
|
@ -197,7 +197,68 @@ function testFailGroup(data) {
|
||||
laterGroup = undefined;
|
||||
laterRejection = undefined;
|
||||
|
||||
finished();
|
||||
testTrap();
|
||||
}
|
||||
|
||||
function testTrap() {
|
||||
var p = new Promise();
|
||||
var message = "Expected exception";
|
||||
p.chainPromise(
|
||||
function() {
|
||||
throw new Error(message);
|
||||
}).trap(
|
||||
function(aError) {
|
||||
is(aError instanceof Error, true, "trap received exception");
|
||||
is(aError.message, message, "trap received correct exception");
|
||||
return 1;
|
||||
}).chainPromise(
|
||||
function(aResult) {
|
||||
is(aResult, 1, "trap restored correct result");
|
||||
testAlways();
|
||||
});
|
||||
p.resolve();
|
||||
}
|
||||
|
||||
function testAlways() {
|
||||
var shouldbeTrue1 = false;
|
||||
var shouldbeTrue2 = false;
|
||||
var p = new Promise();
|
||||
p.chainPromise(
|
||||
function() {
|
||||
throw new Error();
|
||||
}
|
||||
).chainPromise(// Promise rejected, should not be executed
|
||||
function() {
|
||||
ok(false, "This should not be executed");
|
||||
}
|
||||
).always(
|
||||
function(x) {
|
||||
shouldbeTrue1 = true;
|
||||
return "random value";
|
||||
}
|
||||
).trap(
|
||||
function(arg) {
|
||||
ok((arg instanceof Error), "The random value should be ignored");
|
||||
return 1;// We should still have this result later
|
||||
}
|
||||
).trap(
|
||||
function() {
|
||||
ok(false, "This should not be executed 2");
|
||||
}
|
||||
).always(
|
||||
function() {
|
||||
shouldbeTrue2 = true;
|
||||
}
|
||||
).then(
|
||||
function(aResult){
|
||||
ok(shouldbeTrue1, "First always must be executed");
|
||||
ok(shouldbeTrue2, "Second always must be executed");
|
||||
is(aResult, 1, "Result should be unaffected by always");
|
||||
|
||||
testComplete();
|
||||
}
|
||||
);
|
||||
p.resolve();
|
||||
}
|
||||
|
||||
function fail() {
|
||||
@ -207,6 +268,36 @@ function fail() {
|
||||
finish();
|
||||
}
|
||||
|
||||
/**
|
||||
* We wish to launch all tests with several configurations (at the moment,
|
||||
* non-debug and debug mode).
|
||||
*
|
||||
* If 0, we have not completed any test yet.
|
||||
* If 1, we have completed the tests in non-debug mode.
|
||||
* If 2, we have also completed the tests in debug mode.
|
||||
*/
|
||||
var configurationTestComplete = 0;
|
||||
function testComplete() {
|
||||
switch (configurationTestComplete) {
|
||||
case 0:
|
||||
info("Finished run in non-debug mode");
|
||||
configurationTestComplete = 1;
|
||||
Promise.Debug.setDebug(true);
|
||||
window.setTimeout(testBasic, 0);
|
||||
return;
|
||||
case 1:
|
||||
info("Finished run in debug mode");
|
||||
configurationTestComplete = 2;
|
||||
Promise.Debug.setDebug(false);
|
||||
window.setTimeout(finished, 0);
|
||||
return;
|
||||
default:
|
||||
ok(false, "Internal error in testComplete "+configurationTestComplete);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function finished() {
|
||||
gBrowser.removeCurrentTab();
|
||||
info("Finishing Promise Tests");
|
||||
|
@ -48,6 +48,7 @@ include $(topsrcdir)/config/rules.mk
|
||||
MOZ_PKG_REMOVALS = $(srcdir)/removed-files.in
|
||||
|
||||
MOZ_PKG_MANIFEST_P = $(srcdir)/package-manifest.in
|
||||
MOZ_PKG_FATAL_WARNINGS = 1
|
||||
|
||||
MOZ_NONLOCALIZED_PKG_LIST = \
|
||||
xpcom \
|
||||
|
@ -25,19 +25,21 @@
|
||||
[@AB_CD@]
|
||||
@BINPATH@/chrome/@AB_CD@@JAREXT@
|
||||
@BINPATH@/chrome/@AB_CD@.manifest
|
||||
@BINPATH@/@PREF_DIR@/firefox-l10n.js
|
||||
@BINPATH@/searchplugins/*
|
||||
@BINPATH@/defaults/profile/bookmarks.html
|
||||
@BINPATH@/defaults/profile/chrome/*
|
||||
@BINPATH@/defaults/profile/localstore.rdf
|
||||
@BINPATH@/defaults/profile/mimeTypes.rdf
|
||||
@BINPATH@/defaults/profile/chrome/*
|
||||
@BINPATH@/update.locale
|
||||
@BINPATH@/updater.ini
|
||||
@BINPATH@/dictionaries/*
|
||||
@BINPATH@/hyphenation/*
|
||||
@BINPATH@/@PREF_DIR@/firefox-l10n.js
|
||||
@BINPATH@/searchplugins/*
|
||||
#ifdef XP_WIN32
|
||||
@BINPATH@/uninstall/helper.exe
|
||||
#endif
|
||||
#ifdef MOZ_UPDATER
|
||||
@BINPATH@/update.locale
|
||||
@BINPATH@/updater.ini
|
||||
#endif
|
||||
|
||||
[xpcom]
|
||||
@BINPATH@/dependentlibs.list
|
||||
@ -386,10 +388,10 @@
|
||||
@BINPATH@/components/RadioInterfaceLayer.js
|
||||
@BINPATH@/components/SmsDatabaseService.manifest
|
||||
@BINPATH@/components/SmsDatabaseService.js
|
||||
@BINPATH@/components/nsWifiWorker.js
|
||||
@BINPATH@/components/nsWifiWorker.manifest
|
||||
@BINPATH@/components/nsDOMWifiManager.js
|
||||
@BINPATH@/components/nsDOMWifiManager.manifest
|
||||
@BINPATH@/components/WifiWorker.js
|
||||
@BINPATH@/components/WifiWorker.manifest
|
||||
@BINPATH@/components/DOMWifiManager.js
|
||||
@BINPATH@/components/DOMWifiManager.manifest
|
||||
#endif
|
||||
@BINPATH@/components/BrowserProfileMigrators.manifest
|
||||
@BINPATH@/components/ProfileMigrator.js
|
||||
@ -556,11 +558,13 @@ bin/libfreebl_32int64_3.so
|
||||
|
||||
; [Updater]
|
||||
;
|
||||
#ifdef MOZ_UPDATER
|
||||
#ifdef XP_MACOSX
|
||||
@BINPATH@/updater.app/
|
||||
#else
|
||||
@BINPATH@/updater@BIN_SUFFIX@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
; [MaintenanceService]
|
||||
;
|
||||
|
@ -15,7 +15,6 @@
|
||||
@DLL_PREFIX@mozjs@DLL_SUFFIX@
|
||||
#endif
|
||||
LICENSE
|
||||
update.locale
|
||||
browserconfig.properties
|
||||
chrome/US.jar
|
||||
chrome/app-chrome.manifest
|
||||
@ -695,6 +694,15 @@ uninstall/UninstallDeerPark.exe
|
||||
uninstall/UninstallFirefox.exe
|
||||
uninstall/uninst.exe
|
||||
uninstall/uninstall.exe
|
||||
update.locale
|
||||
#ifndef MOZ_UPDATER
|
||||
#ifdef XP_MACOSX
|
||||
updater.app/
|
||||
#else
|
||||
updater@BIN_SUFFIX@
|
||||
#endif
|
||||
updater.ini
|
||||
#endif
|
||||
xpicleanup@BIN_SUFFIX@
|
||||
#ifdef MOZ_OMNIJAR
|
||||
omni.jar
|
||||
@ -927,10 +935,10 @@ xpicleanup@BIN_SUFFIX@
|
||||
components/nsTelephonyWorker.js
|
||||
components/Telephony.manifest
|
||||
components/Telephony.js
|
||||
components/nsWifiWorker.js
|
||||
components/nsWifiWorker.manifest
|
||||
components/nsDOMWifiManager.js
|
||||
components/nsDOMWifiManager.manifest
|
||||
components/WifiWorker.js
|
||||
components/WifiWorker.manifest
|
||||
components/DOMWifiManager.js
|
||||
components/DOMWifiManager.manifest
|
||||
#endif
|
||||
components/txEXSLTRegExFunctions.js
|
||||
components/Weave.js
|
||||
|
@ -17,7 +17,7 @@ browser.contentHandlers.types.1.uri=http://add.my.yahoo.com/rss?url=%s
|
||||
# TRANSLATION NOTE: {moz:domain} and {searchTerms} are placeholders for the site
|
||||
# to be searched and the user's search query. Place them in the appropriate location
|
||||
# for your locale's URL but do not translate them.
|
||||
browser.search.siteSearchURL=http://www.google.com/search?ie=UTF-8&oe=UTF-8&sourceid=navclient&q=site%3A{moz:domain}+{searchTerms}
|
||||
browser.search.siteSearchURL=https://www.google.com/search?ie=UTF-8&oe=UTF-8&sourceid=navclient&q=site%3A{moz:domain}+{searchTerms}
|
||||
|
||||
# increment this number when anything gets changed in the list below. This will
|
||||
# cause Firefox to re-read these prefs and inject any new handlers into the
|
||||
|
@ -1,6 +1,7 @@
|
||||
<!ENTITY % brandDTD
|
||||
SYSTEM "chrome://branding/locale/brand.dtd">
|
||||
%brandDTD;
|
||||
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
|
||||
%brandDTD;
|
||||
<!ENTITY % syncBrandDTD SYSTEM "chrome://browser/locale/syncBrand.dtd">
|
||||
%syncBrandDTD;
|
||||
|
||||
<!-- These strings are used in the about:home page -->
|
||||
|
||||
@ -8,8 +9,6 @@
|
||||
|
||||
<!ENTITY abouthome.searchEngineButton.label "Search">
|
||||
|
||||
<!ENTITY abouthome.aboutMozilla "About Mozilla">
|
||||
|
||||
<!-- LOCALIZATION NOTE (abouthome.defaultSnippet1.v1):
|
||||
text in <a/> will be linked to the Firefox features page on mozilla.com
|
||||
-->
|
||||
@ -19,5 +18,9 @@
|
||||
-->
|
||||
<!ENTITY abouthome.defaultSnippet2.v1 "It's easy to customize your Firefox exactly the way you want it. <a>Choose from thousands of add-ons</a>.">
|
||||
|
||||
<!ENTITY abouthome.syncSetup.label "Set Up Sync">
|
||||
<!ENTITY abouthome.pairDevice.label "Pair a Device">
|
||||
<!ENTITY abouthome.bookmarksButton.label "Bookmarks">
|
||||
<!ENTITY abouthome.historyButton.label "History">
|
||||
<!ENTITY abouthome.settingsButton.label "Settings">
|
||||
<!ENTITY abouthome.addonsButton.label "Add-ons">
|
||||
<!ENTITY abouthome.appsButton.label "Marketplace">
|
||||
<!ENTITY abouthome.downloadsButton.label "Downloads">
|
||||
|
@ -13,22 +13,22 @@
|
||||
<Description>Google Search</Description>
|
||||
<InputEncoding>UTF-8</InputEncoding>
|
||||
<Image width="16" height="16">data:image/png;base64,AAABAAEAEBAAAAEAGABoAwAAFgAAACgAAAAQAAAAIAAAAAEAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADs9Pt8xetPtu9FsfFNtu%2BTzvb2%2B%2Fne4dFJeBw0egA%2FfAJAfAA8ewBBegAAAAD%2B%2FPtft98Mp%2BwWsfAVsvEbs%2FQeqvF8xO7%2F%2F%2F63yqkxdgM7gwE%2FggM%2BfQA%2BegBDeQDe7PIbotgQufcMufEPtfIPsvAbs%2FQvq%2Bfz%2Bf%2F%2B%2B%2FZKhR05hgBBhQI8hgBAgAI9ewD0%2B%2Fg3pswAtO8Cxf4Kw%2FsJvvYAqupKsNv%2B%2Fv7%2F%2FP5VkSU0iQA7jQA9hgBDgQU%2BfQH%2F%2Ff%2FQ6fM4sM4KsN8AteMCruIqqdbZ7PH8%2Fv%2Fg6Nc%2Fhg05kAA8jAM9iQI%2BhQA%2BgQDQu6b97uv%2F%2F%2F7V8Pqw3eiWz97q8%2Ff%2F%2F%2F%2F7%2FPptpkkqjQE4kwA7kAA5iwI8iAA8hQCOSSKdXjiyflbAkG7u2s%2F%2B%2F%2F39%2F%2F7r8utrqEYtjQE8lgA7kwA7kwA9jwA9igA9hACiWSekVRyeSgiYSBHx6N%2F%2B%2Fv7k7OFRmiYtlAA5lwI7lwI4lAA7kgI9jwE9iwI4iQCoVhWcTxCmb0K%2BooT8%2Fv%2F7%2F%2F%2FJ2r8fdwI1mwA3mQA3mgA8lAE8lAE4jwA9iwE%2BhwGfXifWvqz%2B%2Ff%2F58u%2Fev6Dt4tr%2B%2F%2F2ZuIUsggA7mgM6mAM3lgA5lgA6kQE%2FkwBChwHt4dv%2F%2F%2F728ei1bCi7VAC5XQ7kz7n%2F%2F%2F6bsZkgcB03lQA9lgM7kwA2iQktZToPK4r9%2F%2F%2F9%2F%2F%2FSqYK5UwDKZAS9WALIkFn%2B%2F%2F3%2F%2BP8oKccGGcIRJrERILYFEMwAAuEAAdX%2F%2Ff7%2F%2FP%2B%2BfDvGXQLIZgLEWgLOjlf7%2F%2F%2F%2F%2F%2F9QU90EAPQAAf8DAP0AAfMAAOUDAtr%2F%2F%2F%2F7%2B%2Fu2bCTIYwDPZgDBWQDSr4P%2F%2Fv%2F%2F%2FP5GRuABAPkAA%2FwBAfkDAPAAAesAAN%2F%2F%2B%2Fz%2F%2F%2F64g1C5VwDMYwK8Yg7y5tz8%2Fv%2FV1PYKDOcAAP0DAf4AAf0AAfYEAOwAAuAAAAD%2F%2FPvi28ymXyChTATRrIb8%2F%2F3v8fk6P8MAAdUCAvoAAP0CAP0AAfYAAO4AAACAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAA</Image>
|
||||
<Url type="application/x-suggestions+json" method="GET" template="http://suggestqueries.google.com/complete/search?output=firefox&client=firefox&hl={moz:locale}&q={searchTerms}"/>
|
||||
<Url type="text/html" method="GET" template="http://www.google.com/search">
|
||||
<Url type="application/x-suggestions+json" method="GET" template="https://www.google.com/complete/search?output=firefox&client=firefox&hl={moz:locale}&q={searchTerms}"/>
|
||||
<Url type="text/html" method="GET" template="https://www.google.com/search">
|
||||
#expand __GOOGLE_PARAMS__
|
||||
#expand __GOOGLE_CLIENT_PARAM__
|
||||
</Url>
|
||||
<!-- Keyword search URL is the same as the default, but with an additional parameter -->
|
||||
<Url type="application/x-moz-keywordsearch" method="GET" template="http://www.google.com/search">
|
||||
<Url type="application/x-moz-keywordsearch" method="GET" template="https://www.google.com/search">
|
||||
#expand __GOOGLE_PARAMS__
|
||||
#expand __GOOGLE_CLIENT_PARAM__
|
||||
<Param name="channel" value="fflb"/>
|
||||
</Url>
|
||||
<!-- Context/Right-click search URL is the same as the default, but with an additional parameter -->
|
||||
<Url type="application/x-moz-contextsearch" method="GET" template="http://www.google.com/search">
|
||||
<Url type="application/x-moz-contextsearch" method="GET" template="https://www.google.com/search">
|
||||
#expand __GOOGLE_PARAMS__
|
||||
#expand __GOOGLE_CLIENT_PARAM__
|
||||
<Param name="channel" value="rcs"/>
|
||||
</Url>
|
||||
<SearchForm>http://www.google.com/</SearchForm>
|
||||
<SearchForm>https://www.google.com/</SearchForm>
|
||||
</SearchPlugin>
|
||||
|
@ -383,6 +383,15 @@ let BlockedLinks = {
|
||||
Storage.set("blockedLinks", this.links);
|
||||
},
|
||||
|
||||
/**
|
||||
* Unblocks a given link.
|
||||
* @param aLink The link to unblock.
|
||||
*/
|
||||
unblock: function BlockedLinks_unblock(aLink) {
|
||||
if (this.isBlocked(aLink))
|
||||
delete this.links[aLink.url];
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns whether a given link is blocked.
|
||||
* @param aLink The link to check.
|
||||
@ -550,7 +559,7 @@ let Links = {
|
||||
* Resets the links cache.
|
||||
*/
|
||||
resetCache: function Links_resetCache() {
|
||||
this._links = [];
|
||||
this._links = null;
|
||||
},
|
||||
|
||||
/**
|
||||
@ -584,13 +593,17 @@ let Links = {
|
||||
*/
|
||||
let NewTabUtils = {
|
||||
/**
|
||||
* Resets the NewTabUtils module, its links and its storage.
|
||||
* Restores all sites that have been removed from the grid.
|
||||
*/
|
||||
reset: function NewTabUtils_reset() {
|
||||
restore: function NewTabUtils_restore() {
|
||||
Storage.clear();
|
||||
Links.resetCache();
|
||||
PinnedLinks.resetCache();
|
||||
BlockedLinks.resetCache();
|
||||
|
||||
Links.populateCache(function () {
|
||||
AllPages.update();
|
||||
}, true);
|
||||
},
|
||||
|
||||
allPages: AllPages,
|
||||
|