Merge cvs-trunk-mirror to mozilla-central.
--HG-- rename : js/src/jsapi.c => js/src/jsapi.cpp rename : js/src/jsarray.c => js/src/jsarray.cpp rename : js/src/jsatom.c => js/src/jsatom.cpp rename : js/src/jsdate.c => js/src/jsdate.cpp rename : js/src/jsemit.c => js/src/jsemit.cpp rename : js/src/jsgc.c => js/src/jsgc.cpp rename : js/src/jsinterp.c => js/src/jsinterp.cpp rename : js/src/jsnum.c => js/src/jsnum.cpp rename : js/src/jsobj.c => js/src/jsobj.cpp rename : js/src/jsopcode.c => js/src/jsopcode.cpp rename : js/src/jsscope.c => js/src/jsscope.cpp rename : js/src/jsstr.c => js/src/jsstr.cpp rename : js/src/prmjtime.c => js/src/prmjtime.cpp
@ -47,6 +47,8 @@ include $(topsrcdir)/config/config.mk
|
||||
default alldep all::
|
||||
$(RM) -rf $(DIST)/sdk
|
||||
$(RM) -rf $(DIST)/include
|
||||
$(RM) -rf $(DIST)/private
|
||||
$(RM) -rf $(DIST)/public
|
||||
$(RM) -rf _tests
|
||||
|
||||
TIERS += base
|
||||
@ -138,6 +140,9 @@ endif # WINNT
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
# we want to copy PDB files on Windows
|
||||
MAKE_SYM_STORE_ARGS := -c
|
||||
ifdef PDBSTR_PATH
|
||||
MAKE_SYM_STORE_ARGS += -i
|
||||
endif
|
||||
ifeq (,$(CYGWIN_WRAPPER))
|
||||
# this doesn't work with Cygwin Python
|
||||
MAKE_SYM_STORE_ARGS += --vcs-info
|
||||
|
@ -44,8 +44,9 @@ interface nsIDocument;
|
||||
interface nsIFrame;
|
||||
interface nsObjectFrame;
|
||||
interface nsIContent;
|
||||
interface nsITimer;
|
||||
|
||||
[uuid(933f7472-cbe3-4d95-a77a-ce7ea3812b32)]
|
||||
[uuid(27386cf1-f27e-4d2d-9bf4-c4621d50d299)]
|
||||
interface nsIAccessibilityService : nsIAccessibleRetrieval
|
||||
{
|
||||
nsIAccessible createOuterDocAccessible(in nsIDOMNode aNode);
|
||||
@ -100,6 +101,17 @@ interface nsIAccessibilityService : nsIAccessibleRetrieval
|
||||
void invalidateSubtreeFor(in nsIPresShell aPresShell,
|
||||
in nsIContent aChangedContent,
|
||||
in PRUint32 aEvent);
|
||||
|
||||
/**
|
||||
* An internal doc load event has occured. Handle the event and remove it from the list.
|
||||
* @param aTimer The timer created to handle this doc load event
|
||||
* @param aClosure The nsIWebProgress* for the load event
|
||||
* @param aEventType The type of load event, one of: nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_START,
|
||||
* nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE or
|
||||
* nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_STOPPED
|
||||
*/
|
||||
void processDocLoadEvent(in nsITimer aTimer, in voidPtr aClosure, in PRUint32 aEventType);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -64,34 +64,28 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||
{"alertdialog", nsIAccessibleRole::ROLE_ALERT, eNameOkFromChildren, eNoValue, kNoReqStates, kEndEntry},
|
||||
{"application", nsIAccessibleRole::ROLE_APPLICATION, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
|
||||
{"button", nsIAccessibleRole::ROLE_PUSHBUTTON, eNameOkFromChildren, eNoValue, kNoReqStates,
|
||||
{&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
|
||||
{&nsAccessibilityAtoms::aria_pressed, kBoolState, nsIAccessibleStates::STATE_PRESSED},
|
||||
{&nsAccessibilityAtoms::aria_pressed, "mixed", nsIAccessibleStates::STATE_MIXED}, kEndEntry},
|
||||
{"checkbox", nsIAccessibleRole::ROLE_CHECKBUTTON, eNameOkFromChildren, eNoValue, nsIAccessibleStates::STATE_CHECKABLE,
|
||||
{&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
|
||||
{&nsAccessibilityAtoms::aria_checked, kBoolState, nsIAccessibleStates::STATE_CHECKED},
|
||||
{&nsAccessibilityAtoms::aria_checked, "mixed", nsIAccessibleStates::STATE_MIXED},
|
||||
{&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY}, kEndEntry},
|
||||
{"columnheader", nsIAccessibleRole::ROLE_COLUMNHEADER, eNameOkFromChildren, eNoValue, kNoReqStates,
|
||||
{&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
|
||||
{&nsAccessibilityAtoms::aria_selected, kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
|
||||
{&nsAccessibilityAtoms::aria_selected, "false", nsIAccessibleStates::STATE_SELECTABLE},
|
||||
{&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY}, kEndEntry},
|
||||
{"combobox", nsIAccessibleRole::ROLE_COMBOBOX, eNameLabelOrTitle, eHasValueMinMax,
|
||||
nsIAccessibleStates::STATE_COLLAPSED | nsIAccessibleStates::STATE_HASPOPUP,
|
||||
// Manually map EXT_STATE_SUPPORTS_AUTOCOMPLETION aria-autocomplete
|
||||
{&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
|
||||
{&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
|
||||
{&nsAccessibilityAtoms::aria_expanded, kBoolState, nsIAccessibleStates::STATE_EXPANDED}, kEndEntry},
|
||||
{"description", nsIAccessibleRole::ROLE_TEXT_CONTAINER, eNameOkFromChildren, eNoValue, kNoReqStates, kEndEntry},
|
||||
{"dialog", nsIAccessibleRole::ROLE_DIALOG, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
|
||||
{"document", nsIAccessibleRole::ROLE_DOCUMENT, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
|
||||
{"grid", nsIAccessibleRole::ROLE_TABLE, eNameLabelOrTitle, eNoValue, nsIAccessibleStates::STATE_FOCUSABLE,
|
||||
{&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
|
||||
{&nsAccessibilityAtoms::aria_multiselectable, kBoolState, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE},
|
||||
{&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY}, kEndEntry},
|
||||
{"gridcell", nsIAccessibleRole::ROLE_CELL, eNameOkFromChildren, eNoValue, kNoReqStates,
|
||||
{&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
|
||||
{&nsAccessibilityAtoms::aria_expanded, kBoolState, nsIAccessibleStates::STATE_EXPANDED},
|
||||
{&nsAccessibilityAtoms::aria_expanded, "false", nsIAccessibleStates::STATE_COLLAPSED},
|
||||
{&nsAccessibilityAtoms::aria_selected, kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
|
||||
@ -101,13 +95,11 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||
{"heading", nsIAccessibleRole::ROLE_HEADING, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
|
||||
{"img", nsIAccessibleRole::ROLE_GRAPHIC, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
|
||||
{"label", nsIAccessibleRole::ROLE_LABEL, eNameOkFromChildren, eNoValue, kNoReqStates, kEndEntry},
|
||||
{"link", nsIAccessibleRole::ROLE_LINK, eNameOkFromChildren, eNoValue, nsIAccessibleStates::STATE_LINKED,
|
||||
{&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE}, kEndEntry},
|
||||
{"link", nsIAccessibleRole::ROLE_LINK, eNameOkFromChildren, eNoValue, nsIAccessibleStates::STATE_LINKED, kEndEntry},
|
||||
{"list", nsIAccessibleRole::ROLE_LIST, eNameLabelOrTitle, eNoValue, kNoReqStates,
|
||||
{&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
|
||||
{&nsAccessibilityAtoms::aria_multiselectable, kBoolState, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE}, kEndEntry},
|
||||
{"listbox", nsIAccessibleRole::ROLE_LISTBOX, eNameLabelOrTitle, eNoValue, kNoReqStates,
|
||||
{&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
|
||||
{&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
|
||||
{&nsAccessibilityAtoms::aria_multiselectable, kBoolState, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE}, kEndEntry},
|
||||
{"listitem", nsIAccessibleRole::ROLE_LISTITEM, eNameOkFromChildren, eNoValue, kNoReqStates,
|
||||
@ -116,60 +108,46 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||
{&nsAccessibilityAtoms::aria_checked, kBoolState, nsIAccessibleStates::STATE_CHECKED | nsIAccessibleStates::STATE_CHECKABLE},
|
||||
{&nsAccessibilityAtoms::aria_checked, "mixed", nsIAccessibleStates::STATE_MIXED | nsIAccessibleStates::STATE_CHECKABLE},
|
||||
{&nsAccessibilityAtoms::aria_checked, "false", nsIAccessibleStates::STATE_CHECKABLE}, kEndEntry},
|
||||
{"menu", nsIAccessibleRole::ROLE_MENUPOPUP, eNameLabelOrTitle, eNoValue, kNoReqStates,
|
||||
{&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE}, kEndEntry},
|
||||
{"menubar", nsIAccessibleRole::ROLE_MENUBAR, eNameLabelOrTitle, eNoValue, kNoReqStates,
|
||||
{&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE}, kEndEntry},
|
||||
{"menu", nsIAccessibleRole::ROLE_MENUPOPUP, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
|
||||
{"menubar", nsIAccessibleRole::ROLE_MENUBAR, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
|
||||
{"menuitem", nsIAccessibleRole::ROLE_MENUITEM, eNameOkFromChildren, eNoValue, kNoReqStates,
|
||||
{&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
|
||||
{&nsAccessibilityAtoms::aria_checked, kBoolState, nsIAccessibleStates::STATE_CHECKED | nsIAccessibleStates::STATE_CHECKABLE},
|
||||
{&nsAccessibilityAtoms::aria_checked, "mixed", nsIAccessibleStates::STATE_MIXED | nsIAccessibleStates::STATE_CHECKABLE},
|
||||
{&nsAccessibilityAtoms::aria_checked, "false", nsIAccessibleStates::STATE_CHECKABLE}, kEndEntry},
|
||||
{"menuitemcheckbox", nsIAccessibleRole::ROLE_CHECK_MENU_ITEM, eNameOkFromChildren, eNoValue, nsIAccessibleStates::STATE_CHECKABLE,
|
||||
{&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
|
||||
{&nsAccessibilityAtoms::aria_checked, kBoolState, nsIAccessibleStates::STATE_CHECKED },
|
||||
{&nsAccessibilityAtoms::aria_checked, "mixed", nsIAccessibleStates::STATE_MIXED}, kEndEntry},
|
||||
{"menuitemradio", nsIAccessibleRole::ROLE_RADIO_MENU_ITEM, eNameOkFromChildren, eNoValue, nsIAccessibleStates::STATE_CHECKABLE,
|
||||
{&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
|
||||
{&nsAccessibilityAtoms::aria_checked, kBoolState, nsIAccessibleStates::STATE_CHECKED }, kEndEntry},
|
||||
{"option", nsIAccessibleRole::ROLE_OPTION, eNameOkFromChildren, eNoValue, kNoReqStates,
|
||||
{&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
|
||||
{&nsAccessibilityAtoms::aria_selected, kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
|
||||
{&nsAccessibilityAtoms::aria_selected, "false", nsIAccessibleStates::STATE_SELECTABLE},
|
||||
{&nsAccessibilityAtoms::aria_checked, kBoolState, nsIAccessibleStates::STATE_CHECKED | nsIAccessibleStates::STATE_CHECKABLE},
|
||||
{&nsAccessibilityAtoms::aria_checked, "mixed", nsIAccessibleStates::STATE_MIXED | nsIAccessibleStates::STATE_CHECKABLE},
|
||||
{&nsAccessibilityAtoms::aria_checked, "false", nsIAccessibleStates::STATE_CHECKABLE}, kEndEntry},
|
||||
{"presentation", nsIAccessibleRole::ROLE_NOTHING, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
|
||||
{"progressbar", nsIAccessibleRole::ROLE_PROGRESSBAR, eNameLabelOrTitle, eHasValueMinMax, nsIAccessibleStates::STATE_READONLY,
|
||||
{&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE}, kEndEntry},
|
||||
{"progressbar", nsIAccessibleRole::ROLE_PROGRESSBAR, eNameLabelOrTitle, eHasValueMinMax, nsIAccessibleStates::STATE_READONLY, kEndEntry},
|
||||
{"radio", nsIAccessibleRole::ROLE_RADIOBUTTON, eNameOkFromChildren, eNoValue, kNoReqStates,
|
||||
{&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
|
||||
{&nsAccessibilityAtoms::aria_checked, kBoolState, nsIAccessibleStates::STATE_CHECKED}, kEndEntry},
|
||||
{"radiogroup", nsIAccessibleRole::ROLE_GROUPING, eNameLabelOrTitle, eNoValue, kNoReqStates,
|
||||
{&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE}, kEndEntry},
|
||||
{"radiogroup", nsIAccessibleRole::ROLE_GROUPING, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
|
||||
{"region", nsIAccessibleRole::ROLE_PANE, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
|
||||
{"row", nsIAccessibleRole::ROLE_ROW, eNameOkFromChildren, eNoValue, kNoReqStates,
|
||||
{&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
|
||||
{&nsAccessibilityAtoms::aria_selected, kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
|
||||
{&nsAccessibilityAtoms::aria_selected, "false", nsIAccessibleStates::STATE_SELECTABLE},
|
||||
{&nsAccessibilityAtoms::aria_expanded, kBoolState, nsIAccessibleStates::STATE_EXPANDED},
|
||||
{&nsAccessibilityAtoms::aria_expanded, "false", nsIAccessibleStates::STATE_COLLAPSED}, kEndEntry},
|
||||
{"rowheader", nsIAccessibleRole::ROLE_ROWHEADER, eNameOkFromChildren, eNoValue, kNoReqStates,
|
||||
{&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
|
||||
{&nsAccessibilityAtoms::aria_selected, kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
|
||||
{&nsAccessibilityAtoms::aria_selected, "false", nsIAccessibleStates::STATE_SELECTABLE},
|
||||
{&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY}, kEndEntry},
|
||||
{"section", nsIAccessibleRole::ROLE_SECTION, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
|
||||
{"separator", nsIAccessibleRole::ROLE_SEPARATOR, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
|
||||
{"slider", nsIAccessibleRole::ROLE_SLIDER, eNameLabelOrTitle, eHasValueMinMax, kNoReqStates,
|
||||
{&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
|
||||
{&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY}, kEndEntry},
|
||||
{"spinbutton", nsIAccessibleRole::ROLE_SPINBUTTON, eNameLabelOrTitle, eHasValueMinMax, kNoReqStates,
|
||||
{&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
|
||||
{&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY}, kEndEntry},
|
||||
{"status", nsIAccessibleRole::ROLE_STATUSBAR, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
|
||||
{"tab", nsIAccessibleRole::ROLE_PAGETAB, eNameOkFromChildren, eNoValue, kNoReqStates,
|
||||
{&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE}, kEndEntry},
|
||||
{"tab", nsIAccessibleRole::ROLE_PAGETAB, eNameOkFromChildren, eNoValue, kNoReqStates, kEndEntry},
|
||||
{"tablist", nsIAccessibleRole::ROLE_PAGETABLIST, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
|
||||
{"tabpanel", nsIAccessibleRole::ROLE_PROPERTYPAGE, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
|
||||
{"textbox", nsIAccessibleRole::ROLE_ENTRY, eNameLabelOrTitle, eNoValue, kNoReqStates,
|
||||
@ -177,21 +155,16 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||
// Manually map EXT_STATE_SUPPORTS_AUTOCOMPLETION aria-autocomplete
|
||||
{&nsAccessibilityAtoms::aria_autocomplete, "list", nsIAccessibleStates::STATE_HASPOPUP},
|
||||
{&nsAccessibilityAtoms::aria_autocomplete, "both", nsIAccessibleStates::STATE_HASPOPUP},
|
||||
{&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
|
||||
{&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY}, kEndEntry},
|
||||
{"toolbar", nsIAccessibleRole::ROLE_TOOLBAR, eNameLabelOrTitle, eNoValue, kNoReqStates,
|
||||
{&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE}, kEndEntry},
|
||||
{"toolbar", nsIAccessibleRole::ROLE_TOOLBAR, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
|
||||
{"tooltip", nsIAccessibleRole::ROLE_TOOLTIP, eNameOkFromChildren, eNoValue, kNoReqStates, kEndEntry},
|
||||
{"tree", nsIAccessibleRole::ROLE_OUTLINE, eNameLabelOrTitle, eNoValue, kNoReqStates,
|
||||
{&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
|
||||
{&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
|
||||
{&nsAccessibilityAtoms::aria_multiselectable, kBoolState, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE}, kEndEntry},
|
||||
{"treegrid", nsIAccessibleRole::ROLE_TREE_TABLE, eNameLabelOrTitle, eNoValue, kNoReqStates,
|
||||
{&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
|
||||
{&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
|
||||
{&nsAccessibilityAtoms::aria_multiselectable, kBoolState, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE}, kEndEntry},
|
||||
{"treeitem", nsIAccessibleRole::ROLE_OUTLINEITEM, eNameOkFromChildren, eNoValue, kNoReqStates,
|
||||
{&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
|
||||
{&nsAccessibilityAtoms::aria_selected, kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
|
||||
{&nsAccessibilityAtoms::aria_selected, "false", nsIAccessibleStates::STATE_SELECTABLE},
|
||||
{&nsAccessibilityAtoms::aria_expanded, kBoolState, nsIAccessibleStates::STATE_EXPANDED},
|
||||
@ -232,6 +205,7 @@ nsStateMapEntry nsARIAMap::gWAIUnivStateMap[] = {
|
||||
{&nsAccessibilityAtoms::aria_haspopup, kBoolState, nsIAccessibleStates::STATE_HASPOPUP},
|
||||
{&nsAccessibilityAtoms::aria_busy, "true", nsIAccessibleStates::STATE_BUSY},
|
||||
{&nsAccessibilityAtoms::aria_busy, "error", nsIAccessibleStates::STATE_INVALID},
|
||||
{&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
|
||||
kEndEntry
|
||||
};
|
||||
|
||||
|
@ -95,6 +95,9 @@ nsApplicationAccessibleWrap *nsAccessNode::gApplicationAccessible = nsnull;
|
||||
nsIAccessibilityService *nsAccessNode::sAccService = nsnull;
|
||||
nsIAccessibilityService *nsAccessNode::GetAccService()
|
||||
{
|
||||
if (!gIsAccessibilityActive)
|
||||
return nsnull;
|
||||
|
||||
if (!sAccService) {
|
||||
nsresult rv = CallGetService("@mozilla.org/accessibilityService;1",
|
||||
&sAccService);
|
||||
@ -222,8 +225,10 @@ NS_IMETHODIMP nsAccessNode::GetUniqueID(void **aUniqueID)
|
||||
|
||||
NS_IMETHODIMP nsAccessNode::GetOwnerWindow(void **aWindow)
|
||||
{
|
||||
*aWindow = nsnull;
|
||||
nsCOMPtr<nsIAccessibleDocument> docAccessible(GetDocAccessible());
|
||||
NS_ASSERTION(docAccessible, "No root accessible pointer back, Init() not called.");
|
||||
if (!docAccessible)
|
||||
return NS_ERROR_FAILURE; // This node or doc accessible is shut down
|
||||
return docAccessible->GetWindowHandle(aWindow);
|
||||
}
|
||||
|
||||
@ -315,7 +320,7 @@ void nsAccessNode::ShutdownXPAccessibility()
|
||||
NS_IF_RELEASE(sAccService);
|
||||
|
||||
nsApplicationAccessibleWrap::Unload();
|
||||
ClearCache(gGlobalDocAccessibleCache);
|
||||
gGlobalDocAccessibleCache.Enumerate(ClearDocCacheEntry, nsnull);
|
||||
|
||||
// Release gApplicationAccessible after everything else is shutdown
|
||||
// so we don't accidently create it again while tearing down root accessibles
|
||||
@ -791,6 +796,14 @@ PLDHashOperator nsAccessNode::ClearCacheEntry(const void* aKey, nsCOMPtr<nsIAcce
|
||||
return PL_DHASH_REMOVE;
|
||||
}
|
||||
|
||||
PLDHashOperator nsAccessNode::ClearDocCacheEntry(const void* aKey, nsCOMPtr<nsIAccessNode>& aAccessNode, void* aUserArg)
|
||||
{
|
||||
nsCOMPtr<nsPIAccessNode> privateAccessNode(do_QueryInterface(aAccessNode));
|
||||
privateAccessNode->Shutdown();
|
||||
|
||||
return PL_DHASH_NEXT; // nsDocAccessible::Shutdown() removes the doc from doc cache
|
||||
}
|
||||
|
||||
void
|
||||
nsAccessNode::ClearCache(nsAccessNodeHashtable& aCache)
|
||||
{
|
||||
|
@ -98,6 +98,7 @@ class nsAccessNode: public nsIAccessNode, public nsPIAccessNode
|
||||
static void ClearCache(nsAccessNodeHashtable& aCache);
|
||||
|
||||
static PLDHashOperator PR_CALLBACK ClearCacheEntry(const void* aKey, nsCOMPtr<nsIAccessNode>& aAccessNode, void* aUserArg);
|
||||
static PLDHashOperator PR_CALLBACK ClearDocCacheEntry(const void* aKey, nsCOMPtr<nsIAccessNode>& aAccessNode, void* aUserArg);
|
||||
|
||||
// Static cache methods for global document cache
|
||||
static already_AddRefed<nsIAccessibleDocument> GetDocAccessibleFor(nsIDocument *aDocument);
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include "nsAccessibilityService.h"
|
||||
#include "nsAccessibilityUtils.h"
|
||||
#include "nsARIAMap.h"
|
||||
#include "nsIContentViewer.h"
|
||||
#include "nsCURILoader.h"
|
||||
#include "nsDocAccessible.h"
|
||||
#include "nsHTMLImageAccessibleWrap.h"
|
||||
@ -155,10 +156,21 @@ nsAccessibilityService::Observe(nsISupports *aSubject, const char *aTopic,
|
||||
observerService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
|
||||
}
|
||||
nsCOMPtr<nsIWebProgress> progress(do_GetService(NS_DOCUMENTLOADER_SERVICE_CONTRACTID));
|
||||
if (progress) {
|
||||
if (progress)
|
||||
progress->RemoveProgressListener(static_cast<nsIWebProgressListener*>(this));
|
||||
}
|
||||
nsAccessNodeWrap::ShutdownAccessibility();
|
||||
// Cancel and release load timers
|
||||
while (mLoadTimers.Count() > 0 ) {
|
||||
nsCOMPtr<nsITimer> timer = mLoadTimers.ObjectAt(0);
|
||||
void *closure = nsnull;
|
||||
timer->GetClosure(&closure);
|
||||
if (closure) {
|
||||
nsIWebProgress *webProgress = static_cast<nsIWebProgress*>(closure);
|
||||
NS_RELEASE(webProgress); // Release nsIWebProgress for timer
|
||||
}
|
||||
timer->Cancel();
|
||||
mLoadTimers.RemoveObjectAt(0);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
@ -169,70 +181,94 @@ NS_IMETHODIMP nsAccessibilityService::OnStateChange(nsIWebProgress *aWebProgress
|
||||
{
|
||||
NS_ASSERTION(aStateFlags & STATE_IS_DOCUMENT, "Other notifications excluded");
|
||||
|
||||
if (0 == (aStateFlags & (STATE_START | STATE_STOP))) {
|
||||
if (!aWebProgress || 0 == (aStateFlags & (STATE_START | STATE_STOP))) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCAutoString name;
|
||||
aRequest->GetName(name);
|
||||
if (name.EqualsLiteral("about:blank"))
|
||||
return NS_OK;
|
||||
|
||||
if (NS_FAILED(aStatus) && (aStateFlags & STATE_START))
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsITimer> timer = do_CreateInstance("@mozilla.org/timer;1");
|
||||
if (!timer)
|
||||
return NS_OK;
|
||||
mLoadTimers.AppendObject(timer);
|
||||
NS_ADDREF(aWebProgress);
|
||||
|
||||
if (aStateFlags & STATE_START)
|
||||
timer->InitWithFuncCallback(StartLoadCallback, aWebProgress, 0,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
else if (NS_SUCCEEDED(aStatus))
|
||||
timer->InitWithFuncCallback(EndLoadCallback, aWebProgress, 0,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
else // Failed end load
|
||||
timer->InitWithFuncCallback(FailedLoadCallback, aWebProgress, 0,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAccessibilityService::ProcessDocLoadEvent(nsITimer *aTimer, void *aClosure, PRUint32 aEventType)
|
||||
{
|
||||
nsCOMPtr<nsIDOMWindow> domWindow;
|
||||
aWebProgress->GetDOMWindow(getter_AddRefs(domWindow));
|
||||
NS_ASSERTION(domWindow, "DOM Window for state change is null");
|
||||
NS_ENSURE_TRUE(domWindow, NS_ERROR_FAILURE);
|
||||
nsIWebProgress *webProgress = static_cast<nsIWebProgress*>(aClosure);
|
||||
webProgress->GetDOMWindow(getter_AddRefs(domWindow));
|
||||
NS_RELEASE(webProgress);
|
||||
mLoadTimers.RemoveObject(aTimer);
|
||||
NS_ENSURE_STATE(domWindow);
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> domDoc;
|
||||
domWindow->GetDocument(getter_AddRefs(domDoc));
|
||||
nsCOMPtr<nsIDOMNode> domDocNode(do_QueryInterface(domDoc));
|
||||
NS_ENSURE_TRUE(domDocNode, NS_ERROR_FAILURE);
|
||||
nsCOMPtr<nsIAccessibleDocument> docAccessible;
|
||||
|
||||
PRUint32 eventType = 0;
|
||||
if (aStateFlags & STATE_STOP) {
|
||||
// Do not create accessible for page load end events
|
||||
// in case it was already shut down before page finished loading
|
||||
docAccessible = nsAccessNode::GetDocAccessibleFor(domDocNode); // Cached doc accessibles only
|
||||
if (!docAccessible)
|
||||
return NS_OK;
|
||||
nsCOMPtr<nsIDOMDocument> domDocTest;
|
||||
docAccessible->GetDocument(getter_AddRefs(domDocTest));
|
||||
if (domDocTest != domDoc) {
|
||||
// Doc from accessible is not the doc we started from
|
||||
// We must be shutdown, and domDocTest should be null
|
||||
NS_ASSERTION(!domDocTest, "Doc not shut down but reports incorrect DOM document");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
eventType = NS_FAILED(aStatus) ? nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_STOPPED :
|
||||
nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE;
|
||||
}
|
||||
else {
|
||||
// Get the accessible for the new document.
|
||||
// If it not created yet this will create it & cache it, as well as
|
||||
// set up event listeners so that MSAA/ATK toolkit and internal
|
||||
// accessibility events will get fired.
|
||||
nsCOMPtr<nsIAccessible> accessible;
|
||||
GetAccessibleFor(domDocNode, getter_AddRefs(accessible)); // Create if necessary
|
||||
docAccessible = do_QueryInterface(accessible);
|
||||
eventType = nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_START;
|
||||
if (aEventType == nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_START) {
|
||||
nsCOMPtr<nsIWebNavigation> webNav(do_GetInterface(domWindow));
|
||||
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(webNav));
|
||||
NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
|
||||
NS_ENSURE_STATE(docShell);
|
||||
PRUint32 loadType;
|
||||
docShell->GetLoadType(&loadType);
|
||||
if (loadType == LOAD_RELOAD_NORMAL ||
|
||||
loadType == LOAD_RELOAD_BYPASS_CACHE ||
|
||||
loadType == LOAD_RELOAD_BYPASS_PROXY ||
|
||||
loadType == LOAD_RELOAD_BYPASS_PROXY_AND_CACHE) {
|
||||
eventType = nsIAccessibleEvent::EVENT_DOCUMENT_RELOAD;
|
||||
aEventType = nsIAccessibleEvent::EVENT_DOCUMENT_RELOAD;
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsPIAccessibleDocument> privDocAccessible = do_QueryInterface(docAccessible);
|
||||
if (eventType && privDocAccessible) {
|
||||
privDocAccessible->FireDocLoadEvents(eventType);
|
||||
}
|
||||
nsCOMPtr<nsIDOMDocument> domDoc;
|
||||
domWindow->GetDocument(getter_AddRefs(domDoc));
|
||||
nsCOMPtr<nsIDOMNode> docNode = do_QueryInterface(domDoc);
|
||||
NS_ENSURE_STATE(docNode);
|
||||
|
||||
nsCOMPtr<nsIAccessible> accessible;
|
||||
GetAccessibleFor(docNode, getter_AddRefs(accessible));
|
||||
nsCOMPtr<nsPIAccessibleDocument> privDocAccessible = do_QueryInterface(accessible);
|
||||
NS_ENSURE_STATE(privDocAccessible);
|
||||
privDocAccessible->FireDocLoadEvents(aEventType);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsAccessibilityService::StartLoadCallback(nsITimer *aTimer, void *aClosure)
|
||||
{
|
||||
nsIAccessibilityService *accService = nsAccessNode::GetAccService();
|
||||
if (accService)
|
||||
accService->ProcessDocLoadEvent(aTimer, aClosure, nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_START);
|
||||
}
|
||||
|
||||
void nsAccessibilityService::EndLoadCallback(nsITimer *aTimer, void *aClosure)
|
||||
{
|
||||
nsIAccessibilityService *accService = nsAccessNode::GetAccService();
|
||||
if (accService)
|
||||
accService->ProcessDocLoadEvent(aTimer, aClosure, nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE);
|
||||
}
|
||||
|
||||
void nsAccessibilityService::FailedLoadCallback(nsITimer *aTimer, void *aClosure)
|
||||
{
|
||||
nsIAccessibilityService *accService = nsAccessNode::GetAccService();
|
||||
if (accService)
|
||||
accService->ProcessDocLoadEvent(aTimer, aClosure, nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_STOPPED);
|
||||
}
|
||||
|
||||
/* void onProgressChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long aCurSelfProgress, in long aMaxSelfProgress, in long aCurTotalProgress, in long aMaxTotalProgress); */
|
||||
NS_IMETHODIMP nsAccessibilityService::OnProgressChange(nsIWebProgress *aWebProgress,
|
||||
nsIRequest *aRequest, PRInt32 aCurSelfProgress, PRInt32 aMaxSelfProgress,
|
||||
@ -378,6 +414,25 @@ nsAccessibilityService::CreateRootAccessible(nsIPresShell *aShell,
|
||||
nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(presShell));
|
||||
|
||||
nsCOMPtr<nsISupports> container = aDocument->GetContainer();
|
||||
nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(container);
|
||||
NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
|
||||
nsCOMPtr<nsIContentViewer> contentViewer;
|
||||
docShell->GetContentViewer(getter_AddRefs(contentViewer));
|
||||
NS_ENSURE_TRUE(contentViewer, NS_ERROR_FAILURE); // Doc was already shut down
|
||||
PRUint32 busyFlags;
|
||||
docShell->GetBusyFlags(&busyFlags);
|
||||
if (busyFlags != nsIDocShell::BUSY_FLAGS_NONE) {
|
||||
nsCOMPtr<nsIWebNavigation> webNav(do_GetInterface(docShell));
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
webNav->GetCurrentURI(getter_AddRefs(uri));
|
||||
NS_ENSURE_STATE(uri);
|
||||
nsCAutoString url;
|
||||
uri->GetSpec(url);
|
||||
if (url.EqualsLiteral("about:blank")) {
|
||||
return NS_OK; // No load events for a busy about:blank -- they are often temporary
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem =
|
||||
do_QueryInterface(container);
|
||||
NS_ENSURE_TRUE(docShellTreeItem, NS_ERROR_FAILURE);
|
||||
|
@ -40,7 +40,10 @@
|
||||
#define __nsAccessibilityService_h__
|
||||
|
||||
#include "nsIAccessibilityService.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsIWebProgress.h"
|
||||
#include "nsIWebProgressListener.h"
|
||||
#include "nsWeakReference.h"
|
||||
|
||||
@ -135,6 +138,11 @@ private:
|
||||
* @return PR_TRUE if there is a universal ARIA property set on the node
|
||||
*/
|
||||
PRBool HasUniversalAriaProperty(nsIContent *aContent, nsIWeakReference *aWeakShell);
|
||||
|
||||
static void StartLoadCallback(nsITimer *aTimer, void *aClosure);
|
||||
static void EndLoadCallback(nsITimer *aTimer, void *aClosure);
|
||||
static void FailedLoadCallback(nsITimer *aTimer, void *aClosure);
|
||||
nsCOMArray<nsITimer> mLoadTimers;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -78,11 +78,14 @@ void nsCaretAccessible::Shutdown()
|
||||
|
||||
nsresult nsCaretAccessible::ClearControlSelectionListener()
|
||||
{
|
||||
nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryReferent(mCurrentControlSelection));
|
||||
NS_ENSURE_TRUE(selPrivate, NS_ERROR_FAILURE);
|
||||
|
||||
mCurrentControlSelection = nsnull;
|
||||
mCurrentControl = nsnull;
|
||||
mCurrentControlSelection = nsnull;
|
||||
|
||||
nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryReferent(mCurrentControlSelection));
|
||||
if (!selPrivate) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return selPrivate->RemoveSelectionListener(this);
|
||||
}
|
||||
|
||||
|
@ -85,7 +85,7 @@ nsIAtom *nsDocAccessible::gLastFocusedFrameType = nsnull;
|
||||
//-----------------------------------------------------
|
||||
nsDocAccessible::nsDocAccessible(nsIDOMNode *aDOMNode, nsIWeakReference* aShell):
|
||||
nsHyperTextAccessibleWrap(aDOMNode, aShell), mWnd(nsnull),
|
||||
mScrollPositionChangedTicks(0), mIsContentLoaded(PR_FALSE)
|
||||
mScrollPositionChangedTicks(0), mIsContentLoaded(PR_FALSE), mIsLoadCompleteFired(PR_FALSE)
|
||||
{
|
||||
// For GTK+ native window, we do nothing here.
|
||||
if (!mDOMNode)
|
||||
@ -526,17 +526,13 @@ NS_IMETHODIMP nsDocAccessible::Shutdown()
|
||||
nsAccUtils::GetDocShellTreeItemFor(mDOMNode);
|
||||
ShutdownChildDocuments(treeItem);
|
||||
|
||||
if (mDocLoadTimer) {
|
||||
mDocLoadTimer->Cancel();
|
||||
mDocLoadTimer = nsnull;
|
||||
}
|
||||
|
||||
RemoveEventListeners();
|
||||
|
||||
mWeakShell = nsnull; // Avoid reentrancy
|
||||
|
||||
ClearCache(mAccessNodeCache);
|
||||
|
||||
nsCOMPtr<nsIDocument> kungFuDeathGripDoc = mDocument;
|
||||
mDocument = nsnull;
|
||||
|
||||
nsHyperTextAccessibleWrap::Shutdown();
|
||||
@ -553,6 +549,10 @@ NS_IMETHODIMP nsDocAccessible::Shutdown()
|
||||
}
|
||||
}
|
||||
|
||||
// Remove from the cache after other parts of Shutdown(), so that Shutdown() procedures
|
||||
// can find the doc or root accessible in the cache if they need it.
|
||||
gGlobalDocAccessibleCache.Remove(static_cast<void*>(kungFuDeathGripDoc));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -766,10 +766,20 @@ NS_IMETHODIMP nsDocAccessible::FireDocLoadEvents(PRUint32 aEventType)
|
||||
(aEventType == nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE ||
|
||||
aEventType == nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_STOPPED);
|
||||
|
||||
if (mIsContentLoaded == isFinished) {
|
||||
mIsContentLoaded = isFinished;
|
||||
if (isFinished) {
|
||||
if (mIsLoadCompleteFired)
|
||||
return NS_OK;
|
||||
mIsLoadCompleteFired = PR_TRUE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> treeItem =
|
||||
nsAccUtils::GetDocShellTreeItemFor(mDOMNode);
|
||||
if (!treeItem) {
|
||||
return NS_OK;
|
||||
}
|
||||
mIsContentLoaded = isFinished;
|
||||
nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
|
||||
treeItem->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
|
||||
|
||||
if (isFinished) {
|
||||
// Need to wait until scrollable view is available
|
||||
@ -780,36 +790,31 @@ NS_IMETHODIMP nsDocAccessible::FireDocLoadEvents(PRUint32 aEventType)
|
||||
// Make the parent forget about the old document as a child
|
||||
privateAccessible->InvalidateChildren();
|
||||
}
|
||||
// Use short timer before firing state change event for finished doc,
|
||||
// because the window is made visible asynchronously
|
||||
if (!mDocLoadTimer) {
|
||||
mDocLoadTimer = do_CreateInstance("@mozilla.org/timer;1");
|
||||
}
|
||||
if (mDocLoadTimer) {
|
||||
mDocLoadTimer->InitWithFuncCallback(DocLoadCallback, this, 0,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
}
|
||||
} else {
|
||||
nsCOMPtr<nsIDocShellTreeItem> treeItem =
|
||||
nsAccUtils::GetDocShellTreeItemFor(mDOMNode);
|
||||
if (!treeItem) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
|
||||
treeItem->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
|
||||
if (sameTypeRoot != treeItem) {
|
||||
return NS_OK;
|
||||
// Fire show/hide events to indicate frame/iframe content is new, rather than
|
||||
// doc load event which causes screen readers to act is if entire page is reloaded
|
||||
InvalidateCacheSubtree(nsnull, nsIAccessibleEvent::EVENT_DOM_SIGNIFICANT_CHANGE);
|
||||
}
|
||||
// Fire STATE_CHANGE event for doc load finish if focus is in same doc tree
|
||||
if (gLastFocusedNode) {
|
||||
nsCOMPtr<nsIDocShellTreeItem> focusedTreeItem =
|
||||
nsAccUtils::GetDocShellTreeItemFor(gLastFocusedNode);
|
||||
if (focusedTreeItem) {
|
||||
nsCOMPtr<nsIDocShellTreeItem> sameTypeRootOfFocus;
|
||||
focusedTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRootOfFocus));
|
||||
if (sameTypeRoot == sameTypeRootOfFocus) {
|
||||
nsCOMPtr<nsIAccessibleStateChangeEvent> accEvent =
|
||||
new nsAccStateChangeEvent(this, nsIAccessibleStates::STATE_BUSY, PR_FALSE, PR_FALSE);
|
||||
FireAccessibleEvent(accEvent);
|
||||
FireAnchorJumpEvent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Loading document: fire EVENT_STATE_CHANGE to set STATE_BUSY
|
||||
nsCOMPtr<nsIAccessibleStateChangeEvent> accEvent =
|
||||
new nsAccStateChangeEvent(this, nsIAccessibleStates::STATE_BUSY,
|
||||
PR_FALSE, PR_TRUE);
|
||||
FireAccessibleEvent(accEvent);
|
||||
}
|
||||
|
||||
nsAccUtils::FireAccEvent(aEventType, this);
|
||||
if (sameTypeRoot == treeItem) {
|
||||
// Not a frame or iframe
|
||||
nsAccUtils::FireAccEvent(aEventType, this);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -2067,55 +2072,3 @@ nsDocAccessible::FireShowHideEvents(nsIDOMNode *aDOMNode, PRBool aAvoidOnThisNod
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsDocAccessible::DocLoadCallback(nsITimer *aTimer, void *aClosure)
|
||||
{
|
||||
// Doc has finished loading, fire "load finished" event
|
||||
// By using short timer we can wait make the window visible,
|
||||
// which it does asynchronously. This avoids confusing the screen reader with a
|
||||
// hidden window. Waiting also allows us to see of the document has focus,
|
||||
// which is important because we only fire doc loaded events for focused documents.
|
||||
|
||||
nsDocAccessible *docAcc =
|
||||
reinterpret_cast<nsDocAccessible*>(aClosure);
|
||||
if (!docAcc) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Fire doc finished event
|
||||
nsCOMPtr<nsIDOMNode> docDomNode;
|
||||
docAcc->GetDOMNode(getter_AddRefs(docDomNode));
|
||||
nsCOMPtr<nsIDocument> doc(do_QueryInterface(docDomNode));
|
||||
if (doc) {
|
||||
nsCOMPtr<nsISupports> container = doc->GetContainer();
|
||||
nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem = do_QueryInterface(container);
|
||||
if (!docShellTreeItem) {
|
||||
return;
|
||||
}
|
||||
nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
|
||||
docShellTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
|
||||
if (sameTypeRoot != docShellTreeItem) {
|
||||
// A frame or iframe has finished loading new content
|
||||
docAcc->InvalidateCacheSubtree(nsnull, nsIAccessibleEvent::EVENT_DOM_SIGNIFICANT_CHANGE);
|
||||
return;
|
||||
}
|
||||
|
||||
// Fire STATE_CHANGE event for doc load finish if focus is in same doc tree
|
||||
if (gLastFocusedNode) {
|
||||
nsCOMPtr<nsIDocShellTreeItem> focusedTreeItem =
|
||||
nsAccUtils::GetDocShellTreeItemFor(gLastFocusedNode);
|
||||
if (focusedTreeItem) {
|
||||
nsCOMPtr<nsIDocShellTreeItem> sameTypeRootOfFocus;
|
||||
focusedTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRootOfFocus));
|
||||
if (sameTypeRoot == sameTypeRootOfFocus) {
|
||||
nsCOMPtr<nsIAccessibleStateChangeEvent> accEvent =
|
||||
new nsAccStateChangeEvent(docAcc, nsIAccessibleStates::STATE_BUSY,
|
||||
PR_FALSE, PR_FALSE);
|
||||
docAcc->FireAccessibleEvent(accEvent);
|
||||
docAcc->FireAnchorJumpEvent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -214,6 +214,7 @@ class nsDocAccessible : public nsHyperTextAccessibleWrap,
|
||||
nsCOMPtr<nsITimer> mFireEventTimer;
|
||||
PRUint16 mScrollPositionChangedTicks; // Used for tracking scroll events
|
||||
PRPackedBool mIsContentLoaded;
|
||||
PRPackedBool mIsLoadCompleteFired;
|
||||
nsCOMArray<nsIAccessibleEvent> mEventsToFire;
|
||||
|
||||
protected:
|
||||
@ -221,10 +222,6 @@ protected:
|
||||
PRBool mIsAnchorJumped;
|
||||
static PRUint32 gLastFocusedAccessiblesState;
|
||||
static nsIAtom *gLastFocusedFrameType;
|
||||
|
||||
private:
|
||||
static void DocLoadCallback(nsITimer *aTimer, void *aClosure);
|
||||
nsCOMPtr<nsITimer> mDocLoadTimer;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -406,29 +406,11 @@ void nsRootAccessible::TryFireEarlyLoadEvent(nsIDOMNode *aDocNode)
|
||||
nsCOMPtr<nsIDocShellTreeItem> rootContentTreeItem;
|
||||
treeItem->GetSameTypeRootTreeItem(getter_AddRefs(rootContentTreeItem));
|
||||
NS_ASSERTION(rootContentTreeItem, "No root content tree item");
|
||||
if (!rootContentTreeItem) { // Not at root of content
|
||||
return;
|
||||
if (rootContentTreeItem == treeItem) {
|
||||
// No frames or iframes, so we can fire the doc load finished event early
|
||||
FireDelayedToolkitEvent(nsIAccessibleEvent::EVENT_INTERNAL_LOAD, aDocNode,
|
||||
eRemoveDupes);
|
||||
}
|
||||
if (rootContentTreeItem != treeItem) {
|
||||
nsCOMPtr<nsIAccessibleDocument> rootContentDocAccessible =
|
||||
GetDocAccessibleFor(rootContentTreeItem);
|
||||
nsCOMPtr<nsIAccessible> rootContentAccessible =
|
||||
do_QueryInterface(rootContentDocAccessible);
|
||||
if (!rootContentAccessible) {
|
||||
return;
|
||||
}
|
||||
PRUint32 state, extState;
|
||||
rootContentAccessible->GetFinalState(&state, &extState);
|
||||
if ((state & nsIAccessibleStates::STATE_BUSY) ||
|
||||
(extState & nsIAccessibleStates::EXT_STATE_DEFUNCT)) {
|
||||
// Don't fire page load events on subdocuments for initial page load of entire page
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// No frames or iframes, so we can fire the doc load finished event early
|
||||
FireDelayedToolkitEvent(nsIAccessibleEvent::EVENT_INTERNAL_LOAD, aDocNode,
|
||||
eRemoveDupes);
|
||||
}
|
||||
|
||||
PRBool nsRootAccessible::FireAccessibleFocusEvent(nsIAccessible *aAccessible,
|
||||
@ -632,9 +614,6 @@ nsresult nsRootAccessible::HandleEventWithTarget(nsIDOMEvent* aEvent,
|
||||
nsCOMPtr<nsPIAccessNode> privateAcc = do_QueryInterface(accDoc);
|
||||
if (privateAcc) {
|
||||
privateAcc->Shutdown();
|
||||
// Remove from the cache after Shutdown(), so that Shutdown() procedures
|
||||
// can find the doc or root accessible in the cache if they need it.
|
||||
gGlobalDocAccessibleCache.Remove(static_cast<void*>(doc));
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -121,17 +121,17 @@ __try {
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = acc->GetURI(aIndex, getter_AddRefs(uri));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
if (NS_FAILED(rv) || !uri)
|
||||
return E_FAIL;
|
||||
|
||||
nsCAutoString prePath;
|
||||
rv = uri->GetPrePath(prePath);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
if (NS_FAILED(rv))
|
||||
return E_FAIL;
|
||||
|
||||
nsCAutoString path;
|
||||
rv = uri->GetPath(path);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
if (NS_FAILED(rv))
|
||||
return E_FAIL;
|
||||
|
||||
nsAutoString stringURI;
|
||||
|
@ -1394,6 +1394,9 @@ STDMETHODIMP
|
||||
nsAccessibleWrap::get_windowHandle(HWND *windowHandle)
|
||||
{
|
||||
__try {
|
||||
*windowHandle = 0;
|
||||
if (!mDOMNode)
|
||||
return E_FAIL;
|
||||
void *handle = nsnull;
|
||||
nsresult rv = GetOwnerWindow(&handle);
|
||||
if (NS_FAILED(rv))
|
||||
|
@ -162,11 +162,6 @@ __try {
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsDocAccessibleWrap::Shutdown()
|
||||
{
|
||||
return nsDocAccessible::Shutdown();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsDocAccessibleWrap::FireAnchorJumpEvent()
|
||||
{
|
||||
// Staying on the same page, jumping to a named anchor
|
||||
|
@ -87,7 +87,6 @@ public:
|
||||
/* [in] */ VARIANT varChild,
|
||||
/* [retval][out] */ IDispatch __RPC_FAR *__RPC_FAR *ppdispChild);
|
||||
|
||||
NS_IMETHOD Shutdown();
|
||||
NS_IMETHOD FireAnchorJumpEvent();
|
||||
};
|
||||
|
||||
|
@ -48,6 +48,9 @@ include $(topsrcdir)/config/rules.mk
|
||||
_TEST_FILES =\
|
||||
test_bug368835.xul \
|
||||
test_groupattrs.xul \
|
||||
test_nsIAccessibleTable_1.html \
|
||||
test_nsIAccessibleTable_2.html \
|
||||
test_nsIAccessibleTable_3.html \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
|
@ -167,7 +167,7 @@
|
||||
|
||||
function doTest()
|
||||
{
|
||||
// Check whether accessbility support is enabled.
|
||||
// Check whether accessibility support is enabled.
|
||||
if (!("@mozilla.org/accessibleRetrieval;1" in Components.classes)) {
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
|
144
accessible/tests/mochitest/test_nsIAccessibleTable_1.html
Normal file
@ -0,0 +1,144 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//w3c//dtd html 4.0 transitional//en">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
<script type="application/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript">
|
||||
|
||||
function doTest()
|
||||
{
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var table = document.getElementById("table");
|
||||
var accService = Components.classes["@mozilla.org/accessibleRetrieval;1"].
|
||||
getService(Components.interfaces.nsIAccessibleRetrieval);
|
||||
var accTable = accService.getAccessibleFor(table).
|
||||
QueryInterface(Components.interfaces.nsIAccessibleTable);
|
||||
var caption = accTable.caption;
|
||||
is(caption.firstChild.name, "Test Table", "wrong text inside caption");
|
||||
const nsIAccessNode = Components.interfaces.nsIAccessible;
|
||||
|
||||
is(caption.children.queryElementAt(0, nsIAccessNode).name, "Test Table",
|
||||
"wrong text inside caption");
|
||||
|
||||
is(accTable.summary, "this is a test table for nsIAccessibleTable",
|
||||
"wrong summary on table");
|
||||
is(accTable.columns, 4,"wrong number of columns");
|
||||
is(accTable.rows, 3, "wrong number of rows");
|
||||
|
||||
var s = window.getSelection();
|
||||
if (s.rangeCount > 0)
|
||||
s.removeAllRanges();
|
||||
|
||||
var cell = document.getElementById("col2b");
|
||||
var range = document.createRange();
|
||||
range.selectNode(cell);
|
||||
s.addRange(range);
|
||||
|
||||
is(accTable.selectedCellsCount, 1,"only one cell selected");
|
||||
cell = document.getElementById("col2a");
|
||||
range.selectNode(cell);
|
||||
s.addRange(range);
|
||||
cell = document.getElementById("col2c");
|
||||
range.selectNode(cell);
|
||||
s.addRange(range);
|
||||
is(accTable.selectedColumnsCount, 1, "only one column selected");
|
||||
cell = document.getElementById("row2a");
|
||||
range.selectNode(cell);
|
||||
s.addRange(range);
|
||||
cell = document.getElementById("row2b");
|
||||
range.selectNode(cell);
|
||||
s.addRange(range);
|
||||
cell = document.getElementById("row2c");
|
||||
range.selectNode(cell);
|
||||
s.addRange(range);
|
||||
|
||||
is(accTable.selectedRowsCount, 1, "no cells selected");
|
||||
|
||||
var rowheader;
|
||||
var works;
|
||||
works = true;
|
||||
try {
|
||||
rowheader = accTable.rowHeader;
|
||||
}
|
||||
catch (e) {
|
||||
works = false;
|
||||
}
|
||||
todo(works, "rowHeader should not throw");
|
||||
|
||||
var columnHeader;
|
||||
works = true;
|
||||
try {
|
||||
columnHeader = accTable.columnHeader;
|
||||
columnHeaderIndex =columnHeader.getIndexAt(0,2);
|
||||
is(columnHeaderIndex, 2, "columnheaderindex is wrong");
|
||||
}
|
||||
catch (e) {
|
||||
works = false;
|
||||
}
|
||||
todo(works, "columnHeader should not throw");
|
||||
|
||||
var columnDescription;
|
||||
works = true;
|
||||
try{
|
||||
columnDescription = accTable.getColumnDescription(1);
|
||||
}
|
||||
catch (e) {
|
||||
works = false;
|
||||
}
|
||||
todo(works, "columnDescription should not throw");
|
||||
|
||||
var rowDescription;
|
||||
works = true;
|
||||
try {
|
||||
rowDescription = accTable.getRowDescription(1);
|
||||
}
|
||||
catch (e) {
|
||||
works = false;
|
||||
}
|
||||
todo(works, "rowDescription should not throw");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addLoadEvent(doTest);
|
||||
</script>
|
||||
</head>
|
||||
<body >
|
||||
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=410052">Mozilla Bug 410052</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<!-- Test Table -->
|
||||
<br><br><b> Testing Table:</b><br><br>
|
||||
<center>
|
||||
<table id="table" border="1"
|
||||
summary="this is a test table for nsIAccessibleTable" >
|
||||
<caption>Test Table</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>columnHeader_1</th>
|
||||
<th id ="col2a">columnHeader_2</th>
|
||||
<th>columnHeader_3</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr>
|
||||
<th id="row2a">rowHeader_1</th>
|
||||
<td id="row2b">row1_column1</td>
|
||||
<td id ="col2b">row1_column2</td>
|
||||
<td id="row2c">row1_column3</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>rowHeader_2</th>
|
||||
<td>row2_column1</td>
|
||||
<td id ="col2c">row2_column2</td>
|
||||
<td>row2_column3</td>
|
||||
</tr>
|
||||
</table>
|
||||
</center>
|
||||
</body>
|
||||
</html>
|
87
accessible/tests/mochitest/test_nsIAccessibleTable_2.html
Normal file
@ -0,0 +1,87 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//w3c//dtd html 4.0 transitional//en">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
<title> nsIAccessibleTable Interface Test Case </title>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
<script type="application/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript">
|
||||
|
||||
function doTest()
|
||||
{
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
|
||||
var table = document.getElementById("table");
|
||||
var accService = Components.classes["@mozilla.org/accessibleRetrieval;1"].
|
||||
getService(Components.interfaces.nsIAccessibleRetrieval);
|
||||
|
||||
var accTable = accService.getAccessibleFor(table).
|
||||
QueryInterface(Components.interfaces.nsIAccessibleTable);
|
||||
|
||||
is(accTable.getIndexAt(2,4), 17, "wrong index returned");
|
||||
is(accTable.getColumnAtIndex(18), 5,"got wrong column");
|
||||
is(accTable.getRowAtIndex(10), 1, "wrong row");
|
||||
is(accTable.getColumnExtentAt(2,2), 2, "colspan wrong");
|
||||
is(accTable.getColumnExtentAt(0,3), 2, "colspan wrong");
|
||||
is(accTable.getColumnExtentAt(3,5), 1, "colspan");
|
||||
is(accTable.getRowExtentAt(0,7), 4, "rowspan wrong");
|
||||
is(accTable.getRowExtentAt(2,7), 4,"rowspan wrong");
|
||||
is(accTable.getColumnExtentAt(2,3), 1, "colspan wrong");
|
||||
is(accTable.cellRefAt(2,1).firstChild.name, "c1", "wrong cell");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addLoadEvent(doTest);
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=410052">Mozilla Bug 410052</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<!-- Test Table -->
|
||||
<br><br><b> Testing Table:</b><br><br>
|
||||
<center>
|
||||
<table cellpadding="2" cellspacing="2" border="1" width="50%" id="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><br></td>
|
||||
<td><br></td>
|
||||
<td rowspan="1" colspan="2"><br></td>
|
||||
<td><br></td>
|
||||
<td><br></td>
|
||||
<td><br></td>
|
||||
<td rowspan="4" colspan="1"><br></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><br></td>
|
||||
<td><br></td>
|
||||
<td><br></td>
|
||||
<td><br></td>
|
||||
<td><br></td>
|
||||
<td><br></td>
|
||||
<td><br></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><br></td>
|
||||
<td rowspan="2" colspan="2">c1</td>
|
||||
<td><br></td>
|
||||
<td><br></td>
|
||||
<td rowspan="2" colspan="1"><br></td>
|
||||
<td><br></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><br></td>
|
||||
<td><br></td>
|
||||
<td><br></td>
|
||||
<td><br></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</center>
|
||||
</body>
|
||||
</html>
|
127
accessible/tests/mochitest/test_nsIAccessibleTable_3.html
Normal file
@ -0,0 +1,127 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//w3c//dtd html 4.0 transitional//en">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
<title> nsIAccessibleTable Interface Test Case </title>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
<script type="application/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript">
|
||||
|
||||
function doTest()
|
||||
{
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var table = document.getElementById("table");
|
||||
var accService = Components.classes["@mozilla.org/accessibleRetrieval;1"].
|
||||
getService(Components.interfaces.nsIAccessibleRetrieval);
|
||||
|
||||
var accTable = accService.getAccessibleFor(table).
|
||||
QueryInterface(Components.interfaces.nsIAccessibleTable);
|
||||
|
||||
is(accTable.getSelectedCells({}).length, 0, "no cell selected");
|
||||
for (var i = 0; i < 4; i++) {
|
||||
accTable.selectRow(i);
|
||||
for (var j = 0; j < 4; j++) {
|
||||
if (i == j) {
|
||||
ok(accTable.isRowSelected(i),"row not selected");
|
||||
}
|
||||
else {
|
||||
todo(!accTable.isRowSelected(i),"row selected");
|
||||
}
|
||||
}
|
||||
}
|
||||
todo_is(accTable.selectedRowsCount, 1, "only one row should be selected");
|
||||
todo_is(accTable.getSelectedRows({}).length, 1,
|
||||
"only one row should be selected");
|
||||
|
||||
for (var i = 0; i < 4; i++) {
|
||||
accTable.unselectRow(i);
|
||||
ok(!accTable.isRowSelected(i), "row still selected");
|
||||
}
|
||||
todo_is(accTable.getSelectedCells({}).length, 0, "no cell selected");
|
||||
todo_is(accTable.selectedCellsCount, 0, "no cell selected");
|
||||
var s = window.getSelection();
|
||||
if (s.rangeCount > 0)
|
||||
s.removeAllRanges();
|
||||
|
||||
is(accTable.getSelectedCells({}).length, 0, "no cell selected");
|
||||
is(accTable.selectedCellsCount, 0, "no cell selected");
|
||||
for (var i = 0; i < 8; i++) {
|
||||
accTable.selectColumn(i);
|
||||
for (var j = 0; j < 8; j++) {
|
||||
if (i ==j) {
|
||||
ok(accTable.isColumnSelected(i),"column not selected");
|
||||
}
|
||||
else {
|
||||
todo(!accTable.isColumnSelected(i),"column is selected");
|
||||
}
|
||||
}
|
||||
}
|
||||
todo_is(accTable.selectedColumnsCount, 1,
|
||||
"only one column should be selected");
|
||||
todo_is(accTable.getSelectedColumns({}).length, 1,
|
||||
"only one column should be selected");
|
||||
for (var i = 0; i < 8; i++) {
|
||||
accTable.unselectColumn(i);
|
||||
ok(!accTable.isColumnSelected(i),"column still selected");
|
||||
}
|
||||
is(accTable.selectedColumnsCount, 0, "no column should be selected");
|
||||
ok(!accTable.isProbablyForLayout(), "table is not for layout");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addLoadEvent(doTest);
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=410052">Mozilla Bug 410052</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
|
||||
<!-- Test Table -->
|
||||
<br><br><b> Testing Table:</b><br><br>
|
||||
<center>
|
||||
<table cellpadding="2" cellspacing="2" border="1" width="50%" id="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><br></td>
|
||||
<td><br></td>
|
||||
<td rowspan="1" colspan="2"><br></td>
|
||||
<td><br></td>
|
||||
<td><br></td>
|
||||
<td><br></td>
|
||||
<td rowspan="4" colspan="1"><br></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><br></td>
|
||||
<td><br></td>
|
||||
<td><br></td>
|
||||
<td><br></td>
|
||||
<td><br></td>
|
||||
<td><br></td>
|
||||
<td><br></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><br></td>
|
||||
<td rowspan="2" colspan="2">c1</td>
|
||||
<td><br></td>
|
||||
<td><br></td>
|
||||
<td rowspan="2" colspan="1"><br></td>
|
||||
<td><br></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><br></td>
|
||||
<td><br></td>
|
||||
<td><br></td>
|
||||
<td><br></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</center>
|
||||
</body>
|
||||
</html>
|
@ -197,6 +197,7 @@ pref("browser.chrome.site_icons", true);
|
||||
pref("browser.chrome.favicons", true);
|
||||
pref("browser.formfill.enable", true);
|
||||
pref("browser.warnOnQuit", true);
|
||||
pref("browser.warnOnRestart", true);
|
||||
|
||||
#ifdef UNIX_BUT_NOT_MAC
|
||||
pref("browser.urlbar.clickSelectsAll", false);
|
||||
@ -210,6 +211,7 @@ pref("browser.urlbar.doubleClickSelectsAll", false);
|
||||
#endif
|
||||
pref("browser.urlbar.autoFill", false);
|
||||
pref("browser.urlbar.matchOnlyTyped", false);
|
||||
pref("browser.urlbar.filter.javascript", true);
|
||||
|
||||
// the maximum number of results to show in autocomplete when doing richResults
|
||||
pref("browser.urlbar.maxRichResults", 25);
|
||||
@ -364,7 +366,7 @@ pref("privacy.sanitize.promptOnSanitize", true);
|
||||
|
||||
pref("network.proxy.share_proxy_settings", false); // use the same proxy settings for all protocols
|
||||
|
||||
pref("network.cookie.cookieBehavior", 1); // 0-Accept, 1-dontAcceptForeign, 2-dontUse
|
||||
pref("network.cookie.cookieBehavior", 0); // 0-Accept, 1-dontAcceptForeign, 2-dontUse
|
||||
|
||||
// l12n and i18n
|
||||
pref("intl.accept_languages", "chrome://global/locale/intl.properties");
|
||||
@ -571,16 +573,16 @@ pref("browser.safebrowsing.enabled", true);
|
||||
pref("browser.safebrowsing.malware.enabled", true);
|
||||
|
||||
// Non-enhanced mode (local url lists) URL list to check for updates
|
||||
pref("browser.safebrowsing.provider.0.updateURL", "http://sb.google.com/safebrowsing/downloads?client={moz:client}&appver={moz:version}&pver=2.1");
|
||||
pref("browser.safebrowsing.provider.0.updateURL", "http://safebrowsing.clients.google.com/safebrowsing/downloads?client={moz:client}&appver={moz:version}&pver=2.1");
|
||||
|
||||
pref("browser.safebrowsing.dataProvider", 0);
|
||||
|
||||
// Does the provider name need to be localizable?
|
||||
pref("browser.safebrowsing.provider.0.name", "Google");
|
||||
pref("browser.safebrowsing.provider.0.lookupURL", "http://sb.google.com/safebrowsing/lookup?sourceid=firefox-antiphish&features=TrustRank&client={moz:client}&appver={moz:version}&");
|
||||
pref("browser.safebrowsing.provider.0.keyURL", "https://sb-ssl.google.com/safebrowsing/getkey?client={moz:client}&");
|
||||
pref("browser.safebrowsing.provider.0.reportURL", "http://sb.google.com/safebrowsing/report?");
|
||||
pref("browser.safebrowsing.provider.0.gethashURL", "http://sb.google.com/safebrowsing/gethash?client={moz:client}&appver={moz:version}&pver=2.1");
|
||||
pref("browser.safebrowsing.provider.0.lookupURL", "http://safebrowsing.clients.google.com/safebrowsing/lookup?sourceid=firefox-antiphish&features=TrustRank&client={moz:client}&appver={moz:version}&");
|
||||
pref("browser.safebrowsing.provider.0.keyURL", "https://sb-ssl.google.com/safebrowsing/newkey?client={moz:client}&appver={moz:version}&pver=2.1");
|
||||
pref("browser.safebrowsing.provider.0.reportURL", "http://safebrowsing.clients.google.com/safebrowsing/report?");
|
||||
pref("browser.safebrowsing.provider.0.gethashURL", "http://safebrowsing.clients.google.com/safebrowsing/gethash?client={moz:client}&appver={moz:version}&pver=2.1");
|
||||
|
||||
// privacy policy -- Both url and fallbackurl must exist, although they may
|
||||
// point to the same file. fallbackurl must be a chrome url
|
||||
@ -598,6 +600,9 @@ pref("browser.safebrowsing.warning.infoURL", "http://%LOCALE%.www.mozilla.com/%L
|
||||
// Name of the about: page contributed by safebrowsing to handle display of error
|
||||
// pages on phishing/malware hits. (bug 399233)
|
||||
pref("urlclassifier.alternate_error_page", "blocked");
|
||||
|
||||
// The number of random entries to send with a gethash request.
|
||||
pref("urlclassifier.gethashnoise", 4);
|
||||
#endif
|
||||
|
||||
// defaults to true
|
||||
@ -609,7 +614,7 @@ pref("browser.EULA.version", 2);
|
||||
pref("browser.sessionstore.enabled", true);
|
||||
pref("browser.sessionstore.resume_from_crash", true);
|
||||
pref("browser.sessionstore.resume_session_once", false);
|
||||
|
||||
|
||||
// minimal interval between two save operations in milliseconds
|
||||
pref("browser.sessionstore.interval", 10000);
|
||||
// maximum amount of POSTDATA to be saved in bytes per history entry (-1 = all of it)
|
||||
@ -637,6 +642,10 @@ pref("browser.places.createdSmartBookmarks", false);
|
||||
// XXX to be removed after beta 2 (bug 391419)
|
||||
pref("browser.places.migratePostDataAnnotations", true);
|
||||
|
||||
// If true, will update the Smart Bookmarks uri for
|
||||
// recent tags (bug 385245). Useful just for FX3 beta users.
|
||||
pref("browser.places.updateRecentTagsUri", true);
|
||||
|
||||
// the (maximum) number of the recent visits to sample
|
||||
// when calculating frecency
|
||||
pref("places.frecency.numVisits", 10);
|
||||
@ -699,6 +708,9 @@ pref("browser.offline-apps.notify", true);
|
||||
// if true, use full page zoom instead of text zoom
|
||||
pref("browser.zoom.full", true);
|
||||
|
||||
// Whether or not to save and restore zoom levels on a per-site basis.
|
||||
pref("browser.zoom.siteSpecific", true);
|
||||
|
||||
// replace newlines with spaces when pasting into <input type="text"> fields
|
||||
pref("editor.singleLine.pasteNewlines", 2);
|
||||
|
||||
|
@ -184,36 +184,45 @@
|
||||
<menuseparator id="frame-sep"/>
|
||||
<menu id="frame" label="&thisFrameMenu.label;" accesskey="&thisFrameMenu.accesskey;">
|
||||
<menupopup>
|
||||
<menuitem label="&showOnlyThisFrameCmd.label;"
|
||||
<menuitem id="context-showonlythisframe"
|
||||
label="&showOnlyThisFrameCmd.label;"
|
||||
accesskey="&showOnlyThisFrameCmd.accesskey;"
|
||||
oncommand="gContextMenu.showOnlyThisFrame();"/>
|
||||
<menuitem label="&openFrameCmd.label;"
|
||||
<menuitem id="context-openframe"
|
||||
label="&openFrameCmd.label;"
|
||||
accesskey="&openFrameCmd.accesskey;"
|
||||
oncommand="gContextMenu.openFrame();"/>
|
||||
<menuitem label="&openFrameCmdInTab.label;"
|
||||
<menuitem id="context-openframeintab"
|
||||
label="&openFrameCmdInTab.label;"
|
||||
accesskey="&openFrameCmdInTab.accesskey;"
|
||||
oncommand="gContextMenu.openFrameInTab();"/>
|
||||
<menuseparator/>
|
||||
<menuitem label="&reloadFrameCmd.label;"
|
||||
<menuitem id="context-reloadframe"
|
||||
label="&reloadFrameCmd.label;"
|
||||
accesskey="&reloadFrameCmd.accesskey;"
|
||||
oncommand="gContextMenu.reloadFrame();"/>
|
||||
<menuseparator/>
|
||||
<menuitem label="&bookmarkThisFrameCmd.label;"
|
||||
<menuitem id="context-bookmarkframe"
|
||||
label="&bookmarkThisFrameCmd.label;"
|
||||
accesskey="&bookmarkThisFrameCmd.accesskey;"
|
||||
oncommand="gContextMenu.addBookmarkForFrame();"/>
|
||||
<menuitem label="&saveFrameCmd.label;"
|
||||
<menuitem id="context-saveframe"
|
||||
label="&saveFrameCmd.label;"
|
||||
accesskey="&saveFrameCmd.accesskey;"
|
||||
oncommand="saveDocument(gContextMenu.target.ownerDocument);"/>
|
||||
<menuseparator/>
|
||||
<menuitem label="&printFrameCmd.label;"
|
||||
<menuitem id="context-printframe"
|
||||
label="&printFrameCmd.label;"
|
||||
accesskey="&printFrameCmd.accesskey;"
|
||||
oncommand="gContextMenu.printFrame();"/>
|
||||
<menuseparator/>
|
||||
<menuitem label="&viewFrameSourceCmd.label;"
|
||||
<menuitem id="context-viewframesource"
|
||||
label="&viewFrameSourceCmd.label;"
|
||||
accesskey="&viewFrameSourceCmd.accesskey;"
|
||||
oncommand="gContextMenu.viewFrameSource();"
|
||||
observes="isFrameImage"/>
|
||||
<menuitem label="&viewFrameInfoCmd.label;"
|
||||
<menuitem id="context-viewframeinfo"
|
||||
label="&viewFrameInfoCmd.label;"
|
||||
accesskey="&viewFrameInfoCmd.accesskey;"
|
||||
oncommand="gContextMenu.viewFrameInfo();"/>
|
||||
</menupopup>
|
||||
|
@ -582,12 +582,12 @@ var BookmarksEventHandler = {
|
||||
|
||||
var target = aEvent.originalTarget;
|
||||
var view = PlacesUtils.getViewForNode(target);
|
||||
if (PlacesUtils.nodeIsFolder(view.selectedNode)) {
|
||||
if (target.node && PlacesUtils.nodeIsFolder(target.node)) {
|
||||
// Don't open the root folder in tabs when the empty area on the toolbar
|
||||
// is middle-clicked or when a non-bookmark item except for Open in Tabs)
|
||||
// in a bookmarks menupopup is middle-clicked.
|
||||
if (!view.controller.rootNodeIsSelected())
|
||||
view.controller.openSelectionInTabs(aEvent);
|
||||
if (target.localName == "menu" || target.localName == "toolbarbutton")
|
||||
PlacesUtils.openContainerNodeInTabs(target.node, aEvent);
|
||||
}
|
||||
else
|
||||
this.onCommand(aEvent);
|
||||
@ -624,11 +624,8 @@ var BookmarksEventHandler = {
|
||||
*/
|
||||
onCommand: function BM_onCommand(aEvent) {
|
||||
var target = aEvent.originalTarget;
|
||||
if (target.node) {
|
||||
PlacesUtils.getViewForNode(target)
|
||||
.controller
|
||||
.openSelectedNodeWithEvent(aEvent);
|
||||
}
|
||||
if (target.node)
|
||||
PlacesUtils.openNodeWithEvent(target.node, aEvent);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -1027,7 +1024,7 @@ function placesMigrationTasks() {
|
||||
// XXX - REMOVE ME FOR BETA 3 (bug 391419)
|
||||
if (gPrefService.getBoolPref("browser.places.migratePostDataAnnotations")) {
|
||||
const annosvc = PlacesUtils.annotations;
|
||||
const bmsvc = PlacesUtils.bookmarks;
|
||||
var bmsvc = PlacesUtils.bookmarks;
|
||||
const oldPostDataAnno = "URIProperties/POSTData";
|
||||
var pages = annosvc.getPagesWithAnnotation(oldPostDataAnno, {});
|
||||
for (let i = 0; i < pages.length; i++) {
|
||||
@ -1051,4 +1048,30 @@ function placesMigrationTasks() {
|
||||
}
|
||||
gPrefService.setBoolPref("browser.places.migratePostDataAnnotations", false);
|
||||
}
|
||||
|
||||
if (gPrefService.getBoolPref("browser.places.updateRecentTagsUri")) {
|
||||
var bmsvc = PlacesUtils.bookmarks;
|
||||
var tagsFolder = bmsvc.tagsFolder;
|
||||
var oldUriSpec = "place:folder=" + tagsFolder + "&group=3&queryType=1"+
|
||||
"&applyOptionsToContainers=1&sort=12&maxResults=10";
|
||||
|
||||
var maxResults = 10;
|
||||
var newUriSpec = "place:type=" +
|
||||
Ci.nsINavHistoryQueryOptions.RESULTS_AS_TAG_QUERY +
|
||||
"&sort=" +
|
||||
Ci.nsINavHistoryQueryOptions.SORT_BY_DATEADDED_DESCENDING +
|
||||
"&maxResults=" + maxResults;
|
||||
|
||||
var ios = Cc["@mozilla.org/network/io-service;1"].
|
||||
getService(Ci.nsIIOService);
|
||||
|
||||
var oldUri = ios.newURI(oldUriSpec, null, null);
|
||||
var newUri = ios.newURI(newUriSpec, null, null);
|
||||
|
||||
let bookmarks = bmsvc.getBookmarkIdsForURI( oldUri, {});
|
||||
for (let i = 0; i < bookmarks.length; i++) {
|
||||
bmsvc.changeBookmarkURI( bookmarks[i], newUri);
|
||||
}
|
||||
gPrefService.setBoolPref("browser.places.updateRecentTagsUri", false);
|
||||
}
|
||||
}
|
||||
|
@ -192,6 +192,9 @@
|
||||
# Do *not* tamper with these values without talking to ben@mozilla.org
|
||||
#
|
||||
<key id="key_search" key="&searchFocus.commandkey;" command="Tools:Search" modifiers="accel"/>
|
||||
#ifdef XP_MACOSX
|
||||
<key id="key_search2" key="&findOnCmd.commandkey;" command="Tools:Search" modifiers="accel,alt"/>
|
||||
#endif
|
||||
#ifdef XP_WIN
|
||||
<key id="key_search2" key="&searchFocus.commandkey2;" command="Tools:Search" modifiers="accel"/>
|
||||
#endif
|
||||
|
@ -79,13 +79,24 @@ var FullZoom = {
|
||||
getService(Ci.nsIContentPrefService);
|
||||
},
|
||||
|
||||
get _prefBranch FullZoom_get__prefBranch() {
|
||||
delete this._prefBranch;
|
||||
return this._prefBranch = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefBranch2);
|
||||
},
|
||||
|
||||
// browser.zoom.siteSpecific preference cache
|
||||
siteSpecific: undefined,
|
||||
|
||||
|
||||
//**************************************************************************//
|
||||
// nsISupports
|
||||
|
||||
// We can't use the Ci shortcut here because it isn't defined yet.
|
||||
interfaces: [Components.interfaces.nsIDOMEventListener,
|
||||
Components.interfaces.nsIObserver,
|
||||
Components.interfaces.nsIContentPrefObserver,
|
||||
Components.interfaces.nsISupportsWeakReference,
|
||||
Components.interfaces.nsISupports],
|
||||
|
||||
QueryInterface: function FullZoom_QueryInterface(aIID) {
|
||||
@ -104,9 +115,16 @@ var FullZoom = {
|
||||
|
||||
// Register ourselves with the service so we know when our pref changes.
|
||||
this._cps.addObserver(this.name, this);
|
||||
|
||||
// Listen for changes to the browser.zoom.siteSpecific preference so we can
|
||||
// enable/disable per-site saving and restoring of zoom levels accordingly.
|
||||
this.siteSpecific =
|
||||
this._prefBranch.getBoolPref("browser.zoom.siteSpecific");
|
||||
this._prefBranch.addObserver("browser.zoom.siteSpecific", this, true);
|
||||
},
|
||||
|
||||
destroy: function FullZoom_destroy() {
|
||||
this._prefBranch.removeObserver("browser.zoom.siteSpecific", this);
|
||||
this._cps.removeObserver(this.name, this);
|
||||
window.removeEventListener("DOMMouseScroll", this, false);
|
||||
delete this._cps;
|
||||
@ -164,6 +182,21 @@ var FullZoom = {
|
||||
window.setTimeout(function (self) { self._applySettingToPref() }, 0, this);
|
||||
},
|
||||
|
||||
// nsIObserver
|
||||
|
||||
observe: function (aSubject, aTopic, aData) {
|
||||
switch(aTopic) {
|
||||
case "nsPref:changed":
|
||||
switch(aData) {
|
||||
case "browser.zoom.siteSpecific":
|
||||
this.siteSpecific =
|
||||
this._prefBranch.getBoolPref("browser.zoom.siteSpecific");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
// nsIContentPrefObserver
|
||||
|
||||
onContentPrefSet: function FullZoom_onContentPrefSet(aGroup, aName, aValue) {
|
||||
@ -257,7 +290,7 @@ var FullZoom = {
|
||||
* one.
|
||||
**/
|
||||
_applyPrefToSetting: function FullZoom__applyPrefToSetting(aValue) {
|
||||
if (gInPrintPreviewMode)
|
||||
if (!this.siteSpecific || gInPrintPreviewMode)
|
||||
return;
|
||||
|
||||
try {
|
||||
@ -272,7 +305,7 @@ var FullZoom = {
|
||||
},
|
||||
|
||||
_applySettingToPref: function FullZoom__applySettingToPref() {
|
||||
if (gInPrintPreviewMode)
|
||||
if (!this.siteSpecific || gInPrintPreviewMode)
|
||||
return;
|
||||
|
||||
var zoomLevel = ZoomManager.zoom;
|
||||
|
@ -23,6 +23,11 @@ toolbar[printpreview="true"] {
|
||||
-moz-binding: url("chrome://browser/content/urlbarBindings.xml#urlbar-rich-result-popup");
|
||||
}
|
||||
|
||||
#urlbar-throbber:not([busy="true"]),
|
||||
#urlbar-throbber[busy="true"] + #page-proxy-favicon {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* ::::: Unified Back-/Forward Button ::::: */
|
||||
#back-forward-dropmarker > image ,
|
||||
#back-forward-dropmarker > label {
|
||||
|
@ -75,9 +75,7 @@ var gLastBrowserCharset = null;
|
||||
var gPrevCharset = null;
|
||||
var gURLBar = null;
|
||||
var gFindBar = null;
|
||||
var gProxyButton = null;
|
||||
var gProxyFavIcon = null;
|
||||
var gProxyDeck = null;
|
||||
var gNavigatorBundle = null;
|
||||
var gIsLoadingBlank = false;
|
||||
var gLastValidURLStr = "";
|
||||
@ -1968,8 +1966,7 @@ function URLBarSetURI(aURI) {
|
||||
SetPageProxyState(state);
|
||||
}
|
||||
|
||||
// If "ESC" is pressed in the url bar, we replace the urlbar's value with the url of the page
|
||||
// and highlight it, unless it is empty.
|
||||
// Replace the urlbar's value with the url of the page.
|
||||
function handleURLBarRevert() {
|
||||
var throbberElement = document.getElementById("navigator-throbber");
|
||||
var isScrolling = gURLBar.popupOpen;
|
||||
@ -1980,7 +1977,9 @@ function handleURLBarRevert() {
|
||||
// and user is NOT key-scrolling through autocomplete list
|
||||
if ((!throbberElement || !throbberElement.hasAttribute("busy")) && !isScrolling) {
|
||||
URLBarSetURI();
|
||||
if (gURLBar.value)
|
||||
|
||||
// If the value isn't empty and the urlbar has focus, select the value.
|
||||
if (gURLBar.value && gURLBar.hasAttribute("focused"))
|
||||
gURLBar.select();
|
||||
}
|
||||
|
||||
@ -2107,6 +2106,28 @@ function UpdateUrlbarSearchSplitterState()
|
||||
splitter.parentNode.removeChild(splitter);
|
||||
}
|
||||
|
||||
var LocationBarHelpers = {
|
||||
_timeoutID: null,
|
||||
|
||||
_searchBegin: function LocBar_searchBegin() {
|
||||
function delayedBegin(self) {
|
||||
self._timeoutID = null;
|
||||
document.getElementById("urlbar-throbber").setAttribute("busy", "true");
|
||||
}
|
||||
|
||||
this._timeoutID = setTimeout(delayedBegin, 500, this);
|
||||
},
|
||||
|
||||
_searchComplete: function LocBar_searchComplete() {
|
||||
// Did we finish the search before delayedBegin was invoked?
|
||||
if (this._timeoutID) {
|
||||
clearTimeout(this._timeoutID);
|
||||
this._timeoutID = null;
|
||||
}
|
||||
document.getElementById("urlbar-throbber").removeAttribute("busy");
|
||||
}
|
||||
};
|
||||
|
||||
function UpdatePageProxyState()
|
||||
{
|
||||
if (gURLBar && gURLBar.value != gLastValidURLStr)
|
||||
@ -2118,15 +2139,11 @@ function SetPageProxyState(aState)
|
||||
if (!gURLBar)
|
||||
return;
|
||||
|
||||
if (!gProxyButton)
|
||||
gProxyButton = document.getElementById("page-proxy-button");
|
||||
if (!gProxyFavIcon)
|
||||
gProxyFavIcon = document.getElementById("page-proxy-favicon");
|
||||
if (!gProxyDeck)
|
||||
gProxyDeck = document.getElementById("page-proxy-deck");
|
||||
|
||||
gURLBar.setAttribute("pageproxystate", aState);
|
||||
gProxyButton.setAttribute("pageproxystate", aState);
|
||||
gProxyFavIcon.setAttribute("pageproxystate", aState);
|
||||
|
||||
// the page proxy state is set to valid via OnLocationChange, which
|
||||
// gets called when we switch tabs.
|
||||
@ -2150,21 +2167,17 @@ function PageProxySetIcon (aURL)
|
||||
PageProxyClearIcon();
|
||||
else if (gProxyFavIcon.getAttribute("src") != aURL)
|
||||
gProxyFavIcon.setAttribute("src", aURL);
|
||||
else if (gProxyDeck.selectedIndex != 1)
|
||||
gProxyDeck.selectedIndex = 1;
|
||||
}
|
||||
|
||||
function PageProxyClearIcon ()
|
||||
{
|
||||
if (gProxyDeck.selectedIndex != 0)
|
||||
gProxyDeck.selectedIndex = 0;
|
||||
if (gProxyFavIcon.hasAttribute("src"))
|
||||
gProxyFavIcon.removeAttribute("src");
|
||||
gProxyFavIcon.removeAttribute("src");
|
||||
}
|
||||
|
||||
|
||||
function PageProxyDragGesture(aEvent)
|
||||
{
|
||||
if (gProxyButton.getAttribute("pageproxystate") == "valid") {
|
||||
if (gProxyFavIcon.getAttribute("pageproxystate") == "valid") {
|
||||
nsDragAndDrop.startDrag(aEvent, proxyIconDNDObserver);
|
||||
return true;
|
||||
}
|
||||
@ -2969,12 +2982,12 @@ function FillHistoryMenu(aParent) {
|
||||
let iconURL = Cc["@mozilla.org/browser/favicon-service;1"]
|
||||
.getService(Ci.nsIFaviconService)
|
||||
.getFaviconForPage(entry.URI).spec;
|
||||
item.setAttribute("image", iconURL);
|
||||
item.style.listStyleImage = "url(" + iconURL + ")";
|
||||
} catch (ex) {}
|
||||
}
|
||||
|
||||
if (j < index) {
|
||||
item.className = "unified-nav-back";
|
||||
item.className = "unified-nav-back menuitem-iconic";
|
||||
item.setAttribute("tooltiptext", tooltipBack);
|
||||
} else if (j == index) {
|
||||
item.setAttribute("type", "radio");
|
||||
@ -2982,7 +2995,7 @@ function FillHistoryMenu(aParent) {
|
||||
item.className = "unified-nav-current";
|
||||
item.setAttribute("tooltiptext", tooltipCurrent);
|
||||
} else {
|
||||
item.className = "unified-nav-forward";
|
||||
item.className = "unified-nav-forward menuitem-iconic";
|
||||
item.setAttribute("tooltiptext", tooltipForward);
|
||||
}
|
||||
|
||||
@ -3122,9 +3135,7 @@ function BrowserToolboxCustomizeDone(aToolboxChanged)
|
||||
// Update global UI elements that may have been added or removed
|
||||
if (aToolboxChanged) {
|
||||
gURLBar = document.getElementById("urlbar");
|
||||
gProxyButton = document.getElementById("page-proxy-button");
|
||||
gProxyFavIcon = document.getElementById("page-proxy-favicon");
|
||||
gProxyDeck = document.getElementById("page-proxy-deck");
|
||||
gHomeButton.updateTooltip();
|
||||
gIdentityHandler._cacheElements();
|
||||
window.XULBrowserWindow.init();
|
||||
@ -3135,6 +3146,14 @@ function BrowserToolboxCustomizeDone(aToolboxChanged)
|
||||
document.getElementById('Browser:Back').hasAttribute('disabled') &&
|
||||
document.getElementById('Browser:Forward').hasAttribute('disabled');
|
||||
|
||||
// support downgrading to Firefox 2.0
|
||||
var navBar = document.getElementById("nav-bar");
|
||||
navBar.setAttribute("currentset",
|
||||
navBar.getAttribute("currentset")
|
||||
.replace("unified-back-forward-button",
|
||||
"unified-back-forward-button,back-button,forward-button"));
|
||||
document.persist(navBar.id, "currentset");
|
||||
|
||||
#ifndef XP_MACOSX
|
||||
updateEditUIVisibility();
|
||||
#endif
|
||||
@ -4980,12 +4999,18 @@ var OfflineApps = {
|
||||
// OfflineApps Public Methods
|
||||
init: function ()
|
||||
{
|
||||
// XXX: empty init left as a placeholder for patch in bug 397417
|
||||
var obs = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
obs.addObserver(this, "dom-storage-warn-quota-exceeded", false);
|
||||
obs.addObserver(this, "offline-cache-update-completed", false);
|
||||
},
|
||||
|
||||
uninit: function ()
|
||||
{
|
||||
// XXX: empty uninit left as a placeholder for patch in bug 397417
|
||||
var obs = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
obs.removeObserver(this, "dom-storage-warn-quota-exceeded");
|
||||
obs.removeObserver(this, "offline-cache-update-completed");
|
||||
},
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
@ -5013,6 +5038,92 @@ var OfflineApps = {
|
||||
}
|
||||
},
|
||||
|
||||
_getManifestURI: function(aWindow) {
|
||||
var attr = aWindow.document.documentElement.getAttribute("manifest");
|
||||
if (!attr) return null;
|
||||
|
||||
try {
|
||||
var ios = Cc["@mozilla.org/network/io-service;1"].
|
||||
getService(Ci.nsIIOService);
|
||||
|
||||
var contentURI = ios.newURI(aWindow.location.href, null, null);
|
||||
return ios.newURI(attr, aWindow.document.characterSet, contentURI);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
// A cache update isn't tied to a specific window. Try to find
|
||||
// the best browser in which to warn the user about space usage
|
||||
_getBrowserForCacheUpdate: function(aCacheUpdate) {
|
||||
// Prefer the current browser
|
||||
var uri = this._getManifestURI(gBrowser.mCurrentBrowser.contentWindow);
|
||||
if (uri && uri.equals(aCacheUpdate.manifestURI)) {
|
||||
return gBrowser.mCurrentBrowser;
|
||||
}
|
||||
|
||||
var browsers = getBrowser().browsers;
|
||||
for (var i = 0; i < browsers.length; ++i) {
|
||||
uri = this._getManifestURI(browsers[i].contentWindow);
|
||||
if (uri && uri.equals(aCacheUpdate.manifestURI)) {
|
||||
return browsers[i];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
_warnUsage: function(aBrowser, aURI) {
|
||||
if (!aBrowser)
|
||||
return;
|
||||
|
||||
var notificationBox = gBrowser.getNotificationBox(aBrowser);
|
||||
var notification = notificationBox.getNotificationWithValue("offline-app-usage");
|
||||
if (!notification) {
|
||||
var bundle_browser = document.getElementById("bundle_browser");
|
||||
|
||||
var buttons = [{
|
||||
label: bundle_browser.getString("offlineApps.manageUsage"),
|
||||
accessKey: bundle_browser.getString("offlineApps.manageUsageAccessKey"),
|
||||
callback: OfflineApps.manage
|
||||
}];
|
||||
|
||||
var warnQuota = gPrefService.getIntPref("offline-apps.quota.warn");
|
||||
const priority = notificationBox.PRIORITY_WARNING_MEDIUM;
|
||||
var message = bundle_browser.getFormattedString("offlineApps.usage",
|
||||
[ aURI.host,
|
||||
warnQuota / 1024 ]);
|
||||
|
||||
notificationBox.appendNotification(message, "offline-app-usage",
|
||||
"chrome://browser/skin/Info.png",
|
||||
priority, buttons);
|
||||
}
|
||||
|
||||
// Now that we've warned once, prevent the warning from showing up
|
||||
// again.
|
||||
var pm = Cc["@mozilla.org/permissionmanager;1"].
|
||||
getService(Ci.nsIPermissionManager);
|
||||
pm.add(aURI, "offline-app",
|
||||
Ci.nsIOfflineCacheUpdateService.ALLOW_NO_WARN);
|
||||
},
|
||||
|
||||
_checkUsage: function(aURI) {
|
||||
var pm = Cc["@mozilla.org/permissionmanager;1"].
|
||||
getService(Ci.nsIPermissionManager);
|
||||
|
||||
// if the user has already allowed excessive usage, don't bother checking
|
||||
if (pm.testExactPermission(aURI, "offline-app") !=
|
||||
Ci.nsIOfflineCacheUpdateService.ALLOW_NO_WARN) {
|
||||
var usage = getOfflineAppUsage(aURI.asciiHost);
|
||||
var warnQuota = gPrefService.getIntPref("offline-apps.quota.warn");
|
||||
if (usage >= warnQuota * 1024) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
offlineAppRequested: function(aContentWindow) {
|
||||
if (!gPrefService.getBoolPref("browser.offline-apps.notify")) {
|
||||
return;
|
||||
@ -5087,6 +5198,10 @@ var OfflineApps = {
|
||||
pm.add(currentURI, "offline-app", Ci.nsIPermissionManager.DENY_ACTION);
|
||||
},
|
||||
|
||||
manage: function() {
|
||||
openAdvancedPreferences("networkTab");
|
||||
},
|
||||
|
||||
_startFetching: function() {
|
||||
var manifest = content.document.documentElement.getAttribute("manifest");
|
||||
if (!manifest)
|
||||
@ -5102,6 +5217,37 @@ var OfflineApps = {
|
||||
var updateService = Cc["@mozilla.org/offlinecacheupdate-service;1"].
|
||||
getService(Ci.nsIOfflineCacheUpdateService);
|
||||
updateService.scheduleUpdate(manifestURI, contentURI);
|
||||
},
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// nsIObserver
|
||||
observe: function (aSubject, aTopic, aState)
|
||||
{
|
||||
if (aTopic == "dom-storage-warn-quota-exceeded") {
|
||||
if (aSubject) {
|
||||
var uri = Cc["@mozilla.org/network/io-service;1"].
|
||||
getService(Ci.nsIIOService).
|
||||
newURI(aSubject.location.href, null, null);
|
||||
|
||||
if (OfflineApps._checkUsage(uri)) {
|
||||
var browserWindow =
|
||||
this._getBrowserWindowForContentWindow(aSubject);
|
||||
var browser = this._getBrowserForContentWindow(browserWindow,
|
||||
aSubject);
|
||||
OfflineApps._warnUsage(browser, uri);
|
||||
}
|
||||
}
|
||||
} else if (aTopic == "offline-cache-update-completed") {
|
||||
var cacheUpdate = aSubject.QueryInterface(Ci.nsIOfflineCacheUpdate);
|
||||
|
||||
var uri = cacheUpdate.manifestURI;
|
||||
if (OfflineApps._checkUsage(uri)) {
|
||||
var browser = this._getBrowserForCacheUpdate(cacheUpdate);
|
||||
if (browser) {
|
||||
OfflineApps._warnUsage(browser, cacheUpdate.manifestURI);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -90,6 +90,7 @@
|
||||
|
||||
<popupset id="mainPopupSet">
|
||||
<menupopup id="backForwardMenu"
|
||||
chromedir="&locale.dir;"
|
||||
onpopupshowing="return FillHistoryMenu(event.target);"
|
||||
oncommand="gotoHistoryIndex(event);"
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
@ -261,6 +262,7 @@
|
||||
<!-- bug 415444: event.stopPropagation is here for the cloned version of
|
||||
this menupopup -->
|
||||
<menupopup context=""
|
||||
chromedir="&locale.dir;"
|
||||
position="after_start"
|
||||
onpopupshowing="return FillHistoryMenu(event.target);"
|
||||
oncommand="gotoHistoryIndex(event); event.stopPropagation();"
|
||||
@ -305,6 +307,8 @@
|
||||
ontextentered="return handleURLBarCommand(param);"
|
||||
ontextreverted="return handleURLBarRevert();"
|
||||
pageproxystate="invalid"
|
||||
onsearchbegin="LocationBarHelpers._searchBegin();"
|
||||
onsearchcomplete="LocationBarHelpers._searchComplete();"
|
||||
onfocus="document.getElementById('identity-box').style.MozUserFocus= 'normal'"
|
||||
onblur="document.getElementById('identity-box').style.MozUserFocus = 'ignore';">
|
||||
<!-- Use onclick instead of normal popup= syntax since the popup
|
||||
@ -315,18 +319,14 @@
|
||||
onclick="getIdentityHandler().handleIdentityButtonEvent(event);"
|
||||
onkeypress="getIdentityHandler().handleIdentityButtonEvent(event);">
|
||||
<hbox align="center">
|
||||
<deck id="page-proxy-deck" onclick="PageProxyClickHandler(event);">
|
||||
<image id="page-proxy-button"
|
||||
ondraggesture="PageProxyDragGesture(event);"
|
||||
tooltiptext="&proxyIcon.tooltip;"/>
|
||||
<stack id="page-proxy-stack"
|
||||
onclick="PageProxyClickHandler(event);"
|
||||
tooltiptext="&proxyIcon.tooltip;">
|
||||
<image id="urlbar-throbber" busy="false"/>
|
||||
<image id="page-proxy-favicon" validate="never"
|
||||
ondraggesture="PageProxyDragGesture(event);"
|
||||
onload="this.parentNode.selectedIndex = 1;
|
||||
event.stopPropagation();"
|
||||
onerror="this.removeAttribute('src');
|
||||
this.parentNode.selectedIndex = 0;"
|
||||
tooltiptext="&proxyIcon.tooltip;"/>
|
||||
</deck>
|
||||
onerror="this.removeAttribute('src');"/>
|
||||
</stack>
|
||||
<label id="identity-icon-label"/>
|
||||
</hbox>
|
||||
</box>
|
||||
|
@ -110,6 +110,7 @@
|
||||
.footnote {
|
||||
font-size: x-small;
|
||||
text-align: justify;
|
||||
line-height: 110%;
|
||||
}
|
||||
|
||||
h2.title {
|
||||
@ -468,10 +469,8 @@
|
||||
Mozilla Firefox® and the Firefox logo are registered trademarks of the
|
||||
Mozilla Foundation. You are not granted rights or licenses to the trademarks
|
||||
of the Mozilla Foundation or any party, including without limitation the
|
||||
Firefox name or logo.</p>
|
||||
|
||||
<p class="footnote">
|
||||
Gecko® is a registered trademark of Netscape Communications Corporation.</p>
|
||||
Firefox name or logo. Gecko® is a registered trademark of Netscape
|
||||
Communications Corporation.</p>
|
||||
|
||||
<p class="footnote">
|
||||
U.S. GOVERNMENT END USERS. The Software is a “commercial item,”
|
||||
|
@ -362,7 +362,8 @@ nsContextMenu.prototype = {
|
||||
// Set various context menu attributes based on the state of the world.
|
||||
setTarget: function (aNode, aRangeParent, aRangeOffset) {
|
||||
const xulNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
if (aNode.namespaceURI == xulNS) {
|
||||
if (aNode.namespaceURI == xulNS ||
|
||||
this.isTargetAFormControl(aNode)) {
|
||||
this.shouldDisplay = false;
|
||||
return;
|
||||
}
|
||||
@ -1093,6 +1094,18 @@ nsContextMenu.prototype = {
|
||||
"contextMenu.hasBGImage = " + this.hasBGImage + "\n";
|
||||
},
|
||||
|
||||
// Returns true if aNode is a from control (except text boxes).
|
||||
// This is used to disable the context menu for form controls.
|
||||
isTargetAFormControl: function(aNode) {
|
||||
if (aNode instanceof HTMLInputElement)
|
||||
return (aNode.type != "text" && aNode.type != "password");
|
||||
|
||||
return (aNode instanceof HTMLButtonElement) ||
|
||||
(aNode instanceof HTMLSelectElement) ||
|
||||
(aNode instanceof HTMLOptionElement) ||
|
||||
(aNode instanceof HTMLOptGroupElement);
|
||||
},
|
||||
|
||||
isTargetATextBox: function(node) {
|
||||
if (node instanceof HTMLInputElement)
|
||||
return (node.type == "text" || node.type == "password")
|
||||
|
@ -77,33 +77,36 @@
|
||||
ondragexit="nsDragAndDrop.dragExit(event, this.parentNode.parentNode); event.stopPropagation();">
|
||||
<xul:tooltip onpopupshowing="return this.parentNode.parentNode.parentNode.createTooltip(event);"/>
|
||||
<xul:menupopup anonid="tabContextMenu" onpopupshowing="this.parentNode.parentNode.parentNode.updatePopupMenu(this);">
|
||||
<xul:menuitem label="&newTab.label;" accesskey="&newTab.accesskey;"
|
||||
<xul:menuitem id="context_newTab" label="&newTab.label;" accesskey="&newTab.accesskey;"
|
||||
xbl:inherits="oncommand=onnewtab"/>
|
||||
<xul:menuseparator/>
|
||||
<xul:menuitem label="&reloadTab.label;" accesskey="&reloadTab.accesskey;"
|
||||
<xul:menuitem id="context_reloadTab" label="&reloadTab.label;" accesskey="&reloadTab.accesskey;"
|
||||
oncommand="var tabbrowser = this.parentNode.parentNode.parentNode.parentNode;
|
||||
tabbrowser.reloadTab(tabbrowser.mContextTab);"/>
|
||||
<xul:menuitem label="&reloadAllTabs.label;" accesskey="&reloadAllTabs.accesskey;"
|
||||
<xul:menuitem id="context_reloadAllTabs" label="&reloadAllTabs.label;" accesskey="&reloadAllTabs.accesskey;"
|
||||
tbattr="tabbrowser-multiple"
|
||||
oncommand="var tabbrowser = this.parentNode.parentNode.parentNode.parentNode;
|
||||
tabbrowser.reloadAllTabs(tabbrowser.mContextTab);"/>
|
||||
<xul:menuitem label="&closeOtherTabs.label;" accesskey="&closeOtherTabs.accesskey;"
|
||||
<xul:menuitem id="context_closeOtherTabs" label="&closeOtherTabs.label;" accesskey="&closeOtherTabs.accesskey;"
|
||||
tbattr="tabbrowser-multiple"
|
||||
oncommand="var tabbrowser = this.parentNode.parentNode.parentNode.parentNode;
|
||||
tabbrowser.removeAllTabsBut(tabbrowser.mContextTab);"/>
|
||||
<xul:menuseparator/>
|
||||
<xul:menuitem label="&bookmarkThisTab.label;"
|
||||
<xul:menuitem id="context_bookmarkTab"
|
||||
label="&bookmarkThisTab.label;"
|
||||
accesskey="&bookmarkThisTab.accesskey;"
|
||||
oncommand="BookmarkThisTab();"/>
|
||||
<xul:menuitem label="&bookmarkAllTabs.label;"
|
||||
<xul:menuitem id="context_bookmarkAllTabs"
|
||||
label="&bookmarkAllTabs.label;"
|
||||
accesskey="&bookmarkAllTabs.accesskey;"
|
||||
command="Browser:BookmarkAllTabs"/>
|
||||
<xul:menuitem label="&undoCloseTab.label;"
|
||||
<xul:menuitem id="context_undoCloseTab"
|
||||
label="&undoCloseTab.label;"
|
||||
accesskey="&undoCloseTab.accesskey;"
|
||||
command="History:UndoCloseTab"
|
||||
anonid="undoCloseTabMenuItem"/>
|
||||
<xul:menuseparator/>
|
||||
<xul:menuitem label="&closeTab.label;" accesskey="&closeTab.accesskey;"
|
||||
<xul:menuitem id="context_closeTab" label="&closeTab.label;" accesskey="&closeTab.accesskey;"
|
||||
oncommand="var tabbrowser = this.parentNode.parentNode.parentNode.parentNode;
|
||||
tabbrowser.removeTab(tabbrowser.mContextTab);"/>
|
||||
</xul:menupopup>
|
||||
|
@ -384,10 +384,28 @@ function openPreferences(paneID)
|
||||
var pane = win.document.getElementById(paneID);
|
||||
win.document.documentElement.showPane(pane);
|
||||
}
|
||||
return win;
|
||||
}
|
||||
|
||||
return openDialog("chrome://browser/content/preferences/preferences.xul",
|
||||
"Preferences", features, paneID);
|
||||
}
|
||||
|
||||
function openAdvancedPreferences(tabID)
|
||||
{
|
||||
var win = openPreferences("paneAdvanced");
|
||||
if (win) {
|
||||
var selectTab = function() {
|
||||
var tabs = win.document.getElementById("advancedPrefs");
|
||||
tabs.selectedTab = win.document.getElementById(tabID);
|
||||
}
|
||||
|
||||
if (win.document.getElementById("advancedPrefs")) {
|
||||
selectTab();
|
||||
} else {
|
||||
win.addEventListener("load", selectTab, false);
|
||||
}
|
||||
}
|
||||
else
|
||||
openDialog("chrome://browser/content/preferences/preferences.xul",
|
||||
"Preferences", features, paneID);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -637,3 +655,21 @@ function isValidFeed(aData, aPrincipal, aIsFeed)
|
||||
|
||||
return aIsFeed;
|
||||
}
|
||||
|
||||
function getOfflineAppUsage(host)
|
||||
{
|
||||
var cacheService = Components.classes["@mozilla.org/network/cache-service;1"].
|
||||
getService(Components.interfaces.nsICacheService);
|
||||
var cacheSession = cacheService.createSession("HTTP-offline",
|
||||
Components.interfaces.nsICache.STORE_OFFLINE,
|
||||
true).
|
||||
QueryInterface(Components.interfaces.nsIOfflineCacheSession);
|
||||
var usage = cacheSession.getDomainUsage(host);
|
||||
|
||||
var storageManager = Components.classes["@mozilla.org/dom/storagemanager;1"].
|
||||
getService(Components.interfaces.nsIDOMStorageManager);
|
||||
usage += storageManager.getUsage(host);
|
||||
|
||||
return usage;
|
||||
}
|
||||
|
||||
|
@ -64,12 +64,6 @@ SHARED_LIBRARY_LIBS += ../shell/src/$(LIB_PREFIX)shellservice_s.$(LIB_SUFFIX) \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
ifdef MOZ_SAFE_BROWSING
|
||||
REQUIRES += safebrowsing
|
||||
LOCAL_INCLUDES += -I$(srcdir)/../safebrowsing/src
|
||||
SHARED_LIBRARY_LIBS += ../safebrowsing/src/$(LIB_PREFIX)safebrowsing_s.$(LIB_SUFFIX)
|
||||
endif
|
||||
|
||||
EXTRA_DSO_LDOPTS += \
|
||||
$(call EXPAND_LIBNAME_PATH,unicharutil_external_s,$(LIBXUL_DIST)/lib) \
|
||||
$(LIBXUL_DIST)/lib/$(LIB_PREFIX)mozreg_s.$(LIB_SUFFIX) \
|
||||
|
@ -91,12 +91,6 @@
|
||||
#define NS_ABOUTFEEDS_CID \
|
||||
{ 0x12ff56ec, 0x58be, 0x402c, { 0xb0, 0x57, 0x1, 0xf9, 0x61, 0xde, 0x96, 0x9b } }
|
||||
|
||||
#define NS_DOCNAVSTARTPROGRESSLISTENER_CID \
|
||||
{ 0x7baf8179, 0xa4fd, 0x4bc0, { 0xbe, 0x43, 0xa9, 0xb1, 0x22, 0xc5, 0xde, 0xb6 } }
|
||||
|
||||
#define NS_DOCNAVSTARTPROGRESSLISTENER_CONTRACTID \
|
||||
"@mozilla.org/browser/safebrowsing/navstartlistener;1"
|
||||
|
||||
// 6fb0c970-e1b1-11db-8314-0800200c9a66
|
||||
#define NS_PLACESIMPORTEXPORTSERVICE_CID \
|
||||
{ 0x6fb0c970, 0xe1b1, 0x11db, { 0x83, 0x14, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66 } }
|
||||
|
@ -69,9 +69,6 @@
|
||||
#include "nsFeedSniffer.h"
|
||||
#include "nsAboutFeeds.h"
|
||||
#include "nsIAboutModule.h"
|
||||
#ifdef MOZ_SAFE_BROWSING
|
||||
#include "nsDocNavStartProgressListener.h"
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -102,9 +99,6 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsCaminoProfileMigrator)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsICabProfileMigrator)
|
||||
#endif
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsFeedSniffer)
|
||||
#ifdef MOZ_SAFE_BROWSING
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsDocNavStartProgressListener)
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -142,13 +136,6 @@ static const nsModuleComponentInfo components[] =
|
||||
nsAboutFeeds::Create
|
||||
},
|
||||
|
||||
#ifdef MOZ_SAFE_BROWSING
|
||||
{ "Safe browsing document nav start progress listener",
|
||||
NS_DOCNAVSTARTPROGRESSLISTENER_CID,
|
||||
NS_DOCNAVSTARTPROGRESSLISTENER_CONTRACTID,
|
||||
nsDocNavStartProgressListenerConstructor },
|
||||
#endif
|
||||
|
||||
{ "Profile Migrator",
|
||||
NS_FIREFOX_PROFILEMIGRATOR_CID,
|
||||
NS_PROFILEMIGRATOR_CONTRACTID,
|
||||
|
@ -35,8 +35,8 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
#include "nsIMIMEInfo.idl"
|
||||
#include "nsIWebContentHandlerRegistrar.idl"
|
||||
|
||||
interface nsIRequest;
|
||||
|
||||
@ -64,8 +64,8 @@ interface nsIWebContentHandlerInfo : nsIHandlerApp
|
||||
AString getHandlerURI(in AString uri);
|
||||
};
|
||||
|
||||
[scriptable, uuid(632b16a8-5c6b-4dc5-a8db-01771af7a79d)]
|
||||
interface nsIWebContentConverterService : nsISupports
|
||||
[scriptable, uuid(de7cc06e-e778-45cb-b7db-7a114e1e75b1)]
|
||||
interface nsIWebContentConverterService : nsIWebContentHandlerRegistrar
|
||||
{
|
||||
/**
|
||||
* Specifies the handler to be used to automatically handle all links of a
|
||||
@ -128,30 +128,6 @@ interface nsIWebContentConverterService : nsISupports
|
||||
*/
|
||||
void removeContentHandler(in AString contentType, in AString uri);
|
||||
|
||||
/**
|
||||
* Registers a protocol handler for a web service
|
||||
* @param protocol
|
||||
* The protocol scheme to register a service handler for
|
||||
* @param uri
|
||||
* The uri of the service handler to register
|
||||
* @param title
|
||||
* The human readable title of the service
|
||||
*/
|
||||
void registerProtocolHandler(in AString scheme, in AString uri,
|
||||
in AString title);
|
||||
|
||||
/**
|
||||
* Registers a content handler for a web service
|
||||
* @param contentType
|
||||
* The content type to register a service handler for
|
||||
* @param uri
|
||||
* The uri of the service handler to register
|
||||
* @param title
|
||||
* The human readable title of the service
|
||||
*/
|
||||
void registerContentHandler(in AString contentType, in AString uri,
|
||||
in AString title);
|
||||
|
||||
/**
|
||||
* Gets the list of content handlers for a particular type.
|
||||
* @param contentType
|
||||
|
@ -498,9 +498,8 @@ WebContentConverterRegistrar.prototype = {
|
||||
|
||||
/**
|
||||
* See nsIWebContentHandlerRegistrar
|
||||
* This is the web front end into the registration system, so a prompt to
|
||||
* confirm the registration is provided, and the result is saved to
|
||||
* preferences.
|
||||
* If a DOM window is provided, then the request came from content, so we
|
||||
* prompt the user to confirm the registration.
|
||||
*/
|
||||
registerContentHandler:
|
||||
function WCCR_registerContentHandler(aContentType, aURIString, aTitle, aContentWindow) {
|
||||
@ -513,12 +512,16 @@ WebContentConverterRegistrar.prototype = {
|
||||
if (contentType != TYPE_MAYBE_FEED)
|
||||
return;
|
||||
|
||||
var uri = this._checkAndGetURI(aURIString, aContentWindow);
|
||||
|
||||
var browserWindow = this._getBrowserWindowForContentWindow(aContentWindow);
|
||||
var browserElement = this._getBrowserForContentWindow(browserWindow, aContentWindow);
|
||||
var notificationBox = browserWindow.getBrowser().getNotificationBox(browserElement);
|
||||
this._appendFeedReaderNotification(uri, aTitle, notificationBox);
|
||||
if (aContentWindow) {
|
||||
var uri = this._checkAndGetURI(aURIString, aContentWindow);
|
||||
|
||||
var browserWindow = this._getBrowserWindowForContentWindow(aContentWindow);
|
||||
var browserElement = this._getBrowserForContentWindow(browserWindow, aContentWindow);
|
||||
var notificationBox = browserWindow.getBrowser().getNotificationBox(browserElement);
|
||||
this._appendFeedReaderNotification(uri, aTitle, notificationBox);
|
||||
}
|
||||
else
|
||||
this._registerContentHandler(contentType, aURIString, aTitle);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -608,25 +611,8 @@ WebContentConverterRegistrar.prototype = {
|
||||
var outer = aButtonInfo._outer;
|
||||
|
||||
// The reader could have been added from another window mean while
|
||||
if (!outer.getWebContentHandlerByURI(TYPE_MAYBE_FEED, uri)) {
|
||||
if (!outer.getWebContentHandlerByURI(TYPE_MAYBE_FEED, uri))
|
||||
outer._registerContentHandler(TYPE_MAYBE_FEED, uri, name);
|
||||
outer._saveContentHandlerToPrefs(TYPE_MAYBE_FEED, uri, name);
|
||||
|
||||
// Make the new handler the last-selected reader in the preview page
|
||||
// and make sure the preview page is shown the next time a feed is visited
|
||||
var pb = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefService).getBranch(null);
|
||||
pb.setCharPref(PREF_SELECTED_READER, "web");
|
||||
|
||||
var supportsString =
|
||||
Cc["@mozilla.org/supports-string;1"].
|
||||
createInstance(Ci.nsISupportsString);
|
||||
supportsString.data = uri;
|
||||
pb.setComplexValue(PREF_SELECTED_WEB, Ci.nsISupportsString,
|
||||
supportsString);
|
||||
pb.setCharPref(PREF_SELECTED_ACTION, "ask");
|
||||
outer._setAutoHandler(TYPE_MAYBE_FEED, null);
|
||||
}
|
||||
|
||||
// avoid reference cycles
|
||||
aButtonInfo._outer = null;
|
||||
@ -726,6 +712,39 @@ WebContentConverterRegistrar.prototype = {
|
||||
return template.replace(/%s/, contentType);
|
||||
},
|
||||
|
||||
/**
|
||||
* Register a web service handler for a content type.
|
||||
*
|
||||
* @param contentType
|
||||
* the content type being handled
|
||||
* @param uri
|
||||
* the URI of the web service
|
||||
* @param title
|
||||
* the human readable name of the web service
|
||||
*/
|
||||
_registerContentHandler:
|
||||
function WCCR__registerContentHandler(contentType, uri, title) {
|
||||
this._updateContentTypeHandlerMap(contentType, uri, title);
|
||||
this._saveContentHandlerToPrefs(contentType, uri, title);
|
||||
|
||||
if (contentType == TYPE_MAYBE_FEED) {
|
||||
// Make the new handler the last-selected reader in the preview page
|
||||
// and make sure the preview page is shown the next time a feed is visited
|
||||
var pb = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefService).getBranch(null);
|
||||
pb.setCharPref(PREF_SELECTED_READER, "web");
|
||||
|
||||
var supportsString =
|
||||
Cc["@mozilla.org/supports-string;1"].
|
||||
createInstance(Ci.nsISupportsString);
|
||||
supportsString.data = uri;
|
||||
pb.setComplexValue(PREF_SELECTED_WEB, Ci.nsISupportsString,
|
||||
supportsString);
|
||||
pb.setCharPref(PREF_SELECTED_ACTION, "ask");
|
||||
this._setAutoHandler(TYPE_MAYBE_FEED, null);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Update the content type -> handler map. This mapping is not persisted, use
|
||||
* registerContentHandler or _saveContentHandlerToPrefs for that purpose.
|
||||
@ -736,8 +755,8 @@ WebContentConverterRegistrar.prototype = {
|
||||
* @param title
|
||||
* The human readable name of the web service
|
||||
*/
|
||||
_registerContentHandler:
|
||||
function WCCR__registerContentHandler(contentType, uri, title) {
|
||||
_updateContentTypeHandlerMap:
|
||||
function WCCR__updateContentTypeHandlerMap(contentType, uri, title) {
|
||||
if (!(contentType in this._contentTypes))
|
||||
this._contentTypes[contentType] = [];
|
||||
|
||||
@ -805,7 +824,7 @@ WebContentConverterRegistrar.prototype = {
|
||||
var uri = branch.getComplexValue("uri", Ci.nsIPrefLocalizedString).data;
|
||||
var title = branch.getComplexValue("title",
|
||||
Ci.nsIPrefLocalizedString).data;
|
||||
this._registerContentHandler(type, uri, title);
|
||||
this._updateContentTypeHandlerMap(type, uri, title);
|
||||
}
|
||||
catch(ex) {
|
||||
// do nothing, the next branch might have values
|
||||
|
@ -237,7 +237,9 @@ BrowserGlue.prototype = {
|
||||
prefBranch.getBoolPref("browser.sessionstore.resume_session_once"))
|
||||
showPrompt = false;
|
||||
else
|
||||
showPrompt = prefBranch.getBoolPref("browser.warnOnQuit");
|
||||
showPrompt = aQuitType == "restart" ?
|
||||
prefBranch.getBoolPref("browser.warnOnRestart") :
|
||||
prefBranch.getBoolPref("browser.warnOnQuit");
|
||||
} catch (ex) {}
|
||||
|
||||
var buttonChoice = 0;
|
||||
@ -297,10 +299,15 @@ BrowserGlue.prototype = {
|
||||
break;
|
||||
case 0:
|
||||
this._saveSession = true;
|
||||
// could also set browser.warnOnQuit to false here,
|
||||
// but not setting it is a little safer.
|
||||
if (neverAsk.value)
|
||||
prefBranch.setIntPref("browser.startup.page", 3);
|
||||
if (neverAsk.value) {
|
||||
if (aQuitType == "restart")
|
||||
prefBranch.setBoolPref("browser.warnOnRestart", false);
|
||||
else {
|
||||
// could also set browser.warnOnQuit to false here,
|
||||
// but not setting it is a little safer.
|
||||
prefBranch.setIntPref("browser.startup.page", 3);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -532,7 +539,6 @@ BrowserGlue.prototype = {
|
||||
var bookmarksMenuFolder = bmsvc.bookmarksMenuFolder;
|
||||
var unfiledBookmarksFolder = bmsvc.unfiledBookmarksFolder;
|
||||
var toolbarFolder = bmsvc.toolbarFolder;
|
||||
var tagsFolder = bmsvc.tagsFolder;
|
||||
var defaultIndex = bmsvc.DEFAULT_INDEX;
|
||||
|
||||
// index = 0, make it the first folder
|
||||
@ -567,14 +573,11 @@ BrowserGlue.prototype = {
|
||||
var sep = bmsvc.insertSeparator(placesFolder, defaultIndex);
|
||||
|
||||
var recentTagsItem = bmsvc.insertBookmark(placesFolder,
|
||||
this._uri("place:folder=" + tagsFolder +
|
||||
"&group=" + Ci.nsINavHistoryQueryOptions.GROUP_BY_FOLDER +
|
||||
"&queryType=" + Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS +
|
||||
"&applyOptionsToContainers=1" +
|
||||
"&sort=" +
|
||||
Ci.nsINavHistoryQueryOptions.SORT_BY_DATEADDED_DESCENDING +
|
||||
this._uri("place:"+
|
||||
"type=" + Ci.nsINavHistoryQueryOptions.RESULTS_AS_TAG_QUERY +
|
||||
"&sort=" + Ci.nsINavHistoryQueryOptions.SORT_BY_DATEADDED_DESCENDING +
|
||||
"&maxResults=" + maxResults),
|
||||
defaultIndex, recentTagsTitle);
|
||||
defaultIndex, recentTagsTitle);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -72,8 +72,8 @@
|
||||
flex="1"
|
||||
hidecolumnpicker="true"
|
||||
context="placesContext"
|
||||
onkeypress="if (event.keyCode == 13) this.controller.openSelectedNodeWithEvent(event);"
|
||||
onclick="SidebarUtils.handleClick(this, event);"
|
||||
onkeypress="SidebarUtils.handleTreeKeyPress(event);"
|
||||
onclick="SidebarUtils.handleTreeClick(this, event);"
|
||||
onmousemove="SidebarUtils.handleTreeMouseMove(event);"
|
||||
onmouseout="SidebarUtils.clearURLFromStatusBar();">
|
||||
<treecols>
|
||||
|
@ -128,7 +128,8 @@ PlacesController.prototype = {
|
||||
case "placesCmd_open":
|
||||
case "placesCmd_open:window":
|
||||
case "placesCmd_open:tab":
|
||||
return this._view.selectedURINode;
|
||||
var selectedNode = this._view.selectedNode;
|
||||
return selectedNode && PlacesUtils.nodeIsURI(selectedNode);
|
||||
case "placesCmd_new:folder":
|
||||
case "placesCmd_new:livemark":
|
||||
return this._canInsert();
|
||||
@ -140,8 +141,8 @@ PlacesController.prototype = {
|
||||
this._view.getResult().sortingMode ==
|
||||
Ci.nsINavHistoryQueryOptions.SORT_BY_NONE;
|
||||
case "placesCmd_show:info":
|
||||
if (this._view.hasSingleSelection) {
|
||||
var selectedNode = this._view.selectedNode;
|
||||
var selectedNode = this._view.selectedNode;
|
||||
if (selectedNode) {
|
||||
if (PlacesUtils.nodeIsFolder(selectedNode) ||
|
||||
(PlacesUtils.nodeIsBookmark(selectedNode) &&
|
||||
!PlacesUtils.nodeIsLivemarkItem(selectedNode)))
|
||||
@ -149,24 +150,13 @@ PlacesController.prototype = {
|
||||
}
|
||||
return false;
|
||||
case "placesCmd_reloadMicrosummary":
|
||||
if (this._view.hasSingleSelection) {
|
||||
var selectedNode = this._view.selectedNode;
|
||||
if (PlacesUtils.nodeIsBookmark(selectedNode)) {
|
||||
var mss = PlacesUtils.microsummaries;
|
||||
if (mss.hasMicrosummary(selectedNode.itemId))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
var selectedNode = this._view.selectedNode;
|
||||
return selectedNode && PlacesUtils.nodeIsBookmark(selectedNode) &&
|
||||
PlacesUtils.microsummaries.hasMicrosummary(selectedNode.itemId);
|
||||
case "placesCmd_reload":
|
||||
if (this._view.hasSingleSelection) {
|
||||
var selectedNode = this._view.selectedNode;
|
||||
|
||||
// Livemark containers
|
||||
if (PlacesUtils.nodeIsLivemarkContainer(selectedNode))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
// Livemark containers
|
||||
var selectedNode = this._view.selectedNode;
|
||||
return selectedNode && PlacesUtils.nodeIsLivemarkContainer(selectedNode);
|
||||
case "placesCmd_sortBy:name":
|
||||
var selectedNode = this._view.selectedNode;
|
||||
return selectedNode &&
|
||||
@ -223,13 +213,13 @@ PlacesController.prototype = {
|
||||
this.selectAll();
|
||||
break;
|
||||
case "placesCmd_open":
|
||||
this.openSelectedNodeIn("current");
|
||||
PlacesUtils.openNodeIn(this._view.selectedNode, "current");
|
||||
break;
|
||||
case "placesCmd_open:window":
|
||||
this.openSelectedNodeIn("window");
|
||||
PlacesUtils.openNodeIn(this._view.selectedNode, "window");
|
||||
break;
|
||||
case "placesCmd_open:tab":
|
||||
this.openSelectedNodeIn("tab");
|
||||
PlacesUtils.openNodeIn(this._view.selectedNode, "tab");
|
||||
break;
|
||||
case "placesCmd_new:folder":
|
||||
this.newItem("folder");
|
||||
@ -277,9 +267,6 @@ PlacesController.prototype = {
|
||||
* false otherwise.
|
||||
*/
|
||||
_hasRemovableSelection: function PC__hasRemovableSelection(aIsMoveCommand) {
|
||||
if (!this._view.hasSelection)
|
||||
return false;
|
||||
|
||||
var nodes = this._view.getSelectionNodes();
|
||||
var root = this._view.getResultNode();
|
||||
|
||||
@ -328,14 +315,13 @@ PlacesController.prototype = {
|
||||
* Determines whether or not the root node for the view is selected
|
||||
*/
|
||||
rootNodeIsSelected: function PC_rootNodeIsSelected() {
|
||||
if (this._view.hasSelection) {
|
||||
var nodes = this._view.getSelectionNodes();
|
||||
var root = this._view.getResultNode();
|
||||
for (var i = 0; i < nodes.length; ++i) {
|
||||
if (nodes[i] == root)
|
||||
return true;
|
||||
}
|
||||
var nodes = this._view.getSelectionNodes();
|
||||
var root = this._view.getResultNode();
|
||||
for (var i = 0; i < nodes.length; ++i) {
|
||||
if (nodes[i] == root)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
@ -411,12 +397,10 @@ PlacesController.prototype = {
|
||||
*/
|
||||
_buildSelectionMetadata: function PC__buildSelectionMetadata() {
|
||||
var metadata = [];
|
||||
var nodes = [];
|
||||
var root = this._view.getResult().root;
|
||||
if (this._view.hasSelection)
|
||||
nodes = this._view.getSelectionNodes();
|
||||
else // See the second note above
|
||||
nodes = [root];
|
||||
var nodes = this._view.getSelectionNodes();
|
||||
if (nodes.length == 0)
|
||||
nodes.push(root); // See the second note above
|
||||
|
||||
for (var i=0; i < nodes.length; i++) {
|
||||
var nodeData = {};
|
||||
@ -429,6 +413,17 @@ PlacesController.prototype = {
|
||||
switch(nodeType) {
|
||||
case Ci.nsINavHistoryResultNode.RESULT_TYPE_QUERY:
|
||||
nodeData["query"] = true;
|
||||
if (node.parent) {
|
||||
switch (asQuery(node.parent).queryOptions.resultType) {
|
||||
case Ci.nsINavHistoryQueryOptions.RESULTS_AS_SITE_QUERY:
|
||||
nodeData["host"] = true;
|
||||
break;
|
||||
case Ci.nsINavHistoryQueryOptions.RESULTS_AS_DATE_SITE_QUERY:
|
||||
case Ci.nsINavHistoryQueryOptions.RESULTS_AS_DATE_QUERY:
|
||||
nodeData["day"] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Ci.nsINavHistoryResultNode.RESULT_TYPE_DYNAMIC_CONTAINER:
|
||||
nodeData["dynamiccontainer"] = true;
|
||||
@ -437,9 +432,6 @@ PlacesController.prototype = {
|
||||
case Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER_SHORTCUT:
|
||||
nodeData["folder"] = true;
|
||||
break;
|
||||
case Ci.nsINavHistoryResultNode.RESULT_TYPE_HOST:
|
||||
nodeData["host"] = true;
|
||||
break;
|
||||
case Ci.nsINavHistoryResultNode.RESULT_TYPE_SEPARATOR:
|
||||
nodeData["separator"] = true;
|
||||
break;
|
||||
@ -458,8 +450,6 @@ PlacesController.prototype = {
|
||||
nodeData["livemarkChild"] = true;
|
||||
}
|
||||
break;
|
||||
case Ci.nsINavHistoryResultNode.RESULT_TYPE_DAY:
|
||||
nodeData["day"] = true;
|
||||
}
|
||||
|
||||
// Mutability is whether or not a container can have selected items
|
||||
@ -628,49 +618,6 @@ PlacesController.prototype = {
|
||||
this._view.selectAll();
|
||||
},
|
||||
|
||||
/**
|
||||
* Loads the selected node's URL in the appropriate tab or window or as a web
|
||||
* panel given the user's preference specified by modifier keys tracked by a
|
||||
* DOM mouse/key event.
|
||||
* @param aEvent
|
||||
* The DOM mouse/key event with modifier keys set that track the
|
||||
* user's preferred destination window or tab.
|
||||
*/
|
||||
openSelectedNodeWithEvent: function PC_openSelectedNodeWithEvent(aEvent) {
|
||||
this.openSelectedNodeIn(whereToOpenLink(aEvent));
|
||||
},
|
||||
|
||||
/**
|
||||
* Loads the selected node's URL in the appropriate tab or window or as a
|
||||
* web panel.
|
||||
* see also openUILinkIn
|
||||
*/
|
||||
openSelectedNodeIn: function PC_openSelectedNodeIn(aWhere) {
|
||||
var node = this._view.selectedURINode;
|
||||
if (node && PlacesUtils.checkURLSecurity(node)) {
|
||||
var isBookmark = PlacesUtils.nodeIsBookmark(node);
|
||||
|
||||
if (isBookmark)
|
||||
PlacesUtils.markPageAsFollowedBookmark(node.uri);
|
||||
else
|
||||
PlacesUtils.markPageAsTyped(node.uri);
|
||||
|
||||
// Check whether the node is a bookmark which should be opened as
|
||||
// a web panel
|
||||
if (aWhere == "current" && isBookmark) {
|
||||
if (PlacesUtils.annotations
|
||||
.itemHasAnnotation(node.itemId, LOAD_IN_SIDEBAR_ANNO)) {
|
||||
var w = getTopWin();
|
||||
if (w) {
|
||||
w.openWebPanel(node.title, node.uri);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
openUILinkIn(node.uri, aWhere);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Opens the bookmark properties for the selected URI Node.
|
||||
*/
|
||||
@ -699,11 +646,9 @@ PlacesController.prototype = {
|
||||
* Reloads the selected livemark if any.
|
||||
*/
|
||||
reloadSelectedLivemark: function PC_reloadSelectedLivemark() {
|
||||
if (this._view.hasSingleSelection) {
|
||||
var selectedNode = this._view.selectedNode;
|
||||
if (PlacesUtils.nodeIsLivemarkContainer(selectedNode))
|
||||
PlacesUtils.livemarks.reloadLivemarkFolder(selectedNode.itemId);
|
||||
}
|
||||
var selectedNode = this._view.selectedNode;
|
||||
if (selectedNode && PlacesUtils.nodeIsLivemarkContainer(selectedNode))
|
||||
PlacesUtils.livemarks.reloadLivemarkFolder(selectedNode.itemId);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -768,7 +713,7 @@ PlacesController.prototype = {
|
||||
*/
|
||||
openSelectionInTabs: function PC_openLinksInTabs(aEvent) {
|
||||
var node = this._view.selectedNode;
|
||||
if (this._view.hasSingleSelection && PlacesUtils.nodeIsContainer(node))
|
||||
if (node && PlacesUtils.nodeIsContainer(node))
|
||||
PlacesUtils.openContainerNodeInTabs(this._view.selectedNode, aEvent);
|
||||
else
|
||||
PlacesUtils.openURINodesInTabs(this._view.getSelectionNodes(), aEvent);
|
||||
@ -964,14 +909,16 @@ PlacesController.prototype = {
|
||||
// day nodes have time property set to the last day in the interval
|
||||
var endDate = node.time;
|
||||
|
||||
// if this is not the last day container, then beginDate
|
||||
// is the time property of the next day container
|
||||
for (var j = 0; j < root.childCount-1 && !beginDate; ++j) {
|
||||
if (root.getChild(j) != node)
|
||||
continue;
|
||||
var nextNode = root.getChild(j+1);
|
||||
beginDate = nextNode.time
|
||||
}
|
||||
var nodeIdx = 0;
|
||||
var cc = root.childCount;
|
||||
|
||||
// Find index of current day node
|
||||
while (nodeIdx < cc && root.getChild(nodeIdx) != node)
|
||||
++nodeIdx;
|
||||
|
||||
// We have an older day
|
||||
if (nodeIdx+1 < cc)
|
||||
beginDate = root.getChild(nodeIdx+1).time;
|
||||
|
||||
// we want to exclude beginDate from the removal
|
||||
bhist.removePagesByTimeframe(beginDate+1, endDate);
|
||||
@ -1036,11 +983,14 @@ PlacesController.prototype = {
|
||||
var oldViewer = result.viewer;
|
||||
try {
|
||||
result.viewer = null;
|
||||
var nodes = null;
|
||||
if (dragAction == Ci.nsIDragService.DRAGDROP_ACTION_COPY)
|
||||
nodes = this._view.getCopyableSelection();
|
||||
else
|
||||
nodes = this._view.getDragableSelection();
|
||||
var nodes = this._view.getDragableSelection();
|
||||
if (dragAction == Ci.nsIDragService.DRAGDROP_ACTION_MOVE) {
|
||||
nodes = nodes.filter(function(node) {
|
||||
var parent = node.parent;
|
||||
return parent && !PlacesUtils.nodeIsReadOnly(parent);
|
||||
});
|
||||
}
|
||||
|
||||
var dataSet = new TransferDataSet();
|
||||
for (var i = 0; i < nodes.length; ++i) {
|
||||
var node = nodes[i];
|
||||
@ -1086,14 +1036,14 @@ PlacesController.prototype = {
|
||||
var oldViewer = result.viewer;
|
||||
try {
|
||||
result.viewer = null;
|
||||
var nodes = this._view.getCopyableSelection();
|
||||
var nodes = this._view.getSelectionNodes();
|
||||
|
||||
var xferable = Cc["@mozilla.org/widget/transferable;1"].
|
||||
createInstance(Ci.nsITransferable);
|
||||
var foundFolder = false, foundLink = false;
|
||||
var copiedFolders = [];
|
||||
var placeString = mozURLString = htmlString = unicodeString = "";
|
||||
|
||||
|
||||
for (var i = 0; i < nodes.length; ++i) {
|
||||
var node = nodes[i];
|
||||
if (this._shouldSkipNode(node, copiedFolders))
|
||||
@ -1114,7 +1064,7 @@ PlacesController.prototype = {
|
||||
uri) + suffix);
|
||||
htmlString += (PlacesUtils.wrapNode(node, PlacesUtils.TYPE_HTML,
|
||||
uri) + suffix);
|
||||
|
||||
|
||||
var placeSuffix = i < (nodes.length - 1) ? "," : "";
|
||||
return PlacesUtils.wrapNode(node, type, overrideURI) + placeSuffix;
|
||||
}
|
||||
|
@ -102,11 +102,9 @@ function historyAddBookmarks()
|
||||
// no need to check gHistoryTree.view.selection.count
|
||||
// node will be null if there is a multiple selection
|
||||
// or if the selected item is not a URI node
|
||||
var node = gHistoryTree.selectedURINode;
|
||||
if (!node)
|
||||
return;
|
||||
|
||||
PlacesUtils.showMinimalAddBookmarkUI(PlacesUtils._uri(node.uri), node.title);
|
||||
var node = gHistoryTree.selectedNode;
|
||||
if (node && PlacesUtils.nodeIsURI(node))
|
||||
PlacesUtils.showMinimalAddBookmarkUI(PlacesUtils._uri(node.uri), node.title);
|
||||
}
|
||||
|
||||
function searchHistory(aInput)
|
||||
@ -116,7 +114,6 @@ function searchHistory(aInput)
|
||||
|
||||
const NHQO = Ci.nsINavHistoryQueryOptions;
|
||||
var sortingMode;
|
||||
var groups = [];
|
||||
var resultType;
|
||||
|
||||
if (aInput) {
|
||||
@ -134,22 +131,20 @@ function searchHistory(aInput)
|
||||
resultType = NHQO.RESULTS_AS_URI;
|
||||
sortingMode = NHQO.SORT_BY_DATE_DESCENDING;
|
||||
break;
|
||||
case "dayandsite": // fall through
|
||||
groups.push(NHQO.GROUP_BY_DAY);
|
||||
case "dayandsite":
|
||||
resultType = NHQO.RESULTS_AS_DATE_SITE_QUERY;
|
||||
break;
|
||||
case "site":
|
||||
groups.push(NHQO.GROUP_BY_HOST);
|
||||
resultType = NHQO.RESULTS_AS_VISIT;
|
||||
resultType = NHQO.RESULTS_AS_SITE_QUERY;
|
||||
sortingMode = NHQO.SORT_BY_TITLE_ASCENDING;
|
||||
break;
|
||||
case "day":
|
||||
default:
|
||||
resultType = NHQO.RESULTS_AS_VISIT;
|
||||
groups.push(NHQO.GROUP_BY_DAY);
|
||||
sortingMode = NHQO.SORT_BY_TITLE_ASCENDING;
|
||||
resultType = NHQO.RESULTS_AS_DATE_QUERY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
options.setGroupingMode(groups, groups.length);
|
||||
options.sortingMode = sortingMode;
|
||||
options.resultType = resultType;
|
||||
|
||||
|
@ -119,9 +119,9 @@
|
||||
flex="1"
|
||||
type="places"
|
||||
context="placesContext"
|
||||
onkeypress="if (event.keyCode == 13) this.controller.openSelectedNodeWithEvent(event);"
|
||||
hidecolumnpicker="true"
|
||||
onclick="SidebarUtils.handleClick(this, event, true);"
|
||||
onkeypress="SidebarUtils.handleTreeKeyPress(event);"
|
||||
onclick="SidebarUtils.handleTreeClick(this, event);"
|
||||
onmousemove="SidebarUtils.handleTreeMouseMove(event);"
|
||||
onmouseout="SidebarUtils.clearURLFromStatusBar();">
|
||||
<treecols>
|
||||
|
@ -187,11 +187,12 @@
|
||||
<parameter name="aXferData"/>
|
||||
<parameter name="aDragAction"/>
|
||||
<body><![CDATA[
|
||||
this._rootView._selection = aEvent.target.node;
|
||||
this._rootView._cachedInsertionPoint = undefined;
|
||||
|
||||
if (aEvent.ctrlKey)
|
||||
aDragAction.action = Ci.nsIDragService.DRAGDROP_ACTION_COPY;
|
||||
|
||||
// activate the view and cache the dragged node
|
||||
this._rootView._draggedNode = aEvent.target.node;
|
||||
this._rootView.focus();
|
||||
aXferData.data = this._rootView.controller
|
||||
.getTransferData(aDragAction.action);
|
||||
]]></body>
|
||||
@ -248,28 +249,27 @@
|
||||
<body><![CDATA[
|
||||
// Can't drop if the menu isn't a folder
|
||||
var resultNode = this._resultNode;
|
||||
|
||||
if (!PlacesUtils.nodeIsFolder(resultNode))
|
||||
return null;
|
||||
|
||||
var dropPoint = { ip: null, beforeIndex: null, folderNode: null };
|
||||
// Loop through all the nodes to see which one this should
|
||||
// get dropped in/above/below.
|
||||
|
||||
// set the limits for valid items
|
||||
var start = 0;
|
||||
var popup = this;
|
||||
var end = popup.childNodes.length;
|
||||
if (popup == this._rootView &&
|
||||
this._rootView.localName == "menupopup") {
|
||||
// Ignore static content at the top and bottom of the menu.
|
||||
start = this._rootView._startMarker + 1;
|
||||
if (this._rootView._endMarker != -1)
|
||||
end = this._rootView._endMarker;
|
||||
}
|
||||
if (this._startMarker != -1)
|
||||
start = this._startMarker + 1;
|
||||
if (this._endMarker != -1)
|
||||
end = this._endMarker;
|
||||
|
||||
var popupFirstChildY = popup.firstChild.boxObject.y;
|
||||
// Loop through all the nodes to find the correct dropPoint
|
||||
var popupY = popup.boxObject.y;
|
||||
// we should add the scrollBox button height if visible
|
||||
popupY += this._scrollBox.scrollBoxObject.y - popup.boxObject.y;
|
||||
for (var i = start; i < end; i++) {
|
||||
var xulNode = popup.childNodes[i];
|
||||
var nodeY = xulNode.boxObject.y - popupFirstChildY;
|
||||
var nodeY = xulNode.boxObject.y - popupY;
|
||||
var nodeHeight = xulNode.boxObject.height;
|
||||
if (xulNode.node &&
|
||||
PlacesUtils.nodeIsFolder(xulNode.node) &&
|
||||
@ -295,7 +295,7 @@
|
||||
else {
|
||||
// This is a non-folder node. If the mouse is above the middle,
|
||||
// drop above the folder. Otherwise, drop below.
|
||||
if (aEvent.layerY < nodeY + (nodeHeight / 2)) {
|
||||
if (aEvent.layerY <= nodeY + (nodeHeight / 2)) {
|
||||
// Drop above this bookmark.
|
||||
dropPoint.ip = new InsertionPoint(resultNode.itemId,
|
||||
i - start, -1);
|
||||
@ -507,8 +507,6 @@
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<field name="_selection">null</field>
|
||||
|
||||
<!-- nsIPlacesView -->
|
||||
<method name="getResult">
|
||||
<body><![CDATA[
|
||||
@ -588,6 +586,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
// if document.popupNode pointed to this child, null it out,
|
||||
// otherwise controller's command-updating may rely on the removed
|
||||
// item still being "selected".
|
||||
if (document.popupNode == child)
|
||||
document.popupNode = null;
|
||||
child.parentNode.removeChild(child);
|
||||
]]></body>
|
||||
</method>
|
||||
@ -872,21 +875,15 @@
|
||||
<!-- nsIPlacesView -->
|
||||
<property name="hasSelection">
|
||||
<getter><![CDATA[
|
||||
return this._selection != null;
|
||||
]]></getter>
|
||||
</property>
|
||||
|
||||
<!-- nsIPlacesView -->
|
||||
<property name="hasSingleSelection">
|
||||
<getter><![CDATA[
|
||||
return this.hasSelection;
|
||||
return this.selectedNode != null;
|
||||
]]></getter>
|
||||
</property>
|
||||
|
||||
<!-- nsIPlacesView -->
|
||||
<method name="getSelectionNodes">
|
||||
<body><![CDATA[
|
||||
return this.hasSelection ? [this.selectedNode] : [];
|
||||
var selectedNode = this.selectedNode;
|
||||
return selectedNode ? [selectedNode] : [];
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
@ -897,77 +894,58 @@
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<!-- nsIPlacesView -->
|
||||
<method name="getCopyableSelection">
|
||||
<body><![CDATA[
|
||||
return this.getSelectionNodes();
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<!-- nsIPlacesView -->
|
||||
<method name="getDragableSelection">
|
||||
<body><![CDATA[
|
||||
if (PlacesUtils.nodeIsReadOnly(this._resultNode))
|
||||
return null;
|
||||
return this.getSelectionNodes();
|
||||
return [this._draggedNode];
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<!-- nsIPlacesView -->
|
||||
<property name="selectedNode">
|
||||
<getter><![CDATA[
|
||||
return this.hasSelection ? this._selection : null;
|
||||
]]></getter>
|
||||
</property>
|
||||
|
||||
<!-- nsIPlacesView -->
|
||||
<property name="selectedURINode">
|
||||
<getter><![CDATA[
|
||||
var node = this.selectedNode;
|
||||
return node && PlacesUtils.nodeIsURI(node) ? node : null;
|
||||
if (this._contextMenuShown) {
|
||||
var popupNode = document.popupNode;
|
||||
return popupNode.node || popupNode.parentNode._resultNode || null;
|
||||
}
|
||||
return null;
|
||||
]]></getter>
|
||||
</property>
|
||||
|
||||
<!-- nsIPlacesView -->
|
||||
<property name="insertionPoint">
|
||||
<getter><![CDATA[
|
||||
if (this._cachedInsertionPoint !== undefined)
|
||||
return this._cachedInsertionPoint;
|
||||
|
||||
// By default, the insertion point is at the top level, at the end.
|
||||
var index = -1;
|
||||
var folderId = 0;
|
||||
if (PlacesUtils.nodeIsFolder(this._resultNode))
|
||||
folderId = PlacesUtils.getConcreteItemId(this._resultNode);
|
||||
|
||||
if (this.hasSelection) {
|
||||
if (PlacesUtils.nodeIsFolder(this.selectedNode)) {
|
||||
var selectedNode = this.selectedNode;
|
||||
if (selectedNode) {
|
||||
if (PlacesUtils.nodeIsFolder(selectedNode)) {
|
||||
// If there is a folder selected, the insertion point is the
|
||||
// end of the folder.
|
||||
folderId = PlacesUtils.getConcreteItemId(this.selectedNode);
|
||||
} else {
|
||||
folderId = PlacesUtils.getConcreteItemId(selectedNode);
|
||||
}
|
||||
else {
|
||||
// If there is another type of node selected, the insertion point
|
||||
// is after that node.
|
||||
folderId = PlacesUtils.getConcreteItemId(this.selectedNode.parent);
|
||||
index = PlacesUtils.getIndexOfNode(this.selectedNode)
|
||||
folderId = PlacesUtils.getConcreteItemId(selectedNode.parent);
|
||||
index = PlacesUtils.getIndexOfNode(selectedNode)
|
||||
}
|
||||
}
|
||||
this._cachedInsertionPoint = new InsertionPoint(folderId, index);
|
||||
return this._cachedInsertionPoint;
|
||||
return new InsertionPoint(folderId, index);
|
||||
]]></getter>
|
||||
</property>
|
||||
|
||||
<!-- nsIPlacesView -->
|
||||
<method name="selectAll">
|
||||
<body><![CDATA[
|
||||
// Nothing
|
||||
]]></body>
|
||||
<body/>
|
||||
</method>
|
||||
|
||||
<method name="selectItems">
|
||||
<body><![CDATA[
|
||||
// Nothing
|
||||
]]></body>
|
||||
<body/>
|
||||
</method>
|
||||
|
||||
<property name="selType" readonly="true" onget="return 'single';"/>
|
||||
@ -976,6 +954,7 @@
|
||||
<parameter name="aPopup"/>
|
||||
<body><![CDATA[
|
||||
this._ensureInitialized();
|
||||
this._contextMenuShown = true;
|
||||
this.focus();
|
||||
return this.controller.buildContextMenu(aPopup);
|
||||
]]></body>
|
||||
@ -985,6 +964,7 @@
|
||||
<parameter name="aPopup"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
this._contextMenuShown = false;
|
||||
if (window.content)
|
||||
window.content.focus();
|
||||
]]>
|
||||
@ -1013,28 +993,6 @@
|
||||
// when the folder closes because it is no longer applicable.
|
||||
popup.removeAttribute("autoopened");
|
||||
]]></handler>
|
||||
|
||||
<!-- Set selected node on DOMMenuItemActive/contextmenu events
|
||||
so that they're set up when command and click events fire. -->
|
||||
<handler event="DOMMenuItemActive"><![CDATA[
|
||||
// Set the selection to the node that was activated. If that
|
||||
// node has a command but no data associated with it, it should
|
||||
// act on the entire menu.
|
||||
if (event.target.parentNode._resultNode) {
|
||||
this._cachedInsertionPoint = undefined;
|
||||
this._selection = event.target.node ||
|
||||
event.target.parentNode._resultNode;
|
||||
}
|
||||
]]></handler>
|
||||
<handler event="contextmenu"><![CDATA[
|
||||
// DOMMenuItemActive is not dispatched for disabled menuitems and
|
||||
// menuseparators. Set the selection here manually.
|
||||
var popupNode = document.popupNode;
|
||||
// |popupNode == menupopup| happens when the area between
|
||||
// menuseparators is clicked.
|
||||
this._selection = popupNode.node || popupNode.parentNode._resultNode;
|
||||
this._cachedInsertionPoint = undefined;
|
||||
]]></handler>
|
||||
</handlers>
|
||||
</binding>
|
||||
|
||||
|
@ -232,20 +232,19 @@ var PlacesOrganizer = {
|
||||
* The mouse event.
|
||||
*/
|
||||
onTreeClick: function PO_onTreeClick(aEvent) {
|
||||
var currentView = aEvent.currentTarget;
|
||||
var controller = currentView.controller;
|
||||
|
||||
if (aEvent.target.localName != "treechildren")
|
||||
return;
|
||||
|
||||
if (currentView.hasSingleSelection && aEvent.button == 1) {
|
||||
if (PlacesUtils.nodeIsURI(currentView.selectedNode))
|
||||
controller.openSelectedNodeWithEvent(aEvent);
|
||||
else if (PlacesUtils.nodeIsContainer(currentView.selectedNode)) {
|
||||
var currentView = aEvent.currentTarget;
|
||||
var selectedNode = currentView.selectedNode;
|
||||
if (selectedNode && aEvent.button == 1) {
|
||||
if (PlacesUtils.nodeIsURI(selectedNode))
|
||||
PlacesUtils.openNodeWithEvent(selectedNode, aEvent);
|
||||
else if (PlacesUtils.nodeIsContainer(selectedNode)) {
|
||||
// The command execution function will take care of seeing the
|
||||
// selection is a folder/container and loading its contents in
|
||||
// tabs for us.
|
||||
controller.openLinksInTabs();
|
||||
PlacesUtils.openContainerNodeInTabs(selectedNode);
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -258,7 +257,7 @@ var PlacesOrganizer = {
|
||||
},
|
||||
|
||||
openSelectedNode: function PU_openSelectedNode(aEvent) {
|
||||
this._content.controller.openSelectedNodeWithEvent(aEvent);
|
||||
PlacesUtils.openNodeWithEvent(this._content.selectedNode, aEvent);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -525,23 +524,21 @@ var PlacesOrganizer = {
|
||||
|
||||
var contentTree = document.getElementById("placeContent");
|
||||
var detailsDeck = document.getElementById("detailsDeck");
|
||||
if (contentTree.hasSelection) {
|
||||
detailsDeck.selectedIndex = 1;
|
||||
if (contentTree.hasSingleSelection) {
|
||||
var selectedNode = contentTree.selectedNode;
|
||||
if (selectedNode.itemId != -1 &&
|
||||
!PlacesUtils.nodeIsSeparator(selectedNode)) {
|
||||
if (this._paneDisabled) {
|
||||
this._setDetailsFieldsDisabledState(false);
|
||||
this._paneDisabled = false;
|
||||
}
|
||||
|
||||
gEditItemOverlay.initPanel(selectedNode.itemId,
|
||||
{ hiddenRows: ["folderPicker"] });
|
||||
|
||||
this._detectAndSetDetailsPaneMinimalState(selectedNode);
|
||||
return;
|
||||
detailsDeck.selectedIndex = 1;
|
||||
var selectedNode = contentTree.selectedNode;
|
||||
if (selectedNode) {
|
||||
if (selectedNode.itemId != -1 &&
|
||||
!PlacesUtils.nodeIsSeparator(selectedNode)) {
|
||||
if (this._paneDisabled) {
|
||||
this._setDetailsFieldsDisabledState(false);
|
||||
this._paneDisabled = false;
|
||||
}
|
||||
|
||||
gEditItemOverlay.initPanel(selectedNode.itemId,
|
||||
{ hiddenRows: ["folderPicker"] });
|
||||
|
||||
this._detectAndSetDetailsPaneMinimalState(selectedNode);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -37,7 +37,7 @@
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
var SidebarUtils = {
|
||||
handleClick: function SU_handleClick(aTree, aEvent, aGutterSelect) {
|
||||
handleTreeClick: function SU_handleTreeClick(aTree, aEvent, aGutterSelect) {
|
||||
var tbo = aTree.treeBoxObject;
|
||||
|
||||
var row = { }, col = { }, obj = { };
|
||||
@ -67,10 +67,15 @@ var SidebarUtils = {
|
||||
// do this *before* attempting to load the link since openURL uses
|
||||
// selection as an indication of which link to load.
|
||||
tbo.view.selection.select(row.value);
|
||||
aTree.controller.openSelectedNodeWithEvent(aEvent);
|
||||
PlacesUtils.openNodeWithEvent(aTree.selectedNode, aEvent);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
handleTreeKeyPress: function SU_handleTreeKeyPress(aEvent) {
|
||||
if (aEvent.keyCode == KeyEvent.DOM_VK_RETURN)
|
||||
PlacesUtils.openNodeWithEvent(aEvent.target.selectedNode, aEvent);
|
||||
},
|
||||
|
||||
/**
|
||||
* The following function displays the URL of a node that is being
|
||||
* hovered over.
|
||||
|
@ -122,8 +122,6 @@
|
||||
<field name="_dropIndicatorBar">document.getAnonymousElementByAttribute(this, "class", "toolbar-drop-indicator-bar")</field>
|
||||
<field name="_chevron">document.getAnonymousElementByAttribute(this, "class", "chevron")</field>
|
||||
|
||||
<field name="_selection">null</field>
|
||||
|
||||
<field name="_openedMenuButton">null</field>
|
||||
|
||||
<field name="_result">null</field>
|
||||
@ -232,6 +230,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
// if document.popupNode pointed to this child, null it out,
|
||||
// otherwise controller's command-updating may rely on the removed
|
||||
// item still being "selected".
|
||||
if (document.popupNode == child)
|
||||
document.popupNode = null;
|
||||
child.parentNode.removeChild(child);
|
||||
]]></body>
|
||||
</method>
|
||||
@ -331,85 +334,65 @@
|
||||
<!-- nsIPlacesView -->
|
||||
<property name="hasSelection">
|
||||
<getter><![CDATA[
|
||||
return this._selection != null;
|
||||
]]></getter>
|
||||
</property>
|
||||
|
||||
<!-- nsIPlacesView -->
|
||||
<property name="hasSingleSelection">
|
||||
<getter><![CDATA[
|
||||
return this.hasSelection;
|
||||
return this.selectedNode != null;
|
||||
]]></getter>
|
||||
</property>
|
||||
|
||||
<!-- nsIPlacesView -->
|
||||
<method name="getSelectionNodes">
|
||||
<body><![CDATA[
|
||||
return this.hasSelection ? [this.selectedNode] : [];
|
||||
var selectedNode = this.selectedNode;
|
||||
return selectedNode ? [selectedNode] : [];
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<!-- nsIPlacesView -->
|
||||
<method name="getRemovableSelectionRanges">
|
||||
<body><![CDATA[
|
||||
<body><![CDATA[
|
||||
return [this.getSelectionNodes()];
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<!-- nsIPlacesView -->
|
||||
<method name="getCopyableSelection">
|
||||
<body><![CDATA[
|
||||
return this.getSelectionNodes();
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<!-- nsIPlacesView -->
|
||||
<method name="getDragableSelection">
|
||||
<body><![CDATA[
|
||||
if (PlacesUtils.nodeIsReadOnly(this._result.root))
|
||||
return null;
|
||||
return this.getSelectionNodes();
|
||||
return [this._draggedNode];
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<!-- nsIPlacesView -->
|
||||
<property name="selectedNode">
|
||||
<getter><![CDATA[
|
||||
return this.hasSelection ? this._selection : null;
|
||||
]]></getter>
|
||||
</property>
|
||||
|
||||
<!-- nsIPlacesView -->
|
||||
<property name="selectedURINode">
|
||||
<getter><![CDATA[
|
||||
var node = this.selectedNode;
|
||||
return node && PlacesUtils.nodeIsURI(node) ? node : null;
|
||||
if (this._contextMenuShown) {
|
||||
var popupNode = document.popupNode;
|
||||
return popupNode.node || popupNode.parentNode._resultNode || null;
|
||||
}
|
||||
return null;
|
||||
]]></getter>
|
||||
</property>
|
||||
|
||||
<!-- nsIPlacesView -->
|
||||
<property name="insertionPoint">
|
||||
<getter><![CDATA[
|
||||
if (this._cachedInsertionPoint !== undefined)
|
||||
return this._cachedInsertionPoint;
|
||||
|
||||
// By default, the insertion point is at the top level, at the end.
|
||||
var index = -1;
|
||||
var folderId = PlacesUtils.getConcreteItemId(this._result.root);
|
||||
|
||||
if (this.hasSelection) {
|
||||
if (PlacesUtils.nodeIsFolder(this.selectedNode)) {
|
||||
var selectedNode = this.selectedNode;
|
||||
if (selectedNode) {
|
||||
if (PlacesUtils.nodeIsFolder(selectedNode)) {
|
||||
// If there is a folder selected, the insertion point is the
|
||||
// end of the folder.
|
||||
folderId = PlacesUtils.getConcreteItemId(this.selectedNode);
|
||||
} else {
|
||||
folderId = PlacesUtils.getConcreteItemId(selectedNode);
|
||||
}
|
||||
else {
|
||||
// If there is another type of node selected, the insertion point
|
||||
// is after that node.
|
||||
index = PlacesUtils.getIndexOfNode(this.selectedNode);
|
||||
folderId = PlacesUtils.getConcreteItemId(selectedNode.parent);
|
||||
index = PlacesUtils.getIndexOfNode(selectedNode);
|
||||
}
|
||||
}
|
||||
this._cachedInsertionPoint = new InsertionPoint(folderId, index, 1);
|
||||
return this._cachedInsertionPoint;
|
||||
return new InsertionPoint(folderId, index, 1);
|
||||
]]></getter>
|
||||
</property>
|
||||
|
||||
@ -704,7 +687,7 @@
|
||||
this._overFolder.node.open = true;
|
||||
this._overFolder.openTimer = null;
|
||||
}
|
||||
|
||||
|
||||
// Timer to close a menubutton that's been dragged off of.
|
||||
if (timer == this._overFolder.closeTimer) {
|
||||
// Only close the menubutton if the drag session isn't currently over
|
||||
@ -728,7 +711,7 @@
|
||||
this._clearOverFolder();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// The mouse is no longer dragging over the stored menubutton.
|
||||
// Close the menubutton, clear out drag styles, and clear all
|
||||
// timers for opening/closing it.
|
||||
@ -749,7 +732,7 @@
|
||||
this._overFolder.closeTimer = null;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// This function returns information about where to drop when
|
||||
// dragging over this menu--insertion point, child index to drop
|
||||
// before, and folder to drop into.
|
||||
@ -758,7 +741,7 @@
|
||||
var result = this._self.getResult();
|
||||
if (!PlacesUtils.nodeIsFolder(result.root))
|
||||
return null;
|
||||
|
||||
|
||||
var dropPoint = { ip: null, beforeIndex: null, folderNode: null };
|
||||
// Loop through all the nodes to see which one this should
|
||||
// get dropped in/next to
|
||||
@ -787,7 +770,8 @@
|
||||
dropPoint.folderNode = xulNode;
|
||||
return dropPoint;
|
||||
}
|
||||
} else{
|
||||
}
|
||||
else {
|
||||
// This is a non-folder node. If the mouse is left of the middle,
|
||||
// drop to the left of the folder. If it's right, drop to the right.
|
||||
if (event.clientX < xulNode.boxObject.x + (xulNode.boxObject.width / 2)) {
|
||||
@ -809,6 +793,10 @@
|
||||
},
|
||||
|
||||
onDragStart: function TBV_DO_onDragStart(event, xferData, dragAction) {
|
||||
// sub menus have their own d&d handlers
|
||||
if (event.target.parentNode != this._self)
|
||||
return false;
|
||||
|
||||
if (event.target.localName == "toolbarbutton" &&
|
||||
event.target.getAttribute("type") == "menu") {
|
||||
#ifdef XP_WIN
|
||||
@ -823,19 +811,22 @@
|
||||
#endif
|
||||
}
|
||||
|
||||
if (event.ctrlKey) {
|
||||
if (event.ctrlKey)
|
||||
dragAction.action = Ci.nsIDragService.DRAGDROP_ACTION_COPY;
|
||||
}
|
||||
|
||||
// activate the view and cache the dragged node
|
||||
this._self._draggedNode = event.target.node;
|
||||
this._self.focus();
|
||||
xferData.data = this._self._controller.getTransferData(dragAction.action);
|
||||
#ifdef XP_WIN
|
||||
return true;
|
||||
#endif
|
||||
},
|
||||
|
||||
|
||||
canDrop: function TBV_DO_canDrop(event, session) {
|
||||
return PlacesControllerDragHelper.canDrop();
|
||||
},
|
||||
|
||||
|
||||
onDragOver: function TBV_DO_onDragOver(event, flavor, session) {
|
||||
PlacesControllerDragHelper.currentDropTarget = event.target;
|
||||
var dropPoint = this._getDropPoint(event);
|
||||
@ -874,7 +865,8 @@
|
||||
else
|
||||
ind.style.marginLeft = this._self.childNodes[dropPoint.beforeIndex].boxObject.x -
|
||||
this._self.boxObject.x - halfInd + 'px';
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
halfInd = Math.floor(halfInd);
|
||||
if (dropPoint.beforeIndex == -1 || !this._self.childNodes.length)
|
||||
ind.style.marginRight = '0px';
|
||||
@ -946,6 +938,7 @@
|
||||
<method name="buildContextMenu">
|
||||
<parameter name="aPopup"/>
|
||||
<body><![CDATA[
|
||||
this._contextMenuShown = true;
|
||||
this.focus();
|
||||
return this.controller.buildContextMenu(aPopup);
|
||||
]]></body>
|
||||
@ -954,6 +947,7 @@
|
||||
<method name="destroyContextMenu">
|
||||
<parameter name="aPopup"/>
|
||||
<body><![CDATA[
|
||||
this._contextMenuShown = false;
|
||||
if (window.content)
|
||||
window.content.focus();
|
||||
]]></body>
|
||||
@ -1052,22 +1046,6 @@
|
||||
<handler event="mouseout"><![CDATA[
|
||||
window.XULBrowserWindow.setOverLink("", null);
|
||||
]]></handler>
|
||||
<handler event="mousedown"><![CDATA[
|
||||
// When the user clicks down on a button, set it as the selection and
|
||||
// tell the controller that we are the active view.
|
||||
//
|
||||
var target = event.target;
|
||||
if (target == this)
|
||||
this._selection = this.getResult().root;
|
||||
else if (target.parentNode == this &&
|
||||
(target.localName == "toolbarbutton" ||
|
||||
target.localName == "toolbarseparator"))
|
||||
this._selection = target.node;
|
||||
else // Sub-menus are handled by the DOMMenuItemActive handler
|
||||
return;
|
||||
|
||||
this._cachedInsertionPoint = undefined;
|
||||
]]></handler>
|
||||
<handler event="draggesture"><![CDATA[
|
||||
if (event.target.localName == "toolbarbutton" ||
|
||||
event.target.localName == "toolbarseparator")
|
||||
@ -1120,35 +1098,6 @@
|
||||
this._openedMenuButton = null;
|
||||
]]></handler>
|
||||
|
||||
<!-- Set selected node on DOMMenuItemActive/contextmenu events
|
||||
so that they're set up when command and click events fire. -->
|
||||
<handler event="DOMMenuItemActive"><![CDATA[
|
||||
// Set the selection to the node that was activated. If that
|
||||
// node has a command but no data associated with it, it should
|
||||
// act on the entire menu.
|
||||
if (event.target.parentNode._resultNode) {
|
||||
// the chevron has its own view
|
||||
if (this._isChevronChild(event.target))
|
||||
return;
|
||||
|
||||
this._cachedInsertionPoint = undefined;
|
||||
this._selection = event.target.node ||
|
||||
event.target.parentNode._resultNode;
|
||||
}
|
||||
]]></handler>
|
||||
<handler event="contextmenu"><![CDATA[
|
||||
// DOMMenuItemActive is not dispatched for disabled menuitems and
|
||||
// menuseparators. Set the selection here manually.
|
||||
var popupNode = document.popupNode;
|
||||
// the chevron has its own view
|
||||
if (this._isChevronChild(popupNode))
|
||||
return;
|
||||
|
||||
// |popupNode == menupopup| happens when the area between menuseparators
|
||||
// is clicked.
|
||||
this._selection = popupNode.node || popupNode.parentNode._resultNode;
|
||||
this._cachedInsertionPoint = undefined;
|
||||
]]></handler>
|
||||
<handler event="mousemove"><![CDATA[
|
||||
if (this._openedMenuButton == null || PlacesControllerDragHelper.getSession())
|
||||
return;
|
||||
|
@ -97,15 +97,6 @@
|
||||
var query = PlacesUtils.history.getNewQuery();
|
||||
query.searchTerms = filterString;
|
||||
|
||||
// Remove "group by folder" from the options list, because
|
||||
// nsNavHistory::RecursiveGroup doesn't support it.
|
||||
function isFolderGrouping(grouping, index, ary) {
|
||||
return grouping != Ci.nsINavHistoryQueryOptions.GROUP_BY_FOLDER;
|
||||
}
|
||||
var groupings = options.getGroupingMode({});
|
||||
var folderGroupings = groupings.filter(isFolderGrouping);
|
||||
options.setGroupingMode(folderGroupings, folderGroupings.length);
|
||||
|
||||
if (folderRestrict) {
|
||||
query.setFolders(folderRestrict, folderRestrict.length);
|
||||
options.queryType = options.QUERY_TYPE_BOOKMARKS;
|
||||
@ -340,13 +331,6 @@
|
||||
return this.view.selection.count >= 1;
|
||||
]]></getter>
|
||||
</property>
|
||||
|
||||
<!-- nsIPlacesView -->
|
||||
<property name="hasSingleSelection">
|
||||
<getter><![CDATA[
|
||||
return this.view.selection.count == 1;
|
||||
]]></getter>
|
||||
</property>
|
||||
|
||||
<!-- nsIPlacesView -->
|
||||
<method name="getSelectionNodes">
|
||||
@ -418,23 +402,10 @@
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<!-- nsIPlacesView -->
|
||||
<method name="getCopyableSelection">
|
||||
<body><![CDATA[
|
||||
// XXXben implement me!
|
||||
return this.getSelectionNodes();
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<!-- nsIPlacesView -->
|
||||
<method name="getDragableSelection">
|
||||
<body><![CDATA[
|
||||
var nodes = this.getSelectionNodes();
|
||||
for (var i = nodes.length - 1; i >= 0; i--) {
|
||||
if (PlacesUtils.nodeIsReadOnly(nodes[i].parent))
|
||||
nodes.splice(i, 1);
|
||||
}
|
||||
return nodes;
|
||||
return this.getSelectionNodes();
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
@ -442,36 +413,16 @@
|
||||
<property name="selectedNode">
|
||||
<getter><![CDATA[
|
||||
var view = this.view;
|
||||
var selection = view.selection;
|
||||
var rc = selection.getRangeCount();
|
||||
if (rc != 1)
|
||||
if (view.selection.count != 1)
|
||||
return null;
|
||||
|
||||
var selection = view.selection;
|
||||
var min = { }, max = { };
|
||||
selection.getRangeAt(0, min, max);
|
||||
|
||||
return this.getResultView().nodeForTreeIndex(min.value);
|
||||
]]></getter>
|
||||
</property>
|
||||
|
||||
<!-- nsIPlacesView -->
|
||||
<property name="selectedURINode">
|
||||
<getter><![CDATA[
|
||||
var view = this.view;
|
||||
var selection = view.selection;
|
||||
var rc = selection.getRangeCount();
|
||||
if (rc != 1)
|
||||
return null;
|
||||
var min = { }, max = { };
|
||||
selection.getRangeAt(0, min, max);
|
||||
|
||||
// only URI nodes should be returned
|
||||
var node = this.getResultView().nodeForTreeIndex(min.value);
|
||||
if (PlacesUtils.nodeIsURI(node))
|
||||
return node;
|
||||
return null;
|
||||
]]></getter>
|
||||
</property>
|
||||
|
||||
|
||||
<!-- nsIPlacesView -->
|
||||
<property name="insertionPoint">
|
||||
@ -526,7 +477,7 @@
|
||||
// into it even if it is not opened
|
||||
var itemId =
|
||||
PlacesUtils.getConcreteItemId(resultView.nodeForTreeIndex(max.value));
|
||||
if (this.hasSingleSelection && resultView.isContainer(max.value) &&
|
||||
if (selection.count == 1 && resultView.isContainer(max.value) &&
|
||||
(resultView.isContainerOpen(max.value) ||
|
||||
itemId == PlacesUtils.bookmarksMenuFolderId))
|
||||
orientation = Ci.nsITreeView.DROP_ON;
|
||||
|
@ -85,6 +85,13 @@ PlacesTreeView.prototype = {
|
||||
if (this._tree && this._result)
|
||||
this.sortingChanged(this._result.sortingMode);
|
||||
|
||||
var qoInt = Ci.nsINavHistoryQueryOptions;
|
||||
var options = asQuery(this._result.root).queryOptions;
|
||||
this._showQueryAsFolder = (options &&
|
||||
(options.resultType == qoInt.RESULTS_AS_DATE_QUERY ||
|
||||
options.resultType == qoInt.RESULTS_AS_SITE_QUERY ||
|
||||
options.resultType == qoInt.RESULTS_AS_DATE_SITE_QUERY));
|
||||
|
||||
// if there is no tree, BuildVisibleList will clear everything for us
|
||||
this._buildVisibleList();
|
||||
},
|
||||
@ -109,14 +116,6 @@ PlacesTreeView.prototype = {
|
||||
sortType != nsINavHistoryQueryOptions::SORT_BY_DATE_DESCENDING)
|
||||
return; // not date sorting
|
||||
|
||||
// showing sessions only makes sense if we are grouping by date
|
||||
// any other grouping (or recursive grouping) doesn't make sense
|
||||
var groupings = options.getGroupingMode({});
|
||||
for (var i=0; i < groupings.length; i++) {
|
||||
if (groupings[i] != Ci.nsINavHistoryQueryOptions.GROUP_BY_DAY)
|
||||
return; // non-time-based grouping
|
||||
}
|
||||
|
||||
this._showSessions = true;
|
||||
},
|
||||
|
||||
@ -200,26 +199,6 @@ PlacesTreeView.prototype = {
|
||||
var curChild = aContainer.getChild(i);
|
||||
var curChildType = curChild.type;
|
||||
|
||||
// collapse all duplicates starting from here
|
||||
if (this._collapseDuplicates) {
|
||||
var showThis = { value: false };
|
||||
while (i < cc - 1 &&
|
||||
this._canCollapseDuplicates(curChild, aContainer.getChild(i+1),
|
||||
showThis)) {
|
||||
if (showThis.value) {
|
||||
// collapse the first and use the second
|
||||
curChild.viewIndex = -1;
|
||||
curChild = aContainer.getChild(i+1);
|
||||
curChildType = curChild.type;
|
||||
}
|
||||
else {
|
||||
// collapse the second and use the first
|
||||
aContainer.getChild(i+1).viewIndex = -1;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
// don't display separators when sorted
|
||||
if (curChildType == Ci.nsINavHistoryResultNode.RESULT_TYPE_SEPARATOR) {
|
||||
if (this._result.sortingMode !=
|
||||
@ -418,30 +397,6 @@ PlacesTreeView.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* This returns true if the two results can be collapsed as duplicates.
|
||||
* aShowThisOne will be either 0 or 1, indicating which of the
|
||||
* duplicates should be shown.
|
||||
*/
|
||||
_canCollapseDuplicates:
|
||||
function PTV__canCollapseDuplicate(aTop, aNext, aShowThisOne) {
|
||||
if (!this._collapseDuplicates)
|
||||
return false;
|
||||
if (!PlacesUtils.nodeIsVisit(aTop) ||
|
||||
!PlacesUtils.nodeIsVisit(aNext))
|
||||
return false; // only collapse two visits
|
||||
|
||||
asVisit(aTop);
|
||||
asVisit(aNext);
|
||||
|
||||
if (aTop.uri != aNext.uri)
|
||||
return false; // don't collapse nonmatching URIs
|
||||
|
||||
// now we know we want to collapse, show the one with the more recent time
|
||||
aShowThisOne.value = aTop.time < aNext.time;
|
||||
return true;
|
||||
},
|
||||
|
||||
_convertPRTimeToString: function PTV__convertPRTimeToString(aTime) {
|
||||
var timeInMilliseconds = aTime / 1000; // PRTime is in microseconds
|
||||
var timeObj = new Date(timeInMilliseconds);
|
||||
@ -600,44 +555,6 @@ PlacesTreeView.prototype = {
|
||||
}
|
||||
}
|
||||
|
||||
// Try collapsing with the previous node. Note that we do not have to try
|
||||
// to redraw the surrounding rows (which we normally would because session
|
||||
// boundaries may have changed) because when an item is merged, it will
|
||||
// always be in the same session.
|
||||
var showThis = { value: true };
|
||||
if (newViewIndex > 0 &&
|
||||
this._canCollapseDuplicates
|
||||
(this._visibleElements[newViewIndex - 1], aItem, showThis)) {
|
||||
if (!showThis.value) {
|
||||
// new node is invisible, collapsed with previous one
|
||||
aItem.viewIndex = -1;
|
||||
}
|
||||
else {
|
||||
// new node replaces the previous
|
||||
this.itemReplaced(aParent, this._visibleElements[newViewIndex - 1],
|
||||
aItem, 0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// try collapsing with the next node (which is currently at the same
|
||||
// index we are trying to insert at)
|
||||
if (newViewIndex < this._visibleElements.length &&
|
||||
this._canCollapseDuplicates(aItem, this._visibleElements[newViewIndex],
|
||||
showThis)) {
|
||||
if (!showThis.value) {
|
||||
// new node replaces the next node
|
||||
this.itemReplaced(aParent, this._visibleElements[newViewIndex], aItem,
|
||||
0);
|
||||
}
|
||||
else {
|
||||
// new node is invisible, replaced by next one
|
||||
aItem.viewIndex = -1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// no collapsing, insert new item
|
||||
aItem.viewIndex = newViewIndex;
|
||||
this._visibleElements.splice(newViewIndex, 0, aItem);
|
||||
for (var i = newViewIndex + 1;
|
||||
@ -668,40 +585,14 @@ PlacesTreeView.prototype = {
|
||||
// this may have been a container, in which case it has a lot of rows
|
||||
var count = this._countVisibleRowsForItem(aItem);
|
||||
|
||||
// We really want tail recursion here, since we sometimes do another
|
||||
// remove after this when duplicates are being collapsed. This loop
|
||||
// emulates that.
|
||||
while (true) {
|
||||
if (oldViewIndex > this._visibleElements.length)
|
||||
throw("Trying to remove an item with an invalid viewIndex");
|
||||
if (oldViewIndex > this._visibleElements.length)
|
||||
throw("Trying to remove an item with an invalid viewIndex");
|
||||
|
||||
this._visibleElements.splice(oldViewIndex, count);
|
||||
for (var i = oldViewIndex; i < this._visibleElements.length; i++)
|
||||
this._visibleElements[i].viewIndex = i;
|
||||
this._visibleElements.splice(oldViewIndex, count);
|
||||
for (var i = oldViewIndex; i < this._visibleElements.length; i++)
|
||||
this._visibleElements[i].viewIndex = i;
|
||||
|
||||
this._tree.rowCountChanged(oldViewIndex, -count);
|
||||
|
||||
// the removal might have put two things together that should be collapsed
|
||||
if (oldViewIndex > 0 &&
|
||||
oldViewIndex < this._visibleElements.length) {
|
||||
var showThisOne = { value: true };
|
||||
if (this._canCollapseDuplicates
|
||||
(this._visibleElements[oldViewIndex - 1],
|
||||
this._visibleElements[oldViewIndex], showThisOne))
|
||||
{
|
||||
// Fake-tail-recurse to the beginning of this function to
|
||||
// remove the collapsed row. Note that we need to set the
|
||||
// visible index to -1 before looping because we can never
|
||||
// touch the row we're removing (callers may have already
|
||||
// destroyed it).
|
||||
oldViewIndex = oldViewIndex - 1 + (showThisOne.value ? 1 : 0);
|
||||
this._visibleElements[oldViewIndex].viewIndex = -1;
|
||||
count = 1; // next time remove one row
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break; // normal path: just remove once
|
||||
}
|
||||
this._tree.rowCountChanged(oldViewIndex, -count);
|
||||
|
||||
// redraw parent because twisty may have changed
|
||||
if (!aParent.hasChildren)
|
||||
@ -917,22 +808,6 @@ PlacesTreeView.prototype = {
|
||||
return val;
|
||||
},
|
||||
|
||||
// nsINavHistoryResultTreeViewer
|
||||
get collapseDuplicates() {
|
||||
return this._collapseDuplicates;
|
||||
},
|
||||
|
||||
set collapseDuplicates(val) {
|
||||
if (this._collapseDuplicates == val)
|
||||
return val; // no change;
|
||||
|
||||
this._collapseDuplicates = val;
|
||||
if (this._tree && this._result)
|
||||
this.invalidateAll();
|
||||
|
||||
return val;
|
||||
},
|
||||
|
||||
nodeForTreeIndex: function PTV_nodeForTreeIndex(aIndex) {
|
||||
if (aIndex > this._visibleElements.length)
|
||||
throw Cr.NS_ERROR_INVALID_ARG;
|
||||
@ -1007,10 +882,12 @@ PlacesTreeView.prototype = {
|
||||
|
||||
var nodeType = node.type;
|
||||
if (PlacesUtils.containerTypes.indexOf(nodeType) != -1) {
|
||||
if (nodeType == Ci.nsINavHistoryResultNode.RESULT_TYPE_QUERY)
|
||||
if (nodeType == Ci.nsINavHistoryResultNode.RESULT_TYPE_QUERY) {
|
||||
aProperties.AppendElement(this._getAtomFor("query"));
|
||||
else if (nodeType == Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER ||
|
||||
nodeType == Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER_SHORTCUT) {
|
||||
if (this._showQueryAsFolder)
|
||||
aProperties.AppendElement(this._getAtomFor("folder"));
|
||||
} else if (nodeType == Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER ||
|
||||
nodeType == Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER_SHORTCUT) {
|
||||
if (PlacesUtils.annotations.itemHasAnnotation(node.itemId,
|
||||
LMANNO_FEEDURI))
|
||||
aProperties.AppendElement(this._getAtomFor("livemark"));
|
||||
@ -1467,7 +1344,6 @@ function PlacesTreeView(aShowRoot, aFlatList, aOnOpenFlatContainer) {
|
||||
|
||||
this._tree = null;
|
||||
this._result = null;
|
||||
this._collapseDuplicates = true;
|
||||
this._showSessions = false;
|
||||
this._selection = null;
|
||||
this._visibleElements = [];
|
||||
|
@ -349,7 +349,10 @@ var PlacesUtils = {
|
||||
*/
|
||||
nodeIsHost: function PU_nodeIsHost(aNode) {
|
||||
NS_ASSERT(aNode, "null node");
|
||||
return aNode.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_HOST;
|
||||
return aNode.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_QUERY &&
|
||||
aNode.parent &&
|
||||
asQuery(aNode.parent).queryOptions.resultType ==
|
||||
Ci.nsINavHistoryQueryOptions.RESULTS_AS_SITE_QUERY;
|
||||
},
|
||||
|
||||
/**
|
||||
@ -359,7 +362,13 @@ var PlacesUtils = {
|
||||
* @returns true if the node is a day container, false otherwise
|
||||
*/
|
||||
nodeIsDay: function PU_nodeIsDay(aNode) {
|
||||
return aNode.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_DAY;
|
||||
NS_ASSERT(aNode, "null node");
|
||||
var resultType;
|
||||
return aNode.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_QUERY &&
|
||||
aNode.parent &&
|
||||
((resultType = asQuery(aNode.parent).queryOptions.resultType) ==
|
||||
Ci.nsINavHistoryQueryOptions.RESULTS_AS_DATE_QUERY ||
|
||||
resultType == Ci.nsINavHistoryQueryOptions.RESULTS_AS_DATE_SITE_QUERY);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -371,8 +380,6 @@ var PlacesUtils = {
|
||||
containerTypes: [Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER,
|
||||
Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER_SHORTCUT,
|
||||
Ci.nsINavHistoryResultNode.RESULT_TYPE_QUERY,
|
||||
Ci.nsINavHistoryResultNode.RESULT_TYPE_HOST,
|
||||
Ci.nsINavHistoryResultNode.RESULT_TYPE_DAY,
|
||||
Ci.nsINavHistoryResultNode.RESULT_TYPE_DYNAMIC_CONTAINER],
|
||||
nodeIsContainer: function PU_nodeIsContainer(aNode) {
|
||||
NS_ASSERT(aNode, "null node");
|
||||
@ -1666,11 +1673,8 @@ var PlacesUtils = {
|
||||
// Include visible url nodes only
|
||||
let child = aNode.getChild(i);
|
||||
if (this.nodeIsURI(child)) {
|
||||
// If the node contents is visible, add the uri only if its node is
|
||||
// visible. Otherwise follow viewer's collapseDuplicates property,
|
||||
// default to true
|
||||
// If the node contents is visible, add the uri
|
||||
if ((wasOpen && oldViewer && child.viewIndex != -1) ||
|
||||
(oldViewer && !oldViewer.collapseDuplicates) ||
|
||||
urls.indexOf(child.uri) == -1) {
|
||||
urls.push({ uri: child.uri,
|
||||
isBookmark: this.nodeIsBookmark(child) });
|
||||
@ -1780,6 +1784,51 @@ var PlacesUtils = {
|
||||
this._openTabset(urlsToOpen, aEvent);
|
||||
},
|
||||
|
||||
/**
|
||||
* Loads the node's URL in the appropriate tab or window or as a web
|
||||
* panel given the user's preference specified by modifier keys tracked by a
|
||||
* DOM mouse/key event.
|
||||
* @param aNode
|
||||
* An uri result node.
|
||||
* @param aEvent
|
||||
* The DOM mouse/key event with modifier keys set that track the
|
||||
* user's preferred destination window or tab.
|
||||
*/
|
||||
openNodeWithEvent: function PU_openNodeWithEvent(aNode, aEvent) {
|
||||
this.openNodeIn(aNode, whereToOpenLink(aEvent));
|
||||
},
|
||||
|
||||
/**
|
||||
* Loads the node's URL in the appropriate tab or window or as a
|
||||
* web panel.
|
||||
* see also openUILinkIn
|
||||
*/
|
||||
openNodeIn: function PU_openNodeIn(aNode, aWhere) {
|
||||
if (aNode && PlacesUtils.nodeIsURI(aNode) &&
|
||||
PlacesUtils.checkURLSecurity(aNode)) {
|
||||
var isBookmark = PlacesUtils.nodeIsBookmark(aNode);
|
||||
|
||||
if (isBookmark)
|
||||
PlacesUtils.markPageAsFollowedBookmark(aNode.uri);
|
||||
else
|
||||
PlacesUtils.markPageAsTyped(aNode.uri);
|
||||
|
||||
// Check whether the node is a bookmark which should be opened as
|
||||
// a web panel
|
||||
if (aWhere == "current" && isBookmark) {
|
||||
if (PlacesUtils.annotations
|
||||
.itemHasAnnotation(aNode.itemId, LOAD_IN_SIDEBAR_ANNO)) {
|
||||
var w = getTopWin();
|
||||
if (w) {
|
||||
w.openWebPanel(aNode.title, aNode.uri);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
openUILinkIn(aNode.uri, aWhere);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Helper for the toolbar and menu views
|
||||
*/
|
||||
|
@ -37,6 +37,9 @@
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
// Load DownloadUtils module for convertByteUnits
|
||||
Cu.import("resource://gre/modules/DownloadUtils.jsm");
|
||||
|
||||
var gAdvancedPane = {
|
||||
_inited: false,
|
||||
|
||||
@ -196,7 +199,7 @@ var gAdvancedPane = {
|
||||
allowVisible : false,
|
||||
prefilledHost : "",
|
||||
permissionType : "offline-app",
|
||||
manageCapability : Ci.nsIPermissionManager.DENY_ACTION,
|
||||
manageCapability : Components.interfaces.nsIPermissionManager.DENY_ACTION,
|
||||
windowTitle : bundlePreferences.getString("offlinepermissionstitle"),
|
||||
introText : bundlePreferences.getString("offlinepermissionstext") };
|
||||
document.documentElement.openWindow("Browser:Permissions",
|
||||
@ -217,6 +220,8 @@ var gAdvancedPane = {
|
||||
list.removeChild(list.firstChild);
|
||||
}
|
||||
|
||||
var bundle = document.getElementById("bundlePreferences");
|
||||
|
||||
var enumerator = pm.enumerator;
|
||||
while (enumerator.hasMoreElements()) {
|
||||
var perm = enumerator.getNext().QueryInterface(Components.interfaces.nsIPermission);
|
||||
@ -225,9 +230,13 @@ var gAdvancedPane = {
|
||||
perm.capability != Components.interfaces.nsIPermissionManager.DENY_ACTION) {
|
||||
var row = document.createElement("listitem");
|
||||
row.id = "";
|
||||
row.className = "listitem";
|
||||
row.setAttribute("label", perm.host);
|
||||
|
||||
row.className = "offlineapp";
|
||||
row.setAttribute("host", perm.host);
|
||||
var converted = DownloadUtils.
|
||||
convertByteUnits(getOfflineAppUsage(perm.host));
|
||||
row.setAttribute("usage",
|
||||
bundle.getFormattedString("offlineAppUsage",
|
||||
converted));
|
||||
list.appendChild(row);
|
||||
}
|
||||
}
|
||||
@ -248,7 +257,7 @@ var gAdvancedPane = {
|
||||
{
|
||||
var list = document.getElementById("offlineAppsList");
|
||||
var item = list.selectedItem;
|
||||
var host = item.getAttribute("label");
|
||||
var host = item.getAttribute("host");
|
||||
|
||||
var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
|
||||
.getService(Components.interfaces.nsIPromptService);
|
||||
|
@ -51,3 +51,7 @@ richlistitem[selected="true"] {
|
||||
display: -moz-box;
|
||||
min-width: 16px;
|
||||
}
|
||||
|
||||
listitem.offlineapp {
|
||||
-moz-binding: url("chrome://browser/content/preferences/handlers.xml#offlineapp");
|
||||
}
|
||||
|
@ -100,4 +100,14 @@
|
||||
|
||||
</binding>
|
||||
|
||||
<binding id="offlineapp"
|
||||
extends="chrome://global/content/bindings/listbox.xml#listitem">
|
||||
<content>
|
||||
<children>
|
||||
<xul:listcell xbl:inherits="label=host"/>
|
||||
<xul:listcell xbl:inherits="label=usage"/>
|
||||
</children>
|
||||
</content>
|
||||
</binding>
|
||||
|
||||
</bindings>
|
||||
|
@ -197,7 +197,7 @@ var gPrivacyPane = {
|
||||
writeAcceptCookies: function ()
|
||||
{
|
||||
var checkbox = document.getElementById("acceptCookies");
|
||||
return checkbox.checked ? 1 : 2;
|
||||
return checkbox.checked ? 0 : 2;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -69,8 +69,8 @@ var SelectBookmarkDialog = {
|
||||
|
||||
onItemDblClick: function SBD_onItemDblClick() {
|
||||
var bookmarks = document.getElementById("bookmarks");
|
||||
if (bookmarks.hasSingleSelection &&
|
||||
PlacesUtils.nodeIsURI(bookmarks.selectedNode)) {
|
||||
var selectedNode = bookmarks.selectedNode;
|
||||
if (selectedNode && PlacesUtils.nodeIsURI(selectedNode)) {
|
||||
/**
|
||||
* The user has double clicked on a tree row that is a link. Take this to
|
||||
* mean that they want that link to be their homepage, and close the dialog.
|
||||
|
@ -43,11 +43,7 @@ VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
DIRS = public src
|
||||
|
||||
ifdef ENABLE_TESTS
|
||||
DIRS += tests
|
||||
endif
|
||||
DIRS = src
|
||||
|
||||
ifneq (,$(BUILD_OFFICIAL)$(MOZILLA_OFFICIAL))
|
||||
DEFINES += -DOFFICIAL_BUILD=1
|
||||
|
@ -82,7 +82,6 @@ function PROT_Application() {
|
||||
#endif
|
||||
|
||||
// expose some classes
|
||||
this.PROT_Controller = PROT_Controller;
|
||||
this.PROT_PhishingWarden = PROT_PhishingWarden;
|
||||
this.PROT_MalwareWarden = PROT_MalwareWarden;
|
||||
|
||||
@ -93,6 +92,36 @@ function PROT_Application() {
|
||||
this.wrappedJSObject = this;
|
||||
}
|
||||
|
||||
var gInitialized = false;
|
||||
PROT_Application.prototype.initialize = function() {
|
||||
if (gInitialized)
|
||||
return;
|
||||
gInitialized = true;
|
||||
|
||||
var obs = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
obs.addObserver(this, "xpcom-shutdown", true);
|
||||
|
||||
// XXX: move table names to a pref that we originally will download
|
||||
// from the provider (need to workout protocol details)
|
||||
this.malwareWarden = new PROT_MalwareWarden();
|
||||
this.malwareWarden.registerBlackTable("goog-malware-shavar");
|
||||
this.malwareWarden.maybeToggleUpdateChecking();
|
||||
|
||||
this.phishWarden = new PROT_PhishingWarden();
|
||||
this.phishWarden.registerBlackTable("goog-phish-shavar");
|
||||
this.phishWarden.maybeToggleUpdateChecking();
|
||||
}
|
||||
|
||||
PROT_Application.prototype.observe = function(subject, topic, data) {
|
||||
switch (topic) {
|
||||
case "xpcom-shutdown":
|
||||
this.malwareWarden.shutdown();
|
||||
this.phishWarden.shutdown();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name String The type of url to get (either Phish or Error).
|
||||
* @return String the report phishing URL (localized).
|
||||
@ -121,6 +150,8 @@ PROT_Application.prototype.getURIFlags = function(uri) {
|
||||
|
||||
PROT_Application.prototype.QueryInterface = function(iid) {
|
||||
if (iid.equals(Ci.nsISupports) ||
|
||||
iid.equals(Ci.nsISupportsWeakReference) ||
|
||||
iid.equals(Ci.nsIObserver) ||
|
||||
iid.equals(Ci.nsIAboutModule))
|
||||
return this;
|
||||
|
||||
|
@ -1,590 +0,0 @@
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is Google Safe Browsing.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Google Inc.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2006
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Fritz Schneider <fritz@google.com> (original author)
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
// There is one BrowserView per browser window, and each BrowserView
|
||||
// is responsible for keeping track of problems (phishy documents)
|
||||
// within that window. The BrowserView is also responsible for
|
||||
// figuring out what to do about such problems, for example, whether
|
||||
// the tab with a phishy page is currently showing and therefore if we
|
||||
// should be showing a warning.
|
||||
//
|
||||
// The BrowserView receives information from three places:
|
||||
//
|
||||
// - from the phishing warden. When the phishing warden notices a
|
||||
// problem, it queries all browser views to see which one (if any)
|
||||
// has the Document that is problematic. It then hands the problem
|
||||
// off to the appropriate BrowserView.
|
||||
//
|
||||
// - from the controller. The controller responds to explicit user
|
||||
// actions (tab switches, requests to hide the warning message,
|
||||
// etc.) and let's the BrowserView know about any user action
|
||||
// having to do with the problems it is tracking.
|
||||
//
|
||||
// The BrowserView associates at most one "problem" with each Document
|
||||
// in the browser window. It keeps state about which Documents are
|
||||
// problematic by storing a "problem queue" on each browser (tab).
|
||||
// At most one problematic document per browser (tab) is active
|
||||
// at any time. That is, we show the warning for at most one phishy
|
||||
// document at any one time. If another phishy doc loads in that tab,
|
||||
// it goes onto the end of the queue to be activated only when the
|
||||
// currently active document goes away.
|
||||
//
|
||||
// If we had multiple types of warnings (one for after the page had
|
||||
// loaded, one for when the user clicked a link, etc) here's where
|
||||
// we'd select the appropate one to use. As it stands, we only have
|
||||
// one displayer (an "afterload" displayer). A displayer knows _how_
|
||||
// to display a warning, whereas as the BrowserView knows _what_ and
|
||||
// _when_.
|
||||
//
|
||||
// To keep things (relatively) easy to reason about and efficient (the
|
||||
// phishwarden could be querying us inside a progresslistener
|
||||
// notification, or the controller inside an event handler), we have
|
||||
// the following rules:
|
||||
//
|
||||
// - at most one of a displayer's start() or stop() methods is called
|
||||
// in any iteration (if calling two is required, the second is run in
|
||||
// the next event loop)
|
||||
// - displayers should run their operations synchronously so we don't have
|
||||
// to look two places (here and in the displayer) to see what is happening
|
||||
// when
|
||||
// - displayer actions are run after cleaning up the browser view state
|
||||
// in case they have consequences
|
||||
//
|
||||
// TODO: this could use some redesign, but I don't have time.
|
||||
// TODO: the queue needs to be abstracted, but we want another release fast,
|
||||
// so I'm not going to touch it for the time being
|
||||
// TODO: IDN issues and canonical URLs?
|
||||
// TODO: Perhaps we should blur the page before showing a warning in order
|
||||
// to prevent stray keystrokes?
|
||||
|
||||
/**
|
||||
* The BrowerView is responsible for keeping track of and figuring out
|
||||
* what to do with problems within a single browser window.
|
||||
*
|
||||
* TODO
|
||||
* Unify all browser-related state here. Currently it's split
|
||||
* between two objects, this object and the controller. We could have
|
||||
* this object be solely responsible for UI hide/show decisions, which
|
||||
* would probably make it easier to reason about what's going on.
|
||||
*
|
||||
* TODO
|
||||
* Investigate an alternative model. For example, we could factor out
|
||||
* the problem signaling stuff from the tab/UI logic into a
|
||||
* ProblemRegistry. Attach listeners to new docs/requests as they go
|
||||
* by and have these listeners periodically check in with a
|
||||
* ProblemRegistry to see if they're watching a problematic
|
||||
* doc/request. If so, then have them flag the browser view to be
|
||||
* aware of the problem.
|
||||
*
|
||||
* @constructor
|
||||
* @param tabBrowser Reference to the main tabbrowser we'll use to query
|
||||
* for information about active tabs/browsers.
|
||||
*/
|
||||
function PROT_BrowserView(tabBrowser) {
|
||||
this.debugZone = "browserview";
|
||||
this.tabBrowser_ = tabBrowser;
|
||||
this.doc_ = this.tabBrowser_.ownerDocument;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked by the warden to give us the opportunity to handle a
|
||||
* problem. A problem is signaled once per request for a problem
|
||||
* Document and is handled at most once, so there's no issue with us
|
||||
* "losing" a problem due to multiple concurrently loading Documents
|
||||
* with the same URL.
|
||||
*
|
||||
* @param warden Reference to the warden signalling the problem. We'll
|
||||
* need him to instantiate one of his warning displayers
|
||||
*
|
||||
* @param request The nsIRequest that is problematic
|
||||
*
|
||||
* @returns Boolean indicating whether we handled problem
|
||||
*/
|
||||
PROT_BrowserView.prototype.tryToHandleProblemRequest = function(warden,
|
||||
request) {
|
||||
// XXX: pass around the URL instead of the request. request.name isn't
|
||||
// really supposed to be used and isn't guaranteed to give the URL.
|
||||
var url = request.name;
|
||||
var browsers = this.tabBrowser_.browsers;
|
||||
for (var i = 0; i < browsers.length; i++) {
|
||||
var browser = browsers[i];
|
||||
var doc = browser.contentDocument;
|
||||
|
||||
// We only care about top level documents (and not about frames)
|
||||
if (doc.location.href == url && !this.getProblem_(doc, browser)) {
|
||||
this.isProblemDocument_(browser, doc, warden);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* We're sure a particular Document is problematic, so let's instantiate
|
||||
* a dispalyer for it and add it to the problem queue for the browser.
|
||||
*
|
||||
* @param browser Reference to the browser in which the problem doc resides
|
||||
*
|
||||
* @param doc Reference to the problematic document
|
||||
*
|
||||
* @param warden Reference to the warden signalling the problem.
|
||||
*/
|
||||
PROT_BrowserView.prototype.isProblemDocument_ = function(browser,
|
||||
doc,
|
||||
warden) {
|
||||
|
||||
G_Debug(this, "Document is problem: " + doc.location.href);
|
||||
|
||||
var url = doc.location.href;
|
||||
|
||||
// We only have one type of displayer right now
|
||||
var displayer = new warden.displayers_["afterload"]("Phishing afterload",
|
||||
browser,
|
||||
this.doc_,
|
||||
url);
|
||||
|
||||
// We listen for the problematic document being navigated away from
|
||||
// so we can remove it from the problem queue
|
||||
|
||||
var hideHandler = BindToObject(this.onNavAwayFromProblem_,
|
||||
this,
|
||||
doc,
|
||||
browser);
|
||||
doc.defaultView.addEventListener("pagehide", hideHandler, true);
|
||||
|
||||
// More info than we technically need, but it comes in handy for debugging
|
||||
var problem = {
|
||||
"browser_": browser,
|
||||
"doc_": doc,
|
||||
"displayer_": displayer,
|
||||
"url_": url,
|
||||
"hideHandler_": hideHandler,
|
||||
};
|
||||
var numInQueue = this.queueProblem_(browser, problem);
|
||||
|
||||
// If the queue was empty, schedule us to take something out
|
||||
if (numInQueue == 1)
|
||||
new G_Alarm(BindToObject(this.unqueueNextProblem_, this, browser), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked when a problematic document is navigated away from.
|
||||
*
|
||||
* @param doc Reference to the problematic Document navigated away from
|
||||
|
||||
* @param browser Reference to the browser in which the problem document
|
||||
* unloaded
|
||||
*/
|
||||
PROT_BrowserView.prototype.onNavAwayFromProblem_ = function(doc, browser) {
|
||||
|
||||
var problem = this.getProblem_(doc, browser);
|
||||
// We want to know if the user navigated away from the phish site
|
||||
// before or after viewing the warning.
|
||||
var message = problem.displayer_.messageShowing_ ? "phishnavaway"
|
||||
: "ignorenavaway";
|
||||
G_Debug(this, "User nav'd away from problem: " + message);
|
||||
(new PROT_Reporter).report(message, problem.url_);
|
||||
|
||||
G_Assert(this, doc === problem.doc_, "State doc not equal to nav away doc?");
|
||||
G_Assert(this, browser === problem.browser_,
|
||||
"State browser not equal to nav away browser?");
|
||||
|
||||
this.problemResolved(browser, doc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param browser Reference to a browser we'd like to know about
|
||||
*
|
||||
* @returns Boolean indicating if the browser in question has
|
||||
* problematic content
|
||||
*/
|
||||
PROT_BrowserView.prototype.hasProblem = function(browser) {
|
||||
return this.hasNonemptyProblemQueue_(browser);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param browser Reference to a browser we'd like to know about
|
||||
*
|
||||
* @returns Boolean indicating if the browser in question has a
|
||||
* problem (i.e., it has a non-empty problem queue)
|
||||
*/
|
||||
PROT_BrowserView.prototype.hasNonemptyProblemQueue_ = function(browser) {
|
||||
try {
|
||||
return !!browser.PROT_problemState__ &&
|
||||
!!browser.PROT_problemState__.length;
|
||||
} catch(e) {
|
||||
// We could be checking a browser that has just been closed, in
|
||||
// which case its properties will not be valid, causing the above
|
||||
// statement to throw an error. Since this case handled elsewhere,
|
||||
// just return false.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked to indicate that the problem for a particular problematic
|
||||
* document in a browser has been resolved (e.g., by being navigated
|
||||
* away from).
|
||||
*
|
||||
* @param browser Reference to the browser in which resolution is happening
|
||||
*
|
||||
* @param opt_doc Reference to the problematic doc whose problem was resolved
|
||||
* (if absent, assumes the doc assocaited with the currently
|
||||
* active displayer)
|
||||
*/
|
||||
PROT_BrowserView.prototype.problemResolved = function(browser, opt_doc) {
|
||||
var problem;
|
||||
var doc;
|
||||
if (!!opt_doc) {
|
||||
doc = opt_doc;
|
||||
problem = this.getProblem_(doc, browser);
|
||||
} else {
|
||||
problem = this.getCurrentProblem_(browser);
|
||||
doc = problem.doc_;
|
||||
}
|
||||
|
||||
problem.displayer_.done();
|
||||
var wasHead = this.deleteProblemFromQueue_(doc, browser);
|
||||
|
||||
// Peek at the next problem (if any) in the queue for this browser
|
||||
var queueNotEmpty = this.getCurrentProblem_(browser);
|
||||
|
||||
if (wasHead && queueNotEmpty) {
|
||||
G_Debug(this, "More problems pending. Scheduling unqueue.");
|
||||
new G_Alarm(BindToObject(this.unqueueNextProblem_, this, browser), 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Peek at the top of the problem queue and if there's something there,
|
||||
* make it active.
|
||||
*
|
||||
* @param browser Reference to the browser we should activate a problem
|
||||
* displayer in if one is available
|
||||
*/
|
||||
PROT_BrowserView.prototype.unqueueNextProblem_ = function(browser) {
|
||||
var problem = this.getCurrentProblem_(browser);
|
||||
if (!problem) {
|
||||
G_Debug(this, "No problem in queue; doc nav'd away from? (shrug)");
|
||||
return;
|
||||
}
|
||||
|
||||
// Two problem docs that load in rapid succession could both schedule
|
||||
// themselves to be unqueued before this method is called. So ensure
|
||||
// that the problem at the head of the queue is not, in fact, active.
|
||||
if (!problem.displayer_.isActive()) {
|
||||
|
||||
// It could be the case that the server is really slow to respond,
|
||||
// so there might not yet be anything in the problem Document. If
|
||||
// we show the warning when that's the case, the user will see a
|
||||
// blank document greyed out, and if they cancel the dialog
|
||||
// they'll see the page they're navigating away from because it
|
||||
// hasn't been painted over yet (b/c there's no content for the
|
||||
// problem page). So here we ensure that we have content for the
|
||||
// problem page before showing the dialog.
|
||||
var haveContent = false;
|
||||
try {
|
||||
// This will throw if there's no content yet
|
||||
var h = problem.doc_.defaultView.getComputedStyle(problem.doc_.body, "")
|
||||
.getPropertyValue("height");
|
||||
G_Debug(this, "body height: " + h);
|
||||
|
||||
if (Number(h.substring(0, h.length - 2)))
|
||||
haveContent = true;
|
||||
|
||||
} catch (e) {
|
||||
G_Debug(this, "Masked in unqueuenextproblem: " + e);
|
||||
}
|
||||
|
||||
if (!haveContent) {
|
||||
|
||||
G_Debug(this, "Didn't get computed style. Re-queueing.");
|
||||
|
||||
// One stuck problem document in a page shouldn't prevent us
|
||||
// warning on other problem frames that might be loading or
|
||||
// loaded. So stick the Document that doesn't have content
|
||||
// back at the end of the queue.
|
||||
var p = this.removeProblemFromQueue_(problem.doc_, browser);
|
||||
G_Assert(this, p === problem, "Unqueued wrong problem?");
|
||||
this.queueProblem_(browser, problem);
|
||||
|
||||
// Try again in a bit. This opens us up to a potential
|
||||
// vulnerability (put tons of hanging frames in a page
|
||||
// ahead of your real phishy frame), but the risk at the
|
||||
// moment is really low (plus it is outside our threat
|
||||
// model).
|
||||
new G_Alarm(BindToObject(this.unqueueNextProblem_,
|
||||
this,
|
||||
browser),
|
||||
200 /*ms*/);
|
||||
return;
|
||||
}
|
||||
|
||||
problem.displayer_.start();
|
||||
|
||||
// OK, we have content, but there there is an additional
|
||||
// issue. Due to a bfcache bug, if we show the warning during
|
||||
// paint suppression, the collapsing of the content pane affects
|
||||
// the doc we're naving from :( The symptom is a page with grey
|
||||
// screen on navigation to or from a phishing page (the
|
||||
// contentDocument will have width zero).
|
||||
//
|
||||
// Paint supression lasts at most 250ms from when the parser sees
|
||||
// the body, and the parser sees the body well before it has a
|
||||
// height. We err on the side of caution.
|
||||
//
|
||||
// Thanks to bryner for helping to track the bfcache bug down.
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=319646
|
||||
|
||||
if (this.tabBrowser_.selectedBrowser === browser)
|
||||
new G_Alarm(BindToObject(this.problemBrowserMaybeSelected,
|
||||
this,
|
||||
browser),
|
||||
350 /*ms*/);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function that adds a new problem to the queue of problems pending
|
||||
* on this browser.
|
||||
*
|
||||
* @param browser Browser to which we should add state
|
||||
*
|
||||
* @param problem Object (structure, really) encapsulating the problem
|
||||
*
|
||||
* @returns Number indicating the number of items in the queue (and from
|
||||
* which you can infer whether the recently added item was
|
||||
* placed at the head, and hence should be active.
|
||||
*/
|
||||
PROT_BrowserView.prototype.queueProblem_ = function(browser, problem) {
|
||||
G_Debug(this, "Adding problem state for " + problem.url_);
|
||||
|
||||
if (this.hasNonemptyProblemQueue_(browser))
|
||||
G_Debug(this, "Already has problem state. Queueing this problem...");
|
||||
|
||||
// First problem ever signaled on this browser? Make a new queue!
|
||||
if (browser.PROT_problemState__ == undefined)
|
||||
browser.PROT_problemState__ = [];
|
||||
|
||||
browser.PROT_problemState__.push(problem);
|
||||
return browser.PROT_problemState__.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function that removes a problem from the queue and deactivates
|
||||
* it.
|
||||
*
|
||||
* @param doc Reference to the doc for which we should remove state
|
||||
*
|
||||
* @param browser Reference to the browser from which we should remove
|
||||
* state
|
||||
*
|
||||
* @returns Boolean indicating if the remove problem was currently active
|
||||
* (that is, if it was at the head of the queue)
|
||||
*/
|
||||
PROT_BrowserView.prototype.deleteProblemFromQueue_ = function(doc, browser) {
|
||||
G_Debug(this, "Deleting problem state for " + browser);
|
||||
G_Assert(this, !!this.hasNonemptyProblemQueue_(browser),
|
||||
"Browser has no problem state");
|
||||
|
||||
var problem = this.getProblem_(doc, browser);
|
||||
G_Assert(this, !!problem, "Couldnt find state in removeproblemstate???");
|
||||
|
||||
var wasHead = browser.PROT_problemState__[0] === problem;
|
||||
this.removeProblemFromQueue_(doc, browser);
|
||||
|
||||
var hideHandler = problem.hideHandler_;
|
||||
G_Assert(this, !!hideHandler, "No hidehandler in state?");
|
||||
problem.doc_.defaultView.removeEventListener("pagehide",
|
||||
hideHandler,
|
||||
true);
|
||||
return wasHead;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function that removes a problem from the queue but does
|
||||
* NOT deactivate it.
|
||||
*
|
||||
* @param doc Reference to the doc for which we should remove state
|
||||
*
|
||||
* @param browser Reference to the browser from which we should remove
|
||||
* state
|
||||
*
|
||||
* @returns Boolean indicating if the remove problem was currently active
|
||||
* (that is, if it was at the head of the queue)
|
||||
*/
|
||||
PROT_BrowserView.prototype.removeProblemFromQueue_ = function(doc, browser) {
|
||||
G_Debug(this, "Removing problem state for " + browser);
|
||||
G_Assert(this, !!this.hasNonemptyProblemQueue_(browser),
|
||||
"Browser has no problem state");
|
||||
|
||||
var problem = null;
|
||||
// TODO Blech. Let's please have an abstraction here instead.
|
||||
for (var i = 0; i < browser.PROT_problemState__.length; i++)
|
||||
if (browser.PROT_problemState__[i].doc_ === doc) {
|
||||
problem = browser.PROT_problemState__.splice(i, 1)[0];
|
||||
break;
|
||||
}
|
||||
return problem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve (but do not remove) the problem state for a particular
|
||||
* problematic Document in this browser
|
||||
*
|
||||
* @param doc Reference to the problematic doc to get state for
|
||||
*
|
||||
* @param browser Reference to the browser from which to get state
|
||||
*
|
||||
* @returns Object encapsulating the state we stored, or null if none
|
||||
*/
|
||||
PROT_BrowserView.prototype.getProblem_ = function(doc, browser) {
|
||||
if (!this.hasNonemptyProblemQueue_(browser))
|
||||
return null;
|
||||
|
||||
// TODO Blech. Let's please have an abstraction here instead.
|
||||
for (var i = 0; i < browser.PROT_problemState__.length; i++)
|
||||
if (browser.PROT_problemState__[i].doc_ === doc)
|
||||
return browser.PROT_problemState__[i];
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the problem state for the currently active problem Document
|
||||
* in this browser
|
||||
*
|
||||
* @param browser Reference to the browser from which to get state
|
||||
*
|
||||
* @returns Object encapsulating the state we stored, or null if none
|
||||
*/
|
||||
PROT_BrowserView.prototype.getCurrentProblem_ = function(browser) {
|
||||
return browser.PROT_problemState__[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked by the controller when the user switches tabs away from a problem
|
||||
* tab.
|
||||
*
|
||||
* @param browser Reference to the tab that was switched from
|
||||
*/
|
||||
PROT_BrowserView.prototype.problemBrowserUnselected = function(browser) {
|
||||
var problem = this.getCurrentProblem_(browser);
|
||||
G_Assert(this, !!problem, "Couldn't get state from browser");
|
||||
problem.displayer_.browserUnselected();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if the problem browser is selected, and if so,
|
||||
* tell it it to show its warning.
|
||||
*
|
||||
* @param browser Reference to the browser we wish to check
|
||||
*/
|
||||
PROT_BrowserView.prototype.problemBrowserMaybeSelected = function(browser) {
|
||||
var problem = this.getCurrentProblem_(browser);
|
||||
|
||||
if (this.tabBrowser_.selectedBrowser === browser &&
|
||||
problem &&
|
||||
problem.displayer_.isActive())
|
||||
this.problemBrowserSelected(browser);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked by the controller when the user switches tabs to a problem tab
|
||||
*
|
||||
* @param browser Reference to the tab that was switched to
|
||||
*/
|
||||
PROT_BrowserView.prototype.problemBrowserSelected = function(browser) {
|
||||
G_Debug(this, "Problem browser selected");
|
||||
var problem = this.getCurrentProblem_(browser);
|
||||
G_Assert(this, !!problem, "No state? But we're selected!");
|
||||
problem.displayer_.browserSelected();
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked by the controller when the user accepts our warning. Passes
|
||||
* the accept through to the message displayer, which knows what to do
|
||||
* (it will be displayer-specific).
|
||||
*
|
||||
* @param browser Reference to the browser for which the user accepted
|
||||
* our warning
|
||||
*/
|
||||
PROT_BrowserView.prototype.acceptAction = function(browser) {
|
||||
var problem = this.getCurrentProblem_(browser);
|
||||
|
||||
// We run the action only after we're completely through processing
|
||||
// this event. We do this because the action could cause state to be
|
||||
// cleared (e.g., by navigating the problem document) that we need
|
||||
// to finish processing the event.
|
||||
|
||||
new G_Alarm(BindToObject(problem.displayer_.acceptAction,
|
||||
problem.displayer_),
|
||||
0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked by the controller when the user declines our
|
||||
* warning. Passes the decline through to the message displayer, which
|
||||
* knows what to do (it will be displayer-specific).
|
||||
*
|
||||
* @param browser Reference to the browser for which the user declined
|
||||
* our warning
|
||||
*/
|
||||
PROT_BrowserView.prototype.declineAction = function(browser) {
|
||||
var problem = this.getCurrentProblem_(browser);
|
||||
G_Assert(this, !!problem, "User declined but no state???");
|
||||
|
||||
// We run the action only after we're completely through processing
|
||||
// this event. We do this because the action could cause state to be
|
||||
// cleared (e.g., by navigating the problem document) that we need
|
||||
// to finish processing the event.
|
||||
|
||||
new G_Alarm(BindToObject(problem.displayer_.declineAction,
|
||||
problem.displayer_),
|
||||
0);
|
||||
}
|
||||
|
||||
/**
|
||||
* The user wants to see the warning message. So let em! At some point when
|
||||
* we have multiple types of warnings, we'll have to mediate them here.
|
||||
*
|
||||
* @param browser Reference to the browser that has the warning the user
|
||||
* wants to see.
|
||||
*/
|
||||
PROT_BrowserView.prototype.explicitShow = function(browser) {
|
||||
var problem = this.getCurrentProblem_(browser);
|
||||
G_Assert(this, !!problem, "Explicit show on browser w/o problem state???");
|
||||
problem.displayer_.explicitShow();
|
||||
}
|
@ -1,203 +0,0 @@
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is Google Safe Browsing.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Google Inc.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2006
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Fritz Schneider <fritz@google.com> (original author)
|
||||
# Simon Bünzli <zeniko@gmail.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
|
||||
// This is our controller -- the thingy that listens to what the user
|
||||
// is doing. There is one controller per browser window, and each has
|
||||
// a BrowserView that manages information about problems within the
|
||||
// window. The controller figures out when the browser might want to
|
||||
// know about something, but the browser view figures out what exactly
|
||||
// to do (and the BrowserView's displayer figures out how to do it).
|
||||
//
|
||||
// For example, the controller might notice that the user has switched
|
||||
// to a tab that has something problematic in it. It would tell its
|
||||
// BrowserView this, and the BrowserView would figure out whether it
|
||||
// is appropriate to show a warning (e.g., perhaps the user previously
|
||||
// dismissed the warning for that problem). If so, the BrowserView tells
|
||||
// the displayer to show the warning. Anyhoo...
|
||||
//
|
||||
// TODO Could move all browser-related hide/show logic into the browser
|
||||
// view. Need to think about this more.
|
||||
|
||||
/**
|
||||
* Handles user actions, translating them into messages to the view
|
||||
*
|
||||
* @constructor
|
||||
* @param win Reference to the Window (browser window context) we should
|
||||
* attach to
|
||||
* @param tabBrowser Reference to the window's main tabbrowser object.
|
||||
* @param phishingWarden Reference to the PhishingWarden we should register
|
||||
* our browserview with
|
||||
*/
|
||||
function PROT_Controller(win, tabBrowser, phishingWarden) {
|
||||
this.debugZone = "controller";
|
||||
|
||||
this.win_ = win;
|
||||
this.phishingWarden_ = phishingWarden;
|
||||
|
||||
// Use this to query preferences
|
||||
this.prefs_ = new G_Preferences();
|
||||
|
||||
// Set us up to receive the events we want.
|
||||
this.tabBrowser_ = tabBrowser;
|
||||
this.onTabSwitchClosure_ = BindToObject(this.onTabSwitch, this);
|
||||
this.tabBrowser_.mTabBox.addEventListener("select", this.onTabSwitchClosure_, true);
|
||||
|
||||
// Used to determine when the user has switched tabs
|
||||
this.lastTab_ = tabBrowser.selectedBrowser;
|
||||
|
||||
// Install our command controllers. These commands are issued from
|
||||
// various places in our UI, including our preferences dialog, the
|
||||
// warning dialog, etc.
|
||||
var commandHandlers = {
|
||||
"safebrowsing-show-warning" :
|
||||
BindToObject(this.onUserShowWarning, this),
|
||||
"safebrowsing-accept-warning" :
|
||||
BindToObject(this.onUserAcceptWarning, this),
|
||||
"safebrowsing-decline-warning" :
|
||||
BindToObject(this.onUserDeclineWarning, this),
|
||||
};
|
||||
|
||||
this.commandController_ = new PROT_CommandController(commandHandlers);
|
||||
this.win_.controllers.appendController(this.commandController_);
|
||||
|
||||
// This guy embodies the logic of when to display warnings
|
||||
// (displayers embody the how).
|
||||
this.browserView_ = new PROT_BrowserView(this.tabBrowser_);
|
||||
|
||||
G_Debug(this, "Controller initialized.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked when the browser window is closing. Do some cleanup.
|
||||
*/
|
||||
PROT_Controller.prototype.shutdown = function(e) {
|
||||
G_Debug(this, "Browser window closing. Shutting controller down.");
|
||||
|
||||
if (this.commandController_) {
|
||||
this.win_.controllers.removeController(this.commandController_);
|
||||
this.commandController_ = null;
|
||||
}
|
||||
|
||||
// No need to drain the browser view's problem queue explicitly; it will
|
||||
// receive pagehides for all the browsers in its queues as they're torn
|
||||
// down, and it will remove them.
|
||||
this.browserView_ = null;
|
||||
|
||||
if (this.tabBrowser_)
|
||||
this.tabBrowser_.mTabBox.removeEventListener("select", this.onTabSwitchClosure_, true);
|
||||
// Break circular refs so we can be gc'ed.
|
||||
this.tabBrowser_ = this.lastTab_ = null;
|
||||
|
||||
this.win_.removeEventListener("unload", this.onShutdown_, false);
|
||||
this.prefs_ = null;
|
||||
|
||||
G_Debug(this, "Controller shut down.");
|
||||
}
|
||||
|
||||
/**
|
||||
* The user clicked the urlbar icon; they want to see the warning message
|
||||
* again.
|
||||
*/
|
||||
PROT_Controller.prototype.onUserShowWarning = function() {
|
||||
var browser = this.tabBrowser_.selectedBrowser;
|
||||
this.browserView_.explicitShow(browser);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deal with a user accepting our warning.
|
||||
*
|
||||
* TODO the warning hide/display instructions here can probably be moved
|
||||
* into the browserview in the future, given its knowledge of when the
|
||||
* problem doc hides/shows.
|
||||
*/
|
||||
PROT_Controller.prototype.onUserAcceptWarning = function() {
|
||||
G_Debug(this, "User accepted warning.");
|
||||
var browser = this.tabBrowser_.selectedBrowser;
|
||||
G_Assert(this, !!browser, "Couldn't get current browser?!?");
|
||||
G_Assert(this, this.browserView_.hasProblem(browser),
|
||||
"User accept fired, but browser doesn't have warning showing?!?");
|
||||
|
||||
this.browserView_.acceptAction(browser);
|
||||
this.browserView_.problemResolved(browser);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deal with a user declining our warning.
|
||||
*
|
||||
* TODO the warning hide/display instructions here can probably be moved
|
||||
* into the browserview in the future, given its knowledge of when the
|
||||
* problem doc hides/shows.
|
||||
*/
|
||||
PROT_Controller.prototype.onUserDeclineWarning = function() {
|
||||
G_Debug(this, "User declined warning.");
|
||||
var browser = this.tabBrowser_.selectedBrowser;
|
||||
G_Assert(this, this.browserView_.hasProblem(browser),
|
||||
"User decline fired, but browser doesn't have warning showing?!?");
|
||||
this.browserView_.declineAction(browser);
|
||||
// We don't call problemResolved() here because all declining does it
|
||||
// hide the message; we still have the urlbar icon showing, giving
|
||||
// the user the ability to bring the warning message back up if they
|
||||
// so desire.
|
||||
}
|
||||
|
||||
/**
|
||||
* Notice tab switches, and display or hide warnings as appropriate.
|
||||
*
|
||||
* TODO this logic can probably move into the browser view at some
|
||||
* point. But one thing at a time.
|
||||
*/
|
||||
PROT_Controller.prototype.onTabSwitch = function(e) {
|
||||
// Filter spurious events
|
||||
// The event target is usually tabs but can be tabpanels when tabs were opened
|
||||
// programatically via tabbrowser.addTab().
|
||||
if (!e.target || (e.target.localName != "tabs" && e.target.localName != "tabpanels"))
|
||||
return;
|
||||
|
||||
var fromBrowser = this.lastTab_;
|
||||
var toBrowser = this.tabBrowser_.selectedBrowser;
|
||||
|
||||
if (fromBrowser != toBrowser) {
|
||||
this.lastTab_ = toBrowser;
|
||||
|
||||
if (this.browserView_.hasProblem(fromBrowser))
|
||||
this.browserView_.problemBrowserUnselected(fromBrowser);
|
||||
|
||||
if (this.browserView_.hasProblem(toBrowser))
|
||||
this.browserView_.problemBrowserSelected(toBrowser);
|
||||
}
|
||||
}
|
@ -1,83 +0,0 @@
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is Google Safe Browsing.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Google Inc.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2006
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Fritz Schneider <fritz@google.com> (original author)
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
|
||||
// Some misc command-related plumbing used by the controller.
|
||||
|
||||
|
||||
/**
|
||||
* A tiny wrapper class for super-simple command handlers.
|
||||
*
|
||||
* @param commandHandlerMap An object containing name/value pairs where
|
||||
* the name is command name (string) and value
|
||||
* is the function to execute for that command
|
||||
*/
|
||||
function PROT_CommandController(commandHandlerMap) {
|
||||
this.debugZone = "commandhandler";
|
||||
this.cmds_ = commandHandlerMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param cmd Command to query support for
|
||||
* @returns Boolean indicating if this controller supports cmd
|
||||
*/
|
||||
PROT_CommandController.prototype.supportsCommand = function(cmd) {
|
||||
return (cmd in this.cmds_);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trivial implementation
|
||||
*
|
||||
* @param cmd Command to query status of
|
||||
*/
|
||||
PROT_CommandController.prototype.isCommandEnabled = function(cmd) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a command
|
||||
*
|
||||
* @param cmd Command to execute
|
||||
*/
|
||||
PROT_CommandController.prototype.doCommand = function(cmd) {
|
||||
return this.cmds_[cmd]();
|
||||
}
|
||||
|
||||
/**
|
||||
* Trivial implementation
|
||||
*/
|
||||
PROT_CommandController.prototype.onEvent = function(cmd) { }
|
||||
|
@ -131,9 +131,13 @@ PROT_DataProvider.prototype.updateListManager_ = function() {
|
||||
listManager.setUpdateUrl(this.getUpdateURL());
|
||||
|
||||
// setKeyUrl has the side effect of fetching a key from the server.
|
||||
// This shouldn't happen if anti-phishing is disabled or we're in local
|
||||
// list mode, so we need to check for that.
|
||||
var isEnabled = this.prefs_.getPref(kPhishWardenEnabledPref, false);
|
||||
// This shouldn't happen if anti-phishing/anti-malware is disabled.
|
||||
var isEnabled = this.prefs_.getPref(kPhishWardenEnabledPref, false) ||
|
||||
this.prefs_.getPref(kMalwareWardenEnabledPref, false);
|
||||
if (isEnabled) {
|
||||
listManager.setKeyUrl(this.keyURL_);
|
||||
}
|
||||
|
||||
listManager.setGethashUrl(this.getGethashURL());
|
||||
}
|
||||
|
||||
|
@ -18,8 +18,7 @@
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Niels Provos <niels@google.com> (original author)d
|
||||
|
||||
# Niels Provos <niels@google.com> (original author)
|
||||
# Fritz Schneider <fritz@google.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
|
@ -89,8 +89,8 @@ function PROT_MalwareWarden() {
|
||||
};
|
||||
|
||||
try {
|
||||
dbService_.beginUpdate(listener);
|
||||
dbService_.beginStream("");
|
||||
dbService_.beginUpdate(listener, "");
|
||||
dbService_.beginStream("", "");
|
||||
dbService_.updateStream(testUpdate);
|
||||
dbService_.finishStream();
|
||||
dbService_.finishUpdate();
|
||||
|
@ -1,716 +0,0 @@
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is Google Safe Browsing.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Google Inc.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2006
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Fritz Schneider <fritz@google.com> (original author)
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
|
||||
// Implementation of the warning message we show users when we
|
||||
// notice navigation to a phishing page after it has loaded. The
|
||||
// browser view encapsulates all the hide/show logic, so the displayer
|
||||
// doesn't need to know when to display itself, only how.
|
||||
//
|
||||
// Displayers implement the following interface:
|
||||
//
|
||||
// start() -- fired to initialize the displayer (to make it active). When
|
||||
// called, this displayer starts listening for and responding to
|
||||
// events. At most one displayer per tab should be active at a
|
||||
// time, and start() should be called at most once.
|
||||
// declineAction() -- fired when the user declines the warning.
|
||||
// acceptAction() -- fired when the user declines the warning
|
||||
// explicitShow() -- fired when the user wants to see the warning again
|
||||
// browserSelected() -- the browser is the top tab
|
||||
// browserUnselected() -- the browser is no long the top tab
|
||||
// done() -- clean up. May be called once (even if the displayer wasn't
|
||||
// activated).
|
||||
//
|
||||
// At the moment, all displayers share access to the same xul in
|
||||
// safebrowsing-overlay.xul. Hence the need for at most one displayer
|
||||
// to be active per tab at a time.
|
||||
|
||||
/**
|
||||
* Factory that knows how to create a displayer appropriate to the
|
||||
* user's platform. We use a clunky canvas-based displayer for all
|
||||
* platforms until such time as we can overlay semi-transparent
|
||||
* areas over browser content.
|
||||
*
|
||||
* See the base object for a description of the constructor args
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function PROT_PhishMsgDisplayer(msgDesc, browser, doc, url) {
|
||||
|
||||
// TODO: Change this to return a PhishMsgDisplayerTransp on windows
|
||||
// (and maybe other platforms) when Firefox 2.0 hits.
|
||||
|
||||
return new PROT_PhishMsgDisplayerCanvas(msgDesc, browser, doc, url);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Base class that implements most of the plumbing required to hide
|
||||
* and show a phishing warning. Subclasses implement the actual
|
||||
* showMessage and hideMessage methods.
|
||||
*
|
||||
* This class is not meant to be instantiated directly.
|
||||
*
|
||||
* @param msgDesc String describing the kind of warning this is
|
||||
* @param browser Reference to the browser over which we display the msg
|
||||
* @param doc Reference to the document in which browser is found
|
||||
* @param url String containing url of the problem document
|
||||
* @constructor
|
||||
*/
|
||||
function PROT_PhishMsgDisplayerBase(msgDesc, browser, doc, url) {
|
||||
this.debugZone = "phishdisplayer";
|
||||
this.msgDesc_ = msgDesc; // currently unused
|
||||
this.browser_ = browser;
|
||||
this.doc_ = doc;
|
||||
this.url_ = url;
|
||||
|
||||
// We'll need to manipulate the XUL in safebrowsing-overlay.xul
|
||||
this.messageId_ = "safebrowsing-palm-message";
|
||||
this.messageTailId_ = "safebrowsing-palm-message-tail-container";
|
||||
this.messageContentId_ = "safebrowsing-palm-message-content";
|
||||
this.extendedMessageId_ = "safebrowsing-palm-extended-message";
|
||||
this.showmoreLinkId_ = "safebrowsing-palm-showmore-link";
|
||||
this.faqLinkId_ = "safebrowsing-palm-faq-link";
|
||||
this.urlbarIconId_ = "safebrowsing-urlbar-icon";
|
||||
this.refElementId_ = this.urlbarIconId_;
|
||||
|
||||
// We use this to report user actions to the server
|
||||
this.reporter_ = new PROT_Reporter();
|
||||
|
||||
// The active UI elements in our warning send these commands; bind them
|
||||
// to their handlers but don't register the commands until we start
|
||||
// (because another displayer might be active)
|
||||
this.commandHandlers_ = {
|
||||
"safebrowsing-palm-showmore":
|
||||
BindToObject(this.showMore_, this),
|
||||
};
|
||||
|
||||
this.windowWatcher_ =
|
||||
Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
|
||||
.getService(Components.interfaces.nsIWindowWatcher);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns The default background color of the browser
|
||||
*/
|
||||
PROT_PhishMsgDisplayerBase.prototype.getBackgroundColor_ = function() {
|
||||
var pref = Components.classes["@mozilla.org/preferences-service;1"].
|
||||
getService(Components.interfaces.nsIPrefBranch);
|
||||
return pref.getCharPref("browser.display.background_color");
|
||||
}
|
||||
|
||||
/**
|
||||
* Fired when the user declines our warning. Report it!
|
||||
*/
|
||||
PROT_PhishMsgDisplayerBase.prototype.declineAction = function() {
|
||||
G_Debug(this, "User declined warning.");
|
||||
G_Assert(this, this.started_, "Decline on a non-active displayer?");
|
||||
this.reporter_.report("phishdecline", this.url_);
|
||||
|
||||
this.messageShouldShow_ = false;
|
||||
if (this.messageShowing_)
|
||||
this.hideMessage_();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fired when the user accepts our warning
|
||||
*/
|
||||
PROT_PhishMsgDisplayerBase.prototype.acceptAction = function() {
|
||||
G_Assert(this, this.started_, "Accept on an unstarted displayer?");
|
||||
G_Assert(this, this.done_, "Accept on a finished displayer?");
|
||||
G_Debug(this, "User accepted warning.");
|
||||
this.reporter_.report("phishaccept", this.url_);
|
||||
|
||||
var url = this.getMeOutOfHereUrl_();
|
||||
this.browser_.loadURI(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the url for "Get me out of here." This is the browser's default home
|
||||
* page, or, about:blank.
|
||||
* @return String url
|
||||
*/
|
||||
PROT_PhishMsgDisplayerBase.prototype.getMeOutOfHereUrl_ = function() {
|
||||
// Try to get their homepage from prefs.
|
||||
var prefs = Cc["@mozilla.org/preferences-service;1"]
|
||||
.getService(Ci.nsIPrefService).getDefaultBranch(null);
|
||||
|
||||
var url = "about:blank";
|
||||
try {
|
||||
url = prefs.getComplexValue("browser.startup.homepage",
|
||||
Ci.nsIPrefLocalizedString).data;
|
||||
// If url is a pipe-delimited set of pages, just take the first one.
|
||||
// This will need to change once bug 221445 is fixed.
|
||||
if (url.indexOf("|") != -1)
|
||||
url = url.split("|")[0];
|
||||
} catch(e) {
|
||||
G_Debug(this, "Couldn't get homepage pref: " + e);
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked when the browser is resized
|
||||
*/
|
||||
PROT_PhishMsgDisplayerBase.prototype.onBrowserResized_ = function(event) {
|
||||
G_Debug(this, "Got resize for " + event.target);
|
||||
|
||||
if (this.messageShowing_) {
|
||||
this.hideMessage_();
|
||||
this.showMessage_();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked by the browser view when our browser is switched to
|
||||
*/
|
||||
PROT_PhishMsgDisplayerBase.prototype.browserSelected = function() {
|
||||
G_Assert(this, this.started_, "Displayer selected before being started???");
|
||||
|
||||
// If messageshowing hasn't been set, then this is the first time this
|
||||
// problematic browser tab has been on top, so do our setup and show
|
||||
// the warning.
|
||||
if (this.messageShowing_ === undefined) {
|
||||
this.messageShouldShow_ = true;
|
||||
}
|
||||
|
||||
this.addWarningInUrlbar_(); // Goes away when we are unselected or unloaded
|
||||
|
||||
// messageShouldShow might be false if the user dismissed the warning,
|
||||
// switched tabs, and then switched back. We're still active, but don't
|
||||
// want to show the warning again. The user can cause it to show by
|
||||
// clicking our icon in the urlbar.
|
||||
if (this.messageShouldShow_)
|
||||
this.showMessage_();
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked to display the warning message explicitly, for example if the user
|
||||
* clicked the url warning icon.
|
||||
*/
|
||||
PROT_PhishMsgDisplayerBase.prototype.explicitShow = function() {
|
||||
this.messageShouldShow_ = true;
|
||||
if (!this.messageShowing_)
|
||||
this.showMessage_();
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked by the browser view when our browser is switched away from
|
||||
*/
|
||||
PROT_PhishMsgDisplayerBase.prototype.browserUnselected = function() {
|
||||
this.removeWarningInUrlbar_();
|
||||
if (this.messageShowing_)
|
||||
this.hideMessage_();
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked to make this displayer active. The displayer will now start
|
||||
* responding to notifications such as commands and resize events. We
|
||||
* can't do this in the constructor because there might be many
|
||||
* displayers instantiated waiting in the problem queue for a particular
|
||||
* browser (e.g., a page has multiple framed problem pages), and we
|
||||
* don't want them all responding to commands!
|
||||
*
|
||||
* Invoked zero (the page we're a warning for was nav'd away from
|
||||
* before it reaches the head of the problem queue) or one (we're
|
||||
* displaying this warning) times by the browser view.
|
||||
*/
|
||||
PROT_PhishMsgDisplayerBase.prototype.start = function() {
|
||||
G_Assert(this, this.started_ == undefined, "Displayer started twice?");
|
||||
this.started_ = true;
|
||||
|
||||
this.commandController_ = new PROT_CommandController(this.commandHandlers_);
|
||||
this.doc_.defaultView.controllers.appendController(this.commandController_);
|
||||
|
||||
// Add an event listener for when the browser resizes (e.g., user
|
||||
// shows/hides the sidebar).
|
||||
this.resizeHandler_ = BindToObject(this.onBrowserResized_, this);
|
||||
this.browser_.addEventListener("resize",
|
||||
this.resizeHandler_,
|
||||
false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns Boolean indicating whether this displayer is currently
|
||||
* active
|
||||
*/
|
||||
PROT_PhishMsgDisplayerBase.prototype.isActive = function() {
|
||||
return !!this.started_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked by the browser view to clean up after the user is done
|
||||
* interacting with the message. Should be called once by the browser
|
||||
* view.
|
||||
*/
|
||||
PROT_PhishMsgDisplayerBase.prototype.done = function() {
|
||||
G_Assert(this, !this.done_, "Called done more than once?");
|
||||
this.done_ = true;
|
||||
|
||||
// If the Document we're showing the warning for was nav'd away from
|
||||
// before we had a chance to get started, we have nothing to do.
|
||||
if (this.started_) {
|
||||
|
||||
// If we were started, we must be the current problem, so these things
|
||||
// must be showing
|
||||
this.removeWarningInUrlbar_();
|
||||
|
||||
// Could be though that they've closed the warning dialog
|
||||
if (this.messageShowing_)
|
||||
this.hideMessage_();
|
||||
|
||||
if (this.resizeHandler_) {
|
||||
this.browser_.removeEventListener("resize",
|
||||
this.resizeHandler_,
|
||||
false);
|
||||
this.resizeHandler_ = null;
|
||||
}
|
||||
|
||||
var win = this.doc_.defaultView;
|
||||
win.controllers.removeController(this.commandController_);
|
||||
this.commandController_ = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to remove a substring from inside a string.
|
||||
*
|
||||
* @param orig String to remove substring from
|
||||
*
|
||||
* @param toRemove String to remove (if it is present)
|
||||
*
|
||||
* @returns String with the substring removed
|
||||
*/
|
||||
PROT_PhishMsgDisplayerBase.prototype.removeIfExists_ = function(orig,
|
||||
toRemove) {
|
||||
var pos = orig.indexOf(toRemove);
|
||||
if (pos != -1)
|
||||
orig = orig.substring(0, pos) + orig.substring(pos + toRemove.length);
|
||||
|
||||
return orig;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method makes our warning icon visible in the location bar. It will
|
||||
* be removed only when the problematic document is navigated awy from
|
||||
* (i.e., when done() is called), and not when the warning is dismissed.
|
||||
*/
|
||||
PROT_PhishMsgDisplayerBase.prototype.addWarningInUrlbar_ = function() {
|
||||
var urlbarIcon = this.doc_.getElementById(this.urlbarIconId_);
|
||||
if (!urlbarIcon)
|
||||
return;
|
||||
urlbarIcon.setAttribute('level', 'warn');
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides our urlbar icon
|
||||
*/
|
||||
PROT_PhishMsgDisplayerBase.prototype.removeWarningInUrlbar_ = function() {
|
||||
var urlbarIcon = this.doc_.getElementById(this.urlbarIconId_);
|
||||
if (!urlbarIcon)
|
||||
return;
|
||||
urlbarIcon.setAttribute('level', 'safe');
|
||||
}
|
||||
|
||||
/**
|
||||
* VIRTUAL -- Displays the warning message
|
||||
*/
|
||||
PROT_PhishMsgDisplayerBase.prototype.showMessage_ = function() { };
|
||||
|
||||
/**
|
||||
* VIRTUAL -- Hide the warning message from the user.
|
||||
*/
|
||||
PROT_PhishMsgDisplayerBase.prototype.hideMessage_ = function() { };
|
||||
|
||||
/**
|
||||
* Reposition the message relative to refElement in the parent window
|
||||
*
|
||||
* @param message Reference to the element to position
|
||||
* @param tail Reference to the message tail
|
||||
* @param refElement Reference to element relative to which we position
|
||||
* ourselves
|
||||
*/
|
||||
PROT_PhishMsgDisplayerBase.prototype.adjustLocation_ = function(message,
|
||||
tail,
|
||||
refElement) {
|
||||
var refX = refElement.boxObject.x;
|
||||
var refY = refElement.boxObject.y;
|
||||
var refHeight = refElement.boxObject.height;
|
||||
var refWidth = refElement.boxObject.width;
|
||||
G_Debug(this, "Ref element is at [window-relative] (" + refX + ", " +
|
||||
refY + ")");
|
||||
|
||||
var pixelsIntoRefY = -2;
|
||||
var tailY = refY + refHeight - pixelsIntoRefY;
|
||||
var tailPixelsLeftOfRefX = tail.boxObject.width;
|
||||
var tailPixelsIntoRefX = Math.round(refWidth / 2);
|
||||
var tailX = refX - tailPixelsLeftOfRefX + tailPixelsIntoRefX;
|
||||
|
||||
// Move message up a couple pixels so the tail overlaps it.
|
||||
var messageY = tailY + tail.boxObject.height - 2;
|
||||
var messagePixelsLeftOfRefX = 375;
|
||||
var messageX = refX - messagePixelsLeftOfRefX;
|
||||
G_Debug(this, "Message is at [window-relative] (" + messageX + ", " +
|
||||
messageY + ")");
|
||||
G_Debug(this, "Tail is at [window-relative] (" + tailX + ", " +
|
||||
tailY + ")");
|
||||
|
||||
if (messageX < 0) {
|
||||
// We're hanging off the left edge, switch to floating mode
|
||||
tail.style.display = "none";
|
||||
this.adjustLocationFloating_(message);
|
||||
return;
|
||||
}
|
||||
|
||||
tail.style.top = tailY + "px";
|
||||
tail.style.left = tailX + "px";
|
||||
message.style.top = messageY + "px";
|
||||
message.style.left = messageX + "px";
|
||||
|
||||
this.maybeAddScrollbars_();
|
||||
}
|
||||
|
||||
/**
|
||||
* Position the warning bubble with no reference element. In this case we
|
||||
* just center the warning bubble at the top of the users window.
|
||||
* @param message XULElement message bubble XUL container.
|
||||
*/
|
||||
PROT_PhishMsgDisplayerBase.prototype.adjustLocationFloating_ = function(message) {
|
||||
// Compute X offset
|
||||
var browserX = this.browser_.boxObject.x;
|
||||
var browserXCenter = browserX + this.browser_.boxObject.width / 2;
|
||||
var messageX = browserXCenter - (message.boxObject.width / 2);
|
||||
|
||||
// Compute Y offset (top of the browser window)
|
||||
var messageY = this.browser_.boxObject.y;
|
||||
|
||||
// Position message
|
||||
message.style.top = messageY + "px";
|
||||
message.style.left = messageX + "px";
|
||||
|
||||
this.maybeAddScrollbars_();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a vertical scrollbar if we're falling out of the browser window.
|
||||
*/
|
||||
PROT_PhishMsgDisplayerBase.prototype.maybeAddScrollbars_ = function() {
|
||||
var message = this.doc_.getElementById(this.messageId_);
|
||||
|
||||
var content = this.doc_.getElementById(this.messageContentId_);
|
||||
var bottom = content.boxObject.y + content.boxObject.height;
|
||||
var maxY = this.doc_.defaultView.innerHeight;
|
||||
G_Debug(this, "bottom: " + bottom + ", maxY: " + maxY
|
||||
+ ", new height: " + (maxY - content.boxObject.y));
|
||||
if (bottom > maxY) {
|
||||
var newHeight = maxY - content.boxObject.y;
|
||||
if (newHeight < 1)
|
||||
newHeight = 1;
|
||||
|
||||
content.style.height = newHeight + "px";
|
||||
content.style.overflow = "auto";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the extended warning message
|
||||
*/
|
||||
PROT_PhishMsgDisplayerBase.prototype.showMore_ = function() {
|
||||
this.doc_.getElementById(this.extendedMessageId_).hidden = false;
|
||||
this.doc_.getElementById(this.showmoreLinkId_).style.display = "none";
|
||||
|
||||
// set FAQ URL
|
||||
var formatter = Components.classes["@mozilla.org/toolkit/URLFormatterService;1"]
|
||||
.getService(Components.interfaces.nsIURLFormatter);
|
||||
var faqURL = formatter.formatURLPref("browser.safebrowsing.warning.infoURL");
|
||||
var labelEl = this.doc_.getElementById(this.faqLinkId_);
|
||||
labelEl.setAttribute("href", faqURL);
|
||||
|
||||
this.maybeAddScrollbars_();
|
||||
}
|
||||
|
||||
/**
|
||||
* The user clicked on one of the links in the buble. Display the
|
||||
* corresponding page in a new window with all the chrome enabled.
|
||||
*
|
||||
* @param url The URL to display in a new window
|
||||
*/
|
||||
PROT_PhishMsgDisplayerBase.prototype.showURL_ = function(url) {
|
||||
this.windowWatcher_.openWindow(this.windowWatcher_.activeWindow,
|
||||
url,
|
||||
"_blank",
|
||||
null,
|
||||
null);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the warning bubble came up in error, this url goes to a form
|
||||
* to notify the data provider.
|
||||
* @return url String
|
||||
*/
|
||||
PROT_PhishMsgDisplayerBase.prototype.getReportErrorURL_ = function() {
|
||||
var badUrl = this.url_;
|
||||
|
||||
var url = gDataProvider.getReportErrorURL();
|
||||
url += "&url=" + encodeURIComponent(badUrl);
|
||||
return url;
|
||||
}
|
||||
|
||||
/**
|
||||
* URL for the user to report back to us. This is to provide the user
|
||||
* with an action after being warned.
|
||||
*/
|
||||
PROT_PhishMsgDisplayerBase.prototype.getReportGenericURL_ = function() {
|
||||
var badUrl = this.url_;
|
||||
|
||||
var url = gDataProvider.getReportGenericURL();
|
||||
url += "&url=" + encodeURIComponent(badUrl);
|
||||
return url;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A specific implementation of the dislpayer using a canvas. This
|
||||
* class is meant for use on platforms that don't support transparent
|
||||
* elements over browser content (currently: all platforms).
|
||||
*
|
||||
* The main ugliness is the fact that we're hiding the content area and
|
||||
* painting the page to canvas. As a result, we must periodically
|
||||
* re-paint the canvas to reflect updates to the page. Otherwise if
|
||||
* the page was half-loaded when we showed our warning, it would
|
||||
* stay that way even though the page actually finished loading.
|
||||
*
|
||||
* See base constructor for full details of constructor args.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function PROT_PhishMsgDisplayerCanvas(msgDesc, browser, doc, url) {
|
||||
PROT_PhishMsgDisplayerBase.call(this, msgDesc, browser, doc, url);
|
||||
|
||||
this.dimAreaId_ = "safebrowsing-dim-area-canvas";
|
||||
this.pageCanvasId_ = "safebrowsing-page-canvas";
|
||||
this.xhtmlNS_ = "http://www.w3.org/1999/xhtml"; // we create html:canvas
|
||||
}
|
||||
|
||||
PROT_PhishMsgDisplayerCanvas.inherits(PROT_PhishMsgDisplayerBase);
|
||||
|
||||
/**
|
||||
* Displays the warning message. First we make sure the overlay is loaded
|
||||
* then call showMessageAfterOverlay_.
|
||||
*/
|
||||
PROT_PhishMsgDisplayerCanvas.prototype.showMessage_ = function() { }
|
||||
|
||||
/**
|
||||
* This does the actual work of showing the warning message.
|
||||
*/
|
||||
PROT_PhishMsgDisplayerCanvas.prototype.showMessageAfterOverlay_ = function() {
|
||||
this.messageShowing_ = true;
|
||||
|
||||
// Position the canvas overlay. Order here is significant, but don't ask me
|
||||
// why for some of these. You need to:
|
||||
// 1. get browser dimensions
|
||||
// 2. add canvas to the document
|
||||
// 3. unhide the dimmer (gray out overlay)
|
||||
// 4. display to the canvas
|
||||
// 5. unhide the warning message
|
||||
// 6. update link targets in warning message
|
||||
// 7. focus the warning message
|
||||
|
||||
// (1)
|
||||
var w = this.browser_.boxObject.width;
|
||||
G_Debug(this, "browser w=" + w);
|
||||
var h = this.browser_.boxObject.height;
|
||||
G_Debug(this, "browser h=" + h);
|
||||
var x = this.browser_.boxObject.x;
|
||||
G_Debug(this, "browser x=" + w);
|
||||
var y = this.browser_.boxObject.y;
|
||||
G_Debug(this, "browser y=" + h);
|
||||
|
||||
var win = this.browser_.contentWindow;
|
||||
var scrollX = win.scrollX;
|
||||
G_Debug(this, "win scrollx=" + scrollX);
|
||||
var scrollY = win.scrollY;
|
||||
G_Debug(this, "win scrolly=" + scrollY);
|
||||
|
||||
// (2)
|
||||
// We add the canvas dynamically and remove it when we're done because
|
||||
// leaving it hanging around consumes a lot of memory.
|
||||
var pageCanvas = this.doc_.createElementNS(this.xhtmlNS_, "html:canvas");
|
||||
pageCanvas.id = this.pageCanvasId_;
|
||||
pageCanvas.style.left = x + 'px';
|
||||
pageCanvas.style.top = y + 'px';
|
||||
|
||||
var dimarea = this.doc_.getElementById(this.dimAreaId_);
|
||||
this.doc_.getElementById('main-window').insertBefore(pageCanvas,
|
||||
dimarea);
|
||||
|
||||
// (3)
|
||||
dimarea.style.left = x + 'px';
|
||||
dimarea.style.top = y + 'px';
|
||||
dimarea.style.width = w + 'px';
|
||||
dimarea.style.height = h + 'px';
|
||||
dimarea.hidden = false;
|
||||
|
||||
// (4)
|
||||
pageCanvas.setAttribute("width", w);
|
||||
pageCanvas.setAttribute("height", h);
|
||||
|
||||
var bgcolor = this.getBackgroundColor_();
|
||||
|
||||
var cx = pageCanvas.getContext("2d");
|
||||
cx.drawWindow(win, scrollX, scrollY, w, h, bgcolor);
|
||||
|
||||
// Now repaint the window every so often in case the content hasn't fully
|
||||
// loaded at this point.
|
||||
var debZone = this.debugZone;
|
||||
function repaint() {
|
||||
G_Debug(debZone, "Repainting canvas...");
|
||||
cx.drawWindow(win, scrollX, scrollY, w, h, bgcolor);
|
||||
};
|
||||
this.repainter_ = new PROT_PhishMsgCanvasRepainter(repaint);
|
||||
|
||||
// (5)
|
||||
this.showAndPositionWarning_();
|
||||
|
||||
// (6)
|
||||
var link = this.doc_.getElementById('safebrowsing-palm-falsepositive-link');
|
||||
link.href = this.getReportErrorURL_();
|
||||
|
||||
// (7)
|
||||
this.doc_.getElementById(this.messageContentId_).focus();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show and position the warning message. We position the waring message
|
||||
* relative to the icon in the url bar, but if the element doesn't exist,
|
||||
* (e.g., the user remove the url bar from her/his chrome), we anchor at the
|
||||
* top of the window.
|
||||
*/
|
||||
PROT_PhishMsgDisplayerCanvas.prototype.showAndPositionWarning_ = function() {
|
||||
var refElement = this.doc_.getElementById(this.refElementId_);
|
||||
var message = this.doc_.getElementById(this.messageId_);
|
||||
var tail = this.doc_.getElementById(this.messageTailId_);
|
||||
|
||||
message.hidden = false;
|
||||
message.style.display = "block";
|
||||
|
||||
// Determine if the refElement is visible.
|
||||
if (this.isVisibleElement_(refElement)) {
|
||||
// Show tail and position warning relative to refElement.
|
||||
tail.hidden = false;
|
||||
tail.style.display = "block";
|
||||
this.adjustLocation_(message, tail, refElement);
|
||||
} else {
|
||||
// No ref element, position in the top center of window.
|
||||
tail.hidden = true;
|
||||
tail.style.display = "none";
|
||||
this.adjustLocationFloating_(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Boolean true if elt is a visible XUL element.
|
||||
*/
|
||||
PROT_PhishMsgDisplayerCanvas.prototype.isVisibleElement_ = function(elt) {
|
||||
if (!elt)
|
||||
return false;
|
||||
|
||||
// If it's on a collapsed/hidden toolbar, the x position is set to 0.
|
||||
if (elt.boxObject.x == 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide the warning message from the user.
|
||||
*/
|
||||
PROT_PhishMsgDisplayerCanvas.prototype.hideMessage_ = function() { }
|
||||
|
||||
|
||||
/**
|
||||
* Helper class that periodically repaints the canvas. We repaint
|
||||
* frequently at first, and then back off to a less frequent schedule
|
||||
* at "steady state," and finally just stop altogether. We have to do
|
||||
* this because we're not sure if the page has finished loading when
|
||||
* we first paint the canvas, and because we want to reflect any
|
||||
* dynamically written content into the canvas as it appears in the
|
||||
* page after load.
|
||||
*
|
||||
* @param repaintFunc Function to call to repaint browser.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function PROT_PhishMsgCanvasRepainter(repaintFunc) {
|
||||
this.count_ = 0;
|
||||
this.repaintFunc_ = repaintFunc;
|
||||
this.initPeriodMS_ = 500; // Initially repaint every 500ms
|
||||
this.steadyStateAtMS_ = 10 * 1000; // Go slowly after 10 seconds,
|
||||
this.steadyStatePeriodMS_ = 3 * 1000; // repainting every 3 seconds, and
|
||||
this.quitAtMS_ = 20 * 1000; // stop after 20 seconds
|
||||
this.startMS_ = (new Date).getTime();
|
||||
this.alarm_ = new G_Alarm(BindToObject(this.repaint, this),
|
||||
this.initPeriodMS_);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called periodically to repaint the canvas
|
||||
*/
|
||||
PROT_PhishMsgCanvasRepainter.prototype.repaint = function() {
|
||||
this.repaintFunc_();
|
||||
|
||||
var nextRepaint;
|
||||
// If we're in "steady state", use the slow repaint rate, else fast
|
||||
if ((new Date).getTime() - this.startMS_ > this.steadyStateAtMS_)
|
||||
nextRepaint = this.steadyStatePeriodMS_;
|
||||
else
|
||||
nextRepaint = this.initPeriodMS_;
|
||||
|
||||
if (!((new Date).getTime() - this.startMS_ > this.quitAtMS_))
|
||||
this.alarm_ = new G_Alarm(BindToObject(this.repaint, this), nextRepaint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to stop repainting the canvas
|
||||
*/
|
||||
PROT_PhishMsgCanvasRepainter.prototype.cancel = function() {
|
||||
if (this.alarm_) {
|
||||
this.alarm_.cancel();
|
||||
this.alarm_ = null;
|
||||
}
|
||||
this.repaintFunc_ = null;
|
||||
}
|
@ -64,14 +64,6 @@
|
||||
|
||||
const kPhishWardenEnabledPref = "browser.safebrowsing.enabled";
|
||||
|
||||
// We have hardcoded URLs that we let people navigate to in order to
|
||||
// check out the warning.
|
||||
const kTestUrls = {
|
||||
"http://www.google.com/tools/firefox/safebrowsing/phish-o-rama.html": true,
|
||||
"http://www.mozilla.org/projects/bonecho/anti-phishing/its-a-trap.html": true,
|
||||
"http://www.mozilla.com/firefox/its-a-trap.html": true,
|
||||
}
|
||||
|
||||
/**
|
||||
* Abtracts the checking of user/browser actions for signs of
|
||||
* phishing.
|
||||
@ -84,8 +76,6 @@ function PROT_PhishingWarden() {
|
||||
PROT_ListWarden.call(this);
|
||||
|
||||
this.debugZone = "phishwarden";
|
||||
this.testing_ = false;
|
||||
this.browserViews_ = [];
|
||||
|
||||
// Use this to query preferences
|
||||
this.prefs_ = new G_Preferences();
|
||||
@ -106,9 +96,6 @@ function PROT_PhishingWarden() {
|
||||
|
||||
PROT_PhishingWarden.inherits(PROT_ListWarden);
|
||||
|
||||
/**
|
||||
* We implement nsIWebProgressListener
|
||||
*/
|
||||
PROT_PhishingWarden.prototype.QueryInterface = function(iid) {
|
||||
if (iid.equals(Ci.nsISupports) ||
|
||||
iid.equals(Ci.nsISupportsWeakReference))
|
||||
@ -136,9 +123,6 @@ PROT_PhishingWarden.prototype.shutdown = function() {
|
||||
* both, so eventually we will start correctly.
|
||||
*/
|
||||
PROT_PhishingWarden.prototype.maybeToggleUpdateChecking = function() {
|
||||
if (this.testing_)
|
||||
return;
|
||||
|
||||
var phishWardenEnabled = this.prefs_.getPref(kPhishWardenEnabledPref, null);
|
||||
|
||||
G_Debug(this, "Maybe toggling update checking. " +
|
||||
|
@ -1,55 +1,50 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- ***** BEGIN LICENSE BLOCK *****
|
||||
- Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
-
|
||||
- The contents of this file are subject to the Mozilla Public License Version
|
||||
- 1.1 (the "License"); you may not use this file except in compliance with
|
||||
- the License. You may obtain a copy of the License at
|
||||
- http://www.mozilla.org/MPL/
|
||||
-
|
||||
- Software distributed under the License is distributed on an "AS IS" basis,
|
||||
- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
- for the specific language governing rights and limitations under the
|
||||
- License.
|
||||
-
|
||||
- The Original Code is Mozilla Reporter (r.m.o).
|
||||
-
|
||||
- The Initial Developer of the Original Code is
|
||||
- Robert Accettura <robert@accettura.com>.
|
||||
-
|
||||
- Portions created by the Initial Developer are Copyright (C) 2004
|
||||
- the Initial Developer. All Rights Reserved.
|
||||
-
|
||||
- Contributor(s):
|
||||
- Jay Patel <jay@mozilla.org>
|
||||
- Gavin Sharp <gavin@gavinsharp.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 LGPL or the GPL. 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 ***** -->
|
||||
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is Mozilla Reporter (r.m.o).
|
||||
#
|
||||
# The Initial Developer of the Original Code is Robert Accettura <robert@accettura.com>.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2004
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Jay Patel <jay@mozilla.org>
|
||||
# Gavin Sharp <gavin@gavinsharp.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 *****
|
||||
<!DOCTYPE overlay [
|
||||
<!ENTITY % reportphishDTD SYSTEM "chrome://browser/locale/safebrowsing/report-phishing.dtd">
|
||||
%reportphishDTD;
|
||||
<!ENTITY % safebrowsingDTD SYSTEM "chrome://browser/locale/safebrowsing/phishing-afterload-warning-message.dtd">
|
||||
%safebrowsingDTD;
|
||||
]>
|
||||
|
||||
<overlay id="reportPhishingMenuOverlay"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<broadcasterset id="mainBroadcasterSet">
|
||||
<broadcaster id="reportPhishingBroadcaster" disabled="true"/>
|
||||
<broadcaster id="reportPhishingErrorBroadcaster" disabled="true"/>
|
||||
<!--<broadcaster id="reportPhishingErrorBroadcaster" disabled="true"/>-->
|
||||
</broadcasterset>
|
||||
<menupopup id="menu_HelpPopup">
|
||||
<menuitem id="menu_HelpPopup_reportPhishingtoolmenu"
|
||||
@ -59,12 +54,13 @@
|
||||
observes="reportPhishingBroadcaster"
|
||||
oncommand="openUILink(safebrowsing.getReportURL('Phish'), event);"
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
<!-- XXX Bug 415846
|
||||
<menuitem id="menu_HelpPopup_reportPhishingErrortoolmenu"
|
||||
label="&safeb.palm.notforgery.label;..."
|
||||
accesskey="&reportPhishSiteMenu.accesskey;"
|
||||
insertbefore="updateSeparator"
|
||||
observes="reportPhishingErrorBroadcaster"
|
||||
oncommand="openUILinkIn(safebrowsing.getReportURL('Error'), 'tab');"
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
onclick="checkForMiddleClick(this, event);"/>-->
|
||||
</menupopup>
|
||||
</overlay>
|
||||
|
@ -1,77 +0,0 @@
|
||||
# **** BEGIN LICENSE BLOCK ****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is Google Safe Browsing.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Google Inc.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2006
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Fritz Schneider <fritz@google.com> (original author)
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# **** END LICENSE BLOCK ****
|
||||
|
||||
|
||||
// A tiny class to do reporting for us. We report interesting user actions
|
||||
// such as the user hitting a blacklisted page, and the user accepting
|
||||
// or declining the warning.
|
||||
//
|
||||
// Each report has a subject and data. Current reports are:
|
||||
//
|
||||
// subject data meaning
|
||||
// --------------------------------
|
||||
// phishnavaway url the user navigated away from a phishy page
|
||||
// phishdecline url the user declined our warning
|
||||
// phishaccept url the user accepted our warning
|
||||
// phishblhit url the user loaded a phishing page
|
||||
//
|
||||
// We only send reports in advanced protection mode, and even then we
|
||||
// strip cookies from the request before sending it.
|
||||
|
||||
/**
|
||||
* A very complicated class to send pings to the provider. The class does
|
||||
* nothing if we're not in advanced protection mode.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function PROT_Reporter() {
|
||||
this.debugZone = "reporter";
|
||||
this.prefs_ = new G_Preferences();
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a report!
|
||||
*
|
||||
* @param subject String indicating what this report is about (will be
|
||||
* urlencoded)
|
||||
* @param data String giving extra information about this report (will be
|
||||
* urlencoded)
|
||||
*/
|
||||
PROT_Reporter.prototype.report = function(subject, data) {
|
||||
// XXX: this is disabled for now, since we don't have advanced mode
|
||||
// anymore.
|
||||
return;
|
||||
}
|
@ -34,108 +34,36 @@
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
|
||||
/**
|
||||
* This file is included into the main browser chrome from
|
||||
* browser/base/content/global-scripts.inc
|
||||
*/
|
||||
|
||||
var safebrowsing = {
|
||||
controller: null,
|
||||
phishWarden: null,
|
||||
appContext: null,
|
||||
|
||||
startup: function() {
|
||||
setTimeout(safebrowsing.deferredStartup, 2000);
|
||||
|
||||
// clean up
|
||||
window.removeEventListener("load", safebrowsing.startup, false);
|
||||
},
|
||||
|
||||
|
||||
deferredStartup: function() {
|
||||
var appContext = Cc["@mozilla.org/safebrowsing/application;1"]
|
||||
.getService().wrappedJSObject;
|
||||
|
||||
var malwareWarden = new appContext.PROT_MalwareWarden();
|
||||
safebrowsing.malwareWarden = malwareWarden;
|
||||
|
||||
// Register tables
|
||||
malwareWarden.registerBlackTable("goog-malware-shavar");
|
||||
|
||||
malwareWarden.maybeToggleUpdateChecking();
|
||||
|
||||
var phishWarden = new appContext.PROT_PhishingWarden();
|
||||
safebrowsing.phishWarden = phishWarden;
|
||||
|
||||
// Register tables
|
||||
// XXX: move table names to a pref that we originally will download
|
||||
// from the provider (need to workout protocol details)
|
||||
phishWarden.registerBlackTable("goog-phish-shavar");
|
||||
|
||||
// Download/update lists if we're in non-enhanced mode
|
||||
phishWarden.maybeToggleUpdateChecking();
|
||||
safebrowsing.controller = new appContext.PROT_Controller(
|
||||
window, getBrowser(), phishWarden);
|
||||
},
|
||||
|
||||
/**
|
||||
* Clean up.
|
||||
*/
|
||||
shutdown: function() {
|
||||
if (safebrowsing.controller) {
|
||||
// If the user shuts down before deferredStartup, there is no controller.
|
||||
safebrowsing.controller.shutdown();
|
||||
}
|
||||
if (safebrowsing.phishWarden) {
|
||||
safebrowsing.phishWarden.shutdown();
|
||||
}
|
||||
if (safebrowsing.malwareWarden) {
|
||||
safebrowsing.malwareWarden.shutdown();
|
||||
}
|
||||
|
||||
window.removeEventListener("unload", safebrowsing.shutdown, false);
|
||||
this.appContext = Cc["@mozilla.org/safebrowsing/application;1"].
|
||||
getService().wrappedJSObject;
|
||||
this.appContext.initialize();
|
||||
},
|
||||
|
||||
setReportPhishingMenu: function() {
|
||||
var uri = getBrowser().currentURI;
|
||||
if (!uri)
|
||||
return;
|
||||
|
||||
var sbIconElt = document.getElementById("safebrowsing-urlbar-icon");
|
||||
var helpMenuElt = document.getElementById("helpMenu");
|
||||
var phishLevel = sbIconElt.getAttribute("level");
|
||||
|
||||
// Show/hide the appropriate menu item.
|
||||
document.getElementById("menu_HelpPopup_reportPhishingtoolmenu")
|
||||
.hidden = ("safe" != phishLevel);
|
||||
document.getElementById("menu_HelpPopup_reportPhishingErrortoolmenu")
|
||||
.hidden = ("safe" == phishLevel);
|
||||
|
||||
var broadcasterId;
|
||||
if ("safe" == phishLevel) {
|
||||
broadcasterId = "reportPhishingBroadcaster";
|
||||
} else {
|
||||
broadcasterId = "reportPhishingErrorBroadcaster";
|
||||
}
|
||||
|
||||
var broadcaster = document.getElementById(broadcasterId);
|
||||
if (!broadcaster)
|
||||
return;
|
||||
|
||||
var progressListener =
|
||||
Cc["@mozilla.org/browser/safebrowsing/navstartlistener;1"]
|
||||
.createInstance(Ci.nsIDocNavStartProgressListener);
|
||||
broadcaster.setAttribute("disabled", progressListener.isSpurious(uri));
|
||||
var broadcaster = document.getElementById("reportPhishingBroadcaster");
|
||||
if (uri && (uri.schemeIs("http") || uri.schemeIs("https")))
|
||||
broadcaster.removeAttribute("disabled");
|
||||
else
|
||||
broadcaster.disabled = true;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Used to report a phishing page or a false positive
|
||||
* @param name String either "Phish" or "Error"
|
||||
* @return String the report phishing URL.
|
||||
*/
|
||||
getReportURL: function(name) {
|
||||
var appContext = Cc["@mozilla.org/safebrowsing/application;1"]
|
||||
.getService().wrappedJSObject;
|
||||
var reportUrl = appContext.getReportURL(name);
|
||||
var reportUrl = this.appContext.getReportURL(name);
|
||||
|
||||
var pageUrl = getBrowser().currentURI.asciiSpec;
|
||||
reportUrl += "&url=" + encodeURIComponent(pageUrl);
|
||||
@ -145,4 +73,3 @@ var safebrowsing = {
|
||||
}
|
||||
|
||||
window.addEventListener("load", safebrowsing.startup, false);
|
||||
window.addEventListener("unload", safebrowsing.shutdown, false);
|
||||
|
@ -1,116 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<!-- This css and dtd are for the phishing warning message -->
|
||||
|
||||
<?xml-stylesheet
|
||||
href="chrome://browser/skin/safebrowsing/browser-protection.css"
|
||||
type="text/css" ?>
|
||||
<!DOCTYPE window [
|
||||
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd" >
|
||||
%brandDTD;
|
||||
<!ENTITY % safebrowsingDTD SYSTEM "chrome://browser/locale/safebrowsing/phishing-afterload-warning-message.dtd">
|
||||
%safebrowsingDTD;
|
||||
]>
|
||||
|
||||
<overlay id="safebrowsing-overlay"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<window id="main-window">
|
||||
<!-- This is the spike aka tail on top of the warning -->
|
||||
|
||||
<hbox id="safebrowsing-palm-message-tail-container" hidden="true"
|
||||
pack="end">
|
||||
<image id="safebrowsing-palm-message-tail"
|
||||
src="chrome://browser/skin/safebrowsing/tail.png"/>
|
||||
</hbox>
|
||||
|
||||
<!-- This is the phishing afterload warning message -->
|
||||
|
||||
<vbox id="safebrowsing-palm-message" hidden="true" pack="center"
|
||||
class="safebrowsing-palm-fixed-width">
|
||||
|
||||
<!-- This is the main warning area -->
|
||||
|
||||
<vbox id="safebrowsing-palm-message-content"
|
||||
class="safebrowsing-palm-fixed-width"
|
||||
style="-moz-user-focus: normal"
|
||||
role="alert">
|
||||
|
||||
<hbox id="safebrowsing-palm-close-container" align="center"
|
||||
class="safebrowsing-palm-fixed-width">
|
||||
<spacer flex="1"/>
|
||||
<image id="safebrowsing-palm-close"
|
||||
onclick="goDoCommand('safebrowsing-decline-warning')"/>
|
||||
</hbox>
|
||||
|
||||
<!-- Top line -->
|
||||
<description id="safebrowsing-palm-message-titlebox"
|
||||
class="safebrowsing-palm-fixed-width">
|
||||
&safeb.palm.warning.title;
|
||||
</description>
|
||||
|
||||
<!-- Content area: short warning -->
|
||||
|
||||
<description id="safebrowsing-palm-content"
|
||||
class="safebrowsing-paragraph">
|
||||
&safeb.palm.message.p1;
|
||||
<label class="text-link plain"
|
||||
statustext="&safeb.palm.p1.linkStatusText;"
|
||||
id="safebrowsing-palm-showmore-link"
|
||||
onclick="goDoCommand('safebrowsing-palm-showmore'); document.getElementById('safebrowsing-palm-faq-link').focus()"
|
||||
value="&safeb.palm.message.p1.linkText;"/>
|
||||
</description>
|
||||
|
||||
<!-- Content area: rest of the warning, revealed if the user
|
||||
hits the more link -->
|
||||
|
||||
<vbox id="safebrowsing-palm-extended-message" hidden="true"
|
||||
class="safebrowsing-palm-fixed-width">
|
||||
<description class="safebrowsing-palm-paragraph">
|
||||
&safeb.palm.message.p2.start;
|
||||
<label class="text-link plain" id="safebrowsing-palm-faq-link"
|
||||
value="&safeb.palm.message.p2.linkText;"/>
|
||||
&safeb.palm.message.p2.end;
|
||||
</description>
|
||||
</vbox>
|
||||
|
||||
<!-- Main action links -->
|
||||
<description id="safebrowsing-palm-message-actionbox"
|
||||
class="safebrowsing-palm-fixed-width"
|
||||
align="center" crop="none">
|
||||
<label class="safebrowsing-palm-bigtext text-link plain"
|
||||
statustext="&safeb.palm.accept.statustext;"
|
||||
id="safebrowsing-palm-accept-link"
|
||||
onclick="goDoCommand('safebrowsing-accept-warning')"
|
||||
value="&safeb.palm.accept.label;"/>
|
||||
<spacer flex="1"/>
|
||||
<label class="safebrowsing-palm-bigtext text-link plain"
|
||||
statustext="&safeb.palm.decline.statustext;"
|
||||
id="safebrowsing-palm-decline-link"
|
||||
onclick="goDoCommand('safebrowsing-decline-warning')"
|
||||
value="&safeb.palm.decline.label;"/>
|
||||
</description>
|
||||
|
||||
<!-- Footer -->
|
||||
|
||||
<hbox align="center" class="safebrowsing-palm-fixed-width">
|
||||
<spacer flex="1"/>
|
||||
<description>
|
||||
[
|
||||
<label id="safebrowsing-palm-falsepositive-link"
|
||||
class="safebrowsing-palm-smalltext text-link plain"
|
||||
value="&safeb.palm.notforgery.label;"/>
|
||||
]
|
||||
</description>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</vbox>
|
||||
|
||||
<!-- The canvas goes here, but since it takes up so much memory and is
|
||||
rarely used, we add and remove it dynamically -->
|
||||
|
||||
<!-- This dims out the browser content -->
|
||||
<vbox id="safebrowsing-dim-area-canvas" hidden="true">
|
||||
</vbox>
|
||||
</window>
|
||||
</overlay>
|
@ -1,7 +1,5 @@
|
||||
browser.jar:
|
||||
# script file included into main browser.js
|
||||
* content/browser/safebrowsing/sb-loader.js (content/sb-loader.js)
|
||||
+ content/browser/safebrowsing/warning-overlay.xul (content/warning-overlay.xul)
|
||||
+ content/browser/safebrowsing/report-phishing-overlay.xul (content/report-phishing-overlay.xul)
|
||||
+ content/browser/safebrowsing/blockedSite.xhtml (content/blockedSite.xhtml)
|
||||
* content/browser/safebrowsing/report-phishing-overlay.xul (content/report-phishing-overlay.xul)
|
||||
content/browser/safebrowsing/blockedSite.xhtml (content/blockedSite.xhtml)
|
||||
% overlay chrome://browser/content/browser.xul chrome://browser/content/safebrowsing/report-phishing-overlay.xul
|
||||
|
@ -1,50 +0,0 @@
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Google Inc.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2006
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Brett Wilson <brettw@gmail.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
|
||||
DEPTH = ../../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = safebrowsing
|
||||
XPIDL_MODULE = safebrowsing
|
||||
|
||||
XPIDLSRCS = nsIDocNavStartProgressListener.idl
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
@ -41,18 +41,4 @@ VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = safebrowsing
|
||||
LIBRARY_NAME = safebrowsing_s
|
||||
FORCE_STATIC_LIB = 1
|
||||
FORCE_USE_PIC = 1
|
||||
USE_STATIC_LIBS = 1
|
||||
|
||||
REQUIRES = \
|
||||
necko \
|
||||
string \
|
||||
uriloader \
|
||||
xpcom
|
||||
|
||||
CPPSRCS = nsDocNavStartProgressListener.cpp
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
@ -1,379 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Google Safe Browsing.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Google Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2006
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Brett Wilson <brettw@gmail.com>
|
||||
* based on JavaScript code by Fritz Schneider <fritz@google.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsCURILoader.h"
|
||||
#include "nsDocNavStartProgressListener.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsINestedURI.h"
|
||||
#include "nsIRequest.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsIWebProgress.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsStringAPI.h"
|
||||
#include "prlog.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS4(nsDocNavStartProgressListener,
|
||||
nsIDocNavStartProgressListener,
|
||||
nsIWebProgressListener,
|
||||
nsIObserver,
|
||||
nsISupportsWeakReference)
|
||||
|
||||
// NSPR_LOG_MODULES=DocNavStart:5
|
||||
#if defined(PR_LOGGING)
|
||||
static const PRLogModuleInfo *gDocNavStartProgressListenerLog = nsnull;
|
||||
#define LOG(args) PR_LOG(gDocNavStartProgressListenerLog, PR_LOG_DEBUG, args)
|
||||
#else
|
||||
#define LOG(args)
|
||||
#endif
|
||||
|
||||
nsDocNavStartProgressListener::nsDocNavStartProgressListener() :
|
||||
mEnabled(PR_FALSE), mDelay(0), mRequests(nsnull), mTimers(nsnull)
|
||||
{
|
||||
#if defined(PR_LOGGING)
|
||||
if (!gDocNavStartProgressListenerLog)
|
||||
gDocNavStartProgressListenerLog = PR_NewLogModule("DocNavStart");
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
nsDocNavStartProgressListener::~nsDocNavStartProgressListener()
|
||||
{
|
||||
ClearPendingEvents();
|
||||
}
|
||||
|
||||
void
|
||||
nsDocNavStartProgressListener::ClearPendingEvents()
|
||||
{
|
||||
mRequests.Clear();
|
||||
|
||||
PRUint32 length = mTimers.Count();
|
||||
for (PRUint32 i = 0; i < length; ++i) {
|
||||
mTimers[i]->Cancel();
|
||||
}
|
||||
mTimers.Clear();
|
||||
}
|
||||
|
||||
// nsDocNavStartProgressListener::AttachListeners
|
||||
|
||||
nsresult
|
||||
nsDocNavStartProgressListener::AttachListeners()
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIWebProgress> webProgressService = do_GetService(
|
||||
NS_DOCUMENTLOADER_SERVICE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return webProgressService->AddProgressListener(this,
|
||||
nsIWebProgress::NOTIFY_LOCATION);
|
||||
}
|
||||
|
||||
|
||||
// nsDocNavStartProgressListener::DetachListeners
|
||||
|
||||
nsresult
|
||||
nsDocNavStartProgressListener::DetachListeners()
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIWebProgress> webProgressService = do_GetService(
|
||||
NS_DOCUMENTLOADER_SERVICE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return webProgressService->RemoveProgressListener(this);
|
||||
}
|
||||
|
||||
// Helper method for checking a request URI.
|
||||
nsresult
|
||||
nsDocNavStartProgressListener::GetRequestUri(nsIRequest* aReq, nsIURI** uri)
|
||||
{
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
nsresult rv;
|
||||
channel = do_QueryInterface(aReq, &rv);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
rv = channel->GetURI(uri);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// nsIDocNavStartProgressCallback ***********************************************
|
||||
|
||||
// nsDocNavStartProgressListener::GetGlobalProgressListenerEnabled
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocNavStartProgressListener::GetGlobalProgressListenerEnabled(PRBool* aEnabled)
|
||||
{
|
||||
*aEnabled = mEnabled;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// nsDocNavStartProgressListener::SetGlobalProgressListenerEnabled
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocNavStartProgressListener::SetGlobalProgressListenerEnabled(PRBool aEnabled)
|
||||
{
|
||||
if (aEnabled && ! mEnabled) {
|
||||
// enable component
|
||||
mEnabled = PR_TRUE;
|
||||
return AttachListeners();
|
||||
} else if (! aEnabled && mEnabled) {
|
||||
// disable component
|
||||
mEnabled = PR_FALSE;
|
||||
return DetachListeners();
|
||||
}
|
||||
return NS_OK; // nothing to do
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocNavStartProgressListener::GetDelay(PRUint32* aDelay)
|
||||
{
|
||||
*aDelay = mDelay;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocNavStartProgressListener::SetDelay(PRUint32 aDelay)
|
||||
{
|
||||
mDelay = aDelay;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsDocNavStartProgressListener::GetCallback
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocNavStartProgressListener::GetCallback(
|
||||
nsIDocNavStartProgressCallback** aCallback)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCallback);
|
||||
*aCallback = mCallback;
|
||||
NS_IF_ADDREF(*aCallback);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// nsDocNavStartProgressListener::SetCallback
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocNavStartProgressListener::SetCallback(
|
||||
nsIDocNavStartProgressCallback* aCallback)
|
||||
{
|
||||
mCallback = aCallback;
|
||||
|
||||
// Break any cycles we have from mTimers to us by clearing all pending
|
||||
// requests and timers; the timers we use are not exposed externally, but
|
||||
// since we use ourself as an observer with each timer, we have to
|
||||
// manually break this cycle to ensure prompt destruction of this and
|
||||
// the release of everything this entrains, in the case that we can't wait
|
||||
// for all the timers to expire normally for some reason (e.g. application
|
||||
// shutdown).
|
||||
if (!aCallback)
|
||||
ClearPendingEvents();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocNavStartProgressListener::IsSpurious(nsIURI* aURI, PRBool* isSpurious)
|
||||
{
|
||||
NS_PRECONDITION(aURI, "Must have a URI!");
|
||||
|
||||
nsCAutoString scheme;
|
||||
nsresult rv;
|
||||
|
||||
// If there's a nested URI, we want to check the inner URI's scheme.
|
||||
// If we find a spurious scheme then we can break the checking loop at that point.
|
||||
nsCOMPtr<nsIURI> inner = aURI;
|
||||
nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(inner);
|
||||
while (true) {
|
||||
rv = inner->GetScheme(scheme);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
*isSpurious = scheme.Equals("about") ||
|
||||
scheme.Equals("chrome") ||
|
||||
scheme.Equals("file") ||
|
||||
scheme.Equals("javascript");
|
||||
if (*isSpurious || !nestedURI)
|
||||
break;
|
||||
|
||||
rv = nestedURI->GetInnerURI(getter_AddRefs(inner));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nestedURI = do_QueryInterface(inner);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIWebProgressListener ******************************************************
|
||||
|
||||
|
||||
// nsDocNavStartProgressListener::OnStateChange
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocNavStartProgressListener::OnStateChange(nsIWebProgress *aWebProgress,
|
||||
nsIRequest *aRequest,
|
||||
PRUint32 aStateFlags,
|
||||
nsresult aStatus)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// nsDocNavStartProgressListener::OnProgressChange
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocNavStartProgressListener::OnProgressChange(nsIWebProgress *aWebProgress,
|
||||
nsIRequest *aRequest,
|
||||
PRInt32 aCurSelfProgress, PRInt32 aMaxSelfProgress,
|
||||
PRInt32 aCurTotalProgress,
|
||||
PRInt32 aMaxTotalProgress)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// nsDocNavStartProgressListener::OnLocationChange
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocNavStartProgressListener::OnLocationChange(nsIWebProgress *aWebProgress,
|
||||
nsIRequest *aRequest,
|
||||
nsIURI *aLocation)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCAutoString uriString;
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
|
||||
// ignore requests with no URI
|
||||
rv = GetRequestUri(aRequest, getter_AddRefs(uri));
|
||||
if (NS_FAILED(rv))
|
||||
return NS_OK;
|
||||
rv = uri->GetAsciiSpec(uriString);
|
||||
if (NS_FAILED(rv))
|
||||
return NS_OK;
|
||||
|
||||
LOG(("Firing OnLocationChange for %s", uriString.get()));
|
||||
|
||||
// We store the request and a timer in queue. When the timer fires,
|
||||
// we use the request in the front of the queue.
|
||||
nsCOMPtr<nsITimer> timer = do_CreateInstance("@mozilla.org/timer;1", &rv);
|
||||
NS_ENSURE_TRUE(timer, rv);
|
||||
|
||||
rv = timer->Init(this, mDelay, nsITimer::TYPE_ONE_SHOT);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mRequests.AppendObject(aRequest);
|
||||
mTimers.AppendObject(timer);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// nsDocNavStartProgressListener::OnStatusChange
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocNavStartProgressListener::OnStatusChange(nsIWebProgress *aWebProgress,
|
||||
nsIRequest *aRequest,
|
||||
nsresult aStatus,
|
||||
const PRUnichar *aMessage)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// nsDocNavStartProgressListener::OnSecurityChange
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocNavStartProgressListener::OnSecurityChange(nsIWebProgress *aWebProgress,
|
||||
nsIRequest *aRequest,
|
||||
PRUint32 aState)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIObserver ****************************************************************
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocNavStartProgressListener::Observe(nsISupports *subject, const char *topic,
|
||||
const PRUnichar *data)
|
||||
{
|
||||
if (strcmp(topic, NS_TIMER_CALLBACK_TOPIC) == 0) {
|
||||
// Timer callback, pop the front of the request queue and call the callback.
|
||||
#ifdef DEBUG
|
||||
PRUint32 length = mRequests.Count();
|
||||
NS_ASSERTION(length > 0, "timer callback with empty request queue?");
|
||||
length = mTimers.Count();
|
||||
NS_ASSERTION(length > 0, "timer callback with empty timer queue?");
|
||||
#endif
|
||||
|
||||
nsIRequest* request = mRequests[0];
|
||||
|
||||
if (mCallback) {
|
||||
PRBool isSpurious;
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = GetRequestUri(request, getter_AddRefs(uri));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = IsSpurious(uri, &isSpurious);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!isSpurious) {
|
||||
nsCString uriString;
|
||||
rv = uri->GetAsciiSpec(uriString);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// We don't care about URL fragments so we take that off.
|
||||
PRInt32 pos = uriString.FindChar('#');
|
||||
if (pos > -1) {
|
||||
uriString.SetLength(pos);
|
||||
}
|
||||
|
||||
LOG(("Firing DocNavStart for %s", uriString.get()));
|
||||
mCallback->OnDocNavStart(request, uriString);
|
||||
}
|
||||
}
|
||||
|
||||
mRequests.RemoveObjectAt(0);
|
||||
mTimers.RemoveObjectAt(0);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
@ -11,15 +11,10 @@ Function.prototype.inherits = function(parentCtor) {
|
||||
}
|
||||
|
||||
#include ../content/application.js
|
||||
#include ../content/browser-view.js
|
||||
#include ../content/controller.js
|
||||
#include ../content/firefox-commands.js
|
||||
#include ../content/globalstore.js
|
||||
#include ../content/list-warden.js
|
||||
#include ../content/phishing-afterload-displayer.js
|
||||
#include ../content/phishing-warden.js
|
||||
#include ../content/malware-warden.js
|
||||
#include ../content/reporter.js
|
||||
|
||||
var modScope = this;
|
||||
function Init() {
|
||||
|
@ -1,2 +0,0 @@
|
||||
browser.jar:
|
||||
+ content/browser/protection/unittests.xul (unittests.xul)
|
@ -1,70 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<window id="PROT_unittest"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
onload="onProtUnittestLoad();"
|
||||
title="prot unittests">
|
||||
|
||||
<script><![CDATA[
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
function G_Debug(zone, s) {
|
||||
var label = document.createElement('label');
|
||||
var txt = "[" + zone + "] " + s;
|
||||
label.appendChild(document.createTextNode(txt));
|
||||
|
||||
document.documentElement.appendChild(label);
|
||||
}
|
||||
|
||||
function G_Assert(zone, cond, msg) {
|
||||
if (!cond) {
|
||||
G_Debug(zone, msg);
|
||||
throw msg;
|
||||
}
|
||||
}
|
||||
|
||||
function ProtectionPhishWardenTests() {
|
||||
var z = "phishwarden UNITTEST";
|
||||
G_Debug(z, "Starting");
|
||||
|
||||
var listManager = Cc["@mozilla.org/protection/protectionlistmanager;1"]
|
||||
.getService(Ci.nsIProtectionListManager);
|
||||
var warden = Cc['@mozilla.org/protection/phishwarden;1']
|
||||
.createInstance(Ci.nsIProtectionListWarden);
|
||||
// Register tables that we are interested in.
|
||||
warden.registerBlackTable("test-black-url");
|
||||
|
||||
var blacklistedCount = 0;
|
||||
|
||||
var blackURLs = [
|
||||
"http://foo.com/1",
|
||||
"http://foo.com/2",
|
||||
"http://foo.com/3",
|
||||
"http://foo.com/4",
|
||||
"http://www.goodsite.com/test",
|
||||
];
|
||||
|
||||
for (var i = 0; i < blackURLs.length; i++)
|
||||
listManager.safeInsert("test-black-url", blackURLs[i], "1");
|
||||
|
||||
G_Assert(z, !warden.checkUrl("http://bar.com/"), 'should not have found');
|
||||
G_Assert(z, warden.checkUrl("http://foo.com/1"), 'should have found (1)');
|
||||
G_Assert(z, warden.checkUrl("http://foo.com/2"), 'should have found (2)');
|
||||
G_Assert(z, warden.checkUrl("http://foo.com/3"), 'should have found (3)');
|
||||
G_Assert(z, warden.checkUrl("http://foo.com/4"), 'should have found (4)');
|
||||
|
||||
warden.registerWhiteTable('test-white-domain');
|
||||
listManager.safeInsert("test-white-domain", "http://www.goodsite.com/", "1");
|
||||
|
||||
G_Assert(z, !warden.checkUrl("http://www.goodsite.com/"),
|
||||
'whitelist failed?')
|
||||
|
||||
|
||||
G_Debug(z, "PASSED");
|
||||
}
|
||||
|
||||
function onProtUnittestLoad() {
|
||||
ProtectionPhishWardenTests();
|
||||
}
|
||||
]]></script>
|
||||
</window>
|
@ -1396,7 +1396,7 @@ Engine.prototype = {
|
||||
this._urls.push(new EngineURL("text/html", aMethod, aTemplate));
|
||||
|
||||
this._name = aName;
|
||||
this._alias = aAlias;
|
||||
this.alias = aAlias;
|
||||
this._description = aDescription;
|
||||
this._setIcon(aIconURL, true);
|
||||
|
||||
@ -1526,9 +1526,6 @@ Engine.prototype = {
|
||||
break;
|
||||
|
||||
// Non-OpenSearch elements
|
||||
case "Alias":
|
||||
this._alias = child.textContent;
|
||||
break;
|
||||
case "SearchForm":
|
||||
this._searchForm = child.textContent;
|
||||
break;
|
||||
@ -1905,7 +1902,6 @@ Engine.prototype = {
|
||||
}
|
||||
}
|
||||
|
||||
appendTextNode(MOZSEARCH_NS_10, "Alias", this.alias);
|
||||
appendTextNode(MOZSEARCH_NS_10, "UpdateInterval", this._updateInterval);
|
||||
appendTextNode(MOZSEARCH_NS_10, "UpdateUrl", this._updateURL);
|
||||
appendTextNode(MOZSEARCH_NS_10, "IconUpdateUrl", this._iconUpdateURL);
|
||||
|
@ -45,6 +45,8 @@ include $(DEPTH)/config/autoconf.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
_BROWSER_TEST_FILES = browser_405664.js \
|
||||
browser_415700.js \
|
||||
testEngine.xml \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_BROWSER_TEST_FILES)
|
||||
|
90
browser/components/search/test/browser_415700.js
Normal file
@ -0,0 +1,90 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ryan Flint <rflint@dslr.net> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
var gSS = Cc["@mozilla.org/browser/search-service;1"].
|
||||
getService(Ci.nsIBrowserSearchService);
|
||||
var gObs = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
|
||||
var observers = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
switch (aData) {
|
||||
case "engine-added":
|
||||
test2();
|
||||
break;
|
||||
case "engine-current":
|
||||
test3();
|
||||
break;
|
||||
case "engine-removed":
|
||||
test4();
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
gObs.addObserver(observers, "browser-search-engine-modified", false);
|
||||
|
||||
gSS.addEngine("http://localhost:8888/browser/browser/components/search/test/testEngine.xml",
|
||||
Ci.nsISearchEngine.DATA_XML, "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAABGklEQVQoz2NgGB6AnZ1dUlJSXl4eSDIyMhLW4Ovr%2B%2Fr168uXL69Zs4YoG%2BLi4i5dusTExMTGxsbNzd3f37937976%2BnpmZmagbHR09J49e5YvX66kpATVEBYW9ubNm2nTphkbG7e2tp44cQLIuHfvXm5urpaWFlDKysqqu7v73LlzECMYIiIiHj58mJCQoKKicvXq1bS0NKBgW1vbjh074uPjgeqAXE1NzSdPnvDz84M0AEUvXLgAsW379u1z5swBen3jxo2zZ892cHB4%2BvQp0KlAfwI1cHJyghQFBwfv2rULokFXV%2FfixYu7d%2B8GGqGgoMDKyrpu3br9%2B%2FcDuXl5eVA%2FAEWBfoWHAdAYoNuAYQ0XAeoUERFhGDYAAPoUaT2dfWJuAAAAAElFTkSuQmCC",
|
||||
false);
|
||||
}
|
||||
|
||||
function test2() {
|
||||
var engine = gSS.getEngineByName("Foo");
|
||||
ok(engine, "Engine was added.");
|
||||
|
||||
var aEngine = gSS.getEngineByAlias("fooalias");
|
||||
ok(!aEngine, "Alias was not parsed from engine description");
|
||||
|
||||
gSS.currentEngine = engine;
|
||||
}
|
||||
|
||||
function test3() {
|
||||
var engine = gSS.currentEngine;
|
||||
is(engine.name, "Foo", "Current engine was changed successfully");
|
||||
|
||||
gSS.removeEngine(engine);
|
||||
}
|
||||
|
||||
function test4() {
|
||||
var engine = gSS.currentEngine;
|
||||
ok(engine, "An engine is present.");
|
||||
isnot(engine.name, "Foo", "Current engine reset after removal");
|
||||
|
||||
gObs.removeObserver(observers, "browser-search-engine-modified");
|
||||
finish();
|
||||
}
|
12
browser/components/search/test/testEngine.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"
|
||||
xmlns:moz="http://www.mozilla.org/2006/browser/search/">
|
||||
<ShortName>Foo</ShortName>
|
||||
<Description>Foo Search</Description>
|
||||
<InputEncoding>utf-8</InputEncoding>
|
||||
<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAABGklEQVQoz2NgGB6AnZ1dUlJSXl4eSDIyMhLW4Ovr%2B%2Fr168uXL69Zs4YoG%2BLi4i5dusTExMTGxsbNzd3f37937976%2BnpmZmagbHR09J49e5YvX66kpATVEBYW9ubNm2nTphkbG7e2tp44cQLIuHfvXm5urpaWFlDKysqqu7v73LlzECMYIiIiHj58mJCQoKKicvXq1bS0NKBgW1vbjh074uPjgeqAXE1NzSdPnvDz84M0AEUvXLgAsW379u1z5swBen3jxo2zZ892cHB4%2BvQp0KlAfwI1cHJyghQFBwfv2rULokFXV%2FfixYu7d%2B8GGqGgoMDKyrpu3br9%2B%2FcDuXl5eVA%2FAEWBfoWHAdAYoNuAYQ0XAeoUERFhGDYAAPoUaT2dfWJuAAAAAElFTkSuQmCC</Image>
|
||||
<Url type="text/html" method="GET" template="http://localhost:8888/browser/browser/components/search/test/?search">
|
||||
<Param name="test" value="{searchTerms}"/>
|
||||
</Url>
|
||||
<moz:SearchForm>http://localhost:8888/browser/browser/components/search/test/</moz:SearchForm>
|
||||
<moz:Alias>fooalias</moz:Alias>
|
||||
</OpenSearchDescription>
|
@ -506,6 +506,13 @@ SessionStoreService.prototype = {
|
||||
// cache the window state until the window is completely gone
|
||||
aWindow.__SS_dyingCache = this._windows[aWindow.__SSi] || this._lastWindowClosed;
|
||||
|
||||
// reset the _tab property to avoid keeping the tab's XUL element alive
|
||||
// longer than we need it
|
||||
var tabCount = aWindow.__SS_dyingCache.tabs.length;
|
||||
for (var t = 0; t < tabCount; t++) {
|
||||
delete aWindow.__SS_dyingCache.tabs[t]._tab;
|
||||
}
|
||||
|
||||
delete aWindow.__SSi;
|
||||
},
|
||||
|
||||
@ -575,6 +582,10 @@ SessionStoreService.prototype = {
|
||||
// make sure that the tab related data is up-to-date
|
||||
var tabState = this._collectTabData(aTab);
|
||||
this._updateTextAndScrollDataForTab(aWindow, aTab.linkedBrowser, tabState);
|
||||
|
||||
// reset the _tab property to avoid keeping the tab's XUL element alive
|
||||
// longer than we need it
|
||||
delete tabState._tab;
|
||||
|
||||
// store closed-tab data for undo
|
||||
if (tabState.entries.length > 1 || tabState.entries[0].url != "about:blank") {
|
||||
|
@ -47,5 +47,5 @@ MOZ_MORKREADER=1
|
||||
MOZ_SAFE_BROWSING=1
|
||||
MOZ_APP_VERSION=$FIREFOX_VERSION
|
||||
MOZ_NO_XPCOM_OBSOLETE=1
|
||||
MOZ_EXTENSIONS_DEFAULT=" inspector gnomevfs reporter"
|
||||
MOZ_EXTENSIONS_DEFAULT=" gnomevfs reporter"
|
||||
# MOZ_APP_DISPLAYNAME will be set by branding/configure.sh
|
||||
|
@ -87,6 +87,14 @@ extensions/reporter@mozilla.org/install.rdf
|
||||
extensions/reporter@mozilla.org/chrome.manifest
|
||||
extensions/reporter@mozilla.org/chrome/reporter.jar
|
||||
extensions/reporter@mozilla.org/defaults/preferences/reporter.js
|
||||
#Remove Inspector (present from upgrades from Fx2/Fx3b1)
|
||||
components/inspector.xpt
|
||||
extensions/inspector@mozilla.org/install.rdf
|
||||
extensions/inspector@mozilla.org/components/inspector-cmdline.js
|
||||
extensions/inspector@mozilla.org/chrome.manifest
|
||||
extensions/inspector@mozilla.org/chrome/inspector.jar
|
||||
extensions/inspector@mozilla.org/defaults/preferences/inspector.js
|
||||
extensions/inspector@mozilla.org/platform/WINNT/chrome/icons/default/winInspectorMain.ico
|
||||
extensions/inspector@mozilla.org/components/inspector.xpt
|
||||
extensions/inspector@mozilla.org/components/@DLL_PREFIX@inspector@DLL_SUFFIX@
|
||||
extensions/inspector@mozilla.org/chrome/icons/default/winInspectorMain.ico
|
||||
@ -575,12 +583,24 @@ components/xpcom_obsolete.xpt
|
||||
init.d/README
|
||||
redo-prebinding.sh
|
||||
res/viewer.properties
|
||||
res/bloatcycle.html
|
||||
#endif
|
||||
#ifdef XP_UNIX
|
||||
#ifndef XP_MACOSX
|
||||
readme.txt
|
||||
chrome/icons/default/default.xpm
|
||||
#endif
|
||||
#endif
|
||||
dictionaries/PL.dic
|
||||
dictionaries/PL.aff
|
||||
#ifdef MOZ_MEMORY
|
||||
#ifdef XP_WIN
|
||||
Microsoft.VC80.CRT.manifest
|
||||
msvcm80.dll
|
||||
msvcp80.dll
|
||||
msvcr80.dll
|
||||
#endif
|
||||
#endif
|
||||
#ifdef XP_WIN
|
||||
xpicleanup.exe
|
||||
#else
|
||||
|
@ -349,11 +349,3 @@ bin\crashreporter.exe
|
||||
bin\crashreporter.ini
|
||||
bin\crashreporter-override.ini
|
||||
|
||||
; [Additional Developer Tools]
|
||||
[adt]
|
||||
bin\extensions\inspector@mozilla.org\install.rdf
|
||||
bin\extensions\inspector@mozilla.org\components\inspector-cmdline.js
|
||||
bin\extensions\inspector@mozilla.org\chrome.manifest
|
||||
bin\extensions\inspector@mozilla.org\chrome\inspector.jar
|
||||
bin\extensions\inspector@mozilla.org\defaults\preferences\inspector.js
|
||||
bin\extensions\inspector@mozilla.org\platform\WINNT\chrome\icons\default\winInspectorMain.ico
|
||||
|
Before Width: | Height: | Size: 856 B After Width: | Height: | Size: 865 B |
Before Width: | Height: | Size: 924 B After Width: | Height: | Size: 928 B |
@ -187,10 +187,12 @@ menuitem.bookmark-item {
|
||||
list-style-image: url("moz-icon://stock/gtk-directory?size=menu");
|
||||
}
|
||||
|
||||
/* livemarks have the same layout as folder-item, but in the browser-only livemark-item.png */
|
||||
/* only the folder icon has any effect for now, item icon is unused */
|
||||
.bookmark-item[container][livemark] {
|
||||
list-style-image: url("chrome://browser/skin/page-livemarks.png");
|
||||
list-style-image: url("chrome://browser/skin/feeds/feedIcon16.png");
|
||||
}
|
||||
|
||||
.bookmark-item[container][livemark] .bookmark-item {
|
||||
list-style-image: url("chrome://browser/skin/places/livemark-item.png");
|
||||
}
|
||||
|
||||
.bookmark-item[container][tagContainer] {
|
||||
@ -209,13 +211,15 @@ menuitem:not([type]) {
|
||||
}
|
||||
|
||||
menuitem[command="cmd_newNavigator"],
|
||||
#context-openlink {
|
||||
#context-openlink,
|
||||
#context-openframe {
|
||||
list-style-image: url("chrome://browser/skin/Toolbar-small.png");
|
||||
-moz-image-region: rect(0px 80px 16px 64px);
|
||||
}
|
||||
|
||||
menuitem[command="cmd_newNavigatorTab"],
|
||||
#context-openlinkintab {
|
||||
#context-openlinkintab,
|
||||
#context-openframeintab {
|
||||
list-style-image: url("chrome://browser/skin/Toolbar-small.png");
|
||||
-moz-image-region: rect(0px 64px 16px 48px);
|
||||
}
|
||||
@ -231,7 +235,8 @@ menuitem[command="Browser:OpenFile"] {
|
||||
menuitem[command="Browser:SavePage"],
|
||||
#context-savelink,
|
||||
#context-saveimage,
|
||||
#context-savepage {
|
||||
#context-savepage,
|
||||
#context-saveframe {
|
||||
list-style-image: url("moz-icon://stock/gtk-save-as?size=menu");
|
||||
}
|
||||
|
||||
@ -239,7 +244,8 @@ menuitem[command="cmd_printPreview"] {
|
||||
list-style-image: url("moz-icon://stock/gtk-print-preview?size=menu");
|
||||
}
|
||||
|
||||
menuitem[command="cmd_print"] {
|
||||
menuitem[command="cmd_print"],
|
||||
#context-printframe {
|
||||
list-style-image: url("moz-icon://stock/gtk-print?size=menu");
|
||||
}
|
||||
|
||||
@ -278,7 +284,8 @@ menuitem[command="cmd_cut"][disabled],
|
||||
menuitem[command="cmd_copy"],
|
||||
#context-copy,
|
||||
#context-copyimage,
|
||||
#context-copylink {
|
||||
#context-copylink,
|
||||
#context-copyemail {
|
||||
list-style-image: url("moz-icon://stock/gtk-copy?size=menu");
|
||||
}
|
||||
|
||||
@ -324,8 +331,7 @@ menuitem[command="cmd_selectAll"] {
|
||||
}
|
||||
|
||||
menuitem[command="Browser:Stop"],
|
||||
#context-stop,
|
||||
#javascriptConsole {
|
||||
#context-stop {
|
||||
list-style-image: url("moz-icon://stock/gtk-stop?size=menu");
|
||||
}
|
||||
|
||||
@ -335,7 +341,8 @@ menuitem[command="Browser:Stop"][disabled],
|
||||
}
|
||||
|
||||
menuitem[command="Browser:Reload"],
|
||||
#context-reload {
|
||||
#context-reload,
|
||||
#context-reloadframe {
|
||||
list-style-image: url("moz-icon://stock/gtk-refresh?size=menu");
|
||||
}
|
||||
|
||||
@ -416,7 +423,8 @@ menuitem[command="Browser:ShowAllBookmarks"] {
|
||||
}
|
||||
|
||||
menuitem[command="View:PageInfo"],
|
||||
#context-viewinfo {
|
||||
#context-viewinfo,
|
||||
#context-viewframeinfo {
|
||||
list-style-image: url("moz-icon://stock/gtk-info?size=menu");
|
||||
}
|
||||
|
||||
@ -436,6 +444,10 @@ menuitem[key="key_openHelp"] {
|
||||
list-style-image: url("moz-icon://stock/gtk-about?size=menu");
|
||||
}
|
||||
|
||||
#javascriptConsole {
|
||||
list-style-image: url("chrome://global/skin/console/console.png");
|
||||
}
|
||||
|
||||
/* Primary toolbar buttons */
|
||||
.toolbarbutton-1 {
|
||||
-moz-box-orient: vertical;
|
||||
@ -600,6 +612,9 @@ toolbar[iconsize="small"] .toolbarbutton-1[type="menu-button"] {
|
||||
toolbar[iconsize="small"] #back-button {
|
||||
list-style-image: url("moz-icon://stock/gtk-go-back-ltr?size=menu");
|
||||
}
|
||||
.unified-nav-back[_moz-menuactive] {
|
||||
list-style-image: url("moz-icon://stock/gtk-go-back-ltr?size=menu") !important;
|
||||
}
|
||||
toolbar[iconsize="small"] #back-button[disabled="true"] {
|
||||
list-style-image: url("moz-icon://stock/gtk-go-back-ltr?size=menu&state=disabled");
|
||||
}
|
||||
@ -607,6 +622,9 @@ toolbar[iconsize="small"] #back-button[disabled="true"] {
|
||||
toolbar[iconsize="small"] #back-button[chromedir="rtl"] {
|
||||
list-style-image: url("moz-icon://stock/gtk-go-back-rtl?size=menu");
|
||||
}
|
||||
menupopup[chromedir="rtl"] > .unified-nav-back[_moz-menuactive] {
|
||||
list-style-image: url("moz-icon://stock/gtk-go-back-rtl?size=menu") !important;
|
||||
}
|
||||
toolbar[iconsize="small"] #back-button[disabled="true"][chromedir="rtl"] {
|
||||
list-style-image: url("moz-icon://stock/gtk-go-back-rtl?size=menu&state=disabled");
|
||||
}
|
||||
@ -614,6 +632,9 @@ toolbar[iconsize="small"] #back-button[disabled="true"][chromedir="rtl"] {
|
||||
toolbar[iconsize="small"] #forward-button {
|
||||
list-style-image: url("moz-icon://stock/gtk-go-forward-ltr?size=menu");
|
||||
}
|
||||
.unified-nav-forward[_moz-menuactive] {
|
||||
list-style-image: url("moz-icon://stock/gtk-go-forward-ltr?size=menu") !important;
|
||||
}
|
||||
toolbar[iconsize="small"] #forward-button[disabled="true"] {
|
||||
list-style-image: url("moz-icon://stock/gtk-go-forward-ltr?size=menu&state=disabled");
|
||||
}
|
||||
@ -621,6 +642,9 @@ toolbar[iconsize="small"] #forward-button[disabled="true"] {
|
||||
toolbar[iconsize="small"] #forward-button[chromedir="rtl"] {
|
||||
list-style-image: url("moz-icon://stock/gtk-go-forward-rtl?size=menu");
|
||||
}
|
||||
menupopup[chromedir="rtl"] > .unified-nav-forward[_moz-menuactive] {
|
||||
list-style-image: url("moz-icon://stock/gtk-go-forward-rtl?size=menu") !important;
|
||||
}
|
||||
toolbar[iconsize="small"] #forward-button[disabled="true"][chromedir="rtl"] {
|
||||
list-style-image: url("moz-icon://stock/gtk-go-forward-rtl?size=menu&state=disabled");
|
||||
}
|
||||
@ -796,33 +820,34 @@ toolbar[iconsize="small"] #paste-button[disabled="true"] {
|
||||
}
|
||||
|
||||
/* Favicon */
|
||||
#page-proxy-deck,
|
||||
#page-proxy-stack,
|
||||
#page-proxy-favicon,
|
||||
#page-proxy-button {
|
||||
#urlbar-throbber {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
#page-proxy-deck {
|
||||
#page-proxy-stack {
|
||||
margin: 2px 3px;
|
||||
}
|
||||
|
||||
#page-proxy-favicon {
|
||||
list-style-image: none;
|
||||
#page-proxy-favicon:not([src]) {
|
||||
list-style-image: url("chrome://global/skin/icons/folder-item.png");
|
||||
-moz-image-region: rect(0px, 16px, 16px, 0px);
|
||||
}
|
||||
|
||||
#page-proxy-button {
|
||||
list-style-image: url("chrome://global/skin/icons/folder-item.png") !important;
|
||||
-moz-image-region: rect(0px, 16px, 16px, 0px);}
|
||||
#page-proxy-favicon[pageproxystate="invalid"] {
|
||||
-moz-image-region: rect(16px, 16px, 32px, 0px);
|
||||
}
|
||||
|
||||
#page-proxy-button[pageproxystate="invalid"] {
|
||||
cursor: default;
|
||||
-moz-image-region: rect(32px, 16px, 48px, 0px) !important;
|
||||
#urlbar-throbber {
|
||||
list-style-image: url("chrome://global/skin/throbber/Throbber-small.gif");
|
||||
}
|
||||
|
||||
/* Identity indicator */
|
||||
#identity-box {
|
||||
background-color: -moz-dialog;
|
||||
color: -moz-dialogtext;
|
||||
-moz-border-end: 1px solid ThreeDShadow;
|
||||
}
|
||||
|
||||
@ -1186,6 +1211,35 @@ tabpanels {
|
||||
border-bottom: 1px solid threedshadow;
|
||||
}
|
||||
|
||||
#context_newTab {
|
||||
list-style-image: url("chrome://browser/skin/Toolbar-small.png");
|
||||
-moz-image-region: rect(0px 64px 16px 48px);
|
||||
}
|
||||
|
||||
#context_newTab[disabled] {
|
||||
-moz-image-region: rect(16px 64px 32px 48px);
|
||||
}
|
||||
|
||||
#context_reloadTab {
|
||||
list-style-image: url("moz-icon://stock/gtk-refresh?size=menu");
|
||||
}
|
||||
|
||||
#context_closeOtherTabs {
|
||||
list-style-image: url("moz-icon://stock/gtk-clear?size=menu");
|
||||
}
|
||||
|
||||
#context_closeOtherTabs[disabled] {
|
||||
list-style-image: url("moz-icon://stock/gtk-clear?size=menu&state=disabled");
|
||||
}
|
||||
|
||||
#context_undoCloseTab {
|
||||
list-style-image: url("moz-icon://stock/gtk-undelete?size=menu");
|
||||
}
|
||||
|
||||
#context_closeTab {
|
||||
list-style-image: url("moz-icon://stock/gtk-close?size=menu");
|
||||
}
|
||||
|
||||
/* tabbrowser-tab focus ring */
|
||||
.tabbrowser-tab > .tab-text {
|
||||
border: 1px dotted transparent;
|
||||
@ -1272,6 +1326,10 @@ tabpanels {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.tabs-alltabs-button > .toolbarbutton-icon {
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
/* Sidebar */
|
||||
#sidebar-box .tabs-closebutton {
|
||||
margin-bottom: 0px !important;
|
||||
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 10 KiB |
@ -33,10 +33,7 @@ classic.jar:
|
||||
* skin/classic/browser/places/bookmarkProperties.css (places/bookmarkProperties.css)
|
||||
skin/classic/browser/places/bookmarksMenu.png (places/bookmarksMenu.png)
|
||||
* skin/classic/browser/places/editBookmarkOverlay.css (places/editBookmarkOverlay.css)
|
||||
skin/classic/browser/places/livemark-folder.png (places/livemark-folder.png)
|
||||
skin/classic/browser/places/livemark-folder-rtl.png (places/livemark-folder-rtl.png)
|
||||
skin/classic/browser/places/livemark-item.png (places/livemark-item.png)
|
||||
skin/classic/browser/places/livemark-item-rtl.png (places/livemark-item-rtl.png)
|
||||
skin/classic/browser/places/pageStarred.png (places/pageStarred.png)
|
||||
skin/classic/browser/places/starred48.png (places/starred48.png)
|
||||
skin/classic/browser/places/unstarred48.png (places/unstarred48.png)
|
||||
@ -54,14 +51,6 @@ classic.jar:
|
||||
skin/classic/browser/preferences/plugin.png (preferences/plugin.png)
|
||||
* skin/classic/browser/preferences/preferences.css (preferences/preferences.css)
|
||||
skin/classic/browser/preferences/applications.css (preferences/applications.css)
|
||||
#ifdef MOZ_SAFE_BROWSING
|
||||
skin/classic/browser/safebrowsing/browser-protection.css (safebrowsing/browser-protection.css)
|
||||
skin/classic/browser/safebrowsing/close16x16.png (safebrowsing/close16x16.png)
|
||||
skin/classic/browser/safebrowsing/dim.png (safebrowsing/dim.png)
|
||||
skin/classic/browser/safebrowsing/tail.png (safebrowsing/tail.png)
|
||||
skin/classic/browser/safebrowsing/warning16x16.png (safebrowsing/warning16x16.png)
|
||||
skin/classic/browser/safebrowsing/warning24x24.png (safebrowsing/warning24x24.png)
|
||||
#endif
|
||||
skin/classic/browser/tabbrowser/tab-arrow-end.png (tabbrowser/tab-arrow-end.png)
|
||||
skin/classic/browser/tabbrowser/tab-arrow-start.png (tabbrowser/tab-arrow-start.png)
|
||||
skin/classic/browser/tabbrowser/tabDragIndicator.png (tabbrowser/tabDragIndicator.png)
|
||||
|
@ -62,42 +62,22 @@
|
||||
-moz-image-region: rect(0px, 32px, 32px, 0px)
|
||||
}
|
||||
|
||||
#generalTab:hover, #generalTab[selected="true"] {
|
||||
-moz-image-region: rect(32px, 32px, 64px, 0px)
|
||||
}
|
||||
|
||||
#mediaTab {
|
||||
-moz-image-region: rect(0px, 64px, 32px, 32px)
|
||||
}
|
||||
|
||||
#mediaTab:hover, #mediaTab[selected="true"] {
|
||||
-moz-image-region: rect(32px, 64px, 64px, 32px)
|
||||
}
|
||||
|
||||
#feedTab {
|
||||
-moz-image-region: rect(0px, 96px, 32px, 64px)
|
||||
}
|
||||
|
||||
#feedTab:hover, #feedTab[selected="true"] {
|
||||
-moz-image-region: rect(32px, 96px, 64px, 64px)
|
||||
}
|
||||
|
||||
#permTab {
|
||||
-moz-image-region: rect(0px, 128px, 32px, 96px)
|
||||
}
|
||||
|
||||
#permTab:hover, #permTab[selected="true"] {
|
||||
-moz-image-region: rect(32px, 128px, 64px, 96px)
|
||||
}
|
||||
|
||||
#securityTab {
|
||||
-moz-image-region: rect(0px, 160px, 32px, 128px)
|
||||
}
|
||||
|
||||
#securityTab:hover, #securityTab[selected="true"] {
|
||||
-moz-image-region: rect(32px, 160px, 64px, 128px)
|
||||
}
|
||||
|
||||
deck {
|
||||
padding: 10px 10px 10px 10px;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 8.7 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 732 B |
@ -268,84 +268,10 @@
|
||||
}
|
||||
|
||||
/**** menuitem stock icons ****/
|
||||
menuitem:not([type]) {
|
||||
-moz-binding: url("chrome://global/content/bindings/menu.xml#menuitem-iconic");
|
||||
}
|
||||
|
||||
menuitem[command="cmd_cut"] {
|
||||
list-style-image: url("moz-icon://stock/gtk-cut?size=menu");
|
||||
}
|
||||
|
||||
menuitem[command="cmd_cut"][disabled] {
|
||||
list-style-image: url("moz-icon://stock/gtk-cut?size=menu&state=disabled");
|
||||
}
|
||||
|
||||
menuitem[command="cmd_copy"] {
|
||||
list-style-image: url("moz-icon://stock/gtk-copy?size=menu");
|
||||
}
|
||||
|
||||
menuitem[command="cmd_copy"][disabled] {
|
||||
list-style-image: url("moz-icon://stock/gtk-copy?size=menu&state=disabled");
|
||||
}
|
||||
|
||||
menuitem[command="cmd_paste"] {
|
||||
list-style-image: url("moz-icon://stock/gtk-paste?size=menu");
|
||||
}
|
||||
|
||||
menuitem[command="cmd_paste"][disabled] {
|
||||
list-style-image: url("moz-icon://stock/gtk-paste?size=menu&state=disabled");
|
||||
}
|
||||
|
||||
menuitem[command="cmd_delete"] {
|
||||
list-style-image: url("moz-icon://stock/gtk-delete?size=menu");
|
||||
}
|
||||
|
||||
menuitem[command="cmd_delete"][disabled] {
|
||||
list-style-image: url("moz-icon://stock/gtk-delete?size=menu&state=disabled");
|
||||
}
|
||||
|
||||
menuitem[command="cmd_undo"] {
|
||||
list-style-image: url("moz-icon://stock/gtk-undo?size=menu");
|
||||
}
|
||||
|
||||
menuitem[command="cmd_undo"][disabled] {
|
||||
list-style-image: url("moz-icon://stock/gtk-undo?size=menu&state=disabled");
|
||||
}
|
||||
|
||||
menuitem[command="cmd_redo"] {
|
||||
list-style-image: url("moz-icon://stock/gtk-redo?size=menu");
|
||||
}
|
||||
|
||||
menuitem[command="cmd_redo"][disabled] {
|
||||
list-style-image: url("moz-icon://stock/gtk-redo?size=menu&state=disabled");
|
||||
}
|
||||
|
||||
menuitem[command="cmd_selectAll"] {
|
||||
list-style-image: url("moz-icon://stock/gtk-select-all?size=menu");
|
||||
}
|
||||
|
||||
menuitem[command="cmd_selectAll"][disabled] {
|
||||
list-style-image: url("moz-icon://stock/gtk-select-all?size=menu&state=disabled");
|
||||
}
|
||||
|
||||
#orgClose {
|
||||
list-style-image: url("moz-icon://stock/gtk-close?size=menu");
|
||||
}
|
||||
|
||||
menuitem[command="placesCmd_open:window"] {
|
||||
list-style-image: url("chrome://browser/skin/Toolbar-small.png");
|
||||
-moz-image-region: rect(0px 80px 16px 64px);
|
||||
}
|
||||
|
||||
menuitem[command="placesCmd_open:tab"] {
|
||||
list-style-image: url("chrome://browser/skin/Toolbar-small.png");
|
||||
-moz-image-region: rect(0px 64px 16px 48px);
|
||||
}
|
||||
|
||||
menuitem[command="placesCmd_show:info"] {
|
||||
list-style-image: url("moz-icon://stock/gtk-properties?size=menu");
|
||||
}
|
||||
|
||||
menuitem[command="OrganizerCommand_import"] {
|
||||
list-style-image: url("moz-icon://stock/gtk-revert-to-saved?size=menu");
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ treechildren::-moz-tree-image(title, container) {
|
||||
}
|
||||
|
||||
treechildren::-moz-tree-image(title, container, livemark) {
|
||||
list-style-image: url("chrome://browser/skin/page-livemarks.png");
|
||||
list-style-image: url("chrome://browser/skin/feeds/feedIcon16.png");
|
||||
-moz-image-region: auto;
|
||||
}
|
||||
|
||||
@ -50,6 +50,12 @@ treechildren::-moz-tree-image(title, query) {
|
||||
-moz-image-region: auto;
|
||||
}
|
||||
|
||||
/* We want some queries to look like ordinary folders. This must come
|
||||
after the (title, query) selector, or it would get overridden. */
|
||||
treechildren::-moz-tree-image(title, query, folder) {
|
||||
list-style-image: url("moz-icon://stock/gtk-directory?size=menu");
|
||||
}
|
||||
|
||||
treechildren::-moz-tree-row(session-start) {
|
||||
border-top:1px dotted ThreeDShadow;
|
||||
font-weight: bold;
|
||||
@ -58,3 +64,90 @@ treechildren::-moz-tree-row(session-start) {
|
||||
treechildren::-moz-tree-cell-text(date, session-continue) {
|
||||
color: -moz-Field;
|
||||
}
|
||||
|
||||
/**** menuitem stock icons ****/
|
||||
menuitem:not([type]) {
|
||||
-moz-binding: url("chrome://global/content/bindings/menu.xml#menuitem-iconic");
|
||||
}
|
||||
|
||||
menuitem[command="cmd_cut"],
|
||||
menuitem[cmd="cmd_cut"] {
|
||||
list-style-image: url("moz-icon://stock/gtk-cut?size=menu");
|
||||
}
|
||||
|
||||
menuitem[command="cmd_cut"][disabled]
|
||||
menuitem[cmd="cmd_cut"][disabled] {
|
||||
list-style-image: url("moz-icon://stock/gtk-cut?size=menu&state=disabled");
|
||||
}
|
||||
|
||||
menuitem[command="cmd_copy"],
|
||||
menuitem[cmd="cmd_copy"] {
|
||||
list-style-image: url("moz-icon://stock/gtk-copy?size=menu");
|
||||
}
|
||||
|
||||
menuitem[command="cmd_copy"][disabled]
|
||||
menuitem[cmd="cmd_copy"][disabled] {
|
||||
list-style-image: url("moz-icon://stock/gtk-copy?size=menu&state=disabled");
|
||||
}
|
||||
|
||||
menuitem[command="cmd_paste"],
|
||||
menuitem[cmd="cmd_paste"] {
|
||||
list-style-image: url("moz-icon://stock/gtk-paste?size=menu");
|
||||
}
|
||||
|
||||
menuitem[command="cmd_paste"][disabled],
|
||||
menuitem[cmd="cmd_paste"][disabled] {
|
||||
list-style-image: url("moz-icon://stock/gtk-paste?size=menu&state=disabled");
|
||||
}
|
||||
|
||||
menuitem[command="cmd_delete"],
|
||||
menuitem[cmd="cmd_delete"] {
|
||||
list-style-image: url("moz-icon://stock/gtk-delete?size=menu");
|
||||
}
|
||||
|
||||
menuitem[command="cmd_delete"][disabled],
|
||||
menuitem[cmd="cmd_delete"][disabled] {
|
||||
list-style-image: url("moz-icon://stock/gtk-delete?size=menu&state=disabled");
|
||||
}
|
||||
|
||||
menuitem[command="cmd_undo"],
|
||||
menuitem[cmd="cmd_undo"] {
|
||||
list-style-image: url("moz-icon://stock/gtk-undo?size=menu");
|
||||
}
|
||||
|
||||
menuitem[command="cmd_undo"][disabled],
|
||||
menuitem[cmd="cmd_undo"][disabled] {
|
||||
list-style-image: url("moz-icon://stock/gtk-undo?size=menu&state=disabled");
|
||||
}
|
||||
|
||||
menuitem[command="cmd_redo"] {
|
||||
list-style-image: url("moz-icon://stock/gtk-redo?size=menu");
|
||||
}
|
||||
|
||||
menuitem[command="cmd_redo"][disabled] {
|
||||
list-style-image: url("moz-icon://stock/gtk-redo?size=menu&state=disabled");
|
||||
}
|
||||
|
||||
menuitem[command="cmd_selectAll"],
|
||||
menuitem[cmd="cmd_selectAll"] {
|
||||
list-style-image: url("moz-icon://stock/gtk-select-all?size=menu");
|
||||
}
|
||||
|
||||
menuitem[command="cmd_selectAll"][disabled],
|
||||
menuitem[cmd="cmd_selectAll"][disabled] {
|
||||
list-style-image: url("moz-icon://stock/gtk-select-all?size=menu&state=disabled");
|
||||
}
|
||||
|
||||
menuitem[command="placesCmd_open:window"] {
|
||||
list-style-image: url("chrome://browser/skin/Toolbar-small.png");
|
||||
-moz-image-region: rect(0px 80px 16px 64px);
|
||||
}
|
||||
|
||||
menuitem[command="placesCmd_open:tab"] {
|
||||
list-style-image: url("chrome://browser/skin/Toolbar-small.png");
|
||||
-moz-image-region: rect(0px 64px 16px 48px);
|
||||
}
|
||||
|
||||
menuitem[command="placesCmd_show:info"] {
|
||||
list-style-image: url("moz-icon://stock/gtk-properties?size=menu");
|
||||
}
|
||||
|
Before Width: | Height: | Size: 269 B After Width: | Height: | Size: 583 B |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 452 B After Width: | Height: | Size: 565 B |
@ -1,116 +0,0 @@
|
||||
#safebrowsing-palm-message {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
#safebrowsing-palm-message-content {
|
||||
background-color: white;
|
||||
color: black;
|
||||
-moz-box-sizing: border-box;
|
||||
-moz-border-radius: 10px;
|
||||
padding: 10px;
|
||||
border-top: 1px solid;
|
||||
border-left: 1px solid;
|
||||
border-right: 2px solid;
|
||||
border-bottom: 2px solid;
|
||||
z-index: 1;
|
||||
margin: 0;
|
||||
font-size: 120%;
|
||||
}
|
||||
|
||||
.safebrowsing-palm-fixed-width {
|
||||
width: 400px;
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
.safebrowsing-palm-paragraph {
|
||||
padding-bottom: 2em;
|
||||
}
|
||||
|
||||
#safebrowsing-palm-close-container {
|
||||
height: 16px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#safebrowsing-palm-close {
|
||||
cursor: pointer;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
list-style-image: url("chrome://browser/skin/safebrowsing/close16x16.png");
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
#safebrowsing-palm-message-tail-container {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
border-right: 2px solid;
|
||||
z-index: 3;
|
||||
height: 67px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#safebrowsing-palm-message-tail {
|
||||
height: 67px;
|
||||
width: 24px;
|
||||
max-width: 24px;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
#safebrowsing-palm-message-titlebox {
|
||||
background-image: url("chrome://browser/skin/safebrowsing/warning24x24.png");
|
||||
background-repeat: no-repeat;
|
||||
background-position: top left;
|
||||
text-indent: 30px;
|
||||
padding: 0 0 5px;
|
||||
margin-top: -16px;
|
||||
font-size: 120%;
|
||||
font-weight: bold;
|
||||
min-height: 26px;
|
||||
}
|
||||
|
||||
#safebrowsing-palm-message-actionbox {
|
||||
padding: 10px 10px 15px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.safebrowsing-palm-bigtext {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.safebrowsing-palm-smalltext {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
#safebrowsing-palm-google-logo {
|
||||
height: 32px;
|
||||
max-height: 32px;
|
||||
width: 78px;
|
||||
}
|
||||
|
||||
#safebrowsing-page-canvas {
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
#safebrowsing-dim-area-canvas {
|
||||
background-image: url("chrome://browser/skin/safebrowsing/dim.png");
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
#safebrowsing-urlbar-icon {
|
||||
padding: 1px 2px 1px 0;
|
||||
}
|
||||
|
||||
#safebrowsing-urlbar-icon[level="safe"] {
|
||||
list-style-image: none;
|
||||
}
|
||||
|
||||
#safebrowsing-urlbar-icon[level="warn"] {
|
||||
list-style-image: url("chrome://browser/skin/safebrowsing/warning16x16.png");
|
||||
}
|