Tip:
Highlight text to annotate it
X
content/branding/about.png IHDR tEXtSoftware Adobe ImageReadyq IDATx $@H2 m@C0 B7ju HR.RaV
xrek )k&xn% pNh!4 2[MVo3 g{kf $ejV ZF4i ~~sV$ J61_FF "`xpI wDag bw/M$~ 2OKPd 0T6~ a04~ .s^h
ZjVk6k 4O} } +Bb$ @tKl [an_ Ao)0 +ewZu B^dV#,kG S5Hy FO*sJ Xkk~ O-4X um;0 }N>w#x4 ?[&+M 8k]U
1C|R 1,Ax ;j,$ hR1` Vf+5 ?~e? Im]( 'ToUMk 0C(3IU )1/f= Lg`~+J m(E" }i}j ;+D]K +U~q uO&
l{\Sn BTG{ 5;fJ[ C@n. 6)El /hol mq)@ bZ5b6 I+Yc 6u@a rlibEj:$@ hjNo )Dr5 gFVB r5Z5 MpBD
I$A7\+ 6WL4 %4p0Gd +c=O C3ZW JfTy "/R" E;ML 7F~b Uom75# ZD'T[ E|S. 3!RdD9I z4k* qD0w [7$;
i-AO ?qT}cn P$2mJ @ZU5 `wcv %a18! eA11^W ItZ6 k0N[J -0qR(!M jodVa Px$p/r n*)^~ Q'6!(< ,Ajq
f|zQ -1gt ?1VI r7([K (&S= 9Xix m'csK(U fv7i 8vA#c ol`# TKin 'RsW wM~q #oxc3 vDl[6 :lMba p0V: f3=n. r)ix YP+"_ 4}9z JM/^ O'z:. .Z/V ]99J 9ia Qa-# 9piAl_ x&F'
5Ir7 Z@K4 '3=y u$1 &EL\V W\~v eKOz |njvH IRcK )a.5 -=ht+ x[MF "/0M )@p3 SI|G f1X- K9;y Zch=K[
WM'"o Ae}0n :eQx DK(D[e JvX4 9z/d K]Wv NN)2 )1H]1F C][jO (aZB [}Jt d/up r>o: t.8d X8]c
dT75 ,rq; ^SZFC51 $wT2 FSmr"Z'4 JgMq -AxM-a W?bq~b Mx-C H,*&:} VBh OovcCT a;]3h[ z3l4h-
>cLrQ_ %3]" eLxm-!) I-VV $"PbE mM`4 y?V{ -Ax--! VFXvQ\ f`K1] LD*u" DluD]/AxM bG;@ +A / gh
lS 2;vKv p)oq 9"YKa W>'n :z?b ] `@8 i}T, `IzF$ n\gJ 3mYH -@A? y9,T; xKwSY&\ 6RE: c~1LPm xFm^`
5-~Q Y+>v# 4>NZ _(Z] /DPx s_ji {_xM U[xj Bu8u lcF[ 7x= }T;5+ Fi,e A}^] 6G)$ X9~_6 buup TvwR RSkz[ C5OW zbf)Z: o5;@B QWNi Hm0k
%MAAQ o}du hO~U Yv{j V4R"S& EX lrcxa z+I} eb`a Up"WT 4wMF %qeh 7+6X xs>T
+5@N _-#B hM.l3&c P)iw *j6C Ugt?'Jx{)I oivm P%[Z E}._ >}bI Tt4T De5*l uzMew b"R$t,H
HmOD !/%h fjZy*M t>YQK !FB^j5g` >eTt k}1w Qn'dR L2R* :#fg 6I0k `xvF @usB g;0]x] `Q;I
v%ASz #y'l \s=Rm vC ,wAx rS$L TwAx &%4Q W,T= GB?mo ?)'9 %78 5|D1 51oa 3qk. I*1/
Z5 ( 8T\F 1qf0Q0 .G$; W].J1 tt4) rSVj zY86 fzryo E#77Q %HS6 gN>x SRt} RV;b 0D }6 DmC"z
a;Fk} u:lW +x`#B pb ktG= hn1iw (NTY 22!Q JS%r\ N1A5 HS-d Uy>: Cwvoy .rb0
.[-9;/{sq 0xlaG~v ,vtc YsK$ Ik_Ov ~+9p "-{8P N|U% (>q?{ Aw5x$ d2|t}| N7.LvJ$o dZ X`s9 {QGJ M_]\> 29g< ,.\L 6T}"1 qu0? IL9#& OGsN{ a/|X /"\kR Zq+2 {m{7
*1WG{z, 1O4J ;C\= Nj;] "'xb `hcI B!mFh l/ID &egOk~/_8\> ym&B6." `~H: ;k@# v{^$ 1fphb]
Mo}Z W.1Ti 5KOZ*aJ pzpopr Fvg`v KM~ "6YI a~F~ "pNL~? ULCqK HsJ;1 ?>LJCL Nmu?1y v/qf sATq
ZQb' buYG#k8 X9P{*K GQt% lT |ZA g6pj \L3Q I&JV }kbYw z!5r %BMXB pZ-n ac&i
H@`, L26Dl YkCu jf"0|` #)D\ ~L)9 67Z_* xM({ Ozdx yGg): ,^56C@ "QL/@ /47] r`mu LL-O `lgLy Mb;d 2l^_ *"d? .6\{ ,Qp0z5 ~,>u A:eCt QU?a {?^
=3EK 8OLr P/zXs =eZ(Y L};)A )S,HC (4`M >2z/N X:pLiv
0(N'pZ w5s% vFLE ;a@kf \ZBk~^ {rvl dQ3{b piKF ZBf4G FlB% KYXV K)T,7a8 1" > 9hE( 'N{` M mF2 MmyO 2"`J TT-' :RgHg G5bY]^
(N{H: h tCV PZ[& X"AV V ((@' NDa` Ia[a |s#Fk @eZe tk?W QI)j C~#E .`eo '?]fAX W_J; %]{}F
cHh> tJ]V^ fbv5
51!S E$^*H `a}O s>C# X!#Ex (1=n= K&KB_0 >:BP RUaHHeH |W:q `(Kh k.nE %)kF8 Yh)t -OND 2dT*
qMj+ 23DEC DP'q >8\GP1 y`x5 *I,Z o5x- nnh- nM7W *-z< Q#SQ "LDW5 TRC< yE6q=A (ctr m; ^\XI .b$@ $G,_ ZAN< &A"# Q#eH%Dk )@S^ ,b=YX5 gmai05 Wr}/ HL!y
6F7,t (:=:G {#V. &robots.errorTitleText;
&robots.errorShortDescText; &robots.errorLongDesc1; &robots.errorLongDesc2;
&robots.errorLongDesc3; &robots.errorLongDesc4; &robots.errorTrailerDescText; GT4Y& content/browser/aboutRobots-icon.png IHDR
IDATx $:!R X%-#i u_Xk +3w\ >944 QUE~ s(+/D^U JYI{ FNn&ee &J"-3 \GwW3 //^T 'Wfn L&5# EISc-5
-Jz{[ MEG[= udZZt !%_LFF2 0uu2*+KhmQ> BFII %Dq8% R?>{s w0yh 855NMM ?TE.{mW \K+@ A}#Nh
A[[= 3_e\ Crj< eD \*J$H U4(+ -GQSNmM9J
kP7V XCkS- M547U { &G9~D HXfH In]> sGGQ -5B6 2tTOn {vaac x3guL9 Y=3N t-pT
In\< 93>@ "ZjH EII. Q[+EYW RSSNuu955 U47) S)+!-= $Q:q bI:E -tu4 prsz 2E)d TUOhu uD6v
0e;nY V4S+/ etw6 HI%u 17W9 L(Zl @L|$ @\K/ _NHU 2JJrikU :L`y JriQ+ T.6cj MHD Nii. t!$"
"?_Ln I)qx #CBpi [$#V ,1&o Mzf2 OoWB" /"47 R#DK GbJ< QYYDQq XKSc-*U 'M8- &d.5"q +[+ IDATLQ UEsc SYYLYY 'WD^ OEE! RGaQ ~2"_LN^&
EIaQ6 RUUJyy! +"+'Sc N#)% A,N!=3 Cc=L -tu5 JjF" &hZt D\|$2Y R5)5 n^n= GTt(Y L&5- LbJ,1
g7.nN )N%)- LjZ ORj *FVQ@ JjZC[ H!@H "B(B5K fh1^}G dgv{} J)N--1
(LI) )yQ DM w]u9 cE+b*V GW(6V &+0XV OYD[ C*%9)Jv S\@! -T=H #F9( W9~| #$FX 4,LAe 6*aY eZa*C
d@FK W80y {!V@ MZeIV |9CX ;w-p )Cl% !?pc cv/l _VJ) c,yY"rIYV8 m8z|q $EM~ JSYC c&'&i6# }SP((}A
(/$I xHvo .Z+< uX$E _bG!E. AQAv XG&!V 8,A{ /2U= 9pNPjx rd4 b*Ce* fy-{ mvnu 2)j8 .2J!
'>y3 c-eYR %EYRm^L `*3~_ _J|g h?@{>R $AG! 8kX{ cZS3(- TEN2 >X{~ 33KU J+V66 n\(}@ mUmpH
o4j$ G0e1 [`ff (KFqL fgPJ2 A)EYUdyNe+| 4r;g1V` J,v, FqL
%aboutSupportDTD; &aboutSupport.pageTitle;
pref2.name) return 1; return 0; let sortedPrefs
= modifiedPrefs.sort(comparePrefs); let trPrefs = []; sortedPrefs.forEach(function (pref)
{ let tdName = createElement("td", pref.name, "pref-name"); let tdValue = createElement("td",
formatPrefValue(pref.value), "pref-value"); let tr = createParentElement("tr", [tdName,
tdValue]); trPrefs.push(tr); }); appendChildren(document.getElementById("prefs-tbody"), trPrefs); function formatPrefValue(prefValue)
{ // Some pref values are really long and don't have spaces. This can cause // problems
when copying and pasting into some WYSIWYG editors. In general // the exact contents
of really long pref values aren't particularly useful, // so we truncate them to some reasonable
length. let maxPrefValueLen = 120; let text = "" + prefValue; if (text.length > maxPrefValueLen)
text = text.substring(0, maxPrefValueLen) + " return text; function getModifiedPrefs()
{ // We use the low-level prefs API to identify prefs that have been // modified, rather that
Application.prefs.all since the latter is // much, much slower. Application.prefs.all
also gets slower each // time it's called. See bug 517312. let prefService = Cc["@mozilla.org/preferences-service;1"]
.getService(Ci.nsIPrefService); let prefRootBranch = prefService.getBranch(""); let prefNames
= getWhitelistedPrefNames(prefRootBranch); let prefs = [Application.prefs.get(prefName)
for each (prefName in prefNames) if (prefRootBranch.prefHasUserValue(prefName) && !isBlacklisted(prefName))]; return prefs;
function getWhitelistedPrefNames(prefRootBranch) { let results = []; PREFS_WHITELIST.forEach(function
(prefStem) { let prefNames = prefRootBranch.getChildList(prefStem, {}); results = results.concat(prefNames);
}); return results; function isBlacklisted(prefName) { return PREFS_BLACKLIST.some(function (re)
re.test(prefName)); function createParentElement(tagName, childElems) { let elem = document.createElement(tagName);
appendChildren(elem, childElems); return elem; function createElement(tagName, textContent,
opt_class) { let elem = document.createElement(tagName); elem.textContent = textContent; elem.className
= opt_class || ""; return elem; function appendChildren(parentElem, childNodes) {
for (let i = 0; i < childNodes.length; i++) parentElem.appendChild(childNodes[i]); function
copyContentsToClipboard() { // Get the HTML and text representations for the important
part of the page. let contentsDiv = document.getElementById("contents"); let dataHtml = contentsDiv.innerHTML; let
dataText = createTextForElement(contentsDiv); // We can't use plain strings, we have to
use nsSupportsString. let supportsStringClass = Cc["@mozilla.org/supports-string;1"]; let
ssHtml = supportsStringClass.createInstance(Ci.nsISupportsString); let ssText = supportsStringClass.createInstance(Ci.nsISupportsString);
let transferable = Cc["@mozilla.org/widget/transferable;1"] .createInstance(Ci.nsITransferable); // Add
the HTML flavor. transferable.addDataFlavor("text/html"); ssHtml.data = dataHtml; transferable.setTransferData("text/html",
ssHtml, dataHtml.length * 2); // Add the plain text flavor. transferable.addDataFlavor("text/unicode");
ssText.data = dataText; transferable.setTransferData("text/unicode", ssText, dataText.length * 2); // Store the
data into the clipboard. let clipboard = Cc["@mozilla.org/widget/clipboard;1"] .getService(Ci.nsIClipboard);
clipboard.setData(transferable, null, clipboard.kGlobalClipboard); // Return the plain text representation of
an element. Do a little bit // of pretty-printing to make it human-readable. function createTextForElement(elem)
{ // Generate the initial text. let textFragmentAccumulator = []; generateTextForElement(elem, "", textFragmentAccumulator);
let text = textFragmentAccumulator.join(""); // Trim extraneous whitespace before newlines,
then squash extraneous // blank lines. text = text.replace(/[ \t]+\n/g, "\n"); text
= text.replace(/\n\n\n+/g, "\n\n"); // Actual CR/LF pairs are needed for some Windows text
editors. text = text.replace(/\n/g, "\r\n"); return text; function generateTextForElement(elem,
indent, textFragmentAccumulator) { // Add a little extra spacing around most elements.
if (elem.tagName != "td") textFragmentAccumulator.push("\n"); // Generate the text representation for each
child node. let node = elem.firstChild; while (node) { if (node.nodeType == Node.TEXT_NODE)
{ // Text belonging to this element uses its indentation level. generateTextForTextNode(node,
indent, textFragmentAccumulator); } else if (node.nodeType == Node.ELEMENT_NODE) { //
Recurse on the child element with an extra level of indentation. generateTextForElement(node,
indent + " ", textFragmentAccumulator); } // Advance! node = node.nextSibling; function
generateTextForTextNode(node, indent, textFragmentAccumulator) { // If the text node is the first of a run
of text nodes, then start // a new line and add the initial indentation. let prevNode
= node.previousSibling; if (!prevNode || prevNode.nodeType == Node.TEXT_NODE) textFragmentAccumulator.push("\n"
+ indent); // Trim the text node's text content and add proper indentation after // any internal
line breaks. let text = node.textContent.trim().replace("\n", "\n" + indent, "g"); textFragmentAccumulator.push(text);
function openProfileDirectory() { // Get the profile directory. let propertiesService
= Cc["@mozilla.org/file/directory_service;1"] .getService(Ci.nsIProperties); let currProfD
= propertiesService.get("ProfD", Ci.nsIFile); let profileDir = currProfD.path; // Show the
profile directory. let nsLocalFile = Components.Constructor("@mozilla.org/file/local;1", "nsILocalFile", "initWithPath"); new nsLocalFile(profileDir).reveal();
]]> &aboutSupport.pageTitle;
&aboutSupport.pageSubtitle; &aboutSupport.copyToClipboard.label;
&aboutSupport.appBasicsTitle;
&aboutSupport.appBasicsName; &aboutSupport.appBasicsVersion;
&aboutSupport.appBasicsProfileDir;
&aboutSupport.show.label;
&aboutSupport.appBasicsPlugins; about:plugins
&aboutSupport.appBasicsBuildConfig; about:buildconfig
&aboutSupport.extensionsTitle; &aboutSupport.extensionName;
&aboutSupport.extensionVersion; &aboutSupport.extensionEnabled;
&aboutSupport.extensionId;
&aboutSupport.modifiedPrefsTitle;
&aboutSupport.modifiedPrefsName; &aboutSupport.modifiedPrefsValue;
toolbaritem
> hbox[type="places"] { display: none; #main-window:-moz-lwtheme { background-repeat: no-repeat; background-position:
top right; #browser-bottombox[lwthemefooter="true"] { background-repeat: no-repeat; background-position:
bottom left; /* ::::: location bar ::::: */ #urlbar { -moz-binding: url(chrome://browser/content/urlbarBindings.xml#urlbar);
#wrapper-urlbar-container > #urlbar-container > #urlbar { -moz-user-input: disabled; cursor:
-moz-grab; #PopupAutoComplete { -moz-binding: url("chrome://browser/content/urlbarBindings.xml#browser-autocomplete-result-popup");
#PopupAutoCompleteRichResult { -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; #feed-button
> .button-box > .box-inherit > .button-text, #feed-button > .button-box > .button-menu-dropmarker
{ display: none; #feed-menu > .feed-menuitem:-moz-locale-dir(rtl) { direction: rtl; #urlbar[pageproxystate="invalid"]
> #urlbar-icons > .urlbar-icon:not(#go-button), #urlbar[pageproxystate="valid"] > #urlbar-icons
> #go-button , #urlbar[isempty="true"] > #urlbar-icons > #go-button { visibility:
collapse; #identity-box-inner { max-width: 22em; min-width: 1px; #wrapper-search-container
> #search-container > #searchbar > .searchbar-textbox > .autocomplete-textbox-container > .textbox-input-box
> html|*.textbox-input { visibility: hidden; /* ::::: Unified Back-/Forward Button :::::
*/ #back-button > .toolbarbutton-menu-dropmarker, #forward-button > .toolbarbutton-menu-dropmarker,
#back-forward-dropmarker > .toolbarbutton-icon, #back-forward-dropmarker > .toolbarbutton-text
{ display: none; .unified-nav-current { font-weight: bold; #editBMPanel_tagsSelector
{ /* override default listbox width from xul.css */ width: auto; menuitem.spell-suggestion
{ font-weight: bold; #sidebar-box toolbarbutton.tabs-closebutton { -moz-user-focus: normal; /* apply Fitts'
law to the notification bar's close button */ window[sizemode="maximized"] #content
.notification-inner { border-right: 0px !important; /* Hide extension toolbars that neglected
to set the proper class */ window[chromehidden~="location"][chromehidden~="toolbar"] toolbar:not(.chromeclass-menubar), window[chromehidden~="toolbar"]
toolbar:not(.toolbar-primary):not(.chromeclass-menubar) { display: none; #navigator-toolbox , #status-bar
, #mainPopupSet { min-width: 1px; /* Identity UI */ #identity-popup-content-box.unknownIdentity
> #identity-popup-connectedToLabel , #identity-popup-content-box.unknownIdentity > #identity-popup-runByLabel , #identity-popup-content-box.unknownIdentity
> #identity-popup-content-host , #identity-popup-content-box.unknownIdentity > #identity-popup-content-owner , #identity-popup-content-box.verifiedIdentity
> #identity-popup-connectedToLabel2 , #identity-popup-content-box.verifiedDomain > #identity-popup-connectedToLabel2 { display:
none; /* Full Screen UI */ #fullscr-toggler { display: none; min-height: 5px; height:
5px; #navigator-toolbox[inFullscreen="true"] > #fullscr-toggler, #nav-bar[mode="text"]
> #window-controls > toolbarbutton > .toolbarbutton-icon { display: -moz-box; #nav-bar[mode="text"]
> #window-controls > toolbarbutton > .toolbarbutton-text { display: none; /* ::::: Keyboard UI Panel
::::: */ .KUI-panel-closebutton { -moz-binding: url("chrome://global/content/bindings/toolbarbutton.xml#toolbarbutton-image");
.ctrlTab-preview > html|canvas, .allTabs-preview > html|canvas { min-width: inherit; max-width:
inherit; min-height: inherit; max-height: inherit; .ctrlTab-favicon-container, .allTabs-favicon-container
{ -moz-box-align: start; -moz-box-pack: start; .ctrlTab-favicon, .allTabs-favicon { width:
16px; height: 16px; /* ::::: Ctrl-Tab Panel ::::: */ .ctrlTab-preview { -moz-binding:
url("chrome://browser/content/browser-tabPreviews.xml#ctrlTab-preview"); /* ::::: All Tabs Panel ::::: */ .allTabs-preview
{ -moz-binding: url("chrome://browser/content/browser-tabPreviews.xml#allTabs-preview"); vertical-align: top; #allTabs-tab-close-button
{ -moz-binding: url("chrome://global/content/bindings/toolbarbutton.xml#toolbarbutton-image"); margin: 0; #allTabs-container { display: block;
content/browser/browser.js//@line 67 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js" let Ci = Components.interfaces; let Cu =
Components.utils; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); const nsIWebNavigation = Ci.nsIWebNavigation;
var gCharsetMenu = null; var gLastBrowserCharset = null; var gPrevCharset = null; var gProxyFavIcon
= null; var gLastValidURLStr = ""; var gProgressCollapseTimer = null; var gSidebarCommand = ""; var gInPrintPreviewMode
= false; let gDownloadMgr = null; // Global variable that holds the nsContextMenu instance.
var gContextMenu = null; var gChromeState = null; // chrome state before we went into
print preview var gAutoHideTabbarPrefListener = null; var gBookmarkAllTabsHandler = null;
//@line 93 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js" var gEditUIVisible = true; //@line 95 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js"
["gBrowser", "content"], ["gNavToolbox", "navigator-toolbox"], ["gURLBar", "urlbar"], ["gNavigatorBundle",
"bundle_browser"], ["gProgressMeterPanel", "statusbar-progresspanel"], ["gFindBar", "FindToolbar"]
].forEach(function (elementGlobal) { var [name, id] = elementGlobal; window.__defineGetter__(name,
function () { var element = document.getElementById(id); if (!element) return null; delete window[name];
return window[name] = element; }); window.__defineSetter__(name, function (val) { delete window[name]; return
window[name] = val; }); __defineGetter__("gPrefService", function() { delete this.gPrefService; return
this.gPrefService = Cc["@mozilla.org/preferences-service;1"] .getService(Ci.nsIPrefBranch2) .QueryInterface(Ci.nsIPrefService);
__defineGetter__("PluralForm", function() { Cu.import("resource://gre/modules/PluralForm.jsm");
return this.PluralForm; __defineSetter__("PluralForm", function (val) { delete this.PluralForm; return
this.PluralForm = val; //@line 135 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js" __defineGetter__("gCrashReporter", function()
{ delete this.gCrashReporter; return this.gCrashReporter = Cc["@mozilla.org/xre/app-info;1"]. getService(Ci.nsICrashReporter_MOZILLA_1_9_2_BRANCH);
//@line 141 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js" let gInitialPages = [ "about:blank", "about:privatebrowsing",
"about:sessionrestore" * We can avoid adding multiple load event listeners and save some
time by adding * one listener that calls all real handlers. function pageShowEventHandlers(event)
{ // Filter out events that are not about the document load we are interested in if
(event.originalTarget == content.document) { charsetLoadListener(event); XULBrowserWindow.asyncUpdateUI();
* Determine whether or not the content area is displaying a page with frames, * and if
so, toggle the display of the 'save frame as' menu item. **/ function getContentAreaFrameCount()
var saveFrameItem = document.getElementById("menu_saveFrame"); if (!content || !content.frames.length ||
!isContentFrame(document.commandDispatcher.focusedWindow)) saveFrameItem.setAttribute("hidden", "true");
else saveFrameItem.removeAttribute("hidden"); function UpdateBackForwardCommands(aWebNavigation)
{ var backBroadcaster = document.getElementById("Browser:Back"); var forwardBroadcaster = document.getElementById("Browser:Forward");
// Avoid setting attributes on broadcasters if the value hasn't changed! // Remember,
guys, setting attributes on elements is expensive! They // get inherited into anonymous content,
broadcast to other widgets, etc.! // Don't do it if the value hasn't changed! - dwh var
backDisabled = backBroadcaster.hasAttribute("disabled"); var forwardDisabled = forwardBroadcaster.hasAttribute("disabled");
if (backDisabled == aWebNavigation.canGoBack) { if (backDisabled) backBroadcaster.removeAttribute("disabled");
else backBroadcaster.setAttribute("disabled", true); if (forwardDisabled == aWebNavigation.canGoForward)
{ if (forwardDisabled) forwardBroadcaster.removeAttribute("disabled"); else forwardBroadcaster.setAttribute("disabled",
true); //@line 271 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js" function BookmarkThisTab() { PlacesCommandHook.bookmarkPage(gBrowser.mContextTab.linkedBrowser,
PlacesUtils.bookmarksMenuFolderId, true); const gSessionHistoryObserver = { observe:
function(subject, topic, data) if (topic != "browser:purge-session-history") return;
var backCommand = document.getElementById("Browser:Back"); backCommand.setAttribute("disabled", "true");
var fwdCommand = document.getElementById("Browser:Forward"); fwdCommand.setAttribute("disabled", "true");
if (gURLBar) { // Clear undo history of the URL bar gURLBar.editor.transactionManager.clear()
} * Given a starting docshell and a URI to look up, find the docshell the URI * is loaded
in. * @param aDocument * A document to find instead of using just a URI - this is more
specific. * @param aDocShell * The doc shell to start at * @param aSoughtURI * The URI
that we're looking for * @returns The doc shell that the sought URI is loaded in. Can
be in * subframes. function findChildShell(aDocument, aDocShell, aSoughtURI) { aDocShell.QueryInterface(Components.interfaces.nsIWebNavigation);
aDocShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor); var doc = aDocShell.getInterface(Components.interfaces.nsIDOMDocument);
if ((aDocument && doc == aDocument) || (aSoughtURI && aSoughtURI.spec == aDocShell.currentURI.spec))
return aDocShell; var node = aDocShell.QueryInterface(Components.interfaces.nsIDocShellTreeNode); for (var i = 0; i < node.childCount; ++i)
{ var docShell = node.getChildAt(i); docShell = findChildShell(aDocument, docShell, aSoughtURI);
if (docShell) return docShell; return null; const gPopupBlockerObserver = { _reportButton:
null, _kIPM: Components.interfaces.nsIPermissionManager, onUpdatePageReport: function (aEvent) if (aEvent.originalTarget
!= gBrowser.selectedBrowser) return; if (!this._reportButton) this._reportButton = document.getElementById("page-report-button");
if (!gBrowser.pageReport) { // Hide the popup blocker statusbar button this._reportButton.hidden
= true; return; } this._reportButton.hidden = false; // Only show the notification again
if we've not already shown it. Since // notifications are per-browser, we don't need to worry about
re-adding // it. if (!gBrowser.pageReport.reported) { if (gPrefService.getBoolPref("privacy.popups.showBrowserMessage"))
{ var brandBundle = document.getElementById("bundle_brand"); var brandShortName = brandBundle.getString("brandShortName");
var message; var popupCount = gBrowser.pageReport.length; //@line 356 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js"
var popupButtonText = gNavigatorBundle.getString("popupWarningButton"); var popupButtonAccesskey = gNavigatorBundle.getString("popupWarningButton.accesskey");
//@line 362 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js" if (popupCount > 1) message = gNavigatorBundle.getFormattedString("popupWarningMultiple",
[brandShortName, popupCount]); else message = gNavigatorBundle.getFormattedString("popupWarning",
[brandShortName]); var notificationBox = gBrowser.getNotificationBox(); var notification
= notificationBox.getNotificationWithValue("popup-blocked"); if (notification) { notification.label =
message; } else { var buttons = [{ label: popupButtonText, accessKey: popupButtonAccesskey,
popup: "blockedPopupOptions", callback: null }]; const priority = notificationBox.PRIORITY_WARNING_MEDIUM;
notificationBox.appendNotification(message, "popup-blocked", "chrome://browser/skin/Info.png",
priority, buttons); } } // Record the fact that we've reported this blocked popup, so
we don't // show it again. gBrowser.pageReport.reported = true; } }, toggleAllowPopupsForSite: function
(aEvent) var currentURI = gBrowser.selectedBrowser.webNavigation.currentURI; var pm = Components.classes["@mozilla.org/permissionmanager;1"]
.getService(this._kIPM); var shouldBlock = aEvent.target.getAttribute("block") ==
"true"; var perm = shouldBlock ? this._kIPM.DENY_ACTION : this._kIPM.ALLOW_ACTION; pm.add(currentURI,
"popup", perm); gBrowser.getNotificationBox().removeCurrentNotification(); }, fillPopupList: function (aEvent) // XXXben
- rather than using |currentURI| here, which breaks down on multi-framed sites // we should
really walk the pageReport and create a list of "allow for " // menuitems for the
common subset of hosts present in the report, this will // make us frame-safe. // // XXXjst
- Note that when this is fixed to work with multi-framed sites, // also back out the fix
for bug 343772 where // nsGlobalWindow::CheckOpenAllow() was changed to also // check if the top window's
location is whitelisted. var uri = gBrowser.selectedBrowser.webNavigation.currentURI; var blockedPopupAllowSite = document.getElementById("blockedPopupAllowSite");
try { blockedPopupAllowSite.removeAttribute("hidden"); var pm = Cc["@mozilla.org/permissionmanager;1"].getService(this._kIPM);
if (pm.testPermission(uri, "popup") == this._kIPM.ALLOW_ACTION) { // Offer an item to block popups for this
site, if a whitelist entry exists // already for it. let blockString = gNavigatorBundle.getFormattedString("popupBlock",
[uri.host]); blockedPopupAllowSite.setAttribute("label", blockString); blockedPopupAllowSite.setAttribute("block",
"true"); } else { // Offer an item to allow popups for this site let allowString = gNavigatorBundle.getFormattedString("popupAllow",
[uri.host]); blockedPopupAllowSite.setAttribute("label", allowString); blockedPopupAllowSite.removeAttribute("block");
} } catch (e) { blockedPopupAllowSite.setAttribute("hidden", "true"); } if (gPrivateBrowsingUI.privateBrowsingEnabled)
blockedPopupAllowSite.setAttribute("disabled", "true"); else blockedPopupAllowSite.removeAttribute("disabled");
var item = aEvent.target.lastChild; while (item && item.getAttribute("observes") !=
"blockedPopupsSeparator") { var next = item.previousSibling; item.parentNode.removeChild(item); item =
next; } var foundUsablePopupURI = false; var pageReport = gBrowser.pageReport; if (pageReport)
{ for (var i = 0; i < pageReport.length; ++i) { var popupURIspec = pageReport[i].popupWindowURI.spec;
// Sometimes the popup URI that we get back from the pageReport // isn't useful (for instance,
netscape.com's popup URI ends up // being "http://www.netscape.com", which isn't really
the URI of // the popup they're trying to show). This isn't going to be // useful to
the user, so we won't create a menu item for it. if (popupURIspec == "" || popupURIspec
== "about:blank" || popupURIspec == uri.spec) continue; // Because of the short-circuit
above, we may end up in a situation // in which we don't have any usable popup addresses
to show in // the menu, and therefore we shouldn't show the separator. However, // since we got
past the short-circuit, we must've found at least // one usable popup URI and thus we'll
turn on the separator later. foundUsablePopupURI = true; var menuitem = document.createElement("menuitem");
var label = gNavigatorBundle.getFormattedString("popupShowPopupPrefix", [popupURIspec]); menuitem.setAttribute("label",
label); menuitem.setAttribute("popupWindowURI", popupURIspec); menuitem.setAttribute("popupWindowFeatures",
pageReport[i].popupWindowFeatures); menuitem.setAttribute("popupWindowName", pageReport[i].popupWindowName); menuitem.setAttribute("oncommand",
"gPopupBlockerObserver.showBlockedPopup(event);"); menuitem.requestingWindow = pageReport[i].requestingWindow;
menuitem.requestingDocument = pageReport[i].requestingDocument; aEvent.target.appendChild(menuitem); } }
// Show or hide the separator, depending on whether we added any // showable popup addresses
to the menu. var blockedPopupsSeparator = document.getElementById("blockedPopupsSeparator");
if (foundUsablePopupURI) blockedPopupsSeparator.removeAttribute("hidden"); else blockedPopupsSeparator.setAttribute("hidden",
true); var blockedPopupDontShowMessage = document.getElementById("blockedPopupDontShowMessage");
var showMessage = gPrefService.getBoolPref("privacy.popups.showBrowserMessage"); blockedPopupDontShowMessage.setAttribute("checked",
!showMessage); if (aEvent.target.localName == "popup") blockedPopupDontShowMessage.setAttribute("label",
gNavigatorBundle.getString("popupWarningDontShowFromMessage")); else blockedPopupDontShowMessage.setAttribute("label",
gNavigatorBundle.getString("popupWarningDontShowFromStatusbar")); }, showBlockedPopup: function (aEvent) var
target = aEvent.target; var popupWindowURI = target.getAttribute("popupWindowURI");
var features = target.getAttribute("popupWindowFeatures"); var name = target.getAttribute("popupWindowName");
var dwi = target.requestingWindow; // If we have a requesting window and the requesting
document is // still the current document, open the popup. if (dwi && dwi.document ==
target.requestingDocument) { dwi.open(popupWindowURI, name, features); } }, editPopupSettings: function
() var host = ""; try { var uri = gBrowser.selectedBrowser.webNavigation.currentURI; host = uri.host; } catch (e) { } var bundlePreferences
= document.getElementById("bundle_preferences"); var params = { blockVisible : false, sessionVisible
: false, allowVisible : true, prefilledHost : host, permissionType : "popup", windowTitle
: bundlePreferences.getString("popuppermissionstitle"), introText : bundlePreferences.getString("popuppermissionstext")
}; var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] .getService(Components.interfaces.nsIWindowMediator);
var existingWindow = wm.getMostRecentWindow("Browser:Permissions"); if (existingWindow) { existingWindow.initWithParams(params);
existingWindow.focus(); } else window.openDialog("chrome://browser/content/preferences/permissions.xul", "_blank", "resizable,dialog=no,centerscreen",
params); }, dontShowMessage: function () var showMessage = gPrefService.getBoolPref("privacy.popups.showBrowserMessage");
var firstTime = gPrefService.getBoolPref("privacy.popups.firstTime"); // If the info message is showing at the
top of the window, and the user has never // hidden the message before, show an info
box telling the user where the info // will be displayed. if (showMessage && firstTime)
this._displayPageReportFirstTime(); gPrefService.setBoolPref("privacy.popups.showBrowserMessage", !showMessage); gBrowser.getNotificationBox().removeCurrentNotification();
}, _displayPageReportFirstTime: function () window.openDialog("chrome://browser/content/pageReportFirstTime.xul",
"_blank", "dependent"); const gXPInstallObserver = { _findChildShell: function (aDocShell,
aSoughtShell) if (aDocShell == aSoughtShell) return aDocShell; var node = aDocShell.QueryInterface(Components.interfaces.nsIDocShellTreeNode);
for (var i = 0; i < node.childCount; ++i) { var docShell = node.getChildAt(i); docShell
= this._findChildShell(docShell, aSoughtShell); if (docShell == aSoughtShell) return docShell;
} return null; }, _getBrowser: function (aDocShell) for (var i = 0; i < gBrowser.browsers.length;
++i) { var browser = gBrowser.getBrowserAtIndex(i); if (this._findChildShell(browser.docShell,
aDocShell)) return browser; } return null; }, observe: function (aSubject, aTopic, aData)
var brandBundle = document.getElementById("bundle_brand"); switch (aTopic) { case "xpinstall-install-blocked":
var installInfo = aSubject.QueryInterface(Components.interfaces.nsIXPIInstallInfo); var win = installInfo.originatingWindow; var
shell = win.QueryInterface(Components.interfaces.nsIInterfaceRequestor) .getInterface(Components.interfaces.nsIWebNavigation)
.QueryInterface(Components.interfaces.nsIDocShell); var browser = this._getBrowser(shell); if
(browser) { var host = installInfo.originatingURI.host; var brandShortName = brandBundle.getString("brandShortName");
var notificationName, messageString, buttons; if (!gPrefService.getBoolPref("xpinstall.enabled"))
{ notificationName = "xpinstall-disabled" if (gPrefService.prefIsLocked("xpinstall.enabled"))
{ messageString = gNavigatorBundle.getString("xpinstallDisabledMessageLocked"); buttons = []; } else { messageString = gNavigatorBundle.getFormattedString("xpinstallDisabledMessage",
[brandShortName, host]); buttons = [{ label: gNavigatorBundle.getString("xpinstallDisabledButton"),
accessKey: gNavigatorBundle.getString("xpinstallDisabledButton.accesskey"), popup: null, callback: function editPrefs()
{ gPrefService.setBoolPref("xpinstall.enabled", true); return false; } }]; } } else { notificationName
= "xpinstall" messageString = gNavigatorBundle.getFormattedString("xpinstallPromptWarning", [brandShortName, host]); buttons = [{ label:
gNavigatorBundle.getString("xpinstallPromptAllowButton"), accessKey: gNavigatorBundle.getString("xpinstallPromptAllowButton.accesskey"),
popup: null, callback: function() { var mgr = Components.classes["@mozilla.org/xpinstall/install-manager;1"]
.createInstance(Components.interfaces.nsIXPInstallManager); mgr.initManagerWithInstallInfo(installInfo);
return false; } }]; } var notificationBox = gBrowser.getNotificationBox(browser); if
(!notificationBox.getNotificationWithValue(notificationName)) { const priority = notificationBox.PRIORITY_WARNING_MEDIUM;
const iconURL = "chrome://mozapps/skin/update/update.png"; notificationBox.appendNotification(messageString,
notificationName, iconURL, priority, buttons); } } break; } // Simple gestures support
// As per bug #412486, web content must not be allowed to receive any // simple gesture
events. Multi-touch gesture APIs are in their // infancy and we do NOT want to be forced
into supporting an API that // will probably have to change in the future. (The current
Mac OS X // API is undocumented and was reverse-engineered.) Until support is // implemented in the event
dispatcher to keep these events as // chrome-only, we must listen for the simple gesture events
during // the capturing phase and call stopPropagation on every event. let gGestureSupport = { /**
* Add or remove mouse gesture event listeners * * @param aAddListener * True to add/init
listeners and false to remove/uninit */ init: function GS_init(aAddListener) { const gestureEvents
= ["SwipeGesture", "MagnifyGestureStart", "MagnifyGestureUpdate", "MagnifyGesture",
"RotateGestureStart", "RotateGestureUpdate", "RotateGesture", "TapGesture", "PressTapGesture"];
let addRemove = aAddListener ? window.addEventListener : window.removeEventListener; gestureEvents.forEach(function
(event) addRemove("Moz" + event, this, true), this); }, /** * Dispatch events based on the
type of mouse gesture event. For now, make * sure to stop propagation of every gesture
event so that web content cannot * receive gesture events. * * @param aEvent * The gesture
event to handle */ handleEvent: function GS_handleEvent(aEvent) { aEvent.stopPropagation(); // Create a preference
object with some defaults let def = function(aThreshold, aLatched) ({ threshold: aThreshold, latched:
!!aLatched }); switch (aEvent.type) { case "MozSwipeGesture": aEvent.preventDefault();
return this.onSwipe(aEvent); case "MozMagnifyGestureStart": aEvent.preventDefault(); //@line 720 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js"
return this._setupGesture(aEvent, "pinch", def(25, 0), "out", "in"); //@line 724 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js"
case "MozRotateGestureStart": aEvent.preventDefault(); return this._setupGesture(aEvent, "twist",
def(25, 0), "right", "left"); case "MozMagnifyGestureUpdate": case "MozRotateGestureUpdate": aEvent.preventDefault();
return this._doUpdate(aEvent); case "MozTapGesture": aEvent.preventDefault(); return this._doAction(aEvent,
["tap"]); case "MozPressTapGesture": // Fall through to default behavior return; } },
/** * Called at the start of "pinch" and "twist" gestures to setup all of the * information
needed to process the gesture * * @param aEvent * The continual motion start event to handle
* @param aGesture * Name of the gesture to handle * @param aPref * Preference object
with the names of preferences and defaults * @param aInc * Command to trigger for increasing
motion (without gesture name) * @param aDec * Command to trigger for decreasing motion
(without gesture name) */ _setupGesture: function GS__setupGesture(aEvent, aGesture, aPref,
aInc, aDec) { // Try to load user-set values from preferences for (let [pref, def] in Iterator(aPref))
aPref[pref] = this._getPref(aGesture + "." + pref, def); // Keep track of the total
deltas and latching behavior let offset = 0; let latchDir = aEvent.delta > 0 ? 1 :
-1; let isLatched = false; // Create the update function here to capture closure state
this._doUpdate = function GS__doUpdate(aEvent) { // Update the offset with new event data
offset += aEvent.delta; // Check if the cumulative deltas exceed the threshold if (Math.abs(offset)
> aPref["threshold"]) { // Trigger the action if we don't care about latching; otherwise,
make // sure either we're not latched and going the same direction of the // initial
motion; or we're latched and going the opposite way let sameDir = (latchDir ^ offset) >=
0; if (!aPref["latched"] || (isLatched ^ sameDir)) { this._doAction(aEvent, [aGesture,
offset > 0 ? aInc : aDec]); // We must be getting latched or leaving it, so just toggle
isLatched = !isLatched; } // Reset motion counter to prepare for more of the same gesture
offset = 0; } }; // The start event also contains deltas, so handle an update right away this._doUpdate(aEvent);
}, /** * Generator producing the powerset of the input array where the first result
* is the complete set and the last result (before StopIteration) is empty. * * @param
aArray * Source array containing any number of elements * @yield Array that is a subset
of the input array from full set to empty */ _power: function GS__power(aArray) {
// Create a bitmask based on the length of the array let num = 1 = 0) // Only select array elements where the current bit is set yield aArray.reduce(function(aPrev,
aCurr, aIndex) { if (num & 1 = 3) { loadURI(uriToLoad, window.arguments[2],
window.arguments[3] || null, window.arguments[4] || false); content.focus(); } // Note: loadOneOrMoreURIs
*must not* be called if window.arguments.length >= 3. // Such callers expect that window.arguments[0]
is handled as a single URI. else loadOneOrMoreURIs(uriToLoad); if (window.opener && !window.opener.closed)
{ let openerFindBar = window.opener.gFindBar; if (openerFindBar && !openerFindBar.hidden
&& openerFindBar.findMode == gFindBar.FIND_NORMAL) gFindBar.open(); let openerSidebarBox = window.opener.document.getElementById("sidebar-box");
// If the opener had a sidebar, open the same sidebar in our window. // The opener
can be the hidden window too, if we're coming from the state // where no windows are open,
and the hidden window has no sidebar box. if (openerSidebarBox && !openerSidebarBox.hidden)
{ let sidebarCmd = openerSidebarBox.getAttribute("sidebarcommand"); let sidebarCmdElem = document.getElementById(sidebarCmd);
// dynamically generated sidebars will fail this check. if (sidebarCmdElem) { let sidebarBox
= document.getElementById("sidebar-box"); let sidebarTitle = document.getElementById("sidebar-title");
sidebarTitle.setAttribute( "value", window.opener.document.getElementById("sidebar-title").getAttribute("value")); sidebarBox.setAttribute("width", openerSidebarBox.boxObject.width);
sidebarBox.setAttribute("sidebarcommand", sidebarCmd); // Note: we're setting 'src'
on sidebarBox, which is a , not on // the . This lets us
delay the actual load until // delayedStartup(). sidebarBox.setAttribute( "src", window.opener.document.getElementById("sidebar").getAttribute("src"));
mustLoadSidebar = true; sidebarBox.hidden = false; document.getElementById("sidebar-splitter").hidden
= false; sidebarCmdElem.setAttribute("checked", "true"); } } else { let box = document.getElementById("sidebar-box");
if (box.hasAttribute("sidebarcommand")) { let commandID = box.getAttribute("sidebarcommand");
if (commandID) { let command = document.getElementById(commandID); if (command) { mustLoadSidebar = true; box.hidden
= false; document.getElementById("sidebar-splitter").hidden = false; command.setAttribute("checked",
"true"); } else { // Remove the |sidebarcommand| attribute, because the element it // refers
to no longer exists, so we should assume this sidebar // panel has been uninstalled. (249883)
box.removeAttribute("sidebarcommand"); } } } // Certain kinds of automigration rely
on this notification to complete their // tasks BEFORE the browser window is shown.
Cc["@mozilla.org/observer-service;1"] .getService(Ci.nsIObserverService) .notifyObservers(null, "browser-window-before-show",
""); // Set a sane starting width/height for all resolutions on new profiles. if (!document.documentElement.hasAttribute("width"))
{ let defaultWidth = 994; let defaultHeight; if (screen.availHeight = 1600) defaultWidth = (screen.availWidth / 2) - 20; defaultHeight = screen.availHeight
- 10; //@line 1058 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js" } document.documentElement.setAttribute("width",
defaultWidth); document.documentElement.setAttribute("height", defaultHeight); if (gURLBar && document.documentElement.getAttribute("chromehidden").indexOf("toolbar")
!= -1) { gURLBar.setAttribute("readonly", "true"); gURLBar.setAttribute("enablehistory",
"false"); allTabs.readPref(); setTimeout(delayedStartup, 0, isLoadingBlank, mustLoadSidebar); function
HandleAppCommandEvent(evt) { evt.stopPropagation(); switch (evt.command) { case "Back": BrowserBack();
break; case "Forward": BrowserForward(); break; case "Reload": BrowserReloadSkipCache(); break;
case "Stop": BrowserStop(); break; case "Search": BrowserSearch.webSearch(); break; case "Bookmarks":
toggleSidebar('viewBookmarksSidebar'); break; case "Home": BrowserHome(); break; default:
break; function prepareForStartup() { var os = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
gBrowser.addEventListener("DOMUpdatePageReport", gPopupBlockerObserver.onUpdatePageReport,
false); // Note: we need to listen to untrusted events, because the pluginfinder XBL // binding
can't fire trusted ones (runs with page privileges). gBrowser.addEventListener("PluginNotFound",
gMissingPluginInstaller.newMissingPlugin, true, true); gBrowser.addEventListener("PluginCrashed",
gMissingPluginInstaller.pluginInstanceCrashed, true, true); gBrowser.addEventListener("PluginBlocklisted",
gMissingPluginInstaller.newMissingPlugin, true, true); gBrowser.addEventListener("PluginOutdated",
gMissingPluginInstaller.newMissingPlugin, true, true); gBrowser.addEventListener("PluginDisabled",
gMissingPluginInstaller.newDisabledPlugin, true, true); gBrowser.addEventListener("NewPluginInstalled",
gMissingPluginInstaller.refreshBrowser, false); os.addObserver(gMissingPluginInstaller, "plugin-crashed",
false); gBrowser.addEventListener("NewTab", BrowserOpenTab, false); window.addEventListener("AppCommand",
HandleAppCommandEvent, true); var webNavigation; try { webNavigation = getWebNavigation();
if (!webNavigation) throw "no XBL binding for browser"; } catch (e) { alert("Error launching
browser window:" + e); window.close(); // Give up. return; // initialize observers
and listeners // and give C++ access to gBrowser XULBrowserWindow.init(); window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(nsIWebNavigation) .QueryInterface(Ci.nsIDocShellTreeItem).treeOwner .QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIXULWindow) .XULBrowserWindow = window.XULBrowserWindow; window.QueryInterface(Ci.nsIDOMChromeWindow).browserDOMWindow
= new nsBrowserAccess(); // set default character set if provided if ("arguments" in window
&& window.arguments.length > 1 && window.arguments[1]) { if (window.arguments[1].indexOf("charset=")
!= -1) { var arrayArgComponents = window.arguments[1].split("="); if (arrayArgComponents) { //we should "inherit"
the charset menu setting in a new window getMarkupDocumentViewer().defaultCharacterSet = arrayArgComponents[1]; } } // Manually
hook up session and global history for the first browser // so that we don't have to
load global history before bringing up a // window. // Wire up session and global history
before any possible // progress notifications for back/forward button updating webNavigation.sessionHistory
= Components.classes["@mozilla.org/browser/shistory;1"] .createInstance(Components.interfaces.nsISHistory);
os.addObserver(gBrowser.browsers[0], "browser:purge-session-history", false); // remove the disablehistory attribute
so the browser cleans up, as // though it had done this work itself gBrowser.browsers[0].removeAttribute("disablehistory");
// enable global history try { gBrowser.docShell.QueryInterface(Components.interfaces.nsIDocShellHistory).useGlobalHistory = true; } catch(ex) { Components.utils.reportError("Places
database may be locked: " + ex); // hook up UI through progress listener gBrowser.addProgressListener(window.XULBrowserWindow,
Components.interfaces.nsIWebProgress.NOTIFY_ALL); gBrowser.addTabsProgressListener(window.TabsProgressListener);
// setup our common DOMLinkAdded listener gBrowser.addEventListener("DOMLinkAdded",
DOMLinkHandler, false); // setup our MozApplicationManifest listener gBrowser.addEventListener("MozApplicationManifest",
OfflineApps, false); // setup simple gestures support gGestureSupport.init(true); function
delayedStartup(isLoadingBlank, mustLoadSidebar) { var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
os.addObserver(gSessionHistoryObserver, "browser:purge-session-history", false); os.addObserver(gXPInstallObserver,
"xpinstall-install-blocked", false); BrowserOffline.init(); OfflineApps.init(); gBrowser.addEventListener("pageshow",
function(evt) { setTimeout(pageShowEventHandlers, 0, evt); }, true); // Ensure login manager
is up and running. Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager); if (mustLoadSidebar) { let sidebar = document.getElementById("sidebar");
let sidebarBox = document.getElementById("sidebar-box"); sidebar.setAttribute("src", sidebarBox.getAttribute("src"));
UpdateUrlbarSearchSplitterState(); PlacesStarButton.init(); // called when we go into full screen, even
if it is // initiated by a web page script window.addEventListener("fullscreen", onFullScreen,
true); if (isLoadingBlank && gURLBar && isElementVisible(gURLBar)) gURLBar.focus(); else gBrowser.selectedBrowser.focus();
if (gURLBar) gURLBar.emptyText = gURLBarEmptyText.value; gNavToolbox.customizeDone = BrowserToolboxCustomizeDone;
gNavToolbox.customizeChange = BrowserToolboxCustomizeChange; // Set up Sanitize Item initializeSanitizer();
// Enable/Disable auto-hide tabbar gAutoHideTabbarPrefListener = new AutoHideTabbarPrefListener(); gPrefService.addObserver(gAutoHideTabbarPrefListener.domain,
gAutoHideTabbarPrefListener, false); gPrefService.addObserver(gHomeButton.prefDomain, gHomeButton, false); gPrefService.addObserver(gURLBarEmptyText.domain,
gURLBarEmptyText, false); var homeButton = document.getElementById("home-button");
gHomeButton.updateTooltip(homeButton); gHomeButton.updatePersonalToolbarStyle(homeButton); //@line 1243 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js"
// Perform default browser checking (after window opens). var shell = getShellService();
if (shell) { var shouldCheck = shell.shouldCheckDefaultBrowser; var willRecoverSession = false; try { var
ss = Cc["@mozilla.org/browser/sessionstartup;1"]. getService(Ci.nsISessionStartup); willRecoverSession
= (ss.sessionType == Ci.nsISessionStartup.RECOVER_SESSION); } catch (ex) { /* never mind; suppose SessionStore
is broken */ } if (shouldCheck && !shell.isDefaultBrowser(true) && !willRecoverSession) { var brandBundle
= document.getElementById("bundle_brand"); var shellBundle = document.getElementById("bundle_shell");
var brandShortName = brandBundle.getString("brandShortName"); var promptTitle = shellBundle.getString("setDefaultBrowserTitle");
var promptMessage = shellBundle.getFormattedString("setDefaultBrowserMessage", [brandShortName]); var checkboxLabel = shellBundle.getFormattedString("setDefaultBrowserDontAsk",
[brandShortName]); const IPS = Components.interfaces.nsIPromptService; var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
.getService(IPS); var checkEveryTime = { value: shouldCheck }; var rv = ps.confirmEx(window,
promptTitle, promptMessage, IPS.STD_YES_NO_BUTTONS, null, null, null, checkboxLabel, checkEveryTime);
if (rv == 0) shell.setDefaultBrowser(true, false); shell.shouldCheckDefaultBrowser =
checkEveryTime.value; } //@line 1278 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js" // BiDi UI gBidiUI = isBidiEnabled(); if
(gBidiUI) { document.getElementById("documentDirection-separator").hidden = false; document.getElementById("documentDirection-swap").hidden
= false; document.getElementById("textfieldDirection-separator").hidden = false; document.getElementById("textfieldDirection-swap").hidden
= false; //@line 1294 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js" // Initialize the full zoom setting. //
We do this before the session restore service gets initialized so we can // apply full zoom
settings to tabs restored by the session restore service. try { FullZoom.init(); catch(ex)
{ Components.utils.reportError("Failed to init content pref service:\n" + ex); let NP
= {}; Cu.import("resource:///modules/NetworkPrioritizer.jsm", NP); NP.trackBrowserWindow(window); // initialize
the session-restore service (in case it's not already running) if (document.documentElement.getAttribute("windowtype")
== "navigator:browser") { try { var ss = Cc["@mozilla.org/browser/sessionstore;1"].
getService(Ci.nsISessionStore); ss.init(window); } catch(ex) { dump("nsSessionStore could
not be initialized: " + ex + "\n"); } // bookmark-all-tabs command gBookmarkAllTabsHandler
= new BookmarkAllTabsHandler(); // Attach a listener to watch for "command" events bubbling
up from error // pages. This lets us fix bugs like 401575 which require error page UI to
// do privileged things, without letting error pages have any privilege // themselves.
gBrowser.addEventListener("command", BrowserOnCommand, false); tabPreviews.init(); ctrlTab.readPref();
gPrefService.addObserver(ctrlTab.prefName, ctrlTab, false); gPrefService.addObserver(allTabs.prefName,
allTabs, false); // Initialize the microsummary service by retrieving it, prompting its factory
// to create its singleton, whose constructor initializes the service. // Started 4 seconds
after delayedStartup (before the livemarks service below). setTimeout(function() { try
{ Cc["@mozilla.org/microsummary/service;1"].getService(Ci.nsIMicrosummaryService); } catch (ex) { Components.utils.reportError("Failed
to init microsummary service:\n" + ex); } }, 4000); // Delayed initialization of the
livemarks update timer. // Livemark updates don't need to start until after bookmark UI
// such as the toolbar has initialized. Starting 5 seconds after // delayedStartup in order
to stagger this after the microsummary // service (see above) and before the download
manager starts (see below). setTimeout(function() PlacesUtils.livemarks.start(), 5000); //
Initialize the download manager some time after the app starts so that // auto-resume
downloads begin (such as after crashing or quitting with // active downloads) and speeds
up the first-load of the download manager UI. // If the user manually opens the download
manager before the timeout, the // downloads will start right away, and getting the service
again won't hurt. setTimeout(function() { gDownloadMgr = Cc["@mozilla.org/download-manager;1"].
getService(Ci.nsIDownloadManager); // Initialize the downloads monitor panel listener DownloadMonitorPanel.init();
}, 10000); // Delayed initialization of PlacesDBUtils. // This component checks for database coherence
once per day, on // an idle timer, taking corrective actions where needed. setTimeout(function()
PlacesUtils.startPlacesDBUtils(), 15000); //@line 1371 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js"
updateEditUIVisibility(); let placesContext = document.getElementById("placesContext");
placesContext.addEventListener("popupshowing", updateEditUIVisibility, false); placesContext.addEventListener("popuphiding",
updateEditUIVisibility, false); //@line 1376 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js"
// initialize the private browsing UI gPrivateBrowsingUI.init(); gBrowser.mPanelContainer.addEventListener("InstallBrowserTheme",
LightWeightThemeWebInstaller, false, true); gBrowser.mPanelContainer.addEventListener("PreviewBrowserTheme",
LightWeightThemeWebInstaller, false, true); gBrowser.mPanelContainer.addEventListener("ResetBrowserThemePreview",
LightWeightThemeWebInstaller, false, true); if (Win7Features) Win7Features.onOpenWindow();
function BrowserShutdown() if (Win7Features) Win7Features.onCloseWindow(); gPrefService.removeObserver(ctrlTab.prefName,
ctrlTab); gPrefService.removeObserver(allTabs.prefName, allTabs); tabPreviews.uninit(); ctrlTab.uninit();
allTabs.uninit(); gGestureSupport.init(false); try { FullZoom.destroy(); catch(ex) { Components.utils.reportError(ex);
var os = Components.classes["@mozilla.org/observer-service;1"] .getService(Components.interfaces.nsIObserverService);
os.removeObserver(gSessionHistoryObserver, "browser:purge-session-history"); os.removeObserver(gXPInstallObserver,
"xpinstall-install-blocked"); os.removeObserver(gMissingPluginInstaller, "plugin-crashed"); try { gBrowser.removeProgressListener(window.XULBrowserWindow);
gBrowser.removeTabsProgressListener(window.TabsProgressListener); } catch (ex) { PlacesStarButton.uninit();
try { gPrefService.removeObserver(gAutoHideTabbarPrefListener.domain, gAutoHideTabbarPrefListener); gPrefService.removeObserver(gHomeButton.prefDomain,
gHomeButton); gPrefService.removeObserver(gURLBarEmptyText.domain, gURLBarEmptyText); } catch (ex) { Components.utils.reportError(ex);
BrowserOffline.uninit(); OfflineApps.uninit(); DownloadMonitorPanel.uninit(); gPrivateBrowsingUI.uninit();
var windowManager = Components.classes['@mozilla.org/appshell/window-mediator;1'].getService(); var windowManagerInterface = windowManager.QueryInterface(Components.interfaces.nsIWindowMediator);
var enumerator = windowManagerInterface.getEnumerator(null); enumerator.getNext(); if (!enumerator.hasMoreElements())
{ document.persist("sidebar-box", "sidebarcommand"); document.persist("sidebar-box", "width");
document.persist("sidebar-box", "src"); document.persist("sidebar-title", "value"); window.XULBrowserWindow.destroy();
window.XULBrowserWindow = null; window.QueryInterface(Components.interfaces.nsIInterfaceRequestor) .getInterface(Components.interfaces.nsIWebNavigation)
.QueryInterface(Components.interfaces.nsIDocShellTreeItem).treeOwner .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIXULWindow) .XULBrowserWindow = null; window.QueryInterface(Ci.nsIDOMChromeWindow).browserDOMWindow
= null; //@line 1519 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js" function AutoHideTabbarPrefListener() this.toggleAutoHideTabbar();
AutoHideTabbarPrefListener.prototype = domain: "browser.tabs.autoHide", observe: function
(aSubject, aTopic, aPrefName) if (aTopic != "nsPref:changed" || aPrefName != this.domain)
return; this.toggleAutoHideTabbar(); }, toggleAutoHideTabbar: function () if (gBrowser.tabContainer.childNodes.length
== 1 && window.toolbar.visible) { var aVisible = false; try { aVisible = !gPrefService.getBoolPref(this.domain);
} catch (e) { } gBrowser.setStripVisibilityTo(aVisible); } function initializeSanitizer() // Always
use the label with ellipsis var label = gNavigatorBundle.getString("sanitizeWithPromptLabel2"); document.getElementById("sanitizeItem").setAttribute("label",
label); const kDidSanitizeDomain = "privacy.sanitize.didShutdownSanitize"; if (gPrefService.prefHasUserValue(kDidSanitizeDomain))
{ gPrefService.clearUserPref(kDidSanitizeDomain); // We need to persist this preference change,
since we want to // check it at next app start even if the browser exits abruptly gPrefService.savePrefFile(null);
/** * Migrate Firefox 3.0 privacy.item prefs under one of these conditions: * * a) User
has customized any privacy.item prefs * b) privacy.sanitize.sanitizeOnShutdown is set
*/ if (!gPrefService.getBoolPref("privacy.sanitize.migrateFx3Prefs")) { let itemBranch = gPrefService.getBranch("privacy.item.");
let itemCount = { value: 0 }; let itemArray = itemBranch.getChildList("", itemCount);
// See if any privacy.item prefs are set let doMigrate = itemArray.some(function (name)
itemBranch.prefHasUserValue(name)); // Or if sanitizeOnShutdown is set if (!doMigrate)
doMigrate = gPrefService.getBoolPref("privacy.sanitize.sanitizeOnShutdown"); if (doMigrate) { let cpdBranch = gPrefService.getBranch("privacy.cpd.");
let clearOnShutdownBranch = gPrefService.getBranch("privacy.clearOnShutdown."); itemArray.forEach(function (name) { try {
// don't migrate password or offlineApps clearing in the CRH dialog since // there's
no UI for those anymore. They default to false. bug 497656 if (name != "passwords" && name
!= "offlineApps") cpdBranch.setBoolPref(name, itemBranch.getBoolPref(name)); clearOnShutdownBranch.setBoolPref(name,
itemBranch.getBoolPref(name)); } catch(e) { Cu.reportError("Exception thrown during
privacy pref migration: " + e); } }); } gPrefService.setBoolPref("privacy.sanitize.migrateFx3Prefs", true); function gotoHistoryIndex(aEvent) var
index = aEvent.target.getAttribute("index"); if (!index) return false; var where = whereToOpenLink(aEvent);
if (where == "current") { // Normal click. Go there in the current tab and update session
history. try { gBrowser.gotoIndex(index); } catch(ex) { return false; } return true;
else { // Modified click. Go there in a new tab/window. // This code doesn't copy history
or work well with framed pages. var sessionHistory = getWebNavigation().sessionHistory; var
entry = sessionHistory.getEntryAtIndex(index, false); var url = entry.URI.spec; openUILinkIn(url,
where); return true; function BrowserForward(aEvent) { var where = whereToOpenLink(aEvent, false,
true); if (where == "current") { try { gBrowser.goForward(); } catch(ex) { } else { var sessionHistory
= getWebNavigation().sessionHistory; var currentIndex = sessionHistory.index; var entry
= sessionHistory.getEntryAtIndex(currentIndex + 1, false); var url = entry.URI.spec; openUILinkIn(url,
where); function BrowserBack(aEvent) { var where = whereToOpenLink(aEvent, false, true);
if (where == "current") { try { gBrowser.goBack(); } catch(ex) { } else { var sessionHistory
= getWebNavigation().sessionHistory; var currentIndex = sessionHistory.index; var entry
= sessionHistory.getEntryAtIndex(currentIndex - 1, false); var url = entry.URI.spec; openUILinkIn(url,
where); function BrowserHandleBackspace() switch (gPrefService.getIntPref("browser.backspace_action"))
{ case 0: BrowserBack(); break; case 1: goDoCommand("cmd_scrollPageUp"); break; function BrowserHandleShiftBackspace()
switch (gPrefService.getIntPref("browser.backspace_action")) { case 0: BrowserForward(); break; case 1:
goDoCommand("cmd_scrollPageDown"); break; function BrowserStop() try { const stopFlags
= nsIWebNavigation.STOP_ALL; getWebNavigation().stop(stopFlags); catch(ex) { function BrowserReloadOrDuplicate(aEvent)
{ var backgroundTabModifier = aEvent.button == 1 || //@line 1711 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js"
aEvent.ctrlKey; //@line 1713 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js" if (aEvent.shiftKey && !backgroundTabModifier)
{ BrowserReloadSkipCache(); return; var where = whereToOpenLink(aEvent, false, true); if
(where == "current") BrowserReload(); else openUILinkIn(getWebNavigation().currentURI.spec,
where); function BrowserReload() { const reloadFlags = nsIWebNavigation.LOAD_FLAGS_NONE; BrowserReloadWithFlags(reloadFlags);
function BrowserReloadSkipCache() { // Bypass proxy and cache. const reloadFlags = nsIWebNavigation.LOAD_FLAGS_BYPASS_PROXY
| nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE; BrowserReloadWithFlags(reloadFlags); function
BrowserHome() var homePage = gHomeButton.getHomePage(); loadOneOrMoreURIs(homePage); function BrowserGoHome(aEvent)
{ if (aEvent && "button" in aEvent && aEvent.button == 2) // right-click: do nothing return;
var homePage = gHomeButton.getHomePage(); var where = whereToOpenLink(aEvent, false,
true); var urls; // openUILinkIn in utilityOverlay.js doesn't handle loading multiple pages switch
(where) { case "current": loadOneOrMoreURIs(homePage); break; case "tabshifted": case "tab": urls
= homePage.split("|"); var loadInBackground = getBoolPref("browser.tabs.loadBookmarksInBackground",
false); gBrowser.loadTabs(urls, loadInBackground); break; case "window": OpenBrowserWindow();
break; function loadOneOrMoreURIs(aURIString) //@line 1778 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js"
// This function throws for certain malformed URIs, so use exception handling // so that
we don't disrupt startup try { gBrowser.loadTabs(aURIString.split("|"), false, true); } catch (e) { function focusAndSelectUrlBar()
{ if (gURLBar && !gURLBar.readOnly) { if (window.fullScreen) FullScreen.mouseoverToggle(true);
if (isElementVisible(gURLBar)) { gURLBar.focus(); gURLBar.select(); return true; } return false;
function openLocation() { if (focusAndSelectUrlBar()) return; //@line 1821 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js"
openDialog("chrome://browser/content/openLocation.xul", "_blank", "chrome,modal,titlebar", window);
function openLocationCallback() // make sure the DOM is ready setTimeout(function() {
this.openLocation(); }, 0); function BrowserOpenTab() if (!gBrowser) { // If there are no open browser
windows, open a new one window.openDialog("chrome://browser/content/", "_blank", "chrome,all,dialog=no", "about:blank");
return; gBrowser.loadOneTab("about:blank", {inBackground: false}); focusAndSelectUrlBar();
/* Called from the openLocation dialog. This allows that dialog to instruct its opener
to open a new window and then step completely out of the way. Anything less byzantine is
causing horrible crashes, rather believably, though oddly only on Linux. */ function delayedOpenWindow(chrome,
flags, href, postData) // The other way to use setTimeout, // setTimeout(openDialog,
10, chrome, "_blank", flags, url), // doesn't work here. The extra "magic" extra argument
setTimeout adds to // the callback function would confuse prepareForStartup() by making
// window.arguments[1] be an integer instead of null. setTimeout(function() { openDialog(chrome,
"_blank", flags, href, null, null, postData); }, 10); /* Required because the tab needs
time to set up its content viewers and get the load of the URI kicked off before becoming
the active content area. */ function delayedOpenTab(aUrl, aReferrer, aCharset, aPostData, aAllowThirdPartyFixup)
gBrowser.loadOneTab(aUrl, { referrerURI: aReferrer, charset: aCharset, postData: aPostData, inBackground:
false, allowThirdPartyFixup: aAllowThirdPartyFixup}); var gLastOpenDirectory = { _lastDir: null,
get path() { if (!this._lastDir || !this._lastDir.exists()) { try { this._lastDir = gPrefService.getComplexValue("browser.open.lastDir",
Ci.nsILocalFile); if (!this._lastDir.exists()) this._lastDir = null; } catch(e) {} } return
this._lastDir; }, set path(val) { if (!val || !val.exists() || !val.isDirectory()) return;
this._lastDir = val.clone(); // Don't save the last open directory pref inside the Private
Browsing mode if (!gPrivateBrowsingUI.privateBrowsingEnabled) gPrefService.setComplexValue("browser.open.lastDir",
Ci.nsILocalFile, this._lastDir); }, reset: function() { this._lastDir = null; function
BrowserOpenFileWindow() // Get filepicker component. try { const nsIFilePicker = Components.interfaces.nsIFilePicker;
var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker); fp.init(window, gNavigatorBundle.getString("openFile"),
nsIFilePicker.modeOpen); fp.appendFilters(nsIFilePicker.filterAll | nsIFilePicker.filterText | nsIFilePicker.filterImages
| nsIFilePicker.filterXML | nsIFilePicker.filterHTML); fp.displayDirectory = gLastOpenDirectory.path;
if (fp.show() == nsIFilePicker.returnOK) { if (fp.file && fp.file.exists()) gLastOpenDirectory.path
= fp.file.parent.QueryInterface(Ci.nsILocalFile); openTopWin(fp.fileURL.spec); } } catch (ex)
{ function BrowserCloseTabOrWindow() { //@line 1926 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js"
// If the current tab is the last one, this will close the window. gBrowser.removeCurrentTab();
function BrowserTryToCloseWindow() if (WindowIsClosing()) { if (window.fullScreen) { gBrowser.mPanelContainer.removeEventListener("mousemove",
FullScreen._collapseCallback, false); document.removeEventListener("keypress", FullScreen._keyToggleCallback, false); document.removeEventListener("popupshown",
FullScreen._setPopupOpen, false); document.removeEventListener("popuphidden", FullScreen._setPopupOpen, false); gPrefService.removeObserver("browser.fullscreen",
FullScreen); var fullScrToggler = document.getElementById("fullscr-toggler"); if (fullScrToggler) { fullScrToggler.removeEventListener("mouseover",
FullScreen._expandCallback, false); fullScrToggler.removeEventListener("dragenter", FullScreen._expandCallback, false); } } window.close();
// WindowIsClosing does all the necessary checks function loadURI(uri, referrer, postData,
allowThirdPartyFixup) try { if (postData === undefined) postData = null; var flags
= nsIWebNavigation.LOAD_FLAGS_NONE; if (allowThirdPartyFixup) { flags = nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
} gBrowser.loadURIWithFlags(uri, flags, referrer, null, postData); } catch (e) { function getShortcutOrURI(aURL,
aPostDataRef) { var shortcutURL = null; var keyword = aURL; var param = ""; var searchService
= Cc["@mozilla.org/browser/search-service;1"]. getService(Ci.nsIBrowserSearchService); var
offset = aURL.indexOf(" "); if (offset > 0) { keyword = aURL.substr(0, offset); param
= aURL.substr(offset + 1); if (!aPostDataRef) aPostDataRef = {}; var engine = searchService.getEngineByAlias(keyword);
if (engine) { var submission = engine.getSubmission(param, null); aPostDataRef.value = submission.postData;
return submission.uri.spec; [shortcutURL, aPostDataRef.value] = PlacesUtils.getURLAndPostDataForKeyword(keyword);
if (!shortcutURL) return aURL; var postData = ""; if (aPostDataRef.value) postData =
unescape(aPostDataRef.value); if (/%s/i.test(shortcutURL) || /%s/i.test(postData)) { var charset =
""; const re = /^(.*)\&mozcharset=([a-zA-Z][_\-a-zA-Z0-9]+)\s*$/; var matches = shortcutURL.match(re); if (matches)
[, shortcutURL, charset] = matches; else { // Try to get the saved character-set.
try { // makeURI throws if URI is invalid. // Will return an empty string if character-set
is not found. charset = PlacesUtils.history.getCharsetForURI(makeURI(shortcutURL)); } catch (e) {} } var encodedParam = "";
if (charset) encodedParam = escape(convertFromUnicode(charset, param)); else // Default charset is UTF-8
encodedParam = encodeURIComponent(param); shortcutURL = shortcutURL.replace(/%s/g, encodedParam).replace(/%S/g,
param); if (/%s/i.test(postData)) // POST keyword aPostDataRef.value = getPostDataStream(postData,
param, encodedParam, "application/x-www-form-urlencoded"); else if (param) { // This keyword doesn't
take a parameter, but one was provided. Just return // the original URL. aPostDataRef.value
= null; return aURL; return shortcutURL; function getPostDataStream(aStringData, aKeyword,
aEncKeyword, aType) { var dataStream = Cc["@mozilla.org/io/string-input-stream;1"]. createInstance(Ci.nsIStringInputStream); aStringData
= aStringData.replace(/%s/g, aEncKeyword).replace(/%S/g, aKeyword); dataStream.data = aStringData;
var mimeStream = Cc["@mozilla.org/network/mime-input-stream;1"]. createInstance(Ci.nsIMIMEInputStream); mimeStream.addHeader("Content-Type",
aType); mimeStream.addContentLength = true; mimeStream.setData(dataStream); return mimeStream.QueryInterface(Ci.nsIInputStream);
function readFromClipboard() var url; try { // Get clipboard. var clipboard = Components.classes["@mozilla.org/widget/clipboard;1"]
.getService(Components.interfaces.nsIClipboard); // Create transferable that will transfer
the text. var trans = Components.classes["@mozilla.org/widget/transferable;1"] .createInstance(Components.interfaces.nsITransferable);
trans.addDataFlavor("text/unicode"); // If available, use selection clipboard, otherwise
global one if (clipboard.supportsSelectionClipboard()) clipboard.getData(trans, clipboard.kSelectionClipboard);
else clipboard.getData(trans, clipboard.kGlobalClipboard); var data = {}; var dataLen = {}; trans.getTransferData("text/unicode",
data, dataLen); if (data) { data = data.value.QueryInterface(Components.interfaces.nsISupportsString); url = data.data.substring(0, dataLen.value
/ 2); } } catch (ex) { return url; function BrowserViewSourceOfDocument(aDocument) var
pageCookie; var webNav; // Get the document charset var docCharset = "charset=" + aDocument.characterSet;
// Get the nsIWebNavigation associated with the document try { var win; var ifRequestor;
// Get the DOMWindow for the requested document. If the DOMWindow // cannot be found, then
just use the content window... // // ***: This is a bit of a hack... win = aDocument.defaultView;
if (win == window) { win = content; } ifRequestor = win.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
webNav = ifRequestor.getInterface(nsIWebNavigation); } catch(err) { // If nsIWebNavigation cannot
be found, just get the one for the whole // window... webNav = getWebNavigation();
// // Get the 'PageDescriptor' for the current document. This allows the // view-source to
access the cached copy of the content rather than // refetching it from the network...
// try{ var PageLoader = webNav.QueryInterface(Components.interfaces.nsIWebPageDescriptor); pageCookie = PageLoader.currentDescriptor;
} catch(err) { // If no page descriptor is available, just use the view-source URL...
top.gViewSourceUtils.viewSource(webNav.currentURI.spec, pageCookie, aDocument); // doc - document
to use for source, or null for this window's document // initialTab - name of the initial
tab to display, or null for the first tab // imageElement - image to load in the Media
Tab of the Page Info window; can be null/omitted function BrowserPageInfo(doc, initialTab,
imageElement) { var args = {doc: doc, initialTab: initialTab, imageElement: imageElement}; var
windows = Cc['@mozilla.org/appshell/window-mediator;1'] .getService(Ci.nsIWindowMediator) .getEnumerator("Browser:page-info");
var documentURL = doc ? doc.location : window.content.document.location; // Check for windows matching the url while
(windows.hasMoreElements()) { var currentWindow = windows.getNext(); if (currentWindow.document.documentElement.getAttribute("relatedUrl")
== documentURL) { currentWindow.focus(); currentWindow.resetPageInfo(args); return
currentWindow; } // We didn't find a matching window, so open a new one. return openDialog("chrome://browser/content/pageinfo/pageInfo.xul",
"", "chrome,toolbar,dialog=no,resizable", args); //@line 2207 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js"
function URLBarSetURI(aURI, aValid) { var value = gBrowser.userTypedValue; var valid
= false; if (value == null) { let uri = aURI || getWebNavigation().currentURI; //
Replace initial page URIs with an empty string // only if there's no opener (bug 370555).
if (gInitialPages.indexOf(uri.spec) != -1) value = content.opener ? uri.spec : ""; else
value = losslessDecodeURI(uri); let isBlank = (uri.spec == "about:blank"); valid = !isBlank
&& (!aURI || aValid); gURLBar.value = value; SetPageProxyState(valid ? "valid" : "invalid");
function losslessDecodeURI(aURI) { var value = aURI.spec; // Try to decode as UTF-8 if
there's no encoding sequence that we would break. if (!/%25(?:3B|2F|3F|3A|40|26|3D|2B|24|2C|23)/i.test(value))
try { value = decodeURI(value) // 1. decodeURI decodes %25 to %, which creates unintended
// encoding sequences. Re-encode it, unless it's part of // a sequence that survived decodeURI,
i.e. one for: // ';', '/', '?', ':', '@', '&', '=', '+', '$', ',', '#' // (RFC 3987
section 3.2) // 2. Re-encode whitespace so that it doesn't get eaten away // by the location
bar (bug 410726). .replace(/%(?!3B|2F|3F|3A|40|26|3D|2B|24|2C|23)|[\r\n\t]/ig, encodeURIComponent); } catch (e) {} // Encode
invisible characters (soft hyphen, zero-width space, BOM, // line and paragraph separator,
word joiner, invisible times, // invisible separator, object replacement character) (bug
452979) value = value.replace(/[\v\x0c\x1c\x1d\x1e\x1f\u00ad\u200b\ufeff\u2028\u2029\u2060\u2062\u2063\ufffc]/g, encodeURIComponent); // Encode bidirectional
formatting characters. // (RFC 3987 sections 3.2 and 4.1 paragraph 6) value = value.replace(/[\u200e\u200f\u202a\u202b\u202c\u202d\u202e]/g,
encodeURIComponent); return value; function UpdateUrlbarSearchSplitterState() var splitter
= document.getElementById("urlbar-search-splitter"); var urlbar = document.getElementById("urlbar-container");
var searchbar = document.getElementById("search-container"); var ibefore = null; if (urlbar && searchbar)
{ if (urlbar.nextSibling == searchbar) ibefore = searchbar; else if (searchbar.nextSibling
== urlbar) ibefore = urlbar; if (ibefore) { if (!splitter) { splitter = document.createElement("splitter");
splitter.id = "urlbar-search-splitter"; splitter.setAttribute("resizebefore", "flex"); splitter.setAttribute("resizeafter",
"flex"); splitter.className = "chromeclass-toolbar-additional"; } urlbar.parentNode.insertBefore(splitter,
ibefore); } else if (splitter) 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) SetPageProxyState("invalid");
function SetPageProxyState(aState) if (!gURLBar) return; if (!gProxyFavIcon) gProxyFavIcon
= document.getElementById("page-proxy-favicon"); gURLBar.setAttribute("pageproxystate", aState);
gProxyFavIcon.setAttribute("pageproxystate", aState); // the page proxy state is set to
valid via OnLocationChange, which // gets called when we switch tabs. if (aState ==
"valid") { gLastValidURLStr = gURLBar.value; gURLBar.addEventListener("input", UpdatePageProxyState,
false); PageProxySetIcon(gBrowser.mCurrentBrowser.mIconURL); } else if (aState == "invalid") { gURLBar.removeEventListener("input",
UpdatePageProxyState, false); PageProxyClearIcon(); function PageProxySetIcon (aURL) if (!gProxyFavIcon)
return; if (!aURL) PageProxyClearIcon(); else if (gProxyFavIcon.getAttribute("src") !=
aURL) gProxyFavIcon.setAttribute("src", aURL); function PageProxyClearIcon () gProxyFavIcon.removeAttribute("src");
function PageProxyClickHandler(aEvent) if (aEvent.button == 1 && gPrefService.getBoolPref("middlemouse.paste"))
middleMousePaste(aEvent); function BrowserImport() //@line 2374 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js"
window.openDialog("chrome://browser/content/migration/migration.xul", "migration", "modal,centerscreen,chrome,resizable=no");
//@line 2377 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js" * Handle command events bubbling up from
error page content function BrowserOnCommand(event) { // Don't trust synthetic events if (!event.isTrusted)
return; var ot = event.originalTarget; var errorDoc = ot.ownerDocument; // If the event
came from an ssl error page, it is probably either the "Add // Exception " or "Get me
out of here!" button if (/^about:certerror/.test(errorDoc.documentURI)) { if (ot == errorDoc.getElementById('exceptionDialogButton'))
{ var params = { exceptionAdded : false, handlePrivateBrowsing : true }; try { switch
(gPrefService.getIntPref("browser.ssl_override_behavior")) { case 2 : // Pre-fetch & pre-populate params.prefetchCert
= true; case 1 : // Pre-populate params.location = errorDoc.location.href; } } catch (e)
{ Components.utils.reportError("Couldn't get ssl_override pref: " + e); } window.openDialog('chrome://pippki/content/exceptionDialog.xul',
'','chrome,centerscreen,modal', params); // If the user added the exception cert, attempt
to reload the page if (params.exceptionAdded) errorDoc.location.reload(); } else if (ot
== errorDoc.getElementById('getMeOutOfHereButton')) { getMeOutOfHere(); } } else if (/^about:blocked/.test(errorDoc.documentURI))
{ // The event came from a button on a malware/phishing block page // First check whether it's malware
or phishing, so that we can // use the right strings/links var isMalware = /e=malwareBlocked/.test(errorDoc.documentURI);
if (ot == errorDoc.getElementById('getMeOutButton')) { getMeOutOfHere(); } else if (ot == errorDoc.getElementById('reportButton'))
{ // This is the "Why is this site blocked" button. For malware, // we can fetch a site-specific
report, for phishing, we redirect // to the generic page describing phishing protection.
var formatter = Cc["@mozilla.org/toolkit/URLFormatterService;1"] .getService(Components.interfaces.nsIURLFormatter);
if (isMalware) { // Get the stop badware "why is this blocked" report url, // append the
current url, and go there. try { var reportURL = formatter.formatURLPref("browser.safebrowsing.malware.reportURL");
reportURL += errorDoc.location.href; content.location = reportURL; } catch (e) { Components.utils.reportError("Couldn't
get malware report URL: " + e); } } else { // It's a phishing site, not malware try
{ content.location = formatter.formatURLPref("browser.safebrowsing.warning.infoURL"); } catch (e) { Components.utils.reportError("Couldn't
get phishing info URL: " + e); } } } else if (ot == errorDoc.getElementById('ignoreWarningButton'))
{ // Allow users to override and continue through to the site, // but add a notify bar
as a reminder, so that they don't lose // track after, e.g., tab switching. gBrowser.loadURIWithFlags(content.location.href,
nsIWebNavigation.LOAD_FLAGS_BYPASS_CLASSIFIER, null, null, null); var buttons = [{ label:
gNavigatorBundle.getString("safebrowsing.getMeOutOfHereButton.label"), accessKey: gNavigatorBundle.getString("safebrowsing.getMeOutOfHereButton.accessKey"),
callback: function() { getMeOutOfHere(); } }]; if (isMalware) { var title = gNavigatorBundle.getString("safebrowsing.reportedAttackSite");
buttons[1] = { label: gNavigatorBundle.getString("safebrowsing.notAnAttackButton.label"), accessKey: gNavigatorBundle.getString("safebrowsing.notAnAttackButton.accessKey"),
callback: function() { openUILinkIn(safebrowsing.getReportURL('MalwareError'), 'tab'); } }; } else { title = gNavigatorBundle.getString("safebrowsing.reportedWebForgery");
buttons[1] = { label: gNavigatorBundle.getString("safebrowsing.notAForgeryButton.label"), accessKey: gNavigatorBundle.getString("safebrowsing.notAForgeryButton.accessKey"),
callback: function() { openUILinkIn(safebrowsing.getReportURL('Error'), 'tab'); } }; } var notificationBox = gBrowser.getNotificationBox();
notificationBox.appendNotification( title, "blocked-badware-page", "chrome://global/skin/icons/blacklist_favicon.png",
notificationBox.PRIORITY_CRITICAL_HIGH, buttons ); } } else if (/^about:privatebrowsing/.test(errorDoc.documentURI))
{ if (ot == errorDoc.getElementById("startPrivateBrowsing")) { gPrivateBrowsingUI.toggleMode(); } } *
Re-direct the browser to a known-safe page. This function is * used when, for example,
the user browses to a known malware page * and is presented with about:blocked. The
"Get me out of here!" * button should take the user to the default start page so that
even * when their own homepage is infected, we can get them somewhere safe. function getMeOutOfHere()
{ // Get the start page from the *default* pref branch, not the user's 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. if (url.indexOf("|") != -1) url = url.split("|")[0]; } catch(e) { Components.utils.reportError("Couldn't
get homepage pref: " + e); content.location = url; function BrowserFullScreen() window.fullScreen
= !window.fullScreen; function onFullScreen() FullScreen.toggle(); function getWebNavigation()
try { return gBrowser.webNavigation; } catch (e) { return null; function BrowserReloadWithFlags(reloadFlags)
{ /* First, we'll try to use the session history object to reload so * that framesets
are handled properly. If we're in a special * window (such as view-source) that has no
session history, fall * back on using the web navigation's reload method. */ var webNav
= getWebNavigation(); try { var sh = webNav.sessionHistory; if (sh) webNav = sh.QueryInterface(nsIWebNavigation);
} catch (e) { try { webNav.reload(reloadFlags); } catch (e) { function toggleAffectedChrome(aHide)
// chrome to toggle includes: // (*) menubar // (*) navigation bar // (*) bookmarks toolbar
// (*) tabstrip // (*) browser messages // (*) sidebar // (*) find bar // (*) statusbar
gNavToolbox.hidden = aHide; if (aHide) gChromeState = {}; var sidebar = document.getElementById("sidebar-box");
gChromeState.sidebarOpen = !sidebar.hidden; gSidebarCommand = sidebar.getAttribute("sidebarcommand");
gChromeState.hadTabStrip = gBrowser.getStripVisibility(); gBrowser.setStripVisibilityTo(false); var
notificationBox = gBrowser.getNotificationBox(); gChromeState.notificationsOpen = !notificationBox.notificationsHidden;
notificationBox.notificationsHidden = aHide; document.getElementById("sidebar").setAttribute("src",
"about:blank"); var statusbar = document.getElementById("status-bar"); gChromeState.statusbarOpen = !statusbar.hidden;
statusbar.hidden = aHide; gChromeState.findOpen = !gFindBar.hidden; gFindBar.close(); else
{ if (gChromeState.hadTabStrip) { gBrowser.setStripVisibilityTo(true); } if (gChromeState.notificationsOpen) {
gBrowser.getNotificationBox().notificationsHidden = aHide; } if (gChromeState.statusbarOpen)
{ var statusbar = document.getElementById("status-bar"); statusbar.hidden = aHide; } if (gChromeState.findOpen)
gFindBar.open(); if (gChromeState.sidebarOpen) toggleSidebar(gSidebarCommand); function onEnterPrintPreview()
gInPrintPreviewMode = true; toggleAffectedChrome(true); function onExitPrintPreview() // restore chrome
to original state gInPrintPreviewMode = false; toggleAffectedChrome(false); function getPPBrowser()
return gBrowser; function getMarkupDocumentViewer() return gBrowser.markupDocumentViewer; * Content
area tooltip. * *** - this must move into XBL binding/equiv! Do not want to pollute
* browser.js with functionality that can be encapsulated into * browser widget. TEMPORARY!
* NOTE: Any changes to this routine need to be mirrored in ChromeListener::FindTitleText()
* (located in mozilla/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp) * which performs the same function, but for
embedded clients that * don't use a XUL/JS layer. It is important that the logic of
* these two routines be kept more or less in sync. * (pinkerton) **/ function FillInHTMLTooltip(tipElement)
var retVal = false; if (tipElement.namespaceURI == "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul")
return retVal; const XLinkNS = "http://www.w3.org/1999/xlink"; var titleText = null; var XLinkTitleText
= null; var direction = tipElement.ownerDocument.dir; while (!titleText && !XLinkTitleText && tipElement)
{ if (tipElement.nodeType == Node.ELEMENT_NODE) { titleText = tipElement.getAttribute("title");
XLinkTitleText = tipElement.getAttributeNS(XLinkNS, "title"); var defView = tipElement.ownerDocument.defaultView;
// *** Work around bug 350679: // "Tooltips can be fired in documents with no view". if
(!defView) return retVal; direction = defView.getComputedStyle(tipElement, "") .getPropertyValue("direction"); } tipElement
= tipElement.parentNode; var tipNode = document.getElementById("aHTMLTooltip"); tipNode.style.direction = direction; [titleText,
XLinkTitleText].forEach(function (t) { if (t && /\S/.test(t)) { // Per HTML 4.01 6.2
(CDATA section), literal CRs and tabs should be // replaced with spaces, and LFs should
be removed entirely. // *** Bug 322270: We don't preserve the result of entities like
, // which should result in a line break in the tooltip, because we can't // distinguish
that from a literal character in the source by this point. t = t.replace(/[\r\t]/g, '
'); t = t.replace(/\n/g, ''); tipNode.setAttribute("label", t); retVal = true; } }); return retVal; var
browserDragAndDrop = { getDragURLFromDataTransfer : function (dt) var types = dt.types; for
(var t = 0; t < types.length; t++) { var type = types[t]; switch (type) { case "text/uri-list":
var url = dt.getData("URL").replace(/^\s+|\s+$/g, ""); return [url, url]; case "text/plain":
case "text/x-moz-text-internal": var url = dt.getData(type).replace(/^\s+|\s+$/g,
""); return [url, url]; case "text/x-moz-url": var split = dt.getData(type).split("\n");
return [split[0], split[1]]; } } // For shortcuts, we want to check for the file type last, so
that the // url pointed to in one of the url types is found first before the file // type,
which points to the actual file. var file = dt.mozGetDataAt("application/x-moz-file",
0); if (file) { var name = file instanceof Ci.nsIFile ? file.leafName : ""; var fileHandler
= ContentAreaUtils.ioService .getProtocolHandler("file") .QueryInterface(Ci.nsIFileProtocolHandler);
return [fileHandler.getURLSpecFromFile(file), name]; } return [ , ]; }, dragOver : function
(aEvent, statusString) var types = aEvent.dataTransfer.types; if (types.contains("application/x-moz-file")
|| types.contains("text/x-moz-url") || types.contains("text/uri-list") || types.contains("text/x-moz-text-internal")
|| types.contains("text/plain")) { aEvent.preventDefault(); if (statusString) { var statusTextFld = document.getElementById("statusbar-display");
statusTextFld.label = gNavigatorBundle.getString(statusString); } } var proxyIconDNDObserver = { onDragStart:
function (aEvent, aXferData, aDragAction) { if (gProxyFavIcon.getAttribute("pageproxystate")
!= "valid") return; var value = content.location.href; var urlString = value + "\n" + content.document.title;
var htmlString = "" + value + ""; var dt = aEvent.dataTransfer;
dt.setData("text/x-moz-url", urlString); dt.setData("text/uri-list", value); dt.setData("text/plain", value); dt.setData("text/html",
htmlString); } var homeButtonObserver = { onDrop: function (aEvent) { let url = browserDragAndDrop.getDragURLFromDataTransfer(aEvent.dataTransfer)[0];
setTimeout(openHomeDialog, 0, url); }, onDragOver: function (aEvent) { browserDragAndDrop.dragOver(aEvent,
"droponhomebutton"); aEvent.dropEffect = "link"; }, onDragLeave: function (aEvent)
{ var statusTextFld = document.getElementById("statusbar-display"); statusTextFld.label = ""; } function openHomeDialog(aURL)
var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService(Components.interfaces.nsIPromptService); var promptTitle = gNavigatorBundle.getString("droponhometitle");
var promptMsg = gNavigatorBundle.getString("droponhomemsg"); var pressedVal = promptService.confirmEx(window,
promptTitle, promptMsg, promptService.STD_YES_NO_BUTTONS, null, null, null, null, {value:0}); if (pressedVal
== 0) { try { var str = Components.classes["@mozilla.org/supports-string;1"] .createInstance(Components.interfaces.nsISupportsString);
str.data = aURL; gPrefService.setComplexValue("browser.startup.homepage", Components.interfaces.nsISupportsString, str);
var homeButton = document.getElementById("home-button"); homeButton.setAttribute("tooltiptext", aURL);
} catch (ex) { dump("Failed to set the home page.\n"+ex+"\n"); } var bookmarksButtonObserver
= { onDrop: function (aEvent) let [url, name] = browserDragAndDrop.getDragURLFromDataTransfer(aEvent.dataTransfer);
try { PlacesUIUtils.showMinimalAddBookmarkUI(makeURI(url), name); } catch(ex) { } }, onDragOver: function
(aEvent) browserDragAndDrop.dragOver(aEvent, "droponbookmarksbutton"); aEvent.dropEffect
= "link"; }, onDragLeave: function (aEvent) var statusTextFld = document.getElementById("statusbar-display");
statusTextFld.label = ""; var newTabButtonObserver = { onDragOver: function (aEvent) browserDragAndDrop.dragOver(aEvent,
"droponnewtabbutton"); }, onDragLeave: function (aEvent) var statusTextFld = document.getElementById("statusbar-display");
statusTextFld.label = ""; }, onDrop: function (aEvent) let url = browserDragAndDrop.getDragURLFromDataTransfer(aEvent.dataTransfer)[0];
var postData = {}; url = getShortcutOrURI(url, postData); if (url) { nsDragAndDrop.dragDropSecurityCheck(aEvent,
null, url); // allow third-party services to fixup this URL openNewTabWith(url, null,
postData.value, aEvent, true); } var newWindowButtonObserver = { onDragOver: function (aEvent) browserDragAndDrop.dragOver(aEvent,
"droponnewwindowbutton"); }, onDragLeave: function (aEvent) var statusTextFld = document.getElementById("statusbar-display");
statusTextFld.label = ""; }, onDrop: function (aEvent) let url = browserDragAndDrop.getDragURLFromDataTransfer(aEvent.dataTransfer)[0];
var postData = {}; url = getShortcutOrURI(url, postData); if (url) { nsDragAndDrop.dragDropSecurityCheck(aEvent,
null, url); // allow third-party services to fixup this URL openNewWindowWith(url, null,
postData.value, true); } var DownloadsButtonDNDObserver = { /////////////////////////////////////////////////////////////////////////////
// nsDragAndDrop onDragOver: function (aEvent) var statusTextFld = document.getElementById("statusbar-display");
statusTextFld.label = gNavigatorBundle.getString("dropondownloadsbutton"); var types = aEvent.dataTransfer.types; if
(types.contains("text/x-moz-url") || types.contains("text/uri-list") || types.contains("text/plain")) aEvent.preventDefault();
}, onDragLeave: function (aEvent) var statusTextFld = document.getElementById("statusbar-display");
statusTextFld.label = ""; }, onDrop: function (aEvent) let [url, name] = browserDragAndDrop.getDragURLFromDataTransfer(aEvent.dataTransfer);
nsDragAndDrop.dragDropSecurityCheck(aEvent, null, url); saveURL(url, name, null, true,
true); const DOMLinkHandler = { handleEvent: function (event) { switch (event.type) {
case "DOMLinkAdded": this.onLinkAdded(event); break; } }, onLinkAdded: function (event)
{ var link = event.originalTarget; var rel = link.rel && link.rel.toLowerCase(); if
(!link || !link.ownerDocument || !rel || !link.href) return; var feedAdded = false;
var iconAdded = false; var searchAdded = false; var relStrings = rel.split(/\s+/);
var rels = {}; for (let i = 0; i < relStrings.length; i++) rels[relStrings[i]] = true; for (let
relVal in rels) { switch (relVal) { case "feed": case "alternate": if (!feedAdded) { if (!rels.feed
&& rels.alternate && rels.stylesheet) break; if (isValidFeed(link, link.ownerDocument.nodePrincipal,
rels.feed)) { FeedHandler.addFeed(link, link.ownerDocument); feedAdded = true; } } break; case "icon":
if (!iconAdded) { if (!gPrefService.getBoolPref("browser.chrome.site_icons")) break; var targetDoc = link.ownerDocument;
var uri = makeURI(link.href, targetDoc.characterSet); if (gBrowser.isFailedIcon(uri)) break; //
Verify that the load of this icon is legal. // error pages can load their favicon, to
be on the safe side, // only allow chrome:// favicons const aboutNeterr = /^about:neterror\?/;
const aboutBlocked = /^about:blocked\?/; const aboutCert = /^about:certerror\?/; if (!(aboutNeterr.test(targetDoc.documentURI)
|| aboutBlocked.test(targetDoc.documentURI) || aboutCert.test(targetDoc.documentURI))
|| !uri.schemeIs("chrome")) { var ssm = Cc["@mozilla.org/scriptsecuritymanager;1"].
getService(Ci.nsIScriptSecurityManager); try { ssm.checkLoadURIWithPrincipal(targetDoc.nodePrincipal,
uri, Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT); } catch(e) { break; } } try { var contentPolicy
= Cc["@mozilla.org/layout/content-policy;1"]. getService(Ci.nsIContentPolicy); } catch(e)
{ break; // Refuse to load if we can't do a security check. } // Security says okay,
now ask content policy if (contentPolicy.shouldLoad(Ci.nsIContentPolicy.TYPE_IMAGE, uri, targetDoc.documentURIObject, link, link.type,
null) != Ci.nsIContentPolicy.ACCEPT) break; var browserIndex = gBrowser.getBrowserIndexForDocument(targetDoc);
// no browser? no favicon. if (browserIndex == -1) break; var tab = gBrowser.mTabContainer.childNodes[browserIndex];
gBrowser.setIcon(tab, link.href); iconAdded = true; } break; case "search": if (!searchAdded)
{ var type = link.type && link.type.toLowerCase(); type = type.replace(/^\s+|\s*(?:;.*)?$/g,
""); if (type == "application/opensearchdescription+xml" && link.title && /^(?:https?|ftp):/i.test(link.href))
{ var engine = { title: link.title, href: link.href }; BrowserSearch.addEngine(engine,
link.ownerDocument); searchAdded = true; } } break; } } const BrowserSearch = { addEngine:
function(engine, targetDoc) { if (!this.searchBar) return; var browser = gBrowser.getBrowserForDocument(targetDoc);
// ignore search engines from subframes (see bug 479408) if (!browser) return; // Check
to see whether we've already added an engine with this title if (browser.engines) { if
(browser.engines.some(function (e) e.title == engine.title)) return; } // Append the
URI and an appropriate title to the browser data. // Use documentURIObject in the check
for shouldLoadFavIcon so that we // do the right thing with about:-style error pages.
Bug 453442 var iconURL = null; if (gBrowser.shouldLoadFavIcon(targetDoc.documentURIObject)) iconURL = targetDoc.documentURIObject.prePath
+ "/favicon.ico"; var hidden = false; // If this engine (identified by title) is already
in the list, add it // to the list of hidden engines rather than to the main list. //
*** This will need to be changed when engines are identified by URL; // see bug 335102.
var searchService = Cc["@mozilla.org/browser/search-service;1"]. getService(Ci.nsIBrowserSearchService); if
(searchService.getEngineByName(engine.title)) hidden = true; var engines = (hidden ? browser.hiddenEngines
: browser.engines) || []; engines.push({ uri: engine.href, title: engine.title, icon:
iconURL }); if (hidden) browser.hiddenEngines = engines; else { browser.engines = engines;
if (browser == gBrowser.mCurrentBrowser) this.updateSearchButton(); } }, /** * Update the browser UI to show
whether or not additional engines are * available when a page is loaded or the user switches
tabs to a page that * has search engines. */ updateSearchButton: function() { var searchBar
= this.searchBar; // The search bar binding might not be applied even though the element
is // in the document (e.g. when the navigation toolbar is hidden), so check // for .searchButton
specifically. if (!searchBar || !searchBar.searchButton) return; var engines = gBrowser.mCurrentBrowser.engines;
if (engines && engines.length > 0) searchBar.searchButton.setAttribute("addengines", "true"); else searchBar.searchButton.removeAttribute("addengines");
}, /** * Gives focus to the search bar, if it is present on the toolbar, or loads *
the default engine's search form otherwise. For Mac, opens a new window * or focuses an
existing window, if necessary. */ webSearch: function BrowserSearch_webSearch() { //@line
3130 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js" if (window.fullScreen) FullScreen.mouseoverToggle(true);
var searchBar = this.searchBar; if (isElementVisible(searchBar)) { searchBar.select(); searchBar.focus();
} else { var ss = Cc["@mozilla.org/browser/search-service;1"]. getService(Ci.nsIBrowserSearchService); var
searchForm = ss.defaultEngine.searchForm; loadURI(searchForm, null, null, false); }
}, /** * Loads a search results page, given a set of search terms. Uses the current *
engine if the search bar is visible, or the default engine otherwise. * * @param searchText
* The search terms to use for the search. * * @param useNewTab * Boolean indicating
whether or not the search should load in a new * tab. */ loadSearch: function BrowserSearch_search(searchText,
useNewTab) { var ss = Cc["@mozilla.org/browser/search-service;1"]. getService(Ci.nsIBrowserSearchService); var
engine; // If the search bar is visible, use the current engine, otherwise, fall // back
to the default engine. if (isElementVisible(this.searchBar)) engine = ss.currentEngine; else engine =
ss.defaultEngine; var submission = engine.getSubmission(searchText, null); // HTML response // getSubmission can
return null if the engine doesn't have a URL // with a text/html response type. This is
unlikely (since // SearchService._addEngineToStore() should fail for such an engine), // but let's
be on the safe side. if (!submission) return; if (useNewTab) { gBrowser.loadOneTab(submission.uri.spec,
{ postData: submission.postData, relatedToCurrent: true}); } else loadURI(submission.uri.spec,
null, submission.postData, false); }, /** * Returns the search bar element if it is
present in the toolbar, null otherwise. */ get searchBar() { return document.getElementById("searchbar");
}, loadAddEngines: function BrowserSearch_loadAddEngines() { var newWindowPref = gPrefService.getIntPref("browser.link.open_newwindow");
var where = newWindowPref == 3 ? "tab" : "window"; var regionBundle = document.getElementById("bundle_browser_region");
var searchEnginesURL = formatURL("browser.search.searchEnginesURL", true); openUILinkIn(searchEnginesURL, where);
function FillHistoryMenu(aParent) { // Lazily add the hover listeners on first showing and
never remove them if (!aParent.hasStatusListener) { // Show history item's uri in the status
bar when hovering, and clear on exit aParent.addEventListener("DOMMenuItemActive", function(aEvent) { // Only the current page
should have the checked attribute, so skip it if (!aEvent.target.hasAttribute("checked"))
XULBrowserWindow.setOverLink(aEvent.target.getAttribute("uri")); }, false); aParent.addEventListener("DOMMenuItemInactive",
function() { XULBrowserWindow.setOverLink(""); }, false); aParent.hasStatusListener = true;
// Remove old entries if any var children = aParent.childNodes; for (var i = children.length
- 1; i >= 0; --i) { if (children[i].hasAttribute("index")) aParent.removeChild(children[i]); var webNav
= getWebNavigation(); var sessionHistory = webNav.sessionHistory; var count = sessionHistory.count;
if (count = start; j--) {
let item = document.createElement("menuitem"); let entry = sessionHistory.getEntryAtIndex(j,
false); let uri = entry.URI.spec; item.setAttribute("uri", uri); item.setAttribute("label", entry.title
|| uri); item.setAttribute("index", j); if (j != index) { try { let iconURL = Cc["@mozilla.org/browser/favicon-service;1"]
.getService(Ci.nsIFaviconService) .getFaviconForPage(entry.URI).spec; item.style.listStyleImage = "url(" + iconURL
+ ")"; } catch (ex) {} } if (j < index) { item.className = "unified-nav-back menuitem-iconic";
item.setAttribute("tooltiptext", tooltipBack); } else if (j == index) { item.setAttribute("type",
"radio"); item.setAttribute("checked", "true"); item.className = "unified-nav-current"; item.setAttribute("tooltiptext",
tooltipCurrent); } else { item.className = "unified-nav-forward menuitem-iconic"; item.setAttribute("tooltiptext",
tooltipForward); } aParent.appendChild(item); return true; function addToUrlbarHistory(aUrlToAdd)
{ if (aUrlToAdd && aUrlToAdd.indexOf(" ") == -1 && !/[\x00-\x1F]/.test(aUrlToAdd))
PlacesUIUtils.markPageAsTyped(aUrlToAdd); function toJavaScriptConsole() toOpenWindowByType("global:console",
"chrome://global/content/console.xul"); function BrowserDownloadsUI() Cc["@mozilla.org/download-manager-ui;1"].
getService(Ci.nsIDownloadManagerUI).show(window); function toOpenWindowByType(inType, uri, features)
var windowManager = Components.classes['@mozilla.org/appshell/window-mediator;1'].getService(); var windowManagerInterface = windowManager.QueryInterface(Components.interfaces.nsIWindowMediator);
var topWindow = windowManagerInterface.getMostRecentWindow(inType); if (topWindow) topWindow.focus(); else if
(features) window.open(uri, "_blank", features); else window.open(uri, "_blank", "chrome,extrachrome,menubar,resizable,scrollbars,status,toolbar");
function toOpenDialogByTypeAndUrl(inType, relatedUrl, windowUri, features, extraArgument)
var windowManager = Components.classes['@mozilla.org/appshell/window-mediator;1'].getService(); var windowManagerInterface = windowManager.QueryInterface(Components.interfaces.nsIWindowMediator);
var windows = windowManagerInterface.getEnumerator(inType); // Check for windows matching the url while
(windows.hasMoreElements()) { var currentWindow = windows.getNext(); if (currentWindow.document.documentElement.getAttribute("relatedUrl")
== relatedUrl) { currentWindow.focus(); return; } // We didn't find a matching window, so
open a new one. if (features) return window.openDialog(windowUri, "_blank", features, extraArgument); return
window.openDialog(windowUri, "_blank", "chrome,extrachrome,menubar,resizable,scrollbars,status,toolbar", extraArgument); function OpenBrowserWindow()
var charsetArg = new String(); var handler = Components.classes["@mozilla.org/browser/clh;1"]
.getService(Components.interfaces.nsIBrowserHandler); var defaultArgs = handler.defaultArgs; var
wintype = document.documentElement.getAttribute('windowtype'); // if and only if the current window is a
browser window and it has a document with a character // set, then extract the current
charset menu setting from the current document and use it to // initialize the new browser
window... var win; if (window && (wintype == "navigator:browser") && window.content
&& window.content.document) var DocCharset = window.content.document.characterSet; charsetArg
= "charset="+DocCharset; //we should "inherit" the charset menu setting in a new window win
= window.openDialog("chrome://browser/content/", "_blank", "chrome,all,dialog=no", defaultArgs,
charsetArg); else // forget about the charset information. win = window.openDialog("chrome://browser/content/",
"_blank", "chrome,all,dialog=no", defaultArgs); return win; var gCustomizeSheet = false;
// Returns a reference to the window in which the toolbar // customization document is loaded.
function BrowserCustomizeToolbar() // Disable the toolbar context menu items var menubar
= document.getElementById("main-menubar"); for (var i = 0; i < menubar.childNodes.length;
++i) menubar.childNodes[i].setAttribute("disabled", true); var cmd = document.getElementById("cmd_CustomizeToolbars");
cmd.setAttribute("disabled", "true"); var splitter = document.getElementById("urlbar-search-splitter");
if (splitter) splitter.parentNode.removeChild(splitter); var customizeURL = "chrome://global/content/customizeToolbar.xul";
gCustomizeSheet = getBoolPref("toolbar.customization.usesheet", false); if (gCustomizeSheet) { var sheetFrame
= document.getElementById("customizeToolbarSheetIFrame"); sheetFrame.hidden = false; sheetFrame.toolbox
= gNavToolbox; // The document might not have been loaded yet, if this is the first
time. // If it is already loaded, reload it so that the onload initialization code //
re-runs. if (sheetFrame.getAttribute("src") == customizeURL) sheetFrame.contentWindow.location.reload()
else sheetFrame.setAttribute("src", customizeURL); // XXXmano: there's apparently no better
way to get this when the iframe is // hidden var sheetWidth = sheetFrame.style.width.match(/([0-9]+)px/)[1];
document.getElementById("customizeToolbarSheetPopup") .openPopup(gNavToolbox, "after_start", (window.innerWidth
- sheetWidth) / 2, 0); return sheetFrame.contentWindow; } else { return window.openDialog(customizeURL,
"CustomizeToolbar", "chrome,titlebar,toolbar,location,resizable,dependent", gNavToolbox); function BrowserToolboxCustomizeDone(aToolboxChanged)
{ if (gCustomizeSheet) { document.getElementById("customizeToolbarSheetIFrame").hidden = true; document.getElementById("customizeToolbarSheetPopup").hidePopup();
// Update global UI elements that may have been added or removed if (aToolboxChanged)
{ gURLBar = document.getElementById("urlbar"); if (gURLBar) gURLBar.emptyText = gURLBarEmptyText.value;
gProxyFavIcon = document.getElementById("page-proxy-favicon"); gHomeButton.updateTooltip(); gIdentityHandler._cacheElements();
window.XULBrowserWindow.init(); var backForwardDropmarker = document.getElementById("back-forward-dropmarker");
if (backForwardDropmarker) backForwardDropmarker.disabled = 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");
//@line 3442 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js" updateEditUIVisibility(); //@line 3444 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js"
UpdateUrlbarSearchSplitterState(); gHomeButton.updatePersonalToolbarStyle(); // Update the urlbar if (gURLBar) { URLBarSetURI();
XULBrowserWindow.asyncUpdateUI(); PlacesStarButton.updateState(); // Re-enable parts of the UI we disabled
during the dialog var menubar = document.getElementById("main-menubar"); for (var i = 0; i < menubar.childNodes.length;
++i) menubar.childNodes[i].setAttribute("disabled", false); var cmd = document.getElementById("cmd_CustomizeToolbars");
cmd.removeAttribute("disabled"); //@line 3469 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js"
// *** Shouldn't have to do this, but I do if (!gCustomizeSheet) window.focus(); function
BrowserToolboxCustomizeChange() { gHomeButton.updatePersonalToolbarStyle(); * Update the global flag that tracks whether
or not any edit UI (the Edit menu, * edit-related items in the context menu, and edit-related
toolbar buttons * is visible, then update the edit commands' enabled state accordingly.
We use * this flag to skip updating the edit commands on focus or selection changes *
when no UI is visible to improve performance (including pageload performance, * since focus
changes when you load a new page). * If UI is visible, we use goUpdateGlobalEditMenuItems
to set the commands' * enabled state so the UI will reflect it appropriately. * If the
UI isn't visible, we enable all edit commands so keyboard shortcuts * still work and just
lazily disable them as needed when the user presses a * shortcut. * This doesn't work
on Mac, since Mac menus flash when users press their * keyboard shortcuts, so edit UI is
essentially always visible on the Mac, * and we need to always update the edit commands.
Thus on Mac this function * is a no op. function updateEditUIVisibility() //@line 3503 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js"
let editMenuPopupState = document.getElementById("menu_EditPopup").state; let contextMenuPopupState = document.getElementById("contentAreaContextMenu").state;
let placesContextMenuPopupState = document.getElementById("placesContext").state; // The UI is visible if the Edit menu is
opening or open, if the context menu // is open, or if the toolbar has been customized
to include the Cut, Copy, // or Paste toolbar buttons. gEditUIVisible = editMenuPopupState
== "showing" || editMenuPopupState == "open" || contextMenuPopupState == "showing" ||
contextMenuPopupState == "open" || placesContextMenuPopupState == "showing" || placesContextMenuPopupState
== "open" || document.getElementById("cut-button") || document.getElementById("copy-button")
|| document.getElementById("paste-button") ? true : false; // If UI is visible, update
the edit commands' enabled state to reflect // whether or not they are actually enabled
for the current focus/selection. if (gEditUIVisible) goUpdateGlobalEditMenuItems(); // Otherwise,
enable all commands, so that keyboard shortcuts still work, // then lazily determine their
actual enabled state when the user presses // a keyboard shortcut. else { goSetCommandEnabled("cmd_undo",
true); goSetCommandEnabled("cmd_redo", true); goSetCommandEnabled("cmd_cut", true); goSetCommandEnabled("cmd_copy",
true); goSetCommandEnabled("cmd_paste", true); goSetCommandEnabled("cmd_selectAll", true);
goSetCommandEnabled("cmd_delete", true); goSetCommandEnabled("cmd_switchTextDirection", true); //@line 3539 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js"
var FullScreen = _XULNS: "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", toggle: function() // show/hide all menubars,
toolbars, and statusbars (except the full screen toolbar) this.showXULChrome("toolbar",
window.fullScreen); this.showXULChrome("statusbar", window.fullScreen); document.getElementById("View:FullScreen").setAttribute("checked",
!window.fullScreen); var fullScrToggler = document.getElementById("fullscr-toggler");
if (!window.fullScreen) { // Add a tiny toolbar to receive mouseover and dragenter events,
and provide affordance. // This will help simulate the "collapse" metaphor while also
requiring less code and // events than raw listening of mouse coords. if (!fullScrToggler)
{ fullScrToggler = document.createElement("toolbar"); fullScrToggler.id = "fullscr-toggler"; fullScrToggler.setAttribute("customizable",
"false"); fullScrToggler.setAttribute("moz-collapsed", "true"); var navBar = document.getElementById("nav-bar");
navBar.parentNode.insertBefore(fullScrToggler, navBar); } fullScrToggler.addEventListener("mouseover",
this._expandCallback, false); fullScrToggler.addEventListener("dragenter", this._expandCallback, false); if (gPrefService.getBoolPref("browser.fullscreen.autohide"))
gBrowser.mPanelContainer.addEventListener("mousemove", this._collapseCallback, false); document.addEventListener("keypress",
this._keyToggleCallback, false); document.addEventListener("popupshown", this._setPopupOpen, false); document.addEventListener("popuphidden",
this._setPopupOpen, false); this._shouldAnimate = true; this.mouseoverToggle(false); //
Autohide prefs gPrefService.addObserver("browser.fullscreen", this, false); } else { document.removeEventListener("keypress",
this._keyToggleCallback, false); document.removeEventListener("popupshown", this._setPopupOpen, false); document.removeEventListener("popuphidden",
this._setPopupOpen, false); gPrefService.removeObserver("browser.fullscreen", this); if (fullScrToggler) { fullScrToggler.removeEventListener("mouseover",
this._expandCallback, false); fullScrToggler.removeEventListener("dragenter", this._expandCallback, false); } // The user
may quit fullscreen during an animation clearInterval(this._animationInterval); clearTimeout(this._animationTimeout); gNavToolbox.style.marginTop
= "0px"; if (this._isChromeCollapsed) this.mouseoverToggle(true); this._isAnimating = false; // This is needed
if they use the context menu to quit fullscreen this._isPopupOpen = false; gBrowser.mPanelContainer.removeEventListener("mousemove",
this._collapseCallback, false); } }, observe: function(aSubject, aTopic, aData) if (aData
== "browser.fullscreen.autohide") { if (gPrefService.getBoolPref("browser.fullscreen.autohide")) { gBrowser.mPanelContainer.addEventListener("mousemove",
this._collapseCallback, false); } else { gBrowser.mPanelContainer.removeEventListener("mousemove",
this._collapseCallback, false); } } }, // Event callbacks _expandCallback: function()
FullScreen.mouseoverToggle(true); }, _collapseCallback: function() FullScreen.mouseoverToggle(false);
}, _keyToggleCallback: function(aEvent) // if we can use the keyboard (eg Ctrl+L or
Ctrl+E) to open the toolbars, we // should provide a way to collapse them too. if (aEvent.keyCode
== aEvent.DOM_VK_ESCAPE) { FullScreen._shouldAnimate = false; FullScreen.mouseoverToggle(false,
true); } // F6 is another shortcut to the address bar, but its not covered in OpenLocation()
else if (aEvent.keyCode == aEvent.DOM_VK_F6) FullScreen.mouseoverToggle(true); }, // Checks
whether we are allowed to collapse the chrome _isPopupOpen: false, _isChromeCollapsed: false,
_safeToCollapse: function(forceHide) if (!gPrefService.getBoolPref("browser.fullscreen.autohide")) return false; // a popup menu is open in chrome:
don't collapse chrome if (!forceHide && this._isPopupOpen) return false; // a textbox in chrome is focused
(location bar anyone?): don't collapse chrome if (document.commandDispatcher.focusedElement
&& document.commandDispatcher.focusedElement.ownerDocument == document && document.commandDispatcher.focusedElement.localName
== "input") { if (forceHide) // hidden textboxes that still have focus are bad bad bad document.commandDispatcher.focusedElement.blur();
else return false; } return true; }, _setPopupOpen: function(aEvent) // Popups should only veto
chrome collapsing if they were opened when the chrome was not collapsed. // Otherwise,
they would not affect chrome and the user would expect the chrome to go away. // e.g.
we wouldn't want the autoscroll icon firing this event, so when the user // toggles chrome
when moving mouse to the top, it doesn't go away again. if (aEvent.type == "popupshown"
&& !FullScreen._isChromeCollapsed && aEvent.target.localName != "tooltip" && aEvent.target.localName
!= "window") FullScreen._isPopupOpen = true; else if (aEvent.type == "popuphidden" &&
aEvent.target.localName != "tooltip" && aEvent.target.localName != "window") FullScreen._isPopupOpen = false;
}, // Autohide helpers for the context menu item getAutohide: function(aItem) aItem.setAttribute("checked",
gPrefService.getBoolPref("browser.fullscreen.autohide")); }, setAutohide: function() gPrefService.setBoolPref("browser.fullscreen.autohide",
!gPrefService.getBoolPref("browser.fullscreen.autohide")); }, // Animate the toolbars disappearing _shouldAnimate:
true, _isAnimating: false, _animationTimeout: null, _animationInterval: null, _animateUp:
function() // check again, the user may have done something before the animation was due
to start if (!window.fullScreen || !FullScreen._safeToCollapse(false)) { FullScreen._isAnimating = false; FullScreen._shouldAnimate
= true; return; } var animateFrameAmount = 2; function animateUpFrame() { animateFrameAmount
*= 2; if (animateFrameAmount >= (gNavToolbox.boxObject.height + gBrowser.mStrip.boxObject.height)) { //
We've animated enough clearInterval(FullScreen._animationInterval); gNavToolbox.style.marginTop = "0px"; FullScreen._isAnimating
= false; FullScreen._shouldAnimate = false; // Just to make sure FullScreen.mouseoverToggle(false);
return; } gNavToolbox.style.marginTop = (animateFrameAmount * -1) + "px"; } FullScreen._animationInterval
= setInterval(animateUpFrame, 70); }, mouseoverToggle: function(aShow, forceHide) // Don't do anything
if: // a) we're already in the state we want, // b) we're animating and will become collapsed
soon, or // c) we can't collapse because it would be undesirable right now if (aShow
!= this._isChromeCollapsed || (!aShow && this._isAnimating) || (!aShow && !this._safeToCollapse(forceHide)))
return; // browser.fullscreen.animateUp // 0 - never animate up // 1 - animate only
for first collapse after entering fullscreen (default for perf's sake) // 2 - animate every
time it collapses if (gPrefService.getIntPref("browser.fullscreen.animateUp") == 0) this._shouldAnimate = false; if (!aShow
&& this._shouldAnimate) { this._isAnimating = true; this._shouldAnimate = false; this._animationTimeout
= setTimeout(this._animateUp, 800); return; } // The chrome is collapsed so don't spam
needless mousemove events if (aShow) { gBrowser.mPanelContainer.addEventListener("mousemove", this._collapseCallback, false); } else {
gBrowser.mPanelContainer.removeEventListener("mousemove", this._collapseCallback, false); } gBrowser.mStrip.setAttribute("moz-collapsed",
!aShow); var allFSToolbars = document.getElementsByTagNameNS(this._XULNS, "toolbar"); for (var i = 0; i < allFSToolbars.length;
i++) { if (allFSToolbars[i].getAttribute("fullscreentoolbar") == "true") allFSToolbars[i].setAttribute("moz-collapsed",
!aShow); } document.getElementById("fullscr-toggler").setAttribute("moz-collapsed", aShow); this._isChromeCollapsed = !aShow;
if (gPrefService.getIntPref("browser.fullscreen.animateUp") == 2) this._shouldAnimate = true; }, showXULChrome:
function(aTag, aShow) var els = document.getElementsByTagNameNS(this._XULNS, aTag); for (var i = 0; i < els.length; ++i)
{ // *** don't interfere with previously collapsed toolbars if (els[i].getAttribute("fullscreentoolbar")
== "true") { if (!aShow) { var toolbarMode = els[i].getAttribute("mode"); if (toolbarMode
!= "text") { els[i].setAttribute("saved-mode", toolbarMode); els[i].setAttribute("saved-iconsize",
els[i].getAttribute("iconsize")); els[i].setAttribute("mode", "icons"); els[i].setAttribute("iconsize",
"small"); } // Give the main nav bar the fullscreen context menu, otherwise remove it // to prevent
breakage els[i].setAttribute("saved-context", els[i].getAttribute("context")); if (els[i].id
== "nav-bar") els[i].setAttribute("context", "autohide-context"); else els[i].removeAttribute("context");
// Set the inFullscreen attribute to allow specific styling // in fullscreen mode els[i].setAttribute("inFullscreen",
true); } else { function restoreAttr(attrName) { var savedAttr = "saved-" + attrName; if
(els[i].hasAttribute(savedAttr)) { els[i].setAttribute(attrName, els[i].getAttribute(savedAttr)); els[i].removeAttribute(savedAttr);
} } restoreAttr("mode"); restoreAttr("iconsize"); restoreAttr("context"); els[i].removeAttribute("inFullscreen");
} } else { // use moz-collapsed so it doesn't persist hidden/collapsed, // so that new windows
don't have missing toolbars if (aShow) els[i].removeAttribute("moz-collapsed"); else els[i].setAttribute("moz-collapsed",
"true"); } } if (aShow) gNavToolbox.removeAttribute("inFullscreen"); else gNavToolbox.setAttribute("inFullscreen",
true); var controls = document.getElementsByAttribute("fullscreencontrol", "true"); for (var i = 0; i < controls.length;
++i) controls[i].hidden = aShow; * Returns true if |aMimeType| is text-based, false otherwise.
* @param aMimeType * The MIME type to check. * If adding types to this function, please
also check the similar * function in findbar.xml function mimeTypeIsTextBased(aMimeType) return
/^text\/|\+xml$/.test(aMimeType) || aMimeType == "application/x-javascript" || aMimeType
== "application/javascript" || aMimeType == "application/xml" || aMimeType == "mozilla.application/cached-xul";
var XULBrowserWindow = { // Stored Status, Link and Loading values status: "", defaultStatus:
"", jsStatus: "", jsDefaultStatus: "", overLink: "", startTime: 0, statusText: "", lastURI:
null, isBusy: false, statusTimeoutInEffect: false, QueryInterface: function (aIID) {
if (aIID.equals(Ci.nsIWebProgressListener) || aIID.equals(Ci.nsIWebProgressListener2)
|| aIID.equals(Ci.nsISupportsWeakReference) || aIID.equals(Ci.nsIXULBrowserWindow) ||
aIID.equals(Ci.nsISupports)) return this; throw Cr.NS_NOINTERFACE; }, get statusMeter
() { delete this.statusMeter; return this.statusMeter = document.getElementById("statusbar-icon");
}, get stopCommand () { delete this.stopCommand; return this.stopCommand = document.getElementById("Browser:Stop");
}, get reloadCommand () { delete this.reloadCommand; return this.reloadCommand = document.getElementById("Browser:Reload");
}, get statusTextField () { delete this.statusTextField; return this.statusTextField = document.getElementById("statusbar-display");
}, get securityButton () { delete this.securityButton; return this.securityButton = document.getElementById("security-button");
}, get isImage () { delete this.isImage; return this.isImage = document.getElementById("isImage");
}, get _uriFixup () { delete this._uriFixup; return this._uriFixup = Cc["@mozilla.org/docshell/urifixup;1"]
.getService(Ci.nsIURIFixup); }, init: function () { this.throbberElement = document.getElementById("navigator-throbber");
// Initialize the security button's state and tooltip text. Remember to reset // _hostChanged,
otherwise onSecurityChange will short circuit. var securityUI = gBrowser.securityUI; this._hostChanged
= true; this.onSecurityChange(null, null, securityUI.state); }, destroy: function ()
{ // XXXjag to avoid leaks :-/, see bug 60729 delete this.throbberElement; delete this.statusMeter;
delete this.stopCommand; delete this.reloadCommand; delete this.statusTextField; delete this.securityButton;
delete this.statusText; delete this.lastURI; }, setJSStatus: function (status) { this.jsStatus
= status; this.updateStatusField(); }, setJSDefaultStatus: function (status) { this.jsDefaultStatus
= status; this.updateStatusField(); }, setDefaultStatus: function (status) { this.defaultStatus =
status; this.updateStatusField(); }, setOverLink: function (link, b) { // Encode bidirectional
formatting characters. // (RFC 3987 sections 3.2 and 4.1 paragraph 6) this.overLink =
link.replace(/[\u200e\u200f\u202a\u202b\u202c\u202d\u202e]/g, encodeURIComponent); this.updateStatusField();
}, updateStatusField: function () { var text = this.overLink || this.status || this.jsStatus
|| this.jsDefaultStatus || this.defaultStatus; // check the current value so we don't trigger
an attribute change // and cause needless (slow!) UI updates if (this.statusText !=
text) { this.statusTextField.label = text; this.statusText = text; } }, onLinkIconAvailable:
function (aBrowser) { if (gProxyFavIcon && gBrowser.userTypedValue === null) PageProxySetIcon(aBrowser.mIconURL);
// update the favicon in the URL bar }, onProgressChange: function (aWebProgress,
aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress) { //
Check this._busyUI to be safe, because we don't want to update // the progress meter
when restoring a page from bfcache. if (aMaxTotalProgress > 0 && this._busyUI) { // This is highly
optimized. Don't touch this code unless // you are intimately familiar with the cost
of setting // attrs on XUL elements. -- hyatt let percentage = (aCurTotalProgress * 100)
/ aMaxTotalProgress; this.statusMeter.value = percentage; } }, onProgressChange64: function
(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress)
{ return this.onProgressChange(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress,
aCurTotalProgress, aMaxTotalProgress); }, onStateChange: function (aWebProgress, aRequest,
aStateFlags, aStatus) { const nsIWebProgressListener = Ci.nsIWebProgressListener; const nsIChannel
= Ci.nsIChannel; if (aStateFlags & nsIWebProgressListener.STATE_START) { // This (thanks to the filter) is a network
start or the first // stray request (the first request outside of the document load), //
initialize the throbber and his friends. // Call start document load listeners (only
if this is a network load) if (aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK
&& aRequest && aWebProgress.DOMWindow == content) this.startDocumentLoad(aRequest);
this.isBusy = true; if (!(aStateFlags & nsIWebProgressListener.STATE_RESTORING)) { this._busyUI = true; // Turn the throbber
on. if (this.throbberElement) this.throbberElement.setAttribute("busy", "true"); // Turn the status meter on. this.statusMeter.value
= 0; // be sure to clear the progress bar if (gProgressCollapseTimer) { window.clearTimeout(gProgressCollapseTimer);
gProgressCollapseTimer = null; } else this.statusMeter.parentNode.collapsed = false; // ***: This needs to be based on
window activity... this.stopCommand.removeAttribute("disabled"); } } else if (aStateFlags & nsIWebProgressListener.STATE_STOP)
{ if (aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK) { if (aWebProgress.DOMWindow == content)
{ if (aRequest) this.endDocumentLoad(aRequest, aStatus); if (!gBrowser.mTabbedMode && !gBrowser.mCurrentBrowser.mIconURL)
gBrowser.useDefaultIcon(gBrowser.mCurrentTab); } } // This (thanks to the filter) is a network
stop or the last // request stop outside of loading the document, stop throbbers // and
progress bars and such if (aRequest) { let msg = ""; let location; // Get the URI either
from a channel or a pseudo-object if (aRequest instanceof nsIChannel || "URI" in aRequest)
{ location = aRequest.URI; // For keyword URIs clear the user typed value since they
will be changed into real URIs if (location.scheme == "keyword" && aWebProgress.DOMWindow ==
content) gBrowser.userTypedValue = null; if (location.spec != "about:blank") { switch
(aStatus) { case Components.results.NS_BINDING_ABORTED: msg = gNavigatorBundle.getString("nv_stopped");
break; case Components.results.NS_ERROR_NET_TIMEOUT: msg = gNavigatorBundle.getString("nv_timeout");
break; } } } // If msg is false then we did not have an error (channel may have // been
null, in the case of a stray image load). if (!msg && (!location || location.spec !=
"about:blank")) msg = gNavigatorBundle.getString("nv_done"); this.status = ""; this.setDefaultStatus(msg);
// Disable menu entries for images, enable otherwise if (content.document && mimeTypeIsTextBased(content.document.contentType))
this.isImage.removeAttribute('disabled'); else this.isImage.setAttribute('disabled',
'true'); } this.isBusy = false; if (this._busyUI) { this._busyUI = false; // Turn the progress
meter and throbber off. gProgressCollapseTimer = window.setTimeout(function () { gProgressMeterPanel.collapsed
= true; gProgressCollapseTimer = null; }, 100); if (this.throbberElement) this.throbberElement.removeAttribute("busy");
this.stopCommand.setAttribute("disabled", "true"); } } }, onLocationChange: function
(aWebProgress, aRequest, aLocationURI) { var location = aLocationURI ? aLocationURI.spec
: ""; this._hostChanged = true; if (document.tooltipNode) { // Optimise for the common case if (aWebProgress.DOMWindow
== content) { document.getElementById("aHTMLTooltip").hidePopup(); document.tooltipNode = null; } else { for
(let tooltipWindow = document.tooltipNode.ownerDocument.defaultView; tooltipWindow != tooltipWindow.parent; tooltipWindow
= tooltipWindow.parent) { if (tooltipWindow == aWebProgress.DOMWindow) { document.getElementById("aHTMLTooltip").hidePopup();
document.tooltipNode = null; break; } } } } // This code here does not compare uris
exactly when determining // whether or not the message should be hidden since the message
// may be prematurely hidden when an install is invoked by a click // on a link that looks
like this: // // Install Foo // // - which
fires a onLocationChange message to uri + '#'... var selectedBrowser = gBrowser.selectedBrowser;
if (selectedBrowser.lastURI) { let oldSpec = selectedBrowser.lastURI.spec; let oldIndexOfHash
= oldSpec.indexOf("#"); if (oldIndexOfHash != -1) oldSpec = oldSpec.substr(0, oldIndexOfHash);
let newSpec = location; let newIndexOfHash = newSpec.indexOf("#"); if (newIndexOfHash
!= -1) newSpec = newSpec.substr(0, newSpec.indexOf("#")); if (newSpec != oldSpec) { // Remove all the
notifications, except for those which want to // persist across the first location change.
let nBox = gBrowser.getNotificationBox(selectedBrowser); nBox.removeTransientNotifications(); } }
selectedBrowser.lastURI = aLocationURI; // Disable menu entries for images, enable otherwise
if (content.document && mimeTypeIsTextBased(content.document.contentType)) this.isImage.removeAttribute('disabled');
else this.isImage.setAttribute('disabled', 'true'); this.setOverLink("", null); // We
should probably not do this if the value has changed since the user // searched // Update
urlbar only if a new page was loaded on the primary content area // Do not update urlbar
if there was a subframe navigation var browser = gBrowser.selectedBrowser; if (aWebProgress.DOMWindow
== content) { if ((location == "about:blank" && !content.opener) || location == "") {
// Second condition is for new tabs, otherwise // reload function is enabled until tab is
refreshed. this.reloadCommand.setAttribute("disabled", "true"); } else { this.reloadCommand.removeAttribute("disabled");
} if (!gBrowser.mTabbedMode && aWebProgress.isLoadingDocument) gBrowser.setIcon(gBrowser.mCurrentTab, null);
if (gURLBar) { // Strip off "wyciwyg://" and passwords for the location bar let uri =
aLocationURI; try { uri = this._uriFixup.createExposableURI(uri); } catch (e) {} URLBarSetURI(uri, true);
// Update starring UI PlacesStarButton.updateState(); } } UpdateBackForwardCommands(gBrowser.webNavigation);
if (gFindBar.findMode != gFindBar.FIND_NORMAL) { // Close the Find toolbar if we're in old-style
TAF mode gFindBar.close(); } // XXXmano new-findbar, do something useful once it lands. // Of course,
this is especially wrong with bfcache on... // fix bug 253793 - turn off highlight when
page changes gFindBar.getElement("highlight").checked = false; // See bug 358202, when tabs are
switched during a drag operation, // timers don't fire on windows (bug 203573) if (aRequest)
setTimeout(function () { XULBrowserWindow.asyncUpdateUI(); }, 0); else this.asyncUpdateUI(); }, asyncUpdateUI:
function () { FeedHandler.updateFeeds(); BrowserSearch.updateSearchButton(); }, onStatusChange: function (aWebProgress,
aRequest, aStatus, aMessage) { this.status = aMessage; this.updateStatusField(); },
// Properties used to cache security state used to update the UI _state: null, _tooltipText:
null, _hostChanged: false, // onLocationChange will flip this bit onSecurityChange: function
(aWebProgress, aRequest, aState) { // Don't need to do anything if the data we use to
update the UI hasn't // changed if (this._state == aState && this._tooltipText == gBrowser.securityUI.tooltipText
&& !this._hostChanged) { //@line 4238 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js" return; } this._state = aState; //@line 4249
"e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js" this._hostChanged = false; this._tooltipText
= gBrowser.securityUI.tooltipText // aState is defined as a bitmask that may be extended
in the future. // We filter out any unknown bits before testing for known values. const
wpl = Components.interfaces.nsIWebProgressListener; const wpl_security_bits = wpl.STATE_IS_SECURE
| wpl.STATE_IS_BROKEN | wpl.STATE_IS_INSECURE | wpl.STATE_SECURE_HIGH | wpl.STATE_SECURE_MED
| wpl.STATE_SECURE_LOW; var level; switch (this._state & wpl_security_bits) { case wpl.STATE_IS_SECURE
| wpl.STATE_SECURE_HIGH: level = "high"; break; case wpl.STATE_IS_SECURE | wpl.STATE_SECURE_MED:
case wpl.STATE_IS_SECURE | wpl.STATE_SECURE_LOW: level = "low"; break; case wpl.STATE_IS_BROKEN:
level = "broken"; break; } if (level) { this.securityButton.setAttribute("level", level); this.securityButton.hidden = false;
// We don't style the Location Bar based on the the 'level' attribute // anymore, but
still set it for third-party themes. if (gURLBar) gURLBar.setAttribute("level", level); } else
{ this.securityButton.hidden = true; this.securityButton.removeAttribute("level"); if (gURLBar) gURLBar.removeAttribute("level");
} this.securityButton.setAttribute("tooltiptext", this._tooltipText); // Don't pass in the actual
location object, since it can cause us to // hold on to the window object too long.
Just pass in the fields we // care about. (bug 424829) var location = gBrowser.contentWindow.location;
var locationObj = {}; try { locationObj.host = location.host; locationObj.hostname =
location.hostname; locationObj.port = location.port; } catch (ex) { // Can sometimes throw if
the URL being visited has no host/hostname, // e.g. about:blank. The _state for these
pages means we won't need these // properties anyways, though. } gIdentityHandler.checkIdentity(this._state,
locationObj); }, // simulate all change notifications after switching tabs onUpdateCurrentBrowser:
function (aStateFlags, aStatus, aMessage, aTotalProgress) { if (FullZoom.updateBackgroundTabs)
FullZoom.onLocationChange(gBrowser.currentURI, true); var nsIWebProgressListener = Components.interfaces.nsIWebProgressListener;
var loadingDone = aStateFlags & nsIWebProgressListener.STATE_STOP; // use a pseudo-object instead of a (potentially
non-existing) channel for getting // a correct error message - and make sure that the UI
is always either in // loading (STATE_START) or done (STATE_STOP) mode this.onStateChange(
gBrowser.webProgress, { URI: gBrowser.currentURI }, loadingDone ? nsIWebProgressListener.STATE_STOP
: nsIWebProgressListener.STATE_START, aStatus ); // status message and progress value are
undefined if we're done with loading if (loadingDone) return; this.onStatusChange(gBrowser.webProgress,
null, 0, aMessage); this.onProgressChange(gBrowser.webProgress, 0, 0, aTotalProgress, 1); }, startDocumentLoad:
function (aRequest) { // clear out feed data gBrowser.mCurrentBrowser.feeds = null; //
clear out search-engine data gBrowser.mCurrentBrowser.engines = null; var uri = aRequest.QueryInterface(Ci.nsIChannel).URI;
var observerService = Cc["@mozilla.org/observer-service;1"] .getService(Ci.nsIObserverService); // Set
the URI now if it isn't already set, so that the user can tell which // site is loading.
Only do this if the content window has no opener, though // (i.e. the load wasn't triggered
by a content-controlled link), to // minimize spoofing risk. if (gURLBar && gURLBar.value
== "" && !content.opener && getWebNavigation().currentURI.spec == "about:blank") URLBarSetURI(uri); try
{ observerService.notifyObservers(content, "StartDocumentLoad", uri.spec); } catch (e)
{ } }, endDocumentLoad: function (aRequest, aStatus) { var urlStr = aRequest.QueryInterface(Ci.nsIChannel).originalURI.spec;
var observerService = Cc["@mozilla.org/observer-service;1"] .getService(Ci.nsIObserverService); var notification
= Components.isSuccessCode(aStatus) ? "EndDocumentLoad" : "FailDocumentLoad"; try { observerService.notifyObservers(content,
notification, urlStr); } catch (e) { } var TabsProgressListener = { onProgressChange:
function (aBrowser, aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress,
aMaxTotalProgress) { }, onStateChange: function (aBrowser, aWebProgress, aRequest, aStateFlags,
aStatus) { //@line 4381 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js" if (aRequest instanceof Ci.nsIChannel &&
aStateFlags & Ci.nsIWebProgressListener.STATE_START && aStateFlags & Ci.nsIWebProgressListener.STATE_IS_DOCUMENT
&& gCrashReporter.enabled) { gCrashReporter.annotateCrashReport("URL", aRequest.URI.spec); } //@line 4388 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js"
}, onLocationChange: function (aBrowser, aWebProgress, aRequest, aLocationURI) { //
Filter out any sub-frame loads if (aBrowser.contentWindow == aWebProgress.DOMWindow) FullZoom.onLocationChange(aLocationURI,
false, aBrowser); }, onStatusChange: function (aBrowser, aWebProgress, aRequest, aStatus,
aMessage) { }, onRefreshAttempted: function (aBrowser, aWebProgress, aURI, aDelay, aSameURI)
{ if (gPrefService.getBoolPref("accessibility.blockautorefresh")) { let brandBundle = document.getElementById("bundle_brand");
let brandShortName = brandBundle.getString("brandShortName"); let refreshButtonText = gNavigatorBundle.getString("refreshBlocked.goButton");
let refreshButtonAccesskey = gNavigatorBundle.getString("refreshBlocked.goButton.accesskey"); let message = gNavigatorBundle.getFormattedString(aSameURI
? "refreshBlocked.refreshLabel" : "refreshBlocked.redirectLabel", [brandShortName]); let docShell = aWebProgress.DOMWindow
.QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsIWebNavigation) .QueryInterface(Ci.nsIDocShell);
let notificationBox = gBrowser.getNotificationBox(aBrowser); let notification = notificationBox.getNotificationWithValue("refresh-blocked");
if (notification) { notification.label = message; notification.refreshURI = aURI; notification.delay
= aDelay; notification.docShell = docShell; } else { let buttons = [{ label: refreshButtonText,
accessKey: refreshButtonAccesskey, callback: function (aNotification, aButton) { var refreshURI
= aNotification.docShell .QueryInterface(Ci.nsIRefreshURI); refreshURI.forceRefreshURI(aNotification.refreshURI,
aNotification.delay, true); } }]; notification = notificationBox.appendNotification(message,
"refresh-blocked", "chrome://browser/skin/Info.png", notificationBox.PRIORITY_INFO_MEDIUM, buttons);
notification.refreshURI = aURI; notification.delay = aDelay; notification.docShell = docShell;
} return false; } return true; }, onSecurityChange: function (aBrowser, aWebProgress, aRequest,
aState) { function nsBrowserAccess() nsBrowserAccess.prototype = QueryInterface : function(aIID) if (aIID.equals(Ci.nsIBrowserDOMWindow)
|| aIID.equals(Ci.nsISupports)) return this; throw Components.results.NS_NOINTERFACE;
}, openURI : function (aURI, aOpener, aWhere, aContext) var newWindow = null; var isExternal
= (aContext == Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL); if (isExternal && aURI && aURI.schemeIs("chrome"))
{ dump("use -chrome command-line option to load external chrome urls\n"); return null;
} var loadflags = isExternal ? Ci.nsIWebNavigation.LOAD_FLAGS_FROM_EXTERNAL : Ci.nsIWebNavigation.LOAD_FLAGS_NONE; if
(aWhere == Ci.nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW) aWhere = gPrefService.getIntPref("browser.link.open_newwindow");
switch (aWhere) { case Ci.nsIBrowserDOMWindow.OPEN_NEWWINDOW : // FIXME: Bug 408379. So how come this
doesn't send the // referrer like the other loads do? var url = aURI ? aURI.spec : "about:blank";
// Pass all params to openDialog to ensure that "url" isn't passed through // loadOneOrMoreURIs,
which splits based on "|" newWindow = openDialog(getBrowserURL(), "_blank", "all,dialog=no", url, null, null,
null); break; case Ci.nsIBrowserDOMWindow.OPEN_NEWTAB : let win, needToFocusWin; // try the current
window. if we're in a popup, fall back on the most recent browser window if (!window.document.documentElement.getAttribute("chromehidden"))
win = window; else { win = Cc["@mozilla.org/browser/browserglue;1"] .getService(Ci.nsIBrowserGlue) .getMostRecentBrowserWindow();
needToFocusWin = true; } if (!win) { // we couldn't find a suitable window, a new one
needs to be opened. return null; } let loadInBackground = gPrefService.getBoolPref("browser.tabs.loadDivertedInBackground");
let referrer = aOpener ? makeURI(aOpener.location.href) : null; // If this is an external load, we
need to load a blank tab first, // because loadflags can't be passed to loadOneTab. let
loadBlankFirst = !aURI || isExternal; let tab = win.gBrowser.loadOneTab(loadBlankFirst
? "about:blank" : aURI.spec, referrer, null, null, loadInBackground, false); let browser
= win.gBrowser.getBrowserForTab(tab); if (loadBlankFirst && aURI) browser.loadURIWithFlags(aURI.spec,
loadflags, referrer, null, null); newWindow = browser.contentWindow; if (needToFocusWin
|| (!loadInBackground && isExternal)) newWindow.focus(); break; default : // OPEN_CURRENTWINDOW or
an illegal value newWindow = content; if (aURI) { let referrer = aOpener ? makeURI(aOpener.location.href)
: null; gBrowser.loadURIWithFlags(aURI.spec, loadflags, referrer, null, null); } if (!gPrefService.getBoolPref("browser.tabs.loadDivertedInBackground"))
content.focus(); } return newWindow; }, isTabContentWindow : function (aWindow) return gBrowser.browsers.some(function
(browser) browser.contentWindow == aWindow); function onViewToolbarsPopupShowing(aEvent)
var popup = aEvent.target; var i; // Empty the menu for (i = popup.childNodes.length-1;
i >= 0; --i) { var deadItem = popup.childNodes[i]; if (deadItem.hasAttribute("toolbarindex"))
popup.removeChild(deadItem); var firstMenuItem = popup.firstChild; for (i = 0; i < gNavToolbox.childNodes.length;
++i) { var toolbar = gNavToolbox.childNodes[i]; var toolbarName = toolbar.getAttribute("toolbarname");
if (toolbarName) { let menuItem = document.createElement("menuitem"); let hidingAttribute = toolbar.getAttribute("type")
== "menubar" ? "autohide" : "collapsed"; menuItem.setAttribute("toolbarindex", i);
menuItem.setAttribute("type", "checkbox"); menuItem.setAttribute("label", toolbarName);
menuItem.setAttribute("accesskey", toolbar.getAttribute("accesskey")); menuItem.setAttribute("checked", toolbar.getAttribute(hidingAttribute)
!= "true"); popup.insertBefore(menuItem, firstMenuItem); menuItem.addEventListener("command",
onViewToolbarCommand, false); } toolbar = toolbar.nextSibling; function onViewToolbarCommand(aEvent)
var index = aEvent.originalTarget.getAttribute("toolbarindex"); var toolbar = gNavToolbox.childNodes[index];
var hidingAttribute = toolbar.getAttribute("type") == "menubar" ? "autohide" : "collapsed";
toolbar.setAttribute(hidingAttribute, aEvent.originalTarget.getAttribute("checked") != "true"); document.persist(toolbar.id,
hidingAttribute); function displaySecurityInfo() BrowserPageInfo(null, "securityTab"); * Opens
or closes the sidebar identified by commandID. * @param commandID a string identifying the
sidebar to toggle; see the * note below. (Optional if a sidebar is already open.) * @param forceOpen
boolean indicating whether the sidebar should be * opened regardless of its current state
(optional). * @note * We expect to find a xul:broadcaster element with the specified
ID. * The following attributes on that element may be used and/or modified: * - id (required)
the string to match commandID. The convention * is to use this naming scheme: 'viewSidebar'.
* - sidebarurl (required) specifies the URL to load in this sidebar. * - sidebartitle
or label (in that order) specify the title to * display on the sidebar. * - checked indicates
whether the sidebar is currently displayed. * Note that toggleSidebar updates this attribute
when * it changes the sidebar's visibility. * - group this attribute must be set to "sidebar".
function toggleSidebar(commandID, forceOpen) { var sidebarBox = document.getElementById("sidebar-box");
if (!commandID) commandID = sidebarBox.getAttribute("sidebarcommand"); var sidebarBroadcaster = document.getElementById(commandID);
var sidebar = document.getElementById("sidebar"); // xul:browser var sidebarTitle = document.getElementById("sidebar-title");
var sidebarSplitter = document.getElementById("sidebar-splitter"); if (sidebarBroadcaster.getAttribute("checked")
== "true") { if (!forceOpen) { sidebarBroadcaster.removeAttribute("checked"); sidebarBox.setAttribute("sidebarcommand",
""); sidebarTitle.value = ""; sidebar.setAttribute("src", "about:blank"); sidebarBox.hidden = true;
sidebarSplitter.hidden = true; content.focus(); } else { fireSidebarFocusedEvent(); } return;
// now we need to show the specified sidebar // ..but first update the 'checked' state
of all sidebar broadcasters var broadcasters = document.getElementsByAttribute("group",
"sidebar"); for (var i = 0; i < broadcasters.length; ++i) { // skip elements that observe sidebar
broadcasters and random // other elements if (broadcasters[i].localName != "broadcaster")
continue; if (broadcasters[i] != sidebarBroadcaster) broadcasters[i].removeAttribute("checked");
else sidebarBroadcaster.setAttribute("checked", "true"); sidebarBox.hidden = false; sidebarSplitter.hidden
= false; var url = sidebarBroadcaster.getAttribute("sidebarurl"); var title = sidebarBroadcaster.getAttribute("sidebartitle");
if (!title) title = sidebarBroadcaster.getAttribute("label"); sidebar.setAttribute("src", url); // kick
off async load sidebarBox.setAttribute("sidebarcommand", sidebarBroadcaster.id); sidebarTitle.value
= title; // We set this attribute here in addition to setting it on the //
element itself, because the code in BrowserShutdown persists this // attribute, not the "src"
of the . The reason it // does that is that we want to delay sidebar
load a bit when a browser // window opens. See delayedStartup(). sidebarBox.setAttribute("src",
url); if (sidebar.contentDocument.location.href != url) sidebar.addEventListener("load",
sidebarOnLoad, true); else // older code handled this case, so we do it too fireSidebarFocusedEvent();
function sidebarOnLoad(event) { var sidebar = document.getElementById("sidebar"); sidebar.removeEventListener("load",
sidebarOnLoad, true); // We're handling the 'load' event before it bubbles up to the usual
// (non-capturing) event handlers. Let it bubble up before firing the // SidebarFocused
event. setTimeout(fireSidebarFocusedEvent, 0); * Fire a "SidebarFocused" event on the
sidebar's |window| to give the sidebar * a chance to adjust focus as needed. An additional
event is needed, because * we don't want to focus the sidebar when it's opened on startup
or in a new * window, only when the user opens the sidebar. function fireSidebarFocusedEvent()
{ var sidebar = document.getElementById("sidebar"); var event = document.createEvent("Events");
event.initEvent("SidebarFocused", true, false); sidebar.contentWindow.dispatchEvent(event);
var gHomeButton = { prefDomain: "browser.startup.homepage", observe: function (aSubject, aTopic, aPrefName)
if (aTopic != "nsPref:changed" || aPrefName != this.prefDomain) return; this.updateTooltip();
}, updateTooltip: function (homeButton) if (!homeButton) homeButton = document.getElementById("home-button");
if (homeButton) { var homePage = this.getHomePage(); homePage = homePage.replace(/\|/g,', ');
homeButton.setAttribute("tooltiptext", homePage); } }, getHomePage: function () var url; try
{ url = gPrefService.getComplexValue(this.prefDomain, Components.interfaces.nsIPrefLocalizedString).data;
} catch (e) { } // use this if we can't find the pref if (!url) { var SBS = Cc["@mozilla.org/intl/stringbundle;1"].getService(Ci.nsIStringBundleService);
var configBundle = SBS.createBundle("resource:/browserconfig.properties"); url = configBundle.GetStringFromName(this.prefDomain);
} return url; }, updatePersonalToolbarStyle: function (homeButton) if (!homeButton) homeButton
= document.getElementById("home-button"); if (homeButton) homeButton.className = homeButton.parentNode.id
== "PersonalToolbar" || homeButton.parentNode.parentNode.id == "PersonalToolbar" ? homeButton.className.replace("toolbarbutton-1",
"bookmark-item") : homeButton.className.replace("bookmark-item", "toolbarbutton-1"); * Gets the selected text
in the active browser. Leading and trailing * whitespace is removed, and consecutive
whitespace is replaced by a single * space. A maximum of 150 characters will be returned,
regardless of the value * of aCharLen. * @param aCharLen * The maximum number of characters
to return. function getBrowserSelection(aCharLen) { // selections of more than 150 characters
aren't useful const kMaxSelectionLen = 150; const charLen = Math.min(aCharLen || kMaxSelectionLen,
kMaxSelectionLen); var focusedWindow = document.commandDispatcher.focusedWindow; var selection = focusedWindow.getSelection().toString();
if (selection) { if (selection.length > charLen) { // only use the first charLen important
chars. see bug 221361 var pattern = new RegExp("^(?:\\s*.){0," + charLen + "}"); pattern.test(selection);
selection = RegExp.lastMatch; } selection = selection.replace(/^\s+/, "") .replace(/\s+$/,
"") .replace(/\s+/g, " "); if (selection.length > charLen) selection = selection.substr(0,
charLen); return selection; var gWebPanelURI; function openWebPanel(aTitle, aURI) // Ensure
that the web panels sidebar is open. toggleSidebar('viewWebPanelsSidebar', true); // Set the title of the panel. document.getElementById("sidebar-title").value
= aTitle; // Tell the Web Panels sidebar to load the bookmark. var sidebar = document.getElementById("sidebar");
if (sidebar.docShell && sidebar.contentDocument && sidebar.contentDocument.getElementById('web-panels-browser'))
{ sidebar.contentWindow.loadWebPanel(aURI); if (gWebPanelURI) { gWebPanelURI = ""; sidebar.removeEventListener("load",
asyncOpenWebPanel, true); } } else { // The panel is still being constructed. Attach an
onload handler. if (!gWebPanelURI) sidebar.addEventListener("load", asyncOpenWebPanel, true); gWebPanelURI =
aURI; } function asyncOpenWebPanel(event) var sidebar = document.getElementById("sidebar");
if (gWebPanelURI && sidebar.contentDocument && sidebar.contentDocument.getElementById('web-panels-browser'))
sidebar.contentWindow.loadWebPanel(gWebPanelURI); gWebPanelURI = ""; sidebar.removeEventListener("load",
asyncOpenWebPanel, true); * - [ Dependencies ] ---------------------------------------------------------
* utilityOverlay.js: * - gatherTextUnder // Called whenever the user clicks in the
content area, // except when left-clicking on links (special case) // should always return
true for click to go through function contentAreaClick(event, fieldNormalClicks) if (!event.isTrusted ||
event.getPreventDefault()) { return true; } var target = event.target; var linkNode;
if (target instanceof HTMLAnchorElement || target instanceof HTMLAreaElement || target
instanceof HTMLLinkElement) { if (target.hasAttribute("href")) linkNode = target; // xxxmpc: this is kind
of a hack to work around a Gecko bug (see bug 266932) // we're going to walk up the
DOM looking for a parent link node, // this shouldn't be necessary, but we're matching
the existing behaviour for left click var parent = target.parentNode; while (parent)
{ if (parent instanceof HTMLAnchorElement || parent instanceof HTMLAreaElement ||
parent instanceof HTMLLinkElement) { if (parent.hasAttribute("href")) linkNode = parent; } parent = parent.parentNode;
} } else { linkNode = event.originalTarget; while (linkNode && !(linkNode instanceof HTMLAnchorElement))
linkNode = linkNode.parentNode; // cannot be nested. So if we find an anchor without
an // href, there is no useful around the target if (linkNode && !linkNode.hasAttribute("href"))
linkNode = null; } var wrapper = null; if (linkNode) { wrapper = linkNode; if (event.button
== 0 && !event.ctrlKey && !event.shiftKey && !event.altKey && !event.metaKey) { //
A Web panel's links should target the main content area. Do this // if no modifier keys
are down and if there's no target or the target equals // _main (the IE convention) or _content
(the Mozilla convention). // *** Now that markLinkVisited is gone, we may not need to
field _main and // _content here. target = wrapper.getAttribute("target"); if (fieldNormalClicks
&& (!target || target == "_content" || target == "_main")) // IE uses _main, SeaMonkey
uses _content, we support both { if (!wrapper.href) return true; if (wrapper.getAttribute("onclick"))
return true; // javascript links should be executed in the current browser if (wrapper.href.substr(0,
11) === "javascript:") return true; // data links should be executed in the current browser
if (wrapper.href.substr(0, 5) === "data:") return true; try { urlSecurityCheck(wrapper.href,
wrapper.ownerDocument.nodePrincipal); } catch(ex) { return false; } var postData = { }; var
url = getShortcutOrURI(wrapper.href, postData); if (!url) return true; loadURI(url, null,
postData.value, false); event.preventDefault(); return false; } else if (linkNode.getAttribute("rel")
== "sidebar") { // This is the Opera convention for a special link that - when clicked -
allows // you to add a sidebar panel. We support the Opera convention here. The link's //
title attribute contains the title that should be used for the sidebar panel. PlacesUIUtils.showMinimalAddBookmarkUI(makeURI(wrapper.href),
wrapper.getAttribute("title"), null, null, true, true); event.preventDefault(); return
false; } } else { handleLinkClick(event, wrapper.href, linkNode); } return true; } else { // Try
simple XLink var href, realHref, baseURI; linkNode = target; while (linkNode) { if (linkNode.nodeType
== Node.ELEMENT_NODE) { wrapper = linkNode; realHref = wrapper.getAttributeNS("http://www.w3.org/1999/xlink",
"href"); if (realHref) { href = realHref; baseURI = wrapper.baseURI } } linkNode =
linkNode.parentNode; } if (href) { href = makeURLAbsolute(baseURI, href); handleLinkClick(event,
href, null); return true; } } if (event.button == 1 && gPrefService.getBoolPref("middlemouse.contentLoadURL")
&& !gPrefService.getBoolPref("general.autoScroll")) { middleMousePaste(event); } return true;
function handleLinkClick(event, href, linkNode) var doc = event.target.ownerDocument; switch
(event.button) { case 0: // if left button clicked //@line 4966 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js"
if (event.ctrlKey) { //@line 4968 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js" openNewTabWith(href, doc, null, event, false);
event.stopPropagation(); return true; } if (event.shiftKey && event.altKey) { var feedService
= Cc["@mozilla.org/browser/feeds/result-service;1"]. getService(Ci.nsIFeedResultService); feedService.forcePreviewPage
= true; loadURI(href, null, null, false); return false; } if (event.shiftKey) { openNewWindowWith(href,
doc, null, false); event.stopPropagation(); return true; } if (event.altKey) { saveURL(href,
linkNode ? gatherTextUnder(linkNode) : "", null, true, true, doc.documentURIObject);
return true; } return false; case 1: // if middle button clicked var tab = gPrefService.getBoolPref("browser.tabs.opentabfor.middleclick");
if (tab) openNewTabWith(href, doc, null, event, false); else openNewWindowWith(href, doc,
null, false); event.stopPropagation(); return true; return false; function middleMousePaste(event)
var url = readFromClipboard(); if (!url) return; var postData = { }; url = getShortcutOrURI(url,
postData); if (!url) return; try { addToUrlbarHistory(url); } catch (ex) { // Things may go wrong when
adding url to session history, // but don't let that interfere with the loading of the
url. Cu.reportError(ex); openUILink(url, event, true /* ignore the fact this is a middle click
*/); event.stopPropagation(); * Note that most of this routine has been moved into C++
in order to * be available for all tags as well as gecko embedding. See * mozilla/content/base/src/nsContentAreaDragDrop.cpp.
* Do not add any new fuctionality here other than what is needed for * a standalone product.
var contentAreaDNDObserver = { onDrop: function (aEvent) { if (aEvent.getPreventDefault())
return; var types = aEvent.dataTransfer.types; if (!types.contains("application/x-moz-file")
&& !types.contains("text/x-moz-url") && !types.contains("text/uri-list") && !types.contains("text/plain"))
{ aEvent.preventDefault(); return; } let [url, name] = browserDragAndDrop.getDragURLFromDataTransfer(aEvent.dataTransfer);
// valid urls don't contain spaces ' '; if we have a space it // isn't a valid url,
or if it's a javascript: or data: url, // bail out if (!url || !url.length || url.indexOf("
", 0) != -1 || /^\s*(javascript|data):/.test(url)) return; nsDragAndDrop.dragDropSecurityCheck(aEvent,
null, url); switch (document.documentElement.getAttribute('windowtype')) { case "navigator:browser": var postData
= { }; var uri = getShortcutOrURI(url, postData); loadURI(uri, null, postData.value, false);
break; case "navigator:view-source": viewSource(url); break; } // keep the event from being handled
by the dragDrop listeners // built-in to gecko if they happen to be above us. aEvent.preventDefault();
} function MultiplexHandler(event) { try { var node = event.target; var name = node.getAttribute('name');
if (name == 'detectorGroup') { SetForcedDetector(true); SelectDetector(event, false); } else if (name
== 'charsetGroup') { var charset = node.getAttribute('id'); charset = charset.substring('charset.'.length,
charset.length) SetForcedCharset(charset); } else if (name == 'charsetCustomize') {
//do nothing - please remove this else statement, once the charset prefs moves to the pref window
} else { SetForcedCharset(node.getAttribute('id')); } } catch(ex) { alert(ex); } function SelectDetector(event,
doReload) var uri = event.target.getAttribute("id"); var prefvalue = uri.substring('chardet.'.length,
uri.length); if ("off" == prefvalue) { // "off" is special value to turn off the detectors
prefvalue = ""; } try { var pref = Components.classes["@mozilla.org/preferences-service;1"] .getService(Components.interfaces.nsIPrefBranch);
var str = Components.classes["@mozilla.org/supports-string;1"] .createInstance(Components.interfaces.nsISupportsString);
str.data = prefvalue; pref.setComplexValue("intl.charset.detector", Components.interfaces.nsISupportsString, str);
if (doReload) window.content.location.reload(); } catch (ex) { dump("Failed to set the intl.charset.detector
preference.\n"); } function SetForcedDetector(doReload) BrowserSetForcedDetector(doReload); function
SetForcedCharset(charset) BrowserSetForcedCharacterSet(charset); function BrowserSetForcedCharacterSet(aCharset)
var docCharset = gBrowser.docShell.QueryInterface(Ci.nsIDocCharset); docCharset.charset = aCharset; // Save the
forced character-set PlacesUtils.history.setCharsetForURI(getWebNavigation().currentURI, aCharset); BrowserReloadWithFlags(nsIWebNavigation.LOAD_FLAGS_CHARSET_CHANGE);
function BrowserSetForcedDetector(doReload) gBrowser.documentCharsetInfo.forcedDetector
= true; if (doReload) BrowserReloadWithFlags(nsIWebNavigation.LOAD_FLAGS_CHARSET_CHANGE); function UpdateCurrentCharset() // extract
the charset from DOM var wnd = document.commandDispatcher.focusedWindow; if ((window == wnd) || (wnd == null)) wnd
= window.content; // Uncheck previous item if (gPrevCharset) { var pref_item = document.getElementById('charset.'
+ gPrevCharset); if (pref_item) pref_item.setAttribute('checked', 'false'); } var menuitem = document.getElementById('charset.'
+ wnd.document.characterSet); if (menuitem) { menuitem.setAttribute('checked', 'true');
} function UpdateCharsetDetector() var prefvalue; try { var pref = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch); prefvalue = pref.getComplexValue("intl.charset.detector",
Components.interfaces.nsIPrefLocalizedString).data; } catch (ex) { prefvalue = ""; } if (prefvalue
== "") prefvalue = "off"; dump("intl.charset.detector = "+ prefvalue + "\n"); prefvalue = 'chardet.'
+ prefvalue; var menuitem = document.getElementById(prefvalue); if (menuitem) { menuitem.setAttribute('checked',
'true'); } function UpdateMenus(event) // use setTimeout workaround to delay checkmark
the menu // when onmenucomplete is ready then use it instead of oncreate // see bug 78290
for the detail UpdateCurrentCharset(); setTimeout(UpdateCurrentCharset, 0); UpdateCharsetDetector(); setTimeout(UpdateCharsetDetector,
0); function CreateMenu(node) var observerService = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
observerService.notifyObservers(null, "charsetmenu-selected", node); function charsetLoadListener (event)
var charset = window.content.document.characterSet; if (charset.length > 0 && (charset != gLastBrowserCharset))
{ if (!gCharsetMenu) gCharsetMenu = Components.classes['@mozilla.org/rdf/datasource;1?name=charset-menu'].getService().QueryInterface(Components.interfaces.nsICurrentCharsetListener); gCharsetMenu.SetCurrentCharset(charset); gPrevCharset
= gLastBrowserCharset; gLastBrowserCharset = charset; } /* Begin Page Style Functions
*/ function getAllStyleSheets(frameset) { var styleSheetsArray = Array.slice(frameset.document.styleSheets);
for (let i = 0; i < frameset.frames.length; i++) { let frameSheets = getAllStyleSheets(frameset.frames[i]);
styleSheetsArray = styleSheetsArray.concat(frameSheets); return styleSheetsArray; function stylesheetFillPopup(menuPopup)
{ var noStyle = menuPopup.firstChild; var persistentOnly = noStyle.nextSibling; var
sep = persistentOnly.nextSibling; while (sep.nextSibling) menuPopup.removeChild(sep.nextSibling); var
styleSheets = getAllStyleSheets(window.content); var currentStyleSheets = {}; var styleDisabled
= getMarkupDocumentViewer().authorStyleDisabled; var haveAltSheets = false; var altStyleSelected
= false; for (let i = 0; i < styleSheets.length; ++i) { let currentStyleSheet = styleSheets[i];
if (!currentStyleSheet.title) continue; // Skip any stylesheets that don't match the
screen media type. let (media = currentStyleSheet.media.mediaText.toLowerCase()) { if (media && (media.indexOf("screen")
== -1) && (media.indexOf("all") == -1)) continue; } if (!currentStyleSheet.disabled) altStyleSelected
= true; haveAltSheets = true; let lastWithSameTitle = null; if (currentStyleSheet.title in currentStyleSheets)
lastWithSameTitle = currentStyleSheets[currentStyleSheet.title]; if (!lastWithSameTitle) { let menuItem =
document.createElement("menuitem"); menuItem.setAttribute("type", "radio"); menuItem.setAttribute("label", currentStyleSheet.title);
menuItem.setAttribute("data", currentStyleSheet.title); menuItem.setAttribute("checked", !currentStyleSheet.disabled
&& !styleDisabled); menuPopup.appendChild(menuItem); currentStyleSheets[currentStyleSheet.title]
= menuItem; } else if (currentStyleSheet.disabled) { lastWithSameTitle.removeAttribute("checked");
} noStyle.setAttribute("checked", styleDisabled); persistentOnly.setAttribute("checked", !altStyleSelected
&& !styleDisabled); persistentOnly.hidden = (window.content.document.preferredStyleSheetSet)
? haveAltSheets : false; sep.hidden = (noStyle.hidden && persistentOnly.hidden) || !haveAltSheets;
return true; function stylesheetInFrame(frame, title) { return Array.some(frame.document.styleSheets,
function (stylesheet) stylesheet.title == title); function stylesheetSwitchFrame(frame,
title) { var docStyleSheets = frame.document.styleSheets; for (let i = 0; i < docStyleSheets.length;
++i) { let docStyleSheet = docStyleSheets[i]; if (title == "_nostyle") docStyleSheet.disabled
= true; else if (docStyleSheet.title) docStyleSheet.disabled = (docStyleSheet.title != title); else if
(docStyleSheet.disabled) docStyleSheet.disabled = false; function stylesheetSwitchAll(frameset,
title) { if (!title || title == "_nostyle" || stylesheetInFrame(frameset, title)) stylesheetSwitchFrame(frameset,
title); for (let i = 0; i < frameset.frames.length; i++) stylesheetSwitchAll(frameset.frames[i],
title); function setStyleDisabled(disabled) { getMarkupDocumentViewer().authorStyleDisabled
= disabled; /* End of the Page Style functions */ var BrowserOffline = { /////////////////////////////////////////////////////////////////////////////
// BrowserOffline Public Methods init: function () if (!this._uiElement) this._uiElement
= document.getElementById("goOfflineMenuitem"); var os = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
os.addObserver(this, "network:offline-status-changed", false); var ioService = Components.classes["@mozilla.org/network/io-service;1"].
getService(Components.interfaces.nsIIOService2); // if ioService is managing the offline status,
then ioservice.offline // is already set correctly. We will continue to allow the ioService //
to manage its offline state until the user uses the "Work Offline" UI. if (!ioService.manageOfflineStatus)
{ // set the initial state var isOffline = false; try { isOffline = gPrefService.getBoolPref("browser.offline");
} catch (e) { } ioService.offline = isOffline; } this._updateOfflineUI(ioService.offline);
}, uninit: function () try { var os = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService); os.removeObserver(this, "network:offline-status-changed");
} catch (ex) { } }, toggleOfflineStatus: function () var ioService = Components.classes["@mozilla.org/network/io-service;1"].
getService(Components.interfaces.nsIIOService2); // Stop automatic management of the offline
status try { ioService.manageOfflineStatus = false; } catch (ex) { } if (!ioService.offline
&& !this._canGoOffline()) { this._updateOfflineUI(false); return; } ioService.offline = !ioService.offline;
// Save the current state for later use as the initial state // (if there is no netLinkService)
gPrefService.setBoolPref("browser.offline", ioService.offline); }, /////////////////////////////////////////////////////////////////////////////
// nsIObserver observe: function (aSubject, aTopic, aState) if (aTopic != "network:offline-status-changed")
return; this._updateOfflineUI(aState == "offline"); }, /////////////////////////////////////////////////////////////////////////////
// BrowserOffline Implementation Methods _canGoOffline: function () var os = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
if (os) { try { var cancelGoOffline = Components.classes["@mozilla.org/supports-PRBool;1"].createInstance(Components.interfaces.nsISupportsPRBool); os.notifyObservers(cancelGoOffline, "offline-requested",
null); // Something aborted the quit process. if (cancelGoOffline.data) return false; }
catch (ex) { } } return true; }, _uiElement: null, _updateOfflineUI: function (aOffline)
var offlineLocked = gPrefService.prefIsLocked("network.online"); if (offlineLocked) this._uiElement.setAttribute("disabled",
"true"); this._uiElement.setAttribute("checked", aOffline); var OfflineApps = { /////////////////////////////////////////////////////////////////////////////
// OfflineApps Public Methods init: function () 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 () 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"); }, handleEvent: function(event) { if (event.type
== "MozApplicationManifest") { this.offlineAppRequested(event.originalTarget.defaultView); } }, /////////////////////////////////////////////////////////////////////////////
// OfflineApps Implementation Methods // ***: _getBrowserWindowForContentWindow and
_getBrowserForContentWindow // were taken from browser/components/feeds/src/WebContentConverter.
_getBrowserWindowForContentWindow: function(aContentWindow) { return aContentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation) .QueryInterface(Ci.nsIDocShellTreeItem) .rootTreeItem .QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindow) .wrappedJSObject; }, _getBrowserForContentWindow: function(aBrowserWindow,
aContentWindow) { // This depends on pseudo APIs of browser.js and tabbrowser.xml aContentWindow
= aContentWindow.top; var browsers = aBrowserWindow.getBrowser().browsers; for (var i = 0; i < browsers.length; ++i)
{ if (browsers[i].contentWindow == aContentWindow) return browsers[i]; } }, _getManifestURI:
function(aWindow) { if (!aWindow.document.documentElement) return null; var attr = aWindow.document.documentElement.getAttribute("manifest");
if (!attr) return null; try { var contentURI = makeURI(aWindow.location.href, null, null);
return makeURI(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 = gBrowser.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 buttons = [{ label:
gNavigatorBundle.getString("offlineApps.manageUsage"), accessKey: gNavigatorBundle.getString("offlineApps.manageUsageAccessKey"),
callback: OfflineApps.manage }]; var warnQuota = gPrefService.getIntPref("offline-apps.quota.warn");
const priority = notificationBox.PRIORITY_WARNING_MEDIUM; var message = gNavigatorBundle.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); }, // ***: duplicated in preferences/advanced.js
_getOfflineAppUsage: function (host, groups) var cacheService = Components.classes["@mozilla.org/network/application-cache-service;1"].
getService(Components.interfaces.nsIApplicationCacheService); if (!groups) { groups = cacheService.getGroups({});
} var ios = Components.classes["@mozilla.org/network/io-service;1"]. getService(Components.interfaces.nsIIOService);
var usage = 0; for (var i = 0; i < groups.length; i++) { var uri = ios.newURI(groups[i], null,
null); if (uri.asciiHost == host) { var cache = cacheService.getActiveCache(groups[i]);
usage += cache.usage; } } var storageManager = Components.classes["@mozilla.org/dom/storagemanager;1"].
getService(Components.interfaces.nsIDOMStorageManager); usage += storageManager.getUsage(host); return
usage; }, _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 = this._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; } var browserWindow = this._getBrowserWindowForContentWindow(aContentWindow);
var browser = this._getBrowserForContentWindow(browserWindow, aContentWindow); var currentURI = aContentWindow.document.documentURIObject;
var pm = Cc["@mozilla.org/permissionmanager;1"]. getService(Ci.nsIPermissionManager); // don't
bother showing UI if the user has already made a decision if (pm.testExactPermission(currentURI,
"offline-app") != Ci.nsIPermissionManager.UNKNOWN_ACTION) return; try { if (gPrefService.getBoolPref("offline-apps.allow_by_default"))
{ // all pages can use offline capabilities, no need to ask the user return; } } catch(e)
{ // this pref isn't set by default, ignore failures } var host = currentURI.asciiHost;
var notificationBox = gBrowser.getNotificationBox(browser); var notificationID = "offline-app-requested-"
+ host; var notification = notificationBox.getNotificationWithValue(notificationID); if (notification) { notification.documents.push(aContentWindow.document);
} else { var buttons = [{ label: gNavigatorBundle.getString("offlineApps.allow"), accessKey: gNavigatorBundle.getString("offlineApps.allowAccessKey"),
callback: function() { for (var i = 0; i < notification.documents.length; i++) { OfflineApps.allowSite(notification.documents[i]);
} } },{ label: gNavigatorBundle.getString("offlineApps.never"), accessKey: gNavigatorBundle.getString("offlineApps.neverAccessKey"),
callback: function() { for (var i = 0; i < notification.documents.length; i++) { OfflineApps.disallowSite(notification.documents[i]);
} } },{ label: gNavigatorBundle.getString("offlineApps.notNow"), accessKey: gNavigatorBundle.getString("offlineApps.notNowAccessKey"),
callback: function() { /* noop */ } }]; const priority = notificationBox.PRIORITY_INFO_LOW;
var message = gNavigatorBundle.getFormattedString("offlineApps.available", [ host ]); notification = notificationBox.appendNotification(message,
notificationID, "chrome://browser/skin/Info.png", priority, buttons); notification.documents
= [ aContentWindow.document ]; } }, allowSite: function(aDocument) { var pm = Cc["@mozilla.org/permissionmanager;1"].
getService(Ci.nsIPermissionManager); pm.add(aDocument.documentURIObject, "offline-app", Ci.nsIPermissionManager.ALLOW_ACTION);
// When a site is enabled while loading, manifest resources will // start fetching
immediately. This one time we need to do it // ourselves. this._startFetching(aDocument);
}, disallowSite: function(aDocument) { var pm = Cc["@mozilla.org/permissionmanager;1"].
getService(Ci.nsIPermissionManager); pm.add(aDocument.documentURIObject, "offline-app", Ci.nsIPermissionManager.DENY_ACTION);
}, manage: function() { openAdvancedPreferences("networkTab"); }, _startFetching: function(aDocument) {
if (!aDocument.documentElement) return; var manifest = aDocument.documentElement.getAttribute("manifest");
if (!manifest) return; var manifestURI = makeURI(manifest, aDocument.characterSet,
aDocument.documentURIObject); var updateService = Cc["@mozilla.org/offlinecacheupdate-service;1"].
getService(Ci.nsIOfflineCacheUpdateService); updateService.scheduleUpdate(manifestURI,
aDocument.documentURIObject); }, ///////////////////////////////////////////////////////////////////////////// // nsIObserver observe: function (aSubject,
aTopic, aState) if (aTopic == "dom-storage-warn-quota-exceeded") { if (aSubject) { var uri = makeURI(aSubject.location.href);
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); } } } function WindowIsClosing()
var reallyClose = closeWindow(false, warnAboutClosingWindow); if (!reallyClose) return false; var numBrowsers
= gBrowser.browsers.length; for (let i = 0; reallyClose && i < numBrowsers; ++i)
{ let ds = gBrowser.browsers[i].docShell; if (ds.contentViewer && !ds.contentViewer.permitUnload())
reallyClose = false; return reallyClose; * Checks if this is the last full *browser*
window around. If it is, this will * be communicated like quitting. Otherwise, we warn about closing
multiple tabs. * @returns true if closing can proceed, false if it got cancelled. function
warnAboutClosingWindow() { // Popups aren't considered full browser windows. if (!toolbar.visible)
return gBrowser.warnAboutClosingTabs(true); // Figure out if there's at least one other
browser window around. let foundOtherBrowserWindow = false; let wm = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
let e = wm.getEnumerator("navigator:browser"); while (e.hasMoreElements() && !foundOtherBrowserWindow)
{ let win = e.getNext(); if (win != window && win.toolbar.visible) foundOtherBrowserWindow
= true; if (foundOtherBrowserWindow) return gBrowser.warnAboutClosingTabs(true); let os
= Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService); let closingCanceled = Cc["@mozilla.org/supports-PRBool;1"].
createInstance(Ci.nsISupportsPRBool); os.notifyObservers(closingCanceled, "browser-lastwindow-close-requested", null);
if (closingCanceled.data) return false; os.notifyObservers(null, "browser-lastwindow-close-granted", null);
//@line 5782 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js" return true; //@line 5784 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js"
var MailIntegration = { sendLinkForWindow: function (aWindow) { this.sendMessage(aWindow.location.href,
aWindow.document.title); }, sendMessage: function (aBody, aSubject) { // generate a mailto url
based on the url and the url's title var mailtoUrl = "mailto:"; if (aBody) { mailtoUrl += "?body="
+ encodeURIComponent(aBody); mailtoUrl += "&subject=" + encodeURIComponent(aSubject);
} var uri = makeURI(mailtoUrl); // now pass this uri to the operating system this._launchExternalUrl(uri);
}, // a generic method which can be used to pass arbitrary urls to the operating //
system. // aURL --> a nsIURI which represents the url to launch _launchExternalUrl: function
(aURL) { var extProtocolSvc = Components.classes["@mozilla.org/uriloader/external-protocol-service;1"] .getService(Components.interfaces.nsIExternalProtocolService);
if (extProtocolSvc) extProtocolSvc.loadUrl(aURL); function BrowserOpenAddonsMgr(aPane) const
EMTYPE = "Extension:Manager"; var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] .getService(Components.interfaces.nsIWindowMediator);
var theEM = wm.getMostRecentWindow(EMTYPE); if (theEM) { theEM.focus(); if (aPane) theEM.showView(aPane);
return; const EMURL = "chrome://mozapps/content/extensions/extensions.xul"; const EMFEATURES = "chrome,menubar,extra-chrome,toolbar,dialog=no,resizable";
if (aPane) window.openDialog(EMURL, "", EMFEATURES, aPane); else window.openDialog(EMURL, "",
EMFEATURES); function escapeNameValuePair(aName, aValue, aIsFormUrlEncoded) if (aIsFormUrlEncoded)
return escape(aName + "=" + aValue); else return escape(aName) + "=" + escape(aValue);
function AddKeywordForSearchField() var node = document.popupNode; var charset = node.ownerDocument.characterSet;
var docURI = makeURI(node.ownerDocument.URL, charset); var formURI = makeURI(node.form.getAttribute("action"),
charset, docURI); var spec = formURI.spec; var isURLEncoded = (node.form.method.toUpperCase()
== "POST" && (node.form.enctype == "application/x-www-form-urlencoded" || node.form.enctype == "")); var title
= gNavigatorBundle.getFormattedString("addKeywordTitleAutoFill", [node.ownerDocument.title]); var description
= PlacesUIUtils.getDescriptionFromDocument(node.ownerDocument); var el, type; var formData = []; for (var
i=0; i < node.form.elements.length; i++) { el = node.form.elements[i]; if (!el.type)
// happens with fieldsets continue; if (el == node) { formData.push((isURLEncoded)
? escapeNameValuePair(el.name, "%s", true) : // Don't escape "%s", just append escapeNameValuePair(el.name,
"", false) + "%s"); continue; } type = el.type.toLowerCase(); if ((type == "text" || type == "hidden" ||
type == "textarea") || ((type == "checkbox" || type == "radio") && el.checked)) { formData.push(escapeNameValuePair(el.name,
el.value, isURLEncoded)); } else if (el instanceof HTMLSelectElement && el.selectedIndex >=
0) { for (var j=0; j < el.options.length; j++) { if (el.options[j].selected) formData.push(escapeNameValuePair(el.name,
el.options[j].value, isURLEncoded)); } } var postData; if (isURLEncoded) postData
= formData.join("&"); else spec += "?" + formData.join("&"); PlacesUIUtils.showMinimalAddBookmarkUI(makeURI(spec),
title, description, null, null, null, "", postData, charset); function SwitchDocumentDirection(aWindow)
{ aWindow.document.dir = (aWindow.document.dir == "ltr" ? "rtl" : "ltr"); for (var run
= 0; run < aWindow.frames.length; run++) SwitchDocumentDirection(aWindow.frames[run]); function getPluginInfo(pluginElement) var
tagMimetype; var pluginsPage; if (pluginElement instanceof HTMLAppletElement) { tagMimetype
= "application/x-java-vm"; } else { if (pluginElement instanceof HTMLObjectElement) { pluginsPage
= pluginElement.getAttribute("codebase"); } else { pluginsPage = pluginElement.getAttribute("pluginspage");
} // only attempt if a pluginsPage is defined. if (pluginsPage) { var doc = pluginElement.ownerDocument;
var docShell = findChildShell(doc, gBrowser.selectedBrowser.docShell, null); try { pluginsPage = makeURI(pluginsPage,
doc.characterSet, docShell.currentURI).spec; } catch (ex) { pluginsPage = ""; } } tagMimetype
= pluginElement.QueryInterface(Components.interfaces.nsIObjectLoadingContent) .actualType; if (tagMimetype == "") { tagMimetype
= pluginElement.type; } return {mimetype: tagMimetype, pluginsPage: pluginsPage}; var
gMissingPluginInstaller = { get CrashSubmit() { delete this.CrashSubmit; Cu.import("resource://gre/modules/CrashSubmit.jsm",
this); return this.CrashSubmit; }, get crashReportHelpURL() { delete this.crashReportHelpURL; let url
= formatURL("app.support.baseURL", true); url += "plugin-crashed"; this.crashReportHelpURL
= url; return this.crashReportHelpURL; }, // Map the plugin's name to a filtered version
more suitable for user UI. makeNicePluginName : function (aName, aFilename) { if (aName
== "Shockwave Flash") return "Adobe Flash"; // Clean up the plugin name by stripping
off any trailing version numbers // or "plugin". EG, "Foo Bar Plugin 1.23_02" --> "Foo Bar"
let newName = aName.replace(/\bplug-?in\b/i, "").replace(/[\s\d\.\-\_\(\)]+$/, ""); return
newName; }, addLinkClickCallback: function (linkNode, callbackName /*callbackArgs...*/)
{ // *** just doing (callback)(arg) was giving a same-origin error. bug? let self = this;
let callbackArgs = Array.prototype.slice.call(arguments).slice(2); linkNode.addEventListener("click", function(evt)
{ if (!evt.isTrusted) return; evt.preventDefault(); if (callbackArgs.length == 0) callbackArgs
= [ evt ]; (self[callbackName]).apply(self, callbackArgs); }, true); linkNode.addEventListener("keydown",
function(evt) { if (!evt.isTrusted) return; if (evt.keyCode == evt.DOM_VK_RETURN) { evt.preventDefault();
if (callbackArgs.length == 0) callbackArgs = [ evt ]; evt.preventDefault(); (self[callbackName]).apply(self,
callbackArgs); } }, true); }, // Callback for user clicking on a missing (unsupported)
plugin. installSinglePlugin: function (aEvent) { var missingPluginsArray = {}; var pluginInfo
= getPluginInfo(aEvent.target); missingPluginsArray[pluginInfo.mimetype] = pluginInfo; openDialog("chrome://mozapps/content/plugins/pluginInstallerWizard.xul",
"PFSWindow", "chrome,centerscreen,resizable=yes", {plugins: missingPluginsArray, browser: gBrowser.selectedBrowser});
}, // Callback for user clicking on a disabled plugin managePlugins: function (aEvent) {
BrowserOpenAddonsMgr("plugins"); }, // Callback for user clicking "submit a report" link submitReport
: function(pluginDumpID, browserDumpID) { // The crash reporter wants a DOM element
it can append an IFRAME to, // which it uses to submit a form. Let's just give it gBrowser.
this.CrashSubmit.submit(pluginDumpID, gBrowser, null, null); if (browserDumpID) this.CrashSubmit.submit(browserDumpID,
gBrowser, null, null); }, // Callback for user clicking a "reload page" link reloadPage:
function (browser) { browser.reload(); }, // Callback for user clicking the help icon
openHelpPage: function () { openHelpLink("plugin-crashed", false); }, // event listener for missing/blocklisted/outdated
plugins. newMissingPlugin: function (aEvent) { // Since we are expecting also untrusted
events, make sure // that the target is a plugin if (!(aEvent.target instanceof Ci.nsIObjectLoadingContent))
return; // For broken non-object plugin tags, register a click handler so // that the user
can click the plugin replacement to get the new // plugin. Object tags can, and often
do, deal with that themselves, // so don't stomp on the page developers toes. if (aEvent.type
!= "PluginBlocklisted" && aEvent.type != "PluginOutdated" && !(aEvent.target instanceof
HTMLObjectElement)) { gMissingPluginInstaller.addLinkClickCallback(aEvent.target, "installSinglePlugin"); } let hideBarPrefName
= aEvent.type == "PluginOutdated" ? "plugins.hide_infobar_for_outdated_plugin" : "plugins.hide_infobar_for_missing_plugin";
try { if (gPrefService.getBoolPref(hideBarPrefName)) return; } catch (ex) {} // if the pref is
missing, treat it as false, which shows the infobar var browser = gBrowser.getBrowserForDocument(aEvent.target.ownerDocument
.defaultView.top.document); if (!browser.missingPlugins) browser.missingPlugins = {}; var pluginInfo
= getPluginInfo(aEvent.target); browser.missingPlugins[pluginInfo.mimetype] = pluginInfo; var notificationBox = gBrowser.getNotificationBox(browser);
// Should only display one of these warnings per page. // In order of priority, they are:
outdated > missing > blocklisted // If there is already an outdated plugin notification
then do nothing if (notificationBox.getNotificationWithValue("outdated-plugins")) return; var blockedNotification = notificationBox.getNotificationWithValue("blocked-plugins");
var missingNotification = notificationBox.getNotificationWithValue("missing-plugins"); var priority = notificationBox.PRIORITY_WARNING_MEDIUM;
function showBlocklistInfo() { var formatter = Cc["@mozilla.org/toolkit/URLFormatterService;1"].
getService(Ci.nsIURLFormatter); var url = formatter.formatURLPref("extensions.blocklist.detailsURL");
gBrowser.loadOneTab(url, {inBackground: false}); return true; } function showOutdatedPluginsInfo()
{ gPrefService.setBoolPref("plugins.update.notifyUser", false); var formatter = Cc["@mozilla.org/toolkit/URLFormatterService;1"].
getService(Ci.nsIURLFormatter); var url = formatter.formatURLPref("plugins.update.url");
gBrowser.loadOneTab(url, {inBackground: false}); return true; } function showPluginsMissing()
{ // get the urls of missing plugins var missingPluginsArray = gBrowser.selectedBrowser.missingPlugins;
if (missingPluginsArray) { window.openDialog("chrome://mozapps/content/plugins/pluginInstallerWizard.xul", "PFSWindow", "chrome,centerscreen,resizable=yes",
{plugins: missingPluginsArray, browser: gBrowser.selectedBrowser}); } } if (aEvent.type == "PluginBlocklisted")
{ if (blockedNotification || missingNotification) return; let iconURL = "chrome://mozapps/skin/plugins/pluginBlocked-16.png";
let messageString = gNavigatorBundle.getString("blockedpluginsMessage.title"); let buttons = [{ label: gNavigatorBundle.getString("blockedpluginsMessage.infoButton.label"),
accessKey: gNavigatorBundle.getString("blockedpluginsMessage.infoButton.accesskey"), popup: null, callback: showBlocklistInfo
}, { label: gNavigatorBundle.getString("blockedpluginsMessage.searchButton.label"), accessKey: gNavigatorBundle.getString("blockedpluginsMessage.searchButton.accesskey"),
popup: null, callback: showOutdatedPluginsInfo }]; notificationBox.appendNotification(messageString,
"blocked-plugins", iconURL, priority, buttons); } else if (aEvent.type == "PluginOutdated")
{ // Cancel any notification about blocklisting/missing plugins if (blockedNotification) blockedNotification.close();
if (missingNotification) missingNotification.close(); let iconURL = "chrome://mozapps/skin/plugins/pluginOutdated-16.png";
let messageString = gNavigatorBundle.getString("outdatedpluginsMessage.title"); let buttons = [{ label: gNavigatorBundle.getString("outdatedpluginsMessage.updateButton.label"),
accessKey: gNavigatorBundle.getString("outdatedpluginsMessage.updateButton.accesskey"), popup: null, callback: showOutdatedPluginsInfo
}]; notificationBox.appendNotification(messageString, "outdated-plugins", iconURL, priority, buttons);
} else if (aEvent.type == "PluginNotFound") { if (missingNotification) return; // Cancel
any notification about blocklisting plugins if (blockedNotification) blockedNotification.close();
let iconURL = "chrome://mozapps/skin/plugins/pluginGeneric-16.png"; let messageString = gNavigatorBundle.getString("missingpluginsMessage.title");
let buttons = [{ label: gNavigatorBundle.getString("missingpluginsMessage.button.label"), accessKey: gNavigatorBundle.getString("missingpluginsMessage.button.accesskey"),
popup: null, callback: showPluginsMissing }]; notificationBox.appendNotification(messageString,
"missing-plugins", iconURL, priority, buttons); } }, newDisabledPlugin: function (aEvent)
{ // Since we are expecting also untrusted events, make sure // that the target is a
plugin if (!(aEvent.target instanceof Components.interfaces.nsIObjectLoadingContent)) return; gMissingPluginInstaller.addLinkClickCallback(aEvent.target,
"managePlugins"); }, // Crashed-plugin observer. Notified once per plugin crash, before events
// are dispatched to individual plugin instances. observe: function(subject, topic, data) {
if (topic != "plugin-crashed") return; let propertyBag = subject; if (!(propertyBag instanceof
Ci.nsIPropertyBag2) || !(propertyBag instanceof Ci.nsIWritablePropertyBag2)) return; //@line
6205 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js" let pluginDumpID = propertyBag.getPropertyAsAString("pluginDumpID");
let browserDumpID= propertyBag.getPropertyAsAString("browserDumpID"); let shouldSubmit = gCrashReporter.submitReports;
let doPrompt = true; // *** followup to get via gCrashReporter // Submit automatically
when appropriate. if (pluginDumpID && shouldSubmit && !doPrompt) { this.submitReport(pluginDumpID,
browserDumpID); // Submission is async, so we can't easily show failure UI. propertyBag.setPropertyAsBool("submittedCrashReport",
true); } //@line 6217 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js" }, // Crashed-plugin event listener. Called
for every instance of a // plugin in content. pluginInstanceCrashed: function (aEvent)
{ let self = gMissingPluginInstaller; // Evil content could fire a fake event at us,
ignore them. if (!aEvent.isTrusted) return; // Ensure the plugin and event are of the
right type. let plugin = aEvent.target; if (!(aEvent instanceof Ci.nsIDOMDataContainerEvent)
|| !(plugin instanceof Ci.nsIObjectLoadingContent)) return; let submittedReport = aEvent.getData("submittedCrashReport");
let doPrompt = true; // *** followup for .getData("doPrompt"); let submitReports = true; // *** followup
for .getData("submitReports"); let pluginName = aEvent.getData("pluginName"); let pluginFilename
= aEvent.getData("pluginFilename"); let pluginDumpID = aEvent.getData("pluginDumpID"); let browserDumpID
= aEvent.getData("browserDumpID"); // Remap the plugin name to a more user-presentable
form. pluginName = self.makeNicePluginName(pluginName, pluginFilename); // Force a style flush, so
that we ensure our binding is attached. plugin.clientTop; let messageString; try { messageString =
gNavigatorBundle.getFormattedString("crashedpluginsMessage.title", [pluginName]); } catch (e) { messageString
= "The " + pluginName + " plugin has crashed."; } // // Configure the crashed-plugin placeholder.
// let doc = plugin.ownerDocument; let overlay = doc.getAnonymousElementByAttribute(plugin,
"class", "mainBox"); // The binding has role="link" here, since missing/disabled/blocked // plugin
UI has a onclick handler on the whole thing. This isn't needed // for the plugin-crashed
UI, because we use actual HTML links in the text. overlay.removeAttribute("role"); let
statusDiv = doc.getAnonymousElementByAttribute(plugin, "class", "submitStatus"); //@line 6268 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js"
let status; // Determine which message to show regarding crash reports. if (submittedReport)
{ // submitReports && !doPrompt, handled in observer status = "submitted"; } else if
(!submitReports && !doPrompt) { status = "noSubmit"; } else { // doPrompt status =
"please"; // *** can we make the link target actually be blank? let pleaseLink = doc.getAnonymousElementByAttribute(
plugin, "class", "pleaseSubmitLink"); self.addLinkClickCallback(pleaseLink, "submitReport", pluginDumpID, browserDumpID);
} // If we don't have a minidumpID, we can't (or didn't) submit anything. // This can happen
if the plugin is killed from the task manager. if (!pluginDumpID) { status = "noReport";
} statusDiv.setAttribute("status", status); let bottomLinks = doc.getAnonymousElementByAttribute(plugin,
"class", "msg msgBottomLinks"); bottomLinks.style.display = "block"; let helpIcon = doc.getAnonymousElementByAttribute(plugin,
"class", "helpIcon"); self.addLinkClickCallback(helpIcon, "openHelpPage"); // If we're showing the link
to manually trigger report submission, we'll // want to be able to update all the instances
of the UI for this crash to // show an updated message when a report is submitted. if (doPrompt)
{ let observer = { QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakReference]), observe :
function(subject, topic, data) { let propertyBag = subject; if (!(propertyBag instanceof Ci.nsIPropertyBag2))
return; // Ignore notifications for other crashes. if (propertyBag.get("minidumpID")
!= pluginDumpID) return; statusDiv.setAttribute("status", data); }, handleEvent : function(event) {
// Not expected to be called, just here for the closure. } } let obs = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService); // Use a weak reference, so we don't have to remove
it... obs.addObserver(observer, "crash-report-status", true); // ...alas, now we need something to
hold a strong reference to prevent // it from being GC. But I don't want to manually manage
the reference's // lifetime (which should be no greater than the page). // Clever solution?
Use a closue with an event listener on the document. // When the doc goes away, so do
the listener references and the closure. doc.addEventListener("mozCleverClosureHack", observer, false); } //@line 6333 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js"
let crashText = doc.getAnonymousElementByAttribute(plugin, "class", "msg msgCrashed"); crashText.textContent
= messageString; let browser = gBrowser.getBrowserForDocument(doc.defaultView.top.document); let link = doc.getAnonymousElementByAttribute(plugin,
"class", "reloadLink"); self.addLinkClickCallback(link, "reloadPage", browser); let notificationBox
= gBrowser.getNotificationBox(browser); // Is the 's size too small to hold
what we want to show? let pluginRect = plugin.getBoundingClientRect(); // *** bug 446693. The text-shadow on the
submitted-report text at // the bottom causes scrollHeight to be larger than it should be.
let isObjectTooSmall = (overlay.scrollWidth > pluginRect.width) || (overlay.scrollHeight
- 5 > pluginRect.height); if (isObjectTooSmall) { // Hide the overlay's contents. Use visibility
style, so that it // doesn't collapse down to 0x0. overlay.style.visibility = "hidden";
// If another plugin on the page was large enough to show our UI, we // don't want to
show a notification bar. if (!doc.mozNoPluginCrashedNotification) showNotificationBar(pluginDumpID, browserDumpID);
} else { // If a previous plugin on the page was too small and resulted in // adding a
notification bar, then remove it because this plugin // instance it big enough to serve
as in-content notification. hideNotificationBar(); doc.mozNoPluginCrashedNotification = true;
} function hideNotificationBar() { let notification = notificationBox.getNotificationWithValue("plugin-crashed");
if (notification) notificationBox.removeNotification(notification, true); } function showNotificationBar(pluginDumpID,
browserDumpID) { // If there's already an existing notification bar, don't do anything.
let notification = notificationBox.getNotificationWithValue("plugin-crashed"); if (notification) return; // Configure the
notification bar let priority = notificationBox.PRIORITY_WARNING_MEDIUM; let iconURL = "chrome://mozapps/skin/plugins/pluginGeneric-16.png";
let reloadLabel, reloadKey, submitLabel, submitKey; try { reloadLabel = gNavigatorBundle.getString("crashedpluginsMessage.reloadButton.label");
reloadKey = gNavigatorBundle.getString("crashedpluginsMessage.reloadButton.accesskey"); submitLabel = gNavigatorBundle.getString("crashedpluginsMessage.submitButton.label");
submitKey = gNavigatorBundle.getString("crashedpluginsMessage.submitButton.accesskey"); } catch (e) { reloadLabel = "Reload page";
reloadKey = "R"; submitLabel = "Submit a crash report"; submitKey = "S"; } let buttons =
[{ label: reloadLabel, accessKey: reloadKey, popup: null, callback: function() { browser.reload();
}, }]; //@line 6402 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js" let submitButton = { label: submitLabel, accessKey:
submitKey, popup: null, callback: function() { gMissingPluginInstaller.submitReport(pluginDumpID,
browserDumpID); }, }; if (pluginDumpID) buttons.push(submitButton); //@line 6411 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js"
let notification = notificationBox.appendNotification(messageString, "plugin-crashed", iconURL, priority, buttons);
// Add the "learn more" link. let XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
let link = notification.ownerDocument.createElementNS(XULNS, "label"); link.className = "text-link"; let
learnMore; try { learnMore = gNavigatorBundle.getString("crashedpluginsMessage.learnMore"); } catch (e) { learnMore = "Learn More\u2026";
} link.setAttribute("value", learnMore); link.href = gMissingPluginInstaller.crashReportHelpURL;
let description = notification.ownerDocument.getAnonymousElementByAttribute(notification, "anonid", "messageText"); description.appendChild(link);
// Remove the notfication when the page is reloaded. doc.defaultView.top.addEventListener("unload",
function() { notificationBox.removeNotification(notification); }, false); } }, refreshBrowser: function
(aEvent) { // browser elements are anonymous so we can't just use target. var browser
= aEvent.originalTarget; var notificationBox = gBrowser.getNotificationBox(browser); var
notification = notificationBox.getNotificationWithValue("missing-plugins"); // clear the plugin list, now that at least
one plugin has been installed browser.missingPlugins = null; if (notification) { // reset UI notificationBox.removeNotification(notification);
} // reload the browser to make the new plugin show. browser.reload(); function convertFromUnicode(charset,
str) try { var unicodeConverter = Components .classes["@mozilla.org/intl/scriptableunicodeconverter"]
.createInstance(Components.interfaces.nsIScriptableUnicodeConverter); unicodeConverter.charset = charset; str =
unicodeConverter.ConvertFromUnicode(str); return str + unicodeConverter.Finish(); }
catch(ex) { return null; * The Feed Handler object manages discovery of RSS/ATOM feeds
in web pages * and shows UI when they are discovered. var FeedHandler = { /** * The
click handler for the Feed icon in the location bar. Opens the * subscription page if user
is not given a choice of feeds. * (Otherwise the list of available feeds will be presented
to the * user in a popup menu.) */ onFeedButtonClick: function(event) { event.stopPropagation();
if (event.target.hasAttribute("feed") && event.eventPhase == Event.AT_TARGET && (event.button
== 0 || event.button == 1)) { this.subscribeToFeed(null, event); } }, /** * Called when the user clicks
on the Feed icon in the location bar. * Builds a menu of unique feeds associated with the
page, and if there * is only one, shows the feed inline in the browser window. * @param
menuPopup * The feed list menupopup to be populated. * @returns true if the menu should
be shown, false if there was only * one feed and the feed should be shown inline in the
browser * window (do not show the menupopup). */ buildFeedList: function(menuPopup) {
var feeds = gBrowser.selectedBrowser.feeds; if (feeds == null) { // *** hack -- menu opening
depends on setting of an "open" // attribute, and the menu refuses to open if that attribute
is // set (because it thinks it's already open). onpopupshowing gets // called after
the attribute is unset, and it doesn't get unset // if we return false. so we unset it
here; otherwise, the menu // refuses to work past this point. menuPopup.parentNode.removeAttribute("open");
return false; } while (menuPopup.firstChild) menuPopup.removeChild(menuPopup.firstChild);
if (feeds.length == 1) { var feedButton = document.getElementById("feed-button"); if
(feedButton) feedButton.setAttribute("feed", feeds[0].href); return false; } // Build the
menu showing the available feed choices for viewing. for (var i = 0; i < feeds.length;
++i) { var feedInfo = feeds[i]; var menuItem = document.createElement("menuitem"); var
baseTitle = feedInfo.title || feedInfo.href; var labelStr = gNavigatorBundle.getFormattedString("feedShowFeedNew",
[baseTitle]); menuItem.setAttribute("class", "feed-menuitem"); menuItem.setAttribute("label",
labelStr); menuItem.setAttribute("feed", feedInfo.href); menuItem.setAttribute("tooltiptext", feedInfo.href);
menuItem.setAttribute("crop", "center"); menuPopup.appendChild(menuItem); } return true; }, /** * Subscribe to a given
feed. Called when * 1. Page has a single feed and user clicks feed icon in location bar
* 2. Page has a single feed and user selects Subscribe menu item * 3. Page has multiple
feeds and user selects from feed icon popup * 4. Page has multiple feeds and user selects
from Subscribe submenu * @param href * The feed to subscribe to. May be null, in which
case the * event target's feed attribute is examined. * @param event * The event this
method is handling. Used to decide where * to open the preview UI. (Optional, unless
href is null) */ subscribeToFeed: function(href, event) { // Just load the feed in the content
area to either subscribe or show the // preview UI if (!href) href = event.target.getAttribute("feed");
urlSecurityCheck(href, gBrowser.contentPrincipal, Ci.nsIScriptSecurityManager.DISALLOW_INHERIT_PRINCIPAL);
var feedURI = makeURI(href, document.characterSet); // Use the feed scheme so X-Moz-Is-Feed will
be set // The value doesn't matter if (/^https?/.test(feedURI.scheme)) href = "feed:" + href; this.loadFeed(href,
event); }, loadFeed: function(href, event) { var feeds = gBrowser.selectedBrowser.feeds;
try { openUILink(href, event, false, true, false, null); } finally { // We might default
to a livebookmarks modal dialog, // so reset that if the user happens to click it again
gBrowser.selectedBrowser.feeds = feeds; } }, /** * Update the browser UI to show whether
or not feeds are available when * a page is loaded or the user switches tabs to a page
that has feeds. */ updateFeeds: function() { var feedButton = document.getElementById("feed-button");
if (!this._feedMenuitem) this._feedMenuitem = document.getElementById("subscribeToPageMenuitem");
if (!this._feedMenupopup) this._feedMenupopup = document.getElementById("subscribeToPageMenupopup");
var feeds = gBrowser.mCurrentBrowser.feeds; if (!feeds || feeds.length == 0) { if (feedButton)
{ feedButton.collapsed = true; feedButton.removeAttribute("feed"); } this._feedMenuitem.setAttribute("disabled",
"true"); this._feedMenupopup.setAttribute("hidden", "true"); this._feedMenuitem.removeAttribute("hidden");
} else { if (feedButton) feedButton.collapsed = false; if (feeds.length > 1) { this._feedMenuitem.setAttribute("hidden",
"true"); this._feedMenupopup.removeAttribute("hidden"); if (feedButton) feedButton.removeAttribute("feed");
} else { if (feedButton) feedButton.setAttribute("feed", feeds[0].href); this._feedMenuitem.setAttribute("feed",
feeds[0].href); this._feedMenuitem.removeAttribute("disabled"); this._feedMenuitem.removeAttribute("hidden");
this._feedMenupopup.setAttribute("hidden", "true"); } } }, addFeed: function(link, targetDoc)
{ // find which tab this is for, and set the attribute on the browser var browserForLink
= gBrowser.getBrowserForDocument(targetDoc); if (!browserForLink) { // ignore feeds loaded
in subframes (see bug 305472) return; } if (!browserForLink.feeds) browserForLink.feeds
= []; browserForLink.feeds.push({ href: link.href, title: link.title }); if (browserForLink
== gBrowser.mCurrentBrowser) { var feedButton = document.getElementById("feed-button");
if (feedButton) feedButton.collapsed = false; } //@line 40 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser-places.js"
var StarUI = { _itemId: -1, uri: null, _batching: false, // nsISupports QueryInterface: function
SU_QueryInterface(aIID) { if (aIID.equals(Ci.nsIDOMEventListener) || aIID.equals(Ci.nsISupports)) return this;
throw Cr.NS_NOINTERFACE; }, _element: function(aID) { return document.getElementById(aID); },
// Edit-bookmark panel get panel() { delete this.panel; var element = this._element("editBookmarkPanel");
// initially the panel is hidden // to avoid impacting startup / new window performance
element.hidden = false; element.addEventListener("popuphidden", this, false); element.addEventListener("keypress",
this, false); return this.panel = element; }, // list of command elements (by id) to
disable when the panel is opened _blockedCommands: ["cmd_close", "cmd_closeWindow"], _blockCommands:
function SU__blockCommands() { for each(var key in this._blockedCommands) { var elt =
this._element(key); // make sure not to permanently disable this item (see bug 409155) if (elt.hasAttribute("wasDisabled"))
continue; if (elt.getAttribute("disabled") == "true") elt.setAttribute("wasDisabled",
"true"); else { elt.setAttribute("wasDisabled", "false"); elt.setAttribute("disabled", "true");
} } }, _restoreCommandsState: function SU__restoreCommandsState() { for each(var key in this._blockedCommands)
{ var elt = this._element(key); if (elt.getAttribute("wasDisabled") != "true") elt.removeAttribute("disabled");
elt.removeAttribute("wasDisabled"); } }, // nsIDOMEventListener handleEvent: function
SU_handleEvent(aEvent) { switch (aEvent.type) { case "popuphidden": if (aEvent.originalTarget
== this.panel) { if (!this._element("editBookmarkPanelContent").hidden) this.quitEditMode(); this._restoreCommandsState();
this._itemId = -1; this._uri = null; if (this._batching) { PlacesUIUtils.ptm.endBatch(); this._batching
= false; } } break; case "keypress": if (aEvent.getPreventDefault()) { // The event has already been consumed
inside of the panel. break; } switch (aEvent.keyCode) { case KeyEvent.DOM_VK_ESCAPE: if (!this._element("editBookmarkPanelContent").hidden)
this.cancelButtonOnCommand(); break; case KeyEvent.DOM_VK_RETURN: if (aEvent.target.className
== "expander-up" || aEvent.target.className == "expander-down" || aEvent.target.id ==
"editBMPanel_newFolderButton") { //*** Why is this necessary? The getPreventDefault()
check should // be enough. break; } this.panel.hidePopup(); break; } break; } }, _overlayLoaded: false,
_overlayLoading: false, showEditBookmarkPopup: function SU_showEditBookmarkPopup(aItemId,
aAnchorElement, aPosition) { // Performance: load the overlay the first time the panel
is opened // (see bug 392443). if (this._overlayLoading) return; if (this._overlayLoaded) { this._doShowEditBookmarkPanel(aItemId,
aAnchorElement, aPosition); return; } var loadObserver = { _self: this, _itemId: aItemId,
_anchorElement: aAnchorElement, _position: aPosition, observe: function (aSubject, aTopic,
aData) { this._self._overlayLoading = false; this._self._overlayLoaded = true; this._self._doShowEditBookmarkPanel(this._itemId,
this._anchorElement, this._position); } }; this._overlayLoading = true; document.loadOverlay("chrome://browser/content/places/editBookmarkOverlay.xul",
loadObserver); }, _doShowEditBookmarkPanel: function SU__doShowEditBookmarkPanel(aItemId,
aAnchorElement, aPosition) { if (this.panel.state != "closed") return; this._blockCommands();
// un-done in the popuphiding handler // Move the header (star, title, possibly a
button) into the grid, // so that it aligns nicely with the other items (bug 484022).
var rows = this._element("editBookmarkPanelGrid").lastChild; var header = this._element("editBookmarkPanelHeader");
rows.insertBefore(header, rows.firstChild); header.hidden = false; // Set panel title:
// if we are batching, i.e. the bookmark has been added now, // then show Page Bookmarked,
else if the bookmark did already exist, // we are about editing it, then use Edit This
Bookmark. this._element("editBookmarkPanelTitle").value = this._batching ? gNavigatorBundle.getString("editBookmarkPanel.pageBookmarkedTitle")
: gNavigatorBundle.getString("editBookmarkPanel.editBookmarkTitle"); // No description; show the Done, Cancel;
// hide the Edit, Undo buttons this._element("editBookmarkPanelDescription").textContent = ""; this._element("editBookmarkPanelBottomButtons").hidden
= false; this._element("editBookmarkPanelContent").hidden = false; this._element("editBookmarkPanelEditButton").hidden
= true; this._element("editBookmarkPanelUndoRemoveButton").hidden = true; // The remove button is shown only
if we're not already batching, i.e. // if the cancel button/ESC does not remove the
bookmark. this._element("editBookmarkPanelRemoveButton").hidden = this._batching; // The label of the remove
button differs if the URI is bookmarked // multiple times. var bookmarks = PlacesUtils.getBookmarksForURI(gBrowser.currentURI);
var forms = gNavigatorBundle.getString("editBookmark.removeBookmarks.label"); var label = PluralForm.get(bookmarks.length,
forms).replace("#1", bookmarks.length); this._element("editBookmarkPanelRemoveButton").label = label; // unset the unstarred state, if
set this._element("editBookmarkPanelStarIcon").removeAttribute("unstarred"); this._itemId = aItemId !== undefined ? aItemId
: this._itemId; this.beginBatch(); // Consume dismiss clicks, see bug 400924 this.panel.popupBoxObject
.setConsumeRollupEvent(Ci.nsIPopupBoxObject.ROLLUP_CONSUME); this.panel.openPopup(aAnchorElement, aPosition,
-1, -1); gEditItemOverlay.initPanel(this._itemId, { hiddenRows: ["description", "location",
"loadInSidebar", "keyword"] }); }, panelShown: function SU_panelShown(aEvent) { if (aEvent.target
== this.panel) { if (!this._element("editBookmarkPanelContent").hidden) { fieldToFocus = "editBMPanel_" + gPrefService.getCharPref("browser.bookmarks.editDialog.firstEditField");
var elt = this._element(fieldToFocus); elt.focus(); elt.select(); } else { // Note this isn't
actually used anymore, we should remove this // once we decide not to bring back the page
bookmarked notification this.panel.focus(); } } }, showPageBookmarkedNotification: function
PCH_showPageBookmarkedNotification(aItemId, aAnchorElement, aPosition) { this._blockCommands();
// un-done in the popuphiding handler var brandBundle = this._element("bundle_brand");
var brandShortName = brandBundle.getString("brandShortName"); // "Page Bookmarked" title this._element("editBookmarkPanelTitle").value
= gNavigatorBundle.getString("editBookmarkPanel.pageBookmarkedTitle"); // description this._element("editBookmarkPanelDescription").textContent
= gNavigatorBundle.getFormattedString("editBookmarkPanel.pageBookmarkedDescription", [brandShortName]); // show the "Edit.." button
and the Remove Bookmark button, hide the // undo-remove-bookmark button. this._element("editBookmarkPanelEditButton").hidden
= false; this._element("editBookmarkPanelRemoveButton").hidden = false; this._element("editBookmarkPanelUndoRemoveButton").hidden
= true; // unset the unstarred state, if set this._element("editBookmarkPanelStarIcon").removeAttribute("unstarred");
this._itemId = aItemId !== undefined ? aItemId : this._itemId; if (this.panel.state ==
"closed") { // Consume dismiss clicks, see bug 400924 this.panel.popupBoxObject .setConsumeRollupEvent(Ci.nsIPopupBoxObject.ROLLUP_CONSUME);
this.panel.openPopup(aAnchorElement, aPosition, -1, -1); } else this.panel.focus(); }, quitEditMode:
function SU_quitEditMode() { this._element("editBookmarkPanelContent").hidden = true; this._element("editBookmarkPanelBottomButtons").hidden
= true; gEditItemOverlay.uninitPanel(true); }, editButtonCommand: function SU_editButtonCommand()
{ this.showEditBookmarkPopup(); }, cancelButtonOnCommand: function SU_cancelButtonOnCommand() { //
The order here is important! We have to hide the panel first, otherwise // changes done
as part of Undo may change the panel contents and by // that force it to commit more transactions
this.panel.hidePopup(); this.endBatch(); PlacesUIUtils.ptm.undoTransaction(); }, removeBookmarkButtonCommand: function
SU_removeBookmarkButtonCommand() { //@line 327 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser-places.js"
// cache its uri so we can get the new itemId in the case of undo this._uri = PlacesUtils.bookmarks.getBookmarkURI(this._itemId);
// remove all bookmarks for the bookmark's url, this also removes // the tags for the
url var itemIds = PlacesUtils.getBookmarksForURI(this._uri); for (var i=0; i < itemIds.length; i++) {
var txn = PlacesUIUtils.ptm.removeItem(itemIds[i]); PlacesUIUtils.ptm.doTransaction(txn); } //@line
344 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser-places.js" this.panel.hidePopup(); }, undoRemoveBookmarkCommand:
function SU_undoRemoveBookmarkCommand() { // restore the bookmark by undoing the last
transaction and go back // to the edit state this.endBatch(); PlacesUIUtils.ptm.undoTransaction();
this._itemId = PlacesUtils.getMostRecentBookmarkForURI(this._uri); this.showEditBookmarkPopup(); }, beginBatch:
function SU_beginBatch() { if (!this._batching) { PlacesUIUtils.ptm.beginBatch(); this._batching
= true; } }, endBatch: function SU_endBatch() { if (this._batching) { PlacesUIUtils.ptm.endBatch();
this._batching = false; } var PlacesCommandHook = { /** * Adds a bookmark to the page loaded
in the given browser. * * @param aBrowser * a element. * @param [optional]
aParent * The folder in which to create a new bookmark if the page loaded in * aBrowser
isn't bookmarked yet, defaults to the unfiled root. * @param [optional] aShowEditUI * whether
or not to show the edit-bookmark UI for the bookmark item */ bookmarkPage: function PCH_bookmarkPage(aBrowser,
aParent, aShowEditUI) { var uri = aBrowser.currentURI; var itemId = PlacesUtils.getMostRecentBookmarkForURI(uri);
if (itemId == -1) { // Copied over from addBookmarkForBrowser: // Bug 52536: We obtain the URL and title
from the nsIWebNavigation // associated with a rather than from a DOMWindow.
// This is because when a full page plugin is loaded, there is // no DOMWindow (?) but
information about the loaded document // may still be obtained from the webNavigation.
var webNav = aBrowser.webNavigation; var url = webNav.currentURI; var title; var description;
var charset; try { title = webNav.document.title || url.spec; description = PlacesUIUtils.getDescriptionFromDocument(webNav.document);
charset = webNav.document.characterSet; } catch (e) { } if (aShowEditUI) { // If we
bookmark the page here (i.e. page was not "starred" already) // but open right into
the "edit" state, start batching here, so // "Cancel" in that state removes the bookmark.
StarUI.beginBatch(); } var parent = aParent != undefined ? aParent : PlacesUtils.unfiledBookmarksFolderId;
var descAnno = { name: DESCRIPTION_ANNO, value: description }; var txn = PlacesUIUtils.ptm.createItem(uri,
parent, -1, title, null, [descAnno]); PlacesUIUtils.ptm.doTransaction(txn); // Set the character-set if (charset) PlacesUtils.history.setCharsetForURI(uri,
charset); itemId = PlacesUtils.getMostRecentBookmarkForURI(uri); } // Revert the contents of the location
bar if (gURLBar) gURLBar.handleRevert(); // dock the panel to the star icon when possible,
otherwise dock // it to the content area if (aBrowser.contentWindow == window.content)
{ var starIcon = aBrowser.ownerDocument.getElementById("star-button"); if (starIcon && isElementVisible(starIcon))
{ // Make sure the bookmark properties dialog hangs toward the middle of // the location
bar in RTL builds var position = (getComputedStyle(gNavToolbox, "").direction == "rtl") ? 'after_start' :
'after_end'; if (aShowEditUI) StarUI.showEditBookmarkPopup(itemId, starIcon, position); //@line 442 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser-places.js"
return; } } StarUI.showEditBookmarkPopup(itemId, aBrowser, "overlap"); }, /** * Adds a bookmark
to the page loaded in the current tab. */ bookmarkCurrentPage: function PCH_bookmarkCurrentPage(aShowEditUI,
aParent) { this.bookmarkPage(getBrowser().selectedBrowser, aParent, aShowEditUI); }, /** * Adds a bookmark
to the page targeted by a link. * @param aParent * The folder in which to create a new bookmark
if aURL isn't * bookmarked. * @param aURL (string) * the address of the link target
* @param aTitle * The link text */ bookmarkLink: function PCH_bookmarkLink(aParent, aURL, aTitle)
{ var linkURI = makeURI(aURL); var itemId = PlacesUtils.getMostRecentBookmarkForURI(linkURI);
if (itemId == -1) PlacesUIUtils.showMinimalAddBookmarkUI(linkURI, aTitle); else { PlacesUIUtils.showItemProperties(itemId,
PlacesUtils.bookmarks.TYPE_BOOKMARK); } }, /** * This function returns a list of nsIURI
objects characterizing the * tabs currently open in the browser. The URIs will appear
in the * list in the order in which their corresponding tabs appeared. However, * only
the first instance of each URI will be returned. * * @returns a list of nsIURI objects representing
unique locations open */ _getUniqueTabInfo: function BATC__getUniqueTabInfo() { var tabList
= []; var seenURIs = []; var browsers = getBrowser().browsers; for (var i = 0; i
< browsers.length; ++i) { var webNav = browsers[i].webNavigation; var uri = webNav.currentURI; // skip redundant
entries if (uri.spec in seenURIs) continue; // add to the set of seen URIs seenURIs[uri.spec]
= true; tabList.push(uri); } return tabList; }, /** * Adds a folder with bookmarks to
all of the currently open tabs in this * window. */ bookmarkCurrentPages: function
PCH_bookmarkCurrentPages() { var tabURIs = this._getUniqueTabInfo(); PlacesUIUtils.showMinimalAddMultiBookmarkUI(tabURIs);
}, /** * Adds a Live Bookmark to a feed associated with the current page. * @param url * The
nsIURI of the page the feed was attached to * @title title * The title of the feed. Optional.
* @subtitle subtitle * A short description of the feed. Optional. */ addLiveBookmark:
function PCH_addLiveBookmark(url, feedTitle, feedSubtitle) { var feedURI = makeURI(url);
var doc = gBrowser.contentDocument; var title = (arguments.length > 1) ? feedTitle : doc.title;
var description; if (arguments.length > 2) description = feedSubtitle; else description
= PlacesUIUtils.getDescriptionFromDocument(doc); var toolbarIP = new InsertionPoint(PlacesUtils.bookmarks.toolbarFolder,
-1); PlacesUIUtils.showMinimalAddLivemarkUI(feedURI, gBrowser.currentURI, title, description, toolbarIP,
true); }, /** * Opens the Places Organizer. * @param aLeftPaneRoot * The query to select
in the organizer window - options * are: History, AllBookmarks, BookmarksMenu, BookmarksToolbar,
* UnfiledBookmarks and Tags. */ showPlacesOrganizer: function PCH_showPlacesOrganizer(aLeftPaneRoot)
{ var wm = Cc["@mozilla.org/appshell/window-mediator;1"]. getService(Ci.nsIWindowMediator); var organizer
= wm.getMostRecentWindow("Places:Organizer"); if (!organizer) { // No currently open places
window, so open one with the specified mode. openDialog("chrome://browser/content/places/places.xul",
"", "chrome,toolbar=yes,dialog=no,resizable", aLeftPaneRoot); } else { organizer.PlacesOrganizer.selectLeftPaneQuery(aLeftPaneRoot);
organizer.focus(); } }, deleteButtonOnCommand: function PCH_deleteButtonCommand() { PlacesUtils.bookmarks.removeItem(gEditItemOverlay.itemId);
// remove all tags for the associated url PlacesUtils.tagging.untagURI(gEditItemOverlay._uri,
null); this.panel.hidePopup(); // Helper object for the history menu. var HistoryMenu = {
get _ss() { delete this._ss; return this._ss = Cc["@mozilla.org/browser/sessionstore;1"].
getService(Ci.nsISessionStore); }, toggleRecentlyClosedTabs: function PHM_toggleRecentlyClosedTabs() {
// enable/disable the Recently Closed Tabs sub menu var undoPopup = document.getElementById("historyUndoPopup");
// no restorable tabs, so disable menu if (this._ss.getClosedTabCount(window) == 0)
undoPopup.parentNode.setAttribute("disabled", true); else undoPopup.parentNode.removeAttribute("disabled");
}, /** * Re-open a closed tab and put it to the end of the tab strip. * Used for a
middle click. * @param aEvent * The event when the user clicks the menu item */ _undoCloseMiddleClick:
function PHM__undoCloseMiddleClick(aEvent) { if (aEvent.button != 1) return; undoCloseTab(aEvent.originalTarget.value);
gBrowser.moveTabToEnd(); }, /** * Populate when the history menu is opened */ populateUndoSubmenu:
function PHM_populateUndoSubmenu() { var undoPopup = document.getElementById("historyUndoPopup");
// remove existing menu items while (undoPopup.hasChildNodes()) undoPopup.removeChild(undoPopup.firstChild);
// no restorable tabs, so make sure menu is disabled, and return if (this._ss.getClosedTabCount(window)
== 0) { undoPopup.parentNode.setAttribute("disabled", true); return; } // enable menu undoPopup.parentNode.removeAttribute("disabled");
// populate menu var undoItems = eval("(" + this._ss.getClosedTabData(window) + ")");
for (var i = 0; i < undoItems.length; i++) { var m = document.createElement("menuitem");
m.setAttribute("label", undoItems[i].title); if (undoItems[i].image) { let iconURL = undoItems[i].image;
// don't initiate a connection just to fetch a favicon (see bug 467828) if (/^https?:/.test(iconURL))
iconURL = "moz-anno:favicon:" + iconURL; m.setAttribute("image", iconURL); } m.setAttribute("class", "menuitem-iconic
bookmark-item"); m.setAttribute("value", i); m.setAttribute("oncommand", "undoCloseTab("
+ i + ");"); m.addEventListener("click", this._undoCloseMiddleClick, false); if (i == 0) m.setAttribute("key",
"key_undoCloseTab"); undoPopup.appendChild(m); } // "Restore All Tabs" var strings = gNavigatorBundle;
undoPopup.appendChild(document.createElement("menuseparator")); m = undoPopup.appendChild(document.createElement("menuitem"));
m.id = "menu_restoreAllTabs"; m.setAttribute("label", strings.getString("menuRestoreAllTabs.label"));
m.setAttribute("accesskey", strings.getString("menuRestoreAllTabs.accesskey")); m.addEventListener("command", function()
{ for (var i = 0; i < undoItems.length; i++) undoCloseTab(); }, false); }, toggleRecentlyClosedWindows:
function PHM_toggleRecentlyClosedWindows() { // enable/disable the Recently Closed Windows
sub menu let undoPopup = document.getElementById("historyUndoWindowPopup"); // no restorable windows, so disable menu
if (this._ss.getClosedWindowCount() == 0) undoPopup.parentNode.setAttribute("disabled",
true); else undoPopup.parentNode.removeAttribute("disabled"); }, /** * Populate when the history menu is
opened */ populateUndoWindowSubmenu: function PHM_populateUndoWindowSubmenu() { let undoPopup
= document.getElementById("historyUndoWindowPopup"); let menuLabelString = gNavigatorBundle.getString("menuUndoCloseWindowLabel");
let menuLabelStringSingleTab = gNavigatorBundle.getString("menuUndoCloseWindowSingleTabLabel"); // remove existing menu items while (undoPopup.hasChildNodes())
undoPopup.removeChild(undoPopup.firstChild); // no restorable windows, so make sure menu
is disabled, and return if (this._ss.getClosedWindowCount() == 0) { undoPopup.parentNode.setAttribute("disabled",
true); return; } // enable menu undoPopup.parentNode.removeAttribute("disabled"); // populate menu let undoItems = JSON.parse(this._ss.getClosedWindowData());
for (let i = 0; i < undoItems.length; i++) { let undoItem = undoItems[i]; let otherTabsCount
= undoItem.tabs.length - 1; let label = (otherTabsCount == 0) ? menuLabelStringSingleTab
: PluralForm.get(otherTabsCount, menuLabelString); let menuLabel = label.replace("#1", undoItem.title)
.replace("#2", otherTabsCount); let m = document.createElement("menuitem"); m.setAttribute("label", menuLabel); let selectedTab
= undoItem.tabs[undoItem.selected - 1]; if (selectedTab.attributes.image) { let iconURL
= selectedTab.attributes.image; // don't initiate a connection just to fetch a favicon
(see bug 467828) if (/^https?:/.test(iconURL)) iconURL = "moz-anno:favicon:" + iconURL; m.setAttribute("image",
iconURL); } m.setAttribute("class", "menuitem-iconic bookmark-item"); m.setAttribute("oncommand",
"undoCloseWindow(" + i + ");"); if (i == 0) m.setAttribute("key", "key_undoCloseWindow");
undoPopup.appendChild(m); } // "Open All in Windows" undoPopup.appendChild(document.createElement("menuseparator"));
let m = undoPopup.appendChild(document.createElement("menuitem")); m.id = "menu_restoreAllWindows"; m.setAttribute("label",
gNavigatorBundle.getString("menuRestoreAllWindows.label")); m.setAttribute("accesskey", gNavigatorBundle.getString("menuRestoreAllWindows.accesskey"));
m.setAttribute("oncommand", "for (var i = 0; i < " + undoItems.length + "; i++) undoCloseWindow();");
}, /** * popupshowing handler for the history menu. * @param aEvent * The popupshowing event.
*/ onPopupShowing: function PHM_onPopupShowing(aEvent) { // Don't handle events for submenus. if
(aEvent.target != aEvent.currentTarget) return; var menuPopup = aEvent.target; var resultNode
= menuPopup.getResultNode(); resultNode.containerOpen = true; document.getElementById("endHistorySeparator").hidden
= resultNode.childCount == 0; this.toggleRecentlyClosedTabs(); this.toggleRecentlyClosedWindows(); }, /**
* popuphidden handler for the history menu. * @param aEvent * The popuphidden event.
*/ onPopupHidden: function PHM_onPopupHidden(aEvent) { // Don't handle events for submenus. if
(aEvent.target != aEvent.currentTarget) return; var menuPopup = aEvent.target; var resultNode
= menuPopup.getResultNode(); if (resultNode.containerOpen) resultNode.containerOpen = false; * Functions
for handling events in the Bookmarks Toolbar and menu. var BookmarksEventHandler = { /**
* Handler for click event for an item in the bookmarks toolbar or menu. * Menus and
submenus from the folder buttons bubble up to this handler. * Left-click is handled in
the onCommand function. * When items are middle-clicked (or clicked with modifier), open in tabs.
* If the click came through a menu, close the menu. * @param aEvent * DOMEvent for the
click */ onClick: function BT_onClick(aEvent) { // Only handle middle-click or left-click
with modifiers. //@line 784 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser-places.js" var modifKey = aEvent.ctrlKey || aEvent.shiftKey;
//@line 786 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser-places.js" if (aEvent.button == 2 || (aEvent.button
== 0 && !modifKey)) return; var target = aEvent.originalTarget; // If this event bubbled
up from a menu or menuitem, close the menus. // Do this before opening tabs, to avoid
hiding the open tabs confirm-dialog. if (target.localName == "menu" || target.localName == "menuitem")
{ for (node = target.parentNode; node; node = node.parentNode) { if (node.localName
== "menupopup") node.hidePopup(); else if (node.localName != "menu") break; } } if (target.node
&& PlacesUtils.nodeIsContainer(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 (target.localName == "menu" || target.localName
== "toolbarbutton") PlacesUIUtils.openContainerNodeInTabs(target.node, aEvent); } else if (aEvent.button == 1) {
// left-clicks with modifier are already served by onCommand this.onCommand(aEvent);
} }, /** * Handler for command event for an item in the bookmarks toolbar. * Menus
and submenus from the folder buttons bubble up to this handler. * Opens the item. * @param
aEvent * DOMEvent for the command */ onCommand: function BM_onCommand(aEvent) { var target
= aEvent.originalTarget; if (target.node) PlacesUIUtils.openNodeWithEvent(target.node,
aEvent); }, /** * Handler for popupshowing event for an item in bookmarks toolbar or
menu. * If the item isn't the main bookmarks menu, add an "Open All in Tabs" * menuitem
to the bottom of the popup. * @param event * DOMEvent for popupshowing */ onPopupShowing:
function BM_onPopupShowing(event) { var target = event.originalTarget; if (!target.hasAttribute("placespopup"))
return; // Check if the popup contains at least 2 menuitems with places nodes var numNodes
= 0; var hasMultipleURIs = false; var currentChild = target.firstChild; while (currentChild)
{ if (currentChild.localName == "menuitem" && currentChild.node) { if (++numNodes ==
2) { hasMultipleURIs = true; break; } } currentChild = currentChild.nextSibling;
} var itemId = target._resultNode.itemId; var siteURIString = ""; if (itemId != -1
&& PlacesUtils.itemIsLivemark(itemId)) { var siteURI = PlacesUtils.livemarks.getSiteURI(itemId);
if (siteURI) siteURIString = siteURI.spec; } if (!siteURIString && target._endOptOpenSiteURI)
{ target.removeChild(target._endOptOpenSiteURI); target._endOptOpenSiteURI = null; } if (!hasMultipleURIs
&& target._endOptOpenAllInTabs) { target.removeChild(target._endOptOpenAllInTabs); target._endOptOpenAllInTabs = null; } if (!(hasMultipleURIs
|| siteURIString)) { // we don't have to show any option if (target._endOptSeparator)
{ target.removeChild(target._endOptSeparator); target._endOptSeparator = null; target._endMarker
= -1; } return; } if (!target._endOptSeparator) { // create a separator before options target._endOptSeparator
= document.createElement("menuseparator"); target._endOptSeparator.className = "bookmarks-actions-menuseparator";
target._endMarker = target.childNodes.length; target.appendChild(target._endOptSeparator);
} if (siteURIString && !target._endOptOpenSiteURI) { // Add "Open (Feed Name)" menuitem if it's
a livemark with a siteURI target._endOptOpenSiteURI = document.createElement("menuitem"); target._endOptOpenSiteURI.className
= "openlivemarksite-menuitem"; target._endOptOpenSiteURI.setAttribute("siteURI", siteURIString); target._endOptOpenSiteURI.setAttribute("oncommand",
"openUILink(this.getAttribute('siteURI'), event);"); // If a user middle-clicks this
item we serve the oncommand event // We are using checkForMiddleClick because of Bug 246720
// Note: stopPropagation is needed to avoid serving middle-click // with BT_onClick that
would open all items in tabs target._endOptOpenSiteURI.setAttribute("onclick", "checkForMiddleClick(this, event); event.stopPropagation();");
target._endOptOpenSiteURI.setAttribute("label", PlacesUIUtils.getFormattedString("menuOpenLivemarkOrigin.label",
[target.parentNode.getAttribute("label")])); target.appendChild(target._endOptOpenSiteURI);
} if (hasMultipleURIs && !target._endOptOpenAllInTabs) { // Add the "Open All in Tabs" menuitem
if there are // at least two menuitems with places result nodes. target._endOptOpenAllInTabs
= document.createElement("menuitem"); target._endOptOpenAllInTabs.className = "openintabs-menuitem"; target._endOptOpenAllInTabs.setAttribute("oncommand",
"PlacesUIUtils.openContainerNodeInTabs(this.parentNode._resultNode, event);"); target._endOptOpenAllInTabs.setAttribute("onclick",
"checkForMiddleClick(this, event); event.stopPropagation();"); target._endOptOpenAllInTabs.setAttribute("label",
gNavigatorBundle.getString("menuOpenAllInTabs.label")); target.appendChild(target._endOptOpenAllInTabs);
} }, fillInBHTooltip: function(aDocument, aEvent) { var node; var cropped = false; if
(aDocument.tooltipNode.localName == "treechildren") { var tree = aDocument.tooltipNode.parentNode;
var row = {}, column = {}; var tbo = tree.treeBoxObject; tbo.getCellAt(aEvent.clientX, aEvent.clientY,
row, column, {}); if (row.value == -1) return false; node = tree.view.nodeForTreeIndex(row.value);
cropped = tbo.isCellCropped(row.value, column.value); } else node = aDocument.tooltipNode.node;
if (!node) return false; var title = node.title; var url; // Show URL only for URI-type nodes.
if (PlacesUtils.nodeIsURI(node)) url = node.uri; // Show tooltip for containers only if their
title is cropped. if (!cropped && !url) return false; var tooltipTitle = aDocument.getElementById("bhtTitleText");
tooltipTitle.hidden = (!title || (title == url)); if (!tooltipTitle.hidden) tooltipTitle.textContent
= title; var tooltipUrl = aDocument.getElementById("bhtUrlText"); tooltipUrl.hidden = !url; if (!tooltipUrl.hidden)
tooltipUrl.value = url; // Show tooltip. return true; * Drag and Drop handling specifically
for the Bookmarks Menu item in the * top level menu bar var BookmarksMenuDropHandler = {
/** * Need to tell the session to update the state of the cursor as we drag * over
the Bookmarks Menu to show the "can drop" state vs. the "no drop" * state. */ onDragOver:
function BMDH_onDragOver(event, flavor, session) { if (!this.canDrop(event, session)) event.dataTransfer.effectAllowed
= "none"; }, /** * Advertises the set of data types that can be dropped on the Bookmarks
* Menu * @returns a FlavourSet object per nsDragAndDrop parlance. */ getSupportedFlavours:
function BMDH_getSupportedFlavours() { var view = document.getElementById("bookmarksMenuPopup");
return view.getSupportedFlavours(); }, /** * Determine whether or not the user can drop
on the Bookmarks Menu. * @param event * A dragover event * @param session * The active
DragSession * @returns true if the user can drop onto the Bookmarks Menu item, false
* otherwise. */ canDrop: function BMDH_canDrop(event, session) { PlacesControllerDragHelper.currentDataTransfer
= event.dataTransfer; var ip = new InsertionPoint(PlacesUtils.bookmarksMenuFolderId, -1); return ip && PlacesControllerDragHelper.canDrop(ip);
}, /** * Called when the user drops onto the top level Bookmarks Menu item. * @param
event * A drop event * @param data * Data that was dropped * @param session * The active
DragSession */ onDrop: function BMDH_onDrop(event, data, session) { PlacesControllerDragHelper.currentDataTransfer
= event.dataTransfer; // Put the item at the end of bookmark menu var ip = new InsertionPoint(PlacesUtils.bookmarksMenuFolderId,
-1, Ci.nsITreeView.DROP_ON); PlacesControllerDragHelper.onDrop(ip); }, /** * Called when drop target leaves the
menu or after a drop. * @param aEvent * A drop event */ onDragExit: function BMDH_onDragExit(event,
session) { PlacesControllerDragHelper.currentDataTransfer = null; * Handles special drag and drop functionality
for menus on the Bookmarks * Toolbar and Bookmarks Menu. var PlacesMenuDNDController = { _springLoadDelay:
350, // milliseconds /** * All Drag Timers set for the Places UI */ _timers: { }, /**
* Called when the user drags over the Bookmarks top level element. * @param event
* The DragEnter event that spawned the opening. */ onBookmarksMenuDragEnter: function PMDC_onDragEnter(event)
{ if ("loadTime" in this._timers) return; this._setDragTimer("loadTime", this._openBookmarksMenu,
this._springLoadDelay, [event]); }, /** * Creates a timer that will fire during a drag
and drop operation. * @param id * The identifier of the timer being set * @param callback
* The function to call when the timer "fires" * @param delay * The time to wait before
calling the callback function * @param args * An array of arguments to pass to the callback
function */ _setDragTimer: function PMDC__setDragTimer(id, callback, delay, args) { if (!this._dragSupported)
return; // Cancel this timer if it's already running. if (id in this._timers) this._timers[id].cancel();
/** * An object implementing nsITimerCallback that calls a user-supplied * method with the
specified args in the context of the supplied object. */ function Callback(object, method,
args) { this._method = method; this._args = args; this._object = object; } Callback.prototype
= { notify: function C_notify(timer) { this._method.apply(this._object, this._args); } }; var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
timer.initWithCallback(new Callback(this, callback, args), delay, timer.TYPE_ONE_SHOT);
this._timers[id] = timer; }, /** * Determines if a XUL element represents a container in
the Bookmarks system * @returns true if the element is a container element (menu or *`
menu-toolbarbutton), false otherwise. */ _isContainer: function PMDC__isContainer(node)
{ return node.localName == "menu" || (node.localName == "toolbarbutton" && node.getAttribute("type")
== "menu"); }, /** * Opens the Bookmarks Menu when it is dragged over. (This is special-cased,
* since the toplevel Bookmarks is not a member of an existing places * container,
as folders on the personal toolbar or submenus are. * @param event * The DragEnter event
that spawned the opening. */ _openBookmarksMenu: function PMDC__openBookmarksMenu(event) {
if ("loadTime" in this._timers) delete this._timers.loadTime; if (event.target.id == "bookmarksMenu") {
// If this is the bookmarks menu, tell its menupopup child to show. event.target.lastChild.setAttribute("autoopened",
"true"); event.target.lastChild.showPopup(event.target.lastChild); } }, // Whether or not drag and drop to menus
is supported on this platform // Dragging in menus is disabled on OS X due to various
repainting issues. //@line 1136 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser-places.js" _dragSupported: true //@line 1138 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser-places.js"
var PlacesStarButton = { init: function PSB_init() { try { PlacesUtils.bookmarks.addObserver(this,
false); } catch(ex) { Components.utils.reportError("PlacesStarButton.init(): error adding bookmark observer: " + ex);
} }, uninit: function PSB_uninit() { PlacesUtils.bookmarks.removeObserver(this); }, QueryInterface: function PSB_QueryInterface(aIID)
{ if (aIID.equals(Ci.nsINavBookmarkObserver) || aIID.equals(Ci.nsISupports)) return this;
throw Cr.NS_NOINTERFACE; }, _starred: false, _batching: false, updateState: function PSB_updateState()
{ var starIcon = document.getElementById("star-button"); if (!starIcon) return; var uri = getBrowser().currentURI;
this._starred = uri && (PlacesUtils.getMostRecentBookmarkForURI(uri) != -1 || PlacesUtils.getMostRecentFolderForFeedURI(uri)
!= -1); if (this._starred) { starIcon.setAttribute("starred", "true"); starIcon.setAttribute("tooltiptext",
gNavigatorBundle.getString("starButtonOn.tooltip")); } else { starIcon.removeAttribute("starred");
starIcon.setAttribute("tooltiptext", gNavigatorBundle.getString("starButtonOff.tooltip")); } }, onClick: function PSB_onClick(aEvent)
{ if (aEvent.button == 0) PlacesCommandHook.bookmarkCurrentPage(this._starred); // don't bubble to the textbox so that the
address won't be selected aEvent.stopPropagation(); }, // nsINavBookmarkObserver onBeginUpdateBatch:
function PSB_onBeginUpdateBatch() { this._batching = true; }, onEndUpdateBatch: function PSB_onEndUpdateBatch()
{ this.updateState(); this._batching = false; }, onItemAdded: function PSB_onItemAdded(aItemId,
aFolder, aIndex, aItemType) { if (!this._batching && !this._starred) this.updateState(); },
onBeforeItemRemoved: function() {}, onItemRemoved: function PSB_onItemRemoved(aItemId, aFolder,
aIndex, aItemType) { if (!this._batching) this.updateState(); }, onItemChanged: function
PSB_onItemChanged(aItemId, aProperty, aIsAnnotationProperty, aNewValue, aLastModified, aItemType) { if
(!this._batching && aProperty == "uri") this.updateState(); }, onItemVisited: function() { }, onItemMoved:
function() { } //@line 6641 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js" //@line 41 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser-textZoom.js"
// One of the possible values for the mousewheel.* preferences. // From nsEventStateManager.cpp.
const MOUSE_SCROLL_ZOOM = 3; * Controls the "full zoom" setting and its site-specific
preferences. var FullZoom = { //**************************************************************************// // Name & Values // The name of the setting.
Identifies the setting in the prefs database. name: "browser.content.full-zoom", // The
global value (if any) for the setting. Lazily loaded from the service // when first requested,
then updated by the pref change listener as it changes. // If there is no global value,
then this should be undefined. get globalValue FullZoom_get_globalValue() { var globalValue
= this._cps.getPref(null, this.name); if (typeof globalValue != "undefined") globalValue
= this._ensureValid(globalValue); delete this.globalValue; return this.globalValue
= globalValue; }, //**************************************************************************// // Convenience Getters // Content Pref Service
get _cps FullZoom_get__cps() { delete this._cps; return this._cps = Cc["@mozilla.org/content-pref/service;1"].
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 _siteSpecificPref: undefined,
// browser.zoom.updateBackgroundTabs preference cache updateBackgroundTabs: undefined, //
whether we are in private browsing mode _inPrivateBrowsing: false, get siteSpecific FullZoom_get_siteSpecific()
{ return !this._inPrivateBrowsing && this._siteSpecificPref; }, //**************************************************************************//
// 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) { if (!this.interfaces.some(function (v) aIID.equals(v)))
throw Cr.NS_ERROR_NO_INTERFACE; return this; }, //**************************************************************************//
// Initialization & Destruction init: function FullZoom_init() { // Listen for scrollwheel
events so we can save scrollwheel-based changes. window.addEventListener("DOMMouseScroll",
this, false); // Register ourselves with the service so we know when our pref changes.
this._cps.addObserver(this.name, this); // We disable site-specific preferences in Private
Browsing mode, because the // content preferences module is disabled let os = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService); os.addObserver(this, "private-browsing", true); // Retrieve the
initial status of the Private Browsing mode. this._inPrivateBrowsing = Cc["@mozilla.org/privatebrowsing;1"].
getService(Ci.nsIPrivateBrowsingService). privateBrowsingEnabled; this._siteSpecificPref
= this._prefBranch.getBoolPref("browser.zoom.siteSpecific"); this.updateBackgroundTabs = this._prefBranch.getBoolPref("browser.zoom.updateBackgroundTabs");
// Listen for changes to the browser.zoom branch so we can enable/disable // updating
background tabs and per-site saving and restoring of zoom levels. this._prefBranch.addObserver("browser.zoom.",
this, true); }, destroy: function FullZoom_destroy() { let os = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService); os.removeObserver(this, "private-browsing"); this._prefBranch.removeObserver("browser.zoom.",
this); this._cps.removeObserver(this.name, this); window.removeEventListener("DOMMouseScroll",
this, false); delete this._cps; }, //**************************************************************************// // Event Handlers // nsIDOMEventListener
handleEvent: function FullZoom_handleEvent(event) { switch (event.type) { case "DOMMouseScroll":
this._handleMouseScrolled(event); break; } }, _handleMouseScrolled: function FullZoom__handleMouseScrolled(event)
{ // Construct the "mousewheel action" pref key corresponding to this event. // Based
on nsEventStateManager::GetBasePrefKeyForMouseWheel. var pref = "mousewheel"; if (event.axis ==
event.HORIZONTAL_AXIS) pref += ".horizscroll"; if (event.shiftKey) pref += ".withshiftkey";
else if (event.ctrlKey) pref += ".withcontrolkey"; else if (event.altKey) pref += ".withaltkey";
else if (event.metaKey) pref += ".withmetakey"; else pref += ".withnokey"; pref += ".action";
// Don't do anything if this isn't a "zoom" scroll event. var isZoomEvent = false; try
{ isZoomEvent = (gPrefService.getIntPref(pref) == MOUSE_SCROLL_ZOOM); } catch (e) {} if
(!isZoomEvent) return; // *** Lazily cache all the possible action prefs so we don't
have to get // them anew from the pref service for every scroll event? We'd have to // make
sure to observe them so we can update the cache when they change. // We have to call
_applySettingToPref in a timeout because we handle // the event before the event state
manager has a chance to apply the zoom // during nsEventStateManager::PostHandleEvent.
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._siteSpecificPref = this._prefBranch.getBoolPref("browser.zoom.siteSpecific");
break; case "browser.zoom.updateBackgroundTabs": this.updateBackgroundTabs = this._prefBranch.getBoolPref("browser.zoom.updateBackgroundTabs");
break; } break; case "private-browsing": switch (aData) { case "enter": this._inPrivateBrowsing
= true; break; case "exit": this._inPrivateBrowsing = false; break; } break; } }, // nsIContentPrefObserver
onContentPrefSet: function FullZoom_onContentPrefSet(aGroup, aName, aValue) { if (aGroup == this._cps.grouper.group(gBrowser.currentURI))
this._applyPrefToSetting(aValue); else if (aGroup == null) { this.globalValue = this._ensureValid(aValue);
// If the current page doesn't have a site-specific preference, // then its zoom should be set
to the new global preference now that // the global preference has changed. if (!this._cps.hasPref(gBrowser.currentURI,
this.name)) this._applyPrefToSetting(); } }, onContentPrefRemoved: function FullZoom_onContentPrefRemoved(aGroup,
aName) { if (aGroup == this._cps.grouper.group(gBrowser.currentURI)) this._applyPrefToSetting(); else if (aGroup
== null) { this.globalValue = undefined; // If the current page doesn't have a site-specific
preference, // then its zoom should be set to the default preference now that // the
global preference has changed. if (!this._cps.hasPref(gBrowser.currentURI, this.name)) this._applyPrefToSetting(); }
}, // location change observer /** * Called when the location of a tab changes. * When
that happens, we need to update the current zoom level if appropriate. * * @param aURI
* A URI object representing the new location. * @param aIsTabSwitch * Whether this location
change has happened because of a tab switch. * @param aBrowser * (optional) browser object
displaying the document */ onLocationChange: function FullZoom_onLocationChange(aURI, aIsTabSwitch,
aBrowser) { if (!aURI || (aIsTabSwitch && !this.siteSpecific)) return; this._applyPrefToSetting(this._cps.getPref(aURI,
this.name), aBrowser); }, // update state of zoom type menu item updateMenu: function
FullZoom_updateMenu() { var menuItem = document.getElementById("toggle_zoom"); menuItem.setAttribute("checked", !ZoomManager.useFullZoom);
}, //**************************************************************************// // Setting & Pref Manipulation reduce: function
FullZoom_reduce() { ZoomManager.reduce(); this._applySettingToPref(); }, enlarge: function
FullZoom_enlarge() { ZoomManager.enlarge(); this._applySettingToPref(); }, reset: function
FullZoom_reset() { if (typeof this.globalValue != "undefined") ZoomManager.zoom = this.globalValue;
else ZoomManager.reset(); this._removePref(); }, /** * Set the zoom level for the current
tab. * * Per nsPresContext::setFullZoom, we can set the zoom to its current value * without
significant impact on performance, as the setting is only applied * if it differs from
the current setting. In fact getting the zoom and then * checking ourselves if it differs
costs more. * * And perhaps we should always set the zoom even if it was more expensive,
* since DocumentViewerImpl::SetTextZoom claims that child documents can have * a different
text zoom (although it would be unusual), and it implies that * those child text zooms
should get updated when the parent zoom gets set, * and perhaps the same is true for full
zoom * (although DocumentViewerImpl::SetFullZoom doesn't mention it). * * So when we apply
new zoom values to the browser, we simply set the zoom. * We don't check first to see
if the new value is the same as the current * one. **/ _applyPrefToSetting: function
FullZoom__applyPrefToSetting(aValue, aBrowser) { if (!this.siteSpecific && !this._inPrivateBrowsing)
return; var browser = aBrowser || gBrowser.selectedBrowser; try { if (gInPrintPreviewMode || browser.contentDocument
instanceof Ci.nsIImageDocument || this._inPrivateBrowsing) ZoomManager.setZoomForBrowser(browser, 1);
else if (typeof aValue != "undefined") ZoomManager.setZoomForBrowser(browser, this._ensureValid(aValue)); else if (typeof
this.globalValue != "undefined") ZoomManager.setZoomForBrowser(browser, this.globalValue); else ZoomManager.setZoomForBrowser(browser,
1); } catch(ex) {} }, _applySettingToPref: function FullZoom__applySettingToPref() {
if (!this.siteSpecific || gInPrintPreviewMode || content.document instanceof Ci.nsIImageDocument)
return; var zoomLevel = ZoomManager.zoom; this._cps.setPref(gBrowser.currentURI, this.name,
zoomLevel); }, _removePref: function FullZoom__removePref() { if (!(content.document instanceof Ci.nsIImageDocument))
this._cps.removePref(gBrowser.currentURI, this.name); }, //**************************************************************************//
// Utilities _ensureValid: function FullZoom__ensureValid(aValue) { if (isNaN(aValue)) return 1; if (aValue
< ZoomManager.MIN) return ZoomManager.MIN; if (aValue > ZoomManager.MAX) return ZoomManager.MAX;
return aValue; //@line 6643 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js" //@line 39 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser-tabPreviews.js"
* Tab previews utility, produces thumbnails var tabPreviews = { aspectRatio: 0.5625,
// 16:9 init: function tabPreviews_init() { this.width = Math.ceil(screen.availWidth
/ 5.75); this.height = Math.round(this.width * this.aspectRatio); gBrowser.tabContainer.addEventListener("TabSelect",
this, false); gBrowser.tabContainer.addEventListener("SSTabRestored", this, false); }, uninit: function tabPreviews_uninit()
{ gBrowser.tabContainer.removeEventListener("TabSelect", this, false); gBrowser.tabContainer.removeEventListener("SSTabRestored",
this, false); this._selectedTab = null; }, get: function tabPreviews_get(aTab) { if
(aTab.__thumbnail_lastURI && aTab.__thumbnail_lastURI != aTab.linkedBrowser.currentURI.spec) {
aTab.__thumbnail = null; aTab.__thumbnail_lastURI = null; } return aTab.__thumbnail || this.capture(aTab,
!aTab.hasAttribute("busy")); }, capture: function tabPreviews_capture(aTab, aStore) { var thumbnail
= document.createElementNS("http://www.w3.org/1999/xhtml", "canvas"); thumbnail.mozOpaque = true; thumbnail.height
= this.height; thumbnail.width = this.width; var ctx = thumbnail.getContext("2d"); var
win = aTab.linkedBrowser.contentWindow; var snippetWidth = win.innerWidth * .6; var scale
= this.width / snippetWidth; ctx.scale(scale, scale); ctx.drawWindow(win, win.scrollX, win.scrollY,
snippetWidth, snippetWidth * this.aspectRatio, "rgb(255,255,255)"); if (aStore) { aTab.__thumbnail
= thumbnail; aTab.__thumbnail_lastURI = aTab.linkedBrowser.currentURI.spec; } return
thumbnail; }, handleEvent: function tabPreviews_handleEvent(event) { switch (event.type) { case "TabSelect":
if (this._selectedTab && this._selectedTab.parentNode && !this._pendingUpdate) { // Generate a
thumbnail for the tab that was selected. // The timeout keeps the UI snappy and prevents
us from generating thumbnails // for tabs that will be closed. During that timeout,
don't generate other // thumbnails in case multiple TabSelect events occur fast in succession.
this._pendingUpdate = true; setTimeout(function (self, aTab) { self._pendingUpdate = false;
if (aTab.parentNode && !aTab.hasAttribute("busy")) self.capture(aTab, true); }, 2000, this, this._selectedTab);
} this._selectedTab = event.target; break; case "SSTabRestored": this.capture(event.target,
true); break; } var tabPreviewPanelHelper = { opening: function (host) { host.panel.hidden
= false; var handler = this._generateHandler(host); host.panel.addEventListener("popupshown",
handler, false); host.panel.addEventListener("popuphiding", handler, false); host.panel.addEventListener("popuphidden",
handler, false); host._prevFocus = document.commandDispatcher.focusedElement; }, _generateHandler: function (host) { var
self = this; return function (event) { if (event.target == host.panel) { host.panel.removeEventListener(event.type,
arguments.callee, false); self["_" + event.type](host); } }; }, _popupshown: function (host) { if
("setupGUI" in host) host.setupGUI(); }, _popuphiding: function (host) { if ("suspendGUI"
in host) host.suspendGUI(); if (host._prevFocus) { Cc["@mozilla.org/focus-manager;1"] .getService(Ci.nsIFocusManager)
.setFocus(host._prevFocus, Ci.nsIFocusManager.FLAG_NOSCROLL); host._prevFocus = null; } else gBrowser.selectedBrowser.focus();
if (host.tabToSelect) { gBrowser.selectedTab = host.tabToSelect; host.tabToSelect = null;
} }, _popuphidden: function (host) { // Destroy the widget in order to prevent outdated
content // when re-opening the panel. host.panel.hidden = true; * Ctrl-Tab panel var ctrlTab = {
get panel () { delete this.panel; return this.panel = document.getElementById("ctrlTab-panel");
}, get showAllButton () { delete this.showAllButton; return this.showAllButton = document.getElementById("ctrlTab-showAll");
}, get previews () { delete this.previews; return this.previews = this.panel.getElementsByClassName("ctrlTab-preview");
}, get recentlyUsedLimit () { delete this.recentlyUsedLimit; return this.recentlyUsedLimit = gPrefService.getIntPref("browser.ctrlTab.recentlyUsedLimit");
}, get keys () { var keys = {}; ["close", "find", "selectAll"].forEach(function (key)
{ keys[key] = document.getElementById("key_" + key) .getAttribute("key") .toLocaleLowerCase().charCodeAt(0);
}); delete this.keys; return this.keys = keys; }, _selectedIndex: 0, get selected
() this._selectedIndex < 0 ? document.activeElement : this.previews.item(this._selectedIndex),
get isOpen () this.panel.state == "open" || this.panel.state == "showing" || this._timer,
get tabCount () this.tabList.length, get tabPreviewCount () Math.min(this.previews.length - 1, this.tabCount),
get canvasWidth () Math.min(tabPreviews.width, Math.ceil(screen.availWidth * .85 / this.tabPreviewCount)),
get canvasHeight () Math.round(this.canvasWidth * tabPreviews.aspectRatio), get tabList
() { if (this._tabList) return this._tabList; var list = Array.slice(gBrowser.mTabs); if
(this._closing) this.detachTab(this._closing, list); for (let i = 0; i < gBrowser.tabContainer.selectedIndex;
i++) list.push(list.shift()); if (this.recentlyUsedLimit != 0) { let recentlyUsedTabs = this._recentlyUsedTabs;
if (this.recentlyUsedLimit > 0) recentlyUsedTabs = this._recentlyUsedTabs.slice(0, this.recentlyUsedLimit);
for (let i = recentlyUsedTabs.length - 1; i >= 0; i--) { list.splice(list.indexOf(recentlyUsedTabs[i]),
1); list.unshift(recentlyUsedTabs[i]); } } return this._tabList = list; }, init: function
ctrlTab_init() { if (!this._recentlyUsedTabs) { this._recentlyUsedTabs = [gBrowser.selectedTab];
this._init(true); } }, uninit: function ctrlTab_uninit() { this._recentlyUsedTabs = null; this._init(false);
}, prefName: "browser.ctrlTab.previews", readPref: function ctrlTab_readPref() { var
enable = gPrefService.getBoolPref(this.prefName) && (!gPrefService.prefHasUserValue("browser.ctrlTab.disallowForScreenReaders")
|| !gPrefService.getBoolPref("browser.ctrlTab.disallowForScreenReaders")); if (enable) this.init(); else this.uninit();
}, observe: function (aSubject, aTopic, aPrefName) { this.readPref(); }, updatePreviews: function
ctrlTab_updatePreviews() { for (let i = 0; i < this.previews.length; i++) this.updatePreview(this.previews[i],
this.tabList[i]); var showAllLabel = gNavigatorBundle.getString("ctrlTab.showAll.label"); this.showAllButton.label = PluralForm.get(this.tabCount,
showAllLabel).replace("#1", this.tabCount); }, updatePreview: function ctrlTab_updatePreview(aPreview,
aTab) { if (aPreview == this.showAllButton) return; if ((aPreview._tab || null) != aTab)
{ if (aPreview._tab) aPreview._tab.removeEventListener("DOMAttrModified", this, false); aPreview._tab = aTab; if (aTab)
aTab.addEventListener("DOMAttrModified", this, false); } if (aPreview.firstChild) aPreview.removeChild(aPreview.firstChild);
if (aTab) { let canvasWidth = this.canvasWidth; let canvasHeight = this.canvasHeight; aPreview.appendChild(tabPreviews.get(aTab));
aPreview.setAttribute("label", aTab.label); aPreview.setAttribute("tooltiptext", aTab.label);
aPreview.setAttribute("crop", aTab.crop); aPreview.setAttribute("canvaswidth", canvasWidth);
aPreview.setAttribute("canvasstyle", "max-width:" + canvasWidth + "px;" + "min-width:" + canvasWidth
+ "px;" + "max-height:" + canvasHeight + "px;" + "min-height:" + canvasHeight + "px;"); if
(aTab.image) aPreview.setAttribute("image", aTab.image); else aPreview.removeAttribute("image");
aPreview.hidden = false; } else { aPreview.hidden = true; aPreview.removeAttribute("label");
aPreview.removeAttribute("tooltiptext"); aPreview.removeAttribute("image"); } }, advanceFocus: function ctrlTab_advanceFocus(aForward)
{ if (this.panel.state == "open") { if (aForward) document.commandDispatcher.advanceFocus();
else document.commandDispatcher.rewindFocus(); } else { do { this._selectedIndex += aForward
? 1 : -1; if (this._selectedIndex < 0) this._selectedIndex = this.previews.length - 1; else if (this._selectedIndex
>= this.previews.length) this._selectedIndex = 0; } while (this.selected.hidden); } if
(this._timer) { clearTimeout(this._timer); this._timer = null; this._openPanel(); }
}, _mouseOverFocus: function ctrlTab_mouseOverFocus(aPreview) { if (this._trackMouseOver) aPreview.focus();
}, pick: function ctrlTab_pick(aPreview) { if (!this.tabCount) return; var select
= (aPreview || this.selected); if (select == this.showAllButton) this.showAllTabs();
else this.close(select._tab); }, showAllTabs: function ctrlTab_showAllTabs(aPreview) {
this.close(); document.getElementById("Browser:ShowAllTabs").doCommand(); }, remove: function ctrlTab_remove(aPreview)
{ if (aPreview._tab) gBrowser.removeTab(aPreview._tab); }, attachTab: function ctrlTab_attachTab(aTab,
aPos) { if (aPos == 0) this._recentlyUsedTabs.unshift(aTab); else if (aPos) this._recentlyUsedTabs.splice(aPos,
0, aTab); else this._recentlyUsedTabs.push(aTab); }, detachTab: function ctrlTab_detachTab(aTab,
aTabs) { var tabs = aTabs || this._recentlyUsedTabs; var i = tabs.indexOf(aTab); if (i >= 0) tabs.splice(i,
1); }, open: function ctrlTab_open() { if (this.isOpen) return; allTabs.close(); document.addEventListener("keyup",
this, true); this.updatePreviews(); this._selectedIndex = 1; // Add a slight delay before showing
the UI, so that a quick // "ctrl-tab" keypress just flips back to the MRU tab. this._timer
= setTimeout(function (self) { self._timer = null; self._openPanel(); }, 200, this);
}, _openPanel: function ctrlTab_openPanel() { tabPreviewPanelHelper.opening(this); this.panel.width
= Math.min(screen.availWidth * .99, this.canvasWidth * 1.25 * this.tabPreviewCount); var estimateHeight
= this.canvasHeight * 1.25 + 75; this.panel.openPopupAtScreen(screen.availLeft + (screen.availWidth - this.panel.width)
/ 2, screen.availTop + (screen.availHeight - estimateHeight) / 2, false); }, close:
function ctrlTab_close(aTabToSelect) { if (!this.isOpen) return; if (this._timer) {
clearTimeout(this._timer); this._timer = null; this.suspendGUI(); if (aTabToSelect)
gBrowser.selectedTab = aTabToSelect; return; } this.tabToSelect = aTabToSelect; this.panel.hidePopup();
}, setupGUI: function ctrlTab_setupGUI() { this.selected.focus(); this._selectedIndex
= -1; // Track mouse movement after a brief delay so that the item that happens // to
be under the mouse pointer initially won't be selected unintentionally. this._trackMouseOver
= false; setTimeout(function (self) { if (self.isOpen) self._trackMouseOver = true;
}, 0, this); }, suspendGUI: function ctrlTab_suspendGUI() { document.removeEventListener("keyup", this,
true); Array.forEach(this.previews, function (preview) { this.updatePreview(preview, null);
}, this); this._tabList = null; }, onKeyPress: function ctrlTab_onKeyPress(event) { var isOpen
= this.isOpen; if (isOpen) { event.preventDefault(); event.stopPropagation(); } switch (event.keyCode)
{ case event.DOM_VK_TAB: if (event.ctrlKey && !event.altKey && !event.metaKey) { if
(isOpen) { this.advanceFocus(!event.shiftKey); } else if (!event.shiftKey) { event.preventDefault();
event.stopPropagation(); if (gBrowser.mTabs.length > 2) { this.open(); } else if (gBrowser.mTabs.length
== 2) { gBrowser.selectedTab = gBrowser.selectedTab.nextSibling || gBrowser.selectedTab.previousSibling;
} } } break; default: if (isOpen && event.ctrlKey) { if (event.keyCode == event.DOM_VK_DELETE)
{ this.remove(this.selected); break; } switch (event.charCode) { case this.keys.close: this.remove(this.selected);
break; case this.keys.find: case this.keys.selectAll: this.showAllTabs(); break; } } } }, removeClosingTabFromUI:
function ctrlTab_removeClosingTabFromUI(aTab) { if (this.tabCount == 2) { this.close();
return; } this._closing = aTab; this._tabList = null; this.updatePreviews(); this._closing
= null; if (this.selected.hidden) this.advanceFocus(false); if (this.selected == this.showAllButton) this.advanceFocus(false);
// If the current tab is removed, another tab can steal our focus. if (aTab == gBrowser.selectedTab
&& this.panel.state == "open") { setTimeout(function (selected) { selected.focus(); }, 0, this.selected);
} }, handleEvent: function ctrlTab_handleEvent(event) { switch (event.type) { case "DOMAttrModified":
// tab attribute modified (e.g. label, crop, busy, image) for (let i = this.previews.length
- 1; i >= 0; i--) { if (this.previews[i]._tab && this.previews[i]._tab == event.target)
{ this.updatePreview(this.previews[i], event.target); break; } } break; case "TabSelect": this.detachTab(event.target);
this.attachTab(event.target, 0); break; case "TabOpen": this.attachTab(event.target, 1);
break; case "TabClose": this.detachTab(event.target); if (this.isOpen) this.removeClosingTabFromUI(event.target);
break; case "keypress": this.onKeyPress(event); break; case "keyup": if (event.keyCode ==
event.DOM_VK_CONTROL) this.pick(); break; } }, _init: function ctrlTab__init(enable)
{ var toggleEventListener = enable ? "addEventListener" : "removeEventListener"; var tabContainer
= gBrowser.tabContainer; tabContainer[toggleEventListener]("TabOpen", this, false); tabContainer[toggleEventListener]("TabSelect",
this, false); tabContainer[toggleEventListener]("TabClose", this, false); document[toggleEventListener]("keypress",
this, false); gBrowser.mTabBox.handleCtrlTab = !enable; // If we're not running, hide
the "Show All Tabs" menu item, // as Shift+Ctrl+Tab will be handled by the tab bar. document.getElementById("menu_showAllTabs").hidden
= !enable; * All Tabs panel var allTabs = { get panel () { delete this.panel; return
this.panel = document.getElementById("allTabs-panel"); }, get filterField () { delete this.filterField;
return this.filterField = document.getElementById("allTabs-filter"); }, get container () { delete this.container;
return this.container = document.getElementById("allTabs-container"); }, get tabCloseButton () { delete this.tabCloseButton;
return this.tabCloseButton = document.getElementById("allTabs-tab-close-button"); }, get _browserCommandSet () { delete this._browserCommandSet;
return this._browserCommandSet = document.getElementById("mainCommandSet"); }, get isOpen () this.panel.state == "open"
|| this.panel.state == "showing", init: function allTabs_init() { if (this._initiated) return;
this._initiated = true; Array.forEach(gBrowser.mTabs, function (tab) { this._addPreview(tab); },
this); gBrowser.tabContainer.addEventListener("TabOpen", this, false); gBrowser.tabContainer.addEventListener("TabMove",
this, false); gBrowser.tabContainer.addEventListener("TabClose", this, false); }, uninit: function allTabs_uninit()
{ if (!this._initiated) return; gBrowser.tabContainer.removeEventListener("TabOpen", this, false); gBrowser.tabContainer.removeEventListener("TabMove",
this, false); gBrowser.tabContainer.removeEventListener("TabClose", this, false); while (this.container.hasChildNodes())
this.container.removeChild(this.container.firstChild); this._initiated = false; }, prefName: "browser.allTabs.previews",
readPref: function allTabs_readPref() { var allTabsButton = document.getAnonymousElementByAttribute(
gBrowser.tabContainer, "anonid", "alltabs-button"); if (gPrefService.getBoolPref(this.prefName))
{ allTabsButton.removeAttribute("type"); allTabsButton.setAttribute("command", "Browser:ShowAllTabs");
} else { allTabsButton.setAttribute("type", "menu"); allTabsButton.removeAttribute("command");
allTabsButton.removeAttribute("oncommand"); } }, observe: function (aSubject, aTopic,
aPrefName) { this.readPref(); }, pick: function allTabs_pick(aPreview) { if (!aPreview) aPreview
= this._firstVisiblePreview; if (aPreview) this.tabToSelect = aPreview._tab; this.close();
}, closeTab: function allTabs_closeTab(event) { this.filterField.focus(); gBrowser.removeTab(event.currentTarget._targetPreview._tab);
}, filter: function allTabs_filter() { if (this._currentFilter == this.filterField.value)
return; this._currentFilter = this.filterField.value; var filter = this._currentFilter.split(/\s+/g);
this._visible = 0; Array.forEach(this.container.childNodes, function (preview) { var tab = preview._tab;
var matches = 0; if (filter.length) { let tabstring = tab.linkedBrowser.currentURI.spec;
try { tabstring = decodeURI(tabstring); } catch (e) {} tabstring = tab.label + " "
+ tab.label.toLocaleLowerCase() + " " + tabstring; for (let i = 0; i < filter.length; i++) matches
+= tabstring.indexOf(filter[i]) > -1; } if (matches < filter.length) { preview.hidden
= true; tab.removeEventListener("DOMAttrModified", this, false); } else { this._visible++; this._updatePreview(preview);
preview.hidden = false; tab.addEventListener("DOMAttrModified", this, false); } }, this); this._reflow();
}, open: function allTabs_open() { this.init(); if (this.isOpen) return; this.filter(); tabPreviewPanelHelper.opening(this);
this.panel.popupBoxObject.setConsumeRollupEvent(Ci.nsIPopupBoxObject.ROLLUP_CONSUME); var estimateHeight = (this._maxHeight + parseInt(this.container.maxHeight)
+ 50) / 2; this.panel.openPopupAtScreen(screen.availLeft + (screen.availWidth - this._maxWidth) /
2, screen.availTop + (screen.availHeight - estimateHeight) / 2, false); }, close: function
allTabs_close() { this.panel.hidePopup(); }, setupGUI: function allTabs_setupGUI()
{ this.filterField.focus(); this.filterField.setAttribute("emptytext", this.filterField.tooltipText); this.panel.addEventListener("keypress",
this, false); this.panel.addEventListener("keypress", this, true); this._browserCommandSet.addEventListener("command",
this, false); }, suspendGUI: function allTabs_suspendGUI() { Array.forEach(this.container.childNodes,
function (preview) { preview._tab.removeEventListener("DOMAttrModified", this, false); }, this); this.filterField.removeAttribute("emptytext");
this.filterField.value = ""; this._currentFilter = null; this._updateTabCloseButton(); this.panel.removeEventListener("keypress",
this, false); this.panel.removeEventListener("keypress", this, true); this._browserCommandSet.removeEventListener("command",
this, false); }, handleEvent: function allTabs_handleEvent(event) { switch (event.type) { case "DOMAttrModified":
// tab attribute modified (e.g. label, crop, busy, image) this._updatePreview(this._getPreview(event.target));
break; case "TabOpen": if (this.isOpen) this.close(); this._addPreview(event.target); break; case
"TabMove": if (event.target.nextSibling) this.container.insertBefore(this._getPreview(event.target), this._getPreview(event.target.nextSibling));
else this.container.appendChild(this._getPreview(event.target)); break; case "TabClose": this._removePreview(this._getPreview(event.target));
break; case "keypress": this._onKeyPress(event); break; case "command": if (event.target.id
!= "Browser:ShowAllTabs") { // Close the panel when there's a browser command executing
in the background. this.close(); } break; } }, _visible: 0, _currentFilter: null, get
_maxWidth () screen.availWidth * .9, get _maxHeight () screen.availHeight * .75, get _stack
() { delete this._stack; return this._stack = document.getElementById("allTabs-stack");
}, get _previewLabelHeight () { delete this._previewLabelHeight; return this._previewLabelHeight = parseInt(getComputedStyle(this.container.firstChild,
"").lineHeight); }, get _visiblePreviews () Array.filter(this.container.childNodes,
function (preview) !preview.hidden), get _firstVisiblePreview () { if (this._visible == 0) return null;
var previews = this.container.childNodes; for (let i = 0; i < previews.length; i++)
{ if (!previews[i].hidden) return previews[i]; } return null; }, _reflow: function allTabs_reflow()
{ this._updateTabCloseButton(); // the size of the whole preview relative to the thumbnail
const REL_PREVIEW_THUMBNAIL = 1.2; var maxHeight = this._maxHeight; var maxWidth = this._maxWidth;
var rel = tabPreviews.height / tabPreviews.width; var rows, previewHeight, previewWidth, outerHeight;
var previewMaxWidth = tabPreviews.width * REL_PREVIEW_THUMBNAIL; this._columns = Math.floor(maxWidth
/ previewMaxWidth); do { rows = Math.ceil(this._visible / this._columns); previewWidth = Math.min(previewMaxWidth,
Math.round(maxWidth / this._columns)); previewHeight = Math.round(previewWidth * rel); outerHeight
= previewHeight + this._previewLabelHeight; } while (rows * outerHeight > maxHeight
&& ++this._columns); var outerWidth = previewWidth; { let innerWidth = Math.ceil(previewWidth
/ REL_PREVIEW_THUMBNAIL); let innerHeight = Math.ceil(previewHeight / REL_PREVIEW_THUMBNAIL);
var canvasStyle = "max-width:" + innerWidth + "px;" + "min-width:" + innerWidth + "px;"
+ "max-height:" + innerHeight + "px;" + "min-height:" + innerHeight + "px;"; } Array.forEach(this.container.childNodes,
function (preview) { preview.setAttribute("minwidth", outerWidth); preview.setAttribute("height",
outerHeight); preview.setAttribute("canvasstyle", canvasStyle); preview.removeAttribute("closebuttonhover");
}, this); this._stack.width = maxWidth; this.container.width = Math.ceil(outerWidth * Math.min(this._columns,
this._visible)); this.container.left = Math.round((maxWidth - this.container.width) / 2); this.container.maxWidth
= maxWidth - this.container.left; this.container.maxHeight = rows * outerHeight; }, _addPreview: function
allTabs_addPreview(aTab) { var preview = document.createElement("button"); preview.className
= "allTabs-preview"; preview._tab = aTab; return this.container.appendChild(preview);
}, _removePreview: function allTabs_removePreview(aPreview) { var updateUI = (this.isOpen && !aPreview.hidden);
aPreview._tab.removeEventListener("DOMAttrModified", this, false); aPreview._tab = null; this.container.removeChild(aPreview);
if (updateUI) { this._visible--; this._reflow(); this.filterField.focus(); } }, _getPreview:
function allTabs_getPreview(aTab) { var previews = this.container.childNodes; for (let i
= 0; i < previews.length; i++) if (previews[i]._tab == aTab) return previews[i]; return null;
}, _updateTabCloseButton: function allTabs_updateTabCloseButton(event) { if (event && event.target == this.tabCloseButton)
return; if (this.tabCloseButton._targetPreview) { if (event && event.target == this.tabCloseButton._targetPreview)
return; this.tabCloseButton._targetPreview.removeAttribute("closebuttonhover"); } if (event && event.target.parentNode ==
this.container && (event.target._tab.previousSibling || event.target._tab.nextSibling)) { let
preview = event.target.getBoundingClientRect(); let container = this.container.getBoundingClientRect();
let tabCloseButton = this.tabCloseButton.getBoundingClientRect(); let alignLeft = getComputedStyle(this.panel,
"").direction == "rtl"; //@line 874 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser-tabPreviews.js" this.tabCloseButton.left = preview.left -
container.left + parseInt(this.container.left) + (alignLeft ? 0 : preview.width - tabCloseButton.width);
this.tabCloseButton.top = preview.top - container.top; this.tabCloseButton._targetPreview = event.target;
this.tabCloseButton.style.visibility = "visible"; event.target.setAttribute("closebuttonhover",
"true"); } else { this.tabCloseButton.style.visibility = "hidden"; this.tabCloseButton.left = this.tabCloseButton.top
= 0; this.tabCloseButton._targetPreview = null; } }, _updatePreview: function allTabs_updatePreview(aPreview)
{ aPreview.setAttribute("label", aPreview._tab.label); aPreview.setAttribute("tooltiptext", aPreview._tab.label);
aPreview.setAttribute("crop", aPreview._tab.crop); if (aPreview._tab.image) aPreview.setAttribute("image",
aPreview._tab.image); else aPreview.removeAttribute("image"); var thumbnail = tabPreviews.get(aPreview._tab);
if (aPreview.firstChild) { if (aPreview.firstChild == thumbnail) return; aPreview.removeChild(aPreview.firstChild);
} aPreview.appendChild(thumbnail); }, _onKeyPress: function allTabs_onKeyPress(event) { if (event.eventPhase
== event.CAPTURING_PHASE) { this._onCapturingKeyPress(event); return; } if (event.keyCode == event.DOM_VK_ESCAPE)
{ this.close(); event.preventDefault(); event.stopPropagation(); return; } if (event.target == this.filterField)
{ switch (event.keyCode) { case event.DOM_VK_UP: if (this._visible) { let previews = this._visiblePreviews;
let columns = Math.min(previews.length, this._columns); previews[Math.floor(previews.length / columns)
* columns - 1].focus(); event.preventDefault(); event.stopPropagation(); } break; case event.DOM_VK_DOWN:
if (this._visible) { this._firstVisiblePreview.focus(); event.preventDefault(); event.stopPropagation();
} break; } } }, _onCapturingKeyPress: function allTabs_onCapturingKeyPress(event) { switch
(event.keyCode) { case event.DOM_VK_UP: case event.DOM_VK_DOWN: if (event.target != this.filterField)
this._advanceFocusVertically(event); break; case event.DOM_VK_RETURN: if (event.target
== this.filterField) { this.filter(); this.pick(); event.preventDefault(); event.stopPropagation();
} break; } }, _advanceFocusVertically: function allTabs_advanceFocusVertically(event) { var
preview = document.activeElement; if (!preview || preview.parentNode != this.container)
return; event.stopPropagation(); var up = (event.keyCode == event.DOM_VK_UP); var previews
= this._visiblePreviews; if (up && preview == previews[0]) { this.filterField.focus();
return; } var i = previews.indexOf(preview); var columns = Math.min(previews.length, this._columns);
var column = i % columns; var row = Math.floor(i / columns); function newIndex() row * columns
+ column; function outOfBounds() newIndex() >= previews.length; if (up) { row--; if (row
< 0) { let rows = Math.ceil(previews.length / columns); row = rows - 1; column--; if
(outOfBounds()) row--; } } else { row++; if (outOfBounds()) { if (column == columns -
1) { this.filterField.focus(); return; } row = 0; column++; } } previews[newIndex()].focus();
//@line 6645 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js" XPCOMUtils.defineLazyGetter(this, "Win7Features",
function () { //@line 6649 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js" const WINTASKBAR_CONTRACTID = "@mozilla.org/windows-taskbar;1";
if (WINTASKBAR_CONTRACTID in Cc && Cc[WINTASKBAR_CONTRACTID].getService(Ci.nsIWinTaskbar).available) { let temp = {}; Cu.import("resource://gre/modules/WindowsPreviewPerTab.jsm",
temp); let AeroPeek = temp.AeroPeek; return { onOpenWindow: function () { AeroPeek.onOpenWindow(window);
}, onCloseWindow: function () { AeroPeek.onCloseWindow(window); } }; //@line 6666 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js"
return null; * Re-open a closed tab. * @param aIndex * The index of the tab (via nsSessionStore.getClosedTabData)
* @returns a reference to the reopened tab. function undoCloseTab(aIndex) { // wallpaper
patch to prevent an unnecessary blank tab (bug 343895) var blankTabToRemove = null;
if (gBrowser.tabContainer.childNodes.length == 1 && !gPrefService.getBoolPref("browser.tabs.autoHide")
&& gBrowser.selectedBrowser.sessionHistory.count < 2 && gBrowser.selectedBrowser.currentURI.spec
== "about:blank" && !gBrowser.selectedBrowser.contentDocument.body.hasChildNodes() && !gBrowser.selectedTab.hasAttribute("busy"))
blankTabToRemove = gBrowser.selectedTab; var tab = null; var ss = Cc["@mozilla.org/browser/sessionstore;1"].
getService(Ci.nsISessionStore); if (ss.getClosedTabCount(window) > (aIndex || 0)) { tab = ss.undoCloseTab(window,
aIndex || 0); if (blankTabToRemove) gBrowser.removeTab(blankTabToRemove); return tab; * Re-open a closed window. *
@param aIndex * The index of the window (via nsSessionStore.getClosedWindowData) * @returns
a reference to the reopened window. function undoCloseWindow(aIndex) { let ss = Cc["@mozilla.org/browser/sessionstore;1"].
getService(Ci.nsISessionStore); let window = null; if (ss.getClosedWindowCount() >
(aIndex || 0)) window = ss.undoCloseWindow(aIndex || 0); return window; * Format a URL * eg:
* echo formatURL("https://addons.mozilla.org/%LOCALE%/%APP%/%VERSION%/"); * > https://addons.mozilla.org/en-US/firefox/3.0a1/
* Currently supported built-ins are LOCALE, APP, and any value from nsIXULAppInfo, uppercased.
function formatURL(aFormat, aIsPref) { var formatter = Cc["@mozilla.org/toolkit/URLFormatterService;1"].getService(Ci.nsIURLFormatter);
return aIsPref ? formatter.formatURLPref(aFormat) : formatter.formatURL(aFormat); * This also
takes care of updating the command enabled-state when tabs are * created or removed. function
BookmarkAllTabsHandler() { this._command = document.getElementById("Browser:BookmarkAllTabs");
gBrowser.addEventListener("TabOpen", this, true); gBrowser.addEventListener("TabClose",
this, true); this._updateCommandState(); BookmarkAllTabsHandler.prototype = { QueryInterface: function BATH_QueryInterface(aIID)
{ if (aIID.equals(Ci.nsIDOMEventListener) || aIID.equals(Ci.nsISupports)) return this;
throw Cr.NS_NOINTERFACE; }, _updateCommandState: function BATH__updateCommandState(aTabClose)
{ var numTabs = gBrowser.tabContainer.childNodes.length; // The TabClose event is fired before the
tab is removed from the DOM if (aTabClose) numTabs--; if (numTabs > 1) this._command.removeAttribute("disabled");
else this._command.setAttribute("disabled", "true"); }, doCommand: function BATH_doCommand()
{ PlacesCommandHook.bookmarkCurrentPages(); }, // nsIDOMEventListener handleEvent: function(aEvent)
{ this._updateCommandState(aEvent.type == "TabClose"); * Utility object to handle manipulations
of the identity indicators in the UI var gIdentityHandler = { // Mode strings used to control CSS display
IDENTITY_MODE_IDENTIFIED : "verifiedIdentity", // High-quality identity information IDENTITY_MODE_DOMAIN_VERIFIED
: "verifiedDomain", // Minimal SSL CA-signed domain verification IDENTITY_MODE_UNKNOWN
: "unknownIdentity", // No trusted identity information IDENTITY_MODE_MIXED_CONTENT :
"unknownIdentity mixedContent", // SSL with unauthenticated content // Cache the most
recent SSLStatus and Location seen in checkIdentity _lastStatus : null, _lastLocation : null,
// smart getters get _encryptionLabel () { delete this._encryptionLabel; this._encryptionLabel
= {}; this._encryptionLabel[this.IDENTITY_MODE_DOMAIN_VERIFIED] = gNavigatorBundle.getString("identity.encrypted");
this._encryptionLabel[this.IDENTITY_MODE_IDENTIFIED] = gNavigatorBundle.getString("identity.encrypted");
this._encryptionLabel[this.IDENTITY_MODE_UNKNOWN] = gNavigatorBundle.getString("identity.unencrypted");
this._encryptionLabel[this.IDENTITY_MODE_MIXED_CONTENT] = gNavigatorBundle.getString("identity.mixed_content");
return this._encryptionLabel; }, get _identityPopup () { delete this._identityPopup; return this._identityPopup
= document.getElementById("identity-popup"); }, get _identityBox () { delete this._identityBox;
return this._identityBox = document.getElementById("identity-box"); }, get _identityPopupContentBox () { delete
this._identityPopupContentBox; return this._identityPopupContentBox = document.getElementById("identity-popup-content-box");
}, get _identityPopupContentHost () { delete this._identityPopupContentHost; return this._identityPopupContentHost
= document.getElementById("identity-popup-content-host"); }, get _identityPopupContentOwner () { delete
this._identityPopupContentOwner; return this._identityPopupContentOwner = document.getElementById("identity-popup-content-owner");
}, get _identityPopupContentSupp () { delete this._identityPopupContentSupp; return this._identityPopupContentSupp
= document.getElementById("identity-popup-content-supplemental"); }, get _identityPopupContentVerif () { delete
this._identityPopupContentVerif; return this._identityPopupContentVerif = document.getElementById("identity-popup-content-verifier");
}, get _identityPopupEncLabel () { delete this._identityPopupEncLabel; return this._identityPopupEncLabel
= document.getElementById("identity-popup-encryption-label"); }, get _identityIconLabel () { delete this._identityIconLabel;
return this._identityIconLabel = document.getElementById("identity-icon-label"); }, get _overrideService () { delete this._overrideService;
return this._overrideService = Cc["@mozilla.org/security/certoverride;1"] .getService(Ci.nsICertOverrideService); },
/** * Rebuild cache of the elements that may or may not exist depending * on whether
there's a location bar. */ _cacheElements : function() { delete this._identityBox;
delete this._identityIconLabel; this._identityBox = document.getElementById("identity-box");
this._identityIconLabel = document.getElementById("identity-icon-label"); }, /** * Handler for mouseclicks on the "More
Information" button in the * "identity-popup" panel. */ handleMoreInfoClick : function(event)
{ displaySecurityInfo(); event.stopPropagation(); }, /** * Helper to parse out the important
parts of _lastStatus (of the SSL cert in * particular) for use in constructing identity
UI strings */ getIdentityData : function() { var result = {}; var status = this._lastStatus.QueryInterface(Components.interfaces.nsISSLStatus);
var cert = status.serverCert; // Human readable name of Subject result.subjectOrg = cert.organization;
// SubjectName fields, broken up for individual access if (cert.subjectName) { result.subjectNameFields
= {}; cert.subjectName.split(",").forEach(function(v) { var field = v.split("="); this[field[0]]
= field[1]; }, result.subjectNameFields); // Call out city, state, and country specifically
result.city = result.subjectNameFields.L; result.state = result.subjectNameFields.ST;
result.country = result.subjectNameFields.C; } // Human readable name of Certificate Authority
result.caOrg = cert.issuerOrganization || cert.issuerCommonName; result.cert = cert;
return result; }, /** * Determine the identity of the page being displayed by examining its
SSL cert * (if available) and, if necessary, update the UI to reflect this. Intended to
* be called by onSecurityChange * * @param PRUint32 state * @param JS Object location
that mirrors an nsLocation (i.e. has .host and * .hostname and .port) */ checkIdentity
: function(state, location) { var currentStatus = gBrowser.securityUI .QueryInterface(Components.interfaces.nsISSLStatusProvider)
.SSLStatus; this._lastStatus = currentStatus; this._lastLocation = location; let nsIWebProgressListener
= Ci.nsIWebProgressListener; if (state & nsIWebProgressListener.STATE_IDENTITY_EV_TOPLEVEL)
this.setMode(this.IDENTITY_MODE_IDENTIFIED); else if (state & nsIWebProgressListener.STATE_SECURE_HIGH)
this.setMode(this.IDENTITY_MODE_DOMAIN_VERIFIED); else if (state & nsIWebProgressListener.STATE_IS_BROKEN)
this.setMode(this.IDENTITY_MODE_MIXED_CONTENT); else this.setMode(this.IDENTITY_MODE_UNKNOWN);
}, /** * Return the eTLD+1 version of the current hostname */ getEffectiveHost : function()
{ // Cache the eTLDService if this is our first time through if (!this._eTLDService)
this._eTLDService = Cc["@mozilla.org/network/effective-tld-service;1"] .getService(Ci.nsIEffectiveTLDService); try
{ return this._eTLDService.getBaseDomainFromHost(this._lastLocation.hostname); } catch (e) { // If something goes wrong
(e.g. hostname is an IP address) just fail back // to the full domain. return this._lastLocation.hostname;
} }, /** * Update the UI to reflect the specified mode, which should be one of the * IDENTITY_MODE_*
constants. */ setMode : function(newMode) { if (!this._identityBox) { // No identity
box means the identity box is not visible, in which // case there's nothing to do. return;
} this._identityBox.className = newMode; this.setIdentityMessages(newMode); // Update
the popup too, if it's open if (this._identityPopup.state == "open") this.setPopupMessages(newMode);
}, /** * Set up the messages for the primary identity UI based on the specified mode,
* and the details of the SSL cert, where applicable * * @param newMode The newly set identity
mode. Should be one of the IDENTITY_MODE_* constants. */ setIdentityMessages : function(newMode)
{ if (newMode == this.IDENTITY_MODE_DOMAIN_VERIFIED) { var iData = this.getIdentityData(); //
It would be sort of nice to use the CN= field in the cert, since that's // typically what
we want here, but thanks to x509 certs being extensible, // it's not the only place you
have to check, there can be more than one domain, // et cetera, ad nauseum. We know
the cert is valid for location.host, so // let's just use that. Check the pref to determine
how much of the verified // hostname to show var icon_label = ""; switch (gPrefService.getIntPref("browser.identity.ssl_domain_display"))
{ case 2 : // Show full domain icon_label = this._lastLocation.hostname; break; case
1 : // Show eTLD. icon_label = this.getEffectiveHost(); } // We need a port number for all lookups.
If one hasn't been specified, use // the https default var lookupHost = this._lastLocation.host;
if (lookupHost.indexOf(':') < 0) lookupHost += ":443"; // Verifier is either the CA Org,
for a normal cert, or a special string // for certs that are trusted because of a security
exception. var tooltip = gNavigatorBundle.getFormattedString("identity.identified.verifier", [iData.caOrg]); // Check whether this site
is a security exception. XPConnect does the right // thing here in terms of converting
_lastLocation.port from string to int, but // the overrideService doesn't like undefined
ports, so make sure we have // something in the default case (bug 432241). if (this._overrideService.hasMatchingOverride(this._lastLocation.hostname,
(this._lastLocation.port || 443), iData.cert, {}, {})) tooltip = gNavigatorBundle.getString("identity.identified.verified_by_you");
} else if (newMode == this.IDENTITY_MODE_IDENTIFIED) { // If it's identified, then we can populate
the dialog with credentials iData = this.getIdentityData(); tooltip = gNavigatorBundle.getFormattedString("identity.identified.verifier",
[iData.caOrg]); if (iData.country) icon_label = gNavigatorBundle.getFormattedString("identity.identified.title_with_country",
[iData.subjectOrg, iData.country]); else icon_label = iData.subjectOrg; } else { tooltip = gNavigatorBundle.getString("identity.unknown.tooltip");
icon_label = ""; } // Push the appropriate strings out to the UI this._identityBox.tooltipText
= tooltip; this._identityIconLabel.value = icon_label; }, /** * Set up the title and
content messages for the identity message popup, * based on the specified mode, and
the details of the SSL cert, where * applicable * * @param newMode The newly set identity
mode. Should be one of the IDENTITY_MODE_* constants. */ setPopupMessages : function(newMode)
{ this._identityPopup.className = newMode; this._identityPopupContentBox.className =
newMode; // Set the static strings up front this._identityPopupEncLabel.textContent =
this._encryptionLabel[newMode]; // Initialize the optional strings to empty values var supplemental
= ""; var verifier = ""; if (newMode == this.IDENTITY_MODE_DOMAIN_VERIFIED) { var
iData = this.getIdentityData(); var host = this.getEffectiveHost(); var owner = gNavigatorBundle.getString("identity.ownerUnknown2");
verifier = this._identityBox.tooltipText; supplemental = ""; } else if (newMode ==
this.IDENTITY_MODE_IDENTIFIED) { // If it's identified, then we can populate the dialog
with credentials iData = this.getIdentityData(); host = this.getEffectiveHost(); owner = iData.subjectOrg;
verifier = this._identityBox.tooltipText; // Build an appropriate supplemental block
out of whatever location data we have if (iData.city) supplemental += iData.city + "\n"; if (iData.state
&& iData.country) supplemental += gNavigatorBundle.getFormattedString("identity.identified.state_and_country", [iData.state, iData.country]); else if (iData.state)
// State only supplemental += iData.state; else if (iData.country) // Country only supplemental
+= iData.country; } else { // These strings will be hidden in CSS anyhow host = ""; owner
= ""; } // Push the appropriate strings out to the UI this._identityPopupContentHost.textContent
= host; this._identityPopupContentOwner.textContent = owner; this._identityPopupContentSupp.textContent
= supplemental; this._identityPopupContentVerif.textContent = verifier; }, hideIdentityPopup : function()
{ this._identityPopup.hidePopup(); }, /** * Click handler for the identity-box element
in primary chrome. */ handleIdentityButtonEvent : function(event) { event.stopPropagation();
if ((event.type == "click" && event.button != 0) || (event.type == "keypress" && event.charCode
!= KeyEvent.DOM_VK_SPACE && event.keyCode != KeyEvent.DOM_VK_RETURN)) return; // Left
click, space or enter only // Revert the contents of the location bar, see bug 406779 gURLBar.handleRevert();
// Make sure that the display:none style we set in xul is removed now that // the popup
is actually needed this._identityPopup.hidden = false; // Tell the popup to consume dismiss
clicks, to avoid bug 395314 this._identityPopup.popupBoxObject .setConsumeRollupEvent(Ci.nsIPopupBoxObject.ROLLUP_CONSUME);
// Update the popup strings this.setPopupMessages(this._identityBox.className); // Make sure the identity popup hangs toward
the middle of the location bar // in RTL builds var position = (getComputedStyle(gNavToolbox,
"").direction == "rtl") ? 'after_end' : 'after_start'; // Add the "open" attribute to the identity
box for styling this._identityBox.setAttribute("open", "true"); var self = this; this._identityPopup.addEventListener("popuphidden",
function (e) { e.currentTarget.removeEventListener("popuphidden", arguments.callee, false); self._identityBox.removeAttribute("open");
}, false); // Now open the popup, anchored off the primary chrome element this._identityPopup.openPopup(this._identityBox,
position); let DownloadMonitorPanel = { ////////////////////////////////////////////////////////////////////////////// //// DownloadMonitorPanel Member Variables
_panel: null, _activeStr: null, _pausedStr: null, _lastTime: Infinity, _listening: false,
get DownloadUtils() { delete this.DownloadUtils; Cu.import("resource://gre/modules/DownloadUtils.jsm",
this); return this.DownloadUtils; }, ////////////////////////////////////////////////////////////////////////////// //// DownloadMonitorPanel Public Methods
/** * Initialize the status panel and member variables */ init: function DMP_init() {
// Initialize "private" member variables this._panel = document.getElementById("download-monitor");
// Cache the status strings this._activeStr = gNavigatorBundle.getString("activeDownloads");
this._pausedStr = gNavigatorBundle.getString("pausedDownloads"); gDownloadMgr.addListener(this); this._listening
= true; this.updateStatus(); }, uninit: function DMP_uninit() { if (this._listening) gDownloadMgr.removeListener(this);
}, inited: function DMP_inited() { return this._panel != null; }, /** * Update status
based on the number of active and paused downloads */ updateStatus: function DMP_updateStatus()
{ if (!this.inited()) return; let numActive = gDownloadMgr.activeDownloadCount; // Hide
the panel and reset the "last time" if there's no downloads if (numActive == 0) { this._panel.hidden
= true; this._lastTime = Infinity; return; } // Find the download with the longest remaining
time let numPaused = 0; let maxTime = -Infinity; let dls = gDownloadMgr.activeDownloads; while
(dls.hasMoreElements()) { let dl = dls.getNext().QueryInterface(Ci.nsIDownload); if (dl.state == gDownloadMgr.DOWNLOAD_DOWNLOADING)
{ // Figure out if this download takes longer if (dl.speed > 0 && dl.size > 0) maxTime
= Math.max(maxTime, (dl.size - dl.amountTransferred) / dl.speed); else maxTime = -1; } else if
(dl.state == gDownloadMgr.DOWNLOAD_PAUSED) numPaused++; } // Get the remaining time string
and last sec for time estimation let timeLeft; [timeLeft, this._lastTime] = this.DownloadUtils.getTimeLeft(maxTime,
this._lastTime); // Figure out how many downloads are currently downloading let numDls = numActive
- numPaused; let status = this._activeStr; // If all downloads are paused, show the
paused message instead if (numDls == 0) { numDls = numPaused; status = this._pausedStr;
} // Get the correct plural form and insert the number of downloads and time // left message
if necessary status = PluralForm.get(numDls, status); status = status.replace("#1", numDls);
status = status.replace("#2", timeLeft); // Update the panel and show it this._panel.label
= status; this._panel.hidden = false; }, //////////////////////////////////////////////////////////////////////////////
//// nsIDownloadProgressListener /** * Update status for download progress changes */ onProgressChange:
function() { this.updateStatus(); }, /** * Update status for download state changes
*/ onDownloadStateChange: function() { this.updateStatus(); }, onStateChange: function(aWebProgress,
aRequest, aStateFlags, aStatus, aDownload) { }, onSecurityChange: function(aWebProgress,
aRequest, aState, aDownload) { }, ////////////////////////////////////////////////////////////////////////////// //// nsISupports QueryInterface: XPCOMUtils.generateQI([Ci.nsIDownloadProgressListener]),
function getNotificationBox(aWindow) { var foundBrowser = gBrowser.getBrowserForDocument(aWindow.document);
if (foundBrowser) return gBrowser.getNotificationBox(foundBrowser) return null; /* DEPRECATED */ function getBrowser()
gBrowser; function getNavToolbox() gNavToolbox; let gPrivateBrowsingUI = { _observerService:
null, _privateBrowsingService: null, _searchBarValue: null, _findBarValue: null, init: function
PBUI_init() { this._observerService = Cc["@mozilla.org/observer-service;1"]. getService(Ci.nsIObserverService); this._observerService.addObserver(this,
"private-browsing", false); this._observerService.addObserver(this, "private-browsing-transition-complete", false);
this._privateBrowsingService = Cc["@mozilla.org/privatebrowsing;1"]. getService(Ci.nsIPrivateBrowsingService);
if (this.privateBrowsingEnabled) this.onEnterPrivateBrowsing(true); }, uninit: function PBUI_unint() { this._observerService.removeObserver(this,
"private-browsing"); this._observerService.removeObserver(this, "private-browsing-transition-complete");
}, get _disableUIOnToggle PBUI__disableUIOnTogle() { if (this._privateBrowsingService.autoStarted)
return false; try { return !gPrefService.getBoolPref("browser.privatebrowsing.keep_current_session"); } catch (e) { return true; } }, observe:
function PBUI_observe(aSubject, aTopic, aData) { if (aTopic == "private-browsing") { if
(aData == "enter") this.onEnterPrivateBrowsing(); else if (aData == "exit") this.onExitPrivateBrowsing();
} else if (aTopic == "private-browsing-transition-complete") { if (this._disableUIOnToggle) { // use setTimeout
here in order to make the code testable setTimeout(function() { document.getElementById("Tools:PrivateBrowsing")
.removeAttribute("disabled"); }, 0); } } }, _shouldEnter: function PBUI__shouldEnter()
{ try { // Never prompt if the session is not going to be closed, or if user has //
already requested not to be prompted. if (gPrefService.getBoolPref("browser.privatebrowsing.dont_prompt_on_enter")
|| gPrefService.getBoolPref("browser.privatebrowsing.keep_current_session")) return true; } catch (ex) { } var bundleService
= Cc["@mozilla.org/intl/stringbundle;1"]. getService(Ci.nsIStringBundleService); var
pbBundle = bundleService.createBundle("chrome://browser/locale/browser.properties"); var brandBundle = bundleService.createBundle("chrome://branding/locale/brand.properties");
var appName = brandBundle.GetStringFromName("brandShortName"); //@line 7353 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js"
var dialogTitle = pbBundle.GetStringFromName("privateBrowsingDialogTitle"); var header = pbBundle.GetStringFromName("privateBrowsingMessageHeader")
+ "\n\n"; //@line 7356 "e:\builds\moz2_slave\win32_build\build\browser\base\content\browser.js" var message = pbBundle.formatStringFromName("privateBrowsingMessage",
[appName], 1); var promptService = Cc["@mozilla.org/embedcomp/prompt-service;1"]. getService(Ci.nsIPromptService); var flags
= promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_0 + promptService.BUTTON_TITLE_IS_STRING
* promptService.BUTTON_POS_1 + promptService.BUTTON_POS_0_DEFAULT; var neverAsk = {value:false}; var button0Title
= pbBundle.GetStringFromName("privateBrowsingYesTitle"); var button1Title = pbBundle.GetStringFromName("privateBrowsingNoTitle");
var neverAskText = pbBundle.GetStringFromName("privateBrowsingNeverAsk"); var result; var choice = promptService.confirmEx(null,
dialogTitle, header + message, flags, button0Title, button1Title, null, neverAskText, neverAsk);
switch (choice) { case 0: // Start Private Browsing result = true; if (neverAsk.value)
gPrefService.setBoolPref("browser.privatebrowsing.dont_prompt_on_enter", true); break; case 1: // Keep result = false;
break; } return result; }, onEnterPrivateBrowsing: function PBUI_onEnterPrivateBrowsing(aOnWindowOpen)
{ if (BrowserSearch.searchBar) this._searchBarValue = BrowserSearch.searchBar.textbox.value;
if (gFindBar) this._findBarValue = gFindBar.getElement("findbar-textbox").value; this._setPBMenuTitle("stop"); document.getElementById("menu_import").setAttribute("disabled",
"true"); // Disable the Clear Recent History... menu item when in PB mode // temporary fix
until bug 463607 is fixed document.getElementById("Tools:Sanitize").setAttribute("disabled", "true"); if (this._privateBrowsingService.autoStarted)
{ // Disable the menu item in auto-start mode document.getElementById("privateBrowsingItem")
.setAttribute("disabled", "true"); document.getElementById("Tools:PrivateBrowsing") .setAttribute("disabled", "true"); } else
if (window.location.href == getBrowserURL()) { // Adjust the window's title let docElement
= document.documentElement; docElement.setAttribute("title", docElement.getAttribute("title_privatebrowsing"));
docElement.setAttribute("titlemodifier", docElement.getAttribute("titlemodifier_privatebrowsing")); docElement.setAttribute("browsingmode", "private");
gBrowser.updateTitlebar(); } setTimeout(function () { DownloadMonitorPanel.updateStatus();
}, 0); if (!aOnWindowOpen && this._disableUIOnToggle) document.getElementById("Tools:PrivateBrowsing")
.setAttribute("disabled", "true"); }, onExitPrivateBrowsing: function PBUI_onExitPrivateBrowsing() { if
(BrowserSearch.searchBar) { let searchBox = BrowserSearch.searchBar.textbox; searchBox.reset();
if (this._searchBarValue) { searchBox.value = this._searchBarValue; this._searchBarValue
= null; } } if (gURLBar) { gURLBar.editor.transactionManager.clear(); } document.getElementById("menu_import").removeAttribute("disabled");
// Re-enable the Clear Recent History... menu item on exit of PB mode // temporary
fix until bug 463607 is fixed document.getElementById("Tools:Sanitize").removeAttribute("disabled"); if (gFindBar) { let findbox = gFindBar.getElement("findbar-textbox");
findbox.reset(); if (this._findBarValue) { findbox.value = this._findBarValue; this._findBarValue
= null; } } this._setPBMenuTitle("start"); if (window.location.href == getBrowserURL())
{ // Adjust the window's title let docElement = document.documentElement; docElement.setAttribute("title",
docElement.getAttribute("title_normal")); docElement.setAttribute("titlemodifier", docElement.getAttribute("titlemodifier_normal"));
docElement.setAttribute("browsingmode", "normal"); } // Enable the menu item in after exiting
the auto-start mode document.getElementById("privateBrowsingItem") .removeAttribute("disabled"); document.getElementById("Tools:PrivateBrowsing")
.removeAttribute("disabled"); gLastOpenDirectory.reset(); setTimeout(function () { DownloadMonitorPanel.updateStatus();
}, 0); if (this._disableUIOnToggle) document.getElementById("Tools:PrivateBrowsing") .setAttribute("disabled", "true"); }, _setPBMenuTitle:
function PBUI__setPBMenuTitle(aMode) { let pbMenuItem = document.getElementById("privateBrowsingItem");
pbMenuItem.setAttribute("label", pbMenuItem.getAttribute(aMode + "label")); pbMenuItem.setAttribute("accesskey",
pbMenuItem.getAttribute(aMode + "accesskey")); }, toggleMode: function PBUI_toggleMode()
{ // prompt the users on entering the private mode, if needed if (!this.privateBrowsingEnabled)
if (!this._shouldEnter()) return; this._privateBrowsingService.privateBrowsingEnabled = !this.privateBrowsingEnabled; }, get privateBrowsingEnabled
PBUI_get_privateBrowsingEnabled() { return this._privateBrowsingService.privateBrowsingEnabled;
let gURLBarEmptyText = { domain: "browser.urlbar.", observe: function UBET_observe(aSubject, aTopic,
aPrefName) { if (aTopic == "nsPref:changed") { switch (aPrefName) { case "browser.urlbar.autocomplete.enabled":
case "browser.urlbar.default.behavior": gURLBar.emptyText = this.value; break; } } }, get value UBET_get_value()
{ let type = "none"; if (gPrefService.getBoolPref("browser.urlbar.autocomplete.enabled")) { // Bottom 2 bits of default.behavior specify
history/bookmark switch (gPrefService.getIntPref("browser.urlbar.default.behavior") & 3) { case 0: type = "bookmarkhistory";
break; case 1: type = "history"; break; case 2: type = "bookmark"; break; } } return gURLBar.getAttribute(type
+ "emptytext"); var LightWeightThemeWebInstaller = { handleEvent: function (event) { switch
(event.type) { case "InstallBrowserTheme": case "PreviewBrowserTheme": case "ResetBrowserThemePreview":
// ignore requests from background tabs if (event.target.ownerDocument.defaultView.top
!= content) return; } switch (event.type) { case "InstallBrowserTheme": this._installRequest(event);
break; case "PreviewBrowserTheme": this._preview(event); break; case "ResetBrowserThemePreview": this._resetPreview(event);
break; case "pagehide": case "TabSelect": this._resetPreview(); break; } }, get _manager
() { var temp = {}; Cu.import("resource://gre/modules/LightweightThemeManager.jsm", temp); delete this._manager; return this._manager
= temp.LightweightThemeManager; }, _installRequest: function (event) { var node = event.target;
var data = this._getThemeFromNode(node); if (!data) return; if (this._isAllowed(node))
{ this._install(data); return; } var allowButtonText = gNavigatorBundle.getString("lwthemeInstallRequest.allowButton");
var allowButtonAccesskey = gNavigatorBundle.getString("lwthemeInstallRequest.allowButton.accesskey"); var message = gNavigatorBundle.getFormattedString("lwthemeInstallRequest.message",
[node.ownerDocument.location.host]); var buttons = [{ label: allowButtonText, accessKey: allowButtonAccesskey,
callback: function () { LightWeightThemeWebInstaller._install(data); } }]; this._removePreviousNotifications();
var notificationBox = gBrowser.getNotificationBox(); var notificationBar = notificationBox.appendNotification(message,
"lwtheme-install-request", "", notificationBox.PRIORITY_INFO_MEDIUM, buttons); notificationBar.persistence = 1;
}, _install: function (newTheme) { var previousTheme = this._manager.currentTheme; this._manager.currentTheme
= newTheme; if (this._manager.currentTheme && this._manager.currentTheme.id == newTheme.id)
this._postInstallNotification(newTheme, previousTheme); }, _postInstallNotification: function (newTheme,
previousTheme) { function text(id) { return gNavigatorBundle.getString("lwthemePostInstallNotification."
+ id); } var buttons = [{ label: text("undoButton"), accessKey: text("undoButton.accesskey"), callback:
function () { LightWeightThemeWebInstaller._manager.forgetUsedTheme(newTheme.id); LightWeightThemeWebInstaller._manager.currentTheme
= previousTheme; } }, { label: text("manageButton"), accessKey: text("manageButton.accesskey"),
callback: function () { BrowserOpenAddonsMgr("themes"); } }]; this._removePreviousNotifications();
var notificationBox = gBrowser.getNotificationBox(); var notificationBar = notificationBox.appendNotification(text("message"),
"lwtheme-install-notification", "", notificationBox.PRIORITY_INFO_MEDIUM, buttons); notificationBar.persistence = 1;
notificationBar.timeout = Date.now() + 20000; // 20 seconds }, _removePreviousNotifications:
function () { var box = gBrowser.getNotificationBox(); ["lwtheme-install-request", "lwtheme-install-notification"].forEach(function
(value) { var notification = box.getNotificationWithValue(value); if (notification) box.removeNotification(notification);
}); }, _previewWindow: null, _preview: function (event) { if (!this._isAllowed(event.target))
return; var data = this._getThemeFromNode(event.target); if (!data) return; this._resetPreview(); this._previewWindow
= event.target.ownerDocument.defaultView; this._previewWindow.addEventListener("pagehide",
this, true); gBrowser.tabContainer.addEventListener("TabSelect", this, false); this._manager.previewTheme(data);
}, _resetPreview: function (event) { if (!this._previewWindow || event && !this._isAllowed(event.target))
return; this._previewWindow.removeEventListener("pagehide", this, true); this._previewWindow = null; gBrowser.tabContainer.removeEventListener("TabSelect",
this, false); this._manager.resetPreview(); }, _isAllowed: function (node) { var pm
= Cc["@mozilla.org/permissionmanager;1"].getService(Ci.nsIPermissionManager); var prefs = [["xpinstall.whitelist.add", pm.ALLOW_ACTION],
["xpinstall.whitelist.add.36", pm.ALLOW_ACTION], ["xpinstall.blacklist.add", pm.DENY_ACTION]];
prefs.forEach(function ([pref, permission]) { try { var hosts = gPrefService.getCharPref(pref);
} catch (e) {} if (hosts) { hosts.split(",").forEach(function (host) { pm.add(makeURI("http://" + host),
"install", permission); }); gPrefService.setCharPref(pref, ""); } }); var uri = node.ownerDocument.documentURIObject;
return pm.testPermission(uri, "install") == pm.ALLOW_ACTION; }, _getThemeFromNode:
function (node) { return this._manager.parseTheme(node.getAttribute("data-browsertheme"), node.baseURI); content/browser/browser.xul
%browserDTD; %globalRegionDTD; %charsetDTD; %textcontextDTD; %customizeToolbarDTD; %placesDTD; %safebrowsingDTD;
accesskey="&viewFrameSourceCmd.accesskey;" oncommand="gContextMenu.viewFrameSource();"
observes="isFrameImage"/>
content/browser/browser-tabPreviews.xml
content/browser/credits.xhtml &credit.thanks;
Google Yahoo! IBM Sun Microsystems Red Hat
Oregon State University - Open Source Lab Global Netoptex,
Inc Internet Software Consortium Cooley Godward, LLP Greenburg
Traurig, LLP OutCast Communications The Royal Order of Experience
Design Nobox silverorange Glaxstar MozillaZine
Community &credit.poweredByGeckoReg;
&brandFullName;™ &license.part0; ©1998-2010 &license.part1;
&license.contrib;, &license.part2; about:license &license.part3; 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. Gecko® is a registered trademark
of Netscape Communications Corporation. U.S. GOVERNMENT END USERS.
The Software is a “commercial item,” as that term is defined in 48 C.F.R. 2.101
(Oct. 1995), consisting of “commercial computer software” and “commercial
computer software documentation,” as such terms are used in 48 C.F.R. 12.212 (Sept.
1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June
1995), all U.S. Government End Users acquire the Software with only those rights set forth
herein. content/browser/fullscreen-video.xhtml
&securityView.privacy.history; &securityView.privacy.cookies;
&securityView.privacy.passwords;
content/browser/pageinfo/pageInfo.js//@line 42 "e:\builds\moz2_slave\win32_build\build\browser\base\content\pageinfo\pageInfo.js"
//******** define a js object to implement nsITreeView function pageInfoTreeView(copycol)
// copycol is the index number for the column that we want to add to // the copy-n-paste
buffer when the user hits accel-c this.copycol = copycol; this.rows = 0; this.tree = null;
this.data = [ ]; this.selection = null; this.sortcol = null; this.sortdir = 0; pageInfoTreeView.prototype
= { set rowCount(c) { throw "rowCount is a readonly property"; }, get rowCount() {
return this.rows; }, setTree: function(tree) this.tree = tree; }, getCellText: function(row,
column) // row can be null, but js arrays are 0-indexed. // colidx cannot be null, but
can be larger than the number // of columns in the array. In this case it's the fault
of // whoever typoed while calling this function. return this.data[row][column.index] || "";
}, setCellValue: function(row, column, value) }, setCellText: function(row, column, value)
this.data[row][column.index] = value; }, addRow: function(row) this.rows = this.data.push(row);
this.rowCountChanged(this.rows - 1, 1); if (this.selection.count == 0 && this.rowCount
&& !gImageElement) this.selection.select(0); }, rowCountChanged: function(index, count)
this.tree.rowCountChanged(index, count); }, invalidate: function() this.tree.invalidate();
}, clear: function() if (this.tree) this.tree.rowCountChanged(0, -this.rows); this.rows = 0; this.data = [
]; }, handleCopy: function(row) return (row < 0 || this.copycol < 0) ? "" : (this.data[row][this.copycol]
|| ""); }, performActionOnRow: function(action, row) if (action == "copy") { var data = this.handleCopy(row)
this.tree.treeBody.parentNode.setAttribute("copybuffer", data); } }, getRowProperties: function(row,
prop) { }, getCellProperties: function(row, column, prop) { }, getColumnProperties: function(column,
prop) { }, isContainer: function(index) { return false; }, isContainerOpen: function(index)
{ return false; }, isSeparator: function(index) { return false; }, isSorted: function()
{ }, canDrop: function(index, orientation) { return false; }, drop: function(row, orientation)
{ return false; }, getParentIndex: function(index) { return 0; }, hasNextSibling: function(index,
after) { return false; }, getLevel: function(index) { return 0; }, getImageSrc: function(row,
column) { }, getProgressMode: function(row, column) { }, getCellValue: function(row, column)
{ }, toggleOpenState: function(index) { }, cycleHeader: function(col) { }, selectionChanged:
function() { }, cycleCell: function(row, column) { }, isEditable: function(row, column) {
return false; }, isSelectable: function(row, column) { return false; }, performAction:
function(action) { }, performActionOnCell: function(action, row, column) { } // mmm,
yummy. global variables. var gWindow = null; var gDocument = null; var gImageElement =
null; // column number to help using the data array const COL_IMAGE_ADDRESS = 0; const
COL_IMAGE_TYPE = 1; const COL_IMAGE_SIZE = 2; const COL_IMAGE_ALT = 3; const COL_IMAGE_COUNT
= 4; const COL_IMAGE_NODE = 5; const COL_IMAGE_BG = 6; // column number to copy from, second
argument to pageInfoTreeView's constructor const COPYCOL_NONE = -1; const COPYCOL_META_CONTENT
= 1; const COPYCOL_IMAGE = COL_IMAGE_ADDRESS; // one nsITreeView for each tree in the window
var gMetaView = new pageInfoTreeView(COPYCOL_META_CONTENT); var gImageView = new pageInfoTreeView(COPYCOL_IMAGE);
gImageView.getCellProperties = function(row, col, props) { var aserv = Components.classes[ATOM_CONTRACTID]
.getService(Components.interfaces.nsIAtomService); if (gImageView.data[row][COL_IMAGE_SIZE]
== gStrings.unknown && !/^https:/.test(gImageView.data[row][COL_IMAGE_ADDRESS])) props.AppendElement(aserv.getAtom("broken"));
var gImageHash = { }; // localized strings (will be filled in when the document is loaded)
// this isn't all of them, these are just the ones that would otherwise have been loaded
inside a loop var gStrings = { }; var gBundle; const PERMISSION_CONTRACTID = "@mozilla.org/permissionmanager;1";
const PREFERENCES_CONTRACTID = "@mozilla.org/preferences-service;1"; const ATOM_CONTRACTID = "@mozilla.org/atom-service;1";
// a number of services I'll need later // the cache services const nsICacheService
= Components.interfaces.nsICacheService; const ACCESS_READ = Components.interfaces.nsICache.ACCESS_READ;
const cacheService = Components.classes["@mozilla.org/network/cache-service;1"].getService(nsICacheService); var httpCacheSession = cacheService.createSession("HTTP",
0, true); httpCacheSession.doomEntriesIfExpired = false; var ftpCacheSession = cacheService.createSession("FTP",
0, true); ftpCacheSession.doomEntriesIfExpired = false; const nsICookiePermission = Components.interfaces.nsICookiePermission;
const nsIPermissionManager = Components.interfaces.nsIPermissionManager; const nsICertificateDialogs = Components.interfaces.nsICertificateDialogs;
const CERTIFICATEDIALOGS_CONTRACTID = "@mozilla.org/nsCertificateDialogs;1" // clipboard helper try { const gClipboardHelper
= Components.classes["@mozilla.org/widget/clipboardhelper;1"].getService(Components.interfaces.nsIClipboardHelper); catch(e) { // do nothing, later code will
handle the error // Interface for image loading content const nsIImageLoadingContent = Components.interfaces.nsIImageLoadingContent;
// namespaces, don't need all of these yet... const XLinkNS = "http://www.w3.org/1999/xlink";
const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; const XMLNS = "http://www.w3.org/XML/1998/namespace";
const XHTMLNS = "http://www.w3.org/1999/xhtml"; const XHTML2NS = "http://www.w3.org/2002/06/xhtml2"
const XHTMLNSre = "^http\:\/\/www\.w3\.org\/1999\/xhtml$"; const XHTML2NSre = "^http\:\/\/www\.w3\.org\/2002\/06\/xhtml2$";
const XHTMLre = RegExp(XHTMLNSre + "|" + XHTML2NSre, ""); /* Overlays register functions here.
* These arrays are used to hold callbacks that Page Info will call at * various stages.
Use them by simply appending a function to them. * For example, add a function to onLoadRegistry
by invoking * "onLoadRegistry.push(XXXLoadFunc);" * The XXXLoadFunc should be unique to the
overlay module, and will be * invoked as "XXXLoadFunc();" // These functions are called to build the
data displayed in the Page // Info window. The global variables gDocument and gWindow
are set. var onLoadRegistry = [ ]; // These functions are called to remove old data still
displayed in // the window when the document whose information is displayed // changes.
For example, at this time, the list of images of the Media // tab is cleared. var onResetRegistry
= [ ]; // These are called once for each subframe of the target document and // the
target document itself. The frame is passed as an argument. var onProcessFrame = [ ];
// These functions are called once for each element (in all subframes, if any) // in the
target document. The element is passed as an argument. var onProcessElement = [ ];
// These functions are called once when all the elements in all of the target // document
(and all of its subframes, if any) have been processed var onFinished = [ ]; // These functions
are called once when the Page Info window is closed. var onUnloadRegistry = [ ]; /*
Called when PageInfo window is loaded. Arguments are: * window.arguments[0] - (optional) an
object consisting of * - doc: (optional) document to use for source. if not provided, * the
calling window's document will be used * - initialTab: (optional) id of the inital
tab to display function onLoadPageInfo() gBundle = document.getElementById("pageinfobundle");
gStrings.unknown = gBundle.getString("unknown"); gStrings.notSet = gBundle.getString("notset");
gStrings.mediaImg = gBundle.getString("mediaImg"); gStrings.mediaBGImg = gBundle.getString("mediaBGImg");
gStrings.mediaObject = gBundle.getString("mediaObject"); gStrings.mediaEmbed = gBundle.getString("mediaEmbed");
gStrings.mediaLink = gBundle.getString("mediaLink"); gStrings.mediaInput = gBundle.getString("mediaInput");
var args = "arguments" in window && window.arguments.length >= 1 && window.arguments[0]; if (!args ||
!args.doc) { gWindow = window.opener.content; gDocument = gWindow.document; // init media
view var imageTree = document.getElementById("imagetree"); imageTree.view = gImageView; /* Select the
requested tab, if the name is specified */ loadTab(args); Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService) .notifyObservers(window, "page-info-dialog-loaded",
null); function loadPageInfo() var titleFormat = gWindow != gWindow.top ? "pageInfo.frame.title"
: "pageInfo.page.title"; document.title = gBundle.getFormattedString(titleFormat,
[gDocument.location]); document.getElementById("main-window").setAttribute("relatedUrl", gDocument.location); // do the easy stuff
first makeGeneralTab(); // and then the hard stuff makeTabs(gDocument, gWindow); initFeedTab();
onLoadPermission(); /* Call registered overlay init functions */ onLoadRegistry.forEach(function(func)
{ func(); }); function resetPageInfo(args) /* Reset Meta tags part */ gMetaView.clear();
/* Reset Media tab */ var mediaTab = document.getElementById("mediaTab"); if (!mediaTab.hidden) { Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService) .removeObserver(imagePermissionObserver, "perm-changed");
mediaTab.hidden = true; gImageView.clear(); gImageHash = {}; /* Reset Feeds Tab */ var
feedListbox = document.getElementById("feedListbox"); while (feedListbox.firstChild) feedListbox.removeChild(feedListbox.firstChild);
/* Call registered overlay reset functions */ onResetRegistry.forEach(function(func)
{ func(); }); /* Rebuild the data */ loadTab(args); function onUnloadPageInfo() // Remove the
observer, only if there is at least 1 image. if (!document.getElementById("mediaTab").hidden)
{ Components.classes["@mozilla.org/observer-service;1"] .getService(Components.interfaces.nsIObserverService)
.removeObserver(imagePermissionObserver, "perm-changed"); /* Call registered overlay unload functions
*/ onUnloadRegistry.forEach(function(func) { func(); }); function doHelpButton() const
helpTopics = { "generalPanel": "pageinfo_general", "mediaPanel": "pageinfo_media", "feedPanel":
"pageinfo_feed", "permPanel": "pageinfo_permissions", "securityPanel": "pageinfo_security" }; var
deck = document.getElementById("mainDeck"); var helpdoc = helpTopics[deck.selectedPanel.id]
|| "pageinfo_general"; openHelpLink(helpdoc); function showTab(id) var deck = document.getElementById("mainDeck");
var pagel = document.getElementById(id + "Panel"); deck.selectedPanel = pagel; function loadTab(args)
if (args && args.doc) { gDocument = args.doc; gWindow = gDocument.defaultView; gImageElement
= args && args.imageElement; /* Load the page info */ loadPageInfo(); var initialTab
= (args && args.initialTab) || "generalTab"; var radioGroup = document.getElementById("viewGroup");
initialTab = document.getElementById(initialTab) || document.getElementById("generalTab");
radioGroup.selectedItem = initialTab; radioGroup.selectedItem.doCommand(); radioGroup.focus(); function onClickMore()
var radioGrp = document.getElementById("viewGroup"); var radioElt = document.getElementById("securityTab");
radioGrp.selectedItem = radioElt; showTab('security'); function toggleGroupbox(id) var elt = document.getElementById(id);
if (elt.hasAttribute("closed")) { elt.removeAttribute("closed"); if (elt.flexWhenOpened) elt.flex = elt.flexWhenOpened;
else { elt.setAttribute("closed", "true"); if (elt.flex) { elt.flexWhenOpened = elt.flex;
elt.flex = 0; } function makeGeneralTab() var title = (gDocument.title) ? gBundle.getFormattedString("pageTitle",
[gDocument.title]) : gBundle.getString("noPageTitle"); document.getElementById("titletext").value
= title; var url = gDocument.location.toString(); setItemValue("urltext", url); var referrer
= ("referrer" in gDocument && gDocument.referrer); setItemValue("refertext", referrer); var mode
= ("compatMode" in gDocument && gDocument.compatMode == "BackCompat") ? "generalQuirksMode" :
"generalStrictMode"; document.getElementById("modetext").value = gBundle.getString(mode); // find out the
mime type var mimeType = gDocument.contentType; setItemValue("typetext", mimeType); // get
the document characterset var encoding = gDocument.characterSet; document.getElementById("encodingtext").value
= encoding; // get the meta tags var metaNodes = gDocument.getElementsByTagName("meta");
var length = metaNodes.length; var metaGroup = document.getElementById("metaTags"); if
(!length) metaGroup.collapsed = true; else { var metaTagsCaption = document.getElementById("metaTagsCaption");
if (length == 1) metaTagsCaption.label = gBundle.getString("generalMetaTag"); else
metaTagsCaption.label = gBundle.getFormattedString("generalMetaTags", [length]); var metaTree = document.getElementById("metatree");
metaTree.treeBoxObject.view = gMetaView; for (var i = 0; i < length; i++) gMetaView.addRow([metaNodes[i].name
|| metaNodes[i].httpEquiv, metaNodes[i].content]); metaGroup.collapsed = false; // get the date
of last modification var modifiedText = formatDate(gDocument.lastModified, gStrings.notSet); document.getElementById("modifiedtext").value
= modifiedText; // get cache info var cacheKey = url.replace(/#.*$/, ""); try { var cacheEntryDescriptor
= httpCacheSession.openCacheEntry(cacheKey, ACCESS_READ, false); catch(ex) { try { cacheEntryDescriptor
= ftpCacheSession.openCacheEntry(cacheKey, ACCESS_READ, false); } catch(ex2) { } var
sizeText; if (cacheEntryDescriptor) { var pageSize = cacheEntryDescriptor.dataSize;
var kbSize = formatNumber(Math.round(pageSize / 1024 * 100) / 100); sizeText = gBundle.getFormattedString("generalSize",
[kbSize, formatNumber(pageSize)]); setItemValue("sizetext", sizeText); securityOnLoad(); //******** Generic
Build-a-tab // Assumes the views are empty. Only called once to build the tabs, and //
does so by farming the task off to another thread via setTimeout(). // The actual work
is done with a TreeWalker that calls doGrab() once for // each element node in the document.
var gFrameList = [ ]; function makeTabs(aDocument, aWindow) goThroughFrames(aDocument, aWindow);
processFrames(); function goThroughFrames(aDocument, aWindow) gFrameList.push(aDocument); if (aWindow
&& aWindow.frames.length > 0) { var num = aWindow.frames.length; for (var i = 0; i
< num; i++) goThroughFrames(aWindow.frames[i].document, aWindow.frames[i]); // recurse through the
frames function processFrames() if (gFrameList.length) { var doc = gFrameList[0]; onProcessFrame.forEach(function(func)
{ func(doc); }); var iterator = doc.createTreeWalker(doc, NodeFilter.SHOW_ELEMENT, grabAll, true); gFrameList.shift();
setTimeout(doGrab, 16, iterator); onFinished.push(selectImage); else onFinished.forEach(function(func) {
func(); }); function doGrab(iterator) for (var i = 0; i < 50; ++i) if (!iterator.nextNode())
{ processFrames(); return; } setTimeout(doGrab, 16, iterator); function addImage(url, type,
alt, elem, isBg) if (!url) return; if (!gImageHash.hasOwnProperty(url)) gImageHash[url] = { }; if (!gImageHash[url].hasOwnProperty(type))
gImageHash[url][type] = { }; if (!gImageHash[url][type].hasOwnProperty(alt)) { gImageHash[url][type][alt] = gImageView.data.length;
try { // open for READ, in non-blocking mode var cacheEntryDescriptor = httpCacheSession.openCacheEntry(url,
ACCESS_READ, false); } catch(ex) { try { // open for READ, in non-blocking mode cacheEntryDescriptor
= ftpCacheSession.openCacheEntry(url, ACCESS_READ, false); } catch(ex2) { } } var sizeText; if
(cacheEntryDescriptor) { var pageSize = cacheEntryDescriptor.dataSize; var kbSize = formatNumber(Math.round(pageSize
/ 1024 * 100) / 100); sizeText = gBundle.getFormattedString("mediaFileSize", [kbSize]); } else sizeText = gStrings.unknown;
gImageView.addRow([url, type, sizeText, alt, 1, elem, isBg]); // Add the observer, only
once. if (gImageView.data.length == 1) { document.getElementById("mediaTab").hidden
= false; Components.classes["@mozilla.org/observer-service;1"] .getService(Components.interfaces.nsIObserverService)
.addObserver(imagePermissionObserver, "perm-changed", false); } else { var i = gImageHash[url][type][alt];
gImageView.data[i][COL_IMAGE_COUNT]++; if (elem == gImageElement) gImageView.data[i][COL_IMAGE_NODE]
= elem; function grabAll(elem) // check for background images, any node may have multiple
var computedStyle = elem.ownerDocument.defaultView.getComputedStyle(elem, ""); if (computedStyle) { Array.forEach(computedStyle.getPropertyCSSValue("background-image"),
function (url) { if (url.primitiveType == CSSPrimitiveValue.CSS_URI) addImage(url.getStringValue(),
gStrings.mediaBGImg, gStrings.notSet, elem, true); }); // one swi^H^H^Hif-else to rule
them all if (elem instanceof HTMLImageElement) addImage(elem.src, gStrings.mediaImg, (elem.hasAttribute("alt"))
? elem.alt : gStrings.notSet, elem, false); //@line 616 "e:\builds\moz2_slave\win32_build\build\browser\base\content\pageinfo\pageInfo.js"
else if (elem instanceof SVGImageElement) { try { // Note: makeURLAbsolute will throw
if either the baseURI is not a valid URI // or the URI formed from the baseURI and
the URL is not a valid URI var href = makeURLAbsolute(elem.baseURI, elem.href.baseVal); addImage(href, gStrings.mediaImg,
"", elem, false); } catch (e) { } //@line 625 "e:\builds\moz2_slave\win32_build\build\browser\base\content\pageinfo\pageInfo.js"
else if (elem instanceof HTMLLinkElement) { if (elem.rel && /\bicon\b/i.test(elem.rel))
addImage(elem.href, gStrings.mediaLink, "", elem, false); else if (elem instanceof HTMLInputElement
|| elem instanceof HTMLButtonElement) { if (elem.type.toLowerCase() == "image") addImage(elem.src,
gStrings.mediaInput, (elem.hasAttribute("alt")) ? elem.alt : gStrings.notSet, elem, false);
else if (elem instanceof HTMLObjectElement) addImage(elem.data, gStrings.mediaObject,
getValueText(elem), elem, false); else if (elem instanceof HTMLEmbedElement) addImage(elem.src,
gStrings.mediaEmbed, "", elem, false); onProcessElement.forEach(function(func) { func(elem); }); return NodeFilter.FILTER_ACCEPT;
//******** Link Stuff function openURL(target) var url = target.parentNode.childNodes[2].value;
window.open(url, "_blank", "chrome"); function onBeginLinkDrag(event,urlField,descField)
if (event.originalTarget.localName != "treechildren") return; var tree = event.target; if (!("treeBoxObject"
in tree)) tree = tree.parentNode; var row = tree.treeBoxObject.getRowAt(event.clientX,
event.clientY); if (row == -1) return; // Adding URL flavor var col = tree.columns[urlField];
var url = tree.view.getCellText(row, col); col = tree.columns[descField]; var desc =
tree.view.getCellText(row, col); var dt = event.dataTransfer; dt.setData("text/x-moz-url",
url + "\n" + desc); dt.setData("text/url-list", url); dt.setData("text/plain", url); //********
Image Stuff function getSelectedImage(tree) if (!gImageView.rowCount) return null; //
Only works if only one item is selected var clickedRow = tree.currentIndex; // image-node
return gImageView.data[clickedRow][COL_IMAGE_NODE]; function selectSaveFolder() const nsILocalFile
= Components.interfaces.nsILocalFile; const nsIFilePicker = Components.interfaces.nsIFilePicker;
var fp = Components.classes["@mozilla.org/filepicker;1"] .createInstance(nsIFilePicker); var titleText
= gBundle.getString("mediaSelectFolder"); fp.init(window, titleText, nsIFilePicker.modeGetFolder);
try { var prefs = Components.classes[PREFERENCES_CONTRACTID] .getService(Components.interfaces.nsIPrefBranch2);
var initialDir = prefs.getComplexValue("browser.download.dir", nsILocalFile); if (initialDir) fp.displayDirectory
= initialDir; catch (ex) { } fp.appendFilters(nsIFilePicker.filterAll); var ret = fp.show(); if (ret == nsIFilePicker.returnOK)
return fp.file.QueryInterface(nsILocalFile); return null; function saveMedia() var tree
= document.getElementById("imagetree"); var count = tree.view.selection.count; if (count
== 1) { var item = getSelectedImage(tree); var url = gImageView.data[tree.currentIndex][COL_IMAGE_ADDRESS];
if (url) saveURL(url, null, "SaveImageTitle", false, false, makeURI(item.baseURI)); else
{ var odir = selectSaveFolder(); var start = { }; var end = { }; var numRanges = tree.view.selection.getRangeCount();
var rowArray = [ ]; for (var t = 0; t < numRanges; t++) { tree.view.selection.getRangeAt(t, start,
end); for (var v = start.value; v 1) { splitter.collapsed = true; previewBox.collapsed
= true; mediaSaveBox.collapsed = false; tree.flex = 1; else { mediaSaveBox.collapsed = true;
splitter.collapsed = false; previewBox.collapsed = false; tree.flex = 0; makePreview(tree.view.selection.currentIndex);
function makePreview(row) var imageTree = document.getElementById("imagetree"); var
item = getSelectedImage(imageTree); var url = gImageView.data[row][COL_IMAGE_ADDRESS];
var isBG = gImageView.data[row][COL_IMAGE_BG]; setItemValue("imageurltext", url); var imageText;
if (!isBG && //@line 822 "e:\builds\moz2_slave\win32_build\build\browser\base\content\pageinfo\pageInfo.js" !(item instanceof SVGImageElement) && //@line
824 "e:\builds\moz2_slave\win32_build\build\browser\base\content\pageinfo\pageInfo.js" !(gDocument instanceof ImageDocument)) {
imageText = item.title || item.alt; if (!imageText && !(item instanceof HTMLImageElement)) imageText
= getValueText(item); setItemValue("imagetext", imageText); setItemValue("imagelongdesctext",
item.longDesc); // get cache info var cacheKey = url.replace(/#.*$/, ""); try { // open
for READ, in non-blocking mode var cacheEntryDescriptor = httpCacheSession.openCacheEntry(cacheKey,
ACCESS_READ, false); catch(ex) { try { // open for READ, in non-blocking mode cacheEntryDescriptor
= ftpCacheSession.openCacheEntry(cacheKey, ACCESS_READ, false); } catch(ex2) { } //
find out the file size var sizeText; if (cacheEntryDescriptor) { var imageSize = cacheEntryDescriptor.dataSize;
var kbSize = Math.round(imageSize / 1024 * 100) / 100; sizeText = gBundle.getFormattedString("generalSize",
[formatNumber(kbSize), formatNumber(imageSize)]); else sizeText = gBundle.getString("mediaUnknownNotCached");
setItemValue("imagesizetext", sizeText); var mimeType; var numFrames = 1; if (item instanceof
HTMLObjectElement || item instanceof HTMLEmbedElement || item instanceof HTMLLinkElement) mimeType
= item.type; if (!mimeType && !isBG && item instanceof nsIImageLoadingContent) { var imageRequest
= item.getRequest(nsIImageLoadingContent.CURRENT_REQUEST); if (imageRequest) { mimeType = imageRequest.mimeType;
var image = imageRequest.image; if (image) numFrames = image.numFrames; } if (!mimeType)
mimeType = getContentTypeFromHeaders(cacheEntryDescriptor); var imageType; if (mimeType) { // We found
the type, try to display it nicely var imageMimeType = /^image\/(.*)/.exec(mimeType); if (imageMimeType)
{ imageType = imageMimeType[1].toUpperCase(); if (numFrames > 1) imageType = gBundle.getFormattedString("mediaAnimatedImageType",
[imageType, numFrames]); else imageType = gBundle.getFormattedString("mediaImageType",
[imageType]); } else { // the MIME type doesn't begin with image/, display the raw type imageType
= mimeType; } else { // We couldn't find the type, fall back to the value in the treeview
imageType = gImageView.data[row][COL_IMAGE_TYPE]; setItemValue("imagetypetext", imageType);
var imageContainer = document.getElementById("theimagecontainer"); var oldImage = document.getElementById("thepreviewimage");
const regex = /^(https?|ftp|file|gopher|about|chrome|resource):/; var isProtocolAllowed = regex.test(url); if
(/^data:/.test(url) && /^image\//.test(mimeType)) isProtocolAllowed = true; var newImage =
new Image(); newImage.setAttribute("id", "thepreviewimage"); var physWidth = 0, physHeight = 0; var width
= 0, height = 0; if ((item instanceof HTMLLinkElement || item instanceof HTMLInputElement || item
instanceof HTMLImageElement || //@line 918 "e:\builds\moz2_slave\win32_build\build\browser\base\content\pageinfo\pageInfo.js"
item instanceof SVGImageElement || //@line 920 "e:\builds\moz2_slave\win32_build\build\browser\base\content\pageinfo\pageInfo.js"
(item instanceof HTMLObjectElement && /^image\//.test(mimeType)) || isBG) && isProtocolAllowed) { newImage.setAttribute("src",
url); physWidth = newImage.width || 0; physHeight = newImage.height || 0; // "width" and "height"
attributes must be set to newImage, // even if there is no "width" or "height attribute
in item; // otherwise, the preview image cannot be displayed correctly. if (!isBG) { newImage.width
= ("width" in item && item.width) || newImage.naturalWidth; newImage.height = ("height" in item && item.height)
|| newImage.naturalHeight; } else { // the Width and Height of an HTML tag should not
be used for its background image // (for example, "table" can have "width" or "height" attributes)
newImage.width = newImage.naturalWidth; newImage.height = newImage.naturalHeight; } //@line 940 "e:\builds\moz2_slave\win32_build\build\browser\base\content\pageinfo\pageInfo.js"
if (item instanceof SVGImageElement) { newImage.width = item.width.baseVal.value; newImage.height
= item.height.baseVal.value; } //@line 945 "e:\builds\moz2_slave\win32_build\build\browser\base\content\pageinfo\pageInfo.js"
width = newImage.width; height = newImage.height; document.getElementById("theimagecontainer").collapsed
= false document.getElementById("brokenimagecontainer").collapsed = true; else { // fallback image for protocols
not allowed (e.g., data: or javascript:) // or elements not [yet] handled (e.g., object,
embed). document.getElementById("brokenimagecontainer").collapsed = false; document.getElementById("theimagecontainer").collapsed
= true; var imageSize = ""; if (url) { if (width != physWidth || height != physHeight)
{ imageSize = gBundle.getFormattedString("mediaDimensionsScaled", [formatNumber(physWidth), formatNumber(physHeight),
formatNumber(width), formatNumber(height)]); } else { imageSize = gBundle.getFormattedString("mediaDimensions",
[formatNumber(width), formatNumber(height)]); } setItemValue("imagedimensiontext", imageSize);
makeBlockImage(url); imageContainer.removeChild(oldImage); imageContainer.appendChild(newImage); function
makeBlockImage(url) var permissionManager = Components.classes[PERMISSION_CONTRACTID]
.getService(nsIPermissionManager); var prefs = Components.classes[PREFERENCES_CONTRACTID]
.getService(Components.interfaces.nsIPrefBranch2); var checkbox = document.getElementById("blockImage");
var imagePref = prefs.getIntPref("permissions.default.image"); if (!(/^https?:/.test(url)) || imagePref
== 2) // We can't block the images from this host because either is is not // for http(s)
or we don't load images at all checkbox.hidden = true; else { var uri = makeURI(url); if
(uri.host) { checkbox.hidden = false; checkbox.label = gBundle.getFormattedString("mediaBlockImage",
[uri.host]); var perm = permissionManager.testPermission(uri, "image"); checkbox.checked = perm == nsIPermissionManager.DENY_ACTION;
} else checkbox.hidden = true; var imagePermissionObserver = { observe: function (aSubject, aTopic,
aData) if (document.getElementById("mediaPreviewBox").collapsed) return; if (aTopic == "perm-changed") { var
permission = aSubject.QueryInterface(Components.interfaces.nsIPermission); if (permission.type == "image") { var imageTree
= document.getElementById("imagetree"); var row = imageTree.currentIndex; var item =
gImageView.data[row][COL_IMAGE_NODE]; var url = gImageView.data[row][COL_IMAGE_ADDRESS];
if (makeURI(url).host == permission.host) makeBlockImage(url); } } function getContentTypeFromHeaders(cacheEntryDescriptor)
if (!cacheEntryDescriptor) return null; return (/^Content-Type:\s*(.*?)\s*(?:\;|$)/mi .exec(cacheEntryDescriptor.getMetaDataElement("response-head")))[1];
//******** Other Misc Stuff // Modified from the Links Panel v2.3, http://segment7.net/mozilla/links/links.html
// parse a node to extract the contents of the node function getValueText(node) var valueText
= ""; // form input elements don't generally contain information that is useful to our
callers, so return nothing if (node instanceof HTMLInputElement || node instanceof HTMLSelectElement
|| node instanceof HTMLTextAreaElement) return valueText; // otherwise recurse for each child
var length = node.childNodes.length; for (var i = 0; i < length; i++) { var childNode =
node.childNodes[i]; var nodeType = childNode.nodeType; // text nodes are where the goods are if
(nodeType == Node.TEXT_NODE) valueText += " " + childNode.nodeValue; // and elements
can have more text inside them else if (nodeType == Node.ELEMENT_NODE) { // images are special,
we want to capture the alt text as if the image weren't there if (childNode instanceof
HTMLImageElement) valueText += " " + getAltText(childNode); else valueText += " " + getValueText(childNode);
} return stripWS(valueText); // Copied from the Links Panel v2.3, http://segment7.net/mozilla/links/links.html
// traverse the tree in search of an img or area element and grab its alt tag function
getAltText(node) var altText = ""; if (node.alt) return node.alt; var length = node.childNodes.length;
for (var i = 0; i < length; i++) if ((altText = getAltText(node.childNodes[i]) != undefined))
// stupid js warning... return altText; return ""; // Copied from the Links Panel v2.3,
http://segment7.net/mozilla/links/links.html // strip leading and trailing whitespace,
and replace multiple consecutive whitespace characters with a single space function stripWS(text)
var middleRE = /\s+/g; var endRE = /(^\s+)|(\s+$)/g; text = text.replace(middleRE, " "); return
text.replace(endRE, ""); function setItemValue(id, value) var item = document.getElementById(id);
if (value) { item.parentNode.collapsed = false; item.value = value; else item.parentNode.collapsed
= true; function formatNumber(number) return (+number).toLocaleString(); // coerce number
to a numeric value before calling toLocaleString() function formatDate(datestr, unknown) //
scriptable date formatter, for pretty printing dates var dateService = Components.classes["@mozilla.org/intl/scriptabledateformat;1"]
.getService(Components.interfaces.nsIScriptableDateFormat); var date = new Date(datestr); if (!date.valueOf())
return unknown; return dateService.FormatDateTime("", dateService.dateFormatLong, dateService.timeFormatSeconds,
date.getFullYear(), date.getMonth()+1, date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds());
function doCopy() if (!gClipboardHelper) return; var elem = document.commandDispatcher.focusedElement;
if (elem && "treeBoxObject" in elem) { var view = elem.view; var selection = view.selection;
var text = [], tmp = ''; var min = {}, max = {}; var count = selection.getRangeCount();
for (var i = 0; i < count; i++) { selection.getRangeAt(i, min, max); for (var row = min.value; row
radio { -moz-binding: url("chrome://mozapps/content/extensions/extensions.xml#viewbutton");
richlistitem[feed] { -moz-binding: url("chrome://browser/content/pageinfo/feeds.xml#feed"); richlistitem[feed]:not([selected="true"])
.feed-subscribe { display: none; groupbox[closed="true"] > .groupbox-body { visibility: collapse;
/* This following entry can be removed when Bug 522850 is fixed. */ #thepreviewimage
{ min-width: 1px; content/browser/pageinfo/feeds.js//@line 38 "e:\builds\moz2_slave\win32_build\build\browser\base\content\pageinfo\feeds.js"
function initFeedTab() const feedTypes = { "application/rss+xml": gBundle.getString("feedRss"),
"application/atom+xml": gBundle.getString("feedAtom"), "text/xml": gBundle.getString("feedXML"),
"application/xml": gBundle.getString("feedXML"), "application/rdf+xml": gBundle.getString("feedXML")
}; // get the feeds var linkNodes = gDocument.getElementsByTagName("link"); var length = linkNodes.length; for (var i
= 0; i < length; i++) { var link = linkNodes[i]; if (!link.href) continue; var rel = link.rel
&& link.rel.toLowerCase(); var rels = {}; if (rel) { for each (let relVal in rel.split(/\s+/))
rels[relVal] = true; } if (rels.feed || (link.type && rels.alternate && !rels.stylesheet))
{ var type = isValidFeed(link, gDocument.nodePrincipal, rels.feed); if (type) { type = feedTypes[type]
|| feedTypes["application/rss+xml"]; addRow(link.title, type, link.href); } } var feedListbox = document.getElementById("feedListbox");
document.getElementById("feedTab").hidden = feedListbox.getRowCount() == 0; function
onSubscribeFeed() var listbox = document.getElementById("feedListbox"); openUILink(listbox.selectedItem.getAttribute("feedURL"),
null, false, true, false, null); function addRow(name, type, url) var item = document.createElement("richlistitem");
item.setAttribute("feed", "true"); item.setAttribute("name", name); item.setAttribute("type", type); item.setAttribute("feedURL",
url); document.getElementById("feedListbox").appendChild(item); content/browser/pageinfo/feeds.xml
content/browser/pageinfo/permissions.js//@line
36 "e:\builds\moz2_slave\win32_build\build\browser\base\content\pageinfo\permissions.js" const ALLOW = nsIPermissionManager.ALLOW_ACTION;
// 1 const BLOCK = nsIPermissionManager.DENY_ACTION; // 2 const SESSION = nsICookiePermission.ACCESS_SESSION;//
8 var gPermURI; var gPrefs; var gPermObj = { image: function getImageDefaultPermission()
if (gPrefs.getIntPref("permissions.default.image") == 2) return BLOCK; return ALLOW; }, cookie:
function getCookieDefaultPermission() if (gPrefs.getIntPref("network.cookie.cookieBehavior") == 2) return BLOCK; if (gPrefs.getIntPref("network.cookie.lifetimePolicy")
== 2) return SESSION; return ALLOW; }, popup: function getPopupDefaultPermission() if (gPrefs.getBoolPref("dom.disable_open_during_load"))
return BLOCK; return ALLOW; }, install: function getInstallDefaultPermission() if (gPrefs.getBoolPref("xpinstall.whitelist.required"))
return BLOCK; return ALLOW; }, geo: function getGeoDefaultPermissions() return BLOCK; var
permissionObserver = { observe: function (aSubject, aTopic, aData) if (aTopic == "perm-changed")
{ var permission = aSubject.QueryInterface(Components.interfaces.nsIPermission); if (permission.host == gPermURI.host && permission.type
in gPermObj) initRow(permission.type); } function onLoadPermission() gPrefs = Components.classes[PREFERENCES_CONTRACTID]
.getService(Components.interfaces.nsIPrefBranch2); var uri = gDocument.documentURIObject; var
permTab = document.getElementById("permTab"); if(/^https?/.test(uri.scheme)) { gPermURI
= uri; var hostText = document.getElementById("hostText"); hostText.value = gPermURI.host; for (var i
in gPermObj) initRow(i); var os = Components.classes["@mozilla.org/observer-service;1"] .getService(Components.interfaces.nsIObserverService);
os.addObserver(permissionObserver, "perm-changed", false); onUnloadRegistry.push(onUnloadPermission);
permTab.hidden = false; else permTab.hidden = true; function onUnloadPermission() var
os = Components.classes["@mozilla.org/observer-service;1"] .getService(Components.interfaces.nsIObserverService);
os.removeObserver(permissionObserver, "perm-changed"); function initRow(aPartId) var permissionManager
= Components.classes[PERMISSION_CONTRACTID] .getService(nsIPermissionManager); var checkbox
= document.getElementById(aPartId + "Def"); var command = document.getElementById("cmd_"
+ aPartId + "Toggle"); var perm = permissionManager.testPermission(gPermURI, aPartId); if (perm) { checkbox.checked =
false; command.removeAttribute("disabled"); else { checkbox.checked = true; command.setAttribute("disabled",
"true"); perm = gPermObj[aPartId](); setRadioState(aPartId, perm); function onCheckboxClick(aPartId) var
permissionManager = Components.classes[PERMISSION_CONTRACTID] .getService(nsIPermissionManager); var command
= document.getElementById("cmd_" + aPartId + "Toggle"); var checkbox = document.getElementById(aPartId
+ "Def"); if (checkbox.checked) { permissionManager.remove(gPermURI.host, aPartId); command.setAttribute("disabled",
"true"); var perm = gPermObj[aPartId](); setRadioState(aPartId, perm); else { onRadioClick(aPartId); command.removeAttribute("disabled");
function onRadioClick(aPartId) var permissionManager = Components.classes[PERMISSION_CONTRACTID]
.getService(nsIPermissionManager); var radioGroup = document.getElementById(aPartId + "RadioGroup");
var id = radioGroup.selectedItem.id; var permission = id.split('#')[1]; permissionManager.add(gPermURI,
aPartId, permission); function setRadioState(aPartId, aValue) var radio = document.getElementById(aPartId
+ "#" + aValue); radio.radioGroup.selectedItem = radio; content/browser/pageinfo/security.js//@line
40 "e:\builds\moz2_slave\win32_build\build\browser\base\content\pageinfo\security.js" var security = { // Display the server certificate
(static) viewCert : function () { var cert = security._cert; viewCertHelper(window,
cert); }, _getSecurityInfo : function() { const nsIX509Cert = Components.interfaces.nsIX509Cert;
const nsIX509CertDB = Components.interfaces.nsIX509CertDB; const nsX509CertDB = "@mozilla.org/security/x509certdb;1";
const nsISSLStatusProvider = Components.interfaces.nsISSLStatusProvider; const nsISSLStatus = Components.interfaces.nsISSLStatus;
// We don't have separate info for a frame, return null until further notice // (see bug
138479) if (gWindow != gWindow.top) return null; var hName = null; try { hName = gWindow.location.host;
} catch (exception) { } var ui = security._getSecurityUI(); if (!ui) return null; var isBroken = (ui.state
& Components.interfaces.nsIWebProgressListener.STATE_IS_BROKEN); var isInsecure = (ui.state & Components.interfaces.nsIWebProgressListener.STATE_IS_INSECURE);
var isEV = (ui.state & Components.interfaces.nsIWebProgressListener.STATE_IDENTITY_EV_TOPLEVEL); ui.QueryInterface(nsISSLStatusProvider); var
status = ui.SSLStatus; if (!isInsecure && status) { status.QueryInterface(nsISSLStatus);
var cert = status.serverCert; var issuerName = this.mapIssuerOrganization(cert.issuerOrganization)
|| cert.issuerName; var retval = { hostName : hName, cAName : issuerName, encryptionAlgorithm
: undefined, encryptionStrength : undefined, isBroken : isBroken, isEV : isEV, cert :
cert, fullLocation : gWindow.location }; try { retval.encryptionAlgorithm = status.cipherName;
retval.encryptionStrength = status.secretKeyLength; } catch (e) { } return retval; } else {
return { hostName : hName, cAName : "", encryptionAlgorithm : "", encryptionStrength : 0, isBroken :
isBroken, isEV : isEV, cert : null, fullLocation : gWindow.location }; } }, // Find the secureBrowserUI
object (if present) _getSecurityUI : function() { if (window.opener.gBrowser) return window.opener.gBrowser.securityUI;
return null; }, // Interface for mapping a certificate issuer organization to // the
value to be displayed. // Bug 82017 - this implementation should be moved to pipnss C++
code mapIssuerOrganization: function(name) { if (!name) return null; if (name == "RSA
Data Security, Inc.") return "Verisign, Inc."; // No mapping required return name; }, /**
* Open the cookie manager window */ viewCookies : function() var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator); var win = wm.getMostRecentWindow("Browser:Cookies");
var eTLDService = Components.classes["@mozilla.org/network/effective-tld-service;1"]. getService(Components.interfaces.nsIEffectiveTLDService);
var eTLD; var uri = gDocument.documentURIObject; try { eTLD = eTLDService.getBaseDomain(uri);
} catch (e) { // getBaseDomain will fail if the host is an IP address or is empty eTLD
= uri.asciiHost; } if (win) { win.gCookiesWindow.setFilter(eTLD); win.focus(); } else window.openDialog("chrome://browser/content/preferences/cookies.xul",
"Browser:Cookies", "", {filterString : eTLD}); }, /** * Open the login manager window */
viewPasswords : function() var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] .getService(Components.interfaces.nsIWindowMediator);
var win = wm.getMostRecentWindow("Toolkit:PasswordManager"); if (win) { win.setFilter(this._getSecurityInfo().hostName);
win.focus(); } else window.openDialog("chrome://passwordmgr/content/passwordManager.xul", "Toolkit:PasswordManager", "", {filterString
: this._getSecurityInfo().hostName}); }, _cert : null function securityOnLoad() {
var info = security._getSecurityInfo(); if (!info) { document.getElementById("securityTab").hidden
= true; document.getElementById("securityBox").collapsed = true; return; else { document.getElementById("securityTab").hidden
= false; document.getElementById("securityBox").collapsed = false; const pageInfoBundle = document.getElementById("pageinfobundle");
/* Set Identity section text */ setText("security-identity-domain-value", info.hostName); var owner, verifier, generalPageIdentityString;
if (info.cert && !info.isBroken) { // Try to pull out meaningful values. Technically
these fields are optional // so we'll employ fallbacks where appropriate. The EV spec states
that Org // fields must be specified for subject and issuer so that case is simpler. if (info.isEV)
{ owner = info.cert.organization; verifier = security.mapIssuerOrganization(info.cAName);
generalPageIdentityString = pageInfoBundle.getFormattedString("generalSiteIdentity", [owner, verifier]); } else { // Technically,
a non-EV cert might specify an owner in the O field or not, // depending on the CA's issuing
policies. However we don't have any programmatic // way to tell those apart, and no policy
way to establish which organization // vetting standards are good enough (that's what EV
is for) so we default to // treating these certs as domain-validated only. owner = pageInfoBundle.getString("securityNoOwner");
verifier = security.mapIssuerOrganization(info.cAName || info.cert.issuerCommonName || info.cert.issuerName);
generalPageIdentityString = owner; } else { // We don't have valid identity credentials.
owner = pageInfoBundle.getString("securityNoOwner"); verifier = pageInfoBundle.getString("notset");
generalPageIdentityString = owner; setText("security-identity-owner-value", owner); setText("security-identity-verifier-value",
verifier); setText("general-security-identity", generalPageIdentityString); /* Manage the
View Cert button*/ var viewCert = document.getElementById("security-view-cert"); if (info.cert) { security._cert = info.cert;
viewCert.collapsed = false; else viewCert.collapsed = true; /* Set Privacy & History section
text */ var yesStr = pageInfoBundle.getString("yes"); var noStr = pageInfoBundle.getString("no");
var uri = gDocument.documentURIObject; setText("security-privacy-cookies-value", hostHasCookies(uri) ? yesStr : noStr); setText("security-privacy-passwords-value",
realmHasPasswords(uri) ? yesStr : noStr); var visitCount = previousVisitCount(info.hostName);
if(visitCount > 1) { setText("security-privacy-history-value", pageInfoBundle.getFormattedString("securityNVisits",
[visitCount.toLocaleString()])); else if (visitCount == 1) { setText("security-privacy-history-value",
pageInfoBundle.getString("securityOneVisit")); else { setText("security-privacy-history-value",
noStr); /* Set the Technical Detail section messages */ const pkiBundle = document.getElementById("pkiBundle");
var hdr; var msg1; var msg2; if (info.isBroken) { hdr = pkiBundle.getString("pageInfo_MixedContent");
msg1 = pkiBundle.getString("pageInfo_Privacy_Mixed1"); msg2 = pkiBundle.getString("pageInfo_Privacy_None2");
else if (info.encryptionStrength >= 90) { hdr = pkiBundle.getFormattedString("pageInfo_StrongEncryption",
[info.encryptionAlgorithm, info.encryptionStrength + ""]); msg1 = pkiBundle.getString("pageInfo_Privacy_Strong1");
msg2 = pkiBundle.getString("pageInfo_Privacy_Strong2"); security._cert = info.cert; else if (info.encryptionStrength
> 0) { hdr = pkiBundle.getFormattedString("pageInfo_WeakEncryption", [info.encryptionAlgorithm, info.encryptionStrength
+ ""]); msg1 = pkiBundle.getFormattedString("pageInfo_Privacy_Weak1", [info.hostName]); msg2 = pkiBundle.getString("pageInfo_Privacy_Weak2");
else { hdr = pkiBundle.getString("pageInfo_NoEncryption"); if (info.hostName != null) msg1 = pkiBundle.getFormattedString("pageInfo_Privacy_None1",
[info.hostName]); else msg1 = pkiBundle.getString("pageInfo_Privacy_None3"); msg2 = pkiBundle.getString("pageInfo_Privacy_None2");
setText("security-technical-shortform", hdr); setText("security-technical-longform1", msg1);
setText("security-technical-longform2", msg2); setText("general-security-privacy", hdr);
function setText(id, value) var element = document.getElementById(id); if (!element)
return; if (element.localName == "textbox" || element.localName == "label") element.value
= value; else { if (element.hasChildNodes()) element.removeChild(element.firstChild); var
textNode = document.createTextNode(value); element.appendChild(textNode); function viewCertHelper(parent,
cert) if (!cert) return; var cd = Components.classes[CERTIFICATEDIALOGS_CONTRACTID].getService(nsICertificateDialogs); cd.viewCert(parent, cert); * Return true iff
we have cookies for uri function hostHasCookies(uri) { var cookieManager = Components.classes["@mozilla.org/cookiemanager;1"]
.getService(Components.interfaces.nsICookieManager2); return cookieManager.countCookiesFromHost(uri.asciiHost)
> 0; * Return true iff realm (proto://host:port) (extracted from uri) has * saved passwords
function realmHasPasswords(uri) { var passwordManager = Components.classes["@mozilla.org/login-manager;1"]
.getService(Components.interfaces.nsILoginManager); return passwordManager.countLogins(uri.prePath,
"", "") > 0; * Return the number of previous visits recorded for host before today. *
@param host - the domain name to look for in history function previousVisitCount(host,
endTimeReference) { if (!host) return false; var historyService = Components.classes["@mozilla.org/browser/nav-history-service;1"]
.getService(Components.interfaces.nsINavHistoryService); var options = historyService.getNewQueryOptions();
options.resultType = options.RESULTS_AS_VISIT; // Search for visits to this host before
today var query = historyService.getNewQuery(); query.endTimeReference = query.TIME_RELATIVE_TODAY;
query.endTime = 0; query.domain = host; var result = historyService.executeQuery(query,
options); result.root.containerOpen = true; return result.root.childCount; ~t]q content/browser/openLocation.js//@line
41 "e:\builds\moz2_slave\win32_build\build\browser\base\content\openLocation.js" var browser; var dialog = {}; var pref =
null; try { pref = Components.classes["@mozilla.org/preferences-service;1"] .getService(Components.interfaces.nsIPrefBranch);
} catch (ex) { // not critical, remain silent Components.utils.import("resource:///modules/openLocationLastURL.jsm");
function onLoad() dialog.input = document.getElementById("dialog.input"); dialog.open = document.documentElement.getButton("accept");
dialog.openWhereList = document.getElementById("openWhereList"); dialog.openTopWindow = document.getElementById("currentWindow");
dialog.bundle = document.getElementById("openLocationBundle"); if ("arguments" in window && window.arguments.length
>= 1) browser = window.arguments[0]; dialog.openWhereList.selectedItem = dialog.openTopWindow; if (pref) { try
{ var useAutoFill = pref.getBoolPref("browser.urlbar.autoFill"); if (useAutoFill) dialog.input.setAttribute("completedefaultindex",
"true"); } catch (ex) {} try { var value = pref.getIntPref("general.open_location.last_window_choice");
var element = dialog.openWhereList.getElementsByAttribute("value", value)[0]; if (element) dialog.openWhereList.selectedItem
= element; dialog.input.value = gOpenLocationLastURL.value; } catch(ex) { } if (dialog.input.value) dialog.input.select();
// *** should probably be done automatically doEnabling(); function doEnabling() dialog.open.disabled
= !dialog.input.value; function open() var url; var postData = {}; if (browser) url
= browser.getShortcutOrURI(dialog.input.value, postData); else url = dialog.input.value;
try { // Whichever target we use for the load, we allow third-party services to // fixup
the URI switch (dialog.openWhereList.value) { case "0": browser.loadURI(url, null, postData.value,
true); break; case "1": window.opener.delayedOpenWindow(getBrowserURL(), "all,dialog=no", url, postData.value, null,
null, true); break; case "3": browser.delayedOpenTab(url, null, null, postData.value, true); break;
} catch(exception) { if (pref) { gOpenLocationLastURL.value = dialog.input.value; pref.setIntPref("general.open_location.last_window_choice",
dialog.openWhereList.value); // Delay closing slightly to avoid timing bug on Linux. window.close();
return false; function createInstance(contractid, iidName) var iid = Components.interfaces[iidName];
return Components.classes[contractid].createInstance(iid); const nsIFilePicker = Components.interfaces.nsIFilePicker;
function onChooseFile() try { var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker); fp.init(window, dialog.bundle.getString("chooseFileDialogTitle"),
nsIFilePicker.modeOpen); fp.appendFilters(nsIFilePicker.filterHTML | nsIFilePicker.filterText | nsIFilePicker.filterAll
| nsIFilePicker.filterImages | nsIFilePicker.filterXML); if (fp.show() == nsIFilePicker.returnOK &&
fp.fileURL.spec && fp.fileURL.spec.length > 0) dialog.input.value = fp.fileURL.spec;
catch(ex) { doEnabling(); content/browser/openLocation.xul
&enter.label;
content/browser/pageReportFirstTime.xul %pageReportFirstTimeDTD; ]> &startDescription.label;
&done.label;
&endDescription.label; content/browser/safeMode.js//@line
39 "e:\builds\moz2_slave\win32_build\build\browser\base\content\safeMode.js" function restartApp() { var appStartup =
Components.classes["@mozilla.org/toolkit/app-startup;1"] .getService(Components.interfaces.nsIAppStartup);
appStartup.quit(appStartup.eForceQuit | appStartup.eRestart); function clearAllPrefs() { var prefService
= Components.classes["@mozilla.org/preferences-service;1"] .getService(Components.interfaces.nsIPrefService);
prefService.resetUserPrefs(); // Remove the pref-overrides dir, if it exists try { var
fileLocator = Components.classes["@mozilla.org/file/directory_service;1"] .getService(Components.interfaces.nsIProperties);
const NS_APP_PREFS_OVERRIDE_DIR = "PrefDOverride"; var prefOverridesDir = fileLocator.get(NS_APP_PREFS_OVERRIDE_DIR,
Components.interfaces.nsIFile); prefOverridesDir.remove(true); } catch (ex) { Components.utils.reportError(ex);
function restoreDefaultBookmarks() { var prefBranch = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch); prefBranch.setBoolPref("browser.bookmarks.restore_default_bookmarks",
true); function deleteLocalstore() { const nsIDirectoryServiceContractID = "@mozilla.org/file/directory_service;1";
const nsIProperties = Components.interfaces.nsIProperties; var directoryService = Components.classes[nsIDirectoryServiceContractID]
.getService(nsIProperties); var localstoreFile = directoryService.get("LStoreS", Components.interfaces.nsIFile);
if (localstoreFile.exists()) localstoreFile.remove(false); function disableAddons() { // Disable addons
const nsIUpdateItem = Components.interfaces.nsIUpdateItem; var em = Components.classes["@mozilla.org/extensions/manager;1"]
.getService(Components.interfaces.nsIExtensionManager); var type = nsIUpdateItem.TYPE_EXTENSION +
nsIUpdateItem.TYPE_LOCALE; var items = em.getItemList(type, { }); for (var i = 0; i < items.length; ++i)
em.disableItem(items[i].id); // Select the default theme var prefB = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch); if (prefB.prefHasUserValue("general.skins.selectedSkin"))
prefB.clearUserPref("general.skins.selectedSkin"); // Disable plugins var phs = Components.classes["@mozilla.org/plugin/host;1"]
.getService(Components.interfaces.nsIPluginHost); var plugins = phs.getPluginTags({ }); for
(i = 0; i < plugins.length; ++i) plugins[i].disabled = true; function restoreDefaultSearchEngines()
{ var searchService = Components.classes["@mozilla.org/browser/search-service;1"] .getService(Components.interfaces.nsIBrowserSearchService);
searchService.restoreDefaultEngines(); function onOK() { try { if (document.getElementById("resetUserPrefs").checked)
clearAllPrefs(); if (document.getElementById("deleteBookmarks").checked) restoreDefaultBookmarks(); if (document.getElementById("resetToolbars").checked)
deleteLocalstore(); if (document.getElementById("disableAddons").checked) disableAddons(); if (document.getElementById("restoreSearch").checked)
restoreDefaultSearchEngines(); } catch(e) { restartApp(); function onCancel() { var
appStartup = Components.classes["@mozilla.org/toolkit/app-startup;1"] .getService(Components.interfaces.nsIAppStartup);
appStartup.quit(appStartup.eForceQuit); function onLoad() { document.getElementById("tasks")
.addEventListener("CheckboxStateChange", UpdateOKButtonState, false); function UpdateOKButtonState() {
document.documentElement.getButton("accept").disabled = !document.getElementById("resetUserPrefs").checked
&& !document.getElementById("deleteBookmarks").checked && !document.getElementById("resetToolbars").checked
&& !document.getElementById("disableAddons").checked && !document.getElementById("restoreSearch").checked;
content/browser/safeMode.xul %safeModeDTD; %browserDTD;
&safeModeDescription.label;
content/browser/sanitize.js//@line 41 "e:\builds\moz2_slave\win32_build\build\browser\base\content\sanitize.js"
function Sanitizer() {} Sanitizer.prototype = { // warning to the caller: this one may
raise an exception (e.g. bug #265028) clearItem: function (aItemName) if (this.items[aItemName].canClear)
this.items[aItemName].clear(); }, canClearItem: function (aItemName) return this.items[aItemName].canClear;
}, prefDomain: "", getNameFromPreference: function (aPreferenceName) return aPreferenceName.substr(this.prefDomain.length);
}, /** * Deletes privacy sensitive data in a batch, according to user preferences *
* @returns null if everything's fine; an object in the form * { itemName: error, ... } on
(partial) failure */ sanitize: function () var psvc = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefService); var branch = psvc.getBranch(this.prefDomain);
var errors = null; // Cache the range of times to clear if (this.ignoreTimespan) var range
= null; // If we ignore timespan, clear everything else range = this.range || Sanitizer.getClearRange();
for (var itemName in this.items) { var item = this.items[itemName]; item.range = range;
if ("clear" in item && item.canClear && branch.getBoolPref(itemName)) { // Some of these clear() may raise exceptions
(see bug #265028) // to sanitize as much as possible, we catch and store them, // rather
than fail fast. // Callers should check returned errors and give user feedback // about items
that could not be sanitized try { item.clear(); } catch(er) { if (!errors) errors = {};
errors[itemName] = er; dump("Error sanitizing " + itemName + ": " + er + "\n"); } } }
return errors; }, // Time span only makes sense in certain cases. Consumers who want
// to only clear some private data can opt in by setting this to false, // and can optionally
specify a specific range. If timespan is not ignored, // and range is not set, sanitize()
will use the value of the timespan // pref to determine a range ignoreTimespan : true,
range : null, items: { cache: { clear: function () { const Cc = Components.classes; const
Ci = Components.interfaces; var cacheService = Cc["@mozilla.org/network/cache-service;1"].
getService(Ci.nsICacheService); try { // Cache doesn't consult timespan, nor does it
have the // facility for timespan-based eviction. Wipe it. cacheService.evictEntries(Ci.nsICache.STORE_ANYWHERE);
} catch(er) {} }, get canClear() { return true; } }, cookies: { clear: function ()
{ const Ci = Components.interfaces; var cookieMgr = Components.classes["@mozilla.org/cookiemanager;1"]
.getService(Ci.nsICookieManager); if (this.range) { // Iterate through the cookies and delete
any created after our cutoff. var cookiesEnum = cookieMgr.enumerator; while (cookiesEnum.hasMoreElements())
{ var cookie = cookiesEnum.getNext().QueryInterface(Ci.nsICookie2); if (cookie.creationTime > this.range[0])
// This cookie was created after our cutoff, clear it cookieMgr.remove(cookie.host, cookie.name,
cookie.path, false); } } else { // Remove everything cookieMgr.removeAll(); } // clear
any network geolocation provider sessions var psvc = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefService); try { var branch = psvc.getBranch("geo.wifi.access_token.");
branch.deleteBranch(""); } catch (e) {} }, get canClear() { return true; } }, offlineApps:
{ clear: function () { const Cc = Components.classes; const Ci = Components.interfaces; var cacheService
= Cc["@mozilla.org/network/cache-service;1"]. getService(Ci.nsICacheService); try { //
Offline app data is "timeless", and doesn't respect // the setting of timespan, it always
clears everything cacheService.evictEntries(Ci.nsICache.STORE_OFFLINE); } catch(er) {} var storageManagerService
= Cc["@mozilla.org/dom/storagemanager;1"]. getService(Ci.nsIDOMStorageManager); storageManagerService.clearOfflineApps();
}, get canClear() { return true; } }, history: { clear: function () { var globalHistory
= Components.classes["@mozilla.org/browser/global-history;2"] .getService(Components.interfaces.nsIBrowserHistory);
if (this.range) globalHistory.removeVisitsByTimeframe(this.range[0], this.range[1]); else globalHistory.removeAllPages();
try { var os = Components.classes["@mozilla.org/observer-service;1"] .getService(Components.interfaces.nsIObserverService);
os.notifyObservers(null, "browser:purge-session-history", ""); } catch (e) { } // Clear last URL of
the Open Web Location dialog var prefs = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch2); try { prefs.clearUserPref("general.open_location.last_url");
} catch (e) { } }, get canClear() { // bug 347231: Always allow clearing history due
to dependencies on // the browser:purge-session-history notification. (like error console) return
true; } }, formdata: { clear: function () { // Clear undo history of all searchBars
var windowManager = Components.classes['@mozilla.org/appshell/window-mediator;1'] .getService(Components.interfaces.nsIWindowMediator);
var windows = windowManager.getEnumerator("navigator:browser"); while (windows.hasMoreElements()) { var searchBar
= windows.getNext().document.getElementById("searchbar"); if (searchBar) searchBar.textbox.reset();
} var formHistory = Components.classes["@mozilla.org/satchel/form-history;1"] .getService(Components.interfaces.nsIFormHistory2);
if (this.range) formHistory.removeEntriesByTimeframe(this.range[0], this.range[1]); else formHistory.removeAllEntries();
}, get canClear() { var windowManager = Components.classes['@mozilla.org/appshell/window-mediator;1']
.getService(Components.interfaces.nsIWindowMediator); var windows = windowManager.getEnumerator("navigator:browser");
while (windows.hasMoreElements()) { var searchBar = windows.getNext().document.getElementById("searchbar");
if (searchBar) { var transactionMgr = searchBar.textbox.editor.transactionManager; if (searchBar.value || transactionMgr.numberOfUndoItems
|| transactionMgr.numberOfRedoItems) return true; } } var formHistory = Components.classes["@mozilla.org/satchel/form-history;1"]
.getService(Components.interfaces.nsIFormHistory2); return formHistory.hasEntries; } }, downloads:
{ clear: function () { var dlMgr = Components.classes["@mozilla.org/download-manager;1"] .getService(Components.interfaces.nsIDownloadManager);
var dlIDsToRemove = []; if (this.range) { // First, remove the completed/cancelled
downloads dlMgr.removeDownloadsByTimeframe(this.range[0], this.range[1]); // Queue up any active downloads
that started in the time span as well var dlsEnum = dlMgr.activeDownloads; while(dlsEnum.hasMoreElements())
{ var dl = dlsEnum.next(); if(dl.startTime >= this.range[0]) dlIDsToRemove.push(dl.id);
} } else { // Clear all completed/cancelled downloads dlMgr.cleanUp(); // Queue up all
active ones as well var dlsEnum = dlMgr.activeDownloads; while(dlsEnum.hasMoreElements()) { dlIDsToRemove.push(dlsEnum.next().id);
} } // Remove any queued up active downloads dlIDsToRemove.forEach(function(id) { dlMgr.removeDownload(id);
}); }, get canClear() { var dlMgr = Components.classes["@mozilla.org/download-manager;1"] .getService(Components.interfaces.nsIDownloadManager);
return dlMgr.canCleanUp; } }, passwords: { clear: function () { var pwmgr = Components.classes["@mozilla.org/login-manager;1"]
.getService(Components.interfaces.nsILoginManager); // Passwords are timeless, and don't respect
the timeSpan setting pwmgr.removeAllLogins(); }, get canClear() { var pwmgr = Components.classes["@mozilla.org/login-manager;1"]
.getService(Components.interfaces.nsILoginManager); var count = pwmgr.countLogins("", "", "");
// count all logins return (count > 0); } }, sessions: { clear: function () { //
clear all auth tokens var sdr = Components.classes["@mozilla.org/security/sdr;1"] .getService(Components.interfaces.nsISecretDecoderRing);
sdr.logoutAndTeardown(); // clear FTP and plain HTTP auth sessions var os = Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService); os.notifyObservers(null, "net:clear-active-logins",
null); }, get canClear() { return true; } }, siteSettings: { clear: function () {
// Clear site-specific permissions like "Allow this site to open popups" var pm = Components.classes["@mozilla.org/permissionmanager;1"]
.getService(Components.interfaces.nsIPermissionManager); pm.removeAll(); // Clear site-specific settings
like page-zoom level var cps = Components.classes["@mozilla.org/content-pref/service;1"] .getService(Components.interfaces.nsIContentPrefService);
cps.removeGroupedPrefs(); // Clear "Never remember passwords for this site", which is
not handled by // the permission manager var pwmgr = Components.classes["@mozilla.org/login-manager;1"]
.getService(Components.interfaces.nsILoginManager); var hosts = pwmgr.getAllDisabledHosts({})
for each (var host in hosts) { pwmgr.setLoginSavingEnabled(host, true); } }, get canClear() { return true;
} } // "Static" members Sanitizer.prefDomain = "privacy.sanitize."; Sanitizer.prefShutdown
= "sanitizeOnShutdown"; Sanitizer.prefDidShutdown = "didShutdownSanitize"; // Time span constants
corresponding to values of the privacy.sanitize.timeSpan // pref. Used to determine how much history
to clear, for various items Sanitizer.TIMESPAN_EVERYTHING = 0; Sanitizer.TIMESPAN_HOUR = 1; Sanitizer.TIMESPAN_2HOURS
= 2; Sanitizer.TIMESPAN_4HOURS = 3; Sanitizer.TIMESPAN_TODAY = 4; // Return a 2 element array representing
the start and end times, // in the uSec-since-epoch format that PRTime likes. If we should //
clear everything, return null. Use ts if it is defined; otherwise // use the timeSpan
pref. Sanitizer.getClearRange = function (ts) { if (ts === undefined) ts = Sanitizer.prefs.getIntPref("timeSpan");
if (ts === Sanitizer.TIMESPAN_EVERYTHING) return null; // PRTime is microseconds while
JS time is milliseconds var endDate = Date.now() * 1000; switch (ts) { case Sanitizer.TIMESPAN_HOUR
: var startDate = endDate - 3600000000; // 1*60*60*1000000 break; case Sanitizer.TIMESPAN_2HOURS
: startDate = endDate - 7200000000; // 2*60*60*1000000 break; case Sanitizer.TIMESPAN_4HOURS : startDate
= endDate - 14400000000; // 4*60*60*1000000 break; case Sanitizer.TIMESPAN_TODAY : var
d = new Date(); // Start with today d.setHours(0); // zero us back to midnight... d.setMinutes(0);
d.setSeconds(0); startDate = d.valueOf() * 1000; // convert to epoch usec break; default:
throw "Invalid time span for clear private data: " + ts; return [startDate, endDate];
Sanitizer._prefs = null; Sanitizer.__defineGetter__("prefs", function() return Sanitizer._prefs ? Sanitizer._prefs
: Sanitizer._prefs = Components.classes["@mozilla.org/preferences-service;1"] .getService(Components.interfaces.nsIPrefService)
.getBranch(Sanitizer.prefDomain); // Shows sanitization UI Sanitizer.showUI = function(aParentWindow)
var ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"] .getService(Components.interfaces.nsIWindowWatcher);
//@line 452 "e:\builds\moz2_slave\win32_build\build\browser\base\content\sanitize.js" ww.openWindow(aParentWindow, //@line 454 "e:\builds\moz2_slave\win32_build\build\browser\base\content\sanitize.js"
"chrome://browser/content/sanitize.xul", "Sanitize", "chrome,titlebar,dialog,centerscreen,modal",
null); /** * Deletes privacy sensitive data in a batch, optionally showing the * sanitize
UI, according to user preferences Sanitizer.sanitize = function(aParentWindow) Sanitizer.showUI(aParentWindow);
Sanitizer.onStartup = function() // we check for unclean exit with pending sanitization
Sanitizer._checkAndSanitize(); Sanitizer.onShutdown = function() // we check if sanitization
is needed and perform it Sanitizer._checkAndSanitize(); // this is called on startup and shutdown,
to perform pending sanitizations Sanitizer._checkAndSanitize = function() const prefs = Sanitizer.prefs;
if (prefs.getBoolPref(Sanitizer.prefShutdown) && !prefs.prefHasUserValue(Sanitizer.prefDidShutdown))
{ // this is a shutdown or a startup after an unclean exit var s = new Sanitizer(); s.prefDomain
= "privacy.clearOnShutdown."; s.sanitize() || // sanitize() returns null on full success
prefs.setBoolPref(Sanitizer.prefDidShutdown, true); content/browser/sanitize.xul
%brandDTD; %sanitizeDTD;
&sanitizeEverythingUndoWarning;
content/browser/sanitizeDialog.js/* -*- Mode: Java; tab-width: 2; indent-tabs-mode:
nil; c-basic-offset: 2 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL
2.0/LGPL 2.1 * The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with * the License.
You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * Software distributed
under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND,
either express or implied. See the License * for the specific language governing rights
and limitations under the * License. * The Original Code is the Firefox Sanitizer. *
The Initial Developer of the Original Code is * Ben Goodger. * Portions created by the
Initial Developer are Copyright (C) 2005 * the Initial Developer. All Rights Reserved.
* Contributor(s): * Ben Goodger * Giorgio Maone
* Johnathan Nightingale * Drew Willcoxon * Ehsan
Akhgari * 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 *****
*/ const Cc = Components.classes; const Ci = Components.interfaces; var gSanitizePromptDialog
= { get bundleBrowser() if (!this._bundleBrowser) this._bundleBrowser = document.getElementById("bundleBrowser");
return this._bundleBrowser; }, get selectedTimespan() var durList = document.getElementById("sanitizeDurationChoice");
return parseInt(durList.value); }, get sanitizePreferences() if (!this._sanitizePreferences) { this._sanitizePreferences
= document.getElementById("sanitizePreferences"); } return this._sanitizePreferences; }, get
warningBox() return document.getElementById("sanitizeEverythingWarningBox"); }, init: function () // This is used by selectByTimespan()
to determine if the window has loaded. this._inited = true; var s = new Sanitizer(); s.prefDomain
= "privacy.cpd."; for (let i = 0; i < this.sanitizePreferences.childNodes.length; ++i) { var preference = this.sanitizePreferences.childNodes[i];
var name = s.getNameFromPreference(preference.name); if (!s.canClearItem(name)) preference.disabled
= true; } document.documentElement.getButton("accept").label = this.bundleBrowser.getString("sanitizeButtonOK");
if (this.selectedTimespan === Sanitizer.TIMESPAN_EVERYTHING) { this.prepareWarning(); this.warningBox.hidden
= false; } else this.warningBox.hidden = true; }, selectByTimespan: function () //
This method is the onselect handler for the duration dropdown. As a // result it's called
a couple of times before onload calls init(). if (!this._inited) return; var warningBox
= this.warningBox; // If clearing everything if (this.selectedTimespan === Sanitizer.TIMESPAN_EVERYTHING)
{ this.prepareWarning(); if (warningBox.hidden) { warningBox.hidden = false; window.resizeBy(0,
warningBox.boxObject.height); } window.document.title = this.bundleBrowser.getString("sanitizeDialog2.everything.title");
return; } // If clearing a specific time range if (!warningBox.hidden) { window.resizeBy(0,
-warningBox.boxObject.height); warningBox.hidden = true; } window.document.title = window.document.documentElement.getAttribute("noneverythingtitle");
}, sanitize: function () // Update pref values before handing off to the sanitizer (bug 453440)
this.updatePrefs(); var s = new Sanitizer(); s.prefDomain = "privacy.cpd."; s.range =
Sanitizer.getClearRange(this.selectedTimespan); s.ignoreTimespan = !s.range; try { s.sanitize();
} catch (er) { Components.utils.reportError("Exception during sanitize: " + er); } return true;
}, /** * If the panel that displays a warning when the duration is "Everything" is * not
set up, sets it up. Otherwise does nothing. * * @param aDontShowItemList Whether only
the warning message should be updated. * True means the item list visibility status
should not * be changed. */ prepareWarning: function (aDontShowItemList) { // If the date
and time-aware locale warning string is ever used again, // initialize it here. Currently
we use the no-visits warning string, // which does not include date and time. See bug 480169
comment 48. var warningStringID; if (this.hasNonSelectedItems()) { warningStringID = "sanitizeSelectedWarning";
if (!aDontShowItemList) this.showItemList(); } else { warningStringID = "sanitizeEverythingWarning2";
} var warningDesc = document.getElementById("sanitizeEverythingWarning"); warningDesc.textContent = this.bundleBrowser.getString(warningStringID);
}, /** * Called when the value of a preference element is synced from the actual * pref.
Enables or disables the OK button appropriately. */ onReadGeneric: function () var found
= false; // Find any other pref that's checked and enabled. var i = 0; while (!found &&
i < this.sanitizePreferences.childNodes.length) { var preference = this.sanitizePreferences.childNodes[i];
found = !!preference.value && !preference.disabled; i++; } try { document.documentElement.getButton("accept").disabled
= !found; } catch (e) { } // Update the warning prompt if needed this.prepareWarning(true);
return undefined; }, /** * Sanitizer.prototype.sanitize() requires the prefs to be up-to-date. * Because
the type of this prefwindow is "child" -- and that's needed because * without it the
dialog has no OK and Cancel buttons -- the prefs are not * updated on dialogaccept on
platforms that don't support instant-apply * (i.e., Windows). We must therefore manually
set the prefs from their * corresponding preference elements. */ updatePrefs : function () var
tsPref = document.getElementById("privacy.sanitize.timeSpan"); Sanitizer.prefs.setIntPref("timeSpan", this.selectedTimespan);
// Keep the pref for the download history in sync with the history pref. document.getElementById("privacy.cpd.downloads").value
= document.getElementById("privacy.cpd.history").value; // Now manually set the prefs from their
corresponding preference // elements. var prefs = this.sanitizePreferences.rootBranch;
for (let i = 0; i < this.sanitizePreferences.childNodes.length; ++i) { var p = this.sanitizePreferences.childNodes[i];
prefs.setBoolPref(p.name, p.value); } }, /** * Check if all of the history items have
been selected like the default status. */ hasNonSelectedItems: function () { let checkboxes
= document.querySelectorAll("#itemList > [preference]"); for (let i = 0; i < checkboxes.length;
++i) { let pref = document.getElementById(checkboxes[i].getAttribute("preference")); if (!pref.value) return true; } return false;
}, /** * Show the history items list. */ showItemList: function () { var itemList
= document.getElementById("itemList"); var expanderButton = document.getElementById("detailsExpander");
if (itemList.collapsed) { expanderButton.className = "expander-up"; itemList.setAttribute("collapsed",
"false"); if (document.documentElement.boxObject.height) window.resizeBy(0, itemList.boxObject.height);
} }, /** * Hide the history items list. */ hideItemList: function () { var itemList
= document.getElementById("itemList"); var expanderButton = document.getElementById("detailsExpander");
if (!itemList.collapsed) { expanderButton.className = "expander-down"; window.resizeBy(0, -itemList.boxObject.height);
itemList.setAttribute("collapsed", "true"); } }, /** * Called by the item list expander
button to toggle the list's visibility. */ toggleItemList: function () var itemList
= document.getElementById("itemList"); if (itemList.collapsed) this.showItemList();
else this.hideItemList(); //@line 571 "e:\builds\moz2_slave\win32_build\build\browser\base\content\sanitizeDialog.js" content/browser/sanitizeDialog.css/* Places
tree */ #placesTreechildren { -moz-user-focus: normal; #placesTreechildren::-moz-tree-cell(grippyRow),
#placesTreechildren::-moz-tree-cell-text(grippyRow), #placesTreechildren::-moz-tree-image(grippyRow)
{ cursor: -moz-grab; /* Sanitize everything warnings */ #sanitizeEverythingWarning, #sanitizeEverythingUndoWarning
{ white-space: pre-wrap; content/browser/tabbrowser.css.tabbrowser-tabs { -moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-tabs");
.tabbrowser-tab { -moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-tab"); .tabbrowser-arrowscrollbox { -moz-binding:
url("chrome://browser/content/tabbrowser.xml#tabbrowser-arrowscrollbox"); .tabs-alltabs-popup { -moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-alltabs-popup");
.tab-close-button, .tabs-closebutton { -moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-close-tab-button");
.tab-close-button { display: none; .tabbrowser-tabs:not([closebuttons="noclose"]):not([closebuttons="closeatend"]) > .tabbrowser-tab[selected="true"]:not(:only-child)
> .tab-close-button { display: -moz-box; .tabbrowser-tabs[closebuttons="alltabs"]
> .tabbrowser-tab:not(:only-child) > .tab-close-button { display: -moz-box; .tabs-container:not([overflow="true"])
> .tabs-newtab-button, .tabs-container[overflow="true"] > .tabbrowser-arrowscrollbox > .tabs-newtab-button
{ visibility: collapse; .tabs-newtab-button > .toolbarbutton-text { display: none; content/browser/tabbrowser.xml
accesskey="&closeTab.accesskey;" tbattr="tabbrowser-multiple" oncommand="var tabbrowser = this.parentNode.parentNode.parentNode.parentNode;
tabbrowser.removeTab(tabbrowser.mContextTab);"/>
Components.classes['@mozilla.org/preferences-service;1'] .getService(Components.interfaces.nsIPrefService)
.getBranch(null); Components.classes["@mozilla.org/docshell/urifixup;1"]
.getService(Components.interfaces.nsIURIFixup);
Components.classes["@mozilla.org/browser/favicon-service;1"] .getService(Components.interfaces.nsIFaviconService);
document.getAnonymousElementByAttribute(this,
"anonid", "tabbox"); this.mTabBox.childNodes[0] document.getAnonymousElementByAttribute(this, "anonid", "strip"); document.getAnonymousElementByAttribute(this, "anonid", "tabcontainer"); document.getAnonymousElementByAttribute(this, "anonid", "panelcontainer"); this.mTabContainer.childNodes document.getAnonymousElementByAttribute(this,
"anonid", "tbstringbundle"); document.getAnonymousElementByAttribute(this,
"anonid", "undoCloseTabMenuItem"); null null null [] []
new Array() new Array()
false false null false
false null false
null false
0 && aStatus == NS_ERROR_UNKNOWN_HOST) { // to prevent bug 235825: wait for the
request handled // by the automatic keyword resolver return; } // since we (try to) only
handle STATE_STOP of the last request, // the count of open requests should now be
0 this.mRequestCount = 0; } if (aStateFlags & nsIWebProgressListener.STATE_START &&
aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK) { // It's okay to clear what the user typed
when we start // loading a document. If the user types, this counter gets // set to zero,
if the document load ends without an // onLocationChange, this counter gets decremented // (so we keep
it while switching tabs after failed loads) // We need to add 2 because loadURIWithFlags
may have // cancelled a pending load which would have cleared // its anchor scroll detection
temporary increment. if (aWebProgress.DOMWindow == this.mBrowser.contentWindow) this.mBrowser.userTypedClear
+= 2; if (!this.mBlank) { if (!(aStateFlags & nsIWebProgressListener.STATE_RESTORING))
{ this.mTab.setAttribute("busy", "true"); this.mTabBrowser.updateIcon(this.mTab); this.mTabBrowser.setTabTitleLoading(this.mTab);
} if (this.mTabBrowser.mCurrentTab == this.mTab) this.mTabBrowser.mIsBusy = true; } } else
if (aStateFlags & nsIWebProgressListener.STATE_STOP && aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK)
{ if (aWebProgress.DOMWindow == this.mBrowser.contentWindow) { // The document is done loading, we no
longer want the // value cleared. if (this.mBrowser.userTypedClear > 1) this.mBrowser.userTypedClear -= 2; else
if (this.mBrowser.userTypedClear > 0) this.mBrowser.userTypedClear--; if (!this.mBrowser.mIconURL) this.mTabBrowser.useDefaultIcon(this.mTab);
} if (this.mBlank) this.mBlank = false; this.mTab.removeAttribute("busy"); this.mTabBrowser.updateIcon(this.mTab); var
location = aRequest.QueryInterface(nsIChannel).URI; // For keyword URIs clear the user typed
value since they will be changed into real URIs if (location.scheme == "keyword") this.mBrowser.userTypedValue
= null; if (this.mTab.label == this.mTabBrowser.mStringBundle.getString("tabs.loading")) this.mTabBrowser.setTabTitle(this.mTab); if
(this.mTabBrowser.mCurrentTab == this.mTab) this.mTabBrowser.mIsBusy = false; } if (this.mTabBrowser.mCurrentTab
== this.mTab) { for (let i = 0; i < this.mTabBrowser.mProgressListeners.length; i++) { let p = this.mTabBrowser.mProgressListeners[i];
if (p) try { if (!oldBlank) p.onStateChange(aWebProgress, aRequest, aStateFlags, aStatus); // make sure
that the visible status of new blank tabs is correctly set else if ("onUpdateCurrentBrowser"
in p) p.onUpdateCurrentBrowser(aStateFlags, aStatus, "", 0); } catch (e) { // don't inhibit
other listeners Components.utils.reportError(e); } } } for (let i = 0; i < this.mTabBrowser.mTabsProgressListeners.length;
i++) { let p = this.mTabBrowser.mTabsProgressListeners[i]; if (p) try { p.onStateChange(this.mBrowser,
aWebProgress, aRequest, aStateFlags, aStatus); } catch (e) { // don't inhibit other listeners
Components.utils.reportError(e); } } if (aStateFlags & (nsIWebProgressListener.STATE_START |
nsIWebProgressListener.STATE_STOP)) { // reset cached temporary values at beginning
and end this.mMessage = ""; this.mTotalProgress = 0; } this.mStateFlags = aStateFlags; this.mStatus
= aStatus; }, onLocationChange : function(aWebProgress, aRequest, aLocation) { // The document loaded
correctly, clear the value if we should if (this.mBrowser.userTypedClear > 0) this.mBrowser.userTypedValue
= null; if (aWebProgress.DOMWindow == this.mBrowser.contentWindow && aWebProgress.isLoadingDocument) this.mTabBrowser.getBrowserForTab(this.mTab).mIconURL
= null; // changing location, clear out the missing plugins list this.mBrowser.missingPlugins
= null; if (this.mBlank) return; if (this.mTabBrowser.mCurrentTab == this.mTab) { for (let i = 0; i < this.mTabBrowser.mProgressListeners.length;
i++) { let p = this.mTabBrowser.mProgressListeners[i]; if (p) try { p.onLocationChange(aWebProgress,
aRequest, aLocation); } catch (e) { // don't inhibit other listeners Components.utils.reportError(e);
} } } for (let i = 0; i < this.mTabBrowser.mTabsProgressListeners.length; i++) { let p = this.mTabBrowser.mTabsProgressListeners[i];
if (p) try { p.onLocationChange(this.mBrowser, aWebProgress, aRequest, aLocation); } catch
(e) { // don't inhibit other listeners Components.utils.reportError(e); } } }, onStatusChange : function(aWebProgress,
aRequest, aStatus, aMessage) { if (this.mBlank) return; if (this.mTabBrowser.mCurrentTab
== this.mTab) { for (let i = 0; i < this.mTabBrowser.mProgressListeners.length; i++) { let p = this.mTabBrowser.mProgressListeners[i];
if (p) try { p.onStatusChange(aWebProgress, aRequest, aStatus, aMessage); } catch (e)
{ // don't inhibit other listeners Components.utils.reportError(e); } } } for (let i = 0; i < this.mTabBrowser.mTabsProgressListeners.length;
i++) { let p = this.mTabBrowser.mTabsProgressListeners[i]; if (p) try { p.onStatusChange(this.mBrowser,
aWebProgress, aRequest, aStatus, aMessage); } catch (e) { // don't inhibit other listeners
Components.utils.reportError(e); } } this.mMessage = aMessage; }, onSecurityChange : function(aWebProgress,
aRequest, aState) { if (this.mTabBrowser.mCurrentTab == this.mTab) { for (let i = 0; i < this.mTabBrowser.mProgressListeners.length;
i++) { let p = this.mTabBrowser.mProgressListeners[i]; if (p) try { p.onSecurityChange(aWebProgress,
aRequest, aState); } catch (e) { // don't inhibit other listeners Components.utils.reportError(e);
} } } for (let i = 0; i < this.mTabBrowser.mTabsProgressListeners.length; i++) { let p = this.mTabBrowser.mTabsProgressListeners[i];
if (p) try { p.onSecurityChange(this.mBrowser, aWebProgress, aRequest, aState); } catch (e)
{ // don't inhibit other listeners Components.utils.reportError(e); } } }, onRefreshAttempted : function(aWebProgress,
aURI, aDelay, aSameURI) { var allowRefresh = true; if (this.mTabBrowser.mCurrentTab
== this.mTab) { for (let i = 0; i < this.mTabBrowser.mProgressListeners.length; i++) { let p = this.mTabBrowser.mProgressListeners[i];
if (p && "onRefreshAttempted" in p) { try { if (!p.onRefreshAttempted(aWebProgress,
aURI, aDelay, aSameURI)) allowRefresh = false; } catch (e) { // don't inhibit other listeners
Components.utils.reportError(e); } } } } for (let i = 0; i < this.mTabBrowser.mTabsProgressListeners.length;
i++) { let p = this.mTabBrowser.mTabsProgressListeners[i]; if (p && "onRefreshAttempted" in p) { try
{ if (!p.onRefreshAttempted(this.mBrowser, aWebProgress, aURI, aDelay, aSameURI)) allowRefresh
= false; } catch (e) { // don't inhibit other listeners Components.utils.reportError(e);
} } } return allowRefresh; }, QueryInterface : function(aIID) { if (aIID.equals(Components.interfaces.nsIWebProgressListener)
|| aIID.equals(Components.interfaces.nsIWebProgressListener2) || aIID.equals(Components.interfaces.nsISupportsWeakReference)
|| aIID.equals(Components.interfaces.nsISupports)) return this; throw Components.results.NS_NOINTERFACE;
} }); ]]>
sz || req.image.height > sz) return; this.setIcon(aTab, browser.currentURI); } catch (e) { } } }
// Use documentURIObject in the check for shouldLoadFavIcon so that we // do the right
thing with about:-style error pages. Bug 453442 else if (this.shouldLoadFavIcon(docURIObject))
{ var url = docURIObject.prePath + "/favicon.ico"; if (!this.isFailedIcon(url)) this.setIcon(aTab,
url); } ]]>
1 || !this.mPrefs.getBoolPref("browser.tabs.closeWindowWithLastTab")) this.removeTab(event.target); event.stopPropagation();
]]>
return !this.mStrip.collapsed;
0) { // Use the filter hooked up in our addProgressListener
filter = this.mTabFilters[0]; } else { // create a filter and hook it up to our first
browser filter = Components.classes["@mozilla.org/appshell/component/browser-status-filter;1"] .createInstance(Components.interfaces.nsIWebProgress);
this.mTabFilters[0] = filter; this.mCurrentBrowser.webProgress.addProgressListener(filter, Components.interfaces.nsIWebProgress.NOTIFY_ALL);
} // Remove all our progress listeners from the active browser's filter. for (var i =
0; i < this.mProgressListeners.length; i++) { var p = this.mProgressListeners[i]; if
(p) filter.removeProgressListener(p); } // Wire up a progress listener to our filter.
const listener = this.mTabProgressListener(this.mCurrentTab, this.mCurrentBrowser, false); filter.addProgressListener(listener,
Components.interfaces.nsIWebProgress.NOTIFY_ALL); this.mTabListeners[0] = listener; ]]>
1 false/true NO var owner = (aURIs.length > 1) || aLoadInBackground ? null : this.selectedTab;
var firstTabAdded = null; if (aReplace) { try { this.loadURI(aURIs[0], null, null);
} catch (e) { // Ignore failure in case a URI is wrong, so we can continue // opening
the next ones. } } else firstTabAdded = this.addTab(aURIs[0], {ownerTab: owner}); var tabNum = this.mTabContainer.selectedIndex;
for (let i = 1; i < aURIs.length; ++i) { let tab = this.addTab(aURIs[i]); if (aReplace)
this.moveTabTo(tab, ++tabNum); } if (!aLoadInBackground) { if (firstTabAdded) { // .selectedTab setter
focuses the content area this.selectedTab = firstTabAdded; } else window.content.focus();
} ]]>
= 0; --i) { if (this.mTabs[i] != aTab)
this.removeTab(this.mTabs[i]); } } ]]>
[]
false -1 || this._windowIsClosing) return null; var
browser = this.getBrowserForTab(aTab); if (!aTabWillBeMoved) { let ds = browser.docShell;
if (ds && ds.contentViewer && !ds.contentViewer.permitUnload()) return null; } var closeWindow = false; var
l = this.mTabs.length - this._removingTabs.length; var newTab = false; if (l == 1) { closeWindow
= aCloseWindowWithLastTab != null ? aCloseWindowWithLastTab : !window.toolbar.visible || this.mPrefs.getBoolPref("browser.tabs.closeWindowWithLastTab");
// Closing the tab and replacing it with a blank one is notably slower // than closing
the window right away. If the caller opts in, take // the fast path. if (closeWindow
&& aCloseWindowFastpath && this._removingTabs.length == 0 && (this._windowIsClosing = window.closeWindow(true)))
return null; newTab = true; l++; } if (l == 2) { let autohide = this.mPrefs.getBoolPref("browser.tabs.autoHide");
let tabStripHide = !window.toolbar.visible; if (autohide || tabStripHide) this.setStripVisibilityTo(false);
} this._removingTabs.push(aTab); // We're committed to closing the tab now. // Dispatch
a notification. // We dispatch it before any teardown so that event listeners can // inspect
the tab that's about to close. var evt = document.createEvent("UIEvent"); evt.initUIEvent("TabClose",
true, false, window, aTabWillBeMoved ? 1 : 0); aTab.dispatchEvent(evt); // Remove the
tab's filter and progress listener. const filter = this.mTabFilters[aTab._tPos]; browser.webProgress.removeProgressListener(filter);
filter.removeProgressListener(this.mTabListeners[aTab._tPos]); // Remove our title change and blocking listeners
browser.removeEventListener("DOMTitleChanged", this.onTitleChanged, true); // We are no longer
the primary content area. browser.setAttribute("type", "content-targetable"); // Remove this tab
as the owner of any other tabs, since it's going away. Array.forEach(this.mTabs, function
(tab) { if ("owner" in tab && tab.owner == aTab) // |tab| is a child of the tab we're
removing, make it an orphan tab.owner = null; }); return [aTab, closeWindow, newTab];
]]>
if (!this.mTabbedMode)
this.enterTabbedMode(); this.mTabsProgressListeners.push(aListener);
= 0) this.mTabsProgressListeners.splice(pos, 1); ]]>
= 0 && aIndex < this.mTabs.length && aIndex != this.tabContainer.selectedIndex)
this.selectedTab = this.mTabs[aIndex]; if (aEvent) { aEvent.preventDefault(); aEvent.stopPropagation();
} ]]> return this.mTabContainer;
return this.mTabBox.selectedTab;
0 350 1) return dt.effectAllowed = "none"; var types = dt.mozTypesAt(0); var sourceNode
= null; // tabs are always added as the first type if (types[0] == TAB_DROP_TYPE) { var
sourceNode = dt.mozGetDataAt(TAB_DROP_TYPE, 0); if (sourceNode instanceof XULElement
&& sourceNode.localName == "tab" && (sourceNode.parentNode == this.mTabContainer || (sourceNode.ownerDocument.defaultView
instanceof ChromeWindow && sourceNode.ownerDocument.documentElement.getAttribute("windowtype") == "navigator:browser"))) { if (sourceNode.parentNode
== this.mTabContainer && (aEvent.screenX >= sourceNode.boxObject.screenX && aEvent.screenX
= this.mDragTime + this.mDragOverDelay)
this.mTabContainer.selectedItem = aEvent.target; return; } var newIndex = this.getNewIndex(aEvent);
var ib = this.mTabDropIndicatorBar; var ind = ib.firstChild; var scrollRect = tabStrip.scrollClientRect;
var rect = this.getBoundingClientRect(); var minMargin = scrollRect.left - rect.left;
// make sure we don't place the tab drop indicator past the // edge, or the containing box will
flex and stretch // the tab drop indicator bar, which will flex the url bar. // *** todo
// just use first value if you can figure out how to get // the tab drop indicator to
crop instead of flex and stretch // the tab drop indicator bar. var maxMargin = Math.min(minMargin
+ scrollRect.width, ib.getBoundingClientRect().right - ind.clientWidth); if (!ltr) [minMargin,
maxMargin] = [this.clientWidth - maxMargin, this.clientWidth - minMargin]; var newMargin;
if (pixelsToScroll) { // if we are scrolling, put the drop indicator at the edge // so that
it doesn't jump while scrolling newMargin = (pixelsToScroll > 0) ? maxMargin : minMargin;
} else { if (newIndex == this.mTabs.length) { let tabRect = this.mTabs[newIndex-1].getBoundingClientRect();
if (ltr) newMargin = tabRect.right - rect.left; else newMargin = rect.right - tabRect.left;
} else { let tabRect = this.mTabs[newIndex].getBoundingClientRect(); if (ltr) newMargin = tabRect.left - rect.left;
else newMargin = rect.right - tabRect.right; } // ensure we never place the drop indicator
beyond our limits if (newMargin < minMargin) newMargin = minMargin; else if (newMargin
> maxMargin) newMargin = maxMargin; } ind.style.MozMarginStart = newMargin + 'px'; ib.collapsed = false;
]]> draggedTab._tPos)
newIndex--; if (newIndex != draggedTab._tPos) this.moveTabTo(draggedTab, newIndex); } }
else if (draggedTab) { // swap the dropped tab with a new one we create and then close
// it in the other window (making it seem to have moved between // windows) newIndex
= this.getNewIndex(aEvent); newTab = this.addTab("about:blank"); var newBrowser = this.getBrowserForTab(newTab);
// Stop the about:blank load newBrowser.stop(); // make sure it has a docshell newBrowser.docShell;
this.moveTabTo(newTab, newIndex); this.swapBrowsersAndCloseOther(newTab, draggedTab); // We need to set selectedTab
after we've done // swapBrowsersAndCloseOther, so that the updateCurrentBrowser // it triggers
will correctly update our URL bar. this.selectedTab = newTab; } else { var url; for (var i=0;
i < this._supportedLinkDropTypes.length; i++) { let dataType = this._supportedLinkDropTypes[i];
// uri-list: for now, support dropping of the first URL // only var isURLList = dataType
== "text/uri-list"; let urlData = isURLList ? dt.mozGetDataAt("URL", 0) : dt.mozGetDataAt(dataType,
0); if (urlData) { url = transferUtils.retrieveURLFromData(urlData, isURLList ? "text/plain" : dataType); break;
} } NS_ASSERT(url, "In the drop event, at least one mime-type should match our supported
types"); // valid urls don't contain spaces ' '; if we have a space it isn't a valid
url. // Also disallow dropping javascript: or data: urls--bail out if (!url || !url.length
|| url.indexOf(" ", 0) != -1 || /^\s*(javascript|data):/.test(url)) return; // XXXmano: temporary fix until dragDropSecurityCheck
make the // drag-session an optional paramter var dragService = Cc["@mozilla.org/widget/dragservice;1"].
getService(Ci.nsIDragService); var dragSession = dragService.getCurrentSession(); nsDragAndDrop.dragDropSecurityCheck(aEvent,
dragSession, url); var bgLoad = true; try { bgLoad = this.mPrefs.getBoolPref("browser.tabs.loadInBackground");
} catch (e) { } if (aEvent.shiftKey) bgLoad = !bgLoad; if (document.getBindingParent(aEvent.originalTarget).localName
!= "tab" || dropEffect == "copy") { // We're adding a new tab. newIndex = this.getNewIndex(aEvent);
newTab = this.loadOneTab(getShortcutOrURI(url), {inBackground: bgLoad}); this.moveTabTo(newTab,
newIndex); } else { // Load in an existing tab. var tab = aEvent.target; try { this.getBrowserForTab(tab).loadURI(getShortcutOrURI(url));
if (this.mCurrentTab != tab && !bgLoad) this.selectedTab = tab; } catch(ex) { // Just ignore invalid
urls } } } ]]> wX && eX < (wX + window.outerWidth)) { var bo = this.mTabContainer.mTabstrip.boxObject;
// also avoid detaching if the the tab was dropped too close to // the tabbar (half a
tab) var endScreenY = bo.screenY + 1.5 * bo.height; var eY = aEvent.screenY; if (eY
< endScreenY && eY > window.screenY) return; } var draggedTab = dt.mozGetDataAt(TAB_DROP_TYPE,
0); this.replaceTabWithWindow(draggedTab); aEvent.stopPropagation(); ]]>
this.mTabs[i].boxObject.screenX + this.mTabs[i].boxObject.width
/ 2) return i; } return this.mTabs.length; ]]>
0) { this.moveTabTo(this.mCurrentTab, tabPos
- 1); this.mCurrentTab.focus(); } else if (this.arrowKeysShouldWrap) this.moveTabToEnd();
]]> 0) { this.moveTabTo(this.mCurrentTab, 0); this.mCurrentTab.focus(); } ]]>
null
0
document.getAnonymousElementByAttribute(this, "anonid", "arrowscrollbox"); document.getAnonymousElementByAttribute(this, "anonid", "tabs-closebutton"); ({ tabbox: this, observe: function(subject, topic, data) { if (topic
== "nsPref:changed") { switch (data) { case "browser.tabs.closeButtons": subject.QueryInterface(Components.interfaces.nsIPrefBranch);
this.tabbox.mCloseButtons = subject.getIntPref("browser.tabs.closeButtons"); this.tabbox.adjustTabstrip(); break; } }
}, QueryInterface: function(aIID) { if (aIID.equals(Components.interfaces.nsIObserver) || aIID.equals(Components.interfaces.nsISupports))
return this; throw Components.results.NS_NOINTERFACE; } }); 100
250 140 1
this.mTabClipWidth) this.setAttribute("closebuttons", "alltabs"); else this.setAttribute("closebuttons",
"activetab"); break; case 2: case 3: this.setAttribute("closebuttons", "noclose"); break; } this.mTabstripClosebutton.collapsed
= this.mCloseButtons != 3; ]]> null
= tabStrip.scrollSize)
tabStrip.scrollByPixels(-1); } catch (e) {} ]]>
document.getAnonymousElementByAttribute(this, "anonid", "alltabs-popup"); document.getAnonymousElementByAttribute(this, "anonid", "alltabs-box-animate");
null -1 25
[1.00, 0.85, 0.80, 0.75, 0.71, 0.68, 0.65, 0.62, 0.59,
0.57, 0.54, 0.52, 0.50, 0.47, 0.45, 0.44, 0.42, 0.40, 0.38, 0.37, 0.35, 0.34, 0.32,
0.31, 0.30, 0.29, 0.28, 0.27, 0.26, 0.25, 0.24, 0.23, 0.23, 0.22, 0.22, 0.21, 0.21,
0.21, 0.20, 0.20, 0.20, 0.20, 0.20, 0.20, 0.20, 0.20, 0.19, 0.19, 0.19, 0.18, 0.18,
0.17, 0.17, 0.16, 0.15, 0.14, 0.13, 0.11, 0.09, 0.06]
1 && !this._ignoredClick) { this._ignoredClick
= true; return; } // Reset the "ignored click" flag this._ignoredClick = false; tabbedBrowser.removeTab(bindingParent);
tabbedBrowser._blockDblClick = true; /* XXXmano hack (see bug 343628): * Since we're removing
the event target, if the user * double-clicks this button, the dblclick event will be dispatched
* with the tabbar as its event target (and explicit/originalTarget), * which treats that
as a mouse gesture for opening a new tab. * In this context, we're manually blocking
the dblclick event * (see onTabBarDblClick). */ var clickedOnce = false; function enableDblClick(event)
{ if (event.detail == 1 && !clickedOnce) { clickedOnce = true; return; } setTimeout(function()
{ tabbedBrowser._blockDblClick = false; }, 0); tabbedBrowser.removeEventListener("click",
enableDblClick, false); } tabbedBrowser.addEventListener("click", enableDblClick, false); } else // "tabs" tabbedBrowser.removeCurrentTab();
} ]]> // for the one-close-button
case event.stopPropagation();
false
null
var anonid = event.originalTarget.getAttribute("anonid"); if (anonid == "close-button") this.mOverCloseButton
= true; var anonid = event.originalTarget.getAttribute("anonid");
if (anonid == "close-button") this.mOverCloseButton = false; this.style.MozUserFocus = ''; this.style.MozUserFocus = 'ignore';
this.clientTop; this.style.MozUserFocus = 'ignore';
this.clientTop; this.style.MozUserFocus = '';
= tabstripBO.screenX && curTabBO.screenX + curTabBO.width
content/browser/urlbarBindings.xml
= 0) { if (existingSuffix == -1 || existingSuffix > firstSlash) url = url.substring(0, firstSlash)
+ suffix + url.substring(firstSlash + 1); } else url = url + (existingSuffix == -1
? suffix : "/"); url = "http://www." + url; } } var postData = {}; url = getShortcutOrURI(url,
postData); return [url, postData.value]; ]]>
var types = aEvent.dataTransfer.types; if (types.contains("application/x-moz-file")
|| types.contains("text/x-moz-url") || types.contains("text/uri-list") || types.contains("text/unicode")) aEvent.preventDefault();
0
Cc["@mozilla.org/intl/stringbundle;1"]. getService(Ci.nsIStringBundleService). createBundle("chrome://browser/locale/places/places.properties");
content/browser/utilityOverlay.js//@line 39 "e:\builds\moz2_slave\win32_build\build\browser\base\content\utilityOverlay.js"
* Communicator Shared Utility Library * for shared application glue for the Communicator
suite of applications **/ var TAB_DROP_TYPE = "application/x-moz-tabbrowser-tab"; var
gBidiUI = false; function getBrowserURL() return "chrome://browser/content/browser.xul";
function goToggleToolbar( id, elementID ) var toolbar = document.getElementById(id);
var element = document.getElementById(elementID); if (toolbar) var isHidden = toolbar.hidden;
toolbar.hidden = !isHidden; document.persist(id, 'hidden'); if (element) { element.setAttribute("checked",
isHidden ? "true" : "false"); document.persist(elementID, 'checked'); } function getTopWin() var windowManager
= Components.classes['@mozilla.org/appshell/window-mediator;1'] .getService(Components.interfaces.nsIWindowMediator);
return windowManager.getMostRecentWindow("navigator:browser"); function openTopWin( url ) openUILink(url,
{}) function getBoolPref ( prefname, def ) try { var pref = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch); return pref.getBoolPref(prefname); catch(er)
{ return def; // Change focus for this browser window to |aElement|, without focusing the
// window itself. function focusElement(aElement) var msg; // if a content window, focus the
instead as window.focus() // raises the window if (aElement instanceof Window)
{ var browser = getBrowserFromContentWindow(aElement); if (!browser) throw "aElement is not a content
window"; browser.focus(); msg = "focusElement(content) is deprecated. Use gBrowser.selectedBrowser.focus()
instead."; else { aElement.focus(); msg = "focusElement(element) is deprecated. Use
element.focus() instead."; var scriptError = Components.classes["@mozilla.org/scripterror;1"]
.createInstance(Components.interfaces.nsIScriptError); scriptError.init(msg, document.location.href,
null, null, null, scriptError.warningFlag, "chrome javascript"); Components.classes["@mozilla.org/consoleservice;1"]
.getService(Components.interfaces.nsIConsoleService) .logMessage(scriptError); // openUILink handles
clicks on UI elements that cause URLs to load. function openUILink( url, e, ignoreButton,
ignoreAlt, allowKeywordFixup, postData, referrerUrl ) var where = whereToOpenLink(e, ignoreButton,
ignoreAlt); openUILinkIn(url, where, allowKeywordFixup, postData, referrerUrl); /* whereToOpenLink()
looks at an event to decide where to open a link. * The event may be a mouse event (click,
double-click, middle-click) or keypress event (enter). * On Windows, the modifiers are:
* Ctrl new tab, selected * Shift new window * Ctrl+Shift new tab, in background * Alt
save * You can swap Ctrl and Ctrl+shift by toggling the hidden pref * browser.tabs.loadBookmarksInBackground
(not browser.tabs.loadInBackground, which * is for content area links). * Middle-clicking
is the same as Ctrl+clicking (it opens a new tab) and it is * subject to the shift modifier
and pref in the same way. * Exceptions: * - Alt is ignored for menu items selected
using the keyboard so you don't accidentally save stuff. * (Currently, the Alt isn't sent
here at all for menu items, but that will change in bug 126189.) * - Alt is hard to
use in context menus, because pressing Alt closes the menu. * - Alt can't be used on
the bookmarks toolbar because Alt is used for "treat this as something draggable".
* - The button is ignored for the middle-click-paste-URL feature, since it's always a middle-click.
function whereToOpenLink( e, ignoreButton, ignoreAlt ) // This method must treat a null
event like a left click without modifier keys (i.e. // e = { shiftKey:false, ctrlKey:false,
metaKey:false, altKey:false, button:0 }) // for compatibility purposes. if (!e) return
"current"; var shift = e.shiftKey; var ctrl = e.ctrlKey; var meta = e.metaKey; var alt
= e.altKey && !ignoreAlt; // ignoreButton allows "middle-click paste" to use function
without always opening in a new window. var middle = !ignoreButton && e.button == 1; var
middleUsesTabs = getBoolPref("browser.tabs.opentabfor.middleclick", true); // Don't do anything special with right-mouse
clicks. They're probably clicks on context menu items. //@line 177 "e:\builds\moz2_slave\win32_build\build\browser\base\content\utilityOverlay.js"
if (ctrl || (middle && middleUsesTabs)) { //@line 179 "e:\builds\moz2_slave\win32_build\build\browser\base\content\utilityOverlay.js"
if (shift) return "tabshifted"; else return "tab"; else if (alt) { return "save"; else
if (shift || (middle && !middleUsesTabs)) { return "window"; else { return "current";
/* openUILinkIn opens a URL in a place specified by the parameter |where|. * |where| can be:
* "current" current tab (if there aren't any browser windows, then in a new window
instead) * "tab" new tab (if there aren't any browser windows, then in a new window
instead) * "tabshifted" same as "tab" but in background if default is to select new
tabs, and vice versa * "window" new window * "save" save to disk (with no filename hint!)
* allowThirdPartyFixup controls whether third party services such as Google's * I Feel Lucky
are allowed to interpret this URL. This parameter may be * undefined, which is treated as false.
function openUILinkIn( url, where, allowThirdPartyFixup, postData, referrerUrl ) if (!where || !url)
return; if (where == "save") { saveURL(url, null, null, true, null, referrerUrl); return;
const Cc = Components.classes; const Ci = Components.interfaces; var w = getTopWin();
if (!w || where == "window") { var sa = Cc["@mozilla.org/supports-array;1"]. createInstance(Ci.nsISupportsArray); var wuri
= Cc["@mozilla.org/supports-string;1"]. createInstance(Ci.nsISupportsString); wuri.data = url; sa.AppendElement(wuri); sa.AppendElement(null);
sa.AppendElement(referrerUrl); sa.AppendElement(postData); sa.AppendElement(allowThirdPartyFixup); var
ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]. getService(Ci.nsIWindowWatcher); ww.openWindow(w
|| window, getBrowserURL(), null, "chrome,dialog=no,all", sa); return; var loadInBackground = getBoolPref("browser.tabs.loadBookmarksInBackground",
false); switch (where) { case "current": w.loadURI(url, referrerUrl, postData, allowThirdPartyFixup);
break; case "tabshifted": loadInBackground = !loadInBackground; // fall through case
"tab": let browser = w.getBrowser(); browser.loadOneTab(url, { referrerURI: referrerUrl, postData: postData,
inBackground: loadInBackground, allowThirdPartyFixup: allowThirdPartyFixup}); break; // If this
window is active, focus the target window. Otherwise, focus the // content but don't
raise the window, since the URI we just loaded may have // resulted in a new frontmost window
(e.g. "javascript:window.open('');"). var fm = Components.classes["@mozilla.org/focus-manager;1"].
getService(Components.interfaces.nsIFocusManager); if (window == fm.activeWindow) w.content.focus();
else w.gBrowser.selectedBrowser.focus(); // Used as an onclick handler for UI elements
with link-like behavior. // e.g. onclick="checkForMiddleClick(this, event);" function checkForMiddleClick(node,
event) { // We should be using the disabled property here instead of the attribute, //
but some elements that this function is used with don't support it (e.g. // menuitem).
if (node.getAttribute("disabled") == "true") return; // Do nothing if (event.button ==
1) { /* Execute the node's oncommand or command. * * ***: we should use node.oncommand(event)
once bug 246720 is fixed. */ var target = node.hasAttribute("oncommand") ? node :
node.ownerDocument.getElementById(node.getAttribute("command")); var fn = new Function("event", target.getAttribute("oncommand"));
fn.call(target, event); // If the middle-click was on part of a menu, close the menu. //
(Menus close automatically with left-click but not with middle-click.) closeMenus(event.target);
// Closes all popups that are ancestors of the node. function closeMenus(node) if ("tagName"
in node) { if (node.namespaceURI == "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" && (node.tagName == "menupopup" || node.tagName
== "popup")) node.hidePopup(); closeMenus(node.parentNode); // Gather all descendent text under given
document node. function gatherTextUnder ( root ) var text = ""; var node = root.firstChild;
var depth = 1; while ( node && depth > 0 ) { // See if this node is text. if ( node.nodeType
== Node.TEXT_NODE ) { // Add this text to our collection. text += " " + node.data;
} else if ( node instanceof HTMLImageElement) { // If it has an alt= attribute, use that.
var altText = node.getAttribute( "alt" ); if ( altText && altText != "" ) { text =
altText; break; } } // Find next node to test. // First, see if this node has children.
if ( node.hasChildNodes() ) { // Go to first child. node = node.firstChild; depth++; }
else { // No children, try next sibling. if ( node.nextSibling ) { node = node.nextSibling;
} else { // Last resort is our next oldest uncle/aunt. node = node.parentNode.nextSibling;
depth--; } } // Strip leading whitespace. text = text.replace( /^\s+/, "" ); // Strip
trailing whitespace. text = text.replace( /\s+$/, "" ); // Compress remaining whitespace.
text = text.replace( /\s+/g, " " ); return text; function getShellService() var shell
= null; try { shell = Components.classes["@mozilla.org/browser/shell-service;1"] .getService(Components.interfaces.nsIShellService);
} catch (e) {dump("*** e = " + e + "\n");} return shell; function isBidiEnabled() {
// first check the pref. if (getBoolPref("bidi.browser.ui", false)) return true; // if the pref isn't
set, check for an RTL locale and force the pref to true // if we find one. var rv =
false; try { var localeService = Components.classes["@mozilla.org/intl/nslocaleservice;1"] .getService(Components.interfaces.nsILocaleService);
var systemLocale = localeService.getSystemLocale().getCategory("NSILOCALE_CTYPE").substr(0,3); switch (systemLocale) { case "ar-": case "he-":
case "fa-": case "ur-": case "syr": rv = true; var pref = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch); pref.setBoolPref("bidi.browser.ui", true);
} } catch (e) {} return rv; function openAboutDialog() //@line 415 "e:\builds\moz2_slave\win32_build\build\browser\base\content\utilityOverlay.js"
window.openDialog("chrome://browser/content/aboutDialog.xul", "About", "centerscreen,chrome,resizable=no");
//@line 417 "e:\builds\moz2_slave\win32_build\build\browser\base\content\utilityOverlay.js" function openPreferences(paneID, extraArgs)
var instantApply = getBoolPref("browser.preferences.instantApply", false); var features = "chrome,titlebar,toolbar,centerscreen"
+ (instantApply ? ",dialog=no" : ",modal"); var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator); var win = wm.getMostRecentWindow("Browser:Preferences");
if (win) { win.focus(); if (paneID) { var pane = win.document.getElementById(paneID);
win.document.documentElement.showPane(pane); } if (extraArgs && extraArgs["advancedTab"])
{ var advancedPaneTabs = win.document.getElementById("advancedPrefs"); advancedPaneTabs.selectedTab = win.document.getElementById(extraArgs["advancedTab"]);
} return win; return openDialog("chrome://browser/content/preferences/preferences.xul", "Preferences", features, paneID, extraArgs);
function openAdvancedPreferences(tabID) return openPreferences("paneAdvanced", { "advancedTab"
: tabID }); * Opens the release notes page for this version of the application. function
openReleaseNotes() var formatter = Components.classes["@mozilla.org/toolkit/URLFormatterService;1"] .getService(Components.interfaces.nsIURLFormatter);
var relnotesURL = formatter.formatURLPref("app.releaseNotesURL"); openUILinkIn(relnotesURL, "tab"); * Opens
the troubleshooting information (about:support) page for this version * of the application.
function openTroubleshootingPage() openUILinkIn("about:support", "tab"); //@line 473 "e:\builds\moz2_slave\win32_build\build\browser\base\content\utilityOverlay.js"
* Opens the update manager and checks for updates to the application. function checkForUpdates()
var um = Components.classes["@mozilla.org/updates/update-manager;1"]. getService(Components.interfaces.nsIUpdateManager);
var prompter = Components.classes["@mozilla.org/updates/update-prompt;1"]. createInstance(Components.interfaces.nsIUpdatePrompt);
// If there's an update ready to be applied, show the "Update Downloaded" // UI instead
and let the user know they have to restart the browser for // the changes to be applied.
if (um.activeUpdate && um.activeUpdate.state == "pending") prompter.showUpdateDownloaded(um.activeUpdate);
else prompter.checkForUpdates(); //@line 494 "e:\builds\moz2_slave\win32_build\build\browser\base\content\utilityOverlay.js"
function buildHelpMenu() // Enable/disable the "Report Web Forgery" menu item. safebrowsing
object // may not exist in OSX if (typeof safebrowsing != "undefined") safebrowsing.setReportPhishingMenu();
//@line 503 "e:\builds\moz2_slave\win32_build\build\browser\base\content\utilityOverlay.js" var updates = Components.classes["@mozilla.org/updates/update-service;1"].
getService(Components.interfaces.nsIApplicationUpdateService2); var um = Components.classes["@mozilla.org/updates/update-manager;1"].
getService(Components.interfaces.nsIUpdateManager); // Disable the UI if the update enabled pref
has been locked by the // administrator or if we cannot update for some other reason
var checkForUpdates = document.getElementById("checkForUpdates"); var canCheckForUpdates = updates.canCheckForUpdates;
checkForUpdates.setAttribute("disabled", !canCheckForUpdates); if (!canCheckForUpdates) return; var strings
= document.getElementById("bundle_browser"); var activeUpdate = um.activeUpdate; // If
there's an active update, substitute its name into the label // we show for this item, otherwise
display a generic label. function getStringWithUpdateName(key) { if (activeUpdate && activeUpdate.name)
return strings.getFormattedString(key, [activeUpdate.name]); return strings.getString(key + "Fallback");
// By default, show "Check for Updates..." var key = "default"; if (activeUpdate) {
switch (activeUpdate.state) { case "downloading": // If we're downloading an update at present,
show the text: // "Downloading Firefox x.x..." otherwise we're paused, and show // "Resume
Downloading Firefox x.x..." key = updates.isDownloading ? "downloading" : "resume"; break; case "pending":
// If we're waiting for the user to restart, show: "Apply Downloaded // Updates Now..."
key = "pending"; break; } checkForUpdates.label = getStringWithUpdateName("updatesItem_"
+ key); checkForUpdates.accessKey = strings.getString("updatesItem_" + key + ".accesskey"); if (um.activeUpdate
&& updates.isDownloading) checkForUpdates.setAttribute("loading", "true"); else checkForUpdates.removeAttribute("loading");
//@line 556 "e:\builds\moz2_slave\win32_build\build\browser\base\content\utilityOverlay.js" function isElementVisible(aElement) if (!aElement)
return false; // If aElement or a direct or indirect parent is hidden or collapsed, //
height, width or both will be 0. var bo = aElement.boxObject; return (bo.height >
0 && bo.width > 0); function makeURLAbsolute(aBase, aUrl) // Note: makeURI() will throw if aUri
is not a valid URI return makeURI(aUrl, null, makeURI(aBase)).spec; function getBrowserFromContentWindow(aContentWindow)
var browsers = gBrowser.browsers; for (var i = 0; i < browsers.length; i++) { if (browsers[i].contentWindow
== aContentWindow) return browsers[i]; return null; * openNewTabWith: opens a new tab with
the given URL. * @param aURL * The URL to open (as a string). * @param aDocument *
The document from which the URL came, or null. This is used to set the * referrer header
and to do a security check of whether the document is * allowed to reference the URL.
If null, there will be no referrer * header and no security check. * @param aPostData
* Form POST data, or null. * @param aEvent * The triggering event (for the purpose of
determining whether to open * in the background), or null. * @param aAllowThirdPartyFixup *
If true, then we allow the URL text to be sent to third party services * (e.g., Google's
I Feel Lucky) for interpretation. This parameter may * be undefined in which case it is treated
as false. * @param [optional] aReferrer * If aDocument is null, then this will be used
as the referrer. * There will be no security check. */ function openNewTabWith(aURL, aDocument,
aPostData, aEvent, aAllowThirdPartyFixup, aReferrer) if (aDocument) urlSecurityCheck(aURL,
aDocument.nodePrincipal); var prefSvc = Components.classes["@mozilla.org/preferences-service;1"] .getService(Components.interfaces.nsIPrefService);
prefSvc = prefSvc.getBranch(null); // should we open it in a new tab? var loadInBackground
= true; try { loadInBackground = prefSvc.getBoolPref("browser.tabs.loadInBackground"); catch(ex) { if (aEvent && aEvent.shiftKey)
loadInBackground = !loadInBackground; // As in openNewWindowWith(), we want to pass
the charset of the // current document over to a new tab. var wintype = document.documentElement.getAttribute("windowtype");
var originCharset; if (wintype == "navigator:browser") originCharset = window.content.document.characterSet;
// open link in new tab var referrerURI = aDocument ? aDocument.documentURIObject
: aReferrer; var browser = top.document.getElementById("content"); return browser.loadOneTab(aURL, { referrerURI:
referrerURI, charset: originCharset, postData: aPostData, inBackground: loadInBackground,
allowThirdPartyFixup: aAllowThirdPartyFixup}); function openNewWindowWith(aURL, aDocument,
aPostData, aAllowThirdPartyFixup, aReferrer) if (aDocument) urlSecurityCheck(aURL, aDocument.nodePrincipal);
// if and only if the current window is a browser window and it has a // document with
a character set, then extract the current charset menu // setting from the current document
and use it to initialize the new browser // window... var charsetArg = null; var wintype
= document.documentElement.getAttribute("windowtype"); if (wintype == "navigator:browser") charsetArg
= "charset=" + window.content.document.characterSet; var referrerURI = aDocument ? aDocument.documentURIObject
: aReferrer; return window.openDialog(getBrowserURL(), "_blank", "chrome,all,dialog=no", aURL, charsetArg,
referrerURI, aPostData, aAllowThirdPartyFixup); * isValidFeed: checks whether the given data
represents a valid feed. * @param aLink * An object representing a feed with title,
href and type. * @param aPrincipal * The principal of the document, used for security check.
* @param aIsFeed * Whether this is already a known feed or not, if true only a security
* check will be performed. */ function isValidFeed(aLink, aPrincipal, aIsFeed) if (!aLink || !aPrincipal)
return false; var type = aLink.type.toLowerCase().replace(/^\s+|\s*(?:;.*)?$/g, ""); if (!aIsFeed) { aIsFeed = (type ==
"application/rss+xml" || type == "application/atom+xml"); if (aIsFeed) { try { urlSecurityCheck(aLink.href,
aPrincipal, Components.interfaces.nsIScriptSecurityManager.DISALLOW_INHERIT_PRINCIPAL); return type || "application/rss+xml"; } catch(ex)
{ } return null; // aCalledFromModal is optional function openHelpLink(aHelpTopic, aCalledFromModal)
{ var url = Components.classes["@mozilla.org/toolkit/URLFormatterService;1"] .getService(Components.interfaces.nsIURLFormatter)
.formatURLPref("app.support.baseURL"); url += aHelpTopic; var where = aCalledFromModal
? "window" : "tab"; openUILinkIn(url, where); function openPrefsHelp() { var prefs = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch2); // non-instant apply prefwindows are usually
modal, so we can't open in the topmost window, // since its probably behind the window.
var instantApply = prefs.getBoolPref("browser.preferences.instantApply"); var helpTopic = document.getElementsByTagName("prefwindow")[0].currentPane.helpTopic;
openHelpLink(helpTopic, !instantApply); content/browser/web-panels.js//@line 39 "e:\builds\moz2_slave\win32_build\build\browser\base\content\web-panels.js"
const NS_ERROR_MODULE_NETWORK = 2152398848; const NS_NET_STATUS_READ_FROM = NS_ERROR_MODULE_NETWORK
+ 8; const NS_NET_STATUS_WROTE_TO = NS_ERROR_MODULE_NETWORK + 9; function getPanelBrowser() return document.getElementById("web-panels-browser");
var panelProgressListener = { onProgressChange : function (aWebProgress, aRequest, aCurSelfProgress,
aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress) { }, onStateChange : function(aWebProgress,
aRequest, aStateFlags, aStatus) { if (!aRequest) return; //ignore local/resource:/chrome: files
if (aStatus == NS_NET_STATUS_READ_FROM || aStatus == NS_NET_STATUS_WROTE_TO) return;
if (aStateFlags & Ci.nsIWebProgressListener.STATE_START && aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK)
{ window.parent.document.getElementById('sidebar-throbber').setAttribute("loading", "true"); } else if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP
&& aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK) { window.parent.document.getElementById('sidebar-throbber').removeAttribute("loading");
} } , onLocationChange : function(aWebProgress, aRequest, aLocation) { UpdateBackForwardCommands(getPanelBrowser().webNavigation);
}, onStatusChange : function(aWebProgress, aRequest, aStatus, aMessage) { }, onSecurityChange
: function(aWebProgress, aRequest, aState) { }, QueryInterface : function(aIID) { if
(aIID.equals(Ci.nsIWebProgressListener) || aIID.equals(Ci.nsISupportsWeakReference)
|| aIID.equals(Ci.nsISupports)) return this; throw Cr.NS_NOINTERFACE; } var gLoadFired
= false; function loadWebPanel(aURI) { var panelBrowser = getPanelBrowser(); if (gLoadFired)
{ panelBrowser.webNavigation .loadURI(aURI, nsIWebNavigation.LOAD_FLAGS_NONE, null, null,
null); } panelBrowser.setAttribute("cachedurl", aURI); function load() var panelBrowser =
getPanelBrowser(); panelBrowser.webProgress.addProgressListener(panelProgressListener, Ci.nsIWebProgress.NOTIFY_ALL); if (panelBrowser.getAttribute("cachedurl"))
{ panelBrowser.webNavigation .loadURI(panelBrowser.getAttribute("cachedurl"), nsIWebNavigation.LOAD_FLAGS_NONE, null, null,
null); } gLoadFired = true; function unload() getPanelBrowser().webProgress.removeProgressListener(panelProgressListener);
function PanelBrowserStop() getPanelBrowser().webNavigation.stop(nsIWebNavigation.STOP_ALL) function PanelBrowserReload() getPanelBrowser().webNavigation
.sessionHistory .QueryInterface(nsIWebNavigation) .reload(nsIWebNavigation.LOAD_FLAGS_NONE);
%textcontextDTD;
content/browser/baseMenuOverlay.xul
%baseMenuOverlayDTD;
content/browser/nsContextMenu.js//@line
62 "e:\builds\moz2_slave\win32_build\build\browser\base\content\nsContextMenu.js" function nsContextMenu(aXulMenu, aBrowser)
{ this.target = null; this.browser = null; this.menu = null; this.isFrameImage = false;
this.onTextInput = false; this.onKeywordField = false; this.onImage = false; this.onLoadedImage
= false; this.onCompletedImage = false; this.onCanvas = false; this.onVideo = false; this.onAudio
= false; this.onLink = false; this.onMailtoLink = false; this.onSaveableLink = false; this.onMathML
= false; this.link = false; this.linkURL = ""; this.linkURI = null; this.linkProtocol
= null; this.inFrame = false; this.hasBGImage = false; this.isTextSelected = false; this.isContentSelected
= false; this.shouldDisplay = true; this.isDesignMode = false; this.onEditableArea = false; this.ellipsis
= "\u2026"; try { this.ellipsis = gPrefService.getComplexValue("intl.ellipsis", Ci.nsIPrefLocalizedString).data; } catch (e)
{ } // Initialize new menu. this.initMenu(aXulMenu, aBrowser); // Prototype for nsContextMenu
"class." nsContextMenu.prototype = { // onDestroy is a no-op at this point. onDestroy: function
() { }, // Initialize context menu. initMenu: function CM_initMenu(aPopup, aBrowser) {
this.menu = aPopup; this.browser = aBrowser; this.isFrameImage = document.getElementById("isFrameImage");
// Get contextual info. this.setTarget(document.popupNode, document.popupRangeParent, document.popupRangeOffset);
this.isTextSelected = this.isTextSelection(); this.isContentSelected = this.isContentSelection();
// Initialize (disable/remove) menu items. this.initItems(); }, initItems: function CM_initItems()
{ this.initOpenItems(); this.initNavigationItems(); this.initViewItems(); this.initMiscItems();
this.initSpellingItems(); this.initSaveItems(); this.initClipboardItems(); this.initMediaPlayerItems();
}, initOpenItems: function CM_initOpenItems() { var isMailtoInternal = false; if (this.onMailtoLink)
{ var mailtoHandler = Cc["@mozilla.org/uriloader/external-protocol-service;1"]. getService(Ci.nsIExternalProtocolService).
getProtocolHandlerInfo("mailto"); isMailtoInternal = (!mailtoHandler.alwaysAskBeforeHandling
&& mailtoHandler.preferredAction == Ci.nsIHandlerInfo.useHelperApp && (mailtoHandler.preferredApplicationHandler
instanceof Ci.nsIWebHandlerApp)); } var shouldShow = this.onSaveableLink || isMailtoInternal;
this.showItem("context-openlink", shouldShow); this.showItem("context-openlinkintab", shouldShow);
this.showItem("context-sep-open", shouldShow); }, initNavigationItems: function CM_initNavigationItems()
{ var shouldShow = !(this.isContentSelected || this.onLink || this.onImage || this.onCanvas
|| this.onVideo || this.onAudio || this.onTextInput); this.showItem("context-back", shouldShow);
this.showItem("context-forward", shouldShow); this.showItem("context-reload", shouldShow);
this.showItem("context-stop", shouldShow); this.showItem("context-sep-stop", shouldShow);
// ***: Stop is determined in browser.js; the canStop broadcaster is broken //this.setItemAttrFromNode(
"context-stop", "disabled", "canStop" ); }, initSaveItems: function CM_initSaveItems()
{ var shouldShow = !(this.onTextInput || this.onLink || this.isContentSelected ||
this.onImage || this.onCanvas || this.onVideo || this.onAudio); this.showItem("context-savepage",
shouldShow); this.showItem("context-sendpage", shouldShow); // Save+Send link depends on
whether we're in a link. this.showItem("context-savelink", this.onSaveableLink); this.showItem("context-sendlink",
this.onSaveableLink); // Save image depends on having loaded its content, video and audio
don't. this.showItem("context-saveimage", this.onLoadedImage || this.onCanvas); this.showItem("context-savevideo",
this.onVideo); this.showItem("context-saveaudio", this.onAudio); this.setItemAttr("context-savevideo",
"disabled", !this.mediaURL); this.setItemAttr("context-saveaudio", "disabled", !this.mediaURL); // Send media
URL (but not for canvas, since it's a big data: URL) this.showItem("context-sendimage",
this.onImage); this.showItem("context-sendvideo", this.onVideo); this.showItem("context-sendaudio",
this.onAudio); this.setItemAttr("context-sendvideo", "disabled", !this.mediaURL); this.setItemAttr("context-sendaudio",
"disabled", !this.mediaURL); }, initViewItems: function CM_initViewItems() { // View source
is always OK, unless in directory listing. this.showItem("context-viewpartialsource-selection",
this.isContentSelected); this.showItem("context-viewpartialsource-mathml", this.onMathML && !this.isContentSelected);
var shouldShow = !(this.isContentSelected || this.onImage || this.onCanvas || this.onVideo
|| this.onAudio || this.onLink || this.onTextInput); this.showItem("context-viewsource", shouldShow);
this.showItem("context-viewinfo", shouldShow); this.showItem("context-sep-viewsource", shouldShow);
// Set as Desktop background depends on whether an image was clicked on, // and only works
if we have a shell service. var haveSetDesktopBackground = false; //@line 211 "e:\builds\moz2_slave\win32_build\build\browser\base\content\nsContextMenu.js"
// Only enable Set as Desktop Background if we can get the shell service. var shell
= getShellService(); if (shell) haveSetDesktopBackground = true; //@line 216 "e:\builds\moz2_slave\win32_build\build\browser\base\content\nsContextMenu.js"
this.showItem("context-setDesktopBackground", haveSetDesktopBackground && this.onLoadedImage);
if (haveSetDesktopBackground && this.onLoadedImage) { document.getElementById("context-setDesktopBackground")
.disabled = this.disableSetDesktopBackground(); } // Reload image depends on an image that's
not fully loaded this.showItem("context-reloadimage", (this.onImage && !this.onCompletedImage));
// View image depends on having an image that's not standalone // (or is in a frame),
or a canvas. this.showItem("context-viewimage", (this.onImage && (!this.onStandaloneImage
|| this.inFrame)) || this.onCanvas); this.showItem("context-viewvideo", this.onVideo); this.setItemAttr("context-viewvideo",
"disabled", !this.mediaURL); // View background image depends on whether there is one. this.showItem("context-viewbgimage",
shouldShow && !this._hasMultipleBGImages); this.showItem("context-sep-viewbgimage", shouldShow
&& !this._hasMultipleBGImages); document.getElementById("context-viewbgimage") .disabled = !this.hasBGImage; this.showItem("context-viewimageinfo",
this.onImage); }, initMiscItems: function CM_initMiscItems() { var isTextSelected =
this.isTextSelected; // Use "Bookmark This Link" if on a link. this.showItem("context-bookmarkpage",
!(this.isContentSelected || this.onTextInput || this.onLink || this.onImage || this.onVideo
|| this.onAudio)); this.showItem("context-bookmarklink", this.onLink && !this.onMailtoLink); this.showItem("context-searchselect",
isTextSelected); this.showItem("context-keywordfield", this.onTextInput && this.onKeywordField);
this.showItem("frame", this.inFrame); this.showItem("frame-sep", this.inFrame && isTextSelected); // Hide menu
entries for images, show otherwise if (this.inFrame) { if (mimeTypeIsTextBased(this.target.ownerDocument.contentType))
this.isFrameImage.removeAttribute('hidden'); else this.isFrameImage.setAttribute('hidden',
'true'); } // BiDi UI this.showItem("context-sep-bidi", top.gBidiUI); this.showItem("context-bidi-text-direction-toggle",
this.onTextInput && top.gBidiUI); this.showItem("context-bidi-page-direction-toggle", !this.onTextInput && top.gBidiUI); if (this.onImage)
{ var blockImage = document.getElementById("context-blockimage"); var uri = this.target .QueryInterface(Ci.nsIImageLoadingContent)
.currentURI; // this throws if the image URI doesn't have a host (eg, data: image URIs)
// see bug 293758 for details var hostLabel = ""; try { hostLabel = uri.host; } catch
(ex) { } if (hostLabel) { var shortenedUriHost = hostLabel.replace(/^www\./i,""); if (shortenedUriHost.length
> 15) shortenedUriHost = shortenedUriHost.substr(0,15) + this.ellipsis; blockImage.label = gNavigatorBundle.getFormattedString("blockImages",
[shortenedUriHost]); if (this.isImageBlocked()) blockImage.setAttribute("checked", "true");
else blockImage.removeAttribute("checked"); } } // Only show the block image item if
the image can be blocked this.showItem("context-blockimage", this.onImage && hostLabel && !gPrivateBrowsingUI.privateBrowsingEnabled);
}, initSpellingItems: function() { var canSpell = InlineSpellCheckerUI.canSpellCheck; var
onMisspelling = InlineSpellCheckerUI.overMisspelling; this.showItem("spell-check-enabled", canSpell);
this.showItem("spell-separator", canSpell || this.onEditableArea); if (canSpell) {
document.getElementById("spell-check-enabled") .setAttribute("checked", InlineSpellCheckerUI.enabled);
} this.showItem("spell-add-to-dictionary", onMisspelling); // suggestion list this.showItem("spell-suggestions-separator",
onMisspelling); if (onMisspelling) { var menu = document.getElementById("contentAreaContextMenu");
var suggestionsSeparator = document.getElementById("spell-add-to-dictionary"); var numsug = InlineSpellCheckerUI.addSuggestionsToMenu(menu,
suggestionsSeparator, 5); this.showItem("spell-no-suggestions", numsug == 0); } else this.showItem("spell-no-suggestions",
false); // dictionary list this.showItem("spell-dictionaries", InlineSpellCheckerUI.enabled); if (canSpell)
{ var dictMenu = document.getElementById("spell-dictionaries-menu"); var dictSep = document.getElementById("spell-language-separator");
InlineSpellCheckerUI.addDictionaryListToMenu(dictMenu, dictSep); this.showItem("spell-add-dictionaries-main",
false); } else if (this.onEditableArea) { // when there is no spellchecker but we might
be able to spellcheck // add the add to dictionaries item. This will ensure that people // with
no dictionaries will be able to download them this.showItem("spell-add-dictionaries-main",
true); } else this.showItem("spell-add-dictionaries-main", false); }, initClipboardItems: function()
{ // Copy depends on whether there is selected text. // Enabling this context menu item is
now done through the global // command updating system // this.setItemAttr( "context-copy",
"disabled", !this.isTextSelected() ); goUpdateGlobalEditMenuItems(); this.showItem("context-undo", this.onTextInput);
this.showItem("context-sep-undo", this.onTextInput); this.showItem("context-cut", this.onTextInput);
this.showItem("context-copy", this.isContentSelected || this.onTextInput); this.showItem("context-paste",
this.onTextInput); this.showItem("context-delete", this.onTextInput); this.showItem("context-sep-paste",
this.onTextInput); this.showItem("context-selectall", !(this.onLink || this.onImage || this.onVideo
|| this.onAudio) || this.isDesignMode); this.showItem("context-sep-selectall", this.isContentSelected ); // *** dr // ------
// nsDocumentViewer.cpp has code to determine whether we're // on a link or an image. we
really ought to be using that... // Copy email link depends on whether we're on an email
link. this.showItem("context-copyemail", this.onMailtoLink); // Copy link location depends on whether
we're on a non-mailto link. this.showItem("context-copylink", this.onLink && !this.onMailtoLink); this.showItem("context-sep-copylink",
this.onLink && (this.onImage || this.onVideo || this.onAudio)); //@line 380 "e:\builds\moz2_slave\win32_build\build\browser\base\content\nsContextMenu.js"
// Copy image contents depends on whether we're on an image. this.showItem("context-copyimage-contents",
this.onImage); //@line 383 "e:\builds\moz2_slave\win32_build\build\browser\base\content\nsContextMenu.js" // Copy image location depends on whether
we're on an image. this.showItem("context-copyimage", this.onImage); this.showItem("context-copyvideourl",
this.onVideo); this.showItem("context-copyaudiourl", this.onAudio); this.setItemAttr("context-copyvideourl",
"disabled", !this.mediaURL); this.setItemAttr("context-copyaudiourl", "disabled", !this.mediaURL); this.showItem("context-sep-copyimage",
this.onImage || this.onVideo || this.onAudio); }, initMediaPlayerItems: function() { var
onMedia = (this.onVideo || this.onAudio); // Several mutually exclusive items... play/pause,
mute/unmute, show/hide this.showItem("context-media-play", onMedia && (this.target.paused || this.target.ended));
this.showItem("context-media-pause", onMedia && !this.target.paused && !this.target.ended);
this.showItem("context-media-mute", onMedia && !this.target.muted); this.showItem("context-media-unmute",
onMedia && this.target.muted); this.showItem("context-media-showcontrols", onMedia && !this.target.controls); this.showItem("context-media-hidecontrols",
onMedia && this.target.controls); this.showItem("context-video-fullscreen", this.onVideo); // Disable them when there
isn't a valid media source loaded. if (onMedia) { var hasError = (this.target.error != null);
this.setItemAttr("context-media-play", "disabled", hasError); this.setItemAttr("context-media-pause",
"disabled", hasError); this.setItemAttr("context-media-mute", "disabled", hasError); this.setItemAttr("context-media-unmute",
"disabled", hasError); this.setItemAttr("context-media-showcontrols", "disabled", hasError); this.setItemAttr("context-media-hidecontrols",
"disabled", hasError); if (this.onVideo) this.setItemAttr("context-video-fullscreen", "disabled", hasError); } this.showItem("context-media-sep-commands",
onMedia); }, // 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 || this.isTargetAFormControl(aNode)) { this.shouldDisplay = false; } // Initialize
contextual info. this.onImage = false; this.onLoadedImage = false; this.onCompletedImage = false; this.onStandaloneImage
= false; this.onCanvas = false; this.onVideo = false; this.onAudio = false; this.onTextInput
= false; this.onKeywordField = false; this.mediaURL = ""; this.onLink = false; this.linkURL
= ""; this.linkURI = null; this.linkProtocol = ""; this.onMathML = false; this.inFrame
= false; this.hasBGImage = false; this.bgImageURL = ""; this.onEditableArea = false; // Clear
any old spellchecking items from the menu, this used to // be in the menu hiding code
but wasn't getting called in all // situations. Here, we can ensure it gets cleaned up any
time the // menu is shown. Note: must be before uninit because that clears the // internal
vars InlineSpellCheckerUI.clearSuggestionsFromMenu(); InlineSpellCheckerUI.clearDictionaryListFromMenu();
InlineSpellCheckerUI.uninit(); // Remember the node that was clicked. this.target =
aNode; // First, do checks for nodes that never have children. if (this.target.nodeType
== Node.ELEMENT_NODE) { // See if the user clicked on an image. if (this.target instanceof
Ci.nsIImageLoadingContent && this.target.currentURI) { this.onImage = true; var request = this.target.getRequest(Ci.nsIImageLoadingContent.CURRENT_REQUEST);
if (request && (request.imageStatus & request.STATUS_SIZE_AVAILABLE)) this.onLoadedImage = true; if (request &&
(request.imageStatus & request.STATUS_LOAD_COMPLETE)) this.onCompletedImage = true; this.mediaURL
= this.target.currentURI.spec; if (this.target.ownerDocument instanceof ImageDocument) this.onStandaloneImage
= true; } else if (this.target instanceof HTMLCanvasElement) { this.onCanvas = true;
} else if (this.target instanceof HTMLVideoElement) { this.onVideo = true; this.mediaURL = this.target.currentSrc
|| this.target.src; } else if (this.target instanceof HTMLAudioElement) { this.onAudio
= true; this.mediaURL = this.target.currentSrc || this.target.src; } else if (this.target
instanceof HTMLInputElement ) { this.onTextInput = this.isTargetATextBox(this.target); //
allow spellchecking UI on all writable text boxes except passwords if (this.onTextInput
&& ! this.target.readOnly && this.target.type != "password") { this.onEditableArea = true;
InlineSpellCheckerUI.init(this.target.QueryInterface(Ci.nsIDOMNSEditableElement).editor); InlineSpellCheckerUI.initFromEvent(aRangeParent,
aRangeOffset); } this.onKeywordField = this.isTargetAKeywordField(this.target); } else if (this.target instanceof HTMLTextAreaElement)
{ this.onTextInput = true; if (!this.target.readOnly) { this.onEditableArea = true; InlineSpellCheckerUI.init(this.target.QueryInterface(Ci.nsIDOMNSEditableElement).editor);
InlineSpellCheckerUI.initFromEvent(aRangeParent, aRangeOffset); } } else if (this.target instanceof
HTMLHtmlElement) { var bodyElt = this.target.ownerDocument.body; if (bodyElt) { let computedURL; try { computedURL
= this.getComputedURL(bodyElt, "background-image"); this._hasMultipleBGImages = false; } catch
(e) { this._hasMultipleBGImages = true; } if (computedURL) { this.hasBGImage = true;
this.bgImageURL = makeURLAbsolute(bodyElt.baseURI, computedURL); } } } } // Second, bubble out,
looking for items of interest that can have childen. // Always pick the innermost link,
background image, etc. const XMLNS = "http://www.w3.org/XML/1998/namespace"; var elem = this.target; while (elem) { if
(elem.nodeType == Node.ELEMENT_NODE) { // Link? if (!this.onLink && ((elem instanceof
HTMLAnchorElement && elem.href) || (elem instanceof HTMLAreaElement && elem.href) || elem instanceof
HTMLLinkElement || elem.getAttributeNS("http://www.w3.org/1999/xlink", "type") == "simple")) { // Target is a link
or a descendant of a link. this.onLink = true; // xxxmpc: this is kind of a hack to
work around a Gecko bug (see bug 266932) // we're going to walk up the DOM looking
for a parent link node, // this shouldn't be necessary, but we're matching the existing
behaviour for left click var realLink = elem; var parent = elem; while ((parent = parent.parentNode)
&& (parent.nodeType == Node.ELEMENT_NODE)) { try { if ((parent instanceof HTMLAnchorElement
&& parent.href) || (parent instanceof HTMLAreaElement && parent.href) || parent instanceof HTMLLinkElement
|| parent.getAttributeNS("http://www.w3.org/1999/xlink", "type") == "simple") realLink = parent; }
catch (e) { } } // Remember corresponding element. this.link = realLink; this.linkURL
= this.getLinkURL(); this.linkURI = this.getLinkURI(); this.linkProtocol = this.getLinkProtocol();
this.onMailtoLink = (this.linkProtocol == "mailto"); this.onSaveableLink = this.isLinkSaveable(
this.link ); } // Background image? Don't bother if we've already found a // background
image further down the hierarchy. Otherwise, // we look for the computed background-image
style. if (!this.hasBGImage && !this._hasMultipleBGImages) { let bgImgUrl; try { bgImgUrl = this.getComputedURL(elem,
"background-image"); this._hasMultipleBGImages = false; } catch (e) { this._hasMultipleBGImages
= true; } if (bgImgUrl) { this.hasBGImage = true; this.bgImageURL = makeURLAbsolute(elem.baseURI,
bgImgUrl); } } } elem = elem.parentNode; } // See if the user clicked on MathML const
NS_MathML = "http://www.w3.org/1998/Math/MathML"; if ((this.target.nodeType == Node.TEXT_NODE
&& this.target.parentNode.namespaceURI == NS_MathML) || (this.target.namespaceURI
== NS_MathML)) this.onMathML = true; // See if the user clicked in a frame. var docDefaultView
= this.target.ownerDocument.defaultView; if (docDefaultView != docDefaultView.top)
this.inFrame = true; // if the document is editable, show context menu like in text inputs
if (!this.onEditableArea) { var win = this.target.ownerDocument.defaultView; if (win) { var isEditable = false; try {
var editingSession = win.QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsIWebNavigation) .QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIEditingSession); if (editingSession.windowIsEditable(win) && this.getComputedStyle(this.target, "-moz-user-modify")
== "read-write") { isEditable = true; } } catch(ex) { // If someone built with composer
disabled, we can't get an editing session. } if (isEditable) { this.onTextInput = true;
this.onKeywordField = false; this.onImage = false; this.onLoadedImage = false; this.onCompletedImage
= false; this.onMathML = false; this.inFrame = false; this.hasBGImage = false; this.isDesignMode
= true; this.onEditableArea = true; InlineSpellCheckerUI.init(editingSession.getEditorForWindow(win)); var canSpell = InlineSpellCheckerUI.canSpellCheck;
InlineSpellCheckerUI.initFromEvent(aRangeParent, aRangeOffset); this.showItem("spell-check-enabled",
canSpell); this.showItem("spell-separator", canSpell); } } } }, // Returns the computed
style attribute for the given element. getComputedStyle: function(aElem, aProp) { return aElem.ownerDocument
.defaultView .getComputedStyle(aElem, "").getPropertyValue(aProp); }, // Returns a "url"-type computed style
attribute value, with the url() stripped. getComputedURL: function(aElem, aProp) {
var url = aElem.ownerDocument .defaultView.getComputedStyle(aElem, "") .getPropertyCSSValue(aProp); if (url
instanceof CSSValueList) { if (url.length != 1) throw "found multiple URLs"; url =
url[0]; } return url.primitiveType == CSSPrimitiveValue.CSS_URI ? url.getStringValue() : null; }, // Returns
true if clicked-on link targets a resource that can be saved. isLinkSaveable: function(aLink)
{ // We don't do the Right Thing for news/snews yet, so turn them off // until we do. return
this.linkProtocol && !( this.linkProtocol == "mailto" || this.linkProtocol == "javascript"
|| this.linkProtocol == "news" || this.linkProtocol == "snews" ); }, // Open linked-to URL in
a new window. openLink : function () { openNewWindowWith(this.linkURL, this.target.ownerDocument, null, false);
}, // Open linked-to URL in a new tab. openLinkInTab: function() { openNewTabWith(this.linkURL,
this.target.ownerDocument, null, null, false); }, // Open frame in a new tab. openFrameInTab:
function() { var doc = this.target.ownerDocument; var frameURL = doc.location.href; var referrer
= doc.referrer; return openNewTabWith(frameURL, null, null, null, false, referrer ? makeURI(referrer)
: null); }, // Reload clicked-in frame. reloadFrame: function() { this.target.ownerDocument.location.reload();
}, // Open clicked-in frame in its own window. openFrame: function() { var doc = this.target.ownerDocument;
var frameURL = doc.location.href; var referrer = doc.referrer; return openNewWindowWith(frameURL,
null, null, false, referrer ? makeURI(referrer) : null); }, // Open clicked-in frame in the
same window. showOnlyThisFrame: function() { var doc = this.target.ownerDocument; var
frameURL = doc.location.href; urlSecurityCheck(frameURL, this.browser.contentPrincipal, Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT);
var referrer = doc.referrer; this.browser.loadURI(frameURL, referrer ? makeURI(referrer) : null); },
// View Partial Source viewPartialSource: function(aContext) { var focusedWindow =
document.commandDispatcher.focusedWindow; if (focusedWindow == window) focusedWindow
= content; var docCharset = null; if (focusedWindow) docCharset = "charset=" + focusedWindow.document.characterSet;
// "View Selection Source" and others such as "View MathML Source" // are mutually exclusive,
with the precedence given to the selection // when there is one var reference = null;
if (aContext == "selection") reference = focusedWindow.getSelection(); else if (aContext
== "mathml") reference = this.target; else throw "not reached"; // unused (and play nice
for fragments generated via XSLT too) var docUrl = null; window.openDialog("chrome://global/content/viewPartialSource.xul",
"_blank", "scrollbars,resizable,chrome,dialog=no", docUrl, docCharset, reference, aContext);
}, // Open new "view source" window with the frame's URL. viewFrameSource: function()
{ BrowserViewSourceOfDocument(this.target.ownerDocument); }, viewInfo: function() { BrowserPageInfo(this.target.ownerDocument.defaultView.top.document);
}, viewImageInfo: function() { BrowserPageInfo(this.target.ownerDocument.defaultView.top.document, "mediaTab", this.target); }, viewFrameInfo:
function() { BrowserPageInfo(this.target.ownerDocument); }, reloadImage: function(e) { urlSecurityCheck(this.mediaURL,
this.browser.contentPrincipal, Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT); if (this.target instanceof Ci.nsIImageLoadingContent)
this.target.forceReload(); }, // Change current window to the URL of the image, video, or
audio. viewMedia: function(e) { var viewURL; if (this.onCanvas) viewURL = this.target.toDataURL();
else { viewURL = this.mediaURL; urlSecurityCheck(viewURL, this.browser.contentPrincipal, Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT);
} var doc = this.target.ownerDocument; openUILink(viewURL, e, null, null, null, null, doc.documentURIObject
); }, fullScreenVideo: function () { this.target.pause(); openDialog("chrome://browser/content/fullscreen-video.xhtml",
"", "chrome,dialog=no", this.target); }, // Change current window to the URL of the
background image. viewBGImage: function(e) { urlSecurityCheck(this.bgImageURL, this.browser.contentPrincipal,
Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT); var doc = this.target.ownerDocument; openUILink(this.bgImageURL,
e, null, null, null, null, doc.documentURIObject ); }, disableSetDesktopBackground: function()
{ // Disable the Set as Desktop Background menu item if we're still trying // to load
the image or the load failed. if (!(this.target instanceof Ci.nsIImageLoadingContent)) return
true; if (("complete" in this.target) && !this.target.complete) return true; if (this.target.currentURI.schemeIs("javascript"))
return true; var request = this.target .QueryInterface(Ci.nsIImageLoadingContent) .getRequest(Ci.nsIImageLoadingContent.CURRENT_REQUEST);
if (!request) return true; return false; }, setDesktopBackground: function() { //
Paranoia: check disableSetDesktopBackground again, in case the // image changed since
the context menu was initiated. if (this.disableSetDesktopBackground()) return; urlSecurityCheck(this.target.currentURI.spec,
this.target.ownerDocument.nodePrincipal); // Confirm since it's annoying if you hit
this accidentally. const kDesktopBackgroundURL = "chrome://browser/content/setDesktopBackground.xul";
//@line 858 "e:\builds\moz2_slave\win32_build\build\browser\base\content\nsContextMenu.js" // On non-Mac platforms, the Set Wallpaper
dialog is modal. openDialog(kDesktopBackgroundURL, "", "centerscreen,chrome,dialog,modal,dependent",
this.target); //@line 863 "e:\builds\moz2_slave\win32_build\build\browser\base\content\nsContextMenu.js" }, // Save URL of clicked-on frame. saveFrame:
function () { saveDocument(this.target.ownerDocument); }, // Save URL of clicked-on link. saveLink:
function() { // canonical def in nsURILoader.h const NS_ERROR_SAVE_LINK_AS_TIMEOUT = 0x805d0020;
var doc = this.target.ownerDocument; urlSecurityCheck(this.linkURL, doc.nodePrincipal); var linkText = this.linkText();
var linkURL = this.linkURL; // an object to proxy the data through to // nsIExternalHelperAppService.doContent,
which will wait for the // appropriate MIME-type headers and then prompt the user with a //
file picker function saveAsListener() {} saveAsListener.prototype = { extListener:
null, onStartRequest: function saveLinkAs_onStartRequest(aRequest, aContext) { // if the timer fired, the error
status will have been caused by that, // and we'll be restarting in onStopRequest,
so no reason to notify // the user if (aRequest.status == NS_ERROR_SAVE_LINK_AS_TIMEOUT) return;
timer.cancel(); // some other error occured; notify the user... if (!Components.isSuccessCode(aRequest.status))
{ try { const sbs = Cc["@mozilla.org/intl/stringbundle;1"]. getService(Ci.nsIStringBundleService); const
bundle = sbs.createBundle( "chrome://mozapps/locale/downloads/downloads.properties"); const title = bundle.GetStringFromName("downloadErrorAlertTitle");
const msg = bundle.GetStringFromName("downloadErrorGeneric"); const promptSvc = Cc["@mozilla.org/embedcomp/prompt-service;1"].
getService(Ci.nsIPromptService); promptSvc.alert(doc.defaultView, title, msg); } catch (ex) {} return; } var
extHelperAppSvc = Cc["@mozilla.org/uriloader/external-helper-app-service;1"]. getService(Ci.nsIExternalHelperAppService);
var channel = aRequest.QueryInterface(Ci.nsIChannel); this.extListener = extHelperAppSvc.doContent(channel.contentType,
aRequest, doc.defaultView, true); this.extListener.onStartRequest(aRequest, aContext); }, onStopRequest: function saveLinkAs_onStopRequest(aRequest,
aContext, aStatusCode) { if (aStatusCode == NS_ERROR_SAVE_LINK_AS_TIMEOUT) { // do
it the old fashioned way, which will pick the best filename // it can without waiting.
saveURL(linkURL, linkText, null, true, false, doc.documentURIObject); } if (this.extListener)
this.extListener.onStopRequest(aRequest, aContext, aStatusCode); }, onDataAvailable: function
saveLinkAs_onDataAvailable(aRequest, aContext, aInputStream, aOffset, aCount) { this.extListener.onDataAvailable(aRequest,
aContext, aInputStream, aOffset, aCount); } } // in case we need to prompt the user
for authentication function callbacks() {} callbacks.prototype = { getInterface: function
sLA_callbacks_getInterface(aIID) { if (aIID.equals(Ci.nsIAuthPrompt) || aIID.equals(Ci.nsIAuthPrompt2)) { var
ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]. getService(Ci.nsIPromptFactory); return ww.getPrompt(doc.defaultView,
aIID); } throw Cr.NS_ERROR_NO_INTERFACE; } } // if it we don't have the headers after
a short time, the user // won't have received any feedback from their click. that's bad.
so // we give up waiting for the filename. function timerCallback() {} timerCallback.prototype
= { notify: function sLA_timer_notify(aTimer) { channel.cancel(NS_ERROR_SAVE_LINK_AS_TIMEOUT);
return; } } // set up a channel to do the saving var ioService = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService); var channel = ioService.newChannelFromURI(this.getLinkURI());
channel.notificationCallbacks = new callbacks(); channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE
| Ci.nsIChannel.LOAD_CALL_CONTENT_SNIFFERS; if (channel instanceof Ci.nsIHttpChannel)
{ channel.referrer = doc.documentURIObject; if (channel instanceof Ci.nsIHttpChannelInternal)
channel.forceAllowThirdPartyCookie = true; } // fallback to the old way if we don't
see the headers quickly var timeToWait = gPrefService.getIntPref("browser.download.saveLinkAsFilenameTimeout");
var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); timer.initWithCallback(new timerCallback(),
timeToWait, timer.TYPE_ONE_SHOT); // kick off the channel with our proxy object as the
listener channel.asyncOpen(new saveAsListener(), null); }, sendLink: function() { // we don't
know the title of the link so pass in an empty string MailIntegration.sendMessage( this.linkURL,
"" ); }, // Backwards-compatability wrapper saveImage : function() { if (this.onCanvas
|| this.onImage) this.saveMedia(); }, // Save URL of the clicked upon image, video,
or audio. saveMedia: function() { var doc = this.target.ownerDocument; if (this.onCanvas)
{ // Bypass cache, since it's a data: URL. saveImageURL(this.target.toDataURL(), "canvas.png",
"SaveImageTitle", true, false, doc.documentURIObject); } else if (this.onImage) { urlSecurityCheck(this.mediaURL,
doc.nodePrincipal); saveImageURL(this.mediaURL, null, "SaveImageTitle", false, false, doc.documentURIObject);
} else if (this.onVideo || this.onAudio) { urlSecurityCheck(this.mediaURL, doc.nodePrincipal);
var dialogTitle = this.onVideo ? "SaveVideoTitle" : "SaveAudioTitle"; saveURL(this.mediaURL,
null, dialogTitle, false, false, doc.documentURIObject); } }, // Backwards-compatability wrapper sendImage
: function() { if (this.onCanvas || this.onImage) this.sendMedia(); }, sendMedia: function()
{ MailIntegration.sendMessage(this.mediaURL, ""); }, toggleImageBlocking: function(aBlock)
{ var permissionmanager = Cc["@mozilla.org/permissionmanager;1"]. getService(Ci.nsIPermissionManager); var uri
= this.target.QueryInterface(Ci.nsIImageLoadingContent).currentURI; if (aBlock) permissionmanager.add(uri, "image",
Ci.nsIPermissionManager.DENY_ACTION); else permissionmanager.remove(uri.host, "image");
var brandBundle = document.getElementById("bundle_brand"); var app = brandBundle.getString("brandShortName");
var message = gNavigatorBundle.getFormattedString(aBlock ? "imageBlockedWarning" : "imageAllowedWarning",
[app, uri.host]); var notificationBox = this.browser.getNotificationBox(); var notification = notificationBox.getNotificationWithValue("images-blocked");
if (notification) notification.label = message; else { var self = this; var buttons = [{
label: gNavigatorBundle.getString("undo"), accessKey: gNavigatorBundle.getString("undo.accessKey"),
callback: function() { self.toggleImageBlocking(!aBlock); } }]; const priority = notificationBox.PRIORITY_WARNING_MEDIUM;
notificationBox.appendNotification(message, "images-blocked", "chrome://browser/skin/Info.png",
priority, buttons); } // Reload the page to show the effect instantly BrowserReload();
}, isImageBlocked: function() { var permissionmanager = Cc["@mozilla.org/permissionmanager;1"].
getService(Ci.nsIPermissionManager); var uri = this.target.QueryInterface(Ci.nsIImageLoadingContent).currentURI;
return permissionmanager.testPermission(uri, "image") == Ci.nsIPermissionManager.DENY_ACTION;
}, // Generate email address and put it on clipboard. copyEmail: function() { // Copy
the comma-separated list of email addresses only. // There are other ways of embedding
email addresses in a mailto: // link, but such complex parsing is beyond us. var url
= this.linkURL; var qmark = url.indexOf("?"); var addresses; // 7 == length of "mailto:"
addresses = qmark > 7 ? url.substring(7, qmark) : url.substr(7); // Let's try to unescape
it using a character set // in case the address is not ASCII. try { var characterSet = this.target.ownerDocument.characterSet;
const textToSubURI = Cc["@mozilla.org/intl/texttosuburi;1"]. getService(Ci.nsITextToSubURI); addresses
= textToSubURI.unEscapeURIForUI(characterSet, addresses); } catch(ex) { // Do nothing.
} var clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"]. getService(Ci.nsIClipboardHelper); clipboard.copyString(addresses);
}, /////////////// // Utilities // /////////////// // Show/hide one item (specified via name
or the item element itself). showItem: function(aItemOrId, aShow) { var item = aItemOrId.constructor
== String ? document.getElementById(aItemOrId) : aItemOrId; if (item) item.hidden = !aShow;
}, // Set given attribute of specified context-menu item. If the // value is null, then it removes
the attribute (which works // nicely for the disabled attribute). setItemAttr: function(aID,
aAttr, aVal ) { var elem = document.getElementById(aID); if (elem) { if (aVal == null) { // null indicates
attr should be removed. elem.removeAttribute(aAttr); } else { // Set attr=val. elem.setAttribute(aAttr,
aVal); } } }, // Set context menu attribute according to like attribute of another node
// (such as a broadcaster). setItemAttrFromNode: function(aItem_id, aAttr, aOther_id) { var
elem = document.getElementById(aOther_id); if (elem && elem.getAttribute(aAttr) == "true")
this.setItemAttr(aItem_id, aAttr, "true"); else this.setItemAttr(aItem_id, aAttr, null);
}, // Temporary workaround for DOM api not yet implemented by XUL nodes. cloneNode: function(aItem)
{ // Create another element like the one we're cloning. var node = document.createElement(aItem.tagName);
// Copy attributes from argument item to the new one. var attrs = aItem.attributes;
for (var i = 0; i < attrs.length; i++) { var attr = attrs.item(i); node.setAttribute(attr.nodeName,
attr.nodeValue); } // Voila! return node; }, // Generate fully qualified URL for clicked-on
link. getLinkURL: function() { var href = this.link.href; if (href) return href; href
= this.link.getAttributeNS("http://www.w3.org/1999/xlink", "href"); if (!href || !href.match(/\S/))
{ // Without this we try to save as the current doc, // for example, HTML case also throws
if empty throw "Empty href"; } return makeURLAbsolute(this.link.baseURI, href); }, getLinkURI: function() { try {
return makeURI(this.linkURL); } catch (ex) { // e.g. empty URL string } return null;
}, getLinkProtocol: function() { if (this.linkURI) return this.linkURI.scheme; // can be |undefined|
return null; }, // Get text of link. linkText: function() { var text = gatherTextUnder(this.link);
if (!text || !text.match(/\S/)) { text = this.link.getAttribute("title"); if (!text
|| !text.match(/\S/)) { text = this.link.getAttribute("alt"); if (!text || !text.match(/\S/)) text = this.linkURL;
} } return text; }, // Get selected text. Only display the first 15 chars. isTextSelection:
function() { // Get 16 characters, so that we can trim the selection if it's greater
// than 15 chars var selectedText = getBrowserSelection(16); if (!selectedText) return false; if (selectedText.length
> 15) selectedText = selectedText.substr(0,15) + this.ellipsis; // Use the current engine
if the search bar is visible, the default // engine otherwise. var engineName = "";
var ss = Cc["@mozilla.org/browser/search-service;1"]. getService(Ci.nsIBrowserSearchService); if
(isElementVisible(BrowserSearch.searchBar)) engineName = ss.currentEngine.name; else engineName
= ss.defaultEngine.name; // format "Search for " string to show in
menu var menuLabel = gNavigatorBundle.getFormattedString("contextMenuSearchText", [engineName, selectedText]); document.getElementById("context-searchselect").label
= menuLabel; document.getElementById("context-searchselect").accessKey = gNavigatorBundle.getString("contextMenuSearchText.accesskey");
return true; }, // Returns true if anything is selected. isContentSelection: function()
{ return !document.commandDispatcher.focusedWindow.getSelection().isCollapsed; }, toString: function () { return "contextMenu.target
= " + this.target + "\n" + "contextMenu.onImage = " + this.onImage + "\n" + "contextMenu.onLink
= " + this.onLink + "\n" + "contextMenu.link = " + this.link + "\n" + "contextMenu.inFrame
= " + this.inFrame + "\n" + "contextMenu.hasBGImage = " + this.hasBGImage + "\n"; }, // Returns
true if aNode is a from control (except text boxes and images). // 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" && aNode.type != "image");
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") return (node instanceof HTMLTextAreaElement); },
isTargetAKeywordField: function(aNode) { if (!(aNode instanceof HTMLInputElement))
return false; var form = aNode.form; if (!form || aNode.type == "password") return false;
var method = form.method.toUpperCase(); // These are the following types of forms we
can create keywords for: // // method encoding type can create keyword // GET * YES // *
YES // POST YES // POST application/x-www-form-urlencoded YES // POST text/plain NO (a little tricky
to do) // POST multipart/form-data NO // POST everything else YES return (method ==
"GET" || method == "") || (form.enctype != "text/plain") && (form.enctype != "multipart/form-data");
}, // Determines whether or not the separator with the specified ID should be // shown or
not by determining if there are any non-hidden items between it // and the previous separator.
shouldShowSeparator: function (aSeparatorID) { var separator = document.getElementById(aSeparatorID);
if (separator) { var sibling = separator.previousSibling; while (sibling && sibling.localName != "menuseparator")
{ if (!sibling.hidden) return true; sibling = sibling.previousSibling; } } return false;
}, addDictionaries: function() { var uri = formatURL("browser.dictionaries.download.url",
true); var locale = "-"; try { locale = gPrefService.getComplexValue("intl.accept_languages", Ci.nsIPrefLocalizedString).data; } catch (e)
{ } var version = "-"; try { version = Cc["@mozilla.org/xre/app-info;1"]. getService(Ci.nsIXULAppInfo).version; } catch
(e) { } uri = uri.replace(/%LOCALE%/, escape(locale)).replace(/%VERSION%/, version); var newWindowPref = gPrefService.getIntPref("browser.link.open_newwindow");
var where = newWindowPref == 3 ? "tab" : "window"; openUILinkIn(uri, where); }, bookmarkThisPage:
function CM_bookmarkThisPage() { window.top.PlacesCommandHook.bookmarkPage(this.browser, PlacesUtils.bookmarksMenuFolderId, true);
}, bookmarkLink: function CM_bookmarkLink() { window.top.PlacesCommandHook.bookmarkLink(PlacesUtils.bookmarksMenuFolderId,
this.linkURL, this.linkText()); }, addBookmarkForFrame: function CM_addBookmarkForFrame() { var doc
= this.target.ownerDocument; var uri = doc.documentURIObject; var itemId = PlacesUtils.getMostRecentBookmarkForURI(uri);
if (itemId == -1) { var title = doc.title; var description = PlacesUIUtils.getDescriptionFromDocument(doc);
var descAnno = { name: DESCRIPTION_ANNO, value: description }; var txn = PlacesUIUtils.ptm.createItem(uri,
PlacesUtils.bookmarksMenuFolderId, -1, title, null, [descAnno]); PlacesUIUtils.ptm.doTransaction(txn);
itemId = PlacesUtils.getMostRecentBookmarkForURI(uri); StarUI.beginBatch(); } window.top.StarUI.showEditBookmarkPopup(itemId,
this.browser, "overlap"); }, savePageAs: function CM_savePageAs() { saveDocument(this.browser.contentDocument);
}, sendPage: function CM_sendPage() { MailIntegration.sendLinkForWindow(this.browser.contentWindow); }, printFrame: function CM_printFrame()
{ PrintUtils.print(this.target.ownerDocument.defaultView); }, switchPageDirection: function CM_switchPageDirection()
{ SwitchDocumentDirection(this.browser.contentWindow); }, mediaCommand : function CM_mediaCommand(command)
{ var media = this.target; switch (command) { case "play": media.play(); break; case
"pause": media.pause(); break; case "mute": media.muted = true; break; case "unmute":
media.muted = false; break; case "hidecontrols": media.removeAttribute("controls"); break;
case "showcontrols": media.setAttribute("controls", "true"); break; } }, copyMediaLocation :
function () { var clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"]. getService(Ci.nsIClipboardHelper); clipboard.copyString(this.mediaURL);
}, get imageURL() { if (this.onImage) return this.mediaURL; return ""; content/browser/hiddenWindow.xul content/browser/viewSourceOverlay.xul
content/browser/license.html
about:license .very-strong { text-transform:
uppercase; } .path { font-family: monospace; } dt { font-weight: bold; } dd p { margin:
0; } .gnu-number { font-weight: bold; } function correctSpelling() { // Note that
this code only runs if the page is requested using the // URL containing the correct spelling
- i.e. "about:licence". if (document.location.href.match("icence")) { function acceptNode(node) { if (node.hasAttribute("class"))
{ var c = " " + node.className + " "; if (c.indexOf(" correctme ") != -1) { return
NodeFilter.FILTER_ACCEPT; } } else if (node.nodeName == "H1") { return NodeFilter.FILTER_ACCEPT;
} return NodeFilter.FILTER_SKIP; } var treeWalker = document.createTreeWalker(document.documentElement,
NodeFilter.SHOW_ELEMENT, acceptNode, true); if (treeWalker) { var node = treeWalker.nextNode();
while (node) { var text = node.innerHTML; text = text.replace(/icense\b/gi, "icence");
text = text.replace(/icenses\b/gi, "icences"); node.innerHTML = text; node = treeWalker.nextNode();
} document.title = "about:licence"; } } } window.onload = correctSpelling;
about:license
Binaries of this product have been made available to
you by the Mozilla Project under the Mozilla Public License.
Know your rights. All of the source code to this product
is available under licenses which are both free
and open source. Most is available under any one
of the following: the Mozilla Public License (MPL), the GNU General Public License (GPL)
and the GNU Lesser General Public License (LGPL). That is, you may copy and distribute
such software according to the terms of any one of those three licenses. Mozilla Public License Initial
Developers GNU General Public License GNU
Lesser General Public License The remainder of the software which is
not under the MPL/LGPL/GPL tri-license is available under one of a variety of more permissive
licenses. Those that require reproduction of the license text in the distribution are
given below. (Note: your copy of this product may not contain code covered by one or more
of the licenses listed here, depending on the exact product and version you choose.)
Apple/Mozilla NPRuntime License Breakpad
License bspatch License Cairo
Component Licenses Chromium License CSIRO
Australia License Dutch Spellchecking Dictionary License
Expat License gfxFontList
License Google Gears License Google
Gears/iStumbler License Growl License Japan
Network Information Center License Java Embedding
Plugin License jemalloc License libevent
License libffi License Lithuanian
Spellchecking Dictionary License MAAttachedWindow
OpenVision License qcms
License Red Hat xdg_user_dir_lookup License Russian Spellchecking Dictionary License Sparkle
License SunSoft License University
of California License US English Spellchecking Dictionary Licenses
Xiph.org Foundation License Other Required Notices Optional
Notices Mozilla Public License Version 1.1 1. Definitions. 1.0.1. "Commercial Use"
means distribution or otherwise making the Covered Code available to a third party.
1.1. "Contributor" means each entity that creates or contributes
to the creation of Modifications. 1.2. "Contributor Version"
means the combination of the Original Code, prior Modifications used by a Contributor,
and the Modifications made by that particular Contributor. 1.3.
"Covered Code" means the Original Code or Modifications or the combination of
the Original Code and Modifications, in each case including portions thereof. 1.4. "Electronic Distribution Mechanism" means a mechanism generally
accepted in the software development community for the electronic transfer of data.
1.5. "Executable" means Covered Code in any form other than
Source Code. 1.6. "Initial Developer" means the individual
or entity identified as the Initial Developer in the Source Code notice required by Exhibit
A. 1.7. "Larger Work" means a work which combines
Covered Code or portions thereof with code not governed by the terms of this License.
1.8. "License" means this document. 1.8.1.
"Licensable" means having the right to grant, to the maximum extent possible,
whether at the time of the initial grant or subsequently acquired, any and all of the
rights conveyed herein. 1.9. "Modifications" means any addition
to or deletion from the substance or structure of either the Original Code or any previous
Modifications. When Covered Code is released as a series of files, a Modification is:
Any addition to or deletion from the contents of a file containing
Original Code or previous Modifications. Any new file that contains
any part of the Original Code or previous Modifications. 1.10.
"Original Code" means Source Code of computer software code which is described
in the Source Code notice required by Exhibit A as Original Code, and which, at the
time of its release under this License is not already Covered Code governed by this
License. 1.10.1. "Patent Claims" means any patent
claim(s), now owned or hereafter acquired, including without limitation, method, process,
and apparatus claims, in any patent Licensable by grantor. 1.11.
"Source Code" means the preferred form of the Covered Code for making modifications
to it, including all modules it contains, plus any associated interface definition files,
scripts used to control compilation and installation of an Executable, or source code differential
comparisons against either the Original Code or another well known, available Covered Code
of the Contributor's choice. The Source Code can be in a compressed or archival form, provided
the appropriate decompression or de-archiving software is widely available for no charge.
1.12. "You" (or "Your") means an individual or a legal entity
exercising rights under, and complying with all of the terms of, this License or a future
version of this License issued under Section 6.1. For legal entities, "You" includes
any entity which controls, is controlled by, or is under common control with You. For purposes
of this definition, "control" means (a) the power, direct or indirect, to cause the direction
or management of such entity, whether by contract or otherwise, or (b) ownership of more than
fifty percent (50%) of the outstanding shares or beneficial ownership of such entity.
2. Source Code License. 2.1. The Initial Developer
Grant. The Initial Developer hereby grants You a world-wide, royalty-free, non-exclusive
license, subject to third party intellectual property claims: under
intellectual property rights (other than patent or trademark) Licensable by Initial Developer
to use, reproduce, modify, display, perform, sublicense and distribute the Original Code
(or portions thereof) with or without Modifications, and/or as part of a Larger Work; and
under Patents Claims infringed by the making, using or selling
of Original Code, to make, have made, use, practice, sell, and offer for sale, and/or
otherwise dispose of the Original Code (or portions thereof). the
licenses granted in this Section 2.1 (a) and (b)
are effective on the date Initial Developer first distributes Original Code under the
terms of this License. Notwithstanding Section 2.1 (b)
above, no patent license is granted: 1) for code that You delete from the Original Code;
2) separate from the Original Code; or 3) for infringements caused by: i) the modification
of the Original Code or ii) the combination of the Original Code with other software or
devices. 2.2. Contributor Grant. Subject to third
party intellectual property claims, each Contributor hereby grants You a world-wide, royalty-free,
non-exclusive license under intellectual property rights (other than patent
or trademark) Licensable by Contributor, to use, reproduce, modify, display, perform,
sublicense and distribute the Modifications created by such Contributor (or portions thereof)
either on an unmodified basis, with other Modifications, as Covered Code and/or as part
of a Larger Work; and under Patent Claims infringed by the making, using,
or selling of Modifications made by that Contributor either alone and/or in combination with its
Contributor Version (or portions of such combination), to make, use, sell, offer for sale, have made,
and/or otherwise dispose of: 1) Modifications made by that Contributor (or portions thereof);
and 2) the combination of Modifications made by that Contributor with its Contributor Version
(or portions of such combination). the licenses granted in
Sections 2.2 (a) and 2.2 (b) are
effective on the date Contributor first makes Commercial Use of the Covered Code. Notwithstanding Section 2.2 (b) above,
no patent license is granted: 1) for any code that Contributor has deleted from the Contributor
Version; 2) separate from the Contributor Version; 3) for infringements caused by: i)
third party modifications of Contributor Version or ii) the combination of Modifications made
by that Contributor with other software (except as part of the Contributor Version) or other
devices; or 4) under Patent Claims infringed by Covered Code in the absence of Modifications
made by that Contributor. 3. Distribution Obligations. 3.1.
Application of License. The Modifications which You create or to which You contribute
are governed by the terms of this License, including without limitation Section 2.2.
The Source Code version of Covered Code may be distributed only under the terms of this
License or a future version of this License released under Section 6.1,
and You must include a copy of this License with every copy of the Source Code You distribute.
You may not offer or impose any terms on any Source Code version that alters or restricts
the applicable version of this License or the recipients' rights hereunder. However,
You may include an additional document offering the additional rights described in Section
3.5. 3.2. Availability of Source Code. Any Modification
which You create or to which You contribute must be made available in Source Code form
under the terms of this License either on the same media as an Executable version or
via an accepted Electronic Distribution Mechanism to anyone to whom you made an Executable version
available; and if made available via Electronic Distribution Mechanism, must remain available
for at least twelve (12) months after the date it initially became available, or at
least six (6) months after a subsequent version of that particular Modification has been made
available to such recipients. You are responsible for ensuring that the Source Code version
remains available even if the Electronic Distribution Mechanism is maintained by a third party.
3.3. Description of Modifications. You must cause all Covered Code to which
You contribute to contain a file documenting the changes You made to create that Covered
Code and the date of any change. You must include a prominent statement that the Modification
is derived, directly or indirectly, from Original Code provided by the Initial Developer and
including the name of the Initial Developer in (a) the Source Code, and (b) in any notice
in an Executable version or related documentation in which You describe the origin or ownership
of the Covered Code. 3.4. Intellectual Property Matters (a)
Third Party Claims If Contributor has knowledge that a license under a third
party's intellectual property rights is required to exercise the rights granted by such Contributor
under Sections 2.1 or 2.2, Contributor
must include a text file with the Source Code distribution titled "LEGAL" which describes
the claim and the party making the claim in sufficient detail that a recipient will know
whom to contact. If Contributor obtains such knowledge after the Modification is made available
as described in Section 3.2, Contributor shall promptly modify the LEGAL
file in all copies Contributor makes available thereafter and shall take other steps (such
as notifying appropriate mailing lists or newsgroups) reasonably calculated to inform
those who received the Covered Code that new knowledge has been obtained. (b)
Contributor APIs If Contributor's Modifications include an application programming
interface and Contributor has knowledge of patent licenses which are reasonably necessary
to implement that API, Contributor must also include this information in the
legal file. (c) Representations.
Contributor represents that, except as disclosed pursuant to Section 3.4 (a)
above, Contributor believes that Contributor's Modifications are Contributor's original creation(s)
and/or Contributor has sufficient rights to grant the rights conveyed by this License.
3.5. Required Notices. You must duplicate the notice in Exhibit
A in each file of the Source Code. If it is not possible to put such notice in a
particular Source Code file due to its structure, then You must include such notice in a location
(such as a relevant directory) where a user would be likely to look for such a notice.
If You created one or more Modification(s) You may add your name as a Contributor to
the notice described in Exhibit A. You must also duplicate this License
in any documentation for the Source Code where You describe recipients' rights or ownership
rights relating to Covered Code. You may choose to offer, and to charge a fee for, warranty,
support, indemnity or liability obligations to one or more recipients of Covered Code.
However, You may do so only on Your own behalf, and not on behalf of the Initial Developer
or any Contributor. You must make it absolutely clear than any such warranty, support, indemnity
or liability obligation is offered by You alone, and You hereby agree to indemnify the
Initial Developer and every Contributor for any liability incurred by the Initial Developer
or such Contributor as a result of warranty, support, indemnity or liability terms You
offer. 3.6. Distribution of Executable Versions. You may distribute
Covered Code in Executable form only if the requirements of Sections 3.1,
3.2, 3.3, 3.4 and 3.5
have been met for that Covered Code, and if You include a notice stating that the Source
Code version of the Covered Code is available under the terms of this License, including
a description of how and where You have fulfilled the obligations of Section 3.2.
The notice must be conspicuously included in any notice in an Executable version, related
documentation or collateral in which You describe recipients' rights relating to the Covered
Code. You may distribute the Executable version of Covered Code or ownership rights under
a license of Your choice, which may contain terms different from this License, provided
that You are in compliance with the terms of this License and that the license for the
Executable version does not attempt to limit or alter the recipient's rights in the Source
Code version from the rights set forth in this License. If You distribute the Executable
version under a different license You must make it absolutely clear that any terms which
differ from this License are offered by You alone, not by the Initial Developer or any
Contributor. You hereby agree to indemnify the Initial Developer and every Contributor
for any liability incurred by the Initial Developer or such Contributor as a result
of any such terms You offer. 3.7. Larger Works. You may create a Larger
Work by combining Covered Code with other code not governed by the terms of this License
and distribute the Larger Work as a single product. In such a case, You must make sure
the requirements of this License are fulfilled for the Covered Code. 4.
Inability to Comply Due to Statute or Regulation. If it is impossible for You to comply with
any of the terms of this License with respect to some or all of the Covered Code due to
statute, judicial order, or regulation then You must: (a) comply with the terms of this
License to the maximum extent possible; and (b) describe the limitations and the code
they affect. Such description must be included in the legal
file described in Section 3.4 and must be included with all distributions
of the Source Code. Except to the extent prohibited by statute or regulation, such description
must be sufficiently detailed for a recipient of ordinary skill to be able to understand
it. 5. Application of this License. This License applies
to code to which the Initial Developer has attached the notice in Exhibit
A and to related Covered Code. 6. Versions of the License.
6.1. New Versions Netscape Communications Corporation ("Netscape")
may publish revised and/or new versions of the License from time to time. Each version
will be given a distinguishing version number. 6.2. Effect of New Versions
Once Covered Code has been published under a particular version of the License, You may
always continue to use it under the terms of that version. You may also choose to use
such Covered Code under the terms of any subsequent version of the License published by Netscape.
No one other than Netscape has the right to modify the terms applicable to Covered Code
created under this License. 6.3. Derivative Works If You create or
use a modified version of this License (which you may only do in order to apply it to code
which is not already Covered Code governed by this License), You must (a) rename Your
license so that the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape", "MPL", "NPL" or any confusingly
similar phrase do not appear in your license (except to note that your license differs
from this License) and (b) otherwise make it clear that Your version of the license
contains terms which differ from the Mozilla Public License and Netscape Public License.
(Filling in the name of the Initial Developer, Original Code or Contributor in the notice
described in Exhibit A shall not of themselves be deemed to
be modifications of this License.) 7. Disclaimer
of warranty Covered code is provided under this license on an
"as is" basis, without warranty of any kind, either expressed or implied, including, without
limitation, warranties that the covered code is free of defects, merchantable, fit for
a particular purpose or non-infringing. The entire risk as to the quality and performance
of the covered code is with you. Should any covered code prove defective in any respect,
you (not the initial developer or any other contributor) assume the cost of any necessary
servicing, repair or correction. This disclaimer of warranty constitutes an essential part
of this license. No use of any covered code is authorized hereunder except under this
disclaimer. 8. Termination 8.1.
This License and the rights granted hereunder will terminate automatically if You fail to
comply with terms herein and fail to cure such breach within 30 days of becoming aware
of the breach. All sublicenses to the Covered Code which are properly granted shall survive
any termination of this License. Provisions which, by their nature, must remain in effect
beyond the termination of this License shall survive. 8.2. If You
initiate litigation by asserting a patent infringement claim (excluding declatory judgment
actions) against Initial Developer or a Contributor (the Initial Developer or Contributor against
whom You file such action is referred to as "Participant") alleging that: such Participant's Contributor Version directly or indirectly infringes any
patent, then any and all rights granted by such Participant to You under Sections 2.1 and/or 2.2 of this License shall, upon 60 days notice
from Participant terminate prospectively, unless if within 60 days after receipt of
notice You either: (i) agree in writing to pay Participant a mutually agreeable reasonable
royalty for Your past and future use of Modifications made by such Participant, or (ii) withdraw
Your litigation claim with respect to the Contributor Version against such Participant.
If within 60 days of notice, a reasonable royalty and payment arrangement are not mutually
agreed upon in writing by the parties or the litigation claim is not withdrawn, the rights
granted by Participant to You under Sections 2.1 and/or 2.2 automatically terminate at the expiration of the 60 day notice period
specified above. any software, hardware, or device, other than
such Participant's Contributor Version, directly or indirectly infringes any patent, then any
rights granted to You by such Participant under Sections 2.1(b)
and 2.2(b) are revoked effective as of the date You first
made, used, sold, distributed, or had made, Modifications made by that Participant.
8.3. If You assert a patent infringement claim against Participant
alleging that such Participant's Contributor Version directly or indirectly infringes any
patent where such claim is resolved (such as by license or settlement) prior to the
initiation of patent infringement litigation, then the reasonable value of the licenses
granted by such Participant under Sections 2.1 or 2.2 shall be taken into account in determining the amount or value
of any payment or license. 8.4. In the event of termination under Sections
8.1 or 8.2 above, all end user license agreements (excluding
distributors and resellers) which have been validly granted by You or any distributor
hereunder prior to termination shall survive termination. 9. Limitation of liability Under no circumstances
and under no legal theory, whether tort (including negligence), contract, or otherwise, shall
you, the initial developer, any other contributor, or any distributor of covered code, or any
supplier of any of such parties, be liable to any person for any indirect, special, incidental,
or consequential damages of any character including, without limitation, damages for
loss of goodwill, work stoppage, computer failure or malfunction, or any and all other
commercial damages or losses, even if such party shall have been informed of the possibility
of such damages. This limitation of liability shall not apply to liability for death or
personal injury resulting from such party's negligence to the extent applicable law prohibits
such limitation. Some jurisdictions do not allow the exclusion or limitation of incidental
or consequential damages, so this exclusion and limitation may not apply to you.
10. U.S. government end users
The Covered Code is a "commercial item," as that term is defined in 48 C.F.R.
2.101 (Oct. 1995), consisting of "commercial computer software"
and "commercial computer software documentation," as such terms are used in 48 C.F.R.
12.212 (Sept. 1995). Consistent with 48 C.F.R.
12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all U.S.
Government End Users acquire Covered Code with only those rights set forth herein.
11. Miscellaneous This License represents the complete agreement
concerning subject matter hereof. If any provision of this License is held to be unenforceable,
such provision shall be reformed only to the extent necessary to make it enforceable. This
License shall be governed by California law provisions (except to the extent applicable
law, if any, provides otherwise), excluding its conflict-of-law provisions. With respect
to disputes in which at least one party is a citizen of, or an entity chartered or registered
to do business in the United States of America, any litigation relating to this License shall
be subject to the jurisdiction of the Federal Courts of the Northern District of California,
with venue lying in Santa Clara County, California, with the losing party responsible for costs,
including without limitation, court costs and reasonable attorneys' fees and expenses.
The application of the United Nations Convention on Contracts for the International Sale of
Goods is expressly excluded. Any law or regulation which provides that the language of a contract
shall be construed against the drafter shall not apply to this License. 12.
Responsibility for claims As between Initial Developer and the Contributors, each
party is responsible for claims and damages arising, directly or indirectly, out of its
utilization of rights under this License and You agree to work with Initial Developer and
Contributors to distribute such responsibility on an equitable basis. Nothing herein is intended
or shall be deemed to constitute any admission of liability. 13.
Multiple-licensed code Initial Developer may designate portions of the Covered Code
as "Multiple-Licensed". "Multiple-Licensed" means that the Initial Developer permits you
to utilize portions of the Covered Code under Your choice of the MPL or the
alternative licenses, if any, specified by the Initial Developer in the file described
in Exhibit A. Exhibit A - Mozilla Public
License. "The contents of this file are subject to the Mozilla Public License
Version 1.1 (the "License"); you may not use this file except in compliance with the License.
You may obtain a copy of the License at http://www.mozilla.org/MPL/ Software distributed under the License is
distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
the License for the specific language governing rights and limitations under the License.
The Original Code is ______________________________________. The Initial Developer of the Original Code
is ________________________. Portions created by ______________________ are Copyright (C)
______ _______________________. All Rights Reserved. Contributor(s): ______________________________________.
Alternatively, the contents of this file may be used under the terms of the _____ license
(the "[___] License"), in which case the provisions of [______] License are applicable instead
of those above. If you wish to allow use of your version of this file only under the terms
of the [____] License and not to allow others to use your version of this file under the
MPL, indicate your decision by deleting the provisions above and replace them with the
notice and other provisions required by the [___] License. If you do not delete the provisions
above, a recipient may use your version of this file under either the MPL or the [___]
License." NOTE: The text of this Exhibit A may differ slightly from the text
of the notices in the Source Code files of the Original Code. You should use the text
of this Exhibit A rather than the text found in the Original Code Source Code for Your
Modifications. Initial Developers In accordance with MPL
section 3.3, we state that this software is derived,
directly or indirectly, from Original Code provided by some or all of the following people,
companies and organisations: Aaron Leventhal, Aaron Nowack,
Aaron Schulman, Aaron Train, ActiveState Tool Corp, Adam Barth, Adobe System Incorporated,
Akkana Peck, Alex Fritze, Alexander J. Vincent, Alfred Peng, Andreas Gal, Andreas Otte, Andrew
Thompson, Andrew Zabolotny, ArentJan Banck, Arpad Borsos, Asaf Romano, Axel Hecht, Ben
Bucksch, Ben Goodger, Ben Turner, Ben Willmore, Benjamin Smedberg, Berend Cornelius, Bernd
Mielke, Björn Jacke, Blake Ross, Blue Static, Boris Zbarsky, Brad Lassey, Bradley
Baetz, Brendan Eich, Brian Birtles, Brian Bober, Brian Crowder, Brian Ryner, Bruce Davidson,
Bruno Browning, Bruno Escherl, Bruno Haible, Bryan Atwood, Caio Tiago Oliveira, Calum Robinson,
Chinmay Deepakbhai Patel, Chris Double, Chris McAfee, Christian Biesinger, Christopher A.
Aillon, Christopher Blizzard, Christopher Henderson, Christopher Hoess, Christopher
Seawood, Craig Topper, Crocodile Clips Ltd, CSIRO, Cyrus Patel, Dão Gottwald, Dainis
Jonitis, Dan Mosedale, Dan Schaffer, Daniel Boelzle, Daniel Brooks, Daniel Glazman, Daniel
Kouril, Daniel Weber, Daniel Witte, Dantifer Dang, Darin Fisher, Dave Liebreich, Dave Townsend,
David Ascher, David Bienvenu, David Bradley, David Einstein, David Hamp-Gonsalves, David
Hyatt, David P. Caldwell, Diane Trout, Dietrich Ayala, Digital Creations 2 Inc, Disruptive
Innovations SARL, Doron Rosenberg, Doug Turner, Edward Lee, Ehsan Akhgari, Elika J. Etemad,
Eric Belhaire, Eric Hodel, Esben Mose Hansen, Florian Queze, Frank Schönheit, Fred
Jendrzejewski, Fredrik Holmqvist, Gavin Sharp, Geoff Beier, Gervase Markham, Gijs Kruitbosch,
Giorgio Maone, Google Inc, Graeme McCutcheon, Håkan Waara, Heriot-Watt University,
Hewlett-Packard Company, i-DNS.net International, Ian Hickson, Ian Leue, Ian Neal, Ian Oeschger,
IBM Corporation, Igor Bukanov, InnoTek Systemberatung GmbH, Intel Corporation, James Boston, James
L. Nance, Jamie Zawinski, Jan Varga, Jan Wrobel, Jason Barnabe, Jason Orendorff, Jean-Francois
Ducarroz, Jeff Dlouhy, Jeff Tsai, Jeff Walden, Jim Blandy, Jim Mathies, Joe Hewitt, Joey
Minta, John B. Keiser, John C. Griggs, John Fairhurst, John Wolfe, Jonas Sicking, Jonathan
Watt, Josh Aas, Josh Geenen, Joshua Cranmer, Juan Lang, Jungshik Shin, Jussi Kukkonen,
Karsten Düsterloh, Kathleen Brade, Keith Visco, Ken Herron, Kent James, Kevin Gerich,
Kevin Hendricks, Kipp E.B. Hickman, KISA, Kuden, László Né***,
L. David Baron, Lev Serebryakov, Magnus Melin, Makoto Kato, Marc Bevand, Marco Pesenti Gritti,
Mark 'Mook' Yen, Mark Banner, Mark Finkle, Mark Mentovai, Markus G. Kuhn, Markus Stange,
Mats Palmgren, Matt Judy, Matthew Willis, Merike Sell, Michael J. Fromberger, Michael
Johnston, Michael Kohler, Michael Kraft, Michael Ventnor, Michal Ceresna, Michal Novotny, Michiel
van Leeuwen, Mike Connor, Mike Pinkerton, Mike Potter, Mike Shaver, Mitchell Field,
MITRE Corporation, Mozdev Group, Mozilla Corporation, Mozilla Foundation, Mozilla Japan, Mozilla
Messaging, Naoki Hotta, Neil Deakin, Neil Rashbrook, Nelson B. Bolyard, Netscape Communications
Corporation, Nick Kreeger, Nickolay Ponomarev, Nils Maier, Nochum Sossonko, Nokia, Novell
Inc, NTT, OEone Corporation, Oleg Romashin, Olivier Parniere, Olli Pettay, Oracle Corporation,
Paolo Amadini, Pattara Kiatisevi, Paul Ashford, Paul Kocher, Paul Sandoz, Paul Tomlin, Peter
Annema, Peter Van der Beken, Peter Weilbacher, Petr Kostka, Phil Ringnalda, Philipp Kewisch,
Philippe Wittenbergh, Pierre Chanial, POTI Inc, Qualcomm Inc, R.J. Keller, Rajiv Dayal,
Ramalingam Saravanan, Red Hat Inc, Rich Salz, Richard C. Swift, Richard L. Walsh, Richard
Verhoeven, Richard Walsh, Robert Accettura, Robert John Churchill, Robert Kaiser, Robert
Longson, Robert O'Callahan, Robert Sayre, Robert Strong, Roland Mainz, RSA Security
Inc, Ryan Cassin, Ryan VanderMeulen, Samphan Raruenrom, Scooter Morris, Scott MacGregor,
Sean Murphy, Sebastian Schwieger, Sergei Dolgov, Seth Spitzer, Shawn Wilsher, Shy Shalom, Siddharth
Agarwal, Simdesk Technologies Inc, Simmule Turner, Simon Bünzli, Simon Fraser, Simon
Montagu, Simon Paquet, Simon Wilkinson, Smokey Ardisson, Sqlite Project, Srilatha Moturi,
Stanford University, Stefan Sitter, Stephen Horlander, Steve Swanson, Stuart Morgan, Stuart
Parmenter, Sun Microsystems Inc, Sylvain Pasche, Taras Glek, Ted Mielczarek, Theppitak Karoonboonyanan,
Thomas K. Dyas, Tim Copperfield, Tom St Denis, University of Queensland, Vee Satayamas, Vincent
Béron, Vladimir Vukicevic, William Jon McCann, Wladimir Palant, Wolfgang Rosenauer,
YAMASHITA Makoto, Zack Rusin, Zero-Knowledge Systems, Žiga Sancin. GNU General Public License Version 2, June 1991 Copyright (C)
1989, 1991 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
USA Everyone is permitted to copy and distribute verbatim copies of this license
document, but changing it is not allowed. Preamble The licenses for most
software are designed to take away your freedom to share and change it. By contrast, the GNU
General Public License is intended to guarantee your freedom to share and change free software--to
make sure the software is free for all its users. This General Public License applies
to most of the Free Software Foundation's software and to any other program whose authors
commit to using it. (Some other Free Software Foundation software is covered by the GNU
Library General Public License instead.) You can apply it to your programs, too. When
we speak of free software, we are referring to freedom, not price. Our General Public
Licenses are designed to make sure that you have the freedom to distribute copies of free
software (and charge for this service if you wish), that you receive source code or can
get it if you want it, that you can change the software or use pieces of it in new free
programs; and that you know you can do these things. To protect your rights, we need
to make restrictions that forbid anyone to deny you these rights or to ask you to surrender
the rights. These restrictions translate to certain responsibilities for you if you distribute
copies of the software, or if you modify it. For example, if you distribute copies
of such a program, whether gratis or for a fee, you must give the recipients all the
rights that you have. You must make sure that they, too, receive or can get the source code.
And you must show them these terms so they know their rights. We protect your rights
with two steps: (1) copyright the software, and (2) offer you this license which gives
you legal permission to copy, distribute and/or modify the software. Also, for each author's
protection and ours, we want to make certain that everyone understands that there is no
warranty for this free software. If the software is modified by someone else and passed on,
we want its recipients to know that what they have is not the original, so that any problems
introduced by others will not reflect on the original authors' reputations. Finally,
any free program is threatened constantly by software patents. We wish to avoid the
danger that redistributors of a free program will individually obtain patent licenses,
in effect making the program proprietary. To prevent this, we have made it clear that
any patent must be licensed for everyone's free use or not licensed at all. The precise
terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC
LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work
which contains a notice placed by the copyright holder saying it may be distributed under
the terms of this General Public License. The "Program", below, refers to any such program
or work, and a "work based on the Program" means either the Program or any derivative
work under copyright law: that is to say, a work containing the Program or a portion
of it, either verbatim or with modifications and/or translated into another language. (Hereinafter,
translation is included without limitation in the term "modification".) Each licensee
is addressed as "you". Activities other than copying, distribution and modification
are not covered by this License; they are outside its scope. The act of running the
Program is not restricted, and the output from the Program is covered only if its contents
constitute a work based on the Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does. 1.
You may copy and distribute verbatim copies of the Program's source code as you receive
it, in any medium, provided that you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact all the notices that
refer to this License and to the absence of any warranty; and give any other recipients
of the Program a copy of this License along with the Program. You may charge a fee
for the physical act of transferring a copy, and you may at your option offer warranty
protection in exchange for a fee. 2. You may modify
your copy or copies of the Program or any portion of it, thus forming a work based on
the Program, and copy and distribute such modifications or work under the terms of Section
1 above, provided that you also meet all of these conditions: a) You must cause the modified
files to carry prominent notices stating that you changed the files and the date of any
change. b) You must cause any work that you distribute or publish, that in whole or in
part contains or is derived from the Program or any part thereof, to be licensed as a whole
at no charge to all third parties under the terms of this License. c) If the modified
program normally reads commands interactively when run, you must cause it, when started
running for such interactive use in the most ordinary way, to print or display an announcement
including an appropriate copyright notice and a notice that there is no warranty (or
else, saying that you provide a warranty) and that users may redistribute the program
under these conditions, and telling the user how to view a copy of this License. (Exception:
if the Program itself is interactive but does not normally print such an announcement, your
work based on the Program is not required to print an announcement.) These requirements
apply to the modified work as a whole. If identifiable sections of that work are not
derived from the Program, and can be reasonably considered independent and separate works
in themselves, then this License, and its terms, do not apply to those sections when
you distribute them as separate works. But when you distribute the same sections as part
of a whole which is a work based on the Program, the distribution of the whole must be on the
terms of this License, whose permissions for other licensees extend to the entire whole,
and thus to each and every part regardless of who wrote it. Thus, it is not the intent
of this section to claim rights or contest your rights to work written entirely by you;
rather, the intent is to exercise the right to control the distribution of derivative
or collective works based on the Program. In addition, mere aggregation of another
work not based on the Program with the Program (or with a work based on the Program) on a
volume of a storage or distribution medium does not bring the other work under the scope
of this License. 3. You may copy and distribute the Program
(or a work based on it, under Section 2) in object code or executable form under the terms
of Sections 1 and 2 above provided that you also do one of the following: a) Accompany
it with the complete corresponding machine-readable source code, which must be distributed under
the terms of Sections 1 and 2 above on a medium customarily used for software interchange;
or, b) Accompany it with a written offer, valid for at least three years, to give any
third party, for a charge no more than your cost of physically performing source distribution,
a complete machine-readable copy of the corresponding source code, to be distributed under the terms
of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany
it with the information you received as to the offer to distribute corresponding source
code. (This alternative is allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such an offer, in accord with Subsection
b above.) The source code for a work means the preferred form of the work for making
modifications to it. For an executable work, complete source code means all the source
code for all modules it contains, plus any associated interface definition files, plus
the scripts used to control compilation and installation of the executable. However, as
a special exception, the source code distributed need not include anything that is normally
distributed (in either source or binary form) with the major components (compiler, kernel,
and so on) of the operating system on which the executable runs, unless that component
itself accompanies the executable. If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent access to copy the source
code from the same place counts as distribution of the source code, even though third parties
are not compelled to copy the source along with the object code. 4.
You may not copy, modify, sublicense, or distribute the Program except as expressly
provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute
the Program is void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under this License will
not have their licenses terminated so long as such parties remain in full compliance.
5. You are not required to accept this License, since
you have not signed it. However, nothing else grants you permission to modify or distribute
the Program or its derivative works. These actions are prohibited by law if you do not
accept this License. Therefore, by modifying or distributing the Program (or any work based
on the Program), you indicate your acceptance of this License to do so, and all its terms
and conditions for copying, distributing or modifying the Program or works based on it.
6. Each time you redistribute the Program (or any
work based on the Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to these terms and conditions.
You may not impose any further restrictions on the recipients' exercise of the rights
granted herein. You are not responsible for enforcing compliance by third parties to this
License. 7. If, as a consequence of a court judgment or
allegation of patent infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or otherwise) that
contradict the conditions of this License, they do not excuse you from the conditions
of this License. If you cannot distribute so as to satisfy simultaneously your obligations
under this License and any other pertinent obligations, then as a consequence you may
not distribute the Program at all. For example, if a patent license would not permit royalty-free
redistribution of the Program by all those who receive copies directly or indirectly
through you, then the only way you could satisfy both it and this License would be to refrain
entirely from distribution of the Program. If any portion of this section is held
invalid or unenforceable under any particular circumstance, the balance of the section is
intended to apply and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any patents or other
property right claims or to contest validity of any such claims; this section has the sole
purpose of protecting the integrity of the free software distribution system, which is
implemented by public license practices. Many people have made generous contributions to
the wide range of software distributed through that system in reliance on consistent application
of that system; it is up to the author/donor to decide if he or she is willing to distribute
software through any other system and a licensee cannot impose that choice. This section
is intended to make thoroughly clear what is believed to be a consequence of the rest
of this License. 8. If the distribution and/or use of
the Program is restricted in certain countries either by patents or by copyrighted interfaces,
the original copyright holder who places the Program under this License may add an explicit
geographical distribution limitation excluding those countries, so that distribution is permitted
only in or among countries not thus excluded. In such case, this License incorporates the
limitation as if written in the body of this License. 9.
The Free Software Foundation may publish revised and/or new versions of the General Public
License from time to time. Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns. Each version is given a distinguishing
version number. If the Program specifies a version number of this License which applies
to it and "any later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free Software Foundation.
If the Program does not specify a version number of this License, you may choose any
version ever published by the Free Software Foundation. 10.
If you wish to incorporate parts of the Program into other free programs whose
distribution conditions are different, write to the author to ask for permission. For software
which is copyrighted by the Free Software Foundation, write to the Free Software Foundation;
we sometimes make exceptions for this. Our decision will be guided by the two goals of
preserving the free status of all derivatives of our free software and of promoting the
sharing and reuse of software generally. NO WARRANTY 11.
BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM,
TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE
COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY
AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT
HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED
ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL
DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES
OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR
OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs If you develop a new program, and you
want it to be of the greatest possible use to the public, the best way to achieve this
is to make it free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest to attach them
to the start of each source file to most effectively convey the exclusion of warranty; and each
file should have at least the "copyright" line and a pointer to where the full notice
is found. <one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author> This program is free software; you can redistribute
it and/or modify it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your option) any
later version. This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the GNU General Public License for more details. You should have received
a copy of the GNU General Public License along with this program; if not, write to the Free
Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail. If the
program is interactive, make it output a short notice like this when it starts in an interactive
mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes
with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are
welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical
commands `show w' and `show c' should show the appropriate parts of the General Public
License. Of course, the commands you use may be called something other than `show w' and
`show c'; they could even be mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your school, if any,
to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the
names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision'
(which makes passes at compilers) written by James Hacker. <signature of Ty ***>,
1 April 1989 Ty ***, President of Vice This General Public License does not permit
incorporating your program into proprietary programs. If your program is a subroutine
library, you may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Library General Public License
instead of this License. GNU Lesser General Public License Version
2.1, February 1999 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin
St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute
verbatim copies of this license document, but changing it is not allowed. [This is
the first released version of the Lesser GPL. It also counts as the successor of the GNU
Library Public License, version 2, hence the version number 2.1.] Preamble
The licenses for most software are designed to take away your freedom to share and change
it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to
share and change free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some specially designated software
packages--typically libraries--of the Free Software Foundation and other authors who
decide to use it. You can use it too, but we suggest you first think carefully about
whether this license or the ordinary General Public License is the better strategy to use
in any particular case, based on the explanations below. When we speak of free software,
we are referring to freedom of use, not price. Our General Public Licenses are designed to
make sure that you have the freedom to distribute copies of free software (and charge for this
service if you wish); that you receive source code or can get it if you want it; that you
can change the software and use pieces of it in new free programs; and that you are
informed that you can do these things. To protect your rights, we need to make restrictions
that forbid distributors to deny you these rights or to ask you to surrender these rights.
These restrictions translate to certain responsibilities for you if you distribute copies of the library
or if you modify it. For example, if you distribute copies of the library, whether
gratis or for a fee, you must give the recipients all the rights that we gave you. You must
make sure that they, too, receive or can get the source code. If you link other code with
the library, you must provide complete object files to the recipients, so that they can
relink them with the library after making changes to the library and recompiling it.
And you must show them these terms so they know their rights. We protect your rights
with a two-step method: (1) we copyright the library, and (2) we offer you this license,
which gives you legal permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that there is no warranty for
the free library. Also, if the library is modified by someone else and passed on, the
recipients should know that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be introduced by others.
Finally, software patents pose a constant threat to the existence of any free program.
We wish to make sure that a company cannot effectively restrict the users of a free program
by obtaining a restrictive license from a patent holder. Therefore, we insist that any
patent license obtained for a version of the library must be consistent with the full freedom
of use specified in this license. Most GNU software, including some libraries, is
covered by the ordinary GNU General Public License. This license, the GNU Lesser General
Public License, applies to certain designated libraries, and is quite different from the
ordinary General Public License. We use this license for certain libraries in order to
permit linking those libraries into non-free programs. When a program is linked with
a library, whether statically or using a shared library, the combination of the two is legally
speaking a combined work, a derivative of the original library. The ordinary General
Public License therefore permits such linking only if the entire combination fits its criteria
of freedom. The Lesser General Public License permits more lax criteria for linking other
code with the library. We call this license the "Lesser" General Public License because
it does Less to protect the user's freedom than the ordinary General Public License.
It also provides other free software developers Less of an advantage over competing non-free
programs. These disadvantages are the reason we use the ordinary General Public License
for many libraries. However, the Lesser license provides advantages in certain special circumstances.
For example, on rare occasions, there may be a special need to encourage the widest
possible use of a certain library, so that it becomes a de-facto standard. To achieve
this, non-free programs must be allowed to use the library. A more frequent case is that
a free library does the same job as widely used non-free libraries. In this case, there
is little to gain by limiting the free library to free software only, so we use the Lesser
General Public License. In other cases, permission to use a particular library in
non-free programs enables a greater number of people to use a large body of free software.
For example, permission to use the GNU C Library in non-free programs enables many more people
to use the whole GNU operating system, as well as its variant, the GNU/Linux operating
system. Although the Lesser General Public License is Less protective of the users' freedom,
it does ensure that the user of a program that is linked with the Library has the freedom
and the wherewithal to run that program using a modified version of the Library. The
precise terms and conditions for copying, distribution and modification follow. Pay
close attention to the difference between a "work based on the library" and a "work
that uses the library". The former contains code derived from the library, whereas the
latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC
LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software
library or other program which contains a notice placed by the copyright holder or other
authorized party saying it may be distributed under the terms of this Lesser General Public
License (also called "this License"). Each licensee is addressed as "you". A "library"
means a collection of software functions and/or data prepared so as to be conveniently linked
with application programs (which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work which has been distributed
under these terms. A "work based on the Library" means either the Library or any derivative
work under copyright law: that is to say, a work containing the Library or a portion
of it, either verbatim or with modifications and/or translated straightforwardly into another
language. (Hereinafter, translation is included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for making modifications
to it. For a library, complete source code means all the source code for all modules
it contains, plus any associated interface definition files, plus the scripts used to
control compilation and installation of the library. Activities other than copying,
distribution and modification are not covered by this License; they are outside its scope.
The act of running a program using the Library is not restricted, and output from such a
program is covered only if its contents constitute a work based on the Library (independent of
the use of the Library in a tool for writing it). Whether that is true depends on what
the Library does and what the program that uses the Library does. 1.
You may copy and distribute verbatim copies of the Library's complete source code
as you receive it, in any medium, provided that you conspicuously and appropriately publish
on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all
the notices that refer to this License and to the absence of any warranty; and distribute
a copy of this License along with the Library. You may charge a fee for the physical
act of transferring a copy, and you may at your option offer warranty protection in exchange
for a fee. 2. You may modify your copy or copies
of the Library or any portion of it, thus forming a work based on the Library, and copy
and distribute such modifications or work under the terms of Section 1 above, provided
that you also meet all of these conditions: a) The modified work must itself be a software
library. b) You must cause the files modified to carry prominent notices stating that you
changed the files and the date of any change. c) You must cause the whole of the work to
be licensed at no charge to all third parties under the terms of this License. d) If a facility
in the modified Library refers to a function or a table of data to be supplied by an application
program that uses the facility, other than as an argument passed when the facility is
invoked, then you must make a good faith effort to ensure that, in the event an application
does not supply such function or table, the facility still operates, and performs whatever
part of its purpose remains meaningful. (For example, a function in a library to compute
square roots has a purpose that is entirely well-defined independent of the application.
Therefore, Subsection 2d requires that any application-supplied function or table used
by this function must be optional: if the application does not supply it, the square
root function must still compute square roots.) These requirements apply to the modified
work as a whole. If identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in themselves, then this
License, and its terms, do not apply to those sections when you distribute them as separate
works. But when you distribute the same sections as part of a whole which is a work based on
the Library, the distribution of the whole must be on the terms of this License, whose
permissions for other licensees extend to the entire whole, and thus to each and every
part regardless of who wrote Thus, it is not the intent of this section to claim rights
or contest your rights to work written entirely by you; rather, the intent is to exercise
the right to control the distribution of derivative or collective works based on the Library.
In addition, mere aggregation of another work not based on the Library with the Library
(or with a work based on the Library) on a volume of a storage or distribution medium
does not bring the other work under the scope of this License. 3.
You may opt to apply the terms of the ordinary GNU General Public License instead
of this License to a given copy of the Library. To do this, you must alter all the notices
that refer to this License, so that they refer to the ordinary GNU General Public License,
version 2, instead of to this License. (If a newer version than version 2 of the ordinary
GNU General Public License has appeared, then you can specify that version instead if you
wish.) Do not make any other change in these notices. Once this change is made in a
given copy, it is irreversible for that copy, so the ordinary GNU General Public License
applies to all subsequent copies and derivative works made from that copy. This option
is useful when you wish to copy part of the code of the Library into a program that is
not a library. 4. You may copy and distribute the Library
(or a portion or derivative of it, under Section 2) in object code or executable form under
the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding
machine-readable source code, which must be distributed under the terms of Sections 1
and 2 above on a medium customarily used for software interchange. If distribution
of object code is made by offering access to copy from a designated place, then offering
equivalent access to copy the source code from the same place satisfies the requirement
to distribute the source code, even though third parties are not compelled to copy the
source along with the object code. 5. A program that
contains no derivative of any portion of the Library, but is designed to work with the
Library by being compiled or linked with it, is called a "work that uses the Library".
Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside
the scope of this License. However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it contains portions
of the Library), rather than a "work that uses the library". The executable is therefore
covered by this License. Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file that is part of
the Library, the object code for the work may be a derivative work of the Library even
though the source code is not. Whether this is true is especially significant if the work
can be linked without the Library, or if the work is itself a library. The threshold for
this to be true is not precisely defined by law. If such an object file uses only
numerical parameters, data structure layouts and accessors, and small macros and small
inline functions (ten lines or less in length), then the use of the object file is unrestricted,
regardless of whether it is legally a derivative work. (Executables containing this object
code plus portions of the Library will still fall under Section 6.) Otherwise, if the
work is a derivative of the Library, you may distribute the object code for the work under
the terms of Section 6. Any executables containing that work also fall under Section 6, whether
or not they are linked directly with the Library itself. 6.
As an exception to the Sections above, you may also combine or link a "work that uses
the Library" with the Library to produce a work containing portions of the Library, and
distribute that work under terms of your choice, provided that the terms permit modification
of the work for the customer's own use and reverse engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the Library is used
in it and that the Library and its use are covered by this License. You must supply a
copy of this License. If the work during execution displays copyright notices, you must include
the copyright notice for the Library among them, as well as a reference directing the
user to the copy of this License. Also, you must do one of these things: a) Accompany
the work with the complete corresponding machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under Sections 1 and 2 above);
and, if the work is an executable linked with the Library, with the complete machine-readable
"work that uses the Library", as object code and/or source code, so that the user can modify
the Library and then relink to produce a modified executable containing the modified Library.
(It is understood that the user who changes the contents of definitions files in the Library
will not necessarily be able to recompile the application to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism
is one that (1) uses at run time a copy of the library already present on the user's
computer system, rather than copying library functions into the executable, and (2) will
operate properly with a modified version of the library, if the user installs one, as
long as the modified version is interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at least three years, to give the
same user the materials specified in Subsection 6a, above, for a charge no more than the cost
of performing this distribution. d) If distribution of the work is made by offering access to
copy from a designated place, offer equivalent access to copy the above specified materials
from the same place. e) Verify that the user has already received a copy of these materials
or that you have already sent this user a copy. For an executable, the required
form of the "work that uses the Library" must include any data and utility programs needed
for reproducing the executable from it. However, as a special exception, the materials to be
distributed need not include anything that is normally distributed (in either source
or binary form) with the major components (compiler, kernel, and so on) of the operating
system on which the executable runs, unless that component itself accompanies the executable.
It may happen that this requirement contradicts the license restrictions of other proprietary
libraries that do not normally accompany the operating system. Such a contradiction means
you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on
the Library side-by-side in a single library together with other library facilities not
covered by this License, and distribute such a combined library, provided that the separate
distribution of the work based on the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things: a) Accompany the combined library
with a copy of the same work based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the Sections above. b) Give prominent
notice with the combined library of the fact that part of it is a work based on the Library,
and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any attempt otherwise to copy,
modify, sublicense, link with, or distribute the Library is void, and will automatically
terminate your rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses terminated so long
as such parties remain in full compliance. 9. You
are not required to accept this License, since you have not signed it. However, nothing else
grants you permission to modify or distribute the Library or its derivative works. These
actions are prohibited by law if you do not accept this License. Therefore, by modifying
or distributing the Library (or any work based on the Library), you indicate your acceptance
of this License to do so, and all its terms and conditions for copying, distributing or
modifying the Library or works based on it. 10. Each
time you redistribute the Library (or any work based on the Library), the recipient
automatically receives a license from the original licensor to copy, distribute, link
with or modify the Library subject to these terms and conditions. You may not impose any
further restrictions on the recipients' exercise of the rights granted herein. You are not
responsible for enforcing compliance by third parties with this License. 11.
If, as a consequence of a court judgment or allegation of patent infringement or for
any other reason (not limited to patent issues), conditions are imposed on you (whether by
court order, agreement or otherwise) that contradict the conditions of this License,
they do not excuse you from the conditions of this License. If you cannot distribute
so as to satisfy simultaneously your obligations under this License and any other pertinent
obligations, then as a consequence you may not distribute the Library at all. For example,
if a patent license would not permit royalty-free redistribution of the Library by all those
who receive copies directly or indirectly through you, then the only way you could satisfy
both it and this License would be to refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any particular
circumstance, the balance of the section is intended to apply, and the section as a whole
is intended to apply in other circumstances. It is not the purpose of this section to
induce you to infringe any patents or other property right claims or to contest validity
of any such claims; this section has the sole purpose of protecting the integrity of the
free software distribution system which is implemented by public license practices. Many
people have made generous contributions to the wide range of software distributed through
that system in reliance on consistent application of that system; it is up to the author/donor
to decide if he or she is willing to distribute software through any other system and a licensee
cannot impose that choice. This section is intended to make thoroughly clear what
is believed to be a consequence of the rest of this License. 12.
If the distribution and/or use of the Library is restricted in certain countries
either by patents or by copyrighted interfaces, the original copyright holder who places the
Library under this License may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among countries not thus excluded.
In such case, this License incorporates the limitation as if written in the body of this
License. 13. The Free Software Foundation may publish revised
and/or new versions of the Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may differ in detail
to address new problems or concerns. Each version is given a distinguishing version
number. If the Library specifies a version number of this License which applies to it
and "any later version", you have the option of following the terms and conditions either
of that version or of any later version published by the Free Software Foundation. If the Library
does not specify a license version number, you may choose any version ever published
by the Free Software Foundation. 14. If you wish
to incorporate parts of the Library into other free programs whose distribution conditions
are incompatible with these, write to the author to ask for permission. For software
which is copyrighted by the Free Software Foundation, write to the Free Software Foundation;
we sometimes make exceptions for this. Our decision will be guided by the two goals of
preserving the free status of all derivatives of our free software and of promoting the
sharing and reuse of software generally. NO WARRANTY 15.
BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY,
TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE
COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY
AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT
HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED
ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL
DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES
OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR
OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries If you develop a new library, and you
want it to be of the greatest possible use to the public, we recommend making it free
software that everyone can redistribute and change. You can do so by permitting redistribution
under these terms (or, alternatively, under the terms of the ordinary General Public License).
To apply these terms, attach the following notices to the library. It is safest to attach
them to the start of each source file to most effectively convey the exclusion of warranty;
and each file should have at least the "copyright" line and a pointer to where the full notice
is found. <one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author> This library is free software; you can redistribute
it and/or modify it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2.1 of the License, or (at your option) any
later version. This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the GNU Lesser General Public License for more details. You should have
received a copy of the GNU Lesser General Public License along with this library; if
not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301 USA Also add information on how to contact you by electronic and paper
mail. You should also get your employer (if you work as a programmer) or your school,
if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample;
alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library
`Frob' (a library for tweaking knobs) written by James Random Hacker. <signature of Ty
***>, 1 April 1990 Ty ***, President of Vice That's all there is to it!
Apple/Mozilla NPRuntime License This
license applies to the file modules/plugin/base/public/npruntime.h. Copyright © 2004, Apple Computer,
Inc. and The Mozilla Foundation. All rights reserved. Redistribution and use in source
and binary forms, with or without modification, are permitted provided that the following
conditions are met: 1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form
must reproduce the above copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the names of Apple Computer, Inc. ("Apple") or The Mozilla Foundation ("Mozilla")
nor the names of their contributors may be used to endorse or promote products derived
from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED
BY APPLE, MOZILLA AND THEIR CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE, MOZILLA OR THEIR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE. Breakpad License This license
applies to files in the directory toolkit/crashreporter/google-breakpad/ and camino/google-breakpad/.
Copyright (c) 2006, Google Inc. All rights reserved. Redistribution and use in
source and binary forms, with or without modification, are permitted provided that the following
conditions are met: * Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer. * Redistributions in binary form
must reproduce the above copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of Google Inc. nor the names of its contributors may be used to endorse
or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE. bspatch License This license
applies to the files toolkit/mozapps/update/src/updater/bspatch.cpp and toolkit/mozapps/update/src/updater/bspatch.h.
Copyright 2003,2004 Colin Percival All rights reserved Redistribution and use
in source and binary forms, with or without modification, are permitted providing that
the following conditions are met: 1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form
must reproduce the above copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Cairo Component Licenses This license, with different
copyright holders, applies to certain files in the directory gfx/cairo/.
The copyright holders and the applicable ranges of dates are as follows: 2004 Richard
D. Worth 2004, 2005 Red Hat, Inc. 2003 USC, Information Sciences Institute 2004
David Reveman 2005 Novell, Inc. 2004 David Reveman, Peter Nilsson 2000 Keith
Packard, member of The XFree86 Project, Inc. 2005 Lars Knoll & Zack Rusin, Trolltech
1998, 2000, 2002, 2004 Keith Packard 2004 Nicholas Miell 2005 Trolltech AS 2000
SuSE, Inc. 2003 Carl Worth 1987, 1988, 1989, 1998 The Open Group 1987, 1988,
1989 Digital Equipment Corporation, Maynard, Massachusetts. 1998 Keith Packard 2003
Richard Henderson Copyright © <date> <copyright holder> Permission
to use, copy, modify, distribute, and sell this software and its documentation for any
purpose is hereby granted without fee, provided that the above copyright notice appear in
all copies and that both that copyright notice and this permission notice appear in supporting
documentation, and that the name of <copyright holder> not be used in advertising or publicity
pertaining to distribution of the software without specific, written prior permission.
<copyright holder> makes no representations about the suitability of this software for
any purpose. It is provided "as is" without express or implied warranty. <COPYRIGHT
HOLDER> DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR
ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Chromium License This license applies
to some files in the directory ipc/chromium/. Copyright (c) 2006-2008 The Chromium
Authors. All rights reserved. Redistribution and use in source and binary forms, with or
without modification, are permitted provided that the following conditions are met: *
Redistributions of source code must retain the above copyright notice, this list of conditions
and the following disclaimer. * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution. * Neither the name of Google Inc. nor the
names of its contributors may be used to endorse or promote products derived from this software
without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. CSIRO
Australia License This license applies to files in the directories:
media/libfishsound/ media/liboggplay/
media/liboggz/ Copyright (C) 2003 CSIRO
Australia Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met: - Redistributions of source
code must retain the above copyright notice, this list of conditions and the following
disclaimer. - Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution. - Neither the name of the CSIRO nor the names
of its contributors may be used to endorse or promote products derived from this software
without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Dutch Spellchecking Dictionary License This
license applies to certain files in the directory l10n/nl/extensions/spellcheck/hunspell/.
(This code only ships in some localized versions of this product.) Copyright (c)
2006, 2007 OpenTaal Copyright (c) 2001, 2002, 2003, 2005 Simon Brouwer e.a. Copyright (c)
1996 Nederlandstalige Tex Gebruikersgroep All rights reserved. Redistribution and use
in source and binary forms, with or without modification, are permitted provided that
the following conditions are met: * Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer. * Redistributions in binary form
must reproduce the above copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the OpenTaal, Simon Brouwer e.a., or Nederlandstalige Tex Gebruikersgroep
nor the names of its contributors may be used to endorse or promote products derived from
this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE
COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Expat License This license applies to certain files in the directory
parser/expat/. Copyright (c) 1998, 1999, 2000 Thai
Open Source Software Center Ltd and Clark Cooper Copyright (c) 2001, 2002, 2003 Expat
maintainers. Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), to deal in the Software
without restriction, including without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to permit persons to
whom the Software is furnished to do so, subject to the following conditions: The above copyright
notice and this permission notice shall be included in all copies or substantial portions
of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR
A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
OR OTHER DEALINGS IN THE SOFTWARE. gfxFontList
License This license applies to the files gfx/thebes/src/gfxMacPlatformFontList.mm
and gfx/thebes/src/gfxPlatformFontList.cpp. Copyright (C) 2006 Apple Computer,
Inc. All rights reserved. Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met: 1. Redistributions
of source code must retain the above copyright notice, this list of conditions and the following
disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution. 3. Neither the name of Apple Computer, Inc.
("Apple") nor the names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. THIS SOFTWARE IS
PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE. Google Gears This license
applies to the file netwerk/wifi/wlanapi.h. Copyright 2008, Google Inc. Redistribution
and use in source and binary forms, with or without modification, are permitted provided
that the following conditions are met: 1. Redistributions of source code must retain
the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions
in binary form must reproduce the above copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of Google Inc. nor the names of its contributors may be used to endorse
or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Google Gears/iStumbler This license applies
to the file netwerk/wifi/osx_wifi.h. Copyright 2008, Google Inc. Redistribution
and use in source and binary forms, with or without modification, are permitted provided
that the following conditions are met: 1. Redistributions of source code must retain
the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions
in binary form must reproduce the above copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of Google Inc. nor the names of its contributors may be used to endorse
or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. The contents of
this file are taken from Apple80211.h from the iStumbler project (http://www.istumbler.net).
This project is released under the BSD license with the following restrictions. Copyright
(c) 02006, Alf Watt (alf@istumbler.net). All rights reserved. Redistribution and use in
source and binary forms, with or without modification, are permitted provided that the following
conditions are met: * Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer. * Redistributions in binary form
must reproduce the above copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of iStumbler nor the names of its contributors may be used to endorse
or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE. Growl License This license
applies to certain files in the directory toolkit/components/alerts/src/mac/growl/
and camino/growl/. (This code only ships in the Mac OS X version
of the product.) Copyright (c) The Growl Project, 2004-2009 All rights reserved. Redistribution
and use in source and binary forms, with or without modification, are permitted provided
that the following conditions are met: 1. Redistributions of source code must retain
the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions
in binary form must reproduce the above copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of Growl nor the names of its contributors may be used to endorse
or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE. Japan Network Information Center License This license applies to certain files in the directory netwerk/dns/src/.
Copyright (c) 2001,2002 Japan Network Information Center. All rights reserved. By
using this file, you agree to the terms and conditions set forth below. LICENSE TERMS
AND CONDITIONS The following License Terms and Conditions apply, unless a different license
is obtained from Japan Network Information Center ("JPNIC"), a Japanese association,
Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda, Chiyoda-ku, Tokyo 101-0047, Japan. 1. Use,
Modification and Redistribution (including distribution of any modified or derived work)
in source and/or binary forms is permitted under this License Terms and Conditions. 2.
Redistribution of source code must retain the copyright notices as they appear in each
source code file, this License Terms and Conditions. 3. Redistribution in binary form must reproduce
the Copyright Notice, this License Terms and Conditions, in the documentation and/or other
materials provided with the distribution. For the purposes of binary distribution the
"Copyright Notice" refers to the following language: "Copyright (c) 2000-2002 Japan Network
Information Center. All rights reserved." 4. The name of JPNIC may not be used to endorse
or promote products derived from this Software without specific prior written approval of
JPNIC. 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
JPNIC BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES. Java Embedding Plugin License This
license applies to certain files in the directory plugin/oji/JEP/.
(This code only ships in the Mac OS X version of this product.) Copyright (c)
2004, Steven Michaud, All Rights Reserved Permission is hereby granted, free of charge,
to any person obtaining a copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so, subject to the following
conditions: The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS",
WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. jemalloc
License This license applies to files in the directory memory/jemalloc/.
Copyright (C) 2006-2008 Jason Evans <jasone@FreeBSD.org>. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted
provided that the following conditions are met: 1. Redistributions of source code must
retain the above copyright notice(s), this list of conditions and the following disclaimer
as the first lines of this file unmodified other than the possible addition of one or
more copyright notices. 2. Redistributions in binary form must reproduce the above copyright
notice(s), this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
HOLDER(S) ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. libevent
License This license applies to files in the directory ipc/chromium/src/third_party/libevent/.
Copyright 2000-2002 Niels Provos <provos@citi.umich.edu> All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted
provided that the following conditions are met: 1. Redistributions of source code must
retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions
and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products derived from
this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE
AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. libffi License This
license applies to files in the directories js/ctypes/libffi/
and js/ctypes/libffi_msvc/. libffi - Copyright (c) 1996-2008
Red Hat, Inc and others. See source files for details. Permission is hereby granted,
free of charge, to any person obtaining a copy of this software and associated documentation
files (the ``Software''), to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so, subject
to the following conditions: The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED
``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Lithuanian Spellchecking Dictionary License This
license applies to certain files in the directory l10n/lt/extensions/spellcheck/hunspell/.
(This code only ships in some localized versions of this product.) The project has
been sponsored by the Information Society Development Committee of the Government of
Republic of Lithuania. Copyright (c) Albertas Agejevas <alga@uosis.mif.vu.lt>, 2000,
2001 All rights reserved. Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met: 1. Redistributions
of source code must retain the above copyright notice, this list of conditions and the following
disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution. 3. Neither the name of the Albertas Agejevas
nor the names of its contributors may be used to endorse or promote products derived from
this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY ALBERTAS
AGEJEVAS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ALBERTAS AGEJEVAS OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. MAAttachedWindow License This license
applies to the files camino/src/extensions/MAAttachedWindow.h and camino/src/extensions/MAAttachedWindow.mm.
(This code only ships in the Camino browser or products based on it.) This software
is supplied to you by Matt Gemmell in consideration of your agreement to the following terms,
and your use, installation, modification or redistribution of this software constitutes
acceptance of these terms. If you do not agree with these terms, please do not use, install,
modify or redistribute this software. In consideration of your agreement to abide by the following
terms, and subject to these terms, Matt Gemmell grants you a personal, non-exclusive license,
to use, reproduce, modify and redistribute the software, with or without modifications,
in source and/or binary forms; provided that if you redistribute the software in its entirety
and without modifications, you must retain this notice and the following text and disclaimers
in all such redistributions of the software, and that in all cases attribution of Matt
Gemmell as the original author of the source code shall be included in all such resulting
software products or distributions. Neither the name, trademarks, service marks or logos
of Matt Gemmell may be used to endorse or promote products derived from the software
without specific prior written permission from Matt Gemmell. Except as expressly stated
in this notice, no other rights or licenses, express or implied, are granted by Matt Gemmell
herein, including but not limited to any patent rights that may be infringed by your derivative
works or by other works in which the software may be incorporated. The software is provided
by Matt Gemmell on an "AS IS" basis. MATT GEMMELL MAKES NO WARRANTIES, EXPRESS OR IMPLIED,
INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION
WITH YOUR PRODUCTS. IN NO EVENT SHALL MATT GEMMELL BE LIABLE FOR ANY SPECIAL, INDIRECT,
INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY
OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE SOFTWARE, HOWEVER
CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY
OR OTHERWISE, EVEN IF MATT GEMMELL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
OpenVision License This license
applies to the file extensions/auth/gssapi.h. Copyright 1993 by OpenVision Technologies,
Inc. Permission to use, copy, modify, distribute, and sell this software and its documentation
for any purpose is hereby granted without fee, provided that the above copyright notice
appears in all copies and that both that copyright notice and this permission notice appear in
supporting documentation, and that the name of OpenVision not be used in advertising or
publicity pertaining to distribution of the software without specific, written prior permission.
OpenVision makes no representations about the suitability of this software for any purpose.
It is provided "as is" without express or implied warranty. OPENVISION DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS, IN NO EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. qcms License
This license applies to certain files in the directory gfx/qcms/.
Copyright (C) 2009 Mozilla Corporation Copyright (C) 1998-2007 Marti Maria Permission
is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following conditions: The above copyright notice and
this permission notice shall be included in all copies or substantial portions of the
Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE. Red Hat xdg_user_dir_lookup License This
license applies to the xdg_user_dir_lookup function in xpcom/io/SpecialSystemDirectory.cpp.
Copyright (c) 2007 Red Hat, Inc. Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so, subject to the following
conditions: The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS",
WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Russian
Spellchecking Dictionary License This license applies to certain files in the directory
l10n/ru/extensions/spellcheck/hunspell/. (This code only ships in some localized versions
of this product.) * Copyright (c) 1997-2008, Alexander I. Lebedev All rights
reserved. Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met: * Redistributions of source
code must retain the above copyright notice, this list of conditions and the following
disclaimer. * Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution. * Modified versions must be clearly marked
as such. * The name of Alexander I. Lebedev may not be used to endorse or promote products
derived from this software without specific prior written permission. THIS SOFTWARE IS
PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE. Sparkle License This license
applies to certain files in the directory camino/sparkle/.
(This code only ships in the in the Camino browser or products based on it.)
Copyright (c) 2006 Andy Matuschak Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so, subject to the following
conditions: The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS",
WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. SunSoft
License This license applies to the ICC_H
block in gfx/qcms/qcms.h. Copyright (c) 1994-1996 SunSoft, Inc.
Rights Reserved Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), to deal in the Software
without restrict- ion, including without limitation the rights to use, copy, modify, merge, publish
distribute, sublicense, and/or sell copies of the Software, and to permit persons to
whom the Software is furnished to do so, subject to the following conditions: The above copyright
notice and this permission notice shall be included in all copies or substantial portions
of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR
A PARTICULAR PURPOSE AND NON- INFRINGEMENT. IN NO EVENT SHALL SUNSOFT, INC. OR ITS PARENT
COMPANY BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of SunSoft,
Inc. shall not be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without written authorization from SunSoft Inc. University
of California License This license applies to the following files or,
in the case of directories, certain files in those directories: dbm/
db/mork/src/morkQuickSort.cpp xpcom/glue/nsQuickSort.cpp
Copyright (c) 1990, 1993 The Regents of the University of California. All rights
reserved. Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met: 1. Redistributions of
source code must retain the above copyright notice, this list of conditions and the following
disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution. [3 Deleted as of 22nd July 1999; see ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change
for details] 4. Neither the name of the University nor the names of its contributors may be used
to endorse or promote products derived from this software without specific prior written
permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. US English Spellchecking
Dictionary Licenses These licenses apply to certain files in the directory
extensions/spellcheck/locales/en-US/hunspell/. (This code only ships in some localized versions
of this product.) Different parts of the US English dictionary (SCOWL) are subject
to the following licenses as shown below. For additional details, sources, credits,
and public domain references, see README.txt. The collective work of the Spell Checking
Oriented Word Lists (SCOWL) is under the following copyright: Copyright 2000-2007 by Kevin Atkinson
Permission to use, copy, modify, distribute and sell these word lists, the associated
scripts, the output created from the scripts, and its documentation for any purpose is hereby
granted without fee, provided that the above copyright notice appears in all copies and
that both that copyright notice and this permission notice appear in supporting documentation.
Kevin Atkinson makes no representations about the suitability of this array for any purpose.
It is provided "as is" without express or implied warranty. The WordNet database is
under the following copyright: This software and database is being provided to you, the
LICENSEE, by Princeton University under the following license. By obtaining, using and/or
copying this software and database, you agree that you have read, understood, and will comply
with these terms and conditions: Permission to use, copy, modify and distribute this software
and database and its documentation for any purpose and without fee or royalty is hereby
granted, provided that you agree to comply with the following copyright notice and statements,
including the disclaimer, and that the same appear on ALL copies of the software, database
and documentation, including modifications that you make for internal use or for distribution.
WordNet 1.6 Copyright 1997 by Princeton University. All rights reserved. THIS SOFTWARE AND DATABASE
IS PROVIDED "AS IS" AND PRINCETON UNIVERSITY MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS
OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PRINCETON UNIVERSITY MAKES NO REPRESENTATIONS
OR WARRANTIES OF MERCHANT- ABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE
OF THE LICENSED SOFTWARE, DATABASE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY PATENTS,
COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. The name of Princeton University or Princeton
may not be used in advertising or publicity pertaining to distribution of the software
and/or database. Title to copyright in this software, database and any associated documentation
shall at all times remain with Princeton University and LICENSEE agrees to preserve same. The
"UK Advanced Cryptics Dictionary" is under the following copyright: Copyright (c) J Ross
Beresford 1993-1999. All Rights Reserved. The following restriction is placed on the
use of this publication: if The UK Advanced Cryptics Dictionary is used in a software
package or redistributed in any form, the copyright notice must be prominently displayed
and the text of this document must be included verbatim. There are no other restrictions:
I would like to see the list distributed as widely as possible. Various parts are under
the Ispell copyright: Copyright 1993, Geoff Kuenning, Granada Hills, CA All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted
provided that the following conditions are met: 1. Redistributions of source code must
retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions
and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. All modifications to the source code must be clearly marked as such. Binary redistributions
based on modified source code must be clearly marked as modified versions in the documentation
and/or other materials provided with the distribution. (clause 4 removed with permission from Geoff
Kuenning) 5. The name of Geoff Kuenning may not be used to endorse or promote products
derived from this software without specific prior written permission. THIS SOFTWARE IS
PROVIDED BY GEOFF KUENNING AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GEOFF KUENNING OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE. Additional Contributors: Alan Beale <biljir@pobox.com> M Cooper <thegrendel@theriver.com>
Xiph.org Foundation License This
license applies to files in the following directories with the specified copyright year
ranges: media/libogg/, 2002 media/libtheora/,
2002-2007 media/libvorbis/, 2002-2004 Copyright (c) <year>,
Xiph.org Foundation Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met: - Redistributions
of source code must retain the above copyright notice, this list of conditions and the following
disclaimer. - Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution. - Neither the name of the Xiph.org Foundation
nor the names of its contributors may be used to endorse or promote products derived from
this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE
COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Other Required Notices This software is based in part on
the work of the Independent JPEG Group. Portions of the OS/2 and Windows Mobile
versions of this software are copyright ©1996-2002 The FreeType
Project. All rights reserved. Optional
Notices Some permissive software licenses request but do not require
an acknowledgement of the use of their software. We are very grateful to the following people
and projects for their contributions to this product: The zlib
compression library (Jean-loup Gailly, Mark Adler and team) The bzip2
compression library (Julian Seward) The libpng
graphics library (Glenn Randers-Pehrson and team) The sqlite
database engine (D. Richard Hipp and team) The Nullsoft
Scriptable Install System Return
to top. content/browser/certerror/aboutCertError.xhtml %globalDTD; %certerrorDTD;
&certerror.pagetitle;
tags, but // not allow for any injection by just using innerHTML.
Instead, // just find the right target text node. var intro = document.getElementById('introContentP1');
function replaceWithHost(node) { if (node.textContent == "#1") node.textContent = location.host;
else for(var i = 0; i < node.childNodes.length; i++) replaceWithHost(node.childNodes[i]);
}; replaceWithHost(intro); if (getCSSClass() == "expertBadCert") { toggle('technicalContent');
toggle('expertContent'); } var tech = document.getElementById("technicalContentText"); if (tech) tech.textContent = getDescription();
addDomainErrorLink(); } /* In the case of SSL error pages about domain mismatch, see
if we can hyperlink the user to the correct site. We don't want to do this generically
since it allows MitM attacks to redirect users to a site under attacker control, but in certain
cases it is safe (and helpful!) to do so. Bug 402210 */ function addDomainErrorLink()
{ // Rather than textContent, we need to treat description as HTML var sd = document.getElementById("technicalContentText");
if (sd) { var desc = getDescription(); // sanitize description text - see bug 441169
// First, find the index of the tag we care about, being careful not to // use an
over-greedy regex var re = /
if (perm.type == "offline-app" && perm.capability != Components.interfaces.nsIPermissionManager.DEFAULT_ACTION
&& perm.capability != Components.interfaces.nsIPermissionManager.DENY_ACTION) { var row = document.createElement("listitem");
row.id = ""; row.className = "offlineapp"; row.setAttribute("host", perm.host); var converted
= DownloadUtils. convertByteUnits(this._getOfflineAppUsage(perm.host, groups)); row.setAttribute("usage", bundle.getFormattedString("offlineAppUsage",
converted)); list.appendChild(row); } } }, offlineAppSelected: function() var removeButton
= document.getElementById("offlineAppsListRemove"); var list = document.getElementById("offlineAppsList");
if (list.selectedItem) { removeButton.setAttribute("disabled", "false"); } else { removeButton.setAttribute("disabled",
"true"); } }, removeOfflineApp: function() var list = document.getElementById("offlineAppsList");
var item = list.selectedItem; var host = item.getAttribute("host"); var prompts =
Components.classes["@mozilla.org/embedcomp/prompt-service;1"] .getService(Components.interfaces.nsIPromptService);
var flags = prompts.BUTTON_TITLE_IS_STRING * prompts.BUTTON_POS_0 + prompts.BUTTON_TITLE_CANCEL
* prompts.BUTTON_POS_1; var bundle = document.getElementById("bundlePreferences"); var title = bundle.getString("offlineAppRemoveTitle");
var prompt = bundle.getFormattedString("offlineAppRemovePrompt", [host]); var confirm = bundle.getString("offlineAppRemoveConfirm");
var result = prompts.confirmEx(window, title, prompt, flags, confirm, null, null, null,
{}); if (result != 0) return; // clear offline cache entries var cacheService = Components.classes["@mozilla.org/network/application-cache-service;1"].
getService(Components.interfaces.nsIApplicationCacheService); var ios = Components.classes["@mozilla.org/network/io-service;1"].
getService(Components.interfaces.nsIIOService); var groups = cacheService.getGroups({}); for
(var i = 0; i < groups.length; i++) { var uri = ios.newURI(groups[i], null, null); if
(uri.asciiHost == host) { var cache = cacheService.getActiveCache(groups[i]); cache.discard(); } } // send out an offline-app-removed
signal. The nsDOMStorage // service will clear DOM storage for this host. var obs = Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService); obs.notifyObservers(null, "offline-app-removed",
host); // remove the permission var pm = Components.classes["@mozilla.org/permissionmanager;1"]
.getService(Components.interfaces.nsIPermissionManager); pm.remove(host, "offline-app", Components.interfaces.nsIPermissionManager.ALLOW_ACTION);
pm.remove(host, "offline-app", Components.interfaces.nsIOfflineCacheUpdateService.ALLOW_NO_WARN); list.removeChild(item); gAdvancedPane.offlineAppSelected();
}, // UPDATE TAB /* * Preferences: * * app.update.enabled * - true if updates to the application are
enabled, false otherwise * extensions.update.enabled * - true if updates to extensions and themes
are enabled, false otherwise * browser.search.update * - true if updates to search engines are
enabled, false otherwise * app.update.auto * - true if updates should be automatically
downloaded and installed, * possibly with a warning if incompatible extensions are installed
(see * app.update.mode); false if the user should be asked what he wants to do * when
an update is available * app.update.mode * - an integer: * 0 do not warn if an update
will disable extensions or themes * 1 warn if an update will disable extensions or themes
* 2 warn if an update will disable extensions or themes *or* if the * update is a major
update */ /** * Enables and disables various UI preferences as necessary to reflect locked,
* disabled, and checked/unchecked states. * * UI state matrix for update preference
conditions * * UI Components: Preferences * 1 = Firefox checkbox i = app.update.enabled
* 2 = When updates for Firefox are found label ii = app.update.auto * 3 = Automatic
Radiogroup (Ask vs. Automatically) iii = app.update.mode * 4 = Warn before disabling
extensions checkbox * * States: * Element p val locked Disabled * 1 i t/f f false *
i t/f t true * ii t/f t/f false * iii 0/1/2 t/f false * 2,3 i t t/f false * i f t/f true
* ii t/f f false * ii t/f t true * iii 0/1/2 t/f false * 4 i t t/f false * i f t/f true
* ii t t/f false * ii f t/f true * iii 0/1/2 f false * iii 0/1/2 t true * */ //@line 434
"e:\builds\moz2_slave\win32_build\build\browser\components\preferences\advanced.js" updateAppUpdateItems: function () var aus
= Components.classes["@mozilla.org/updates/update-service;1"]. getService(Components.interfaces.nsIApplicationUpdateService2);
var enabledPref = document.getElementById("app.update.enabled"); var enableAppUpdate = document.getElementById("enableAppUpdate");
enableAppUpdate.disabled = !aus.canCheckForUpdates || enabledPref.locked; }, /** * Enables/disables
UI for "when updates are found" based on the values, * and "locked" states of associated
preferences. */ updateAutoItems: function () var enabledPref = document.getElementById("app.update.enabled");
var autoPref = document.getElementById("app.update.auto"); var updateModeLabel = document.getElementById("updateModeLabel");
var updateMode = document.getElementById("updateMode"); var disable = enabledPref.locked || !enabledPref.value
|| autoPref.locked; updateModeLabel.disabled = updateMode.disabled = disable; }, /**
* Enables/disables the "warn if incompatible extensions/themes exist" UI * based on the
values and "locked" states of various preferences. */ updateModeItems: function () var enabledPref
= document.getElementById("app.update.enabled"); var autoPref = document.getElementById("app.update.auto");
var modePref = document.getElementById("app.update.mode"); var warnIncompatible = document.getElementById("warnIncompatible");
var disable = enabledPref.locked || !enabledPref.value || autoPref.locked || !autoPref.value ||
modePref.locked; warnIncompatible.disabled = disable; }, /** * Stores the value of the
app.update.mode preference, which is a tristate * integer preference. We store the value
here so that we can properly * restore the preference value if the UI reflecting the
preference value * is in a state which can represent either of two integer values (as
* opposed to only one possible value in the other UI state). */ _modePreference: -1,
/** * Reads the app.update.mode preference and converts its value into a * true/false
value for use in determining whether the "Warn me if this will * disable extensions or themes"
checkbox is checked. We also save the value * of the preference so that the preference
value can be properly restored if * the user's preferences cannot adequately be expressed
by a single checkbox. * * app.update.modee Checkbox State Meaning * 0 Unchecked Do not
warn * 1 Checked Warn if there are incompatibilities * 2 Checked Warn if there are incompatibilities,
* or the update is major. */ readAddonWarn: function () var preference = document.getElementById("app.update.mode");
var doNotWarn = preference.value != 0; gAdvancedPane._modePreference = doNotWarn ? preference.value : 1; return
doNotWarn; }, /** * Converts the state of the "Warn me if this will disable extensions
or * themes" checkbox into the integer preference which represents it, * returning that value.
*/ writeAddonWarn: function () var warnIncompatible = document.getElementById("warnIncompatible");
return !warnIncompatible.checked ? 0 : gAdvancedPane._modePreference; }, /** * Displays the history of installed
updates. */ showUpdates: function () var prompter = Components.classes["@mozilla.org/updates/update-prompt;1"]
.createInstance(Components.interfaces.nsIUpdatePrompt); prompter.showUpdateHistory(window); }, //@line
531 "e:\builds\moz2_slave\win32_build\build\browser\components\preferences\advanced.js" /** * The Extensions checkbox and button
are disabled only if the enable Addon * update preference is locked. */ updateAddonUpdateUI:
function () var enabledPref = document.getElementById("extensions.update.enabled"); var enableAddonUpdate = document.getElementById("enableAddonUpdate");
enableAddonUpdate.disabled = enabledPref.locked; }, // ENCRYPTION TAB /* * Preferences: *
* security.enable_ssl3 * - true if SSL 3 encryption is enabled, false otherwise *
security.enable_tls * - true if TLS encryption is enabled, false otherwise * security.default_personal_cert
* - a string: * "Select Automatically" select a certificate automatically when a site *
requests one * "Ask Every Time" present a dialog to the user so he can select * the
certificate to use on a site which * requests one */ /** * Displays the user's certificates
and associated options. */ showCertificates: function () document.documentElement.openWindow("mozilla:certmanager",
"chrome://pippki/content/certManager.xul", "", null); }, /** * Displays a dialog which
describes the user's CRLs. */ showCRLs: function () document.documentElement.openWindow("mozilla:crlmanager",
"chrome://pippki/content/crlManager.xul", "", null); }, /** * Displays a dialog in
which OCSP preferences can be configured. */ showOCSP: function () document.documentElement.openSubDialog("chrome://mozapps/content/preferences/ocsp.xul",
"", null); }, /** * Displays a dialog from which the user can manage his security devices.
*/ showSecurityDevices: function () document.documentElement.openWindow("mozilla:devicemanager", "chrome://pippki/content/device_manager.xul",
"", null); //@line 601 "e:\builds\moz2_slave\win32_build\build\browser\components\preferences\advanced.js" // SYSTEM DEFAULTS /* * Preferences: * *
browser.shell.checkDefault * - true if a default-browser check (and prompt to make
it so if necessary) * occurs at startup, false otherwise */ /** * Checks whether the browser
is currently registered with the operating * system as the default browser. If the browser
is not currently the * default browser, the user is given the option of making it the
default; * otherwise, the user is informed that this browser already is the browser.
*/ checkNow: function () var shellSvc = Components.classes["@mozilla.org/browser/shell-service;1"]
.getService(Components.interfaces.nsIShellService); var brandBundle = document.getElementById("bundleBrand");
var shellBundle = document.getElementById("bundleShell"); var brandShortName = brandBundle.getString("brandShortName");
var promptTitle = shellBundle.getString("setDefaultBrowserTitle"); var promptMessage; const IPS = Components.interfaces.nsIPromptService;
var psvc = Components.classes["@mozilla.org/embedcomp/prompt-service;1"] .getService(IPS); if (!shellSvc.isDefaultBrowser(false))
{ promptMessage = shellBundle.getFormattedString("setDefaultBrowserMessage", [brandShortName]); var rv = psvc.confirmEx(window,
promptTitle, promptMessage, IPS.STD_YES_NO_BUTTONS, null, null, null, null, { }); if (rv == 0)
shellSvc.setDefaultBrowser(true, false); } else { promptMessage = shellBundle.getFormattedString("alreadyDefaultBrowser",
[brandShortName]); psvc.alert(window, promptTitle, promptMessage); } //@line 647 "e:\builds\moz2_slave\win32_build\build\browser\components\preferences\advanced.js"
content/browser/preferences/advanced-scripts.xul
content/browser/preferences/applications.xul
&defaultFont.label;
&defaultSize.label;
&chooseLanguage.label;
content/browser/preferences/content.js//@line
40 "e:\builds\moz2_slave\win32_build\build\browser\components\preferences\content.js" var gContentPane = { /** * Initializes the
fonts dropdowns displayed in this pane. */ init: function () this._rebuildFonts(); var
menulist = document.getElementById("defaultFont"); if (menulist.selectedIndex == -1) { menulist.insertItemAt(0,
"", "", ""); menulist.selectedIndex = 0; } }, // UTILITY FUNCTIONS /** * Utility function
to enable/disable the button specified by aButtonID based * on the value of the Boolean
preference specified by aPreferenceID. */ updateButtons: function (aButtonID, aPreferenceID)
var button = document.getElementById(aButtonID); var preference = document.getElementById(aPreferenceID);
button.disabled = preference.value != true; return undefined; }, /** * The exceptions
types which may be passed to this._showExceptions(). */ _exceptionsParams: { popup: { blockVisible:
false, sessionVisible: false, allowVisible: true, prefilledHost: "", permissionType: "popup"
}, image: { blockVisible: true, sessionVisible: false, allowVisible: true, prefilledHost:
"", permissionType: "image" } }, /** * Displays the exceptions dialog of the given type, where
types map onto the * the fields in this._exceptionsParams. */ _showExceptions: function (aPermissionType)
var bundlePreferences = document.getElementById("bundlePreferences"); var params = this._exceptionsParams[aPermissionType];
params.windowTitle = bundlePreferences.getString(aPermissionType + "permissionstitle"); params.introText =
bundlePreferences.getString(aPermissionType + "permissionstext"); document.documentElement.openWindow("Browser:Permissions",
"chrome://browser/content/preferences/permissions.xul", "", params); }, // BEGIN UI CODE /* * Preferences:
* * dom.disable_open_during_load * - true if popups are blocked by default, false otherwise
* permissions.default.image * - an integer: * 1 all images should be loaded, * 2 no images
should be loaded, * 3 load only images from the site on which the current page resides
* (i.e., if viewing foo.example.com, foo.example.com/foo.jpg and * bar.foo.example.com/bar.jpg load but
example.com/quux.jpg does not) * javascript.enabled * - true if JavaScript is enabled, false
otherwise */ // POP-UPS /** * Displays the popup exceptions dialog where specific site
popup preferences * can be set. */ showPopupExceptions: function () this._showExceptions("popup");
}, // IMAGES /** * Converts the value of the permissions.default.image preference into
a * Boolean value for use in determining the state of the "load images" * checkbox, returning
true if images should be loaded and false otherwise. */ readLoadImages: function ()
var pref = document.getElementById("permissions.default.image"); return (pref.value == 1 || pref.value ==
3); }, /** * Returns the "load images" preference value which maps to the state of the * preferences
UI. */ writeLoadImages: function () { return (document.getElementById("loadImages").checked)
? 1 : 2; }, /** * Displays image exception preferences for which websites can and cannot
* load images. */ showImageExceptions: function () this._showExceptions("image"); }, //
JAVASCRIPT /** * Displays the advanced JavaScript preferences for enabling or disabling * various
annoying behaviors. */ showAdvancedJS: function () document.documentElement.openSubDialog("chrome://browser/content/preferences/advanced-scripts.xul",
"", null); }, // FONTS /** * Populates the default font list in UI. */ _rebuildFonts:
function () var langGroupPref = document.getElementById("font.language.group"); this._selectDefaultLanguageGroup(langGroupPref.value,
this._readDefaultFontTypeForLanguage(langGroupPref.value) == "serif"); }, /** * */ _selectDefaultLanguageGroup:
function (aLanguageGroup, aIsSerif) const kFontNameFmtSerif = "font.name.serif.%LANG%";
const kFontNameFmtSansSerif = "font.name.sans-serif.%LANG%"; const kFontNameListFmtSerif = "font.name-list.serif.%LANG%";
const kFontNameListFmtSansSerif = "font.name-list.sans-serif.%LANG%"; const kFontSizeFmtVariable = "font.size.variable.%LANG%";
var prefs = [{ format : aIsSerif ? kFontNameFmtSerif : kFontNameFmtSansSerif, type : "fontname",
element : "defaultFont", fonttype : aIsSerif ? "serif" : "sans-serif" }, { format : aIsSerif
? kFontNameListFmtSerif : kFontNameListFmtSansSerif, type : "unichar", element : null, fonttype
: aIsSerif ? "serif" : "sans-serif" }, { format : kFontSizeFmtVariable, type : "int",
element : "defaultFontSize", fonttype : null }]; var preferences = document.getElementById("contentPreferences");
for (var i = 0; i < prefs.length; ++i) { var preference = document.getElementById(prefs[i].format.replace(/%LANG%/,
aLanguageGroup)); if (!preference) { preference = document.createElement("preference"); var
name = prefs[i].format.replace(/%LANG%/, aLanguageGroup); preference.id = name; preference.setAttribute("name",
name); preference.setAttribute("type", prefs[i].type); preferences.appendChild(preference); } if
(!prefs[i].element) continue; var element = document.getElementById(prefs[i].element);
if (element) { element.setAttribute("preference", preference.id); if (prefs[i].fonttype) FontBuilder.buildFontList(aLanguageGroup,
prefs[i].fonttype, element); preference.setElementValue(element); } } }, /** * Returns the type of the current
default font for the language denoted by * aLanguageGroup. */ _readDefaultFontTypeForLanguage:
function (aLanguageGroup) const kDefaultFontType = "font.default.%LANG%"; var defaultFontTypePref
= kDefaultFontType.replace(/%LANG%/, aLanguageGroup); var preference = document.getElementById(defaultFontTypePref);
if (!preference) { preference = document.createElement("preference"); preference.id = defaultFontTypePref; preference.setAttribute("name",
defaultFontTypePref); preference.setAttribute("type", "string"); preference.setAttribute("onchange",
"gContentPane._rebuildFonts();"); document.getElementById("contentPreferences").appendChild(preference); } return preference.value; }, /** * Displays
the fonts dialog, where web page font names and sizes can be * configured. */ configureFonts:
function () document.documentElement.openSubDialog("chrome://browser/content/preferences/fonts.xul", "", null); }, /** * Displays the colors dialog,
where default web page/link/etc. colors can be * configured. */ configureColors: function
() document.documentElement.openSubDialog("chrome://browser/content/preferences/colors.xul", "", null); }, // LANGUAGES /** * Shows a
dialog in which the preferred language for web content may be set. */ showLanguages:
function () document.documentElement.openSubDialog("chrome://browser/content/preferences/languages.xul", "", null); content/browser/preferences/connection.xul
content/browser/preferences/connection.js//@line
38 "e:\builds\moz2_slave\win32_build\build\browser\components\preferences\connection.js" var gConnectionsDialog = { beforeAccept: function
() var proxyTypePref = document.getElementById("network.proxy.type"); if (proxyTypePref.value == 2) { this.doAutoconfigURLFixup();
return true; } if (proxyTypePref.value != 1) return true; var httpProxyURLPref = document.getElementById("network.proxy.http");
var httpProxyPortPref = document.getElementById("network.proxy.http_port"); var shareProxiesPref = document.getElementById("network.proxy.share_proxy_settings");
if (shareProxiesPref.value) { var proxyPrefs = ["ssl", "ftp", "socks", "gopher"]; for
(var i = 0; i < proxyPrefs.length; ++i) { var proxyServerURLPref = document.getElementById("network.proxy."
+ proxyPrefs[i]); var proxyPortPref = document.getElementById("network.proxy." + proxyPrefs[i] + "_port"); var backupServerURLPref
= document.getElementById("network.proxy.backup." + proxyPrefs[i]); var backupPortPref = document.getElementById("network.proxy.backup."
+ proxyPrefs[i] + "_port"); backupServerURLPref.value = proxyServerURLPref.value; backupPortPref.value
= proxyPortPref.value; proxyServerURLPref.value = httpProxyURLPref.value; proxyPortPref.value
= httpProxyPortPref.value; } } var noProxiesPref = document.getElementById("network.proxy.no_proxies_on");
noProxiesPref.value = noProxiesPref.value.replace(/[;]/g,','); return true; }, checkForSystemProxy: function
() if ("@mozilla.org/system-proxy-settings;1" in Components.classes) document.getElementById("systemPref").removeAttribute("hidden");
}, proxyTypeChanged: function () var proxyTypePref = document.getElementById("network.proxy.type");
// Update http var httpProxyURLPref = document.getElementById("network.proxy.http"); httpProxyURLPref.disabled = proxyTypePref.value
!= 1; var httpProxyPortPref = document.getElementById("network.proxy.http_port"); httpProxyPortPref.disabled = proxyTypePref.value
!= 1; // Now update the other protocols this.updateProtocolPrefs(); var shareProxiesPref = document.getElementById("network.proxy.share_proxy_settings");
shareProxiesPref.disabled = proxyTypePref.value != 1; var noProxiesPref = document.getElementById("network.proxy.no_proxies_on");
noProxiesPref.disabled = proxyTypePref.value != 1; var autoconfigURLPref = document.getElementById("network.proxy.autoconfig_url");
autoconfigURLPref.disabled = proxyTypePref.value != 2; this.updateReloadButton(); }, updateReloadButton:
function () // Disable the "Reload PAC" button if the selected proxy type is not PAC or
// if the current value of the PAC textbox does not match the value stored // in prefs.
Likewise, disable the reload button if PAC is not configured // in prefs. var typedURL
= document.getElementById("networkProxyAutoconfigURL").value; var proxyTypeCur = document.getElementById("network.proxy.type").value;
var prefs = Components.classes["@mozilla.org/preferences-service;1"]. getService(Components.interfaces.nsIPrefBranch);
var pacURL = prefs.getCharPref("network.proxy.autoconfig_url"); var proxyType = prefs.getIntPref("network.proxy.type");
var disableReloadPref = document.getElementById("pref.advanced.proxies.disable_button.reload"); disableReloadPref.disabled = (proxyTypeCur
!= 2 || proxyType != 2 || typedURL != pacURL); }, readProxyType: function () this.proxyTypeChanged();
return undefined; }, updateProtocolPrefs: function () var proxyTypePref = document.getElementById("network.proxy.type");
var shareProxiesPref = document.getElementById("network.proxy.share_proxy_settings"); var proxyPrefs = ["ssl", "ftp", "socks", "gopher"];
for (var i = 0; i < proxyPrefs.length; ++i) { var proxyServerURLPref = document.getElementById("network.proxy."
+ proxyPrefs[i]); var proxyPortPref = document.getElementById("network.proxy." + proxyPrefs[i] + "_port"); // Restore previous
per-proxy custom settings, if present. if (!shareProxiesPref.value) { var backupServerURLPref
= document.getElementById("network.proxy.backup." + proxyPrefs[i]); var backupPortPref = document.getElementById("network.proxy.backup."
+ proxyPrefs[i] + "_port"); if (backupServerURLPref.hasUserValue) { proxyServerURLPref.value = backupServerURLPref.value;
backupServerURLPref.reset(); } if (backupPortPref.hasUserValue) { proxyPortPref.value = backupPortPref.value;
backupPortPref.reset(); } } proxyServerURLPref.updateElements(); proxyPortPref.updateElements(); proxyServerURLPref.disabled
= proxyTypePref.value != 1 || shareProxiesPref.value; proxyPortPref.disabled = proxyServerURLPref.disabled;
} var socksVersionPref = document.getElementById("network.proxy.socks_version"); socksVersionPref.disabled = proxyTypePref.value
!= 1 || shareProxiesPref.value; return undefined; }, readProxyProtocolPref: function (aProtocol,
aIsPort) var shareProxiesPref = document.getElementById("network.proxy.share_proxy_settings"); if (shareProxiesPref.value) { var pref =
document.getElementById("network.proxy.http" + (aIsPort ? "_port" : "")); return pref.value;
} var backupPref = document.getElementById("network.proxy.backup." + aProtocol + (aIsPort ? "_port" : ""));
return backupPref.hasUserValue ? backupPref.value : undefined; }, reloadPAC: function () Components.classes["@mozilla.org/network/protocol-proxy-service;1"].
getService().reloadPAC(); }, doAutoconfigURLFixup: function () var autoURL = document.getElementById("networkProxyAutoconfigURL");
var autoURLPref = document.getElementById("network.proxy.autoconfig_url"); var URIFixup = Components.classes["@mozilla.org/docshell/urifixup;1"]
.getService(Components.interfaces.nsIURIFixup); try { autoURLPref.value = autoURL.value =
URIFixup.createFixupURI(autoURL.value, 0).spec; } catch(ex) {} }, readHTTPProxyServer: function
() var shareProxiesPref = document.getElementById("network.proxy.share_proxy_settings"); if (shareProxiesPref.value) this.updateProtocolPrefs();
return undefined; }, readHTTPProxyPort: function () var shareProxiesPref = document.getElementById("network.proxy.share_proxy_settings");
if (shareProxiesPref.value) this.updateProtocolPrefs(); return undefined; \_9O. content/browser/preferences/fonts.xul
&language.label;
&proportional.label;
&serif.label; &sans-serif.label;
&monospace.label;
&minSize.label;
content/browser/preferences/fonts.js//@line
39 "e:\builds\moz2_slave\win32_build\build\browser\components\preferences\fonts.js" //@line 41 "e:\builds\moz2_slave\win32_build\build\browser\components\preferences\fonts.js"
const kDefaultFontType = "font.default.%LANG%"; const kFontNameFmtSerif = "font.name.serif.%LANG%";
const kFontNameFmtSansSerif = "font.name.sans-serif.%LANG%"; const kFontNameFmtMonospace = "font.name.monospace.%LANG%";
const kFontNameListFmtSerif = "font.name-list.serif.%LANG%"; const kFontNameListFmtSansSerif = "font.name-list.sans-serif.%LANG%";
const kFontNameListFmtMonospace = "font.name-list.monospace.%LANG%"; const kFontSizeFmtVariable = "font.size.variable.%LANG%";
const kFontSizeFmtFixed = "font.size.fixed.%LANG%"; const kFontMinSizeFmt = "font.minimum-size.%LANG%";
var gFontsDialog = { _selectLanguageGroup: function (aLanguageGroup) var prefs = [{
format: kDefaultFontType, type: "string", element: "defaultFontType", fonttype: null},
{ format: kFontNameFmtSerif, type: "fontname", element: "serif", fonttype: "serif" }, {
format: kFontNameFmtSansSerif, type: "fontname", element: "sans-serif", fonttype: "sans-serif"
}, { format: kFontNameFmtMonospace, type: "fontname", element: "monospace", fonttype:
"monospace" }, { format: kFontNameListFmtSerif, type: "unichar", element: null, fonttype:
"serif" }, { format: kFontNameListFmtSansSerif, type: "unichar", element: null, fonttype:
"sans-serif" }, { format: kFontNameListFmtMonospace, type: "unichar", element: null, fonttype:
"monospace" }, { format: kFontSizeFmtVariable, type: "int", element: "sizeVar", fonttype:
null }, { format: kFontSizeFmtFixed, type: "int", element: "sizeMono", fonttype: null
}, { format: kFontMinSizeFmt, type: "int", element: "minSize", fonttype: null }]; var
preferences = document.getElementById("fontPreferences"); for (var i = 0; i < prefs.length; ++i) {
var preference = document.getElementById(prefs[i].format.replace(/%LANG%/, aLanguageGroup)); if (!preference) { preference
= document.createElement("preference"); var name = prefs[i].format.replace(/%LANG%/, aLanguageGroup);
preference.id = name; preference.setAttribute("name", name); preference.setAttribute("type", prefs[i].type);
preferences.appendChild(preference); } if (!prefs[i].element) continue; var element
= document.getElementById(prefs[i].element); if (element) { element.setAttribute("preference",
preference.id); if (prefs[i].fonttype) FontBuilder.buildFontList(aLanguageGroup, prefs[i].fonttype, element); preference.setElementValue(element);
} } }, readFontLanguageGroup: function () var languagePref = document.getElementById("font.language.group");
this._selectLanguageGroup(languagePref.value); return undefined; }, readFontSelection: function
(aElement) // Determine the appropriate value to select, for the following cases: // -
there is no setting // - the font selected by the user is no longer present (e.g. deleted
from // fonts folder) var preference = document.getElementById(aElement.getAttribute("preference")); if (preference.value) { var fontItems = aElement.getElementsByAttribute("value",
preference.value); // There is a setting that actually is in the list. Respect it. if (fontItems.length
> 0) return undefined; } var defaultValue = aElement.firstChild.firstChild.getAttribute("value");
var languagePref = document.getElementById("font.language.group"); preference = document.getElementById("font.name-list."
+ aElement.id + "." + languagePref.value); if (!preference || !preference.hasUserValue)
return defaultValue; var fontNames = preference.value.split(","); var stripWhitespace = /^\s*(.*)\s*$/; for
(var i = 0; i < fontNames.length; ++i) { var fontName = fontNames[i].replace(stripWhitespace,
"$1"); fontItems = aElement.getElementsByAttribute("value", fontName); if (fontItems.length) break; }
if (fontItems.length) return fontItems[0].getAttribute("value"); return defaultValue; }, _charsetMenuInitialized:
false, readDefaultCharset: function () if (!this._charsetMenuInitialized) { var os
= Components.classes["@mozilla.org/observer-service;1"] .getService(Components.interfaces.nsIObserverService);
os.notifyObservers(null, "charsetmenu-selected", "other"); this._charsetMenuInitialized =
true; } return undefined; }, readUseDocumentFonts: function () var preference = document.getElementById("browser.display.use_document_fonts");
return preference.value == 1; }, writeUseDocumentFonts: function () var useDocumentFonts = document.getElementById("useDocumentFonts");
return useDocumentFonts.checked ? 1 : 0; content/browser/preferences/handlers.xml %brandDTD; %applicationsDTD;
return this.getAttribute("type");
gApplicationsPane.rebuildActionsMenu();
content/browser/preferences/handlers.css/* ***** BEGIN LICENSE BLOCK ***** * Version:
MPL 1.1/GPL 2.0/LGPL 2.1 * The contents of this file are subject to the Mozilla Public
License Version * 1.1 (the "License"); you may not use this file except in compliance
with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/
* Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT
WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language
governing rights and limitations under the * License. * The Original Code is the Mozilla
browser. * The Initial Developer of the Original Code is Mozilla. * Portions created by the
Initial Developer are Copyright (C) 2007 * the Initial Developer. All Rights Reserved.
* Contributor(s): * Myk Melez * 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 *****
*/ richlistitem { -moz-binding: url("chrome://browser/content/preferences/handlers.xml#handler"); richlistitem[selected="true"] { -moz-binding:
url("chrome://browser/content/preferences/handlers.xml#handler-selected"); * Make the icons appear. * Note: we display
the icon box for every item whether or not it has an icon * so the labels of all the
items align vertically. .actionsMenu > menupopup > menuitem > .menu-iconic-left { display:
-moz-box; min-width: 16px; listitem.offlineapp { -moz-binding: url("chrome://browser/content/preferences/handlers.xml#offlineapp");
content/browser/preferences/languages.xul
&languages.customize.prefLangDescript; &languages.customize.active.label;
content/browser/preferences/languages.js//@line
40 "e:\builds\moz2_slave\win32_build\build\browser\components\preferences\languages.js" var gLanguagesDialog = { _availableLanguagesList
: [], _acceptLanguages : { }, _selectedItemID : null, init: function () if (!this._availableLanguagesList.length)
this._loadAvailableLanguages(); }, get _activeLanguages() return document.getElementById("activeLanguages");
}, get _availableLanguages() return document.getElementById("availableLanguages"); }, _loadAvailableLanguages: function ()
// This is a parser for: resource://gre/res/language.properties // The file is formatted like so: // ab[-cd].accept=true|false
// ab = language // cd = region var bundleAccepted = document.getElementById("bundleAccepted");
var bundleRegions = document.getElementById("bundleRegions"); var bundleLanguages = document.getElementById("bundleLanguages");
var bundlePreferences = document.getElementById("bundlePreferences"); function LanguageInfo(aName, aABCD, aIsVisible)
{ this.name = aName; this.abcd = aABCD; this.isVisible = aIsVisible; } // 1) Read the available
languages out of language.properties var strings = bundleAccepted.strings; while (strings.hasMoreElements())
{ var currString = strings.getNext(); if (!(currString instanceof Components.interfaces.nsIPropertyElement))
break; var property = currString.key.split("."); // ab[-cd].accept if (property[1] == "accept")
{ var abCD = property[0]; var abCDPairs = abCD.split("-"); // ab[-cd] var useABCDFormat
= abCDPairs.length > 1; var ab = useABCDFormat ? abCDPairs[0] : abCD; var cd = useABCDFormat
? abCDPairs[1] : ""; if (ab) { var language = ""; try { language = bundleLanguages.getString(ab);
} catch (e) { continue; }; var region = ""; if (useABCDFormat) { try { region = bundleRegions.getString(cd);
} catch (e) { continue; } } var name = ""; if (useABCDFormat) name = bundlePreferences.getFormattedString("languageRegionCodeFormat",
[language, region, abCD]); else name = bundlePreferences.getFormattedString("languageCodeFormat", [language, abCD]); if (name && abCD) { var
isVisible = currString.value == "true" && (!(abCD in this._acceptLanguages) || !this._acceptLanguages[abCD]);
var li = new LanguageInfo(name, abCD, isVisible); this._availableLanguagesList.push(li); }
} } } this._buildAvailableLanguageList(); }, _buildAvailableLanguageList: function
() var availableLanguagesPopup = document.getElementById("availableLanguagesPopup"); while (availableLanguagesPopup.hasChildNodes())
availableLanguagesPopup.removeChild(availableLanguagesPopup.firstChild); // Sort the list of languages by name this._availableLanguagesList.sort(function
(a, b) { return a.name.localeCompare(b.name); }); // Load the UI with the data for (var
i = 0; i < this._availableLanguagesList.length; ++i) { var abCD = this._availableLanguagesList[i].abcd;
if (this._availableLanguagesList[i].isVisible && (!(abCD in this._acceptLanguages) ||
!this._acceptLanguages[abCD])) { var menuitem = document.createElement("menuitem"); menuitem.id
= this._availableLanguagesList[i].abcd; availableLanguagesPopup.appendChild(menuitem); menuitem.setAttribute("label", this._availableLanguagesList[i].name);
} } }, readAcceptLanguages: function () while (this._activeLanguages.hasChildNodes())
this._activeLanguages.removeChild(this._activeLanguages.firstChild); var selectedIndex = 0; var preference = document.getElementById("intl.accept_languages");
if (preference.value == "") return undefined; var languages = preference.value.toLowerCase().split(/\s*,\s*/);
for (var i = 0; i < languages.length; ++i) { var name = this._getLanguageName(languages[i]);
if (!name) name = "[" + languages[i] + "]"; var listitem = document.createElement("listitem");
listitem.id = languages[i]; if (languages[i] == this._selectedItemID) selectedIndex =
i; this._activeLanguages.appendChild(listitem); listitem.setAttribute("label", name); //
Hash this language as an "Active" language so we don't // show it in the list that can
be added. this._acceptLanguages[languages[i]] = true; } if (this._activeLanguages.childNodes.length
> 0) { this._activeLanguages.ensureIndexIsVisible(selectedIndex); this._activeLanguages.selectedIndex = selectedIndex;
} return undefined; }, writeAcceptLanguages: function () return undefined; }, onAvailableLanguageSelect:
function () var addButton = document.getElementById("addButton"); addButton.disabled = false; this._availableLanguages.removeAttribute("accesskey");
}, addLanguage: function () var selectedID = this._availableLanguages.selectedItem.id;
var preference = document.getElementById("intl.accept_languages"); var arrayOfPrefs = preference.value.toLowerCase().split(/\s*,\s*/);
for (var i = 0; i < arrayOfPrefs.length; ++i ){ if (arrayOfPrefs[i] == selectedID) return;
} this._selectedItemID = selectedID; if (preference.value == "") preference.value = selectedID; else
preference.value += "," + selectedID; this._acceptLanguages[selectedID] = true; this._availableLanguages.selectedItem
= null; // Reuild the available list with the added item removed... this._buildAvailableLanguageList();
this._availableLanguages.setAttribute("label", this._availableLanguages.getAttribute("label2"));
}, removeLanguage: function () // Build the new preference value string. var languagesArray
= []; for (var i = 0; i < this._activeLanguages.childNodes.length; ++i) { var item = this._activeLanguages.childNodes[i];
if (!item.selected) languagesArray.push(item.id); else this._acceptLanguages[item.id] = false;
} var string = languagesArray.join(","); // Get the item to select after the remove
operation completes. var selection = this._activeLanguages.selectedItems; var lastSelected = selection[selection.length-1];
var selectItem = lastSelected.nextSibling || lastSelected.previousSibling; selectItem
= selectItem ? selectItem.id : null; this._selectedItemID = selectItem; // Update the preference and
force a UI rebuild var preference = document.getElementById("intl.accept_languages"); preference.value = string; this._buildAvailableLanguageList();
}, _getLanguageName: function (aABCD) if (!this._availableLanguagesList.length) this._loadAvailableLanguages();
for (var i = 0; i < this._availableLanguagesList.length; ++i) { if (aABCD == this._availableLanguagesList[i].abcd)
return this._availableLanguagesList[i].name; } return ""; }, moveUp: function () var selectedItem
= this._activeLanguages.selectedItems[0]; var previousItem = selectedItem.previousSibling;
var string = ""; for (var i = 0; i < this._activeLanguages.childNodes.length; ++i) { var item = this._activeLanguages.childNodes[i];
string += (i == 0 ? "" : ","); if (item.id == previousItem.id) string += selectedItem.id;
else if (item.id == selectedItem.id) string += previousItem.id; else string += item.id;
} this._selectedItemID = selectedItem.id; // Update the preference and force a UI rebuild
var preference = document.getElementById("intl.accept_languages"); preference.value = string; }, moveDown: function
() var selectedItem = this._activeLanguages.selectedItems[0]; var nextItem = selectedItem.nextSibling; var
string = ""; for (var i = 0; i < this._activeLanguages.childNodes.length; ++i) { var item = this._activeLanguages.childNodes[i];
string += (i == 0 ? "" : ","); if (item.id == nextItem.id) string += selectedItem.id;
else if (item.id == selectedItem.id) string += nextItem.id; else string += item.id; }
this._selectedItemID = selectedItem.id; // Update the preference and force a UI rebuild
var preference = document.getElementById("intl.accept_languages"); preference.value = string; }, onLanguageSelect:
function () var upButton = document.getElementById("up"); var downButton = document.getElementById("down");
var removeButton = document.getElementById("remove"); switch (this._activeLanguages.selectedCount)
{ case 0: upButton.disabled = downButton.disabled = removeButton.disabled = true; break; case
1: upButton.disabled = this._activeLanguages.selectedIndex == 0; downButton.disabled = this._activeLanguages.selectedIndex
== this._activeLanguages.childNodes.length - 1; removeButton.disabled = false; break;
default: upButton.disabled = true; downButton.disabled = true; removeButton.disabled = false; }
content/browser/preferences/main.xul
%brandDTD; %mainDTD;
&manageAddonsDescWin.label;
content/browser/preferences/main.js//@line
40 "e:\builds\moz2_slave\win32_build\build\browser\components\preferences\main.js" var gMainPane = { _pane: null, /** * Initialization
of this. */ init: function () this._pane = document.getElementById("paneMain"); //
set up the "use current page" label-changing listener this._updateUseCurrentButton(); window.addEventListener("focus",
this._updateUseCurrentButton, false); }, // HOME PAGE /* * Preferences: * * browser.startup.homepage
* - the user's home page, as a string; if the home page is a set of tabs, * this will
be those URLs separated by the pipe character "|" * browser.startup.page * - what page(s)
to show when the user starts the application, as an integer: * * 0: a blank page * 1: the
home page (as set by the browser.startup.homepage pref) * 2: the last page the user visited
(DEPRECATED) * 3: windows and tabs from the last session (a.k.a. session restore) * *
The deprecated option is not exposed in UI; however, if the user has it * selected and
doesn't change the UI for this preference, the deprecated * option is preserved. */
/** * Sets the home page to the current displayed page (or frontmost tab, if the * most recent
browser window contains multiple tabs), updating preference * window UI to reflect this. */
setHomePageToCurrent: function () var win; if (document.documentElement.instantApply)
{ // If we're in instant-apply mode, use the most recent browser window var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator); win = wm.getMostRecentWindow("navigator:browser");
} else win = window.opener; if (win) { var homePage = document.getElementById("browser.startup.homepage");
var browser = win.document.getElementById("content"); var newVal = browser.browsers[0].currentURI.spec;
if (browser.browsers.length > 1) { // *** using dangerous "|" joiner! for (var i =
1; i < browser.browsers.length; i++) newVal += "|" + browser.browsers[i].currentURI.spec;
} homePage.value = newVal; } }, /** * Displays a dialog in which the user can select a bookmark
to use as home * page. If the user selects a bookmark, that bookmark's name is displayed
in * UI and the bookmark's address is stored to the home page preference. */ setHomePageToBookmark:
function () var rv = { urls: null, names: null }; document.documentElement.openSubDialog("chrome://browser/content/preferences/selectBookmark.xul",
"resizable", rv); if (rv.urls && rv.names) { var homePage = document.getElementById("browser.startup.homepage");
// *** still using dangerous "|" joiner! homePage.value = rv.urls.join("|"); } },
/** * Switches the "Use Current Page" button between its singular and plural * forms.
*/ _updateUseCurrentButton: function () { var useCurrent = document.getElementById("useCurrent");
var windowIsPresent; var win; if (document.documentElement.instantApply) { const Cc = Components.classes, Ci = Components.interfaces;
// If we're in instant-apply mode, use the most recent browser window var wm = Cc["@mozilla.org/appshell/window-mediator;1"]
.getService(Ci.nsIWindowMediator); win = wm.getMostRecentWindow("navigator:browser");
} else win = window.opener; if (win && win.document.documentElement .getAttribute("windowtype") == "navigator:browser")
{ windowIsPresent = true; var tabbrowser = win.document.getElementById("content");
if (tabbrowser.browsers.length > 1) useCurrent.label = useCurrent.getAttribute("label2"); else
useCurrent.label = useCurrent.getAttribute("label1"); } else { windowIsPresent = false; useCurrent.label
= useCurrent.getAttribute("label1"); } // In this case, the button's disabled state
is set by preferences.xml. if (document.getElementById ("pref.browser.homepage.disable_button.current_page").locked)
return; useCurrent.disabled = !windowIsPresent; }, /** * Restores the default home page as
the user's home page. */ restoreDefaultHomePage: function () var homePage = document.getElementById("browser.startup.homepage");
homePage.value = homePage.defaultValue; }, // DOWNLOADS /* * Preferences: * * browser.download.showWhenStarting
- bool * True if the Download Manager should be opened when a download is * started, false
if it shouldn't be opened. * browser.download.closeWhenDone - bool * True if the Download Manager should
be closed when all downloads * complete, false if it should be left open. * browser.download.useDownloadDir
- bool * True - Save files directly to the folder configured via the * browser.download.folderList
preference. * False - Always ask the user where to save a file and default to * browser.download.lastDir
when displaying a folder picker dialog. * browser.download.dir - local file handle
* A local folder the user may have selected for downloaded files to be * saved. Migration
of other browser settings may also set this path. * This folder is enabled when folderList
equals 2. * browser.download.lastDir - local file handle * May contain the last folder
path accessed when the user browsed * via the file save-as dialog. (see contentAreaUtils.js)
* browser.download.folderList - int * Indicates the location users wish to save downloaded
files too. * It is also used to display special file labels when the default * download location
is either the Desktop or the Downloads folder. * Values: * 0 - The desktop is the default
download location. * 1 - The system's downloads folder is the default download location.
* 2 - The default download location is elsewhere as specified in * browser.download.dir. *
browser.download.downloadDir * deprecated. * browser.download.defaultFolder * deprecated.
*/ /** * Updates preferences which depend upon the value of the preference which *
determines whether the Downloads manager is opened at the start of a * download. */ readShowDownloadsWhenStarting:
function () this.showDownloadsWhenStartingPrefChanged(); // don't override the preference's value
in UI return undefined; }, /** * Enables or disables the "close Downloads manager when
downloads finished" * preference element, consequently updating the associated UI.
*/ showDownloadsWhenStartingPrefChanged: function () var showWhenStartingPref = document.getElementById("browser.download.manager.showWhenStarting");
var closeWhenDonePref = document.getElementById("browser.download.manager.closeWhenDone"); closeWhenDonePref.disabled = !showWhenStartingPref.value;
}, /** * Enables/disables the folder field and Browse button based on whether a * default
download directory is being used. */ readUseDownloadDir: function () var downloadFolder = document.getElementById("downloadFolder");
var chooseFolder = document.getElementById("chooseFolder"); var preference = document.getElementById("browser.download.useDownloadDir");
downloadFolder.disabled = !preference.value; chooseFolder.disabled = !preference.value;
// don't override the preference's value in UI return undefined; }, /** * Displays
a file picker in which the user can choose the location where * downloads are automatically
saved, updating preferences and UI in * response to the choice, if one is made. */ chooseFolder:
function () const nsIFilePicker = Components.interfaces.nsIFilePicker; const nsILocalFile = Components.interfaces.nsILocalFile;
var fp = Components.classes["@mozilla.org/filepicker;1"] .createInstance(nsIFilePicker); var bundlePreferences
= document.getElementById("bundlePreferences"); var title = bundlePreferences.getString("chooseDownloadFolderTitle");
fp.init(window, title, nsIFilePicker.modeGetFolder); fp.appendFilters(nsIFilePicker.filterAll);
var folderListPref = document.getElementById("browser.download.folderList"); var currentDirPref = this._indexToFolder(folderListPref.value);
// file var defDownloads = this._indexToFolder(1); // file // First try to open what's currently
configured if (currentDirPref && currentDirPref.exists()) { fp.displayDirectory = currentDirPref;
} // Try the system's download dir else if (defDownloads && defDownloads.exists()) {
fp.displayDirectory = defDownloads; } // Fall back to Desktop else { fp.displayDirectory
= this._indexToFolder(0); } if (fp.show() == nsIFilePicker.returnOK) { var file =
fp.file.QueryInterface(nsILocalFile); var currentDirPref = document.getElementById("browser.download.dir");
currentDirPref.value = file; var folderListPref = document.getElementById("browser.download.folderList");
folderListPref.value = this._folderToIndex(file); // Note, the real prefs will not be updated
yet, so dnld manager's // userDownloadsDirectory may not return the right folder after //
this code executes. displayDownloadDirPref will be called on // the assignment above
to update the UI. } }, /** * Initializes the download folder display settings based on
the user's * preferences. */ displayDownloadDirPref: function () var folderListPref = document.getElementById("browser.download.folderList");
var bundlePreferences = document.getElementById("bundlePreferences"); var downloadFolder = document.getElementById("downloadFolder");
var currentDirPref = document.getElementById("browser.download.dir"); // The user's download folder is based on
the preferences listed above. // However, if the system does not support a download
folder, the // actual path returned will be the system's desktop or home folder. // If
this is the case, skip off displaying the Download label and // display Desktop, even
though folderList might be 1. var fileLocator = Components.classes["@mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties); var desk = fileLocator.get("Desk", Components.interfaces.nsILocalFile);
var dnldMgr = Components.classes["@mozilla.org/download-manager;1"] .getService(Components.interfaces.nsIDownloadManager);
var supportDownloadLabel = !dnldMgr.defaultDownloadsDirectory.equals(desk); // Used in defining the correct path to the
folder icon. var ios = Components.classes["@mozilla.org/network/io-service;1"] .getService(Components.interfaces.nsIIOService);
var fph = ios.getProtocolHandler("file") .QueryInterface(Components.interfaces.nsIFileProtocolHandler); var iconUrlSpec; // Display a 'pretty' label
or the path in the UI. if (folderListPref.value == 2) { // Custom path selected and is configured
downloadFolder.label = this._getDisplayNameOfFile(currentDirPref.value); iconUrlSpec = fph.getURLSpecFromFile(currentDirPref.value);
} else if (folderListPref.value == 1 && supportDownloadLabel) { // 'Downloads' //
In 1.5, this pointed to a folder we created called 'My Downloads' // and was available
as an option in the 1.5 drop down. On XP this // was in My Documents, on OSX it was in
User Docs. In 2.0, we did // away with the drop down option, although the special label
was // still supported for the folder if it existed. Because it was // not exposed it
was rarely used. // With 3.0, a new desktop folder - 'Downloads' was introduced for //
platforms and versions that don't support a default system downloads // folder. See
nsDownloadManager for details. downloadFolder.label = bundlePreferences.getString("downloadsFolderName");
iconUrlSpec = fph.getURLSpecFromFile(this._indexToFolder(1)); } else { // 'Desktop' downloadFolder.label
= bundlePreferences.getString("desktopFolderName"); iconUrlSpec = fph.getURLSpecFromFile(desk);
} downloadFolder.image = "moz-icon://" + iconUrlSpec + "?size=16"; // don't override
the preference's value in UI return undefined; }, /** * Returns the textual path of a folder
in readable form. */ _getDisplayNameOfFile: function (aFolder) // TODO: would like to
add support for 'Downloads on Macintosh HD' // for OS X users. return aFolder ? aFolder.path
: ""; }, /** * Returns the Downloads folder. If aFolder is "Desktop", then the Downloads
* folder returned is the desktop folder; otherwise, it is a folder whose name * indicates
that it is a download folder and whose path is as determined by * the XPCOM directory
service via the download manager's attribute * defaultDownloadsDirectory. * * @throws
if aFolder is not "Desktop" or "Downloads" */ _getDownloadsFolder: function (aFolder)
switch(aFolder) { case "Desktop": var fileLoc = Components.classes["@mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties); return fileLoc.get("Desk", Components.interfaces.nsILocalFile);
break; case "Downloads": var dnldMgr = Components.classes["@mozilla.org/download-manager;1"] .getService(Components.interfaces.nsIDownloadManager);
return dnldMgr.defaultDownloadsDirectory; break; } throw "ASSERTION FAILED: folder type
should be 'Desktop' or 'Downloads'"; }, /** * Determines the type of the given folder.
* * @param aFolder * the folder whose type is to be determined * @returns integer *
0 if aFolder is the Desktop or is unspecified, * 1 if aFolder is the Downloads folder,
* 2 otherwise */ _folderToIndex: function (aFolder) if (!aFolder || aFolder.equals(this._getDownloadsFolder("Desktop")))
return 0; else if (aFolder.equals(this._getDownloadsFolder("Downloads"))) return 1; return 2; }, /** * Converts an integer
into the corresponding folder. * * @param aIndex * an integer * @returns the Desktop
folder if aIndex == 0, * the Downloads folder if aIndex == 1, * the folder stored in browser.download.dir
*/ _indexToFolder: function (aIndex) switch (aIndex) { case 0: return this._getDownloadsFolder("Desktop");
case 1: return this._getDownloadsFolder("Downloads"); } var currentDirPref = document.getElementById("browser.download.dir");
return currentDirPref.value; }, /** * Returns the value for the browser.download.folderList
preference. */ getFolderListPref: function () var folderListPref = document.getElementById("browser.download.folderList");
switch(folderListPref.value) { case 0: // Desktop case 1: // Downloads return folderListPref.value;
break; case 2: // Custom var currentDirPref = document.getElementById("browser.download.dir");
if (currentDirPref.value) { // Resolve to a known location if possible. We are writing
out // to prefs on this call, so now would be a good time to do it. return this._folderToIndex(currentDirPref.value);
} return 0; break; } }, /** * Displays the Add-ons Manager. */ showAddonsMgr: function
() const EMTYPE = "Extension:Manager"; var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator); var theEM = wm.getMostRecentWindow(EMTYPE);
if (theEM) { theEM.focus(); theEM.showView("extensions"); return; } const EMURL = "chrome://mozapps/content/extensions/extensions.xul";
const EMFEATURES = "chrome,menubar,extra-chrome,toolbar,dialog=no,resizable"; window.openDialog(EMURL, "", EMFEATURES, "extensions");
content/browser/preferences/permissions.xul
content/browser/preferences/permissions.js//@line
39 "e:\builds\moz2_slave\win32_build\build\browser\components\preferences\permissions.js" const nsIPermissionManager = Components.interfaces.nsIPermissionManager;
const nsICookiePermission = Components.interfaces.nsICookiePermission; function Permission(host, rawHost, type, capability,
perm) this.host = host; this.rawHost = rawHost; this.type = type; this.capability = capability;
this.perm = perm; var gPermissionManager = { _type : "", _permissions : [], _pm :
Components.classes["@mozilla.org/permissionmanager;1"] .getService(Components.interfaces.nsIPermissionManager),
_bundle : null, _tree : null, _view: { _rowCount: 0, get rowCount() { return this._rowCount;
}, getCellText: function (aRow, aColumn) { if (aColumn.id == "siteCol") return gPermissionManager._permissions[aRow].rawHost;
else if (aColumn.id == "statusCol") return gPermissionManager._permissions[aRow].capability;
return ""; }, isSeparator: function(aIndex) { return false; }, isSorted: function()
{ return false; }, isContainer: function(aIndex) { return false; }, setTree: function(aTree){},
getImageSrc: function(aRow, aColumn) {}, getProgressMode: function(aRow, aColumn)
{}, getCellValue: function(aRow, aColumn) {}, cycleHeader: function(column) {}, getRowProperties:
function(row,prop){}, getColumnProperties: function(column,prop){}, getCellProperties:
function(row,column,prop){ if (column.element.getAttribute("id") == "siteCol") prop.AppendElement(this._ltrAtom);
} }, _getCapabilityString: function (aCapability) var stringKey = null; switch (aCapability)
{ case nsIPermissionManager.ALLOW_ACTION: stringKey = "can"; break; case nsIPermissionManager.DENY_ACTION:
stringKey = "cannot"; break; case nsICookiePermission.ACCESS_SESSION: stringKey = "canSession"; break; } return
this._bundle.getString(stringKey); }, addPermission: function (aCapability) var textbox = document.getElementById("url");
var host = textbox.value.replace(/^\s*([-\w]*:\/+)?/, ""); // trim any leading space and scheme
try { var ioService = Components.classes["@mozilla.org/network/io-service;1"] .getService(Components.interfaces.nsIIOService);
var uri = ioService.newURI("http://"+host, null, null); host = uri.host; } catch(ex)
{ var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"] .getService(Components.interfaces.nsIPromptService);
var message = this._bundle.getString("invalidURI"); var title = this._bundle.getString("invalidURITitle");
promptService.alert(window, title, message); return; } var capabilityString = this._getCapabilityString(aCapability);
// check whether the permission already exists, if not, add it var exists = false; for (var
i = 0; i < this._permissions.length; ++i) { if (this._permissions[i].rawHost == host)
{ // Avoid calling the permission manager if the capability settings are // the same.
Otherwise allow the call to the permissions manager to // update the listbox for us. exists
= this._permissions[i].perm == aCapability; break; } } if (!exists) { host = (host.charAt(0)
== ".") ? host.substring(1,host.length) : host; var uri = ioService.newURI("http://"
+ host, null, null); this._pm.add(uri, this._type, aCapability); } textbox.value = ""; textbox.focus();
// covers a case where the site exists already, so the buttons don't disable this.onHostInput(textbox);
// enable "remove all" button as needed document.getElementById("removeAllPermissions").disabled = this._permissions.length == 0; }, onHostInput:
function (aSiteField) document.getElementById("btnSession").disabled = !aSiteField.value; document.getElementById("btnBlock").disabled
= !aSiteField.value; document.getElementById("btnAllow").disabled = !aSiteField.value; }, onHostKeyPress: function
(aEvent) if (aEvent.keyCode == KeyEvent.DOM_VK_RETURN) document.getElementById("btnAllow").click();
}, onLoad: function () this._bundle = document.getElementById("bundlePreferences"); var params = window.arguments[0]; this.init(params);
}, init: function (aParams) if (this._type) { // reusing an open dialog, clear the old
observer this.uninit(); } this._type = aParams.permissionType; this._manageCapability = aParams.manageCapability;
var permissionsText = document.getElementById("permissionsText"); while (permissionsText.hasChildNodes()) permissionsText.removeChild(permissionsText.firstChild);
permissionsText.appendChild(document.createTextNode(aParams.introText)); document.title = aParams.windowTitle; document.getElementById("btnBlock").hidden
= !aParams.blockVisible; document.getElementById("btnSession").hidden = !aParams.sessionVisible; document.getElementById("btnAllow").hidden
= !aParams.allowVisible; var urlFieldVisible = (aParams.blockVisible || aParams.sessionVisible
|| aParams.allowVisible); var urlField = document.getElementById("url"); urlField.value
= aParams.prefilledHost; urlField.hidden = !urlFieldVisible; this.onHostInput(urlField);
var urlLabel = document.getElementById("urlLabel"); urlLabel.hidden = !urlFieldVisible; var os
= Components.classes["@mozilla.org/observer-service;1"] .getService(Components.interfaces.nsIObserverService);
os.addObserver(this, "perm-changed", false); if (this._type == "install") { var enumerator
= this._pm.enumerator; if (!enumerator.hasMoreElements()) this._updatePermissions(); } this._loadPermissions();
urlField.focus(); this._ltrAtom = Components.classes["@mozilla.org/atom-service;1"] .getService(Components.interfaces.nsIAtomService)
.getAtom("ltr"); }, uninit: function () var os = Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService); os.removeObserver(this, "perm-changed");
}, observe: function (aSubject, aTopic, aData) if (aTopic == "perm-changed") { var permission
= aSubject.QueryInterface(Components.interfaces.nsIPermission); if (aData == "added") { this._addPermissionToList(permission);
++this._view._rowCount; this._tree.treeBoxObject.rowCountChanged(this._view.rowCount - 1, 1); // Re-do the sort, since we inserted
this new item at the end. gTreeUtils.sort(this._tree, this._view, this._permissions, this._lastPermissionSortColumn,
this._lastPermissionSortAscending); } else if (aData == "changed") { for (var i = 0;
i < this._permissions.length; ++i) { if (this._permissions[i].host == permission.host) { this._permissions[i].capability
= this._getCapabilityString(permission.capability); break; } } // Re-do the sort, if the status
changed from Block to Allow // or vice versa, since if we're sorted on status, we may no
// longer be in order. if (this._lastPermissionSortColumn.id == "statusCol") { gTreeUtils.sort(this._tree,
this._view, this._permissions, this._lastPermissionSortColumn, this._lastPermissionSortAscending); } this._tree.treeBoxObject.invalidate();
} // No UI other than this window causes this method to be sent a "deleted" // notification,
so we don't need to implement it since Delete is handled // directly by the Permission Removal
handlers. If that ever changes, those // implementations will have to move into here.
} }, onPermissionSelected: function () var hasSelection = this._tree.view.selection.count
> 0; var hasRows = this._tree.view.rowCount > 0; document.getElementById("removePermission").disabled
= !hasRows || !hasSelection; document.getElementById("removeAllPermissions").disabled = !hasRows; }, onPermissionDeleted: function
() if (!this._view.rowCount) return; var removedPermissions = []; gTreeUtils.deleteSelectedItems(this._tree,
this._view, this._permissions, removedPermissions); for (var i = 0; i < removedPermissions.length;
++i) { var p = removedPermissions[i]; this._pm.remove(p.host, p.type); } document.getElementById("removePermission").disabled
= !this._permissions.length; document.getElementById("removeAllPermissions").disabled = !this._permissions.length; }, onAllPermissionsDeleted:
function () if (!this._view.rowCount) return; var removedPermissions = []; gTreeUtils.deleteAll(this._tree,
this._view, this._permissions, removedPermissions); for (var i = 0; i < removedPermissions.length;
++i) { var p = removedPermissions[i]; this._pm.remove(p.host, p.type); } document.getElementById("removePermission").disabled
= true; document.getElementById("removeAllPermissions").disabled = true; }, onPermissionKeyPress: function
(aEvent) if (aEvent.keyCode == 46) this.onPermissionDeleted(); }, _lastPermissionSortColumn: "", _lastPermissionSortAscending:
false, onPermissionSort: function (aColumn) this._lastPermissionSortAscending = gTreeUtils.sort(this._tree,
this._view, this._permissions, aColumn, this._lastPermissionSortColumn, this._lastPermissionSortAscending); this._lastPermissionSortColumn
= aColumn; }, _loadPermissions: function () this._tree = document.getElementById("permissionsTree");
this._permissions = []; // load permissions into a table var count = 0; var enumerator
= this._pm.enumerator; while (enumerator.hasMoreElements()) { var nextPermission = enumerator.getNext().QueryInterface(Components.interfaces.nsIPermission);
this._addPermissionToList(nextPermission); } this._view._rowCount = this._permissions.length;
// sort and display the table this._tree.treeBoxObject.view = this._view; this.onPermissionSort("rawHost",
false); // disable "remove all" button if there are none document.getElementById("removeAllPermissions").disabled
= this._permissions.length == 0; }, _addPermissionToList: function (aPermission) if (aPermission.type
== this._type && (!this._manageCapability || (aPermission.capability == this._manageCapability)))
{ var host = aPermission.host; var capabilityString = this._getCapabilityString(aPermission.capability);
var p = new Permission(host, (host.charAt(0) == ".") ? host.substring(1,host.length)
: host, aPermission.type, capabilityString, aPermission.capability); this._permissions.push(p);
} }, _updatePermissions: function () try { var ioService = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService); var pbi = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch2); var prefList = [["xpinstall.whitelist.add",
nsIPermissionManager.ALLOW_ACTION], ["xpinstall.whitelist.add.36", nsIPermissionManager.ALLOW_ACTION], ["xpinstall.blacklist.add",
nsIPermissionManager.DENY_ACTION]]; for (var i = 0; i < prefList.length; ++i) { try {
// this pref is a comma-delimited list of hosts var hosts = pbi.getCharPref(prefList[i][0]);
} catch(ex) { continue; } if (!hosts) continue; hostList = hosts.split(","); var capability
= prefList[i][1]; for (var j = 0; j < hostList.length; ++j) { // trim leading and trailing spaces
var host = hostList[j].replace(/^\s*/,"").replace(/\s*$/,""); try { var uri = ioService.newURI("http://"
+ host, null, null); this._pm.add(uri, this._type, capability); } catch(ex) { } } pbi.setCharPref(prefList[i][0],
""); } } catch(ex) { } }, setHost: function (aHost) document.getElementById("url").value
= aHost; function setHost(aHost) gPermissionManager.setHost(aHost); function initWithParams(aParams) gPermissionManager.init(aParams);
content/browser/preferences/permissionsutils.js//@line 38 "e:\builds\moz2_slave\win32_build\build\browser\components\preferences\permissionsutils.js"
var gTreeUtils = { deleteAll: function (aTree, aView, aItems, aDeletedItems) for (var i
= 0; i < aItems.length; ++i) aDeletedItems.push(aItems[i]); aItems.splice(0); var oldCount = aView.rowCount;
aView._rowCount = 0; aTree.treeBoxObject.rowCountChanged(0, -oldCount); }, deleteSelectedItems: function
(aTree, aView, aItems, aDeletedItems) var selection = aTree.view.selection; selection.selectEventsSuppressed
= true; var rc = selection.getRangeCount(); for (var i = 0; i < rc; ++i) { var min =
{ }; var max = { }; selection.getRangeAt(i, min, max); for (var j = min.value; j
&historyHeader.pre.label;
&historyHeader.post.label;
&rememberDescription.label; &rememberActions.pre.label;&rememberActions.clearHistory.label;&rememberActions.middle.label;&rememberActions.removeCookies.label;&rememberActions.post.label;
&dontrememberDescription.label;
&dontrememberActions.pre.label;&dontrememberActions.clearHistory.label;&dontrememberActions.post.label;
&rememberHistory.post.label;
&keepUntil.label;
&locbar.pre.label;
&locbar.post.label;
content/browser/preferences/privacy.js/* //@line 42 "e:\builds\moz2_slave\win32_build\build\browser\components\preferences\privacy.js"
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); var gPrivacyPane = { /** * Whether the use
has selected the auto-start private browsing mode in the UI. */ _autoStartPrivateBrowsing:
false, /** * Sets up the UI for the number of days of history to keep, and updates the
* label of the "Clear Now..." button. */ init: function () this._updateHistoryDaysUI();
this._updateSanitizeSettingsButton(); this.initializeHistoryMode(); this.updateHistoryModePane(); this.updatePrivacyMicroControls();
this.initAutoStartPrivateBrowsingObserver(); }, // HISTORY MODE /** * The list of preferences
which affect the initial history mode settings. * If the auto start private browsing mode
pref is active, the initial * history mode would be set to "Don't remember anything".
* If all of these preferences have their default values, and the auto-start * private
browsing mode is not active, the initial history mode would be * set to "Remember everything".
* Otherwise, the initial history mode would be set to "Custom". * * Extensions adding
their own preferences can append their IDs to this array if needed. */ prefsForDefault:
[ "browser.history_expire_days", "browser.history_expire_days_min", "browser.download.manager.retention", "browser.formfill.enable",
"network.cookie.cookieBehavior", "network.cookie.lifetimePolicy", "privacy.sanitize.sanitizeOnShutdown" ],
/** * The list of control IDs which are dependent on the auto-start private * browsing setting,
such that in "Custom" mode they would be disabled if * the auto-start private browsing checkbox
is checked, and enabled otherwise. * * Extensions adding their own controls can append their
IDs to this array if needed. */ dependentControls: [ "rememberHistoryDays", "rememberAfter",
"rememberDownloads", "rememberForms", "keepUntil", "keepCookiesUntil", "alwaysClear", "clearDataSettings"
], /** * Check whether all the preferences values are set to their default values *
* @param aPrefs an array of pref names to check for * @returns boolean true if all of
the prefs are set to their default values, * false otherwise */ _checkDefaultValues:
function(aPrefs) { for (let i = 0; i < aPrefs.length; ++i) { let pref = document.getElementById(aPrefs[i]);
if (pref.value != pref.defaultValue) return false; } return true; }, /** * Initialize
the history mode menulist based on the privacy preferences */ initializeHistoryMode: function
PPP_initializeHistoryMode() let mode; let getVal = function (aPref) document.getElementById(aPref).value;
if (this._checkDefaultValues(this.prefsForDefault)) { if (getVal("browser.privatebrowsing.autostart"))
mode = "dontremember"; else mode = "remember"; } else mode = "custom"; document.getElementById("historyMode").value
= mode; }, /** * Update the selected pane based on the history mode menulist */ updateHistoryModePane:
function PPP_updateHistoryModePane() let selectedIndex = -1; switch (document.getElementById("historyMode").value)
{ case "remember": selectedIndex = 0; break; case "dontremember": selectedIndex = 1; break;
case "custom": selectedIndex = 2; break; } document.getElementById("historyPane").selectedIndex
= selectedIndex; }, /** * Update the private browsing auto-start pref and the history mode
* micro-management prefs based on the history mode menulist */ updateHistoryModePrefs: function
PPP_updateHistoryModePrefs() let pref = document.getElementById("browser.privatebrowsing.autostart"); switch (document.getElementById("historyMode").value)
{ case "remember": pref.value = false; // select the remember history option if needed
let rememberHistoryCheckbox = document.getElementById("rememberHistoryDays"); if (!rememberHistoryCheckbox.checked) { rememberHistoryCheckbox.checked
= true; this.onchangeHistoryDaysCheck(); } // select the remember downloads option
if needed if (!document.getElementById("rememberDownloads").checked) document.getElementById("browser.download.manager.retention").value
= 2; // select the remember forms history option document.getElementById("browser.formfill.enable").value
= true; // select the accept cookies option document.getElementById("network.cookie.cookieBehavior").value
= 0; // select the cookie lifetime policy option document.getElementById("network.cookie.lifetimePolicy").value
= 0; // select the clear on close option document.getElementById("privacy.sanitize.sanitizeOnShutdown").value
= false; break; case "dontremember": pref.value = true; break; } }, /** * Update the privacy
micro-management controls based on the * value of the private browsing auto-start checkbox.
*/ updatePrivacyMicroControls: function PPP_updatePrivacyMicroControls() if (document.getElementById("historyMode").value
== "custom") { let disabled = this._autoStartPrivateBrowsing = document.getElementById("privateBrowsingAutoStart").checked;
this.dependentControls .forEach(function (aElement) document.getElementById(aElement).disabled
= disabled); // adjust the cookie controls status this.readAcceptCookies(); document.getElementById("keepCookiesUntil").value
= disabled ? 2 : document.getElementById("network.cookie.lifetimePolicy").value; // adjust the checked state of the sanitizeOnShutdown
checkbox document.getElementById("alwaysClear").checked = disabled ? false : document.getElementById("privacy.sanitize.sanitizeOnShutdown").value;
// adjust the checked state of the remember history checkboxes document.getElementById("rememberHistoryDays").checked
= disabled ? false : document.getElementById("browser.history_expire_days").value > 0; this.onchangeHistoryDaysCheck(); document.getElementById("rememberDownloads").checked
= disabled ? false : this.readDownloadRetention(); document.getElementById("rememberForms").checked
= disabled ? false : document.getElementById("browser.formfill.enable").value; if (!disabled) { // adjust the Settings button
for sanitizeOnShutdown this._updateSanitizeSettingsButton(); } } }, // PRIVATE BROWSING /** * Install
the observer for the auto-start private browsing mode pref. */ initAutoStartPrivateBrowsingObserver:
function PPP_initAutoStartPrivateBrowsingObserver() let prefService = document.getElementById("privacyPreferences")
.service .QueryInterface(Components.interfaces.nsIPrefBranch2); prefService.addObserver("browser.privatebrowsing.autostart",
this.autoStartPrivateBrowsingObserver, true); }, autoStartPrivateBrowsingObserver: QueryInterface:
XPCOMUtils.generateQI([Components.interfaces.nsIObserver, Components.interfaces.nsISupportsWeakReference]),
observe: function PPP_observe(aSubject, aTopic, aData) { let privateBrowsingService = Components.classes["@mozilla.org/privatebrowsing;1"].
getService(Components.interfaces.nsIPrivateBrowsingService); // Toggle the private browsing mode without
switching the session let prefValue = document.getElementById("browser.privatebrowsing.autostart").value; let keepCurrentSession = document.getElementById("browser.privatebrowsing.keep_current_session");
keepCurrentSession.value = true; // If activating from within the private browsing mode, reset
the // private session if (prefValue && privateBrowsingService.privateBrowsingEnabled) privateBrowsingService.privateBrowsingEnabled
= false; privateBrowsingService.privateBrowsingEnabled = prefValue; keepCurrentSession.reset();
} }, // HISTORY /** * Read the location bar enabled and suggestion prefs * @return Int
value for suggestion menulist */ readSuggestionPref: function PPP_readSuggestionPref() let getVal
= function(aPref) document.getElementById("browser.urlbar." + aPref).value; // Suggest nothing if autocomplete
is not enabled if (!getVal("autocomplete.enabled")) return -1; // Bottom 2 bits of default.behavior
specify history/bookmark return getVal("default.behavior") & 3; }, /** * Write the location bar enabled
and suggestion prefs when necessary * @return Bool value for enabled pref */ writeSuggestionPref:
function PPP_writeSuggestionPref() let menuVal = document.getElementById("locationBarSuggestion").value;
let enabled = menuVal != -1; // Only update default.behavior if we're giving suggestions
if (enabled) { // Put the selected menu item's value directly into the bottom 2 bits let
behavior = document.getElementById("browser.urlbar.default.behavior"); behavior.value = behavior.value >> 2 0); textbox.disabled = !checkbox.checked; }, /** * Responds to the checking or unchecking
of the days-of-history UI, storing * the appropriate value to the days-of-history preference and
enabling or * disabling the number textbox as appropriate. */ onchangeHistoryDaysCheck:
function () var pref = document.getElementById("browser.history_expire_days"); var mirror = document.getElementById("browser.history_expire_days.mirror");
var textbox = document.getElementById("historyDays"); var checkbox = document.getElementById("rememberHistoryDays");
if (!this._autoStartPrivateBrowsing) pref.value = checkbox.checked ? mirror.value : 0; textbox.disabled
= !checkbox.checked; }, /** * Responds to changes in the days-of-history textbox, *
unchecking the history-enabled checkbox if the days * value is zero. */ onkeyupHistoryDaysText:
function () var textbox = document.getElementById("historyDays"); var checkbox = document.getElementById("rememberHistoryDays");
checkbox.checked = textbox.value != 0; }, /** * Converts the value of the browser.download.manager.retention
preference * into a Boolean value. "remove on close" and "don't remember" both map *
to an unchecked checkbox, while "remember" maps to a checked checkbox. */ readDownloadRetention:
function () var pref = document.getElementById("browser.download.manager.retention"); return (pref.value == 2); }, /** * Returns
the appropriate value of the browser.download.manager.retention * preference for the current UI. */ writeDownloadRetention:
function () var checkbox = document.getElementById("rememberDownloads"); return checkbox.checked ? 2 : 0; }, // COOKIES
/* * Preferences: * * network.cookie.cookieBehavior * - determines how the browser should handle
cookies: * 0 means enable all cookies * 1 means reject third party cookies; see * netwerk/cookie/src/nsCookieService.cpp
for a hairier definition * 2 means disable all cookies * network.cookie.lifetimePolicy
* - determines how long cookies are stored: * 0 means keep cookies until they expire
* 1 means ask how long to keep each cookie * 2 means keep cookies until the browser
is closed */ /** * Reads the network.cookie.cookieBehavior preference value and * enables/disables the
rest of the cookie UI accordingly, returning true * if cookies are enabled. */ readAcceptCookies:
function () var pref = document.getElementById("network.cookie.cookieBehavior"); var acceptThirdParty = document.getElementById("acceptThirdParty");
var keepUntil = document.getElementById("keepUntil"); var menu = document.getElementById("keepCookiesUntil");
// enable the rest of the UI for anything other than "disable all cookies" var acceptCookies
= (pref.value != 2); acceptThirdParty.disabled = !acceptCookies; keepUntil.disabled = menu.disabled
= this._autoStartPrivateBrowsing || !acceptCookies; return acceptCookies; }, readAcceptThirdPartyCookies:
function () var pref = document.getElementById("network.cookie.cookieBehavior"); return pref.value == 0; }, /** * Enables/disables
the "keep until" label and menulist in response to the * "accept cookies" checkbox being checked
or unchecked. */ writeAcceptCookies: function () var accept = document.getElementById("acceptCookies");
var acceptThirdParty = document.getElementById("acceptThirdParty"); // if we're enabling cookies, automatically
check 'accept third party' if (accept.checked) acceptThirdParty.checked = true; return accept.checked
? (acceptThirdParty.checked ? 0 : 1) : 2; }, writeAcceptThirdPartyCookies: function
() var accept = document.getElementById("acceptCookies"); var acceptThirdParty = document.getElementById("acceptThirdParty");
return accept.checked ? (acceptThirdParty.checked ? 0 : 1) : 2; }, /** * Displays fine-grained,
per-site preferences for cookies. */ showCookieExceptions: function () var bundlePreferences = document.getElementById("bundlePreferences");
var params = { blockVisible : true, sessionVisible : true, allowVisible : true, prefilledHost
: "", permissionType : "cookie", windowTitle : bundlePreferences.getString("cookiepermissionstitle"),
introText : bundlePreferences.getString("cookiepermissionstext") }; document.documentElement.openWindow("Browser:Permissions",
"chrome://browser/content/preferences/permissions.xul", "", params); }, /** * Displays all the user's
cookies in a dialog. */ showCookies: function (aCategory) document.documentElement.openWindow("Browser:Cookies",
"chrome://browser/content/preferences/cookies.xul", "", null); }, // CLEAR PRIVATE DATA /* *
Preferences: * * privacy.sanitize.sanitizeOnShutdown * - true if the user's private data is cleared
on startup according to the * Clear Private Data settings, false otherwise */ /** * Displays
the Clear Private Data settings dialog. */ showClearPrivateDataSettings: function ()
document.documentElement.openSubDialog("chrome://browser/content/preferences/sanitize.xul", "", null); }, /** * Displays a dialog from
which individual parts of private data may be * cleared. */ clearPrivateDataNow: function
(aClearEverything) var ts = document.getElementById("privacy.sanitize.timeSpan"); var timeSpanOrig = ts.value; if (aClearEverything)
ts.value = 0; const Cc = Components.classes, Ci = Components.interfaces; var glue = Cc["@mozilla.org/browser/browserglue;1"]
.getService(Ci.nsIBrowserGlue); glue.sanitize(window); // reset the timeSpan pref if (aClearEverything)
ts.value = timeSpanOrig; }, /** * Enables or disables the "Settings..." button depending
* on the privacy.sanitize.sanitizeOnShutdown preference value */ _updateSanitizeSettingsButton:
function () { var settingsButton = document.getElementById("clearDataSettings"); var sanitizeOnShutdownPref = document.getElementById("privacy.sanitize.sanitizeOnShutdown");
settingsButton.disabled = !sanitizeOnShutdownPref.value; } content/browser/preferences/sanitize.xul %brandDTD; %sanitizeDTD;
&clearDataSettings2.label;
content/browser/preferences/security.xul
%brandDTD; %securityDTD;
&chooseWarnings.label;
content/browser/preferences/security.js//@line
38 "e:\builds\moz2_slave\win32_build\build\browser\components\preferences\security.js" var gSecurityPane = { _pane: null, /** *
Initializes master password UI. */ init: function () this._pane = document.getElementById("paneSecurity");
this._initMasterPasswordUI(); }, // ADD-ONS /* * Preferences: * * xpinstall.whitelist.required
* - true if a site must be added to a site whitelist before extensions * provided by
the site may be installed from it, false if the extension * may be directly installed
after a confirmation dialog */ /** * Enables/disables the add-ons Exceptions button depending on
whether * or not add-on installation warnings are displayed. */ readWarnAddonInstall: function
() var warn = document.getElementById("xpinstall.whitelist.required"); var exceptions = document.getElementById("addonExceptions");
exceptions.disabled = !warn.value; // don't override the preference value return undefined;
}, /** * Displays the exceptions lists for add-on installation warnings. */ showAddonExceptions:
function () var bundlePrefs = document.getElementById("bundlePreferences"); var params = this._addonParams; if (!params.windowTitle
|| !params.introText) { params.windowTitle = bundlePrefs.getString("addons_permissions_title");
params.introText = bundlePrefs.getString("addonspermissionstext"); } document.documentElement.openWindow("Browser:Permissions",
"chrome://browser/content/preferences/permissions.xul", "", params); }, /** * Parameters for the
add-on install permissions dialog. */ _addonParams: { blockVisible: false, sessionVisible: false,
allowVisible: true, prefilledHost: "", permissionType: "install" }, // PASSWORDS /* * Preferences:
* * signon.rememberSignons * - true if passwords are remembered, false otherwise */ /** *
Enables/disables the Exceptions button used to configure sites where * passwords are never
saved. */ readSavePasswords: function () var pref = document.getElementById("signon.rememberSignons");
var excepts = document.getElementById("passwordExceptions"); excepts.disabled = !pref.value; // don't override
pref value in UI return undefined; }, /** * Displays a dialog in which the user can
view and modify the list of sites * where passwords are never saved. */ showPasswordExceptions:
function () document.documentElement.openWindow("Toolkit:PasswordManagerExceptions", "chrome://passwordmgr/content/passwordManagerExceptions.xul",
"", null); }, /** * Initializes master password UI: the "use master password" checkbox, selects
* the master password button to show, and enables/disables it as necessary. * The master
password is controlled by various bits of NSS functionality, so * the UI for it can't
be controlled by the normal preference bindings. */ _initMasterPasswordUI: function () var
noMP = !this._masterPasswordSet(); var button = document.getElementById("changeMasterPassword");
button.disabled = noMP; var checkbox = document.getElementById("useMasterPassword"); checkbox.checked = !noMP; }, /** * Returns
true if the user has a master password set and false otherwise. */ _masterPasswordSet:
function () const Cc = Components.classes, Ci = Components.interfaces; var secmodDB
= Cc["@mozilla.org/security/pkcs11moduledb;1"]. getService(Ci.nsIPKCS11ModuleDB); var slot
= secmodDB.findSlotByName(""); if (slot) { var status = slot.status; var hasMP =
status != Ci.nsIPKCS11Slot.SLOT_UNINITIALIZED && status != Ci.nsIPKCS11Slot.SLOT_READY;
return hasMP; } else { // *** I have no bloody idea what this means return false; } }, /**
* Enables/disables the master password button depending on the state of the * "use master
password" checkbox, and prompts for master password removal if * one is set. */ updateMasterPasswordButton:
function () var checkbox = document.getElementById("useMasterPassword"); var button = document.getElementById("changeMasterPassword");
button.disabled = !checkbox.checked; // unchecking the checkbox should try to immediately remove
the master // password, because it's impossible to non-destructively remove the master //
password used to encrypt all the passwords without providing it (by // design), and it
would be extremely odd to pop up that dialog when the // user closes the prefwindow and
saves his settings if (!checkbox.checked) this._removeMasterPassword(); else this.changeMasterPassword();
this._initMasterPasswordUI(); }, /** * Displays the "remove master password" dialog to allow
the user to remove * the current master password. When the dialog is dismissed, master password
* UI is automatically updated. */ _removeMasterPassword: function () const Cc = Components.classes,
Ci = Components.interfaces; var secmodDB = Cc["@mozilla.org/security/pkcs11moduledb;1"].
getService(Ci.nsIPKCS11ModuleDB); if (secmodDB.isFIPSEnabled) { var promptService = Cc["@mozilla.org/embedcomp/prompt-service;1"].
getService(Ci.nsIPromptService); var bundle = document.getElementById("bundlePreferences");
promptService.alert(window, bundle.getString("pw_change_failed_title"), bundle.getString("pw_change2empty_in_fips_mode"));
} else { document.documentElement.openSubDialog("chrome://mozapps/content/preferences/removemp.xul", "", null); } this._initMasterPasswordUI();
}, /** * Displays a dialog in which the master password may be changed. */ changeMasterPassword:
function () document.documentElement.openSubDialog("chrome://mozapps/content/preferences/changemp.xul", "", null); this._initMasterPasswordUI();
}, /** * Shows the sites where the user has saved passwords and the associated login
* information. */ showPasswords: function () document.documentElement.openWindow("Toolkit:PasswordManager",
"chrome://passwordmgr/content/passwordManager.xul", "", null); }, // WARNING MESSAGES /** *
Displays the security warnings dialog which allows changing the * "submitting unencrypted
information", "moving from secure to unsecure", * etc. dialogs that every user immediately
disables when he sees them. */ showWarningMessageSettings: function () document.documentElement.openSubDialog("chrome://browser/content/preferences/securityWarnings.xul",
"", null); content/browser/preferences/securityWarnings.xul
content/browser/preferences/securityWarnings.js//@line 38 "e:\builds\moz2_slave\win32_build\build\browser\components\preferences\securityWarnings.js"
function secWarningSyncTo(aEvent) { var prefName = aEvent.target.getAttribute("preference")
+ ".show_once"; var prefOnce = document.getElementById(prefName); prefOnce.value = false; return undefined;
content/browser/preferences/selectBookmark.xul
&selectBookmark.label;
content/browser/preferences/selectBookmark.js//* -*- Mode: C++; tab-width: 8; indent-tabs-mode:
nil; c-basic-offset: 2 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL
2.0/LGPL 2.1 * The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with * the License.
You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * Software distributed
under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND,
either express or implied. See the License * for the specific language governing rights
and limitations under the * License. * The Original Code is Select Bookmark for Home
Page Dialog. * 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): * Ben Goodger * 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 *****
*/ * SelectBookmarkDialog controls the user interface for the "Use Bookmark for * Home
Page" dialog. * The caller (gMainPane.setHomePageToBookmark in main.js) invokes this dialog * with a single
argument - a reference to an object with a .urls property and * a .names property. This
dialog is responsible for updating the contents of * the .urls property with an array of URLs
to use as home pages and for * updating the .names property with an array of names for
those URLs before it * closes. */ var SelectBookmarkDialog = { init: function SBD_init() { document.getElementById("bookmarks").place
= "place:queryType=1&folder=" + PlacesUIUtils.allBookmarksFolderId; // Initial update of the OK button. this.selectionChanged();
}, /** * Update the disabled state of the OK button as the user changes the * selection
within the view. */ selectionChanged: function SBD_selectionChanged() { var accept = document.documentElement.getButton("accept");
var bookmarks = document.getElementById("bookmarks"); var disableAcceptButton = true; if (bookmarks.hasSelection)
{ if (!PlacesUtils.nodeIsSeparator(bookmarks.selectedNode)) disableAcceptButton = false; } accept.disabled
= disableAcceptButton; }, onItemDblClick: function SBD_onItemDblClick() { var bookmarks
= document.getElementById("bookmarks"); 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. */ document.documentElement.getButton("accept").click(); } }, /** * User accepts their selection.
Set all the selected URLs or the contents * of the selected folder as the list of homepages.
*/ accept: function SBD_accept() { var bookmarks = document.getElementById("bookmarks"); NS_ASSERT(bookmarks.hasSelection,
"Should not be able to accept dialog if there is no selected URL!"); var urls = []; var
names = []; var selectedNode = bookmarks.selectedNode; if (PlacesUtils.nodeIsFolder(selectedNode))
{ var contents = PlacesUtils.getFolderContents(selectedNode.itemId).root; var cc = contents.childCount; for (var i
= 0; i < cc; ++i) { var node = contents.getChild(i); if (PlacesUtils.nodeIsURI(node)) { urls.push(node.uri);
names.push(node.title); } } } else { urls.push(selectedNode.uri); names.push(selectedNode.title); } window.arguments[0].urls
= urls; window.arguments[0].names = names; content/browser/preferences/tabs.xul %tabsDTD;
content/browser/preferences/tabs.js//@line 39 "e:\builds\moz2_slave\win32_build\build\browser\components\preferences\tabs.js"
var gTabsPane = { /* * Preferences: * * browser.link.open_newwindow * - determines where pages which would open
in a new window are opened: * 0 opens such links in the default window, * 1 opens such
links in the most recent window or tab, * 2 opens such links in a new window, * 3 opens
such links in a new tab * browser.tabs.autoHide * - true if the tab bar is hidden when only
one tab is open, false to always * show it * browser.tabs.loadInBackground * - true
if display should switch to a new tab which has been opened from a * link, false if display
shouldn't switch * browser.tabs.warnOnClose * - true if when closing a window with multiple
tabs the user is warned and * allowed to cancel the action, false to just close the window
* browser.tabs.warnOnOpen * - true if the user should be warned if he attempts to open
a lot of tabs at * once (e.g. a large folder of bookmarks), false otherwise */ /** * Determines
where a link which opens a new window will open. * * @returns |true| if such links should
be opened in new tabs */ readLinkTarget: function() { var openNewWindow = document.getElementById("browser.link.open_newwindow");
return openNewWindow.value != 2; }, /** * Determines where a link which opens a new
window will open. * * @returns 2 if such links should be opened in new windows, * 3 if such
links should be opened in new tabs */ writeLinkTarget: function() { var linkTargeting = document.getElementById("linkTargeting");
return linkTargeting.checked ? 3 : 2; content/browser/search/search.xml %browserDTD;
document.getAnonymousElementByAttribute(this,
"anonid", "searchbar-stringbundle"); document.getAnonymousElementByAttribute(this,
"anonid", "searchbar-textbox"); document.getAnonymousElementByAttribute(this,
"anonid", "searchbar-popup"); null null
document.getAnonymousElementByAttribute(this, "anonid", "searchbar-engine-button");
= 0; i--) { if (items[i].getAttribute("class").indexOf("addengine")
!= -1) popup.removeChild(items[i]); } var addengines = getBrowser().mCurrentBrowser.engines;
if (addengines && addengines.length > 0) { const kXULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
// Find the (first) separator in the remaining menu, or the first item // if no separators
are present. var insertLocation = popup.firstChild; while (insertLocation.nextSibling && insertLocation.localName
!= "menuseparator") { insertLocation = insertLocation.nextSibling; } if (insertLocation.localName != "menuseparator")
insertLocation = popup.firstChild; var separator = document.createElementNS(kXULNS, "menuseparator");
separator.setAttribute("class", "addengine-separator"); popup.insertBefore(separator, insertLocation);
// Insert the "add this engine" items. for (var i = 0; i < addengines.length; i++) {
var menuitem = document.createElement("menuitem"); var engineInfo = addengines[i]; var labelStr
= this._stringBundle.getFormattedString("cmd_addFoundEngine", [engineInfo.title]); menuitem = document.createElementNS(kXULNS,
"menuitem"); menuitem.setAttribute("class", "menuitem-iconic addengine-item"); menuitem.setAttribute("label",
labelStr); menuitem.setAttribute("tooltiptext", engineInfo.uri); menuitem.setAttribute("uri",
engineInfo.uri); if (engineInfo.icon) menuitem.setAttribute("src", engineInfo.icon); menuitem.setAttribute("title",
engineInfo.title); popup.insertBefore(menuitem, insertLocation); } } ]]>
= 0; --i) { var menuitem
= document.createElementNS(kXULNS, "menuitem"); var name = engines[i].name; menuitem.setAttribute("label",
name); menuitem.setAttribute("id", name); menuitem.setAttribute("class", "menuitem-iconic
searchbar-engine-menuitem"); // Since this menu is rebuilt by the observer method whenever
a new // engine is selected, the "selected" attribute does not need to be // explicitly
cleared anywhere. if (engines[i] == this.currentEngine) menuitem.setAttribute("selected", "true");
var tooltip = this._stringBundle.getFormattedString("searchtip", [name]); menuitem.setAttribute("tooltiptext",
tooltip); if (engines[i].iconURI) menuitem.setAttribute("src", engines[i].iconURI.spec); popup.insertBefore(menuitem,
popup.firstChild); menuitem.engine = engines[i]; } this._needToBuildPopup = false; ]]>
= 0 && newIndex < this.engines.length) this.currentEngine
= this.engines[newIndex]; aEvent.preventDefault(); aEvent.stopPropagation(); ]]>
100 ?
width : 100); // setConsumeRollupEvent() before we call openPopup(), // see bug #404438
for more details popup.popupBoxObject.setConsumeRollupEvent( this.consumeRollupEvent ? Ci.nsIPopupBoxObject.ROLLUP_CONSUME
: Ci.nsIPopupBoxObject.ROLLUP_NO_CONSUME); popup.openPopup(null, "", innerRect.left,
outerRect.bottom, false, false); } ]]>
nsDragAndDrop.drop(event, this.searchbarDNDObserver);
content/browser/search/searchbarBindings.css@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
.searchbar-textbox { -moz-binding: url("chrome://browser/content/search/search.xml#searchbar-textbox"); .searchbar-engine-button { -moz-user-focus:
none; content/browser/search/engineManager.xul
&engineManager.intro;
content/browser/search/engineManager.js//@line
40 "e:\builds\moz2_slave\win32_build\build\browser\components\search\content\engineManager.js" const Ci = Components.interfaces; const Cc
= Components.classes; const ENGINE_FLAVOR = "text/x-moz-search-engine"; const BROWSER_SUGGEST_PREF
= "browser.search.suggest.enabled"; var gEngineView = null; var gEngineManagerDialog = { init:
function engineManager_init() { gEngineView = new EngineView(new EngineStore()); var
prefService = Cc["@mozilla.org/preferences-service;1"]. getService(Ci.nsIPrefBranch); var suggestEnabled
= prefService.getBoolPref(BROWSER_SUGGEST_PREF); document.getElementById("enableSuggest").checked
= suggestEnabled; var tree = document.getElementById("engineList"); tree.view = gEngineView; var os = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService); os.addObserver(this, "browser-search-engine-modified", false);
}, observe: function engineManager_observe(aEngine, aTopic, aVerb) { if (aTopic == "browser-search-engine-modified")
{ aEngine.QueryInterface(Ci.nsISearchEngine) switch (aVerb) { case "engine-added": gEngineView._engineStore.addEngine(aEngine);
gEngineView.rowCountChanged(gEngineView.lastIndex, 1); break; case "engine-changed": gEngineView._engineStore.reloadIcons();
break; case "engine-removed": case "engine-current": // Not relevant return; } gEngineView.invalidate();
} }, onOK: function engineManager_onOK() { // Remove the observer var os = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService); os.removeObserver(this, "browser-search-engine-modified"); // Set
the preference var newSuggestEnabled = document.getElementById("enableSuggest").checked; var prefService = Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefBranch); prefService.setBoolPref(BROWSER_SUGGEST_PREF, newSuggestEnabled); // Commit the changes
gEngineView._engineStore.commit(); }, onCancel: function engineManager_onCancel() { // Remove
the observer var os = Cc["@mozilla.org/observer-service;1"]. getService(Ci.nsIObserverService); os.removeObserver(this,
"browser-search-engine-modified"); }, onRestoreDefaults: function engineManager_onRestoreDefaults()
{ var num = gEngineView._engineStore.restoreDefaultEngines(); gEngineView.rowCountChanged(0, num); gEngineView.invalidate();
}, showRestoreDefaults: function engineManager_showRestoreDefaults(val) { document.documentElement.getButton("extra2").disabled
= !val; }, loadAddEngines: function engineManager_loadAddEngines() { this.onOK(); window.opener.BrowserSearch.loadAddEngines();
window.close(); }, remove: function engineManager_remove() { gEngineView._engineStore.removeEngine(gEngineView.selectedEngine);
var index = gEngineView.selectedIndex; gEngineView.rowCountChanged(index, -1); gEngineView.invalidate(); gEngineView.selection.select(Math.min(index,
gEngineView.lastIndex)); gEngineView.ensureRowIsVisible(Math.min(index, gEngineView.lastIndex)); document.getElementById("engineList").focus();
}, /** * Moves the selected engine either up or down in the engine list * @param aDir
* -1 to move the selected engine down, +1 to move it up. */ bump: function engineManager_move(aDir)
{ var selectedEngine = gEngineView.selectedEngine; var newIndex = gEngineView.selectedIndex
- aDir; gEngineView._engineStore.moveEngine(selectedEngine, newIndex); gEngineView.invalidate(); gEngineView.selection.select(newIndex);
gEngineView.ensureRowIsVisible(newIndex); this.showRestoreDefaults(true); document.getElementById("engineList").focus();
}, editKeyword: function engineManager_editKeyword() { var selectedEngine = gEngineView.selectedEngine;
if (!selectedEngine) return; var prompt = Cc["@mozilla.org/embedcomp/prompt-service;1"].
getService(Ci.nsIPromptService); var alias = { value: selectedEngine.alias }; var strings
= document.getElementById("engineManagerBundle"); var title = strings.getString("editTitle");
var msg = strings.getFormattedString("editMsg", [selectedEngine.name]); while (prompt.prompt(window,
title, msg, alias, null, { })) { var bduplicate = false; var eduplicate = false; if (alias.value
!= "") { try { let bmserv = Cc["@mozilla.org/browser/nav-bookmarks-service;1"]. getService(Ci.nsINavBookmarksService); if
(bmserv.getURIForKeyword(alias.value)) bduplicate = true; } catch(ex) {} // Check for duplicates
in changes we haven't committed yet let engines = gEngineView._engineStore.engines; for each
(let engine in engines) { if (engine.alias == alias.value && engine.name != selectedEngine.name)
{ eduplicate = true; break; } } } // Notify the user if they have chosen an existing engine/bookmark
keyword if (eduplicate || bduplicate) { var dtitle = strings.getString("duplicateTitle");
var bmsg = strings.getString("duplicateBookmarkMsg"); var emsg = strings.getFormattedString("duplicateEngineMsg",
[engine.name]); prompt.alert(window, dtitle, (eduplicate) ? emsg : bmsg); } else { gEngineView._engineStore.changeEngine(selectedEngine,
"alias", alias.value); gEngineView.invalidate(); break; } } }, onSelect: function engineManager_onSelect()
{ // buttons only work if an engine is selected and it's not the last engine var disableButtons
= (gEngineView.selectedIndex == -1) || (gEngineView.lastIndex == 0); var lastSelected = (gEngineView.selectedIndex
== gEngineView.lastIndex); var firstSelected = (gEngineView.selectedIndex == 0); var noSelection
= (gEngineView.selectedIndex == -1); document.getElementById("cmd_remove").setAttribute("disabled", disableButtons); document.getElementById("cmd_moveup").setAttribute("disabled",
disableButtons || firstSelected); document.getElementById("cmd_movedown").setAttribute("disabled", disableButtons || lastSelected); document.getElementById("cmd_editkeyword").setAttribute("disabled",
noSelection); function onDragEngineStart(event) { var selectedIndex = gEngineView.selectedIndex;
if (selectedIndex > 0) { event.dataTransfer.setData(ENGINE_FLAVOR, selectedIndex.toString()); event.dataTransfer.effectAllowed
= "move"; // "Operation" objects function EngineMoveOp(aEngineClone, aNewIndex) { if
(!aEngineClone) throw new Error("bad args to new EngineMoveOp!"); this._engine = aEngineClone.originalEngine;
this._newIndex = aNewIndex; EngineMoveOp.prototype = { _engine: null, _newIndex: null, commit:
function EMO_commit() { var searchService = Cc["@mozilla.org/browser/search-service;1"].
getService(Ci.nsIBrowserSearchService); searchService.moveEngine(this._engine, this._newIndex); function EngineRemoveOp(aEngineClone)
{ if (!aEngineClone) throw new Error("bad args to new EngineRemoveOp!"); this._engine
= aEngineClone.originalEngine; EngineRemoveOp.prototype = { _engine: null, commit: function ERO_commit()
{ var searchService = Cc["@mozilla.org/browser/search-service;1"]. getService(Ci.nsIBrowserSearchService); searchService.removeEngine(this._engine);
function EngineUnhideOp(aEngineClone, aNewIndex) { if (!aEngineClone) throw new Error("bad
args to new EngineUnhideOp!"); this._engine = aEngineClone.originalEngine; this._newIndex
= aNewIndex; EngineUnhideOp.prototype = { _engine: null, _newIndex: null, commit:
function EUO_commit() { this._engine.hidden = false; var searchService = Cc["@mozilla.org/browser/search-service;1"].
getService(Ci.nsIBrowserSearchService); searchService.moveEngine(this._engine, this._newIndex); function EngineChangeOp(aEngineClone,
aProp, aValue) { if (!aEngineClone) throw new Error("bad args to new EngineChangeOp!");
this._engine = aEngineClone.originalEngine; this._prop = aProp; this._newValue = aValue;
EngineChangeOp.prototype = { _engine: null, _prop: null, _newValue: null, commit: function
ECO_commit() { this._engine[this._prop] = this._newValue; function EngineStore() {
var searchService = Cc["@mozilla.org/browser/search-service;1"]. getService(Ci.nsIBrowserSearchService); this._engines
= searchService.getVisibleEngines({}).map(this._cloneEngine); this._defaultEngines = searchService.getDefaultEngines({}).map(this._cloneEngine);
this._ops = []; // check if we need to disable the restore defaults button var someHidden
= this._defaultEngines.some(function (e) {return e.hidden;}); gEngineManagerDialog.showRestoreDefaults(someHidden);
EngineStore.prototype = { _engines: null, _defaultEngines: null, _ops: null, get engines()
{ return this._engines; }, set engines(val) { this._engines = val; return val; }, _getIndexForEngine:
function ES_getIndexForEngine(aEngine) { return this._engines.indexOf(aEngine); },
_getEngineByName: function ES_getEngineByName(aName) { for each (var engine in this._engines)
if (engine.name == aName) return engine; return null; }, _cloneEngine: function ES_cloneObj(aEngine)
{ var newO=[]; for (var i in aEngine) newO[i] = aEngine[i]; newO.originalEngine = aEngine;
return newO; }, // Callback for Array's some(). A thisObj must be passed to some() _isSameEngine:
function ES_isSameEngine(aEngineClone) { return aEngineClone.originalEngine == this.originalEngine;
}, commit: function ES_commit() { var searchService = Cc["@mozilla.org/browser/search-service;1"].
getService(Ci.nsIBrowserSearchService); var currentEngine = this._cloneEngine(searchService.currentEngine);
for (var i = 0; i < this._ops.length; i++) this._ops[i].commit(); // Restore currentEngine
if it is a default engine that is still visible. // Needed if the user deletes currentEngine
and then restores it. if (this._defaultEngines.some(this._isSameEngine, currentEngine) && !currentEngine.originalEngine.hidden)
searchService.currentEngine = currentEngine.originalEngine; }, addEngine: function ES_addEngine(aEngine)
{ this._engines.push(this._cloneEngine(aEngine)); }, moveEngine: function ES_moveEngine(aEngine,
aNewIndex) { if (aNewIndex < 0 || aNewIndex > this._engines.length - 1) throw new Error("ES_moveEngine:
invalid aNewIndex!"); var index = this._getIndexForEngine(aEngine); if (index == -1) throw new Error("ES_moveEngine:
invalid engine?"); if (index == aNewIndex) return; // nothing to do // Move the engine
in our internal store var removedEngine = this._engines.splice(index, 1)[0]; this._engines.splice(aNewIndex,
0, removedEngine); this._ops.push(new EngineMoveOp(aEngine, aNewIndex)); }, removeEngine: function ES_removeEngine(aEngine)
{ var index = this._getIndexForEngine(aEngine); if (index == -1) throw new Error("invalid
engine?"); this._engines.splice(index, 1); this._ops.push(new EngineRemoveOp(aEngine));
if (this._defaultEngines.some(this._isSameEngine, aEngine)) gEngineManagerDialog.showRestoreDefaults(true);
}, restoreDefaultEngines: function ES_restoreDefaultEngines() { var added = 0; for (var i = 0; i < this._defaultEngines.length;
++i) { var e = this._defaultEngines[i]; // If the engine is already in the list, just
move it. if (this._engines.some(this._isSameEngine, e)) { this.moveEngine(this._getEngineByName(e.name),
i); } else { // Otherwise, add it back to our internal store this._engines.splice(i,
0, e); this._ops.push(new EngineUnhideOp(e, i)); added++; } } gEngineManagerDialog.showRestoreDefaults(false);
return added; }, changeEngine: function ES_changeEngine(aEngine, aProp, aNewValue) { var index = this._getIndexForEngine(aEngine);
if (index == -1) throw new Error("invalid engine?"); this._engines[index][aProp] =
aNewValue; this._ops.push(new EngineChangeOp(aEngine, aProp, aNewValue)); }, reloadIcons: function
ES_reloadIcons() { this._engines.forEach(function (e) { e.uri = e.originalEngine.uri; }); function
EngineView(aEngineStore) { this._engineStore = aEngineStore; EngineView.prototype = {
_engineStore: null, tree: null, get lastIndex() { return this.rowCount - 1; }, get selectedIndex()
{ var seln = this.selection; if (seln.getRangeCount() > 0) { var min = { }; seln.getRangeAt(0,
min, { }); return min.value; } return -1; }, get selectedEngine() { return this._engineStore.engines[this.selectedIndex];
}, // Helpers rowCountChanged: function (index, count) { this.tree.rowCountChanged(index,
count); }, invalidate: function () { this.tree.invalidate(); }, ensureRowIsVisible: function (index)
{ this.tree.ensureRowIsVisible(index); }, getSourceIndexFromDrag: function () { var
dragService = Cc["@mozilla.org/widget/dragservice;1"]. getService().QueryInterface(Ci.nsIDragService);
var dragSession = dragService.getCurrentSession(); var transfer = Cc["@mozilla.org/widget/transferable;1"].
createInstance(Ci.nsITransferable); transfer.addDataFlavor(ENGINE_FLAVOR); dragSession.getData(transfer, 0); var dataObj
= {}; var len = {}; var sourceIndex = -1; try { transfer.getAnyTransferData({}, dataObj,
len); } catch (ex) {} if (dataObj.value) { sourceIndex = dataObj.value.QueryInterface(Ci.nsISupportsString).data;
sourceIndex = parseInt(sourceIndex.substring(0, len.value)); } return sourceIndex; }, //
nsITreeView get rowCount() { return this._engineStore.engines.length; }, getImageSrc: function(index, column)
{ if (column.id == "engineName" && this._engineStore.engines[index].iconURI) return this._engineStore.engines[index].iconURI.spec;
return ""; }, getCellText: function(index, column) { if (column.id == "engineName") return
this._engineStore.engines[index].name; else if (column.id == "engineKeyword") return this._engineStore.engines[index].alias;
return ""; }, setTree: function(tree) { this.tree = tree; }, canDrop: function(targetIndex,
orientation) { var sourceIndex = this.getSourceIndexFromDrag(); return (sourceIndex != -1 && sourceIndex
!= targetIndex && sourceIndex != (targetIndex + orientation)); }, drop: function(dropIndex,
orientation) { var sourceIndex = this.getSourceIndexFromDrag(); var sourceEngine = this._engineStore.engines[sourceIndex];
if (dropIndex > sourceIndex) { if (orientation == Ci.nsITreeView.DROP_BEFORE) dropIndex--;
} else { if (orientation == Ci.nsITreeView.DROP_AFTER) dropIndex++; } this._engineStore.moveEngine(sourceEngine,
dropIndex); gEngineManagerDialog.showRestoreDefaults(true); // Redraw, and adjust selection this.invalidate();
this.selection.clearSelection(); this.selection.select(dropIndex); }, selection: null, getRowProperties: function(index,
properties) { }, getCellProperties: function(index, column, properties) { }, getColumnProperties:
function(column, properties) { }, isContainer: function(index) { return false; }, isContainerOpen:
function(index) { return false; }, isContainerEmpty: function(index) { return false; }, isSeparator:
function(index) { return false; }, isSorted: function(index) { return false; }, getParentIndex:
function(index) { return -1; }, hasNextSibling: function(parentIndex, index) { return false;
}, getLevel: function(index) { return 0; }, getProgressMode: function(index, column)
{ }, getCellValue: function(index, column) { }, toggleOpenState: function(index) {
}, cycleHeader: function(column) { }, selectionChanged: function() { }, cycleCell: function(row, column)
{ }, isEditable: function(index, column) { return false; }, isSelectable: function(index,
column) { return false; }, setCellValue: function(index, column, value) { }, setCellText: function(index,
column, value) { }, performAction: function(action) { }, performActionOnRow: function(action,
index) { }, performActionOnCell: function(action, index, column) { } content/browser/aboutSessionRestore.xhtml &restorepage.errorTitle;
&restorepage.problemDesc; &restorepage.tryThis; &restorepage.restoreSome;
&restorepage.startNew;
content/browser/aboutSessionRestore.js/* ***** BEGIN LICENSE BLOCK ***** * Version:
MPL 1.1/GPL 2.0/LGPL 2.1 * The contents of this file are subject to the Mozilla Public
License Version * 1.1 (the "License"); you may not use this file except in compliance
with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/
* Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT
WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language
governing rights and limitations under the * License. * The Original Code is the nsSessionStore
component. * The Initial Developer of the Original Code is * Simon B nzli
* Portions created by the Initial Developer are Copyright (C) 2008 * the Initial Developer.
All Rights Reserved. * Contributor(s): * Alternatively, the contents of this file may
be used under the terms of * either the GNU General Public License Version 2 or later
(the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead * of those
above. If you wish to allow use of your version of this file only * under the terms of either
the GPL or the LGPL, and not to allow others to * use your version of this file under the
terms of the MPL, indicate your * decision by deleting the provisions above and replace
them with the notice * and other provisions required by the GPL or the LGPL. If you do
not delete * the provisions above, a recipient may use your version of this file under *
the terms of any one of the MPL, the GPL or the LGPL. * ***** END LICENSE BLOCK *****
*/ const Cc = Components.classes; const Ci = Components.interfaces; var gStateObject;
var gTreeData; // Page initialization window.onload = function() { // the crashed session state
is kept inside a textbox so that SessionStore picks it up // (for when the tab is closed
or the session crashes right again) var sessionData = document.getElementById("sessionData");
if (!sessionData.value) { var ss = Cc["@mozilla.org/browser/sessionstartup;1"].getService(Ci.nsISessionStartup); sessionData.value = ss.state; if (!sessionData.value)
{ document.getElementById("errorTryAgain").disabled = true; return; } // make sure the data is
tracked to be restored in case of a subsequent crash var event = document.createEvent("UIEvents");
event.initUIEvent("input", true, true, window, 0); sessionData.dispatchEvent(event); var
s = new Components.utils.Sandbox("about:blank"); gStateObject = Components.utils.evalInSandbox("("
+ sessionData.value + ")", s); initTreeView(); document.getElementById("errorTryAgain").focus();
function initTreeView() { var tabList = document.getElementById("tabList"); var winLabel = tabList.getAttribute("_window_label");
gTreeData = []; gStateObject.windows.forEach(function(aWinData, aIx) { var winState = { label: winLabel.replace("%S",
(aIx + 1)), open: true, checked: true, ix: aIx }; winState.tabs = aWinData.tabs.map(function(aTabData)
{ var entry = aTabData.entries[aTabData.index - 1] || { url: "about:blank" }; var iconURL
= aTabData.attributes && aTabData.attributes.image || null; // don't initiate a connection just
to fetch a favicon (see bug 462863) if (/^https?:/.test(iconURL)) iconURL = "moz-anno:favicon:" + iconURL; return
{ label: entry.title || entry.url, checked: true, src: iconURL, parent: winState }; });
gTreeData.push(winState); for each (var tab in winState.tabs) gTreeData.push(tab); },
this); tabList.view = treeView; tabList.view.selection.select(0); // User actions function restoreSession()
{ document.getElementById("errorTryAgain").disabled = true; // remove all unselected tabs from
the state before restoring it var ix = gStateObject.windows.length - 1; for (var t = gTreeData.length - 1; t
>= 0; t--) { if (treeView.isContainer(t)) { if (gTreeData[t].checked === 0) // this
window will be restored partially gStateObject.windows[ix].tabs = gStateObject.windows[ix].tabs.filter(function(aTabData,
aIx) gTreeData[t].tabs[aIx].checked); else if (!gTreeData[t].checked) // this window
won't be restored at all gStateObject.windows.splice(ix, 1); ix--; } var stateString = gStateObject.toSource();
var ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore); var top = getBrowserWindow(); // if there's
only this page open, reuse the window for restoring the session if (top.gBrowser.tabContainer.childNodes.length
== 1) { ss.setWindowState(top, stateString, true); return; // restore the session into
a new window and close the current tab var newWindow = top.openDialog(top.location, "_blank",
"chrome,dialog=no,all"); newWindow.addEventListener("load", function() { newWindow.removeEventListener("load",
arguments.callee, true); ss.setWindowState(newWindow, stateString, true); var tabbrowser = top.gBrowser;
var tabIndex = tabbrowser.getBrowserIndexForDocument(document); tabbrowser.removeTab(tabbrowser.tabContainer.childNodes[tabIndex]);
}, true); function startNewSession() { var prefBranch = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
if (prefBranch.getIntPref("browser.startup.page") == 0) getBrowserWindow().gBrowser.loadURI("about:blank");
else getBrowserWindow().BrowserHome(); function onListClick(aEvent) { // don't react to right-clicks
if (aEvent.button == 2) return; var row = {}, col = {}; treeView.treeBox.getCellAt(aEvent.clientX,
aEvent.clientY, row, col, {}); if (col.value) { // restore this specific tab in the same
window for middle-clicking // or Ctrl+clicking on a tab's title if ((aEvent.button == 1
|| aEvent.ctrlKey) && col.value.id == "title" && !treeView.isContainer(row.value)) restoreSingleTab(row.value,
aEvent.shiftKey); else if (col.value.id == "restore") toggleRowChecked(row.value); function
onListKeyDown(aEvent) { switch (aEvent.keyCode) case KeyEvent.DOM_VK_SPACE: toggleRowChecked(document.getElementById("tabList").currentIndex);
break; case KeyEvent.DOM_VK_RETURN: var ix = document.getElementById("tabList").currentIndex;
if (aEvent.ctrlKey && !treeView.isContainer(ix)) restoreSingleTab(ix, aEvent.shiftKey); break;
case KeyEvent.DOM_VK_UP: case KeyEvent.DOM_VK_DOWN: case KeyEvent.DOM_VK_PAGE_UP: case KeyEvent.DOM_VK_PAGE_DOWN:
case KeyEvent.DOM_VK_HOME: case KeyEvent.DOM_VK_END: aEvent.preventDefault(); // else the page
scrolls unwantedly break; // Helper functions function getBrowserWindow() { return window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShellTreeItem).rootTreeItem .QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow);
function toggleRowChecked(aIx) { var item = gTreeData[aIx]; item.checked = !item.checked;
treeView.treeBox.invalidateRow(aIx); function isChecked(aItem) aItem.checked; if (treeView.isContainer(aIx))
{ // (un)check all tabs of this window as well for each (var tab in item.tabs) { tab.checked
= item.checked; treeView.treeBox.invalidateRow(gTreeData.indexOf(tab)); } else { // update the window's checkmark
as well (0 means "partially checked") item.parent.checked = item.parent.tabs.every(isChecked) ? true
: item.parent.tabs.some(isChecked) ? 0 : false; treeView.treeBox.invalidateRow(gTreeData.indexOf(item.parent));
document.getElementById("errorTryAgain").disabled = !gTreeData.some(isChecked); function restoreSingleTab(aIx,
aShifted) { var tabbrowser = getBrowserWindow().gBrowser; var newTab = tabbrowser.addTab(); var item
= gTreeData[aIx]; var ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore); var tabState = gStateObject.windows[item.parent.ix]
.tabs[aIx - gTreeData.indexOf(item.parent) - 1]; ss.setTabState(newTab, tabState.toSource());
// respect the preference as to whether to select the tab (the Shift key inverses) var
prefBranch = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch); if (prefBranch.getBoolPref("browser.tabs.loadInBackground")
!= !aShifted) tabbrowser.selectedTab = newTab; // Tree controller var treeView = { _atoms:
{}, _getAtom: function(aName) if (!this._atoms[aName]) { var as = Cc["@mozilla.org/atom-service;1"].getService(Ci.nsIAtomService);
this._atoms[aName] = as.getAtom(aName); } return this._atoms[aName]; }, treeBox: null,
selection: null, get rowCount() { return gTreeData.length; }, setTree: function(treeBox) { this.treeBox
= treeBox; }, getCellText: function(idx, column) { return gTreeData[idx].label; },
isContainer: function(idx) { return "open" in gTreeData[idx]; }, getCellValue: function(idx,
column){ return gTreeData[idx].checked; }, isContainerOpen: function(idx) { return gTreeData[idx].open;
}, isContainerEmpty: function(idx) { return false; }, isSeparator: function(idx) { return
false; }, isSorted: function() { return false; }, isEditable: function(idx, column) { return
false; }, getLevel: function(idx) { return this.isContainer(idx) ? 0 : 1; }, getParentIndex:
function(idx) { if (!this.isContainer(idx)) for (var t = idx - 1; t >= 0 ; t--) if (this.isContainer(t))
return t; return -1; }, hasNextSibling: function(idx, after) { var thisLevel = this.getLevel(idx);
for (var t = after + 1; t < gTreeData.length; t++) if (this.getLevel(t) thisLevel; t++); var deletecount = t - idx - 1; gTreeData.splice(idx + 1,
deletecount); this.treeBox.rowCountChanged(idx + 1, -deletecount); } else { // add this window's
tab rows to the view var toinsert = gTreeData[idx].tabs; for (var i = 0; i < toinsert.length; i++)
gTreeData.splice(idx + i + 1, 0, toinsert[i]); this.treeBox.rowCountChanged(idx + 1, toinsert.length);
} item.open = !item.open; this.treeBox.invalidateRow(idx); }, getCellProperties: function(idx, column,
prop) { if (column.id == "restore" && this.isContainer(idx) && gTreeData[idx].checked === 0) prop.AppendElement(this._getAtom("partial"));
if (column.id == "title") prop.AppendElement(this._getAtom(this.getImageSrc(idx, column) ? "icon" : "noicon")); }, getRowProperties:
function(idx, prop) { var winState = gTreeData[idx].parent || gTreeData[idx]; if (winState.ix % 2 !=
0) prop.AppendElement(this._getAtom("alternate")); }, getImageSrc: function(idx, column) {
if (column.id == "title") return gTreeData[idx].src || null; return null; }, getProgressMode
: function(idx, column) { }, cycleHeader: function(column) { }, cycleCell: function(idx,
column) { }, selectionChanged: function() { }, performAction: function(action) { },
performActionOnCell: function(action, index, column) { }, getColumnProperties: function(column,
prop) { } content/browser/setDesktopBackground.xul
content/browser/setDesktopBackground.js//@line
39 "e:\builds\moz2_slave\win32_build\build\browser\components\shell\content\setDesktopBackground.js" var Ci = Components.interfaces; var gSetBackground
= { //@line 44 "e:\builds\moz2_slave\win32_build\build\browser\components\shell\content\setDesktopBackground.js" _position : "", _backgroundColor : 0, //@line
49 "e:\builds\moz2_slave\win32_build\build\browser\components\shell\content\setDesktopBackground.js" _screenWidth : 0, _screenHeight : 0, _image
: null, _canvas : null, get _shell() return Components.classes["@mozilla.org/browser/shell-service;1"]
.getService(Ci.nsIShellService); }, load: function () this._canvas = document.getElementById("screen");
this._screenWidth = screen.width; this._screenHeight = screen.height; //@line 68 "e:\builds\moz2_slave\win32_build\build\browser\components\shell\content\setDesktopBackground.js"
if (this._screenWidth / this._screenHeight >= 1.6) document.getElementById("monitor").setAttribute("aspectratio",
"16:10"); // make sure that the correct dimensions will be used setTimeout(function(self) {
self.init(window.arguments[0]); }, 0, this); }, init: function (aImage) this._image =
aImage; // set the size of the coordinate space this._canvas.width = this._canvas.clientWidth;
this._canvas.height = this._canvas.clientHeight; var ctx = this._canvas.getContext("2d"); ctx.scale(this._canvas.clientWidth
/ this._screenWidth, this._canvas.clientHeight / this._screenHeight); //@line 89 "e:\builds\moz2_slave\win32_build\build\browser\components\shell\content\setDesktopBackground.js"
this._initColor(); //@line 101 "e:\builds\moz2_slave\win32_build\build\browser\components\shell\content\setDesktopBackground.js" this.updatePosition(); }, //@line 105 "e:\builds\moz2_slave\win32_build\build\browser\components\shell\content\setDesktopBackground.js"
_initColor: function () var color = this._shell.desktopBackgroundColor; const rMask = 4294901760; const gMask = 65280;
const bMask = 255; var r = (color & rMask) >> 16; var g = (color & gMask) >> 8; var
b = (color & bMask); this.updateColor(this._rgbToHex(r, g, b)); var colorpicker = document.getElementById("desktopColor");
colorpicker.color = this._backgroundColor; }, updateColor: function (aColor) this._backgroundColor
= aColor; this._canvas.style.backgroundColor = aColor; }, // Converts a color string in
the format "#RRGGBB" to an integer. _hexStringToLong: function (aString) return parseInt(aString.substring(1,3),
16)
&feedPage.title;
SubscribeHandler.init();
content/browser/feeds/subscribe.js/* -*- Mode: C++; tab-width: 8; indent-tabs-mode:
nil; c-basic-offset: 2 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL
2.0/LGPL 2.1 * The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with * the License.
You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * Software distributed
under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND,
either express or implied. See the License * for the specific language governing rights
and limitations under the * License. * The Original Code is the Feed Subscribe Handler.
* 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):
* Ben Goodger * Asaf Romano * 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 SubscribeHandler = { /** * The nsIFeedWriter object that produces
the UI */ _feedWriter: null, init: function SH_init() { this._feedWriter = new BrowserFeedWriter();
this._feedWriter.init(window); }, writeContent: function SH_writeContent() { this._feedWriter.writeContent();
}, uninit: function SH_uninit() { this._feedWriter.close(); }, subscribe: function FH_subscribe() {
this._feedWriter.subscribe(); content/browser/places/bookmarkProperties2.xul
content/browser/places/places.xul
%editMenuOverlayDTD; %browserDTD;
&detailsPane.selectAnItemText.description;
control="infoBoxExpander"/>
content/browser/places/places.js/* -*- Mode: C++; tab-width: 8; indent-tabs-mode:
nil; c-basic-offset: 2 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL
2.0/LGPL 2.1 * The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with * the License.
You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * Software distributed
under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND,
either express or implied. See the License * for the specific language governing rights
and limitations under the * License. * The Original Code is Mozilla Places Organizer.
* The Initial Developer of the Original Code is Google Inc. * Portions created by the Initial
Developer are Copyright (C) 2005-2006 * the Initial Developer. All Rights Reserved. *
Contributor(s): * Ben Goodger * Annie Sullivan
* Asaf Romano * Ehsan Akhgari * Drew Willcoxon
* 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 PlacesOrganizer
= { _places: null, _content: null, // IDs of fields from editBookmarkOverlay that should
be hidden when infoBox // is minimal. IDs should be kept in sync with the IDs of the
elements // observing additionalInfoBroadcaster. _additionalInfoFields: [ "editBMPanel_descriptionRow",
"editBMPanel_loadInSidebarCheckbox", "editBMPanel_keywordRow", ], _initFolderTree: function() { var leftPaneRoot
= PlacesUIUtils.leftPaneFolderId; this._places.place = "place:excludeItems=1&expandQueries=0&folder="
+ leftPaneRoot; }, selectLeftPaneQuery: function PO_selectLeftPaneQuery(aQueryName) { var itemId
= PlacesUIUtils.leftPaneQueries[aQueryName]; this._places.selectItems([itemId]); // Forcefully
expand all-bookmarks if (aQueryName == "AllBookmarks") asContainer(this._places.selectedNode).containerOpen
= true; }, init: function PO_init() { this._places = document.getElementById("placesList");
this._content = document.getElementById("placeContent"); this._initFolderTree(); var leftPaneSelection
= "AllBookmarks"; // default to all-bookmarks if ("arguments" in window && window.arguments.length
> 0) leftPaneSelection = window.arguments[0]; this.selectLeftPaneQuery(leftPaneSelection);
// clear the back-stack this._backHistory.splice(0); document.getElementById("OrganizerCommand:Back").setAttribute("disabled",
true); var view = this._content.treeBoxObject.view; if (view.rowCount > 0) view.selection.select(0);
this._content.focus(); // Set up the search UI. PlacesSearchBox.init(); //@line 95 "e:\builds\moz2_slave\win32_build\build\browser\components\places\content\places.js"
window.addEventListener("AppCommand", this, true); //@line 118 "e:\builds\moz2_slave\win32_build\build\browser\components\places\content\places.js"
// remove the "Properties" context-menu item, we've our own details pane document.getElementById("placesContext")
.removeChild(document.getElementById("placesContext_show:info")); }, QueryInterface: function PO_QueryInterface(aIID)
{ if (aIID.equals(Components.interfaces.nsIDOMEventListener) || aIID.equals(Components.interfaces.nsISupports))
return this; throw Components.results.NS_NOINTERFACE; }, handleEvent: function PO_handleEvent(aEvent)
{ if (aEvent.type != "AppCommand") return; aEvent.stopPropagation(); switch (aEvent.command)
{ case "Back": if (this._backHistory.length > 0) this.back(); break; case "Forward":
if (this._forwardHistory.length > 0) this.forward(); break; case "Search": PlacesSearchBox.findAll();
break; } }, destroy: function PO_destroy() { }, _location: null, get location() { return
this._location; }, set location(aLocation) { if (!aLocation || this._location == aLocation)
return aLocation; if (this.location) { this._backHistory.unshift(this.location); this._forwardHistory.splice(0); } this._location
= aLocation; this._places.selectPlaceURI(aLocation); if (!this._places.hasSelection) { // If no
node was found for the given place: uri, just load it directly this._content.place = aLocation;
} this.onContentTreeSelect(); // update navigation commands if (this._backHistory.length ==
0) document.getElementById("OrganizerCommand:Back").setAttribute("disabled", true); else document.getElementById("OrganizerCommand:Back").removeAttribute("disabled");
if (this._forwardHistory.length == 0) document.getElementById("OrganizerCommand:Forward").setAttribute("disabled", true); else document.getElementById("OrganizerCommand:Forward").removeAttribute("disabled");
return aLocation; }, _backHistory: [], _forwardHistory: [], back: function PO_back() { this._forwardHistory.unshift(this.location);
var historyEntry = this._backHistory.shift(); this._location = null; this.location = historyEntry;
}, forward: function PO_forward() { this._backHistory.unshift(this.location); var historyEntry = this._forwardHistory.shift();
this._location = null; this.location = historyEntry; }, /** * Called when a place folder is selected
in the left pane. * @param resetSearchBox * true if the search box should also be reset,
false otherwise. * The search box should be reset when a new folder in the left * pane
is selected; the search scope and text need to be cleared in * preparation for the new
folder. Note that if the user manually * resets the search box, either by clicking
its reset button or by * deleting its text, this will be false. */ _cachedLeftPaneSelectedURI:
null, onPlaceSelected: function PO_onPlaceSelected(resetSearchBox) { // Don't change the right-hand pane contents
when there's no selection. if (!this._places.hasSelection) return; var node = this._places.selectedNode;
var queries = asQuery(node).getQueries({}); // Items are only excluded on the left pane.
var options = node.queryOptions.clone(); options.excludeItems = false; var placeURI = PlacesUtils.history.queriesToQueryString(queries,
queries.length, options); // If either the place of the content tree in the right pane
has changed or // the user cleared the search box, update the place, hide the search UI,
// and update the back/forward buttons by setting location. if (this._content.place
!= placeURI || !resetSearchBox) { this._content.place = placeURI; PlacesSearchBox.hideSearchUI();
this.location = node.uri; } // Update the selected folder title where it appears in
the UI: the folder // scope button, "Find in " command, and the
search box // emptytext. They must be updated even if the selection hasn't changed -- //
specifically when node's title changes. In that case a selection event // is generated,
this method is called, but the selection does not change. var folderButton = document.getElementById("scopeBarFolder");
var folderTitle = node.title || folderButton.getAttribute("emptytitle"); folderButton.setAttribute("label", folderTitle);
var cmd = document.getElementById("OrganizerCommand_find:current"); var label = PlacesUIUtils.getFormattedString("findInPrefix",
[folderTitle]); cmd.setAttribute("label", label); if (PlacesSearchBox.filterCollection
== "collection") PlacesSearchBox.updateCollectionTitle(folderTitle); // When we invalidate a container we use
suppressSelectionEvent, when it is // unset a select event is fired, in many cases the
selection did not really // change, so we should check for it, and return early in such
a case. Note // that we cannot return any earlier than this point, because when //
!resetSearchBox, we need to update location and hide the UI as above, // even though the
selection has not changed. if (node.uri == this._cachedLeftPaneSelectedURI) return;
this._cachedLeftPaneSelectedURI = node.uri; // At this point, resetSearchBox is true,
because the left pane selection // has changed; otherwise we would have returned earlier.
PlacesSearchBox.searchFilter.reset(); this._setSearchScopeForNode(node); if (this._places.treeBoxObject.focused) this._fillDetailsPane([node]);
}, /** * Sets the search scope based on aNode's properties. * @param aNode * the node to set
up scope from */ _setSearchScopeForNode: function PO__setScopeForNode(aNode) { var itemId =
aNode.itemId; if (PlacesUtils.nodeIsHistoryContainer(aNode) || itemId == PlacesUIUtils.leftPaneQueries["History"])
{ PlacesQueryBuilder.setScope("history"); } // Default to All Bookmarks for all other
nodes, per bug 469437. else PlacesQueryBuilder.setScope("bookmarks"); // Enable or disable the folder scope button.
var folderButton = document.getElementById("scopeBarFolder"); folderButton.hidden = !PlacesUtils.nodeIsFolder(aNode)
|| itemId == PlacesUIUtils.allBookmarksFolderId; }, /** * Handle clicks on the tree. * Single
Left click, right click or modified click do not result in any * special action, since
they're related to selection. * @param aEvent * The mouse event. */ onTreeClick: function
PO_onTreeClick(aEvent) { // Only handle clicks on tree children. if (aEvent.target.localName
!= "treechildren") return; var currentView = aEvent.currentTarget; var selectedNode
= currentView.selectedNode; if (selectedNode) { var doubleClickOnFlatList = (aEvent.button
== 0 && aEvent.detail == 2 && aEvent.target.parentNode.flatList); var middleClick = (aEvent.button == 1 &&
aEvent.detail == 1); if (PlacesUtils.nodeIsURI(selectedNode) && (doubleClickOnFlatList || middleClick))
{ // Open associated uri in the browser. PlacesOrganizer.openSelectedNode(aEvent);
} else if (middleClick && PlacesUtils.nodeIsContainer(selectedNode)) { // The command execution function will
take care of seeing if the // selection is a folder or a different container type, and
will // load its contents in tabs. PlacesUIUtils.openContainerNodeInTabs(selectedNode, aEvent); } } }, /** * Handle focus changes
on the trees. * When moving focus between panes we should update the details pane contents.
* @param aEvent * The mouse event. */ onTreeFocus: function PO_onTreeFocus(aEvent) { var currentView
= aEvent.currentTarget; var selectedNodes = currentView.selectedNode ? [currentView.selectedNode]
: this._content.getSelectionNodes(); this._fillDetailsPane(selectedNodes); }, openFlatContainer: function PO_openFlatContainerFlatContainer(aContainer)
{ if (aContainer.itemId != -1) this._places.selectItems([aContainer.itemId]); else if (PlacesUtils.nodeIsQuery(aContainer))
this._places.selectPlaceURI(aContainer.uri); }, openSelectedNode: function PO_openSelectedNode(aEvent)
{ PlacesUIUtils.openNodeWithEvent(this._content.selectedNode, aEvent); }, /** * Returns the options associated
with the query currently loaded in the * main places pane. */ getCurrentOptions: function
PO_getCurrentOptions() { return asQuery(this._content.getResult().root).queryOptions; }, /** * Returns the queries associated with
the query currently loaded in the * main places pane. */ getCurrentQueries: function PO_getCurrentQueries()
{ return asQuery(this._content.getResult().root).getQueries({}); }, /** * Show the migration wizard for importing
from a file. */ importBookmarks: function PO_import() { // ***: ifdef it to be non-modal
(non-"sheet") on mac (see bug 259039) var features = "modal,centerscreen,chrome,resizable=no";
// The migrator window will set this to true when it closes, if the user // chose to migrate
from a specific file. window.fromFile = false; openDialog("chrome://browser/content/migration/migration.xul",
"migration", features, "bookmarks"); if (window.fromFile) this.importFromFile(); }, /** * Open a file-picker
and import the selected file into the bookmarks store */ importFromFile: function PO_importFromFile()
{ var fp = Cc["@mozilla.org/filepicker;1"]. createInstance(Ci.nsIFilePicker); fp.init(window,
PlacesUIUtils.getString("SelectImport"), Ci.nsIFilePicker.modeOpen); fp.appendFilters(Ci.nsIFilePicker.filterHTML);
if (fp.show() != Ci.nsIFilePicker.returnCancel) { if (fp.file) { var importer = Cc["@mozilla.org/browser/places/import-export-service;1"].
getService(Ci.nsIPlacesImportExportService); var file = fp.file.QueryInterface(Ci.nsILocalFile);
importer.importHTMLFromFile(file, false); } } }, /** * Allows simple exporting of bookmarks.
*/ exportBookmarks: function PO_exportBookmarks() { var fp = Cc["@mozilla.org/filepicker;1"].
createInstance(Ci.nsIFilePicker); fp.init(window, PlacesUIUtils.getString("EnterExport"), Ci.nsIFilePicker.modeSave);
fp.appendFilters(Ci.nsIFilePicker.filterHTML); fp.defaultString = "bookmarks.html"; if (fp.show()
!= Ci.nsIFilePicker.returnCancel) { var exporter = Cc["@mozilla.org/browser/places/import-export-service;1"].
getService(Ci.nsIPlacesImportExportService); exporter.exportHTMLToFile(fp.file); } },
/** * Populates the restore menu with the dates of the backups available. */ populateRestoreMenu:
function PO_populateRestoreMenu() { var restorePopup = document.getElementById("fileRestorePopup");
var dateSvc = Cc["@mozilla.org/intl/scriptabledateformat;1"]. getService(Ci.nsIScriptableDateFormat); //
remove existing menu items // last item is the restoreFromFile item while (restorePopup.childNodes.length
> 1) restorePopup.removeChild(restorePopup.firstChild); // get list of files var localizedFilename
= PlacesUtils.getString("bookmarksArchiveFilename"); var localizedFilenamePrefix = localizedFilename.substr(0,
localizedFilename.indexOf("-")); var fileList = []; var files = this.bookmarksBackupDir.directoryEntries;
while (files.hasMoreElements()) { var f = files.getNext().QueryInterface(Ci.nsIFile);
var rx = new RegExp("^(bookmarks|" + localizedFilenamePrefix + ")-([0-9]{4}-[0-9]{2}-[0-9]{2})\.json$");
if (!f.isHidden() && f.leafName.match(rx)) { var date = f.leafName.match(rx)[2].replace(/-/g,
"/"); var dateObj = new Date(date); fileList.push({date: dateObj, filename: f.leafName}); } } fileList.sort(function
PO_fileList_compare(a, b) { return b.date - a.date; }); if (fileList.length == 0) return;
// populate menu for (var i = 0; i < fileList.length; i++) { var m = restorePopup.insertBefore (document.createElement("menuitem"),
document.getElementById("restoreFromFile")); m.setAttribute("label", dateSvc.FormatDate("",
Ci.nsIScriptableDateFormat.dateFormatLong, fileList[i].date.getFullYear(), fileList[i].date.getMonth()
+ 1, fileList[i].date.getDate())); m.setAttribute("value", fileList[i].filename); m.setAttribute("oncommand",
"PlacesOrganizer.onRestoreMenuItemClick(this);"); } restorePopup.insertBefore(document.createElement("menuseparator"),
document.getElementById("restoreFromFile")); }, /** * Called when a menuitem is selected
from the restore menu. */ onRestoreMenuItemClick: function PO_onRestoreMenuItemClick(aMenuItem)
{ var dirSvc = Cc["@mozilla.org/file/directory_service;1"]. getService(Ci.nsIProperties); var bookmarksFile
= dirSvc.get("ProfD", Ci.nsIFile); bookmarksFile.append("bookmarkbackups"); bookmarksFile.append(aMenuItem.getAttribute("value"));
if (!bookmarksFile.exists()) return; this.restoreBookmarksFromFile(bookmarksFile); }, /** * Called when 'Choose File...' is
selected from the restore menu. * Prompts for a file and restores bookmarks to those
in the file. */ onRestoreBookmarksFromFile: function PO_onRestoreBookmarksFromFile()
{ var fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker); fp.init(window, PlacesUIUtils.getString("bookmarksRestoreTitle"),
Ci.nsIFilePicker.modeOpen); fp.appendFilter(PlacesUIUtils.getString("bookmarksRestoreFilterName"), PlacesUIUtils.getString("bookmarksRestoreFilterExtension"));
fp.appendFilters(Ci.nsIFilePicker.filterAll); var dirSvc = Cc["@mozilla.org/file/directory_service;1"].
getService(Ci.nsIProperties); var backupsDir = dirSvc.get("Desk", Ci.nsILocalFile); fp.displayDirectory
= backupsDir; if (fp.show() != Ci.nsIFilePicker.returnCancel) this.restoreBookmarksFromFile(fp.file); },
/** * Restores bookmarks from a JSON file. */ restoreBookmarksFromFile: function PO_restoreBookmarksFromFile(aFile)
{ // check file extension if (!aFile.leafName.match(/\.json$/)) { this._showErrorAlert(PlacesUIUtils.getString("bookmarksRestoreFormatError"));
return; } // confirm ok to delete existing bookmarks var prompts = Cc["@mozilla.org/embedcomp/prompt-service;1"].
getService(Ci.nsIPromptService); if (!prompts.confirm(null, PlacesUIUtils.getString("bookmarksRestoreAlertTitle"),
PlacesUIUtils.getString("bookmarksRestoreAlert"))) return; try { PlacesUtils.restoreBookmarksFromJSONFile(aFile);
} catch(ex) { this._showErrorAlert(PlacesUIUtils.getString("bookmarksRestoreParseError")); } }, _showErrorAlert: function PO__showErrorAlert(aMsg)
{ var brandShortName = document.getElementById("brandStrings"). getString("brandShortName"); Cc["@mozilla.org/embedcomp/prompt-service;1"].
getService(Ci.nsIPromptService). alert(window, brandShortName, aMsg); }, /** * Backup bookmarks
to desktop, auto-generate a filename with a date. * The file is a JSON serialization
of bookmarks, tags and any annotations * of those items. */ backupBookmarks: function
PO_backupBookmarks() { var fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker); fp.init(window, PlacesUIUtils.getString("bookmarksBackupTitle"),
Ci.nsIFilePicker.modeSave); fp.appendFilter(PlacesUIUtils.getString("bookmarksRestoreFilterName"), PlacesUIUtils.getString("bookmarksRestoreFilterExtension"));
var dirSvc = Cc["@mozilla.org/file/directory_service;1"]. getService(Ci.nsIProperties); var backupsDir
= dirSvc.get("Desk", Ci.nsILocalFile); fp.displayDirectory = backupsDir; fp.defaultString = PlacesUtils.getBackupFilename();
if (fp.show() != Ci.nsIFilePicker.returnCancel) { PlacesUtils.backupBookmarksToFile(fp.file);
// copy new backup to /backups dir (bug 424389) var latestBackup = PlacesUtils.getMostRecentBackup();
if (!latestBackup || latestBackup != fp.file) { latestBackup.remove(false); var name =
PlacesUtils.getBackupFilename(); fp.file.copyTo(this.bookmarksBackupDir, name); } } }, get bookmarksBackupDir() {
delete this.bookmarksBackupDir; var dirSvc = Cc["@mozilla.org/file/directory_service;1"].
getService(Ci.nsIProperties); var bookmarksBackupDir = dirSvc.get("ProfD", Ci.nsIFile); bookmarksBackupDir.append("bookmarkbackups");
if (!bookmarksBackupDir.exists()) bookmarksBackupDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0700); return this.bookmarksBackupDir = bookmarksBackupDir;
}, _paneDisabled: false, _setDetailsFieldsDisabledState: function PO__setDetailsFieldsDisabledState(aDisabled)
{ if (aDisabled) { document.getElementById("paneElementsBroadcaster") .setAttribute("disabled", "true"); } else
{ document.getElementById("paneElementsBroadcaster") .removeAttribute("disabled"); } }, _detectAndSetDetailsPaneMinimalState:
function PO__detectAndSetDetailsPaneMinimalState(aNode) { /** * The details of simple folder-items
(as opposed to livemarks) or the * of livemark-children are not likely to fill the infoBox anyway,
* thus we remove the "More/Less" button and show all details. * * the wasminimal attribute
here is used to persist the "more/less" * state in a bookmark->folder->bookmark scenario.
*/ var infoBox = document.getElementById("infoBox"); var infoBoxExpander = document.getElementById("infoBoxExpander");
var infoBoxExpanderWrapper = document.getElementById("infoBoxExpanderWrapper"); var additionalInfoBroadcaster = document.getElementById("additionalInfoBroadcaster");
if (!aNode) { infoBoxExpanderWrapper.hidden = true; return; } if (aNode.itemId != -1
&& ((PlacesUtils.nodeIsFolder(aNode) && !PlacesUtils.nodeIsLivemarkContainer(aNode))
|| PlacesUtils.nodeIsLivemarkItem(aNode))) { if (infoBox.getAttribute("minimal") ==
"true") infoBox.setAttribute("wasminimal", "true"); infoBox.removeAttribute("minimal");
infoBoxExpanderWrapper.hidden = true; } else { if (infoBox.getAttribute("wasminimal")
== "true") infoBox.setAttribute("minimal", "true"); infoBox.removeAttribute("wasminimal");
infoBoxExpanderWrapper.hidden = this._additionalInfoFields.every(function (id) document.getElementById(id).collapsed);
} additionalInfoBroadcaster.hidden = infoBox.getAttribute("minimal") == "true"; }, // NOT YET USED updateThumbnailProportions:
function PO_updateThumbnailProportions() { var previewBox = document.getElementById("previewBox");
var canvas = document.getElementById("itemThumbnail"); var height = previewBox.boxObject.height;
var width = height * (screen.width / screen.height); canvas.width = width; canvas.height = height;
}, onContentTreeSelect: function PO_onContentTreeSelect() { if (this._content.treeBoxObject.focused)
this._fillDetailsPane(this._content.getSelectionNodes()); }, _fillDetailsPane: function PO__fillDetailsPane(aNodeList)
{ var infoBox = document.getElementById("infoBox"); var detailsDeck = document.getElementById("detailsDeck");
// Make sure the infoBox UI is visible if we need to use it, we hide it // below when
we don't. infoBox.hidden = false; var aSelectedNode = aNodeList.length == 1 ? aNodeList[0] :
null; // If a textbox within a panel is focused, force-blur it so its contents // are saved
if (gEditItemOverlay.itemId != -1) { var focusedElement = document.commandDispatcher.focusedElement;
if ((focusedElement instanceof HTMLInputElement || focusedElement instanceof HTMLTextAreaElement)
&& /^editBMPanel.*/.test(focusedElement.parentNode.parentNode.id)) focusedElement.blur(); // don't update the
panel if we are already editing this node unless we're // in multi-edit mode if (aSelectedNode)
{ var concreteId = PlacesUtils.getConcreteItemId(aSelectedNode); var nodeIsSame = gEditItemOverlay.itemId
== aSelectedNode.itemId || gEditItemOverlay.itemId == concreteId || (aSelectedNode.itemId ==
-1 && gEditItemOverlay.uri && gEditItemOverlay.uri == aSelectedNode.uri); if (nodeIsSame &&
detailsDeck.selectedIndex == 1 && !gEditItemOverlay.multiEdit) return; } } // Clean up the panel before initing
it again. gEditItemOverlay.uninitPanel(false); if (aSelectedNode && !PlacesUtils.nodeIsSeparator(aSelectedNode))
{ detailsDeck.selectedIndex = 1; // Using the concrete itemId is arguably wrong. The
bookmarks API // does allow setting properties for folder shortcuts as well, but since //
the UI does not distinct between the couple, we better just show // the concrete item properties
for shortcuts to root nodes. var concreteId = PlacesUtils.getConcreteItemId(aSelectedNode);
var isRootItem = concreteId != -1 && PlacesUtils.isRootItem(concreteId); var readOnly = isRootItem || aSelectedNode.parent.itemId
== PlacesUIUtils.leftPaneFolderId; var useConcreteId = isRootItem || PlacesUtils.nodeIsTagQuery(aSelectedNode);
var itemId = -1; if (concreteId != -1 && useConcreteId) itemId = concreteId; else if
(aSelectedNode.itemId != -1) itemId = aSelectedNode.itemId; else itemId = PlacesUtils._uri(aSelectedNode.uri);
gEditItemOverlay.initPanel(itemId, { hiddenRows: ["folderPicker"], forceReadOnly: readOnly
}); // Dynamically generated queries, like history date containers, have // itemId !=0
and do not exist in history. For them the panel is // read-only, but empty, since it
can't get a valid title for the object. // In such a case we force the title using the
selectedNode one, for UI // polishness. if (aSelectedNode.itemId == -1 && (PlacesUtils.nodeIsDay(aSelectedNode)
|| PlacesUtils.nodeIsHost(aSelectedNode))) gEditItemOverlay._element("namePicker").value
= aSelectedNode.title; this._detectAndSetDetailsPaneMinimalState(aSelectedNode); } else if (!aSelectedNode && aNodeList[0])
{ var itemIds = []; for (var i = 0; i < aNodeList.length; i++) { if (!PlacesUtils.nodeIsBookmark(aNodeList[i])
&& !PlacesUtils.nodeIsURI(aNodeList[i])) { detailsDeck.selectedIndex = 0; var selectItemDesc
= document.getElementById("selectItemDescription"); var itemsCountLabel = document.getElementById("itemsCountText");
selectItemDesc.hidden = false; itemsCountLabel.value = PlacesUIUtils.getFormattedString("detailsPane.multipleItems",
[aNodeList.length]); infoBox.hidden = true; return; } itemIds[i] = aNodeList[i].itemId
!= -1 ? aNodeList[i].itemId : PlacesUtils._uri(aNodeList[i].uri); } detailsDeck.selectedIndex = 1; gEditItemOverlay.initPanel(itemIds,
{ hiddenRows: ["folderPicker", "loadInSidebar", "location", "keyword", "description", "name"]});
this._detectAndSetDetailsPaneMinimalState(aSelectedNode); } else { detailsDeck.selectedIndex = 0; infoBox.hidden
= true; var selectItemDesc = document.getElementById("selectItemDescription"); var itemsCountLabel = document.getElementById("itemsCountText");
var rowCount = this._content.treeBoxObject.view.rowCount; if (rowCount == 0) { selectItemDesc.hidden
= true; itemsCountLabel.value = PlacesUIUtils.getString("detailsPane.noItems"); } else { selectItemDesc.hidden = false; if
(rowCount == 1) itemsCountLabel.value = PlacesUIUtils.getString("detailsPane.oneItem"); else { itemsCountLabel.value = PlacesUIUtils.getFormattedString("detailsPane.multipleItems",
[rowCount]); } } } }, // NOT YET USED _updateThumbnail: function PO__updateThumbnail() { var bo =
document.getElementById("previewBox").boxObject; var width = bo.width; var height = bo.height;
var canvas = document.getElementById("itemThumbnail"); var ctx = canvas.getContext('2d'); var notAvailableText
= canvas.getAttribute("notavailabletext"); ctx.save(); ctx.fillStyle = "-moz-Dialog";
ctx.fillRect(0, 0, width, height); ctx.translate(width/2, height/2); ctx.fillStyle = "GrayText"; ctx.mozTextStyle
= "12pt sans serif"; var len = ctx.mozMeasureText(notAvailableText); ctx.translate(-len/2,0); ctx.mozDrawText(notAvailableText);
ctx.restore(); }, toggleAdditionalInfoFields: function PO_toggleAdditionalInfoFields()
{ var infoBox = document.getElementById("infoBox"); var infoBoxExpander = document.getElementById("infoBoxExpander");
var infoBoxExpanderLabel = document.getElementById("infoBoxExpanderLabel"); var additionalInfoBroadcaster = document.getElementById("additionalInfoBroadcaster");
if (infoBox.getAttribute("minimal") == "true") { infoBox.removeAttribute("minimal"); infoBoxExpanderLabel.value
= infoBoxExpanderLabel.getAttribute("lesslabel"); infoBoxExpanderLabel.accessKey = infoBoxExpanderLabel.getAttribute("lessaccesskey");
infoBoxExpander.className = "expander-up"; additionalInfoBroadcaster.removeAttribute("hidden");
} else { infoBox.setAttribute("minimal", "true"); infoBoxExpanderLabel.value = infoBoxExpanderLabel.getAttribute("morelabel");
infoBoxExpanderLabel.accessKey = infoBoxExpanderLabel.getAttribute("moreaccesskey"); infoBoxExpander.className = "expander-down";
additionalInfoBroadcaster.setAttribute("hidden", "true"); } }, /** * Save the current search
(or advanced query) to the bookmarks root. */ saveSearch: function PO_saveSearch()
{ // Get the place: uri for the query. // If the advanced query builder is showing,
use that. var options = this.getCurrentOptions(); //@line 833 "e:\builds\moz2_slave\win32_build\build\browser\components\places\content\places.js"
var queries = this.getCurrentQueries(); //@line 835 "e:\builds\moz2_slave\win32_build\build\browser\components\places\content\places.js"
var placeSpec = PlacesUtils.history.queriesToQueryString(queries, queries.length, options); var placeURI =
Cc["@mozilla.org/network/io-service;1"]. getService(Ci.nsIIOService). newURI(placeSpec, null, null); // Prompt the
user for a name for the query. // *** - using prompt service for now; will need to make
// a real dialog and localize when we're sure this is the UI we want. var title =
PlacesUIUtils.getString("saveSearch.title"); var inputLabel = PlacesUIUtils.getString("saveSearch.inputLabel");
var defaultText = PlacesUIUtils.getString("saveSearch.inputDefaultText"); var prompts = Cc["@mozilla.org/embedcomp/prompt-service;1"].
getService(Ci.nsIPromptService); var check = {value: false}; var input = {value: defaultText};
var save = prompts.prompt(null, title, inputLabel, input, null, check); // Don't add the query
if the user cancels or clears the seach name. if (!save || input.value == "") return; //
Add the place: uri as a bookmark under the bookmarks root. var txn = PlacesUIUtils.ptm.createItem(placeURI,
PlacesUtils.bookmarksMenuFolderId, PlacesUtils.bookmarks.DEFAULT_INDEX, input.value); PlacesUIUtils.ptm.doTransaction(txn);
// select and load the new query this._places.selectPlaceURI(placeSpec); * A set of utilities relating to search within
Bookmarks and History. var PlacesSearchBox = { /** * The Search text field */ get searchFilter()
{ return document.getElementById("searchFilter"); }, /** * Folders to include when searching.
*/ _folders: [], get folders() { if (this._folders.length == 0) this._folders.push(PlacesUtils.bookmarksMenuFolderId,
PlacesUtils.unfiledBookmarksFolderId, PlacesUtils.toolbarFolderId); return this._folders; }, set folders(aFolders)
{ this._folders = aFolders; return aFolders; }, /** * Run a search for the specified text,
over the collection specified by * the dropdown arrow. The default is all bookmarks, but can
be * localized to the active collection. * @param filterString * The text to search
for. */ search: function PSB_search(filterString) { var PO = PlacesOrganizer; // If the user
empties the search box manually, reset it and load all // contents of the current scope.
// *** this might be to jumpy, maybe should search for "", so results // are ungrouped,
and search box not reset if (filterString == "") { PO.onPlaceSelected(false); return;
} var currentOptions = PO.getCurrentOptions(); var content = PO._content; // Search according
to the current scope and folders, which were set by // PQB_setScope() switch (PlacesSearchBox.filterCollection)
{ case "collection": content.applyFilter(filterString, this.folders); // *** changing the button
text is badness //var scopeBtn = document.getElementById("scopeBarFolder"); //scopeBtn.label = PlacesOrganizer._places.selectedNode.title;
break; case "bookmarks": content.applyFilter(filterString, this.folders); break; case "history": if (currentOptions.queryType
!= Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY) { var query = PlacesUtils.history.getNewQuery();
query.searchTerms = filterString; var options = currentOptions.clone(); // Make sure we're
getting uri results. options.resultType = currentOptions.RESULT_TYPE_URI; options.queryType
= Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY; content.load([query], options); } else content.applyFilter(filterString);
break; default: throw "Invalid filterCollection on search"; break; } PlacesSearchBox.showSearchUI();
// Update the details panel PlacesOrganizer.onContentTreeSelect(); }, /** * Finds across all bookmarks */ findAll:
function PSB_findAll() { PlacesQueryBuilder.setScope("bookmarks"); this.focus(); }, /** * Finds in the currently
selected Place. */ findCurrent: function PSB_findCurrent() { PlacesQueryBuilder.setScope("collection");
this.focus(); }, /** * Updates the display with the title of the current collection.
* @param title * The title of the current collection. */ updateCollectionTitle: function
PSB_updateCollectionTitle(title) { if (title) this.searchFilter.emptyText = PlacesUIUtils.getFormattedString("searchCurrentDefault",
[title]); else this.searchFilter.emptyText = this.filterCollection == "history" ? PlacesUIUtils.getString("searchHistory")
: PlacesUIUtils.getString("searchBookmarks"); }, /** * Gets/sets the active collection
from the dropdown menu. */ get filterCollection() { return this.searchFilter.getAttribute("collection");
}, set filterCollection(collectionName) { if (collectionName == this.filterCollection)
return collectionName; this.searchFilter.setAttribute("collection", collectionName); var newGrayText = null; if
(collectionName == "collection") { newGrayText = PlacesOrganizer._places.selectedNode.title
|| document.getElementById("scopeBarFolder"). getAttribute("emptytitle"); } this.updateCollectionTitle(newGrayText);
return collectionName; }, /** * Focus the search box */ focus: function PSB_focus()
{ this.searchFilter.focus(); }, /** * Set up the gray text in the search bar as the
Places View loads. */ init: function PSB_init() { this.updateCollectionTitle(); }, /** *
Gets or sets the text shown in the Places Search Box */ get value() { return this.searchFilter.value;
}, set value(value) { return this.searchFilter.value = value; }, showSearchUI: function PSB_showSearchUI()
{ // Hide the advanced search controls when the user hasn't searched var searchModifiers
= document.getElementById("searchModifiers"); searchModifiers.hidden = false; //@line 1044
"e:\builds\moz2_slave\win32_build\build\browser\components\places\content\places.js" }, hideSearchUI: function PSB_hideSearchUI()
{ var searchModifiers = document.getElementById("searchModifiers"); searchModifiers.hidden = true; * Functions
and data for advanced query builder var PlacesQueryBuilder = { queries: [], queryOptions: null, //@line
1523 "e:\builds\moz2_slave\win32_build\build\browser\components\places\content\places.js" /** * Called when a scope button in the scope
bar is clicked. * @param aButton * the scope button that was selected */ onScopeSelected:
function PQB_onScopeSelected(aButton) { switch (aButton.id) { case "scopeBarHistory": this.setScope("history");
break; case "scopeBarFolder": this.setScope("collection"); break; case "scopeBarAll": this.setScope("bookmarks");
break; default: throw "Invalid search scope button ID"; break; } }, /** * Sets the search
scope. This can be called when no search is active, and * in that case, when the user
does begin a search aScope will be used (see * PSB_search()). If there is an active search,
it's performed again to * update the content tree. * @param aScope * the search scope,
"bookmarks", "collection", or "history" */ setScope: function PQB_setScope(aScope)
{ // Determine filterCollection, folders, and scopeButtonId based on aScope. var filterCollection;
var folders = []; var scopeButtonId; switch (aScope) { case "history": filterCollection
= "history"; scopeButtonId = "scopeBarHistory"; break; case "collection": // The folder scope
button can only become hidden upon selecting a new // folder in the left pane, and the
disabled state will remain unchanged // until a new folder is selected. See PO__setScopeForNode().
if (!document.getElementById("scopeBarFolder").hidden) { filterCollection = "collection"; scopeButtonId
= "scopeBarFolder"; folders.push(PlacesUtils.getConcreteItemId( PlacesOrganizer._places.selectedNode)); break;
} // Fall through. If collection scope doesn't make sense for the // selected node, choose
bookmarks scope. case "bookmarks": filterCollection = "bookmarks"; scopeButtonId = "scopeBarAll";
folders.push(PlacesUtils.bookmarksMenuFolderId, PlacesUtils.toolbarFolderId, PlacesUtils.unfiledBookmarksFolderId);
break; default: throw "Invalid search scope"; break; } // Check the appropriate scope button
in the scope bar. document.getElementById(scopeButtonId).checked = true; // Update the search box. Re-search
if there's an active search. PlacesSearchBox.filterCollection = filterCollection; PlacesSearchBox.folders
= folders; var searchStr = PlacesSearchBox.searchFilter.value; if (searchStr) PlacesSearchBox.search(searchStr);
* Population and commands for the View Menu. var ViewMenu = { /** * Removes content generated
previously from a menupopup. * @param popup * The popup that contains the previously
generated content. * @param startID * The id attribute of an element that is the start
of the * dynamically generated region - remove elements after this * item only. * Must be
contained by popup. Can be null (in which case the * contents of popup are removed).
* @param endID * The id attribute of an element that is the end of the * dynamically generated
region - remove elements up to this * item only. * Must be contained by popup. Can be
null (in which case all * items until the end of the popup will be removed). Ignored
* if startID is null. * @returns The element for the caller to insert new items before,
* null if the caller should just append to the popup. */ _clean: function VM__clean(popup,
startID, endID) { if (endID) NS_ASSERT(startID, "meaningless to have valid endID and null
startID"); if (startID) { var startElement = document.getElementById(startID); NS_ASSERT(startElement.parentNode
== popup, "startElement is not in popup"); NS_ASSERT(startElement, "startID does not
correspond to an existing element"); var endElement = null; if (endID) { endElement = document.getElementById(endID);
NS_ASSERT(endElement.parentNode == popup, "endElement is not in popup"); NS_ASSERT(endElement,
"endID does not correspond to an existing element"); } while (startElement.nextSibling
!= endElement) popup.removeChild(startElement.nextSibling); return endElement; } else { while(popup.hasChildNodes())
popup.removeChild(popup.firstChild); } return null; }, /** * Fills a menupopup with a list
of columns * @param event * The popupshowing event that invoked this function. * @param
startID * see _clean * @param endID * see _clean * @param type * the type of the menuitem,
e.g. "radio" or "checkbox". * Can be null (no-type). * Checkboxes are checked if the
column is visible. * @param propertyPrefix * If propertyPrefix is non-null: * propertyPrefix
+ column ID + ".label" will be used to get the * localized label string. * propertyPrefix
+ column ID + ".accesskey" will be used to get the * localized accesskey. * If propertyPrefix
is null, the column label is used as label and * no accesskey is assigned. */ fillWithColumns:
function VM_fillWithColumns(event, startID, endID, type, propertyPrefix) { var popup
= event.target; var pivot = this._clean(popup, startID, endID); // If no column is "sort-active",
the "Unsorted" item needs to be checked, // so track whether or not we find a column
that is sort-active. var isSorted = false; var content = document.getElementById("placeContent");
var columns = content.columns; for (var i = 0; i < columns.count; ++i) { var column
= columns.getColumnAt(i).element; var menuitem = document.createElement("menuitem"); menuitem.id
= "menucol_" + column.id; menuitem.column = column; var label = column.getAttribute("label");
if (propertyPrefix) { var menuitemPrefix = propertyPrefix; // for string properties,
use "name" as the id, instead of "title" // see bug #386287 for details var columnId
= column.getAttribute("anonid"); menuitemPrefix += columnId == "title" ? "name" : columnId;
label = PlacesUIUtils.getString(menuitemPrefix + ".label"); var accesskey = PlacesUIUtils.getString(menuitemPrefix
+ ".accesskey"); menuitem.setAttribute("accesskey", accesskey); } menuitem.setAttribute("label",
label); if (type == "radio") { menuitem.setAttribute("type", "radio"); menuitem.setAttribute("name", "columns");
// This column is the sort key. Its item is checked. if (column.getAttribute("sortDirection")
!= "") { menuitem.setAttribute("checked", "true"); isSorted = true; } } else if (type
== "checkbox") { menuitem.setAttribute("type", "checkbox"); // Cannot uncheck the primary
column. if (column.getAttribute("primary") == "true") menuitem.setAttribute("disabled",
"true"); // Items for visible columns are checked. if (!column.hidden) menuitem.setAttribute("checked",
"true"); } if (pivot) popup.insertBefore(menuitem, pivot); else popup.appendChild(menuitem);
} event.stopPropagation(); }, /** * Set up the content of the view menu. */ populateSortMenu:
function VM_populateSortMenu(event) { this.fillWithColumns(event, "viewUnsorted", "directionSeparator", "radio",
"view.sortBy."); var sortColumn = this._getSortColumn(); var viewSortAscending = document.getElementById("viewSortAscending");
var viewSortDescending = document.getElementById("viewSortDescending"); // We need to remove an existing checked
attribute because the unsorted // menu item is not rebuilt every time we open the menu
like the others. var viewUnsorted = document.getElementById("viewUnsorted"); if (!sortColumn) { viewSortAscending.removeAttribute("checked");
viewSortDescending.removeAttribute("checked"); viewUnsorted.setAttribute("checked", "true");
} else if (sortColumn.getAttribute("sortDirection") == "ascending") { viewSortAscending.setAttribute("checked",
"true"); viewSortDescending.removeAttribute("checked"); viewUnsorted.removeAttribute("checked");
} else if (sortColumn.getAttribute("sortDirection") == "descending") { viewSortDescending.setAttribute("checked",
"true"); viewSortAscending.removeAttribute("checked"); viewUnsorted.removeAttribute("checked");
} }, /** * Shows/Hides a tree column. * @param element * The menuitem element for the column
*/ showHideColumn: function VM_showHideColumn(element) { var column = element.column; var splitter
= column.nextSibling; if (splitter && splitter.localName != "splitter") splitter = null; if (element.getAttribute("checked")
== "true") { column.setAttribute("hidden", "false"); if (splitter) splitter.removeAttribute("hidden");
} else { column.setAttribute("hidden", "true"); if (splitter) splitter.setAttribute("hidden",
"true"); } }, /** * Gets the last column that was sorted. * @returns the currently sorted
column, null if there is no sorted column. */ _getSortColumn: function VM__getSortColumn()
{ var content = document.getElementById("placeContent"); var cols = content.columns; for (var i =
0; i < cols.count; ++i) { var column = cols.getColumnAt(i).element; var sortDirection = column.getAttribute("sortDirection");
if (sortDirection == "ascending" || sortDirection == "descending") return column; } return
null; }, /** * Sorts the view by the specified column. * @param aColumn * The colum that
is the sort key. Can be null - the * current sort column or the title column will be used.
* @param aDirection * The direction to sort - "ascending" or "descending". * Can be null
- the last direction or descending will be used. * * If both aColumnID and aDirection
are null, the view will be unsorted. */ setSortColumn: function VM_setSortColumn(aColumn, aDirection)
{ var result = document.getElementById("placeContent").getResult(); if (!aColumn && !aDirection) { result.sortingMode
= Ci.nsINavHistoryQueryOptions.SORT_BY_NONE; return; } var columnId; if (aColumn) { columnId
= aColumn.getAttribute("anonid"); if (!aDirection) { var sortColumn = this._getSortColumn();
if (sortColumn) aDirection = sortColumn.getAttribute("sortDirection"); } } else { var sortColumn = this._getSortColumn();
columnId = sortColumn ? sortColumn.getAttribute("anonid") : "title"; } // This maps the possible values
of columnId (i.e., anonid's of treecols in // placeContent) to the default sortingMode
and sortingAnnotation values for // each column. // key: Sort key in the name of one of the
// nsINavHistoryQueryOptions.SORT_BY_* constants // dir: Default sort direction to use if
none has been specified // anno: The annotation to sort by, if key is "ANNOTATION" var colLookupTable
= { title: { key: "TITLE", dir: "ascending" }, tags: { key: "TAGS", dir: "ascending"
}, url: { key: "URI", dir: "ascending" }, date: { key: "DATE", dir: "descending" },
visitCount: { key: "VISITCOUNT", dir: "descending" }, keyword: { key: "KEYWORD", dir: "ascending"
}, dateAdded: { key: "DATEADDED", dir: "descending" }, lastModified: { key: "LASTMODIFIED", dir:
"descending" }, description: { key: "ANNOTATION", dir: "ascending", anno: DESCRIPTION_ANNO
} }; // Make sure we have a valid column. if (!colLookupTable.hasOwnProperty(columnId))
throw("Invalid column"); // Use a default sort direction if none has been specified.
If aDirection // is invalid, result.sortingMode will be undefined, which has the effect //
of unsorting the tree. aDirection = (aDirection || colLookupTable[columnId].dir).toUpperCase();
var sortConst = "SORT_BY_" + colLookupTable[columnId].key + "_" + aDirection; result.sortingAnnotation
= colLookupTable[columnId].anno || ""; result.sortingMode = Ci.nsINavHistoryQueryOptions[sortConst];
content/browser/places/places.xml
content/browser/places/places.csstree[type="places"]
{ -moz-binding: url("chrome://browser/content/places/tree.xml#places-tree"); hbox[type="places"] { -moz-binding: url("chrome://browser/content/places/toolbar.xml#places-bar");
.bookmarks-toolbar-customize, toolbarpaletteitem .bookmarks-toolbar-items { display: none;
toolbarpaletteitem .bookmarks-toolbar-customize { display: -moz-box; .toolbar-drop-indicator
{ position: relative; z-index: 1; menupopup[type="places"] { -moz-binding: url("chrome://browser/content/places/menu.xml#places-menupopup");
menupopup[placespopup="true"] { -moz-binding: url("chrome://browser/content/places/menu.xml#places-popup-base");
content/browser/places/organizer.css .history-calendar { -moz-binding: url("chrome://browser/content/places/places.xml#calendar");
button.commandButton { -moz-binding: url("chrome://browser/content/places/places.xml#command-button"); .filterList { -moz-binding: url("chrome://browser/content/places/places.xml#filter-button");
#contentTitle { width: 0px; #searchFilter { width: 23em; content/browser/places/bookmarkProperties.xul
content/browser/places/bookmarkProperties.js/* -*- Mode: C++; tab-width: 8; indent-tabs-mode:
nil; c-basic-offset: 2 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL
2.0/LGPL 2.1 * The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with * the License.
You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * Software distributed
under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND,
either express or implied. See the License * for the specific language governing rights
and limitations under the * License. * The Original Code is the Places Bookmark Properties
dialog. * 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): * Joe Hughes * Dietrich Ayala
* Asaf Romano * Marco Bonardo * 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 ***** */ * The panel is initialized based on data given in the js object passed
* as window.arguments[0]. The object must have the following fields set: * @ action
(String). Possible values: * - "add" - for adding a new item. * @ type (String). Possible
values: * - "bookmark" * @ loadBookmarkInSidebar - optional, the default state for the *
"Load this bookmark in the sidebar" field. * - "folder" * @ URIList (Array of nsIURI
objects) - optional, list of uris to * be bookmarked under the new folder. * - "livemark"
* @ uri (nsIURI object) - optional, the default uri for the new item. * The property is not
used for the "folder with items" type. * @ title (String) - optional, the default title
for the new item. * @ description (String) - optional, the default description for the
new * item. * @ defaultInsertionPoint (InsertionPoint JS object) - optional, the * default insertion
point for the new item. * @ keyword (String) - optional, the default keyword for the new
item. * @ postData (String) - optional, POST data to accompany the keyword. * @ charSet
(String) - optional, character-set to accompany the keyword. * Notes: * 1) If |uri| is set
for a bookmark/livemark item and |title| isn't, * the dialog will query the history tables
for the title associated * with the given uri. If the dialog is set to adding a folder
with * bookmark items under it (see URIList), a default static title is * used ("[Folder
Name]"). * 2) The index field of the default insertion point is ignored if * the folder
picker is shown. * - "edit" - for editing a bookmark item or a folder. * @ type (String).
Possible values: * - "bookmark" * @ itemId (Integer) - the id of the bookmark item.
* - "folder" (also applies to livemarks) * @ itemId (Integer) - the id of the folder.
* @ hiddenRows (Strings array) - optional, list of rows to be hidden * regardless of
the item edited or added by the dialog. * Possible values: * - "title" * - "location"
* - "description" * - "keyword" * - "tags" * - "loadInSidebar" * - "feedLocation" *
- "siteLocation" * - "folderPicker" - hides both the tree and the menu. * @ readOnly (Boolean)
- optional, states if the panel should be read-only * window.arguments[0].performed
is set to true if any transaction has * been performed by the dialog. const BOOKMARK_ITEM
= 0; const BOOKMARK_FOLDER = 1; const LIVEMARK_CONTAINER = 2; const ACTION_EDIT = 0; const ACTION_ADD
= 1; var BookmarkPropertiesPanel = { /** UI Text Strings */ __strings: null, get _strings()
{ if (!this.__strings) { this.__strings = document.getElementById("stringBundle");
} return this.__strings; }, _action: null, _itemType: null, _itemId: -1, _uri: null,
_loadInSidebar: false, _title: "", _description: "", _URIs: [], _keyword: "", _postData: null,
_charSet: "", _feedURI: null, _siteURI: null, _defaultInsertionPoint: null, _hiddenRows:
[], _batching: false, _readOnly: false, /** * This method returns the correct label
for the dialog's "accept" * button based on the variant of the dialog. */ _getAcceptLabel:
function BPP__getAcceptLabel() { if (this._action == ACTION_ADD) { if (this._URIs.length) return
this._strings.getString("dialogAcceptLabelAddMulti"); if (this._itemType == LIVEMARK_CONTAINER)
return this._strings.getString("dialogAcceptLabelAddLivemark"); if (this._dummyItem || this._loadInSidebar)
return this._strings.getString("dialogAcceptLabelAddItem"); return this._strings.getString("dialogAcceptLabelSaveItem");
} return this._strings.getString("dialogAcceptLabelEdit"); }, /** * This method returns the correct
title for the current variant * of this dialog. */ _getDialogTitle: function BPP__getDialogTitle()
{ if (this._action == ACTION_ADD) { if (this._itemType == BOOKMARK_ITEM) return this._strings.getString("dialogTitleAddBookmark");
if (this._itemType == LIVEMARK_CONTAINER) return this._strings.getString("dialogTitleAddLivemark");
// add folder NS_ASSERT(this._itemType == BOOKMARK_FOLDER, "Unknown item type"); if
(this._URIs.length) return this._strings.getString("dialogTitleAddMulti"); return this._strings.getString("dialogTitleAddFolder");
} if (this._action == ACTION_EDIT) { return this._strings.getFormattedString("dialogTitleEdit",
[this._title]); } return ""; }, /** * Determines the initial data for the item edited or added
by this dialog */ _determineItemInfo: function BPP__determineItemInfo() { var dialogInfo
= window.arguments[0]; this._action = dialogInfo.action == "add" ? ACTION_ADD : ACTION_EDIT; this._hiddenRows
= dialogInfo.hiddenRows ? dialogInfo.hiddenRows : []; if (this._action == ACTION_ADD) {
NS_ASSERT("type" in dialogInfo, "missing type property for add action"); if ("title" in
dialogInfo) this._title = dialogInfo.title; if ("defaultInsertionPoint" in dialogInfo)
{ this._defaultInsertionPoint = dialogInfo.defaultInsertionPoint; } else this._defaultInsertionPoint = new
InsertionPoint(PlacesUtils.bookmarksMenuFolderId, PlacesUtils.bookmarks.DEFAULT_INDEX, Ci.nsITreeView.DROP_ON);
switch(dialogInfo.type) { case "bookmark": this._itemType = BOOKMARK_ITEM; if ("uri"
in dialogInfo) { NS_ASSERT(dialogInfo.uri instanceof Ci.nsIURI, "uri property should
be a uri object"); this._uri = dialogInfo.uri; if (typeof(this._title) != "string") { this._title
= this._getURITitleFromHistory(this._uri) || this._uri.spec; } } else { this._uri
= PlacesUtils._uri("about:blank"); this._title = this._strings.getString("newBookmarkDefault");
this._dummyItem = true; } if ("loadBookmarkInSidebar" in dialogInfo) this._loadInSidebar = dialogInfo.loadBookmarkInSidebar;
if ("keyword" in dialogInfo) { this._keyword = dialogInfo.keyword; this._isAddKeywordDialog
= true; if ("postData" in dialogInfo) this._postData = dialogInfo.postData; if ("charSet" in dialogInfo)
this._charSet = dialogInfo.charSet; } break; case "folder": this._itemType = BOOKMARK_FOLDER;
if (!this._title) { if ("URIList" in dialogInfo) { this._title = this._strings.getString("bookmarkAllTabsDefault");
this._URIs = dialogInfo.URIList; } else this._title = this._strings.getString("newFolderDefault");
this._dummyItem = true; } break; case "livemark": this._itemType = LIVEMARK_CONTAINER; if ("feedURI"
in dialogInfo) this._feedURI = dialogInfo.feedURI; if ("siteURI" in dialogInfo) this._siteURI
= dialogInfo.siteURI; if (!this._title) { if (this._feedURI) { this._title = this._getURITitleFromHistory(this._feedURI)
|| this._feedURI.spec; } else this._title = this._strings.getString("newLivemarkDefault");
} } if ("description" in dialogInfo) this._description = dialogInfo.description; } else { // edit
NS_ASSERT("itemId" in dialogInfo); this._itemId = dialogInfo.itemId; this._title = PlacesUtils.bookmarks.getItemTitle(this._itemId);
// Don't show folderPicker when editing this._hiddenRows.push("folderPicker"); this._readOnly = !!dialogInfo.readOnly; switch
(dialogInfo.type) { case "bookmark": this._itemType = BOOKMARK_ITEM; this._uri = PlacesUtils.bookmarks.getBookmarkURI(this._itemId);
// keyword this._keyword = PlacesUtils.bookmarks .getKeywordForBookmark(this._itemId); //
Load In Sidebar this._loadInSidebar = PlacesUtils.annotations .itemHasAnnotation(this._itemId, LOAD_IN_SIDEBAR_ANNO);
break; case "folder": if (PlacesUtils.itemIsLivemark(this._itemId)) { this._itemType = LIVEMARK_CONTAINER; this._feedURI
= PlacesUtils.livemarks.getFeedURI(this._itemId); this._siteURI = PlacesUtils.livemarks.getSiteURI(this._itemId);
} else this._itemType = BOOKMARK_FOLDER; break; } // Description if (PlacesUtils.annotations
.itemHasAnnotation(this._itemId, DESCRIPTION_ANNO)) { this._description = PlacesUtils.annotations
.getItemAnnotation(this._itemId, DESCRIPTION_ANNO); } } }, /** * This method returns the title
string corresponding to a given URI. * If none is available from the bookmark service
(probably because * the given URI doesn't appear in bookmarks or history), we synthesize
* a title from the first 100 characters of the URI. * * @param aURI * nsIURI object for
which we want the title * * @returns a title string */ _getURITitleFromHistory: function
BPP__getURITitleFromHistory(aURI) { NS_ASSERT(aURI instanceof Ci.nsIURI); // get the title from
History return PlacesUtils.history.getPageTitle(aURI); }, /** * This method should be called by
the onload of the Bookmark Properties * dialog to initialize the state of the panel. */
onDialogLoad: function BPP_onDialogLoad() { this._determineItemInfo(); document.title
= this._getDialogTitle(); var acceptButton = document.documentElement.getButton("accept");
acceptButton.label = this._getAcceptLabel(); this._beginBatch(); switch (this._action)
{ case ACTION_EDIT: this._fillEditProperties(); acceptButton.disabled = this._readOnly; break;
case ACTION_ADD: this._fillAddProperties(); // if this is an uri related dialog disable
accept button until // the user fills an uri value. if (this._itemType == BOOKMARK_ITEM
|| this._itemType == LIVEMARK_CONTAINER) acceptButton.disabled = !this._inputIsValid();
break; } // When collapsible elements change their collapsed attribute we must // resize
the dialog. // sizeToContent is not usable due to bug 90276, so we'll use resizeTo //
instead and cache the element size. See WSucks in the legacy // UI code (addBookmark2.js).
if (!this._element("tagsRow").collapsed) { this._element("tagsSelectorRow") .addEventListener("DOMAttrModified",
this, false); } if (!this._element("folderRow").collapsed) { this._element("folderTreeRow") .addEventListener("DOMAttrModified",
this, false); } if (!this._readOnly) { // Listen on uri fields to enable accept button
if input is valid if (this._itemType == BOOKMARK_ITEM) { this._element("locationField") .addEventListener("input",
this, false); if (this._isAddKeywordDialog) { this._element("keywordField") .addEventListener("input",
this, false); } } else if (this._itemType == LIVEMARK_CONTAINER) { this._element("feedLocationField")
.addEventListener("input", this, false); this._element("siteLocationField") .addEventListener("input", this, false);
} } window.sizeToContent(); }, // nsIDOMEventListener _elementsHeight: [], handleEvent: function
BPP_handleEvent(aEvent) { var target = aEvent.target; switch (aEvent.type) { case "input": if (target.id
== "editBMPanel_locationField" || target.id == "editBMPanel_feedLocationField" || target.id
== "editBMPanel_siteLocationField" || target.id == "editBMPanel_keywordField") { // Check
uri fields to enable accept button if input is valid document.documentElement .getButton("accept").disabled
= !this._inputIsValid(); } break; case "DOMAttrModified": // this is called when collapsing a node,
but also its direct children, // we only need to resize when the original node changes.
if ((target.id == "editBMPanel_tagsSelectorRow" || target.id == "editBMPanel_folderTreeRow")
&& aEvent.attrName == "collapsed" && target == aEvent.originalTarget) { var id = target.id;
var newHeight = window.outerHeight; if (aEvent.newValue) // is collapsed newHeight -= this._elementsHeight[id];
else { this._elementsHeight[id] = target.boxObject.height; newHeight += this._elementsHeight[id]; }
window.resizeTo(window.outerWidth, newHeight); } break; } }, _beginBatch: function BPP__beginBatch()
{ if (this._batching) return; PlacesUIUtils.ptm.beginBatch(); this._batching = true; }, _endBatch: function
BPP__endBatch() { if (!this._batching) return; PlacesUIUtils.ptm.endBatch(); this._batching
= false; }, _fillEditProperties: function BPP__fillEditProperties() { gEditItemOverlay.initPanel(this._itemId,
{ hiddenRows: this._hiddenRows, forceReadOnly: this._readOnly }); }, _fillAddProperties:
function BPP__fillAddProperties() { this._createNewItem(); // Edit the new item gEditItemOverlay.initPanel(this._itemId,
{ hiddenRows: this._hiddenRows }); // Empty location field if the uri is about:blank,
this way inserting a new // url will be easier for the user, Accept button will be automatically
// disabled by the input listener until the user fills the field. var locationField =
this._element("locationField"); if (locationField.value == "about:blank") locationField.value =
""; }, // nsISupports QueryInterface: function BPP_QueryInterface(aIID) { if (aIID.equals(Ci.nsIDOMEventListener)
|| aIID.equals(Ci.nsISupports)) return this; throw Cr.NS_NOINTERFACE; }, _element: function
BPP__element(aID) { return document.getElementById("editBMPanel_" + aID); }, onDialogUnload: function BPP_onDialogUnload()
{ // gEditItemOverlay does not exist anymore here, so don't rely on it. // Calling removeEventListener
with arguments which do not identify any // currently registered EventListener on the
EventTarget has no effect. this._element("tagsSelectorRow") .removeEventListener("DOMAttrModified", this,
false); this._element("folderTreeRow") .removeEventListener("DOMAttrModified", this, false); this._element("locationField")
.removeEventListener("input", this, false); this._element("feedLocationField") .removeEventListener("input",
this, false); this._element("siteLocationField") .removeEventListener("input", this, false);
}, onDialogAccept: function BPP_onDialogAccept() { // We must blur current focused element
to save its changes correctly document.commandDispatcher.focusedElement.blur(); // The order here is important! We have to
uninit the panel first, otherwise // late changes could force it to commit more transactions.
gEditItemOverlay.uninitPanel(true); gEditItemOverlay = null; this._endBatch(); window.arguments[0].performed
= true; }, onDialogCancel: function BPP_onDialogCancel() { // The order here is important! We have
to uninit the panel first, otherwise // changes done as part of Undo may change the panel
contents and by // that force it to commit more transactions. gEditItemOverlay.uninitPanel(true);
gEditItemOverlay = null; this._endBatch(); PlacesUIUtils.ptm.undoTransaction(); window.arguments[0].performed
= false; }, /** * This method checks to see if the input fields are in a valid state.
* * @returns true if the input is valid, false otherwise */ _inputIsValid: function
BPP__inputIsValid() { if (this._itemType == BOOKMARK_ITEM && !this._containsValidURI("locationField"))
return false; if (this._isAddKeywordDialog && !this._element("keywordField").value.length)
return false; // Feed Location has to be a valid URI; // Site Location has to be a valid
URI or empty if (this._itemType == LIVEMARK_CONTAINER) { if (!this._containsValidURI("feedLocationField"))
return false; if (!this._containsValidURI("siteLocationField") && (this._element("siteLocationField").value.length
> 0)) return false; } return true; }, /** * Determines whether the XUL textbox with
the given ID contains a * string that can be converted into an nsIURI. * * @param aTextboxID
* the ID of the textbox element whose contents we'll test * * @returns true if the textbox
contains a valid URI string, false otherwise */ _containsValidURI: function BPP__containsValidURI(aTextboxID)
{ try { var value = this._element(aTextboxID).value; if (value) { var uri = PlacesUIUtils.createFixedURI(value);
return true; } } catch (e) { } return false; }, /** * [New Item Mode] Get the insertion
point details for the new item, given * dialog state and opening arguments. * * The container-identifier
and insertion-index are returned separately in * the form of [containerIdentifier, insertionIndex]
*/ _getInsertionPointDetails: function BPP__getInsertionPointDetails() { var containerId = this._defaultInsertionPoint.itemId;
var indexInContainer = this._defaultInsertionPoint.index; return [containerId, indexInContainer]; },
/** * Returns a transaction for creating a new bookmark item representing the * various
fields and opening arguments of the dialog. */ _getCreateNewBookmarkTransaction: function
BPP__getCreateNewBookmarkTransaction(aContainer, aIndex) { var annotations = []; var childTransactions
= []; if (this._description) { childTransactions.push( PlacesUIUtils.ptm.editItemDescription(-1,
this._description)); } if (this._loadInSidebar) { childTransactions.push( PlacesUIUtils.ptm.setLoadInSidebar(-1,
this._loadInSidebar)); } if (this._postData) { childTransactions.push( PlacesUIUtils.ptm.editBookmarkPostData(-1,
this._postData)); } //*** TODO: this should be in a transaction! if (this._charSet) PlacesUtils.history.setCharsetForURI(this._uri,
this._charSet); var transactions = [PlacesUIUtils.ptm.createItem(this._uri, aContainer, aIndex, this._title, this._keyword,
annotations, childTransactions)]; return PlacesUIUtils.ptm.aggregateTransactions(this._getDialogTitle(), transactions); }, /** * Returns a childItems-transactions
array representing the URIList with * which the dialog has been opened. */ _getTransactionsForURIList:
function BPP__getTransactionsForURIList() { var transactions = []; for (var i = 0;
i < this._URIs.length; ++i) { var uri = this._URIs[i]; var title = this._getURITitleFromHistory(uri);
transactions.push(PlacesUIUtils.ptm.createItem(uri, -1, -1, title)); } return transactions; },
/** * Returns a transaction for creating a new folder item representing the * various
fields and opening arguments of the dialog. */ _getCreateNewFolderTransaction: function
BPP__getCreateNewFolderTransaction(aContainer, aIndex) { var annotations = []; var childItemsTransactions;
if (this._URIs.length) childItemsTransactions = this._getTransactionsForURIList(); if (this._description)
annotations.push(this._getDescriptionAnnotation(this._description)); return PlacesUIUtils.ptm.createFolder(this._title,
aContainer, aIndex, annotations, childItemsTransactions); }, /** * Returns a transaction for creating
a new live-bookmark item representing * the various fields and opening arguments of the
dialog. */ _getCreateNewLivemarkTransaction: function BPP__getCreateNewLivemarkTransaction(aContainer,
aIndex) { return PlacesUIUtils.ptm.createLivemark(this._feedURI, this._siteURI, this._title, aContainer, aIndex);
}, /** * Dialog-accept code-path for creating a new item (any type) */ _createNewItem: function
BPP__getCreateItemTransaction() { var [container, index] = this._getInsertionPointDetails();
var txn; switch (this._itemType) { case BOOKMARK_FOLDER: txn = this._getCreateNewFolderTransaction(container,
index); break; case LIVEMARK_CONTAINER: txn = this._getCreateNewLivemarkTransaction(container,
index); break; default: // BOOKMARK_ITEM txn = this._getCreateNewBookmarkTransaction(container,
index); } PlacesUIUtils.ptm.doTransaction(txn); this._itemId = PlacesUtils.bookmarks.getIdForItemAt(container,
index); content/browser/places/placesOverlay.xul %editMenuOverlayDTD;
content/browser/places/toolbar.xml
document.getAnonymousElementByAttribute(this, "class", "bookmarks-toolbar-items")
document.getAnonymousElementByAttribute(this, "class", "toolbar-drop-indicator")
document.getAnonymousElementByAttribute(this, "class", "chevron")
document.getAnonymousElementByAttribute(this, "anonid", "chevronPopup") null true document.defaultView.getComputedStyle(this.parentNode, "") .direction == "rtl"
scrollRect.right); } child.style.visibility
= childOverflowed ? "hidden" : "visible"; } // We rebuild the chevron on popupShowing,
so if it is open // we must update it. if (this._chevron.open) this._updateChevronPopupNodesVisibility();
]]>
element for the container, // we need
the . var popup = parentElt.firstChild; // Move the node. popup.removeChild(nodeElt);
popup.insertBefore(nodeElt, popup.childNodes[aNewIndex]); } }, nodeTitleChanged: function TV_V_nodeTitleChanged(aNode,
aNewTitle) { let nodeElt = aNode._DOMElement; NS_ASSERT(nodeElt, "node must have _DOMElement
set"); // There's no UI representation for the root node, thus there's // nothing to
be done when the title changes. if (nodeElt == this._self) return; if (nodeElt.parentNode
== this._self) { // Node is on the toolbar nodeElt.label = aNewTitle; this._self.updateChevron();
} else { // Node is within a built menu. nodeElt.label = aNewTitle || PlacesUIUtils.getBestTitle(aNode);
} }, nodeURIChanged: function TV_V_nodeURIChanged(aNode, aURIString) { let nodeElt = aNode._DOMElement;
NS_ASSERT(nodeElt, "node must have _DOMElement set"); nodeElt.setAttribute("scheme", PlacesUIUtils.guessUrlSchemeForUI(aURIString));
}, nodeIconChanged: function TV_V_nodeIconChanged(aNode) { let nodeElt = aNode._DOMElement; NS_ASSERT(nodeElt,
"node must have _DOMElement set"); // There's no UI representation for the root node, thus
there's // nothing to be done when the icon changes. if (nodeElt == this._self) return;
let icon = aNode.icon; if (icon) { if (nodeElt.getAttribute("image") != icon) nodeElt.setAttribute("image", icon);
} else nodeElt.removeAttribute("image"); }, nodeAnnotationChanged: function TV_V_nodeAnnotationChanged(aNode,
aAnno) { // Ensure the changed annotation is a livemark one. if (/^livemark\//.test(aAnno)
&& PlacesUtils.nodeIsLivemarkContainer(aNode)) { let nodeElt = aNode._DOMElement; NS_ASSERT(nodeElt,
"node must have _DOMElement set"); if (!nodeElt.hasAttribute("livemark")) nodeElt.setAttribute("livemark", "true");
// Add or remove the livemark status menuitem. PlacesUIUtils.ensureLivemarkStatusMenuItem(nodeElt.firstChild);
} }, nodeHistoryDetailsChanged: function() { }, nodeTagsChanged: function() { }, nodeDateAddedChanged:
function() { }, nodeLastModifiedChanged: function() { }, nodeKeywordChanged: function() { },
nodeReplaced: function TV_V_nodeReplaced(aParentNode, aOldNode, aNewNode, aIndex) { let nodeElt
= aOldNode._DOMElement; NS_ASSERT(nodeElt, "node must have _DOMElement set"); // No worries:
If nodeElt is the last item (i.e. no nextSibling), // insertNewItem/insertNewItemToPopup will
insert the new element as // the last item. let next = nodeElt.nextSibling; let parentElt
= aParentNode._DOMElement; NS_ASSERT(parentElt, "parent node must have _DOMElement set");
if (parentElt == this._self) { // Node is on the toolbar. this._self.removeItem(nodeElt);
this._self.insertNewItem(aNewNode, next); this._self.updateChevron(); } else if (parentElt._built)
{ // Node is within a built menu. let popup = parentElt.firstChild; popup.removeItem(nodeElt);
this._self.insertNewItemToPopup(aNewNode, popup, next); } }, containerOpened: function
TV_V_containerOpened(aContainer) { this.invalidateContainer(aContainer); }, containerClosed: function TV_V_containerClosed(aContainer)
{ this.invalidateContainer(aContainer); }, invalidateContainer: function TV_V_invalidateContainer(aContainer)
{ let containerNodeElt = aContainer._DOMElement; NS_ASSERT(containerNodeElt, "node must have
_DOMElement set"); if (containerNodeElt == this._self) { // Container is the toolbar
itself. this._self._rebuild(); } else if (containerNodeElt._built) { // Container is a built menu. containerNodeElt._built
= false; // If the menupopup is open we should live-update it. if (containerNodeElt.open)
this._self._rebuildPopup(containerNodeElt.firstChild); } }, sortingChanged: function TV_V_sortingChanged(aSortingMode)
{ } })]]>
0) { if (aPopup._emptyMenuItem)
aPopup._emptyMenuItem.hidden = true; for (let i = 0; i < cc; ++i) { var child = resultNode.getChild(i);
this.insertNewItemToPopup(child, aPopup, null); } } else { // This menu is empty. If there
is no static content, add // an element to show it is empty. if (aPopup._startMarker
== -1 && aPopup._endMarker == -1) this._showEmptyMenuItem(aPopup); } aPopup.parentNode._built = true; ]]>
nodeRect.right - threshold) : (aEvent.clientX < nodeRect.left
+ threshold)) { // Drop before this folder. dropPoint.ip = new InsertionPoint(PlacesUtils.getConcreteItemId(this._resultNode),
nodeIndex, Ci.nsITreeView.DROP_BEFORE); dropPoint.beforeIndex = nodeIndex; } else if (this._isRTL ? (aEvent.clientX
> nodeRect.left + threshold) : (aEvent.clientX < nodeRect.right - threshold)) { // Drop
inside this folder. dropPoint.ip = new InsertionPoint(PlacesUtils.getConcreteItemId(xulNode.node), -1, Ci.nsITreeView.DROP_ON, PlacesUtils.nodeIsTagQuery(xulNode.node));
dropPoint.beforeIndex = nodeIndex; dropPoint.folderNode = xulNode; } else { // Drop after this folder.
let beforeIndex = (nodeIndex == this.childNodes.length - 1) ? -1 : nodeIndex + 1; dropPoint.ip
= new InsertionPoint(PlacesUtils.getConcreteItemId(this._resultNode), beforeIndex, Ci.nsITreeView.DROP_BEFORE);
dropPoint.beforeIndex = beforeIndex; } } else { // This is a non-folder node or a read-only
folder. // Drop before it with regards to RTL mode. let threshold = nodeRect.width
* 0.5; if (this._isRTL ? (aEvent.clientX > nodeRect.left + threshold) : (aEvent.clientX
< nodeRect.left + threshold)) { // Drop before this bookmark. dropPoint.ip = new InsertionPoint(PlacesUtils.getConcreteItemId(this._resultNode),
nodeIndex, Ci.nsITreeView.DROP_BEFORE); dropPoint.beforeIndex = nodeIndex; } else { // Drop after this
bookmark. let beforeIndex = nodeIndex == this.childNodes.length - 1 ? -1 : nodeIndex
+ 1; dropPoint.ip = new InsertionPoint(PlacesUtils.getConcreteItemId(this._resultNode), beforeIndex, Ci.nsITreeView.DROP_BEFORE);
dropPoint.beforeIndex = beforeIndex; } } } else { // We are most likely dragging on
the empty area of the // toolbar, we should drop after the last node. dropPoint.ip =
new InsertionPoint(PlacesUtils.getConcreteItemId(this._resultNode), -1, Ci.nsITreeView.DROP_BEFORE); dropPoint.beforeIndex
= -1; } return dropPoint; ]]>
= Math.abs(translateX/2)) { // Don't start the drag event.preventDefault();
// Open the menu draggedDOMNode.open = true; return; } // if the menu is open, close it
if (draggedDOMNode.open) { draggedDOMNode.firstChild.hidePopup(); draggedDOMNode.open = false; } } // activate
the view and cache the dragged node this._draggedNode = draggedDOMNode.node; this.focus(); this._controller.setDataTransfer(event);
event.stopPropagation(); ]]>
content/browser/places/menu.xml
document.getAnonymousElementByAttribute(this,
"class", "menupopup-drop-indicator-bar"); document.getAnonymousElementByAttribute(this,
"class", "popup-internal-box"); -1 -1 PlacesUIUtils.getViewForNode(this);
node.boxObject.screenY + node.boxObject.height / 2) node = node.nextSibling;
newMarginTop = node ? node.boxObject.screenY - sbo.screenY : sbo.height; } else if (scrollDir
== 1) newMarginTop = sbo.height; // set the new marginTop based on arrowscrollbox newMarginTop
+= sbo.y - this._scrollBox.boxObject.y; this._indicatorBar.firstChild.style.marginTop = newMarginTop + "px"; this._indicatorBar.hidden
= false; aEvent.stopPropagation(); ]]>
= this.childNodes[this._endMarker].boxObject.y)
betweenMarkers = false; // hide the dropmarker if current node is not a places bookmark item
return !(target && target.node && betweenMarkers && this.canDrop(aEvent)); ]]>
false
null null
0) { if (aPopup._emptyMenuItem) aPopup._emptyMenuItem.hidden = true; for (var i = 0; i < cc; ++i) { var
child = aPopup._resultNode.getChild(i); this.insertNewItem(child, aPopup, null); } } else { // This menu is
empty. If there is no static content, add // an element to show it is empty. if (aPopup._startMarker
== -1 && aPopup._endMarker == -1) this._showEmptyMenuItem(aPopup); } aPopup.parentNode._built = true; ]]>
element
for the container, // we need the let popup = parentElt.firstChild; let index
= popup._startMarker + 1 + aIndex; this._self.insertNewItem(aNode, popup, popup.childNodes[index]); if (popup._emptyMenuItem)
popup._emptyMenuItem.hidden = true; }, nodeRemoved: function PMV_nodeRemoved(aParentNode, aNode,
aIndex) { let parentElt = aParentNode._DOMElement; NS_ASSERT(parentElt, "parent node must have
_DOMElement set"); if (!parentElt._built) return; // parentElt is the element
for the container, // we need the let popup = parentElt.firstChild; let nodeElt
= aNode._DOMElement; NS_ASSERT(nodeElt, "node must have _DOMElement set"); popup.removeChild(nodeElt);
// Figure out if we need to show the "" menu-item. // TODO Bug 517701: This doesn't
seem to handle the case of an empty // root (parentElt == this._self.parentNode). if (!popup.hasChildNodes()
|| (popup.childNodes.length == 1 && popup.firstChild == popup._emptyMenuItem)) this._self._showEmptyMenuItem(popup);
if (popup._endMarker != -1) popup._endMarker--; }, nodeMoved: function PMV_nodeMoved(aNode,
aOldParent, aOldIndex, aNewParent, aNewIndex) { // Note: the current implementation of
moveItem does not actually // use this notification when the item in question is moved from one
// folder to another. Instead, it calls nodeRemoved and nodeInserted // for the two folders. Thus,
we can assume aOldParent == aNewParent. let nodeElt = aNode._DOMElement; NS_ASSERT(nodeElt,
"node must have _DOMElement set"); // If our root node is a folder, it might be moved.
There's nothing // we need to do in that case. if (nodeElt == this._self.parentNode) return;
// Move the node. let popup = nodeElt.parentNode; let index = popup._startMarker + 1 + aNewIndex;
popup.removeChild(nodeElt); popup.insertBefore(nodeElt, popup.childNodes[index]); }, nodeTitleChanged:
function PMV__nodeTitleChanged(aNode, aNewTitle) { let nodeElt = aNode._DOMElement; NS_ASSERT(nodeElt,
"node must have _DOMElement set"); // There's no UI representation for the root node, thus
there's // nothing to be done when the title changes. if (nodeElt == this._self.parentNode)
return; nodeElt.label = aNewTitle || PlacesUIUtils.getBestTitle(aNode); }, nodeURIChanged: function PMV_nodeURIChanged(aNode,
aURIString) { let nodeElt = aNode._DOMElement; NS_ASSERT(nodeElt, "node must have _DOMElement
set"); nodeElt.setAttribute("scheme", PlacesUIUtils.guessUrlSchemeForUI(aURIString)); }, nodeIconChanged: function PMV_nodeIconChanged(aNode)
{ let nodeElt = aNode._DOMElement; NS_ASSERT(nodeElt, "node must have _DOMElement set"); // There's
no UI representation for the root node, thus there's // nothing to be done when the icon
changes. if (nodeElt == this._self.parentNode) return; var icon = aNode.icon; if (icon)
{ if (nodeElt.getAttribute("image") != icon) nodeElt.setAttribute("image", icon); } else
nodeElt.removeAttribute("image"); }, nodeAnnotationChanged: function PMV_nodeAnnotationChanged(aNode,
aAnno) { // Ensure the changed annotation is a livemark one. if (/^livemark\//.test(aAnno)
&& PlacesUtils.nodeIsLivemarkContainer(aNode)) { let nodeElt = aNode._DOMElement; NS_ASSERT(nodeElt,
"node must have _DOMElement set"); if (!nodeElt.hasAttribute("livemark")) nodeElt.setAttribute("livemark", "true");
// Add or remove the livemark status menuitem. PlacesUIUtils.ensureLivemarkStatusMenuItem(nodeElt.firstChild);
} }, nodeHistoryDetailsChanged: function() { }, nodeTagsChanged: function() { }, nodeDateAddedChanged:
function() { }, nodeLastModifiedChanged: function() { }, nodeKeywordChanged: function() { },
nodeReplaced: function PMV_nodeReplaced(aParentNode, aOldNode, aNewNode, aIndex) { let parentElt
= aParentNode._DOMElement; NS_ASSERT(parentElt, "parent node must have _DOMElement set");
if (!parentElt._built) return; // parentElt is the element for the container,
// we need the . let popup = parentElt.firstChild; let nodeElt = aOldNode._DOMElement; NS_ASSERT(nodeElt,
"node must have _DOMElement set"); // No worries: If nodeElt is the last item (i.e. no nextSibling),
// insertNewItem will insert the new element as the last item. let next = nodeElt.nextSibling;
this._self.removeItem(nodeElt); this._self.insertNewItem(aNewNode, popup, next); }, containerOpened: function
PMV_containerOpened(aNode) { this.invalidateContainer(aNode); }, containerClosed: function PMV_containerClosed(aNode)
{ this.invalidateContainer(aNode); }, invalidateContainer: function PMV_invalidateContainer(aContainer)
{ // Do nothing if the entire view is already marked un-built. if (!this._self.parentNode._built)
return; let containerNodeElt = aContainer._DOMElement; NS_ASSERT(containerNodeElt, "node must have
_DOMElement set"); containerNodeElt._built = false; // If the menupopup is open we should
live-update it. if (containerNodeElt.open) this._self._rebuild(containerNodeElt.firstChild);
}, sortingChanged: function PMV_sortingChanged(aSortingMode) { } })]]>
content/browser/places/tree.xml
result->treeviewer cycle. // Note: unsetting the result's viewer
also unsets // the viewer's reference to our treeBoxObject. var result = this.getResult();
if (result) { result.viewer = null; result.root.containerOpen = false; } this.view = null; ]]>
= 0; --i) { var index = view.treeIndexForNode(parents[i]);
if (view.isContainer(index) && !view.isContainerOpen(index)) view.toggleOpenState(index); } // Select the
specified node... } var index = view.treeIndexForNode(node); view.selection.select(index); // ... and ensure
it's visible, not scrolled off somewhere. this.treeBoxObject.ensureRowIsVisible(index);
]]>
= 1; ]]>
0; child++) { var childNode = node.getChild(child); var found = findNodes(childNode);
if (!foundOne) foundOne = found; } // If we didn't find any additional matches in this
node's // subtree, revert the node to its previous openness. if (foundOne) nodesToOpen.unshift(node);
node.containerOpen = previousOpenness; return foundOne; } // Null the viewer while looking
for nodes var result = this.getResult(); var oldViewer = result.viewer; result.viewer
= null; findNodes(this.getResultNode()); result.viewer = oldViewer; // For all the nodes we've found,
highlight the corresponding // index in the tree. var resultview = this.view; var selection
= this.view.selection; selection.selectEventsSuppressed = true; selection.clearSelection(); // Open
nodes containing found items for (var i = 0; i < nodesToOpen.length; i++) { nodesToOpen[i].containerOpen
= true; } for (var i = 0; i < nodes.length; i++) { var index = resultview.treeIndexForNode(nodes[i]);
selection.rangedSelect(index, index, true); } selection.selectEventsSuppressed = false;
]]>
rowHeight * 0.75) { // If we are below the 75% of a container the treeview
we try // to drop after the node. orientation = Ci.nsITreeView.DROP_AFTER; } else if (PlacesUtils.nodeIsContainer(node)
&& eventY > rowHeight * 0.25) { // If we are below the 25% of a container the treeview
we try // to drop inside the node. orientation = Ci.nsITreeView.DROP_ON; } return this.view.canDrop(row.value,
orientation, aEvent.dataTransfer); ]]>
content/browser/places/utils.js/* -*- Mode: C++; tab-width: 8; indent-tabs-mode:
nil; c-basic-offset: 2 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL
2.0/LGPL 2.1 * The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with * the License.
You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * Software distributed
under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND,
either express or implied. See the License * for the specific language governing rights
and limitations under the * License. * The Original Code is the Places Command Controller.
* The Initial Developer of the Original Code is Google Inc. * Portions created by the Initial
Developer are Copyright (C) 2005 * the Initial Developer. All Rights Reserved. * Contributor(s):
* Ben Goodger * Myk Melez * Asaf Romano
* Sungjoon Steve Won * Dietrich Ayala
* Marco Bonardo * Alternatively, the contents of this file may be used under
the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case
the provisions of the GPL or the LGPL are applicable instead * of those above. If you
wish to allow use of your version of this file only * under the terms of either the
GPL or the LGPL, and not to allow others to * use your version of this file under the
terms of the MPL, indicate your * decision by deleting the provisions above and replace
them with the notice * and other provisions required by the GPL or the LGPL. If you do
not delete * the provisions above, a recipient may use your version of this file under *
the terms of any one of the MPL, the GPL or the LGPL. * ***** END LICENSE BLOCK *****
*/ function LOG(str) { dump("*** " + str + "\n"); var Ci = Components.interfaces; var
Cc = Components.classes; var Cr = Components.results; __defineGetter__("PlacesUtils", function()
{ delete this.PlacesUtils var tmpScope = {}; Components.utils.import("resource://gre/modules/utils.js",
tmpScope); return this.PlacesUtils = tmpScope.PlacesUtils; const LOAD_IN_SIDEBAR_ANNO = "bookmarkProperties/loadInSidebar";
const DESCRIPTION_ANNO = "bookmarkProperties/description"; const GUID_ANNO = "placesInternal/GUID"; const
LMANNO_FEEDURI = "livemark/feedURI"; const LMANNO_SITEURI = "livemark/siteURI"; const
ORGANIZER_FOLDER_ANNO = "PlacesOrganizer/OrganizerFolder"; const ORGANIZER_QUERY_ANNO = "PlacesOrganizer/OrganizerQuery";
const ORGANIZER_LEFTPANE_VERSION = 6; const EXCLUDE_FROM_BACKUP_ANNO = "places/excludeFromBackup";
//@line 73 "e:\builds\moz2_slave\win32_build\build\browser\components\places\content\utils.js" // On other platforms, the transferable system
converts "\r\n" to "\n". const NEWLINE = "\r\n"; //@line 76 "e:\builds\moz2_slave\win32_build\build\browser\components\places\content\utils.js"
function QI_node(aNode, aIID) { return aNode.QueryInterface(aIID); function asVisit(aNode) { return QI_node(aNode,
Ci.nsINavHistoryVisitResultNode); } function asFullVisit(aNode){ return QI_node(aNode,
Ci.nsINavHistoryFullVisitResultNode);} function asContainer(aNode){ return QI_node(aNode,
Ci.nsINavHistoryContainerResultNode);} function asQuery(aNode) { return QI_node(aNode, Ci.nsINavHistoryQueryResultNode);
} var PlacesUIUtils = { /** * The Microsummary Service */ get microsummaries() { delete this.microsummaries;
return this.microsummaries = Cc["@mozilla.org/microsummary/service;1"]. getService(Ci.nsIMicrosummaryService); },
get RDF() { delete this.RDF; return this.RDF = Cc["@mozilla.org/rdf/rdf-service;1"]. getService(Ci.nsIRDFService);
}, get localStore() { delete this.localStore; return this.localStore = this.RDF.GetDataSource("rdf:local-store");
}, get ptm() { delete this.ptm; return this.ptm = Cc["@mozilla.org/browser/placesTransactionsService;1"].
getService(Ci.nsIPlacesTransactionsService); }, get clipboard() { delete this.clipboard;
return this.clipboard = Cc["@mozilla.org/widget/clipboard;1"]. getService(Ci.nsIClipboard); }, get URIFixup()
{ delete this.URIFixup; return this.URIFixup = Cc["@mozilla.org/docshell/urifixup;1"].
getService(Ci.nsIURIFixup); }, get ellipsis() { delete this.ellipsis; var pref = Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefBranch); return this.ellipsis = pref.getComplexValue("intl.ellipsis", Ci.nsIPrefLocalizedString).data;
}, get privateBrowsing() { delete this.privateBrowsing; return this.privateBrowsing = Cc["@mozilla.org/privatebrowsing;1"].
getService(Ci.nsIPrivateBrowsingService); }, /** * Makes a URI from a spec, and do
fixup * @param aSpec * The string spec of the URI * @returns A URI object for the spec.
*/ createFixedURI: function PU_createFixedURI(aSpec) { return this.URIFixup.createFixupURI(aSpec,
0); }, /** * Wraps a string in a nsISupportsString wrapper * @param aString * The string to wrap
* @returns A nsISupportsString object containing a string. */ _wrapString: function PU__wrapString(aString)
{ var s = Cc["@mozilla.org/supports-string;1"]. createInstance(Ci.nsISupportsString); s.data
= aString; return s; }, /** * String bundle helpers */ get _bundle() { const PLACES_STRING_BUNDLE_URI
= "chrome://browser/locale/places/places.properties"; delete this._bundle; return this._bundle
= Cc["@mozilla.org/intl/stringbundle;1"]. getService(Ci.nsIStringBundleService). createBundle(PLACES_STRING_BUNDLE_URI);
}, getFormattedString: function PU_getFormattedString(key, params) { return this._bundle.formatStringFromName(key,
params, params.length); }, getString: function PU_getString(key) { return this._bundle.GetStringFromName(key);
}, /** * Get a transaction for copying a uri item from one container to another *
as a bookmark. * @param aData * JSON object of dropped or pasted item properties * @param
aContainer * The container being copied into * @param aIndex * The index within the container
the item is copied to * @returns A nsITransaction object that performs the copy. */ _getURIItemCopyTransaction:
function (aData, aContainer, aIndex) { return this.ptm.createItem(PlacesUtils._uri(aData.uri),
aContainer, aIndex, aData.title, ""); }, /** * Get a transaction for copying a bookmark
item from one container to * another. * @param aData * JSON object of dropped or pasted item
properties * @param aContainer * The container being copied into * @param aIndex * The index
within the container the item is copied to * @param [optional] aExcludeAnnotations
* Optional, array of annotations (listed by their names) to exclude * when copying the
item. * @returns A nsITransaction object that performs the copy. */ _getBookmarkItemCopyTransaction:
function PU__getBookmarkItemCopyTransaction(aData, aContainer, aIndex, aExcludeAnnotations)
{ var itemURL = PlacesUtils._uri(aData.uri); var itemTitle = aData.title; var keyword
= aData.keyword || null; var annos = aData.annos || []; // always exclude GUID when copying
any item var excludeAnnos = [GUID_ANNO]; if (aExcludeAnnotations) excludeAnnos = excludeAnnos.concat(aExcludeAnnotations);
annos = annos.filter(function(aValue, aIndex, aArray) { return excludeAnnos.indexOf(aValue.name)
== -1; }); var childTxns = []; if (aData.dateAdded) childTxns.push(this.ptm.editItemDateAdded(null,
aData.dateAdded)); if (aData.lastModified) childTxns.push(this.ptm.editItemLastModified(null,
aData.lastModified)); if (aData.tags) { var tags = aData.tags.split(", "); // filter out
tags already present, so that undo doesn't remove them // from pre-existing bookmarks
var storedTags = PlacesUtils.tagging.getTagsForURI(itemURL, {}); tags = tags.filter(function (aTag)
{ return (storedTags.indexOf(aTag) == -1); }, this); if (tags.length) childTxns.push(this.ptm.tagURI(itemURL,
tags)); } return this.ptm.createItem(itemURL, aContainer, aIndex, itemTitle, keyword, annos,
childTxns); }, /** * Gets a transaction for copying (recursively nesting to include children)
* a folder (or container) and its contents from one folder to another. * * @param aData
* Unwrapped dropped folder data - Obj containing folder and children * @param aContainer *
The container we are copying into * @param aIndex * The index in the destination container
to insert the new items * @returns A nsITransaction object that will perform the copy. */ _getFolderCopyTransaction:
function PU__getFolderCopyTransaction(aData, aContainer, aIndex) { var self = this; function
getChildItemsTransactions(aChildren) { var childItemsTransactions = []; var cc = aChildren.length;
var index = aIndex; for (var i = 0; i < cc; ++i) { var txn = null; var node = aChildren[i];
// Make sure that items are given the correct index, this will be // passed by the transaction
manager to the backend for the insertion. // Insertion behaves differently if index
== DEFAULT_INDEX (append) if (aIndex != PlacesUtils.bookmarks.DEFAULT_INDEX) index
= i; if (node.type == PlacesUtils.TYPE_X_MOZ_PLACE_CONTAINER) { if (node.livemark && node.annos) // node
is a livemark txn = self._getLivemarkCopyTransaction(node, aContainer, index); else txn = self._getFolderCopyTransaction(node,
aContainer, index); } else if (node.type == PlacesUtils.TYPE_X_MOZ_PLACE_SEPARATOR)
txn = self.ptm.createSeparator(-1, index); else if (node.type == PlacesUtils.TYPE_X_MOZ_PLACE)
txn = self._getBookmarkItemCopyTransaction(node, -1, index); NS_ASSERT(txn, "Unexpected item
under a bookmarks folder"); if (txn) childItemsTransactions.push(txn); } return childItemsTransactions; } // tag
folders use tag transactions if (aContainer == PlacesUtils.tagsFolderId) { var txns
= []; if (aData.children) { aData.children.forEach(function(aChild) { txns.push(this.ptm.tagURI(PlacesUtils._uri(aChild.uri),
[aData.title])); }, this); } return this.ptm.aggregateTransactions("addTags", txns); } else if (aData.livemark && aData.annos)
{ // Place is a Livemark Container return this._getLivemarkCopyTransaction(aData, aContainer,
aIndex); } else { var childItems = getChildItemsTransactions(aData.children); if (aData.dateAdded) childItems.push(this.ptm.editItemDateAdded(null,
aData.dateAdded)); if (aData.lastModified) childItems.push(this.ptm.editItemLastModified(null,
aData.lastModified)); var annos = aData.annos || []; annos = annos.filter(function(aAnno)
{ // always exclude GUID when copying any item return aAnno.name != GUID_ANNO; });
return this.ptm.createFolder(aData.title, aContainer, aIndex, annos, childItems); }
}, _getLivemarkCopyTransaction: function PU__getLivemarkCopyTransaction(aData, aContainer,
aIndex) { NS_ASSERT(aData.livemark && aData.annos, "node is not a livemark"); // Place is a Livemark
Container var feedURI = null; var siteURI = null; aData.annos = aData.annos.filter(function(aAnno)
{ if (aAnno.name == LMANNO_FEEDURI) { feedURI = PlacesUtils._uri(aAnno.value); return false;
} else if (aAnno.name == LMANNO_SITEURI) { siteURI = PlacesUtils._uri(aAnno.value);
return false; } // always exclude GUID when copying any item return aAnno.name != GUID_ANNO;
}); return this.ptm.createLivemark(feedURI, siteURI, aData.title, aContainer, aIndex,
aData.annos); }, /** * Constructs a Transaction for the drop or paste of a blob of data into
* a container. * @param data * The unwrapped data blob of dropped or pasted data. * @param
type * The content type of the data * @param container * The container the data was dropped
or pasted into * @param index * The index within the container the item was dropped
or pasted at * @param copy * The drag action was copy, so don't move folders or links.
* @returns An object implementing nsITransaction that can perform * the move/insert. */ makeTransaction:
function PU_makeTransaction(data, type, container, index, copy) { switch (data.type) { case PlacesUtils.TYPE_X_MOZ_PLACE_CONTAINER:
if (copy) return this._getFolderCopyTransaction(data, container, index); // Otherwise move the item.
return this.ptm.moveItem(data.id, container, index); break; case PlacesUtils.TYPE_X_MOZ_PLACE:
if (data.id == -1) // Not bookmarked. return this._getURIItemCopyTransaction(data, container,
index); if (copy) return this._getBookmarkItemCopyTransaction(data, container, index); // Otherwise move the item.
return this.ptm.moveItem(data.id, container, index); break; case PlacesUtils.TYPE_X_MOZ_PLACE_SEPARATOR:
// There is no data in a separator, so copying it just amounts to // inserting a new separator.
if (copy) return this.ptm.createSeparator(container, index); // Otherwise move the item. return
this.ptm.moveItem(data.id, container, index); break; default: if (type == PlacesUtils.TYPE_X_MOZ_URL
|| type == PlacesUtils.TYPE_UNICODE || type == TAB_DROP_TYPE) { var title = (type !=
PlacesUtils.TYPE_UNICODE) ? data.title : data.uri; return this.ptm.createItem(PlacesUtils._uri(data.uri),
container, index, title); } } return null; }, /** * Methods to show the bookmarkProperties
dialog in its various modes. * * The showMinimalAdd* methods open the dialog by its alternative
URI. Thus * they persist the dialog dimensions separately from the showAdd* methods. * Note
these variants also do not return the dialog "performed" state since * they may not open
the dialog modally. */ /** * Shows the "Add Bookmark" dialog. * * @param [optional] aURI
* An nsIURI object for which the "add bookmark" dialog is * to be shown. * @param [optional]
aTitle * The default title for the new bookmark. * @param [optional] aDescription The default
description for the new bookmark * @param [optional] aDefaultInsertionPoint * The default
insertion point for the new item. If set, the folder * picker would be hidden unless
aShowPicker is set to true, in which * case the dialog only uses the folder identifier
from the insertion * point as the initially selected item in the folder picker. * @param
[optional] aShowPicker * see above * @param [optional] aLoadInSidebar * If true, the dialog
will default to load the new item in the * sidebar (as a web panel). * @param [optional]
aKeyword * The default keyword for the new bookmark. The keyword field * will be shown
in the dialog if this is used. * @param [optional] aPostData * POST data for POST-style keywords.
* @param [optional] aCharSet * The character set for the bookmarked page. * @return true
if any transaction has been performed. * * Notes: * - the location, description and
"loadInSidebar" fields are * visible only if there is no initial URI (aURI is null).
* - When aDefaultInsertionPoint is not set, the dialog defaults to the * bookmarks root
folder. */ showAddBookmarkUI: function PU_showAddBookmarkUI(aURI, aTitle, aDescription, aDefaultInsertionPoint,
aShowPicker, aLoadInSidebar, aKeyword, aPostData, aCharSet) { var info = { action: "add", type:
"bookmark" }; if (aURI) info.uri = aURI; // allow default empty title if (typeof(aTitle)
== "string") info.title = aTitle; if (aDescription) info.description = aDescription; if (aDefaultInsertionPoint)
{ info.defaultInsertionPoint = aDefaultInsertionPoint; if (!aShowPicker) info.hiddenRows = ["folderPicker"];
} if (aLoadInSidebar) info.loadBookmarkInSidebar = true; if (typeof(aKeyword) == "string")
{ info.keyword = aKeyword; if (typeof(aPostData) == "string") info.postData = aPostData; if
(typeof(aCharSet) == "string") info.charSet = aCharSet; } return this._showBookmarkDialog(info);
}, /** * @see showAddBookmarkUI * This opens the dialog with only the name and folder pickers
visible by * default. * * You can still pass in the various paramaters as the default properties
* for the new bookmark. * * The keyword field will be visible only if the aKeyword parameter
* was used. */ showMinimalAddBookmarkUI: function PU_showMinimalAddBookmarkUI(aURI,
aTitle, aDescription, aDefaultInsertionPoint, aShowPicker, aLoadInSidebar, aKeyword, aPostData,
aCharSet) { var info = { action: "add", type: "bookmark", hiddenRows: ["description"] };
if (aURI) info.uri = aURI; // allow default empty title if (typeof(aTitle) == "string")
info.title = aTitle; if (aDescription) info.description = aDescription; if (aDefaultInsertionPoint)
{ info.defaultInsertionPoint = aDefaultInsertionPoint; if (!aShowPicker) info.hiddenRows.push("folderPicker");
} if (aLoadInSidebar) info.loadBookmarkInSidebar = true; else info.hiddenRows = info.hiddenRows.concat(["location",
"loadInSidebar"]); if (typeof(aKeyword) == "string") { info.keyword = aKeyword; //
Hide the Tags field if we are adding a keyword. info.hiddenRows.push("tags"); // Keyword related
params. if (typeof(aPostData) == "string") info.postData = aPostData; if (typeof(aCharSet)
== "string") info.charSet = aCharSet; } else info.hiddenRows.push("keyword"); this._showBookmarkDialog(info,
true); }, /** * Shows the "Add Live Bookmark" dialog. * * @param [optional] aFeedURI *
The feed URI for which the dialog is to be shown (nsIURI). * @param [optional] aSiteURI
* The site URI for the new live-bookmark (nsIURI). * @param [optional] aDefaultInsertionPoint
* The default insertion point for the new item. If set, the folder * picker would be
hidden unless aShowPicker is set to true, in which * case the dialog only uses the folder
identifier from the insertion * point as the initially selected item in the folder picker.
* @param [optional] aShowPicker * see above * @return true if any transaction has been
performed. * * Notes: * - the feedURI and description fields are visible only if there
is no * initial feed URI (aFeedURI is null). * - When aDefaultInsertionPoint is not set,
the dialog defaults to the * bookmarks root folder. */ showAddLivemarkUI: function PU_showAddLivemarkURI(aFeedURI,
aSiteURI, aTitle, aDescription, aDefaultInsertionPoint, aShowPicker) { var info = { action: "add",
type: "livemark" }; if (aFeedURI) info.feedURI = aFeedURI; if (aSiteURI) info.siteURI =
aSiteURI; // allow default empty title if (typeof(aTitle) == "string") info.title =
aTitle; if (aDescription) info.description = aDescription; if (aDefaultInsertionPoint)
{ info.defaultInsertionPoint = aDefaultInsertionPoint; if (!aShowPicker) info.hiddenRows = ["folderPicker"];
} return this._showBookmarkDialog(info); }, /** * @see showAddLivemarkUI * This opens
the dialog with only the name and folder pickers visible by * default. * * You can still pass
in the various paramaters as the default properties * for the new live-bookmark. */ showMinimalAddLivemarkUI:
function PU_showMinimalAddLivemarkURI(aFeedURI, aSiteURI, aTitle, aDescription, aDefaultInsertionPoint,
aShowPicker) { var info = { action: "add", type: "livemark", hiddenRows: ["feedLocation",
"siteLocation", "description"] }; if (aFeedURI) info.feedURI = aFeedURI; if (aSiteURI) info.siteURI
= aSiteURI; // allow default empty title if (typeof(aTitle) == "string") info.title
= aTitle; if (aDescription) info.description = aDescription; if (aDefaultInsertionPoint)
{ info.defaultInsertionPoint = aDefaultInsertionPoint; if (!aShowPicker) info.hiddenRows.push("folderPicker");
} this._showBookmarkDialog(info, true); }, /** * Show an "Add Bookmarks" dialog to
allow the adding of a folder full * of bookmarks corresponding to the objects in the uriList.
This will * be called most often as the result of a "Bookmark All Tabs..." command. * *
@param aURIList List of nsIURI objects representing the locations * to be bookmarked. * @return
true if any transaction has been performed. */ showMinimalAddMultiBookmarkUI: function
PU_showAddMultiBookmarkUI(aURIList) { NS_ASSERT(aURIList.length, "showAddMultiBookmarkUI expects a list of
nsIURI objects"); var info = { action: "add", type: "folder", hiddenRows: ["description"],
URIList: aURIList }; this._showBookmarkDialog(info, true); }, /** * Opens the properties dialog
for a given item identifier. * * @param aItemId * item identifier for which the properties
are to be shown * @param aType * item type, either "bookmark" or "folder" * @param [optional]
aReadOnly * states if properties dialog should be readonly * @return true if any transaction
has been performed. */ showItemProperties: function PU_showItemProperties(aItemId, aType,
aReadOnly) { var info = { action: "edit", type: aType, itemId: aItemId, readOnly: aReadOnly
}; return this._showBookmarkDialog(info); }, /** * Shows the "New Folder" dialog.
* * @param [optional] aTitle * The default title for the new bookmark. * @param [optional]
aDefaultInsertionPoint * The default insertion point for the new item. If set, the folder
* picker would be hidden unless aShowPicker is set to true, in which * case the dialog
only uses the folder identifier from the insertion * point as the initially selected item in
the folder picker. * @param [optional] aShowPicker * see above * @return true if any transaction
has been performed. */ showAddFolderUI: function PU_showAddFolderUI(aTitle, aDefaultInsertionPoint,
aShowPicker) { var info = { action: "add", type: "folder", hiddenRows: [] }; // allow
default empty title if (typeof(aTitle) == "string") info.title = aTitle; if (aDefaultInsertionPoint)
{ info.defaultInsertionPoint = aDefaultInsertionPoint; if (!aShowPicker) info.hiddenRows.push("folderPicker");
} return this._showBookmarkDialog(info); }, /** * Shows the bookmark dialog corresponding
to the specified info * * @param aInfo * Describes the item to be edited/added in the
dialog. * See documentation at the top of bookmarkProperties.js * @param aMinimalUI
* [optional] if true, the dialog is opened by its alternative * chrome: uri. * * @return
true if any transaction has been performed, false otherwise. */ _showBookmarkDialog: function
PU__showBookmarkDialog(aInfo, aMinimalUI) { var dialogURL = aMinimalUI ? "chrome://browser/content/places/bookmarkProperties2.xul"
: "chrome://browser/content/places/bookmarkProperties.xul"; var features; if (aMinimalUI) features =
"centerscreen,chrome,dialog,resizable,modal"; else features = "centerscreen,chrome,modal,resizable=no";
window.openDialog(dialogURL, "", features, aInfo); return ("performed" in aInfo && aInfo.performed);
}, /** * Returns the closet ancestor places view for the given DOM node * @param aNode
* a DOM node * @return the closet ancestor places view if exists, null otherwsie. */
getViewForNode: function PU_getViewForNode(aNode) { var node = aNode; // the view for a
of which its associated menupopup is a places view, // is the menupopup if (node.localName
== "menu" && !node.node && node.firstChild.getAttribute("type") == "places") return node.firstChild; while
(node) { // XXXmano: Use QueryInterface(nsIPlacesView) once we implement it... if (node.getAttribute("type")
== "places") return node; node = node.parentNode; } return null; }, /** * By calling this before
we visit a URL, we will use TRANSITION_TYPED * as the transition for the visit to that
URL (if we don't have a referrer). * This is used when visiting pages from the history
menu, history sidebar, * url bar, url autocomplete results, and history searches from the places
* organizer. If we don't call this, we'll treat those visits as * TRANSITION_LINK.
*/ markPageAsTyped: function PU_markPageAsTyped(aURL) { PlacesUtils.history.QueryInterface(Ci.nsIBrowserHistory)
.markPageAsTyped(this.createFixedURI(aURL)); }, /** * By calling this before we visit
a URL, we will use TRANSITION_BOOKMARK * as the transition for the visit to that URL
(if we don't have a referrer). * This is used when visiting pages from the bookmarks menu,
* personal toolbar, and bookmarks from within the places organizer. * If we don't call this,
we'll treat those visits as TRANSITION_LINK. */ markPageAsFollowedBookmark: function PU_markPageAsFollowedBookmark(aURL)
{ PlacesUtils.history.markPageAsFollowedBookmark(this.createFixedURI(aURL)); }, /** * Allows opening of javascript/data
URI only if the given node is * bookmarked (see bug 224521). * @param aURINode * a URI
node * @return true if it's safe to open the node in the browser, false otherwise. * */
checkURLSecurity: function PU_checkURLSecurity(aURINode) { if (!PlacesUtils.nodeIsBookmark(aURINode))
{ var uri = PlacesUtils._uri(aURINode.uri); if (uri.schemeIs("javascript") || uri.schemeIs("data"))
{ const BRANDING_BUNDLE_URI = "chrome://branding/locale/brand.properties"; var brandShortName = Cc["@mozilla.org/intl/stringbundle;1"].
getService(Ci.nsIStringBundleService). createBundle(BRANDING_BUNDLE_URI). GetStringFromName("brandShortName"); var promptService
= Cc["@mozilla.org/embedcomp/prompt-service;1"]. getService(Ci.nsIPromptService); var errorStr
= this.getString("load-js-data-url-error"); promptService.alert(window, brandShortName,
errorStr); return false; } } return true; }, /** * Get the description associated with
a document, as specified in a * element. * @param doc * A DOM Document to get a description
for * @returns A description string if a META element was discovered with a * "description"
or "httpequiv" attribute, empty string otherwise. */ getDescriptionFromDocument: function PU_getDescriptionFromDocument(doc)
{ var metaElements = doc.getElementsByTagName("META"); for (var i = 0; i < metaElements.length; ++i)
{ if (metaElements[i].name.toLowerCase() == "description" || metaElements[i].httpEquiv.toLowerCase()
== "description") { return metaElements[i].content; } } return ""; }, /** * Retrieve the description
of an item * @param aItemId * item identifier * @returns the description of the given item,
or an empty string if it is * not set. */ getItemDescription: function PU_getItemDescription(aItemId)
{ if (PlacesUtils.annotations.itemHasAnnotation(aItemId, DESCRIPTION_ANNO)) return PlacesUtils.annotations.getItemAnnotation(aItemId,
DESCRIPTION_ANNO); return ""; }, /** * Gives the user a chance to cancel loading lots of
tabs at once */ _confirmOpenInTabs: function PU__confirmOpenInTabs(numTabsToOpen) { var
pref = Cc["@mozilla.org/preferences-service;1"]. getService(Ci.nsIPrefBranch); const kWarnOnOpenPref
= "browser.tabs.warnOnOpen"; var reallyOpen = true; if (pref.getBoolPref(kWarnOnOpenPref))
{ if (numTabsToOpen >= pref.getIntPref("browser.tabs.maxOpenBeforeWarn")) { var promptService = Cc["@mozilla.org/embedcomp/prompt-service;1"].
getService(Ci.nsIPromptService); // default to true: if it were false, we wouldn't get
this far var warnOnOpen = { value: true }; var messageKey = "tabs.openWarningMultipleBranded";
var openKey = "tabs.openButtonMultiple"; const BRANDING_BUNDLE_URI = "chrome://branding/locale/brand.properties";
var brandShortName = Cc["@mozilla.org/intl/stringbundle;1"]. getService(Ci.nsIStringBundleService). createBundle(BRANDING_BUNDLE_URI).
GetStringFromName("brandShortName"); var buttonPressed = promptService.confirmEx(window, this.getString("tabs.openWarningTitle"),
this.getFormattedString(messageKey, [numTabsToOpen, brandShortName]), (promptService.BUTTON_TITLE_IS_STRING
* promptService.BUTTON_POS_0) + (promptService.BUTTON_TITLE_CANCEL * promptService.BUTTON_POS_1), this.getString(openKey),
null, null, this.getFormattedString("tabs.openWarningPromptMeBranded", [brandShortName]), warnOnOpen); reallyOpen
= (buttonPressed == 0); // don't set the pref unless they press OK and it's false if
(reallyOpen && !warnOnOpen.value) pref.setBoolPref(kWarnOnOpenPref, false); } } return reallyOpen; }, /** aItemsToOpen
needs to be an array of objects of the form: * {uri: string, isBookmark: boolean} */
_openTabset: function PU__openTabset(aItemsToOpen, aEvent) { if (!aItemsToOpen.length) return;
var urls = []; for (var i = 0; i < aItemsToOpen.length; i++) { var item = aItemsToOpen[i]; if (item.isBookmark)
this.markPageAsFollowedBookmark(item.uri); else this.markPageAsTyped(item.uri); urls.push(item.uri);
} var browserWindow = getTopWin(); var where = browserWindow ? whereToOpenLink(aEvent,
false, true) : "window"; if (where == "window") { window.openDialog(getBrowserURL(), "_blank",
"chrome,all,dialog=no", urls.join("|")); return; } var loadInBackground = where == "tabshifted"
? true : false; var replaceCurrentTab = where == "tab" ? false : true; browserWindow.getBrowser().loadTabs(urls,
loadInBackground, replaceCurrentTab); }, openContainerNodeInTabs: function PU_openContainerInTabs(aNode,
aEvent) { var urlsToOpen = PlacesUtils.getURLsForContainerNode(aNode); if (!this._confirmOpenInTabs(urlsToOpen.length))
return; this._openTabset(urlsToOpen, aEvent); }, openURINodesInTabs: function PU_openURINodesInTabs(aNodes,
aEvent) { var urlsToOpen = []; for (var i=0; i < aNodes.length; i++) { // skip over separators
and folders if (PlacesUtils.nodeIsURI(aNodes[i])) urlsToOpen.push({uri: aNodes[i].uri, isBookmark:
PlacesUtils.nodeIsBookmark(aNodes[i])}); } 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)
&& this.checkURLSecurity(aNode)) { var isBookmark = PlacesUtils.nodeIsBookmark(aNode); if (isBookmark)
this.markPageAsFollowedBookmark(aNode.uri); else this.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 guessing scheme from an url string. * Used to avoid nsIURI
overhead in frequently called UI functions. * * @param aUrlString the url to guess the
scheme from. * * @return guessed scheme for this url string. * * @note this is not supposed
be perfect, so use it only for UI purposes. */ guessUrlSchemeForUI: function PUU_guessUrlSchemeForUI(aUrlString)
{ return aUrlString.substr(0, aUrlString.indexOf(":")); }, /** * Helper for the toolbar and menu
views */ createMenuItemForNode: function PUU_createMenuItemForNode(aNode) { var element; var type = aNode.type; if
(type == Ci.nsINavHistoryResultNode.RESULT_TYPE_SEPARATOR) element = document.createElement("menuseparator");
else { if (PlacesUtils.uriTypes.indexOf(type) != -1) { element = document.createElement("menuitem");
element.className = "menuitem-iconic bookmark-item"; element.setAttribute("scheme", this.guessUrlSchemeForUI(aNode.uri));
} else if (PlacesUtils.containerTypes.indexOf(type) != -1) { element = document.createElement("menu");
element.setAttribute("container", "true"); if (aNode.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_QUERY)
{ element.setAttribute("query", "true"); if (PlacesUtils.nodeIsTagQuery(aNode)) element.setAttribute("tagContainer",
"true"); else if (PlacesUtils.nodeIsDay(aNode)) element.setAttribute("dayContainer", "true");
else if (PlacesUtils.nodeIsHost(aNode)) element.setAttribute("hostContainer", "true"); } else if (aNode.itemId != -1) {
if (PlacesUtils.nodeIsLivemarkContainer(aNode)) element.setAttribute("livemark", "true");
} var popup = document.createElement("menupopup"); popup.setAttribute("placespopup", "true");
popup._resultNode = asContainer(aNode); //@line 1046 "e:\builds\moz2_slave\win32_build\build\browser\components\places\content\utils.js"
// no context menu on mac popup.setAttribute("context", "placesContext"); //@line 1049 "e:\builds\moz2_slave\win32_build\build\browser\components\places\content\utils.js"
element.appendChild(popup); element.className = "menu-iconic bookmark-item"; } else throw
"Unexpected node"; element.setAttribute("label", this.getBestTitle(aNode)); var icon = aNode.icon;
if (icon) element.setAttribute("image", icon); } element.node = aNode; element.node._DOMElement
= element; return element; }, cleanPlacesPopup: function PU_cleanPlacesPopup(aPopup) { //
Remove places popup children and update markers to keep track of // their indices. var start
= aPopup._startMarker != -1 ? aPopup._startMarker + 1 : 0; var end = aPopup._endMarker != -1
? aPopup._endMarker : aPopup.childNodes.length; var items = []; var placesNodeFound = false;
for (var i = start; i < end; ++i) { var item = aPopup.childNodes[i]; if (item.getAttribute("builder")
== "end") { // we need to do this for menus that have static content at the end but //
are initially empty, eg. the history menu, we need to know where to // start inserting
new items. aPopup._endMarker = i; break; } if (item.node) { items.push(item); placesNodeFound
= true; } else { // This is static content... if (!placesNodeFound) // ...at the start of
the popup // Initialized in menu.xml, in the base binding aPopup._startMarker++; else
{ // ...after places nodes aPopup._endMarker = i; break; } } } for (var i = 0; i < items.length;
++i) { aPopup.removeChild(items[i]); if (aPopup._endMarker != -1) aPopup._endMarker--; } }, getBestTitle:
function PU_getBestTitle(aNode) { var title; if (!aNode.title && PlacesUtils.uriTypes.indexOf(aNode.type)
!= -1) { // if node title is empty, try to set the label using host and filename //
PlacesUtils._uri() will throw if aNode.uri is not a valid URI try { var uri = PlacesUtils._uri(aNode.uri);
var host = uri.host; var fileName = uri.QueryInterface(Ci.nsIURL).fileName; // if fileName is empty, use path to distinguish
labels title = host + (fileName ? (host ? "/" + this.ellipsis + "/" : "") + fileName
: uri.path); } catch (e) { // Use (no title) for non-standard URIs (data:, javascript:,
...) title = ""; } } else title = aNode.title; return title || this.getString("noTitle");
}, get leftPaneQueries() { // build the map this.leftPaneFolderId; return this.leftPaneQueries;
}, // Get the folder id for the organizer left-pane folder. get leftPaneFolderId()
{ var leftPaneRoot = -1; var allBookmarksId; // Shortcuts to services. var bs = PlacesUtils.bookmarks;
var as = PlacesUtils.annotations; // Get all items marked as being the left pane folder.
We should only have // one of them. var items = as.getItemsWithAnnotation(ORGANIZER_FOLDER_ANNO,
{}); if (items.length > 1) { // Something went wrong, we cannot have more than one left
pane folder, // remove all left pane folders and continue. We will create a new one. items.forEach(bs.removeItem);
} else if (items.length == 1 && items[0] != -1) { leftPaneRoot = items[0]; // Check
organizer left pane version. var version = as.getItemAnnotation(leftPaneRoot, ORGANIZER_FOLDER_ANNO);
if (version != ORGANIZER_LEFTPANE_VERSION) { // If version is not valid we must rebuild
the left pane. bs.removeItem(leftPaneRoot); leftPaneRoot = -1; } } var queriesTitles
= { "PlacesRoot": "", "History": this.getString("OrganizerQueryHistory"), // TODO: Bug 489681, Tags needs its own string
in places.properties "Tags": bs.getItemTitle(PlacesUtils.tagsFolderId), "AllBookmarks": this.getString("OrganizerQueryAllBookmarks"),
"Downloads": this.getString("OrganizerQueryDownloads"), "BookmarksToolbar": null, "BookmarksMenu":
null, "UnfiledBookmarks": null }; if (leftPaneRoot != -1) { // A valid left pane folder has
been found. // Build the leftPaneQueries Map. This is used to quickly access them // associating
a mnemonic name to the real item ids. delete this.leftPaneQueries; this.leftPaneQueries
= {}; var items = as.getItemsWithAnnotation(ORGANIZER_QUERY_ANNO, {}); // While looping through queries we
will also check for titles validity. for (var i = 0; i < items.length; i++) { var queryName
= as.getItemAnnotation(items[i], ORGANIZER_QUERY_ANNO); this.leftPaneQueries[queryName] = items[i];
// Titles could have been corrupted or the user could have changed his // locale. Check
title is correctly set and eventually fix it. if (bs.getItemTitle(items[i]) != queriesTitles[queryName])
bs.setItemTitle(items[i], queriesTitles[queryName]); } delete this.leftPaneFolderId; return this.leftPaneFolderId
= leftPaneRoot; } var self = this; var callback = { // Helper to create an organizer special
query. create_query: function CB_create_query(aQueryName, aParentId, aQueryUrl) { let itemId = bs.insertBookmark(aParentId,
PlacesUtils._uri(aQueryUrl), bs.DEFAULT_INDEX, queriesTitles[aQueryName]); // Mark as special
organizer query. as.setItemAnnotation(itemId, ORGANIZER_QUERY_ANNO, aQueryName, 0, as.EXPIRE_NEVER);
// We should never backup this, since it changes between profiles. as.setItemAnnotation(itemId,
EXCLUDE_FROM_BACKUP_ANNO, 1, 0, as.EXPIRE_NEVER); // Add to the queries map. self.leftPaneQueries[aQueryName]
= itemId; return itemId; }, // Helper to create an organizer special folder. create_folder:
function CB_create_folder(aFolderName, aParentId, aIsRoot) { // Left Pane Root Folder. let folderId
= bs.createFolder(aParentId, queriesTitles[aFolderName], bs.DEFAULT_INDEX); // We should never backup
this, since it changes between profiles. as.setItemAnnotation(folderId, EXCLUDE_FROM_BACKUP_ANNO, 1, 0, as.EXPIRE_NEVER);
// Disallow manipulating this folder within the organizer UI. bs.setFolderReadonly(folderId,
true); if (aIsRoot) { // Mark as special left pane root. as.setItemAnnotation(folderId,
ORGANIZER_FOLDER_ANNO, ORGANIZER_LEFTPANE_VERSION, 0, as.EXPIRE_NEVER); } else { // Mark as special
organizer folder. as.setItemAnnotation(folderId, ORGANIZER_QUERY_ANNO, aFolderName, 0, as.EXPIRE_NEVER);
self.leftPaneQueries[aFolderName] = folderId; } return folderId; }, runBatched: function
CB_runBatched(aUserData) { delete self.leftPaneQueries; self.leftPaneQueries = { }; // Left Pane Root
Folder. leftPaneRoot = this.create_folder("PlacesRoot", bs.placesRoot, true); // History Query. this.create_query("History",
leftPaneRoot, "place:type=" + Ci.nsINavHistoryQueryOptions.RESULTS_AS_DATE_QUERY + "&sort=" + Ci.nsINavHistoryQueryOptions.SORT_BY_DATE_DESCENDING);
// ***: Downloads. // Tags Query. this.create_query("Tags", leftPaneRoot, "place:type=" + Ci.nsINavHistoryQueryOptions.RESULTS_AS_TAG_QUERY
+ "&sort=" + Ci.nsINavHistoryQueryOptions.SORT_BY_TITLE_ASCENDING); // All Bookmarks Folder. allBookmarksId
= this.create_folder("AllBookmarks", leftPaneRoot, false); // All Bookmarks->Bookmarks Toolbar
Query. this.create_query("BookmarksToolbar", allBookmarksId, "place:folder=TOOLBAR");
// All Bookmarks->Bookmarks Menu Query. this.create_query("BookmarksMenu", allBookmarksId, "place:folder=BOOKMARKS_MENU");
// All Bookmarks->Unfiled Bookmarks Query. this.create_query("UnfiledBookmarks", allBookmarksId,
"place:folder=UNFILED_BOOKMARKS"); } }; bs.runInBatchMode(callback, null); delete this.leftPaneFolderId; return
this.leftPaneFolderId = leftPaneRoot; }, /** * Get the folder id for the organizer
left-pane folder. */ get allBookmarksFolderId() { // ensure the left-pane root is initialized;
this.leftPaneFolderId; delete this.allBookmarksFolderId; return this.allBookmarksFolderId = this.leftPaneQueries["AllBookmarks"];
}, /** * If an item is a left-pane query, returns the name of the query * or an empty
string if not. * * @param aItemId id of a container * @returns the name of the query,
or empty string if not a left-pane query */ getLeftPaneQueryNameFromId: function PU_getLeftPaneQueryNameFromId(aItemId)
{ var queryName = ""; // If the let pane hasn't been built, use the annotation service
// directly, to avoid building the left pane too early. if (this.__lookupGetter__("leftPaneFolderId"))
{ try { queryName = PlacesUtils.annotations. getItemAnnotation(aItemId, ORGANIZER_QUERY_ANNO);
} catch (ex) { // doesn't have the annotation queryName = ""; } } else { // If the left
pane has already been built, use the name->id map // cached in PlacesUIUtils. for (let [name,
id] in Iterator(this.leftPaneQueries)) { if (aItemId == id) queryName = name; } }
return queryName; }, /** * Add, update or remove the livemark status menuitem. * @param
aPopup * The livemark container popup */ ensureLivemarkStatusMenuItem: function PU_ensureLivemarkStatusMenuItem(aPopup)
{ var itemId = aPopup._resultNode.itemId; var lmStatus = null; if (PlacesUtils.annotations
.itemHasAnnotation(itemId, "livemark/loadfailed")) lmStatus = "bookmarksLivemarkFailed"; else
if (PlacesUtils.annotations .itemHasAnnotation(itemId, "livemark/loading")) lmStatus = "bookmarksLivemarkLoading";
if (lmStatus && !aPopup._lmStatusMenuItem) { // Create the status menuitem and cache
it in the popup object. aPopup._lmStatusMenuItem = document.createElement("menuitem"); aPopup._lmStatusMenuItem.setAttribute("lmStatus",
lmStatus); aPopup._lmStatusMenuItem.setAttribute("label", this.getString(lmStatus)); aPopup._lmStatusMenuItem.setAttribute("disabled",
true); aPopup.insertBefore(aPopup._lmStatusMenuItem, aPopup.childNodes.item(aPopup._startMarker
+ 1)); aPopup._startMarker++; } else if (lmStatus && aPopup._lmStatusMenuItem.getAttribute("lmStatus")
!= lmStatus) { // Status has changed, update the cached status menuitem. aPopup._lmStatusMenuItem.setAttribute("label",
this.getString(lmStatus)); } else if (!lmStatus && aPopup._lmStatusMenuItem){ // No status,
remove the cached menuitem. aPopup.removeChild(aPopup._lmStatusMenuItem); aPopup._lmStatusMenuItem = null; aPopup._startMarker--;
} content/browser/places/controller.js/* -*- Mode: C++; tab-width: 8; indent-tabs-mode:
nil; c-basic-offset: 2 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL
2.0/LGPL 2.1 * The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with * the License.
You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * Software distributed
under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND,
either express or implied. See the License * for the specific language governing rights
and limitations under the * License. * The Original Code is the Places Command Controller.
* The Initial Developer of the Original Code is Google Inc. * Portions created by the Initial
Developer are Copyright (C) 2005 * the Initial Developer. All Rights Reserved. * Contributor(s):
* Ben Goodger * Myk Melez * Asaf Romano
* Marco Bonardo * 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 *****
*/ // XXXmano: we should move most/all of these constants to PlacesUtils const ORGANIZER_ROOT_BOOKMARKS
= "place:folder=BOOKMARKS_MENU&excludeItems=1&queryType=1"; const ORGANIZER_SUBSCRIPTIONS_QUERY = "place:annotation=livemark%2FfeedURI";
// No change to the view, preserve current selection const RELOAD_ACTION_NOTHING = 0;
// Inserting items new to the view, select the inserted rows const RELOAD_ACTION_INSERT
= 1; // Removing items from the view, select the first item after the last selected const
RELOAD_ACTION_REMOVE = 2; // Moving items within a view, don't treat the dropped items
as additional // rows. const RELOAD_ACTION_MOVE = 3; // when removing a bunch of pages we
split them in chunks to avoid passing // a too big array to RemovePages // 300 is the
best choice with an history of about 150000 visits // smaller chunks could cause a Slow
Script warning with a huge history const REMOVE_PAGES_CHUNKLEN = 300; // if we are removing less than this
pages we will remove them one by one // since it will be reflected faster on the UI //
10 is a good compromise, since allows the user to delete a little amount of // urls
for privacy reasons, but does not cause heavy disk access const REMOVE_PAGES_MAX_SINGLEREMOVES
= 10; * Represents an insertion point within a container where we can insert * items.
* @param aItemId * The identifier of the parent container * @param aIndex * The index within
the container where we should insert * @param aOrientation * The orientation of the insertion.
NOTE: the adjustments to the * insertion point to accommodate the orientation should be done
by * the person who constructs the IP, not the user. The orientation * is provided for
informational purposes only! * @param [optional] aIsTag * Indicates if parent container is
a tag * @param [optional] aDropNearItemId * When defined we will calculate index based
on this itemId * @constructor function InsertionPoint(aItemId, aIndex, aOrientation, aIsTag, aDropNearItemId)
{ this.itemId = aItemId; this._index = aIndex; this.orientation = aOrientation; this.isTag
= aIsTag; this.dropNearItemId = aDropNearItemId; InsertionPoint.prototype = { set index(val)
{ return this._index = val; }, get index() { if (this.dropNearItemId > 0) { // If dropNearItemId
is set up we must calculate the real index of // the item near which we will drop. var
index = PlacesUtils.bookmarks.getItemIndex(this.dropNearItemId); return this.orientation == Ci.nsITreeView.DROP_BEFORE
? index : index + 1; } return this._index; * Places Controller function PlacesController(aView)
{ this._view = aView; PlacesController.prototype = { /** * The places view. */ _view: null,
isCommandEnabled: function PC_isCommandEnabled(aCommand) { switch (aCommand) { case "cmd_undo": return
PlacesUIUtils.ptm.numberOfUndoItems > 0; case "cmd_redo": return PlacesUIUtils.ptm.numberOfRedoItems
> 0; case "cmd_cut": case "placesCmd_cut": var nodes = this._view.getSelectionNodes();
// If selection includes history nodes there's no reason to allow cut. for (var i = 0; i
< nodes.length; i++) { if (nodes[i].itemId == -1) return false; } // Otherwise fallback
to cmd_delete check. case "cmd_delete": case "placesCmd_delete": return this._hasRemovableSelection(false);
case "placesCmd_deleteDataHost": return this._hasRemovableSelection(false) && !PlacesUIUtils.privateBrowsing.privateBrowsingEnabled;
case "placesCmd_moveBookmarks": return this._hasRemovableSelection(true); case "cmd_copy": case "placesCmd_copy": return
this._view.hasSelection; case "cmd_paste": case "placesCmd_paste": return this._canInsert(true)
&& this._isClipboardDataPasteable(); case "cmd_selectAll": if (this._view.selType !=
"single") { var rootNode = this._view.getResultNode(); if (rootNode.containerOpen && rootNode.childCount
> 0) return true; } return false; case "placesCmd_open": case "placesCmd_open:window": case "placesCmd_open:tab":
var selectedNode = this._view.selectedNode; return selectedNode && PlacesUtils.nodeIsURI(selectedNode);
case "placesCmd_new:folder": case "placesCmd_new:livemark": return this._canInsert(); case "placesCmd_new:bookmark":
return this._canInsert(); case "placesCmd_new:separator": return this._canInsert() && !asQuery(this._view.getResultNode()).queryOptions.excludeItems
&& this._view.getResult().sortingMode == Ci.nsINavHistoryQueryOptions.SORT_BY_NONE;
case "placesCmd_show:info": var selectedNode = this._view.selectedNode; if (selectedNode
&& PlacesUtils.getConcreteItemId(selectedNode) != -1 && !PlacesUtils.nodeIsLivemarkItem(selectedNode))
return true; return false; case "placesCmd_reloadMicrosummary": var selectedNode = this._view.selectedNode;
return selectedNode && PlacesUtils.nodeIsBookmark(selectedNode) && PlacesUIUtils.microsummaries.hasMicrosummary(selectedNode.itemId);
case "placesCmd_reload": // Livemark containers var selectedNode = this._view.selectedNode;
return selectedNode && PlacesUtils.nodeIsLivemarkContainer(selectedNode); case "placesCmd_sortBy:name": var selectedNode
= this._view.selectedNode; return selectedNode && PlacesUtils.nodeIsFolder(selectedNode)
&& !PlacesUtils.nodeIsReadOnly(selectedNode) && this._view.getResult().sortingMode ==
Ci.nsINavHistoryQueryOptions.SORT_BY_NONE; case "placesCmd_createBookmark": var node
= this._view.selectedNode; return node && PlacesUtils.nodeIsURI(node) && node.itemId
== -1; default: return false; } }, supportsCommand: function PC_supportsCommand(aCommand) { //LOG("supportsCommand:
" + command); // Non-Places specific commands that we also support switch (aCommand) {
case "cmd_undo": case "cmd_redo": case "cmd_cut": case "cmd_copy": case "cmd_paste": case "cmd_delete":
case "cmd_selectAll": return true; } // All other Places Commands are prefixed with "placesCmd_"
... this // filters out other commands that we do _not_ support (see 329587). const CMD_PREFIX
= "placesCmd_"; return (aCommand.substr(0, CMD_PREFIX.length) == CMD_PREFIX); }, doCommand:
function PC_doCommand(aCommand) { switch (aCommand) { case "cmd_undo": PlacesUIUtils.ptm.undoTransaction();
break; case "cmd_redo": PlacesUIUtils.ptm.redoTransaction(); break; case "cmd_cut": case "placesCmd_cut":
this.cut(); break; case "cmd_copy": case "placesCmd_copy": this.copy(); break; case "cmd_paste": case
"placesCmd_paste": this.paste(); break; case "cmd_delete": case "placesCmd_delete": this.remove("Remove
Selection"); break; case "placesCmd_deleteDataHost": var host; if (PlacesUtils.nodeIsHost(this._view.selectedNode))
{ var queries = this._view.selectedNode.getQueries({}); host = queries[0].domain; } else host = PlacesUtils._uri(this._view.selectedNode.uri).host;
PlacesUIUtils.privateBrowsing.removeDataFromDomain(host); break; case "cmd_selectAll": this.selectAll();
break; case "placesCmd_open": PlacesUIUtils.openNodeIn(this._view.selectedNode, "current"); break; case "placesCmd_open:window":
PlacesUIUtils.openNodeIn(this._view.selectedNode, "window"); break; case "placesCmd_open:tab":
PlacesUIUtils.openNodeIn(this._view.selectedNode, "tab"); break; case "placesCmd_new:folder":
this.newItem("folder"); break; case "placesCmd_new:bookmark": this.newItem("bookmark"); break; case "placesCmd_new:livemark":
this.newItem("livemark"); break; case "placesCmd_new:separator": this.newSeparator(); break; case "placesCmd_show:info":
this.showBookmarkPropertiesForSelection(); break; case "placesCmd_moveBookmarks": this.moveSelectedBookmarks();
break; case "placesCmd_reload": this.reloadSelectedLivemark(); break; case "placesCmd_reloadMicrosummary":
this.reloadSelectedMicrosummary(); break; case "placesCmd_sortBy:name": this.sortFolderByName();
break; case "placesCmd_createBookmark": var node = this._view.selectedNode; PlacesUIUtils.showMinimalAddBookmarkUI(PlacesUtils._uri(node.uri),
node.title); break; } }, onEvent: function PC_onEvent(eventName) { }, /** * Determine
whether or not the selection can be removed, either by the * delete or cut operations based
on whether or not any of its contents * are non-removable. We don't need to worry about
recursion here since it * is a policy decision that a removable item not be placed inside
a non- * removable item. * @param aIsMoveCommand * True if the command for which this method
is called only moves the * selected items to another container, false otherwise. *
@returns true if all nodes in the selection can be removed, * false otherwise. */ _hasRemovableSelection:
function PC__hasRemovableSelection(aIsMoveCommand) { var ranges = this._view.getRemovableSelectionRanges();
if (!ranges.length) return false; var root = this._view.getResultNode(); for (var j
= 0; j < ranges.length; j++) { var nodes = ranges[j]; for (var i = 0; i < nodes.length;
++i) { // Disallow removing the view's root node if (nodes[i] == root) return false; if
(PlacesUtils.nodeIsFolder(nodes[i]) && !PlacesControllerDragHelper.canMoveNode(nodes[i])) return false; // We don't call nodeIsReadOnly
here, because nodeIsReadOnly means that // a node has children that cannot be edited,
reordered or removed. Here, // we don't care if a node's children can't be reordered or
edited, just // that they're removable. All history results have removable children //
(based on the principle that any URL in the history table should be // removable), but
some special bookmark folders may have non-removable // children, e.g. live bookmark folder children.
It doesn't make sense // to delete a child of a live bookmark folder, since when the
folder // refreshes, the child will return. var parent = nodes[i].parent || root; if (PlacesUtils.isReadonlyFolder(parent))
return false; } } return true; }, /** * Determines whether or not nodes can be inserted relative
to the selection. */ _canInsert: function PC__canInsert(isPaste) { var ip = this._view.insertionPoint;
return ip != null && (isPaste || ip.isTag != true); }, /** * Determines whether or
not the root node for the view is selected */ rootNodeIsSelected: function PC_rootNodeIsSelected()
{ 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; },
/** * Looks at the data on the clipboard to see if it is paste-able. * Paste-able data
is: * - in a format that the view can receive * @returns true if: - clipboard data is of
a TYPE_X_MOZ_PLACE_* flavor, - clipboard data is of type TEXT_UNICODE and is a valid URI.
*/ _isClipboardDataPasteable: function PC__isClipboardDataPasteable() { // if the clipboard contains TYPE_X_MOZ_PLACE_*
data, it is definitely // pasteable, with no need to unwrap all the nodes. var flavors
= PlacesControllerDragHelper.placesFlavors; var clipboard = PlacesUIUtils.clipboard; var
hasPlacesData = clipboard.hasDataMatchingFlavors(flavors, flavors.length, Ci.nsIClipboard.kGlobalClipboard);
if (hasPlacesData) return this._view.insertionPoint != null; // if the clipboard doesn't have
TYPE_X_MOZ_PLACE_* data, we also allow // pasting of valid "text/unicode" and "text/x-moz-url"
data var xferable = Cc["@mozilla.org/widget/transferable;1"]. createInstance(Ci.nsITransferable); xferable.addDataFlavor(PlacesUtils.TYPE_X_MOZ_URL);
xferable.addDataFlavor(PlacesUtils.TYPE_UNICODE); clipboard.getData(xferable, Ci.nsIClipboard.kGlobalClipboard);
try { // getAnyTransferData will throw if no data is available. var data = { }, type
= { }; xferable.getAnyTransferData(type, data, { }); data = data.value.QueryInterface(Ci.nsISupportsString).data;
if (type.value != PlacesUtils.TYPE_X_MOZ_URL && type.value != PlacesUtils.TYPE_UNICODE)
return false; // unwrapNodes() will throw if the data blob is malformed. var unwrappedNodes
= PlacesUtils.unwrapNodes(data, type.value); return this._view.insertionPoint != null;
} catch (e) { // getAnyTransferData or unwrapNodes failed return false; } }, /** * Gathers information
about the selected nodes according to the following * rules: * "link" node is a URI
* "bookmark" node is a bookamrk * "livemarkChild" node is a child of a livemark * "tagChild"
node is a child of a tag * "folder" node is a folder * "query" node is a query * "dynamiccontainer"
node is a dynamic container * "separator" node is a separator line * "host" node is
a host * * @returns an array of objects corresponding the selected nodes. Each * object has each
of the properties above set if its corresponding * node matches the rule. In addition, the
annotations names for each * node are set on its corresponding object as properties.
* Notes: * 1) This can be slow, so don't call it anywhere performance critical! *
2) A single-object array corresponding the root node is returned if * there's no selection.
*/ _buildSelectionMetadata: function PC__buildSelectionMetadata() { var metadata = []; var root = this._view.getResultNode();
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 = {};
var node = nodes[i]; var nodeType = node.type; var uri = null; // We don't use the nodeIs*
methods here to avoid going through the type // property way too often 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; break; case Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER:
case Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER_SHORTCUT: nodeData["folder"] = true; break; case Ci.nsINavHistoryResultNode.RESULT_TYPE_SEPARATOR:
nodeData["separator"] = true; break; case Ci.nsINavHistoryResultNode.RESULT_TYPE_URI:
case Ci.nsINavHistoryResultNode.RESULT_TYPE_VISIT: case Ci.nsINavHistoryResultNode.RESULT_TYPE_FULL_VISIT:
nodeData["link"] = true; uri = PlacesUtils._uri(node.uri); if (PlacesUtils.nodeIsBookmark(node)) { nodeData["bookmark"]
= true; PlacesUtils.nodeIsTagQuery(node.parent) var mss = PlacesUIUtils.microsummaries; if
(mss.hasMicrosummary(node.itemId)) nodeData["microsummary"] = true; var parentNode = node.parent; if
(parentNode) { if (PlacesUtils.nodeIsTagQuery(parentNode)) nodeData["tagChild"] = true; else if (PlacesUtils.nodeIsLivemarkContainer(parentNode))
nodeData["livemarkChild"] = true; } } break; } // annotations if (uri) { var names =
PlacesUtils.annotations.getPageAnnotationNames(uri, {}); for (var j = 0; j < names.length; ++j)
nodeData[names[j]] = true; } // For items also include the item-specific annotations
if (node.itemId != -1) { names = PlacesUtils.annotations .getItemAnnotationNames(node.itemId, {});
for (j = 0; j < names.length; ++j) nodeData[names[j]] = true; } metadata.push(nodeData); } return
metadata; }, /** * Determines if a context-menu item should be shown * @param aMenuItem *
the context menu item * @param aMetaData * meta data about the selection * @returns
true if the conditions (see buildContextMenu) are satisfied * and the item can be displayed,
false otherwise. */ _shouldShowMenuItem: function PC__shouldShowMenuItem(aMenuItem, aMetaData)
{ var selectiontype = aMenuItem.getAttribute("selectiontype"); if (selectiontype == "multiple" && aMetaData.length
== 1) return false; if (selectiontype == "single" && aMetaData.length != 1) return
false; var forceHideAttr = aMenuItem.getAttribute("forcehideselection"); if (forceHideAttr) { var forceHideRules =
forceHideAttr.split("|"); for (var i = 0; i < aMetaData.length; ++i) { for (var j=0;
j < forceHideRules.length; ++j) { if (forceHideRules[j] in aMetaData[i]) return false; } } } var selectionAttr
= aMenuItem.getAttribute("selection"); if (selectionAttr) { if (selectionAttr == "any")
return true; var showRules = selectionAttr.split("|"); var anyMatched = false; function metaDataNodeMatches(metaDataNode,
rules) { for (var i=0; i < rules.length; i++) { if (rules[i] in metaDataNode) return true;
} return false; } for (var i = 0; i < aMetaData.length; ++i) { if (metaDataNodeMatches(aMetaData[i],
showRules)) anyMatched = true; else return false; } return anyMatched; } return !aMenuItem.hidden;
}, /** * Detects information (meta-data rules) about the current selection in the * view
(see _buildSelectionMetadata) and sets the visibility state for each * of the menu-items
in the given popup with the following rules applied: * 1) The "selectiontype" attribute
may be set on a menu-item to "single" * if the menu-item should be visible only if there
is a single node * selected, or to "multiple" if the menu-item should be visible only if
* multiple nodes are selected. If the attribute is not set or if it is * set to an invalid
value, the menu-item may be visible for both types of * selection. * 2) The "selection"
attribute may be set on a menu-item to the various * meta-data rules for which it may
be visible. The rules should be * separated with the | character. * 3) A menu-item may
be visible only if at least one of the rules set in * its selection attribute apply to
each of the selected nodes in the * view. * 4) The "forcehideselection" attribute may
be set on a menu-item to rules * for which it should be hidden. This attribute takes
priority over the * selection attribute. A menu-item would be hidden if at least one
of the * given rules apply to one of the selected nodes. The rules should be * separated with
the | character. * 5) The "hideifnoinsertionpoint" attribute may be set on a menu-item to *
true if it should be hidden when there's no insertion point * 6) The visibility state
of a menu-item is unchanged if none of these * attribute are set. * 7) These attributes
should not be set on separators for which the * visibility state is "auto-detected."
* 8) The "hideifprivatebrowsing" attribute may be set on a menu-item to * true if it
should be hidden inside the private browsing mode * @param aPopup * The menupopup to build
children into. * @return true if at least one item is visible, false otherwise. */
buildContextMenu: function PC_buildContextMenu(aPopup) { var metadata = this._buildSelectionMetadata();
var ip = this._view.insertionPoint; var noIp = !ip || ip.isTag; var separator = null;
var visibleItemsBeforeSep = false; var anyVisible = false; for (var i = 0; i < aPopup.childNodes.length;
++i) { var item = aPopup.childNodes[i]; if (item.localName != "menuseparator") { //
We allow pasting into tag containers, so special case that. var hideIfNoIP = item.getAttribute("hideifnoinsertionpoint")
== "true" && noIp && !(ip && ip.isTag && item.id == "placesContext_paste"); var hideIfPB
= item.getAttribute("hideifprivatebrowsing") == "true" && PlacesUIUtils.privateBrowsing.privateBrowsingEnabled;
item.hidden = hideIfNoIP || hideIfPB || !this._shouldShowMenuItem(item, metadata); if (!item.hidden) { visibleItemsBeforeSep
= true; anyVisible = true; // Show the separator above the menu-item if any if (separator)
{ separator.hidden = false; separator = null; } } } else { // menuseparator // Initially
hide it. It will be unhidden if there will be at least one // visible menu-item above
and below it. item.hidden = true; // We won't show the separator at all if no items are
visible above it if (visibleItemsBeforeSep) separator = item; // New separator, count
again: visibleItemsBeforeSep = false; } } // Set Open Folder/Links In Tabs items enabled
state if they're visible if (anyVisible) { var openContainerInTabsItem = document.getElementById("placesContext_openContainer:tabs");
if (!openContainerInTabsItem.hidden && this._view.selectedNode && PlacesUtils.nodeIsContainer(this._view.selectedNode))
{ openContainerInTabsItem.disabled = !PlacesUtils.hasChildURIs(this._view.selectedNode); } else { // see selectiontype rule in the
overlay var openLinksInTabsItem = document.getElementById("placesContext_openLinks:tabs"); openLinksInTabsItem.disabled = openLinksInTabsItem.hidden;
} } return anyVisible; }, /** * Select all links in the current view. */ selectAll: function
PC_selectAll() { this._view.selectAll(); }, /** * Opens the bookmark properties for
the selected URI Node. */ showBookmarkPropertiesForSelection: function PC_showBookmarkPropertiesForSelection()
{ var node = this._view.selectedNode; if (!node) return; var itemType = PlacesUtils.nodeIsFolder(node)
|| PlacesUtils.nodeIsTagQuery(node) ? "folder" : "bookmark"; var concreteId = PlacesUtils.getConcreteItemId(node);
var isRootItem = PlacesUtils.isRootItem(concreteId); var itemId = node.itemId; if (isRootItem
|| PlacesUtils.nodeIsTagQuery(node)) { // If this is a root or the Tags query we use
the concrete itemId to catch // the correct title for the node. itemId = concreteId;
} PlacesUIUtils.showItemProperties(itemId, itemType, isRootItem /* read only */); },
/** * This method can be run on a URI parameter to ensure that it didn't * receive a string
instead of an nsIURI object. */ _assertURINotString: function PC__assertURINotString(value) {
NS_ASSERT((typeof(value) == "object") && !(value instanceof String), "This method should
be passed a URI as a nsIURI object, not as a string."); }, /** * Reloads the selected
livemark if any. */ reloadSelectedLivemark: function PC_reloadSelectedLivemark() { var
selectedNode = this._view.selectedNode; if (selectedNode && PlacesUtils.nodeIsLivemarkContainer(selectedNode))
PlacesUtils.livemarks.reloadLivemarkFolder(selectedNode.itemId); }, /** * Reload the microsummary associated
with the selection */ reloadSelectedMicrosummary: function PC_reloadSelectedMicrosummary()
{ var selectedNode = this._view.selectedNode; var mss = PlacesUIUtils.microsummaries; if
(mss.hasMicrosummary(selectedNode.itemId)) mss.refreshMicrosummary(selectedNode.itemId);
}, /** * Gives the user a chance to cancel loading lots of tabs at once */ _confirmOpenTabs:
function(numTabsToOpen) { var pref = Cc["@mozilla.org/preferences-service;1"]. getService(Ci.nsIPrefBranch); const kWarnOnOpenPref
= "browser.tabs.warnOnOpen"; var reallyOpen = true; if (pref.getBoolPref(kWarnOnOpenPref))
{ if (numTabsToOpen >= pref.getIntPref("browser.tabs.maxOpenBeforeWarn")) { var promptService = Cc["@mozilla.org/embedcomp/prompt-service;1"].
getService(Ci.nsIPromptService); // default to true: if it were false, we wouldn't get
this far var warnOnOpen = { value: true }; var messageKey = "tabs.openWarningMultipleBranded";
var openKey = "tabs.openButtonMultiple"; var strings = document.getElementById("placeBundle");
const BRANDING_BUNDLE_URI = "chrome://branding/locale/brand.properties"; var brandShortName = Cc["@mozilla.org/intl/stringbundle;1"].
getService(Ci.nsIStringBundleService). createBundle(BRANDING_BUNDLE_URI). GetStringFromName("brandShortName"); var buttonPressed
= promptService.confirmEx(window, PlacesUIUtils.getString("tabs.openWarningTitle"), PlacesUIUtils.getFormattedString(messageKey,
[numTabsToOpen, brandShortName]), (promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_0) + (promptService.BUTTON_TITLE_CANCEL
* promptService.BUTTON_POS_1), PlacesUIUtils.getString(openKey), null, null, PlacesUIUtils.getFormattedString("tabs.openWarningPromptMeBranded",
[brandShortName]), warnOnOpen); reallyOpen = (buttonPressed == 0); // don't set the
pref unless they press OK and it's false if (reallyOpen && !warnOnOpen.value) pref.setBoolPref(kWarnOnOpenPref,
false); } } return reallyOpen; }, /** * Opens the links in the selected folder, or the selected
links in new tabs. */ openSelectionInTabs: function PC_openLinksInTabs(aEvent) { var
node = this._view.selectedNode; if (node && PlacesUtils.nodeIsContainer(node)) PlacesUIUtils.openContainerNodeInTabs(this._view.selectedNode,
aEvent); else PlacesUIUtils.openURINodesInTabs(this._view.getSelectionNodes(), aEvent); }, /** * Shows the Add Bookmark UI
for the current insertion point. * * @param aType * the type of the new item (bookmark/livemark/folder)
*/ newItem: function PC_newItem(aType) { var ip = this._view.insertionPoint; if (!ip)
throw Cr.NS_ERROR_NOT_AVAILABLE; var performed = false; if (aType == "bookmark") performed
= PlacesUIUtils.showAddBookmarkUI(null, null, null, ip); else if (aType == "livemark") performed
= PlacesUIUtils.showAddLivemarkUI(null, null, null, null, ip); else // folder performed
= PlacesUIUtils.showAddFolderUI(null, ip); if (performed) { // select the new item var
insertedNodeId = PlacesUtils.bookmarks .getIdForItemAt(ip.itemId, ip.index); this._view.selectItems([insertedNodeId],
false); } }, /** * Create a new Bookmark folder somewhere. Prompts the user for the name
* of the folder. */ newFolder: function PC_newFolder() { var ip = this._view.insertionPoint; if
(!ip) throw Cr.NS_ERROR_NOT_AVAILABLE; var performed = false; performed = PlacesUIUtils.showAddFolderUI(null,
ip); if (performed) { // select the new item var insertedNodeId = PlacesUtils.bookmarks
.getIdForItemAt(ip.itemId, ip.index); this._view.selectItems([insertedNodeId], false); } }, /** * Create a new Bookmark separator
somewhere. */ newSeparator: function PC_newSeparator() { var ip = this._view.insertionPoint; if
(!ip) throw Cr.NS_ERROR_NOT_AVAILABLE; var txn = PlacesUIUtils.ptm.createSeparator(ip.itemId,
ip.index); PlacesUIUtils.ptm.doTransaction(txn); // select the new item var insertedNodeId
= PlacesUtils.bookmarks .getIdForItemAt(ip.itemId, ip.index); this._view.selectItems([insertedNodeId],
false); }, /** * Opens a dialog for moving the selected nodes. */ moveSelectedBookmarks:
function PC_moveBookmarks() { window.openDialog("chrome://browser/content/places/moveBookmarks.xul", "", "chrome, modal", this._view.getSelectionNodes());
}, /** * Sort the selected folder by name */ sortFolderByName: function PC_sortFolderByName()
{ var itemId = PlacesUtils.getConcreteItemId(this._view.selectedNode); var txn = PlacesUIUtils.ptm.sortFolderByName(itemId);
PlacesUIUtils.ptm.doTransaction(txn); }, /** * Walk the list of folders we're removing
in this delete operation, and * see if the selected node specified is already implicitly
being removed * because it is a child of that folder. * @param node * Node to check for
containment. * @param pastFolders * List of folders the calling function has already traversed
* @returns true if the node should be skipped, false otherwise. */ _shouldSkipNode: function
PC_shouldSkipNode(node, pastFolders) { /** * Determines if a node is contained by another
node within a resultset. * @param node * The node to check for containment for * @param
parent * The parent container to check for containment in * @returns true if node is
a member of parent's children, false otherwise. */ function isContainedBy(node, parent)
{ var cursor = node.parent; while (cursor) { if (cursor == parent) return true; cursor
= cursor.parent; } return false; } for (var j = 0; j < pastFolders.length; ++j) { if (isContainedBy(node,
pastFolders[j])) return true; } return false; }, /** * Creates a set of transactions for
the removal of a range of items. * A range is an array of adjacent nodes in a view.
* @param [in] range * An array of nodes to remove. Should all be adjacent. * @param [out]
transactions * An array of transactions. * @param [optional] removedFolders * An array
of folder nodes that have already been removed. */ _removeRange: function PC__removeRange(range,
transactions, removedFolders) { NS_ASSERT(transactions instanceof Array, "Must pass a transactions
array"); if (!removedFolders) removedFolders = []; for (var i = 0; i < range.length; ++i)
{ var node = range[i]; if (this._shouldSkipNode(node, removedFolders)) continue; if (PlacesUtils.nodeIsTagQuery(node.parent))
{ // This is a uri node inside a tag container. It needs a special // untag transaction. var
tagItemId = PlacesUtils.getConcreteItemId(node.parent); var uri = PlacesUtils._uri(node.uri); transactions.push(PlacesUIUtils.ptm.untagURI(uri,
[tagItemId])); } else if (PlacesUtils.nodeIsTagQuery(node) && node.parent && PlacesUtils.nodeIsQuery(node.parent)
&& asQuery(node.parent).queryOptions.resultType == Ci.nsINavHistoryQueryOptions.RESULTS_AS_TAG_QUERY)
{ // This is a tag container. // Untag all URIs tagged with this tag only if the tag
container is // child of the "Tags" query in the library, in all other places we //
must only remove the query node. var tag = node.title; var URIs = PlacesUtils.tagging.getURIsForTag(tag);
for (var j = 0; j < URIs.length; j++) transactions.push(PlacesUIUtils.ptm.untagURI(URIs[j], [tag])); } else if (PlacesUtils.nodeIsURI(node)
&& PlacesUtils.nodeIsQuery(node.parent) && asQuery(node.parent).queryOptions.queryType
== Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY) { // This is a uri node inside an history
query. var bhist = PlacesUtils.history.QueryInterface(Ci.nsIBrowserHistory); bhist.removePage(PlacesUtils._uri(node.uri));
// History deletes are not undoable, so we don't have a transaction. } else if (node.itemId
== -1 && PlacesUtils.nodeIsQuery(node) && asQuery(node).queryOptions.queryType ==
Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY) { // This is a dynamically generated history
query, like queries // grouped by site, time or both. Dynamically generated queries don't
// have an itemId even if they are descendants of a bookmark. this._removeHistoryContainer(node);
// History deletes are not undoable, so we don't have a transaction. } else { // This
is a common bookmark item. if (PlacesUtils.nodeIsFolder(node)) { // If this is a folder we add it to our
array of folders, used // to skip nodes that are children of an already removed folder.
removedFolders.push(node); } transactions.push(PlacesUIUtils.ptm.removeItem(node.itemId)); } } }, /** * Removes the set of selected
ranges from bookmarks. * @param txnName * See |remove|. */ _removeRowsFromBookmarks:
function PC__removeRowsFromBookmarks(txnName) { var ranges = this._view.getRemovableSelectionRanges();
var transactions = []; var removedFolders = []; for (var i = 0; i < ranges.length;
i++) this._removeRange(ranges[i], transactions, removedFolders); if (transactions.length
> 0) { var txn = PlacesUIUtils.ptm.aggregateTransactions(txnName, transactions); PlacesUIUtils.ptm.doTransaction(txn);
} }, /** * Removes the set of selected ranges from history. */ _removeRowsFromHistory: function
PC__removeRowsFromHistory() { // Other containers are history queries, just delete from history
// history deletes are not undoable. var nodes = this._view.getSelectionNodes(); var
URIs = []; var bhist = PlacesUtils.history.QueryInterface(Ci.nsIBrowserHistory); var root = this._view.getResultNode(); for
(var i = 0; i < nodes.length; ++i) { var node = nodes[i]; if (PlacesUtils.nodeIsURI(node))
{ var uri = PlacesUtils._uri(node.uri); // avoid trying to delete the same url twice
if (URIs.indexOf(uri) < 0) { URIs.push(uri); } } else if (PlacesUtils.nodeIsQuery(node)
&& asQuery(node).queryOptions.queryType == Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY)
this._removeHistoryContainer(node); } // if we have to delete a lot of urls RemovePage
will be slow, it's better // to delete them in bunch and rebuild the full treeView if
(URIs.length > REMOVE_PAGES_MAX_SINGLEREMOVES) { // do removal in chunks to avoid passing
a too big array to removePages for (var i = 0; i < URIs.length; i += REMOVE_PAGES_CHUNKLEN)
{ var URIslice = URIs.slice(i, i + REMOVE_PAGES_CHUNKLEN); // set DoBatchNotify (third param) only on
the last chunk, so we update // the treeView when we are done. bhist.removePages(URIslice,
URIslice.length, (i + REMOVE_PAGES_CHUNKLEN) >= URIs.length); } } else { // if we have
to delete fewer urls, removepage will allow us to avoid // rebuilding the full treeView
for (var i = 0; i < URIs.length; ++i) bhist.removePage(URIs[i]); } }, /** * Removes history visits for an
history container node. * @param [in] aContainerNode * The container node to remove. */ _removeHistoryContainer:
function PC_removeHistoryContainer(aContainerNode) { var bhist = PlacesUtils.history.QueryInterface(Ci.nsIBrowserHistory);
if (PlacesUtils.nodeIsHost(aContainerNode)) { // Site container. bhist.removePagesFromHost(aContainerNode.title,
true); } else if (PlacesUtils.nodeIsDay(aContainerNode)) { // Day container. var query = aContainerNode.getQueries({})[0];
var beginTime = query.beginTime; var endTime = query.endTime; NS_ASSERT(query && beginTime
&& endTime, "A valid date container query should exist!"); // We want to exclude beginTime
from the removal because // removePagesByTimeframe includes both extremes, while date containers
// exclude the lower extreme. So, if we would not exclude it, we would // end up removing
more history than requested. bhist.removePagesByTimeframe(beginTime+1, endTime); } }, /** * Removes the selection
* @param aTxnName * A name for the transaction if this is being performed * as part of another
operation. */ remove: function PC_remove(aTxnName) { if (!this._hasRemovableSelection(false))
return; NS_ASSERT(aTxnName !== undefined, "Must supply Transaction Name"); var root
= this._view.getResultNode(); if (PlacesUtils.nodeIsFolder(root)) this._removeRowsFromBookmarks(aTxnName); else
if (PlacesUtils.nodeIsQuery(root)) { var queryType = asQuery(root).queryOptions.queryType; if
(queryType == Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS) this._removeRowsFromBookmarks(aTxnName); else
if (queryType == Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY) this._removeRowsFromHistory(); else NS_ASSERT(false,
"implement support for QUERY_TYPE_UNIFIED"); } else NS_ASSERT(false, "unexpected root");
}, /** * Fills a DataTransfer object with the content of the selection that can be
* dropped elsewhere. * @param aEvent * The dragstart event. */ setDataTransfer: function
PC_setDataTransfer(aEvent) { var dt = aEvent.dataTransfer; var doCopy = ["copyLink", "copy", "link"].indexOf(dt.effectAllowed)
!= -1; var result = this._view.getResult(); var oldViewer = result.viewer; try { result.viewer
= null; var nodes = this._view.getDraggableSelection(); for (var i = 0; i < nodes.length; ++i) {
var node = nodes[i]; function addData(type, index, overrideURI) { var wrapNode = PlacesUtils.wrapNode(node,
type, overrideURI, doCopy); dt.mozSetDataAt(type, wrapNode, index); } function addURIData(index,
overrideURI) { addData(PlacesUtils.TYPE_X_MOZ_URL, index, overrideURI); addData(PlacesUtils.TYPE_UNICODE,
index, overrideURI); addData(PlacesUtils.TYPE_HTML, index, overrideURI); } // This order is _important_!
It controls how this and other // applications select data to be inserted based on type.
addData(PlacesUtils.TYPE_X_MOZ_PLACE, i); // Drop the feed uri for livemark containers
if (PlacesUtils.nodeIsLivemarkContainer(node)) addURIData(i, PlacesUtils.livemarks.getFeedURI(node.itemId).spec);
else if (node.uri) addURIData(i); } } finally { if (oldViewer) result.viewer = oldViewer;
} }, /** * Copy Bookmarks and Folders to the clipboard */ copy: function PC_copy()
{ var result = this._view.getResult(); var oldViewer = result.viewer; try { result.viewer
= null; 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; placeString = mozURLString
= htmlString = unicodeString = ""; for (var i = 0; i < nodes.length; ++i) { var node
= nodes[i]; if (this._shouldSkipNode(node, copiedFolders)) continue; if (PlacesUtils.nodeIsFolder(node))
copiedFolders.push(node); function generateChunk(type, overrideURI) { var suffix = i < (nodes.length
- 1) ? NEWLINE : ""; var uri = overrideURI; if (PlacesUtils.nodeIsLivemarkContainer(node))
uri = PlacesUtils.livemarks.getFeedURI(node.itemId).spec mozURLString += (PlacesUtils.wrapNode(node,
PlacesUtils.TYPE_X_MOZ_URL, uri) + suffix); unicodeString += (PlacesUtils.wrapNode(node,
PlacesUtils.TYPE_UNICODE, uri) + suffix); htmlString += (PlacesUtils.wrapNode(node,
PlacesUtils.TYPE_HTML, uri) + suffix); var placeSuffix = i < (nodes.length - 1) ? ","
: ""; var resolveShortcuts = !PlacesControllerDragHelper.canMoveNode(node); return PlacesUtils.wrapNode(node, type, overrideURI,
resolveShortcuts) + placeSuffix; } // all items wrapped as TYPE_X_MOZ_PLACE placeString
+= generateChunk(PlacesUtils.TYPE_X_MOZ_PLACE); } function addData(type, data) { xferable.addDataFlavor(type);
xferable.setTransferData(type, PlacesUIUtils._wrapString(data), data.length * 2); } // This order is _important_!
It controls how this and other applications // select data to be inserted based on type.
if (placeString) addData(PlacesUtils.TYPE_X_MOZ_PLACE, placeString); if (mozURLString) addData(PlacesUtils.TYPE_X_MOZ_URL,
mozURLString); if (unicodeString) addData(PlacesUtils.TYPE_UNICODE, unicodeString); if (htmlString) addData(PlacesUtils.TYPE_HTML,
htmlString); if (placeString || unicodeString || htmlString || mozURLString) { PlacesUIUtils.clipboard.setData(xferable,
null, Ci.nsIClipboard.kGlobalClipboard); } } finally { if (oldViewer) result.viewer
= oldViewer; } }, /** * Cut Bookmarks and Folders to the clipboard */ cut: function
PC_cut() { this.copy(); this.remove("Cut Selection"); }, /** * Paste Bookmarks and Folders from
the clipboard */ paste: function PC_paste() { // Strategy: // // There can be data of
various types (folder, separator, link) on the // clipboard. We need to get all of that
data and build edit transactions // for them. This means asking the clipboard once for each
type and // aggregating the results. /** * Constructs a transferable that can receive
data of specific types. * @param types * The types of data the transferable can hold,
in order of * preference. * @returns The transferable. */ function makeXferable(types) { var xferable
= Cc["@mozilla.org/widget/transferable;1"]. createInstance(Ci.nsITransferable); for (var
i = 0; i < types.length; ++i) xferable.addDataFlavor(types[i]); return xferable; } var clipboard = PlacesUIUtils.clipboard;
var ip = this._view.insertionPoint; if (!ip) throw Cr.NS_ERROR_NOT_AVAILABLE; /** * Gets
a list of transactions to perform the paste of specific types. * @param types * The types
of data to form paste transactions for * @returns An array of transactions that perform
the paste. */ function getTransactions(types) { var xferable = makeXferable(types); clipboard.getData(xferable,
Ci.nsIClipboard.kGlobalClipboard); var data = { }, type = { }; try { xferable.getAnyTransferData(type,
data, { }); data = data.value.QueryInterface(Ci.nsISupportsString).data; var items = PlacesUtils.unwrapNodes(data,
type.value); var transactions = []; var index = ip.index; for (var i = 0; i < items.length;
++i) { var txn; if (ip.isTag) { var uri = PlacesUtils._uri(items[i].uri); txn = PlacesUIUtils.ptm.tagURI(uri,
[ip.itemId]); } else { // adjusted to make sure that items are given the correct index
// transactions insert differently if index == -1 // transaction will enqueue the item.
if (ip.index > -1) index = ip.index + i; txn = PlacesUIUtils.makeTransaction(items[i],
type.value, ip.itemId, index, true); } transactions.push(txn); } return transactions; } catch (e) { //
getAnyTransferData will throw if there is no data of the specified // type on the clipboard.
// unwrapNodes will throw if the data that is present is malformed in // some way. //
In either case, don't fail horribly, just return no data. } return []; } // Get transactions
to paste any folders, separators or links that might // be on the clipboard, aggregate
them and execute them. var transactions = getTransactions([PlacesUtils.TYPE_X_MOZ_PLACE,
PlacesUtils.TYPE_X_MOZ_URL, PlacesUtils.TYPE_UNICODE]); var txn = PlacesUIUtils.ptm.aggregateTransactions("Paste",
transactions); PlacesUIUtils.ptm.doTransaction(txn); // select the pasted items, they should be
consecutive var insertedNodeIds = []; for (var i = 0; i < transactions.length; ++i)
insertedNodeIds.push(PlacesUtils.bookmarks .getIdForItemAt(ip.itemId, ip.index + i));
if (insertedNodeIds.length > 0) this._view.selectItems(insertedNodeIds, false); * Handles drag and drop operations
for views. Note that this is view agnostic! * You should not use PlacesController._view
within these methods, since * the view that the item(s) have been dropped on was not necessarily
active. * Drop functions are passed the view that is being dropped on. var PlacesControllerDragHelper
= { /** * DOM Element currently being dragged over */ currentDropTarget: null, /** * Current
nsIDOMDataTransfer * We need to cache this because we don't have access to the event
in the * treeView's canDrop or drop methods, and session.dataTransfer would not be * filled
for drag and drop from external sources (eg. the OS). */ currentDataTransfer: null, /**
* Determines if the mouse is currently being dragged over a child node of * this menu.
This is necessary so that the menu doesn't close while the * mouse is dragging over one
of its submenus * @param node * The container node * @returns true if the user is dragging
over a node within the hierarchy of * the container, false otherwise. */ draggingOverChildNode:
function PCDH_draggingOverChildNode(node) { var currentNode = this.currentDropTarget;
while (currentNode) { if (currentNode == node) return true; currentNode = currentNode.parentNode;
} return false; }, /** * @returns The current active drag session. Returns null if there
is none. */ getSession: function PCDH__getSession() { var dragService = Cc["@mozilla.org/widget/dragservice;1"].
getService(Ci.nsIDragService); return dragService.getCurrentSession(); }, /** * Extract the first accepted flavor
from a flavors array. * @param aFlavors * The flavors array. */ getFirstValidFlavor:
function PCDH_getFirstValidFlavor(aFlavors) { for (var i = 0; i < aFlavors.length; i++)
{ if (this.GENERIC_VIEW_DROP_TYPES.indexOf(aFlavors[i]) != -1) return aFlavors[i]; } return null;
}, /** * Determines whether or not the data currently being dragged can be dropped *
on a places view. * @param ip * The insertion point where the items should be dropped */
canDrop: function PCDH_canDrop(ip) { var dt = this.currentDataTransfer; var dropCount
= dt.mozItemCount; // Check every dragged item for (var i = 0; i < dropCount; i++)
{ var flavor = this.getFirstValidFlavor(dt.mozTypesAt(i)); if (!flavor) return false; var data = dt.mozGetDataAt(flavor,
i); // urls can be dropped on any insertionpoint // XXXmano: // Remember: this method is called
for each dragover event! // Thus we shouldn't use unwrapNodes here at all if possible.
// I think it would be OK to accept bogus data here (e.g. text which was // somehow
wrapped as TAB_DROP_TYPE, this is not in our control, and // will just case the actual
drop to be a no-op), and only rule out valid // expected cases, which are either unsupported
flavors, or items which // cannot be dropped in the current insertionpoint. The last case
will // likely force us to use unwrapNodes for the private data types of // places. if
(flavor == TAB_DROP_TYPE) continue; try { var dragged = PlacesUtils.unwrapNodes(data,
flavor)[0]; } catch (e) { return false; } // Only bookmarks and urls can be dropped
into tag containers if (ip.isTag && ip.orientation == Ci.nsITreeView.DROP_ON && dragged.type
!= PlacesUtils.TYPE_X_MOZ_URL && (dragged.type != PlacesUtils.TYPE_X_MOZ_PLACE || /^place:/.test(dragged.uri)))
return false; // The following loop disallows the dropping of a folder on itself or //
on any of its descendants. if (dragged.type == PlacesUtils.TYPE_X_MOZ_PLACE_CONTAINER
|| /^place:/.test(dragged.uri)) { var parentId = ip.itemId; while (parentId != PlacesUtils.placesRootId)
{ if (dragged.concreteId == parentId || dragged.id == parentId) return false; parentId
= PlacesUtils.bookmarks.getFolderIdForItem(parentId); } } } return true; }, /** * Determines if
a node can be moved. * * @param aNode * A nsINavHistoryResultNode node. * @returns True
if the node can be moved, false otherwise. */ canMoveNode: function PCDH_canMoveNode(aNode)
{ // can't move query root if (!aNode.parent) return false; var parentId = PlacesUtils.getConcreteItemId(aNode.parent);
var concreteId = PlacesUtils.getConcreteItemId(aNode); // can't move children of tag containers
if (PlacesUtils.nodeIsTagQuery(aNode.parent)) return false; // can't move children of read-only
containers if (PlacesUtils.nodeIsReadOnly(aNode.parent)) return false; // check for special folders,
etc if (PlacesUtils.nodeIsContainer(aNode) && !this.canMoveContainer(aNode.itemId, parentId))
return false; return true; }, /** * Determines if a container node can be moved. * * @param
aId * A bookmark folder id. * @param [optional] aParentId * The parent id of the folder.
* @returns True if the container can be moved to the target. */ canMoveContainer: function
PCDH_canMoveContainer(aId, aParentId) { if (aId == -1) return false; // Disallow moving
of roots and special folders const ROOTS = [PlacesUtils.placesRootId, PlacesUtils.bookmarksMenuFolderId,
PlacesUtils.tagsFolderId, PlacesUtils.unfiledBookmarksFolderId, PlacesUtils.toolbarFolderId]; if (ROOTS.indexOf(aId)
!= -1) return false; // Get parent id if necessary if (aParentId == null || aParentId
== -1) aParentId = PlacesUtils.bookmarks.getFolderIdForItem(aId); if (PlacesUtils.bookmarks.getFolderReadonly(aParentId))
return false; return true; }, /** * Handles the drop of one or more items onto a view.
* @param insertionPoint * The insertion point where the items should be dropped */ onDrop:
function PCDH_onDrop(insertionPoint) { var dt = this.currentDataTransfer; var doCopy
= ["copy", "link"].indexOf(dt.dropEffect) != -1; var transactions = []; var dropCount
= dt.mozItemCount; var movedCount = 0; for (var i = 0; i < dropCount; ++i) { var flavor
= this.getFirstValidFlavor(dt.mozTypesAt(i)); if (!flavor) return false; var data = dt.mozGetDataAt(flavor,
i); var unwrapped; if (flavor != TAB_DROP_TYPE) { // There's only ever one in the D&D case.
unwrapped = PlacesUtils.unwrapNodes(data, flavor)[0]; } else if (data instanceof XULElement
&& data.localName == "tab" && data.ownerDocument.defaultView instanceof ChromeWindow) { var uri = data.linkedBrowser.currentURI;
var spec = uri ? uri.spec : "about:blank"; var title = data.label; unwrapped = { uri:
spec, title: data.label, type: PlacesUtils.TYPE_X_MOZ_URL}; } else throw("bogus data was passed as a
tab") var index = insertionPoint.index; // Adjust insertion index to prevent reversal
of dragged items. When you // drag multiple elts upward: need to increment index or each
successive // elt will be inserted at the same index, each above the previous. var dragginUp
= insertionPoint.itemId == unwrapped.parent && index < PlacesUtils.bookmarks.getItemIndex(unwrapped.id);
if (index != -1 && dragginUp) index+= movedCount++; // if dragging over a tag container we should
tag the item if (insertionPoint.isTag && insertionPoint.orientation == Ci.nsITreeView.DROP_ON)
{ var uri = PlacesUtils._uri(unwrapped.uri); var tagItemId = insertionPoint.itemId; transactions.push(PlacesUIUtils.ptm.tagURI(uri,[tagItemId]));
} else { transactions.push(PlacesUIUtils.makeTransaction(unwrapped, flavor, insertionPoint.itemId, index, doCopy));
} } var txn = PlacesUIUtils.ptm.aggregateTransactions("DropItems", transactions); PlacesUIUtils.ptm.doTransaction(txn);
}, /** * Checks if we can insert into a container. * @param aContainer * The container were
we are want to drop */ disallowInsertion: function(aContainer) { NS_ASSERT(aContainer,
"empty container"); // allow dropping into Tag containers if (PlacesUtils.nodeIsTagQuery(aContainer))
return false; // Disallow insertion of items under readonly folders return (!PlacesUtils.nodeIsFolder(aContainer)
|| PlacesUtils.nodeIsReadOnly(aContainer)); }, placesFlavors: [PlacesUtils.TYPE_X_MOZ_PLACE_CONTAINER,
PlacesUtils.TYPE_X_MOZ_PLACE_SEPARATOR, PlacesUtils.TYPE_X_MOZ_PLACE], // The order matters. GENERIC_VIEW_DROP_TYPES:
[PlacesUtils.TYPE_X_MOZ_PLACE_CONTAINER, PlacesUtils.TYPE_X_MOZ_PLACE_SEPARATOR, PlacesUtils.TYPE_X_MOZ_PLACE, PlacesUtils.TYPE_X_MOZ_URL,
TAB_DROP_TYPE, PlacesUtils.TYPE_UNICODE], /** * Returns our flavourSet */ get flavourSet()
{ delete this.flavourSet; var flavourSet = new FlavourSet(); var acceptedDropFlavours
= this.GENERIC_VIEW_DROP_TYPES; acceptedDropFlavours.forEach(flavourSet.appendFlavour, flavourSet); return this.flavourSet = flavourSet;
function goUpdatePlacesCommands() { // Get the controller for one of the places commands.
var placesController = doGetPlacesControllerForCommand("placesCmd_open"); if (!placesController) return; function updatePlacesCommand(aCommand)
{ goSetCommandEnabled(aCommand, placesController.isCommandEnabled(aCommand)); updatePlacesCommand("placesCmd_open"); updatePlacesCommand("placesCmd_open:window");
updatePlacesCommand("placesCmd_open:tab"); updatePlacesCommand("placesCmd_new:folder");
updatePlacesCommand("placesCmd_new:bookmark"); updatePlacesCommand("placesCmd_new:livemark");
updatePlacesCommand("placesCmd_new:separator"); updatePlacesCommand("placesCmd_show:info");
updatePlacesCommand("placesCmd_moveBookmarks"); updatePlacesCommand("placesCmd_reload"); updatePlacesCommand("placesCmd_reloadMicrosummary");
updatePlacesCommand("placesCmd_sortBy:name"); updatePlacesCommand("placesCmd_cut"); updatePlacesCommand("placesCmd_copy");
updatePlacesCommand("placesCmd_paste"); updatePlacesCommand("placesCmd_delete"); function doGetPlacesControllerForCommand(aCommand)
var placesController = top.document.commandDispatcher .getControllerForCommand(aCommand); if (!placesController)
{ // If building commands for a context menu, look for an element in the // current popup.
var element = document.popupNode; while (element) { var isContextMenuShown = ("_contextMenuShown"
in element) && element._contextMenuShown; // Check for the parent menupopup or the
hbox used for toolbars if ((element.localName == "menupopup" || element.localName == "hbox")
&& isContextMenuShown) { placesController = element.controllers.getControllerForCommand(aCommand);
break; } element = element.parentNode; } return placesController; function goDoPlacesCommand(aCommand)
var controller = doGetPlacesControllerForCommand(aCommand); if (controller && controller.isCommandEnabled(aCommand))
controller.doCommand(aCommand); content/browser/places/treeView.js/* -*- Mode: C++; tab-width: 8; indent-tabs-mode:
nil; c-basic-offset: 2 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL
2.0/LGPL 2.1 * The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with * the License.
You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * Software distributed
under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND,
either express or implied. See the License * for the specific language governing rights
and limitations under the * License. * The Original Code is Mozilla History System *
The Initial Developer of the Original Code is * Google Inc. * Portions created by the
Initial Developer are Copyright (C) 2005 * the Initial Developer. All Rights Reserved.
* Contributor(s): * Brett Wilson (original author) * Asaf Romano
(Javascript version) * 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 ***** */ PlacesTreeView.prototype
= { _makeAtom: function PTV__makeAtom(aString) { return Cc["@mozilla.org/atom-service;1"].
getService(Ci.nsIAtomService). getAtom(aString); }, _atoms: [], _getAtomFor: function PTV__getAtomFor(aName)
{ if (!this._atoms[aName]) this._atoms[aName] = this._makeAtom(aName); return this._atoms[aName];
}, _ensureValidRow: function PTV__ensureValidRow(aRow) { if (aRow < 0 || aRow >= this._visibleElements.length)
throw Cr.NS_ERROR_INVALID_ARG; }, __dateService: null, get _dateService() { if (!this.__dateService)
{ this.__dateService = Cc["@mozilla.org/intl/scriptabledateformat;1"]. getService(Ci.nsIScriptableDateFormat); }
return this.__dateService; }, QueryInterface: function PTV_QueryInterface(aIID) { if (aIID.equals(Ci.nsITreeView)
|| aIID.equals(Ci.nsINavHistoryResultViewer) || aIID.equals(Ci.nsINavHistoryResultTreeViewer)
|| aIID.equals(Ci.nsISupports)) return this; throw Cr.NS_ERROR_NO_INTERFACE; }, /** *
This is called once both the result and the tree are set. */ _finishInit: function PTV__finishInit()
{ var selection = this.selection; if (selection) selection.selectEventsSuppressed = true; this._rootNode._viewIndex
= -1; if (!this._rootNode.containerOpen) { // This triggers containerOpened which
then builds the visible section. this._rootNode.containerOpen = true; } else this.invalidateContainer(this._rootNode);
// "Activate" the sorting column and update commands. this.sortingChanged(this._result.sortingMode);
if (selection) selection.selectEventsSuppressed = false; }, _rootNode: null, /** * This takes
a container and recursively appends visible elements to the * given array. This is used
to build the visible element list (with * this._visibleElements passed as the array),
or portions thereof (with * a separate array that is merged with the main list later).
* * aVisibleStartIndex is the visible index of the beginning of the 'aVisible' * array.
When aVisible is this._visibleElements, this is 0. This is non-zero * when we are building
up a sub-region for insertion. Then, this is the * index where the new array will be
inserted into this._visibleElements. * It is used to compute each node's viewIndex.
*/ _buildVisibleSection: function PTV__buildVisibleSection(aContainer, aVisible, aToOpen, aVisibleStartIndex) if
(!aContainer.containerOpen) return; // nothing to do const openLiteral = PlacesUIUtils.RDF.GetResource("http://home.netscape.com/NC-rdf#open");
const trueLiteral = PlacesUIUtils.RDF.GetLiteral("true"); var cc = aContainer.childCount; var sortingMode
= this._result.sortingMode; for (var i=0; i < cc; i++) { var curChild = aContainer.getChild(i);
var curChildType = curChild.type; // Don't display separators when sorted. if (curChildType
== Ci.nsINavHistoryResultNode.RESULT_TYPE_SEPARATOR) { if (sortingMode != Ci.nsINavHistoryQueryOptions.SORT_BY_NONE)
{ curChild._viewIndex = -1; continue; } } // Add the node to the visible-nodes array
and set its viewIndex. curChild._viewIndex = aVisibleStartIndex + aVisible.length; aVisible.push(curChild);
// Recursively do containers. if (!this._flatList && curChild instanceof Ci.nsINavHistoryContainerResultNode)
{ var resource = this._getResourceForNode(curChild); var isopen = resource != null && PlacesUIUtils.localStore.HasAssertion(resource,
openLiteral, trueLiteral, true); if (isopen != curChild.containerOpen) aToOpen.push(curChild);
else if (curChild.containerOpen && curChild.childCount > 0) this._buildVisibleSection(curChild,
aVisible, aToOpen, aVisibleStartIndex); } } }, /** * This counts how many rows a node
takes in the tree. For containers it * will count the node itself plus any child node
following it. */ _countVisibleRowsForNode: function PTV__countVisibleRowsForNode(aNode)
{ if (aNode == this._rootNode) return this._visibleElements.length; var viewIndex = aNode._viewIndex; NS_ASSERT(viewIndex
>= 0, "Node is not visible, no rows to count"); var outerLevel = aNode.indentLevel; for (var
i = viewIndex + 1; i < this._visibleElements.length; i++) { if (this._visibleElements[i].indentLevel
this._visibleElements.length)
throw "Trying to expand a node that is not visible"; NS_ASSERT(this._visibleElements[aContainer._viewIndex]
== aContainer, "Visible index is out of sync!"); } var startReplacement = aContainer._viewIndex
+ 1; var replaceCount = this._countVisibleRowsForNode(aContainer); // We don't replace the container node itself
so we should decrease the // replaceCount by 1, unless the container is our root node,
which isn't // visible. if (aContainer != this._rootNode) replaceCount -= 1; // Persist
selection state. var previouslySelectedNodes = []; var selection = this.selection; var
rc = selection.getRangeCount(); for (var rangeIndex = 0; rangeIndex < rc; rangeIndex++) { var
min = { }, max = { }; selection.getRangeAt(rangeIndex, min, max); var lastIndex = Math.min(max.value,
startReplacement + replaceCount -1); // If this range does not overlap the replaced chunk,
we don't need to // persist the selection. if (max.value < startReplacement || min.value
> lastIndex) continue; // If this range starts before the replaced chunk, we should persist
from // startReplacement to lastIndex. var firstIndex = Math.max(min.value, startReplacement);
for (var nodeIndex = firstIndex; nodeIndex = startReplacement && nodeIndex
< startReplacement + replaceCount) node._viewIndex = -1; previouslySelectedNodes.push( { node:
node, oldIndex: nodeIndex }); } } // Building the new list will set the new elements' visible
indices. var newElements = []; var toOpenElements = []; this._buildVisibleSection(aContainer,
newElements, toOpenElements, startReplacement); // Actually update the visible list. //
***: We can probably make this more efficient using splice through // Function.apply. this._visibleElements
= this._visibleElements.slice(0, startReplacement).concat(newElements) .concat(this._visibleElements.slice(startReplacement
+ replaceCount, this._visibleElements.length)); // If the new area has a different size,
we'll have to renumber the // elements following the area. if (replaceCount != newElements.length)
{ for (var i = startReplacement + newElements.length; i < this._visibleElements.length; i++) {
this._visibleElements[i]._viewIndex = i; } } // now update the number of elements selection.selectEventsSuppressed
= true; this._tree.beginUpdateBatch(); if (replaceCount) this._tree.rowCountChanged(startReplacement,
-replaceCount); if (newElements.length) this._tree.rowCountChanged(startReplacement, newElements.length); if (!this._flatList)
{ // now, open any containers that were persisted for (var i = 0; i < toOpenElements.length;
i++) { var item = toOpenElements[i]; var parent = item.parent; // avoid recursively opening
containers while (parent) { if (parent.uri == item.uri) break; parent = parent.parent;
} // if we don't have a parent, we made it all the way to the root // and didn't find
a match, so we can open our item if (!parent && !item.containerOpen) item.containerOpen
= true; } } this._tree.endUpdateBatch(); // restore selection if (previouslySelectedNodes.length
> 0) { for (var i = 0; i < previouslySelectedNodes.length; i++) { var nodeInfo = previouslySelectedNodes[i];
var index = nodeInfo.node._viewIndex; // If the nodes under the invalidated container
were preserved, we can // just use viewIndex. if (index == -1) { // Otherwise, try to find
an equal node. var itemId = PlacesUtils.getConcreteItemId(nodeInfo.node); if (itemId != 1) { // Search by itemId. for
(var j = 0; j < newElements.length && index == -1; j++) { if (PlacesUtils.getConcreteItemId(newElements[j])
== itemId) index = newElements[j]._viewIndex; } } else { // Search by uri. var uri = nodeInfo.node.uri;
if (uri) { for (var j = 0; j < newElements.length && index == -1; j++) { if (newElements[j].uri
== uri) index = newElements[j]._viewIndex; } } } } // Select the found node, if any.
if (index != -1) selection.rangedSelect(index, index, true); } // If only one node was previously
selected and there's no selection now, // select the node at its old viewIndex, if
any. if (previouslySelectedNodes.length == 1 && selection.getRangeCount() == 0 && this._visibleElements.length
> previouslySelectedNodes[0].oldIndex) { selection.rangedSelect(previouslySelectedNodes[0].oldIndex,
previouslySelectedNodes[0].oldIndex, true); } } selection.selectEventsSuppressed = false;
}, _convertPRTimeToString: function PTV__convertPRTimeToString(aTime) { var timeInMilliseconds = aTime / 1000;
// PRTime is in microseconds // Date is calculated starting from midnight, so the modulo with
a day are // milliseconds from today's midnight. // getTimezoneOffset corrects that based
on local time. // 86400000 = 24 * 60 * 60 * 1000 = 1 day // 60000 = 60 * 1000 = 1 minute
var dateObj = new Date(); var timeZoneOffsetInMs = dateObj.getTimezoneOffset() * 60000; var
now = dateObj.getTime() - timeZoneOffsetInMs; var midnight = now - (now % (86400000)); var
dateFormat = timeInMilliseconds - timeZoneOffsetInMs >= midnight ? Ci.nsIScriptableDateFormat.dateFormatNone
: Ci.nsIScriptableDateFormat.dateFormatShort; var timeObj = new Date(timeInMilliseconds);
return (this._dateService.FormatDateTime("", dateFormat, Ci.nsIScriptableDateFormat.timeFormatNoSeconds,
timeObj.getFullYear(), timeObj.getMonth() + 1, timeObj.getDate(), timeObj.getHours(),
timeObj.getMinutes(), timeObj.getSeconds())); }, COLUMN_TYPE_UNKNOWN: 0, COLUMN_TYPE_TITLE:
1, COLUMN_TYPE_URI: 2, COLUMN_TYPE_DATE: 3, COLUMN_TYPE_VISITCOUNT: 4, COLUMN_TYPE_KEYWORD:
5, COLUMN_TYPE_DESCRIPTION: 6, COLUMN_TYPE_DATEADDED: 7, COLUMN_TYPE_LASTMODIFIED: 8, COLUMN_TYPE_TAGS:
9, _getColumnType: function PTV__getColumnType(aColumn) { var columnType = aColumn.element.getAttribute("anonid")
|| aColumn.id; switch (columnType) { case "title": return this.COLUMN_TYPE_TITLE; case
"url": return this.COLUMN_TYPE_URI; case "date": return this.COLUMN_TYPE_DATE; case "visitCount":
return this.COLUMN_TYPE_VISITCOUNT; case "keyword": return this.COLUMN_TYPE_KEYWORD; case "description":
return this.COLUMN_TYPE_DESCRIPTION; case "dateAdded": return this.COLUMN_TYPE_DATEADDED;
case "lastModified": return this.COLUMN_TYPE_LASTMODIFIED; case "tags": return this.COLUMN_TYPE_TAGS;
} return this.COLUMN_TYPE_UNKNOWN; }, _sortTypeToColumnType: function PTV__sortTypeToColumnType(aSortType)
{ switch (aSortType) { case Ci.nsINavHistoryQueryOptions.SORT_BY_TITLE_ASCENDING: return [this.COLUMN_TYPE_TITLE, false]; case
Ci.nsINavHistoryQueryOptions.SORT_BY_TITLE_DESCENDING: return [this.COLUMN_TYPE_TITLE, true]; case
Ci.nsINavHistoryQueryOptions.SORT_BY_DATE_ASCENDING: return [this.COLUMN_TYPE_DATE, false]; case
Ci.nsINavHistoryQueryOptions.SORT_BY_DATE_DESCENDING: return [this.COLUMN_TYPE_DATE, true]; case
Ci.nsINavHistoryQueryOptions.SORT_BY_URI_ASCENDING: return [this.COLUMN_TYPE_URI, false]; case
Ci.nsINavHistoryQueryOptions.SORT_BY_URI_DESCENDING: return [this.COLUMN_TYPE_URI, true]; case
Ci.nsINavHistoryQueryOptions.SORT_BY_VISITCOUNT_ASCENDING: return [this.COLUMN_TYPE_VISITCOUNT, false];
case Ci.nsINavHistoryQueryOptions.SORT_BY_VISITCOUNT_DESCENDING: return [this.COLUMN_TYPE_VISITCOUNT, true];
case Ci.nsINavHistoryQueryOptions.SORT_BY_KEYWORD_ASCENDING: return [this.COLUMN_TYPE_KEYWORD, false];
case Ci.nsINavHistoryQueryOptions.SORT_BY_KEYWORD_DESCENDING: return [this.COLUMN_TYPE_KEYWORD, true]; case
Ci.nsINavHistoryQueryOptions.SORT_BY_ANNOTATION_ASCENDING: if (this._result.sortingAnnotation == DESCRIPTION_ANNO)
return [this.COLUMN_TYPE_DESCRIPTION, false]; break; case Ci.nsINavHistoryQueryOptions.SORT_BY_ANNOTATION_DESCENDING:
if (this._result.sortingAnnotation == DESCRIPTION_ANNO) return [this.COLUMN_TYPE_DESCRIPTION, true];
case Ci.nsINavHistoryQueryOptions.SORT_BY_DATEADDED_ASCENDING: return [this.COLUMN_TYPE_DATEADDED, false];
case Ci.nsINavHistoryQueryOptions.SORT_BY_DATEADDED_DESCENDING: return [this.COLUMN_TYPE_DATEADDED, true];
case Ci.nsINavHistoryQueryOptions.SORT_BY_LASTMODIFIED_ASCENDING: return [this.COLUMN_TYPE_LASTMODIFIED, false];
case Ci.nsINavHistoryQueryOptions.SORT_BY_LASTMODIFIED_DESCENDING: return [this.COLUMN_TYPE_LASTMODIFIED, true];
case Ci.nsINavHistoryQueryOptions.SORT_BY_TAGS_ASCENDING: return [this.COLUMN_TYPE_TAGS, false]; case
Ci.nsINavHistoryQueryOptions.SORT_BY_TAGS_DESCENDING: return [this.COLUMN_TYPE_TAGS, true]; } return
[this.COLUMN_TYPE_UNKNOWN, false]; }, // nsINavHistoryResultViewer nodeInserted: function
PTV_nodeInserted(aParentNode, aNode, aNewIndex) { if (!this._tree) return; if (!this._result)
throw Cr.NS_ERROR_UNEXPECTED; if (PlacesUtils.nodeIsSeparator(aNode) && this._result.sortingMode != Ci.nsINavHistoryQueryOptions.SORT_BY_NONE)
{ aNode._viewIndex = -1; return; } // Update parent when inserting the first item, since
twisty may // have changed. if (aParentNode.childCount == 1) this._tree.invalidateRow(aParentNode._viewIndex);
// compute the new view index of the item var newViewIndex = -1; if (aNewIndex == 0)
{ // item is the first thing in our child list, it takes our index +1. Note // that
this computation still works if the parent is an invisible root // node, because root_index
+ 1 = -1 + 1 = 0 newViewIndex = aParentNode._viewIndex + 1; } else { // Here, we try to find the
next visible element in the child list so we // can set the new visible index to be
right before that. Note that we // have to search DOWN instead of up, because some siblings
could have // children themselves that would be in the way. for (var i = aNewIndex + 1;
i < aParentNode.childCount; i++) { var viewIndex = aParentNode.getChild(i)._viewIndex; if
(viewIndex >= 0) { // the view indices of subsequent children have not been shifted
so // the next item will have what should be our index newViewIndex = viewIndex; break;
} } if (newViewIndex < 0) { // At the end of the child list without finding a visible
sibling: This // is a little harder because we don't know how many rows the last item
// in our list takes up (it could be a container with many children). var prevChild = aParentNode.getChild(aNewIndex
- 1); newViewIndex = prevChild._viewIndex + this._countVisibleRowsForNode(prevChild);
} } aNode._viewIndex = newViewIndex; this._visibleElements.splice(newViewIndex, 0, aNode); for (var i = newViewIndex + 1;
i < this._visibleElements.length; i++) { this._visibleElements[i]._viewIndex = i;
} this._tree.rowCountChanged(newViewIndex, 1); if (PlacesUtils.nodeIsContainer(aNode)
&& asContainer(aNode).containerOpen) this._refreshVisibleSection(aNode); }, // This is used in nodeRemoved and nodeMoved
to fix viewIndex values. // Throws if the node has an invalid viewIndex. _fixViewIndexOnRemove:
function PTV_fixViewIndexOnRemove(aNode, aParentNode) { var oldViewIndex = aNode._viewIndex; //
this may have been a container, in which case it has a lot of rows var count = this._countVisibleRowsForNode(aNode);
if (oldViewIndex > this._visibleElements.length) throw("Trying to remove a node with an invalid
viewIndex"); this._visibleElements.splice(oldViewIndex, count); for (var i = oldViewIndex; i < this._visibleElements.length;
i++) this._visibleElements[i]._viewIndex = i; this._tree.rowCountChanged(oldViewIndex,
-count); // redraw parent because twisty may have changed if (!aParentNode.hasChildren)
this._tree.invalidateRow(aParentNode._viewIndex); }, /** * THIS FUNCTION DOES NOT HANDLE cases
where a collapsed node is being * removed but the node it is collapsed with is not being
removed (this then * just swap out the removee with its collapsing partner). The only time
* when we really remove things is when deleting URIs, which will apply to * all collapsees.
This function is called sometimes when resorting items. * However, we won't do this when sorted
by date because dates will never * change for visits, and date sorting is the only time
things are collapsed. */ nodeRemoved: function PTV_nodeRemoved(aParentNode, aNode, aOldIndex)
{ NS_ASSERT(this._result, "Got a notification but have no result!"); if (!this._tree) return;
// nothing to do var oldViewIndex = aNode._viewIndex; if (oldViewIndex < 0) { // There's nothing
to do if the node was already invisible. return; } // If the node was exclusively selected,
the node next to it will be // selected. var selectNext = false; var selection = this.selection;
if (selection.getRangeCount() == 1) { var min = { }, max = { }; selection.getRangeAt(0,
min, max); if (min.value == max.value && this.nodeForTreeIndex(min.value) == aNode)
selectNext = true; } // Remove the node and fix viewIndex values. this._fixViewIndexOnRemove(aNode,
aParentNode); // Restore selection if the node was exclusively selected. if (!selectNext)
return; // Restore selection if (this._visibleElements.length > oldViewIndex) selection.rangedSelect(oldViewIndex,
oldViewIndex, true); else if (this._visibleElements.length > 0) { // if we removed the last child, we
select the new last child if exists selection.rangedSelect(this._visibleElements.length - 1, this._visibleElements.length - 1, true);
} }, /** * Be careful, aOldIndex and aNewIndex specify the index in the * corresponding parent
nodes, not the visible indexes. */ nodeMoved: function PTV_nodeMoved(aNode, aOldParent,
aOldIndex, aNewParent, aNewIndex) { NS_ASSERT(this._result, "Got a notification but have no result!");
if (!this._tree) return; // nothing to do var oldViewIndex = aNode._viewIndex; if (oldViewIndex
< 0) { // There's nothing to do if the node was already invisible. return; } // This may
have been a container, in which case it has a lot of rows. var count = this._countVisibleRowsForNode(aNode);
// Persist selection state. var nodesToSelect = []; var selection = this.selection; var
rc = selection.getRangeCount(); for (var rangeIndex = 0; rangeIndex < rc; rangeIndex++) { var
min = { }, max = { }; selection.getRangeAt(rangeIndex, min, max); var lastIndex = Math.min(max.value,
oldViewIndex + count -1); if (min.value < oldViewIndex || min.value > lastIndex) continue;
for (var nodeIndex = min.value; nodeIndex 0) selection.selectEventsSuppressed = true; // Remove node from the old position.
this._fixViewIndexOnRemove(aNode, aOldParent); // Insert the node into the new position.
this.nodeInserted(aNewParent, aNode, aNewIndex); // Restore selection. if (nodesToSelect.length
> 0) { for (var i = 0; i < nodesToSelect.length; i++) { var node = nodesToSelect[i]; var index
= node._viewIndex; selection.rangedSelect(index, index, true); } selection.selectEventsSuppressed
= false; } }, /** * Be careful, the parameter 'aIndex' here specifies the node's index in
the * parent node, not the visible index. */ nodeReplaced: function PTV_nodeReplaced(aParentNode,
aOldNode, aNewNode, aIndexDoNotUse) { if (!this._tree) return; var viewIndex = aOldNode._viewIndex;
aNewNode._viewIndex = viewIndex; if (viewIndex >= 0 && viewIndex < this._visibleElements.length)
{ this._visibleElements[viewIndex] = aNewNode; } aOldNode._viewIndex = -1; this._tree.invalidateRow(viewIndex);
}, _invalidateCellValue: function PTV__invalidateCellValue(aNode, aColumnType) { NS_ASSERT(this._result, "Got
a notification but have no result!"); let viewIndex = aNode._viewIndex; if (viewIndex
== -1) // invisible return; if (this._tree) { let column = this._findColumnByType(aColumnType);
if (column && !column.element.hidden) this._tree.invalidateCell(viewIndex, column); // Last modified time is altered
for almost all node changes. if (aColumnType != this.COLUMN_TYPE_LASTMODIFIED) { let lastModifiedColumn
= this._findColumnByType(this.COLUMN_TYPE_LASTMODIFIED); if (lastModifiedColumn && !lastModifiedColumn.hidden)
this._tree.invalidateCell(viewIndex, lastModifiedColumn); } } }, nodeTitleChanged: function PTV_nodeTitleChanged(aNode,
aNewTitle) { this._invalidateCellValue(aNode, this.COLUMN_TYPE_TITLE); }, nodeURIChanged:
function PTV_nodeURIChanged(aNode, aNewURI) { this._invalidateCellValue(aNode, this.COLUMN_TYPE_URI);
}, nodeIconChanged: function PTV_nodeIconChanged(aNode) { this._invalidateCellValue(aNode, this.COLUMN_TYPE_TITLE);
}, nodeHistoryDetailsChanged: function PTV_nodeHistoryDetailsChanged(aNode, aUpdatedVisitDate, aUpdatedVisitCount) {
this._invalidateCellValue(aNode, this.COLUMN_TYPE_DATE); this._invalidateCellValue(aNode, this.COLUMN_TYPE_VISITCOUNT);
}, nodeTagsChanged: function PTV_nodeTagsChanged(aNode) { this._invalidateCellValue(aNode, this.COLUMN_TYPE_TAGS);
}, nodeKeywordChanged: function PTV_nodeKeywordChanged(aNode, aNewKeyword) { this._invalidateCellValue(aNode,
this.COLUMN_TYPE_KEYWORD); }, nodeAnnotationChanged: function PTV_nodeAnnotationChanged(aNode,
aAnno) { if (aAnno == DESCRIPTION_ANNO) this._invalidateCellValue(aNode, this.COLUMN_TYPE_DESCRIPTION); }, nodeDateAddedChanged:
function PTV_nodeDateAddedChanged(aNode, aNewValue) { this._invalidateCellValue(aNode, this.COLUMN_TYPE_DATEADDED);
}, nodeLastModifiedChanged: function PTV_nodeLastModifiedChanged(aNode, aNewValue) { this._invalidateCellValue(aNode,
this.COLUMN_TYPE_LASTMODIFIED); }, containerOpened: function PTV_containerOpened(aNode) { this.invalidateContainer(aNode);
}, containerClosed: function PTV_containerClosed(aNode) { this.invalidateContainer(aNode); }, invalidateContainer:
function PTV_invalidateContainer(aNode) { NS_ASSERT(this._result, "Got a notification
but have no result!"); if (!this._tree) return; // nothing to do, container is not visible
if (aNode._viewIndex >= this._visibleElements.length) { // be paranoid about visible indices since
others can change it throw Cr.NS_ERROR_UNEXPECTED; } this._refreshVisibleSection(aNode); },
_columns: [], _findColumnByType: function PTV__findColumnByType(aColumnType) { if (this._columns[aColumnType])
return this._columns[aColumnType]; var columns = this._tree.columns; var colCount = columns.count;
for (var i = 0; i < colCount; i++) { let column = columns.getColumnAt(i); let columnType
= this._getColumnType(column); this._columns[columnType] = column; if (columnType == aColumnType)
return column; } // That's completely valid. Most of our trees actually include just the
// title column. return null; }, sortingChanged: function PTV__sortingChanged(aSortingMode)
{ if (!this._tree || !this._result) return; // depending on the sort mode, certain commands
may be disabled window.updateCommands("sort"); var columns = this._tree.columns; // clear
old sorting indicator var sortedColumn = columns.getSortedColumn(); if (sortedColumn)
sortedColumn.element.removeAttribute("sortDirection"); // set new sorting indicator by looking through
all columns for ours if (aSortingMode == Ci.nsINavHistoryQueryOptions.SORT_BY_NONE)
return; var [desiredColumn, desiredIsDescending] = this._sortTypeToColumnType(aSortingMode);
var colCount = columns.count; var column = this._findColumnByType(desiredColumn); if
(column) { let sortDir = desiredIsDescending ? "descending" : "ascending"; column.element.setAttribute("sortDirection",
sortDir); } }, get result() { return this._result; }, set result(val) { // Some methods (e.g.
getURLsFromContainer) temporarily null out the // viewer when they do temporary changes
to the view, this does _not_ // call setResult(null), but then, we're called again with the result
// object which is already set for this viewer. At that point, // we should do nothing. if
(this._result != val) { if (this._result) this._rootNode.containerOpen = false; this._result
= val; this._rootNode = val ? val.root : null; // If the tree is not set yet, setTree
will call finishInit. if (this._tree && val) this._finishInit(); } return val; }, nodeForTreeIndex:
function PTV_nodeForTreeIndex(aIndex) { if (aIndex > this._visibleElements.length) throw
Cr.NS_ERROR_INVALID_ARG; return this._visibleElements[aIndex]; }, treeIndexForNode: function PTV_treeNodeForIndex(aNode)
{ var viewIndex = aNode._viewIndex; if (viewIndex < 0) return Ci.nsINavHistoryResultTreeViewer.INDEX_INVISIBLE;
NS_ASSERT(this._visibleElements[viewIndex] == aNode, "Node's visible index and array
out of sync"); return viewIndex; }, _getResourceForNode: function PTV_getResourceForNode(aNode) var
uri = aNode.uri; NS_ASSERT(uri, "if there is no uri, we can't persist the open state");
return uri ? PlacesUIUtils.RDF.GetResource(uri) : null; }, // nsITreeView get rowCount()
{ return this._visibleElements.length; }, get selection() { return this._selection;
}, set selection(val) { return this._selection = val; }, getRowProperties: function PTV_getRowProperties(aRow,
aProperties) { }, getCellProperties: function PTV_getCellProperties(aRow, aColumn, aProperties)
{ this._ensureValidRow(aRow); // for anonid-trees, we need to add the column-type manually var
columnType = aColumn.element.getAttribute("anonid"); if (columnType) aProperties.AppendElement(this._getAtomFor(columnType));
else var columnType = aColumn.id; // Set the "ltr" property on url cells if (columnType
== "url") aProperties.AppendElement(this._getAtomFor("ltr")); if (columnType != "title") return; var node
= this._visibleElements[aRow]; if (!node._cellProperties) { let properties = new Array(); var itemId
= node.itemId; var nodeType = node.type; if (PlacesUtils.containerTypes.indexOf(nodeType)
!= -1) { if (nodeType == Ci.nsINavHistoryResultNode.RESULT_TYPE_QUERY) { properties.push(this._getAtomFor("query"));
if (PlacesUtils.nodeIsTagQuery(node)) properties.push(this._getAtomFor("tagContainer")); else if (PlacesUtils.nodeIsDay(node)) properties.push(this._getAtomFor("dayContainer"));
else if (PlacesUtils.nodeIsHost(node)) properties.push(this._getAtomFor("hostContainer")); } else if (nodeType == Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER
|| nodeType == Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER_SHORTCUT) { if (PlacesUtils.nodeIsLivemarkContainer(node))
properties.push(this._getAtomFor("livemark")); } if (itemId != -1) { var queryName = PlacesUIUtils.getLeftPaneQueryNameFromId(itemId);
if (queryName) properties.push(this._getAtomFor("OrganizerQuery_" + queryName)); } } else if (nodeType == Ci.nsINavHistoryResultNode.RESULT_TYPE_SEPARATOR)
properties.push(this._getAtomFor("separator")); else if (PlacesUtils.nodeIsURI(node)) { properties.push(this._getAtomFor(PlacesUIUtils.guessUrlSchemeForUI(node.uri)));
if (itemId != -1) { if (PlacesUtils.nodeIsLivemarkContainer(node.parent)) properties.push(this._getAtomFor("livemarkItem"));
} } node._cellProperties = properties; } for (var i = 0; i < node._cellProperties.length;
i++) aProperties.AppendElement(node._cellProperties[i]); }, getColumnProperties: function(aColumn,
aProperties) { }, isContainer: function PTV_isContainer(aRow) { this._ensureValidRow(aRow); var node =
this._visibleElements[aRow]; if (PlacesUtils.nodeIsContainer(node)) { // Flat-lists may ignore expandQueries
and other query options when // they are asked to open a container. if (this._flatList) return
true; // treat non-expandable childless queries as non-containers if (PlacesUtils.nodeIsQuery(node))
{ var parent = node.parent; if ((PlacesUtils.nodeIsQuery(parent) || PlacesUtils.nodeIsFolder(parent)) &&
!node.hasChildren) return asQuery(parent).queryOptions.expandQueries; } return true; } return false; }, isContainerOpen:
function PTV_isContainerOpen(aRow) { if (this._flatList) return false; this._ensureValidRow(aRow);
return this._visibleElements[aRow].containerOpen; }, isContainerEmpty: function PTV_isContainerEmpty(aRow)
{ if (this._flatList) return true; this._ensureValidRow(aRow); return !this._visibleElements[aRow].hasChildren;
}, isSeparator: function PTV_isSeparator(aRow) { this._ensureValidRow(aRow); return PlacesUtils.nodeIsSeparator(this._visibleElements[aRow]);
}, isSorted: function PTV_isSorted() { return this._result.sortingMode != Ci.nsINavHistoryQueryOptions.SORT_BY_NONE;
}, canDrop: function PTV_canDrop(aRow, aOrientation) { if (!this._result) throw Cr.NS_ERROR_UNEXPECTED;
// drop position into a sorted treeview would be wrong if (this.isSorted()) return false;
var ip = this._getInsertionPoint(aRow, aOrientation); return ip && PlacesControllerDragHelper.canDrop(ip);
}, _getInsertionPoint: function PTV__getInsertionPoint(index, orientation) { var container = this._result.root;
var dropNearItemId = -1; // When there's no selection, assume the container is the container
// the view is populated from (i.e. the result's itemId). if (index != -1) { var lastSelected
= this.nodeForTreeIndex(index); if (this.isContainer(index) && orientation == Ci.nsITreeView.DROP_ON)
{ // If the last selected item is an open container, append _into_ // it, rather than
insert adjacent to it. container = lastSelected; index = -1; } else if (lastSelected.containerOpen
&& orientation == Ci.nsITreeView.DROP_AFTER && lastSelected.hasChildren) { // If the
last selected node is an open container and the user is // trying to drag into it as a
first node, really insert into it. container = lastSelected; orientation = Ci.nsITreeView.DROP_ON;
index = 0; } else { // Use the last-selected node's container unless the root node //
is selected, in which case we use the root node itself as the // insertion point. container
= lastSelected.parent || container; // avoid the potentially expensive call to getIndexOfNode()
// if we know this container doesn't allow insertion if (PlacesControllerDragHelper.disallowInsertion(container))
return null; var queryOptions = asQuery(this._result.root).queryOptions; if (queryOptions.sortingMode != Ci.nsINavHistoryQueryOptions.SORT_BY_NONE)
{ // If we are within a sorted view, insert at the ends index = -1; } else if (queryOptions.excludeItems
|| queryOptions.excludeQueries || queryOptions.excludeReadOnlyFolders) { // Some item may be invisible, insert near
last selected one. // We don't replace index here to avoid requests to the db, // instead
it will be calculated later by the controller. index = -1; dropNearItemId = lastSelected.itemId;
} else { var lsi = PlacesUtils.getIndexOfNode(lastSelected); index = orientation == Ci.nsITreeView.DROP_BEFORE
? lsi : lsi + 1; } } } if (PlacesControllerDragHelper.disallowInsertion(container)) return null; return new InsertionPoint(PlacesUtils.getConcreteItemId(container),
index, orientation, PlacesUtils.nodeIsTagQuery(container), dropNearItemId); }, drop: function PTV_drop(aRow,
aOrientation) { // We are responsible for translating the |index| and |orientation|
// parameters into a container id and index within the container, // since this information
is specific to the tree view. var ip = this._getInsertionPoint(aRow, aOrientation); if (!ip) return; PlacesControllerDragHelper.onDrop(ip);
}, getParentIndex: function PTV_getParentIndex(aRow) { this._ensureValidRow(aRow); var parent
= this._visibleElements[aRow].parent; if (!parent || parent._viewIndex < 0) return
-1; return parent._viewIndex; }, hasNextSibling: function PTV_hasNextSibling(aRow, aAfterIndex)
{ this._ensureValidRow(aRow); if (aRow == this._visibleElements.length -1) { // this
is the last thing in the list -> no next sibling return false; } var thisLevel = this._visibleElements[aRow].indentLevel;
for (var i = aAfterIndex + 1; i < this._visibleElements.length; ++i) { var nextLevel = this._visibleElements[i].indentLevel;
if (nextLevel == thisLevel) return true; if (nextLevel < thisLevel) break; } return false;
}, getLevel: function PTV_getLevel(aRow) { this._ensureValidRow(aRow); // Level is
0 for nodes at the root level, 1 for its children and so on. return this._visibleElements[aRow].indentLevel;
}, getImageSrc: function PTV_getImageSrc(aRow, aColumn) { this._ensureValidRow(aRow); //
only the title column has an image if (this._getColumnType(aColumn) != this.COLUMN_TYPE_TITLE) return ""; return
this._visibleElements[aRow].icon; }, getProgressMode: function(aRow, aColumn) { }, getCellValue:
function(aRow, aColumn) { }, getCellText: function PTV_getCellText(aRow, aColumn) {
this._ensureValidRow(aRow); var node = this._visibleElements[aRow]; var columnType = this._getColumnType(aColumn);
switch (columnType) { case this.COLUMN_TYPE_TITLE: // normally, this is just the title, but
we don't want empty items in // the tree view so return a special string if the title is
empty. // Do it here so that callers can still get at the 0 length title // if they go through
the "result" API. if (PlacesUtils.nodeIsSeparator(node)) return ""; return PlacesUIUtils.getBestTitle(node);
case this.COLUMN_TYPE_TAGS: return node.tags; case this.COLUMN_TYPE_URI: if (PlacesUtils.nodeIsURI(node))
return node.uri; return ""; case this.COLUMN_TYPE_DATE: let nodeTime = node.time; if (nodeTime ==
0 || !PlacesUtils.nodeIsURI(node)) { // hosts and days shouldn't have a value for
the date column. // Actually, you could argue this point, but looking at the // results,
seeing the most recently visited date is not what // I expect, and gives me no information
I know how to use. // Only show this for URI-based items. return ""; } return this._convertPRTimeToString(nodeTime);
case this.COLUMN_TYPE_VISITCOUNT: return node.accessCount; case this.COLUMN_TYPE_KEYWORD: if (PlacesUtils.nodeIsBookmark(node))
return PlacesUtils.bookmarks.getKeywordForBookmark(node.itemId); return ""; case this.COLUMN_TYPE_DESCRIPTION:
if (node.itemId != -1) { try { return PlacesUtils.annotations. getItemAnnotation(node.itemId, DESCRIPTION_ANNO);
} catch (ex) { /* has no description */ } } return ""; case this.COLUMN_TYPE_DATEADDED:
if (node.dateAdded) return this._convertPRTimeToString(node.dateAdded); return ""; case this.COLUMN_TYPE_LASTMODIFIED:
if (node.lastModified) return this._convertPRTimeToString(node.lastModified); return ""; } return ""; }, setTree: function
PTV_setTree(aTree) { var hasOldTree = this._tree != null; this._tree = aTree; if (this._result)
{ if (hasOldTree) { // detach from result when we are detaching from the tree. // This
breaks the reference cycle between us and the result. if (!aTree) this._result.viewer
= null; } if (aTree) this._finishInit(); } }, toggleOpenState: function PTV_toggleOpenState(aRow)
{ if (!this._result) throw Cr.NS_ERROR_UNEXPECTED; this._ensureValidRow(aRow); var node = this._visibleElements[aRow];
if (this._flatList && this._openContainerCallback) { this._openContainerCallback(node); return;
} var resource = this._getResourceForNode(node); if (resource) { const openLiteral = PlacesUIUtils.RDF.GetResource("http://home.netscape.com/NC-rdf#open");
const trueLiteral = PlacesUIUtils.RDF.GetLiteral("true"); if (node.containerOpen) PlacesUIUtils.localStore.Unassert(resource,
openLiteral, trueLiteral); else PlacesUIUtils.localStore.Assert(resource, openLiteral, trueLiteral, true); } node.containerOpen
= !node.containerOpen; }, cycleHeader: function PTV_cycleHeader(aColumn) { if (!this._result)
throw Cr.NS_ERROR_UNEXPECTED; // Sometimes you want a tri-state sorting, and sometimes
you don't. This // rule allows tri-state sorting when the root node is a folder. This will
// catch the most common cases. When you are looking at folders, you want // the third
state to reset the sorting to the natural bookmark order. When // you are looking at
history, that third state has no meaning so we try // to disallow it. // // The problem
occurs when you have a query that results in bookmark // folders. One example of this
is the subscriptions view. In these cases, // this rule doesn't allow you to sort those
sub-folders by their natural // order. var allowTriState = PlacesUtils.nodeIsFolder(this._result.root);
var oldSort = this._result.sortingMode; var oldSortingAnnotation = this._result.sortingAnnotation;
var newSort; var newSortingAnnotation = ""; const NHQO = Ci.nsINavHistoryQueryOptions;
var columnType = this._getColumnType(aColumn); switch (columnType) { case this.COLUMN_TYPE_TITLE:
if (oldSort == NHQO.SORT_BY_TITLE_ASCENDING) newSort = NHQO.SORT_BY_TITLE_DESCENDING; else
if (allowTriState && oldSort == NHQO.SORT_BY_TITLE_DESCENDING) newSort = NHQO.SORT_BY_NONE; else newSort
= NHQO.SORT_BY_TITLE_ASCENDING; break; case this.COLUMN_TYPE_URI: if (oldSort == NHQO.SORT_BY_URI_ASCENDING)
newSort = NHQO.SORT_BY_URI_DESCENDING; else if (allowTriState && oldSort == NHQO.SORT_BY_URI_DESCENDING)
newSort = NHQO.SORT_BY_NONE; else newSort = NHQO.SORT_BY_URI_ASCENDING; break; case
this.COLUMN_TYPE_DATE: if (oldSort == NHQO.SORT_BY_DATE_ASCENDING) newSort = NHQO.SORT_BY_DATE_DESCENDING; else
if (allowTriState && oldSort == NHQO.SORT_BY_DATE_DESCENDING) newSort = NHQO.SORT_BY_NONE; else newSort
= NHQO.SORT_BY_DATE_ASCENDING; break; case this.COLUMN_TYPE_VISITCOUNT: // visit count
default is unusual because we sort by descending // by default because you are most likely
to be looking for // highly visited sites when you click it if (oldSort == NHQO.SORT_BY_VISITCOUNT_DESCENDING)
newSort = NHQO.SORT_BY_VISITCOUNT_ASCENDING; else if (allowTriState && oldSort == NHQO.SORT_BY_VISITCOUNT_ASCENDING)
newSort = NHQO.SORT_BY_NONE; else newSort = NHQO.SORT_BY_VISITCOUNT_DESCENDING; break;
case this.COLUMN_TYPE_KEYWORD: if (oldSort == NHQO.SORT_BY_KEYWORD_ASCENDING) newSort
= NHQO.SORT_BY_KEYWORD_DESCENDING; else if (allowTriState && oldSort == NHQO.SORT_BY_KEYWORD_DESCENDING)
newSort = NHQO.SORT_BY_NONE; else newSort = NHQO.SORT_BY_KEYWORD_ASCENDING; break;
case this.COLUMN_TYPE_DESCRIPTION: if (oldSort == NHQO.SORT_BY_ANNOTATION_ASCENDING &&
oldSortingAnnotation == DESCRIPTION_ANNO) { newSort = NHQO.SORT_BY_ANNOTATION_DESCENDING;
newSortingAnnotation = DESCRIPTION_ANNO; } else if (allowTriState && oldSort == NHQO.SORT_BY_ANNOTATION_DESCENDING
&& oldSortingAnnotation == DESCRIPTION_ANNO) newSort = NHQO.SORT_BY_NONE; else { newSort
= NHQO.SORT_BY_ANNOTATION_ASCENDING; newSortingAnnotation = DESCRIPTION_ANNO; } break; case this.COLUMN_TYPE_DATEADDED:
if (oldSort == NHQO.SORT_BY_DATEADDED_ASCENDING) newSort = NHQO.SORT_BY_DATEADDED_DESCENDING;
else if (allowTriState && oldSort == NHQO.SORT_BY_DATEADDED_DESCENDING) newSort = NHQO.SORT_BY_NONE; else newSort
= NHQO.SORT_BY_DATEADDED_ASCENDING; break; case this.COLUMN_TYPE_LASTMODIFIED: if (oldSort
== NHQO.SORT_BY_LASTMODIFIED_ASCENDING) newSort = NHQO.SORT_BY_LASTMODIFIED_DESCENDING; else
if (allowTriState && oldSort == NHQO.SORT_BY_LASTMODIFIED_DESCENDING) newSort = NHQO.SORT_BY_NONE; else newSort
= NHQO.SORT_BY_LASTMODIFIED_ASCENDING; break; case this.COLUMN_TYPE_TAGS: if (oldSort ==
NHQO.SORT_BY_TAGS_ASCENDING) newSort = NHQO.SORT_BY_TAGS_DESCENDING; else if (allowTriState && oldSort == NHQO.SORT_BY_TAGS_DESCENDING)
newSort = NHQO.SORT_BY_NONE; else newSort = NHQO.SORT_BY_TAGS_ASCENDING; break; default:
throw Cr.NS_ERROR_INVALID_ARG; } this._result.sortingAnnotation = newSortingAnnotation; this._result.sortingMode
= newSort; }, isEditable: function PTV_isEditable(aRow, aColumn) { // At this point we only support
editing the title field. if (aColumn.index != 0) return false; var node = this.nodeForTreeIndex(aRow);
if (!PlacesUtils.nodeIsReadOnly(node) && (PlacesUtils.nodeIsFolder(node) || (PlacesUtils.nodeIsBookmark(node)
&& !PlacesUtils.nodeIsLivemarkItem(node)))) return true; return false; }, setCellText:
function PTV_setCellText(aRow, aColumn, aText) { // we may only get here if the cell is
editable var node = this.nodeForTreeIndex(aRow); if (node.title != aText) { var txn = PlacesUIUtils.ptm.editItemTitle(node.itemId,
aText); PlacesUIUtils.ptm.doTransaction(txn); } }, selectionChanged: function() { }, cycleCell:
function PTV_cycleCell(aRow, aColumn) { }, isSelectable: function(aRow, aColumn) {
return false; }, performAction: function(aAction) { }, performActionOnRow: function(aAction,
aRow) { }, performActionOnCell: function(aAction, aRow, aColumn) { } function PlacesTreeView(aFlatList,
aOnOpenFlatContainer) { this._tree = null; this._result = null; this._selection = null;
this._visibleElements = []; this._flatList = aFlatList; this._openContainerCallback
= aOnOpenFlatContainer; content/browser/places/demos/time.xul
content/browser/places/demos/time.html
body { background-color:white; color:black;
font-family:verdana,helvetica;} .item { font-size:9pt; padding:3px; padding-top:0px; margin-top:0px;
} .itemnew { font-size:9pt; padding:3px; margin-left:5em; border-top:1px dotted #888;
padding-top:0px; } .time { font-size:7pt; border-top:2px solid black; margin-top:10px;
margin-bottom:2px; font-weight:bold; } .host { font-size:7pt; font-weight:bold; color:#888;
width:8em; overflow:hidden; } .title { margin:0px; padding:2px; } .url { font-size:7pt; color:#080;
padding-left:12em; } .favicon { padding-right:8px; position:relative; top:2px; }
content/browser/places/demos/time.css.day1 { background-color:white; } .day2 { background-color:#EEE;
} .green { background-color:green; } .red { background-color:red; } content/browser/places/demos/time.js/*
***** 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 Places * 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
(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 ***** */ window.addEventListener("load",
BW_startup, false); var BW_frame; var BW_historyService = Components.classes["@mozilla.org/browser/nav-history-service;1"].
getService(Components.interfaces.nsINavHistoryService); var BW_result; var loadedIframe = false; var
loadedBretts = false; function BW_startup() { BW_frame = document.getElementById("theframe");
var options = BW_historyService.getNewQueryOptions(); options.sortingMode = options.SORT_BY_DATE_DESCENDING;
options.resultType = options.RESULTS_AS_VISIT; options.maxResults = 200; var query = BW_historyService.getNewQuery();
BW_result = BW_historyService.executeQuery(query, options); BW_result.root.containerOpen =
true; BW_frame.contentWindow.addEventListener("load", BW_fill, true); loadedBretts = true; if (loadedIframe
&& loadedBretts) BW_fill(); //BW_frame.onload = BW_fill; //BW_frame.contentDocument.onLoad
= BW_fill; //BW_fill(); function BW_loadiframe() { loadedIframe = true; if (loadedIframe
&& loadedBretts) BW_fill(); function BW_getTLD(host) { var count = 0; for (var i = host.length
- 2; i > 0; i --) { if (host[i] == '.') { count ++; if (count == 2) { return host.substr(i
+ 1); } } return host; var BW_filled = false; function BW_fill() { if (BW_filled) return;
BW_filled = true; BW_frame.setAttribute('onload', ''); var container = BW_result.root; var
length = container.childCount; dump("doc = " + BW_frame.contentDocument + "\n"); var
doc = BW_frame.contentDocument; var ios = Components.classes["@mozilla.org/network/io-service;1"].
getService(Components.interfaces.nsIIOService); var dateformat = Components.classes["@mozilla.org/intl/scriptabledateformat;1"]
.getService(Components.interfaces.nsIScriptableDateFormat); var table = doc.createElement('table'); doc.body.appendChild(table);
var counts = new Array(240); for (var i = 0; i < counts.length; i ++) { counts[i]
= 0; var now = new Date(); now.setHours(0); now.setMinutes(0); now.setSeconds(0); now.setMilliseconds(0);
now.setDate(now.getDate()+1); var tonightUS = now.getTime() * 1000; var usPerHour =
3600000000; var previousSession = -1; var previousMS = 18437736874454810627; var previousHost
= ""; for (var i = 0; i < length; i ++) { var child = container.getChild(i); child.QueryInterface(Components.interfaces.nsINavHistoryVisitResultNode);
var session = child.sessionId; var thisBin = Math.floor((tonightUS - child.time) /
usPerHour); if (thisBin >= 0 && thisBin < counts.length) { counts[thisBin] = counts[thisBin]
+ 1; } var ms = child.time / 1000; var addedTime = false; if (previousMS - ms > 600000) {
addedTime = true; var t = new Date(ms); var tr = doc.createElement('tr'); table.appendChild(tr);
var td = doc.createElement('td'); td.setAttribute('colspan', '2'); td.setAttribute('class', 'time'); tr.appendChild(td);
var timestring = dateformat.FormatDateTime("", dateformat.dateFormatShort, dateformat.timeFormatNoSeconds,
t.getFullYear(), t.getMonth(), t.getDate(), t.getHours(), t.getMinutes(), 0); var timetext
= doc.createTextNode(timestring); td.appendChild(timetext); } previousMS = ms; var tr = doc.createElement('tr');
table.appendChild(tr); // URL var spec; var uri; try { spec = child.uri; uri = ios.newURI(spec,
null, null); } catch(e) { spec = null; uri = null; } // host name if needed on left
var td = doc.createElement('td'); td.setAttribute('valign', 'top'); td.setAttribute('align', 'right');
td.setAttribute('class', 'host'); tr.appendChild(td); var host = BW_getTLD(uri.host); if (addedTime
|| host != previousHost) { // add host name var hosttext = doc.createTextNode(host); td.appendChild(hosttext);
} previousHost = host; // right section var td = doc.createElement('td'); td.setAttribute('valign',
'top'); tr.appendChild(td); if (! addedTime && (i == 0 || child.sessionId != previousSession))
td.setAttribute('class', 'itemnew'); else td.setAttribute('class', 'item'); previousSession
= session; // title div and text var titlediv = doc.createElement('div'); titlediv.setAttribute('class',
'title'); var imgelt = doc.createElement('img'); if (child.icon) imgelt.setAttribute('src',
child.icon.spec); else imgelt.setAttribute('src', 'chrome://browser/skin/places/defaultFavicon.png');
imgelt.setAttribute('width', 16); imgelt.setAttribute('height', 16); imgelt.setAttribute('class', 'favicon');
titlediv.appendChild(imgelt); var titletext = doc.createTextNode(child.title); titlediv.appendChild(titletext);
td.appendChild(titlediv); // URL if (spec) { /* // this does bold host names var host
= uri.host; var hostStart = spec.indexOf(host); if (hostStart >= 0) { var prehost = spec.substring(0,
hostStart); var prehosttext = doc.createTextNode(prehost); var posthost = spec.substring(hostStart +
host.length, spec.length); var posthosttext = doc.createTextNode(posthost); var hosttext
= doc.createTextNode(host); var boldElement = doc.createElement('b'); boldElement.appendChild(hosttext);
var urldiv = doc.createElement('div'); urldiv.setAttribute('class', 'url'); urldiv.appendChild(prehosttext); urldiv.appendChild(boldElement);
urldiv.appendChild(posthosttext); td.appendChild(urldiv); } */ var urldiv = doc.createElement('div');
urldiv.setAttribute('class', 'url'); var urltext = doc.createTextNode(spec); urldiv.appendChild(urltext);
td.appendChild(urldiv); } // smooth the counts var counts2 = new Array(counts.length); for
(var i = 0; i < counts.length; i ++) { var ttl = 0; var acc = 0; for (var j = -2; j
= counts.length) continue; var scale;
if (j == -2 || j == 2) scale = 0.33; else if (j == -1 || j == 1) scale = 0.66; else
scale = 1.0; acc += counts[i+j] * scale; ttl += scale; } counts2[i] = Math.round(acc);
// fill in the day bargraphs var daylist = document.getElementById("daylist"); for
(var i = 0; i < counts2.length / 24; i ++) { var day = document.createElement('hbox');
day.setAttribute('align', 'center'); if (i % 2) day.setAttribute('class', 'day2'); else
day.setAttribute('class', 'day1'); daylist.appendChild(day); var text = document.createTextNode("Today
- " + i ); var description = document.createElement('description'); description.setAttribute('flex', '1'); description.appendChild(text);
day.appendChild(description); var bars = document.createElement('vbox'); bars.setAttribute('align',
'end'); day.appendChild(bars); for (var b = 0; b < 24; b++) { var box = document.createElement('hbox');
box.setAttribute('width', '' + counts2[i*24 + b]); box.setAttribute('height', '1'); box.setAttribute('class',
'green'); bars.appendChild(box); } content/browser/history/history-panel.xul
%placesDTD;
content/browser/places/history-panel.js//@line 40 "e:\builds\moz2_slave\win32_build\build\browser\components\places\content\history-panel.js"
var gHistoryTree; var gSearchBox; var gHistoryGrouping = ""; var gSearching = false; function HistorySidebarInit()
gHistoryTree = document.getElementById("historyTree"); gSearchBox = document.getElementById("search-box");
gHistoryGrouping = document.getElementById("viewButton"). getAttribute("selectedsort"); if (gHistoryGrouping
== "site") document.getElementById("bysite").setAttribute("checked", "true"); else if (gHistoryGrouping == "visited")
document.getElementById("byvisited").setAttribute("checked", "true"); else if (gHistoryGrouping == "lastvisited")
document.getElementById("bylastvisited").setAttribute("checked", "true"); else if (gHistoryGrouping == "dayandsite")
document.getElementById("bydayandsite").setAttribute("checked", "true"); else document.getElementById("byday").setAttribute("checked",
"true"); searchHistory(""); function GroupBy(groupingType) gHistoryGrouping = groupingType; searchHistory(gSearchBox.value);
function searchHistory(aInput) var query = PlacesUtils.history.getNewQuery(); var options
= PlacesUtils.history.getNewQueryOptions(); const NHQO = Ci.nsINavHistoryQueryOptions;
var sortingMode; var resultType; switch (gHistoryGrouping) { case "visited": resultType = NHQO.RESULTS_AS_URI;
sortingMode = NHQO.SORT_BY_VISITCOUNT_DESCENDING; break; case "lastvisited": resultType = NHQO.RESULTS_AS_URI;
sortingMode = NHQO.SORT_BY_DATE_DESCENDING; break; case "dayandsite": resultType = NHQO.RESULTS_AS_DATE_SITE_QUERY;
break; case "site": resultType = NHQO.RESULTS_AS_SITE_QUERY; sortingMode = NHQO.SORT_BY_TITLE_ASCENDING;
break; case "day": default: resultType = NHQO.RESULTS_AS_DATE_QUERY; break; if (aInput)
{ query.searchTerms = aInput; if (gHistoryGrouping != "visited" && gHistoryGrouping != "lastvisited")
{ sortingMode = NHQO.SORT_BY_TITLE_ASCENDING; resultType = NHQO.RESULTS_AS_URI; } options.sortingMode
= sortingMode; options.resultType = resultType; // call load() on the tree manually // instead
of setting the place attribute in history-panel.xul // otherwise, we will end up calling load()
twice gHistoryTree.load([query], options); window.addEventListener("SidebarFocused",
function() gSearchBox.focus(), false); content/browser/bookmarks/bookmarksPanel.xul
content/browser/bookmarks/bookmarksPanel.js//@line 37 "e:\builds\moz2_slave\win32_build\build\browser\components\places\content\bookmarksPanel.js"
function init() { document.getElementById("bookmarks-view").place = "place:queryType=1&folder=" + window.top.PlacesUIUtils.allBookmarksFolderId;
function searchBookmarks(aSearchString) { var tree = document.getElementById('bookmarks-view');
if (!aSearchString) tree.place = tree.place; else tree.applyFilter(aSearchString, [PlacesUtils.bookmarksMenuFolderId,
PlacesUtils.unfiledBookmarksFolderId, PlacesUtils.toolbarFolderId]); window.addEventListener("SidebarFocused",
function() document.getElementById("search-box").focus(), false); content/browser/bookmarks/sidebarUtils.js//@line
39 "e:\builds\moz2_slave\win32_build\build\browser\components\places\content\sidebarUtils.js" var SidebarUtils = { handleTreeClick: function
SU_handleTreeClick(aTree, aEvent, aGutterSelect) { // right-clicks are not handled here if
(aEvent.button == 2) return; var tbo = aTree.treeBoxObject; var row = { }, col = { }, obj = { }; tbo.getCellAt(aEvent.clientX,
aEvent.clientY, row, col, obj); if (row.value == -1 || obj.value == "twisty") return; var
mouseInGutter = false; if (aGutterSelect) { var x = { }, y = { }, w = { }, h = { };
tbo.getCoordsForCellItem(row.value, col.value, "image", x, y, w, h); // getCoordsForCellItem
returns the x coordinate in logical coordinates // (i.e., starting from the left and right
sides in LTR and RTL modes, // respectively.) Therefore, we make sure to exclude the blank
area // before the tree item icon (that is, to the left or right of it in // LTR and RTL
modes, respectively) from the click target area. var isRTL = window.getComputedStyle(aTree,
null).direction == "rtl"; if (isRTL) mouseInGutter = aEvent.clientX > x.value; else mouseInGutter
= aEvent.clientX < x.value; } //@line 73 "e:\builds\moz2_slave\win32_build\build\browser\components\places\content\sidebarUtils.js"
var modifKey = aEvent.ctrlKey || aEvent.shiftKey; //@line 75 "e:\builds\moz2_slave\win32_build\build\browser\components\places\content\sidebarUtils.js"
var isContainer = tbo.view.isContainer(row.value); var openInTabs = isContainer && (aEvent.button
== 1 || (aEvent.button == 0 && modifKey)) && PlacesUtils.hasChildURIs(tbo.view.nodeForTreeIndex(row.value));
if (aEvent.button == 0 && isContainer && !openInTabs) { tbo.view.toggleOpenState(row.value);
return; } else if (!mouseInGutter && openInTabs && aEvent.originalTarget.localName == "treechildren")
{ tbo.view.selection.select(row.value); PlacesUIUtils.openContainerNodeInTabs(aTree.selectedNode, aEvent); } else if (!mouseInGutter && !isContainer
&& aEvent.originalTarget.localName == "treechildren") { // Clear all other selection since we're
loading a link now. We must // 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);
PlacesUIUtils.openNodeWithEvent(aTree.selectedNode, aEvent); } }, handleTreeKeyPress: function
SU_handleTreeKeyPress(aEvent) { if (aEvent.keyCode == KeyEvent.DOM_VK_RETURN) PlacesUIUtils.openNodeWithEvent(aEvent.target.selectedNode,
aEvent); }, /** * The following function displays the URL of a node that is being * hovered
over. */ handleTreeMouseMove: function SU_handleTreeMouseMove(aEvent) { if (aEvent.target.localName != "treechildren")
return; var tree = aEvent.target.parentNode; var tbo = tree.treeBoxObject; var row = {
}, col = { }, obj = { }; tbo.getCellAt(aEvent.clientX, aEvent.clientY, row, col, obj); // row.value
is -1 when the mouse is hovering an empty area within the tree. // To avoid showing
a URL from a previously hovered node, // for a currently hovered non-url node, we must
clear the URL from the // status bar in these cases. if (row.value != -1) { var cell =
tree.view.nodeForTreeIndex(row.value); if (PlacesUtils.nodeIsURI(cell)) window.top.XULBrowserWindow.setOverLink(cell.uri,
null); else this.clearURLFromStatusBar(); } else this.clearURLFromStatusBar(); },
clearURLFromStatusBar: function SU_clearURLFromStatusBar() { window.top.XULBrowserWindow.setOverLink("",
null); content/browser/places/moveBookmarks.xul
content/browser/places/moveBookmarks.js/* -*- Mode: C++; tab-width: 8; indent-tabs-mode:
nil; c-basic-offset: 2 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL
2.0/LGPL 2.1 * The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with * the License.
You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * Software distributed
under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND,
either express or implied. See the License * for the specific language governing rights
and limitations under the * License. * The Original Code is the Places Move Bookmarks
Dialog. * The Initial Developer of the Original Code is Mozilla Corporation. * Portions created
by the Initial Developer are Copyright (C) 2007 * the Initial Developer. All Rights Reserved.
* Contributor(s): * Asaf Romano * Sungjoon Steve Won
* 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 gMoveBookmarksDialog = { _nodes: null,
_foldersTree: null, get foldersTree() { if (!this._foldersTree) this._foldersTree =
document.getElementById("foldersTree"); return this._foldersTree; }, init: function() {
this._nodes = window.arguments[0]; this.foldersTree.place = "place:excludeItems=1&excludeQueries=1&excludeReadOnlyFolders=1&folder="
+ PlacesUIUtils.allBookmarksFolderId; }, onOK: function MBD_onOK(aEvent) { var selectedNode
= this.foldersTree.selectedNode; NS_ASSERT(selectedNode, "selectedNode must be set in a single-selection
tree with initial selection set"); var selectedFolderID = PlacesUtils.getConcreteItemId(selectedNode);
var transactions = []; for (var i=0; i < this._nodes.length; i++) { // Nothing to do
if the node is already under the selected folder if (this._nodes[i].parent.itemId ==
selectedFolderID) continue; transactions.push(new PlacesUIUtils.ptm.moveItem(this._nodes[i].itemId,
selectedFolderID, -1)); } if (transactions.length != 0) { var txn = PlacesUIUtils.ptm.aggregateTransactions("Move
Items", transactions); PlacesUIUtils.ptm.doTransaction(txn); } }, newFolder: function MBD_newFolder()
{ // The command is disabled when the tree is not focused this.foldersTree.focus(); goDoCommand("placesCmd_new:folder");
content/browser/places/editBookmarkOverlay.xul
content/browser/places/editBookmarkOverlay.js/* -*- Mode: C++; tab-width: 8; indent-tabs-mode:
nil; c-basic-offset: 2 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL
2.0/LGPL 2.1 * The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with * the License.
You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * Software distributed
under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND,
either express or implied. See the License * for the specific language governing rights
and limitations under the * License. * The Original Code is the Places Bookmark Properties
dialog. * 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): * Asaf Romano * 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 *****
*/ const LAST_USED_ANNO = "bookmarkPropertiesDialog/folderLastUsed"; const STATIC_TITLE_ANNO = "bookmarks/staticTitle";
const MAX_FOLDER_ITEM_IN_MENU_LIST = 5; var gEditItemOverlay = { _uri: null, _itemId:
-1, _itemIds: [], _uris: [], _tags: [], _allTags: [], _multiEdit: false, _itemType: -1, _readOnly:
false, _microsummaries: null, _hiddenRows: [], _observersAdded: false, _staticFoldersListBuilt:
false, _initialized: false, // the first field which was edited after this panel was initialized
for // a certain item _firstEditedField: "", get itemId() { return this._itemId; },
get uri() { return this._uri; }, get multiEdit() { return this._multiEdit; }, /** * Determines
the initial data for the item edited or added by this dialog */ _determineInfo: function
EIO__determineInfo(aInfo) { // hidden rows if (aInfo && aInfo.hiddenRows) this._hiddenRows
= aInfo.hiddenRows; else this._hiddenRows.splice(0); // force-read-only this._readOnly = aInfo
&& aInfo.forceReadOnly; }, _showHideRows: function EIO__showHideRows() { var isBookmark
= this._itemId != -1 && this._itemType == Ci.nsINavBookmarksService.TYPE_BOOKMARK;
var isQuery = false; if (this._uri) isQuery = this._uri.schemeIs("place"); this._element("nameRow").collapsed
= this._hiddenRows.indexOf("name") != -1; this._element("folderRow").collapsed = this._hiddenRows.indexOf("folderPicker")
!= -1 || this._readOnly; this._element("tagsRow").collapsed = !this._uri || this._hiddenRows.indexOf("tags")
!= -1 || isQuery; // Collapse the tag selector if the item does not accept tags. if (!this._element("tagsSelectorRow").collapsed
&& this._element("tagsRow").collapsed) this.toggleTagsSelector(); this._element("descriptionRow").collapsed
= this._hiddenRows.indexOf("description") != -1 || this._readOnly; this._element("keywordRow").collapsed
= !isBookmark || this._readOnly || this._hiddenRows.indexOf("keyword") != -1 || isQuery; this._element("locationRow").collapsed
= !(this._uri && !isQuery) || this._hiddenRows.indexOf("location") != -1; this._element("loadInSidebarCheckbox").collapsed
= !isBookmark || isQuery || this._readOnly || this._hiddenRows.indexOf("loadInSidebar")
!= -1; this._element("feedLocationRow").collapsed = !this._isLivemark || this._hiddenRows.indexOf("feedLocation")
!= -1; this._element("siteLocationRow").collapsed = !this._isLivemark || this._hiddenRows.indexOf("siteLocation")
!= -1; this._element("selectionCount").hidden = !this._multiEdit; }, /** * Initialize the
panel * @param aFor * Either a places-itemId (of a bookmark, folder or a live bookmark),
* an array of itemIds (used for bulk tagging), or a URI object (in * which case, the panel
would be initialized in read-only mode). * @param [optional] aInfo * JS object which
stores additional info for the panel * initialization. The following properties may bet set: * *
hiddenRows (Strings array): list of rows to be hidden regardless * of the item edited.
Possible values: "title", "location", * "description", "keyword", "loadInSidebar", "feedLocation",
* "siteLocation", folderPicker" * * forceReadOnly - set this flag to initialize the panel to
its * read-only (view) mode even if the given item is editable. */ initPanel: function EIO_initPanel(aFor,
aInfo) { // For sanity ensure that the implementer has uninited the panel before // trying to
init it again, or we could end up leaking due to observers. if (this._initialized) this.uninitPanel(false);
var aItemIdList; if (aFor.length) { aItemIdList = aFor; aFor = aItemIdList[0]; } else if
(this._multiEdit) { this._multiEdit = false; this._tags = []; this._uris = []; this._allTags
= []; this._itemIds = []; this._element("selectionCount").hidden = true; } this._folderMenuList = this._element("folderMenuList");
this._folderTree = this._element("folderTree"); this._determineInfo(aInfo); if (aFor instanceof
Ci.nsIURI) { this._itemId = -1; this._uri = aFor; this._readOnly = true; } else {
this._itemId = aFor; var containerId = PlacesUtils.bookmarks.getFolderIdForItem(this._itemId); this._itemType = PlacesUtils.bookmarks.getItemType(this._itemId);
if (this._itemType == Ci.nsINavBookmarksService.TYPE_BOOKMARK) { this._uri = PlacesUtils.bookmarks.getBookmarkURI(this._itemId);
if (!this._readOnly) // If readOnly wasn't forced through aInfo this._readOnly = PlacesUtils.itemIsLivemark(containerId);
this._initTextField("keywordField", PlacesUtils.bookmarks .getKeywordForBookmark(this._itemId)); //
Load In Sidebar checkbox this._element("loadInSidebarCheckbox").checked = PlacesUtils.annotations.itemHasAnnotation(this._itemId,
LOAD_IN_SIDEBAR_ANNO); } else { if (!this._readOnly) // If readOnly wasn't forced through aInfo
this._readOnly = false; this._uri = null; this._isLivemark = PlacesUtils.itemIsLivemark(this._itemId);
if (this._isLivemark) { var feedURI = PlacesUtils.livemarks.getFeedURI(this._itemId); var siteURI = PlacesUtils.livemarks.getSiteURI(this._itemId);
this._initTextField("feedLocationField", feedURI.spec); this._initTextField("siteLocationField", siteURI
? siteURI.spec : ""); } } // folder picker this._initFolderMenuList(containerId); //
description field this._initTextField("descriptionField", PlacesUIUtils.getItemDescription(this._itemId));
} if (this._itemId == -1 || this._itemType == Ci.nsINavBookmarksService.TYPE_BOOKMARK)
{ this._isLivemark = false; this._initTextField("locationField", this._uri.spec); if (!aItemIdList) { var tags
= PlacesUtils.tagging.getTagsForURI(this._uri, {}).join(", "); this._initTextField("tagsField",
tags, false); } else { this._multiEdit = true; this._allTags = []; this._itemIds =
aItemIdList; var nodeToCheck = 0; for (var i = 0; i < aItemIdList.length; i++) { if (aItemIdList[i]
instanceof Ci.nsIURI) { this._uris[i] = aItemIdList[i]; this._itemIds[i] = -1; } else this._uris[i]
= PlacesUtils.bookmarks.getBookmarkURI(this._itemIds[i], {}); this._tags[i] = PlacesUtils.tagging.getTagsForURI(this._uris[i],
{}); if (this._tags[i].length < this._tags[nodeToCheck].length) nodeToCheck = i; } this._getCommonTags(nodeToCheck);
this._initTextField("tagsField", this._allTags.join(", "), false); this._element("itemsCountText").value
= PlacesUIUtils.getFormattedString("detailsPane.multipleItems", [this._itemIds.length]); } // tags selector
this._rebuildTagsSelectorList(); } // name picker this._initNamePicker(); this._showHideRows();
// observe changes if (!this._observersAdded) { if (this._itemId != -1) PlacesUtils.bookmarks.addObserver(this,
false); window.addEventListener("unload", this, false); this._observersAdded = true;
} this._initialized = true; }, _getCommonTags: function(aArrIndex) { var tempArray = this._tags[aArrIndex];
var isAllTag; for (var k = 0; k < tempArray.length; k++) { isAllTag = true; for (var j = 0; j
< this._tags.length; j++) { if (j == aArrIndex) continue; if (this._tags[j].indexOf(tempArray[k])
== -1) { isAllTag = false; break; } } if (isAllTag) this._allTags.push(tempArray[k]);
} }, _initTextField: function(aTextFieldId, aValue, aReadOnly) { var field = this._element(aTextFieldId);
field.readOnly = aReadOnly !== undefined ? aReadOnly : this._readOnly; if (field.value
!= aValue) { field.value = aValue; // clear the undo stack var editor = field.editor;
if (editor) editor.transactionManager.clear(); } }, /** * Appends a menu-item representing
a bookmarks folder to a menu-popup. * @param aMenupopup * The popup to which the menu-item
should be added. * @param aFolderId * The identifier of the bookmarks folder. * @return
the new menu item. */ _appendFolderItemToMenupopup: function EIO__appendFolderItemToMenuList(aMenupopup,
aFolderId) { // First make sure the folders-separator is visible this._element("foldersSeparator").hidden
= false; var folderMenuItem = document.createElement("menuitem"); var folderTitle = PlacesUtils.bookmarks.getItemTitle(aFolderId)
folderMenuItem.folderId = aFolderId; folderMenuItem.setAttribute("label", folderTitle); folderMenuItem.className =
"menuitem-iconic folder-icon"; aMenupopup.appendChild(folderMenuItem); return folderMenuItem; }, _initFolderMenuList:
function EIO__initFolderMenuList(aSelectedFolder) { // clean up first var menupopup = this._folderMenuList.menupopup;
while (menupopup.childNodes.length > 6) menupopup.removeChild(menupopup.lastChild); const bms = PlacesUtils.bookmarks; const annos
= PlacesUtils.annotations; // Build the static list var unfiledItem = this._element("unfiledRootItem");
if (!this._staticFoldersListBuilt) { unfiledItem.label = bms.getItemTitle(PlacesUtils.unfiledBookmarksFolderId);
unfiledItem.folderId = PlacesUtils.unfiledBookmarksFolderId; var bmMenuItem = this._element("bmRootItem");
bmMenuItem.label = bms.getItemTitle(PlacesUtils.bookmarksMenuFolderId); bmMenuItem.folderId = PlacesUtils.bookmarksMenuFolderId;
var toolbarItem = this._element("toolbarFolderItem"); toolbarItem.label = bms.getItemTitle(PlacesUtils.toolbarFolderId);
toolbarItem.folderId = PlacesUtils.toolbarFolderId; this._staticFoldersListBuilt = true; } //
List of recently used folders: var folderIds = annos.getItemsWithAnnotation(LAST_USED_ANNO,
{ }); /** * The value of the LAST_USED_ANNO annotation is the time (in the form of *
Date.getTime) at which the folder has been last used. * * First we build the annotated
folders array, each item has both the * folder identifier and the time at which it was last-used
by this dialog * set. Then we sort it descendingly based on the time field. */ this._recentFolders
= []; for (var i = 0; i < folderIds.length; i++) { var lastUsed = annos.getItemAnnotation(folderIds[i],
LAST_USED_ANNO); this._recentFolders.push({ folderId: folderIds[i], lastUsed: lastUsed
}); } this._recentFolders.sort(function(a, b) { if (b.lastUsed < a.lastUsed) return -1;
if (b.lastUsed > a.lastUsed) return 1; return 0; }); var numberOfItems = Math.min(MAX_FOLDER_ITEM_IN_MENU_LIST,
this._recentFolders.length); for (var i = 0; i < numberOfItems; i++) { this._appendFolderItemToMenupopup(menupopup,
this._recentFolders[i].folderId); } var defaultItem = this._getFolderMenuItem(aSelectedFolder);
this._folderMenuList.selectedItem = defaultItem; // Set a selectedIndex attribute to show
special icons this._folderMenuList.setAttribute("selectedIndex", this._folderMenuList.selectedIndex); // Hide
the folders-separator if no folder is annotated as recently-used this._element("foldersSeparator").hidden
= (menupopup.childNodes.length 2) menupopup.removeChild(menupopup.lastChild);
if (this._microsummaries) { this._microsummaries.removeObserver(this); this._microsummaries = null; } var itemToSelect
= userEnteredNameField; try { if (this._itemId != -1 && this._itemType == Ci.nsINavBookmarksService.TYPE_BOOKMARK
&& !this._readOnly) this._microsummaries = PlacesUIUtils.microsummaries .getMicrosummaries(this._uri,
-1); } catch(ex) { // getMicrosummaries will throw an exception in at least two cases:
// 1. the bookmarked URI contains a scheme that the service won't // download for security
reasons (currently it only handles http, // https, and file); // 2. the page to which
the URI refers isn't HTML or XML (the only two // content types the service knows how
to summarize). this._microsummaries = null; } if (this._microsummaries) { var enumerator
= this._microsummaries.Enumerate(); if (enumerator.hasMoreElements()) { // Show the drop marker if there are microsummaries
droppable = true; while (enumerator.hasMoreElements()) { var microsummary = enumerator.getNext()
.QueryInterface(Ci.nsIMicrosummary); var menuItem = this._createMicrosummaryMenuItem(microsummary);
if (PlacesUIUtils.microsummaries .isMicrosummary(this._itemId, microsummary)) itemToSelect = menuItem; menupopup.appendChild(menuItem);
} } this._microsummaries.addObserver(this); } if (namePicker.selectedItem == itemToSelect)
namePicker.value = itemToSelect.label; else namePicker.selectedItem = itemToSelect; namePicker.setAttribute("droppable",
droppable); namePicker.readOnly = this._readOnly; // clear the undo stack var editor = namePicker.editor;
if (editor) editor.transactionManager.clear(); }, // nsIMicrosummaryObserver onContentLoaded:
function EIO_onContentLoaded(aMicrosummary) { var namePicker = this._element("namePicker");
var childNodes = namePicker.menupopup.childNodes; // 0: user-entered item; 1: separator for
(var i = 2; i < childNodes.length; i++) { if (childNodes[i].microsummary == aMicrosummary)
{ var newLabel = aMicrosummary.content; // XXXmano: non-editable menulist would do
this for us, see bug 360220 // We should fix editable-menulists to set the DOMAttrModified
handler // as well. // // Also note the order importance: if the label of the menu-item
is // set to something different than the menulist's current value, // the menulist
no longer has selectedItem set if (namePicker.selectedItem == childNodes[i]) namePicker.value = newLabel;
childNodes[i].label = newLabel; return; } } }, onElementAppended: function EIO_onElementAppended(aMicrosummary)
{ var namePicker = this._element("namePicker"); namePicker.menupopup .appendChild(this._createMicrosummaryMenuItem(aMicrosummary));
// Make sure the drop-marker is shown namePicker.setAttribute("droppable", "true"); }, uninitPanel: function EIO_uninitPanel(aHideCollapsibleElements)
{ if (aHideCollapsibleElements) { // hide the folder tree if it was previously visible
var folderTreeRow = this._element("folderTreeRow"); if (!folderTreeRow.collapsed) this.toggleFolderTreeVisibility();
// hide the tag selector if it was previously visible var tagsSelectorRow = this._element("tagsSelectorRow");
if (!tagsSelectorRow.collapsed) this.toggleTagsSelector(); } if (this._observersAdded) { if (this._itemId
!= -1) PlacesUtils.bookmarks.removeObserver(this); this._observersAdded = false; } if (this._microsummaries)
{ this._microsummaries.removeObserver(this); this._microsummaries = null; } this._itemId
= -1; this._uri = null; this._uris = []; this._tags = []; this._allTags = []; this._itemIds
= []; this._multiEdit = false; this._firstEditedField = ""; this._initialized = false; }, onTagsFieldBlur:
function EIO_onTagsFieldBlur() { if (this._updateTags()) // if anything has changed this._mayUpdateFirstEditField("tagsField");
}, _updateTags: function EIO__updateTags() { if (this._multiEdit) return this._updateMultipleTagsForItems();
return this._updateSingleTagForItem(); }, _updateSingleTagForItem: function EIO__updateSingleTagForItem()
{ var currentTags = PlacesUtils.tagging.getTagsForURI(this._uri, { }); var tags = this._getTagsArrayFromTagField();
if (tags.length > 0 || currentTags.length > 0) { var tagsToRemove = []; var tagsToAdd
= []; var txns = []; for (var i = 0; i < currentTags.length; i++) { if (tags.indexOf(currentTags[i])
== -1) tagsToRemove.push(currentTags[i]); } for (var i = 0; i < tags.length; i++)
{ if (currentTags.indexOf(tags[i]) == -1) tagsToAdd.push(tags[i]); } if (tagsToRemove.length
> 0) txns.push(PlacesUIUtils.ptm.untagURI(this._uri, tagsToRemove)); if (tagsToAdd.length > 0)
txns.push(PlacesUIUtils.ptm.tagURI(this._uri, tagsToAdd)); if (txns.length > 0) { var aggregate
= PlacesUIUtils.ptm.aggregateTransactions("Update tags", txns); PlacesUIUtils.ptm.doTransaction(aggregate);
// Ensure the tagsField is in sync, clean it up from empty tags var tags = PlacesUtils.tagging.getTagsForURI(this._uri,
{}).join(", "); this._initTextField("tagsField", tags, false); return true; } } return false;
}, /** * Stores the first-edit field for this dialog, if the passed-in field * is indeed
the first edited field * @param aNewField * the id of the field that may be set (without
the "editBMPanel_" * prefix) */ _mayUpdateFirstEditField: function EIO__mayUpdateFirstEditField(aNewField)
{ // * The first-edit-field behavior is not applied in the multi-edit case // * if this._firstEditedField
is already set, this is not the first field, // so there's nothing to do if (this._multiEdit
|| this._firstEditedField) return; this._firstEditedField = aNewField; // set the pref var prefs =
Cc["@mozilla.org/preferences-service;1"]. getService(Ci.nsIPrefBranch); prefs.setCharPref("browser.bookmarks.editDialog.firstEditField",
aNewField); }, _updateMultipleTagsForItems: function EIO__updateMultipleTagsForItems()
{ var tags = this._getTagsArrayFromTagField(); if (tags.length > 0 || this._allTags.length
> 0) { var tagsToRemove = []; var tagsToAdd = []; var txns = []; for (var i = 0; i <
this._allTags.length; i++) { if (tags.indexOf(this._allTags[i]) == -1) tagsToRemove.push(this._allTags[i]);
} for (var i = 0; i < this._tags.length; i++) { tagsToAdd[i] = []; for (var j = 0;
j < tags.length; j++) { if (this._tags[i].indexOf(tags[j]) == -1) tagsToAdd[i].push(tags[j]); } } if
(tagsToAdd.length > 0) { for (i = 0; i < this._uris.length; i++) { if (tagsToAdd[i].length
> 0) txns.push(PlacesUIUtils.ptm.tagURI(this._uris[i], tagsToAdd[i])); } } if (tagsToRemove.length
> 0) { for (var i = 0; i < this._uris.length; i++) txns.push(PlacesUIUtils.ptm.untagURI(this._uris[i],
tagsToRemove)); } if (txns.length > 0) { var aggregate = PlacesUIUtils.ptm.aggregateTransactions("Update
tags", txns); PlacesUIUtils.ptm.doTransaction(aggregate); this._allTags = tags; this._tags = []; for
(i = 0; i < this._uris.length; i++) this._tags[i] = PlacesUtils.tagging.getTagsForURI(this._uris[i],
{}); // Ensure the tagsField is in sync, clean it up from empty tags this._initTextField("tagsField",
tags, false); return true; } } return false; }, onNamePickerInput: function EIO_onNamePickerInput()
{ var title = this._element("namePicker").value; this._element("userEnteredName").label =
title; }, onNamePickerChange: function EIO_onNamePickerChange() { if (this._itemId == -1) return; var namePicker
= this._element("namePicker") var txns = []; const ptm = PlacesUIUtils.ptm; // Here
we update either the item title or its cached static title var newTitle = this._element("userEnteredName").label;
if (this._getItemStaticTitle() != newTitle) { this._mayUpdateFirstEditField("namePicker");
if (PlacesUIUtils.microsummaries.hasMicrosummary(this._itemId)) { // Note: this implicitly also takes care
of the microsummary->static // title case, the removeMicorosummary method in the service
will set // the item-title to the value of this annotation. // // XXXmano: use a transaction
PlacesUtils.setAnnotationsForItem(this._itemId, [{name: STATIC_TITLE_ANNO, value: newTitle}]);
} else txns.push(ptm.editItemTitle(this._itemId, newTitle)); } var newMicrosummary = namePicker.selectedItem.microsummary;
// Only add a microsummary update to the transaction if the microsummary // has actually
changed, i.e. the user selected no microsummary, but the // bookmark previously had one, or
the user selected a microsummary which // is not the one the bookmark previously had
if ((newMicrosummary == null && PlacesUIUtils.microsummaries.hasMicrosummary(this._itemId)) || (newMicrosummary != null && !PlacesUIUtils.microsummaries
.isMicrosummary(this._itemId, newMicrosummary))) { txns.push(ptm.editBookmarkMicrosummary(this._itemId,
newMicrosummary)); } var aggregate = ptm.aggregateTransactions("Edit Item Title", txns); ptm.doTransaction(aggregate);
}, onDescriptionFieldBlur: function EIO_onDescriptionFieldBlur() { var description = this._element("descriptionField").value;
if (description != PlacesUIUtils.getItemDescription(this._itemId)) { var txn = PlacesUIUtils.ptm .editItemDescription(this._itemId,
description); PlacesUIUtils.ptm.doTransaction(txn); } }, onLocationFieldBlur: function EIO_onLocationFieldBlur()
{ var uri; try { uri = PlacesUIUtils.createFixedURI(this._element("locationField").value); } catch(ex) { return; } if (!this._uri.equals(uri))
{ var txn = PlacesUIUtils.ptm.editBookmarkURI(this._itemId, uri); PlacesUIUtils.ptm.doTransaction(txn);
this._uri = uri; } }, onKeywordFieldBlur: function EIO_onKeywordFieldBlur() { var keyword
= this._element("keywordField").value; if (keyword != PlacesUtils.bookmarks.getKeywordForBookmark(this._itemId))
{ var txn = PlacesUIUtils.ptm.editBookmarkKeyword(this._itemId, keyword); PlacesUIUtils.ptm.doTransaction(txn);
} }, onFeedLocationFieldBlur: function EIO_onFeedLocationFieldBlur() { var uri; try { uri = PlacesUIUtils.createFixedURI(this._element("feedLocationField").value);
} catch(ex) { return; } var currentFeedURI = PlacesUtils.livemarks.getFeedURI(this._itemId);
if (!currentFeedURI.equals(uri)) { var txn = PlacesUIUtils.ptm.editLivemarkFeedURI(this._itemId,
uri); PlacesUIUtils.ptm.doTransaction(txn); } }, onSiteLocationFieldBlur: function EIO_onSiteLocationFieldBlur()
{ var uri = null; try { uri = PlacesUIUtils.createFixedURI(this._element("siteLocationField").value); } catch(ex) { } var currentSiteURI = PlacesUtils.livemarks.getSiteURI(this._itemId);
if (!uri || !currentSiteURI.equals(uri)) { var txn = PlacesUIUtils.ptm.editLivemarkSiteURI(this._itemId,
uri); PlacesUIUtils.ptm.doTransaction(txn); } }, onLoadInSidebarCheckboxCommand: function
EIO_onLoadInSidebarCheckboxCommand() { var loadInSidebarChecked = this._element("loadInSidebarCheckbox").checked;
var txn = PlacesUIUtils.ptm.setLoadInSidebar(this._itemId, loadInSidebarChecked); PlacesUIUtils.ptm.doTransaction(txn);
}, toggleFolderTreeVisibility: function EIO_toggleFolderTreeVisibility() { var expander = this._element("foldersExpander");
var folderTreeRow = this._element("folderTreeRow"); if (!folderTreeRow.collapsed) { expander.className
= "expander-down"; expander.setAttribute("tooltiptext", expander.getAttribute("tooltiptextdown"));
folderTreeRow.collapsed = true; this._element("chooseFolderSeparator").hidden = this._element("chooseFolderMenuItem").hidden
= false; } else { expander.className = "expander-up" expander.setAttribute("tooltiptext", expander.getAttribute("tooltiptextup"));
folderTreeRow.collapsed = false; // XXXmano: Ideally we would only do this once, but for
some odd reason, // the editable mode set on this tree, together with its collapsed
state // breaks the view. const FOLDER_TREE_PLACE_URI = "place:excludeItems=1&excludeQueries=1&excludeReadOnlyFolders=1&folder="
+ PlacesUIUtils.allBookmarksFolderId; this._folderTree.place = FOLDER_TREE_PLACE_URI; this._element("chooseFolderSeparator").hidden
= this._element("chooseFolderMenuItem").hidden = true; var currentFolder = this._getFolderIdFromMenuList();
this._folderTree.selectItems([currentFolder]); this._folderTree.focus(); } }, _getFolderIdFromMenuList:
function EIO__getFolderIdFromMenuList() { var selectedItem = this._folderMenuList.selectedItem;
NS_ASSERT("folderId" in selectedItem, "Invalid menuitem in the folders-menulist"); return
selectedItem.folderId; }, /** * Get the corresponding menu-item in the folder-menu-list for a bookmarks
* folder if such an item exists. Otherwise, this creates a menu-item for the * folder.
If the items-count limit (see MAX_FOLDERS_IN_MENU_LIST) is reached, * the new item replaces the last
menu-item. * @param aFolderId * The identifier of the bookmarks folder. */ _getFolderMenuItem:
function EIO__getFolderMenuItem(aFolderId) { var menupopup = this._folderMenuList.menupopup;
for (var i=0; i < menupopup.childNodes.length; i++) { if (menupopup.childNodes[i].folderId
&& menupopup.childNodes[i].folderId == aFolderId) return menupopup.childNodes[i]; } // 3 special
folders + separator + folder-items-count limit if (menupopup.childNodes.length == 4 + MAX_FOLDER_ITEM_IN_MENU_LIST)
menupopup.removeChild(menupopup.lastChild); return this._appendFolderItemToMenupopup(menupopup,
aFolderId); }, onFolderMenuListCommand: function EIO_onFolderMenuListCommand(aEvent) { //
Set a selectedIndex attribute to show special icons this._folderMenuList.setAttribute("selectedIndex",
this._folderMenuList.selectedIndex); if (aEvent.target.id == "editBMPanel_chooseFolderMenuItem") {
// reset the selection back to where it was and expand the tree // (this menu-item is
hidden when the tree is already visible var container = PlacesUtils.bookmarks.getFolderIdForItem(this._itemId);
var item = this._getFolderMenuItem(container); this._folderMenuList.selectedItem = item;
// XXXmano HACK: setTimeout 100, otherwise focus goes back to the // menulist right away
setTimeout(function(self) self.toggleFolderTreeVisibility(), 100, this); return; } // Move the item var
container = this._getFolderIdFromMenuList(); if (PlacesUtils.bookmarks.getFolderIdForItem(this._itemId)
!= container) { var txn = PlacesUIUtils.ptm.moveItem(this._itemId, container, -1); PlacesUIUtils.ptm.doTransaction(txn);
// Mark the containing folder as recently-used if it isn't in the // static list if (container
!= PlacesUtils.unfiledBookmarksFolderId && container != PlacesUtils.toolbarFolderId
&& container != PlacesUtils.bookmarksMenuFolderId) this._markFolderAsRecentlyUsed(container);
} // Update folder-tree selection var folderTreeRow = this._element("folderTreeRow"); if (!folderTreeRow.collapsed)
{ var selectedNode = this._folderTree.selectedNode; if (!selectedNode || PlacesUtils.getConcreteItemId(selectedNode)
!= container) this._folderTree.selectItems([container]); } }, onFolderTreeSelect: function EIO_onFolderTreeSelect()
{ var selectedNode = this._folderTree.selectedNode; // Disable the "New Folder" button if we
cannot create a new folder this._element("newFolderButton") .disabled = !this._folderTree.insertionPoint
|| !selectedNode; if (!selectedNode) return; var folderId = PlacesUtils.getConcreteItemId(selectedNode);
if (this._getFolderIdFromMenuList() == folderId) return; var folderItem = this._getFolderMenuItem(folderId);
this._folderMenuList.selectedItem = folderItem; folderItem.doCommand(); }, _markFolderAsRecentlyUsed:
function EIO__markFolderAsRecentlyUsed(aFolderId) { var txns = []; // Expire old unused recent
folders var anno = this._getLastUsedAnnotationObject(false); while (this._recentFolders.length > MAX_FOLDER_ITEM_IN_MENU_LIST)
{ var folderId = this._recentFolders.pop().folderId; txns.push(PlacesUIUtils.ptm.setItemAnnotation(folderId,
anno)); } // Mark folder as recently used anno = this._getLastUsedAnnotationObject(true);
txns.push(PlacesUIUtils.ptm.setItemAnnotation(aFolderId, anno)); var aggregate = PlacesUIUtils.ptm.aggregateTransactions("Update
last used folders", txns); PlacesUIUtils.ptm.doTransaction(aggregate); }, /** * Returns an object which could then
be used to set/unset the * LAST_USED_ANNO annotation for a folder. * * @param aLastUsed
* Whether to set or unset the LAST_USED_ANNO annotation. * @returns an object representing
the annotation which could then be used * with the transaction manager. */ _getLastUsedAnnotationObject:
function EIO__getLastUsedAnnotationObject(aLastUsed) { var anno = { name: LAST_USED_ANNO, type:
Ci.nsIAnnotationService.TYPE_INT32, flags: 0, value: aLastUsed ? new Date().getTime()
: null, expires: Ci.nsIAnnotationService.EXPIRE_NEVER }; return anno; }, _rebuildTagsSelectorList:
function EIO__rebuildTagsSelectorList() { var tagsSelector = this._element("tagsSelector");
var tagsSelectorRow = this._element("tagsSelectorRow"); if (tagsSelectorRow.collapsed) return; while
(tagsSelector.hasChildNodes()) tagsSelector.removeChild(tagsSelector.lastChild); var tagsInField = this._getTagsArrayFromTagField();
var allTags = PlacesUtils.tagging.allTags; for (var i = 0; i < allTags.length; i++)
{ var tag = allTags[i]; var elt = document.createElement("listitem"); elt.setAttribute("type", "checkbox"); elt.setAttribute("label",
tag); if (tagsInField.indexOf(tag) != -1) elt.setAttribute("checked", "true"); tagsSelector.appendChild(elt);
} }, toggleTagsSelector: function EIO_toggleTagsSelector() { var tagsSelector = this._element("tagsSelector");
var tagsSelectorRow = this._element("tagsSelectorRow"); var expander = this._element("tagsSelectorExpander");
if (tagsSelectorRow.collapsed) { expander.className = "expander-up"; expander.setAttribute("tooltiptext",
expander.getAttribute("tooltiptextup")); tagsSelectorRow.collapsed = false; this._rebuildTagsSelectorList();
// This is a no-op if we've added the listener. tagsSelector.addEventListener("CheckboxStateChange",
this, false); } else { expander.className = "expander-down"; expander.setAttribute("tooltiptext",
expander.getAttribute("tooltiptextdown")); tagsSelectorRow.collapsed = true; } }, _getTagsArrayFromTagField:
function EIO__getTagsArrayFromTagField() { // we don't require the leading space (after
each comma) var tags = this._element("tagsField").value.split(","); for (var i=0; i < tags.length; i++) { //
remove trailing and leading spaces tags[i] = tags[i].replace(/^\s+/, "").replace(/\s+$/,
""); // remove empty entries from the array. if (tags[i] == "") { tags.splice(i, 1); i--;
} } return tags; }, newFolder: function EIO_newFolder() { var ip = this._folderTree.insertionPoint;
// default to the bookmarks menu folder if (!ip || ip.itemId == PlacesUIUtils.allBookmarksFolderId)
{ ip = new InsertionPoint(PlacesUtils.bookmarksMenuFolderId, PlacesUtils.bookmarks.DEFAULT_INDEX, Ci.nsITreeView.DROP_ON);
} // XXXmano: add a separate "New Folder" string at some point... var defaultLabel
= this._element("newFolderButton").label; var txn = PlacesUIUtils.ptm.createFolder(defaultLabel,
ip.itemId, ip.index); PlacesUIUtils.ptm.doTransaction(txn); this._folderTree.focus(); this._folderTree.selectItems([this._lastNewItem]);
this._folderTree.startEditing(this._folderTree.view.selection.currentIndex, this._folderTree.columns.getFirstColumn());
}, // nsIDOMEventListener handleEvent: function EIO_nsIDOMEventListener(aEvent) { switch (aEvent.type)
{ case "CheckboxStateChange": // Update the tags field when items are checked/unchecked
in the listbox var tags = this._getTagsArrayFromTagField(); if (aEvent.target.checked) { if (tags.indexOf(aEvent.target.label)
== -1) tags.push(aEvent.target.label); } else { var indexOfItem = tags.indexOf(aEvent.target.label);
if (indexOfItem != -1) tags.splice(indexOfItem, 1); } this._element("tagsField").value =
tags.join(", "); this._updateTags(); break; case "unload": this.uninitPanel(false); break;
} }, // nsINavBookmarkObserver onItemChanged: function EIO_onItemChanged(aItemId, aProperty,
aIsAnnotationProperty, aValue, aLastModified, aItemType) { if (this._itemId != aItemId)
{ if (aProperty == "title") { // If the title of a folder which is listed within the folders
// menulist has been changed, we need to update the label of its // representing element.
var menupopup = this._folderMenuList.menupopup; for (var i=0; i < menupopup.childNodes.length;
i++) { if (menupopup.childNodes[i].folderId == aItemId) { menupopup.childNodes[i].label
= aValue; break; } } } return; } switch (aProperty) { case "title": if (PlacesUtils.annotations.itemHasAnnotation(this._itemId,
STATIC_TITLE_ANNO)) return; // onContentLoaded updates microsummary-items var userEnteredNameField
= this._element("userEnteredName"); if (userEnteredNameField.value != aValue) { userEnteredNameField.value
= aValue; var namePicker = this._element("namePicker"); if (namePicker.selectedItem == userEnteredNameField)
{ namePicker.label = aValue; // clear undo stack namePicker.editor.transactionManager.clear();
} } break; case "uri": var locationField = this._element("locationField"); if (locationField.value
!= aValue) { this._uri = Cc["@mozilla.org/network/io-service;1"]. getService(Ci.nsIIOService). newURI(aValue,
null, null); this._initTextField("locationField", this._uri.spec); this._initNamePicker();
// for microsummaries this._initTextField("tagsField", PlacesUtils.tagging .getTagsForURI(this._uri,
{ }).join(", "), false); this._rebuildTagsSelectorList(); } break; case "keyword": this._initTextField("keywordField",
PlacesUtils.bookmarks .getKeywordForBookmark(this._itemId)); break; case DESCRIPTION_ANNO: this._initTextField("descriptionField",
PlacesUIUtils.getItemDescription(this._itemId)); break; case LOAD_IN_SIDEBAR_ANNO: this._element("loadInSidebarCheckbox").checked
= PlacesUtils.annotations.itemHasAnnotation(this._itemId, LOAD_IN_SIDEBAR_ANNO); break; case LMANNO_FEEDURI:
var feedURISpec = PlacesUtils.livemarks.getFeedURI(this._itemId).spec; this._initTextField("feedLocationField", feedURISpec);
break; case LMANNO_SITEURI: var siteURISpec = ""; var siteURI = PlacesUtils.livemarks.getSiteURI(this._itemId);
if (siteURI) siteURISpec = siteURI.spec; this._initTextField("siteLocationField", siteURISpec); break; } }, onItemMoved: function
EIO_onItemMoved(aItemId, aOldParent, aOldIndex, aNewParent, aNewIndex, aItemType) { if (aItemId
!= this._itemId || aNewParent == this._getFolderIdFromMenuList()) return; var folderItem = this._getFolderMenuItem(aNewParent);
// just setting selectItem _does not_ trigger oncommand, so we don't // recurse this._folderMenuList.selectedItem
= folderItem; }, onItemAdded: function EIO_onItemAdded(aItemId, aFolder, aIndex, aItemType) { this._lastNewItem
= aItemId; }, onBeginUpdateBatch: function() { }, onEndUpdateBatch: function() { }, onBeforeItemRemoved:
function() { }, onItemRemoved: function() { }, onItemVisited: function() { }, content/browser/aboutPrivateBrowsing.xhtml &privatebrowsingpage.title; &privatebrowsingpage.title.normal;
&privatebrowsingpage.issueDesc;
&privatebrowsingpage.issueDesc.normal;
&privatebrowsingpage.description;
&privatebrowsingpage.howToStop;
&privatebrowsingpage.howToStart; &privatebrowsingpage.moreInfo;
&privatebrowsingpage.learnMore;
content/browser/migration/migration.xul
&importFrom.label;
&importFromBookmarks.label;
&noMigrationSources.label;
&selectProfile.label;
&importItems.label;
&migrating.label;
&done.label; content/browser/migration/migration.js//@line
36 "e:\builds\moz2_slave\win32_build\build\browser\components\migration\content\migration.js" const kIMig = Components.interfaces.nsIBrowserProfileMigrator;
const kIPStartup = Components.interfaces.nsIProfileStartup; const kProfileMigratorContractIDPrefix =
"@mozilla.org/profile/migrator;1?app=browser&type="; var MigrationWizard = { _source: "", // Source
Profile Migrator ContractID suffix _itemsFlags: kIMig.ALL, // Selected Import Data Sources
(16-bit bitfield) _selectedProfile: null, // Selected Profile name to import from _wiz:
null, _migrator: null, _autoMigrate: null, _bookmarks: false, init: function () var os
= Components.classes["@mozilla.org/observer-service;1"] .getService(Components.interfaces.nsIObserverService);
os.addObserver(this, "Migration:Started", false); os.addObserver(this, "Migration:ItemBeforeMigrate",
false); os.addObserver(this, "Migration:ItemAfterMigrate", false); os.addObserver(this, "Migration:Ended",
false); this._wiz = document.documentElement; if ("arguments" in window && window.arguments.length
> 1) { this._source = window.arguments[0]; this._migrator = window.arguments[1].QueryInterface(kIMig);
this._autoMigrate = window.arguments[2].QueryInterface(kIPStartup); if (this._autoMigrate) { // Show the "nothing"
option in the automigrate case to provide an // easily identifiable way to avoid migration
and create a new profile. var nothing = document.getElementById("nothing"); nothing.hidden = false; } } this.onImportSourcePageShow();
}, uninit: function () var os = Components.classes["@mozilla.org/observer-service;1"] .getService(Components.interfaces.nsIObserverService);
os.removeObserver(this, "Migration:Started"); os.removeObserver(this, "Migration:ItemBeforeMigrate");
os.removeObserver(this, "Migration:ItemAfterMigrate"); os.removeObserver(this, "Migration:Ended");
}, // 1 - Import Source onImportSourcePageShow: function () // Reference to the "From File"
radio button var fromfile = null; //XXXquark This function is called before init, so check
for bookmarks here if ("arguments" in window && window.arguments[0] == "bookmarks") {
this._bookmarks = true; fromfile = document.getElementById("fromfile"); fromfile.hidden = false; var importBookmarks
= document.getElementById("importBookmarks"); importBookmarks.hidden = false; var importAll
= document.getElementById("importAll"); importAll.hidden = true; } this._wiz.canRewind = false; //
The migrator to select. If the "fromfile" migrator is available, use it // as the default
in case we have no other migrators. var selectedMigrator = fromfile; // Figure out what source apps
are are available to import from: var group = document.getElementById("importSourceGroup");
for (var i = 0; i < group.childNodes.length; ++i) { var suffix = group.childNodes[i].id;
if (suffix != "nothing" && suffix != "fromfile") { var contractID = kProfileMigratorContractIDPrefix
+ suffix; try { var migrator = Components.classes[contractID].createInstance(kIMig); } catch (e) { dump("*** invalid contractID
=" + contractID + "\n"); return; } if (migrator.sourceExists && !(suffix == "phoenix" && !this._autoMigrate))
{ // Save this as the first selectable item, if we don't already have // one, or if it
is the migrator that was passed to us. if (!selectedMigrator || this._source == suffix)
selectedMigrator = group.childNodes[i]; } else { // Hide this option group.childNodes[i].hidden
= true; } } } if (selectedMigrator) group.selectedItem = selectedMigrator; else { // We didn't find
a migrator, notify the user document.getElementById("noSources").hidden = false; this._wiz.canAdvance = false; document.getElementById("importBookmarks").hidden
= true; document.getElementById("importAll").hidden = true; } }, onImportSourcePageAdvanced:
function () var newSource = document.getElementById("importSourceGroup").selectedItem.id; if (newSource == "nothing" || newSource ==
"fromfile") { if(newSource == "fromfile") window.opener.fromFile = true; document.documentElement.cancel();
return false; } if (!this._migrator || (newSource != this._source)) { // Create the migrator
for the selected source. var contractID = kProfileMigratorContractIDPrefix + newSource;
this._migrator = Components.classes[contractID].createInstance(kIMig); this._itemsFlags = kIMig.ALL; this._selectedProfile
= null; } this._source = newSource; // check for more than one source profile if (this._migrator.sourceHasMultipleProfiles)
this._wiz.currentPage.next = "selectProfile"; else { if (this._autoMigrate) this._wiz.currentPage.next
= "homePageImport"; else if (this._bookmarks) this._wiz.currentPage.next = "migrating" else
this._wiz.currentPage.next = "importItems"; var sourceProfiles = this._migrator.sourceProfiles;
if (sourceProfiles && sourceProfiles.Count() == 1) { var profileName = sourceProfiles.QueryElementAt(0,
Components.interfaces.nsISupportsString); this._selectedProfile = profileName.data;
} else this._selectedProfile = ""; } }, // 2 - [Profile Selection] onSelectProfilePageShow:
function () // Disabling this for now, since we ask about import sources in automigration
// too and don't want to disable the back button // if (this._autoMigrate) // document.documentElement.getButton("back").disabled
= true; var profiles = document.getElementById("profiles"); while (profiles.hasChildNodes()) profiles.removeChild(profiles.firstChild);
// Note that this block is still reached even if the user chose 'From File' // and
we canceled the dialog. When that happens, _migrator will be null. if (this._migrator)
{ var sourceProfiles = this._migrator.sourceProfiles; var count = sourceProfiles.Count(); for (var
i = 0; i < count; ++i) { var item = document.createElement("radio"); var str = sourceProfiles.QueryElementAt(i,
Components.interfaces.nsISupportsString); item.id = str.data; item.setAttribute("label",
str.data); profiles.appendChild(item); } } profiles.selectedItem = this._selectedProfile
? document.getElementById(this._selectedProfile) : profiles.firstChild; }, onSelectProfilePageRewound:
function () var profiles = document.getElementById("profiles"); this._selectedProfile = profiles.selectedItem.id;
}, onSelectProfilePageAdvanced: function () var profiles = document.getElementById("profiles");
this._selectedProfile = profiles.selectedItem.id; // If we're automigrating or just doing bookmarks
don't show the item selection page if (this._autoMigrate) this._wiz.currentPage.next = "homePageImport";
else if (this._bookmarks) this._wiz.currentPage.next = "migrating" }, // 3 - ImportItems onImportItemsPageShow:
function () var dataSources = document.getElementById("dataSources"); while (dataSources.hasChildNodes()) dataSources.removeChild(dataSources.firstChild);
var bundle = document.getElementById("bundle"); var items = this._migrator.getMigrateData(this._selectedProfile,
this._autoMigrate); for (var i = 0; i < 16; ++i) { var itemID = (items >> i) & 0x1 ?
Math.pow(2, i) : 0; if (itemID > 0) { var checkbox = document.createElement("checkbox");
checkbox.id = itemID; checkbox.setAttribute("label", bundle.getString(itemID + "_" + this._source));
dataSources.appendChild(checkbox); if (!this._itemsFlags || this._itemsFlags & itemID) checkbox.checked
= true; } } }, onImportItemsPageRewound: function () this._wiz.canAdvance = true; this.onImportItemsPageAdvanced();
}, onImportItemsPageAdvanced: function () var dataSources = document.getElementById("dataSources");
this._itemsFlags = 0; for (var i = 0; i < dataSources.childNodes.length; ++i) { var
checkbox = dataSources.childNodes[i]; if (checkbox.localName == "checkbox" && checkbox.checked) this._itemsFlags
|= parseInt(checkbox.id); } }, onImportItemCommand: function (aEvent) var items = document.getElementById("dataSources");
var checkboxes = items.getElementsByTagName("checkbox"); var oneChecked = false; for (var i = 0; i
< checkboxes.length; ++i) { if (checkboxes[i].checked) { oneChecked = true; break; } } this._wiz.canAdvance
= oneChecked; }, // 4 - Home Page Selection onHomePageMigrationPageShow: function ()
// only want this on the first run if (!this._autoMigrate) { this._wiz.advance(); return; } var bundle
= document.getElementById("brandBundle"); // These strings don't exist when not using
official branding. If that's // the case, just skip this page. try { var pageTitle
= bundle.getString("homePageMigrationPageTitle"); var pageDesc = bundle.getString("homePageMigrationDescription");
var mainStr = bundle.getString("homePageSingleStartMain"); } catch (e) { this._wiz.advance(); return;
} document.getElementById("homePageImport").setAttribute("label", pageTitle); document.getElementById("homePageImportDesc").setAttribute("value",
pageDesc); this._wiz._adjustWizardHeader(); var singleStart = document.getElementById("homePageSingleStart");
singleStart.setAttribute("label", mainStr); singleStart.setAttribute("value", "DEFAULT");
var source = null; switch (this._source) { case "ie": case "macie": source = "sourceNameIE";
break; case "opera": source = "sourceNameOpera"; break; case "dogbert": source = "sourceNameDogbert";
break; case "safari": source = "sourceNameSafari"; break; case "seamonkey": source = "sourceNameSeamonkey";
break; } // semi-wallpaper for crash when multiple profiles exist, since we haven't
initialized mSourceProfile in places this._migrator.getMigrateData(this._selectedProfile, this._autoMigrate); var oldHomePageURL =
this._migrator.sourceHomePageURL; if (oldHomePageURL && source) { var bundle2 = document.getElementById("bundle");
var appName = bundle2.getString(source); var oldHomePageLabel = bundle.getFormattedString("homePageImport",
[appName]); var oldHomePage = document.getElementById("oldHomePage"); oldHomePage.setAttribute("label", oldHomePageLabel);
oldHomePage.setAttribute("value", oldHomePageURL); oldHomePage.removeAttribute("hidden"); }
else { // if we don't have at least two options, just advance this._wiz.advance(); } }, onHomePageMigrationPageAdvanced:
function () // we might not have a selectedItem if we're in fallback mode try { var radioGroup
= document.getElementById("homePageRadiogroup"); this._newHomePage = radioGroup.selectedItem.value;
} catch(ex) {} }, // 5 - Migrating onMigratingPageShow: function () this._wiz.getButton("cancel").disabled
= true; this._wiz.canRewind = false; this._wiz.canAdvance = false; // When automigrating, show all
of the data that can be received from this source. if (this._autoMigrate) this._itemsFlags
= this._migrator.getMigrateData(this._selectedProfile, this._autoMigrate); // When importing bookmarks,
show only bookmarks if (this._bookmarks) this._itemsFlags = 32; this._listItems("migratingItems");
setTimeout(this.onMigratingMigrate, 0, this); }, onMigratingMigrate: function (aOuter)
aOuter._migrator.migrate(aOuter._itemsFlags, aOuter._autoMigrate, aOuter._selectedProfile);
}, _listItems: function (aID) var items = document.getElementById(aID); while (items.hasChildNodes())
items.removeChild(items.firstChild); var bundle = document.getElementById("bundle"); var
brandBundle = document.getElementById("brandBundle"); var itemID; for (var i = 0; i < 16; ++i)
{ var itemID = (this._itemsFlags >> i) & 0x1 ? Math.pow(2, i) : 0; if (itemID > 0)
{ var label = document.createElement("label"); label.id = itemID + "_migrated"; try { label.setAttribute("value",
bundle.getString(itemID + "_" + this._source)); items.appendChild(label); } catch (e) { //
if the block above throws, we've enumerated all the import data types we // currently
support and are now just wasting time, break. break; } } } }, observe: function (aSubject,
aTopic, aData) switch (aTopic) { case "Migration:Started": break; case "Migration:ItemBeforeMigrate":
var label = document.getElementById(aData + "_migrated"); if (label) label.setAttribute("style",
"font-weight: bold"); break; case "Migration:ItemAfterMigrate": var label = document.getElementById(aData
+ "_migrated"); if (label) label.removeAttribute("style"); break; case "Migration:Ended": if (this._autoMigrate)
{ if (this._newHomePage) { try { // set homepage properly var prefSvc = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefService); var prefBranch = prefSvc.getBranch(null);
if (this._newHomePage == "DEFAULT") { try { prefBranch.clearUserPref("browser.startup.homepage");
} catch (e) { } } else { var str = Components.classes["@mozilla.org/supports-string;1"] .createInstance(Components.interfaces.nsISupportsString);
str.data = this._newHomePage; prefBranch.setComplexValue("browser.startup.homepage", Components.interfaces.nsISupportsString, str);
} var dirSvc = Components.classes["@mozilla.org/file/directory_service;1"] .getService(Components.interfaces.nsIProperties);
var prefFile = dirSvc.get("ProfDS", Components.interfaces.nsIFile); prefFile.append("prefs.js"); prefSvc.savePrefFile(prefFile);
} catch(ex) { dump(ex); } } // We're done now. this._wiz.canAdvance = true; this._wiz.advance();
setTimeout(close, 5000); } else { this._wiz.canAdvance = true; var nextButton = this._wiz.getButton("next");
nextButton.click(); } break; } }, onDonePageShow: function () this._wiz.getButton("cancel").disabled
= true; this._wiz.canRewind = false; this._listItems("doneItems"); content/browser/safebrowsing/sb-loader.js//@line
36 "e:\builds\moz2_slave\win32_build\build\browser\components\safebrowsing\content\sb-loader.js" var safebrowsing = { appContext: null, startup:
function() { setTimeout(function() { safebrowsing.deferredStartup(); }, 2000); window.removeEventListener("load",
safebrowsing.startup, false); }, deferredStartup: function() { this.appContext.initialize();
}, setReportPhishingMenu: function() { // A phishing page will have a specific about:blocked
content documentURI var isPhishingPage = /^about:blocked\?e=phishingBlocked/.test(content.document.documentURI);
// Show/hide the appropriate menu item. document.getElementById("menu_HelpPopup_reportPhishingtoolmenu") .hidden = isPhishingPage; document.getElementById("menu_HelpPopup_reportPhishingErrortoolmenu")
.hidden = !isPhishingPage; var broadcasterId = isPhishingPage ? "reportPhishingErrorBroadcaster"
: "reportPhishingBroadcaster"; var broadcaster = document.getElementById(broadcasterId);
if (!broadcaster) return; var uri = getBrowser().currentURI; if (uri && (uri.schemeIs("http") || uri.schemeIs("https")))
broadcaster.removeAttribute("disabled"); else broadcaster.setAttribute("disabled", true);
}, /** * Lazy init getter for appContext */ get appContext() { delete this.appContext;
return this.appContext = Cc["@mozilla.org/safebrowsing/application;1"] .getService().wrappedJSObject; }, /** * Used
to report a phishing page or a false positive * @param name String One of "Phish", "Error",
"Malware" or "MalwareError" * @return String the report phishing URL. */ getReportURL:
function(name) { var reportUrl = this.appContext.getReportURL(name); var pageUrl = getBrowser().currentURI.asciiSpec;
reportUrl += "&url=" + encodeURIComponent(pageUrl); return reportUrl; window.addEventListener("load",
safebrowsing.startup, false); content/browser/safebrowsing/report-phishing-overlay.xul %safebrowsingDTD; content/browser/safebrowsing/blockedSite.xhtml
%globalDTD; %brandDTD; %blockedSiteDTD; /* Style warning button to look like a small
text link in the bottom right. This is preferable to just using a text link since there is already
a mechanism in browser.js for trapping oncommand events from unprivileged chrome pages (BrowserOnCommand).*/
#ignoreWarningButton { -moz-appearance: none; background: transparent; border: none; color:
white; /* Hard coded because netError.css forces this page's background to dark red
*/ text-decoration: underline; margin: 0; padding: 0; position: relative; top: 23px;
left: 20px; font-size: smaller; } #ignoreWarning { text-align: right; }
&safeb.blocked.phishingPage.title; &safeb.blocked.malwarePage.title;
&safeb.blocked.phishingPage.shortDesc; &safeb.blocked.malwarePage.shortDesc;
&safeb.blocked.phishingPage.longDesc;
&safeb.blocked.malwarePage.longDesc;
initPage();
content/branding/about.pngPK content/branding/aboutCredits.pngPK content/branding/aboutFooter.pngPK
content/branding/icon48.pngPK content/branding/icon64.pngPK content/browser/aboutDialog.xulPK content/browser/aboutDialog.jsPK
content/browser/aboutDialog.cssPK content/browser/aboutRobots.xhtmlPK GT4Y& content/browser/aboutRobots-icon.pngPK
content/browser/aboutRobots-icon-rtl.pngPK content/browser/aboutRobots-widget-left.pngPK
content/browser/aboutRobots-widget-right.pngPK content/browser/aboutSupport.xhtmlPK