summaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
authorThomas Groman <tgroman@nuegia.net>2020-04-20 20:49:37 -0700
committerThomas Groman <tgroman@nuegia.net>2020-04-20 20:49:37 -0700
commitf9cab004186edb425a9b88ad649726605080a17c (patch)
treee2dae51d3144e83d097a12e7a1499e3ea93f90be /components
parentf428692de8b59ab89a66502c079e1823dfda8aeb (diff)
downloadwebbrowser-f9cab004186edb425a9b88ad649726605080a17c.tar
webbrowser-f9cab004186edb425a9b88ad649726605080a17c.tar.gz
webbrowser-f9cab004186edb425a9b88ad649726605080a17c.tar.lz
webbrowser-f9cab004186edb425a9b88ad649726605080a17c.tar.xz
webbrowser-f9cab004186edb425a9b88ad649726605080a17c.zip
move browser to webbrowser/
Diffstat (limited to 'components')
-rw-r--r--components/BrowserComponents.manifest64
-rw-r--r--components/abouthome/aboutHome.css343
-rw-r--r--components/abouthome/aboutHome.js227
-rw-r--r--components/abouthome/aboutHome.xhtml62
-rw-r--r--components/abouthome/addons.pngbin1444 -> 0 bytes
-rw-r--r--components/abouthome/addons@2x.pngbin3783 -> 0 bytes
-rw-r--r--components/abouthome/bookmarks.pngbin1276 -> 0 bytes
-rw-r--r--components/abouthome/bookmarks@2x.pngbin2946 -> 0 bytes
-rw-r--r--components/abouthome/downloads.pngbin898 -> 0 bytes
-rw-r--r--components/abouthome/downloads@2x.pngbin2018 -> 0 bytes
-rw-r--r--components/abouthome/history.pngbin1654 -> 0 bytes
-rw-r--r--components/abouthome/history@2x.pngbin4629 -> 0 bytes
-rw-r--r--components/abouthome/jar.mn33
-rw-r--r--components/abouthome/moz.build8
-rw-r--r--components/abouthome/noise.pngbin4025 -> 0 bytes
-rw-r--r--components/abouthome/restore-large.pngbin2841 -> 0 bytes
-rw-r--r--components/abouthome/restore-large@2x.pngbin7267 -> 0 bytes
-rw-r--r--components/abouthome/restore.pngbin1796 -> 0 bytes
-rw-r--r--components/abouthome/restore@2x.pngbin4810 -> 0 bytes
-rw-r--r--components/abouthome/settings.pngbin1557 -> 0 bytes
-rw-r--r--components/abouthome/settings@2x.pngbin3836 -> 0 bytes
-rw-r--r--components/abouthome/snippet1.pngbin1470 -> 0 bytes
-rw-r--r--components/abouthome/snippet1@2x.pngbin3243 -> 0 bytes
-rw-r--r--components/abouthome/snippet2.pngbin3287 -> 0 bytes
-rw-r--r--components/abouthome/snippet2@2x.pngbin11027 -> 0 bytes
-rw-r--r--components/abouthome/sync.pngbin1879 -> 0 bytes
-rw-r--r--components/abouthome/sync@2x.pngbin4615 -> 0 bytes
-rw-r--r--components/build/Makefile.in8
-rw-r--r--components/build/moz.build36
-rw-r--r--components/build/nsBrowserCompsCID.h31
-rw-r--r--components/build/nsModule.cpp91
-rw-r--r--components/certerror/content/aboutCertError.css17
-rw-r--r--components/certerror/content/aboutCertError.xhtml247
-rw-r--r--components/certerror/jar.mn7
-rw-r--r--components/certerror/moz.build7
-rw-r--r--components/dirprovider/DirectoryProvider.cpp268
-rw-r--r--components/dirprovider/DirectoryProvider.h51
-rw-r--r--components/dirprovider/moz.build13
-rw-r--r--components/distribution.js345
-rw-r--r--components/downloads/BrowserDownloads.manifest4
-rw-r--r--components/downloads/DownloadsCommon.jsm1920
-rw-r--r--components/downloads/DownloadsLogger.jsm76
-rw-r--r--components/downloads/DownloadsStartup.js278
-rw-r--r--components/downloads/DownloadsTaskbar.jsm177
-rw-r--r--components/downloads/DownloadsUI.js151
-rw-r--r--components/downloads/DownloadsViewUI.jsm250
-rw-r--r--components/downloads/content/allDownloadsViewOverlay.css56
-rw-r--r--components/downloads/content/allDownloadsViewOverlay.js1399
-rw-r--r--components/downloads/content/allDownloadsViewOverlay.xul119
-rw-r--r--components/downloads/content/contentAreaDownloadsView.css11
-rw-r--r--components/downloads/content/contentAreaDownloadsView.js15
-rw-r--r--components/downloads/content/contentAreaDownloadsView.xul45
-rw-r--r--components/downloads/content/download.css45
-rw-r--r--components/downloads/content/download.xml188
-rw-r--r--components/downloads/content/downloads.css132
-rw-r--r--components/downloads/content/downloads.js1614
-rw-r--r--components/downloads/content/downloadsOverlay.xul142
-rw-r--r--components/downloads/content/indicator.js609
-rw-r--r--components/downloads/content/indicatorOverlay.xul60
-rw-r--r--components/downloads/jar.mn18
-rw-r--r--components/downloads/moz.build23
-rw-r--r--components/feeds/BrowserFeeds.manifest28
-rw-r--r--components/feeds/FeedConverter.js591
-rw-r--r--components/feeds/FeedWriter.js1397
-rw-r--r--components/feeds/WebContentConverter.js927
-rw-r--r--components/feeds/content/subscribe.css7
-rw-r--r--components/feeds/content/subscribe.js23
-rw-r--r--components/feeds/content/subscribe.xhtml65
-rw-r--r--components/feeds/content/subscribe.xml40
-rw-r--r--components/feeds/jar.mn9
-rw-r--r--components/feeds/moz.build33
-rw-r--r--components/feeds/nsFeedSniffer.cpp363
-rw-r--r--components/feeds/nsFeedSniffer.h37
-rw-r--r--components/feeds/nsIFeedResultService.idl66
-rw-r--r--components/feeds/nsIWebContentConverterRegistrar.idl117
-rw-r--r--components/fuel/fuelApplication.js822
-rw-r--r--components/fuel/fuelApplication.manifest3
-rw-r--r--components/fuel/fuelIApplication.idl347
-rw-r--r--components/fuel/moz.build14
-rw-r--r--components/moz.build47
-rw-r--r--components/newtab/cells.js126
-rw-r--r--components/newtab/drag.js151
-rw-r--r--components/newtab/dragDataHelper.js22
-rw-r--r--components/newtab/drop.js150
-rw-r--r--components/newtab/dropPreview.js222
-rw-r--r--components/newtab/dropTargetShim.js232
-rw-r--r--components/newtab/grid.js175
-rw-r--r--components/newtab/jar.mn8
-rw-r--r--components/newtab/moz.build8
-rw-r--r--components/newtab/newTab.css349
-rw-r--r--components/newtab/newTab.js69
-rw-r--r--components/newtab/newTab.xhtml61
-rw-r--r--components/newtab/page.js244
-rw-r--r--components/newtab/search.js134
-rw-r--r--components/newtab/sites.js353
-rw-r--r--components/newtab/transformations.js270
-rw-r--r--components/newtab/undo.js116
-rw-r--r--components/newtab/updater.js177
-rw-r--r--components/nsAboutRedirector.js114
-rw-r--r--components/nsBrowserContentHandler.js803
-rw-r--r--components/nsBrowserGlue.js1867
-rw-r--r--components/nsIBrowserGlue.idl47
-rw-r--r--components/nsIBrowserHandler.idl20
-rw-r--r--components/pageinfo/feeds.js59
-rw-r--r--components/pageinfo/feeds.xml40
-rw-r--r--components/pageinfo/jar.mn13
-rw-r--r--components/pageinfo/moz.build8
-rw-r--r--components/pageinfo/pageInfo.css26
-rw-r--r--components/pageinfo/pageInfo.js1286
-rw-r--r--components/pageinfo/pageInfo.xml29
-rw-r--r--components/pageinfo/pageInfo.xul507
-rw-r--r--components/pageinfo/permissions.js341
-rw-r--r--components/pageinfo/security.js378
-rw-r--r--components/permissions/aboutPermissions.css11
-rw-r--r--components/permissions/aboutPermissions.js1335
-rw-r--r--components/permissions/aboutPermissions.xml113
-rw-r--r--components/permissions/aboutPermissions.xul313
-rw-r--r--components/permissions/jar.mn9
-rw-r--r--components/permissions/moz.build7
-rw-r--r--components/places/PlacesUIUtils.jsm1373
-rw-r--r--components/places/content/bookmarkProperties.js675
-rw-r--r--components/places/content/bookmarkProperties.xul43
-rw-r--r--components/places/content/bookmarksPanel.js25
-rw-r--r--components/places/content/bookmarksPanel.xul55
-rw-r--r--components/places/content/browserPlacesViews.js1754
-rw-r--r--components/places/content/controller.js1895
-rw-r--r--components/places/content/downloadsViewOverlay.xul47
-rw-r--r--components/places/content/editBookmarkOverlay.js1063
-rw-r--r--components/places/content/editBookmarkOverlay.xul228
-rw-r--r--components/places/content/history-panel.js91
-rw-r--r--components/places/content/history-panel.xul95
-rw-r--r--components/places/content/menu.xml488
-rw-r--r--components/places/content/moveBookmarks.js54
-rw-r--r--components/places/content/moveBookmarks.xul53
-rw-r--r--components/places/content/organizer.css7
-rw-r--r--components/places/content/places.css16
-rw-r--r--components/places/content/places.js1553
-rw-r--r--components/places/content/places.xul471
-rw-r--r--components/places/content/placesOverlay.xul247
-rw-r--r--components/places/content/sidebarUtils.js108
-rw-r--r--components/places/content/tree.xml789
-rw-r--r--components/places/content/treeView.js1770
-rw-r--r--components/places/jar.mn34
-rw-r--r--components/places/moz.build9
-rw-r--r--components/preferences/advanced.js755
-rw-r--r--components/preferences/advanced.xul465
-rw-r--r--components/preferences/applicationManager.js102
-rw-r--r--components/preferences/applicationManager.xul59
-rw-r--r--components/preferences/applications.js1890
-rw-r--r--components/preferences/applications.xul99
-rw-r--r--components/preferences/colors.xul102
-rw-r--r--components/preferences/connection.js200
-rw-r--r--components/preferences/connection.xul164
-rw-r--r--components/preferences/content.js187
-rw-r--r--components/preferences/content.xul171
-rw-r--r--components/preferences/cookies.js948
-rw-r--r--components/preferences/cookies.xul106
-rw-r--r--components/preferences/fonts.js144
-rw-r--r--components/preferences/fonts.xul279
-rw-r--r--components/preferences/handlers.css25
-rw-r--r--components/preferences/handlers.xml81
-rw-r--r--components/preferences/jar.mn44
-rw-r--r--components/preferences/languages.js304
-rw-r--r--components/preferences/languages.xul98
-rw-r--r--components/preferences/main.js473
-rw-r--r--components/preferences/main.xul188
-rw-r--r--components/preferences/moz.build14
-rw-r--r--components/preferences/newtaburl.js102
-rw-r--r--components/preferences/permissions.js463
-rw-r--r--components/preferences/permissions.xul85
-rw-r--r--components/preferences/preferences.xul92
-rw-r--r--components/preferences/privacy.js485
-rw-r--r--components/preferences/privacy.xul273
-rw-r--r--components/preferences/sanitize.js12
-rw-r--r--components/preferences/sanitize.xul108
-rw-r--r--components/preferences/security.js251
-rw-r--r--components/preferences/security.xul181
-rw-r--r--components/preferences/selectBookmark.js83
-rw-r--r--components/preferences/selectBookmark.xul44
-rw-r--r--components/preferences/sync.js192
-rw-r--r--components/preferences/sync.xul178
-rw-r--r--components/preferences/tabs.js90
-rw-r--r--components/preferences/tabs.xul102
-rw-r--r--components/privatebrowsing/content/aboutPrivateBrowsing.xhtml156
-rw-r--r--components/privatebrowsing/jar.mn6
-rw-r--r--components/privatebrowsing/moz.build7
-rw-r--r--components/search/content/engineManager.js492
-rw-r--r--components/search/content/engineManager.xul93
-rw-r--r--components/search/content/search.xml837
-rw-r--r--components/search/content/searchbarBindings.css13
-rw-r--r--components/search/jar.mn9
-rw-r--r--components/search/moz.build7
-rw-r--r--components/sessionstore/DocumentUtils.jsm230
-rw-r--r--components/sessionstore/SessionStorage.jsm165
-rw-r--r--components/sessionstore/SessionStore.jsm4786
-rw-r--r--components/sessionstore/XPathGenerator.jsm97
-rw-r--r--components/sessionstore/_SessionFile.jsm314
-rw-r--r--components/sessionstore/content/aboutSessionRestore.js320
-rw-r--r--components/sessionstore/content/aboutSessionRestore.xhtml94
-rw-r--r--components/sessionstore/content/content-sessionStore.js40
-rw-r--r--components/sessionstore/jar.mn8
-rw-r--r--components/sessionstore/moz.build29
-rw-r--r--components/sessionstore/nsISessionStartup.idl59
-rw-r--r--components/sessionstore/nsISessionStore.idl206
-rw-r--r--components/sessionstore/nsSessionStartup.js296
-rw-r--r--components/sessionstore/nsSessionStore.js37
-rw-r--r--components/sessionstore/nsSessionStore.manifest18
-rw-r--r--components/shell/ShellService.jsm114
-rw-r--r--components/shell/content/setDesktopBackground.js214
-rw-r--r--components/shell/content/setDesktopBackground.xul84
-rw-r--r--components/shell/jar.mn7
-rw-r--r--components/shell/moz.build40
-rw-r--r--components/shell/nsGNOMEShellService.cpp637
-rw-r--r--components/shell/nsGNOMEShellService.h36
-rw-r--r--components/shell/nsIGNOMEShellService.idl19
-rw-r--r--components/shell/nsIMacShellService.idl15
-rw-r--r--components/shell/nsIShellService.idl95
-rw-r--r--components/shell/nsIWindowsShellService.idl17
-rw-r--r--components/shell/nsMacShellService.cpp434
-rw-r--r--components/shell/nsMacShellService.h32
-rw-r--r--components/shell/nsSetDefaultBrowser.js30
-rw-r--r--components/shell/nsSetDefaultBrowser.manifest3
-rw-r--r--components/shell/nsShellService.h12
-rw-r--r--components/shell/nsWindowsShellService.cpp1277
-rw-r--r--components/shell/nsWindowsShellService.h37
-rw-r--r--components/statusbar/Downloads.jsm674
-rw-r--r--components/statusbar/Progress.jsm183
-rw-r--r--components/statusbar/Status.jsm492
-rw-r--r--components/statusbar/Status4Evar.jsm312
-rw-r--r--components/statusbar/Toolbars.jsm221
-rw-r--r--components/statusbar/content-thunk.js23
-rw-r--r--components/statusbar/content/overlay.css14
-rw-r--r--components/statusbar/content/overlay.js16
-rw-r--r--components/statusbar/content/overlay.xul82
-rw-r--r--components/statusbar/content/prefs.css10
-rw-r--r--components/statusbar/content/prefs.js274
-rw-r--r--components/statusbar/content/prefs.xml704
-rw-r--r--components/statusbar/content/prefs.xul297
-rw-r--r--components/statusbar/content/tabbrowser.xml218
-rw-r--r--components/statusbar/jar.mn15
-rw-r--r--components/statusbar/moz.build25
-rw-r--r--components/statusbar/status4evar.idl57
-rw-r--r--components/statusbar/status4evar.js695
-rw-r--r--components/statusbar/status4evar.manifest3
-rw-r--r--components/sync/aboutSyncTabs-bindings.xml46
-rw-r--r--components/sync/aboutSyncTabs.css11
-rw-r--r--components/sync/aboutSyncTabs.js313
-rw-r--r--components/sync/aboutSyncTabs.xul68
-rw-r--r--components/sync/addDevice.js157
-rw-r--r--components/sync/addDevice.xul129
-rw-r--r--components/sync/genericChange.js234
-rw-r--r--components/sync/genericChange.xul123
-rw-r--r--components/sync/jar.mn22
-rw-r--r--components/sync/key.xhtml54
-rw-r--r--components/sync/moz.build8
-rw-r--r--components/sync/notification.xml129
-rw-r--r--components/sync/progress.js71
-rw-r--r--components/sync/progress.xhtml55
-rw-r--r--components/sync/quota.js247
-rw-r--r--components/sync/quota.xul65
-rw-r--r--components/sync/setup.js1071
-rw-r--r--components/sync/setup.xul491
-rw-r--r--components/sync/utils.js218
263 files changed, 0 insertions, 66150 deletions
diff --git a/components/BrowserComponents.manifest b/components/BrowserComponents.manifest
deleted file mode 100644
index 0ff14d0..0000000
--- a/components/BrowserComponents.manifest
+++ /dev/null
@@ -1,64 +0,0 @@
-# nsAboutRedirector.js
-component {8cc51368-6aa0-43e8-b762-bde9b9fd828c} nsAboutRedirector.js
-# Each entry here should be coupled with an entry in nsAboutRedirector.js
-contract @mozilla.org/network/protocol/about;1?what=certerror {8cc51368-6aa0-43e8-b762-bde9b9fd828c}
-contract @mozilla.org/network/protocol/about;1?what=downloads {8cc51368-6aa0-43e8-b762-bde9b9fd828c}
-contract @mozilla.org/network/protocol/about;1?what=feeds {8cc51368-6aa0-43e8-b762-bde9b9fd828c}
-contract @mozilla.org/network/protocol/about;1?what=home {8cc51368-6aa0-43e8-b762-bde9b9fd828c}
-contract @mozilla.org/network/protocol/about;1?what=newtab {8cc51368-6aa0-43e8-b762-bde9b9fd828c}
-contract @mozilla.org/network/protocol/about;1?what=palemoon {8cc51368-6aa0-43e8-b762-bde9b9fd828c}
-contract @mozilla.org/network/protocol/about;1?what=permissions {8cc51368-6aa0-43e8-b762-bde9b9fd828c}
-contract @mozilla.org/network/protocol/about;1?what=privatebrowsing {8cc51368-6aa0-43e8-b762-bde9b9fd828c}
-contract @mozilla.org/network/protocol/about;1?what=rights {8cc51368-6aa0-43e8-b762-bde9b9fd828c}
-contract @mozilla.org/network/protocol/about;1?what=sessionrestore {8cc51368-6aa0-43e8-b762-bde9b9fd828c}
-#ifdef MOZ_SERVICES_SYNC
-contract @mozilla.org/network/protocol/about;1?what=sync-progress {8cc51368-6aa0-43e8-b762-bde9b9fd828c}
-contract @mozilla.org/network/protocol/about;1?what=sync-tabs {8cc51368-6aa0-43e8-b762-bde9b9fd828c}
-#endif
-
-# nsBrowserContentHandler.js
-component {5d0ce354-df01-421a-83fb-7ead0990c24e} nsBrowserContentHandler.js application={8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}
-contract @mozilla.org/browser/clh;1 {5d0ce354-df01-421a-83fb-7ead0990c24e} application={8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}
-component {47cd0651-b1be-4a0f-b5c4-10e5a573ef71} nsBrowserContentHandler.js application={8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}
-contract @mozilla.org/browser/final-clh;1 {47cd0651-b1be-4a0f-b5c4-10e5a573ef71} application={8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}
-contract @mozilla.org/uriloader/content-handler;1?type=text/html {5d0ce354-df01-421a-83fb-7ead0990c24e} application={8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}
-contract @mozilla.org/uriloader/content-handler;1?type=application/vnd.mozilla.xul+xml {5d0ce354-df01-421a-83fb-7ead0990c24e} application={8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}
-contract @mozilla.org/uriloader/content-handler;1?type=image/svg+xml {5d0ce354-df01-421a-83fb-7ead0990c24e} application={8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}
-contract @mozilla.org/uriloader/content-handler;1?type=text/rdf {5d0ce354-df01-421a-83fb-7ead0990c24e} application={8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}
-contract @mozilla.org/uriloader/content-handler;1?type=text/xml {5d0ce354-df01-421a-83fb-7ead0990c24e} application={8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}
-contract @mozilla.org/uriloader/content-handler;1?type=application/xhtml+xml {5d0ce354-df01-421a-83fb-7ead0990c24e} application={8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}
-contract @mozilla.org/uriloader/content-handler;1?type=text/css {5d0ce354-df01-421a-83fb-7ead0990c24e} application={8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}
-contract @mozilla.org/uriloader/content-handler;1?type=text/plain {5d0ce354-df01-421a-83fb-7ead0990c24e} application={8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}
-contract @mozilla.org/uriloader/content-handler;1?type=image/gif {5d0ce354-df01-421a-83fb-7ead0990c24e} application={8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}
-contract @mozilla.org/uriloader/content-handler;1?type=image/jpeg {5d0ce354-df01-421a-83fb-7ead0990c24e} application={8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}
-contract @mozilla.org/uriloader/content-handler;1?type=image/jpg {5d0ce354-df01-421a-83fb-7ead0990c24e} application={8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}
-contract @mozilla.org/uriloader/content-handler;1?type=image/png {5d0ce354-df01-421a-83fb-7ead0990c24e} application={8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}
-contract @mozilla.org/uriloader/content-handler;1?type=image/bmp {5d0ce354-df01-421a-83fb-7ead0990c24e} application={8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}
-contract @mozilla.org/uriloader/content-handler;1?type=image/x-icon {5d0ce354-df01-421a-83fb-7ead0990c24e} application={8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}
-contract @mozilla.org/uriloader/content-handler;1?type=image/vnd.microsoft.icon {5d0ce354-df01-421a-83fb-7ead0990c24e} application={8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}
-contract @mozilla.org/uriloader/content-handler;1?type=image/webp {5d0ce354-df01-421a-83fb-7ead0990c24e} application={8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}
-contract @mozilla.org/uriloader/content-handler;1?type=application/http-index-format {5d0ce354-df01-421a-83fb-7ead0990c24e} application={8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}
-category command-line-handler m-browser @mozilla.org/browser/clh;1 application={8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}
-category command-line-handler x-default @mozilla.org/browser/final-clh;1 application={8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}
-category command-line-validator b-browser @mozilla.org/browser/clh;1 application={8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}
-
-# nsBrowserGlue.js
-
-# WebappRT doesn't need these instructions, and they don't necessarily work
-# with it, but it does use a GRE directory that the GRE shares with Firefox,
-# so in order to prevent the instructions from being processed for WebappRT,
-# we need to restrict them to the applications that depend on them, i.e.:
-#
-# b2g: {3c2e2abc-06d4-11e1-ac3b-374f68613e61}
-# browser: {8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}
-# mobile/android: {aa3c5121-dab2-40e2-81ca-7ea25febc110}
-# mobile/xul: {a23983c0-fd0e-11dc-95ff-0800200c9a66}
-#
-# In theory we should do this for all these instructions, but in practice it is
-# sufficient to do it for the app-startup one, and the file is simpler that way.
-
-component {eab9012e-5f74-4cbc-b2b5-a590235513cc} nsBrowserGlue.js
-contract @mozilla.org/browser/browserglue;1 {eab9012e-5f74-4cbc-b2b5-a590235513cc}
-category app-startup nsBrowserGlue service,@mozilla.org/browser/browserglue;1 application={3c2e2abc-06d4-11e1-ac3b-374f68613e61} application={8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4} application={aa3c5121-dab2-40e2-81ca-7ea25febc110} application={a23983c0-fd0e-11dc-95ff-0800200c9a66}
-component {d8903bf6-68d5-4e97-bcd1-e4d3012f721a} nsBrowserGlue.js
-contract @mozilla.org/content-permission/prompt;1 {d8903bf6-68d5-4e97-bcd1-e4d3012f721a}
diff --git a/components/abouthome/aboutHome.css b/components/abouthome/aboutHome.css
deleted file mode 100644
index 2b062e8..0000000
--- a/components/abouthome/aboutHome.css
+++ /dev/null
@@ -1,343 +0,0 @@
-%if 0
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-%endif
-
-html {
- font: message-box;
- font-size: 100%;
- background-color: hsl(0,0%,90%);
- color: #000;
- height: 100%;
-}
-
-body {
- margin: 0;
- display: -moz-box;
- -moz-box-orient: vertical;
- width: 100%;
- height: 100%;
- background-image: url(chrome://browser/content/abouthome/noise.png),
- linear-gradient(hsla(0,0%,100%,.7), hsla(0,0%,100%,.4));
-}
-
-input,
-button {
- font-size: inherit;
- font-family: inherit;
-}
-
-a {
- color: -moz-nativehyperlinktext;
- text-decoration: none;
-}
-
-.spacer {
- -moz-box-flex: 1;
-}
-
-#topSection {
- text-align: center;
-}
-
-#brandLogo {
- height: 192px;
- width: 192px;
- margin: 22px auto 31px;
- background-image: url("chrome://branding/content/about-logo.png");
- background-size: 192px auto;
- background-position: center center;
- background-repeat: no-repeat;
-}
-
-#searchForm {
- width: 470px;
-}
-
-#searchForm {
- display: -moz-box;
-}
-
-#searchLogoContainer {
- display: -moz-box;
- -moz-box-align: center;
- padding-top: 2px;
- -moz-padding-end: 8px;
-}
-
-#searchLogoContainer[hidden] {
- display: none;
-}
-
-#searchEngineLogo {
- display: inline-block;
- height: 28px;
- width: 70px;
- min-width: 70px;
-}
-
-#searchText {
- -moz-box-flex: 1;
- padding: 6px 8px;
- background: hsla(0,0%,100%,.9) padding-box;
- border: 1px solid;
- border-color: hsla(210,54%,20%,.15) hsla(210,54%,20%,.17) hsla(210,54%,20%,.2);
- box-shadow: 0 1px 0 hsla(210,65%,9%,.02) inset,
- 0 0 2px hsla(210,65%,9%,.1) inset,
- 0 1px 0 hsla(0,0%,100%,.2);
- border-radius: 2.5px 0 0 2.5px;
-}
-
-#searchText:-moz-dir(rtl) {
- border-radius: 0 2.5px 2.5px 0;
-}
-
-#searchText:focus,
-#searchText[autofocus] {
- border-color: hsla(206,100%,60%,.6) hsla(206,76%,52%,.6) hsla(204,100%,40%,.6);
-}
-
-#searchSubmit {
- -moz-margin-start: -1px;
- background: linear-gradient(hsla(0,0%,100%,.8), hsla(0,0%,100%,.1)) padding-box;
- padding: 0 9px;
- border: 1px solid;
- border-color: hsla(210,54%,20%,.15) hsla(210,54%,20%,.17) hsla(210,54%,20%,.2);
- -moz-border-start: 1px solid transparent;
- border-radius: 0 2.5px 2.5px 0;
- box-shadow: 0 0 2px hsla(0,0%,100%,.5) inset,
- 0 1px 0 hsla(0,0%,100%,.2);
- cursor: pointer;
- transition-property: background-color, border-color, box-shadow;
- transition-duration: 150ms;
-}
-
-#searchSubmit:-moz-dir(rtl) {
- border-radius: 2.5px 0 0 2.5px;
-}
-
-#searchText:focus + #searchSubmit,
-#searchText + #searchSubmit:hover,
-#searchText[autofocus] + #searchSubmit {
- border-color: #59b5fc #45a3e7 #3294d5;
- color: white;
-}
-
-#searchText:focus + #searchSubmit,
-#searchText[autofocus] + #searchSubmit {
- background-image: linear-gradient(#4cb1ff, #1793e5);
- box-shadow: 0 1px 0 hsla(0,0%,100%,.2) inset,
- 0 0 0 1px hsla(0,0%,100%,.1) inset,
- 0 1px 0 hsla(210,54%,20%,.03);
-}
-
-#searchText + #searchSubmit:hover {
- background-image: linear-gradient(#66bdff, #0d9eff);
- box-shadow: 0 1px 0 hsla(0,0%,100%,.2) inset,
- 0 0 0 1px hsla(0,0%,100%,.1) inset,
- 0 1px 0 hsla(210,54%,20%,.03),
- 0 0 4px hsla(206,100%,20%,.2);
-}
-
-#searchText + #searchSubmit:hover:active {
- box-shadow: 0 1px 1px hsla(211,79%,6%,.1) inset,
- 0 0 1px hsla(211,79%,6%,.2) inset;
- transition-duration: 0ms;
-}
-
-#launcher {
- display: -moz-box;
- -moz-box-align: center;
- -moz-box-pack: center;
- width: 100%;
- background-color: hsla(0,0%,0%,.03);
- border-top: 1px solid hsla(0,0%,0%,.03);
- box-shadow: 0 1px 2px hsla(0,0%,0%,.02) inset,
- 0 -1px 0 hsla(0,0%,100%,.25);
-}
-
-#launcher:not([session]),
-body[narrow] #launcher[session] {
- display: block; /* display separator and restore button on separate lines */
- text-align: center;
- white-space: nowrap; /* prevent navigational buttons from wrapping */
-}
-
-.launchButton {
- display: -moz-box;
- -moz-box-orient: vertical;
- margin: 16px 1px;
- padding: 14px 6px;
- min-width: 88px;
- max-width: 176px;
- max-height: 85px;
- vertical-align: top;
- white-space: normal;
- background: transparent padding-box;
- border: 1px solid transparent;
- border-radius: 2.5px;
- color: #525c66;
- font-size: 75%;
- cursor: pointer;
- transition-property: background-color, border-color, box-shadow;
- transition-duration: 150ms;
-}
-
-body[narrow] #launcher[session] > .launchButton {
- margin: 4px 1px;
-}
-
-.launchButton:hover {
- background-color: hsla(211,79%,6%,.03);
- border-color: hsla(210,54%,20%,.15) hsla(210,54%,20%,.17) hsla(210,54%,20%,.2);
-}
-
-.launchButton:hover:active {
- background-image: linear-gradient(hsla(211,79%,6%,.02), hsla(211,79%,6%,.05));
- border-color: hsla(210,54%,20%,.2) hsla(210,54%,20%,.23) hsla(210,54%,20%,.25);
- box-shadow: 0 1px 1px hsla(211,79%,6%,.05) inset,
- 0 0 1px hsla(211,79%,6%,.1) inset;
- transition-duration: 0ms;
-}
-
-.launchButton[hidden],
-#launcher:not([session]) > #restorePreviousSessionSeparator,
-#launcher:not([session]) > #restorePreviousSession {
- display: none;
-}
-
-#restorePreviousSessionSeparator {
- width: 3px;
- height: 116px;
- margin: 0 10px;
- background-image: linear-gradient(hsla(0,0%,100%,0), hsla(0,0%,100%,.35), hsla(0,0%,100%,0)),
- linear-gradient(hsla(211,79%,6%,0), hsla(211,79%,6%,.2), hsla(211,79%,6%,0)),
- linear-gradient(hsla(0,0%,100%,0), hsla(0,0%,100%,.35), hsla(0,0%,100%,0));
- background-position: left top, center, right bottom;
- background-size: 1px auto;
- background-repeat: no-repeat;
-}
-
-body[narrow] #restorePreviousSessionSeparator {
- margin: 0 auto;
- width: 512px;
- height: 3px;
- background-image: linear-gradient(to right, hsla(0,0%,100%,0), hsla(0,0%,100%,.35), hsla(0,0%,100%,0)),
- linear-gradient(to right, hsla(211,79%,6%,0), hsla(211,79%,6%,.2), hsla(211,79%,6%,0)),
- linear-gradient(to right, hsla(0,0%,100%,0), hsla(0,0%,100%,.35), hsla(0,0%,100%,0));
- background-size: auto 1px;
-}
-
-#restorePreviousSession {
- max-width: none;
- font-size: 90%;
-}
-
-body[narrow] #restorePreviousSession {
- font-size: 80%;
-}
-
-.launchButton::before {
- display: block;
- width: 32px;
- height: 32px;
- margin: 0 auto 6px;
- line-height: 0; /* remove extra vertical space due to non-zero font-size */
-}
-
-#downloads::before {
- content: url("chrome://browser/content/abouthome/downloads.png");
-}
-
-#bookmarks::before {
- content: url("chrome://browser/content/abouthome/bookmarks.png");
-}
-
-#history::before {
- content: url("chrome://browser/content/abouthome/history.png");
-}
-
-#addons::before {
- content: url("chrome://browser/content/abouthome/addons.png");
-}
-
-%ifdef MOZ_SERVICES_SYNC
-#sync::before {
- content: url("chrome://browser/content/abouthome/sync.png");
-}
-%endif
-
-#settings::before {
- content: url("chrome://browser/content/abouthome/settings.png");
-}
-
-#restorePreviousSession::before {
- content: url("chrome://browser/content/abouthome/restore-large.png");
- height: 48px;
- width: 48px;
- display: inline-block; /* display on same line as text label */
- vertical-align: middle;
- margin-bottom: 0;
- -moz-margin-end: 8px;
-}
-
-#restorePreviousSession:-moz-dir(rtl)::before {
- transform: scaleX(-1);
-}
-
-body[narrow] #restorePreviousSession::before {
- content: url("chrome://browser/content/abouthome/restore.png");
- height: 32px;
- width: 32px;
-}
-
-/* [HiDPI]
- * At resolutions above 1dppx, prefer downscaling the 2x Retina graphics
- * rather than upscaling the original-size ones (bug 818940).
- */
-@media not all and (max-resolution: 1dppx) {
- #brandLogo {
- background-image: url("chrome://branding/content/about-logo@2x.png");
- }
-
- .launchButton::before {
- transform: scale(.5);
- transform-origin: 0 0;
- }
-
- #downloads::before {
- content: url("chrome://browser/content/abouthome/downloads@2x.png");
- }
-
- #bookmarks::before {
- content: url("chrome://browser/content/abouthome/bookmarks@2x.png");
- }
-
- #history::before {
- content: url("chrome://browser/content/abouthome/history@2x.png");
- }
-
- #addons::before {
- content: url("chrome://browser/content/abouthome/addons@2x.png");
- }
-
-%ifdef MOZ_SERVICES_SYNC
- #sync::before {
- content: url("chrome://browser/content/abouthome/sync@2x.png");
- }
-%endif
-
- #settings::before {
- content: url("chrome://browser/content/abouthome/settings@2x.png");
- }
-
- #restorePreviousSession::before {
- content: url("chrome://browser/content/abouthome/restore-large@2x.png");
- }
-
- body[narrow] #restorePreviousSession::before {
- content: url("chrome://browser/content/abouthome/restore@2x.png");
- }
-}
-
diff --git a/components/abouthome/aboutHome.js b/components/abouthome/aboutHome.js
deleted file mode 100644
index 6ff8eee..0000000
--- a/components/abouthome/aboutHome.js
+++ /dev/null
@@ -1,227 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-const SEARCH_ENGINES = {
- "DuckDuckGo": {
- image: "data:image/png;base64," +
- "iVBORw0KGgoAAAANSUhEUgAAAIwAAAA4CAYAAAAvmxBdAAAVhUlEQVR4Xu3dd5SU1d3A8e/vPs/0" +
- "2crussBSdkHEAgoomEQSUTAW3hRbfMUeUwgSj9FoorGXqDGxBHvMazRGE0KsBQuiEVRUEEEM0pfO" +
- "1tndmZ32PPf3knDCUZAlIYsxOfM553f2v91/vnufOzP33BFV5TOnQFQ1snFN/YCVb88Z6S2dd1B8" +
- "3Qf7lTSv6R9PNle4uXQEVNRxvUy4qL29pPeGRNXA5d6g4fOLhoyYN2C/oe8Vl5QmAoFAnm72GQqm" +
- "oKO9vXj5e/NHtr48/fjq92eOq2xYOsixvuMpKFuhfJywjQMYI5oKF7evrR09t/LE7z3Ze9TYZyPx" +
- "+FpjjPdfEkxBY0ND9ftP//7EkpceOLNm/cJh+J6rylYWcIwSiCHhuEo4ggRdMCLq+UomK5pJq2Y7" +
- "BD8HqoIAAmKhPdKjuX7EMc9WnfCde/YZOfot13Xz/6HBFKi1pdmlCya23Dz5PPeDN/eygCqAqIn3" +
- "ULduiAb2Ha3BfUYgJeUgBhxHRAwgoupbfF/wPcXL461bRX7xm5Jb8q7Yhno0lzUYMIANx9Lh0y99" +
- "svjEc292YkXzAfufE0yBse0tX+qY+uNrOp/+9SGo5yggTlADQw72I4efQGDf4Wg6RW7xO5Jf8g7+" +
- "ulVi21rRXAr8HKpWRBzFCSGRIpyKSnX6701wv0PU7Vunms2RmfO0ZGc/Z/zWjSKiAqJOdV1LyUVT" +
- "7wkdcuQvENP8mQ+mQGPZt2ZelLj2nCl+Q30ZAqijoVFH+rGTJiHROJnXniE75znxN64yms8AKghd" +
- "062DEZVIqQbq9tHwYcdpcL+DNDvvFUlNv1dsywYHA0jAjx512lslF956vkSL5n5Wgymwfq+O/7vx" +
- "jvZfX/0/+FkXC27N3n7xlOvVlFdp8pFfSnbuC0bTbYKqIOw+BcSoKeut0WNPtZEjjtPOx++X1FMP" +
- "GPysAXD777epxy1PXuj2qXsEsJ+hYArUy9e2Xn7GtPTLj44AFVVHY1/7tld0+g8l+cht2vnE/Y7N" +
- "p0S2htJ9FEDUlPWxxZOusE5VjSRunIK3YbkrAhIpzlRMfeGy4P6jbwH8z0AwBZrPDWqacvQzmfkv" +
- "D0ZETbxCS3/wC9/t1ZeWq78t3oZlDqiwp6nRyJiveMXnXEL7fdeTef1JV9UKKlp118wrQgeNvX5X" +
- "0Rj2uMJjqOmik/6UmbclFkSdylrb4/qHfU0naTzvK463fqkLKijo1oGt0/3ESudrT7jNPznTxL8x" +
- "iehXvuUhroJKw6RxV+aWzJ8MyL9vhSmIJm778fT2h244CiPqVg+0Pa64TzPzZtv2X18XUD8jAIiB" +
- "3nWEK6rBDaHZTmyiCb+lGe1MoGpB6FZOWR+/7KJbbXb+n0lOv8tV64mJlnX2mr74ZKei11PshMue" +
- "UmA6X3nyqrbf/uxIAKe4l5ZdcqdNz5vNllhc9TKCAIAaQ6puNLEzzqN86EhQRTs78BvWkX3/bTpf" +
- "mkZm3p/RbAoM3cJrWe+03PB9yn881drOlJd85gHXT7VGG77/1TvK7n1pRThe/MGnuMIU+M2bj91w" +
- "wrBHbUdDnEDUVlx2n29TbbT8/AIXLy18hAQiFJ8wmdD44wnvPwoxZvs9ENlFb9D2qxvIzH0BxNId" +
- "VMGtGuBXXPNrm7j7OskueNkBKDnjkudKp1x7ItD5KQRToNavaLzgGy91vjr9ABAtPuUCL/LFo2m8" +
- "8ETHJlsMwsek9zqEztMvRbw8TjBMqLSU4spKiquqicVjiAgANtVBx8O3kbjvOtTPgPCvUwjufZBX" +
- "ftEt2njBScZv2+gYN5KvfvCN84N7H3DHpxBMQerNmZc3nHvU5ajnBGqHedW3Psam848jv+I9F2FH" +
- "4qA4gIJvkHgZgeGHEvzSUZSMP4FQccnHVpvk0w+Seu73ZN57Hc11guFfo6JFX/+uFzpgNE1XnOUi" +
- "KpEDvriy4p4XxrrB0Jo9GExB0+bNtanvjX/VX7mor6jR6rtmeOk3ZpJ46CZXRKWrx4MTK6fkrB8S" +
- "n3AqTnkVuAFEgO0qU1Xw8ngbVpO462o6ZjyCGMu/RB3tOfUZr+03t5B5+/kAIhq7/g8/rTrqhEv3" +
- "YDAFCx+889qiWyZfahVihx2fL598haw7ebRRmzbshCgEBgyj+rY/Eui/F/8UVVp+eTmt918HRvlX" +
- "hOqGexWX3q4bvn2kg582nZW1awc9vuhL4Whs1R4IpqC1ubnXhm8d/mp45cK9cEK29/0v+22P3Elq" +
- "xsMBhJ3Ssj7U/OYVwv0GsTvU99h03nGkXnsKEXabqqNVV96b75z9vCRf+kPAEWi5+P4fjvzfs2/e" +
- "Ay+rC96f9fzYPqsX11mF2EGH+yYal9TMJ4wCKJ9ILAQmXbXbsWSyeVLpPGUX3ULm3Tfxk43sNrG0" +
- "/eE+Uz7pMk29/Li1Nmeyj917QsexJ9xbVFzcDmDoFgWe5wWysx7/mvq+o1Y0NuEUOp6bpjaXEgV2" +
- "Nuke/Sg6+n8B8H3LklWNzJq7gtXrW7BW6UpzopN7fj+X+6bNZdqCNuKnnof6oOzmqEr2w/cc9fMa" +
- "2OsAtQoVq947YPVfFu/XzStMQWtTU1WPJXNHWwWnR28bHjZKWu+9AUVFlE+mkDxoPEXxCNYq055f" +
- "yKamJGNHD0REUFVA2JlgwOGbJxxMLBKkrSNDONWTjkfvxG/dwO6yXobO2TMl+sVjNPPBO+pmM+FV" +
- "s18cP3T0597oxmAKNqxYtm9R07oaayG0/0HqNW4mt26Vg4LyycSD7N6jcIFM3iMWDTH5lKEEXId/" +
- "RFEsxN+VFkfQWDXxcceReHQqGHaPqnS+NctUXnyzlUBIfS8jzvzXxnieF3ZdN+PSLQo6PlhwcMxa" +
- "Y30IH/h5Mu+/o9bLsCu58l4AhIMuR4/ZG9cx/LNS6RwbGzuorSkjfuTxtP7hLsBntwjkNq0T9TxM" +
- "RV/1Ni2jdPUH+3q5XNFfgzF0hwLHXfmXA3wFcRwN7zuC9HvviKqC0uXkjYsCIrItlpa2TmbM/pCV" +
- "a5tR1a5DTWWZ+MNHuPTWGbwwZxnBQfvi9hwAym6PptvFb20kWDsQtRBNbO6ZSyX7dNcjqUA1HG9a" +
- "308VJF6qblVvydUvQa2KCjtlFGwqScazRAMOAIn2NOdc9kfqN7Ry8jEHcvyRQ6mrKWdn1m5KsHJd" +
- "C9Fw4G97oKMO+SrBQUPIbVgBwu5RJbP8Qwn03UvVn4FR39H21kFUVi0wdIeCYDjRWKkKpqiHqlr1" +
- "WpsEdvGfDLgNa2nPeADbVpctEeD7lufnLGXpqka6MnhAJRMnDKdf7zLO/NpIxA0QqKlF7XZ/a+uA" +
- "bB0UdGcrjKrkN9QT6N0fFVEVcFJt3bXCFKiq6zdtKlYFJxoDL49NZ1GlawLRVYtozfhUFwFA76pi" +
- "vvyFvXnpjWVUlcU4aP8auuI6hovPOQxVRUQAMOE4WFC2MmEI9YaiUUJ0X0F9yKyGxIuW3AZA+DgF" +
- "v61ZnPJKRQEFL9FS3k3BFAjq4uWCqkAoiFormvdF6ZoKRFcupjnt8XfhUIDLJx3BN48/mMqyGPFY" +
- "iF1jWyyqis21E6iGyF5CdD8hMkQI9gYJCFgAiB6oaN7Q8LAFYQeay6iJRFQFVMHx8+HuC6ZAsCoA" +
- "iICqKICyS6H1S9mcaEf7Fm1bIYJBl9qacrqm4DWguTWgafDbIL8O0u9R/qWn6HGEgxMTAFC2soAB" +
- "P6G0zrS0PKEggPIxqqBWQURQUO3mE3cF4uG6nirYnAeOYzGOURB2wSTb8NavJrNPLyIBh11jayTN" +
- "v0TbHgevETQHeKAWALcYQEDZSkBEyayDtlmWttlKvpGthE8WDInN5nRbLMZ43RdMgS/hWEqh3E+m" +
- "RNygEgqqtrNrCsFlC2g79OBdB6OKpl5G10+C7CpAQYRtRPgYB/x2JTlfScxSUksUzW4XirIDtWDi" +
- "ZeolWrEWACQUaeuuYApEck5JeTNKX789gRhHnJJS8pvXIkKX1ED0w3m0ZM+muoguaXYxWj8R/CYQ" +
- "AQSskmsCJw5OVEDA71BSi5S217b+9FOg2/ekXUcc6NmX/MZ1YFUQcGJFm7ormAIh41b1Wm+VAzXZ" +
- "gteR0GDNYNJL39cthF0IL1tIUzIPFXStcy74jSAGAFWl/lpLxzuKBMCJAgb8JKgHOHyMKv8QMUZD" +
- "g4aQnPMiKoCIOqU9VnZbMAWSD9UN+QDlWJvJSeYv7xMeOpzEzD8h7Fpw43Kam5rw+xXjGGGnIsPB" +
- "REHTgGDTkF6tqANY8JJsgwEUAJSPPL0EULoWjGmgujfp5R8KgImVtG0JZhWAoVsUlIz/2jtqRUGl" +
- "8903NDb8EMSEUNjlmM40/pplpHIeXZHwUKTHZMAFwIkJ1acZghWAgNqPjAIGnDhE66DHl4Wacw0D" +
- "LjGE+8FOP7VQcCur1cSKNbe+XhSIjfjCMhONd+cepiBYO/hdU1TW6idbyjvemWuqzv2JBqr62OzG" +
- "FQ67oh7BD9+l/YjDKA4H2CkJID0vJ1OfQJvvI1QjlI8zFB0sZJYr2U3gd4I44JZAsEoI9gS3FCQo" +
- "CEpmDXgZ2PnLftkS+xc0/eH7+Ml2wUB05Ji54jipbgymwEQi6yNDhi1Mvv3KYdk1SyW3ZqUWjz3G" +
- "Njw81QgqdEFVCS9ZQFPGUlNC10yUxBt9aLjXEttHKB4txIcKsf3lb+GgoApYthLAQm6j0vqK0vSs" +
- "Jd8CIjuPsnjcMdoy7TeiqBjj+LERh7wIaDcGUyCO27klkGc7tgSDlzctT/7eVpx8Ng2/uwfVHLsS" +
- "Wv0+ifYUWhVBROiKWh8vBe3v6t/GhCHYE6IDhUidEKoGEwIvCZl6SP1F6Vyh+B2AbB1lRyiEB+zl" +
- "B/v0p+PtOQaBQJ8BqyN77/c2QDcHU1AybsLTm35184Vec0NVYsbjUn3uj6Ro9OFe++szAghdcho3" +
- "0LlpI7naHoRcoStueSXKNvgZSK+GzlWKiO74ASMg0vV7LwCqRstPPlsTzz2Gl2wTMVB82DHPumXl" +
- "mwvXfewB6vvO6h+c/mDLE787Ra1or8mXeMWHHcmHJx3uiPiGLqgE2XTlg3z+xK9THg3SlbZZM1h+" +
- "1gTApzsFq+u8QQ8+ydKTxomX2OSYaFHH4N++OD42YvTcPbDCFIjj+JWnn3tX2ysvTMgnmoo3P3CH" +
- "6XHyWfT46kS/6YmHBFTYCdEcgSXvksh+lfIoXQrVDsKUVOIlNrGdrhaRrlmjvS66yjb+7n7JNW9y" +
- "cUR7njFlRmz4qPl78H6YgtiBo96s/t4lz6iKesmEs/6Gy2yvC66QQGU/q12djbEQWrqI5lSOXa8E" +
- "fQgP2ptP+n1N8SCpoPPPnbBT0dIj/icfrhssmx+611GBQGXftupvnX8bIvk9G0xhlfGqTv/2jZEB" +
- "+zQAND89zU0teFv7Xn6TlUDUdtEMwbVLaG9N4FslmW+gKbOGjN+5wzFNE45QPGY8WFAAC4niEHdM" +
- "GMjJU0bw4Ji+GPsP9qIQqq6zfS6+Rtb85HzRXMqAY/v+6PpH3PKKN9mOc+WVV9K9CiQQ3Bzdd1iw" +
- "afrDX1LNO8m359LzrO+pW1yh7W+/blAr7AjJWzoOPZaaAX2Yu/lWHls1ldc2z2VjOklJsILiQBwR" +
- "wVefXDRAy1N/gnyWv4yu4s4zhzCztox2DAIctaABlF1y4mW29md32y2bdJqfneYCUnzI4cv6XnrD" +
- "d8SYxKd1e0OBaqz+yose23j/z8cBFA3/gjfw9l/Lxjt+rg2P/soFX9iBQ+OP7mTUWWeyoOkaXtv0" +
- "KqtTsDxpSfoVfLn34YzoU8bsxnksb23EeWMxxwRyvDGigqVJWJ5U2vLQvznNA3cuIJLz6YqEiuyA" +
- "a27x1fOov+J8x+bTxo2Xdw6btfDUYK8+j32aN1AViKT6/eS6ye1zXn45tWR+Tce7r7v1V/zQ73/N" +
- "L0R9z2+Y9oCzQzTWx/1wEa1pH8SwlWDE0JBp5oHVv2eB+jQnhdaUoWNQnIE1LmQUUP4uHzDkHEOY" +
- "nQSjYCJFtt9lN/kmFmflxZMdm0sbxbGDpj50+5ZYngT49IMpPJqW7TP9pVPf/fy+T3qJTcUtM59y" +
- "FPEGXHuLOOUV3oZ7fuGieeEjgsvfo7WjE9cN8FECOI5gEEQEgJyFVF7ZnhXBIqiyA1UIlFb5tdff" +
- "ZlFY+aMpjt/ebFSh/yU/nV467pgrAf/fdItmgVtS9uqwF98620TK0mCl5aUn3OWTT6dq4tky8Of3" +
- "eSZSZlXZJrC+nmRTC0aibE/4OFVFAWv4GMcqxirbUysaG3yAN+S3T2i+sYHlF37H8doajSr0Ovv7" +
- "s/qce+E5QPbffO1qQah33+kH/nnhaYHKfq2qKm3vvOYu/to43LIKhr0415aOOTpvNaBWwSSayNav" +
- "QrR0hzhcP86g6H4MjNUyuuJArjrwO9w06hGOesWl3+oOgr5iBEpSecJZH2vZOiqKG7N9Jl3k7f2b" +
- "P7Hp/+7RlZed7/rpdqM4ts+5lz5be+2txyHS/hm62Lkg39x05AenfOWejoVv9hdUkIBWTzzHqznv" +
- "YumYN1fX//JnJvXBItNy7k8lftpgZm28iRVJZXM2yoiKcXx3yERqi3qxvaY/Pcqyb09kc0WQRf3i" +
- "lKY8Rq5IYBF1wnFKDxtva6ZcaHONTdRffZF0Ll/iYsAEI/m6a29/qPq0b56/LZbPVjAFNpMeuvrK" +
- "i2/f+ODdY9TmHXwI1dT6vSedpz3GHyvJhfN1VUMSjhljFrb/UuLBfeRzPY+hX7w/O2PzORYePYbk" +
- "orcQFRXXJVBdo+Vjj7QVx5+MuAHZcPdt2vTsYw54gkKopq55yN2/vano4M/dBmQBPqvBFKiWtc56" +
- "4YJlF3x3Unb96nIEUKOR2sG28usnafmErxOoHUwwGkLEiCDCNgg70paXnmPNjVdr0fCRWjJmLOEB" +
- "daRXraDxj7+j9dUXjc2kBFTEuH7VSWfOrbvqpkvc0rI/Awrw2Q+mwPgdHaPX3X3rj9dNvfEom0kF" +
- "VAEVdYvLtGjoAVo85ggtGf05CfcbqMGqKjGhMB9pRwEBUN/Ha23R9OrlZFatlMRrL2v73NclXb/C" +
- "qJ8XMQCyJaZD1g687hdTi0aMvh+Rlv/AL9gq0Hw+3PbWnMPX3n7jlLY5s8baXDYEgIIiagIh3NIe" +
- "Gqqq1EBVb9zyCtxoXDFGbT5n/PaE5ho2mtzmjeSbW/A720R9X8SwTbimf33Pb5zxUO9vTv5VoKKq" +
- "/r/gK/wKbDYTTi1eNHTzH393SvPzT0/IrF5Zp2KNCFtpF8cqBba/ndVEYqmKCcfP6Xn8xEeLRx78" +
- "rFtS2oCIAvx3BVMgms/H8q3N+zc9/cTYphlPf/6vIWU3ru+jnufySUTULSpujwzca9mWPcy8skMP" +
- "e6Xkc4fODlb32iyOk6cb/T/N+faHj8AX2gAAAABJRU5ErkJggg=="
- }
-};
-
-// This global tracks if the page has been set up before, to prevent double inits
-var gInitialized = false;
-var gObserver = new MutationObserver(function (mutations) {
- for (let mutation of mutations) {
- if (mutation.attributeName == "searchEngineURL") {
- setupSearchEngine();
- if (!gInitialized) {
- gInitialized = true;
- }
- return;
- }
- }
-});
-
-window.addEventListener("pageshow", function () {
- // Delay search engine setup, cause browser.js::BrowserOnAboutPageLoad runs
- // later and may use asynchronous getters.
- window.gObserver.observe(document.documentElement, { attributes: true });
- fitToWidth();
- window.addEventListener("resize", fitToWidth);
-});
-
-window.addEventListener("pagehide", function() {
- window.gObserver.disconnect();
- window.removeEventListener("resize", fitToWidth);
-});
-
-function onSearchSubmit(aEvent)
-{
- let searchTerms = document.getElementById("searchText").value;
- let searchURL = document.documentElement.getAttribute("searchEngineURL");
-
- if (searchURL && searchTerms.length > 0) {
- // Send an event that a search was performed. This was originally
- // added so Firefox Health Report could record that a search from
- // about:home had occurred.
- let engineName = document.documentElement.getAttribute("searchEngineName");
- let event = new CustomEvent("AboutHomeSearchEvent", {detail: engineName});
- document.dispatchEvent(event);
-
- const SEARCH_TOKEN = "_searchTerms_";
- let searchPostData = document.documentElement.getAttribute("searchEnginePostData");
- if (searchPostData) {
- // Check if a post form already exists. If so, remove it.
- const POST_FORM_NAME = "searchFormPost";
- let form = document.forms[POST_FORM_NAME];
- if (form) {
- form.parentNode.removeChild(form);
- }
-
- // Create a new post form.
- form = document.body.appendChild(document.createElement("form"));
- form.setAttribute("name", POST_FORM_NAME);
- // Set the URL to submit the form to.
- form.setAttribute("action", searchURL.replace(SEARCH_TOKEN, searchTerms));
- form.setAttribute("method", "post");
-
- // Create new <input type=hidden> elements for search param.
- searchPostData = searchPostData.split("&");
- for (let postVar of searchPostData) {
- let [name, value] = postVar.split("=");
- if (value == SEARCH_TOKEN) {
- value = searchTerms;
- }
- let input = document.createElement("input");
- input.setAttribute("type", "hidden");
- input.setAttribute("name", name);
- input.setAttribute("value", value);
- form.appendChild(input);
- }
- // Submit the form.
- form.submit();
- } else {
- searchURL = searchURL.replace(SEARCH_TOKEN, encodeURIComponent(searchTerms));
- window.location.href = searchURL;
- }
- }
-
- aEvent.preventDefault();
-}
-
-
-function setupSearchEngine()
-{
- // The "autofocus" attribute doesn't focus the form element
- // immediately when the element is first drawn, so the
- // attribute is also used for styling when the page first loads.
- let searchText = document.getElementById("searchText");
- searchText.addEventListener("blur", function searchText_onBlur() {
- searchText.removeEventListener("blur", searchText_onBlur);
- searchText.removeAttribute("autofocus");
- });
-
- let searchEngineName = document.documentElement.getAttribute("searchEngineName");
- let searchEngineInfo = SEARCH_ENGINES[searchEngineName];
- let logoElt = document.getElementById("searchEngineLogo");
-
- // Add search engine logo.
- if (searchEngineInfo && searchEngineInfo.image) {
- logoElt.parentNode.hidden = false;
- logoElt.src = searchEngineInfo.image;
- logoElt.alt = searchEngineName;
- searchText.placeholder = "";
- }
- else {
- logoElt.parentNode.hidden = true;
- searchText.placeholder = searchEngineName;
- }
-
-}
-
-function fitToWidth() {
- if (window.scrollMaxX) {
- document.body.setAttribute("narrow", "true");
- } else if (document.body.hasAttribute("narrow")) {
- document.body.removeAttribute("narrow");
- fitToWidth();
- }
-}
diff --git a/components/abouthome/aboutHome.xhtml b/components/abouthome/aboutHome.xhtml
deleted file mode 100644
index d72ec49..0000000
--- a/components/abouthome/aboutHome.xhtml
+++ /dev/null
@@ -1,62 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!DOCTYPE html [
- <!ENTITY % htmlDTD
- PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
- "DTD/xhtml1-strict.dtd">
- %htmlDTD;
- <!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd">
- %globalDTD;
- <!ENTITY % aboutHomeDTD SYSTEM "chrome://browser/locale/aboutHome.dtd">
- %aboutHomeDTD;
- <!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd" >
- %browserDTD;
-]>
-
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title>&abouthome.pageTitle;</title>
-
- <link rel="icon" type="image/png" id="favicon"
- href="chrome://branding/content/icon32.png"/>
- <link rel="stylesheet" type="text/css" media="all"
- href="chrome://browser/content/abouthome/aboutHome.css"/>
-
- <script type="text/javascript;version=1.8"
- src="chrome://browser/content/abouthome/aboutHome.js"/>
- </head>
-
- <body dir="&locale.dir;">
- <div class="spacer"/>
- <div id="topSection">
- <div id="brandLogo"></div>
-
- <div id="searchContainer">
- <form name="searchForm" id="searchForm" onsubmit="onSearchSubmit(event)">
- <div id="searchLogoContainer"><img id="searchEngineLogo"/></div>
- <input type="text" name="q" value="" id="searchText" maxlength="256"
- autofocus="autofocus"/>
- <input id="searchSubmit" type="submit" value="&abouthome.searchEngineButton.label;"/>
- </form>
- </div>
- </div>
- <div class="spacer"/>
-
- <div id="launcher">
- <button class="launchButton" id="downloads">&abouthome.downloadsButton.label;</button>
- <button class="launchButton" id="bookmarks">&abouthome.bookmarksButton.label;</button>
- <button class="launchButton" id="history">&abouthome.historyButton.label;</button>
- <button class="launchButton" id="addons">&abouthome.addonsButton.label;</button>
-#ifdef MOZ_SERVICES_SYNC
- <button class="launchButton" id="sync">&abouthome.syncButton.label;</button>
-#endif
- <button class="launchButton" id="settings">&abouthome.settingsButton.label;</button>
- <div id="restorePreviousSessionSeparator"/>
- <button class="launchButton" id="restorePreviousSession">&historyRestoreLastSession.label;</button>
- </div>
- </body>
-</html>
diff --git a/components/abouthome/addons.png b/components/abouthome/addons.png
deleted file mode 100644
index 41519ce..0000000
--- a/components/abouthome/addons.png
+++ /dev/null
Binary files differ
diff --git a/components/abouthome/addons@2x.png b/components/abouthome/addons@2x.png
deleted file mode 100644
index d4d04ee..0000000
--- a/components/abouthome/addons@2x.png
+++ /dev/null
Binary files differ
diff --git a/components/abouthome/bookmarks.png b/components/abouthome/bookmarks.png
deleted file mode 100644
index 5c7e194..0000000
--- a/components/abouthome/bookmarks.png
+++ /dev/null
Binary files differ
diff --git a/components/abouthome/bookmarks@2x.png b/components/abouthome/bookmarks@2x.png
deleted file mode 100644
index 7ede007..0000000
--- a/components/abouthome/bookmarks@2x.png
+++ /dev/null
Binary files differ
diff --git a/components/abouthome/downloads.png b/components/abouthome/downloads.png
deleted file mode 100644
index 3d4d10e..0000000
--- a/components/abouthome/downloads.png
+++ /dev/null
Binary files differ
diff --git a/components/abouthome/downloads@2x.png b/components/abouthome/downloads@2x.png
deleted file mode 100644
index d384a22..0000000
--- a/components/abouthome/downloads@2x.png
+++ /dev/null
Binary files differ
diff --git a/components/abouthome/history.png b/components/abouthome/history.png
deleted file mode 100644
index ae742b1..0000000
--- a/components/abouthome/history.png
+++ /dev/null
Binary files differ
diff --git a/components/abouthome/history@2x.png b/components/abouthome/history@2x.png
deleted file mode 100644
index 696902e..0000000
--- a/components/abouthome/history@2x.png
+++ /dev/null
Binary files differ
diff --git a/components/abouthome/jar.mn b/components/abouthome/jar.mn
deleted file mode 100644
index e1ae4ac..0000000
--- a/components/abouthome/jar.mn
+++ /dev/null
@@ -1,33 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-browser.jar:
-* content/browser/abouthome/aboutHome.xhtml
- content/browser/abouthome/aboutHome.js
-* content/browser/abouthome/aboutHome.css
- content/browser/abouthome/noise.png
- content/browser/abouthome/snippet1.png
- content/browser/abouthome/snippet2.png
- content/browser/abouthome/downloads.png
- content/browser/abouthome/bookmarks.png
- content/browser/abouthome/history.png
- content/browser/abouthome/addons.png
-#ifdef MOZ_SERVICES_SYNC
- content/browser/abouthome/sync.png
-#endif
- content/browser/abouthome/settings.png
- content/browser/abouthome/restore.png
- content/browser/abouthome/restore-large.png
- content/browser/abouthome/snippet1@2x.png
- content/browser/abouthome/snippet2@2x.png
- content/browser/abouthome/downloads@2x.png
- content/browser/abouthome/bookmarks@2x.png
- content/browser/abouthome/history@2x.png
- content/browser/abouthome/addons@2x.png
-#ifdef MOZ_SERVICES_SYNC
- content/browser/abouthome/sync@2x.png
-#endif
- content/browser/abouthome/settings@2x.png
- content/browser/abouthome/restore@2x.png
- content/browser/abouthome/restore-large@2x.png \ No newline at end of file
diff --git a/components/abouthome/moz.build b/components/abouthome/moz.build
deleted file mode 100644
index 2d64d50..0000000
--- a/components/abouthome/moz.build
+++ /dev/null
@@ -1,8 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-JAR_MANIFESTS += ['jar.mn']
-
diff --git a/components/abouthome/noise.png b/components/abouthome/noise.png
deleted file mode 100644
index 3467cf4..0000000
--- a/components/abouthome/noise.png
+++ /dev/null
Binary files differ
diff --git a/components/abouthome/restore-large.png b/components/abouthome/restore-large.png
deleted file mode 100644
index ef593e6..0000000
--- a/components/abouthome/restore-large.png
+++ /dev/null
Binary files differ
diff --git a/components/abouthome/restore-large@2x.png b/components/abouthome/restore-large@2x.png
deleted file mode 100644
index d5c71d0..0000000
--- a/components/abouthome/restore-large@2x.png
+++ /dev/null
Binary files differ
diff --git a/components/abouthome/restore.png b/components/abouthome/restore.png
deleted file mode 100644
index 5c3d6f4..0000000
--- a/components/abouthome/restore.png
+++ /dev/null
Binary files differ
diff --git a/components/abouthome/restore@2x.png b/components/abouthome/restore@2x.png
deleted file mode 100644
index 5acb630..0000000
--- a/components/abouthome/restore@2x.png
+++ /dev/null
Binary files differ
diff --git a/components/abouthome/settings.png b/components/abouthome/settings.png
deleted file mode 100644
index 4b0c309..0000000
--- a/components/abouthome/settings.png
+++ /dev/null
Binary files differ
diff --git a/components/abouthome/settings@2x.png b/components/abouthome/settings@2x.png
deleted file mode 100644
index c77cb9a..0000000
--- a/components/abouthome/settings@2x.png
+++ /dev/null
Binary files differ
diff --git a/components/abouthome/snippet1.png b/components/abouthome/snippet1.png
deleted file mode 100644
index ce2ec55..0000000
--- a/components/abouthome/snippet1.png
+++ /dev/null
Binary files differ
diff --git a/components/abouthome/snippet1@2x.png b/components/abouthome/snippet1@2x.png
deleted file mode 100644
index f57cd0a..0000000
--- a/components/abouthome/snippet1@2x.png
+++ /dev/null
Binary files differ
diff --git a/components/abouthome/snippet2.png b/components/abouthome/snippet2.png
deleted file mode 100644
index e0724fb..0000000
--- a/components/abouthome/snippet2.png
+++ /dev/null
Binary files differ
diff --git a/components/abouthome/snippet2@2x.png b/components/abouthome/snippet2@2x.png
deleted file mode 100644
index 40577f5..0000000
--- a/components/abouthome/snippet2@2x.png
+++ /dev/null
Binary files differ
diff --git a/components/abouthome/sync.png b/components/abouthome/sync.png
deleted file mode 100644
index 11e40cc..0000000
--- a/components/abouthome/sync.png
+++ /dev/null
Binary files differ
diff --git a/components/abouthome/sync@2x.png b/components/abouthome/sync@2x.png
deleted file mode 100644
index 6354f5b..0000000
--- a/components/abouthome/sync@2x.png
+++ /dev/null
Binary files differ
diff --git a/components/build/Makefile.in b/components/build/Makefile.in
deleted file mode 100644
index 2387227..0000000
--- a/components/build/Makefile.in
+++ /dev/null
@@ -1,8 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-include $(topsrcdir)/config/rules.mk
-
-# Ensure that we don't embed a manifest referencing the CRT.
-EMBED_MANIFEST_AT =
diff --git a/components/build/moz.build b/components/build/moz.build
deleted file mode 100644
index ea1f771..0000000
--- a/components/build/moz.build
+++ /dev/null
@@ -1,36 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-EXPORTS += ['nsBrowserCompsCID.h']
-
-SOURCES += ['nsModule.cpp']
-
-XPCOMBinaryComponent('browsercomps')
-
-LOCAL_INCLUDES += [
- '../dirprovider',
- '../feeds',
- '../shell',
-]
-
-if CONFIG['OS_ARCH'] == 'WINNT':
- OS_LIBS += [
- 'esent',
- 'netapi32',
- 'ole32',
- 'shell32',
- 'shlwapi',
- 'version',
- ]
- DELAYLOAD_DLLS += [
- 'esent.dll',
- 'netapi32.dll',
- ]
-
-# Mac: Need to link with CoreFoundation for Mac Migrators (PList reading code)
-# GTK2: Need to link with glib for GNOME shell service
-if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('cocoa', 'gtk2', 'gtk3'):
- OS_LIBS += CONFIG['TK_LIBS']
diff --git a/components/build/nsBrowserCompsCID.h b/components/build/nsBrowserCompsCID.h
deleted file mode 100644
index bbaa9ab..0000000
--- a/components/build/nsBrowserCompsCID.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/////////////////////////////////////////////////////////////////////////////
-
-#define NS_SHELLSERVICE_CID \
-{ 0x63c7b9f4, 0xcc8, 0x43f8, { 0xb6, 0x66, 0xa, 0x66, 0x16, 0x55, 0xcb, 0x73 } }
-
-#define NS_SHELLSERVICE_CONTRACTID \
- "@mozilla.org/browser/shell-service;1"
-
-#define NS_RDF_FORWARDPROXY_INFER_DATASOURCE_CID \
-{ 0x7a024bcf, 0xedd5, 0x4d9a, { 0x86, 0x14, 0xd4, 0x4b, 0xe1, 0xda, 0xda, 0xd3 } }
-
-#define NS_FEEDSNIFFER_CID \
-{ 0x6893e69, 0x71d8, 0x4b23, { 0x81, 0xeb, 0x80, 0x31, 0x4d, 0xaf, 0x3e, 0x66 } }
-
-#define NS_FEEDSNIFFER_CONTRACTID \
- "@mozilla.org/browser/feeds/sniffer;1"
-
-#define NS_ABOUTFEEDS_CID \
-{ 0x12ff56ec, 0x58be, 0x402c, { 0xb0, 0x57, 0x1, 0xf9, 0x61, 0xde, 0x96, 0x9b } }
-
-// 136e2c4d-c5a4-477c-b131-d93d7d704f64
-#define NS_PRIVATE_BROWSING_SERVICE_WRAPPER_CID \
-{ 0x136e2c4d, 0xc5a4, 0x477c, { 0xb1, 0x31, 0xd9, 0x3d, 0x7d, 0x70, 0x4f, 0x64 } }
-
-// {6DEB193C-F87D-4078-BC78-5E64655B4D62}
-#define NS_BROWSERDIRECTORYPROVIDER_CID \
-{ 0x6deb193c, 0xf87d, 0x4078, { 0xbc, 0x78, 0x5e, 0x64, 0x65, 0x5b, 0x4d, 0x62 } }
diff --git a/components/build/nsModule.cpp b/components/build/nsModule.cpp
deleted file mode 100644
index f98fc08..0000000
--- a/components/build/nsModule.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/ModuleUtils.h"
-
-#include "nsBrowserCompsCID.h"
-#include "DirectoryProvider.h"
-
-#if defined(XP_WIN)
-#include "nsWindowsShellService.h"
-#elif defined(XP_MACOSX)
-#include "nsMacShellService.h"
-#elif defined(MOZ_WIDGET_GTK)
-#include "nsGNOMEShellService.h"
-#endif
-
-#include "rdf.h"
-#include "nsFeedSniffer.h"
-
-#include "nsNetCID.h"
-
-using namespace mozilla::browser;
-
-/////////////////////////////////////////////////////////////////////////////
-
-NS_GENERIC_FACTORY_CONSTRUCTOR(DirectoryProvider)
-#if defined(XP_WIN)
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsWindowsShellService)
-#elif defined(XP_MACOSX)
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsMacShellService)
-#elif defined(MOZ_WIDGET_GTK)
-NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsGNOMEShellService, Init)
-#endif
-
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsFeedSniffer)
-
-NS_DEFINE_NAMED_CID(NS_BROWSERDIRECTORYPROVIDER_CID);
-#if defined(XP_WIN)
-NS_DEFINE_NAMED_CID(NS_SHELLSERVICE_CID);
-#elif defined(MOZ_WIDGET_GTK)
-NS_DEFINE_NAMED_CID(NS_SHELLSERVICE_CID);
-#endif
-NS_DEFINE_NAMED_CID(NS_FEEDSNIFFER_CID);
-#ifdef XP_MACOSX
-NS_DEFINE_NAMED_CID(NS_SHELLSERVICE_CID);
-#endif
-
-static const mozilla::Module::CIDEntry kBrowserCIDs[] = {
- { &kNS_BROWSERDIRECTORYPROVIDER_CID, false, nullptr, DirectoryProviderConstructor },
-#if defined(XP_WIN)
- { &kNS_SHELLSERVICE_CID, false, nullptr, nsWindowsShellServiceConstructor },
-#elif defined(MOZ_WIDGET_GTK)
- { &kNS_SHELLSERVICE_CID, false, nullptr, nsGNOMEShellServiceConstructor },
-#endif
- { &kNS_FEEDSNIFFER_CID, false, nullptr, nsFeedSnifferConstructor },
-#ifdef XP_MACOSX
- { &kNS_SHELLSERVICE_CID, false, nullptr, nsMacShellServiceConstructor },
-#endif
- { nullptr }
-};
-
-static const mozilla::Module::ContractIDEntry kBrowserContracts[] = {
- { NS_BROWSERDIRECTORYPROVIDER_CONTRACTID, &kNS_BROWSERDIRECTORYPROVIDER_CID },
-#if defined(XP_WIN)
- { NS_SHELLSERVICE_CONTRACTID, &kNS_SHELLSERVICE_CID },
-#elif defined(MOZ_WIDGET_GTK)
- { NS_SHELLSERVICE_CONTRACTID, &kNS_SHELLSERVICE_CID },
-#endif
- { NS_FEEDSNIFFER_CONTRACTID, &kNS_FEEDSNIFFER_CID },
-#ifdef XP_MACOSX
- { NS_SHELLSERVICE_CONTRACTID, &kNS_SHELLSERVICE_CID },
-#endif
- { nullptr }
-};
-
-static const mozilla::Module::CategoryEntry kBrowserCategories[] = {
- { XPCOM_DIRECTORY_PROVIDER_CATEGORY, "browser-directory-provider", NS_BROWSERDIRECTORYPROVIDER_CONTRACTID },
- { NS_CONTENT_SNIFFER_CATEGORY, "Feed Sniffer", NS_FEEDSNIFFER_CONTRACTID },
- { nullptr }
-};
-
-static const mozilla::Module kBrowserModule = {
- mozilla::Module::kVersion,
- kBrowserCIDs,
- kBrowserContracts,
- kBrowserCategories
-};
-
-NSMODULE_DEFN(nsBrowserCompsModule) = &kBrowserModule;
diff --git a/components/certerror/content/aboutCertError.css b/components/certerror/content/aboutCertError.css
deleted file mode 100644
index 059d812..0000000
--- a/components/certerror/content/aboutCertError.css
+++ /dev/null
@@ -1,17 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/* Logical CSS rules belong here, but presentation & theming rules
- should live in the CSS of the appropriate theme */
-
-#technicalContentText {
- overflow: auto;
- white-space: pre-wrap;
-}
-
-.expander[hidden],
-.expander[hidden] + *,
-.expander[collapsed] + * {
- display: none;
-}
diff --git a/components/certerror/content/aboutCertError.xhtml b/components/certerror/content/aboutCertError.xhtml
deleted file mode 100644
index c8a7e44..0000000
--- a/components/certerror/content/aboutCertError.xhtml
+++ /dev/null
@@ -1,247 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<!DOCTYPE html [
- <!ENTITY % htmlDTD
- PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
- "DTD/xhtml1-strict.dtd">
- %htmlDTD;
- <!ENTITY % globalDTD
- SYSTEM "chrome://global/locale/global.dtd">
- %globalDTD;
- <!ENTITY % certerrorDTD
- SYSTEM "chrome://browser/locale/aboutCertError.dtd">
- %certerrorDTD;
-]>
-
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title>&certerror.pagetitle;</title>
- <link rel="stylesheet" href="chrome://browser/skin/aboutCertError.css" type="text/css" media="all" />
- <link rel="stylesheet" href="chrome://browser/content/certerror/aboutCertError.css" type="text/css" media="all" />
- <!-- This page currently uses the same favicon as neterror.xhtml.
- If the location of the favicon is changed for both pages, the
- FAVICON_ERRORPAGE_URL symbol in toolkit/components/places/src/nsFaviconService.h
- should be updated. If this page starts using a different favicon
- than neterror.xhtml nsFaviconService->SetAndLoadFaviconForPage
- should be updated to ignore this one as well. -->
- <link rel="icon" type="image/png" id="favicon" href="chrome://global/skin/icons/warning-16.png"/>
-
- <script type="application/javascript"><![CDATA[
- // Error url MUST be formatted like this:
- // about:certerror?e=error&u=url&d=desc
-
- // Note that this file uses document.documentURI to get
- // the URL (with the format from above). This is because
- // document.location.href gets the current URI off the docshell,
- // which is the URL displayed in the location bar, i.e.
- // the URI that the user attempted to load.
-
- function getCSSClass()
- {
- var url = document.documentURI;
- var matches = url.match(/s\=([^&]+)\&/);
- // s is optional, if no match just return nothing
- if (!matches || matches.length < 2)
- return "";
-
- // parenthetical match is the second entry
- return decodeURIComponent(matches[1]);
- }
-
- function getDescription()
- {
- var url = document.documentURI;
- var desc = url.search(/d\=/);
-
- // desc == -1 if not found; if so, return an empty string
- // instead of what would turn out to be portions of the URI
- if (desc == -1)
- return "";
-
- return decodeURIComponent(url.slice(desc + 2));
- }
-
- function initPage()
- {
- // Replace the "#1" string in the intro with the hostname. Trickier
- // than it might seem since we want to preserve the <b> 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');
- }
-
- // Disallow overrides if this is a Strict-Transport-Security
- // host and the cert is bad (STS Spec section 7.3) or if the
- // certerror is in a frame (bug 633691).
- if (getCSSClass() == "badStsCert" || window != top)
- document.getElementById("expertContent").setAttribute("hidden", "true");
-
- 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 <a> tag we care about, being careful not to
- // use an over-greedy regex
- var re = /<a id="cert_domain_link" title="([^"]+)">/;
- var result = re.exec(desc);
- if(!result)
- return;
-
- // Remove sd's existing children
- sd.textContent = "";
-
- // Everything up to the link should be text content
- sd.appendChild(document.createTextNode(desc.slice(0, result.index)));
-
- // Now create the link itself
- var anchorEl = document.createElement("a");
- anchorEl.setAttribute("id", "cert_domain_link");
- anchorEl.setAttribute("title", result[1]);
- anchorEl.appendChild(document.createTextNode(result[1]));
- sd.appendChild(anchorEl);
-
- // Finally, append text for anything after the closing </a>
- sd.appendChild(document.createTextNode(desc.slice(desc.indexOf("</a>") + "</a>".length)));
- }
-
- var link = document.getElementById('cert_domain_link');
- if (!link)
- return;
-
- var okHost = link.getAttribute("title");
- var thisHost = document.location.hostname;
- var proto = document.location.protocol;
-
- // If okHost is a wildcard domain ("*.example.com") let's
- // use "www" instead. "*.example.com" isn't going to
- // get anyone anywhere useful. bug 432491
- okHost = okHost.replace(/^\*\./, "www.");
-
- /* case #1:
- * example.com uses an invalid security certificate.
- *
- * The certificate is only valid for www.example.com
- *
- * Make sure to include the "." ahead of thisHost so that
- * a MitM attack on paypal.com doesn't hyperlink to "notpaypal.com"
- *
- * We'd normally just use a RegExp here except that we lack a
- * library function to escape them properly (bug 248062), and
- * domain names are famous for having '.' characters in them,
- * which would allow spurious and possibly hostile matches.
- */
- if (endsWith(okHost, "." + thisHost))
- link.href = proto + okHost;
-
- /* case #2:
- * browser.garage.maemo.org uses an invalid security certificate.
- *
- * The certificate is only valid for garage.maemo.org
- */
- if (endsWith(thisHost, "." + okHost))
- link.href = proto + okHost;
-
- // If we set a link, meaning there's something helpful for
- // the user here, expand the section by default
- if (link.href && getCSSClass() != "expertBadCert")
- toggle("technicalContent");
- }
-
- function endsWith(haystack, needle) {
- return haystack.slice(-needle.length) == needle;
- }
-
- function toggle(id) {
- var el = document.getElementById(id);
- if (el.getAttribute("collapsed"))
- el.removeAttribute("collapsed");
- else
- el.setAttribute("collapsed", true);
- }
- ]]></script>
- </head>
-
- <body dir="&locale.dir;">
-
- <!-- PAGE CONTAINER (for styling purposes only) -->
- <div id="errorPageContainer">
-
- <!-- Error Title -->
- <div id="errorTitle">
- <h1 id="errorTitleText">&certerror.longpagetitle;</h1>
- </div>
-
- <!-- LONG CONTENT (the section most likely to require scrolling) -->
- <div id="errorLongContent">
- <div id="introContent">
- <p id="introContentP1">&certerror.introPara1;</p>
- <p>&certerror.introPara2;</p>
- </div>
-
- <div id="whatShouldIDoContent">
- <h2>&certerror.whatShouldIDo.heading;</h2>
- <div id="whatShouldIDoContentText">
- <p>&certerror.whatShouldIDo.content;</p>
- <button id='getMeOutOfHereButton'>&certerror.getMeOutOfHere.label;</button>
- </div>
- </div>
-
- <!-- The following sections can be unhidden by default by setting the
- "browser.xul.error_pages.expert_bad_cert" pref to true -->
- <h2 id="technicalContent" class="expander" collapsed="true">
- <button onclick="toggle('technicalContent');">&certerror.technical.heading;</button>
- </h2>
- <p id="technicalContentText"/>
-
- <h2 id="expertContent" class="expander" collapsed="true">
- <button onclick="toggle('expertContent');">&certerror.expert.heading;</button>
- </h2>
- <div>
- <p>&certerror.expert.content;</p>
- <p>&certerror.expert.contentPara2;</p>
- <button id='exceptionDialogButton'>&certerror.addException.label;</button>
- </div>
- </div>
- </div>
-
- <!--
- - Note: It is important to run the script this way, instead of using
- - an onload handler. This is because error pages are loaded as
- - LOAD_BACKGROUND, which means that onload handlers will not be executed.
- -->
- <script type="application/javascript">initPage();</script>
-
- </body>
-</html>
diff --git a/components/certerror/jar.mn b/components/certerror/jar.mn
deleted file mode 100644
index 08e0710..0000000
--- a/components/certerror/jar.mn
+++ /dev/null
@@ -1,7 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-browser.jar:
- content/browser/certerror/aboutCertError.xhtml (content/aboutCertError.xhtml)
- content/browser/certerror/aboutCertError.css (content/aboutCertError.css)
diff --git a/components/certerror/moz.build b/components/certerror/moz.build
deleted file mode 100644
index c97072b..0000000
--- a/components/certerror/moz.build
+++ /dev/null
@@ -1,7 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-JAR_MANIFESTS += ['jar.mn'] \ No newline at end of file
diff --git a/components/dirprovider/DirectoryProvider.cpp b/components/dirprovider/DirectoryProvider.cpp
deleted file mode 100644
index 85728b3..0000000
--- a/components/dirprovider/DirectoryProvider.cpp
+++ /dev/null
@@ -1,268 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsIDirectoryService.h"
-#include "DirectoryProvider.h"
-
-#include "nsIFile.h"
-#include "nsISimpleEnumerator.h"
-#include "nsIPrefService.h"
-#include "nsIPrefBranch.h"
-
-#include "nsArrayEnumerator.h"
-#include "nsEnumeratorUtils.h"
-#include "nsAppDirectoryServiceDefs.h"
-#include "nsDirectoryServiceDefs.h"
-#include "nsCategoryManagerUtils.h"
-#include "nsComponentManagerUtils.h"
-#include "nsCOMArray.h"
-#include "nsDirectoryServiceUtils.h"
-#include "mozilla/ModuleUtils.h"
-#include "nsServiceManagerUtils.h"
-#include "nsStringAPI.h"
-#include "nsXULAppAPI.h"
-#include "nsIPrefLocalizedString.h"
-
-namespace mozilla {
-namespace browser {
-
-NS_IMPL_ISUPPORTS(DirectoryProvider,
- nsIDirectoryServiceProvider,
- nsIDirectoryServiceProvider2)
-
-NS_IMETHODIMP
-DirectoryProvider::GetFile(const char *aKey, bool *aPersist, nsIFile* *aResult)
-{
- return NS_ERROR_FAILURE;
-}
-
-static void
-AppendFileKey(const char *key, nsIProperties* aDirSvc,
- nsCOMArray<nsIFile> &array)
-{
- nsCOMPtr<nsIFile> file;
- nsresult rv = aDirSvc->Get(key, NS_GET_IID(nsIFile), getter_AddRefs(file));
- if (NS_FAILED(rv))
- return;
-
- bool exists;
- rv = file->Exists(&exists);
- if (NS_FAILED(rv) || !exists)
- return;
-
- array.AppendObject(file);
-}
-
-// Appends the distribution-specific search engine directories to the
-// array. The directory structure is as follows:
-
-// appdir/
-// \- distribution/
-// \- searchplugins/
-// |- common/
-// \- locale/
-// |- <locale 1>/
-// ...
-// \- <locale N>/
-
-// common engines are loaded for all locales. If there is no locale
-// directory for the current locale, there is a pref:
-// "distribution.searchplugins.defaultLocale"
-// which specifies a default locale to use.
-
-static void
-AppendDistroSearchDirs(nsIProperties* aDirSvc, nsCOMArray<nsIFile> &array)
-{
- nsCOMPtr<nsIFile> searchPlugins;
- nsresult rv = aDirSvc->Get(XRE_APP_DISTRIBUTION_DIR,
- NS_GET_IID(nsIFile),
- getter_AddRefs(searchPlugins));
- if (NS_FAILED(rv))
- return;
- searchPlugins->AppendNative(NS_LITERAL_CSTRING("searchplugins"));
-
- bool exists;
- rv = searchPlugins->Exists(&exists);
- if (NS_FAILED(rv) || !exists)
- return;
-
- nsCOMPtr<nsIFile> commonPlugins;
- rv = searchPlugins->Clone(getter_AddRefs(commonPlugins));
- if (NS_SUCCEEDED(rv)) {
- commonPlugins->AppendNative(NS_LITERAL_CSTRING("common"));
- rv = commonPlugins->Exists(&exists);
- if (NS_SUCCEEDED(rv) && exists)
- array.AppendObject(commonPlugins);
- }
-
- nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
- if (prefs) {
-
- nsCOMPtr<nsIFile> localePlugins;
- rv = searchPlugins->Clone(getter_AddRefs(localePlugins));
- if (NS_FAILED(rv))
- return;
-
- localePlugins->AppendNative(NS_LITERAL_CSTRING("locale"));
-
- nsCString locale;
- nsCOMPtr<nsIPrefLocalizedString> prefString;
- rv = prefs->GetComplexValue("general.useragent.locale",
- NS_GET_IID(nsIPrefLocalizedString),
- getter_AddRefs(prefString));
- if (NS_SUCCEEDED(rv)) {
- nsAutoString wLocale;
- prefString->GetData(getter_Copies(wLocale));
- CopyUTF16toUTF8(wLocale, locale);
- } else {
- rv = prefs->GetCharPref("general.useragent.locale", getter_Copies(locale));
- }
-
- if (NS_SUCCEEDED(rv)) {
-
- nsCOMPtr<nsIFile> curLocalePlugins;
- rv = localePlugins->Clone(getter_AddRefs(curLocalePlugins));
- if (NS_SUCCEEDED(rv)) {
-
- curLocalePlugins->AppendNative(locale);
- rv = curLocalePlugins->Exists(&exists);
- if (NS_SUCCEEDED(rv) && exists) {
- array.AppendObject(curLocalePlugins);
- return; // all done
- }
- }
- }
-
- // we didn't append the locale dir - try the default one
- nsCString defLocale;
- rv = prefs->GetCharPref("distribution.searchplugins.defaultLocale",
- getter_Copies(defLocale));
- if (NS_SUCCEEDED(rv)) {
-
- nsCOMPtr<nsIFile> defLocalePlugins;
- rv = localePlugins->Clone(getter_AddRefs(defLocalePlugins));
- if (NS_SUCCEEDED(rv)) {
-
- defLocalePlugins->AppendNative(defLocale);
- rv = defLocalePlugins->Exists(&exists);
- if (NS_SUCCEEDED(rv) && exists)
- array.AppendObject(defLocalePlugins);
- }
- }
- }
-}
-
-NS_IMETHODIMP
-DirectoryProvider::GetFiles(const char *aKey, nsISimpleEnumerator* *aResult)
-{
- nsresult rv;
-
- if (!strcmp(aKey, NS_APP_SEARCH_DIR_LIST)) {
- nsCOMPtr<nsIProperties> dirSvc
- (do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
- if (!dirSvc)
- return NS_ERROR_FAILURE;
-
- nsCOMArray<nsIFile> baseFiles;
-
- /**
- * We want to preserve the following order, since the search service loads
- * engines in first-loaded-wins order.
- * - extension search plugin locations (prepended below using
- * NS_NewUnionEnumerator)
- * - distro search plugin locations
- * - user search plugin locations (profile)
- * - app search plugin location (shipped engines)
- */
- AppendDistroSearchDirs(dirSvc, baseFiles);
- AppendFileKey(NS_APP_USER_SEARCH_DIR, dirSvc, baseFiles);
- AppendFileKey(NS_APP_SEARCH_DIR, dirSvc, baseFiles);
-
- nsCOMPtr<nsISimpleEnumerator> baseEnum;
- rv = NS_NewArrayEnumerator(getter_AddRefs(baseEnum), baseFiles);
- if (NS_FAILED(rv))
- return rv;
-
- nsCOMPtr<nsISimpleEnumerator> list;
- rv = dirSvc->Get(XRE_EXTENSIONS_DIR_LIST,
- NS_GET_IID(nsISimpleEnumerator), getter_AddRefs(list));
- if (NS_FAILED(rv))
- return rv;
-
- static char const *const kAppendSPlugins[] = {"searchplugins", nullptr};
-
- nsCOMPtr<nsISimpleEnumerator> extEnum =
- new AppendingEnumerator(list, kAppendSPlugins);
- if (!extEnum)
- return NS_ERROR_OUT_OF_MEMORY;
-
- return NS_NewUnionEnumerator(aResult, extEnum, baseEnum);
- }
-
- return NS_ERROR_FAILURE;
-}
-
-NS_IMPL_ISUPPORTS(DirectoryProvider::AppendingEnumerator, nsISimpleEnumerator)
-
-NS_IMETHODIMP
-DirectoryProvider::AppendingEnumerator::HasMoreElements(bool *aResult)
-{
- *aResult = mNext ? true : false;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-DirectoryProvider::AppendingEnumerator::GetNext(nsISupports* *aResult)
-{
- if (aResult)
- NS_ADDREF(*aResult = mNext);
-
- mNext = nullptr;
-
- nsresult rv;
-
- // Ignore all errors
-
- bool more;
- while (NS_SUCCEEDED(mBase->HasMoreElements(&more)) && more) {
- nsCOMPtr<nsISupports> nextbasesupp;
- mBase->GetNext(getter_AddRefs(nextbasesupp));
-
- nsCOMPtr<nsIFile> nextbase(do_QueryInterface(nextbasesupp));
- if (!nextbase)
- continue;
-
- nextbase->Clone(getter_AddRefs(mNext));
- if (!mNext)
- continue;
-
- char const *const * i = mAppendList;
- while (*i) {
- mNext->AppendNative(nsDependentCString(*i));
- ++i;
- }
-
- bool exists;
- rv = mNext->Exists(&exists);
- if (NS_SUCCEEDED(rv) && exists)
- break;
-
- mNext = nullptr;
- }
-
- return NS_OK;
-}
-
-DirectoryProvider::AppendingEnumerator::AppendingEnumerator
- (nsISimpleEnumerator* aBase,
- char const *const *aAppendList) :
- mBase(aBase),
- mAppendList(aAppendList)
-{
- // Initialize mNext to begin.
- GetNext(nullptr);
-}
-
-} // namespace browser
-} // namespace mozilla
diff --git a/components/dirprovider/DirectoryProvider.h b/components/dirprovider/DirectoryProvider.h
deleted file mode 100644
index 43fa85a..0000000
--- a/components/dirprovider/DirectoryProvider.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef DirectoryProvider_h__
-#define DirectoryProvider_h__
-
-#include "nsIDirectoryService.h"
-#include "nsComponentManagerUtils.h"
-#include "nsISimpleEnumerator.h"
-#include "nsIFile.h"
-#include "mozilla/Attributes.h"
-
-#define NS_BROWSERDIRECTORYPROVIDER_CONTRACTID \
- "@mozilla.org/browser/directory-provider;1"
-
-namespace mozilla {
-namespace browser {
-
-class DirectoryProvider final : public nsIDirectoryServiceProvider2
-{
-public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIDIRECTORYSERVICEPROVIDER
- NS_DECL_NSIDIRECTORYSERVICEPROVIDER2
-
-private:
- ~DirectoryProvider() {}
-
- class AppendingEnumerator final : public nsISimpleEnumerator
- {
- public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSISIMPLEENUMERATOR
-
- AppendingEnumerator(nsISimpleEnumerator* aBase,
- char const *const *aAppendList);
-
- private:
- ~AppendingEnumerator() {}
-
- nsCOMPtr<nsISimpleEnumerator> mBase;
- char const *const *const mAppendList;
- nsCOMPtr<nsIFile> mNext;
- };
-};
-
-} // namespace browser
-} // namespace mozilla
-
-#endif // DirectoryProvider_h__
diff --git a/components/dirprovider/moz.build b/components/dirprovider/moz.build
deleted file mode 100644
index b01c4a3..0000000
--- a/components/dirprovider/moz.build
+++ /dev/null
@@ -1,13 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-EXPORTS.mozilla.browser += ['DirectoryProvider.h']
-
-SOURCES += ['DirectoryProvider.cpp']
-
-FINAL_LIBRARY = 'browsercomps'
-
-LOCAL_INCLUDES += ['../build']
diff --git a/components/distribution.js b/components/distribution.js
deleted file mode 100644
index 121e55b..0000000
--- a/components/distribution.js
+++ /dev/null
@@ -1,345 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-this.EXPORTED_SYMBOLS = [ "DistributionCustomizer" ];
-
-var Ci = Components.interfaces;
-var Cc = Components.classes;
-var Cr = Components.results;
-var Cu = Components.utils;
-
-const DISTRIBUTION_CUSTOMIZATION_COMPLETE_TOPIC =
- "distribution-customization-complete";
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
- "resource://gre/modules/PlacesUtils.jsm");
-
-this.DistributionCustomizer = function DistributionCustomizer() {
- let dirSvc = Cc["@mozilla.org/file/directory_service;1"].
- getService(Ci.nsIProperties);
- let iniFile = dirSvc.get("XREExeF", Ci.nsIFile);
- iniFile.leafName = "distribution";
- iniFile.append("distribution.ini");
- if (iniFile.exists())
- this._iniFile = iniFile;
-}
-
-DistributionCustomizer.prototype = {
- _iniFile: null,
-
- get _ini() {
- let ini = Cc["@mozilla.org/xpcom/ini-parser-factory;1"].
- getService(Ci.nsIINIParserFactory).
- createINIParser(this._iniFile);
- this.__defineGetter__("_ini", function() ini);
- return this._ini;
- },
-
- get _locale() {
- let locale = this._prefs.getCharPref("general.useragent.locale", "en-US");
- this.__defineGetter__("_locale", function() locale);
- return this._locale;
- },
-
- get _prefSvc() {
- let svc = Cc["@mozilla.org/preferences-service;1"].
- getService(Ci.nsIPrefService);
- this.__defineGetter__("_prefSvc", function() svc);
- return this._prefSvc;
- },
-
- get _prefs() {
- let branch = this._prefSvc.getBranch(null);
- this.__defineGetter__("_prefs", function() branch);
- return this._prefs;
- },
-
- get _ioSvc() {
- let svc = Cc["@mozilla.org/network/io-service;1"].
- getService(Ci.nsIIOService);
- this.__defineGetter__("_ioSvc", function() svc);
- return this._ioSvc;
- },
-
- _makeURI: function DIST__makeURI(spec) {
- return this._ioSvc.newURI(spec, null, null);
- },
-
- _parseBookmarksSection:
- function DIST_parseBookmarksSection(parentId, section) {
- let keys = [];
- for (let i in enumerate(this._ini.getKeys(section)))
- keys.push(i);
- keys.sort();
-
- let items = {};
- let defaultItemId = -1;
- let maxItemId = -1;
-
- for (let i = 0; i < keys.length; i++) {
- let m = /^item\.(\d+)\.(\w+)\.?(\w*)/.exec(keys[i]);
- if (m) {
- let [foo, iid, iprop, ilocale] = m;
- iid = parseInt(iid);
-
- if (ilocale)
- continue;
-
- if (!items[iid])
- items[iid] = {};
- if (keys.indexOf(keys[i] + "." + this._locale) >= 0) {
- items[iid][iprop] = this._ini.getString(section, keys[i] + "." +
- this._locale);
- } else {
- items[iid][iprop] = this._ini.getString(section, keys[i]);
- }
-
- if (iprop == "type" && items[iid]["type"] == "default")
- defaultItemId = iid;
-
- if (maxItemId < iid)
- maxItemId = iid;
- } else {
- dump("Key did not match: " + keys[i] + "\n");
- }
- }
-
- let prependIndex = 0;
- for (let iid = 0; iid <= maxItemId; iid++) {
- if (!items[iid])
- continue;
-
- let index = PlacesUtils.bookmarks.DEFAULT_INDEX;
- let newId;
-
- switch (items[iid]["type"]) {
- case "default":
- break;
-
- case "folder":
- if (iid < defaultItemId)
- index = prependIndex++;
-
- newId = PlacesUtils.bookmarks.createFolder(parentId,
- items[iid]["title"],
- index);
-
- this._parseBookmarksSection(newId, "BookmarksFolder-" +
- items[iid]["folderId"]);
-
- if (items[iid]["description"])
- PlacesUtils.annotations.setItemAnnotation(newId,
- "bookmarkProperties/description",
- items[iid]["description"], 0,
- PlacesUtils.annotations.EXPIRE_NEVER);
-
- break;
-
- case "separator":
- if (iid < defaultItemId)
- index = prependIndex++;
- PlacesUtils.bookmarks.insertSeparator(parentId, index);
- break;
-
- case "livemark":
- if (iid < defaultItemId)
- index = prependIndex++;
-
- // Don't bother updating the livemark contents on creation.
- PlacesUtils.livemarks.addLivemark({ title: items[iid]["title"]
- , parentId: parentId
- , index: index
- , feedURI: this._makeURI(items[iid]["feedLink"])
- , siteURI: this._makeURI(items[iid]["siteLink"])
- }).then(null, Cu.reportError);
- break;
-
- case "bookmark":
- default:
- if (iid < defaultItemId)
- index = prependIndex++;
-
- newId = PlacesUtils.bookmarks.insertBookmark(parentId,
- this._makeURI(items[iid]["link"]),
- index, items[iid]["title"]);
-
- if (items[iid]["description"])
- PlacesUtils.annotations.setItemAnnotation(newId,
- "bookmarkProperties/description",
- items[iid]["description"], 0,
- PlacesUtils.annotations.EXPIRE_NEVER);
-
- break;
- }
- }
- },
-
- _customizationsApplied: false,
- applyCustomizations: function DIST_applyCustomizations() {
- this._customizationsApplied = true;
- if (!this._iniFile)
- return this._checkCustomizationComplete();
-
- // nsPrefService loads very early. Reload prefs so we can set
- // distribution defaults during the prefservice:after-app-defaults
- // notification (see applyPrefDefaults below)
- this._prefSvc.QueryInterface(Ci.nsIObserver);
- this._prefSvc.observe(null, "reload-default-prefs", null);
- },
-
- _bookmarksApplied: false,
- applyBookmarks: function DIST_applyBookmarks() {
- this._bookmarksApplied = true;
- if (!this._iniFile)
- return this._checkCustomizationComplete();
-
- let sections = enumToObject(this._ini.getSections());
-
- // The global section, and several of its fields, is required
- // (we also check here to be consistent with applyPrefDefaults below)
- if (!sections["Global"])
- return this._checkCustomizationComplete();
- let globalPrefs = enumToObject(this._ini.getKeys("Global"));
- if (!(globalPrefs["id"] && globalPrefs["version"] && globalPrefs["about"]))
- return this._checkCustomizationComplete();
-
- let bmProcessedPref;
- try {
- bmProcessedPref = this._ini.getString("Global",
- "bookmarks.initialized.pref");
- }
- catch (e) {
- bmProcessedPref = "distribution." +
- this._ini.getString("Global", "id") + ".bookmarksProcessed";
- }
-
- let bmProcessed = this._prefs.getBoolPref(bmProcessedPref, false);
-
- if (!bmProcessed) {
- if (sections["BookmarksMenu"])
- this._parseBookmarksSection(PlacesUtils.bookmarksMenuFolderId,
- "BookmarksMenu");
- if (sections["BookmarksToolbar"])
- this._parseBookmarksSection(PlacesUtils.toolbarFolderId,
- "BookmarksToolbar");
- this._prefs.setBoolPref(bmProcessedPref, true);
- }
- return this._checkCustomizationComplete();
- },
-
- _prefDefaultsApplied: false,
- applyPrefDefaults: function DIST_applyPrefDefaults() {
- this._prefDefaultsApplied = true;
- if (!this._iniFile)
- return this._checkCustomizationComplete();
-
- let sections = enumToObject(this._ini.getSections());
-
- // The global section, and several of its fields, is required
- if (!sections["Global"])
- return this._checkCustomizationComplete();
- let globalPrefs = enumToObject(this._ini.getKeys("Global"));
- if (!(globalPrefs["id"] && globalPrefs["version"] && globalPrefs["about"]))
- return this._checkCustomizationComplete();
-
- let defaults = this._prefSvc.getDefaultBranch(null);
-
- // Global really contains info we set as prefs. They're only
- // separate because they are "special" (read: required)
-
- defaults.setCharPref("distribution.id", this._ini.getString("Global", "id"));
- defaults.setCharPref("distribution.version",
- this._ini.getString("Global", "version"));
-
- let partnerAbout = Cc["@mozilla.org/supports-string;1"].
- createInstance(Ci.nsISupportsString);
- try {
- if (globalPrefs["about." + this._locale]) {
- partnerAbout.data = this._ini.getString("Global", "about." + this._locale);
- } else {
- partnerAbout.data = this._ini.getString("Global", "about");
- }
- defaults.setComplexValue("distribution.about",
- Ci.nsISupportsString, partnerAbout);
- } catch (e) {
- /* ignore bad prefs due to bug 895473 and move on */
- Cu.reportError(e);
- }
-
- if (sections["Preferences"]) {
- for (let key in enumerate(this._ini.getKeys("Preferences"))) {
- try {
- let value = eval(this._ini.getString("Preferences", key));
- switch (typeof value) {
- case "boolean":
- defaults.setBoolPref(key, value);
- break;
- case "number":
- defaults.setIntPref(key, value);
- break;
- case "string":
- defaults.setCharPref(key, value);
- break;
- case "undefined":
- defaults.setCharPref(key, value);
- break;
- }
- } catch (e) { /* ignore bad prefs and move on */ }
- }
- }
-
- // We eval() the localizable prefs as well (even though they'll
- // always get set as a string) to keep the INI format consistent:
- // string prefs always need to be in quotes
-
- let localizedStr = Cc["@mozilla.org/pref-localizedstring;1"].
- createInstance(Ci.nsIPrefLocalizedString);
-
- if (sections["LocalizablePreferences"]) {
- for (let key in enumerate(this._ini.getKeys("LocalizablePreferences"))) {
- try {
- let value = eval(this._ini.getString("LocalizablePreferences", key));
- value = value.replace("%LOCALE%", this._locale, "g");
- localizedStr.data = "data:text/plain," + key + "=" + value;
- defaults.setComplexValue(key, Ci.nsIPrefLocalizedString, localizedStr);
- } catch (e) { /* ignore bad prefs and move on */ }
- }
- }
-
- if (sections["LocalizablePreferences-" + this._locale]) {
- for (let key in enumerate(this._ini.getKeys("LocalizablePreferences-" + this._locale))) {
- try {
- let value = eval(this._ini.getString("LocalizablePreferences-" + this._locale, key));
- localizedStr.data = "data:text/plain," + key + "=" + value;
- defaults.setComplexValue(key, Ci.nsIPrefLocalizedString, localizedStr);
- } catch (e) { /* ignore bad prefs and move on */ }
- }
- }
-
- return this._checkCustomizationComplete();
- },
-
- _checkCustomizationComplete: function DIST__checkCustomizationComplete() {
- let prefDefaultsApplied = this._prefDefaultsApplied || !this._iniFile;
- if (this._customizationsApplied && this._bookmarksApplied &&
- prefDefaultsApplied) {
- let os = Cc["@mozilla.org/observer-service;1"].
- getService(Ci.nsIObserverService);
- os.notifyObservers(null, DISTRIBUTION_CUSTOMIZATION_COMPLETE_TOPIC, null);
- }
- }
-};
-
-function enumerate(UTF8Enumerator) {
- while (UTF8Enumerator.hasMore())
- yield UTF8Enumerator.getNext();
-}
-
-function enumToObject(UTF8Enumerator) {
- let ret = {};
- for (let i in enumerate(UTF8Enumerator))
- ret[i] = 1;
- return ret;
-}
diff --git a/components/downloads/BrowserDownloads.manifest b/components/downloads/BrowserDownloads.manifest
deleted file mode 100644
index 1881ca1..0000000
--- a/components/downloads/BrowserDownloads.manifest
+++ /dev/null
@@ -1,4 +0,0 @@
-component {49507fe5-2cee-4824-b6a3-e999150ce9b8} DownloadsStartup.js
-contract @mozilla.org/browser/downloadsstartup;1 {49507fe5-2cee-4824-b6a3-e999150ce9b8}
-category profile-after-change DownloadsStartup @mozilla.org/browser/downloadsstartup;1
-component {4d99321e-d156-455b-81f7-e7aa2308134f} DownloadsUI.js
diff --git a/components/downloads/DownloadsCommon.jsm b/components/downloads/DownloadsCommon.jsm
deleted file mode 100644
index efe31ce..0000000
--- a/components/downloads/DownloadsCommon.jsm
+++ /dev/null
@@ -1,1920 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=2 et sw=2 tw=80 filetype=javascript: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-this.EXPORTED_SYMBOLS = [
- "DownloadsCommon",
-];
-
-/**
- * Handles the Downloads panel shared methods and data access.
- *
- * This file includes the following constructors and global objects:
- *
- * DownloadsCommon
- * This object is exposed directly to the consumers of this JavaScript module,
- * and provides shared methods for all the instances of the user interface.
- *
- * DownloadsData
- * Retrieves the list of past and completed downloads from the underlying
- * Downloads API data, and provides asynchronous notifications allowing
- * to build a consistent view of the available data.
- *
- * DownloadsIndicatorData
- * This object registers itself with DownloadsData as a view, and transforms the
- * notifications it receives into overall status data, that is then broadcast to
- * the registered download status indicators.
- */
-
-////////////////////////////////////////////////////////////////////////////////
-//// Globals
-
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-const Cu = Components.utils;
-const Cr = Components.results;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
- "resource://gre/modules/NetUtil.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
- "resource://gre/modules/PluralForm.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "Downloads",
- "resource://gre/modules/Downloads.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "DownloadUIHelper",
- "resource://gre/modules/DownloadUIHelper.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "DownloadUtils",
- "resource://gre/modules/DownloadUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
- "resource://gre/modules/FileUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "OS",
- "resource://gre/modules/osfile.jsm")
-XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
- "resource://gre/modules/PlacesUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
- "resource://gre/modules/PrivateBrowsingUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "RecentWindow",
- "resource:///modules/RecentWindow.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
- "resource://gre/modules/PlacesUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "Promise",
- "resource://gre/modules/Promise.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "DownloadsLogger",
- "resource:///modules/DownloadsLogger.jsm");
-
-const nsIDM = Ci.nsIDownloadManager;
-
-const kDownloadsStringBundleUrl =
- "chrome://browser/locale/downloads/downloads.properties";
-
-const kPrefConfirmOpenExe = "browser.download.confirmOpenExecutable";
-
-const kDownloadsStringsRequiringFormatting = {
- sizeWithUnits: true,
- shortTimeLeftSeconds: true,
- shortTimeLeftMinutes: true,
- shortTimeLeftHours: true,
- shortTimeLeftDays: true,
- statusSeparator: true,
- statusSeparatorBeforeNumber: true,
- fileExecutableSecurityWarning: true
-};
-
-const kDownloadsStringsRequiringPluralForm = {
- otherDownloads2: true
-};
-
-const kPartialDownloadSuffix = ".part";
-
-const kPrefBranch = Services.prefs.getBranch("browser.download.");
-
-var PrefObserver = {
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
- Ci.nsISupportsWeakReference]),
- getPref: function PO_getPref(name) {
- try {
- switch (typeof this.prefs[name]) {
- case "boolean":
- return kPrefBranch.getBoolPref(name);
- }
- } catch (ex) { }
- return this.prefs[name];
- },
- observe: function PO_observe(aSubject, aTopic, aData) {
- if (this.prefs.hasOwnProperty(aData)) {
- return this[aData] = this.getPref(aData);
- }
- },
- register: function PO_register(prefs) {
- this.prefs = prefs;
- kPrefBranch.addObserver("", this, true);
- for (let key in prefs) {
- let name = key;
- XPCOMUtils.defineLazyGetter(this, name, function () {
- return PrefObserver.getPref(name);
- });
- }
- },
-};
-
-PrefObserver.register({
- // prefName: defaultValue
- debug: false,
- animateNotifications: true
-});
-
-
-////////////////////////////////////////////////////////////////////////////////
-//// DownloadsCommon
-
-/**
- * This object is exposed directly to the consumers of this JavaScript module,
- * and provides shared methods for all the instances of the user interface.
- */
-this.DownloadsCommon = {
- log: function DC_log(...aMessageArgs) {
- delete this.log;
- this.log = function DC_log(...aMessageArgs) {
- if (!PrefObserver.debug) {
- return;
- }
- DownloadsLogger.log.apply(DownloadsLogger, aMessageArgs);
- }
- this.log.apply(this, aMessageArgs);
- },
-
- error: function DC_error(...aMessageArgs) {
- delete this.error;
- this.error = function DC_error(...aMessageArgs) {
- if (!PrefObserver.debug) {
- return;
- }
- DownloadsLogger.reportError.apply(DownloadsLogger, aMessageArgs);
- }
- this.error.apply(this, aMessageArgs);
- },
- /**
- * Returns an object whose keys are the string names from the downloads string
- * bundle, and whose values are either the translated strings or functions
- * returning formatted strings.
- */
- get strings()
- {
- let strings = {};
- let sb = Services.strings.createBundle(kDownloadsStringBundleUrl);
- let enumerator = sb.getSimpleEnumeration();
- while (enumerator.hasMoreElements()) {
- let string = enumerator.getNext().QueryInterface(Ci.nsIPropertyElement);
- let stringName = string.key;
- if (stringName in kDownloadsStringsRequiringFormatting) {
- strings[stringName] = function () {
- // Convert "arguments" to a real array before calling into XPCOM.
- return sb.formatStringFromName(stringName,
- Array.slice(arguments, 0),
- arguments.length);
- };
- } else if (stringName in kDownloadsStringsRequiringPluralForm) {
- strings[stringName] = function (aCount) {
- // Convert "arguments" to a real array before calling into XPCOM.
- let formattedString = sb.formatStringFromName(stringName,
- Array.slice(arguments, 0),
- arguments.length);
- return PluralForm.get(aCount, formattedString);
- };
- } else {
- strings[stringName] = string.value;
- }
- }
- delete this.strings;
- return this.strings = strings;
- },
-
- /**
- * Generates a very short string representing the given time left.
- *
- * @param aSeconds
- * Value to be formatted. It represents the number of seconds, it must
- * be positive but does not need to be an integer.
- *
- * @return Formatted string, for example "30s" or "2h". The returned value is
- * maximum three characters long, at least in English.
- */
- formatTimeLeft: function DC_formatTimeLeft(aSeconds)
- {
- // Decide what text to show for the time
- let seconds = Math.round(aSeconds);
- if (!seconds) {
- return "";
- } else if (seconds <= 30) {
- return DownloadsCommon.strings["shortTimeLeftSeconds"](seconds);
- }
- let minutes = Math.round(aSeconds / 60);
- if (minutes < 60) {
- return DownloadsCommon.strings["shortTimeLeftMinutes"](minutes);
- }
- let hours = Math.round(minutes / 60);
- if (hours < 48) { // two days
- return DownloadsCommon.strings["shortTimeLeftHours"](hours);
- }
- let days = Math.round(hours / 24);
- return DownloadsCommon.strings["shortTimeLeftDays"](Math.min(days, 99));
- },
-
- /**
- * Indicates whether we should show the full Download Manager window interface
- * instead of the simplified panel interface. The behavior of downloads
- * across browsing session is consistent with the selected interface.
- */
- get useToolkitUI()
- {
- /* Toolkit UI is currently incompatible.
- * FIXME: Either fix the toolkitUI (make DBConnection work) or remove
- * the unused code altogether
- */
- //try {
- // return Services.prefs.getBoolPref("browser.download.useToolkitUI");
- //} catch (ex) { }
- return false;
- },
-
- /**
- * Indicates whether we should show visual notification on the indicator
- * when a download event is triggered.
- */
- get animateNotifications()
- {
- return PrefObserver.animateNotifications;
- },
-
- /**
- * Get access to one of the DownloadsData or PrivateDownloadsData objects,
- * depending on the privacy status of the window in question.
- *
- * @param aWindow
- * The browser window which owns the download button.
- */
- getData: function DC_getData(aWindow) {
- if (PrivateBrowsingUtils.isWindowPrivate(aWindow)) {
- return PrivateDownloadsData;
- } else {
- return DownloadsData;
- }
- },
-
- /**
- * Initializes the data link for both the private and non-private downloads
- * data objects.
- *
- * @param aDownloadManagerService
- * Reference to the service implementing nsIDownloadManager. We need
- * this because getService isn't available for us when this method is
- * called, and we must ensure to register our listeners before the
- * getService call for the Download Manager returns.
- */
- initializeAllDataLinks: function DC_initializeAllDataLinks(aDownloadManagerService) {
- DownloadsData.initializeDataLink(aDownloadManagerService);
- PrivateDownloadsData.initializeDataLink(aDownloadManagerService);
- },
-
- /**
- * Terminates the data link for both the private and non-private downloads
- * data objects.
- */
- terminateAllDataLinks: function DC_terminateAllDataLinks() {
- DownloadsData.terminateDataLink();
- PrivateDownloadsData.terminateDataLink();
- },
-
- /**
- * Reloads the specified kind of downloads from the non-private store.
- * This method must only be called when Private Browsing Mode is disabled.
- *
- * @param aActiveOnly
- * True to load only active downloads from the database.
- */
- ensureAllPersistentDataLoaded:
- function DC_ensureAllPersistentDataLoaded(aActiveOnly) {
- DownloadsData.ensurePersistentDataLoaded(aActiveOnly);
- },
-
- /**
- * Get access to one of the DownloadsIndicatorData or
- * PrivateDownloadsIndicatorData objects, depending on the privacy status of
- * the window in question.
- */
- getIndicatorData: function DC_getIndicatorData(aWindow) {
- if (PrivateBrowsingUtils.isWindowPrivate(aWindow)) {
- return PrivateDownloadsIndicatorData;
- } else {
- return DownloadsIndicatorData;
- }
- },
-
- /**
- * Returns a reference to the DownloadsSummaryData singleton - creating one
- * in the process if one hasn't been instantiated yet.
- *
- * @param aWindow
- * The browser window which owns the download button.
- * @param aNumToExclude
- * The number of items on the top of the downloads list to exclude
- * from the summary.
- */
- getSummary: function DC_getSummary(aWindow, aNumToExclude)
- {
- if (PrivateBrowsingUtils.isWindowPrivate(aWindow)) {
- if (this._privateSummary) {
- return this._privateSummary;
- }
- return this._privateSummary = new DownloadsSummaryData(true, aNumToExclude);
- } else {
- if (this._summary) {
- return this._summary;
- }
- return this._summary = new DownloadsSummaryData(false, aNumToExclude);
- }
- },
- _summary: null,
- _privateSummary: null,
-
- /**
- * Returns the legacy state integer value for the provided Download object.
- */
- stateOfDownload(download) {
- // Collapse state using the correct priority.
- if (!download.stopped) {
- return nsIDM.DOWNLOAD_DOWNLOADING;
- }
- if (download.succeeded) {
- return nsIDM.DOWNLOAD_FINISHED;
- }
- if (download.error) {
- if (download.error.becauseBlockedByParentalControls) {
- return nsIDM.DOWNLOAD_BLOCKED_PARENTAL;
- }
- if (download.error.becauseBlockedByReputationCheck) {
- return nsIDM.DOWNLOAD_DIRTY;
- }
- return nsIDM.DOWNLOAD_FAILED;
- }
- if (download.canceled) {
- if (download.hasPartialData) {
- return nsIDM.DOWNLOAD_PAUSED;
- }
- return nsIDM.DOWNLOAD_CANCELED;
- }
- return nsIDM.DOWNLOAD_NOTSTARTED;
- },
-
- /**
- * Helper function required because the Downloads Panel and the Downloads View
- * don't share the controller yet.
- */
- removeAndFinalizeDownload(download) {
- Downloads.getList(Downloads.ALL)
- .then(list => list.remove(download))
- .then(() => download.finalize(true))
- .catch(Cu.reportError);
- },
-
- /**
- * Given an iterable collection of Download objects, generates and returns
- * statistics about that collection.
- *
- * @param downloads An iterable collection of Download objects.
- *
- * @return Object whose properties are the generated statistics. Currently,
- * we return the following properties:
- *
- * numActive : The total number of downloads.
- * numPaused : The total number of paused downloads.
- * numDownloading : The total number of downloads being downloaded.
- * totalSize : The total size of all downloads once completed.
- * totalTransferred: The total amount of transferred data for these
- * downloads.
- * slowestSpeed : The slowest download rate.
- * rawTimeLeft : The estimated time left for the downloads to
- * complete.
- * percentComplete : The percentage of bytes successfully downloaded.
- */
- summarizeDownloads(downloads) {
- let summary = {
- numActive: 0,
- numPaused: 0,
- numDownloading: 0,
- totalSize: 0,
- totalTransferred: 0,
- // slowestSpeed is Infinity so that we can use Math.min to
- // find the slowest speed. We'll set this to 0 afterwards if
- // it's still at Infinity by the time we're done iterating all
- // download.
- slowestSpeed: Infinity,
- rawTimeLeft: -1,
- percentComplete: -1
- }
-
- for (let download of downloads) {
- summary.numActive++;
-
- if (!download.stopped) {
- summary.numDownloading++;
- if (download.hasProgress && download.speed > 0) {
- let sizeLeft = download.totalBytes - download.currentBytes;
- summary.rawTimeLeft = Math.max(summary.rawTimeLeft,
- sizeLeft / download.speed);
- summary.slowestSpeed = Math.min(summary.slowestSpeed,
- download.speed);
- }
- } else if (download.canceled && download.hasPartialData) {
- summary.numPaused++;
- }
- // Only add to total values if we actually know the download size.
- if (download.succeeded) {
- summary.totalSize += download.target.size;
- summary.totalTransferred += download.target.size;
- } else if (download.hasProgress) {
- summary.totalSize += download.totalBytes;
- summary.totalTransferred += download.currentBytes;
- }
- }
-
- if (summary.totalSize != 0) {
- summary.percentComplete = (summary.totalTransferred /
- summary.totalSize) * 100;
- }
-
- if (summary.slowestSpeed == Infinity) {
- summary.slowestSpeed = 0;
- }
-
- return summary;
- },
-
- /**
- * If necessary, smooths the estimated number of seconds remaining for one
- * or more downloads to complete.
- *
- * @param aSeconds
- * Current raw estimate on number of seconds left for one or more
- * downloads. This is a floating point value to help get sub-second
- * accuracy for current and future estimates.
- */
- smoothSeconds: function DC_smoothSeconds(aSeconds, aLastSeconds)
- {
- // We apply an algorithm similar to the DownloadUtils.getTimeLeft function,
- // though tailored to a single time estimation for all downloads. We never
- // apply something if the new value is less than half the previous value.
- let shouldApplySmoothing = aLastSeconds >= 0 &&
- aSeconds > aLastSeconds / 2;
- if (shouldApplySmoothing) {
- // Apply hysteresis to favor downward over upward swings. Trust only 30%
- // of the new value if lower, and 10% if higher (exponential smoothing).
- let diff = aSeconds - aLastSeconds;
- aSeconds = aLastSeconds + (diff < 0 ? .3 : .1) * diff;
-
- // If the new time is similar, reuse something close to the last time
- // left, but subtract a little to provide forward progress.
- diff = aSeconds - aLastSeconds;
- let diffPercent = diff / aLastSeconds * 100;
- if (Math.abs(diff) < 5 || Math.abs(diffPercent) < 5) {
- aSeconds = aLastSeconds - (diff < 0 ? .4 : .2);
- }
- }
-
- // In the last few seconds of downloading, we are always subtracting and
- // never adding to the time left. Ensure that we never fall below one
- // second left until all downloads are actually finished.
- return aLastSeconds = Math.max(aSeconds, 1);
- },
-
- /**
- * Opens a downloaded file.
- *
- * @param aFile
- * the downloaded file to be opened.
- * @param aMimeInfo
- * the mime type info object. May be null.
- * @param aOwnerWindow
- * the window with which this action is associated.
- */
- openDownloadedFile: function DC_openDownloadedFile(aFile, aMimeInfo, aOwnerWindow) {
- if (!(aFile instanceof Ci.nsIFile))
- throw new Error("aFile must be a nsIFile object");
- if (aMimeInfo && !(aMimeInfo instanceof Ci.nsIMIMEInfo))
- throw new Error("Invalid value passed for aMimeInfo");
- if (!(aOwnerWindow instanceof Ci.nsIDOMWindow))
- throw new Error("aOwnerWindow must be a dom-window object");
-
-#ifdef XP_WIN
- // On Windows, the system will provide a native confirmation prompt
- // for .exe files. Exclude this from our prompt, but prompt on other
- // executable types.
- let isWindowsExe = aFile.leafName.toLowerCase().endsWith(".exe");
-#else
- let isWindowsExe = false;
-#endif
-
- // Confirm opening executable files if required.
- if (aFile.isExecutable() && !isWindowsExe) {
- let showAlert = true;
- try {
- showAlert = Services.prefs.getBoolPref(kPrefConfirmOpenExe);
- } catch (ex) {
- // If the preference does not exist, continue with the prompt.
- }
-
- if (showAlert) {
- let name = aFile.leafName;
- let message =
- DownloadsCommon.strings.fileExecutableSecurityWarning(name, name);
- let title =
- DownloadsCommon.strings.fileExecutableSecurityWarningTitle;
-
- let open = Services.prompt.confirm(aOwnerWindow, title, message);
- if (!open) {
- return;
- }
- }
- }
-
- // Actually open the file.
- try {
- if (aMimeInfo && aMimeInfo.preferredAction == aMimeInfo.useHelperApp) {
- aMimeInfo.launchWithFile(aFile);
- return;
- }
- }
- catch(ex) { }
-
- // If either we don't have the mime info, or the preferred action failed,
- // attempt to launch the file directly.
- try {
- aFile.launch();
- }
- catch(ex) {
- // If launch fails, try sending it through the system's external "file:"
- // URL handler.
- Cc["@mozilla.org/uriloader/external-protocol-service;1"]
- .getService(Ci.nsIExternalProtocolService)
- .loadUrl(NetUtil.newURI(aFile));
- }
- },
-
- /**
- * Show a downloaded file in the system file manager.
- *
- * @param aFile
- * a downloaded file.
- */
- showDownloadedFile: function DC_showDownloadedFile(aFile) {
- if (!(aFile instanceof Ci.nsIFile))
- throw new Error("aFile must be a nsIFile object");
- try {
- // Show the directory containing the file and select the file.
- aFile.reveal();
- } catch (ex) {
- // If reveal fails for some reason (e.g., it's not implemented on unix
- // or the file doesn't exist), try using the parent if we have it.
- let parent = aFile.parent;
- if (parent) {
- try {
- // Open the parent directory to show where the file should be.
- parent.launch();
- } catch (ex) {
- // If launch also fails (probably because it's not implemented), let
- // the OS handler try to open the parent.
- Cc["@mozilla.org/uriloader/external-protocol-service;1"]
- .getService(Ci.nsIExternalProtocolService)
- .loadUrl(NetUtil.newURI(parent));
- }
- }
- }
- }
-};
-
-/**
- * Returns true if we are executing on Windows Vista or a later version.
- */
-XPCOMUtils.defineLazyGetter(DownloadsCommon, "isWinVistaOrHigher", function () {
- let os = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS;
- if (os != "WINNT") {
- return false;
- }
- let sysInfo = Cc["@mozilla.org/system-info;1"].getService(Ci.nsIPropertyBag2);
- return parseFloat(sysInfo.getProperty("version")) >= 6;
-});
-
-/**
- * Returns true to indicate that we should hook the panel to the JavaScript API
- * for downloads instead of the nsIDownloadManager back-end.
- * This is kept for compatibility/leftovers and should be removed later.
- */
-XPCOMUtils.defineLazyGetter(DownloadsCommon, "useJSTransfer", function () {
- return true;
-});
-
-////////////////////////////////////////////////////////////////////////////////
-//// DownloadsData
-
-/**
- * Retrieves the list of past and completed downloads from the underlying
- * Download Manager data, and provides asynchronous notifications allowing to
- * build a consistent view of the available data.
- *
- * This object responds to real-time changes in the underlying Download Manager
- * data. For example, the deletion of one or more downloads is notified through
- * the nsIObserver interface, while any state or progress change is notified
- * through the nsIDownloadProgressListener interface.
- *
- * Note that using this object does not automatically start the Download Manager
- * service. Consumers will see an empty list of downloads until the service is
- * actually started. This is useful to display a neutral progress indicator in
- * the main browser window until the autostart timeout elapses.
- *
- * Note that DownloadsData and PrivateDownloadsData are two equivalent singleton
- * objects, one accessing non-private downloads, and the other accessing private
- * ones.
- */
-function DownloadsDataCtor(aPrivate) {
- this._isPrivate = aPrivate;
-
- // Contains all the available Download objects and their integer state.
- this.oldDownloadStates = new Map();
-
- // Array of view objects that should be notified when the available download
- // data changes.
- this._views = [];
-}
-
-DownloadsDataCtor.prototype = {
- /**
- * Starts receiving events for current downloads.
- */
- initializeDataLink() {
- if (!this._dataLinkInitialized) {
- let promiseList = Downloads.getList(this._isPrivate ? Downloads.PRIVATE
- : Downloads.PUBLIC);
- promiseList.then(list => list.addView(this)).then(null, Cu.reportError);
- this._dataLinkInitialized = true;
- }
- },
- _dataLinkInitialized: false,
-
- /**
- * Stops receiving events for current downloads and cancels any pending read.
- */
- terminateDataLink: function DD_terminateDataLink()
- {
- Cu.reportError("terminateDataLink not applicable with JS Transfers");
- return;
- },
-
- /**
- * Iterator for all the available Download objects. This is empty until the
- * data has been loaded using the JavaScript API for downloads.
- */
- get downloads() this.oldDownloadStates.keys(),
-
- /**
- * True if there are finished downloads that can be removed from the list.
- */
- get canRemoveFinished()
- {
- for (let download of this.downloads) {
- // Stopped, paused, and failed downloads with partial data are removed.
- if (download.stopped && !(download.canceled && download.hasPartialData)) {
- return true;
- }
- }
- return false;
- },
-
- /**
- * Asks the back-end to remove finished downloads from the list.
- */
- removeFinished: function DD_removeFinished()
- {
- let promiseList = Downloads.getList(this._isPrivate ? Downloads.PRIVATE
- : Downloads.PUBLIC);
- promiseList.then(list => list.removeFinished())
- .then(null, Cu.reportError);
- },
-
- //////////////////////////////////////////////////////////////////////////////
- //// Integration with the asynchronous Downloads back-end
-
- onDownloadAdded(download) {
- // Download objects do not store the end time of downloads, as the Downloads
- // API does not need to persist this information for all platforms. Once a
- // download terminates on a Desktop browser, it becomes a history download,
- // for which the end time is stored differently, as a Places annotation.
- download.endTime = Date.now();
-
- this.oldDownloadStates.set(download,
- DownloadsCommon.stateOfDownload(download));
-
- for (let view of this._views) {
- view.onDownloadAdded(download, true);
- }
- },
-
- onDownloadChanged(download) {
- let oldState = this.oldDownloadStates.get(download);
- let newState = DownloadsCommon.stateOfDownload(download);
- this.oldDownloadStates.set(download, newState);
-
- if (oldState != newState) {
- if (download.succeeded ||
- (download.canceled && !download.hasPartialData) ||
- download.error) {
- // Store the end time that may be displayed by the views.
- download.endTime = Date.now();
-
- // This state transition code should actually be located in a Downloads
- // API module (bug 941009). Moreover, the fact that state is stored as
- // annotations should be ideally hidden behind methods of
- // nsIDownloadHistory (bug 830415).
- if (!this._isPrivate) {
- try {
- let downloadMetaData = {
- state: DownloadsCommon.stateOfDownload(download),
- endTime: download.endTime,
- };
- if (download.succeeded) {
- downloadMetaData.fileSize = download.target.size;
- }
-
- PlacesUtils.annotations.setPageAnnotation(
- NetUtil.newURI(download.source.url),
- "downloads/metaData",
- JSON.stringify(downloadMetaData), 0,
- PlacesUtils.annotations.EXPIRE_WITH_HISTORY);
- } catch (ex) {
- Cu.reportError(ex);
- }
- }
- }
-
- for (let view of this._views) {
- try {
- view.onDownloadStateChanged(download);
- } catch (ex) {
- Cu.reportError(ex);
- }
- }
-
- if (download.succeeded ||
- (download.error && download.error.becauseBlocked)) {
- this._notifyDownloadEvent("finish");
- }
- }
-
- if (!download.newDownloadNotified) {
- download.newDownloadNotified = true;
- this._notifyDownloadEvent("start");
- }
-
- for (let view of this._views) {
- view.onDownloadChanged(download);
- }
- },
-
- onDownloadRemoved(download) {
- this.oldDownloadStates.delete(download);
-
- for (let view of this._views) {
- view.onDownloadRemoved(download);
- }
- },
-
- //////////////////////////////////////////////////////////////////////////////
- //// Registration of views
-
- /**
- * Adds an object to be notified when the available download data changes.
- * The specified object is initialized with the currently available downloads.
- *
- * @param aView
- * DownloadsView object to be added. This reference must be passed to
- * removeView before termination.
- */
- addView: function DD_addView(aView)
- {
- this._views.push(aView);
- this._updateView(aView);
- },
-
- /**
- * Removes an object previously added using addView.
- *
- * @param aView
- * DownloadsView object to be removed.
- */
- removeView: function DD_removeView(aView)
- {
- let index = this._views.indexOf(aView);
- if (index != -1) {
- this._views.splice(index, 1);
- }
- },
-
- /**
- * Ensures that the currently loaded data is added to the specified view.
- *
- * @param aView
- * DownloadsView object to be initialized.
- */
- _updateView: function DD_updateView(aView)
- {
- // Indicate to the view that a batch loading operation is in progress.
- aView.onDataLoadStarting();
-
- // Sort backwards by start time, ensuring that the most recent
- // downloads are added first regardless of their state.
- // Tycho:
- //let loadedItemsArray = [dataItem
- // for each (dataItem in this.dataItems)
- // if (dataItem)];
- let downloadsArray = [...this.downloads];
- downloadsArray.sort((a, b) => b.startTime - a.startTime);
- downloadsArray.forEach(download => aView.onDownloadAdded(download, false));
-
- // Notify the view that all data is available unless loading is in progress.
- if (!this._pendingStatement) {
- aView.onDataLoadCompleted();
- }
- },
-
- //////////////////////////////////////////////////////////////////////////////
- //// In-memory downloads data store
-
- /**
- * Clears the loaded data.
- */
- clear: function DD_clear()
- {
- this._terminateDataAccess();
- this.dataItems = {};
- },
-
- /**
- * Returns the data item associated with the provided source object. The
- * source can be a download object that we received from the Download Manager
- * because of a real-time notification, or a row from the downloads database,
- * during the asynchronous data load.
- *
- * In case we receive download status notifications while we are still
- * populating the list of downloads from the database, we want the real-time
- * status to take precedence over the state that is read from the database,
- * which might be older. This is achieved by creating the download item if
- * it's not already in the list, but never updating the returned object using
- * the data from the database, if the object already exists.
- *
- * @param aSource
- * Object containing the data with which the item should be initialized
- * if it doesn't already exist in the list. This should implement
- * either nsIDownload or mozIStorageRow. If the item exists, this
- * argument is only used to retrieve the download identifier.
- * @param aMayReuseGUID
- * If false, indicates that the download should not be added if a
- * download with the same identifier was removed in the meantime. This
- * ensures that, while loading the list asynchronously, downloads that
- * have been removed in the meantime do no reappear inadvertently.
- *
- * @return New or existing data item, or null if the item was deleted from the
- * list of available downloads.
- */
- _getOrAddDataItem: function DD_getOrAddDataItem(aSource, aMayReuseGUID)
- {
- let downloadGuid = (aSource instanceof Ci.nsIDownload)
- ? aSource.guid
- : aSource.getResultByName("guid");
- if (downloadGuid in this.dataItems) {
- let existingItem = this.dataItems[downloadGuid];
- if (existingItem || !aMayReuseGUID) {
- // Returns null if the download was removed and we can't reuse the item.
- return existingItem;
- }
- }
- DownloadsCommon.log("Creating a new DownloadsDataItem with downloadGuid =",
- downloadGuid);
- let dataItem = new DownloadsDataItem(aSource);
- this.dataItems[downloadGuid] = dataItem;
-
- // Create the view items before returning.
- let addToStartOfList = aSource instanceof Ci.nsIDownload;
- this._views.forEach(
- function (view) view.onDataItemAdded(dataItem, addToStartOfList)
- );
- return dataItem;
- },
-
- /**
- * Removes the data item with the specified identifier.
- *
- * This method can be called at most once per download identifier.
- */
- _removeDataItem: function DD_removeDataItem(aDownloadId)
- {
- if (aDownloadId in this.dataItems) {
- let dataItem = this.dataItems[aDownloadId];
- this.dataItems[aDownloadId] = null;
- this._views.forEach(
- function (view) view.onDataItemRemoved(dataItem)
- );
- }
- },
-
- //////////////////////////////////////////////////////////////////////////////
- //// Persistent data loading
-
- /**
- * Represents an executing statement, allowing its cancellation.
- */
- _pendingStatement: null,
-
- /**
- * Indicates which kind of items from the persistent downloads database have
- * been fully loaded in memory and are available to the views. This can
- * assume the value of one of the kLoad constants.
- */
- _loadState: 0,
-
- /** No downloads have been fully loaded yet. */
- get kLoadNone() 0,
- /** All the active downloads in the database are loaded in memory. */
- get kLoadActive() 1,
- /** All the downloads in the database are loaded in memory. */
- get kLoadAll() 2,
-
- /**
- * Reloads the specified kind of downloads from the persistent database. This
- * method must only be called when Private Browsing Mode is disabled.
- *
- * @param aActiveOnly
- * True to load only active downloads from the database.
- */
- ensurePersistentDataLoaded:
- function DD_ensurePersistentDataLoaded(aActiveOnly)
- {
- if (this == PrivateDownloadsData) {
- Cu.reportError("ensurePersistentDataLoaded should not be called on PrivateDownloadsData");
- return;
- }
-
- if (this._pendingStatement) {
- // We are already in the process of reloading all downloads.
- return;
- }
-
- if (aActiveOnly) {
- if (this._loadState == this.kLoadNone) {
- DownloadsCommon.log("Loading only active downloads from the persistence database");
- // Indicate to the views that a batch loading operation is in progress.
- this._views.forEach(
- function (view) view.onDataLoadStarting()
- );
-
- // Reload the list using the Download Manager service. The list is
- // returned in no particular order.
- let downloads = Services.downloads.activeDownloads;
- while (downloads.hasMoreElements()) {
- let download = downloads.getNext().QueryInterface(Ci.nsIDownload);
- this._getOrAddDataItem(download, true);
- }
- this._loadState = this.kLoadActive;
-
- // Indicate to the views that the batch loading operation is complete.
- this._views.forEach(
- function (view) view.onDataLoadCompleted()
- );
- DownloadsCommon.log("Active downloads done loading.");
- }
- } else {
- if (this._loadState != this.kLoadAll) {
- // Load only the relevant columns from the downloads database. The
- // columns are read in the _initFromDataRow method of DownloadsDataItem.
- // Order by descending download identifier so that the most recent
- // downloads are notified first to the listening views.
- DownloadsCommon.log("Loading all downloads from the persistence database.");
- let dbConnection = Services.downloads.DBConnection;
- let statement = dbConnection.createAsyncStatement(
- "SELECT guid, target, name, source, referrer, state, "
- + "startTime, endTime, currBytes, maxBytes "
- + "FROM moz_downloads "
- + "ORDER BY startTime DESC"
- );
- try {
- this._pendingStatement = statement.executeAsync(this);
- } finally {
- statement.finalize();
- }
- }
- }
- },
-
- /**
- * Cancels any pending data access and ensures views are notified.
- */
- _terminateDataAccess: function DD_terminateDataAccess()
- {
- if (this._pendingStatement) {
- this._pendingStatement.cancel();
- this._pendingStatement = null;
- }
-
- // Close all the views on the current data. Create a copy of the array
- // because some views might unregister while processing this event.
- Array.slice(this._views, 0).forEach(
- function (view) view.onDataInvalidated()
- );
- },
-
- //////////////////////////////////////////////////////////////////////////////
- //// mozIStorageStatementCallback
-
- handleResult: function DD_handleResult(aResultSet)
- {
- for (let row = aResultSet.getNextRow();
- row;
- row = aResultSet.getNextRow()) {
- // Add the download to the list and initialize it with the data we read,
- // unless we already received a notification providing more reliable
- // information for this download.
- this._getOrAddDataItem(row, false);
- }
- },
-
- handleError: function DD_handleError(aError)
- {
- DownloadsCommon.error("Database statement execution error (",
- aError.result, "): ", aError.message);
- },
-
- handleCompletion: function DD_handleCompletion(aReason)
- {
- DownloadsCommon.log("Loading all downloads from database completed with reason:",
- aReason);
- this._pendingStatement = null;
-
- // To ensure that we don't inadvertently delete more downloads from the
- // database than needed on shutdown, we should update the load state only if
- // the operation completed successfully.
- if (aReason == Ci.mozIStorageStatementCallback.REASON_FINISHED) {
- this._loadState = this.kLoadAll;
- }
-
- // Indicate to the views that the batch loading operation is complete, even
- // if the lookup failed or was canceled. The only possible glitch happens
- // in case the database backend changes while loading data, when the views
- // would open and immediately close. This case is rare enough not to need a
- // special treatment.
- this._views.forEach(
- function (view) view.onDataLoadCompleted()
- );
- },
-
- //////////////////////////////////////////////////////////////////////////////
- //// nsIObserver
-
- observe: function DD_observe(aSubject, aTopic, aData)
- {
- switch (aTopic) {
- case "download-manager-remove-download-guid":
- // If a single download was removed, remove the corresponding data item.
- if (aSubject) {
- let downloadGuid = aSubject.QueryInterface(Ci.nsISupportsCString).data;
- DownloadsCommon.log("A single download with id",
- downloadGuid, "was removed.");
- this._removeDataItem(downloadGuid);
- break;
- }
-
- // Multiple downloads have been removed. Iterate over known downloads
- // and remove those that don't exist anymore.
- DownloadsCommon.log("Multiple downloads were removed.");
- for each (let dataItem in this.dataItems) {
- if (dataItem) {
- // Bug 449811 - We have to bind to the dataItem because Javascript
- // doesn't do fresh let-bindings per loop iteration.
- let dataItemBinding = dataItem;
- Services.downloads.getDownloadByGUID(dataItemBinding.downloadGuid,
- function(aStatus, aResult) {
- if (aStatus == Components.results.NS_ERROR_NOT_AVAILABLE) {
- DownloadsCommon.log("Removing download with id",
- dataItemBinding.downloadGuid);
- this._removeDataItem(dataItemBinding.downloadGuid);
- }
- }.bind(this));
- }
- }
- break;
- }
- },
-
- //////////////////////////////////////////////////////////////////////////////
- //// nsIDownloadProgressListener
-
- onDownloadStateChange: function DD_onDownloadStateChange(aOldState, aDownload)
- {
- if (aDownload.isPrivate != this._isPrivate) {
- // Ignore the downloads with a privacy status other than what we are
- // tracking.
- return;
- }
-
- // When a new download is added, it may have the same identifier of a
- // download that we previously deleted during this session, and we also
- // want to provide a visible indication that the download started.
- let isNew = aOldState == nsIDM.DOWNLOAD_NOTSTARTED ||
- aOldState == nsIDM.DOWNLOAD_QUEUED;
-
- let dataItem = this._getOrAddDataItem(aDownload, isNew);
- if (!dataItem) {
- return;
- }
-
- let wasInProgress = dataItem.inProgress;
-
- DownloadsCommon.log("A download changed its state to:", aDownload.state);
- dataItem.state = aDownload.state;
- dataItem.referrer = aDownload.referrer && aDownload.referrer.spec;
- dataItem.resumable = aDownload.resumable;
- dataItem.startTime = Math.round(aDownload.startTime / 1000);
- dataItem.currBytes = aDownload.amountTransferred;
- dataItem.maxBytes = aDownload.size;
-
- if (wasInProgress && !dataItem.inProgress) {
- dataItem.endTime = Date.now();
- }
-
- // When a download is retried, we create a different download object from
- // the database with the same ID as before. This means that the nsIDownload
- // that the dataItem holds might now need updating.
- //
- // We only overwrite this in the event that _download exists, because if it
- // doesn't, that means that no caller ever tried to get the nsIDownload,
- // which means it was never retrieved and doesn't need to be overwritten.
- if (dataItem._download) {
- dataItem._download = aDownload;
- }
-
- for (let view of this._views) {
- try {
- view.getViewItem(dataItem).onStateChange(aOldState);
- } catch (ex) {
- Cu.reportError(ex);
- }
- }
-
- if (isNew && !dataItem.newDownloadNotified) {
- dataItem.newDownloadNotified = true;
- this._notifyDownloadEvent("start");
- }
-
- // This is a final state of which we are only notified once.
- if (dataItem.done) {
- this._notifyDownloadEvent("finish");
- }
-
- // TODO Bug 830415: this isn't the right place to set these annotation.
- // It should be set it in places' nsIDownloadHistory implementation.
- if (!this._isPrivate && !dataItem.inProgress) {
- let downloadMetaData = { state: dataItem.state,
- endTime: dataItem.endTime };
- if (dataItem.done)
- downloadMetaData.fileSize = dataItem.maxBytes;
-
- try {
- PlacesUtils.annotations.setPageAnnotation(
- NetUtil.newURI(dataItem.uri), "downloads/metaData", JSON.stringify(downloadMetaData), 0,
- PlacesUtils.annotations.EXPIRE_WITH_HISTORY);
- }
- catch(ex) {
- Cu.reportError(ex);
- }
- }
- },
-
- onProgressChange: function DD_onProgressChange(aWebProgress, aRequest,
- aCurSelfProgress,
- aMaxSelfProgress,
- aCurTotalProgress,
- aMaxTotalProgress, aDownload)
- {
- if (aDownload.isPrivate != this._isPrivate) {
- // Ignore the downloads with a privacy status other than what we are
- // tracking.
- return;
- }
-
- let dataItem = this._getOrAddDataItem(aDownload, false);
- if (!dataItem) {
- return;
- }
-
- dataItem.currBytes = aDownload.amountTransferred;
- dataItem.maxBytes = aDownload.size;
- dataItem.speed = aDownload.speed;
- dataItem.percentComplete = aDownload.percentComplete;
-
- this._views.forEach(
- function (view) view.getViewItem(dataItem).onProgressChange()
- );
- },
-
- onStateChange: function () { },
-
- onSecurityChange: function () { },
-
- //////////////////////////////////////////////////////////////////////////////
- //// Notifications sent to the most recent browser window only
-
- /**
- * Set to true after the first download causes the downloads panel to be
- * displayed.
- */
- get panelHasShownBefore() {
- try {
- return Services.prefs.getBoolPref("browser.download.panel.shown");
- } catch (ex) { }
- return false;
- },
-
- set panelHasShownBefore(aValue) {
- Services.prefs.setBoolPref("browser.download.panel.shown", aValue);
- return aValue;
- },
-
- /**
- * Displays a new or finished download notification in the most recent browser
- * window, if one is currently available with the required privacy type.
- *
- * @param aType
- * Set to "start" for new downloads, "finish" for completed downloads.
- */
- _notifyDownloadEvent: function DD_notifyDownloadEvent(aType)
- {
- DownloadsCommon.log("Attempting to notify that a new download has started or finished.");
- if (DownloadsCommon.useToolkitUI) {
- DownloadsCommon.log("Cancelling notification - we're using the toolkit downloads manager.");
- return;
- }
-
- // Show the panel in the most recent browser window, if present.
- let browserWin = RecentWindow.getMostRecentBrowserWindow({ private: this._isPrivate });
- if (!browserWin) {
- return;
- }
-
- if (this.panelHasShownBefore) {
- // For new downloads after the first one, don't show the panel
- // automatically, but provide a visible notification in the topmost
- // browser window, if the status indicator is already visible.
- DownloadsCommon.log("Showing new download notification.");
- browserWin.DownloadsIndicatorView.showEventNotification(aType);
- return;
- }
- this.panelHasShownBefore = true;
- browserWin.DownloadsPanel.showPanel();
- }
-};
-
-XPCOMUtils.defineLazyGetter(this, "PrivateDownloadsData", function() {
- return new DownloadsDataCtor(true);
-});
-
-XPCOMUtils.defineLazyGetter(this, "DownloadsData", function() {
- return new DownloadsDataCtor(false);
-});
-
-////////////////////////////////////////////////////////////////////////////////
-//// DownloadsViewPrototype
-
-/**
- * A prototype for an object that registers itself with DownloadsData as soon
- * as a view is registered with it.
- */
-const DownloadsViewPrototype = {
- //////////////////////////////////////////////////////////////////////////////
- //// Registration of views
-
- /**
- * Array of view objects that should be notified when the available status
- * data changes.
- *
- * SUBCLASSES MUST OVERRIDE THIS PROPERTY.
- */
- _views: null,
-
- /**
- * Determines whether this view object is over the private or non-private
- * downloads.
- *
- * SUBCLASSES MUST OVERRIDE THIS PROPERTY.
- */
- _isPrivate: false,
-
- /**
- * Adds an object to be notified when the available status data changes.
- * The specified object is initialized with the currently available status.
- *
- * @param aView
- * View object to be added. This reference must be
- * passed to removeView before termination.
- */
- addView: function DVP_addView(aView)
- {
- // Start receiving events when the first of our views is registered.
- if (this._views.length == 0) {
- if (this._isPrivate) {
- PrivateDownloadsData.addView(this);
- } else {
- DownloadsData.addView(this);
- }
- }
-
- this._views.push(aView);
- this.refreshView(aView);
- },
-
- /**
- * Updates the properties of an object previously added using addView.
- *
- * @param aView
- * View object to be updated.
- */
- refreshView: function DVP_refreshView(aView)
- {
- // Update immediately even if we are still loading data asynchronously.
- // Subclasses must provide these two functions!
- this._refreshProperties();
- this._updateView(aView);
- },
-
- /**
- * Removes an object previously added using addView.
- *
- * @param aView
- * View object to be removed.
- */
- removeView: function DVP_removeView(aView)
- {
- let index = this._views.indexOf(aView);
- if (index != -1) {
- this._views.splice(index, 1);
- }
-
- // Stop receiving events when the last of our views is unregistered.
- if (this._views.length == 0) {
- if (this._isPrivate) {
- PrivateDownloadsData.removeView(this);
- } else {
- DownloadsData.removeView(this);
- }
- }
- },
-
- //////////////////////////////////////////////////////////////////////////////
- //// Callback functions from DownloadsData
-
- /**
- * Indicates whether we are still loading downloads data asynchronously.
- */
- _loading: false,
-
- /**
- * Called before multiple downloads are about to be loaded.
- */
- onDataLoadStarting: function DVP_onDataLoadStarting()
- {
- this._loading = true;
- },
-
- /**
- * Called after data loading finished.
- */
- onDataLoadCompleted: function DVP_onDataLoadCompleted()
- {
- this._loading = false;
- },
-
- /**
- * Called when the downloads database becomes unavailable (for example, we
- * entered Private Browsing Mode and the database backend changed).
- * References to existing data should be discarded.
- *
- * @note Subclasses should override this.
- */
- onDataInvalidated: function DVP_onDataInvalidated()
- {
- throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
- },
-
- /**
- * Called when a new download data item is available, either during the
- * asynchronous data load or when a new download is started.
- *
- * @param download
- * Download object that was just added.
- * @param newest
- * When true, indicates that this item is the most recent and should be
- * added in the topmost position. This happens when a new download is
- * started. When false, indicates that the item is the least recent
- * with regard to the items that have been already added. The latter
- * generally happens during the asynchronous data load.
- *
- * @note Subclasses should override this.
- */
- onDownloadAdded(download, newest) {
- throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
- },
-
- /**
- * Called when the overall state of a Download has changed. In particular,
- * this is called only once when the download succeeds or is blocked
- * permanently, and is never called if only the current progress changed.
- *
- * The onDownloadChanged notification will always be sent afterwards.
- *
- * @note Subclasses should override this.
- */
- onDownloadStateChanged(download) {
- throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
- },
-
- /**
- * Called every time any state property of a Download may have changed,
- * including progress properties.
- *
- * Note that progress notification changes are throttled at the Downloads.jsm
- * API level, and there is no throttling mechanism in the front-end.
- *
- * @note Subclasses should override this.
- */
- onDownloadChanged(download) {
- throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
- },
-
- /**
- * Called when a data item is removed, ensures that the widget associated with
- * the view item is removed from the user interface.
- *
- * @param download
- * Download object that is being removed.
- *
- * @note Subclasses should override this.
- */
- onDownloadRemoved(download) {
- throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
- },
-
- /**
- * Private function used to refresh the internal properties being sent to
- * each registered view.
- *
- * @note Subclasses should override this.
- */
- _refreshProperties: function DID_refreshProperties()
- {
- throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
- },
-
- /**
- * Private function used to refresh an individual view.
- *
- * @note Subclasses should override this.
- */
- _updateView: function DID_updateView()
- {
- throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
- }
-};
-
-////////////////////////////////////////////////////////////////////////////////
-//// DownloadsIndicatorData
-
-/**
- * This object registers itself with DownloadsData as a view, and transforms the
- * notifications it receives into overall status data, that is then broadcast to
- * the registered download status indicators.
- *
- * Note that using this object does not automatically start the Download Manager
- * service. Consumers will see an empty list of downloads until the service is
- * actually started. This is useful to display a neutral progress indicator in
- * the main browser window until the autostart timeout elapses.
- */
-function DownloadsIndicatorDataCtor(aPrivate) {
- this._isPrivate = aPrivate;
- this._views = [];
-}
-DownloadsIndicatorDataCtor.prototype = {
- __proto__: DownloadsViewPrototype,
-
- /**
- * Removes an object previously added using addView.
- *
- * @param aView
- * DownloadsIndicatorView object to be removed.
- */
- removeView: function DID_removeView(aView)
- {
- DownloadsViewPrototype.removeView.call(this, aView);
-
- if (this._views.length == 0) {
- this._itemCount = 0;
- }
- },
-
- //////////////////////////////////////////////////////////////////////////////
- //// Callback functions from DownloadsData
-
- onDataLoadCompleted: function DID_onDataLoadCompleted()
- {
- DownloadsViewPrototype.onDataLoadCompleted.call(this);
- this._updateViews();
- },
-
- /**
- * Called when the downloads database becomes unavailable (for example, we
- * entered Private Browsing Mode and the database backend changed).
- * References to existing data should be discarded.
- */
- onDataInvalidated: function DID_onDataInvalidated()
- {
- this._itemCount = 0;
- },
-
- onDownloadAdded(download, newest) {
- this._itemCount++;
- this._updateViews();
- },
-
- onDownloadStateChanged(download) {
- if (download.succeeded || download.error) {
- this.attention = true;
- }
-
- // Since the state of a download changed, reset the estimated time left.
- this._lastRawTimeLeft = -1;
- this._lastTimeLeft = -1;
- },
-
- onDownloadChanged(download) {
- this._updateViews();
- },
-
- onDownloadRemoved(download) {
- this._itemCount--;
- this._updateViews();
- },
-
- //////////////////////////////////////////////////////////////////////////////
- //// Propagation of properties to our views
-
- // The following properties are updated by _refreshProperties and are then
- // propagated to the views. See _refreshProperties for details.
- _hasDownloads: false,
- _counter: "",
- _percentComplete: -1,
- _paused: false,
-
- /**
- * Indicates whether the download indicators should be highlighted.
- */
- set attention(aValue)
- {
- this._attention = aValue;
- this._updateViews();
- return aValue;
- },
- _attention: false,
-
- /**
- * Indicates whether the user is interacting with downloads, thus the
- * attention indication should not be shown even if requested.
- */
- set attentionSuppressed(aValue)
- {
- this._attentionSuppressed = aValue;
- this._attention = false;
- this._updateViews();
- return aValue;
- },
- _attentionSuppressed: false,
-
- /**
- * Computes aggregate values and propagates the changes to our views.
- */
- _updateViews: function DID_updateViews()
- {
- // Do not update the status indicators during batch loads of download items.
- if (this._loading) {
- return;
- }
-
- this._refreshProperties();
- this._views.forEach(this._updateView, this);
- },
-
- /**
- * Updates the specified view with the current aggregate values.
- *
- * @param aView
- * DownloadsIndicatorView object to be updated.
- */
- _updateView: function DID_updateView(aView)
- {
- aView.hasDownloads = this._hasDownloads;
- aView.counter = this._counter;
- aView.percentComplete = this._percentComplete;
- aView.paused = this._paused;
- aView.attention = this._attention && !this._attentionSuppressed;
- },
-
- //////////////////////////////////////////////////////////////////////////////
- //// Property updating based on current download status
-
- /**
- * Number of download items that are available to be displayed.
- */
- _itemCount: 0,
-
- /**
- * Floating point value indicating the last number of seconds estimated until
- * the longest download will finish. We need to store this value so that we
- * don't continuously apply smoothing if the actual download state has not
- * changed. This is set to -1 if the previous value is unknown.
- */
- _lastRawTimeLeft: -1,
-
- /**
- * Last number of seconds estimated until all in-progress downloads with a
- * known size and speed will finish. This value is stored to allow smoothing
- * in case of small variations. This is set to -1 if the previous value is
- * unknown.
- */
- _lastTimeLeft: -1,
-
- /**
- * A generator function for the Download objects this summary is currently
- * interested in. This generator is passed off to summarizeDownloads in order
- * to generate statistics about the downloads we care about - in this case,
- * it's all active downloads.
- */
- * _activeDownloads() {
- let downloads = this._isPrivate ? PrivateDownloadsData.downloads
- : DownloadsData.downloads;
- for (let download of downloads) {
- if (!download.stopped || (download.canceled && download.hasPartialData)) {
- yield download;
- }
- }
- },
-
- /**
- * Computes aggregate values based on the current state of downloads.
- */
- _refreshProperties: function DID_refreshProperties()
- {
- let summary =
- DownloadsCommon.summarizeDownloads(this._activeDownloads());
-
- // Determine if the indicator should be shown or get attention.
- this._hasDownloads = (this._itemCount > 0);
-
- // If all downloads are paused, show the progress indicator as paused.
- this._paused = summary.numActive > 0 &&
- summary.numActive == summary.numPaused;
-
- this._percentComplete = summary.percentComplete;
-
- // Display the estimated time left, if present.
- if (summary.rawTimeLeft == -1) {
- // There are no downloads with a known time left.
- this._lastRawTimeLeft = -1;
- this._lastTimeLeft = -1;
- this._counter = "";
- } else {
- // Compute the new time left only if state actually changed.
- if (this._lastRawTimeLeft != summary.rawTimeLeft) {
- this._lastRawTimeLeft = summary.rawTimeLeft;
- this._lastTimeLeft = DownloadsCommon.smoothSeconds(summary.rawTimeLeft,
- this._lastTimeLeft);
- }
- this._counter = DownloadsCommon.formatTimeLeft(this._lastTimeLeft);
- }
- }
-};
-
-XPCOMUtils.defineLazyGetter(this, "PrivateDownloadsIndicatorData", function() {
- return new DownloadsIndicatorDataCtor(true);
-});
-
-XPCOMUtils.defineLazyGetter(this, "DownloadsIndicatorData", function() {
- return new DownloadsIndicatorDataCtor(false);
-});
-
-////////////////////////////////////////////////////////////////////////////////
-//// DownloadsSummaryData
-
-/**
- * DownloadsSummaryData is a view for DownloadsData that produces a summary
- * of all downloads after a certain exclusion point aNumToExclude. For example,
- * if there were 5 downloads in progress, and a DownloadsSummaryData was
- * constructed with aNumToExclude equal to 3, then that DownloadsSummaryData
- * would produce a summary of the last 2 downloads.
- *
- * @param aIsPrivate
- * True if the browser window which owns the download button is a private
- * window.
- * @param aNumToExclude
- * The number of items to exclude from the summary, starting from the
- * top of the list.
- */
-function DownloadsSummaryData(aIsPrivate, aNumToExclude) {
- this._numToExclude = aNumToExclude;
- // Since we can have multiple instances of DownloadsSummaryData, we
- // override these values from the prototype so that each instance can be
- // completely separated from one another.
- this._loading = false;
-
- this._downloads = [];
-
- // Floating point value indicating the last number of seconds estimated until
- // the longest download will finish. We need to store this value so that we
- // don't continuously apply smoothing if the actual download state has not
- // changed. This is set to -1 if the previous value is unknown.
- this._lastRawTimeLeft = -1;
-
- // Last number of seconds estimated until all in-progress downloads with a
- // known size and speed will finish. This value is stored to allow smoothing
- // in case of small variations. This is set to -1 if the previous value is
- // unknown.
- this._lastTimeLeft = -1;
-
- // The following properties are updated by _refreshProperties and are then
- // propagated to the views.
- this._showingProgress = false;
- this._details = "";
- this._description = "";
- this._numActive = 0;
- this._percentComplete = -1;
-
- this._isPrivate = aIsPrivate;
- this._views = [];
-}
-
-DownloadsSummaryData.prototype = {
- __proto__: DownloadsViewPrototype,
-
- /**
- * Removes an object previously added using addView.
- *
- * @param aView
- * DownloadsSummary view to be removed.
- */
- removeView: function DSD_removeView(aView)
- {
- DownloadsViewPrototype.removeView.call(this, aView);
-
- if (this._views.length == 0) {
- // Clear out our collection of Download objects. If we ever have
- // another view registered with us, this will get re-populated.
- this._downloads = [];
- }
- },
-
- //////////////////////////////////////////////////////////////////////////////
- //// Callback functions from DownloadsData - see the documentation in
- //// DownloadsViewPrototype for more information on what these functions
- //// are used for.
-
- onDataLoadCompleted: function DSD_onDataLoadCompleted()
- {
- DownloadsViewPrototype.onDataLoadCompleted.call(this);
- this._updateViews();
- },
-
- onDataInvalidated: function DSD_onDataInvalidated()
- {
- this._dataItems = [];
- },
-
- onDownloadAdded(download, newest) {
- if (newest) {
- this._downloads.unshift(download);
- } else {
- this._downloads.push(download);
- }
-
- this._updateViews();
- },
-
- onDownloadStateChanged() {
- // Since the state of a download changed, reset the estimated time left.
- this._lastRawTimeLeft = -1;
- this._lastTimeLeft = -1;
- },
-
- onDownloadChanged() {
- this._updateViews();
- },
-
- onDownloadRemoved(download) {
- let itemIndex = this._downloads.indexOf(download);
- this._downloads.splice(itemIndex, 1);
- this._updateViews();
- },
-
- //////////////////////////////////////////////////////////////////////////////
- //// Propagation of properties to our views
-
- /**
- * Computes aggregate values and propagates the changes to our views.
- */
- _updateViews: function DSD_updateViews()
- {
- // Do not update the status indicators during batch loads of download items.
- if (this._loading) {
- return;
- }
-
- this._refreshProperties();
- this._views.forEach(this._updateView, this);
- },
-
- /**
- * Updates the specified view with the current aggregate values.
- *
- * @param aView
- * DownloadsIndicatorView object to be updated.
- */
- _updateView: function DSD_updateView(aView)
- {
- aView.showingProgress = this._showingProgress;
- aView.percentComplete = this._percentComplete;
- aView.description = this._description;
- aView.details = this._details;
- },
-
- //////////////////////////////////////////////////////////////////////////////
- //// Property updating based on current download status
-
- /**
- * A generator function for the Download objects this summary is currently
- * interested in. This generator is passed off to summarizeDownloads in order
- * to generate statistics about the downloads we care about - in this case,
- * it's the downloads in this._downloads after the first few to exclude,
- * which was set when constructing this DownloadsSummaryData instance.
- */
- * _downloadsForSummary() {
- if (this._downloads.length > 0) {
- for (let i = this._numToExclude; i < this._downloads.length; ++i) {
- yield this._downloads[i];
- }
- }
- },
-
- /**
- * Computes aggregate values based on the current state of downloads.
- */
- _refreshProperties: function DSD_refreshProperties()
- {
- // Pre-load summary with default values.
- let summary =
- DownloadsCommon.summarizeDownloads(this._downloadsForSummary());
-
- this._description = DownloadsCommon.strings
- .otherDownloads2(summary.numActive);
- this._percentComplete = summary.percentComplete;
-
- // If all downloads are paused, show the progress indicator as paused.
- this._showingProgress = summary.numDownloading > 0 ||
- summary.numPaused > 0;
-
- // Display the estimated time left, if present.
- if (summary.rawTimeLeft == -1) {
- // There are no downloads with a known time left.
- this._lastRawTimeLeft = -1;
- this._lastTimeLeft = -1;
- this._details = "";
- } else {
- // Compute the new time left only if state actually changed.
- if (this._lastRawTimeLeft != summary.rawTimeLeft) {
- this._lastRawTimeLeft = summary.rawTimeLeft;
- this._lastTimeLeft = DownloadsCommon.smoothSeconds(summary.rawTimeLeft,
- this._lastTimeLeft);
- }
- [this._details] = DownloadUtils.getDownloadStatusNoRate(
- summary.totalTransferred, summary.totalSize, summary.slowestSpeed,
- this._lastTimeLeft);
- }
- }
-}
diff --git a/components/downloads/DownloadsLogger.jsm b/components/downloads/DownloadsLogger.jsm
deleted file mode 100644
index 1218539..0000000
--- a/components/downloads/DownloadsLogger.jsm
+++ /dev/null
@@ -1,76 +0,0 @@
-/* -*- Mode: js2; js2-basic-offset: 2; indent-tabs-mode: nil; -*- */
-/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/**
- * The contents of this file were copied almost entirely from
- * toolkit/identity/LogUtils.jsm. Until we've got a more generalized logging
- * mechanism for toolkit, I think this is going to be how we roll.
- */
-
-"use strict";
-
-this.EXPORTED_SYMBOLS = ["DownloadsLogger"];
-const PREF_DEBUG = "browser.download.debug";
-
-const Cu = Components.utils;
-const Ci = Components.interfaces;
-const Cc = Components.classes;
-const Cr = Components.results;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-
-this.DownloadsLogger = {
- _generateLogMessage: function _generateLogMessage(args) {
- // create a string representation of a list of arbitrary things
- let strings = [];
-
- for (let arg of args) {
- if (typeof arg === 'string') {
- strings.push(arg);
- } else if (arg === undefined) {
- strings.push('undefined');
- } else if (arg === null) {
- strings.push('null');
- } else {
- try {
- strings.push(JSON.stringify(arg, null, 2));
- } catch(err) {
- strings.push("<<something>>");
- }
- }
- };
- return 'Downloads: ' + strings.join(' ');
- },
-
- /**
- * log() - utility function to print a list of arbitrary things
- *
- * Enable with about:config pref browser.download.debug
- */
- log: function DL_log(...args) {
- let output = this._generateLogMessage(args);
- dump(output + "\n");
-
- // Additionally, make the output visible in the Error Console
- Services.console.logStringMessage(output);
- },
-
- /**
- * reportError() - report an error through component utils as well as
- * our log function
- */
- reportError: function DL_reportError(...aArgs) {
- // Report the error in the browser
- let output = this._generateLogMessage(aArgs);
- Cu.reportError(output);
- dump("ERROR:" + output + "\n");
- for (let frame = Components.stack.caller; frame; frame = frame.caller) {
- dump("\t" + frame + "\n");
- }
- }
-
-};
diff --git a/components/downloads/DownloadsStartup.js b/components/downloads/DownloadsStartup.js
deleted file mode 100644
index e1dd207..0000000
--- a/components/downloads/DownloadsStartup.js
+++ /dev/null
@@ -1,278 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/**
- * This component listens to notifications for startup, shutdown and session
- * restore, controlling which downloads should be loaded from the database.
- *
- * To avoid affecting startup performance, this component monitors the current
- * session restore state, but defers the actual downloads data manipulation
- * until the Download Manager service is loaded.
- */
-
-"use strict";
-
-////////////////////////////////////////////////////////////////////////////////
-//// Globals
-
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-const Cu = Components.utils;
-const Cr = Components.results;
-
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "DownloadsCommon",
- "resource:///modules/DownloadsCommon.jsm");
-XPCOMUtils.defineLazyServiceGetter(this, "gSessionStartup",
- "@mozilla.org/browser/sessionstartup;1",
- "nsISessionStartup");
-
-const kObservedTopics = [
- "sessionstore-windows-restored",
- "sessionstore-browser-state-restored",
- "download-manager-initialized",
- "download-manager-change-retention",
- "last-pb-context-exited",
- "browser-lastwindow-close-granted",
- "quit-application",
- "profile-change-teardown",
-];
-
-/**
- * CID of our implementation of nsIDownloadManagerUI.
- */
-const kDownloadsUICid = Components.ID("{4d99321e-d156-455b-81f7-e7aa2308134f}");
-
-/**
- * Contract ID of the service implementing nsIDownloadManagerUI.
- */
-const kDownloadsUIContractId = "@mozilla.org/download-manager-ui;1";
-
-/**
- * CID of the JavaScript implementation of nsITransfer.
- */
-const kTransferCid = Components.ID("{1b4c85df-cbdd-4bb6-b04e-613caece083c}");
-
-/**
- * Contract ID of the service implementing nsITransfer.
- */
-const kTransferContractId = "@mozilla.org/transfer;1";
-
-////////////////////////////////////////////////////////////////////////////////
-//// DownloadsStartup
-
-function DownloadsStartup() { }
-
-DownloadsStartup.prototype = {
- classID: Components.ID("{49507fe5-2cee-4824-b6a3-e999150ce9b8}"),
-
- _xpcom_factory: XPCOMUtils.generateSingletonFactory(DownloadsStartup),
-
- //////////////////////////////////////////////////////////////////////////////
- //// nsISupports
-
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
- Ci.nsISupportsWeakReference]),
-
- //////////////////////////////////////////////////////////////////////////////
- //// nsIObserver
-
- observe: function DS_observe(aSubject, aTopic, aData)
- {
- switch (aTopic) {
- case "profile-after-change":
- // Override Toolkit's nsIDownloadManagerUI implementation with our own.
- // This must be done at application startup and not in the manifest to
- // ensure that our implementation overrides the original one.
- Components.manager.QueryInterface(Ci.nsIComponentRegistrar)
- .registerFactory(kDownloadsUICid, "",
- kDownloadsUIContractId, null);
-
- Components.manager.QueryInterface(Ci.nsIComponentRegistrar)
- .registerFactory(kTransferCid, "",
- kTransferContractId, null);
- break;
-
- case "sessionstore-windows-restored":
- case "sessionstore-browser-state-restored":
- // Unless there is no saved session, there is a chance that we are
- // starting up after a restart or a crash. We should check the disk
- // database to see if there are completed downloads to recover and show
- // in the panel, in addition to in-progress downloads.
- if (gSessionStartup.sessionType != Ci.nsISessionStartup.NO_SESSION) {
- this._restoringSession = true;
- }
- this._ensureDataLoaded();
- break;
-
- case "download-manager-initialized":
- // Don't initialize the JavaScript data and user interface layer if we
- // are initializing the Download Manager service during shutdown.
- if (this._shuttingDown) {
- break;
- }
-
- // Start receiving events for active and new downloads before we return
- // from this observer function. We can't defer the execution of this
- // step, to ensure that we don't lose events raised in the meantime.
- DownloadsCommon.initializeAllDataLinks(
- aSubject.QueryInterface(Ci.nsIDownloadManager));
-
- this._downloadsServiceInitialized = true;
-
- // Since this notification is generated during the getService call and
- // we need to get the Download Manager service ourselves, we must post
- // the handler on the event queue to be executed later.
- Services.tm.mainThread.dispatch(this._ensureDataLoaded.bind(this),
- Ci.nsIThread.DISPATCH_NORMAL);
- break;
-
- case "download-manager-change-retention":
- // If we're using the Downloads Panel, we override the retention
- // preference to always retain downloads on completion.
- if (!DownloadsCommon.useToolkitUI) {
- aSubject.QueryInterface(Ci.nsISupportsPRInt32).data = 2;
- }
- break;
-
- case "browser-lastwindow-close-granted":
- // When using the panel interface, downloads that are already completed
- // should be removed when the last full browser window is closed. This
- // event is invoked only if the application is not shutting down yet.
- // If the Download Manager service is not initialized, we don't want to
- // initialize it just to clean up completed downloads, because they can
- // be present only in case there was a browser crash or restart.
- if (this._downloadsServiceInitialized &&
- !DownloadsCommon.useToolkitUI) {
- Services.downloads.cleanUp();
- }
- break;
-
- case "last-pb-context-exited":
- // Similar to the above notification, but for private downloads.
- if (this._downloadsServiceInitialized &&
- !DownloadsCommon.useToolkitUI) {
- Services.downloads.cleanUpPrivate();
- }
- break;
-
- case "quit-application":
- // When the application is shutting down, we must free all resources in
- // addition to cleaning up completed downloads. If the Download Manager
- // service is not initialized, we don't want to initialize it just to
- // clean up completed downloads, because they can be present only in
- // case there was a browser crash or restart.
- this._shuttingDown = true;
- if (!this._downloadsServiceInitialized) {
- break;
- }
-
- DownloadsCommon.terminateAllDataLinks();
-
- // When using the panel interface, downloads that are already completed
- // should be removed when quitting the application.
- if (!DownloadsCommon.useToolkitUI && aData != "restart") {
- this._cleanupOnShutdown = true;
- }
- break;
-
- case "profile-change-teardown":
- // If we need to clean up, we must do it synchronously after all the
- // "quit-application" listeners are invoked, so that the Download
- // Manager service has a chance to pause or cancel in-progress downloads
- // before we remove completed downloads from the list. Note that, since
- // "quit-application" was invoked, we've already exited Private Browsing
- // Mode, thus we are always working on the disk database.
- if (this._cleanupOnShutdown) {
- Services.downloads.cleanUp();
- }
-
- if (!DownloadsCommon.useToolkitUI) {
- // If we got this far, that means that we finished our first session
- // with the Downloads Panel without crashing. This means that we don't
- // have to force displaying only active downloads on the next startup
- // now.
- this._firstSessionCompleted = true;
- }
- break;
- }
- },
-
- //////////////////////////////////////////////////////////////////////////////
- //// Private
-
- /**
- * Indicates whether we're restoring a previous session. This is used by
- * _recoverAllDownloads to determine whether or not we should load and
- * display all downloads data, or restrict it to only the active downloads.
- */
- _restoringSession: false,
-
- /**
- * Indicates whether the Download Manager service has been initialized. This
- * flag is required because we want to avoid accessing the service immediately
- * at browser startup. The service will start when the user first requests a
- * download, or some time after browser startup.
- */
- _downloadsServiceInitialized: false,
-
- /**
- * True while we are processing the "quit-application" event, and later.
- */
- _shuttingDown: false,
-
- /**
- * True during shutdown if we need to remove completed downloads.
- */
- _cleanupOnShutdown: false,
-
- /**
- * True if we should display all downloads, as opposed to just active
- * downloads. We decide to display all downloads if we're restoring a session,
- * or if we're using the Downloads Panel anytime after the first session with
- * it has completed.
- */
- get _recoverAllDownloads() {
- return this._restoringSession ||
- (!DownloadsCommon.useToolkitUI && this._firstSessionCompleted);
- },
-
- /**
- * True if we've ever completed a session with the Downloads Panel enabled.
- */
- get _firstSessionCompleted() {
- return Services.prefs
- .getBoolPref("browser.download.panel.firstSessionCompleted");
- },
-
- set _firstSessionCompleted(aValue) {
- Services.prefs.setBoolPref("browser.download.panel.firstSessionCompleted",
- aValue);
- return aValue;
- },
-
- /**
- * Ensures that persistent download data is reloaded at the appropriate time.
- */
- _ensureDataLoaded: function DS_ensureDataLoaded()
- {
- if (!this._downloadsServiceInitialized) {
- return;
- }
-
- // If the previous session has been already restored, then we ensure that
- // all the downloads are loaded. Otherwise, we only ensure that the active
- // downloads from the previous session are loaded.
- DownloadsCommon.ensureAllPersistentDataLoaded(!this._recoverAllDownloads);
- }
-};
-
-////////////////////////////////////////////////////////////////////////////////
-//// Module
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([DownloadsStartup]);
diff --git a/components/downloads/DownloadsTaskbar.jsm b/components/downloads/DownloadsTaskbar.jsm
deleted file mode 100644
index cf915ab..0000000
--- a/components/downloads/DownloadsTaskbar.jsm
+++ /dev/null
@@ -1,177 +0,0 @@
-/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
-/* vim: set ts=2 et sw=2 tw=80 filetype=javascript: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/**
- * Handles the download progress indicator in the taskbar.
- */
-
-"use strict";
-
-this.EXPORTED_SYMBOLS = [
- "DownloadsTaskbar",
-];
-
-////////////////////////////////////////////////////////////////////////////////
-//// Globals
-
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-const Cu = Components.utils;
-const Cr = Components.results;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "Downloads",
- "resource://gre/modules/Downloads.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "RecentWindow",
- "resource:///modules/RecentWindow.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "Services",
- "resource://gre/modules/Services.jsm");
-
-XPCOMUtils.defineLazyGetter(this, "gWinTaskbar", function () {
- if (!("@mozilla.org/windows-taskbar;1" in Cc)) {
- return null;
- }
- let winTaskbar = Cc["@mozilla.org/windows-taskbar;1"]
- .getService(Ci.nsIWinTaskbar);
- return winTaskbar.available && winTaskbar;
-});
-
-XPCOMUtils.defineLazyGetter(this, "gMacTaskbarProgress", function () {
- return ("@mozilla.org/widget/macdocksupport;1" in Cc) &&
- Cc["@mozilla.org/widget/macdocksupport;1"]
- .getService(Ci.nsITaskbarProgress);
-});
-
-////////////////////////////////////////////////////////////////////////////////
-//// DownloadsTaskbar
-
-/**
- * Handles the download progress indicator in the taskbar.
- */
-this.DownloadsTaskbar = {
- /**
- * Underlying DownloadSummary providing the aggregate download information, or
- * null if the indicator has never been initialized.
- */
- _summary: null,
-
- /**
- * nsITaskbarProgress object to which download information is dispatched.
- * This can be null if the indicator has never been initialized or if the
- * indicator is currently hidden on Windows.
- */
- _taskbarProgress: null,
-
- /**
- * This method is called after a new browser window is opened, and ensures
- * that the download progress indicator is displayed in the taskbar.
- *
- * On Windows, the indicator is attached to the first browser window that
- * calls this method. When the window is closed, the indicator is moved to
- * another browser window, if available, in no particular order. When there
- * are no browser windows visible, the indicator is hidden.
- *
- * On Mac OS X, the indicator is initialized globally when this method is
- * called for the first time. Subsequent calls have no effect.
- *
- * @param aBrowserWindow
- * nsIDOMWindow object of the newly opened browser window to which the
- * indicator may be attached.
- */
- registerIndicator(aBrowserWindow) {
- if (!this._taskbarProgress) {
- if (gMacTaskbarProgress) {
- // On Mac OS X, we have to register the global indicator only once.
- this._taskbarProgress = gMacTaskbarProgress;
- // Free the XPCOM reference on shutdown, to prevent detecting a leak.
- Services.obs.addObserver(() => {
- this._taskbarProgress = null;
- gMacTaskbarProgress = null;
- }, "quit-application-granted", false);
- } else if (gWinTaskbar) {
- // On Windows, the indicator is currently hidden because we have no
- // previous browser window, thus we should attach the indicator now.
- this._attachIndicator(aBrowserWindow);
- } else {
- // The taskbar indicator is not available on this platform.
- return;
- }
- }
-
- // Ensure that the DownloadSummary object will be created asynchronously.
- if (!this._summary) {
- Downloads.getSummary(Downloads.ALL).then(summary => {
- // In case the method is re-entered, we simply ignore redundant
- // invocations of the callback, instead of keeping separate state.
- if (this._summary) {
- return;
- }
- this._summary = summary;
- return this._summary.addView(this);
- }).then(null, Cu.reportError);
- }
- },
-
- /**
- * On Windows, attaches the taskbar indicator to the specified browser window.
- */
- _attachIndicator(aWindow) {
- // Activate the indicator on the specified window.
- let docShell = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsIDocShellTreeItem).treeOwner
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIXULWindow).docShell;
- this._taskbarProgress = gWinTaskbar.getTaskbarProgress(docShell);
-
- // If the DownloadSummary object has already been created, we should update
- // the state of the new indicator, otherwise it will be updated as soon as
- // the DownloadSummary view is registered.
- if (this._summary) {
- this.onSummaryChanged();
- }
-
- aWindow.addEventListener("unload", () => {
- // Locate another browser window, excluding the one being closed.
- let browserWindow = RecentWindow.getMostRecentBrowserWindow();
- if (browserWindow) {
- // Move the progress indicator to the other browser window.
- this._attachIndicator(browserWindow);
- } else {
- // The last browser window has been closed. We remove the reference to
- // the taskbar progress object so that the indicator will be registered
- // again on the next browser window that is opened.
- this._taskbarProgress = null;
- }
- }, false);
- },
-
- //////////////////////////////////////////////////////////////////////////////
- //// DownloadSummary view
-
- onSummaryChanged() {
- // If the last browser window has been closed, we have no indicator any more.
- if (!this._taskbarProgress) {
- return;
- }
-
- if (this._summary.allHaveStopped || this._summary.progressTotalBytes == 0) {
- this._taskbarProgress.setProgressState(
- Ci.nsITaskbarProgress.STATE_NO_PROGRESS, 0, 0);
- } else {
- // For a brief moment before completion, some download components may
- // report more transferred bytes than the total number of bytes. Thus,
- // ensure that we never break the expectations of the progress indicator.
- let progressCurrentBytes = Math.min(this._summary.progressTotalBytes,
- this._summary.progressCurrentBytes);
- this._taskbarProgress.setProgressState(
- Ci.nsITaskbarProgress.STATE_NORMAL,
- progressCurrentBytes,
- this._summary.progressTotalBytes);
- }
- },
-};
diff --git a/components/downloads/DownloadsUI.js b/components/downloads/DownloadsUI.js
deleted file mode 100644
index afdbda8..0000000
--- a/components/downloads/DownloadsUI.js
+++ /dev/null
@@ -1,151 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/**
- * This component implements the nsIDownloadManagerUI interface and opens the
- * downloads panel in the most recent browser window when requested.
- *
- * If a specific preference is set, this component transparently forwards all
- * calls to the original implementation in Toolkit, that shows the window UI.
- */
-
-"use strict";
-
-////////////////////////////////////////////////////////////////////////////////
-//// Globals
-
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-const Cu = Components.utils;
-const Cr = Components.results;
-
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "DownloadsCommon",
- "resource:///modules/DownloadsCommon.jsm");
-XPCOMUtils.defineLazyServiceGetter(this, "gBrowserGlue",
- "@mozilla.org/browser/browserglue;1",
- "nsIBrowserGlue");
-XPCOMUtils.defineLazyModuleGetter(this, "RecentWindow",
- "resource:///modules/RecentWindow.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
- "resource://gre/modules/PrivateBrowsingUtils.jsm");
-
-////////////////////////////////////////////////////////////////////////////////
-//// DownloadsUI
-
-function DownloadsUI()
-{
- XPCOMUtils.defineLazyGetter(this, "_toolkitUI", function () {
- // Create Toolkit's nsIDownloadManagerUI implementation.
- return Components.classesByID["{7dfdf0d1-aff6-4a34-bad1-d0fe74601642}"]
- .getService(Ci.nsIDownloadManagerUI);
- });
-}
-
-DownloadsUI.prototype = {
- classID: Components.ID("{4d99321e-d156-455b-81f7-e7aa2308134f}"),
-
- _xpcom_factory: XPCOMUtils.generateSingletonFactory(DownloadsUI),
-
- //////////////////////////////////////////////////////////////////////////////
- //// nsISupports
-
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIDownloadManagerUI]),
-
- //////////////////////////////////////////////////////////////////////////////
- //// nsIDownloadManagerUI
-
- show: function DUI_show(aWindowContext, aDownload, aReason, aUsePrivateUI)
- {
- if (DownloadsCommon.useToolkitUI && !PrivateBrowsingUtils.isWindowPrivate(aWindowContext)) {
- this._toolkitUI.show(aWindowContext, aDownload, aReason, aUsePrivateUI);
- return;
- }
-
- if (!aReason) {
- aReason = Ci.nsIDownloadManagerUI.REASON_USER_INTERACTED;
- }
-
- if (aReason == Ci.nsIDownloadManagerUI.REASON_NEW_DOWNLOAD) {
- const kMinimized = Ci.nsIDOMChromeWindow.STATE_MINIMIZED;
- let browserWin = gBrowserGlue.getMostRecentBrowserWindow();
-
- if (!browserWin || browserWin.windowState == kMinimized) {
- this._showDownloadManagerUI(aWindowContext, aUsePrivateUI);
- }
- else {
- // If the indicator is visible, then new download notifications are
- // already handled by the panel service.
- browserWin.DownloadsButton.checkIsVisible(function(isVisible) {
- if (!isVisible) {
- this._showDownloadManagerUI(aWindowContext, aUsePrivateUI);
- }
- }.bind(this));
- }
- } else {
- this._showDownloadManagerUI(aWindowContext, aUsePrivateUI);
- }
- },
-
- get visible()
- {
- // If we're still using the toolkit downloads manager, delegate the call
- // to it. Otherwise, return true for now, until we decide on how we want
- // to indicate that a new download has started if a browser window is
- // not available or minimized.
- return DownloadsCommon.useToolkitUI ? this._toolkitUI.visible : true;
- },
-
- getAttention: function DUI_getAttention()
- {
- if (DownloadsCommon.useToolkitUI) {
- this._toolkitUI.getAttention();
- }
- },
-
- /**
- * Helper function that opens the download manager UI.
- */
- _showDownloadManagerUI:
- function DUI_showDownloadManagerUI(aWindowContext, aUsePrivateUI)
- {
- // If we weren't given a window context, try to find a browser window
- // to use as our parent - and if that doesn't work, error out and give up.
- let parentWindow = aWindowContext;
- if (!parentWindow) {
- parentWindow = RecentWindow.getMostRecentBrowserWindow({ private: !!aUsePrivateUI });
- if (!parentWindow) {
- Components.utils.reportError(
- "Couldn't find a browser window to open the Places Downloads View " +
- "from.");
- return;
- }
- }
-
- // If window is private then show it in a tab.
- if (PrivateBrowsingUtils.isWindowPrivate(parentWindow)) {
- parentWindow.openUILinkIn("about:downloads", "tab");
- return;
- } else {
- let organizer = Services.wm.getMostRecentWindow("Places:Organizer");
- if (!organizer) {
- parentWindow.openDialog("chrome://browser/content/places/places.xul",
- "", "chrome,toolbar=yes,dialog=no,resizable",
- "Downloads");
- } else {
- organizer.PlacesOrganizer.selectLeftPaneQuery("Downloads");
- organizer.focus();
- }
- }
- }
-};
-
-////////////////////////////////////////////////////////////////////////////////
-//// Module
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([DownloadsUI]);
diff --git a/components/downloads/DownloadsViewUI.jsm b/components/downloads/DownloadsViewUI.jsm
deleted file mode 100644
index ede593e..0000000
--- a/components/downloads/DownloadsViewUI.jsm
+++ /dev/null
@@ -1,250 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/*
- * This module is imported by code that uses the "download.xml" binding, and
- * provides prototypes for objects that handle input and display information.
- */
-
-"use strict";
-
-this.EXPORTED_SYMBOLS = [
- "DownloadsViewUI",
-];
-
-const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "DownloadUtils",
- "resource://gre/modules/DownloadUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "DownloadsCommon",
- "resource:///modules/DownloadsCommon.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "OS",
- "resource://gre/modules/osfile.jsm");
-
-this.DownloadsViewUI = {};
-
-/**
- * A download element shell is responsible for handling the commands and the
- * displayed data for a single element that uses the "download.xml" binding.
- *
- * The information to display is obtained through the associated Download object
- * from the JavaScript API for downloads, and commands are executed using a
- * combination of Download methods and DownloadsCommon.jsm helper functions.
- *
- * Specialized versions of this shell must be defined, and they are required to
- * implement the "download" property or getter. Currently these objects are the
- * HistoryDownloadElementShell and the DownloadsViewItem for the panel. The
- * history view may use a HistoryDownload object in place of a Download object.
- */
-this.DownloadsViewUI.DownloadElementShell = function () {}
-
-this.DownloadsViewUI.DownloadElementShell.prototype = {
- /**
- * The richlistitem for the download, initialized by the derived object.
- */
- element: null,
-
- /**
- * URI string for the file type icon displayed in the download element.
- */
- get image() {
- if (!this.download.target.path) {
- // Old history downloads may not have a target path.
- return "moz-icon://.unknown?size=32";
- }
-
- // When a download that was previously in progress finishes successfully, it
- // means that the target file now exists and we can extract its specific
- // icon, for example from a Windows executable. To ensure that the icon is
- // reloaded, however, we must change the URI used by the XUL image element,
- // for example by adding a query parameter. This only works if we add one of
- // the parameters explicitly supported by the nsIMozIconURI interface.
- return "moz-icon://" + this.download.target.path + "?size=32" +
- (this.download.succeeded ? "&state=normal" : "");
- },
-
- /**
- * The user-facing label for the download. This is normally the leaf name of
- * the download target file. In case this is a very old history download for
- * which the target file is unknown, the download source URI is displayed.
- */
- get displayName() {
- if (!this.download.target.path) {
- return this.download.source.url;
- }
- return OS.Path.basename(this.download.target.path);
- },
-
- get extendedDisplayName() {
- let s = DownloadsCommon.strings;
- let referrer = this.download.source.referrer ||
- this.download.source.url;
- let [displayHost, fullHost] = DownloadUtils.getURIHost(referrer);
- return s.statusSeparator(this.displayName, displayHost);
- },
-
- get extendedDisplayNameTip() {
- let s = DownloadsCommon.strings;
- let referrer = this.download.source.referrer ||
- this.download.source.url;
- let [displayHost, fullHost] = DownloadUtils.getURIHost(referrer);
- return s.statusSeparator(this.displayName, fullHost);
- },
-
- /**
- * The progress element for the download, or undefined in case the XBL binding
- * has not been applied yet.
- */
- get _progressElement() {
- if (!this.__progressElement) {
- // If the element is not available now, we will try again the next time.
- this.__progressElement =
- this.element.ownerDocument.getAnonymousElementByAttribute(
- this.element, "anonid",
- "progressmeter");
- }
- return this.__progressElement;
- },
-
- /**
- * Processes a major state change in the user interface, then proceeds with
- * the normal progress update. This function is not called for every progress
- * update in order to improve performance.
- */
- _updateState() {
- this.element.setAttribute("displayName", this.displayName);
- this.element.setAttribute("extendedDisplayName", this.extendedDisplayName);
- this.element.setAttribute("extendedDisplayNameTip", this.extendedDisplayNameTip);
- this.element.setAttribute("image", this.image);
- this.element.setAttribute("state",
- DownloadsCommon.stateOfDownload(this.download));
-
- // Since state changed, reset the time left estimation.
- this.lastEstimatedSecondsLeft = Infinity;
-
- this._updateProgress();
- },
-
- /**
- * Updates the elements that change regularly for in-progress downloads,
- * namely the progress bar and the status line.
- */
- _updateProgress() {
- if (this.download.succeeded) {
- // We only need to add or remove this attribute for succeeded downloads.
- if (this.download.target.exists) {
- this.element.setAttribute("exists", "true");
- } else {
- this.element.removeAttribute("exists");
- }
- }
-
- // The progress bar is only displayed for in-progress downloads.
- if (this.download.hasProgress) {
- this.element.setAttribute("progressmode", "normal");
- this.element.setAttribute("progress", this.download.progress);
- } else {
- this.element.setAttribute("progressmode", "undetermined");
- }
-
- // Dispatch the ValueChange event for accessibility, if possible.
- if (this._progressElement) {
- let event = this.element.ownerDocument.createEvent("Events");
- event.initEvent("ValueChange", true, true);
- this._progressElement.dispatchEvent(event);
- }
-
- let status = this.statusTextAndTip;
- this.element.setAttribute("status", status.text);
- this.element.setAttribute("statusTip", status.tip);
- },
-
- lastEstimatedSecondsLeft: Infinity,
-
- /**
- * Returns the text for the status line and the associated tooltip. These are
- * returned by a single property because they are computed together. The
- * result may be overridden by derived objects.
- */
- get statusTextAndTip() this.rawStatusTextAndTip,
-
- /**
- * Derived objects may call this to get the status text.
- */
- get rawStatusTextAndTip() {
- const nsIDM = Ci.nsIDownloadManager;
- let s = DownloadsCommon.strings;
-
- let text = "";
- let tip = "";
-
- if (!this.download.stopped) {
- let totalBytes = this.download.hasProgress ? this.download.totalBytes
- : -1;
- // By default, extended status information including the individual
- // download rate is displayed in the tooltip. The history view overrides
- // the getter and displays the datails in the main area instead.
- [text] = DownloadUtils.getDownloadStatusNoRate(
- this.download.currentBytes,
- totalBytes,
- this.download.speed,
- this.lastEstimatedSecondsLeft);
- let newEstimatedSecondsLeft;
- [tip, newEstimatedSecondsLeft] = DownloadUtils.getDownloadStatus(
- this.download.currentBytes,
- totalBytes,
- this.download.speed,
- this.lastEstimatedSecondsLeft);
- this.lastEstimatedSecondsLeft = newEstimatedSecondsLeft;
- } else if (this.download.canceled && this.download.hasPartialData) {
- let totalBytes = this.download.hasProgress ? this.download.totalBytes
- : -1;
- let transfer = DownloadUtils.getTransferTotal(this.download.currentBytes,
- totalBytes);
-
- // We use the same XUL label to display both the state and the amount
- // transferred, for example "Paused - 1.1 MB".
- text = s.statusSeparatorBeforeNumber(s.statePaused, transfer);
- } else if (!this.download.succeeded && !this.download.canceled &&
- !this.download.error) {
- text = s.stateStarting;
- } else {
- let stateLabel;
-
- if (this.download.succeeded) {
- // For completed downloads, show the file size (e.g. "1.5 MB").
- if (this.download.target.size !== undefined) {
- let [size, unit] =
- DownloadUtils.convertByteUnits(this.download.target.size);
- stateLabel = s.sizeWithUnits(size, unit);
- } else {
- // History downloads may not have a size defined.
- stateLabel = s.sizeUnknown;
- }
- } else if (this.download.canceled) {
- stateLabel = s.stateCanceled;
- } else if (this.download.error.becauseBlockedByParentalControls) {
- stateLabel = s.stateBlockedParentalControls;
- } else if (this.download.error.becauseBlockedByReputationCheck) {
- stateLabel = s.stateDirty;
- } else {
- stateLabel = s.stateFailed;
- }
-
- let referrer = this.download.source.referrer || this.download.source.url;
- let [displayHost, fullHost] = DownloadUtils.getURIHost(referrer);
-
- let date = new Date(this.download.endTime);
- let [displayDate, fullDate] = DownloadUtils.getReadableDates(date);
-
- let firstPart = s.statusSeparator(stateLabel, displayHost);
- text = s.statusSeparator(firstPart, displayDate);
- tip = s.statusSeparator(fullHost, fullDate);
- }
-
- return { text, tip: tip || text };
- },
-};
diff --git a/components/downloads/content/allDownloadsViewOverlay.css b/components/downloads/content/allDownloadsViewOverlay.css
deleted file mode 100644
index c062ae4..0000000
--- a/components/downloads/content/allDownloadsViewOverlay.css
+++ /dev/null
@@ -1,56 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/**
- * The downloads richlistbox may list thousands of items, and it turns out
- * XBL binding attachment, and even more so detachment, is a performance hog.
- * This hack makes sure we don't apply any binding to inactive items (inactive
- * items are history downloads that haven't been in the visible area).
- * We can do this because the richlistbox implementation does not interact
- * much with the richlistitem binding. However, this may turn out to have
- * some side effects (see bug 828111 for the details).
- *
- * We might be able to do away with this workaround once bug 653881 is fixed.
- */
-richlistitem.download {
- -moz-binding: none;
-}
-
-richlistitem.download[active] {
- -moz-binding: url('chrome://browser/content/downloads/download.xml#download-full-ui');
-}
-
-richlistitem.download[active]:-moz-any([state="-1"],/* Starting (initial) */
- [state="0"], /* Downloading */
- [state="4"], /* Paused */
- [state="5"], /* Starting (queued) */
- [state="7"]) /* Scanning */
-{
- -moz-binding: url('chrome://browser/content/downloads/download.xml#download-in-progress-full-ui');
-}
-
-.download-state:not( [state="0"] /* Downloading */)
- .downloadPauseMenuItem,
-.download-state:not( [state="4"] /* Paused */)
- .downloadResumeMenuItem,
-.download-state:not(:-moz-any([state="2"], /* Failed */
- [state="4"]) /* Paused */)
- .downloadCancelMenuItem,
-.download-state[state]:not(:-moz-any([state="1"], /* Finished */
- [state="2"], /* Failed */
- [state="3"], /* Canceled */
- [state="6"], /* Blocked (parental) */
- [state="8"], /* Blocked (dirty) */
- [state="9"]) /* Blocked (policy) */)
- .downloadRemoveFromHistoryMenuItem,
-.download-state:not(:-moz-any([state="-1"],/* Starting (initial) */
- [state="0"], /* Downloading */
- [state="1"], /* Finished */
- [state="4"], /* Paused */
- [state="5"]) /* Starting (queued) */)
- .downloadShowMenuItem,
-.download-state[state="7"] /* Scanning */ .downloadCommandsSeparator
-{
- display: none;
-}
diff --git a/components/downloads/content/allDownloadsViewOverlay.js b/components/downloads/content/allDownloadsViewOverlay.js
deleted file mode 100644
index 4830f21..0000000
--- a/components/downloads/content/allDownloadsViewOverlay.js
+++ /dev/null
@@ -1,1399 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-var { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "DownloadUtils",
- "resource://gre/modules/DownloadUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "DownloadsCommon",
- "resource:///modules/DownloadsCommon.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "DownloadsViewUI",
- "resource:///modules/DownloadsViewUI.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
- "resource://gre/modules/FileUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
- "resource://gre/modules/NetUtil.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "OS",
- "resource://gre/modules/osfile.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
- "resource://gre/modules/PlacesUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "Promise",
- "resource://gre/modules/Promise.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "RecentWindow",
- "resource:///modules/RecentWindow.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "Services",
- "resource://gre/modules/Services.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "Task",
- "resource://gre/modules/Task.jsm");
-
-const nsIDM = Ci.nsIDownloadManager;
-
-const DESTINATION_FILE_URI_ANNO = "downloads/destinationFileURI";
-const DOWNLOAD_META_DATA_ANNO = "downloads/metaData";
-
-const DOWNLOAD_VIEW_SUPPORTED_COMMANDS =
- ["cmd_delete", "cmd_copy", "cmd_paste", "cmd_selectAll",
- "downloadsCmd_pauseResume", "downloadsCmd_cancel",
- "downloadsCmd_open", "downloadsCmd_show", "downloadsCmd_retry",
- "downloadsCmd_openReferrer", "downloadsCmd_clearDownloads"];
-
-/**
- * Represents a download from the browser history. It implements part of the
- * interface of the Download object.
- *
- * @param aPlacesNode
- * The Places node from which the history download should be initialized.
- */
-function HistoryDownload(aPlacesNode) {
- // TODO (bug 829201): history downloads should get the referrer from Places.
- this.source = {
- url: aPlacesNode.uri,
- };
- this.target = {
- path: undefined,
- exists: false,
- size: undefined,
- };
-
- // In case this download cannot obtain its end time from the Places metadata,
- // use the time from the Places node, that is the start time of the download.
- this.endTime = aPlacesNode.time / 1000;
-}
-
-HistoryDownload.prototype = {
- /**
- * Pushes information from Places metadata into this object.
- */
- updateFromMetaData(metaData) {
- try {
- this.target.path = Cc["@mozilla.org/network/protocol;1?name=file"]
- .getService(Ci.nsIFileProtocolHandler)
- .getFileFromURLSpec(metaData.targetFileSpec).path;
- } catch (ex) {
- this.target.path = undefined;
- }
-
- if ("state" in metaData) {
- this.succeeded = metaData.state == nsIDM.DOWNLOAD_FINISHED;
- this.error = metaData.state == nsIDM.DOWNLOAD_FAILED
- ? { message: "History download failed." }
- : metaData.state == nsIDM.DOWNLOAD_BLOCKED_PARENTAL
- ? { becauseBlockedByParentalControls: true }
- : metaData.state == nsIDM.DOWNLOAD_DIRTY
- ? { becauseBlockedByReputationCheck: true }
- : null;
- this.canceled = metaData.state == nsIDM.DOWNLOAD_CANCELED ||
- metaData.state == nsIDM.DOWNLOAD_PAUSED;
- this.endTime = metaData.endTime;
-
- // Normal history downloads are assumed to exist until the user interface
- // is refreshed, at which point these values may be updated.
- this.target.exists = true;
- this.target.size = metaData.fileSize;
- } else {
- // Metadata might be missing from a download that has started but hasn't
- // stopped already. Normally, this state is overridden with the one from
- // the corresponding in-progress session download. But if the browser is
- // terminated abruptly and additionally the file with information about
- // in-progress downloads is lost, we may end up using this state. We use
- // the failed state to allow the download to be restarted.
- //
- // On the other hand, if the download is missing the target file
- // annotation as well, it is just a very old one, and we can assume it
- // succeeded.
- this.succeeded = !this.target.path;
- this.error = this.target.path ? { message: "Unstarted download." } : null;
- this.canceled = false;
-
- // These properties may be updated if the user interface is refreshed.
- this.target.exists = false;
- this.target.size = undefined;
- }
- },
-
- /**
- * History downloads are never in progress.
- */
- stopped: true,
-
- /**
- * No percentage indication is shown for history downloads.
- */
- hasProgress: false,
-
- /**
- * History downloads cannot be restarted using their partial data, even if
- * they are indicated as paused in their Places metadata. The only way is to
- * use the information from a persisted session download, that will be shown
- * instead of the history download. In case this session download is not
- * available, we show the history download as canceled, not paused.
- */
- hasPartialData: false,
-
- /**
- * This method mimicks the "start" method of session downloads, and is called
- * when the user retries a history download.
- *
- * At present, we always ask the user for a new target path when retrying a
- * history download. In the future we may consider reusing the known target
- * path if the folder still exists and the file name is not already used,
- * except when the user preferences indicate that the target path should be
- * requested every time a new download is started.
- */
- start() {
- let browserWin = RecentWindow.getMostRecentBrowserWindow();
- let initiatingDoc = browserWin ? browserWin.document : document;
-
- // Do not suggest a file name if we don't know the original target.
- let leafName = this.target.path ? OS.Path.basename(this.target.path) : null;
- DownloadURL(this.source.url, leafName, initiatingDoc);
-
- return Promise.resolve();
- },
-
- /**
- * This method mimicks the "refresh" method of session downloads, except that
- * it cannot notify that the data changed to the Downloads View.
- */
- refresh: Task.async(function* () {
- try {
- this.target.size = (yield OS.File.stat(this.target.path)).size;
- this.target.exists = true;
- } catch (ex) {
- // We keep the known file size from the metadata, if any.
- this.target.exists = false;
- }
- }),
-};
-
-/**
- * A download element shell is responsible for handling the commands and the
- * displayed data for a single download view element.
- *
- * The shell may contain a session download, a history download, or both. When
- * both a history and a session download are present, the session download gets
- * priority and its information is displayed.
- *
- * On construction, a new richlistitem is created, and can be accessed through
- * the |element| getter. The shell doesn't insert the item in a richlistbox, the
- * caller must do it and remove the element when it's no longer needed.
- *
- * The caller is also responsible for forwarding status notifications for
- * session downloads, calling the onStateChanged and onChanged methods.
- *
- * @param [optional] aSessionDownload
- * The session download, required if aHistoryDownload is not set.
- * @param [optional] aHistoryDownload
- * The history download, required if aSessionDownload is not set.
- */
-function HistoryDownloadElementShell(aSessionDownload, aHistoryDownload) {
- this.element = document.createElement("richlistitem");
- this.element._shell = this;
-
- this.element.classList.add("download");
- this.element.classList.add("download-state");
-
- if (aSessionDownload) {
- this.sessionDownload = aSessionDownload;
- }
- if (aHistoryDownload) {
- this.historyDownload = aHistoryDownload;
- }
-}
-
-HistoryDownloadElementShell.prototype = {
- __proto__: DownloadsViewUI.DownloadElementShell.prototype,
-
- /**
- * Manages the "active" state of the shell. By default all the shells without
- * a session download are inactive, thus their UI is not updated. They must
- * be activated when entering the visible area. Session downloads are always
- * active.
- */
- ensureActive: function DES_ensureActive() {
- if (!this._active) {
- this._active = true;
- this.element.setAttribute("active", true);
- this._updateUI();
- }
- },
- get active() !!this._active,
-
- /**
- * Overrides the base getter to return the Download or HistoryDownload object
- * for displaying information and executing commands in the user interface.
- */
- get download() this._sessionDownload || this._historyDownload,
-
- _sessionDownload: null,
- get sessionDownload() this._sessionDownload,
- set sessionDownload(aValue) {
- if (this._sessionDownload != aValue) {
- if (!aValue && !this._historyDownload) {
- throw new Error("Should always have either a Download or a HistoryDownload");
- }
-
- this._sessionDownload = aValue;
-
- this.ensureActive();
- this._updateUI();
- }
- return aValue;
- },
-
- _historyDownload: null,
- get historyDownload() this._historyDownload,
- set historyDownload(aValue) {
- if (this._historyDownload != aValue) {
- if (!aValue && !this._sessionDownload) {
- throw new Error("Should always have either a Download or a HistoryDownload");
- }
-
- this._historyDownload = aValue;
-
- // We don't need to update the UI if we had a session data item, because
- // the places information isn't used in this case.
- if (!this._sessionDownload) {
- this._updateUI();
- }
- }
- return aValue;
- },
-
- _updateUI() {
- // There is nothing to do if the item has always been invisible.
- if (!this.active) {
- return;
- }
-
- // Since the state changed, we may need to check the target file again.
- this._targetFileChecked = false;
-
- this._updateState();
- },
-
- get statusTextAndTip() {
- let status = this.rawStatusTextAndTip;
-
- // The base object would show extended progress information in the tooltip,
- // but we move this to the main view and never display a tooltip.
- if (!this.download.stopped) {
- status.text = status.tip;
- }
- status.tip = "";
-
- return status;
- },
-
- onStateChanged() {
- this.element.setAttribute("image", this.image);
- this.element.setAttribute("state",
- DownloadsCommon.stateOfDownload(this.download));
-
- if (this.element.selected) {
- goUpdateDownloadCommands();
- } else {
- goUpdateCommand("downloadsCmd_clearDownloads");
- }
- },
-
- onChanged() {
- this._updateProgress();
- },
-
- /* nsIController */
- isCommandEnabled: function DES_isCommandEnabled(aCommand) {
- // The only valid command for inactive elements is cmd_delete.
- if (!this.active && aCommand != "cmd_delete")
- return false;
- switch (aCommand) {
- case "downloadsCmd_open":
- // This property is false if the download did not succeed.
- return this.download.target.exists;
- case "downloadsCmd_show":
- // TODO: Bug 827010 - Handle part-file asynchronously.
- if (this._sessionDownload && this.download.target.partFilePath) {
- let partFile = new FileUtils.File(this.download.target.partFilePath);
- if (partFile.exists()) {
- return true;
- }
- }
-
- // This property is false if the download did not succeed.
- return this.download.target.exists;
- case "downloadsCmd_pauseResume":
- return this.download.hasPartialData && !this.download.error;
- case "downloadsCmd_retry":
- return this.download.canceled || this.download.error;
- case "downloadsCmd_openReferrer":
- return !!this.download.source.referrer;
- case "cmd_delete":
- // We don't want in-progress downloads to be removed accidentally.
- return this.download.stopped;
- case "downloadsCmd_cancel":
- return !!this._sessionDownload;
- }
- return false;
- },
-
- /* nsIController */
- doCommand: function DES_doCommand(aCommand) {
- switch (aCommand) {
- case "downloadsCmd_open": {
- let file = new FileUtils.File(this.download.target.path);
- DownloadsCommon.openDownloadedFile(file, null, window);
- break;
- }
- case "downloadsCmd_show": {
- let file = new FileUtils.File(this.download.target.path);
- DownloadsCommon.showDownloadedFile(file);
- break;
- }
- case "downloadsCmd_openReferrer": {
- openURL(this.download.source.referrer);
- break;
- }
- case "downloadsCmd_cancel": {
- this.download.cancel().catch(() => {});
- this.download.removePartialData().catch(Cu.reportError);
- break;
- }
- case "cmd_delete": {
- if (this._sessionDownload) {
- DownloadsCommon.removeAndFinalizeDownload(this.download);
- }
- if (this._historyDownload) {
- let uri = NetUtil.newURI(this.download.source.url);
- PlacesUtils.bhistory.removePage(uri);
- }
- break;
- }
- case "downloadsCmd_retry": {
- // Errors when retrying are already reported as download failures.
- this.download.start().catch(() => {});
- break;
- }
- case "downloadsCmd_pauseResume": {
- // This command is only enabled for session downloads.
- if (this.download.stopped) {
- this.download.start();
- } else {
- this.download.cancel();
- }
- break;
- }
- }
- },
-
- // Returns whether or not the download handled by this shell should
- // show up in the search results for the given term. Both the display
- // name for the download and the url are searched.
- matchesSearchTerm: function DES_matchesSearchTerm(aTerm) {
- if (!aTerm)
- return true;
- aTerm = aTerm.toLowerCase();
- return this.displayName.toLowerCase().contains(aTerm) ||
- this.download.source.url.toLowerCase().contains(aTerm);
- },
-
- // Handles return keypress on the element (the keypress listener is
- // set in the DownloadsPlacesView object).
- doDefaultCommand: function DES_doDefaultCommand() {
- function getDefaultCommandForState(aState) {
- switch (aState) {
- case nsIDM.DOWNLOAD_FINISHED:
- return "downloadsCmd_open";
- case nsIDM.DOWNLOAD_PAUSED:
- return "downloadsCmd_pauseResume";
- case nsIDM.DOWNLOAD_NOTSTARTED:
- case nsIDM.DOWNLOAD_QUEUED:
- return "downloadsCmd_cancel";
- case nsIDM.DOWNLOAD_FAILED:
- case nsIDM.DOWNLOAD_CANCELED:
- return "downloadsCmd_retry";
- case nsIDM.DOWNLOAD_SCANNING:
- return "downloadsCmd_show";
- case nsIDM.DOWNLOAD_BLOCKED_PARENTAL:
- case nsIDM.DOWNLOAD_DIRTY:
- case nsIDM.DOWNLOAD_BLOCKED_POLICY:
- return "downloadsCmd_openReferrer";
- }
- return "";
- }
- let state = DownloadsCommon.stateOfDownload(this.download);
- let command = getDefaultCommandForState(state);
- if (command && this.isCommandEnabled(command))
- this.doCommand(command);
- },
-
- /**
- * This method is called by the outer download view, after the controller
- * commands have already been updated. In case we did not check for the
- * existence of the target file already, we can do it now and then update
- * the commands as needed.
- */
- onSelect: function DES_onSelect() {
- if (!this.active)
- return;
-
- // If this is a history download for which no target file information is
- // available, we cannot retrieve information about the target file.
- if (!this.download.target.path) {
- return;
- }
-
- // Start checking for existence. This may be done twice if onSelect is
- // called again before the information is collected.
- if (!this._targetFileChecked) {
- this._checkTargetFileOnSelect().catch(Cu.reportError);
- }
- },
-
- _checkTargetFileOnSelect: Task.async(function* () {
- try {
- yield this.download.refresh();
- } finally {
- // Do not try to check for existence again if this failed once.
- this._targetFileChecked = true;
- }
-
- // Update the commands only if the element is still selected.
- if (this.element.selected) {
- goUpdateDownloadCommands();
- }
-
- // Ensure the interface has been updated based on the new values. We need to
- // do this because history downloads can't trigger update notifications.
- this._updateProgress();
- }),
-};
-
-/**
- * A Downloads Places View is a places view designed to show a places query
- * for history downloads alongside the session downloads.
- *
- * As we don't use the places controller, some methods implemented by other
- * places views are not implemented by this view.
- *
- * A richlistitem in this view can represent either a past download or a session
- * download, or both. Session downloads are shown first in the view, and as long
- * as they exist they "collapses" their history "counterpart" (So we don't show two
- * items for every download).
- */
-function DownloadsPlacesView(aRichListBox, aActive = true) {
- this._richlistbox = aRichListBox;
- this._richlistbox._placesView = this;
- window.controllers.insertControllerAt(0, this);
-
- // Map download URLs to download element shells regardless of their type
- this._downloadElementsShellsForURI = new Map();
-
- // Map download data items to their element shells.
- this._viewItemsForDownloads = new WeakMap();
-
- // Points to the last session download element. We keep track of this
- // in order to keep all session downloads above past downloads.
- this._lastSessionDownloadElement = null;
-
- this._searchTerm = "";
-
- this._active = aActive;
-
- // Register as a downloads view. The places data will be initialized by
- // the places setter.
- this._initiallySelectedElement = null;
- this._downloadsData = DownloadsCommon.getData(window.opener || window);
- this._downloadsData.addView(this);
-
- // Get the Download button out of the attention state since we're about to
- // view all downloads.
- DownloadsCommon.getIndicatorData(window).attention = false;
-
- // Make sure to unregister the view if the window is closed.
- window.addEventListener("unload", function() {
- window.controllers.removeController(this);
- this._downloadsData.removeView(this);
- this.result = null;
- }.bind(this), true);
- // Resizing the window may change items visibility.
- window.addEventListener("resize", function() {
- this._ensureVisibleElementsAreActive();
- }.bind(this), true);
-}
-
-DownloadsPlacesView.prototype = {
- get associatedElement() this._richlistbox,
-
- get active() this._active,
- set active(val) {
- this._active = val;
- if (this._active)
- this._ensureVisibleElementsAreActive();
- return this._active;
- },
-
- /**
- * This cache exists in order to optimize the load of the Downloads View, when
- * Places annotations for history downloads must be read. In fact, annotations
- * are stored in a single table, and reading all of them at once is much more
- * efficient than an individual query.
- *
- * When this property is first requested, it reads the annotations for all the
- * history downloads and stores them indefinitely.
- *
- * The historical annotations are not expected to change for the duration of
- * the session, except in the case where a session download is running for the
- * same URI as a history download. To ensure we don't use stale data, URIs
- * corresponding to session downloads are permanently removed from the cache.
- * This is a very small mumber compared to history downloads.
- *
- * This property returns a Map from each download source URI found in Places
- * annotations to an object with the format:
- *
- * { targetFileSpec, state, endTime, fileSize, ... }
- *
- * The targetFileSpec property is the value of "downloads/destinationFileURI",
- * while the other properties are taken from "downloads/metaData". Any of the
- * properties may be missing from the object.
- */
- get _cachedPlacesMetaData() {
- if (!this.__cachedPlacesMetaData) {
- this.__cachedPlacesMetaData = new Map();
-
- // Read the metadata annotations first, but ignore invalid JSON.
- for (let result of PlacesUtils.annotations.getAnnotationsWithName(
- DOWNLOAD_META_DATA_ANNO)) {
- try {
- this.__cachedPlacesMetaData.set(result.uri.spec,
- JSON.parse(result.annotationValue));
- } catch (ex) {}
- }
-
- // Add the target file annotations to the metadata.
- for (let result of PlacesUtils.annotations.getAnnotationsWithName(
- DESTINATION_FILE_URI_ANNO)) {
- let metaData = this.__cachedPlacesMetaData.get(result.uri.spec);
- if (!metaData) {
- metaData = {};
- this.__cachedPlacesMetaData.set(result.uri.spec, metaData);
- }
- metaData.targetFileSpec = result.annotationValue;
- }
- }
-
- return this.__cachedPlacesMetaData;
- },
- __cachedPlacesMetaData: null,
-
- /**
- * Reads current metadata from Places annotations for the specified URI, and
- * returns an object with the format:
- *
- * { targetFileSpec, state, endTime, fileSize, ... }
- *
- * The targetFileSpec property is the value of "downloads/destinationFileURI",
- * while the other properties are taken from "downloads/metaData". Any of the
- * properties may be missing from the object.
- */
- _getPlacesMetaDataFor(spec) {
- let metaData = {};
-
- try {
- let uri = NetUtil.newURI(spec);
- try {
- metaData = JSON.parse(PlacesUtils.annotations.getPageAnnotation(
- uri, DOWNLOAD_META_DATA_ANNO));
- } catch (ex) {}
- metaData.targetFileSpec = PlacesUtils.annotations.getPageAnnotation(
- uri, DESTINATION_FILE_URI_ANNO);
- } catch (ex) {}
-
- return metaData;
- },
-
- /**
- * Given a data item for a session download, or a places node for a past
- * download, updates the view as necessary.
- * 1. If the given data is a places node, we check whether there are any
- * elements for the same download url. If there are, then we just reset
- * their places node. Otherwise we add a new download element.
- * 2. If the given data is a data item, we first check if there's a history
- * download in the list that is not associated with a data item. If we
- * found one, we use it for the data item as well and reposition it
- * alongside the other session downloads. If we don't, then we go ahead
- * and create a new element for the download.
- *
- * @param [optional] sessionDownload
- * A Download object, or null for history downloads.
- * @param [optional] aPlacesNode
- * The Places node for a history download, or null for session downloads.
- * @param [optional] aNewest
- * @see onDownloadAdded. Ignored for history downloads.
- * @param [optional] aDocumentFragment
- * To speed up the appending of multiple elements to the end of the
- * list which are coming in a single batch (i.e. invalidateContainer),
- * a document fragment may be passed to which the new elements would
- * be appended. It's the caller's job to ensure the fragment is merged
- * to the richlistbox at the end.
- */
- _addDownloadData(sessionDownload, aPlacesNode, aNewest = false,
- aDocumentFragment = null) {
- let downloadURI = aPlacesNode ? aPlacesNode.uri
- : sessionDownload.source.url;
- let shellsForURI = this._downloadElementsShellsForURI.get(downloadURI);
- if (!shellsForURI) {
- shellsForURI = new Set();
- this._downloadElementsShellsForURI.set(downloadURI, shellsForURI);
- }
-
- // When a session download is attached to a shell, we ensure not to keep
- // stale metadata around for the corresponding history download. This
- // prevents stale state from being used if the view is rebuilt.
- //
- // Note that we will eagerly load the data in the cache at this point, even
- // if we have seen no history download. The case where no history download
- // will appear at all is rare enough in normal usage, so we can apply this
- // simpler solution rather than keeping a list of cache items to ignore.
- if (sessionDownload) {
- this._cachedPlacesMetaData.delete(sessionDownload.source.url);
- }
-
- let newOrUpdatedShell = null;
-
- // Trivial: if there are no shells for this download URI, we always
- // need to create one.
- let shouldCreateShell = shellsForURI.size == 0;
-
- // However, if we do have shells for this download uri, there are
- // few options:
- // 1) There's only one shell and it's for a history download (it has
- // no data item). In this case, we update this shell and move it
- // if necessary
- // 2) There are multiple shells, indicating multiple downloads for
- // the same download uri are running. In this case we create
- // another shell for the download (so we have one shell for each data
- // item).
- //
- // Note: If a cancelled session download is already in the list, and the
- // download is retried, onDownloadAdded is called again for the same
- // data item. Thus, we also check that we make sure we don't have a view item
- // already.
- if (!shouldCreateShell &&
- sessionDownload && !this._viewItemsForDownloads.has(sessionDownload)) {
- // If there's a past-download-only shell for this download-uri with no
- // associated data item, use it for the new data item. Otherwise, go ahead
- // and create another shell.
- shouldCreateShell = true;
- for (let shell of shellsForURI) {
- if (!shell.sessionDownload) {
- shouldCreateShell = false;
- shell.sessionDownload = sessionDownload;
- newOrUpdatedShell = shell;
- this._viewItemsForDownloads.set(sessionDownload, shell);
- break;
- }
- }
- }
-
- if (shouldCreateShell) {
- // If we are adding a new history download here, it means there is no
- // associated session download, thus we must read the Places metadata,
- // because it will not be obscured by the session download.
- let historyDownload = null;
- if (aPlacesNode) {
- let metaData = this._cachedPlacesMetaData.get(aPlacesNode.uri) ||
- this._getPlacesMetaDataFor(aPlacesNode.uri);
- historyDownload = new HistoryDownload(aPlacesNode);
- historyDownload.updateFromMetaData(metaData);
- }
- let shell = new HistoryDownloadElementShell(sessionDownload,
- historyDownload);
- shell.element._placesNode = aPlacesNode;
- newOrUpdatedShell = shell;
- shellsForURI.add(shell);
- if (sessionDownload) {
- this._viewItemsForDownloads.set(sessionDownload, shell);
- }
- }
- else if (aPlacesNode) {
- // We are updating information for a history download for which we have
- // at least one download element shell already. There are two cases:
- // 1) There are one or more download element shells for this source URI,
- // each with an associated session download. We update the Places node
- // because we may need it later, but we don't need to read the Places
- // metadata until the last session download is removed.
- // 2) Occasionally, we may receive a duplicate notification for a history
- // download with no associated session download. We have exactly one
- // download element shell in this case, but the metdata cannot have
- // changed, just the reference to the Places node object is different.
- // So, we update all the node references and keep the metadata intact.
- for (let shell of shellsForURI) {
- if (!shell.historyDownload) {
- // Create the element to host the metadata when needed.
- shell.historyDownload = new HistoryDownload(aPlacesNode);
- }
- shell.element._placesNode = aPlacesNode;
- }
- }
-
- if (newOrUpdatedShell) {
- if (aNewest) {
- this._richlistbox.insertBefore(newOrUpdatedShell.element,
- this._richlistbox.firstChild);
- if (!this._lastSessionDownloadElement) {
- this._lastSessionDownloadElement = newOrUpdatedShell.element;
- }
- // Some operations like retrying an history download move an element to
- // the top of the richlistbox, along with other session downloads.
- // More generally, if a new download is added, should be made visible.
- this._richlistbox.ensureElementIsVisible(newOrUpdatedShell.element);
- } else if (sessionDownload) {
- let before = this._lastSessionDownloadElement ?
- this._lastSessionDownloadElement.nextSibling : this._richlistbox.firstChild;
- this._richlistbox.insertBefore(newOrUpdatedShell.element, before);
- this._lastSessionDownloadElement = newOrUpdatedShell.element;
- }
- else {
- let appendTo = aDocumentFragment || this._richlistbox;
- appendTo.appendChild(newOrUpdatedShell.element);
- }
-
- if (this.searchTerm) {
- newOrUpdatedShell.element.hidden =
- !newOrUpdatedShell.element._shell.matchesSearchTerm(this.searchTerm);
- }
- }
-
- // If aDocumentFragment is defined this is a batch change, so it's up to
- // the caller to append the fragment and activate the visible shells.
- if (!aDocumentFragment) {
- this._ensureVisibleElementsAreActive();
- goUpdateCommand("downloadsCmd_clearDownloads");
- }
- },
-
- _removeElement: function DPV__removeElement(aElement) {
- // If the element was selected exclusively, select its next
- // sibling first, if not, try for previous sibling, if any.
- if ((aElement.nextSibling || aElement.previousSibling) &&
- this._richlistbox.selectedItems &&
- this._richlistbox.selectedItems.length == 1 &&
- this._richlistbox.selectedItems[0] == aElement) {
- this._richlistbox.selectItem(aElement.nextSibling ||
- aElement.previousSibling);
- }
-
- if (this._lastSessionDownloadElement == aElement)
- this._lastSessionDownloadElement = aElement.previousSibling;
-
- this._richlistbox.removeItemFromSelection(aElement);
- this._richlistbox.removeChild(aElement);
- this._ensureVisibleElementsAreActive();
- goUpdateCommand("downloadsCmd_clearDownloads");
- },
-
- _removeHistoryDownloadFromView:
- function DPV__removeHistoryDownloadFromView(aPlacesNode) {
- let downloadURI = aPlacesNode.uri;
- let shellsForURI = this._downloadElementsShellsForURI.get(downloadURI);
- if (shellsForURI) {
- for (let shell of shellsForURI) {
- if (shell.sessionDownload) {
- shell.historyDownload = null;
- }
- else {
- this._removeElement(shell.element);
- shellsForURI.delete(shell);
- if (shellsForURI.size == 0)
- this._downloadElementsShellsForURI.delete(downloadURI);
- }
- }
- }
- },
-
- _removeSessionDownloadFromView(download) {
- let shells = this._downloadElementsShellsForURI
- .get(download.source.url);
- if (shells.size == 0)
- throw new Error("Should have had at leaat one shell for this uri");
-
- let shell = this._viewItemsForDownloads.get(download);
- if (!shells.has(shell))
- throw new Error("Missing download element shell in shells list for url");
-
- // If there's more than one item for this download uri, we can let the
- // view item for this this particular data item go away.
- // If there's only one item for this download uri, we should only
- // keep it if it is associated with a history download.
- if (shells.size > 1 || !shell.historyDownload) {
- this._removeElement(shell.element);
- shells.delete(shell);
- if (shells.size == 0)
- this._downloadElementsShellsForURI.delete(download.source.url);
- }
- else {
- // We have one download element shell containing both a session download
- // and a history download, and we are now removing the session download.
- // Previously, we did not use the Places metadata because it was obscured
- // by the session download. Since this is no longer the case, we have to
- // read the latest metadata before removing the session download.
- let url = shell.historyDownload.source.url;
- let metaData = this._getPlacesMetaDataFor(url);
- shell.historyDownload.updateFromMetaData(metaData);
- shell.sessionDownload = null;
- // Move it below the session-download items;
- if (this._lastSessionDownloadElement == shell.element) {
- this._lastSessionDownloadElement = shell.element.previousSibling;
- }
- else {
- let before = this._lastSessionDownloadElement ?
- this._lastSessionDownloadElement.nextSibling : this._richlistbox.firstChild;
- this._richlistbox.insertBefore(shell.element, before);
- }
- }
- },
-
- _ensureVisibleElementsAreActive:
- function DPV__ensureVisibleElementsAreActive() {
- if (!this.active || this._ensureVisibleTimer || !this._richlistbox.firstChild)
- return;
-
- this._ensureVisibleTimer = setTimeout(function() {
- delete this._ensureVisibleTimer;
- if (!this._richlistbox.firstChild)
- return;
-
- let rlbRect = this._richlistbox.getBoundingClientRect();
- let winUtils = window.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIDOMWindowUtils);
- let nodes = winUtils.nodesFromRect(rlbRect.left, rlbRect.top,
- 0, rlbRect.width, rlbRect.height, 0,
- true, false);
- // nodesFromRect returns nodes in z-index order, and for the same z-index
- // sorts them in inverted DOM order, thus starting from the one that would
- // be on top.
- let firstVisibleNode, lastVisibleNode;
- for (let node of nodes) {
- if (node.localName === "richlistitem" && node._shell) {
- node._shell.ensureActive();
- // The first visible node is the last match.
- firstVisibleNode = node;
- // While the last visible node is the first match.
- if (!lastVisibleNode)
- lastVisibleNode = node;
- }
- }
-
- // Also activate the first invisible nodes in both boundaries (that is,
- // above and below the visible area) to ensure proper keyboard navigation
- // in both directions.
- let nodeBelowVisibleArea = lastVisibleNode && lastVisibleNode.nextSibling;
- if (nodeBelowVisibleArea && nodeBelowVisibleArea._shell)
- nodeBelowVisibleArea._shell.ensureActive();
-
- let nodeABoveVisibleArea =
- firstVisibleNode && firstVisibleNode.previousSibling;
- if (nodeABoveVisibleArea && nodeABoveVisibleArea._shell)
- nodeABoveVisibleArea._shell.ensureActive();
- }.bind(this), 10);
- },
-
- _place: "",
- get place() this._place,
- set place(val) {
- // Don't reload everything if we don't have to.
- if (this._place == val) {
- // XXXmano: places.js relies on this behavior (see Bug 822203).
- this.searchTerm = "";
- return val;
- }
-
- this._place = val;
-
- let history = PlacesUtils.history;
- let queries = { }, options = { };
- history.queryStringToQueries(val, queries, { }, options);
- if (!queries.value.length)
- queries.value = [history.getNewQuery()];
-
- let result = history.executeQueries(queries.value, queries.value.length,
- options.value);
- result.addObserver(this, false);
- return val;
- },
-
- _result: null,
- get result() this._result,
- set result(val) {
- if (this._result == val)
- return val;
-
- if (this._result) {
- this._result.removeObserver(this);
- this._resultNode.containerOpen = false;
- }
-
- if (val) {
- this._result = val;
- this._resultNode = val.root;
- this._resultNode.containerOpen = true;
- this._ensureInitialSelection();
- }
- else {
- delete this._resultNode;
- delete this._result;
- }
-
- return val;
- },
-
- get selectedNodes() {
- return [for (element of this._richlistbox.selectedItems)
- if (element._placesNode)
- element._placesNode];
- },
-
- get selectedNode() {
- let selectedNodes = this.selectedNodes;
- return selectedNodes.length == 1 ? selectedNodes[0] : null;
- },
-
- get hasSelection() this.selectedNodes.length > 0,
-
- containerStateChanged:
- function DPV_containerStateChanged(aNode, aOldState, aNewState) {
- this.invalidateContainer(aNode)
- },
-
- invalidateContainer:
- function DPV_invalidateContainer(aContainer) {
- if (aContainer != this._resultNode)
- throw new Error("Unexpected container node");
- if (!aContainer.containerOpen)
- throw new Error("Root container for the downloads query cannot be closed");
-
- let suppressOnSelect = this._richlistbox.suppressOnSelect;
- this._richlistbox.suppressOnSelect = true;
- try {
- // Remove the invalidated history downloads from the list and unset the
- // places node for data downloads.
- // Loop backwards since _removeHistoryDownloadFromView may removeChild().
- for (let i = this._richlistbox.childNodes.length - 1; i >= 0; --i) {
- let element = this._richlistbox.childNodes[i];
- if (element._placesNode) {
- this._removeHistoryDownloadFromView(element._placesNode);
- }
- }
- }
- finally {
- this._richlistbox.suppressOnSelect = suppressOnSelect;
- }
-
- if (aContainer.childCount > 0) {
- let elementsToAppendFragment = document.createDocumentFragment();
- for (let i = 0; i < aContainer.childCount; i++) {
- try {
- this._addDownloadData(null, aContainer.getChild(i), false,
- elementsToAppendFragment);
- }
- catch(ex) {
- Cu.reportError(ex);
- }
- }
-
- // _addDownloadData may not add new elements if there were already
- // data items in place.
- if (elementsToAppendFragment.firstChild) {
- this._appendDownloadsFragment(elementsToAppendFragment);
- this._ensureVisibleElementsAreActive();
- }
- }
-
- goUpdateDownloadCommands();
- },
-
- _appendDownloadsFragment: function DPV__appendDownloadsFragment(aDOMFragment) {
- // Workaround multiple reflows hang by removing the richlistbox
- // and adding it back when we're done.
-
- // Hack for bug 836283: reset xbl fields to their old values after the
- // binding is reattached to avoid breaking the selection state
- let xblFields = new Map();
- for (let [key, value] in Iterator(this._richlistbox)) {
- xblFields.set(key, value);
- }
-
- let parentNode = this._richlistbox.parentNode;
- let nextSibling = this._richlistbox.nextSibling;
- parentNode.removeChild(this._richlistbox);
- this._richlistbox.appendChild(aDOMFragment);
- parentNode.insertBefore(this._richlistbox, nextSibling);
-
- for (let [key, value] of xblFields) {
- this._richlistbox[key] = value;
- }
- },
-
- nodeInserted: function DPV_nodeInserted(aParent, aPlacesNode) {
- this._addDownloadData(null, aPlacesNode);
- },
-
- nodeRemoved: function DPV_nodeRemoved(aParent, aPlacesNode, aOldIndex) {
- this._removeHistoryDownloadFromView(aPlacesNode);
- },
-
- nodeAnnotationChanged() {},
- nodeIconChanged() {},
- nodeTitleChanged() {},
- nodeKeywordChanged: function() {},
- nodeDateAddedChanged: function() {},
- nodeLastModifiedChanged: function() {},
- nodeHistoryDetailsChanged: function() {},
- nodeTagsChanged: function() {},
- sortingChanged: function() {},
- nodeMoved: function() {},
- nodeURIChanged: function() {},
- batching: function() {},
-
- get controller() this._richlistbox.controller,
-
- get searchTerm() this._searchTerm,
- set searchTerm(aValue) {
- if (this._searchTerm != aValue) {
- for (let element of this._richlistbox.childNodes) {
- element.hidden = !element._shell.matchesSearchTerm(aValue);
- }
- this._ensureVisibleElementsAreActive();
- }
- return this._searchTerm = aValue;
- },
-
- /**
- * When the view loads, we want to select the first item.
- * However, because session downloads, for which the data is loaded
- * asynchronously, always come first in the list, and because the list
- * may (or may not) already contain history downloads at that point, it
- * turns out that by the time we can select the first item, the user may
- * have already started using the view.
- * To make things even more complicated, in other cases, the places data
- * may be loaded after the session downloads data. Thus we cannot rely on
- * the order in which the data comes in.
- * We work around this by attempting to select the first element twice,
- * once after the places data is loaded and once when the session downloads
- * data is done loading. However, if the selection has changed in-between,
- * we assume the user has already started using the view and give up.
- */
- _ensureInitialSelection: function DPV__ensureInitialSelection() {
- // Either they're both null, or the selection has not changed in between.
- if (this._richlistbox.selectedItem == this._initiallySelectedElement) {
- let firstDownloadElement = this._richlistbox.firstChild;
- if (firstDownloadElement != this._initiallySelectedElement) {
- // We may be called before _ensureVisibleElementsAreActive,
- // or before the download binding is attached. Therefore, ensure the
- // first item is activated, and pass the item to the richlistbox
- // setters only at a point we know for sure the binding is attached.
- firstDownloadElement._shell.ensureActive();
- Services.tm.mainThread.dispatch(function() {
- this._richlistbox.selectedItem = firstDownloadElement;
- this._richlistbox.currentItem = firstDownloadElement;
- this._initiallySelectedElement = firstDownloadElement;
- }.bind(this), Ci.nsIThread.DISPATCH_NORMAL);
- }
- }
- },
-
- onDataLoadStarting: function() { },
- onDataLoadCompleted: function DPV_onDataLoadCompleted() {
- this._ensureInitialSelection();
- },
-
- onDownloadAdded(download, newest) {
- this._addDownloadData(download, null, newest);
- },
-
- onDownloadStateChanged(download) {
- this._viewItemsForDownloads.get(download).onStateChanged();
- },
-
- onDownloadChanged(download) {
- this._viewItemsForDownloads.get(download).onChanged();
- },
-
- onDownloadRemoved(download) {
- this._removeSessionDownloadFromView(download);
- },
-
- supportsCommand: function DPV_supportsCommand(aCommand) {
- if (DOWNLOAD_VIEW_SUPPORTED_COMMANDS.indexOf(aCommand) != -1) {
- // The clear-downloads command may be performed by the toolbar-button,
- // which can be focused on OS X. Thus enable this command even if the
- // richlistbox is not focused.
- // For other commands, be prudent and disable them unless the richlistview
- // is focused. It's important to make the decision here rather than in
- // isCommandEnabled. Otherwise our controller may "steal" commands from
- // other controls in the window (see goUpdateCommand &
- // getControllerForCommand).
- if (document.activeElement == this._richlistbox ||
- aCommand == "downloadsCmd_clearDownloads") {
- return true;
- }
- }
- return false;
- },
-
- isCommandEnabled: function DPV_isCommandEnabled(aCommand) {
- switch (aCommand) {
- case "cmd_copy":
- return this._richlistbox.selectedItems.length > 0;
- case "cmd_selectAll":
- return true;
- case "cmd_paste":
- return this._canDownloadClipboardURL();
- case "downloadsCmd_clearDownloads":
- return this._canClearDownloads();
- default:
- return Array.every(this._richlistbox.selectedItems, function(element) {
- return element._shell.isCommandEnabled(aCommand);
- });
- }
- },
-
- _canClearDownloads: function DPV__canClearDownloads() {
- // Downloads can be cleared if there's at least one removable download in
- // the list (either a history download or a completed session download).
- // Because history downloads are always removable and are listed after the
- // session downloads, check from bottom to top.
- for (let elt = this._richlistbox.lastChild; elt; elt = elt.previousSibling) {
- // Stopped, paused, and failed downloads with partial data are removed.
- let download = elt._shell.download;
- if (download.stopped && !(download.canceled && download.hasPartialData)) {
- return true;
- }
- }
- return false;
- },
-
- _copySelectedDownloadsToClipboard:
- function DPV__copySelectedDownloadsToClipboard() {
- let urls = [for (element of this._richlistbox.selectedItems)
- element._shell.download.source.url];
-
- Cc["@mozilla.org/widget/clipboardhelper;1"]
- .getService(Ci.nsIClipboardHelper)
- .copyString(urls.join("\n"), document);
- },
-
- _getURLFromClipboardData: function DPV__getURLFromClipboardData() {
- let trans = Cc["@mozilla.org/widget/transferable;1"].
- createInstance(Ci.nsITransferable);
- trans.init(null);
-
- let flavors = ["text/x-moz-url", "text/unicode"];
- flavors.forEach(trans.addDataFlavor);
-
- Services.clipboard.getData(trans, Services.clipboard.kGlobalClipboard);
-
- // Getting the data or creating the nsIURI might fail.
- try {
- let data = {};
- trans.getAnyTransferData({}, data, {});
- let [url, name] = data.value.QueryInterface(Ci.nsISupportsString)
- .data.split("\n");
- if (url)
- return [NetUtil.newURI(url, null, null).spec, name];
- }
- catch(ex) { }
-
- return ["", ""];
- },
-
- _canDownloadClipboardURL: function DPV__canDownloadClipboardURL() {
- let [url, name] = this._getURLFromClipboardData();
- return url != "";
- },
-
- _downloadURLFromClipboard: function DPV__downloadURLFromClipboard() {
- let [url, name] = this._getURLFromClipboardData();
- let browserWin = RecentWindow.getMostRecentBrowserWindow();
- let initiatingDoc = browserWin ? browserWin.document : document;
- DownloadURL(url, name, initiatingDoc);
- },
-
- doCommand: function DPV_doCommand(aCommand) {
- // Commands may be invoked with keyboard shortcuts even if disabled.
- if (!this.isCommandEnabled(aCommand)) {
- return;
- }
- switch (aCommand) {
- case "cmd_copy":
- this._copySelectedDownloadsToClipboard();
- break;
- case "cmd_selectAll":
- this._richlistbox.selectAll();
- break;
- case "cmd_paste":
- this._downloadURLFromClipboard();
- break;
- case "downloadsCmd_clearDownloads":
- this._downloadsData.removeFinished();
- if (this.result) {
- Cc["@mozilla.org/browser/download-history;1"]
- .getService(Ci.nsIDownloadHistory)
- .removeAllDownloads();
- }
- // There may be no selection or focus change as a result
- // of these change, and we want the command updated immediately.
- goUpdateCommand("downloadsCmd_clearDownloads");
- break;
- default: {
- // Cloning the nodelist into an array to get a frozen list of selected items.
- // Otherwise, the selectedItems nodelist is live and doCommand may alter the
- // selection while we are trying to do one particular action, like removing
- // items from history.
- let selectedElements = [...this._richlistbox.selectedItems];
- for (let element of selectedElements) {
- element._shell.doCommand(aCommand);
- }
- }
- }
- },
-
- onEvent: function() { },
-
- onContextMenu: function DPV_onContextMenu(aEvent)
- {
- let element = this._richlistbox.selectedItem;
- if (!element || !element._shell)
- return false;
-
- // Set the state attribute so that only the appropriate items are displayed.
- let contextMenu = document.getElementById("downloadsContextMenu");
- let download = element._shell.download;
- contextMenu.setAttribute("state",
- DownloadsCommon.stateOfDownload(download));
-
- if (!download.stopped) {
- // The hasPartialData property of a download may change at any time after
- // it has started, so ensure we update the related command now.
- goUpdateCommand("downloadsCmd_pauseResume");
- }
- return true;
- },
-
- onKeyPress: function DPV_onKeyPress(aEvent) {
- let selectedElements = this._richlistbox.selectedItems;
- if (aEvent.keyCode == KeyEvent.DOM_VK_RETURN) {
- // In the content tree, opening bookmarks by pressing return is only
- // supported when a single item is selected. To be consistent, do the
- // same here.
- if (selectedElements.length == 1) {
- let element = selectedElements[0];
- if (element._shell)
- element._shell.doDefaultCommand();
- }
- }
- else if (aEvent.charCode == " ".charCodeAt(0)) {
- // Pause/Resume every selected download
- for (let element of selectedElements) {
- if (element._shell.isCommandEnabled("downloadsCmd_pauseResume"))
- element._shell.doCommand("downloadsCmd_pauseResume");
- }
- }
- },
-
- onDoubleClick: function DPV_onDoubleClick(aEvent) {
- if (aEvent.button != 0)
- return;
-
- let selectedElements = this._richlistbox.selectedItems;
- if (selectedElements.length != 1)
- return;
-
- let element = selectedElements[0];
- if (element._shell)
- element._shell.doDefaultCommand();
- },
-
- onScroll: function DPV_onScroll() {
- this._ensureVisibleElementsAreActive();
- },
-
- onSelect: function DPV_onSelect() {
- goUpdateDownloadCommands();
-
- let selectedElements = this._richlistbox.selectedItems;
- for (let elt of selectedElements) {
- if (elt._shell)
- elt._shell.onSelect();
- }
- },
-
- onDragStart: function DPV_onDragStart(aEvent) {
- // TODO Bug 831358: Support d&d for multiple selection.
- // For now, we just drag the first element.
- let selectedItem = this._richlistbox.selectedItem;
- if (!selectedItem)
- return;
-
- let targetPath = selectedItem._shell.download.target.path;
- if (!targetPath) {
- return;
- }
-
- // We must check for existence synchronously because this is a DOM event.
- let file = new FileUtils.File(targetPath);
- if (!file.exists())
- return;
-
- let dt = aEvent.dataTransfer;
- dt.mozSetDataAt("application/x-moz-file", file, 0);
- let url = Services.io.newFileURI(file).spec;
- dt.setData("text/uri-list", url);
- dt.setData("text/plain", url);
- dt.effectAllowed = "copyMove";
- dt.addElement(selectedItem);
- },
-
- onDragOver: function DPV_onDragOver(aEvent) {
- let types = aEvent.dataTransfer.types;
- if (types.contains("text/uri-list") ||
- types.contains("text/x-moz-url") ||
- types.contains("text/plain")) {
- aEvent.preventDefault();
- }
- },
-
- onDrop: function DPV_onDrop(aEvent) {
- let dt = aEvent.dataTransfer;
- // If dragged item is from our source, do not try to
- // redownload already downloaded file.
- if (dt.mozGetDataAt("application/x-moz-file", 0))
- return;
-
- let links = Services.droppedLinkHandler.dropLinks(aEvent);
- if (!links.length)
- return;
- let browserWin = RecentWindow.getMostRecentBrowserWindow();
- let initiatingDoc = browserWin ? browserWin.document : document;
- for (let link of links) {
- if (link.url.startsWith("about:"))
- continue;
- DownloadURL(link.url, link.name, initiatingDoc);
- }
- }
-};
-
-for (let methodName of ["load", "applyFilter", "selectNode", "selectItems"]) {
- DownloadsPlacesView.prototype[methodName] = function() {
- throw new Error("|" + methodName + "| is not implemented by the downloads view.");
- }
-}
-
-function goUpdateDownloadCommands() {
- for (let command of DOWNLOAD_VIEW_SUPPORTED_COMMANDS) {
- goUpdateCommand(command);
- }
-}
diff --git a/components/downloads/content/allDownloadsViewOverlay.xul b/components/downloads/content/allDownloadsViewOverlay.xul
deleted file mode 100644
index 4e9bfd1..0000000
--- a/components/downloads/content/allDownloadsViewOverlay.xul
+++ /dev/null
@@ -1,119 +0,0 @@
-<?xml version="1.0"?>
-
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-<?xml-stylesheet href="chrome://browser/content/downloads/allDownloadsViewOverlay.css"?>
-<?xml-stylesheet href="chrome://browser/skin/downloads/allDownloadsViewOverlay.css"?>
-
-<!DOCTYPE overlay [
-<!ENTITY % downloadsDTD SYSTEM "chrome://browser/locale/downloads/downloads.dtd">
-%downloadsDTD;
-]>
-
-<!-- This overlay provides a downloads view that lists both session downloads,
- using the DownloadsView API, and history downloads, using places queries.
- The view also implements a command controller and a context menu for
- managing the downloads list. In order to use this view:
- 1. Apply this overlay to your window.
- 2. Insert in all the overlay entry-points, namely:
- <richlistbox id="downloadsRichListBox"/>
- <commandset id="downloadCommands"/>
- <menupopup id="downloadsContextMenu"/>
- 3. Make sure your window has the editMenuOverlay overlay applied,
- because the view implements cmd_copy and cmd_delete.
- 4. Make sure your window has the globalOverlay.js script loaded.
- 5. To initialize the view
- let view = new DownloadsPlacesView(document.getElementById("downloadsRichListBox"));
- // This is what the Places Library uses. It could be tweaked a bit as long as the
- // transition-type is set correctly
- view.place = "place:transition=7&sort=4";
--->
-<overlay id="downloadsViewOverlay"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-
- <script type="application/javascript"
- src="chrome://browser/content/downloads/allDownloadsViewOverlay.js"/>
- <script type="application/javascript"
- src="chrome://global/content/contentAreaUtils.js"/>
-
- <richlistbox flex="1"
- seltype="multiple"
- id="downloadsRichListBox" context="downloadsContextMenu"
- onscroll="return this._placesView.onScroll();"
- onkeypress="return this._placesView.onKeyPress(event);"
- ondblclick="return this._placesView.onDoubleClick(event);"
- oncontextmenu="return this._placesView.onContextMenu(event);"
- ondragstart="this._placesView.onDragStart(event);"
- ondragover="this._placesView.onDragOver(event);"
- ondrop="this._placesView.onDrop(event);"
- onfocus="goUpdateDownloadCommands();"
- onselect="this._placesView.onSelect();"
- onblur="goUpdateDownloadCommands();"/>
-
- <commandset id="downloadCommands"
- commandupdater="true"
- events="focus,select,contextmenu"
- oncommandupdate="goUpdateDownloadCommands();">
- <command id="downloadsCmd_pauseResume"
- oncommand="goDoCommand('downloadsCmd_pauseResume')"/>
- <command id="downloadsCmd_cancel"
- oncommand="goDoCommand('downloadsCmd_cancel')"/>
- <command id="downloadsCmd_open"
- oncommand="goDoCommand('downloadsCmd_open')"/>
- <command id="downloadsCmd_show"
- oncommand="goDoCommand('downloadsCmd_show')"/>
- <command id="downloadsCmd_retry"
- oncommand="goDoCommand('downloadsCmd_retry')"/>
- <command id="downloadsCmd_openReferrer"
- oncommand="goDoCommand('downloadsCmd_openReferrer')"/>
- <command id="downloadsCmd_clearDownloads"
- oncommand="goDoCommand('downloadsCmd_clearDownloads')"/>
- </commandset>
-
- <menupopup id="downloadsContextMenu" class="download-state">
- <menuitem command="downloadsCmd_pauseResume"
- class="downloadPauseMenuItem"
- label="&cmd.pause.label;"
- accesskey="&cmd.pause.accesskey;"/>
- <menuitem command="downloadsCmd_pauseResume"
- class="downloadResumeMenuItem"
- label="&cmd.resume.label;"
- accesskey="&cmd.resume.accesskey;"/>
- <menuitem command="downloadsCmd_cancel"
- class="downloadCancelMenuItem"
- label="&cmd.cancel.label;"
- accesskey="&cmd.cancel.accesskey;"/>
- <menuitem command="cmd_delete"
- class="downloadRemoveFromHistoryMenuItem"
- label="&cmd.removeFromHistory.label;"
- accesskey="&cmd.removeFromHistory.accesskey;"/>
- <menuitem command="downloadsCmd_show"
- class="downloadShowMenuItem"
-#ifdef XP_MACOSX
- label="&cmd.showMac.label;"
- accesskey="&cmd.showMac.accesskey;"
-#else
- label="&cmd.show.label;"
- accesskey="&cmd.show.accesskey;"
-#endif
- />
-
- <menuseparator class="downloadCommandsSeparator"/>
-
- <menuitem command="downloadsCmd_openReferrer"
- label="&cmd.goToDownloadPage.label;"
- accesskey="&cmd.goToDownloadPage.accesskey;"/>
- <menuitem command="cmd_copy"
- label="&cmd.copyDownloadLink.label;"
- accesskey="&cmd.copyDownloadLink.accesskey;"/>
-
- <menuseparator/>
-
- <menuitem command="downloadsCmd_clearDownloads"
- label="&cmd.clearDownloads.label;"
- accesskey="&cmd.clearDownloads.accesskey;"/>
- </menupopup>
-</overlay>
diff --git a/components/downloads/content/contentAreaDownloadsView.css b/components/downloads/content/contentAreaDownloadsView.css
deleted file mode 100644
index abaae1f..0000000
--- a/components/downloads/content/contentAreaDownloadsView.css
+++ /dev/null
@@ -1,11 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#downloadsListEmptyDescription {
- display: none;
-}
-
-#downloadsRichListBox:empty + #downloadsListEmptyDescription {
- display: -moz-box;
-}
diff --git a/components/downloads/content/contentAreaDownloadsView.js b/components/downloads/content/contentAreaDownloadsView.js
deleted file mode 100644
index fbb18ab..0000000
--- a/components/downloads/content/contentAreaDownloadsView.js
+++ /dev/null
@@ -1,15 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
-
-var ContentAreaDownloadsView = {
- init: function CADV_init() {
- let view = new DownloadsPlacesView(document.getElementById("downloadsRichListBox"));
- // Do not display the Places downloads in private windows
- if (!PrivateBrowsingUtils.isWindowPrivate(window)) {
- view.place = "place:transition=7&sort=4";
- }
- }
-};
diff --git a/components/downloads/content/contentAreaDownloadsView.xul b/components/downloads/content/contentAreaDownloadsView.xul
deleted file mode 100644
index a91de1e..0000000
--- a/components/downloads/content/contentAreaDownloadsView.xul
+++ /dev/null
@@ -1,45 +0,0 @@
-<?xml version="1.0"?>
-
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-<?xml-stylesheet href="chrome://global/skin/"?>
-<?xml-stylesheet href="chrome://browser/content/downloads/contentAreaDownloadsView.css"?>
-<?xml-stylesheet href="chrome://browser/skin/downloads/contentAreaDownloadsView.css"?>
-
-<?xul-overlay href="chrome://browser/content/downloads/allDownloadsViewOverlay.xul"?>
-
-<?xul-overlay href="chrome://global/content/editMenuOverlay.xul"?>
-
-<!DOCTYPE window [
-<!ENTITY % downloadsDTD SYSTEM "chrome://browser/locale/downloads/downloads.dtd">
-%downloadsDTD;
-]>
-
-<window id="contentAreaDownloadsView"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- title="&downloads.title;"
- onload="ContentAreaDownloadsView.init();">
-
- <script type="application/javascript"
- src="chrome://global/content/globalOverlay.js"/>
- <script type="application/javascript"
- src="chrome://browser/content/downloads/contentAreaDownloadsView.js"/>
-
- <commandset id="editMenuCommands"/>
-
- <keyset id="editMenuKeys">
-#ifdef XP_MACOSX
- <key id="key_delete2" keycode="VK_BACK" command="cmd_delete"/>
-#endif
- </keyset>
-
- <stack flex="1">
- <richlistbox id="downloadsRichListBox"/>
- <description id="downloadsListEmptyDescription"
- value="&downloadsListEmpty.label;"/>
- </stack>
- <commandset id="downloadCommands"/>
- <menupopup id="downloadsContextMenu"/>
-</window>
diff --git a/components/downloads/content/download.css b/components/downloads/content/download.css
deleted file mode 100644
index 7412fa7..0000000
--- a/components/downloads/content/download.css
+++ /dev/null
@@ -1,45 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-richlistitem.download button {
- /* These buttons should never get focus, as that would "disable"
- the downloads view controller (it's only used when the richlistbox
- is focused). */
- -moz-user-focus: none;
-}
-
-/*** Visibility of controls inside download items ***/
-
-.download-state:-moz-any( [state="6"], /* Blocked (parental) */
- [state="8"], /* Blocked (dirty) */
- [state="9"]) /* Blocked (policy) */
- > .downloadTypeIcon:not(.blockedIcon),
-
-.download-state:not(:-moz-any([state="6"], /* Blocked (parental) */
- [state="8"], /* Blocked (dirty) */
- [state="9"]) /* Blocked (policy) */)
- > .downloadTypeIcon.blockedIcon,
-
-.download-state:not(:-moz-any([state="-1"],/* Starting (initial) */
- [state="5"], /* Starting (queued) */
- [state="0"], /* Downloading */
- [state="4"], /* Paused */
- [state="7"]) /* Scanning */)
- > vbox > .downloadProgress,
-
-.download-state:not(:-moz-any([state="-1"],/* Starting (initial) */
- [state="5"], /* Starting (queued) */
- [state="0"], /* Downloading */
- [state="4"]) /* Paused */)
- > .downloadCancel,
-
-.download-state[state]:not(:-moz-any([state="2"], /* Failed */
- [state="3"]) /* Canceled */)
- > .downloadRetry,
-
-.download-state:not( [state="1"] /* Finished */)
- > .downloadShow
-{
- display: none;
-}
diff --git a/components/downloads/content/download.xml b/components/downloads/content/download.xml
deleted file mode 100644
index 542901b..0000000
--- a/components/downloads/content/download.xml
+++ /dev/null
@@ -1,188 +0,0 @@
-<?xml version="1.0"?>
-<!-- -*- Mode: HTML; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- -->
-<!-- vim: set ts=2 et sw=2 tw=80: -->
-
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this file,
- - You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!DOCTYPE bindings SYSTEM "chrome://browser/locale/downloads/downloads.dtd">
-
-<bindings id="downloadBindings"
- xmlns="http://www.mozilla.org/xbl"
- xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:xbl="http://www.mozilla.org/xbl">
-
- <binding id="download"
- extends="chrome://global/content/bindings/richlistbox.xml#richlistitem">
- <content orient="horizontal"
- align="center"
- onclick="DownloadsView.onDownloadClick(event);">
- <xul:image class="downloadTypeIcon"
- validate="always"
- xbl:inherits="src=image"/>
- <xul:image class="downloadTypeIcon blockedIcon"/>
- <xul:vbox pack="center"
- flex="1"
- class="downloadContainer"
- style="width: &downloadDetails.width;">
- <!-- We're letting localizers put a min-width in here primarily
- because of the downloads summary at the bottom of the list of
- download items. An element in the summary has the same min-width
- on a description, and we don't want the panel to change size if the
- summary isn't being displayed, so we ensure that items share the
- same minimum width.
- -->
- <xul:description class="downloadDisplayName"
- crop="center"
- style="min-width: &downloadsSummary.minWidth2;"
- xbl:inherits="value=displayName,tooltiptext=displayName"/>
- <xul:progressmeter anonid="progressmeter"
- class="downloadProgress"
- min="0"
- max="100"
- xbl:inherits="mode=progressmode,value=progress"/>
- <xul:description class="downloadDetails"
- crop="end"
- xbl:inherits="value=status,tooltiptext=statusTip"/>
- </xul:vbox>
- <xul:stack>
- <xul:button class="downloadButton downloadCancel"
- tooltiptext="&cmd.cancel.label;"
- oncommand="DownloadsView.onDownloadCommand(event, 'downloadsCmd_cancel');"/>
- <xul:button class="downloadButton downloadRetry"
- tooltiptext="&cmd.retry.label;"
- oncommand="DownloadsView.onDownloadCommand(event, 'downloadsCmd_retry');"/>
- <xul:button class="downloadButton downloadShow"
-#ifdef XP_MACOSX
- tooltiptext="&cmd.showMac.label;"
-#else
- tooltiptext="&cmd.show.label;"
-#endif
- oncommand="DownloadsView.onDownloadCommand(event, 'downloadsCmd_show');"/>
- </xul:stack>
- </content>
- </binding>
-
- <binding id="download-in-progress"
- extends="chrome://global/content/bindings/richlistbox.xml#richlistitem">
- <content orient="horizontal"
- align="center"
- onclick="DownloadsView.onDownloadClick(event);">
- <xul:image class="downloadTypeIcon"
- validate="always"
- xbl:inherits="src=image"/>
- <xul:image class="downloadTypeIcon blockedIcon"/>
- <xul:vbox pack="center"
- flex="1"
- class="downloadContainer"
- style="width: &downloadDetails.width;">
- <xul:description class="downloadDisplayName"
- crop="center"
- style="min-width: &downloadsSummary.minWidth2;"
- xbl:inherits="value=displayName,tooltiptext=extendedDisplayNameTip"/>
- <xul:progressmeter anonid="progressmeter"
- class="downloadProgress"
- min="0"
- max="100"
- xbl:inherits="mode=progressmode,value=progress"/>
- <xul:description class="downloadDetails"
- crop="end"
- xbl:inherits="value=status,tooltiptext=statusTip"/>
- </xul:vbox>
- <xul:stack>
- <xul:button class="downloadButton downloadCancel"
- tooltiptext="&cmd.cancel.label;"
- oncommand="DownloadsView.onDownloadCommand(event, 'downloadsCmd_cancel');"/>
- <xul:button class="downloadButton downloadRetry"
- tooltiptext="&cmd.retry.label;"
- oncommand="DownloadsView.onDownloadCommand(event, 'downloadsCmd_retry');"/>
- <xul:button class="downloadButton downloadShow"
- tooltiptext="&cmd.show.label;"
- oncommand="DownloadsView.onDownloadCommand(event, 'downloadsCmd_show');"/>
- </xul:stack>
- </content>
- </binding>
-
- <binding id="download-full-ui"
- extends="chrome://global/content/bindings/richlistbox.xml#richlistitem">
- <resources>
- <stylesheet src="chrome://browser/content/downloads/download.css"/>
- </resources>
-
- <content orient="horizontal" align="center">
- <xul:image class="downloadTypeIcon"
- validate="always"
- xbl:inherits="src=image"/>
- <xul:image class="downloadTypeIcon blockedIcon"/>
- <xul:vbox pack="center" flex="1">
- <xul:description class="downloadDisplayName"
- crop="center"
- xbl:inherits="value=displayName,tooltiptext=displayName"/>
- <xul:progressmeter anonid="progressmeter"
- class="downloadProgress"
- min="0"
- max="100"
- xbl:inherits="mode=progressmode,value=progress"/>
- <xul:description class="downloadDetails"
- style="width: &downloadDetails.width;"
- crop="end"
- xbl:inherits="value=status,tooltiptext=statusTip"/>
- </xul:vbox>
-
- <xul:button class="downloadButton downloadCancel"
- tooltiptext="&cmd.cancel.label;"
- oncommand="goDoCommand('downloadsCmd_cancel')"/>
- <xul:button class="downloadButton downloadRetry"
- tooltiptext="&cmd.retry.label;"
- oncommand="goDoCommand('downloadsCmd_retry')"/>
- <xul:button class="downloadButton downloadShow"
-#ifdef XP_MACOSX
- tooltiptext="&cmd.showMac.label;"
-#else
- tooltiptext="&cmd.show.label;"
-#endif
- oncommand="goDoCommand('downloadsCmd_show')"/>
-
- </content>
- </binding>
-
- <binding id="download-in-progress-full-ui"
- extends="chrome://global/content/bindings/richlistbox.xml#richlistitem">
- <resources>
- <stylesheet src="chrome://browser/content/downloads/download.css"/>
- </resources>
-
- <content orient="horizontal" align="center">
- <xul:image class="downloadTypeIcon"
- validate="always"
- xbl:inherits="src=image"/>
- <xul:image class="downloadTypeIcon blockedIcon"/>
- <xul:vbox pack="center" flex="1">
- <xul:description class="downloadDisplayName"
- crop="end"
- xbl:inherits="value=extendedDisplayName,tooltiptext=extendedDisplayNameTip"/>
- <xul:progressmeter anonid="progressmeter"
- class="downloadProgress"
- min="0"
- max="100"
- xbl:inherits="mode=progressmode,value=progress"/>
- <xul:description class="downloadDetails"
- style="width: &downloadDetails.width;"
- crop="end"
- xbl:inherits="value=status,tooltiptext=statusTip"/>
- </xul:vbox>
-
- <xul:button class="downloadButton downloadCancel"
- tooltiptext="&cmd.cancel.label;"
- oncommand="goDoCommand('downloadsCmd_cancel')"/>
- <xul:button class="downloadButton downloadRetry"
- tooltiptext="&cmd.retry.label;"
- oncommand="goDoCommand('downloadsCmd_retry')"/>
- <xul:button class="downloadButton downloadShow"
- tooltiptext="&cmd.show.label;"
- oncommand="goDoCommand('downloadsCmd_show')"/>
-
- </content>
- </binding>
-</bindings>
diff --git a/components/downloads/content/downloads.css b/components/downloads/content/downloads.css
deleted file mode 100644
index 825db68..0000000
--- a/components/downloads/content/downloads.css
+++ /dev/null
@@ -1,132 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/*** Download items ***/
-
-richlistitem[type="download"] {
- -moz-binding: url('chrome://browser/content/downloads/download.xml#download');
-}
-
-richlistitem[type="download"]:-moz-any([state="-1"],/* Starting (initial) */
- [state="0"], /* Downloading */
- [state="4"], /* Paused */
- [state="5"], /* Starting (queued) */
- [state="7"]) /* Scanning */
-{
- -moz-binding: url('chrome://browser/content/downloads/download.xml#download-in-progress');
-}
-
-richlistitem[type="download"]:not([selected]) button {
- /* Only focus buttons in the selected item. */
- -moz-user-focus: none;
-}
-
-/*** Visibility of controls inside download items ***/
-
-.download-state:-moz-any( [state="6"], /* Blocked (parental) */
- [state="8"], /* Blocked (dirty) */
- [state="9"]) /* Blocked (policy) */
- .downloadTypeIcon:not(.blockedIcon),
-
-.download-state:not(:-moz-any([state="6"], /* Blocked (parental) */
- [state="8"], /* Blocked (dirty) */
- [state="9"]) /* Blocked (policy) */)
- .downloadTypeIcon.blockedIcon,
-
-.download-state:not(:-moz-any([state="-1"],/* Starting (initial) */
- [state="0"], /* Downloading */
- [state="4"], /* Paused */
- [state="5"], /* Starting (queued) */
- [state="7"]) /* Scanning */)
- .downloadProgress,
-
-.download-state:not( [state="0"] /* Downloading */)
- .downloadPauseMenuItem,
-
-.download-state:not( [state="4"] /* Paused */)
- .downloadResumeMenuItem,
-
-.download-state:not(:-moz-any([state="2"], /* Failed */
- [state="4"]) /* Paused */)
- .downloadCancelMenuItem,
-
-.download-state:not(:-moz-any([state="1"], /* Finished */
- [state="2"], /* Failed */
- [state="3"], /* Canceled */
- [state="6"], /* Blocked (parental) */
- [state="8"], /* Blocked (dirty) */
- [state="9"]) /* Blocked (policy) */)
- .downloadRemoveFromHistoryMenuItem,
-
-.download-state:not(:-moz-any([state="-1"],/* Starting (initial) */
- [state="0"], /* Downloading */
- [state="1"], /* Finished */
- [state="4"], /* Paused */
- [state="5"]) /* Starting (queued) */)
- .downloadShowMenuItem,
-
-.download-state[state="7"] /* Scanning */ .downloadCommandsSeparator
-
-{
- display: none;
-}
-
-/*** Visibility of download buttons and indicator controls. ***/
-
-.download-state:not(:-moz-any([state="-1"],/* Starting (initial) */
- [state="0"], /* Downloading */
- [state="4"], /* Paused */
- [state="5"]) /* Starting (queued) */)
- .downloadCancel,
-
-.download-state:not(:-moz-any([state="2"], /* Failed */
- [state="3"]) /* Canceled */)
- .downloadRetry,
-
-.download-state:not( [state="1"] /* Finished */)
- .downloadShow,
-
-#downloads-indicator:-moz-any([progress],
- [counter],
- [paused]) #downloads-indicator-icon,
-
-#downloads-indicator:not(:-moz-any([progress],
- [counter],
- [paused]))
- #downloads-indicator-progress-area
-
-{
- visibility: hidden;
-}
-
-.download-state[state="1"]:not([exists]) .downloadShow
-{
- display: none;
-}
-
-#downloadsSummary:not([inprogress]) > vbox > #downloadsSummaryProgress,
-#downloadsSummary:not([inprogress]) > vbox > #downloadsSummaryDetails,
-#downloadsFooter[showingsummary] > #downloadsHistory,
-#downloadsFooter:not([showingsummary]) > #downloadsSummary
-{
- display: none;
-}
-
-/* Hacks for toolbar full and text modes, until bug 573329 removes them */
-
-toolbar[mode="text"] > #downloads-indicator {
- display: -moz-box;
- -moz-box-orient: vertical;
- -moz-box-pack: center;
-}
-
-toolbar[mode="text"] > #downloads-indicator > .toolbarbutton-text {
- -moz-box-ordinal-group: 1;
-}
-
-toolbar[mode="text"] > #downloads-indicator > .toolbarbutton-icon {
- display: -moz-box;
- -moz-box-ordinal-group: 2;
- visibility: collapse;
-}
diff --git a/components/downloads/content/downloads.js b/components/downloads/content/downloads.js
deleted file mode 100644
index ee1c690..0000000
--- a/components/downloads/content/downloads.js
+++ /dev/null
@@ -1,1614 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-var { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "DownloadsCommon",
- "resource:///modules/DownloadsCommon.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "DownloadsViewUI",
- "resource:///modules/DownloadsViewUI.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
- "resource://gre/modules/FileUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
- "resource://gre/modules/NetUtil.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
- "resource://gre/modules/PlacesUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "Services",
- "resource://gre/modules/Services.jsm");
-
-/**
- * Handles the Downloads panel user interface for each browser window.
- *
- * This file includes the following constructors and global objects:
- *
- * DownloadsPanel
- * Main entry point for the downloads panel interface.
- *
- * DownloadsOverlayLoader
- * Allows loading the downloads panel and the status indicator interfaces on
- * demand, to improve startup performance.
- *
- * DownloadsView
- * Builds and updates the downloads list widget, responding to changes in the
- * download state and real-time data. In addition, handles part of the user
- * interaction events raised by the downloads list widget.
- *
- * DownloadsViewItem
- * Builds and updates a single item in the downloads list widget, responding to
- * changes in the download state and real-time data.
- *
- * DownloadsViewController
- * Handles part of the user interaction events raised by the downloads list
- * widget, in particular the "commands" that apply to multiple items, and
- * dispatches the commands that apply to individual items.
- *
- * DownloadsViewItemController
- * Handles all the user interaction events, in particular the "commands",
- * related to a single item in the downloads list widgets.
- */
-
-/**
- * A few words on focus and focusrings
- *
- * We do quite a few hacks in the Downloads Panel for focusrings. In fact, we
- * basically suppress most if not all XUL-level focusrings, and style/draw
- * them ourselves (using :focus instead of -moz-focusring). There are a few
- * reasons for this:
- *
- * 1) Richlists on OSX don't have focusrings; instead, they are shown as
- * selected. This makes for some ambiguity when we have a focused/selected
- * item in the list, and the mouse is hovering a completed download (which
- * highlights).
- * 2) Windows doesn't show focusrings until after the first time that tab is
- * pressed (and by then you're focusing the second item in the panel).
- * 3) Richlistbox sets -moz-focusring even when we select it with a mouse.
- *
- * In general, the desired behaviour is to focus the first item after pressing
- * tab/down, and show that focus with a ring. Then, if the mouse moves over
- * the panel, to hide that focus ring; essentially resetting us to the state
- * before pressing the key.
- *
- * We end up capturing the tab/down key events, and preventing their default
- * behaviour. We then set a "keyfocus" attribute on the panel, which allows
- * us to draw a ring around the currently focused element. If the panel is
- * closed or the mouse moves over the panel, we remove the attribute.
- */
-
-"use strict";
-
-////////////////////////////////////////////////////////////////////////////////
-//// DownloadsPanel
-
-/**
- * Main entry point for the downloads panel interface.
- */
-const DownloadsPanel = {
- //////////////////////////////////////////////////////////////////////////////
- //// Initialization and termination
-
- /**
- * Internal state of the downloads panel, based on one of the kState
- * constants. This is not the same state as the XUL panel element.
- */
- _state: 0,
-
- /** The panel is not linked to downloads data yet. */
- get kStateUninitialized() 0,
- /** This object is linked to data, but the panel is invisible. */
- get kStateHidden() 1,
- /** The panel will be shown as soon as possible. */
- get kStateWaitingData() 2,
- /** The panel is almost shown - we're just waiting to get a handle on the
- anchor. */
- get kStateWaitingAnchor() 3,
- /** The panel is open. */
- get kStateShown() 4,
-
- /**
- * Location of the panel overlay.
- */
- get kDownloadsOverlay()
- "chrome://browser/content/downloads/downloadsOverlay.xul",
-
- /**
- * Starts loading the download data in background, without opening the panel.
- * Use showPanel instead to load the data and open the panel at the same time.
- *
- * @param aCallback
- * Called when initialization is complete.
- */
- initialize: function DP_initialize(aCallback)
- {
- DownloadsCommon.log("Attempting to initialize DownloadsPanel for a window.");
- if (this._state != this.kStateUninitialized) {
- DownloadsCommon.log("DownloadsPanel is already initialized.");
- DownloadsOverlayLoader.ensureOverlayLoaded(this.kDownloadsOverlay,
- aCallback);
- return;
- }
- this._state = this.kStateHidden;
-
- window.addEventListener("unload", this.onWindowUnload, false);
-
- // Ensure that the Download Manager service is running. This resumes
- // active downloads if required. If there are downloads to be shown in the
- // panel, starting the service will make us load their data asynchronously.
- DownloadsCommon.initializeAllDataLinks();
-
-
- // Now that data loading has eventually started, load the required XUL
- // elements and initialize our views.
- DownloadsCommon.log("Ensuring DownloadsPanel overlay loaded.");
- DownloadsOverlayLoader.ensureOverlayLoaded(this.kDownloadsOverlay,
- function DP_I_callback() {
- DownloadsViewController.initialize();
- DownloadsCommon.log("Attaching DownloadsView...");
- DownloadsCommon.getData(window).addView(DownloadsView);
- DownloadsCommon.getSummary(window, DownloadsView.kItemCountLimit)
- .addView(DownloadsSummary);
- DownloadsCommon.log("DownloadsView attached - the panel for this window",
- "should now see download items come in.");
- DownloadsPanel._attachEventListeners();
- DownloadsCommon.log("DownloadsPanel initialized.");
- aCallback();
- });
- },
-
- /**
- * Closes the downloads panel and frees the internal resources related to the
- * downloads. The downloads panel can be reopened later, even after this
- * function has been called.
- */
- terminate: function DP_terminate()
- {
- DownloadsCommon.log("Attempting to terminate DownloadsPanel for a window.");
- if (this._state == this.kStateUninitialized) {
- DownloadsCommon.log("DownloadsPanel was never initialized. Nothing to do.");
- return;
- }
-
- window.removeEventListener("unload", this.onWindowUnload, false);
-
- // Ensure that the panel is closed before shutting down.
- this.hidePanel();
-
- DownloadsViewController.terminate();
- DownloadsCommon.getData(window).removeView(DownloadsView);
- DownloadsCommon.getSummary(window, DownloadsView.kItemCountLimit)
- .removeView(DownloadsSummary);
- this._unattachEventListeners();
-
- this._state = this.kStateUninitialized;
-
- DownloadsSummary.active = false;
- DownloadsCommon.log("DownloadsPanel terminated.");
- },
-
- //////////////////////////////////////////////////////////////////////////////
- //// Panel interface
-
- /**
- * Main panel element in the browser window, or null if the panel overlay
- * hasn't been loaded yet.
- */
- get panel()
- {
- // If the downloads panel overlay hasn't loaded yet, just return null
- // without resetting this.panel.
- let downloadsPanel = document.getElementById("downloadsPanel");
- if (!downloadsPanel)
- return null;
-
- delete this.panel;
- return this.panel = downloadsPanel;
- },
-
- /**
- * Starts opening the downloads panel interface, anchored to the downloads
- * button of the browser window. The list of downloads to display is
- * initialized the first time this method is called, and the panel is shown
- * only when data is ready.
- */
- showPanel: function DP_showPanel()
- {
- DownloadsCommon.log("Opening the downloads panel.");
-
- if (this.isPanelShowing) {
- DownloadsCommon.log("Panel is already showing - focusing instead.");
- this._focusPanel();
- return;
- }
-
- this.initialize(function DP_SP_callback() {
- // Delay displaying the panel because this function will sometimes be
- // called while another window is closing (like the window for selecting
- // whether to save or open the file), and that would cause the panel to
- // close immediately.
- setTimeout(function () DownloadsPanel._openPopupIfDataReady(), 0);
- }.bind(this));
-
- DownloadsCommon.log("Waiting for the downloads panel to appear.");
- this._state = this.kStateWaitingData;
- },
-
- /**
- * Hides the downloads panel, if visible, but keeps the internal state so that
- * the panel can be reopened quickly if required.
- */
- hidePanel: function DP_hidePanel()
- {
- DownloadsCommon.log("Closing the downloads panel.");
-
- if (!this.isPanelShowing) {
- DownloadsCommon.log("Downloads panel is not showing - nothing to do.");
- return;
- }
-
- this.panel.hidePopup();
-
- // Ensure that we allow the panel to be reopened. Note that, if the popup
- // was open, then the onPopupHidden event handler has already updated the
- // current state, otherwise we must update the state ourselves.
- this._state = this.kStateHidden;
- DownloadsCommon.log("Downloads panel is now closed.");
- },
-
- /**
- * Indicates whether the panel is shown or will be shown.
- */
- get isPanelShowing()
- {
- return this._state == this.kStateWaitingData ||
- this._state == this.kStateWaitingAnchor ||
- this._state == this.kStateShown;
- },
-
- /**
- * Returns whether the user has started keyboard navigation.
- */
- get keyFocusing()
- {
- return this.panel.hasAttribute("keyfocus");
- },
-
- /**
- * Set to true if the user has started keyboard navigation, and we should be
- * showing focusrings in the panel. Also adds a mousemove event handler to
- * the panel which disables keyFocusing.
- */
- set keyFocusing(aValue)
- {
- if (aValue) {
- this.panel.setAttribute("keyfocus", "true");
- this.panel.addEventListener("mousemove", this);
- } else {
- this.panel.removeAttribute("keyfocus");
- this.panel.removeEventListener("mousemove", this);
- }
- return aValue;
- },
-
- /**
- * Handles the mousemove event for the panel, which disables focusring
- * visualization.
- */
- handleEvent: function DP_handleEvent(aEvent)
- {
- if (aEvent.type == "mousemove") {
- this.keyFocusing = false;
- }
- },
-
- //////////////////////////////////////////////////////////////////////////////
- //// Callback functions from DownloadsView
-
- /**
- * Called after data loading finished.
- */
- onViewLoadCompleted: function DP_onViewLoadCompleted()
- {
- this._openPopupIfDataReady();
- },
-
- //////////////////////////////////////////////////////////////////////////////
- //// User interface event functions
-
- onWindowUnload: function DP_onWindowUnload()
- {
- // This function is registered as an event listener, we can't use "this".
- DownloadsPanel.terminate();
- },
-
- onPopupShown: function DP_onPopupShown(aEvent)
- {
- // Ignore events raised by nested popups.
- if (aEvent.target != aEvent.currentTarget) {
- return;
- }
-
- DownloadsCommon.log("Downloads panel has shown.");
- this._state = this.kStateShown;
-
- // Since at most one popup is open at any given time, we can set globally.
- DownloadsCommon.getIndicatorData(window).attentionSuppressed = true;
-
- // Ensure that the first item is selected when the panel is focused.
- if (DownloadsView.richListBox.itemCount > 0 &&
- DownloadsView.richListBox.selectedIndex == -1) {
- DownloadsView.richListBox.selectedIndex = 0;
- }
-
- this._focusPanel();
- },
-
- onPopupHidden: function DP_onPopupHidden(aEvent)
- {
- // Ignore events raised by nested popups.
- if (aEvent.target != aEvent.currentTarget) {
- return;
- }
-
- DownloadsCommon.log("Downloads panel has hidden.");
-
- // Removes the keyfocus attribute so that we stop handling keyboard
- // navigation.
- this.keyFocusing = false;
-
- // Since at most one popup is open at any given time, we can set globally.
- DownloadsCommon.getIndicatorData(window).attentionSuppressed = false;
-
- // Allow the anchor to be hidden.
- DownloadsButton.releaseAnchor();
-
- // Allow the panel to be reopened.
- this._state = this.kStateHidden;
- },
-
- //////////////////////////////////////////////////////////////////////////////
- //// Related operations
-
- /**
- * Shows or focuses the user interface dedicated to downloads history.
- */
- showDownloadsHistory: function DP_showDownloadsHistory()
- {
- DownloadsCommon.log("Showing download history.");
- // Hide the panel before showing another window, otherwise focus will return
- // to the browser window when the panel closes automatically.
- this.hidePanel();
-
- BrowserDownloadsUI();
- },
-
- //////////////////////////////////////////////////////////////////////////////
- //// Internal functions
-
- /**
- * Attach event listeners to a panel element. These listeners should be
- * removed in _unattachEventListeners. This is called automatically after the
- * panel has successfully loaded.
- */
- _attachEventListeners: function DP__attachEventListeners()
- {
- // Handle keydown to support accel-V.
- this.panel.addEventListener("keydown", this._onKeyDown.bind(this), false);
- // Handle keypress to be able to preventDefault() events before they reach
- // the richlistbox, for keyboard navigation.
- this.panel.addEventListener("keypress", this._onKeyPress.bind(this), false);
- },
-
- /**
- * Unattach event listeners that were added in _attachEventListeners. This
- * is called automatically on panel termination.
- */
- _unattachEventListeners: function DP__unattachEventListeners()
- {
- this.panel.removeEventListener("keydown", this._onKeyDown.bind(this),
- false);
- this.panel.removeEventListener("keypress", this._onKeyPress.bind(this),
- false);
- },
-
- _onKeyPress: function DP__onKeyPress(aEvent)
- {
- // Handle unmodified keys only.
- if (aEvent.altKey || aEvent.ctrlKey || aEvent.shiftKey || aEvent.metaKey) {
- return;
- }
-
- let richListBox = DownloadsView.richListBox;
-
- // If the user has pressed the tab, up, or down cursor key, start keyboard
- // navigation, thus enabling focusrings in the panel. Keyboard navigation
- // is automatically disabled if the user moves the mouse on the panel, or
- // if the panel is closed.
- if ((aEvent.keyCode == Ci.nsIDOMKeyEvent.DOM_VK_TAB ||
- aEvent.keyCode == Ci.nsIDOMKeyEvent.DOM_VK_UP ||
- aEvent.keyCode == Ci.nsIDOMKeyEvent.DOM_VK_DOWN) &&
- !this.keyFocusing) {
- this.keyFocusing = true;
- // Ensure there's a selection, we will show the focus ring around it and
- // prevent the richlistbox from changing the selection.
- if (DownloadsView.richListBox.selectedIndex == -1)
- DownloadsView.richListBox.selectedIndex = 0;
- aEvent.preventDefault();
- return;
- }
-
- if (aEvent.keyCode == Ci.nsIDOMKeyEvent.DOM_VK_DOWN) {
- // If the last element in the list is selected, or the footer is already
- // focused, focus the footer.
- if (richListBox.selectedItem === richListBox.lastChild ||
- document.activeElement.parentNode.id === "downloadsFooter") {
- DownloadsFooter.focus();
- aEvent.preventDefault();
- return;
- }
- }
-
- // Pass keypress events to the richlistbox view when it's focused.
- if (document.activeElement === richListBox) {
- DownloadsView.onDownloadKeyPress(aEvent);
- }
- },
-
- /**
- * Keydown listener that listens for the keys to start key focusing, as well
- * as the the accel-V "paste" event, which initiates a file download if the
- * pasted item can be resolved to a URI.
- */
- _onKeyDown: function DP__onKeyDown(aEvent)
- {
- // If the footer is focused and the downloads list has at least 1 element
- // in it, focus the last element in the list when going up.
- if (aEvent.keyCode == Ci.nsIDOMKeyEvent.DOM_VK_UP &&
- document.activeElement.parentNode.id === "downloadsFooter" &&
- DownloadsView.richListBox.firstChild) {
- DownloadsView.richListBox.focus();
- DownloadsView.richListBox.selectedItem = DownloadsView.richListBox.lastChild;
- aEvent.preventDefault();
- return;
- }
-
- let pasting = aEvent.keyCode == Ci.nsIDOMKeyEvent.DOM_VK_V &&
-#ifdef XP_MACOSX
- aEvent.metaKey;
-#else
- aEvent.ctrlKey;
-#endif
-
- if (!pasting) {
- return;
- }
-
- DownloadsCommon.log("Received a paste event.");
-
- let trans = Cc["@mozilla.org/widget/transferable;1"]
- .createInstance(Ci.nsITransferable);
- trans.init(null);
- let flavors = ["text/x-moz-url", "text/unicode"];
- flavors.forEach(trans.addDataFlavor);
- Services.clipboard.getData(trans, Services.clipboard.kGlobalClipboard);
- // Getting the data or creating the nsIURI might fail
- try {
- let data = {};
- trans.getAnyTransferData({}, data, {});
- let [url, name] = data.value
- .QueryInterface(Ci.nsISupportsString)
- .data
- .split("\n");
- if (!url) {
- return;
- }
-
- let uri = NetUtil.newURI(url);
- DownloadsCommon.log("Pasted URL seems valid. Starting download.");
- DownloadURL(uri.spec, name, document);
- } catch (ex) {}
- },
-
- /**
- * Move focus to the main element in the downloads panel, unless another
- * element in the panel is already focused.
- */
- _focusPanel: function DP_focusPanel()
- {
- // We may be invoked while the panel is still waiting to be shown.
- if (this._state != this.kStateShown) {
- return;
- }
-
- let element = document.commandDispatcher.focusedElement;
- while (element && element != this.panel) {
- element = element.parentNode;
- }
- if (!element) {
- if (DownloadsView.richListBox.itemCount > 0) {
- DownloadsView.richListBox.focus();
- } else {
- DownloadsFooter.focus();
- }
- }
- },
-
- /**
- * Opens the downloads panel when data is ready to be displayed.
- */
- _openPopupIfDataReady: function DP_openPopupIfDataReady()
- {
- // We don't want to open the popup if we already displayed it, or if we are
- // still loading data.
- if (this._state != this.kStateWaitingData || DownloadsView.loading) {
- return;
- }
-
- this._state = this.kStateWaitingAnchor;
-
- // Ensure the anchor is visible. If that is not possible, show the panel
- // anchored to the top area of the window, near the default anchor position.
- DownloadsButton.getAnchor(function DP_OPIDR_callback(aAnchor) {
- // If somehow we've switched states already (by getting a panel hiding
- // event before an overlay is loaded, for example), bail out.
- if (this._state != this.kStateWaitingAnchor)
- return;
-
- // At this point, if the window is minimized, opening the panel could fail
- // without any notification, and there would be no way to either open or
- // close the panel any more. To prevent this, check if the window is
- // minimized and in that case force the panel to the closed state.
- if (window.windowState == Ci.nsIDOMChromeWindow.STATE_MINIMIZED) {
- DownloadsButton.releaseAnchor();
- this._state = this.kStateHidden;
- return;
- }
-
- // When the panel is opened, we check if the target files of visible items
- // still exist, and update the allowed items interactions accordingly. We
- // do these checks on a background thread, and don't prevent the panel to
- // be displayed while these checks are being performed.
- for (let viewItem of DownloadsView._visibleViewItems.values()) {
- viewItem.download.refresh().catch(Cu.reportError);
- }
-
- if (aAnchor) {
- DownloadsCommon.log("Opening downloads panel popup.");
- this.panel.openPopup(aAnchor, "bottomcenter topright", 0, 0, false,
- null);
- } else {
- DownloadsCommon.error("We can't find the anchor! Failure case - opening",
- "downloads panel on TabsToolbar. We should never",
- "get here!");
- Components.utils.reportError(
- "Downloads button cannot be found");
- }
- }.bind(this));
- }
-};
-
-XPCOMUtils.defineConstant(this, "DownloadsPanel", DownloadsPanel);
-
-////////////////////////////////////////////////////////////////////////////////
-//// DownloadsOverlayLoader
-
-/**
- * Allows loading the downloads panel and the status indicator interfaces on
- * demand, to improve startup performance.
- */
-const DownloadsOverlayLoader = {
- /**
- * We cannot load two overlays at the same time, thus we use a queue of
- * pending load requests.
- */
- _loadRequests: [],
-
- /**
- * True while we are waiting for an overlay to be loaded.
- */
- _overlayLoading: false,
-
- /**
- * This object has a key for each overlay URI that is already loaded.
- */
- _loadedOverlays: {},
-
- /**
- * Loads the specified overlay and invokes the given callback when finished.
- *
- * @param aOverlay
- * String containing the URI of the overlay to load in the current
- * window. If this overlay has already been loaded using this
- * function, then the overlay is not loaded again.
- * @param aCallback
- * Invoked when loading is completed. If the overlay is already
- * loaded, the function is called immediately.
- */
- ensureOverlayLoaded: function DOL_ensureOverlayLoaded(aOverlay, aCallback)
- {
- // The overlay is already loaded, invoke the callback immediately.
- if (aOverlay in this._loadedOverlays) {
- aCallback();
- return;
- }
-
- // The callback will be invoked when loading is finished.
- this._loadRequests.push({ overlay: aOverlay, callback: aCallback });
- if (this._overlayLoading) {
- return;
- }
-
- function DOL_EOL_loadCallback() {
- this._overlayLoading = false;
- this._loadedOverlays[aOverlay] = true;
-
- // Loading the overlay causes all the persisted XUL attributes to be
- // reapplied, including "iconsize" on the toolbars. Until bug 640158 is
- // fixed, we must recalculate the correct "iconsize" attributes manually.
- retrieveToolbarIconsizesFromTheme();
-
- this.processPendingRequests();
- }
-
- this._overlayLoading = true;
- DownloadsCommon.log("Loading overlay ", aOverlay);
- document.loadOverlay(aOverlay, DOL_EOL_loadCallback.bind(this));
- },
-
- /**
- * Re-processes all the currently pending requests, invoking the callbacks
- * and/or loading more overlays as needed. In most cases, there will be a
- * single request for one overlay, that will be processed immediately.
- */
- processPendingRequests: function DOL_processPendingRequests()
- {
- // Re-process all the currently pending requests, yet allow more requests
- // to be appended at the end of the array if we're not ready for them.
- let currentLength = this._loadRequests.length;
- for (let i = 0; i < currentLength; i++) {
- let request = this._loadRequests.shift();
-
- // We must call ensureOverlayLoaded again for each request, to check if
- // the associated callback can be invoked now, or if we must still wait
- // for the associated overlay to load.
- this.ensureOverlayLoaded(request.overlay, request.callback);
- }
- }
-};
-
-XPCOMUtils.defineConstant(this, "DownloadsOverlayLoader", DownloadsOverlayLoader);
-
-////////////////////////////////////////////////////////////////////////////////
-//// DownloadsView
-
-/**
- * Builds and updates the downloads list widget, responding to changes in the
- * download state and real-time data. In addition, handles part of the user
- * interaction events raised by the downloads list widget.
- */
-const DownloadsView = {
- //////////////////////////////////////////////////////////////////////////////
- //// Functions handling download items in the list
-
- /**
- * Maximum number of items shown by the list at any given time.
- */
- kItemCountLimit: 3,
-
- /**
- * Indicates whether we are still loading downloads data asynchronously.
- */
- loading: false,
-
- /**
- * Ordered array of all Download objects. We need to keep this array because
- * only a limited number of items are shown at once, and if an item that is
- * currently visible is removed from the list, we might need to take another
- * item from the array and make it appear at the bottom.
- */
- _downloads: [],
-
- /**
- * Associates the visible Download objects with their corresponding
- * DownloadsViewItem object. There is a limited number of view items in the
- * panel at any given time.
- */
- _visibleViewItems: new Map(),
-
- /**
- * Called when the number of items in the list changes.
- */
- _itemCountChanged: function DV_itemCountChanged()
- {
- DownloadsCommon.log("The downloads item count has changed - we are tracking",
- this._downloads.length, "downloads in total.");
- let count = this._downloads.length;
- let hiddenCount = count - this.kItemCountLimit;
-
- if (count > 0) {
- DownloadsCommon.log("Setting the panel's hasdownloads attribute to true.");
- DownloadsPanel.panel.setAttribute("hasdownloads", "true");
- } else {
- DownloadsCommon.log("Removing the panel's hasdownloads attribute.");
- DownloadsPanel.panel.removeAttribute("hasdownloads");
- }
-
- // If we've got some hidden downloads, we should activate the
- // DownloadsSummary. The DownloadsSummary will determine whether or not
- // it's appropriate to actually display the summary.
- DownloadsSummary.active = hiddenCount > 0;
- },
-
- /**
- * Element corresponding to the list of downloads.
- */
- get richListBox()
- {
- delete this.richListBox;
- return this.richListBox = document.getElementById("downloadsListBox");
- },
-
- /**
- * Element corresponding to the button for showing more downloads.
- */
- get downloadsHistory()
- {
- delete this.downloadsHistory;
- return this.downloadsHistory = document.getElementById("downloadsHistory");
- },
-
- //////////////////////////////////////////////////////////////////////////////
- //// Callback functions from DownloadsData
-
- /**
- * Called before multiple downloads are about to be loaded.
- */
- onDataLoadStarting: function DV_onDataLoadStarting()
- {
- DownloadsCommon.log("onDataLoadStarting called for DownloadsView.");
- this.loading = true;
- },
-
- /**
- * Called after data loading finished.
- */
- onDataLoadCompleted: function DV_onDataLoadCompleted()
- {
- DownloadsCommon.log("onDataLoadCompleted called for DownloadsView.");
-
- this.loading = false;
-
- // We suppressed item count change notifications during the batch load, at
- // this point we should just call the function once.
- this._itemCountChanged();
-
- // Notify the panel that all the initially available downloads have been
- // loaded. This ensures that the interface is visible, if still required.
- DownloadsPanel.onViewLoadCompleted();
- },
-
- /**
- * Called when the downloads database becomes unavailable (for example,
- * entering Private Browsing Mode). References to existing data should be
- * discarded.
- */
- onDataInvalidated: function DV_onDataInvalidated()
- {
- DownloadsCommon.log("Downloads data has been invalidated. Cleaning up",
- "DownloadsView.");
-
- DownloadsPanel.terminate();
-
- // Clear the list by replacing with a shallow copy.
- let emptyView = this.richListBox.cloneNode(false);
- this.richListBox.parentNode.replaceChild(emptyView, this.richListBox);
- this.richListBox = emptyView;
- this._viewItems = {};
- this._dataItems = [];
- },
-
- /**
- * Called when a new download data item is available, either during the
- * asynchronous data load or when a new download is started.
- *
- * @param aDownload
- * Download object that was just added.
- * @param aNewest
- * When true, indicates that this item is the most recent and should be
- * added in the topmost position. This happens when a new download is
- * started. When false, indicates that the item is the least recent
- * and should be appended. The latter generally happens during the
- * asynchronous data load.
- */
- onDownloadAdded(download, aNewest) {
- DownloadsCommon.log("A new download data item was added - aNewest =",
- aNewest);
-
- if (aNewest) {
- this._downloads.unshift(download);
- } else {
- this._downloads.push(download);
- }
-
- let itemsNowOverflow = this._downloads.length > this.kItemCountLimit;
- if (aNewest || !itemsNowOverflow) {
- // The newly added item is visible in the panel and we must add the
- // corresponding element. This is either because it is the first item, or
- // because it was added at the bottom but the list still doesn't overflow.
- this._addViewItem(download, aNewest);
- }
- if (aNewest && itemsNowOverflow) {
- // If the list overflows, remove the last item from the panel to make room
- // for the new one that we just added at the top.
- this._removeViewItem(this._downloads[this.kItemCountLimit]);
- }
-
- // For better performance during batch loads, don't update the count for
- // every item, because the interface won't be visible until load finishes.
- if (!this.loading) {
- this._itemCountChanged();
- }
- },
-
- onDownloadStateChanged(download) {
- let viewItem = this._visibleViewItems.get(download);
- if (viewItem) {
- viewItem.onStateChanged();
- }
- },
-
- onDownloadChanged(download) {
- let viewItem = this._visibleViewItems.get(download);
- if (viewItem) {
- viewItem.onChanged();
- }
- },
-
- /**
- * Called when a data item is removed. Ensures that the widget associated
- * with the view item is removed from the user interface.
- *
- * @param download
- * Download object that is being removed.
- */
- onDownloadRemoved(download) {
- DownloadsCommon.log("A download data item was removed.");
-
- let itemIndex = this._downloads.indexOf(download);
- this._downloads.splice(itemIndex, 1);
-
- if (itemIndex < this.kItemCountLimit) {
- // The item to remove is visible in the panel.
- this._removeViewItem(download);
- if (this._downloads.length >= this.kItemCountLimit) {
- // Reinsert the next item into the panel.
- this._addViewItem(this._downloads[this.kItemCountLimit - 1], false);
- }
- }
-
- this._itemCountChanged();
- },
-
- /**
- * Associates each richlistitem for a download with its corresponding
- * DownloadsViewItemController object.
- */
- _controllersForElements: new Map(),
-
- controllerForElement(element) {
- return this._controllersForElements.get(element);
- },
-
- /**
- * Creates a new view item associated with the specified data item, and adds
- * it to the top or the bottom of the list.
- */
- _addViewItem(download, aNewest)
- {
- DownloadsCommon.log("Adding a new DownloadsViewItem to the downloads list.",
- "aNewest =", aNewest);
-
- let element = document.createElement("richlistitem");
- let viewItem = new DownloadsViewItem(download, element);
- this._visibleViewItems.set(download, viewItem);
- let viewItemController = new DownloadsViewItemController(download);
- this._controllersForElements.set(element, viewItemController);
- if (aNewest) {
- this.richListBox.insertBefore(element, this.richListBox.firstChild);
- } else {
- this.richListBox.appendChild(element);
- }
- },
-
- /**
- * Removes the view item associated with the specified data item.
- */
- _removeViewItem(download) {
- DownloadsCommon.log("Removing a DownloadsViewItem from the downloads list.");
- let element = this._visibleViewItems.get(download).element;
- let previousSelectedIndex = this.richListBox.selectedIndex;
- this.richListBox.removeChild(element);
- if (previousSelectedIndex != -1) {
- this.richListBox.selectedIndex = Math.min(previousSelectedIndex,
- this.richListBox.itemCount - 1);
- }
- this._visibleViewItems.delete(download);
- this._controllersForElements.delete(element);
- },
-
- //////////////////////////////////////////////////////////////////////////////
- //// User interface event functions
-
- /**
- * Helper function to do commands on a specific download item.
- *
- * @param aEvent
- * Event object for the event being handled. If the event target is
- * not a richlistitem that represents a download, this function will
- * walk up the parent nodes until it finds a DOM node that is.
- * @param aCommand
- * The command to be performed.
- */
- onDownloadCommand: function DV_onDownloadCommand(aEvent, aCommand)
- {
- let target = aEvent.target;
- while (target.nodeName != "richlistitem") {
- target = target.parentNode;
- }
- DownloadsView.controllerForElement(target).doCommand(aCommand);
- },
-
- onDownloadClick: function DV_onDownloadClick(aEvent)
- {
- // Handle primary clicks only, and exclude the action button.
- if (aEvent.button == 0 &&
- !aEvent.originalTarget.hasAttribute("oncommand")) {
- goDoCommand("downloadsCmd_open");
- }
- },
-
- /**
- * Handles keypress events on a download item.
- */
- onDownloadKeyPress: function DV_onDownloadKeyPress(aEvent)
- {
- // Pressing the key on buttons should not invoke the action because the
- // event has already been handled by the button itself.
- if (aEvent.originalTarget.hasAttribute("command") ||
- aEvent.originalTarget.hasAttribute("oncommand")) {
- return;
- }
-
- if (aEvent.charCode == " ".charCodeAt(0)) {
- goDoCommand("downloadsCmd_pauseResume");
- return;
- }
-
- if (aEvent.keyCode == KeyEvent.DOM_VK_ENTER ||
- aEvent.keyCode == KeyEvent.DOM_VK_RETURN) {
- goDoCommand("downloadsCmd_doDefault");
- }
- },
-
-
- /**
- * Mouse listeners to handle selection on hover.
- */
- onDownloadMouseOver: function DV_onDownloadMouseOver(aEvent)
- {
- if (aEvent.originalTarget.parentNode == this.richListBox)
- this.richListBox.selectedItem = aEvent.originalTarget;
- },
- onDownloadMouseOut: function DV_onDownloadMouseOut(aEvent)
- {
- if (aEvent.originalTarget.parentNode == this.richListBox) {
- // If the destination element is outside of the richlistitem, clear the
- // selection.
- let element = aEvent.relatedTarget;
- while (element && element != aEvent.originalTarget) {
- element = element.parentNode;
- }
- if (!element)
- this.richListBox.selectedIndex = -1;
- }
- },
-
- onDownloadContextMenu: function DV_onDownloadContextMenu(aEvent)
- {
- let element = this.richListBox.selectedItem;
- if (!element) {
- return;
- }
-
- DownloadsViewController.updateCommands();
-
- // Set the state attribute so that only the appropriate items are displayed.
- let contextMenu = document.getElementById("downloadsContextMenu");
- contextMenu.setAttribute("state", element.getAttribute("state"));
- },
-
- onDownloadDragStart: function DV_onDownloadDragStart(aEvent)
- {
- let element = this.richListBox.selectedItem;
- if (!element) {
- return;
- }
-
- // We must check for existence synchronously because this is a DOM event.
- let localFile = new FileUtils.File(DownloadsView.controllerForElement(element)
- .download.target.path);
- if (!localFile.exists()) {
- return;
- }
-
- let dataTransfer = aEvent.dataTransfer;
- dataTransfer.mozSetDataAt("application/x-moz-file", localFile, 0);
- dataTransfer.effectAllowed = "copyMove";
- var url = Services.io.newFileURI(localFile).spec;
- dataTransfer.setData("text/uri-list", url);
- dataTransfer.setData("text/plain", url);
- dataTransfer.addElement(element);
-
- aEvent.stopPropagation();
- }
-}
-
-XPCOMUtils.defineConstant(this, "DownloadsView", DownloadsView);
-
-////////////////////////////////////////////////////////////////////////////////
-//// DownloadsViewItem
-
-/**
- * Builds and updates a single item in the downloads list widget, responding to
- * changes in the download state and real-time data.
- *
- * @param download
- * Download object to be associated with the view item.
- * @param aElement
- * XUL element corresponding to the single download item in the view.
- */
-function DownloadsViewItem(download, aElement) {
- this.download = download;
-
- this.element = aElement;
- this.element._shell = this;
-
- this.element.setAttribute("type", "download");
- this.element.classList.add("download-state");
-
- this._updateState();
-}
-
-DownloadsViewItem.prototype = {
- __proto__: DownloadsViewUI.DownloadElementShell.prototype,
-
- /**
- * The XUL element corresponding to the associated richlistbox item.
- */
- _element: null,
-
- onStateChanged() {
- this.element.setAttribute("image", this.image);
- this.element.setAttribute("state",
- DownloadsCommon.stateOfDownload(this.download));
- },
-
- onChanged() {
- this._updateProgress();
- },
-};
-
-////////////////////////////////////////////////////////////////////////////////
-//// DownloadsViewController
-
-/**
- * Handles part of the user interaction events raised by the downloads list
- * widget, in particular the "commands" that apply to multiple items, and
- * dispatches the commands that apply to individual items.
- */
-const DownloadsViewController = {
- //////////////////////////////////////////////////////////////////////////////
- //// Initialization and termination
-
- initialize: function DVC_initialize()
- {
- window.controllers.insertControllerAt(0, this);
- },
-
- terminate: function DVC_terminate()
- {
- window.controllers.removeController(this);
- },
-
- //////////////////////////////////////////////////////////////////////////////
- //// nsIController
-
- supportsCommand: function DVC_supportsCommand(aCommand)
- {
- // Firstly, determine if this is a command that we can handle.
- if (!(aCommand in this.commands) &&
- !(aCommand in DownloadsViewItemController.prototype.commands)) {
- return false;
- }
- // Secondly, determine if focus is on a control in the downloads list.
- let element = document.commandDispatcher.focusedElement;
- while (element && element != DownloadsView.richListBox) {
- element = element.parentNode;
- }
- // We should handle the command only if the downloads list is among the
- // ancestors of the focused element.
- return !!element;
- },
-
- isCommandEnabled: function DVC_isCommandEnabled(aCommand)
- {
- // Handle commands that are not selection-specific.
- if (aCommand == "downloadsCmd_clearList") {
- return DownloadsCommon.getData(window).canRemoveFinished;
- }
-
- // Other commands are selection-specific.
- let element = DownloadsView.richListBox.selectedItem;
- return element && DownloadsView.controllerForElement(element)
- .isCommandEnabled(aCommand);
- },
-
- doCommand: function DVC_doCommand(aCommand)
- {
- // If this command is not selection-specific, execute it.
- if (aCommand in this.commands) {
- this.commands[aCommand].apply(this);
- return;
- }
-
- // Other commands are selection-specific.
- let element = DownloadsView.richListBox.selectedItem;
- if (element) {
- // The doCommand function also checks if the command is enabled.
- DownloadsView.controllerForElement(element).doCommand(aCommand);
- }
- },
-
- onEvent: function () { },
-
- //////////////////////////////////////////////////////////////////////////////
- //// Other functions
-
- updateCommands: function DVC_updateCommands()
- {
- Object.keys(this.commands).forEach(goUpdateCommand);
- Object.keys(DownloadsViewItemController.prototype.commands)
- .forEach(goUpdateCommand);
- },
-
- //////////////////////////////////////////////////////////////////////////////
- //// Selection-independent commands
-
- /**
- * This object contains one key for each command that operates regardless of
- * the currently selected item in the list.
- */
- commands: {
- downloadsCmd_clearList: function DVC_downloadsCmd_clearList()
- {
- DownloadsCommon.getData(window).removeFinished();
- }
- }
-};
-
-XPCOMUtils.defineConstant(this, "DownloadsViewController", DownloadsViewController);
-
-////////////////////////////////////////////////////////////////////////////////
-//// DownloadsViewItemController
-
-/**
- * Handles all the user interaction events, in particular the "commands",
- * related to a single item in the downloads list widgets.
- */
-function DownloadsViewItemController(download) {
- this.download = download;
-}
-
-DownloadsViewItemController.prototype = {
- isCommandEnabled: function DVIC_isCommandEnabled(aCommand)
- {
- switch (aCommand) {
- case "downloadsCmd_open": {
- if (!this.download.succeeded) {
- return false;
- }
-
- let file = new FileUtils.File(this.download.target.path);
- return file.exists();
- }
- case "downloadsCmd_show": {
- let file = new FileUtils.File(this.download.target.path);
- if (file.exists()) {
- return true;
- }
-
- if (!this.download.target.partFilePath) {
- return false;
- }
-
- let partFile = new FileUtils.File(this.download.target.partFilePath);
- return partFile.exists();
- }
- case "downloadsCmd_pauseResume":
- return this.download.hasPartialData && !this.download.error;
- case "downloadsCmd_retry":
- return this.download.canceled || this.download.error;
- case "downloadsCmd_openReferrer":
- return !!this.download.source.referrer;
- case "cmd_delete":
- case "downloadsCmd_cancel":
- case "downloadsCmd_copyLocation":
- case "downloadsCmd_doDefault":
- return true;
- }
- return false;
- },
-
- doCommand: function DVIC_doCommand(aCommand)
- {
- if (this.isCommandEnabled(aCommand)) {
- this.commands[aCommand].apply(this);
- }
- },
-
- //////////////////////////////////////////////////////////////////////////////
- //// Item commands
-
- /**
- * This object contains one key for each command that operates on this item.
- *
- * In commands, the "this" identifier points to the controller item.
- */
- commands: {
- cmd_delete: function DVIC_cmd_delete()
- {
- DownloadsCommon.removeAndFinalizeDownload(this.download);
- PlacesUtils.bhistory.removePage(
- NetUtil.newURI(this.download.source.url));
- },
-
- downloadsCmd_cancel: function DVIC_downloadsCmd_cancel()
- {
- this.download.cancel().catch(() => {});
- this.download.removePartialData().catch(Cu.reportError);
- },
-
- downloadsCmd_open: function DVIC_downloadsCmd_open()
- {
- this.download.launch().catch(Cu.reportError);
-
- // We explicitly close the panel here to give the user the feedback that
- // their click has been received, and we're handling the action.
- // Otherwise, we'd have to wait for the file-type handler to execute
- // before the panel would close. This also helps to prevent the user from
- // accidentally opening a file several times.
- DownloadsPanel.hidePanel();
- },
-
- downloadsCmd_show: function DVIC_downloadsCmd_show()
- {
- let file = new FileUtils.File(this.download.target.path);
- DownloadsCommon.showDownloadedFile(file);
-
- // We explicitly close the panel here to give the user the feedback that
- // their click has been received, and we're handling the action.
- // Otherwise, we'd have to wait for the operating system file manager
- // window to open before the panel closed. This also helps to prevent the
- // user from opening the containing folder several times.
- DownloadsPanel.hidePanel();
- },
-
- downloadsCmd_pauseResume: function DVIC_downloadsCmd_pauseResume()
- {
- if (this.download.stopped) {
- this.download.start();
- } else {
- this.download.cancel();
- }
- },
-
- downloadsCmd_retry: function DVIC_downloadsCmd_retry()
- {
- this.download.start().catch(() => {});
- },
-
- downloadsCmd_openReferrer: function DVIC_downloadsCmd_openReferrer()
- {
- openURL(this.download.source.referrer);
- },
-
- downloadsCmd_copyLocation: function DVIC_downloadsCmd_copyLocation()
- {
- let clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"]
- .getService(Ci.nsIClipboardHelper);
- clipboard.copyString(this.download.source.url, document);
- },
-
- downloadsCmd_doDefault: function DVIC_downloadsCmd_doDefault()
- {
- const nsIDM = Ci.nsIDownloadManager;
-
- // Determine the default command for the current item.
- let defaultCommand = function () {
- switch (DownloadsCommon.stateOfDownload(this.download)) {
- case nsIDM.DOWNLOAD_NOTSTARTED: return "downloadsCmd_cancel";
- case nsIDM.DOWNLOAD_FINISHED: return "downloadsCmd_open";
- case nsIDM.DOWNLOAD_FAILED: return "downloadsCmd_retry";
- case nsIDM.DOWNLOAD_CANCELED: return "downloadsCmd_retry";
- case nsIDM.DOWNLOAD_PAUSED: return "downloadsCmd_pauseResume";
- case nsIDM.DOWNLOAD_QUEUED: return "downloadsCmd_cancel";
- case nsIDM.DOWNLOAD_BLOCKED_PARENTAL: return "downloadsCmd_openReferrer";
- case nsIDM.DOWNLOAD_SCANNING: return "downloadsCmd_show";
- case nsIDM.DOWNLOAD_DIRTY: return "downloadsCmd_openReferrer";
- case nsIDM.DOWNLOAD_BLOCKED_POLICY: return "downloadsCmd_openReferrer";
- }
- return "";
- }.apply(this);
- if (defaultCommand && this.isCommandEnabled(defaultCommand))
- this.doCommand(defaultCommand);
- }
- }
-};
-
-
-////////////////////////////////////////////////////////////////////////////////
-//// DownloadsSummary
-
-/**
- * Manages the summary at the bottom of the downloads panel list if the number
- * of items in the list exceeds the panels limit.
- */
-const DownloadsSummary = {
-
- /**
- * Sets the active state of the summary. When active, the summary subscribes
- * to the DownloadsCommon DownloadsSummaryData singleton.
- *
- * @param aActive
- * Set to true to activate the summary.
- */
- set active(aActive)
- {
- if (aActive == this._active || !this._summaryNode) {
- return this._active;
- }
- if (aActive) {
- DownloadsCommon.getSummary(window, DownloadsView.kItemCountLimit)
- .refreshView(this);
- } else {
- DownloadsFooter.showingSummary = false;
- }
-
- return this._active = aActive;
- },
-
- /**
- * Returns the active state of the downloads summary.
- */
- get active() this._active,
-
- _active: false,
-
- /**
- * Sets whether or not we show the progress bar.
- *
- * @param aShowingProgress
- * True if we should show the progress bar.
- */
- set showingProgress(aShowingProgress)
- {
- if (aShowingProgress) {
- this._summaryNode.setAttribute("inprogress", "true");
- } else {
- this._summaryNode.removeAttribute("inprogress");
- }
- // If progress isn't being shown, then we simply do not show the summary.
- return DownloadsFooter.showingSummary = aShowingProgress;
- },
-
- /**
- * Sets the amount of progress that is visible in the progress bar.
- *
- * @param aValue
- * A value between 0 and 100 to represent the progress of the
- * summarized downloads.
- */
- set percentComplete(aValue)
- {
- if (this._progressNode) {
- this._progressNode.setAttribute("value", aValue);
- }
- return aValue;
- },
-
- /**
- * Sets the description for the download summary.
- *
- * @param aValue
- * A string representing the description of the summarized
- * downloads.
- */
- set description(aValue)
- {
- if (this._descriptionNode) {
- this._descriptionNode.setAttribute("value", aValue);
- this._descriptionNode.setAttribute("tooltiptext", aValue);
- }
- return aValue;
- },
-
- /**
- * Sets the details for the download summary, such as the time remaining,
- * the amount of bytes transferred, etc.
- *
- * @param aValue
- * A string representing the details of the summarized
- * downloads.
- */
- set details(aValue)
- {
- if (this._detailsNode) {
- this._detailsNode.setAttribute("value", aValue);
- this._detailsNode.setAttribute("tooltiptext", aValue);
- }
- return aValue;
- },
-
- /**
- * Focuses the root element of the summary.
- */
- focus: function()
- {
- if (this._summaryNode) {
- this._summaryNode.focus();
- }
- },
-
- /**
- * Respond to keydown events on the Downloads Summary node.
- *
- * @param aEvent
- * The keydown event being handled.
- */
- onKeyDown: function DS_onKeyDown(aEvent)
- {
- if (aEvent.charCode == " ".charCodeAt(0) ||
- aEvent.keyCode == KeyEvent.DOM_VK_ENTER ||
- aEvent.keyCode == KeyEvent.DOM_VK_RETURN) {
- DownloadsPanel.showDownloadsHistory();
- }
- },
-
- /**
- * Respond to click events on the Downloads Summary node.
- *
- * @param aEvent
- * The click event being handled.
- */
- onClick: function DS_onClick(aEvent)
- {
- DownloadsPanel.showDownloadsHistory();
- },
-
- /**
- * Element corresponding to the root of the downloads summary.
- */
- get _summaryNode()
- {
- let node = document.getElementById("downloadsSummary");
- if (!node) {
- return null;
- }
- delete this._summaryNode;
- return this._summaryNode = node;
- },
-
- /**
- * Element corresponding to the progress bar in the downloads summary.
- */
- get _progressNode()
- {
- let node = document.getElementById("downloadsSummaryProgress");
- if (!node) {
- return null;
- }
- delete this._progressNode;
- return this._progressNode = node;
- },
-
- /**
- * Element corresponding to the main description of the downloads
- * summary.
- */
- get _descriptionNode()
- {
- let node = document.getElementById("downloadsSummaryDescription");
- if (!node) {
- return null;
- }
- delete this._descriptionNode;
- return this._descriptionNode = node;
- },
-
- /**
- * Element corresponding to the secondary description of the downloads
- * summary.
- */
- get _detailsNode()
- {
- let node = document.getElementById("downloadsSummaryDetails");
- if (!node) {
- return null;
- }
- delete this._detailsNode;
- return this._detailsNode = node;
- }
-};
-
-XPCOMUtils.defineConstant(this, "DownloadsSummary", DownloadsSummary);
-
-////////////////////////////////////////////////////////////////////////////////
-//// DownloadsFooter
-
-/**
- * Manages events sent to to the footer vbox, which contains both the
- * DownloadsSummary as well as the "Show All Downloads" button.
- */
-const DownloadsFooter = {
-
- /**
- * Focuses the appropriate element within the footer. If the summary
- * is visible, focus it. If not, focus the "Show All Downloads"
- * button.
- */
- focus: function DF_focus()
- {
- if (this._showingSummary) {
- DownloadsSummary.focus();
- } else {
- DownloadsView.downloadsHistory.focus();
- }
- },
-
- _showingSummary: false,
-
- /**
- * Sets whether or not the Downloads Summary should be displayed in the
- * footer. If not, the "Show All Downloads" button is shown instead.
- */
- set showingSummary(aValue)
- {
- if (this._footerNode) {
- if (aValue) {
- this._footerNode.setAttribute("showingsummary", "true");
- } else {
- this._footerNode.removeAttribute("showingsummary");
- }
- this._showingSummary = aValue;
- }
- return aValue;
- },
-
- /**
- * Element corresponding to the footer of the downloads panel.
- */
- get _footerNode()
- {
- let node = document.getElementById("downloadsFooter");
- if (!node) {
- return null;
- }
- delete this._footerNode;
- return this._footerNode = node;
- }
-};
-
-XPCOMUtils.defineConstant(this, "DownloadsFooter", DownloadsFooter);
diff --git a/components/downloads/content/downloadsOverlay.xul b/components/downloads/content/downloadsOverlay.xul
deleted file mode 100644
index ca35ee3..0000000
--- a/components/downloads/content/downloadsOverlay.xul
+++ /dev/null
@@ -1,142 +0,0 @@
-<?xml version="1.0"?>
-# -*- Mode: HTML; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
-# vim: set ts=2 et sw=2 tw=80:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this file,
-# You can obtain one at http://mozilla.org/MPL/2.0/.
-
-<?xml-stylesheet href="chrome://browser/content/downloads/downloads.css"?>
-<?xml-stylesheet href="chrome://browser/skin/downloads/downloads.css"?>
-
-<!DOCTYPE overlay SYSTEM "chrome://browser/locale/downloads/downloads.dtd">
-
-<overlay xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- id="downloadsOverlay">
-
- <commandset>
- <command id="downloadsCmd_doDefault"
- oncommand="goDoCommand('downloadsCmd_doDefault')"/>
- <command id="downloadsCmd_pauseResume"
- oncommand="goDoCommand('downloadsCmd_pauseResume')"/>
- <command id="downloadsCmd_cancel"
- oncommand="goDoCommand('downloadsCmd_cancel')"/>
- <command id="downloadsCmd_open"
- oncommand="goDoCommand('downloadsCmd_open')"/>
- <command id="downloadsCmd_show"
- oncommand="goDoCommand('downloadsCmd_show')"/>
- <command id="downloadsCmd_retry"
- oncommand="goDoCommand('downloadsCmd_retry')"/>
- <command id="downloadsCmd_openReferrer"
- oncommand="goDoCommand('downloadsCmd_openReferrer')"/>
- <command id="downloadsCmd_copyLocation"
- oncommand="goDoCommand('downloadsCmd_copyLocation')"/>
- <command id="downloadsCmd_clearList"
- oncommand="goDoCommand('downloadsCmd_clearList')"/>
- </commandset>
-
- <popupset id="mainPopupSet">
- <!-- The panel has level="top" to ensure that it is never hidden by the
- taskbar on Windows. See bug 672365. For accessibility to screen
- readers, we use a label on the panel instead of the anchor because the
- panel can also be displayed without an anchor. -->
- <panel id="downloadsPanel"
- aria-label="&downloads.title;"
- role="group"
- type="arrow"
- orient="vertical"
- level="top"
- consumeoutsideclicks="true"
- onpopupshown="DownloadsPanel.onPopupShown(event);"
- onpopuphidden="DownloadsPanel.onPopupHidden(event);">
- <!-- The following popup menu should be a child of the panel element,
- otherwise flickering may occur when the cursor is moved over the area
- of a disabled menu item that overlaps the panel. See bug 492960. -->
- <menupopup id="downloadsContextMenu"
- class="download-state">
- <menuitem command="downloadsCmd_pauseResume"
- class="downloadPauseMenuItem"
- label="&cmd.pause.label;"
- accesskey="&cmd.pause.accesskey;"/>
- <menuitem command="downloadsCmd_pauseResume"
- class="downloadResumeMenuItem"
- label="&cmd.resume.label;"
- accesskey="&cmd.resume.accesskey;"/>
- <menuitem command="downloadsCmd_cancel"
- class="downloadCancelMenuItem"
- label="&cmd.cancel.label;"
- accesskey="&cmd.cancel.accesskey;"/>
- <menuitem command="cmd_delete"
- class="downloadRemoveFromHistoryMenuItem"
- label="&cmd.removeFromHistory.label;"
- accesskey="&cmd.removeFromHistory.accesskey;"/>
- <menuitem command="downloadsCmd_show"
- class="downloadShowMenuItem"
-#ifdef XP_MACOSX
- label="&cmd.showMac.label;"
- accesskey="&cmd.showMac.accesskey;"
-#else
- label="&cmd.show.label;"
- accesskey="&cmd.show.accesskey;"
-#endif
- />
-
- <menuseparator class="downloadCommandsSeparator"/>
-
- <menuitem command="downloadsCmd_openReferrer"
- label="&cmd.goToDownloadPage.label;"
- accesskey="&cmd.goToDownloadPage.accesskey;"/>
- <menuitem command="downloadsCmd_copyLocation"
- label="&cmd.copyDownloadLink.label;"
- accesskey="&cmd.copyDownloadLink.accesskey;"/>
-
- <menuseparator/>
-
- <menuitem command="downloadsCmd_clearList"
- label="&cmd.clearList.label;"
- accesskey="&cmd.clearList.accesskey;"/>
- </menupopup>
-
- <richlistbox id="downloadsListBox"
- class="plain"
- flex="1"
- context="downloadsContextMenu"
- onmouseover="DownloadsView.onDownloadMouseOver(event);"
- onmouseout="DownloadsView.onDownloadMouseOut(event);"
- oncontextmenu="DownloadsView.onDownloadContextMenu(event);"
- ondragstart="DownloadsView.onDownloadDragStart(event);"/>
- <description id="emptyDownloads"
- mousethrough="always">
- &downloadsPanelEmpty.label;
- </description>
-
- <vbox id="downloadsFooter">
- <hbox id="downloadsSummary"
- align="center"
- orient="horizontal"
- onkeydown="DownloadsSummary.onKeyDown(event);"
- onclick="DownloadsSummary.onClick(event);">
- <image class="downloadTypeIcon" />
- <vbox>
- <description id="downloadsSummaryDescription"
- style="min-width: &downloadsSummary.minWidth2;"/>
- <progressmeter id="downloadsSummaryProgress"
- class="downloadProgress"
- min="0"
- max="100"
- mode="normal" />
- <description id="downloadsSummaryDetails"
- style="width: &downloadDetails.width;"
- crop="end"/>
- </vbox>
- </hbox>
-
- <button id="downloadsHistory"
- class="plain"
- label="&downloadsHistory.label;"
- accesskey="&downloadsHistory.accesskey;"
- oncommand="DownloadsPanel.showDownloadsHistory();"/>
- </vbox>
- </panel>
- </popupset>
-</overlay>
diff --git a/components/downloads/content/indicator.js b/components/downloads/content/indicator.js
deleted file mode 100644
index 1a2175a..0000000
--- a/components/downloads/content/indicator.js
+++ /dev/null
@@ -1,609 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/**
- * Handles the indicator that displays the progress of ongoing downloads, which
- * is also used as the anchor for the downloads panel.
- *
- * This module includes the following constructors and global objects:
- *
- * DownloadsButton
- * Main entry point for the downloads indicator. Depending on how the toolbars
- * have been customized, this object determines if we should show a fully
- * functional indicator, a placeholder used during customization and in the
- * customization palette, or a neutral view as a temporary anchor for the
- * downloads panel.
- *
- * DownloadsIndicatorView
- * Builds and updates the actual downloads status widget, responding to changes
- * in the global status data, or provides a neutral view if the indicator is
- * removed from the toolbars and only used as a temporary anchor. In addition,
- * handles the user interaction events raised by the widget.
- */
-
-"use strict";
-
-////////////////////////////////////////////////////////////////////////////////
-//// DownloadsButton
-
-/**
- * Main entry point for the downloads indicator. Depending on how the toolbars
- * have been customized, this object determines if we should show a fully
- * functional indicator, a placeholder used during customization and in the
- * customization palette, or a neutral view as a temporary anchor for the
- * downloads panel.
- */
-const DownloadsButton = {
- /**
- * Location of the indicator overlay.
- */
- get kIndicatorOverlay()
- "chrome://browser/content/downloads/indicatorOverlay.xul",
-
- /**
- * Returns a reference to the downloads button position placeholder, or null
- * if not available because it has been removed from the toolbars.
- */
- get _placeholder()
- {
- return document.getElementById("downloads-button");
- },
-
- /**
- * This function is called asynchronously just after window initialization.
- *
- * NOTE: This function should limit the input/output it performs to improve
- * startup time, and in particular should not cause the Download Manager
- * service to start.
- */
- initializeIndicator: function DB_initializeIndicator()
- {
- this._update();
- },
-
- /**
- * Indicates whether toolbar customization is in progress.
- */
- _customizing: false,
-
- /**
- * This function is called when toolbar customization starts.
- *
- * During customization, we never show the actual download progress indication
- * or the event notifications, but we show a neutral placeholder. The neutral
- * placeholder is an ordinary button defined in the browser window that can be
- * moved freely between the toolbars and the customization palette.
- */
- customizeStart: function DB_customizeStart()
- {
- // Hide the indicator and prevent it to be displayed as a temporary anchor
- // during customization, even if requested using the getAnchor method.
- this._customizing = true;
- this._anchorRequested = false;
-
- let indicator = DownloadsIndicatorView.indicator;
- if (indicator) {
- indicator.collapsed = true;
- }
-
- let placeholder = this._placeholder;
- if (placeholder) {
- placeholder.collapsed = false;
- }
- },
-
- /**
- * This function is called when toolbar customization ends.
- */
- customizeDone: function DB_customizeDone()
- {
- this._customizing = false;
- this._update();
- },
-
- /**
- * This function is called during initialization or when toolbar customization
- * ends. It determines if we should enable or disable the object that keeps
- * the indicator updated, and ensures that the placeholder is hidden unless it
- * has been moved to the customization palette.
- *
- * NOTE: This function is also called on startup, thus it should limit the
- * input/output it performs, and in particular should not cause the
- * Download Manager service to start.
- */
- _update: function DB_update() {
- this._updatePositionInternal();
-
- if (!DownloadsCommon.useToolkitUI) {
- DownloadsIndicatorView.ensureInitialized();
- } else {
- DownloadsIndicatorView.ensureTerminated();
- }
- },
-
- /**
- * Determines the position where the indicator should appear, and moves its
- * associated element to the new position. This does not happen if the
- * indicator is currently being used as the anchor for the panel, to ensure
- * that the panel doesn't flicker because we move the DOM element to which
- * it's anchored.
- */
- updatePosition: function DB_updatePosition()
- {
- if (!this._anchorRequested) {
- this._updatePositionInternal();
- }
- },
-
- /**
- * Determines the position where the indicator should appear, and moves its
- * associated element to the new position.
- *
- * @return Anchor element, or null if the indicator is not visible.
- */
- _updatePositionInternal: function DB_updatePositionInternal()
- {
- let indicator = DownloadsIndicatorView.indicator;
- if (!indicator) {
- // Exit now if the indicator overlay isn't loaded yet.
- return null;
- }
-
- let placeholder = this._placeholder;
- if (!placeholder) {
- // The placeholder has been removed from the browser window.
- indicator.collapsed = true;
- // Move the indicator to a safe position on the toolbar, since otherwise
- // it may break the merge of adjacent items, like back/forward + urlbar.
- indicator.parentNode.appendChild(indicator);
- return null;
- }
-
- // Position the indicator where the placeholder is located. We should
- // update the position even if the placeholder is located on an invisible
- // toolbar, because the toolbar may be displayed later.
- placeholder.parentNode.insertBefore(indicator, placeholder);
- placeholder.collapsed = true;
- indicator.collapsed = false;
-
- indicator.open = this._anchorRequested;
-
- // Determine if the placeholder is located on an invisible toolbar.
- if (!isElementVisible(placeholder.parentNode)) {
- return null;
- }
-
- return DownloadsIndicatorView.indicatorAnchor;
- },
-
- /**
- * Checks whether the indicator is, or will soon be visible in the browser
- * window.
- *
- * @param aCallback
- * Called once the indicator overlay has loaded. Gets a boolean
- * argument representing the indicator visibility.
- */
- checkIsVisible: function DB_checkIsVisible(aCallback)
- {
- function DB_CEV_callback() {
- if (!this._placeholder) {
- aCallback(false);
- } else {
- let element = DownloadsIndicatorView.indicator || this._placeholder;
- aCallback(isElementVisible(element.parentNode));
- }
- }
- DownloadsOverlayLoader.ensureOverlayLoaded(this.kIndicatorOverlay,
- DB_CEV_callback.bind(this));
- },
-
- /**
- * Indicates whether we should try and show the indicator temporarily as an
- * anchor for the panel, even if the indicator would be hidden by default.
- */
- _anchorRequested: false,
-
- /**
- * Ensures that there is an anchor available for the panel.
- *
- * @param aCallback
- * Called when the anchor is available, passing the element where the
- * panel should be anchored, or null if an anchor is not available (for
- * example because both the tab bar and the navigation bar are hidden).
- */
- getAnchor: function DB_getAnchor(aCallback)
- {
- // Do not allow anchoring the panel to the element while customizing.
- if (this._customizing) {
- aCallback(null);
- return;
- }
-
- function DB_GA_callback() {
- this._anchorRequested = true;
- aCallback(this._updatePositionInternal());
- }
-
- DownloadsOverlayLoader.ensureOverlayLoaded(this.kIndicatorOverlay,
- DB_GA_callback.bind(this));
- },
-
- /**
- * Allows the temporary anchor to be hidden.
- */
- releaseAnchor: function DB_releaseAnchor()
- {
- this._anchorRequested = false;
- this._updatePositionInternal();
- },
-
- get _tabsToolbar()
- {
- delete this._tabsToolbar;
- return this._tabsToolbar = document.getElementById("TabsToolbar");
- },
-
- get _navBar()
- {
- delete this._navBar;
- return this._navBar = document.getElementById("nav-bar");
- }
-};
-
-Object.defineProperty(this, "DownloadsButton", {
- value: DownloadsButton,
- enumerable: true,
- writable: false
-});
-
-////////////////////////////////////////////////////////////////////////////////
-//// DownloadsIndicatorView
-
-/**
- * Builds and updates the actual downloads status widget, responding to changes
- * in the global status data, or provides a neutral view if the indicator is
- * removed from the toolbars and only used as a temporary anchor. In addition,
- * handles the user interaction events raised by the widget.
- */
-const DownloadsIndicatorView = {
- /**
- * True when the view is connected with the underlying downloads data.
- */
- _initialized: false,
-
- /**
- * True when the user interface elements required to display the indicator
- * have finished loading in the browser window, and can be referenced.
- */
- _operational: false,
-
- /**
- * Prepares the downloads indicator to be displayed.
- */
- ensureInitialized: function DIV_ensureInitialized()
- {
- if (this._initialized) {
- return;
- }
- this._initialized = true;
-
- window.addEventListener("unload", this.onWindowUnload, false);
- DownloadsCommon.getIndicatorData(window).addView(this);
- },
-
- /**
- * Frees the internal resources related to the indicator.
- */
- ensureTerminated: function DIV_ensureTerminated()
- {
- if (!this._initialized) {
- return;
- }
- this._initialized = false;
-
- window.removeEventListener("unload", this.onWindowUnload, false);
- DownloadsCommon.getIndicatorData(window).removeView(this);
-
- // Reset the view properties, so that a neutral indicator is displayed if we
- // are visible only temporarily as an anchor.
- this.counter = "";
- this.percentComplete = 0;
- this.paused = false;
- this.attention = false;
- },
-
- /**
- * Ensures that the user interface elements required to display the indicator
- * are loaded, then invokes the given callback.
- */
- _ensureOperational: function DIV_ensureOperational(aCallback)
- {
- if (this._operational) {
- aCallback();
- return;
- }
-
- function DIV_EO_callback() {
- this._operational = true;
-
- // If the view is initialized, we need to update the elements now that
- // they are finally available in the document.
- if (this._initialized) {
- DownloadsCommon.getIndicatorData(window).refreshView(this);
- }
-
- aCallback();
- }
-
- DownloadsOverlayLoader.ensureOverlayLoaded(
- DownloadsButton.kIndicatorOverlay,
- DIV_EO_callback.bind(this));
- },
-
- //////////////////////////////////////////////////////////////////////////////
- //// Direct control functions
-
- /**
- * Set while we are waiting for a notification to fade out.
- */
- _notificationTimeout: null,
-
- /**
- * If the status indicator is visible in its assigned position, shows for a
- * brief time a visual notification of a relevant event, like a new download.
- *
- * @param aType
- * Set to "start" for new downloads, "finish" for completed downloads.
- */
- showEventNotification: function DIV_showEventNotification(aType)
- {
- if (!this._initialized) {
- return;
- }
-
- if (!DownloadsCommon.animateNotifications) {
- return;
- }
-
- // No need to show visual notification if the panel is visible.
- if (DownloadsPanel.isPanelShowing) {
- return;
- }
-
- function DIV_SEN_callback() {
- if (this._notificationTimeout) {
- clearTimeout(this._notificationTimeout);
- }
-
- // Now that the overlay is loaded, place the indicator in its final
- // position.
- DownloadsButton.updatePosition();
-
- let indicator = this.indicator;
- indicator.setAttribute("notification", aType);
- this._notificationTimeout = setTimeout(
- function () indicator.removeAttribute("notification"), 1000);
- }
-
- this._ensureOperational(DIV_SEN_callback.bind(this));
- },
-
- //////////////////////////////////////////////////////////////////////////////
- //// Callback functions from DownloadsIndicatorData
-
- /**
- * Indicates whether the indicator should be shown because there are some
- * downloads to be displayed.
- */
- set hasDownloads(aValue)
- {
- if (this._hasDownloads != aValue) {
- this._hasDownloads = aValue;
-
- // If there is at least one download, ensure that the view elements are
- // loaded before determining the position of the downloads button.
- if (aValue) {
- this._ensureOperational(function() DownloadsButton.updatePosition());
- } else {
- DownloadsButton.updatePosition();
- }
- }
- return aValue;
- },
- get hasDownloads()
- {
- return this._hasDownloads;
- },
- _hasDownloads: false,
-
- /**
- * Status text displayed in the indicator. If this is set to an empty value,
- * then the small downloads icon is displayed instead of the text.
- */
- set counter(aValue)
- {
- if (!this._operational) {
- return this._counter;
- }
-
- if (this._counter !== aValue) {
- this._counter = aValue;
- if (this._counter)
- this.indicator.setAttribute("counter", "true");
- else
- this.indicator.removeAttribute("counter");
- // We have to set the attribute instead of using the property because the
- // XBL binding isn't applied if the element is invisible for any reason.
- this._indicatorCounter.setAttribute("value", aValue);
- }
- return aValue;
- },
- _counter: null,
-
- /**
- * Progress indication to display, from 0 to 100, or -1 if unknown. The
- * progress bar is hidden if the current progress is unknown and no status
- * text is set in the "counter" property.
- */
- set percentComplete(aValue)
- {
- if (!this._operational) {
- return this._percentComplete;
- }
-
- if (this._percentComplete !== aValue) {
- this._percentComplete = aValue;
- if (this._percentComplete >= 0)
- this.indicator.setAttribute("progress", "true");
- else
- this.indicator.removeAttribute("progress");
- // We have to set the attribute instead of using the property because the
- // XBL binding isn't applied if the element is invisible for any reason.
- this._indicatorProgress.setAttribute("value", Math.max(aValue, 0));
- }
- return aValue;
- },
- _percentComplete: null,
-
- /**
- * Indicates whether the progress won't advance because of a paused state.
- * Setting this property forces a paused progress bar to be displayed, even if
- * the current progress information is unavailable.
- */
- set paused(aValue)
- {
- if (!this._operational) {
- return this._paused;
- }
-
- if (this._paused != aValue) {
- this._paused = aValue;
- if (this._paused) {
- this.indicator.setAttribute("paused", "true")
- } else {
- this.indicator.removeAttribute("paused");
- }
- }
- return aValue;
- },
- _paused: false,
-
- /**
- * Set when the indicator should draw user attention to itself.
- */
- set attention(aValue)
- {
- if (!this._operational) {
- return this._attention;
- }
-
- if (this._attention != aValue) {
- this._attention = aValue;
- if (aValue) {
- this.indicator.setAttribute("attention", "true");
- } else {
- this.indicator.removeAttribute("attention");
- }
- }
- return aValue;
- },
- _attention: false,
-
- //////////////////////////////////////////////////////////////////////////////
- //// User interface event functions
-
- onWindowUnload: function DIV_onWindowUnload()
- {
- // This function is registered as an event listener, we can't use "this".
- DownloadsIndicatorView.ensureTerminated();
- },
-
- onCommand: function DIV_onCommand(aEvent)
- {
- if (DownloadsCommon.useToolkitUI) {
- // The panel won't suppress attention for us, we need to clear now.
- DownloadsCommon.getIndicatorData(window).attention = false;
- BrowserDownloadsUI();
- } else {
- DownloadsPanel.showPanel();
- }
-
- aEvent.stopPropagation();
- },
-
- onDragOver: function DIV_onDragOver(aEvent)
- {
- browserDragAndDrop.dragOver(aEvent);
- },
-
- onDrop: function DIV_onDrop(aEvent)
- {
- let dt = aEvent.dataTransfer;
- // If dragged item is from our source, do not try to
- // redownload already downloaded file.
- if (dt.mozGetDataAt("application/x-moz-file", 0))
- return;
-
- let links = browserDragAndDrop.dropLinks(aEvent);
- if (!links.length)
- return;
- let sourceDoc = dt.mozSourceNode ? dt.mozSourceNode.ownerDocument : document;
- let handled = false;
- for (let link of links) {
- if (link.url.startsWith("about:"))
- continue;
- saveURL(link.url, link.name, null, true, true, null, sourceDoc);
- handled = true;
- }
- if (handled) {
- aEvent.preventDefault();
- }
- },
-
- /**
- * Returns a reference to the main indicator element, or null if the element
- * is not present in the browser window yet.
- */
- get indicator()
- {
- let indicator = document.getElementById("downloads-indicator");
- if (!indicator) {
- return null;
- }
-
- // Once the element is loaded, it will never be unloaded.
- delete this.indicator;
- return this.indicator = indicator;
- },
-
- get indicatorAnchor()
- {
- delete this.indicatorAnchor;
- return this.indicatorAnchor =
- document.getElementById("downloads-indicator-anchor");
- },
-
- get _indicatorCounter()
- {
- delete this._indicatorCounter;
- return this._indicatorCounter =
- document.getElementById("downloads-indicator-counter");
- },
-
- get _indicatorProgress()
- {
- delete this._indicatorProgress;
- return this._indicatorProgress =
- document.getElementById("downloads-indicator-progress");
- }
-};
-
-Object.defineProperty(this, "DownloadsIndicatorView", {
- value: DownloadsIndicatorView,
- enumerable: true,
- writable: false
-});
diff --git a/components/downloads/content/indicatorOverlay.xul b/components/downloads/content/indicatorOverlay.xul
deleted file mode 100644
index efb6cab..0000000
--- a/components/downloads/content/indicatorOverlay.xul
+++ /dev/null
@@ -1,60 +0,0 @@
-<?xml version="1.0"?>
-<!-- -*- Mode: HTML; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- -->
-<!-- vim: set ts=2 et sw=2 tw=80: -->
-
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this file,
- - You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<?xml-stylesheet href="chrome://browser/content/downloads/downloads.css"?>
-<?xml-stylesheet href="chrome://browser/skin/downloads/downloads.css"?>
-
-<!DOCTYPE overlay [
- <!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd" >
- %browserDTD;
- <!ENTITY % downloadsDTD SYSTEM "chrome://browser/locale/downloads/downloads.dtd" >
- %downloadsDTD;
-]>
-
-<overlay xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- id="indicatorOverlay">
-
- <popupset>
- <!-- The downloads indicator is placed in its final toolbar location
- programmatically, and can be shown temporarily even when its
- placeholder is removed from the toolbars. Its initial location within
- the document must not be a toolbar or the toolbar palette, otherwise the
- toolbar handling code could remove it from the document. -->
- <toolbarbutton id="downloads-indicator"
- class="toolbarbutton-1 chromeclass-toolbar-additional"
- tooltiptext="&downloads.tooltip;"
- collapsed="true"
- oncommand="DownloadsIndicatorView.onCommand(event);"
- ondrop="DownloadsIndicatorView.onDrop(event);"
- ondragover="DownloadsIndicatorView.onDragOver(event);"
- ondragenter="DownloadsIndicatorView.onDragOver(event);"
- ondragleave="DownloadsIndicatorView.onDragLeave(event);"
- skipintoolbarset="true">
- <!-- The panel's anchor area is smaller than the outer button, but must
- always be visible and must not move or resize when the indicator
- state changes, otherwise the panel could change its position or lose
- its arrow unexpectedly. -->
- <stack id="downloads-indicator-anchor"
- class="toolbarbutton-icon">
- <vbox id="downloads-indicator-progress-area"
- pack="center">
- <description id="downloads-indicator-counter"/>
- <progressmeter id="downloads-indicator-progress"
- class="plain"
- min="0"
- max="100"/>
- </vbox>
- <vbox id="downloads-indicator-icon"/>
- <vbox id="downloads-indicator-notification"/>
- </stack>
- <label class="toolbarbutton-text" crop="right" flex="1"
- value="&downloads.label;"/>
- </toolbarbutton>
- </popupset>
-</overlay>
diff --git a/components/downloads/jar.mn b/components/downloads/jar.mn
deleted file mode 100644
index 8c0b519..0000000
--- a/components/downloads/jar.mn
+++ /dev/null
@@ -1,18 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-browser.jar:
-* content/browser/downloads/download.xml (content/download.xml)
- content/browser/downloads/download.css (content/download.css)
- content/browser/downloads/downloads.css (content/downloads.css)
-* content/browser/downloads/downloads.js (content/downloads.js)
-* content/browser/downloads/downloadsOverlay.xul (content/downloadsOverlay.xul)
- content/browser/downloads/indicator.js (content/indicator.js)
- content/browser/downloads/indicatorOverlay.xul (content/indicatorOverlay.xul)
-* content/browser/downloads/allDownloadsViewOverlay.xul (content/allDownloadsViewOverlay.xul)
- content/browser/downloads/allDownloadsViewOverlay.js (content/allDownloadsViewOverlay.js)
- content/browser/downloads/allDownloadsViewOverlay.css (content/allDownloadsViewOverlay.css)
-* content/browser/downloads/contentAreaDownloadsView.xul (content/contentAreaDownloadsView.xul)
- content/browser/downloads/contentAreaDownloadsView.js (content/contentAreaDownloadsView.js)
- content/browser/downloads/contentAreaDownloadsView.css (content/contentAreaDownloadsView.css)
diff --git a/components/downloads/moz.build b/components/downloads/moz.build
deleted file mode 100644
index abfaab7..0000000
--- a/components/downloads/moz.build
+++ /dev/null
@@ -1,23 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-JAR_MANIFESTS += ['jar.mn']
-
-EXTRA_COMPONENTS += [
- 'BrowserDownloads.manifest',
- 'DownloadsStartup.js',
- 'DownloadsUI.js',
-]
-
-EXTRA_JS_MODULES += [
- 'DownloadsLogger.jsm',
- 'DownloadsTaskbar.jsm',
- 'DownloadsViewUI.jsm',
-]
-
-EXTRA_PP_JS_MODULES += [
- 'DownloadsCommon.jsm',
-]
diff --git a/components/feeds/BrowserFeeds.manifest b/components/feeds/BrowserFeeds.manifest
deleted file mode 100644
index a584323..0000000
--- a/components/feeds/BrowserFeeds.manifest
+++ /dev/null
@@ -1,28 +0,0 @@
-# WebappRT doesn't need these instructions, and they don't necessarily work
-# with it, but it does use a GRE directory that the GRE shares with Firefox,
-# so in order to prevent the instructions from being processed for WebappRT,
-# we need to restrict them to the applications that depend on them, i.e.:
-#
-# b2g: {3c2e2abc-06d4-11e1-ac3b-374f68613e61}
-# browser: {8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}
-# mobile/android: {aa3c5121-dab2-40e2-81ca-7ea25febc110}
-# mobile/xul: {a23983c0-fd0e-11dc-95ff-0800200c9a66}
-#
-# In theory we should do this for all these instructions, but in practice it is
-# sufficient to do it for the app-startup one, and the file is simpler that way.
-
-component {229fa115-9412-4d32-baf3-2fc407f76fb1} FeedConverter.js
-contract @mozilla.org/streamconv;1?from=application/vnd.mozilla.maybe.feed&to=*/* {229fa115-9412-4d32-baf3-2fc407f76fb1}
-contract @mozilla.org/streamconv;1?from=application/vnd.mozilla.maybe.video.feed&to=*/* {229fa115-9412-4d32-baf3-2fc407f76fb1}
-contract @mozilla.org/streamconv;1?from=application/vnd.mozilla.maybe.audio.feed&to=*/* {229fa115-9412-4d32-baf3-2fc407f76fb1}
-component {2376201c-bbc6-472f-9b62-7548040a61c6} FeedConverter.js
-contract @mozilla.org/browser/feeds/result-service;1 {2376201c-bbc6-472f-9b62-7548040a61c6}
-component {4f91ef2e-57ba-472e-ab7a-b4999e42d6c0} FeedConverter.js
-contract @mozilla.org/network/protocol;1?name=feed {4f91ef2e-57ba-472e-ab7a-b4999e42d6c0}
-component {1c31ed79-accd-4b94-b517-06e0c81999d5} FeedConverter.js
-contract @mozilla.org/network/protocol;1?name=pcast {1c31ed79-accd-4b94-b517-06e0c81999d5}
-component {49bb6593-3aff-4eb3-a068-2712c28bd58e} FeedWriter.js
-contract @mozilla.org/browser/feeds/result-writer;1 {49bb6593-3aff-4eb3-a068-2712c28bd58e}
-component {792a7e82-06a0-437c-af63-b2d12e808acc} WebContentConverter.js
-contract @mozilla.org/embeddor.implemented/web-content-handler-registrar;1 {792a7e82-06a0-437c-af63-b2d12e808acc}
-category app-startup WebContentConverter service,@mozilla.org/embeddor.implemented/web-content-handler-registrar;1 application={3c2e2abc-06d4-11e1-ac3b-374f68613e61} application={8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4} application={aa3c5121-dab2-40e2-81ca-7ea25febc110} application={a23983c0-fd0e-11dc-95ff-0800200c9a66}
diff --git a/components/feeds/FeedConverter.js b/components/feeds/FeedConverter.js
deleted file mode 100644
index d0f5737..0000000
--- a/components/feeds/FeedConverter.js
+++ /dev/null
@@ -1,591 +0,0 @@
-/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
-Components.utils.import("resource://gre/modules/debug.js");
-Components.utils.import("resource://gre/modules/Services.jsm");
-
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-const Cr = Components.results;
-
-function LOG(str) {
- dump("*** " + str + "\n");
-}
-
-const FS_CONTRACTID = "@mozilla.org/browser/feeds/result-service;1";
-const FPH_CONTRACTID = "@mozilla.org/network/protocol;1?name=feed";
-const PCPH_CONTRACTID = "@mozilla.org/network/protocol;1?name=pcast";
-
-const TYPE_MAYBE_FEED = "application/vnd.mozilla.maybe.feed";
-const TYPE_MAYBE_VIDEO_FEED = "application/vnd.mozilla.maybe.video.feed";
-const TYPE_MAYBE_AUDIO_FEED = "application/vnd.mozilla.maybe.audio.feed";
-const TYPE_ANY = "*/*";
-
-const PREF_SELECTED_APP = "browser.feeds.handlers.application";
-const PREF_SELECTED_WEB = "browser.feeds.handlers.webservice";
-const PREF_SELECTED_ACTION = "browser.feeds.handler";
-const PREF_SELECTED_READER = "browser.feeds.handler.default";
-
-const PREF_VIDEO_SELECTED_APP = "browser.videoFeeds.handlers.application";
-const PREF_VIDEO_SELECTED_WEB = "browser.videoFeeds.handlers.webservice";
-const PREF_VIDEO_SELECTED_ACTION = "browser.videoFeeds.handler";
-const PREF_VIDEO_SELECTED_READER = "browser.videoFeeds.handler.default";
-
-const PREF_AUDIO_SELECTED_APP = "browser.audioFeeds.handlers.application";
-const PREF_AUDIO_SELECTED_WEB = "browser.audioFeeds.handlers.webservice";
-const PREF_AUDIO_SELECTED_ACTION = "browser.audioFeeds.handler";
-const PREF_AUDIO_SELECTED_READER = "browser.audioFeeds.handler.default";
-
-function getPrefAppForType(t) {
- switch (t) {
- case Ci.nsIFeed.TYPE_VIDEO:
- return PREF_VIDEO_SELECTED_APP;
-
- case Ci.nsIFeed.TYPE_AUDIO:
- return PREF_AUDIO_SELECTED_APP;
-
- default:
- return PREF_SELECTED_APP;
- }
-}
-
-function getPrefWebForType(t) {
- switch (t) {
- case Ci.nsIFeed.TYPE_VIDEO:
- return PREF_VIDEO_SELECTED_WEB;
-
- case Ci.nsIFeed.TYPE_AUDIO:
- return PREF_AUDIO_SELECTED_WEB;
-
- default:
- return PREF_SELECTED_WEB;
- }
-}
-
-function getPrefActionForType(t) {
- switch (t) {
- case Ci.nsIFeed.TYPE_VIDEO:
- return PREF_VIDEO_SELECTED_ACTION;
-
- case Ci.nsIFeed.TYPE_AUDIO:
- return PREF_AUDIO_SELECTED_ACTION;
-
- default:
- return PREF_SELECTED_ACTION;
- }
-}
-
-function getPrefReaderForType(t) {
- switch (t) {
- case Ci.nsIFeed.TYPE_VIDEO:
- return PREF_VIDEO_SELECTED_READER;
-
- case Ci.nsIFeed.TYPE_AUDIO:
- return PREF_AUDIO_SELECTED_READER;
-
- default:
- return PREF_SELECTED_READER;
- }
-}
-
-function safeGetCharPref(pref, defaultValue) {
- var prefs =
- Cc["@mozilla.org/preferences-service;1"].
- getService(Ci.nsIPrefBranch);
- try {
- return prefs.getCharPref(pref);
- }
- catch (e) {
- }
- return defaultValue;
-}
-
-function FeedConverter() {
-}
-FeedConverter.prototype = {
- classID: Components.ID("{229fa115-9412-4d32-baf3-2fc407f76fb1}"),
-
- /**
- * This is the downloaded text data for the feed.
- */
- _data: null,
-
- /**
- * This is the object listening to the conversion, which is ultimately the
- * docshell for the load.
- */
- _listener: null,
-
- /**
- * Records if the feed was sniffed
- */
- _sniffed: false,
-
- /**
- * See nsIStreamConverter.idl
- */
- convert: function FC_convert(sourceStream, sourceType, destinationType,
- context) {
- throw Cr.NS_ERROR_NOT_IMPLEMENTED;
- },
-
- /**
- * See nsIStreamConverter.idl
- */
- asyncConvertData: function FC_asyncConvertData(sourceType, destinationType,
- listener, context) {
- this._listener = listener;
- },
-
- /**
- * Whether or not the preview page is being forced.
- */
- _forcePreviewPage: false,
-
- /**
- * Release our references to various things once we're done using them.
- */
- _releaseHandles: function FC__releaseHandles() {
- this._listener = null;
- this._request = null;
- this._processor = null;
- },
-
- /**
- * See nsIFeedResultListener.idl
- */
- handleResult: function FC_handleResult(result) {
- // Feeds come in various content types, which our feed sniffer coerces to
- // the maybe.feed type. However, feeds are used as a transport for
- // different data types, e.g. news/blogs (traditional feed), video/audio
- // (podcasts) and photos (photocasts, photostreams). Each of these is
- // different in that there's a different class of application suitable for
- // handling feeds of that type, but without a content-type differentiation
- // it is difficult for us to disambiguate.
- //
- // The other problem is that if the user specifies an auto-action handler
- // for one feed application, the fact that the content type is shared means
- // that all other applications will auto-load with that handler too,
- // regardless of the content-type.
- //
- // This means that content-type alone is not enough to determine whether
- // or not a feed should be auto-handled. This means that for feeds we need
- // to always use this stream converter, even when an auto-action is
- // specified, not the basic one provided by WebContentConverter. This
- // converter needs to consume all of the data and parse it, and based on
- // that determination make a judgment about type.
- //
- // Since there are no content types for this content, and I'm not going to
- // invent any, the upshot is that while a user can set an auto-handler for
- // generic feed content, the system will prevent them from setting an auto-
- // handler for other stream types. In those cases, the user will always see
- // the preview page and have to select a handler. We can guess and show
- // a client handler, but will not be able to show web handlers for those
- // types.
- //
- // If this is just a feed, not some kind of specialized application, then
- // auto-handlers can be set and we should obey them.
- try {
- var feedService =
- Cc["@mozilla.org/browser/feeds/result-service;1"].
- getService(Ci.nsIFeedResultService);
- if (!this._forcePreviewPage && result.doc) {
- var feed = result.doc.QueryInterface(Ci.nsIFeed);
- var handler = safeGetCharPref(getPrefActionForType(feed.type), "ask");
-
- if (handler != "ask") {
- if (handler == "reader")
- handler = safeGetCharPref(getPrefReaderForType(feed.type), "bookmarks");
- switch (handler) {
- case "web":
- var wccr =
- Cc["@mozilla.org/embeddor.implemented/web-content-handler-registrar;1"].
- getService(Ci.nsIWebContentConverterService);
- if ((feed.type == Ci.nsIFeed.TYPE_FEED &&
- wccr.getAutoHandler(TYPE_MAYBE_FEED)) ||
- (feed.type == Ci.nsIFeed.TYPE_VIDEO &&
- wccr.getAutoHandler(TYPE_MAYBE_VIDEO_FEED)) ||
- (feed.type == Ci.nsIFeed.TYPE_AUDIO &&
- wccr.getAutoHandler(TYPE_MAYBE_AUDIO_FEED))) {
- wccr.loadPreferredHandler(this._request);
- return;
- }
- break;
-
- default:
- LOG("unexpected handler: " + handler);
- // fall through -- let feed service handle error
- case "bookmarks":
- case "client":
- try {
- var title = feed.title ? feed.title.plainText() : "";
- var desc = feed.subtitle ? feed.subtitle.plainText() : "";
- feedService.addToClientReader(result.uri.spec, title, desc, feed.type);
- return;
- } catch(ex) { /* fallback to preview mode */ }
- }
- }
- }
-
- var ios =
- Cc["@mozilla.org/network/io-service;1"].
- getService(Ci.nsIIOService);
- var chromeChannel;
-
- // handling a redirect, hence forwarding the loadInfo from the old channel
- // to the newchannel.
- var oldChannel = this._request.QueryInterface(Ci.nsIChannel);
- var loadInfo = oldChannel.loadInfo;
-
- // If there was no automatic handler, or this was a podcast,
- // photostream or some other kind of application, show the preview page
- // if the parser returned a document.
- if (result.doc) {
-
- // Store the result in the result service so that the display
- // page can access it.
- feedService.addFeedResult(result);
-
- // Now load the actual XUL document.
- var aboutFeedsURI = ios.newURI("about:feeds", null, null);
- chromeChannel = ios.newChannelFromURIWithLoadInfo(aboutFeedsURI, loadInfo);
- chromeChannel.originalURI = result.uri;
- chromeChannel.owner =
- Services.scriptSecurityManager.getNoAppCodebasePrincipal(aboutFeedsURI);
- } else {
- chromeChannel = ios.newChannelFromURIWithLoadInfo(result.uri, loadInfo);
- }
-
- chromeChannel.loadGroup = this._request.loadGroup;
- chromeChannel.asyncOpen2(this._listener);
- }
- finally {
- this._releaseHandles();
- }
- },
-
- /**
- * See nsIStreamListener.idl
- */
- onDataAvailable: function FC_onDataAvailable(request, context, inputStream,
- sourceOffset, count) {
- if (this._processor)
- this._processor.onDataAvailable(request, context, inputStream,
- sourceOffset, count);
- },
-
- /**
- * See nsIRequestObserver.idl
- */
- onStartRequest: function FC_onStartRequest(request, context) {
- var channel = request.QueryInterface(Ci.nsIChannel);
-
- // Check for a header that tells us there was no sniffing
- // The value doesn't matter.
- try {
- var httpChannel = channel.QueryInterface(Ci.nsIHttpChannel);
- // Make sure to check requestSucceeded before the potentially-throwing
- // getResponseHeader.
- if (!httpChannel.requestSucceeded) {
- // Just give up, but don't forget to cancel the channel first!
- request.cancel(Cr.NS_BINDING_ABORTED);
- return;
- }
- var noSniff = httpChannel.getResponseHeader("X-Moz-Is-Feed");
- }
- catch (ex) {
- this._sniffed = true;
- }
-
- this._request = request;
-
- // Save and reset the forced state bit early, in case there's some kind of
- // error.
- var feedService =
- Cc["@mozilla.org/browser/feeds/result-service;1"].
- getService(Ci.nsIFeedResultService);
- this._forcePreviewPage = feedService.forcePreviewPage;
- feedService.forcePreviewPage = false;
-
- // Parse feed data as it comes in
- this._processor =
- Cc["@mozilla.org/feed-processor;1"].
- createInstance(Ci.nsIFeedProcessor);
- this._processor.listener = this;
- this._processor.parseAsync(null, channel.URI);
-
- this._processor.onStartRequest(request, context);
- },
-
- /**
- * See nsIRequestObserver.idl
- */
- onStopRequest: function FC_onStopRequest(request, context, status) {
- if (this._processor)
- this._processor.onStopRequest(request, context, status);
- },
-
- /**
- * See nsISupports.idl
- */
- QueryInterface: function FC_QueryInterface(iid) {
- if (iid.equals(Ci.nsIFeedResultListener) ||
- iid.equals(Ci.nsIStreamConverter) ||
- iid.equals(Ci.nsIStreamListener) ||
- iid.equals(Ci.nsIRequestObserver)||
- iid.equals(Ci.nsISupports))
- return this;
- throw Cr.NS_ERROR_NO_INTERFACE;
- },
-};
-
-/**
- * Keeps parsed FeedResults around for use elsewhere in the UI after the stream
- * converter completes.
- */
-function FeedResultService() {
-}
-
-FeedResultService.prototype = {
- classID: Components.ID("{2376201c-bbc6-472f-9b62-7548040a61c6}"),
-
- /**
- * A URI spec -> [nsIFeedResult] hash. We have to keep a list as the
- * value in case the same URI is requested concurrently.
- */
- _results: { },
-
- /**
- * See nsIFeedResultService.idl
- */
- forcePreviewPage: false,
-
- /**
- * See nsIFeedResultService.idl
- */
- addToClientReader: function FRS_addToClientReader(spec, title, subtitle, feedType) {
- var prefs =
- Cc["@mozilla.org/preferences-service;1"].
- getService(Ci.nsIPrefBranch);
-
- var handler = safeGetCharPref(getPrefActionForType(feedType), "bookmarks");
- if (handler == "ask" || handler == "reader")
- handler = safeGetCharPref(getPrefReaderForType(feedType), "bookmarks");
-
- switch (handler) {
- case "client":
- var clientApp = prefs.getComplexValue(getPrefAppForType(feedType), Ci.nsILocalFile);
-
- // For the benefit of applications that might know how to deal with more
- // URLs than just feeds, send feed: URLs in the following format:
- //
- // http urls: replace scheme with feed, e.g.
- // http://foo.com/index.rdf -> feed://foo.com/index.rdf
- // other urls: prepend feed: scheme, e.g.
- // https://foo.com/index.rdf -> feed:https://foo.com/index.rdf
- var ios =
- Cc["@mozilla.org/network/io-service;1"].
- getService(Ci.nsIIOService);
- var feedURI = ios.newURI(spec, null, null);
- if (feedURI.schemeIs("http")) {
- feedURI.scheme = "feed";
- spec = feedURI.spec;
- }
- else
- spec = "feed:" + spec;
-
- // Retrieving the shell service might fail on some systems, most
- // notably systems where GNOME is not installed.
- try {
- var ss =
- Cc["@mozilla.org/browser/shell-service;1"].
- getService(Ci.nsIShellService);
- ss.openApplicationWithURI(clientApp, spec);
- } catch(e) {
- // If we couldn't use the shell service, fallback to using a
- // nsIProcess instance
- var p =
- Cc["@mozilla.org/process/util;1"].
- createInstance(Ci.nsIProcess);
- p.init(clientApp);
- p.run(false, [spec], 1);
- }
- break;
-
- default:
- // "web" should have been handled elsewhere
- LOG("unexpected handler: " + handler);
- // fall through
- case "bookmarks":
- var wm =
- Cc["@mozilla.org/appshell/window-mediator;1"].
- getService(Ci.nsIWindowMediator);
- var topWindow = wm.getMostRecentWindow("navigator:browser");
- topWindow.PlacesCommandHook.addLiveBookmark(spec, title, subtitle);
- break;
- }
- },
-
- /**
- * See nsIFeedResultService.idl
- */
- addFeedResult: function FRS_addFeedResult(feedResult) {
- NS_ASSERT(feedResult.uri != null, "null URI!");
- NS_ASSERT(feedResult.uri != null, "null feedResult!");
- var spec = feedResult.uri.spec;
- if(!this._results[spec])
- this._results[spec] = [];
- this._results[spec].push(feedResult);
- },
-
- /**
- * See nsIFeedResultService.idl
- */
- getFeedResult: function RFS_getFeedResult(uri) {
- NS_ASSERT(uri != null, "null URI!");
- var resultList = this._results[uri.spec];
- for (var i in resultList) {
- if (resultList[i].uri == uri)
- return resultList[i];
- }
- return null;
- },
-
- /**
- * See nsIFeedResultService.idl
- */
- removeFeedResult: function FRS_removeFeedResult(uri) {
- NS_ASSERT(uri != null, "null URI!");
- var resultList = this._results[uri.spec];
- if (!resultList)
- return;
- var deletions = 0;
- for (var i = 0; i < resultList.length; ++i) {
- if (resultList[i].uri == uri) {
- delete resultList[i];
- ++deletions;
- }
- }
-
- // send the holes to the end
- resultList.sort();
- // and trim the list
- resultList.splice(resultList.length - deletions, deletions);
- if (resultList.length == 0)
- delete this._results[uri.spec];
- },
-
- createInstance: function FRS_createInstance(outer, iid) {
- if (outer != null)
- throw Cr.NS_ERROR_NO_AGGREGATION;
- return this.QueryInterface(iid);
- },
-
- QueryInterface: function FRS_QueryInterface(iid) {
- if (iid.equals(Ci.nsIFeedResultService) ||
- iid.equals(Ci.nsIFactory) ||
- iid.equals(Ci.nsISupports))
- return this;
- throw Cr.NS_ERROR_NOT_IMPLEMENTED;
- },
-};
-
-/**
- * A protocol handler that attempts to deal with the variant forms of feed:
- * URIs that are actually either http or https.
- */
-function GenericProtocolHandler() {
-}
-GenericProtocolHandler.prototype = {
- _init: function GPH_init(scheme) {
- var ios =
- Cc["@mozilla.org/network/io-service;1"].
- getService(Ci.nsIIOService);
- this._http = ios.getProtocolHandler("http");
- this._scheme = scheme;
- },
-
- get scheme() {
- return this._scheme;
- },
-
- get protocolFlags() {
- return this._http.protocolFlags;
- },
-
- get defaultPort() {
- return this._http.defaultPort;
- },
-
- allowPort: function GPH_allowPort(port, scheme) {
- return this._http.allowPort(port, scheme);
- },
-
- newURI: function GPH_newURI(spec, originalCharset, baseURI) {
- // Feed URIs can be either nested URIs of the form feed:realURI (in which
- // case we create a nested URI for the realURI) or feed://example.com, in
- // which case we create a nested URI for the real protocol which is http.
-
- var scheme = this._scheme + ":";
- if (spec.substr(0, scheme.length) != scheme)
- throw Cr.NS_ERROR_MALFORMED_URI;
-
- var prefix = spec.substr(scheme.length, 2) == "//" ? "http:" : "";
- var inner = Cc["@mozilla.org/network/io-service;1"].
- getService(Ci.nsIIOService).newURI(spec.replace(scheme, prefix),
- originalCharset, baseURI);
- var netutil = Cc["@mozilla.org/network/util;1"].getService(Ci.nsINetUtil);
- const URI_INHERITS_SECURITY_CONTEXT = Ci.nsIProtocolHandler
- .URI_INHERITS_SECURITY_CONTEXT;
- if (netutil.URIChainHasFlags(inner, URI_INHERITS_SECURITY_CONTEXT))
- throw Cr.NS_ERROR_MALFORMED_URI;
-
- var uri = netutil.newSimpleNestedURI(inner);
- uri.spec = inner.spec.replace(prefix, scheme);
- return uri;
- },
-
- newChannel2: function GPH_newChannel(aUri, aLoadInfo) {
- var inner = aUri.QueryInterface(Ci.nsINestedURI).innerURI;
- var channel = Cc["@mozilla.org/network/io-service;1"].
- getService(Ci.nsIIOService).
- newChannelFromURIWithLoadInfo(inner, aLoadInfo);
-
- if (channel instanceof Components.interfaces.nsIHttpChannel)
- // Set this so we know this is supposed to be a feed
- channel.setRequestHeader("X-Moz-Is-Feed", "1", false);
- channel.originalURI = aUri;
- return channel;
- },
-
-
- QueryInterface: function GPH_QueryInterface(iid) {
- if (iid.equals(Ci.nsIProtocolHandler) ||
- iid.equals(Ci.nsISupports))
- return this;
- throw Cr.NS_ERROR_NO_INTERFACE;
- }
-};
-
-function FeedProtocolHandler() {
- this._init('feed');
-}
-FeedProtocolHandler.prototype = new GenericProtocolHandler();
-FeedProtocolHandler.prototype.classID = Components.ID("{4f91ef2e-57ba-472e-ab7a-b4999e42d6c0}");
-
-function PodCastProtocolHandler() {
- this._init('pcast');
-}
-PodCastProtocolHandler.prototype = new GenericProtocolHandler();
-PodCastProtocolHandler.prototype.classID = Components.ID("{1c31ed79-accd-4b94-b517-06e0c81999d5}");
-
-var components = [FeedConverter,
- FeedResultService,
- FeedProtocolHandler,
- PodCastProtocolHandler];
-
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
diff --git a/components/feeds/FeedWriter.js b/components/feeds/FeedWriter.js
deleted file mode 100644
index facde58..0000000
--- a/components/feeds/FeedWriter.js
+++ /dev/null
@@ -1,1397 +0,0 @@
-# -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-const Cr = Components.results;
-const Cu = Components.utils;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/NetUtil.jsm");
-
-const FEEDWRITER_CID = Components.ID("{49bb6593-3aff-4eb3-a068-2712c28bd58e}");
-const FEEDWRITER_CONTRACTID = "@mozilla.org/browser/feeds/result-writer;1";
-
-function LOG(str) {
- var prefB = Cc["@mozilla.org/preferences-service;1"].
- getService(Ci.nsIPrefBranch);
-
- var shouldLog = prefB.getBoolPref("feeds.log", false);
-
- if (shouldLog)
- dump("*** Feeds: " + str + "\n");
-}
-
-/**
- * Wrapper function for nsIIOService::newURI.
- * @param aURLSpec
- * The URL string from which to create an nsIURI.
- * @returns an nsIURI object, or null if the creation of the URI failed.
- */
-function makeURI(aURLSpec, aCharset) {
- var ios = Cc["@mozilla.org/network/io-service;1"].
- getService(Ci.nsIIOService);
- try {
- return ios.newURI(aURLSpec, aCharset, null);
- } catch (ex) { }
-
- return null;
-}
-
-const XML_NS = "http://www.w3.org/XML/1998/namespace";
-const HTML_NS = "http://www.w3.org/1999/xhtml";
-const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
-const TYPE_MAYBE_FEED = "application/vnd.mozilla.maybe.feed";
-const TYPE_MAYBE_AUDIO_FEED = "application/vnd.mozilla.maybe.audio.feed";
-const TYPE_MAYBE_VIDEO_FEED = "application/vnd.mozilla.maybe.video.feed";
-const URI_BUNDLE = "chrome://browser/locale/feeds/subscribe.properties";
-
-const PREF_SELECTED_APP = "browser.feeds.handlers.application";
-const PREF_SELECTED_WEB = "browser.feeds.handlers.webservice";
-const PREF_SELECTED_ACTION = "browser.feeds.handler";
-const PREF_SELECTED_READER = "browser.feeds.handler.default";
-
-const PREF_VIDEO_SELECTED_APP = "browser.videoFeeds.handlers.application";
-const PREF_VIDEO_SELECTED_WEB = "browser.videoFeeds.handlers.webservice";
-const PREF_VIDEO_SELECTED_ACTION = "browser.videoFeeds.handler";
-const PREF_VIDEO_SELECTED_READER = "browser.videoFeeds.handler.default";
-
-const PREF_AUDIO_SELECTED_APP = "browser.audioFeeds.handlers.application";
-const PREF_AUDIO_SELECTED_WEB = "browser.audioFeeds.handlers.webservice";
-const PREF_AUDIO_SELECTED_ACTION = "browser.audioFeeds.handler";
-const PREF_AUDIO_SELECTED_READER = "browser.audioFeeds.handler.default";
-
-const PREF_SHOW_FIRST_RUN_UI = "browser.feeds.showFirstRunUI";
-
-const TITLE_ID = "feedTitleText";
-const SUBTITLE_ID = "feedSubtitleText";
-
-function getPrefAppForType(t) {
- switch (t) {
- case Ci.nsIFeed.TYPE_VIDEO:
- return PREF_VIDEO_SELECTED_APP;
-
- case Ci.nsIFeed.TYPE_AUDIO:
- return PREF_AUDIO_SELECTED_APP;
-
- default:
- return PREF_SELECTED_APP;
- }
-}
-
-function getPrefWebForType(t) {
- switch (t) {
- case Ci.nsIFeed.TYPE_VIDEO:
- return PREF_VIDEO_SELECTED_WEB;
-
- case Ci.nsIFeed.TYPE_AUDIO:
- return PREF_AUDIO_SELECTED_WEB;
-
- default:
- return PREF_SELECTED_WEB;
- }
-}
-
-function getPrefActionForType(t) {
- switch (t) {
- case Ci.nsIFeed.TYPE_VIDEO:
- return PREF_VIDEO_SELECTED_ACTION;
-
- case Ci.nsIFeed.TYPE_AUDIO:
- return PREF_AUDIO_SELECTED_ACTION;
-
- default:
- return PREF_SELECTED_ACTION;
- }
-}
-
-function getPrefReaderForType(t) {
- switch (t) {
- case Ci.nsIFeed.TYPE_VIDEO:
- return PREF_VIDEO_SELECTED_READER;
-
- case Ci.nsIFeed.TYPE_AUDIO:
- return PREF_AUDIO_SELECTED_READER;
-
- default:
- return PREF_SELECTED_READER;
- }
-}
-
-/**
- * Converts a number of bytes to the appropriate unit that results in a
- * number that needs fewer than 4 digits
- *
- * @return a pair: [new value with 3 sig. figs., its unit]
- */
-function convertByteUnits(aBytes) {
- var units = ["bytes", "kilobyte", "megabyte", "gigabyte"];
- let unitIndex = 0;
-
- // convert to next unit if it needs 4 digits (after rounding), but only if
- // we know the name of the next unit
- while ((aBytes >= 999.5) && (unitIndex < units.length - 1)) {
- aBytes /= 1024;
- unitIndex++;
- }
-
- // Get rid of insignificant bits by truncating to 1 or 0 decimal points
- // 0 -> 0; 1.2 -> 1.2; 12.3 -> 12.3; 123.4 -> 123; 234.5 -> 235
- aBytes = aBytes.toFixed((aBytes > 0) && (aBytes < 100) ? 1 : 0);
-
- return [aBytes, units[unitIndex]];
-}
-
-function FeedWriter() {}
-FeedWriter.prototype = {
- _mimeSvc : Cc["@mozilla.org/mime;1"].
- getService(Ci.nsIMIMEService),
-
- _getPropertyAsBag: function FW__getPropertyAsBag(container, property) {
- return container.fields.getProperty(property).
- QueryInterface(Ci.nsIPropertyBag2);
- },
-
- _getPropertyAsString: function FW__getPropertyAsString(container, property) {
- try {
- return container.fields.getPropertyAsAString(property);
- }
- catch (e) {
- }
- return "";
- },
-
- _setContentText: function FW__setContentText(id, text) {
- this._contentSandbox.element = this._document.getElementById(id);
- this._contentSandbox.textNode = text.createDocumentFragment(this._contentSandbox.element);
- var codeStr =
- "while (element.hasChildNodes()) " +
- " element.removeChild(element.firstChild);" +
- "element.appendChild(textNode);";
- if (text.base) {
- this._contentSandbox.spec = text.base.spec;
- codeStr += "element.setAttributeNS('" + XML_NS + "', 'base', spec);";
- }
- Cu.evalInSandbox(codeStr, this._contentSandbox);
- this._contentSandbox.element = null;
- this._contentSandbox.textNode = null;
- },
-
- /**
- * Safely sets the href attribute on an anchor tag, providing the URI
- * specified can be loaded according to rules.
- * @param element
- * The element to set a URI attribute on
- * @param attribute
- * The attribute of the element to set the URI to, e.g. href or src
- * @param uri
- * The URI spec to set as the href
- */
- _safeSetURIAttribute:
- function FW__safeSetURIAttribute(element, attribute, uri) {
- var secman = Cc["@mozilla.org/scriptsecuritymanager;1"].
- getService(Ci.nsIScriptSecurityManager);
- const flags = Ci.nsIScriptSecurityManager.DISALLOW_INHERIT_PRINCIPAL;
- try {
- secman.checkLoadURIStrWithPrincipal(this._feedPrincipal, uri, flags);
- // checkLoadURIStrWithPrincipal will throw if the link URI should not be
- // loaded, either because our feedURI isn't allowed to load it or per
- // the rules specified in |flags|, so we'll never "linkify" the link...
- }
- catch (e) {
- // Not allowed to load this link because secman.checkLoadURIStr threw
- return;
- }
-
- this._contentSandbox.element = element;
- this._contentSandbox.uri = uri;
- var codeStr = "element.setAttribute('" + attribute + "', uri);";
- Cu.evalInSandbox(codeStr, this._contentSandbox);
- },
-
- /**
- * Use this sandbox to run any dom manipulation code on nodes which
- * are already inserted into the content document.
- */
- __contentSandbox: null,
- get _contentSandbox() {
- // This whole sandbox setup is totally archaic. It was introduced in bug
- // 360529, presumably before the existence of a solid security membrane,
- // since all of the manipulation of content here should be made safe by
- // Xrays.
- // Now that anonymous content is no longer content-accessible, manipulating
- // the xml stylesheet content can't be done from content anymore.
- //
- // The right solution would be to rip out all of this sandbox junk and
- // manipulate the DOM directly, but that would require a lot of rewriting.
- // So, for now, we just give the sandbox an nsExpandedPrincipal with [].
- // This has the effect of giving it Xrays, and making it same-origin with
- // the XBL scope, thereby letting it manipulate anonymous content.
- if (!this.__contentSandbox)
- this.__contentSandbox = new Cu.Sandbox([this._window],
- {sandboxName: 'FeedWriter'});
-
- return this.__contentSandbox;
- },
-
- /**
- * Calls doCommand for a given XUL element within the context of the
- * content document.
- *
- * @param aElement
- * the XUL element to call doCommand() on.
- */
- _safeDoCommand: function FW___safeDoCommand(aElement) {
- this._contentSandbox.element = aElement;
- Cu.evalInSandbox("element.doCommand();", this._contentSandbox);
- this._contentSandbox.element = null;
- },
-
- __faviconService: null,
- get _faviconService() {
- if (!this.__faviconService)
- this.__faviconService = Cc["@mozilla.org/browser/favicon-service;1"].
- getService(Ci.nsIFaviconService);
-
- return this.__faviconService;
- },
-
- __bundle: null,
- get _bundle() {
- if (!this.__bundle) {
- this.__bundle = Cc["@mozilla.org/intl/stringbundle;1"].
- getService(Ci.nsIStringBundleService).
- createBundle(URI_BUNDLE);
- }
- return this.__bundle;
- },
-
- _getFormattedString: function FW__getFormattedString(key, params) {
- return this._bundle.formatStringFromName(key, params, params.length);
- },
-
- _getString: function FW__getString(key) {
- return this._bundle.GetStringFromName(key);
- },
-
- /* Magic helper methods to be used instead of xbl properties */
- _getSelectedItemFromMenulist: function FW__getSelectedItemFromList(aList) {
- var node = aList.firstChild.firstChild;
- while (node) {
- if (node.localName == "menuitem" && node.getAttribute("selected") == "true")
- return node;
-
- node = node.nextSibling;
- }
-
- return null;
- },
-
- _setCheckboxCheckedState: function FW__setCheckboxCheckedState(aCheckbox, aValue) {
- // see checkbox.xml, xbl bindings are not applied within the sandbox!
- this._contentSandbox.checkbox = aCheckbox;
- var codeStr;
- var change = (aValue != (aCheckbox.getAttribute('checked') == 'true'));
- if (aValue)
- codeStr = "checkbox.setAttribute('checked', 'true'); ";
- else
- codeStr = "checkbox.removeAttribute('checked'); ";
-
- if (change) {
- this._contentSandbox.document = this._document;
- codeStr += "var event = document.createEvent('Events'); " +
- "event.initEvent('CheckboxStateChange', true, true);" +
- "checkbox.dispatchEvent(event);"
- }
-
- Cu.evalInSandbox(codeStr, this._contentSandbox);
- },
-
- /**
- * Returns a date suitable for displaying in the feed preview.
- * If the date cannot be parsed, the return value is "false".
- * @param dateString
- * A date as extracted from a feed entry. (entry.updated)
- */
- _parseDate: function FW__parseDate(dateString) {
- // Convert the date into the user's local time zone
- dateObj = new Date(dateString);
-
- // Make sure the date we're given is valid.
- if (!dateObj.getTime())
- return false;
-
- var dateService = Cc["@mozilla.org/intl/scriptabledateformat;1"].
- getService(Ci.nsIScriptableDateFormat);
- return dateService.FormatDateTime("", dateService.dateFormatLong, dateService.timeFormatNoSeconds,
- dateObj.getFullYear(), dateObj.getMonth()+1, dateObj.getDate(),
- dateObj.getHours(), dateObj.getMinutes(), dateObj.getSeconds());
- },
-
- /**
- * Returns the feed type.
- */
- __feedType: null,
- _getFeedType: function FW__getFeedType() {
- if (this.__feedType != null)
- return this.__feedType;
-
- try {
- // grab the feed because it's got the feed.type in it.
- var container = this._getContainer();
- var feed = container.QueryInterface(Ci.nsIFeed);
- this.__feedType = feed.type;
- return feed.type;
- } catch (ex) { }
-
- return Ci.nsIFeed.TYPE_FEED;
- },
-
- /**
- * Maps a feed type to a maybe-feed mimetype.
- */
- _getMimeTypeForFeedType: function FW__getMimeTypeForFeedType() {
- switch (this._getFeedType()) {
- case Ci.nsIFeed.TYPE_VIDEO:
- return TYPE_MAYBE_VIDEO_FEED;
-
- case Ci.nsIFeed.TYPE_AUDIO:
- return TYPE_MAYBE_AUDIO_FEED;
-
- default:
- return TYPE_MAYBE_FEED;
- }
- },
-
- /**
- * Writes the feed title into the preview document.
- * @param container
- * The feed container
- */
- _setTitleText: function FW__setTitleText(container) {
- if (container.title) {
- var title = container.title.plainText();
- this._setContentText(TITLE_ID, container.title);
- this._contentSandbox.document = this._document;
- this._contentSandbox.title = title;
- var codeStr = "document.title = title;"
- Cu.evalInSandbox(codeStr, this._contentSandbox);
- }
-
- var feed = container.QueryInterface(Ci.nsIFeed);
- if (feed && feed.subtitle)
- this._setContentText(SUBTITLE_ID, container.subtitle);
- },
-
- /**
- * Writes the title image into the preview document if one is present.
- * @param container
- * The feed container
- */
- _setTitleImage: function FW__setTitleImage(container) {
- try {
- var parts = container.image;
-
- // Set up the title image (supplied by the feed)
- var feedTitleImage = this._document.getElementById("feedTitleImage");
- this._safeSetURIAttribute(feedTitleImage, "src",
- parts.getPropertyAsAString("url"));
-
- // Set up the title image link
- var feedTitleLink = this._document.getElementById("feedTitleLink");
-
- var titleText = this._getFormattedString("linkTitleTextFormat",
- [parts.getPropertyAsAString("title")]);
- this._contentSandbox.feedTitleLink = feedTitleLink;
- this._contentSandbox.titleText = titleText;
- this._contentSandbox.feedTitleText = this._document.getElementById("feedTitleText");
- this._contentSandbox.titleImageWidth = parseInt(parts.getPropertyAsAString("width")) + 15;
-
- // Fix the margin on the main title, so that the image doesn't run over
- // the underline
- var codeStr = "feedTitleLink.setAttribute('title', titleText); " +
- "feedTitleText.style.marginRight = titleImageWidth + 'px';";
- Cu.evalInSandbox(codeStr, this._contentSandbox);
- this._contentSandbox.feedTitleLink = null;
- this._contentSandbox.titleText = null;
- this._contentSandbox.feedTitleText = null;
- this._contentSandbox.titleImageWidth = null;
-
- this._safeSetURIAttribute(feedTitleLink, "href",
- parts.getPropertyAsAString("link"));
- }
- catch (e) {
- LOG("Failed to set Title Image (this is benign): " + e);
- }
- },
-
- /**
- * Writes all entries contained in the feed.
- * @param container
- * The container of entries in the feed
- */
- _writeFeedContent: function FW__writeFeedContent(container) {
- // Build the actual feed content
- var feed = container.QueryInterface(Ci.nsIFeed);
- if (feed.items.length == 0)
- return;
-
- this._contentSandbox.feedContent =
- this._document.getElementById("feedContent");
-
- for (var i = 0; i < feed.items.length; ++i) {
- var entry = feed.items.queryElementAt(i, Ci.nsIFeedEntry);
- entry.QueryInterface(Ci.nsIFeedContainer);
-
- var entryContainer = this._document.createElementNS(HTML_NS, "div");
- entryContainer.className = "entry";
-
- // If the entry has a title, make it a link
- if (entry.title) {
- var a = this._document.createElementNS(HTML_NS, "a");
- var span = this._document.createElementNS(HTML_NS, "span");
- a.appendChild(span);
- if (entry.title.base)
- span.setAttributeNS(XML_NS, "base", entry.title.base.spec);
- span.appendChild(entry.title.createDocumentFragment(a));
-
- // Entries are not required to have links, so entry.link can be null.
- if (entry.link)
- this._safeSetURIAttribute(a, "href", entry.link.spec);
-
- var title = this._document.createElementNS(HTML_NS, "h3");
- title.appendChild(a);
-
- var lastUpdated = this._parseDate(entry.updated);
- if (lastUpdated) {
- var dateDiv = this._document.createElementNS(HTML_NS, "div");
- dateDiv.className = "lastUpdated";
- dateDiv.textContent = lastUpdated;
- title.appendChild(dateDiv);
- }
-
- entryContainer.appendChild(title);
- }
-
- var body = this._document.createElementNS(HTML_NS, "div");
- var summary = entry.summary || entry.content;
- var docFragment = null;
- if (summary) {
- if (summary.base)
- body.setAttributeNS(XML_NS, "base", summary.base.spec);
- else
- LOG("no base?");
- docFragment = summary.createDocumentFragment(body);
- if (docFragment)
- body.appendChild(docFragment);
-
- // If the entry doesn't have a title, append a # permalink
- // See http://scripting.com/rss.xml for an example
- if (!entry.title && entry.link) {
- var a = this._document.createElementNS(HTML_NS, "a");
- a.appendChild(this._document.createTextNode("#"));
- this._safeSetURIAttribute(a, "href", entry.link.spec);
- body.appendChild(this._document.createTextNode(" "));
- body.appendChild(a);
- }
-
- }
- body.className = "feedEntryContent";
- entryContainer.appendChild(body);
-
- if (entry.enclosures && entry.enclosures.length > 0) {
- var enclosuresDiv = this._buildEnclosureDiv(entry);
- entryContainer.appendChild(enclosuresDiv);
- }
-
- this._contentSandbox.entryContainer = entryContainer;
- this._contentSandbox.clearDiv =
- this._document.createElementNS(HTML_NS, "div");
- this._contentSandbox.clearDiv.style.clear = "both";
-
- var codeStr = "feedContent.appendChild(entryContainer); " +
- "feedContent.appendChild(clearDiv);"
- Cu.evalInSandbox(codeStr, this._contentSandbox);
- }
-
- this._contentSandbox.feedContent = null;
- this._contentSandbox.entryContainer = null;
- this._contentSandbox.clearDiv = null;
- },
-
- /**
- * Takes a url to a media item and returns the best name it can come up with.
- * Frequently this is the filename portion (e.g. passing in
- * http://example.com/foo.mpeg would return "foo.mpeg"), but in more complex
- * cases, this will return the entire url (e.g. passing in
- * http://example.com/somedirectory/ would return
- * http://example.com/somedirectory/).
- * @param aURL
- * The URL string from which to create a display name
- * @returns a string
- */
- _getURLDisplayName: function FW__getURLDisplayName(aURL) {
- var url = makeURI(aURL);
- url.QueryInterface(Ci.nsIURL);
- if (url == null || url.fileName.length == 0)
- return decodeURIComponent(aURL);
-
- return decodeURIComponent(url.fileName);
- },
-
- /**
- * Takes a FeedEntry with enclosures, generates the HTML code to represent
- * them, and returns that.
- * @param entry
- * FeedEntry with enclosures
- * @returns element
- */
- _buildEnclosureDiv: function FW__buildEnclosureDiv(entry) {
- var enclosuresDiv = this._document.createElementNS(HTML_NS, "div");
- enclosuresDiv.className = "enclosures";
-
- enclosuresDiv.appendChild(this._document.createTextNode(this._getString("mediaLabel")));
-
- var roundme = function(n) {
- return (Math.round(n * 100) / 100).toLocaleString();
- }
-
- for (var i_enc = 0; i_enc < entry.enclosures.length; ++i_enc) {
- var enc = entry.enclosures.queryElementAt(i_enc, Ci.nsIWritablePropertyBag2);
-
- if (!(enc.hasKey("url")))
- continue;
-
- var enclosureDiv = this._document.createElementNS(HTML_NS, "div");
- enclosureDiv.setAttribute("class", "enclosure");
-
- var mozicon = "moz-icon://.txt?size=16";
- var type_text = null;
- var size_text = null;
-
- if (enc.hasKey("type")) {
- type_text = enc.get("type");
- try {
- var handlerInfoWrapper = this._mimeSvc.getFromTypeAndExtension(enc.get("type"), null);
-
- if (handlerInfoWrapper)
- type_text = handlerInfoWrapper.description;
-
- if (type_text && type_text.length > 0)
- mozicon = "moz-icon://goat?size=16&contentType=" + enc.get("type");
-
- } catch (ex) { }
-
- }
-
- if (enc.hasKey("length") && /^[0-9]+$/.test(enc.get("length"))) {
- var enc_size = convertByteUnits(parseInt(enc.get("length")));
-
- var size_text = this._getFormattedString("enclosureSizeText",
- [enc_size[0], this._getString(enc_size[1])]);
- }
-
- var iconimg = this._document.createElementNS(HTML_NS, "img");
- iconimg.setAttribute("src", mozicon);
- iconimg.setAttribute("class", "type-icon");
- enclosureDiv.appendChild(iconimg);
-
- enclosureDiv.appendChild(this._document.createTextNode( " " ));
-
- var enc_href = this._document.createElementNS(HTML_NS, "a");
- enc_href.appendChild(this._document.createTextNode(this._getURLDisplayName(enc.get("url"))));
- this._safeSetURIAttribute(enc_href, "href", enc.get("url"));
- enclosureDiv.appendChild(enc_href);
-
- if (type_text && size_text)
- enclosureDiv.appendChild(this._document.createTextNode( " (" + type_text + ", " + size_text + ")"));
-
- else if (type_text)
- enclosureDiv.appendChild(this._document.createTextNode( " (" + type_text + ")"))
-
- else if (size_text)
- enclosureDiv.appendChild(this._document.createTextNode( " (" + size_text + ")"))
-
- enclosuresDiv.appendChild(enclosureDiv);
- }
-
- return enclosuresDiv;
- },
-
- /**
- * Gets a valid nsIFeedContainer object from the parsed nsIFeedResult.
- * Displays error information if there was one.
- * @param result
- * The parsed feed result
- * @returns A valid nsIFeedContainer object containing the contents of
- * the feed.
- */
- _getContainer: function FW__getContainer(result) {
- var feedService =
- Cc["@mozilla.org/browser/feeds/result-service;1"].
- getService(Ci.nsIFeedResultService);
-
- result = null;
- try {
- result =
- feedService.getFeedResult(this._getOriginalURI(this._window));
- }
- catch (e) {
- // Ignore.
- }
-
- if (!result) {
- LOG("Subscribe Preview: feed not available?!");
- return null;
- }
-
- if (result.bozo) {
- LOG("Subscribe Preview: feed result is bozo?!");
- }
-
- try {
- var container = result.doc;
- }
- catch (e) {
- LOG("Subscribe Preview: no result.doc? Why didn't the original reload?");
- return null;
- }
- return container;
- },
-
- /**
- * Get the human-readable display name of a file. This could be the
- * application name.
- * @param file
- * A nsIFile to look up the name of
- * @returns The display name of the application represented by the file.
- */
- _getFileDisplayName: function FW__getFileDisplayName(file) {
-#ifdef XP_WIN
- if (file instanceof Ci.nsILocalFileWin) {
- try {
- return file.getVersionInfoField("FileDescription");
- } catch (e) {}
- }
-#endif
-#ifdef XP_MACOSX
- if (file instanceof Ci.nsILocalFileMac) {
- try {
- return file.bundleDisplayName;
- } catch (e) {}
- }
-#endif
- return file.leafName;
- },
-
- /**
- * Helper method to set the selected application and system default
- * reader menuitems details from a file object
- * @param aMenuItem
- * The menuitem on which the attributes should be set
- * @param aFile
- * The menuitem's associated file
- */
- _initMenuItemWithFile: function(aMenuItem, aFile) {
- this._contentSandbox.menuitem = aMenuItem;
- this._contentSandbox.label = this._getFileDisplayName(aFile);
- // For security reasons, access to moz-icon:file://... URIs is
- // no longer allowed (indirect file system access from content).
- // We use a dummy application instead to get a generic icon.
- this._contentSandbox.image = "moz-icon://dummy.exe?size=16";
- var codeStr = "menuitem.setAttribute('label', label); " +
- "menuitem.setAttribute('image', image);"
- Cu.evalInSandbox(codeStr, this._contentSandbox);
- },
-
- /**
- * Helper method to get an element in the XBL binding where the handler
- * selection UI lives
- */
- _getUIElement: function FW__getUIElement(id) {
- return this._document.getAnonymousElementByAttribute(
- this._document.getElementById("feedSubscribeLine"), "anonid", id);
- },
-
- /**
- * Displays a prompt from which the user may choose a (client) feed reader.
- * @param aCallback the callback method, passes in true if a feed reader was
- * selected, false otherwise.
- */
- _chooseClientApp: function FW__chooseClientApp(aCallback) {
- try {
- let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
- let fpCallback = function fpCallback_done(aResult) {
- if (aResult == Ci.nsIFilePicker.returnOK) {
- this._selectedApp = fp.file;
- if (this._selectedApp) {
- // XXXben - we need to compare this with the running instance
- // executable just don't know how to do that via script
- // XXXmano TBD: can probably add this to nsIShellService
-#ifdef XP_WIN
-#expand if (fp.file.leafName != "__MOZ_APP_NAME__.exe") {
-#else
-#ifdef XP_MACOSX
-#expand if (fp.file.leafName != "__MOZ_MACBUNDLE_NAME__") {
-#else
-#expand if (fp.file.leafName != "__MOZ_APP_NAME__-bin") {
-#endif
-#endif
- this._initMenuItemWithFile(this._contentSandbox.selectedAppMenuItem,
- this._selectedApp);
-
- // Show and select the selected application menuitem
- let codeStr = "selectedAppMenuItem.hidden = false;" +
- "selectedAppMenuItem.doCommand();"
- Cu.evalInSandbox(codeStr, this._contentSandbox);
- if (aCallback) {
- aCallback(true);
- return;
- }
- }
- }
- }
- if (aCallback) {
- aCallback(false);
- }
- }.bind(this);
-
- fp.init(this._window, this._getString("chooseApplicationDialogTitle"),
- Ci.nsIFilePicker.modeOpen);
- fp.appendFilters(Ci.nsIFilePicker.filterApps);
- fp.open(fpCallback);
- } catch(ex) {
- }
- },
-
- _setAlwaysUseCheckedState: function FW__setAlwaysUseCheckedState(feedType) {
- var checkbox = this._getUIElement("alwaysUse");
- if (checkbox) {
- var alwaysUse = false;
- try {
- var prefs = Cc["@mozilla.org/preferences-service;1"].
- getService(Ci.nsIPrefBranch);
- if (prefs.getCharPref(getPrefActionForType(feedType)) != "ask")
- alwaysUse = true;
- }
- catch(ex) { }
- this._setCheckboxCheckedState(checkbox, alwaysUse);
- }
- },
-
- _setSubscribeUsingLabel: function FW__setSubscribeUsingLabel() {
- var stringLabel = "subscribeFeedUsing";
- switch (this._getFeedType()) {
- case Ci.nsIFeed.TYPE_VIDEO:
- stringLabel = "subscribeVideoPodcastUsing";
- break;
-
- case Ci.nsIFeed.TYPE_AUDIO:
- stringLabel = "subscribeAudioPodcastUsing";
- break;
- }
-
- this._contentSandbox.subscribeUsing =
- this._getUIElement("subscribeUsingDescription");
- this._contentSandbox.label = this._getString(stringLabel);
- var codeStr = "subscribeUsing.setAttribute('value', label);"
- Cu.evalInSandbox(codeStr, this._contentSandbox);
- },
-
- _setAlwaysUseLabel: function FW__setAlwaysUseLabel() {
- var checkbox = this._getUIElement("alwaysUse");
- if (checkbox) {
- if (this._handlersMenuList) {
- var handlerName = this._getSelectedItemFromMenulist(this._handlersMenuList)
- .getAttribute("label");
- var stringLabel = "alwaysUseForFeeds";
- switch (this._getFeedType()) {
- case Ci.nsIFeed.TYPE_VIDEO:
- stringLabel = "alwaysUseForVideoPodcasts";
- break;
-
- case Ci.nsIFeed.TYPE_AUDIO:
- stringLabel = "alwaysUseForAudioPodcasts";
- break;
- }
-
- this._contentSandbox.checkbox = checkbox;
- this._contentSandbox.label = this._getFormattedString(stringLabel, [handlerName]);
-
- var codeStr = "checkbox.setAttribute('label', label);";
- Cu.evalInSandbox(codeStr, this._contentSandbox);
- }
- }
- },
-
- // nsIDomEventListener
- handleEvent: function(event) {
- if (event.target.ownerDocument != this._document) {
- LOG("FeedWriter.handleEvent: Someone passed the feed writer as a listener to the events of another document!");
- return;
- }
-
- if (event.type == "command") {
- switch (event.target.getAttribute("anonid")) {
- case "subscribeButton":
- this.subscribe();
- break;
- case "chooseApplicationMenuItem":
- /* Bug 351263: Make sure to not steal focus if the "Choose
- * Application" item is being selected with the keyboard. We do this
- * by ignoring command events while the dropdown is closed (user
- * arrowing through the combobox), but handling them while the
- * combobox dropdown is open (user pressed enter when an item was
- * selected). If we don't show the filepicker here, it will be shown
- * when clicking "Subscribe Now".
- */
- var popupbox = this._handlersMenuList.firstChild.boxObject;
- if (popupbox.popupState == "hiding") {
- this._chooseClientApp(function(aResult) {
- if (!aResult) {
- // Select the (per-prefs) selected handler if no application
- // was selected
- this._setSelectedHandler(this._getFeedType());
- }
- }.bind(this));
- }
- break;
- default:
- this._setAlwaysUseLabel();
- }
- }
- },
-
- _setSelectedHandler: function FW__setSelectedHandler(feedType) {
- var prefs =
- Cc["@mozilla.org/preferences-service;1"].
- getService(Ci.nsIPrefBranch);
-
- var handler = prefs.getCharPref(getPrefReaderForType(feedType), "bookmarks");
-
- switch (handler) {
- case "web": {
- if (this._handlersMenuList) {
- var url;
- try {
- url = prefs.getComplexValue(getPrefWebForType(feedType), Ci.nsISupportsString).data;
- } catch (ex) {
- LOG("FeedWriter._setSelectedHandler: invalid or no handler in prefs");
- return;
- }
- var handlers =
- this._handlersMenuList.getElementsByAttribute("webhandlerurl", url);
- if (handlers.length == 0) {
- LOG("FeedWriter._setSelectedHandler: selected web handler isn't in the menulist")
- return;
- }
-
- this._safeDoCommand(handlers[0]);
- }
- break;
- }
- case "client": {
- try {
- this._selectedApp =
- prefs.getComplexValue(getPrefAppForType(feedType), Ci.nsILocalFile);
- }
- catch(ex) {
- this._selectedApp = null;
- }
-
- if (this._selectedApp) {
- this._initMenuItemWithFile(this._contentSandbox.selectedAppMenuItem,
- this._selectedApp);
- var codeStr = "selectedAppMenuItem.hidden = false; " +
- "selectedAppMenuItem.doCommand(); ";
-
- // Only show the default reader menuitem if the default reader
- // isn't the selected application
- if (this._defaultSystemReader) {
- var shouldHide =
- this._defaultSystemReader.path == this._selectedApp.path;
- codeStr += "defaultHandlerMenuItem.hidden = " + shouldHide + ";"
- }
- Cu.evalInSandbox(codeStr, this._contentSandbox);
- break;
- }
- }
- case "bookmarks":
- default: {
- var liveBookmarksMenuItem = this._getUIElement("liveBookmarksMenuItem");
- if (liveBookmarksMenuItem)
- this._safeDoCommand(liveBookmarksMenuItem);
- }
- }
- },
-
- _initSubscriptionUI: function FW__initSubscriptionUI() {
- var handlersMenuPopup = this._getUIElement("handlersMenuPopup");
- if (!handlersMenuPopup)
- return;
-
- var feedType = this._getFeedType();
- var codeStr;
-
- // change the background
- var header = this._document.getElementById("feedHeader");
- this._contentSandbox.header = header;
- switch (feedType) {
- case Ci.nsIFeed.TYPE_VIDEO:
- codeStr = "header.className = 'videoPodcastBackground'; ";
- break;
-
- case Ci.nsIFeed.TYPE_AUDIO:
- codeStr = "header.className = 'audioPodcastBackground'; ";
- break;
-
- default:
- codeStr = "header.className = 'feedBackground'; ";
- }
-
- var liveBookmarksMenuItem = this._getUIElement("liveBookmarksMenuItem");
-
- // Last-selected application
- var menuItem = liveBookmarksMenuItem.cloneNode(false);
- menuItem.removeAttribute("selected");
- menuItem.setAttribute("anonid", "selectedAppMenuItem");
- menuItem.className = "menuitem-iconic selectedAppMenuItem";
- menuItem.setAttribute("handlerType", "client");
- try {
- var prefs = Cc["@mozilla.org/preferences-service;1"].
- getService(Ci.nsIPrefBranch);
- this._selectedApp = prefs.getComplexValue(getPrefAppForType(feedType),
- Ci.nsILocalFile);
-
- if (this._selectedApp.exists())
- this._initMenuItemWithFile(menuItem, this._selectedApp);
- else {
- // Hide the menuitem if the last selected application doesn't exist
- menuItem.setAttribute("hidden", true);
- }
- }
- catch(ex) {
- // Hide the menuitem until an application is selected
- menuItem.setAttribute("hidden", true);
- }
- this._contentSandbox.handlersMenuPopup = handlersMenuPopup;
- this._contentSandbox.selectedAppMenuItem = menuItem;
-
- codeStr += "handlersMenuPopup.appendChild(selectedAppMenuItem); ";
-
- // List the default feed reader
- try {
- this._defaultSystemReader = Cc["@mozilla.org/browser/shell-service;1"].
- getService(Ci.nsIShellService).
- defaultFeedReader;
- menuItem = liveBookmarksMenuItem.cloneNode(false);
- menuItem.removeAttribute("selected");
- menuItem.setAttribute("anonid", "defaultHandlerMenuItem");
- menuItem.className = "menuitem-iconic defaultHandlerMenuItem";
- menuItem.setAttribute("handlerType", "client");
-
- this._initMenuItemWithFile(menuItem, this._defaultSystemReader);
-
- // Hide the default reader item if it points to the same application
- // as the last-selected application
- if (this._selectedApp &&
- this._selectedApp.path == this._defaultSystemReader.path)
- menuItem.hidden = true;
- }
- catch(ex) { menuItem = null; /* no default reader */ }
-
- if (menuItem) {
- this._contentSandbox.defaultHandlerMenuItem = menuItem;
- codeStr += "handlersMenuPopup.appendChild(defaultHandlerMenuItem); ";
- }
-
- // "Choose Application..." menuitem
- menuItem = liveBookmarksMenuItem.cloneNode(false);
- menuItem.removeAttribute("selected");
- menuItem.setAttribute("anonid", "chooseApplicationMenuItem");
- menuItem.className = "menuitem-iconic chooseApplicationMenuItem";
- menuItem.setAttribute("label", this._getString("chooseApplicationMenuItem"));
-
- this._contentSandbox.chooseAppMenuItem = menuItem;
- codeStr += "handlersMenuPopup.appendChild(chooseAppMenuItem); ";
-
- // separator
- this._contentSandbox.chooseAppSep =
- menuItem = liveBookmarksMenuItem.nextSibling.cloneNode(false);
- codeStr += "handlersMenuPopup.appendChild(chooseAppSep); ";
-
- Cu.evalInSandbox(codeStr, this._contentSandbox);
-
- // List of web handlers
- var wccr = Cc["@mozilla.org/embeddor.implemented/web-content-handler-registrar;1"].
- getService(Ci.nsIWebContentConverterService);
- var handlers = wccr.getContentHandlers(this._getMimeTypeForFeedType(feedType));
- if (handlers.length != 0) {
- for (var i = 0; i < handlers.length; ++i) {
- if (!handlers[i].uri) {
- LOG("Handler with name " + handlers[i].name + " has no URI!? Skipping...");
- continue;
- }
- menuItem = liveBookmarksMenuItem.cloneNode(false);
- menuItem.removeAttribute("selected");
- menuItem.className = "menuitem-iconic";
- menuItem.setAttribute("label", handlers[i].name);
- menuItem.setAttribute("handlerType", "web");
- menuItem.setAttribute("webhandlerurl", handlers[i].uri);
- this._contentSandbox.menuItem = menuItem;
- codeStr = "handlersMenuPopup.appendChild(menuItem);";
- Cu.evalInSandbox(codeStr, this._contentSandbox);
-
- this._setFaviconForWebReader(handlers[i].uri, menuItem);
- }
- this._contentSandbox.menuItem = null;
- }
-
- this._setSelectedHandler(feedType);
-
- // "Subscribe using..."
- this._setSubscribeUsingLabel();
-
- // "Always use..." checkbox initial state
- this._setAlwaysUseCheckedState(feedType);
- this._setAlwaysUseLabel();
-
- // We update the "Always use.." checkbox label whenever the selected item
- // in the list is changed
- handlersMenuPopup.addEventListener("command", this, false);
-
- // Set up the "Subscribe Now" button
- this._getUIElement("subscribeButton")
- .addEventListener("command", this, false);
-
- // first-run ui
- var showFirstRunUI = prefs.getBoolPref(PREF_SHOW_FIRST_RUN_UI, true);
- if (showFirstRunUI) {
- var textfeedinfo1, textfeedinfo2;
- switch (feedType) {
- case Ci.nsIFeed.TYPE_VIDEO:
- textfeedinfo1 = "feedSubscriptionVideoPodcast1";
- textfeedinfo2 = "feedSubscriptionVideoPodcast2";
- break;
- case Ci.nsIFeed.TYPE_AUDIO:
- textfeedinfo1 = "feedSubscriptionAudioPodcast1";
- textfeedinfo2 = "feedSubscriptionAudioPodcast2";
- break;
- default:
- textfeedinfo1 = "feedSubscriptionFeed1";
- textfeedinfo2 = "feedSubscriptionFeed2";
- }
-
- this._contentSandbox.feedinfo1 =
- this._document.getElementById("feedSubscriptionInfo1");
- this._contentSandbox.feedinfo1Str = this._getString(textfeedinfo1);
- this._contentSandbox.feedinfo2 =
- this._document.getElementById("feedSubscriptionInfo2");
- this._contentSandbox.feedinfo2Str = this._getString(textfeedinfo2);
- this._contentSandbox.header = header;
- codeStr = "feedinfo1.textContent = feedinfo1Str; " +
- "feedinfo2.textContent = feedinfo2Str; " +
- "header.setAttribute('firstrun', 'true');"
- Cu.evalInSandbox(codeStr, this._contentSandbox);
- prefs.setBoolPref(PREF_SHOW_FIRST_RUN_UI, false);
- }
- },
-
- /**
- * Returns the original URI object of the feed and ensures that this
- * component is only ever invoked from the preview document.
- * @param aWindow
- * The window of the document invoking the BrowserFeedWriter
- */
- _getOriginalURI: function FW__getOriginalURI(aWindow) {
- var chan = aWindow.QueryInterface(Ci.nsIInterfaceRequestor).
- getInterface(Ci.nsIWebNavigation).
- QueryInterface(Ci.nsIDocShell).currentDocumentChannel;
-
- var nullPrincipal = Cc["@mozilla.org/nullprincipal;1"].
- createInstance(Ci.nsIPrincipal);
-
- // this channel is not going to be openend, use a nullPrincipal
- // and the most restrctive securityFlag.
- let resolvedURI = NetUtil.newChannel({
- uri: "about:feeds",
- loadingPrincipal: nullPrincipal,
- securityFlags: Ci.nsILoadInfo.SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED,
- contentPolicyType: Ci.nsIContentPolicy.TYPE_OTHER
- }).URI;
-
- if (resolvedURI.equals(chan.URI))
- return chan.originalURI;
-
- return null;
- },
-
- _window: null,
- _document: null,
- _feedURI: null,
- _feedPrincipal: null,
- _handlersMenuList: null,
-
- // BrowserFeedWriter WebIDL methods
- init: function FW_init(aWindow) {
- var window = aWindow;
- this._feedURI = this._getOriginalURI(window);
- if (!this._feedURI)
- return;
-
- this._window = window;
- this._document = window.document;
- this._document.getElementById("feedSubscribeLine").offsetTop;
- this._handlersMenuList = this._getUIElement("handlersMenuList");
-
- var secman = Cc["@mozilla.org/scriptsecuritymanager;1"].
- getService(Ci.nsIScriptSecurityManager);
- this._feedPrincipal = secman.createCodebasePrincipal(this._feedURI, {});
-
- LOG("Subscribe Preview: feed uri = " + this._window.location.href);
-
- // Set up the subscription UI
- this._initSubscriptionUI();
- var prefs = Cc["@mozilla.org/preferences-service;1"].
- getService(Ci.nsIPrefBranch);
- prefs.addObserver(PREF_SELECTED_ACTION, this, false);
- prefs.addObserver(PREF_SELECTED_READER, this, false);
- prefs.addObserver(PREF_SELECTED_WEB, this, false);
- prefs.addObserver(PREF_SELECTED_APP, this, false);
- prefs.addObserver(PREF_VIDEO_SELECTED_ACTION, this, false);
- prefs.addObserver(PREF_VIDEO_SELECTED_READER, this, false);
- prefs.addObserver(PREF_VIDEO_SELECTED_WEB, this, false);
- prefs.addObserver(PREF_VIDEO_SELECTED_APP, this, false);
-
- prefs.addObserver(PREF_AUDIO_SELECTED_ACTION, this, false);
- prefs.addObserver(PREF_AUDIO_SELECTED_READER, this, false);
- prefs.addObserver(PREF_AUDIO_SELECTED_WEB, this, false);
- prefs.addObserver(PREF_AUDIO_SELECTED_APP, this, false);
- },
-
- writeContent: function FW_writeContent() {
- if (!this._window)
- return;
-
- try {
- // Set up the feed content
- var container = this._getContainer();
- if (!container)
- return;
-
- this._setTitleText(container);
- this._setTitleImage(container);
- this._writeFeedContent(container);
- }
- finally {
- this._removeFeedFromCache();
- }
- },
-
- close: function FW_close() {
- this._getUIElement("handlersMenuPopup")
- .removeEventListener("command", this, false);
- this._getUIElement("subscribeButton")
- .removeEventListener("command", this, false);
- this._document = null;
- this._window = null;
- var prefs = Cc["@mozilla.org/preferences-service;1"].
- getService(Ci.nsIPrefBranch);
- prefs.removeObserver(PREF_SELECTED_ACTION, this);
- prefs.removeObserver(PREF_SELECTED_READER, this);
- prefs.removeObserver(PREF_SELECTED_WEB, this);
- prefs.removeObserver(PREF_SELECTED_APP, this);
- prefs.removeObserver(PREF_VIDEO_SELECTED_ACTION, this);
- prefs.removeObserver(PREF_VIDEO_SELECTED_READER, this);
- prefs.removeObserver(PREF_VIDEO_SELECTED_WEB, this);
- prefs.removeObserver(PREF_VIDEO_SELECTED_APP, this);
-
- prefs.removeObserver(PREF_AUDIO_SELECTED_ACTION, this);
- prefs.removeObserver(PREF_AUDIO_SELECTED_READER, this);
- prefs.removeObserver(PREF_AUDIO_SELECTED_WEB, this);
- prefs.removeObserver(PREF_AUDIO_SELECTED_APP, this);
-
- this._removeFeedFromCache();
- this.__faviconService = null;
- this.__bundle = null;
- this._feedURI = null;
- this.__contentSandbox = null;
- },
-
- _removeFeedFromCache: function FW__removeFeedFromCache() {
- if (this._feedURI) {
- var feedService = Cc["@mozilla.org/browser/feeds/result-service;1"].
- getService(Ci.nsIFeedResultService);
- feedService.removeFeedResult(this._feedURI);
- this._feedURI = null;
- }
- },
-
- subscribe: function FW_subscribe() {
- var feedType = this._getFeedType();
-
- // Subscribe to the feed using the selected handler and save prefs
- var prefs = Cc["@mozilla.org/preferences-service;1"].
- getService(Ci.nsIPrefBranch);
- var defaultHandler = "reader";
- var useAsDefault = this._getUIElement("alwaysUse").getAttribute("checked");
-
- var selectedItem = this._getSelectedItemFromMenulist(this._handlersMenuList);
- let subscribeCallback = function() {
- if (selectedItem.hasAttribute("webhandlerurl")) {
- var webURI = selectedItem.getAttribute("webhandlerurl");
- prefs.setCharPref(getPrefReaderForType(feedType), "web");
-
- var supportsString = Cc["@mozilla.org/supports-string;1"].
- createInstance(Ci.nsISupportsString);
- supportsString.data = webURI;
- prefs.setComplexValue(getPrefWebForType(feedType), Ci.nsISupportsString,
- supportsString);
-
- var wccr = Cc["@mozilla.org/embeddor.implemented/web-content-handler-registrar;1"].
- getService(Ci.nsIWebContentConverterService);
- var handler = wccr.getWebContentHandlerByURI(this._getMimeTypeForFeedType(feedType), webURI);
- if (handler) {
- if (useAsDefault) {
- wccr.setAutoHandler(this._getMimeTypeForFeedType(feedType), handler);
- }
-
- this._window.location.href = handler.getHandlerURI(this._window.location.href);
- }
- } else {
- switch (selectedItem.getAttribute("anonid")) {
- case "selectedAppMenuItem":
- prefs.setComplexValue(getPrefAppForType(feedType), Ci.nsILocalFile,
- this._selectedApp);
- prefs.setCharPref(getPrefReaderForType(feedType), "client");
- break;
- case "defaultHandlerMenuItem":
- prefs.setComplexValue(getPrefAppForType(feedType), Ci.nsILocalFile,
- this._defaultSystemReader);
- prefs.setCharPref(getPrefReaderForType(feedType), "client");
- break;
- case "liveBookmarksMenuItem":
- defaultHandler = "bookmarks";
- prefs.setCharPref(getPrefReaderForType(feedType), "bookmarks");
- break;
- }
- var feedService = Cc["@mozilla.org/browser/feeds/result-service;1"].
- getService(Ci.nsIFeedResultService);
-
- // Pull the title and subtitle out of the document
- var feedTitle = this._document.getElementById(TITLE_ID).textContent;
- var feedSubtitle = this._document.getElementById(SUBTITLE_ID).textContent;
- feedService.addToClientReader(this._window.location.href, feedTitle, feedSubtitle, feedType);
- }
-
- // If "Always use..." is checked, we should set PREF_*SELECTED_ACTION
- // to either "reader" (If a web reader or if an application is selected),
- // or to "bookmarks" (if the live bookmarks option is selected).
- // Otherwise, we should set it to "ask"
- if (useAsDefault) {
- prefs.setCharPref(getPrefActionForType(feedType), defaultHandler);
- } else {
- prefs.setCharPref(getPrefActionForType(feedType), "ask");
- }
- }.bind(this);
-
- // Show the file picker before subscribing if the
- // choose application menuitem was chosen using the keyboard
- if (selectedItem.getAttribute("anonid") == "chooseApplicationMenuItem") {
- this._chooseClientApp(function(aResult) {
- if (aResult) {
- selectedItem =
- this._getSelectedItemFromMenulist(this._handlersMenuList);
- subscribeCallback();
- }
- }.bind(this));
- } else {
- subscribeCallback();
- }
- },
-
- // nsIObserver
- observe: function FW_observe(subject, topic, data) {
- if (!this._window) {
- // this._window is null unless this.init was called with a trusted
- // window object.
- return;
- }
-
- var feedType = this._getFeedType();
-
- if (topic == "nsPref:changed") {
- switch (data) {
- case PREF_SELECTED_READER:
- case PREF_SELECTED_WEB:
- case PREF_SELECTED_APP:
- case PREF_VIDEO_SELECTED_READER:
- case PREF_VIDEO_SELECTED_WEB:
- case PREF_VIDEO_SELECTED_APP:
- case PREF_AUDIO_SELECTED_READER:
- case PREF_AUDIO_SELECTED_WEB:
- case PREF_AUDIO_SELECTED_APP:
- this._setSelectedHandler(feedType);
- break;
- case PREF_SELECTED_ACTION:
- case PREF_VIDEO_SELECTED_ACTION:
- case PREF_AUDIO_SELECTED_ACTION:
- this._setAlwaysUseCheckedState(feedType);
- }
- }
- },
-
- /**
- * Sets the icon for the given web-reader item in the readers menu.
- * The icon is fetched and stored through the favicon service.
- *
- * @param aReaderUrl
- * the reader url.
- * @param aMenuItem
- * the reader item in the readers menulist.
- *
- * @note For privacy reasons we cannot set the image attribute directly
- * to the icon url. See Bug 358878 for details.
- */
- _setFaviconForWebReader:
- function FW__setFaviconForWebReader(aReaderUrl, aMenuItem) {
- var readerURI = makeURI(aReaderUrl);
- if (!/^https?$/.test(readerURI.scheme)) {
- // Don't try to get a favicon for non http(s) URIs.
- return;
- }
- var faviconURI = makeURI(readerURI.prePath + "/favicon.ico");
- var self = this;
- var usePrivateBrowsing = this._window.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsIDocShell)
- .QueryInterface(Ci.nsILoadContext)
- .usePrivateBrowsing;
- var nullPrincipal = Cc["@mozilla.org/nullprincipal;1"]
- .createInstance(Ci.nsIPrincipal);
- this._faviconService.setAndFetchFaviconForPage(readerURI, faviconURI, false,
- usePrivateBrowsing ? this._faviconService.FAVICON_LOAD_PRIVATE
- : this._faviconService.FAVICON_LOAD_NON_PRIVATE,
- function (aURI, aDataLen, aData, aMimeType) {
- if (aDataLen > 0) {
- var dataURL = "data:" + aMimeType + ";base64," +
- btoa(String.fromCharCode.apply(null, aData));
- self._contentSandbox.menuItem = aMenuItem;
- self._contentSandbox.dataURL = dataURL;
- var codeStr = "menuItem.setAttribute('image', dataURL);";
- Cu.evalInSandbox(codeStr, self._contentSandbox);
- self._contentSandbox.menuItem = null;
- self._contentSandbox.dataURL = null;
- }
- }, nullPrincipal);
- },
-
- classID: FEEDWRITER_CID,
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMEventListener, Ci.nsIObserver,
- Ci.nsINavHistoryObserver,
- Ci.nsIDOMGlobalPropertyInitializer])
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([FeedWriter]);
diff --git a/components/feeds/WebContentConverter.js b/components/feeds/WebContentConverter.js
deleted file mode 100644
index 42e2ede..0000000
--- a/components/feeds/WebContentConverter.js
+++ /dev/null
@@ -1,927 +0,0 @@
-/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
-Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
-
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-const Cr = Components.results;
-
-function LOG(str) {
- dump("*** " + str + "\n");
-}
-
-const WCCR_CONTRACTID = "@mozilla.org/embeddor.implemented/web-content-handler-registrar;1";
-const WCCR_CLASSID = Components.ID("{792a7e82-06a0-437c-af63-b2d12e808acc}");
-
-const WCC_CLASSID = Components.ID("{db7ebf28-cc40-415f-8a51-1b111851df1e}");
-const WCC_CLASSNAME = "Web Service Handler";
-
-const TYPE_MAYBE_FEED = "application/vnd.mozilla.maybe.feed";
-const TYPE_ANY = "*/*";
-const TYPE_BLACKLIST = [
- "application/x-www-form-urlencoded",
- "application/xhtml+xml",
- "application/xml",
- "application/mathml+xml",
- "application/xslt+xml",
- "application/x-xpinstall",
- "image/gif",
- "image/jpg",
- "image/jpeg",
- "image/png",
- "image/x-png",
- "image/webp",
-#ifdef MOZ_JXR
- "image/jxr",
- "image/vnd.ms-photo",
-#endif
- "image/svg+xml",
- "image/bmp",
- "image/x-ms-bmp",
- "image/icon",
- "image/x-icon",
- "image/vnd.microsoft.icon",
- "multipart/x-mixed-replace",
- "multipart/form-data",
- "text/cache-manifest",
- "text/css",
- "text/xsl",
- "text/html",
- "text/ping",
- "text/plain",
- "text/xml",
- "text/javascript", // To prevent malicious intent blocking scripting.
- "text/ecmascript"];
-
-const PREF_CONTENTHANDLERS_AUTO = "browser.contentHandlers.auto.";
-const PREF_CONTENTHANDLERS_BRANCH = "browser.contentHandlers.types.";
-const PREF_SELECTED_WEB = "browser.feeds.handlers.webservice";
-const PREF_SELECTED_ACTION = "browser.feeds.handler";
-const PREF_SELECTED_READER = "browser.feeds.handler.default";
-const PREF_HANDLER_EXTERNAL_PREFIX = "network.protocol-handler.external";
-const PREF_ALLOW_DIFFERENT_HOST = "gecko.handlerService.allowRegisterFromDifferentHost";
-
-const STRING_BUNDLE_URI = "chrome://browser/locale/feeds/subscribe.properties";
-
-const NS_ERROR_MODULE_DOM = 2152923136;
-const NS_ERROR_DOM_SYNTAX_ERR = NS_ERROR_MODULE_DOM + 12;
-
-function WebContentConverter() {
-}
-WebContentConverter.prototype = {
- convert: function WCC_convert() { },
- asyncConvertData: function WCC_asyncConvertData() { },
- onDataAvailable: function WCC_onDataAvailable() { },
- onStopRequest: function WCC_onStopRequest() { },
-
- onStartRequest: function WCC_onStartRequest(request, context) {
- var wccr =
- Cc[WCCR_CONTRACTID].
- getService(Ci.nsIWebContentConverterService);
- wccr.loadPreferredHandler(request);
- },
-
- QueryInterface: function WCC_QueryInterface(iid) {
- if (iid.equals(Ci.nsIStreamConverter) ||
- iid.equals(Ci.nsIStreamListener) ||
- iid.equals(Ci.nsISupports))
- return this;
- throw Cr.NS_ERROR_NO_INTERFACE;
- }
-};
-
-var WebContentConverterFactory = {
- createInstance: function WCCF_createInstance(outer, iid) {
- if (outer != null)
- throw Cr.NS_ERROR_NO_AGGREGATION;
- return new WebContentConverter().QueryInterface(iid);
- },
-
- QueryInterface: function WCC_QueryInterface(iid) {
- if (iid.equals(Ci.nsIFactory) ||
- iid.equals(Ci.nsISupports))
- return this;
- throw Cr.NS_ERROR_NO_INTERFACE;
- }
-};
-
-function ServiceInfo(contentType, uri, name) {
- this._contentType = contentType;
- this._uri = uri;
- this._name = name;
-}
-ServiceInfo.prototype = {
- /**
- * See nsIHandlerApp
- */
- get name() {
- return this._name;
- },
-
- /**
- * See nsIHandlerApp
- */
- equals: function SI_equals(aHandlerApp) {
- if (!aHandlerApp)
- throw Cr.NS_ERROR_NULL_POINTER;
-
- if (aHandlerApp instanceof Ci.nsIWebContentHandlerInfo &&
- aHandlerApp.contentType == this.contentType &&
- aHandlerApp.uri == this.uri)
- return true;
-
- return false;
- },
-
- /**
- * See nsIWebContentHandlerInfo
- */
- get contentType() {
- return this._contentType;
- },
-
- /**
- * See nsIWebContentHandlerInfo
- */
- get uri() {
- return this._uri;
- },
-
- /**
- * See nsIWebContentHandlerInfo
- */
- getHandlerURI: function SI_getHandlerURI(uri) {
- return this._uri.replace(/%s/gi, encodeURIComponent(uri));
- },
-
- QueryInterface: function SI_QueryInterface(iid) {
- if (iid.equals(Ci.nsIWebContentHandlerInfo) ||
- iid.equals(Ci.nsISupports))
- return this;
- throw Cr.NS_ERROR_NO_INTERFACE;
- }
-};
-
-function WebContentConverterRegistrar() {
- this._contentTypes = { };
- this._autoHandleContentTypes = { };
-}
-
-WebContentConverterRegistrar.prototype = {
- get stringBundle() {
- var sb = Cc["@mozilla.org/intl/stringbundle;1"].
- getService(Ci.nsIStringBundleService).
- createBundle(STRING_BUNDLE_URI);
- delete WebContentConverterRegistrar.prototype.stringBundle;
- return WebContentConverterRegistrar.prototype.stringBundle = sb;
- },
-
- _getFormattedString: function WCCR__getFormattedString(key, params) {
- return this.stringBundle.formatStringFromName(key, params, params.length);
- },
-
- _getString: function WCCR_getString(key) {
- return this.stringBundle.GetStringFromName(key);
- },
-
- /**
- * See nsIWebContentConverterService
- */
- getAutoHandler:
- function WCCR_getAutoHandler(contentType) {
- contentType = this._resolveContentType(contentType);
- if (contentType in this._autoHandleContentTypes)
- return this._autoHandleContentTypes[contentType];
- return null;
- },
-
- /**
- * See nsIWebContentConverterService
- */
- setAutoHandler:
- function WCCR_setAutoHandler(contentType, handler) {
- if (handler && !this._typeIsRegistered(contentType, handler.uri))
- throw Cr.NS_ERROR_NOT_AVAILABLE;
-
- contentType = this._resolveContentType(contentType);
- this._setAutoHandler(contentType, handler);
-
- var ps =
- Cc["@mozilla.org/preferences-service;1"].
- getService(Ci.nsIPrefService);
- var autoBranch = ps.getBranch(PREF_CONTENTHANDLERS_AUTO);
- if (handler)
- autoBranch.setCharPref(contentType, handler.uri);
- else if (autoBranch.prefHasUserValue(contentType))
- autoBranch.clearUserPref(contentType);
-
- ps.savePrefFile(null);
- },
-
- /**
- * Update the internal data structure (not persistent)
- */
- _setAutoHandler:
- function WCCR__setAutoHandler(contentType, handler) {
- if (handler)
- this._autoHandleContentTypes[contentType] = handler;
- else if (contentType in this._autoHandleContentTypes)
- delete this._autoHandleContentTypes[contentType];
- },
-
- /**
- * See nsIWebContentConverterService
- */
- getWebContentHandlerByURI:
- function WCCR_getWebContentHandlerByURI(contentType, uri) {
- var handlers = this.getContentHandlers(contentType, { });
- for (var i = 0; i < handlers.length; ++i) {
- if (handlers[i].uri == uri)
- return handlers[i];
- }
- return null;
- },
-
- /**
- * See nsIWebContentConverterService
- */
- loadPreferredHandler:
- function WCCR_loadPreferredHandler(request) {
- var channel = request.QueryInterface(Ci.nsIChannel);
- var contentType = this._resolveContentType(channel.contentType);
- var handler = this.getAutoHandler(contentType);
- if (handler) {
- request.cancel(Cr.NS_ERROR_FAILURE);
-
- var webNavigation =
- channel.notificationCallbacks.getInterface(Ci.nsIWebNavigation);
- webNavigation.loadURI(handler.getHandlerURI(channel.URI.spec),
- Ci.nsIWebNavigation.LOAD_FLAGS_NONE,
- null, null, null);
- }
- },
-
- /**
- * See nsIWebContentConverterService
- */
- removeProtocolHandler:
- function WCCR_removeProtocolHandler(aProtocol, aURITemplate) {
- var eps = Cc["@mozilla.org/uriloader/external-protocol-service;1"].
- getService(Ci.nsIExternalProtocolService);
- var handlerInfo = eps.getProtocolHandlerInfo(aProtocol);
- var handlers = handlerInfo.possibleApplicationHandlers;
- for (let i = 0; i < handlers.length; i++) {
- try { // We only want to test web handlers
- let handler = handlers.queryElementAt(i, Ci.nsIWebHandlerApp);
- if (handler.uriTemplate == aURITemplate) {
- handlers.removeElementAt(i);
- var hs = Cc["@mozilla.org/uriloader/handler-service;1"].
- getService(Ci.nsIHandlerService);
- hs.store(handlerInfo);
- return;
- }
- } catch (e) { /* it wasn't a web handler */ }
- }
- },
-
- /**
- * See nsIWebContentConverterService
- */
- removeContentHandler:
- function WCCR_removeContentHandler(contentType, uri) {
- function notURI(serviceInfo) {
- return serviceInfo.uri != uri;
- }
-
- if (contentType in this._contentTypes) {
- this._contentTypes[contentType] =
- this._contentTypes[contentType].filter(notURI);
- }
- },
-
- /**
- *
- */
- _mappings: {
- "application/rss+xml": TYPE_MAYBE_FEED,
- "application/atom+xml": TYPE_MAYBE_FEED,
- },
-
- /**
- * These are types for which there is a separate content converter aside
- * from our built in generic one. We should not automatically register
- * a factory for creating a converter for these types.
- */
- _blockedTypes: {
- "application/vnd.mozilla.maybe.feed": true,
- },
-
- /**
- * Determines the "internal" content type based on the _mappings.
- * @param contentType
- * @returns The resolved contentType value.
- */
- _resolveContentType:
- function WCCR__resolveContentType(contentType) {
- if (contentType in this._mappings)
- return this._mappings[contentType];
- return contentType;
- },
-
- _makeURI: function(aURL, aOriginCharset, aBaseURI) {
- var ioService = Components.classes["@mozilla.org/network/io-service;1"]
- .getService(Components.interfaces.nsIIOService);
- return ioService.newURI(aURL, aOriginCharset, aBaseURI);
- },
-
- _checkAndGetURI:
- function WCCR_checkAndGetURI(aURIString, aContentWindow)
- {
- try {
- let baseURI = aContentWindow.document.baseURIObject;
- var uri = this._makeURI(aURIString, null, baseURI);
- } catch (ex) {
- // not supposed to throw according to spec
- return;
- }
-
- // For security reasons we reject non-http(s) urls (see bug 354316),
- // we may need to revise this once we support more content types
- // XXX this should be a "security exception" according to spec, but that
- // isn't defined yet.
- if (uri.scheme != "http" && uri.scheme != "https")
- throw("Permission denied to add " + uri.spec + " as a content or protocol handler");
-
- // We also reject handlers registered from a different host (see bug 402287)
- // The pref allows us to test the feature
- var pb = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
- if (!pb.getBoolPref(PREF_ALLOW_DIFFERENT_HOST) &&
- (!["http:", "https:"].includes(aContentWindow.location.protocol) ||
- aContentWindow.location.hostname != uri.host)) {
- throw("Permission denied to add " + uri.spec + " as a content or protocol handler");
- }
-
- // If the uri doesn't contain '%s', it won't be a good handler
- if (uri.spec.indexOf("%s") < 0)
- throw NS_ERROR_DOM_SYNTAX_ERR;
-
- return uri;
- },
-
- /**
- * Determines if a web handler is already registered.
- *
- * @param aProtocol
- * The scheme of the web handler we are checking for.
- * @param aURITemplate
- * The URI template that the handler uses to handle the protocol.
- * @return true if it is already registered, false otherwise.
- */
- _protocolHandlerRegistered:
- function WCCR_protocolHandlerRegistered(aProtocol, aURITemplate) {
- var eps = Cc["@mozilla.org/uriloader/external-protocol-service;1"].
- getService(Ci.nsIExternalProtocolService);
- var handlerInfo = eps.getProtocolHandlerInfo(aProtocol);
- var handlers = handlerInfo.possibleApplicationHandlers;
- for (let i = 0; i < handlers.length; i++) {
- try { // We only want to test web handlers
- let handler = handlers.queryElementAt(i, Ci.nsIWebHandlerApp);
- if (handler.uriTemplate == aURITemplate)
- return true;
- } catch (e) { /* it wasn't a web handler */ }
- }
- return false;
- },
-
- /**
- * See nsIWebContentHandlerRegistrar
- */
- registerProtocolHandler:
- function WCCR_registerProtocolHandler(aProtocol, aURIString, aTitle, aContentWindow) {
- LOG("registerProtocolHandler(" + aProtocol + "," + aURIString + "," + aTitle + ")");
-
- var uri = this._checkAndGetURI(aURIString, aContentWindow);
-
- // If the protocol handler is already registered, just return early.
- if (this._protocolHandlerRegistered(aProtocol, uri.spec)) {
- return;
- }
-
- var browserWindow = this._getBrowserWindowForContentWindow(aContentWindow);
- if (PrivateBrowsingUtils.isWindowPrivate(browserWindow)) {
- // Inside the private browsing mode, we don't want to alert the user to save
- // a protocol handler. We log it to the error console so that web developers
- // would have some way to tell what's going wrong.
- Cc["@mozilla.org/consoleservice;1"].
- getService(Ci.nsIConsoleService).
- logStringMessage("Web page denied access to register a protocol handler inside private browsing mode");
- return;
- }
-
- // First, check to make sure this isn't already handled internally (we don't
- // want to let them take over, say "chrome").
- var ios = Cc["@mozilla.org/network/io-service;1"].
- getService(Ci.nsIIOService);
- var handler = ios.getProtocolHandler(aProtocol);
- if (!(handler instanceof Ci.nsIExternalProtocolHandler)) {
- // This is handled internally, so we don't want them to register
- // XXX this should be a "security exception" according to spec, but that
- // isn't defined yet.
- throw("Permission denied to add " + aURIString + "as a protocol handler");
- }
-
- // check if it is in the black list
- var pb = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
- var allowed = pb.getBoolPref(PREF_HANDLER_EXTERNAL_PREFIX + "." + aProtocol,
- pb.getBoolPref(PREF_HANDLER_EXTERNAL_PREFIX + "-default"));
- if (!allowed) {
- // XXX this should be a "security exception" according to spec
- throw("Not allowed to register a protocol handler for " + aProtocol);
- }
-
- // Now Ask the user and provide the proper callback
- var message = this._getFormattedString("addProtocolHandler",
- [aTitle, uri.host, aProtocol]);
-
- var notificationIcon = uri.prePath + "/favicon.ico";
- var notificationValue = "Protocol Registration: " + aProtocol;
- var addButton = {
- label: this._getString("addProtocolHandlerAddButton"),
- accessKey: this._getString("addHandlerAddButtonAccesskey"),
- protocolInfo: { protocol: aProtocol, uri: uri.spec, name: aTitle },
-
- callback:
- function WCCR_addProtocolHandlerButtonCallback(aNotification, aButtonInfo) {
- var protocol = aButtonInfo.protocolInfo.protocol;
- var uri = aButtonInfo.protocolInfo.uri;
- var name = aButtonInfo.protocolInfo.name;
-
- var handler = Cc["@mozilla.org/uriloader/web-handler-app;1"].
- createInstance(Ci.nsIWebHandlerApp);
- handler.name = name;
- handler.uriTemplate = uri;
-
- var eps = Cc["@mozilla.org/uriloader/external-protocol-service;1"].
- getService(Ci.nsIExternalProtocolService);
- var handlerInfo = eps.getProtocolHandlerInfo(protocol);
- handlerInfo.possibleApplicationHandlers.appendElement(handler, false);
-
- // Since the user has agreed to add a new handler, chances are good
- // that the next time they see a handler of this type, they're going
- // to want to use it. Reset the handlerInfo to ask before the next
- // use.
- handlerInfo.alwaysAskBeforeHandling = true;
-
- var hs = Cc["@mozilla.org/uriloader/handler-service;1"].
- getService(Ci.nsIHandlerService);
- hs.store(handlerInfo);
- }
- };
- var browserElement = this._getBrowserForContentWindow(browserWindow, aContentWindow);
- var notificationBox = browserWindow.gBrowser.getNotificationBox(browserElement);
- notificationBox.appendNotification(message,
- notificationValue,
- notificationIcon,
- notificationBox.PRIORITY_INFO_LOW,
- [addButton]);
- },
-
- /**
- * See nsIWebContentHandlerRegistrar
- * If a DOM window is provided, then the request came from content, so we
- * prompt the user to confirm the registration.
- */
- registerContentHandler:
- function WCCR_registerContentHandler(aContentType, aURIString, aTitle, aContentWindow) {
- LOG("registerContentHandler(" + aContentType + "," + aURIString + "," + aTitle + ")");
-
- // Check against the type blacklist.
- // XXX this should be a "security exception" according to spec, but that
- // isn't defined yet.
- var contentType = this._resolveContentType(aContentType);
- for (let blacklistType of TYPE_BLACKLIST) {
- if (contentType == blacklistType) {
- console.error("Unable to register content handler for prohibited MIME type %s.", contentType);
- return;
- }
- }
-
- if (aContentWindow) {
- var uri = this._checkAndGetURI(aURIString, aContentWindow);
-
- var browserWindow = this._getBrowserWindowForContentWindow(aContentWindow);
- var browserElement = this._getBrowserForContentWindow(browserWindow, aContentWindow);
- var notificationBox = browserWindow.gBrowser.getNotificationBox(browserElement);
- this._appendFeedReaderNotification(uri, aTitle, notificationBox);
- }
- else
- this._registerContentHandler(contentType, aURIString, aTitle);
- },
-
- /**
- * Returns the browser chrome window in which the content window is in
- */
- _getBrowserWindowForContentWindow:
- function WCCR__getBrowserWindowForContentWindow(aContentWindow) {
- return aContentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsIDocShellTreeItem)
- .rootTreeItem
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIDOMWindow)
- .wrappedJSObject;
- },
-
- /**
- * Returns the <xul:browser> element associated with the given content
- * window.
- *
- * @param aBrowserWindow
- * The browser window in which the content window is in.
- * @param aContentWindow
- * The content window. It's possible to pass a child content window
- * (i.e. the content window of a frame/iframe).
- */
- _getBrowserForContentWindow:
- function WCCR__getBrowserForContentWindow(aBrowserWindow, aContentWindow) {
- // This depends on pseudo APIs of browser.js and tabbrowser.xml
- aContentWindow = aContentWindow.top;
- var browsers = aBrowserWindow.gBrowser.browsers;
- for (var i = 0; i < browsers.length; ++i) {
- if (browsers[i].contentWindow == aContentWindow)
- return browsers[i];
- }
- },
-
- /**
- * Appends a notifcation for the given feed reader details.
- *
- * The notification could be either a pseudo-dialog which lets
- * the user to add the feed reader:
- * [ [icon] Add %feed-reader-name% (%feed-reader-host%) as a Feed Reader? (Add) [x] ]
- *
- * or a simple message for the case where the feed reader is already registered:
- * [ [icon] %feed-reader-name% is already registered as a Feed Reader [x] ]
- *
- * A new notification isn't appended if the given notificationbox has a
- * notification for the same feed reader.
- *
- * @param aURI
- * The url of the feed reader as a nsIURI object
- * @param aName
- * The feed reader name as it was passed to registerContentHandler
- * @param aNotificationBox
- * The notification box to which a notification might be appended
- * @return true if a notification has been appended, false otherwise.
- */
- _appendFeedReaderNotification:
- function WCCR__appendFeedReaderNotification(aURI, aName, aNotificationBox) {
- var uriSpec = aURI.spec;
- var notificationValue = "feed reader notification: " + uriSpec;
- var notificationIcon = aURI.prePath + "/favicon.ico";
-
- // Don't append a new notification if the notificationbox
- // has a notification for the given feed reader already
- if (aNotificationBox.getNotificationWithValue(notificationValue))
- return false;
-
- var buttons, message;
- if (this.getWebContentHandlerByURI(TYPE_MAYBE_FEED, uriSpec))
- message = this._getFormattedString("handlerRegistered", [aName]);
- else {
- message = this._getFormattedString("addHandler", [aName, aURI.host]);
- var self = this;
- var addButton = {
- _outer: self,
- label: self._getString("addHandlerAddButton"),
- accessKey: self._getString("addHandlerAddButtonAccesskey"),
- feedReaderInfo: { uri: uriSpec, name: aName },
-
- /* static */
- callback:
- function WCCR__addFeedReaderButtonCallback(aNotification, aButtonInfo) {
- var uri = aButtonInfo.feedReaderInfo.uri;
- var name = aButtonInfo.feedReaderInfo.name;
- var outer = aButtonInfo._outer;
-
- // The reader could have been added from another window mean while
- if (!outer.getWebContentHandlerByURI(TYPE_MAYBE_FEED, uri))
- outer._registerContentHandler(TYPE_MAYBE_FEED, uri, name);
-
- // avoid reference cycles
- aButtonInfo._outer = null;
-
- return false;
- }
- };
- buttons = [addButton];
- }
-
- aNotificationBox.appendNotification(message,
- notificationValue,
- notificationIcon,
- aNotificationBox.PRIORITY_INFO_LOW,
- buttons);
- return true;
- },
-
- /**
- * Save Web Content Handler metadata to persistent preferences.
- * @param contentType
- * The content Type being handled
- * @param uri
- * The uri of the web service
- * @param title
- * The human readable name of the web service
- *
- * This data is stored under:
- *
- * browser.contentHandlers.type0 = content/type
- * browser.contentHandlers.uri0 = http://www.foo.com/q=%s
- * browser.contentHandlers.title0 = Foo 2.0alphr
- */
- _saveContentHandlerToPrefs:
- function WCCR__saveContentHandlerToPrefs(contentType, uri, title) {
- var ps =
- Cc["@mozilla.org/preferences-service;1"].
- getService(Ci.nsIPrefService);
- var i = 0;
- var typeBranch = null;
- while (true) {
- typeBranch =
- ps.getBranch(PREF_CONTENTHANDLERS_BRANCH + i + ".");
- try {
- typeBranch.getCharPref("type");
- ++i;
- }
- catch (e) {
- // No more handlers
- break;
- }
- }
- if (typeBranch) {
- typeBranch.setCharPref("type", contentType);
- var pls =
- Cc["@mozilla.org/pref-localizedstring;1"].
- createInstance(Ci.nsIPrefLocalizedString);
- pls.data = uri;
- typeBranch.setComplexValue("uri", Ci.nsIPrefLocalizedString, pls);
- pls.data = title;
- typeBranch.setComplexValue("title", Ci.nsIPrefLocalizedString, pls);
-
- ps.savePrefFile(null);
- }
- },
-
- /**
- * Determines if there is a type with a particular uri registered for the
- * specified content type already.
- * @param contentType
- * The content type that the uri handles
- * @param uri
- * The uri of the
- */
- _typeIsRegistered: function WCCR__typeIsRegistered(contentType, uri) {
- if (!(contentType in this._contentTypes))
- return false;
-
- var services = this._contentTypes[contentType];
- for (var i = 0; i < services.length; ++i) {
- // This uri has already been registered
- if (services[i].uri == uri)
- return true;
- }
- return false;
- },
-
- /**
- * Gets a stream converter contract id for the specified content type.
- * @param contentType
- * The source content type for the conversion.
- * @returns A contract id to construct a converter to convert between the
- * contentType and *\/*.
- */
- _getConverterContractID: function WCCR__getConverterContractID(contentType) {
- const template = "@mozilla.org/streamconv;1?from=%s&to=*/*";
- return template.replace(/%s/, contentType);
- },
-
- /**
- * Register a web service handler for a content type.
- *
- * @param contentType
- * the content type being handled
- * @param uri
- * the URI of the web service
- * @param title
- * the human readable name of the web service
- */
- _registerContentHandler:
- function WCCR__registerContentHandler(contentType, uri, title) {
- this._updateContentTypeHandlerMap(contentType, uri, title);
- this._saveContentHandlerToPrefs(contentType, uri, title);
-
- if (contentType == TYPE_MAYBE_FEED) {
- // Make the new handler the last-selected reader in the preview page
- // and make sure the preview page is shown the next time a feed is visited
- var pb = Cc["@mozilla.org/preferences-service;1"].
- getService(Ci.nsIPrefService).getBranch(null);
- pb.setCharPref(PREF_SELECTED_READER, "web");
-
- var supportsString =
- Cc["@mozilla.org/supports-string;1"].
- createInstance(Ci.nsISupportsString);
- supportsString.data = uri;
- pb.setComplexValue(PREF_SELECTED_WEB, Ci.nsISupportsString,
- supportsString);
- pb.setCharPref(PREF_SELECTED_ACTION, "ask");
- this._setAutoHandler(TYPE_MAYBE_FEED, null);
- }
- },
-
- /**
- * Update the content type -> handler map. This mapping is not persisted, use
- * registerContentHandler or _saveContentHandlerToPrefs for that purpose.
- * @param contentType
- * The content Type being handled
- * @param uri
- * The uri of the web service
- * @param title
- * The human readable name of the web service
- */
- _updateContentTypeHandlerMap:
- function WCCR__updateContentTypeHandlerMap(contentType, uri, title) {
- if (!(contentType in this._contentTypes))
- this._contentTypes[contentType] = [];
-
- // Avoid adding duplicates
- if (this._typeIsRegistered(contentType, uri))
- return;
-
- this._contentTypes[contentType].push(new ServiceInfo(contentType, uri, title));
-
- if (!(contentType in this._blockedTypes)) {
- var converterContractID = this._getConverterContractID(contentType);
- var cr = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
- cr.registerFactory(WCC_CLASSID, WCC_CLASSNAME, converterContractID,
- WebContentConverterFactory);
- }
- },
-
- /**
- * See nsIWebContentConverterService
- */
- getContentHandlers:
- function WCCR_getContentHandlers(contentType, countRef) {
- countRef.value = 0;
- if (!(contentType in this._contentTypes))
- return [];
-
- var handlers = this._contentTypes[contentType];
- countRef.value = handlers.length;
- return handlers;
- },
-
- /**
- * See nsIWebContentConverterService
- */
- resetHandlersForType:
- function WCCR_resetHandlersForType(contentType) {
- // currently unused within the tree, so only useful for extensions; previous
- // impl. was buggy (and even infinite-looped!), so I argue that this is a
- // definite improvement
- throw Cr.NS_ERROR_NOT_IMPLEMENTED;
- },
-
- /**
- * Registers a handler from the settings on a preferences branch.
- *
- * @param branch
- * an nsIPrefBranch containing "type", "uri", and "title" preferences
- * corresponding to the content handler to be registered
- */
- _registerContentHandlerWithBranch: function(branch) {
- /**
- * Since we support up to six predefined readers, we need to handle gaps
- * better, since the first branch with user-added values will be .6
- *
- * How we deal with that is to check to see if there's no prefs in the
- * branch and stop cycling once that's true. This doesn't fix the case
- * where a user manually removes a reader, but that's not supported yet!
- */
- var vals = branch.getChildList("");
- if (vals.length == 0)
- return;
-
- try {
- var type = branch.getCharPref("type");
- var uri = branch.getComplexValue("uri", Ci.nsIPrefLocalizedString).data;
- var title = branch.getComplexValue("title",
- Ci.nsIPrefLocalizedString).data;
- this._updateContentTypeHandlerMap(type, uri, title);
- }
- catch(ex) {
- // do nothing, the next branch might have values
- }
- },
-
- /**
- * Load the auto handler, content handler and protocol tables from
- * preferences.
- */
- _init: function WCCR__init() {
- var ps =
- Cc["@mozilla.org/preferences-service;1"].
- getService(Ci.nsIPrefService);
-
- var kids = ps.getBranch(PREF_CONTENTHANDLERS_BRANCH)
- .getChildList("");
-
- // first get the numbers of the providers by getting all ###.uri prefs
- var nums = [];
- for (var i = 0; i < kids.length; i++) {
- var match = /^(\d+)\.uri$/.exec(kids[i]);
- if (!match)
- continue;
- else
- nums.push(match[1]);
- }
-
- // sort them, to get them back in order
- nums.sort(function(a, b) {return a - b;});
-
- // now register them
- for (var i = 0; i < nums.length; i++) {
- var branch = ps.getBranch(PREF_CONTENTHANDLERS_BRANCH + nums[i] + ".");
- this._registerContentHandlerWithBranch(branch);
- }
-
- // We need to do this _after_ registering all of the available handlers,
- // so that getWebContentHandlerByURI can return successfully.
- try {
- var autoBranch = ps.getBranch(PREF_CONTENTHANDLERS_AUTO);
- var childPrefs = autoBranch.getChildList("");
- for (var i = 0; i < childPrefs.length; ++i) {
- var type = childPrefs[i];
- var uri = autoBranch.getCharPref(type);
- if (uri) {
- var handler = this.getWebContentHandlerByURI(type, uri);
- this._setAutoHandler(type, handler);
- }
- }
- }
- catch (e) {
- // No auto branch yet, that's fine
- //LOG("WCCR.init: There is no auto branch, benign");
- }
- },
-
- /**
- * See nsIObserver
- */
- observe: function WCCR_observe(subject, topic, data) {
- var os =
- Cc["@mozilla.org/observer-service;1"].
- getService(Ci.nsIObserverService);
- switch (topic) {
- case "app-startup":
- os.addObserver(this, "browser-ui-startup-complete", false);
- break;
- case "browser-ui-startup-complete":
- os.removeObserver(this, "browser-ui-startup-complete");
- this._init();
- break;
- }
- },
-
- /**
- * See nsIFactory
- */
- createInstance: function WCCR_createInstance(outer, iid) {
- if (outer != null)
- throw Cr.NS_ERROR_NO_AGGREGATION;
- return this.QueryInterface(iid);
- },
-
- classID: WCCR_CLASSID,
-
- /**
- * See nsISupports
- */
- QueryInterface: XPCOMUtils.generateQI(
- [Ci.nsIWebContentConverterService,
- Ci.nsIWebContentHandlerRegistrar,
- Ci.nsIObserver,
- Ci.nsIFactory]),
-
- _xpcom_categories: [{
- category: "app-startup",
- service: true
- }]
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([WebContentConverterRegistrar]);
diff --git a/components/feeds/content/subscribe.css b/components/feeds/content/subscribe.css
deleted file mode 100644
index bf2524d..0000000
--- a/components/feeds/content/subscribe.css
+++ /dev/null
@@ -1,7 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#feedSubscribeLine {
- -moz-binding: url(subscribe.xml#feedreaderUI);
-}
diff --git a/components/feeds/content/subscribe.js b/components/feeds/content/subscribe.js
deleted file mode 100644
index ab2eac4..0000000
--- a/components/feeds/content/subscribe.js
+++ /dev/null
@@ -1,23 +0,0 @@
-/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-var SubscribeHandler = {
- /**
- * The nsIFeedWriter object that produces the UI
- */
- _feedWriter: null,
-
- init: function SH_init() {
- this._feedWriter = new BrowserFeedWriter();
- },
-
- writeContent: function SH_writeContent() {
- this._feedWriter.writeContent();
- },
-
- uninit: function SH_uninit() {
- this._feedWriter.close();
- }
-};
diff --git a/components/feeds/content/subscribe.xhtml b/components/feeds/content/subscribe.xhtml
deleted file mode 100644
index 8ad069f..0000000
--- a/components/feeds/content/subscribe.xhtml
+++ /dev/null
@@ -1,65 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-
-<!DOCTYPE html [
- <!ENTITY % htmlDTD
- PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
- "DTD/xhtml1-strict.dtd">
- %htmlDTD;
- <!ENTITY % globalDTD
- SYSTEM "chrome://global/locale/global.dtd">
- %globalDTD;
- <!ENTITY % feedDTD
- SYSTEM "chrome://browser/locale/feeds/subscribe.dtd">
- %feedDTD;
-]>
-
-<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
-
-<html id="feedHandler"
- xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title>&feedPage.title;</title>
- <link rel="stylesheet"
- href="chrome://browser/skin/feeds/subscribe.css"
- type="text/css"
- media="all"/>
- <link rel="stylesheet"
- href="chrome://browser/content/feeds/subscribe.css"
- type="text/css"
- media="all"/>
- <script type="application/javascript"
- src="chrome://browser/content/feeds/subscribe.js"/>
- </head>
- <body onload="SubscribeHandler.writeContent();" onunload="SubscribeHandler.uninit();">
- <div id="feedHeaderContainer">
- <div id="feedHeader" dir="&locale.dir;">
- <div id="feedIntroText">
- <p id="feedSubscriptionInfo1" />
- <p id="feedSubscriptionInfo2" />
- </div>
- <div id="feedSubscribeLine"></div>
- </div>
- </div>
-
- <script type="application/javascript">
- SubscribeHandler.init();
- </script>
-
- <div id="feedBody">
- <div id="feedTitle">
- <a id="feedTitleLink">
- <img id="feedTitleImage"/>
- </a>
- <div id="feedTitleContainer">
- <h1 id="feedTitleText"/>
- <h2 id="feedSubtitleText"/>
- </div>
- </div>
- <div id="feedContent"/>
- </div>
- </body>
-</html>
diff --git a/components/feeds/content/subscribe.xml b/components/feeds/content/subscribe.xml
deleted file mode 100644
index 949bcfd..0000000
--- a/components/feeds/content/subscribe.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!DOCTYPE bindings [
- <!ENTITY % feedDTD
- SYSTEM "chrome://browser/locale/feeds/subscribe.dtd">
- %feedDTD;
-]>
-<bindings id="feedBindings"
- xmlns="http://www.mozilla.org/xbl"
- xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
- <binding id="feedreaderUI" bindToUntrustedContent="true">
- <content>
- <xul:vbox>
- <xul:hbox align="center">
- <xul:description anonid="subscribeUsingDescription" class="subscribeUsingDescription"/>
- <xul:menulist anonid="handlersMenuList" class="handlersMenuList" aria-labelledby="subscribeUsingDescription">
- <xul:menupopup anonid="handlersMenuPopup" class="handlersMenuPopup">
- <xul:menuitem anonid="liveBookmarksMenuItem" label="&feedLiveBookmarks;" class="menuitem-iconic liveBookmarksMenuItem" image="chrome://browser/skin/page-livemarks.png" selected="true"/>
- <xul:menuseparator/>
- </xul:menupopup>
- </xul:menulist>
- </xul:hbox>
- <xul:hbox>
- <xul:checkbox anonid="alwaysUse" class="alwaysUse" checked="false"/>
- </xul:hbox>
- <xul:hbox align="center">
- <xul:spacer flex="1"/>
- <xul:button label="&feedSubscribeNow;" anonid="subscribeButton" class="subscribeButton"/>
- </xul:hbox>
- </xul:vbox>
- </content>
- <resources>
- <stylesheet src="chrome://browser/skin/feeds/subscribe-ui.css"/>
- </resources>
- </binding>
-</bindings>
-
diff --git a/components/feeds/jar.mn b/components/feeds/jar.mn
deleted file mode 100644
index f8896f8..0000000
--- a/components/feeds/jar.mn
+++ /dev/null
@@ -1,9 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-browser.jar:
- content/browser/feeds/subscribe.xhtml (content/subscribe.xhtml)
- content/browser/feeds/subscribe.js (content/subscribe.js)
- content/browser/feeds/subscribe.xml (content/subscribe.xml)
- content/browser/feeds/subscribe.css (content/subscribe.css)
diff --git a/components/feeds/moz.build b/components/feeds/moz.build
deleted file mode 100644
index 736920a..0000000
--- a/components/feeds/moz.build
+++ /dev/null
@@ -1,33 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-JAR_MANIFESTS += ['jar.mn']
-
-XPIDL_SOURCES += [
- 'nsIFeedResultService.idl',
- 'nsIWebContentConverterRegistrar.idl',
-]
-
-XPIDL_MODULE = 'browser-feeds'
-
-SOURCES += ['nsFeedSniffer.cpp']
-
-EXTRA_COMPONENTS += [
- 'BrowserFeeds.manifest',
- 'FeedConverter.js',
-]
-
-EXTRA_PP_COMPONENTS += [
- 'FeedWriter.js',
- 'WebContentConverter.js',
-]
-
-FINAL_LIBRARY = 'browsercomps'
-
-for var in ('MOZ_APP_NAME', 'MOZ_MACBUNDLE_NAME'):
- DEFINES[var] = CONFIG[var]
-
-LOCAL_INCLUDES += ['../build']
diff --git a/components/feeds/nsFeedSniffer.cpp b/components/feeds/nsFeedSniffer.cpp
deleted file mode 100644
index f314d3d..0000000
--- a/components/feeds/nsFeedSniffer.cpp
+++ /dev/null
@@ -1,363 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsFeedSniffer.h"
-
-
-#include "nsNetCID.h"
-#include "nsXPCOM.h"
-#include "nsCOMPtr.h"
-#include "nsStringStream.h"
-
-#include "nsBrowserCompsCID.h"
-
-#include "nsICategoryManager.h"
-#include "nsIServiceManager.h"
-#include "nsComponentManagerUtils.h"
-#include "nsServiceManagerUtils.h"
-
-#include "nsIStreamConverterService.h"
-#include "nsIStreamConverter.h"
-
-#include "nsIStreamListener.h"
-
-#include "nsIHttpChannel.h"
-#include "nsIMIMEHeaderParam.h"
-
-#include "nsMimeTypes.h"
-#include "nsIURI.h"
-#include <algorithm>
-
-#define TYPE_ATOM "application/atom+xml"
-#define TYPE_RSS "application/rss+xml"
-#define TYPE_MAYBE_FEED "application/vnd.mozilla.maybe.feed"
-
-#define NS_RDF "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-#define NS_RSS "http://purl.org/rss/1.0/"
-
-#define MAX_BYTES 512u
-
-NS_IMPL_ISUPPORTS(nsFeedSniffer,
- nsIContentSniffer,
- nsIStreamListener,
- nsIRequestObserver)
-
-nsresult
-nsFeedSniffer::ConvertEncodedData(nsIRequest* request,
- const uint8_t* data,
- uint32_t length)
-{
- nsresult rv = NS_OK;
-
- mDecodedData = "";
- nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(request));
- if (!httpChannel)
- return NS_ERROR_NO_INTERFACE;
-
- nsAutoCString contentEncoding;
- httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Content-Encoding"),
- contentEncoding);
- if (!contentEncoding.IsEmpty()) {
- nsCOMPtr<nsIStreamConverterService> converterService(do_GetService(NS_STREAMCONVERTERSERVICE_CONTRACTID));
- if (converterService) {
- ToLowerCase(contentEncoding);
-
- nsCOMPtr<nsIStreamListener> converter;
- rv = converterService->AsyncConvertData(contentEncoding.get(),
- "uncompressed", this, nullptr,
- getter_AddRefs(converter));
- NS_ENSURE_SUCCESS(rv, rv);
-
- converter->OnStartRequest(request, nullptr);
-
- nsCOMPtr<nsIStringInputStream> rawStream =
- do_CreateInstance(NS_STRINGINPUTSTREAM_CONTRACTID);
- if (!rawStream)
- return NS_ERROR_FAILURE;
-
- rv = rawStream->SetData((const char*)data, length);
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = converter->OnDataAvailable(request, nullptr, rawStream, 0, length);
- NS_ENSURE_SUCCESS(rv, rv);
-
- converter->OnStopRequest(request, nullptr, NS_OK);
- }
- }
- return rv;
-}
-
-template<int N>
-static bool
-StringBeginsWithLowercaseLiteral(nsAString& aString,
- const char (&aSubstring)[N])
-{
- return StringHead(aString, N).LowerCaseEqualsLiteral(aSubstring);
-}
-
-bool
-HasAttachmentDisposition(nsIHttpChannel* httpChannel)
-{
- if (!httpChannel)
- return false;
-
- uint32_t disp;
- nsresult rv = httpChannel->GetContentDisposition(&disp);
-
- if (NS_SUCCEEDED(rv) && disp == nsIChannel::DISPOSITION_ATTACHMENT)
- return true;
-
- return false;
-}
-
-/**
- * @return the first occurrence of a character within a string buffer,
- * or nullptr if not found
- */
-static const char*
-FindChar(char c, const char *begin, const char *end)
-{
- for (; begin < end; ++begin) {
- if (*begin == c)
- return begin;
- }
- return nullptr;
-}
-
-/**
- *
- * Determine if a substring is the "documentElement" in the document.
- *
- * All of our sniffed substrings: <rss, <feed, <rdf:RDF must be the "document"
- * element within the XML DOM, i.e. the root container element. Otherwise,
- * it's possible that someone embedded one of these tags inside a document of
- * another type, e.g. a HTML document, and we don't want to show the preview
- * page if the document isn't actually a feed.
- *
- * @param start
- * The beginning of the data being sniffed
- * @param end
- * The end of the data being sniffed, right before the substring that
- * was found.
- * @returns true if the found substring is the documentElement, false
- * otherwise.
- */
-static bool
-IsDocumentElement(const char *start, const char* end)
-{
- // For every tag in the buffer, check to see if it's a PI, Doctype or
- // comment, our desired substring or something invalid.
- while ( (start = FindChar('<', start, end)) ) {
- ++start;
- if (start >= end)
- return false;
-
- // Check to see if the character following the '<' is either '?' or '!'
- // (processing instruction or doctype or comment)... these are valid nodes
- // to have in the prologue.
- if (*start != '?' && *start != '!')
- return false;
-
- // Now advance the iterator until the '>' (We do this because we don't want
- // to sniff indicator substrings that are embedded within other nodes, e.g.
- // comments: <!-- <rdf:RDF .. > -->
- start = FindChar('>', start, end);
- if (!start)
- return false;
-
- ++start;
- }
- return true;
-}
-
-/**
- * Determines whether or not a string exists as the root element in an XML data
- * string buffer.
- * @param dataString
- * The data being sniffed
- * @param substring
- * The substring being tested for existence and root-ness.
- * @returns true if the substring exists and is the documentElement, false
- * otherwise.
- */
-static bool
-ContainsTopLevelSubstring(nsACString& dataString, const char *substring)
-{
- int32_t offset = dataString.Find(substring);
- if (offset == -1)
- return false;
-
- const char *begin = dataString.BeginReading();
-
- // Only do the validation when we find the substring.
- return IsDocumentElement(begin, begin + offset);
-}
-
-NS_IMETHODIMP
-nsFeedSniffer::GetMIMETypeFromContent(nsIRequest* request,
- const uint8_t* data,
- uint32_t length,
- nsACString& sniffedType)
-{
- nsCOMPtr<nsIHttpChannel> channel(do_QueryInterface(request));
- if (!channel)
- return NS_ERROR_NO_INTERFACE;
-
- // Check that this is a GET request, since you can't subscribe to a POST...
- nsAutoCString method;
- channel->GetRequestMethod(method);
- if (!method.EqualsLiteral("GET")) {
- sniffedType.Truncate();
- return NS_OK;
- }
-
- // We need to find out if this is a load of a view-source document. In this
- // case we do not want to override the content type, since the source display
- // does not need to be converted from feed format to XUL. More importantly,
- // we don't want to change the content type from something
- // nsContentDLF::CreateInstance knows about (e.g. application/xml, text/html
- // etc) to something that only the application fe knows about (maybe.feed)
- // thus deactivating syntax highlighting.
- nsCOMPtr<nsIURI> originalURI;
- channel->GetOriginalURI(getter_AddRefs(originalURI));
-
- nsAutoCString scheme;
- originalURI->GetScheme(scheme);
- if (scheme.EqualsLiteral("view-source")) {
- sniffedType.Truncate();
- return NS_OK;
- }
-
- // Check the Content-Type to see if it is set correctly. If it is set to
- // something specific that we think is a reliable indication of a feed, don't
- // bother sniffing since we assume the site maintainer knows what they're
- // doing.
- nsAutoCString contentType;
- channel->GetContentType(contentType);
- bool noSniff = contentType.EqualsLiteral(TYPE_RSS) ||
- contentType.EqualsLiteral(TYPE_ATOM);
-
- // Check to see if this was a feed request from the location bar or from
- // the feed: protocol. This is also a reliable indication.
- // The value of the header doesn't matter.
- if (!noSniff) {
- nsAutoCString sniffHeader;
- nsresult foundHeader =
- channel->GetRequestHeader(NS_LITERAL_CSTRING("X-Moz-Is-Feed"),
- sniffHeader);
- noSniff = NS_SUCCEEDED(foundHeader);
- }
-
- if (noSniff) {
- // check for an attachment after we have a likely feed.
- if(HasAttachmentDisposition(channel)) {
- sniffedType.Truncate();
- return NS_OK;
- }
-
- // set the feed header as a response header, since we have good metadata
- // telling us that the feed is supposed to be RSS or Atom
- channel->SetResponseHeader(NS_LITERAL_CSTRING("X-Moz-Is-Feed"),
- NS_LITERAL_CSTRING("1"), false);
- sniffedType.AssignLiteral(TYPE_MAYBE_FEED);
- return NS_OK;
- }
-
- // Don't sniff arbitrary types. Limit sniffing to situations that
- // we think can reasonably arise.
- if (!contentType.EqualsLiteral(TEXT_HTML) &&
- !contentType.EqualsLiteral(APPLICATION_OCTET_STREAM) &&
- // Same criterion as XMLHttpRequest. Should we be checking for "+xml"
- // and check for text/xml and application/xml by hand instead?
- contentType.Find("xml") == -1) {
- sniffedType.Truncate();
- return NS_OK;
- }
-
- // Now we need to potentially decompress data served with
- // Content-Encoding: gzip
- nsresult rv = ConvertEncodedData(request, data, length);
- if (NS_FAILED(rv))
- return rv;
-
- // We cap the number of bytes to scan at MAX_BYTES to prevent picking up
- // false positives by accidentally reading document content, e.g. a "how to
- // make a feed" page.
- const char* testData;
- if (mDecodedData.IsEmpty()) {
- testData = (const char*)data;
- length = std::min(length, MAX_BYTES);
- } else {
- testData = mDecodedData.get();
- length = std::min(mDecodedData.Length(), MAX_BYTES);
- }
-
- // The strategy here is based on that described in:
- // http://blogs.msdn.com/rssteam/articles/PublishersGuide.aspx
- // for interoperarbility purposes.
-
- // Thus begins the actual sniffing.
- nsDependentCSubstring dataString((const char*)testData, length);
-
- bool isFeed = false;
-
- // RSS 0.91/0.92/2.0
- isFeed = ContainsTopLevelSubstring(dataString, "<rss");
-
- // Atom 1.0
- if (!isFeed)
- isFeed = ContainsTopLevelSubstring(dataString, "<feed");
-
- // RSS 1.0
- if (!isFeed) {
- isFeed = ContainsTopLevelSubstring(dataString, "<rdf:RDF") &&
- dataString.Find(NS_RDF) != -1 &&
- dataString.Find(NS_RSS) != -1;
- }
-
- // If we sniffed a feed, coerce our internal type
- if (isFeed && !HasAttachmentDisposition(channel))
- sniffedType.AssignLiteral(TYPE_MAYBE_FEED);
- else
- sniffedType.Truncate();
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsFeedSniffer::OnStartRequest(nsIRequest* request, nsISupports* context)
-{
- return NS_OK;
-}
-
-nsresult
-nsFeedSniffer::AppendSegmentToString(nsIInputStream* inputStream,
- void* closure,
- const char* rawSegment,
- uint32_t toOffset,
- uint32_t count,
- uint32_t* writeCount)
-{
- nsCString* decodedData = static_cast<nsCString*>(closure);
- decodedData->Append(rawSegment, count);
- *writeCount = count;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsFeedSniffer::OnDataAvailable(nsIRequest* request, nsISupports* context,
- nsIInputStream* stream, uint64_t offset,
- uint32_t count)
-{
- uint32_t read;
- return stream->ReadSegments(AppendSegmentToString, &mDecodedData, count,
- &read);
-}
-
-NS_IMETHODIMP
-nsFeedSniffer::OnStopRequest(nsIRequest* request, nsISupports* context,
- nsresult status)
-{
- return NS_OK;
-}
diff --git a/components/feeds/nsFeedSniffer.h b/components/feeds/nsFeedSniffer.h
deleted file mode 100644
index a0eb986..0000000
--- a/components/feeds/nsFeedSniffer.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-
-#include "nsIContentSniffer.h"
-#include "nsIStreamListener.h"
-#include "nsStringAPI.h"
-#include "mozilla/Attributes.h"
-
-class nsFeedSniffer final : public nsIContentSniffer,
- nsIStreamListener
-{
-public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSICONTENTSNIFFER
- NS_DECL_NSIREQUESTOBSERVER
- NS_DECL_NSISTREAMLISTENER
-
- static nsresult AppendSegmentToString(nsIInputStream* inputStream,
- void* closure,
- const char* rawSegment,
- uint32_t toOffset,
- uint32_t count,
- uint32_t* writeCount);
-
-protected:
- ~nsFeedSniffer() {}
-
- nsresult ConvertEncodedData(nsIRequest* request, const uint8_t* data,
- uint32_t length);
-
-private:
- nsCString mDecodedData;
-};
-
diff --git a/components/feeds/nsIFeedResultService.idl b/components/feeds/nsIFeedResultService.idl
deleted file mode 100644
index cb0f332..0000000
--- a/components/feeds/nsIFeedResultService.idl
+++ /dev/null
@@ -1,66 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-interface nsIURI;
-interface nsIRequest;
-interface nsIFeedResult;
-
-/**
- * nsIFeedResultService provides a globally-accessible object for retrieving
- * the results of feed processing.
- */
-[scriptable, uuid(950a829e-c20e-4dc3-b447-f8b753ae54da)]
-interface nsIFeedResultService : nsISupports
-{
- /**
- * When set to true, forces the preview page to be displayed, regardless
- * of the user's preferences.
- */
- attribute boolean forcePreviewPage;
-
- /**
- * Adds a URI to the user's specified external feed handler, or live
- * bookmarks.
- * @param uri
- * The uri of the feed to add.
- * @param title
- * The title of the feed to add.
- * @param subtitle
- * The subtitle of the feed to add.
- * @param feedType
- * The nsIFeed type of the feed. See nsIFeed.idl
- */
- void addToClientReader(in AUTF8String uri,
- in AString title,
- in AString subtitle,
- in unsigned long feedType);
-
- /**
- * Registers a Feed Result object with a globally accessible service
- * so that it can be accessed by a singleton method outside the usual
- * flow of control in document loading.
- *
- * @param feedResult
- * An object implementing nsIFeedResult representing the feed.
- */
- void addFeedResult(in nsIFeedResult feedResult);
-
- /**
- * Gets a Feed Handler object registered using addFeedResult.
- *
- * @param uri
- * The URI of the feed a handler is being requested for
- */
- nsIFeedResult getFeedResult(in nsIURI uri);
-
- /**
- * Unregisters a Feed Handler object registered using addFeedResult.
- * @param uri
- * The feed URI the handler was registered under. This must be
- * the same *instance* the feed was registered under.
- */
- void removeFeedResult(in nsIURI uri);
-};
diff --git a/components/feeds/nsIWebContentConverterRegistrar.idl b/components/feeds/nsIWebContentConverterRegistrar.idl
deleted file mode 100644
index 08ce2f4..0000000
--- a/components/feeds/nsIWebContentConverterRegistrar.idl
+++ /dev/null
@@ -1,117 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsIMIMEInfo.idl"
-#include "nsIWebContentHandlerRegistrar.idl"
-
-interface nsIRequest;
-
-[scriptable, uuid(eb361098-5158-4b21-8f98-50b445f1f0b2)]
-interface nsIWebContentHandlerInfo : nsIHandlerApp
-{
- /**
- * The content type handled by the handler
- */
- readonly attribute AString contentType;
-
- /**
- * The uri of the handler, with an embedded %s where the URI of the loaded
- * document will be encoded.
- */
- readonly attribute AString uri;
-
- /**
- * Gets the service URL Spec, with the loading document URI encoded in it.
- * @param uri
- * The URI of the document being loaded
- * @returns The URI of the service with the loading document URI encoded in
- * it.
- */
- AString getHandlerURI(in AString uri);
-};
-
-[scriptable, uuid(de7cc06e-e778-45cb-b7db-7a114e1e75b1)]
-interface nsIWebContentConverterService : nsIWebContentHandlerRegistrar
-{
- /**
- * Specifies the handler to be used to automatically handle all links of a
- * certain content type from now on.
- * @param contentType
- * The content type to automatically load with the specified handler
- * @param handler
- * A web service handler. If this is null, no automatic action is
- * performed and the user must choose.
- * @throws NS_ERROR_NOT_AVAILABLE if the service refered to by |handler| is
- * not already registered.
- */
- void setAutoHandler(in AString contentType, in nsIWebContentHandlerInfo handler);
-
- /**
- * Gets the auto handler specified for a particular content type
- * @param contentType
- * The content type to look up an auto handler for.
- * @returns The web service handler that will automatically handle all
- * documents of the specified type. null if there is no automatic
- * handler. (Handlers may be registered, just none of them specified
- * as "automatic").
- */
- nsIWebContentHandlerInfo getAutoHandler(in AString contentType);
-
- /**
- * Gets a web handler for the specified service URI
- * @param contentType
- * The content type of the service being located
- * @param uri
- * The service URI of the handler to locate.
- * @returns A web service handler that uses the specified uri.
- */
- nsIWebContentHandlerInfo getWebContentHandlerByURI(in AString contentType,
- in AString uri);
-
- /**
- * Loads the preferred handler when content of a registered type is about
- * to be loaded.
- * @param request
- * The nsIRequest for the load of the content
- */
- void loadPreferredHandler(in nsIRequest request);
-
- /**
- * Removes a registered protocol handler
- * @param protocol
- * The protocol scheme to remove a service handler for
- * @param uri
- * The uri of the service handler to remove
- */
- void removeProtocolHandler(in AString protocol, in AString uri);
-
- /**
- * Removes a registered content handler
- * @param contentType
- * The content type to remove a service handler for
- * @param uri
- * The uri of the service handler to remove
- */
- void removeContentHandler(in AString contentType, in AString uri);
-
- /**
- * Gets the list of content handlers for a particular type.
- * @param contentType
- * The content type to get handlers for
- * @returns An array of nsIWebContentHandlerInfo objects
- */
- void getContentHandlers(in AString contentType,
- [optional] out unsigned long count,
- [retval,array,size_is(count)] out nsIWebContentHandlerInfo handlers);
-
- /**
- * Resets the list of available content handlers to the default set from
- * the distribution.
- * @param contentType
- * The content type to reset handlers for
- */
- void resetHandlersForType(in AString contentType);
-};
-
diff --git a/components/fuel/fuelApplication.js b/components/fuel/fuelApplication.js
deleted file mode 100644
index bc3a091..0000000
--- a/components/fuel/fuelApplication.js
+++ /dev/null
@@ -1,822 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-const Ci = Components.interfaces;
-const Cc = Components.classes;
-
-Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "Deprecated",
- "resource://gre/modules/Deprecated.jsm");
-
-const APPLICATION_CID = Components.ID("fe74cf80-aa2d-11db-abbd-0800200c9a66");
-const APPLICATION_CONTRACTID = "@mozilla.org/fuel/application;1";
-
-//=================================================
-// Singleton that holds services and utilities
-var Utilities = {
- get bookmarks() {
- let bookmarks = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
- getService(Ci.nsINavBookmarksService);
- this.__defineGetter__("bookmarks", function() bookmarks);
- return this.bookmarks;
- },
-
- get bookmarksObserver() {
- let bookmarksObserver = new BookmarksObserver();
- this.__defineGetter__("bookmarksObserver", function() bookmarksObserver);
- return this.bookmarksObserver;
- },
-
- get annotations() {
- let annotations = Cc["@mozilla.org/browser/annotation-service;1"].
- getService(Ci.nsIAnnotationService);
- this.__defineGetter__("annotations", function() annotations);
- return this.annotations;
- },
-
- get history() {
- let history = Cc["@mozilla.org/browser/nav-history-service;1"].
- getService(Ci.nsINavHistoryService);
- this.__defineGetter__("history", function() history);
- return this.history;
- },
-
- get windowMediator() {
- let windowMediator = Cc["@mozilla.org/appshell/window-mediator;1"].
- getService(Ci.nsIWindowMediator);
- this.__defineGetter__("windowMediator", function() windowMediator);
- return this.windowMediator;
- },
-
- makeURI: function fuelutil_makeURI(aSpec) {
- if (!aSpec)
- return null;
- var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
- return ios.newURI(aSpec, null, null);
- },
-
- free: function fuelutil_free() {
- delete this.bookmarks;
- delete this.bookmarksObserver;
- delete this.annotations;
- delete this.history;
- delete this.windowMediator;
- }
-};
-
-
-//=================================================
-// Window implementation
-
-var fuelWindowMap = new WeakMap();
-function getWindow(aWindow) {
- let fuelWindow = fuelWindowMap.get(aWindow);
- if (!fuelWindow) {
- fuelWindow = new Window(aWindow);
- fuelWindowMap.set(aWindow, fuelWindow);
- }
- return fuelWindow;
-}
-
-// Don't call new Window() directly; use getWindow instead.
-function Window(aWindow) {
- this._window = aWindow;
- this._events = new Events();
-
- this._watch("TabOpen");
- this._watch("TabMove");
- this._watch("TabClose");
- this._watch("TabSelect");
-}
-
-Window.prototype = {
- get events() {
- return this._events;
- },
-
- get _tabbrowser() {
- return this._window.getBrowser();
- },
-
- /*
- * Helper used to setup event handlers on the XBL element. Note that the events
- * are actually dispatched to tabs, so we capture them.
- */
- _watch: function win_watch(aType) {
- this._tabbrowser.tabContainer.addEventListener(aType, this,
- /* useCapture = */ true);
- },
-
- handleEvent: function win_handleEvent(aEvent) {
- this._events.dispatch(aEvent.type, getBrowserTab(this, aEvent.originalTarget.linkedBrowser));
- },
-
- get tabs() {
- var tabs = [];
- var browsers = this._tabbrowser.browsers;
- for (var i=0; i<browsers.length; i++)
- tabs.push(getBrowserTab(this, browsers[i]));
- return tabs;
- },
-
- get activeTab() {
- return getBrowserTab(this, this._tabbrowser.selectedBrowser);
- },
-
- open: function win_open(aURI) {
- return getBrowserTab(this, this._tabbrowser.addTab(aURI.spec).linkedBrowser);
- },
-
- QueryInterface: XPCOMUtils.generateQI([Ci.fuelIWindow])
-};
-
-//=================================================
-// BrowserTab implementation
-
-var fuelBrowserTabMap = new WeakMap();
-function getBrowserTab(aFUELWindow, aBrowser) {
- let fuelBrowserTab = fuelBrowserTabMap.get(aBrowser);
- if (!fuelBrowserTab) {
- fuelBrowserTab = new BrowserTab(aFUELWindow, aBrowser);
- fuelBrowserTabMap.set(aBrowser, fuelBrowserTab);
- }
- else {
- // This tab may have moved to another window, so make sure its cached
- // window is up-to-date.
- fuelBrowserTab._window = aFUELWindow;
- }
-
- return fuelBrowserTab;
-}
-
-// Don't call new BrowserTab() directly; call getBrowserTab instead.
-function BrowserTab(aFUELWindow, aBrowser) {
- this._window = aFUELWindow;
- this._browser = aBrowser;
- this._events = new Events();
-
- this._watch("load");
-}
-
-BrowserTab.prototype = {
- get _tabbrowser() {
- return this._window._tabbrowser;
- },
-
- get uri() {
- return this._browser.currentURI;
- },
-
- get index() {
- var tabs = this._tabbrowser.tabs;
- for (var i=0; i<tabs.length; i++) {
- if (tabs[i].linkedBrowser == this._browser)
- return i;
- }
- return -1;
- },
-
- get events() {
- return this._events;
- },
-
- get window() {
- return this._window;
- },
-
- get document() {
- return this._browser.contentDocument;
- },
-
- /*
- * Helper used to setup event handlers on the XBL element
- */
- _watch: function bt_watch(aType) {
- this._browser.addEventListener(aType, this,
- /* useCapture = */ true);
- },
-
- handleEvent: function bt_handleEvent(aEvent) {
- if (aEvent.type == "load") {
- if (!(aEvent.originalTarget instanceof Ci.nsIDOMDocument))
- return;
-
- if (aEvent.originalTarget.defaultView instanceof Ci.nsIDOMWindow &&
- aEvent.originalTarget.defaultView.frameElement)
- return;
- }
- this._events.dispatch(aEvent.type, this);
- },
- /*
- * Helper used to determine the index offset of the browsertab
- */
- _getTab: function bt_gettab() {
- var tabs = this._tabbrowser.tabs;
- return tabs[this.index] || null;
- },
-
- load: function bt_load(aURI) {
- this._browser.loadURI(aURI.spec, null, null);
- },
-
- focus: function bt_focus() {
- this._tabbrowser.selectedTab = this._getTab();
- this._tabbrowser.focus();
- },
-
- close: function bt_close() {
- this._tabbrowser.removeTab(this._getTab());
- },
-
- moveBefore: function bt_movebefore(aBefore) {
- this._tabbrowser.moveTabTo(this._getTab(), aBefore.index);
- },
-
- moveToEnd: function bt_moveend() {
- this._tabbrowser.moveTabTo(this._getTab(), this._tabbrowser.browsers.length);
- },
-
- QueryInterface: XPCOMUtils.generateQI([Ci.fuelIBrowserTab])
-};
-
-
-//=================================================
-// Annotations implementation
-function Annotations(aId) {
- this._id = aId;
-}
-
-Annotations.prototype = {
- get names() {
- return Utilities.annotations.getItemAnnotationNames(this._id);
- },
-
- has: function ann_has(aName) {
- return Utilities.annotations.itemHasAnnotation(this._id, aName);
- },
-
- get: function ann_get(aName) {
- if (this.has(aName))
- return Utilities.annotations.getItemAnnotation(this._id, aName);
- return null;
- },
-
- set: function ann_set(aName, aValue, aExpiration) {
- Utilities.annotations.setItemAnnotation(this._id, aName, aValue, 0, aExpiration);
- },
-
- remove: function ann_remove(aName) {
- if (aName)
- Utilities.annotations.removeItemAnnotation(this._id, aName);
- },
-
- QueryInterface: XPCOMUtils.generateQI([Ci.fuelIAnnotations])
-};
-
-
-//=================================================
-// BookmarksObserver implementation (internal class)
-//
-// BookmarksObserver is a global singleton which watches the browser's
-// bookmarks and sends you events when things change.
-//
-// You can register three different kinds of event listeners on
-// BookmarksObserver, using addListener, addFolderListener, and
-// addRootlistener.
-//
-// - addListener(aId, aEvent, aListener) lets you listen to a specific
-// bookmark. You can listen to the "change", "move", and "remove" events.
-//
-// - addFolderListener(aId, aEvent, aListener) lets you listen to a specific
-// bookmark folder. You can listen to "addchild" and "removechild".
-//
-// - addRootListener(aEvent, aListener) lets you listen to the root bookmark
-// node. This lets you hear "add", "remove", and "change" events on all
-// bookmarks.
-//
-
-function BookmarksObserver() {
- this._eventsDict = {};
- this._folderEventsDict = {};
- this._rootEvents = new Events();
- Utilities.bookmarks.addObserver(this, /* ownsWeak = */ true);
-}
-
-BookmarksObserver.prototype = {
- onBeginUpdateBatch: function () {},
- onEndUpdateBatch: function () {},
- onItemVisited: function () {},
-
- onItemAdded: function bo_onItemAdded(aId, aFolder, aIndex, aItemType, aURI) {
- this._rootEvents.dispatch("add", aId);
- this._dispatchToEvents("addchild", aId, this._folderEventsDict[aFolder]);
- },
-
- onItemRemoved: function bo_onItemRemoved(aId, aFolder, aIndex) {
- this._rootEvents.dispatch("remove", aId);
- this._dispatchToEvents("remove", aId, this._eventsDict[aId]);
- this._dispatchToEvents("removechild", aId, this._folderEventsDict[aFolder]);
- },
-
- onItemChanged: function bo_onItemChanged(aId, aProperty, aIsAnnotationProperty, aValue) {
- this._rootEvents.dispatch("change", aProperty);
- this._dispatchToEvents("change", aProperty, this._eventsDict[aId]);
- },
-
- onItemMoved: function bo_onItemMoved(aId, aOldParent, aOldIndex, aNewParent, aNewIndex) {
- this._dispatchToEvents("move", aId, this._eventsDict[aId]);
- },
-
- _dispatchToEvents: function bo_dispatchToEvents(aEvent, aData, aEvents) {
- if (aEvents) {
- aEvents.dispatch(aEvent, aData);
- }
- },
-
- _addListenerToDict: function bo_addListenerToDict(aId, aEvent, aListener, aDict) {
- var events = aDict[aId];
- if (!events) {
- events = new Events();
- aDict[aId] = events;
- }
- events.addListener(aEvent, aListener);
- },
-
- _removeListenerFromDict: function bo_removeListenerFromDict(aId, aEvent, aListener, aDict) {
- var events = aDict[aId];
- if (!events) {
- return;
- }
- events.removeListener(aEvent, aListener);
- if (events._listeners.length == 0) {
- delete aDict[aId];
- }
- },
-
- addListener: function bo_addListener(aId, aEvent, aListener) {
- this._addListenerToDict(aId, aEvent, aListener, this._eventsDict);
- },
-
- removeListener: function bo_removeListener(aId, aEvent, aListener) {
- this._removeListenerFromDict(aId, aEvent, aListener, this._eventsDict);
- },
-
- addFolderListener: function addFolderListener(aId, aEvent, aListener) {
- this._addListenerToDict(aId, aEvent, aListener, this._folderEventsDict);
- },
-
- removeFolderListener: function removeFolderListener(aId, aEvent, aListener) {
- this._removeListenerFromDict(aId, aEvent, aListener, this._folderEventsDict);
- },
-
- addRootListener: function addRootListener(aEvent, aListener) {
- this._rootEvents.addListener(aEvent, aListener);
- },
-
- removeRootListener: function removeRootListener(aEvent, aListener) {
- this._rootEvents.removeListener(aEvent, aListener);
- },
-
- QueryInterface: XPCOMUtils.generateQI([Ci.nsINavBookmarksObserver,
- Ci.nsISupportsWeakReference])
-};
-
-//=================================================
-// Bookmark implementation
-//
-// Bookmark event listeners are stored in BookmarksObserver, not in the
-// Bookmark objects themselves. Thus, you don't have to hold on to a Bookmark
-// object in order for your event listener to stay valid, and Bookmark objects
-// not kept alive by the extension can be GC'ed.
-//
-// A consequence of this is that if you have two different Bookmark objects x
-// and y for the same bookmark (i.e., x != y but x.id == y.id), and you do
-//
-// x.addListener("foo", fun);
-// y.removeListener("foo", fun);
-//
-// the second line will in fact remove the listener added in the first line.
-//
-
-function Bookmark(aId, aParent, aType) {
- this._id = aId;
- this._parent = aParent;
- this._type = aType || "bookmark";
- this._annotations = new Annotations(this._id);
-
- // Our _events object forwards to bookmarksObserver.
- var self = this;
- this._events = {
- addListener: function bookmarkevents_al(aEvent, aListener) {
- Utilities.bookmarksObserver.addListener(self._id, aEvent, aListener);
- },
- removeListener: function bookmarkevents_rl(aEvent, aListener) {
- Utilities.bookmarksObserver.removeListener(self._id, aEvent, aListener);
- },
- QueryInterface: XPCOMUtils.generateQI([Ci.extIEvents])
- };
-
- // For our onItemMoved listener, which updates this._parent.
- Utilities.bookmarks.addObserver(this, /* ownsWeak = */ true);
-}
-
-Bookmark.prototype = {
- get id() {
- return this._id;
- },
-
- get title() {
- return Utilities.bookmarks.getItemTitle(this._id);
- },
-
- set title(aTitle) {
- Utilities.bookmarks.setItemTitle(this._id, aTitle);
- },
-
- get uri() {
- return Utilities.bookmarks.getBookmarkURI(this._id);
- },
-
- set uri(aURI) {
- return Utilities.bookmarks.changeBookmarkURI(this._id, aURI);
- },
-
- get description() {
- return this._annotations.get("bookmarkProperties/description");
- },
-
- set description(aDesc) {
- this._annotations.set("bookmarkProperties/description", aDesc, Ci.nsIAnnotationService.EXPIRE_NEVER);
- },
-
- get keyword() {
- return Utilities.bookmarks.getKeywordForBookmark(this._id);
- },
-
- set keyword(aKeyword) {
- Utilities.bookmarks.setKeywordForBookmark(this._id, aKeyword);
- },
-
- get type() {
- return this._type;
- },
-
- get parent() {
- return this._parent;
- },
-
- set parent(aFolder) {
- Utilities.bookmarks.moveItem(this._id, aFolder.id, Utilities.bookmarks.DEFAULT_INDEX);
- // this._parent is updated in onItemMoved
- },
-
- get annotations() {
- return this._annotations;
- },
-
- get events() {
- return this._events;
- },
-
- remove : function bm_remove() {
- Utilities.bookmarks.removeItem(this._id);
- },
-
- onBeginUpdateBatch: function () {},
- onEndUpdateBatch: function () {},
- onItemAdded: function () {},
- onItemVisited: function () {},
- onItemRemoved: function () {},
- onItemChanged: function () {},
-
- onItemMoved: function(aId, aOldParent, aOldIndex, aNewParent, aNewIndex) {
- if (aId == this._id) {
- this._parent = new BookmarkFolder(aNewParent, Utilities.bookmarks.getFolderIdForItem(aNewParent));
- }
- },
-
- QueryInterface: XPCOMUtils.generateQI([Ci.fuelIBookmark,
- Ci.nsINavBookmarksObserver,
- Ci.nsISupportsWeakReference])
-};
-
-
-//=================================================
-// BookmarkFolder implementation
-//
-// As with Bookmark, events on BookmarkFolder are handled by the
-// BookmarksObserver singleton.
-//
-
-function BookmarkFolder(aId, aParent) {
- this._id = aId;
- this._parent = aParent;
- this._annotations = new Annotations(this._id);
-
- // Our event listeners are handled by the BookmarksObserver singleton. This
- // is a bit complicated because there are three different kinds of events we
- // might want to listen to here:
- //
- // - If this._parent is null, we're the root bookmark folder, and all our
- // listeners should be root listeners.
- //
- // - Otherwise, events ending with "child" (addchild, removechild) are
- // handled by a folder listener.
- //
- // - Other events are handled by a vanilla bookmark listener.
-
- var self = this;
- this._events = {
- addListener: function bmfevents_al(aEvent, aListener) {
- if (self._parent) {
- if (/child$/.test(aEvent)) {
- Utilities.bookmarksObserver.addFolderListener(self._id, aEvent, aListener);
- }
- else {
- Utilities.bookmarksObserver.addListener(self._id, aEvent, aListener);
- }
- }
- else {
- Utilities.bookmarksObserver.addRootListener(aEvent, aListener);
- }
- },
- removeListener: function bmfevents_rl(aEvent, aListener) {
- if (self._parent) {
- if (/child$/.test(aEvent)) {
- Utilities.bookmarksObserver.removeFolderListener(self._id, aEvent, aListener);
- }
- else {
- Utilities.bookmarksObserver.removeListener(self._id, aEvent, aListener);
- }
- }
- else {
- Utilities.bookmarksObserver.removeRootListener(aEvent, aListener);
- }
- },
- QueryInterface: XPCOMUtils.generateQI([Ci.extIEvents])
- };
-
- // For our onItemMoved listener, which updates this._parent.
- Utilities.bookmarks.addObserver(this, /* ownsWeak = */ true);
-}
-
-BookmarkFolder.prototype = {
- get id() {
- return this._id;
- },
-
- get title() {
- return Utilities.bookmarks.getItemTitle(this._id);
- },
-
- set title(aTitle) {
- Utilities.bookmarks.setItemTitle(this._id, aTitle);
- },
-
- get description() {
- return this._annotations.get("bookmarkProperties/description");
- },
-
- set description(aDesc) {
- this._annotations.set("bookmarkProperties/description", aDesc, Ci.nsIAnnotationService.EXPIRE_NEVER);
- },
-
- get type() {
- return "folder";
- },
-
- get parent() {
- return this._parent;
- },
-
- set parent(aFolder) {
- Utilities.bookmarks.moveItem(this._id, aFolder.id, Utilities.bookmarks.DEFAULT_INDEX);
- // this._parent is updated in onItemMoved
- },
-
- get annotations() {
- return this._annotations;
- },
-
- get events() {
- return this._events;
- },
-
- get children() {
- var items = [];
-
- var options = Utilities.history.getNewQueryOptions();
- var query = Utilities.history.getNewQuery();
- query.setFolders([this._id], 1);
- var result = Utilities.history.executeQuery(query, options);
- var rootNode = result.root;
- rootNode.containerOpen = true;
- var cc = rootNode.childCount;
- for (var i=0; i<cc; ++i) {
- var node = rootNode.getChild(i);
- if (node.type == node.RESULT_TYPE_FOLDER) {
- var folder = new BookmarkFolder(node.itemId, this._id);
- items.push(folder);
- }
- else if (node.type == node.RESULT_TYPE_SEPARATOR) {
- var separator = new Bookmark(node.itemId, this._id, "separator");
- items.push(separator);
- }
- else {
- var bookmark = new Bookmark(node.itemId, this._id, "bookmark");
- items.push(bookmark);
- }
- }
- rootNode.containerOpen = false;
-
- return items;
- },
-
- addBookmark: function bmf_addbm(aTitle, aUri) {
- var newBookmarkID = Utilities.bookmarks.insertBookmark(this._id, aUri, Utilities.bookmarks.DEFAULT_INDEX, aTitle);
- var newBookmark = new Bookmark(newBookmarkID, this, "bookmark");
- return newBookmark;
- },
-
- addSeparator: function bmf_addsep() {
- var newBookmarkID = Utilities.bookmarks.insertSeparator(this._id, Utilities.bookmarks.DEFAULT_INDEX);
- var newBookmark = new Bookmark(newBookmarkID, this, "separator");
- return newBookmark;
- },
-
- addFolder: function bmf_addfolder(aTitle) {
- var newFolderID = Utilities.bookmarks.createFolder(this._id, aTitle, Utilities.bookmarks.DEFAULT_INDEX);
- var newFolder = new BookmarkFolder(newFolderID, this);
- return newFolder;
- },
-
- remove: function bmf_remove() {
- Utilities.bookmarks.removeItem(this._id);
- },
-
- // observer
- onBeginUpdateBatch: function () {},
- onEndUpdateBatch : function () {},
- onItemAdded : function () {},
- onItemRemoved : function () {},
- onItemChanged : function () {},
-
- onItemMoved: function bf_onItemMoved(aId, aOldParent, aOldIndex, aNewParent, aNewIndex) {
- if (this._id == aId) {
- this._parent = new BookmarkFolder(aNewParent, Utilities.bookmarks.getFolderIdForItem(aNewParent));
- }
- },
-
- QueryInterface: XPCOMUtils.generateQI([Ci.fuelIBookmarkFolder,
- Ci.nsINavBookmarksObserver,
- Ci.nsISupportsWeakReference])
-};
-
-//=================================================
-// BookmarkRoots implementation
-function BookmarkRoots() {
-}
-
-BookmarkRoots.prototype = {
- get menu() {
- if (!this._menu)
- this._menu = new BookmarkFolder(Utilities.bookmarks.bookmarksMenuFolder, null);
-
- return this._menu;
- },
-
- get toolbar() {
- if (!this._toolbar)
- this._toolbar = new BookmarkFolder(Utilities.bookmarks.toolbarFolder, null);
-
- return this._toolbar;
- },
-
- get tags() {
- if (!this._tags)
- this._tags = new BookmarkFolder(Utilities.bookmarks.tagsFolder, null);
-
- return this._tags;
- },
-
- get unfiled() {
- if (!this._unfiled)
- this._unfiled = new BookmarkFolder(Utilities.bookmarks.unfiledBookmarksFolder, null);
-
- return this._unfiled;
- },
-
- QueryInterface: XPCOMUtils.generateQI([Ci.fuelIBookmarkRoots])
-};
-
-
-//=================================================
-// Factory - Treat Application as a singleton
-// XXX This is required, because we're registered for the 'JavaScript global
-// privileged property' category, whose handler always calls createInstance.
-// See bug 386535.
-var gSingleton = null;
-var ApplicationFactory = {
- createInstance: function af_ci(aOuter, aIID) {
- if (aOuter != null)
- throw Components.results.NS_ERROR_NO_AGGREGATION;
-
- if (gSingleton == null) {
- gSingleton = new Application();
- }
-
- return gSingleton.QueryInterface(aIID);
- }
-};
-
-
-#include ../../../../toolkit/components/exthelper/extApplication.js
-
-//=================================================
-// Application constructor
-function Application() {
- Deprecated.warning("FUEL is deprecated, you should use the standard Toolkit API instead.",
- "https://github.com/MoonchildProductions/UXP/issues/1083");
- this.initToolkitHelpers();
-}
-
-//=================================================
-// Application implementation
-function ApplicationPrototype() {
- // for nsIClassInfo + XPCOMUtils
- this.classID = APPLICATION_CID;
-
- // redefine the default factory for XPCOMUtils
- this._xpcom_factory = ApplicationFactory;
-
- // for nsISupports
- this.QueryInterface = XPCOMUtils.generateQI([
- Ci.fuelIApplication,
- Ci.extIApplication,
- Ci.nsIObserver,
- Ci.nsISupportsWeakReference
- ]);
-
- // for nsIClassInfo
- this.classInfo = XPCOMUtils.generateCI({
- classID: APPLICATION_CID,
- contractID: APPLICATION_CONTRACTID,
- interfaces: [
- Ci.fuelIApplication,
- Ci.extIApplication,
- Ci.nsIObserver
- ],
- flags: Ci.nsIClassInfo.SINGLETON
- });
-
- // for nsIObserver
- this.observe = function (aSubject, aTopic, aData) {
- // Call the extApplication version of this function first
- var superPrototype = Object.getPrototypeOf(Object.getPrototypeOf(this));
- superPrototype.observe.call(this, aSubject, aTopic, aData);
- if (aTopic == "xpcom-shutdown") {
- this._obs.removeObserver(this, "xpcom-shutdown");
- Utilities.free();
- }
- };
-
- Object.defineProperty(this, "bookmarks", {
- get: function bookmarks () {
- let bookmarks = new BookmarkRoots();
- Object.defineProperty(this, "bookmarks", { value: bookmarks });
- return this.bookmarks;
- },
- enumerable: true,
- configurable: true
- });
-
- Object.defineProperty(this, "windows", {
- get: function windows() {
- var win = [];
- var browserEnum = Utilities.windowMediator.getEnumerator("navigator:browser");
-
- while (browserEnum.hasMoreElements())
- win.push(getWindow(browserEnum.getNext()));
-
- return win;
- },
- enumerable: true,
- configurable: true
- });
-
- Object.defineProperty(this, "activeWindow", {
- get: () => getWindow(Utilities.windowMediator.getMostRecentWindow("navigator:browser")),
- enumerable: true,
- configurable: true
- });
-
-};
-
-// set the proto, defined in extApplication.js
-ApplicationPrototype.prototype = extApplication.prototype;
-
-Application.prototype = new ApplicationPrototype();
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([Application]);
-
diff --git a/components/fuel/fuelApplication.manifest b/components/fuel/fuelApplication.manifest
deleted file mode 100644
index 67e6d0f..0000000
--- a/components/fuel/fuelApplication.manifest
+++ /dev/null
@@ -1,3 +0,0 @@
-component {fe74cf80-aa2d-11db-abbd-0800200c9a66} fuelApplication.js
-contract @mozilla.org/fuel/application;1 {fe74cf80-aa2d-11db-abbd-0800200c9a66}
-category JavaScript-global-privileged-property Application @mozilla.org/fuel/application;1
diff --git a/components/fuel/fuelIApplication.idl b/components/fuel/fuelIApplication.idl
deleted file mode 100644
index 69b51b0..0000000
--- a/components/fuel/fuelIApplication.idl
+++ /dev/null
@@ -1,347 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-#include "extIApplication.idl"
-
-interface nsIVariant;
-interface nsIURI;
-interface nsIDOMHTMLDocument;
-
-interface fuelIBookmarkFolder;
-interface fuelIBrowserTab;
-
-/**
- * Interface representing a collection of annotations associated
- * with a bookmark or bookmark folder.
- */
-[scriptable, uuid(335c9292-91a1-4ca0-ad0b-07d5f63ed6cd)]
-interface fuelIAnnotations : nsISupports
-{
- /**
- * Array of the annotation names associated with the owning item
- */
- readonly attribute nsIVariant names;
-
- /**
- * Determines if an annotation exists with the given name.
- * @param aName
- * The name of the annotation
- * @returns true if an annotation exists with the given name,
- * false otherwise.
- */
- boolean has(in AString aName);
-
- /**
- * Gets the value of an annotation with the given name.
- * @param aName
- * The name of the annotation
- * @returns A variant containing the value of the annotation. Supports
- * string, boolean and number.
- */
- nsIVariant get(in AString aName);
-
- /**
- * Sets the value of an annotation with the given name.
- * @param aName
- * The name of the annotation
- * @param aValue
- * The new value of the annotation. Supports string, boolean
- * and number
- * @param aExpiration
- * The expiration policy for the annotation.
- * See nsIAnnotationService.
- */
- void set(in AString aName, in nsIVariant aValue, in int32_t aExpiration);
-
- /**
- * Removes the named annotation from the owner item.
- * @param aName
- * The name of annotation.
- */
- void remove(in AString aName);
-};
-
-
-/**
- * Interface representing a bookmark item.
- */
-[scriptable, uuid(808585b6-7568-4b26-8c62-545221bf2b8c)]
-interface fuelIBookmark : nsISupports
-{
- /**
- * The id of the bookmark.
- */
- readonly attribute long long id;
-
- /**
- * The title of the bookmark.
- */
- attribute AString title;
-
- /**
- * The uri of the bookmark.
- */
- attribute nsIURI uri;
-
- /**
- * The description of the bookmark.
- */
- attribute AString description;
-
- /**
- * The keyword associated with the bookmark.
- */
- attribute AString keyword;
-
- /**
- * The type of the bookmark.
- * values: "bookmark", "separator"
- */
- readonly attribute AString type;
-
- /**
- * The parent folder of the bookmark.
- */
- attribute fuelIBookmarkFolder parent;
-
- /**
- * The annotations object for the bookmark.
- */
- readonly attribute fuelIAnnotations annotations;
-
- /**
- * The events object for the bookmark.
- * supports: "remove", "change", "visit", "move"
- */
- readonly attribute extIEvents events;
-
- /**
- * Removes the item from the parent folder. Used to
- * delete a bookmark or separator
- */
- void remove();
-};
-
-
-/**
- * Interface representing a bookmark folder. Folders
- * can hold bookmarks, separators and other folders.
- */
-[scriptable, uuid(9f42fe20-52de-4a55-8632-a459c7716aa0)]
-interface fuelIBookmarkFolder : nsISupports
-{
- /**
- * The id of the folder.
- */
- readonly attribute long long id;
-
- /**
- * The title of the folder.
- */
- attribute AString title;
-
- /**
- * The description of the folder.
- */
- attribute AString description;
-
- /**
- * The type of the folder.
- * values: "folder"
- */
- readonly attribute AString type;
-
- /**
- * The parent folder of the folder.
- */
- attribute fuelIBookmarkFolder parent;
-
- /**
- * The annotations object for the folder.
- */
- readonly attribute fuelIAnnotations annotations;
-
- /**
- * The events object for the folder.
- * supports: "add", "addchild", "remove", "removechild", "change", "move"
- */
- readonly attribute extIEvents events;
-
- /**
- * Array of all bookmarks, separators and folders contained
- * in this folder.
- */
- readonly attribute nsIVariant children;
-
- /**
- * Adds a new child bookmark to this folder.
- * @param aTitle
- * The title of bookmark.
- * @param aURI
- * The uri of bookmark.
- */
- fuelIBookmark addBookmark(in AString aTitle, in nsIURI aURI);
-
- /**
- * Adds a new child separator to this folder.
- */
- fuelIBookmark addSeparator();
-
- /**
- * Adds a new child folder to this folder.
- * @param aTitle
- * The title of folder.
- */
- fuelIBookmarkFolder addFolder(in AString aTitle);
-
- /**
- * Removes the folder from the parent folder.
- */
- void remove();
-};
-
-/**
- * Interface representing a container for bookmark roots. Roots
- * are the top level parents for the various types of bookmarks in the system.
- */
-[scriptable, uuid(c9a80870-eb3c-11dc-95ff-0800200c9a66)]
-interface fuelIBookmarkRoots : nsISupports
-{
- /**
- * The folder for the 'bookmarks menu' root.
- */
- readonly attribute fuelIBookmarkFolder menu;
-
- /**
- * The folder for the 'personal toolbar' root.
- */
- readonly attribute fuelIBookmarkFolder toolbar;
-
- /**
- * The folder for the 'tags' root.
- */
- readonly attribute fuelIBookmarkFolder tags;
-
- /**
- * The folder for the 'unfiled bookmarks' root.
- */
- readonly attribute fuelIBookmarkFolder unfiled;
-};
-
-/**
- * Interface representing a browser window.
- */
-[scriptable, uuid(207edb28-eb5e-424e-a862-b0e97C8de866)]
-interface fuelIWindow : nsISupports
-{
- /**
- * A collection of browser tabs within the browser window.
- */
- readonly attribute nsIVariant tabs;
-
- /**
- * The currently-active tab within the browser window.
- */
- readonly attribute fuelIBrowserTab activeTab;
-
- /**
- * Open a new browser tab, pointing to the specified URI.
- * @param aURI
- * The uri to open the browser tab to
- */
- fuelIBrowserTab open(in nsIURI aURI);
-
- /**
- * The events object for the browser window.
- * supports: "TabOpen", "TabClose", "TabMove", "TabSelect"
- */
- readonly attribute extIEvents events;
-};
-
-/**
- * Interface representing a browser tab.
- */
-[scriptable, uuid(3073ceff-777c-41ce-9ace-ab37268147c1)]
-interface fuelIBrowserTab : nsISupports
-{
- /**
- * The current uri of this tab.
- */
- readonly attribute nsIURI uri;
-
- /**
- * The current index of this tab in the browser window.
- */
- readonly attribute int32_t index;
-
- /**
- * The browser window that is holding the tab.
- */
- readonly attribute fuelIWindow window;
-
- /**
- * The content document of the browser tab.
- */
- readonly attribute nsIDOMHTMLDocument document;
-
- /**
- * The events object for the browser tab.
- * supports: "load"
- */
- readonly attribute extIEvents events;
-
- /**
- * Load a new URI into this browser tab.
- * @param aURI
- * The uri to load into the browser tab
- */
- void load(in nsIURI aURI);
-
- /**
- * Give focus to this browser tab, and bring it to the front.
- */
- void focus();
-
- /**
- * Close the browser tab. This may not actually close the tab
- * as script may abort the close operation.
- */
- void close();
-
- /**
- * Moves this browser tab before another browser tab within the window.
- * @param aBefore
- * The tab before which the target tab will be moved
- */
- void moveBefore(in fuelIBrowserTab aBefore);
-
- /**
- * Move this browser tab to the last tab within the window.
- */
- void moveToEnd();
-};
-
-/**
- * Interface for managing and accessing the applications systems
- */
-[scriptable, uuid(fe74cf80-aa2d-11db-abbd-0800200c9a66)]
-interface fuelIApplication : extIApplication
-{
- /**
- * The root bookmarks object for the application.
- * Contains all the bookmark roots in the system.
- */
- readonly attribute fuelIBookmarkRoots bookmarks;
-
- /**
- * An array of browser windows within the application.
- */
- readonly attribute nsIVariant windows;
-
- /**
- * The currently active browser window.
- */
- readonly attribute fuelIWindow activeWindow;
-};
diff --git a/components/fuel/moz.build b/components/fuel/moz.build
deleted file mode 100644
index 5c468f2..0000000
--- a/components/fuel/moz.build
+++ /dev/null
@@ -1,14 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-XPIDL_SOURCES += ['fuelIApplication.idl']
-
-XPIDL_MODULE = 'fuel'
-
-EXTRA_COMPONENTS += ['fuelApplication.manifest']
-
-EXTRA_PP_COMPONENTS += ['fuelApplication.js']
-
diff --git a/components/moz.build b/components/moz.build
deleted file mode 100644
index 48d4552..0000000
--- a/components/moz.build
+++ /dev/null
@@ -1,47 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-DIRS += [
- 'abouthome',
- 'certerror',
- 'dirprovider',
- 'downloads',
- 'feeds',
- 'fuel',
- 'newtab',
- 'pageinfo',
- 'places',
- 'permissions',
- 'preferences',
- 'privatebrowsing',
- 'search',
- 'sessionstore',
- 'shell',
- 'statusbar',
-]
-
-if CONFIG['MOZ_SERVICES_SYNC']:
- DIRS += ['sync']
-
-DIRS += ['build']
-
-XPIDL_SOURCES += [
- 'nsIBrowserGlue.idl',
- 'nsIBrowserHandler.idl',
-]
-
-XPIDL_MODULE = 'browsercompsbase'
-
-EXTRA_PP_COMPONENTS += [
- 'BrowserComponents.manifest',
- 'nsAboutRedirector.js',
- 'nsBrowserContentHandler.js',
- 'nsBrowserGlue.js',
-]
-
-EXTRA_JS_MODULES += [
- 'distribution.js',
-] \ No newline at end of file
diff --git a/components/newtab/cells.js b/components/newtab/cells.js
deleted file mode 100644
index 47d4ef5..0000000
--- a/components/newtab/cells.js
+++ /dev/null
@@ -1,126 +0,0 @@
-#ifdef 0
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-#endif
-
-/**
- * This class manages a cell's DOM node (not the actually cell content, a site).
- * It's mostly read-only, i.e. all manipulation of both position and content
- * aren't handled here.
- */
-function Cell(aGrid, aNode) {
- this._grid = aGrid;
- this._node = aNode;
- this._node._newtabCell = this;
-
- // Register drag-and-drop event handlers.
- ["dragenter", "dragover", "dragexit", "drop"].forEach(function (aType) {
- this._node.addEventListener(aType, this, false);
- }, this);
-}
-
-Cell.prototype = {
- /**
- * The grid.
- */
- _grid: null,
-
- /**
- * The cell's DOM node.
- */
- get node() { return this._node; },
-
- /**
- * The cell's offset in the grid.
- */
- get index() {
- let index = this._grid.cells.indexOf(this);
-
- // Cache this value, overwrite the getter.
- Object.defineProperty(this, "index", {value: index, enumerable: true});
-
- return index;
- },
-
- /**
- * The previous cell in the grid.
- */
- get previousSibling() {
- let prev = this.node.previousElementSibling;
- prev = prev && prev._newtabCell;
-
- // Cache this value, overwrite the getter.
- Object.defineProperty(this, "previousSibling", {value: prev, enumerable: true});
-
- return prev;
- },
-
- /**
- * The next cell in the grid.
- */
- get nextSibling() {
- let next = this.node.nextElementSibling;
- next = next && next._newtabCell;
-
- // Cache this value, overwrite the getter.
- Object.defineProperty(this, "nextSibling", {value: next, enumerable: true});
-
- return next;
- },
-
- /**
- * The site contained in the cell, if any.
- */
- get site() {
- let firstChild = this.node.firstElementChild;
- return firstChild && firstChild._newtabSite;
- },
-
- /**
- * Checks whether the cell contains a pinned site.
- * @return Whether the cell contains a pinned site.
- */
- containsPinnedSite: function Cell_containsPinnedSite() {
- let site = this.site;
- return site && site.isPinned();
- },
-
- /**
- * Checks whether the cell contains a site (is empty).
- * @return Whether the cell is empty.
- */
- isEmpty: function Cell_isEmpty() {
- return !this.site;
- },
-
- /**
- * Handles all cell events.
- */
- handleEvent: function Cell_handleEvent(aEvent) {
- // We're not responding to external drag/drop events
- // when our parent window is in private browsing mode.
- if (inPrivateBrowsingMode() && !gDrag.draggedSite)
- return;
-
- if (aEvent.type != "dragexit" && !gDrag.isValid(aEvent))
- return;
-
- switch (aEvent.type) {
- case "dragenter":
- aEvent.preventDefault();
- gDrop.enter(this, aEvent);
- break;
- case "dragover":
- aEvent.preventDefault();
- break;
- case "dragexit":
- gDrop.exit(this, aEvent);
- break;
- case "drop":
- aEvent.preventDefault();
- gDrop.drop(this, aEvent);
- break;
- }
- }
-};
diff --git a/components/newtab/drag.js b/components/newtab/drag.js
deleted file mode 100644
index e3928eb..0000000
--- a/components/newtab/drag.js
+++ /dev/null
@@ -1,151 +0,0 @@
-#ifdef 0
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-#endif
-
-/**
- * This singleton implements site dragging functionality.
- */
-var gDrag = {
- /**
- * The site offset to the drag start point.
- */
- _offsetX: null,
- _offsetY: null,
-
- /**
- * The site that is dragged.
- */
- _draggedSite: null,
- get draggedSite() { return this._draggedSite; },
-
- /**
- * The cell width/height at the point the drag started.
- */
- _cellWidth: null,
- _cellHeight: null,
- get cellWidth() { return this._cellWidth; },
- get cellHeight() { return this._cellHeight; },
-
- /**
- * Start a new drag operation.
- * @param aSite The site that's being dragged.
- * @param aEvent The 'dragstart' event.
- */
- start: function Drag_start(aSite, aEvent) {
- this._draggedSite = aSite;
-
- // Mark nodes as being dragged.
- let selector = ".newtab-site, .newtab-control, .newtab-thumbnail";
- let parentCell = aSite.node.parentNode;
- let nodes = parentCell.querySelectorAll(selector);
- for (let i = 0; i < nodes.length; i++)
- nodes[i].setAttribute("dragged", "true");
-
- parentCell.setAttribute("dragged", "true");
-
- this._setDragData(aSite, aEvent);
-
- // Store the cursor offset.
- let node = aSite.node;
- let rect = node.getBoundingClientRect();
- this._offsetX = aEvent.clientX - rect.left;
- this._offsetY = aEvent.clientY - rect.top;
-
- // Store the cell dimensions.
- let cellNode = aSite.cell.node;
- this._cellWidth = cellNode.offsetWidth;
- this._cellHeight = cellNode.offsetHeight;
-
- gTransformation.freezeSitePosition(aSite);
- },
-
- /**
- * Handles the 'drag' event.
- * @param aSite The site that's being dragged.
- * @param aEvent The 'drag' event.
- */
- drag: function Drag_drag(aSite, aEvent) {
- // Get the viewport size.
- let {clientWidth, clientHeight} = document.documentElement;
-
- // We'll want a padding of 5px.
- let border = 5;
-
- // Enforce minimum constraints to keep the drag image inside the window.
- let left = Math.max(scrollX + aEvent.clientX - this._offsetX, border);
- let top = Math.max(scrollY + aEvent.clientY - this._offsetY, border);
-
- // Enforce maximum constraints to keep the drag image inside the window.
- left = Math.min(left, scrollX + clientWidth - this.cellWidth - border);
- top = Math.min(top, scrollY + clientHeight - this.cellHeight - border);
-
- // Update the drag image's position.
- gTransformation.setSitePosition(aSite, {left: left, top: top});
- },
-
- /**
- * Ends the current drag operation.
- * @param aSite The site that's being dragged.
- * @param aEvent The 'dragend' event.
- */
- end: function Drag_end(aSite, aEvent) {
- let nodes = gGrid.node.querySelectorAll("[dragged]")
- for (let i = 0; i < nodes.length; i++)
- nodes[i].removeAttribute("dragged");
-
- // Slide the dragged site back into its cell (may be the old or the new cell).
- gTransformation.slideSiteTo(aSite, aSite.cell, {unfreeze: true});
-
- this._draggedSite = null;
- },
-
- /**
- * Checks whether we're responsible for a given drag event.
- * @param aEvent The drag event to check.
- * @return Whether we should handle this drag and drop operation.
- */
- isValid: function Drag_isValid(aEvent) {
- let link = gDragDataHelper.getLinkFromDragEvent(aEvent);
-
- // Check that the drag data is non-empty.
- // Can happen when dragging places folders.
- if (!link || !link.url) {
- return false;
- }
-
- // Check that we're not accepting URLs which would inherit the caller's
- // principal (such as javascript: or data:).
- return gLinkChecker.checkLoadURI(link.url);
- },
-
- /**
- * Initializes the drag data for the current drag operation.
- * @param aSite The site that's being dragged.
- * @param aEvent The 'dragstart' event.
- */
- _setDragData: function Drag_setDragData(aSite, aEvent) {
- let {url, title} = aSite;
-
- let dt = aEvent.dataTransfer;
- dt.mozCursor = "default";
- dt.effectAllowed = "move";
- dt.setData("text/plain", url);
- dt.setData("text/uri-list", url);
- dt.setData("text/x-moz-url", url + "\n" + title);
- dt.setData("text/html", "<a href=\"" + url + "\">" + url + "</a>");
-
- // Create and use an empty drag element. We don't want to use the default
- // drag image with its default opacity.
- let dragElement = document.createElementNS(HTML_NAMESPACE, "div");
- dragElement.classList.add("newtab-drag");
- let scrollbox = document.getElementById("newtab-vertical-margin");
- scrollbox.appendChild(dragElement);
- dt.setDragImage(dragElement, 0, 0);
-
- // After the 'dragstart' event has been processed we can remove the
- // temporary drag element from the DOM.
- setTimeout(() => scrollbox.removeChild(dragElement), 0);
- }
-};
diff --git a/components/newtab/dragDataHelper.js b/components/newtab/dragDataHelper.js
deleted file mode 100644
index 675ff26..0000000
--- a/components/newtab/dragDataHelper.js
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifdef 0
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-#endif
-
-var gDragDataHelper = {
- get mimeType() {
- return "text/x-moz-url";
- },
-
- getLinkFromDragEvent: function DragDataHelper_getLinkFromDragEvent(aEvent) {
- let dt = aEvent.dataTransfer;
- if (!dt || !dt.types.includes(this.mimeType)) {
- return null;
- }
-
- let data = dt.getData(this.mimeType) || "";
- let [url, title] = data.split(/[\r\n]+/);
- return {url: url, title: title};
- }
-};
diff --git a/components/newtab/drop.js b/components/newtab/drop.js
deleted file mode 100644
index 7486524..0000000
--- a/components/newtab/drop.js
+++ /dev/null
@@ -1,150 +0,0 @@
-#ifdef 0
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-#endif
-
-// A little delay that prevents the grid from being too sensitive when dragging
-// sites around.
-const DELAY_REARRANGE_MS = 100;
-
-/**
- * This singleton implements site dropping functionality.
- */
-var gDrop = {
- /**
- * The last drop target.
- */
- _lastDropTarget: null,
-
- /**
- * Handles the 'dragenter' event.
- * @param aCell The drop target cell.
- */
- enter: function Drop_enter(aCell) {
- this._delayedRearrange(aCell);
- },
-
- /**
- * Handles the 'dragexit' event.
- * @param aCell The drop target cell.
- * @param aEvent The 'dragexit' event.
- */
- exit: function Drop_exit(aCell, aEvent) {
- if (aEvent.dataTransfer && !aEvent.dataTransfer.mozUserCancelled) {
- this._delayedRearrange();
- } else {
- // The drag operation has been cancelled.
- this._cancelDelayedArrange();
- this._rearrange();
- }
- },
-
- /**
- * Handles the 'drop' event.
- * @param aCell The drop target cell.
- * @param aEvent The 'dragexit' event.
- */
- drop: function Drop_drop(aCell, aEvent) {
- // The cell that is the drop target could contain a pinned site. We need
- // to find out where that site has gone and re-pin it there.
- if (aCell.containsPinnedSite())
- this._repinSitesAfterDrop(aCell);
-
- // Pin the dragged or insert the new site.
- this._pinDraggedSite(aCell, aEvent);
-
- this._cancelDelayedArrange();
-
- // Update the grid and move all sites to their new places.
- gUpdater.updateGrid();
- },
-
- /**
- * Re-pins all pinned sites in their (new) positions.
- * @param aCell The drop target cell.
- */
- _repinSitesAfterDrop: function Drop_repinSitesAfterDrop(aCell) {
- let sites = gDropPreview.rearrange(aCell);
-
- // Filter out pinned sites.
- let pinnedSites = sites.filter(function (aSite) {
- return aSite && aSite.isPinned();
- });
-
- // Re-pin all shifted pinned cells.
- pinnedSites.forEach(aSite => aSite.pin(sites.indexOf(aSite)));
- },
-
- /**
- * Pins the dragged site in its new place.
- * @param aCell The drop target cell.
- * @param aEvent The 'dragexit' event.
- */
- _pinDraggedSite: function Drop_pinDraggedSite(aCell, aEvent) {
- let index = aCell.index;
- let draggedSite = gDrag.draggedSite;
-
- if (draggedSite) {
- // Pin the dragged site at its new place.
- if (aCell != draggedSite.cell)
- draggedSite.pin(index);
- } else {
- let link = gDragDataHelper.getLinkFromDragEvent(aEvent);
- if (link) {
- // A new link was dragged onto the grid. Create it by pinning its URL.
- gPinnedLinks.pin(link, index);
-
- // Make sure the newly added link is not blocked.
- gBlockedLinks.unblock(link);
- }
- }
- },
-
- /**
- * Time a rearrange with a little delay.
- * @param aCell The drop target cell.
- */
- _delayedRearrange: function Drop_delayedRearrange(aCell) {
- // The last drop target didn't change so there's no need to re-arrange.
- if (this._lastDropTarget == aCell)
- return;
-
- let self = this;
-
- function callback() {
- self._rearrangeTimeout = null;
- self._rearrange(aCell);
- }
-
- this._cancelDelayedArrange();
- this._rearrangeTimeout = setTimeout(callback, DELAY_REARRANGE_MS);
-
- // Store the last drop target.
- this._lastDropTarget = aCell;
- },
-
- /**
- * Cancels a timed rearrange, if any.
- */
- _cancelDelayedArrange: function Drop_cancelDelayedArrange() {
- if (this._rearrangeTimeout) {
- clearTimeout(this._rearrangeTimeout);
- this._rearrangeTimeout = null;
- }
- },
-
- /**
- * Rearrange all sites in the grid depending on the current drop target.
- * @param aCell The drop target cell.
- */
- _rearrange: function Drop_rearrange(aCell) {
- let sites = gGrid.sites;
-
- // We need to rearrange the grid only if there's a current drop target.
- if (aCell)
- sites = gDropPreview.rearrange(aCell);
-
- gTransformation.rearrangeSites(sites, {unfreeze: !aCell});
- }
-};
diff --git a/components/newtab/dropPreview.js b/components/newtab/dropPreview.js
deleted file mode 100644
index fd7587a..0000000
--- a/components/newtab/dropPreview.js
+++ /dev/null
@@ -1,222 +0,0 @@
-#ifdef 0
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-#endif
-
-/**
- * This singleton provides the ability to re-arrange the current grid to
- * indicate the transformation that results from dropping a cell at a certain
- * position.
- */
-var gDropPreview = {
- /**
- * Rearranges the sites currently contained in the grid when a site would be
- * dropped onto the given cell.
- * @param aCell The drop target cell.
- * @return The re-arranged array of sites.
- */
- rearrange: function DropPreview_rearrange(aCell) {
- let sites = gGrid.sites;
-
- // Insert the dragged site into the current grid.
- this._insertDraggedSite(sites, aCell);
-
- // After the new site has been inserted we need to correct the positions
- // of all pinned tabs that have been moved around.
- this._repositionPinnedSites(sites, aCell);
-
- return sites;
- },
-
- /**
- * Inserts the currently dragged site into the given array of sites.
- * @param aSites The array of sites to insert into.
- * @param aCell The drop target cell.
- */
- _insertDraggedSite: function DropPreview_insertDraggedSite(aSites, aCell) {
- let dropIndex = aCell.index;
- let draggedSite = gDrag.draggedSite;
-
- // We're currently dragging a site.
- if (draggedSite) {
- let dragCell = draggedSite.cell;
- let dragIndex = dragCell.index;
-
- // Move the dragged site into its new position.
- if (dragIndex != dropIndex) {
- aSites.splice(dragIndex, 1);
- aSites.splice(dropIndex, 0, draggedSite);
- }
- // We're handling an external drag item.
- } else {
- aSites.splice(dropIndex, 0, null);
- }
- },
-
- /**
- * Correct the position of all pinned sites that might have been moved to
- * different positions after the dragged site has been inserted.
- * @param aSites The array of sites containing the dragged site.
- * @param aCell The drop target cell.
- */
- _repositionPinnedSites:
- function DropPreview_repositionPinnedSites(aSites, aCell) {
-
- // Collect all pinned sites.
- let pinnedSites = this._filterPinnedSites(aSites, aCell);
-
- // Correct pinned site positions.
- pinnedSites.forEach(function (aSite) {
- aSites[aSites.indexOf(aSite)] = aSites[aSite.cell.index];
- aSites[aSite.cell.index] = aSite;
- }, this);
-
- // There might be a pinned cell that got pushed out of the grid, try to
- // sneak it in by removing a lower-priority cell.
- if (this._hasOverflowedPinnedSite(aSites, aCell))
- this._repositionOverflowedPinnedSite(aSites, aCell);
- },
-
- /**
- * Filter pinned sites out of the grid that are still on their old positions
- * and have not moved.
- * @param aSites The array of sites to filter.
- * @param aCell The drop target cell.
- * @return The filtered array of sites.
- */
- _filterPinnedSites: function DropPreview_filterPinnedSites(aSites, aCell) {
- let draggedSite = gDrag.draggedSite;
-
- // When dropping on a cell that contains a pinned site make sure that all
- // pinned cells surrounding the drop target are moved as well.
- let range = this._getPinnedRange(aCell);
-
- return aSites.filter(function (aSite, aIndex) {
- // The site must be valid, pinned and not the dragged site.
- if (!aSite || aSite == draggedSite || !aSite.isPinned())
- return false;
-
- let index = aSite.cell.index;
-
- // If it's not in the 'pinned range' it's a valid pinned site.
- return (index > range.end || index < range.start);
- });
- },
-
- /**
- * Determines the range of pinned sites surrounding the drop target cell.
- * @param aCell The drop target cell.
- * @return The range of pinned cells.
- */
- _getPinnedRange: function DropPreview_getPinnedRange(aCell) {
- let dropIndex = aCell.index;
- let range = {start: dropIndex, end: dropIndex};
-
- // We need a pinned range only when dropping on a pinned site.
- if (aCell.containsPinnedSite()) {
- let links = gPinnedLinks.links;
-
- // Find all previous siblings of the drop target that are pinned as well.
- while (range.start && links[range.start - 1])
- range.start--;
-
- let maxEnd = links.length - 1;
-
- // Find all next siblings of the drop target that are pinned as well.
- while (range.end < maxEnd && links[range.end + 1])
- range.end++;
- }
-
- return range;
- },
-
- /**
- * Checks if the given array of sites contains a pinned site that has
- * been pushed out of the grid.
- * @param aSites The array of sites to check.
- * @param aCell The drop target cell.
- * @return Whether there is an overflowed pinned cell.
- */
- _hasOverflowedPinnedSite:
- function DropPreview_hasOverflowedPinnedSite(aSites, aCell) {
-
- // If the drop target isn't pinned there's no way a pinned site has been
- // pushed out of the grid so we can just exit here.
- if (!aCell.containsPinnedSite())
- return false;
-
- let cells = gGrid.cells;
-
- // No cells have been pushed out of the grid, nothing to do here.
- if (aSites.length <= cells.length)
- return false;
-
- let overflowedSite = aSites[cells.length];
-
- // Nothing to do if the site that got pushed out of the grid is not pinned.
- return (overflowedSite && overflowedSite.isPinned());
- },
-
- /**
- * We have a overflowed pinned site that we need to re-position so that it's
- * visible again. We try to find a lower-priority cell (empty or containing
- * an unpinned site) that we can move it to.
- * @param aSites The array of sites.
- * @param aCell The drop target cell.
- */
- _repositionOverflowedPinnedSite:
- function DropPreview_repositionOverflowedPinnedSite(aSites, aCell) {
-
- // Try to find a lower-priority cell (empty or containing an unpinned site).
- let index = this._indexOfLowerPrioritySite(aSites, aCell);
-
- if (index > -1) {
- let cells = gGrid.cells;
- let dropIndex = aCell.index;
-
- // Move all pinned cells to their new positions to let the overflowed
- // site fit into the grid.
- for (let i = index + 1, lastPosition = index; i < aSites.length; i++) {
- if (i != dropIndex) {
- aSites[lastPosition] = aSites[i];
- lastPosition = i;
- }
- }
-
- // Finally, remove the overflowed site from its previous position.
- aSites.splice(cells.length, 1);
- }
- },
-
- /**
- * Finds the index of the last cell that is empty or contains an unpinned
- * site. These are considered to be of a lower priority.
- * @param aSites The array of sites.
- * @param aCell The drop target cell.
- * @return The cell's index.
- */
- _indexOfLowerPrioritySite:
- function DropPreview_indexOfLowerPrioritySite(aSites, aCell) {
-
- let cells = gGrid.cells;
- let dropIndex = aCell.index;
-
- // Search (beginning with the last site in the grid) for a site that is
- // empty or unpinned (an thus lower-priority) and can be pushed out of the
- // grid instead of the pinned site.
- for (let i = cells.length - 1; i >= 0; i--) {
- // The cell that is our drop target is not a good choice.
- if (i == dropIndex)
- continue;
-
- let site = aSites[i];
-
- // We can use the cell only if it's empty or the site is un-pinned.
- if (!site || !site.isPinned())
- return i;
- }
-
- return -1;
- }
-};
diff --git a/components/newtab/dropTargetShim.js b/components/newtab/dropTargetShim.js
deleted file mode 100644
index 57a97fa..0000000
--- a/components/newtab/dropTargetShim.js
+++ /dev/null
@@ -1,232 +0,0 @@
-#ifdef 0
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-#endif
-
-/**
- * This singleton provides a custom drop target detection. We need this because
- * the default DnD target detection relies on the cursor's position. We want
- * to pick a drop target based on the dragged site's position.
- */
-var gDropTargetShim = {
- /**
- * Cache for the position of all cells, cleaned after drag finished.
- */
- _cellPositions: null,
-
- /**
- * The last drop target that was hovered.
- */
- _lastDropTarget: null,
-
- /**
- * Initializes the drop target shim.
- */
- init: function () {
- gGrid.node.addEventListener("dragstart", this, true);
- },
-
- /**
- * Add all event listeners needed during a drag operation.
- */
- _addEventListeners: function () {
- gGrid.node.addEventListener("dragend", this);
-
- let docElement = document.documentElement;
- docElement.addEventListener("dragover", this);
- docElement.addEventListener("dragenter", this);
- docElement.addEventListener("drop", this);
- },
-
- /**
- * Remove all event listeners that were needed during a drag operation.
- */
- _removeEventListeners: function () {
- gGrid.node.removeEventListener("dragend", this);
-
- let docElement = document.documentElement;
- docElement.removeEventListener("dragover", this);
- docElement.removeEventListener("dragenter", this);
- docElement.removeEventListener("drop", this);
- },
-
- /**
- * Handles all shim events.
- */
- handleEvent: function (aEvent) {
- switch (aEvent.type) {
- case "dragstart":
- this._dragstart(aEvent);
- break;
- case "dragenter":
- aEvent.preventDefault();
- break;
- case "dragover":
- this._dragover(aEvent);
- break;
- case "drop":
- this._drop(aEvent);
- break;
- case "dragend":
- this._dragend(aEvent);
- break;
- }
- },
-
- /**
- * Handles the 'dragstart' event.
- * @param aEvent The 'dragstart' event.
- */
- _dragstart: function (aEvent) {
- if (aEvent.target.classList.contains("newtab-link")) {
- gGrid.lock();
- this._addEventListeners();
- }
- },
-
- /**
- * Handles the 'dragover' event.
- * @param aEvent The 'dragover' event.
- */
- _dragover: function (aEvent) {
- // XXX bug 505521 - Use the dragover event to retrieve the
- // current mouse coordinates while dragging.
- let sourceNode = aEvent.dataTransfer.mozSourceNode.parentNode;
- gDrag.drag(sourceNode._newtabSite, aEvent);
-
- // Find the current drop target, if there's one.
- this._updateDropTarget(aEvent);
-
- // If we have a valid drop target,
- // let the drag-and-drop service know.
- if (this._lastDropTarget) {
- aEvent.preventDefault();
- }
- },
-
- /**
- * Handles the 'drop' event.
- * @param aEvent The 'drop' event.
- */
- _drop: function (aEvent) {
- // We're accepting all drops.
- aEvent.preventDefault();
-
- // remember that drop event was seen, this explicitly
- // assumes that drop event preceeds dragend event
- this._dropSeen = true;
-
- // Make sure to determine the current drop target
- // in case the dragover event hasn't been fired.
- this._updateDropTarget(aEvent);
-
- // A site was successfully dropped.
- this._dispatchEvent(aEvent, "drop", this._lastDropTarget);
- },
-
- /**
- * Handles the 'dragend' event.
- * @param aEvent The 'dragend' event.
- */
- _dragend: function (aEvent) {
- if (this._lastDropTarget) {
- if (aEvent.dataTransfer.mozUserCancelled || !this._dropSeen) {
- // The drag operation was cancelled or no drop event was generated
- this._dispatchEvent(aEvent, "dragexit", this._lastDropTarget);
- this._dispatchEvent(aEvent, "dragleave", this._lastDropTarget);
- }
-
- // Clean up.
- this._lastDropTarget = null;
- this._cellPositions = null;
- }
-
- this._dropSeen = false;
- gGrid.unlock();
- this._removeEventListeners();
- },
-
- /**
- * Tries to find the current drop target and will fire
- * appropriate dragenter, dragexit, and dragleave events.
- * @param aEvent The current drag event.
- */
- _updateDropTarget: function (aEvent) {
- // Let's see if we find a drop target.
- let target = this._findDropTarget(aEvent);
-
- if (target != this._lastDropTarget) {
- if (this._lastDropTarget)
- // We left the last drop target.
- this._dispatchEvent(aEvent, "dragexit", this._lastDropTarget);
-
- if (target)
- // We're now hovering a (new) drop target.
- this._dispatchEvent(aEvent, "dragenter", target);
-
- if (this._lastDropTarget)
- // We left the last drop target.
- this._dispatchEvent(aEvent, "dragleave", this._lastDropTarget);
-
- this._lastDropTarget = target;
- }
- },
-
- /**
- * Determines the current drop target by matching the dragged site's position
- * against all cells in the grid.
- * @return The currently hovered drop target or null.
- */
- _findDropTarget: function () {
- // These are the minimum intersection values - we want to use the cell if
- // the site is >= 50% hovering its position.
- let minWidth = gDrag.cellWidth / 2;
- let minHeight = gDrag.cellHeight / 2;
-
- let cellPositions = this._getCellPositions();
- let rect = gTransformation.getNodePosition(gDrag.draggedSite.node);
-
- // Compare each cell's position to the dragged site's position.
- for (let i = 0; i < cellPositions.length; i++) {
- let inter = rect.intersect(cellPositions[i].rect);
-
- // If the intersection is big enough we found a drop target.
- if (inter.width >= minWidth && inter.height >= minHeight)
- return cellPositions[i].cell;
- }
-
- // No drop target found.
- return null;
- },
-
- /**
- * Gets the positions of all cell nodes.
- * @return The (cached) cell positions.
- */
- _getCellPositions: function DropTargetShim_getCellPositions() {
- if (this._cellPositions)
- return this._cellPositions;
-
- return this._cellPositions = gGrid.cells.map(function (cell) {
- return {cell: cell, rect: gTransformation.getNodePosition(cell.node)};
- });
- },
-
- /**
- * Dispatches a custom DragEvent on the given target node.
- * @param aEvent The source event.
- * @param aType The event type.
- * @param aTarget The target node that receives the event.
- */
- _dispatchEvent: function (aEvent, aType, aTarget) {
- let node = aTarget.node;
- let event = document.createEvent("DragEvent");
-
- // The event should not bubble to prevent recursion.
- event.initDragEvent(aType, false, true, window, 0, 0, 0, 0, 0, false, false,
- false, false, 0, node, aEvent.dataTransfer);
-
- node.dispatchEvent(event);
- }
-};
diff --git a/components/newtab/grid.js b/components/newtab/grid.js
deleted file mode 100644
index e63ea54..0000000
--- a/components/newtab/grid.js
+++ /dev/null
@@ -1,175 +0,0 @@
-#ifdef 0
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-#endif
-
-/**
- * This singleton represents the grid that contains all sites.
- */
-var gGrid = {
- /**
- * The DOM node of the grid.
- */
- _node: null,
- _gridDefaultContent: null,
- get node() { return this._node; },
-
- /**
- * The cached DOM fragment for sites.
- */
- _siteFragment: null,
-
- /**
- * All cells contained in the grid.
- */
- _cells: [],
- get cells() { return this._cells; },
-
- /**
- * All sites contained in the grid's cells. Sites may be empty.
- */
- get sites() {
- // return [for (cell of this.cells) cell.site];
- let aSites = [];
- for (let cell of this.cells) {
- aSites.push(cell.site);
- }
- return aSites;
- },
-
- // Tells whether the grid has already been initialized.
- get ready() { return !!this._ready; },
-
- // Returns whether the page has finished loading yet.
- get isDocumentLoaded() { return document.readyState == "complete"; },
-
- /**
- * Initializes the grid.
- * @param aSelector The query selector of the grid.
- */
- init: function Grid_init() {
- this._node = document.getElementById("newtab-grid");
- this._gridDefaultContent = this._node.lastChild;
- this._createSiteFragment();
-
- gLinks.populateCache(() => {
- this._refreshGrid();
- this._ready = true;
- });
- },
-
- /**
- * Creates a new site in the grid.
- * @param aLink The new site's link.
- * @param aCell The cell that will contain the new site.
- * @return The newly created site.
- */
- createSite: function Grid_createSite(aLink, aCell) {
- let node = aCell.node;
- node.appendChild(this._siteFragment.cloneNode(true));
- return new Site(node.firstElementChild, aLink);
- },
-
- /**
- * Handles all grid events.
- */
- handleEvent: function Grid_handleEvent(aEvent) {
- // Any specific events should go here.
- },
-
- /**
- * Locks the grid to block all pointer events.
- */
- lock: function Grid_lock() {
- this.node.setAttribute("locked", "true");
- },
-
- /**
- * Unlocks the grid to allow all pointer events.
- */
- unlock: function Grid_unlock() {
- this.node.removeAttribute("locked");
- },
-
- /**
- * Renders the grid.
- */
- refresh() {
- this._refreshGrid();
- },
-
- /**
- * Renders the grid, including cells and sites.
- */
- _refreshGrid() {
- let row = document.createElementNS(HTML_NAMESPACE, "div");
- row.classList.add("newtab-row");
- let cell = document.createElementNS(HTML_NAMESPACE, "div");
- cell.classList.add("newtab-cell");
-
- // Clear the grid
- this._node.innerHTML = "";
-
- // Creates the structure of one row
- for (let i = 0; i < gGridPrefs.gridColumns; i++) {
- row.appendChild(cell.cloneNode(true));
- }
-
- // Creates the grid
- for (let j = 0; j < gGridPrefs.gridRows; j++) {
- this._node.appendChild(row.cloneNode(true));
- }
-
- // Create cell array.
- let cellElements = this.node.querySelectorAll(".newtab-cell");
- let cells = Array.from(cellElements, (cell) => new Cell(this, cell));
-
- // Fetch links.
- let links = gLinks.getLinks();
-
- // Create sites.
- let numLinks = Math.min(links.length, cells.length);
- for (let i = 0; i < numLinks; i++) {
- if (links[i]) {
- this.createSite(links[i], cells[i]);
- }
- }
-
- this._cells = cells;
- },
-
- /**
- * Creates the DOM fragment that is re-used when creating sites.
- */
- _createSiteFragment: function Grid_createSiteFragment() {
- let site = document.createElementNS(HTML_NAMESPACE, "div");
- site.classList.add("newtab-site");
- site.setAttribute("draggable", "true");
-
- // Create the site's inner HTML code.
- site.innerHTML =
- '<a class="newtab-link">' +
- ' <span class="newtab-thumbnail placeholder"/>' +
- ' <span class="newtab-thumbnail thumbnail"/>' +
- ' <span class="newtab-title"/>' +
- '</a>' +
- '<input type="button" title="' + newTabString("pin") + '"' +
- ' class="newtab-control newtab-control-pin"/>' +
- '<input type="button" title="' + newTabString("block") + '"' +
- ' class="newtab-control newtab-control-block"/>';
-
- this._siteFragment = document.createDocumentFragment();
- this._siteFragment.appendChild(site);
- },
-
- /**
- * Test a tile at a given position for being pinned or history
- * @param position Position in sites array
- */
- _isHistoricalTile: function Grid_isHistoricalTile(aPos) {
- let site = this.sites[aPos];
- return site && (site.isPinned() || site.link && site.link.type == "history");
- }
-
-};
diff --git a/components/newtab/jar.mn b/components/newtab/jar.mn
deleted file mode 100644
index 2d62914..0000000
--- a/components/newtab/jar.mn
+++ /dev/null
@@ -1,8 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-browser.jar:
- content/browser/newtab/newTab.xhtml
-* content/browser/newtab/newTab.js
- content/browser/newtab/newTab.css \ No newline at end of file
diff --git a/components/newtab/moz.build b/components/newtab/moz.build
deleted file mode 100644
index 2d64d50..0000000
--- a/components/newtab/moz.build
+++ /dev/null
@@ -1,8 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-JAR_MANIFESTS += ['jar.mn']
-
diff --git a/components/newtab/newTab.css b/components/newtab/newTab.css
deleted file mode 100644
index 3c7cfa1..0000000
--- a/components/newtab/newTab.css
+++ /dev/null
@@ -1,349 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-html {
- width: 100%;
- height: 100%;
-}
-
-body {
- font: message-box;
- width: 100%;
- height: 100%;
- padding: 0;
- margin: 0;
- background-color: #F9F9F9;
- display: -moz-box;
- position: relative;
- -moz-box-flex: 1;
- -moz-user-focus: normal;
- -moz-box-orient: vertical;
-}
-
-input {
- font: message-box;
- font-size: 16px;
-}
-
-input[type=button] {
- cursor: pointer;
-}
-
-/* UNDO */
-#newtab-undo-container {
- transition: opacity 100ms ease-out;
- -moz-box-align: center;
- -moz-box-pack: center;
-}
-
-#newtab-undo-container[undo-disabled] {
- opacity: 0;
- pointer-events: none;
-}
-
-/* TOGGLE */
-#newtab-toggle {
- position: absolute;
- top: 12px;
- right: 12px;
-}
-
-#newtab-toggle:-moz-locale-dir(rtl) {
- left: 12px;
- right: auto;
-}
-
-/* MARGINS */
-#newtab-vertical-margin {
- display: -moz-box;
- position: relative;
- -moz-box-flex: 1;
- -moz-box-orient: vertical;
-}
-
-#newtab-margin-undo-container {
- display: -moz-box;
- left: 6px;
- position: absolute;
- top: 6px;
- z-index: 1;
-}
-
-#newtab-margin-undo-container:dir(rtl) {
- left: auto;
- right: 6px;
-}
-
-#newtab-undo-close-button:dir(rtl) {
- float:left;
-}
-
-#newtab-horizontal-margin {
- display: -moz-box;
- -moz-box-flex: 5;
-}
-
-#newtab-margin-top {
- min-height: 10px;
- max-height: 30px;
- display: -moz-box;
- -moz-box-flex: 1;
- -moz-box-align: center;
- -moz-box-pack: center;
-}
-
-#newtab-margin-bottom {
- min-height: 40px;
- max-height: 80px;
- -moz-box-flex: 1;
-}
-
-.newtab-side-margin {
- min-width: 40px;
- max-width: 300px;
- -moz-box-flex: 1;
-}
-
-/* GRID */
-#newtab-grid {
- display: -moz-box;
- -moz-box-flex: 5;
- -moz-box-orient: vertical;
- min-width: 600px;
- min-height: 400px;
- transition: 175ms ease-out;
- transition-property: opacity;
-}
-
-#newtab-grid[page-disabled] {
- opacity: 0;
-}
-
-#newtab-grid[locked],
-#newtab-grid[page-disabled] {
- pointer-events: none;
-}
-
-/* ROWS */
-.newtab-row {
- display: -moz-box;
- -moz-box-orient: horizontal;
- -moz-box-direction: normal;
- -moz-box-flex: 1;
-}
-
-/*
- * Thumbnail image sizes are determined in the preferences:
- * toolkit.pageThumbs.minWidth
- * toolkit.pageThumbs.minHeight
- */
-/* CELLS */
-.newtab-cell {
- display: -moz-box;
- -moz-box-flex: 1;
-}
-
-/* SITES */
-.newtab-site {
- position: relative;
- -moz-box-flex: 1;
- transition: 150ms ease-out;
- transition-property: top, left, opacity;
-}
-
-.newtab-site[frozen] {
- position: absolute;
- pointer-events: none;
-}
-
-.newtab-site[dragged] {
- transition-property: none;
- z-index: 10;
-}
-
-/* LINK + THUMBNAILS */
-.newtab-link,
-.newtab-thumbnail {
- position: absolute;
- left: 0;
- top: 0;
- right: 0;
- bottom: 0;
-}
-
-/* TITLES */
-.newtab-title {
- overflow: hidden;
- position: absolute;
- right: 0;
- text-align: center;
-}
-
-.newtab-title {
- bottom: 0;
- white-space: nowrap;
- text-overflow: ellipsis;
- vertical-align: middle;
-}
-
-.newtab-title {
- left: 0;
- padding: 0 4px;
-}
-
-/* CONTROLS */
-.newtab-control {
- position: absolute;
- opacity: 0;
- transition: opacity 100ms ease-out;
-}
-
-.newtab-control:-moz-focusring,
-.newtab-cell:not([ignorehover]) > .newtab-site:hover > .newtab-control {
- opacity: 1;
-}
-
-.newtab-control[dragged] {
- opacity: 0 !important;
-}
-
-@media (-moz-touch-enabled) {
- .newtab-control {
- opacity: 1;
- }
-}
-
-/* DRAG & DROP */
-
-/*
- * This is just a temporary drag element used for dataTransfer.setDragImage()
- * so that we can use custom drag images and elements. It needs an opacity of
- * 0.01 so that the core code detects that it's in fact a visible element.
- */
-.newtab-drag {
- width: 1px;
- height: 1px;
- background-color: #fff;
- opacity: 0.01;
-}
-
-/* SEARCH */
-#searchContainer {
- display: -moz-box;
- position: relative;
- -moz-box-pack: center;
- margin: 10px 0 15px;
-}
-
-#searchContainer[page-disabled] {
- opacity: 0;
- pointer-events: none;
-}
-
-#searchForm {
- display: -moz-box;
- position: relative;
- height: 36px;
- -moz-box-flex: 1;
- max-width: 600px; /* 2 * (290 cell width + 10 cell margin) */
-}
-
-#searchEngineLogo {
- border: 1px transparent;
- padding: 2px 4px;
- margin: 0;
- width: 32px;
- height: 32px;
- position: absolute;
-}
-
-#searchText {
- -moz-box-flex: 1;
- padding-top: 6px;
- padding-bottom: 6px;
- padding-inline-start: 42px;
- padding-inline-end: 8px;
- background: hsla(0,0%,100%,.9) padding-box;
- border: 1px solid;
- border-spacing: 0;
- border-radius: 2px 0 0 2px;
- border-color: hsla(210,54%,20%,.15) hsla(210,54%,20%,.17) hsla(210,54%,20%,.2);
- box-shadow: 0 1px 0 hsla(210,65%,9%,.02) inset,
- 0 0 2px hsla(210,65%,9%,.1) inset,
- 0 1px 0 hsla(0,0%,100%,.2);
- color: inherit;
- unicode-bidi: plaintext;
-}
-
-#searchText:dir(rtl) {
- border-radius: 0 2px 2px 0;
-}
-
-#searchText[aria-expanded="true"] {
- border-radius: 2px 0 0 0;
-}
-
-#searchText[aria-expanded="true"]:dir(rtl) {
- border-radius: 0 2px 0 0;
-}
-
-#searchText[keepfocus],
-#searchText:focus {
- border-color: hsla(216,100%,60%,.6) hsla(216,76%,52%,.6) hsla(214,100%,40%,.6);
-}
-
-#searchSubmit {
- margin-inline-start: -1px;
- padding: 0;
- border: 1px solid;
- background-color: #e0e0e0;
- color: black;
- border-color: hsla(220,54%,20%,.15) hsla(220,54%,20%,.17) hsla(220,54%,20%,.2);
- border-radius: 0 2px 2px 0;
- box-shadow: 0 0 2px hsla(0,0%,100%,.5) inset,
- 0 1px 0 hsla(0,0%,100%,.2);
- cursor: pointer;
- transition-property: background-color, border-color, box-shadow;
- transition-duration: 150ms;
- width: 50px;
-}
-
-#searchSubmit:dir(rtl) {
- border-radius: 2px 0 0 2px;
-}
-
-#searchSubmit:hover {
- background-color: hsl(220,54%,20%);
- color: white;
-}
-
-#searchText:focus + #searchSubmit,
-#searchText + #searchSubmit:hover {
- border-color: #5985fc #4573e7 #3264d5;
-}
-
-#searchText:focus + #searchSubmit,
-#searchText[keepfocus] + #searchSubmit {
- box-shadow: 0 1px 0 hsla(0,0%,100%,.2) inset,
- 0 0 0 1px hsla(0,0%,100%,.1) inset,
- 0 1px 0 hsla(220,54%,20%,.03);
-}
-
-#searchText + #searchSubmit:hover {
- box-shadow: 0 1px 0 hsla(0,0%,100%,.2) inset,
- 0 0 0 1px hsla(0,0%,100%,.1) inset,
- 0 1px 0 hsla(220,54%,20%,.03),
- 0 0 4px hsla(216,100%,20%,.2);
-}
-
-#searchText + #searchSubmit:hover:active {
- box-shadow: 0 1px 1px hsla(221,79%,6%,.1) inset,
- 0 0 1px hsla(221,79%,6%,.2) inset;
- transition-duration: 0ms;
-}
-
-.contentSearchSuggestionTable {
- font: message-box;
- font-size: 16px;
-}
diff --git a/components/newtab/newTab.js b/components/newtab/newTab.js
deleted file mode 100644
index 0022f21..0000000
--- a/components/newtab/newTab.js
+++ /dev/null
@@ -1,69 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-var Cu = Components.utils;
-var Ci = Components.interfaces;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/PageThumbs.jsm");
-Cu.import("resource://gre/modules/BackgroundPageThumbs.jsm");
-Cu.import("resource://gre/modules/NewTabUtils.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "Rect",
- "resource://gre/modules/Geometry.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
- "resource://gre/modules/PrivateBrowsingUtils.jsm");
-
-var {
- links: gLinks,
- allPages: gAllPages,
- linkChecker: gLinkChecker,
- pinnedLinks: gPinnedLinks,
- blockedLinks: gBlockedLinks,
- gridPrefs: gGridPrefs
-} = NewTabUtils;
-
-XPCOMUtils.defineLazyGetter(this, "gStringBundle", function() {
- return Services.strings.
- createBundle("chrome://browser/locale/newTab.properties");
-});
-
-function newTabString(name, args) {
- let stringName = "newtab." + name;
- if (!args) {
- return gStringBundle.GetStringFromName(stringName);
- }
- return gStringBundle.formatStringFromName(stringName, args, args.length);
-}
-
-function inPrivateBrowsingMode() {
- return PrivateBrowsingUtils.isContentWindowPrivate(window);
-}
-
-const HTML_NAMESPACE = "http://www.w3.org/1999/xhtml";
-const XUL_NAMESPACE = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
-
-const TILES_EXPLAIN_LINK = "https://support.mozilla.org/kb/how-do-tiles-work-firefox";
-const TILES_INTRO_LINK = "https://www.mozilla.org/firefox/tiles/";
-const TILES_PRIVACY_LINK = "https://www.mozilla.org/privacy/";
-
-#include transformations.js
-#include page.js
-#include grid.js
-#include cells.js
-#include sites.js
-#include drag.js
-#include dragDataHelper.js
-#include drop.js
-#include dropTargetShim.js
-#include dropPreview.js
-#include updater.js
-#include undo.js
-#include search.js
-
-// Everything is loaded. Initialize the New Tab Page.
-gPage.init();
diff --git a/components/newtab/newTab.xhtml b/components/newtab/newTab.xhtml
deleted file mode 100644
index de000e7..0000000
--- a/components/newtab/newTab.xhtml
+++ /dev/null
@@ -1,61 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!DOCTYPE html [
- <!ENTITY % newTabDTD SYSTEM "chrome://browser/locale/newTab.dtd">
- %newTabDTD;
- <!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd">
- %browserDTD;
- <!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd">
- %globalDTD;
-]>
-
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
- <title>&newtab.pageTitle;</title>
-
- <link rel="stylesheet" type="text/css" media="all" href="chrome://global/skin/" />
- <link rel="stylesheet" type="text/css" media="all" href="chrome://browser/content/newtab/newTab.css" />
- <link rel="stylesheet" type="text/css" media="all" href="chrome://browser/skin/newtab/newTab.css" />
-</head>
-
-<body dir="&locale.dir;">
- <div id="newtab-vertical-margin">
- <div id="newtab-margin-top"/>
-
- <div id="newtab-margin-undo-container">
- <div id="newtab-undo-container" undo-disabled="true">
- <label id="newtab-undo-label">&newtab.undo.removedLabel;</label>
- <button id="newtab-undo-button" tabindex="-1"
- class="newtab-undo-button">&newtab.undo.undoButton;</button>
- <button id="newtab-undo-restore-button" tabindex="-1"
- class="newtab-undo-button">&newtab.undo.restoreButton;</button>
- <button id="newtab-undo-close-button" tabindex="-1" title="&newtab.undo.closeTooltip;"/>
- </div>
- </div>
-
- <div id="searchContainer">
- <form name="searchForm" id="searchForm" onsubmit="onSearchSubmit(event)">
- <div id="searchLogoContainer"><img id="searchEngineLogo"/></div>
- <input type="text" name="q" value="" id="searchText" maxlength="256"/>
- <input id="searchSubmit" type="submit" value="&newtab.searchEngineButton.label;"/>
- </form>
- </div>
-
- <div id="newtab-horizontal-margin">
- <div class="newtab-side-margin"/>
- <div id="newtab-grid">
- <!-- site grid -->
- </div>
- <div class="newtab-side-margin"/>
- </div>
-
- <div id="newtab-margin-bottom"/>
- <input id="newtab-toggle" type="button"/>
- </div>
-</body>
-<script type="text/javascript;version=1.8" src="chrome://browser/content/newtab/newTab.js"/>
-</html>
diff --git a/components/newtab/page.js b/components/newtab/page.js
deleted file mode 100644
index 34387fd..0000000
--- a/components/newtab/page.js
+++ /dev/null
@@ -1,244 +0,0 @@
-#ifdef 0
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-#endif
-
-// The amount of time we wait while coalescing updates for hidden pages.
-const SCHEDULE_UPDATE_TIMEOUT_MS = 1000;
-
-/**
- * This singleton represents the whole 'New Tab Page' and takes care of
- * initializing all its components.
- */
-var gPage = {
- /**
- * Initializes the page.
- */
- init: function Page_init() {
- // Add ourselves to the list of pages to receive notifications.
- gAllPages.register(this);
-
- // Listen for 'unload' to unregister this page.
- addEventListener("unload", this, false);
-
- // Listen for toggle button clicks.
- let button = document.getElementById("newtab-toggle");
- button.addEventListener("click", e => this.toggleEnabled(e));
-
- // XXX bug 991111 - Not all click events are correctly triggered when
- // listening from xhtml nodes -- in particular middle clicks on sites, so
- // listen from the xul window and filter then delegate
- addEventListener("click", this, false);
-
- // Check if the new tab feature is enabled.
- let enabled = gAllPages.enabled;
- if (enabled)
- this._init();
-
- this._updateAttributes(enabled);
- },
-
- /**
- * Listens for notifications specific to this page.
- */
- observe: function Page_observe(aSubject, aTopic, aData) {
- if (aTopic == "nsPref:changed") {
- let enabled = gAllPages.enabled;
- this._updateAttributes(enabled);
-
- // Initialize the whole page if we haven't done that, yet.
- if (enabled) {
- this._init();
- } else {
- gUndoDialog.hide();
- }
- } else if (aTopic == "page-thumbnail:create" && gGrid.ready) {
- for (let site of gGrid.sites) {
- if (site && site.url === aData) {
- site.refreshThumbnail();
- }
- }
- }
- },
-
- /**
- * Updates the page's grid right away for visible pages. If the page is
- * currently hidden, i.e. in a background tab or in the preloader, then we
- * batch multiple update requests and refresh the grid once after a short
- * delay. Accepts a single parameter the specifies the reason for requesting
- * a page update. The page may decide to delay or prevent a requested updated
- * based on the given reason.
- */
- update(reason = "") {
- // Update immediately if we're visible.
- if (!document.hidden) {
- // Ignore updates where reason=links-changed as those signal that the
- // provider's set of links changed. We don't want to update visible pages
- // in that case, it is ok to wait until the user opens the next tab.
- if (reason != "links-changed" && gGrid.ready) {
- gGrid.refresh();
- }
-
- return;
- }
-
- // Bail out if we scheduled before.
- if (this._scheduleUpdateTimeout) {
- return;
- }
-
- this._scheduleUpdateTimeout = setTimeout(() => {
- // Refresh if the grid is ready.
- if (gGrid.ready) {
- gGrid.refresh();
- }
-
- this._scheduleUpdateTimeout = null;
- }, SCHEDULE_UPDATE_TIMEOUT_MS);
- },
-
- /**
- * Internally initializes the page. This runs only when/if the feature
- * is/gets enabled.
- */
- _init: function Page_init() {
- if (this._initialized)
- return;
-
- this._initialized = true;
-
- // Set submit button label for when CSS background are disabled (e.g.
- // high contrast mode).
- document.getElementById("searchSubmit").value =
- document.body.getAttribute("dir") == "ltr" ? "\u25B6" : "\u25C0";
-
- if (document.hidden) {
- addEventListener("visibilitychange", this);
- } else {
- setTimeout(() => this.onPageFirstVisible());
- }
-
- // Initialize and render the grid.
- gGrid.init();
-
- // Initialize the drop target shim.
- gDropTargetShim.init();
-
-#ifdef XP_MACOSX
- // Workaround to prevent a delay on MacOSX due to a slow drop animation.
- document.addEventListener("dragover", this, false);
- document.addEventListener("drop", this, false);
-#endif
- },
-
- /**
- * Updates the 'page-disabled' attributes of the respective DOM nodes.
- * @param aValue Whether the New Tab Page is enabled or not.
- */
- _updateAttributes: function Page_updateAttributes(aValue) {
- // Set the nodes' states.
- let nodeSelector = "#newtab-grid, #searchContainer";
- for (let node of document.querySelectorAll(nodeSelector)) {
- if (aValue)
- node.removeAttribute("page-disabled");
- else
- node.setAttribute("page-disabled", "true");
- }
-
- // Enables/disables the control and link elements.
- let inputSelector = ".newtab-control, .newtab-link";
- for (let input of document.querySelectorAll(inputSelector)) {
- if (aValue)
- input.removeAttribute("tabindex");
- else
- input.setAttribute("tabindex", "-1");
- }
- },
-
- /**
- * Handles unload event
- */
- _handleUnloadEvent: function Page_handleUnloadEvent() {
- gAllPages.unregister(this);
- },
-
- /**
- * Handles all page events.
- */
- handleEvent: function Page_handleEvent(aEvent) {
- switch (aEvent.type) {
- case "load":
- this.onPageVisibleAndLoaded();
- break;
- case "unload":
- this._handleUnloadEvent();
- break;
- case "click":
- let {button, target} = aEvent;
- // Go up ancestors until we find a Site or not
- while (target) {
- if (target.hasOwnProperty("_newtabSite")) {
- target._newtabSite.onClick(aEvent);
- break;
- }
- target = target.parentNode;
- }
- break;
- case "dragover":
- if (gDrag.isValid(aEvent) && gDrag.draggedSite)
- aEvent.preventDefault();
- break;
- case "drop":
- if (gDrag.isValid(aEvent) && gDrag.draggedSite) {
- aEvent.preventDefault();
- aEvent.stopPropagation();
- }
- break;
- case "visibilitychange":
- // Cancel any delayed updates for hidden pages now that we're visible.
- if (this._scheduleUpdateTimeout) {
- clearTimeout(this._scheduleUpdateTimeout);
- this._scheduleUpdateTimeout = null;
-
- // An update was pending so force an update now.
- this.update();
- }
-
- setTimeout(() => this.onPageFirstVisible());
- removeEventListener("visibilitychange", this);
- break;
- }
- },
-
- onPageFirstVisible: function () {
- // Record another page impression.
- Services.telemetry.getHistogramById("NEWTAB_PAGE_SHOWN").add(true);
-
- for (let site of gGrid.sites) {
- if (site) {
- // The site may need to modify and/or re-render itself if
- // something changed after newtab was created by preloader.
- // For example, the suggested tile endTime may have passed.
- site.onFirstVisible();
- }
- }
-
- // save timestamp to compute page life-span delta
- this._firstVisibleTime = Date.now();
-
- if (document.readyState == "complete") {
- this.onPageVisibleAndLoaded();
- } else {
- addEventListener("load", this);
- }
- },
-
- onPageVisibleAndLoaded() {
- },
-
- toggleEnabled: function(aEvent) {
- gAllPages.enabled = !gAllPages.enabled;
- aEvent.stopPropagation();
- }
-};
diff --git a/components/newtab/search.js b/components/newtab/search.js
deleted file mode 100644
index 8bc959e..0000000
--- a/components/newtab/search.js
+++ /dev/null
@@ -1,134 +0,0 @@
-#ifdef 0
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-#endif
-
-const SEARCH_ENGINES = {
- "DuckDuckGo": {
- image: "data:image/png;base64," +
- "iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAACT1BMVEXvISn/////9/fvUlr3ra3/" +
- "zs7/7+/va2v/5+f/xsbvMTn/tbX/3t7/vb3vOUL3WmPvQkr/zgDvKTHvSlL3hIT3paX/1tbnISn3" +
- "c3v3e3v3a3P3jIz3nJz/tb33c3PvKSn3lJT39/cAc73vSkr3e4Tv7+/3Yxj3pa3/tQj3jJT3nKX3" +
- "Y2P/xs73hIzvQkL/vQjvQiHn5+f3hBD/ztbvMTH/vcb/3ucIc733lJz/pQilzufe7/fvMSHOzs73" +
- "//cQrUpKvVprxmP3Y2vvShiUzmvWlJRzzmMYtUrvOTnn7/davVrWra3v9//nY2PvISGUxudztd7e" +
- "3t7/76XvKSHea2v/xgDnOUK93vfW5/f/1t73Uhj/52ut3q2l3rXO784pjMZrrdb/rQjera3/5+/e" +
- "paWMxufO79aEazkYrUr/nAj3jBD3axj3lBD///fehIRKpd7/1hCEYzk5vVL3//8ptVLW77UxtVLn" +
- "SlLW1tZCvVp7vef/1gj/3invSkL//+fWtbXvpaX/3kr/97XvnJznWmMxjM5zvefOxsbWnKXWjIzG" +
- "3u/ea3Pn997O5/fnQkqExuf3Whit1u/nUlrnxs7v5+d7zmuU1pT3exDOSjFjrVL/987/pUoQe8b/" +
- "75T/3jFKxnO158bWKSl7zoRSxmtajEK1e0pzxlqcUjH/1iHOMSnOvb33cxDWnJx7td6EzmP/74xz" +
- "azlrcznec3Pe771jxlpzczne78YpvVqEvWPn99YxvWOtSjHee3vG787OOTE5lEK1QjHv9+drzmve" +
- "tbXO772q+r8wAAAFbUlEQVR4Xo2X84PzTBDHN3Zqu2fbemzbNl7atm3btvGHvTNJ2myuyd3NL2mT" +
- "zmdnvjM76RImyGQlH5dCHBeSmscNmQkyfwBrZMLEY2aRF5cMSDYPEx+LZpUlAYRQbVEpnuc1je/M" +
- "SbVwYoVFAbpE0IaLmiwqiVymmE3H84YuGs2mheCEhQH5qPUrje2ONxHKVIkXR2x2MxsMkDnLvftk" +
- "2fSTQNCzSAgngwCCipkXxHiU+BsnCDFE8f6AQgnwaTGhkmDLymW8jPsBeIsth8iCpha618El1wgo" +
- "4FOhWyWLWY+O8pbnAwTI29S1ElncJBmF4L0AGeJSdR4dUpt5w+DL0nAgoUuGGKKCBxDCOxrykaDb" +
- "+yFQjhUylLlXpAB5jGnIqV6uvvWUcAAhLmDBXIAMrkXRdHQ+cerUiWefq1hRrAgg8LikUgdkQUAx" +
- "6+2Ze0WLEO/1BQzrHCFNrAPAeDSD4q/Ln6R3p68MSYzDAUiwIEutJM0bHXE/gpEhJMxaAB3T6aT8" +
- "mfkm+QBiMlwKFqAHvrHu9tvTOLrEdX4hFAkJWQB42qbVyam75ruv3zvF+wBCKJ0MAAV6SAy5+raA" +
- "y+lb9tYBUw9sffKRJh+CDl2SAEAPquaC76swU1c+zlxbA9if/EIY78AcCBODDKjnVzDM0+sb57zq" +
- "N14gdpbg4nraBaxm3NWpIDKNgJIIDTxEAKMyVM9/VrFcpijK52PbNhmk0RQORCA8dhGhIkDA+qPV" +
- "Y/U8No2NHZsUfQCdzYTECSiRSRJKgxYAnK6+tnVrPYL7q2P7GNNnT0L3SQSS61AowK4BAExWq9XJ" +
- "OmDT5D4GtUab7p92W1aD6AFBOjUKcONNKMG2o9vmScmhd+v5SCTS91StDLBwmHR5q0iiM4yv3X5g" +
- "sD1i24tUHc0GQOrOihdw+ZV7drx+8I1IzfpaCQ1oSIGsbqEBdxy8KkLb8dYt7m7AFBpEJI8OUIAd" +
- "Hve+wX509IqYgzLqxKMi5X+r6737wgHfMrZBKGwpQMWP0PN8/8qLn15cSRosEQeI3coxGrzRVfE2" +
- "BEyTAMNpmbA3k2erPOyq+CUCPGvv3OmGykYBQhiYFbynDLu2uyW826qb7bSlv/VCe2R3vQqhIYQQ" +
- "nLmSGKUAT1AqXn7V6p72iUsTThsNuhKUAeKMNFaiW2nG08H90IF1m6DywVdsHgA4bPgRGgAqUgBr" +
- "DwxOtPcdv9RK6yklnaGKOXBMmN7RVCtJJMiUdG2s78dv9HbY7KrI9AQBOHwjaxaA6cKhRLXCHkpF" +
- "PrAJYBz1su7LtSBQIjzozgI5AJDWsQ7gTJxETTHuEh5yW8kR5+1fvQBT5PDdWgPokE6GSuK3Aaby" +
- "2KwNyGFIZ8/NfexVMAGXEfe8MA5QTVdrgGe2M9evev6FMwiAYr308nVzcx/SgHwSlswyLgDLHU0K" +
- "tX5UZwCwZsM1b7516J1333v/g2UAuJoCNMsmZkEDZBXujCoOIfVJxQKsvXnDshvWfrEcAV9RAoqY" +
- "rfdvHjY06R3tVmtjzQYsQ8ByC/C1O0dEzqkAGqELbiZ1W/RvBr51Ad9ZgO8dQCkh4/q5xvMC6hot" +
- "sBl7rP1QT+HHQz9RGoSHhkyMgqEBdNPFWSWMY+1nBPxy+MjvZ2aZxB9n/zz3FwKiOTZfotb3AhhF" +
- "xSUUNmGSjX+vWvPPYacVWJOkUilUT05ymEVb0JFHj9l/AVn+35b/jsx6YzNz8mja+iAEH7rYDntY" +
- "Gaz3dizW080KWaeICx77kiG7lTKG6EEoPb0Wu0lZ9OA5whFH8GxHQjOMQls5HSs5t/glHX2FYtT/" +
- "mGAs/fCtFU0vQJUSQYfvIBvVyukuLhbjuood/H6WCbD/AQSFvIO3JDxgAAAAAElFTkSuQmCC"
- }
-};
-
-// This global tracks if the page has been set up before, to prevent double inits
-var gInitialized = false;
-var gObserver = new MutationObserver(function (mutations) {
- for (let mutation of mutations) {
- if (mutation.attributeName == "searchEngineURL") {
- setupSearchEngine();
- if (!gInitialized) {
- gInitialized = true;
- }
- return;
- }
- }
-});
-
-window.addEventListener("pageshow", function () {
- window.gObserver.observe(document.documentElement, { attributes: true });
-});
-
-window.addEventListener("pagehide", function() {
- window.gObserver.disconnect();
-});
-
-function onSearchSubmit(aEvent) {
- let searchTerms = document.getElementById("searchText").value;
- let searchURL = document.documentElement.getAttribute("searchEngineURL");
-
- if (searchURL && searchTerms.length > 0) {
- const SEARCH_TOKEN = "_searchTerms_";
- let searchPostData = document.documentElement.getAttribute("searchEnginePostData");
- if (searchPostData) {
- // Check if a post form already exists. If so, remove it.
- const POST_FORM_NAME = "searchFormPost";
- let form = document.forms[POST_FORM_NAME];
- if (form) {
- form.parentNode.removeChild(form);
- }
-
- // Create a new post form.
- form = document.body.appendChild(document.createElement("form"));
- form.setAttribute("name", POST_FORM_NAME);
- // Set the URL to submit the form to.
- form.setAttribute("action", searchURL.replace(SEARCH_TOKEN, searchTerms));
- form.setAttribute("method", "post");
-
- // Create new <input type=hidden> elements for search param.
- searchPostData = searchPostData.split("&");
- for (let postVar of searchPostData) {
- let [name, value] = postVar.split("=");
- if (value == SEARCH_TOKEN) {
- value = searchTerms;
- }
- let input = document.createElement("input");
- input.setAttribute("type", "hidden");
- input.setAttribute("name", name);
- input.setAttribute("value", value);
- form.appendChild(input);
- }
- // Submit the form.
- form.submit();
- } else {
- searchURL = searchURL.replace(SEARCH_TOKEN, encodeURIComponent(searchTerms));
- window.location.href = searchURL;
- }
- }
-
- aEvent.preventDefault();
-}
-
-
-function setupSearchEngine() {
- let searchText = document.getElementById("searchText");
- let searchEngineName = document.documentElement.getAttribute("searchEngineName");
- let searchEngineInfo = SEARCH_ENGINES[searchEngineName];
- let logoElt = document.getElementById("searchEngineLogo");
-
- // Add search engine logo.
- if (searchEngineInfo && searchEngineInfo.image) {
- logoElt.parentNode.hidden = false;
- logoElt.src = searchEngineInfo.image;
- logoElt.alt = searchEngineName;
- searchText.placeholder = "";
- } else {
- logoElt.parentNode.hidden = true;
- searchText.placeholder = searchEngineName;
- }
-}
diff --git a/components/newtab/sites.js b/components/newtab/sites.js
deleted file mode 100644
index cb56752..0000000
--- a/components/newtab/sites.js
+++ /dev/null
@@ -1,353 +0,0 @@
-#ifdef 0
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-#endif
-
-const THUMBNAIL_PLACEHOLDER_ENABLED =
- Services.prefs.getBoolPref("browser.newtabpage.thumbnailPlaceholder");
-
-/**
- * This class represents a site that is contained in a cell and can be pinned,
- * moved around or deleted.
- */
-function Site(aNode, aLink) {
- this._node = aNode;
- this._node._newtabSite = this;
-
- this._link = aLink;
-
- this._render();
- this._addEventHandlers();
-}
-
-Site.prototype = {
- /**
- * The site's DOM node.
- */
- get node() { return this._node; },
-
- /**
- * The site's link.
- */
- get link() { return this._link; },
-
- /**
- * The url of the site's link.
- */
- get url() { return this.link.url; },
-
- /**
- * The title of the site's link.
- */
- get title() { return this.link.title || this.link.url; },
-
- /**
- * The site's parent cell.
- */
- get cell() {
- let parentNode = this.node.parentNode;
- return parentNode && parentNode._newtabCell;
- },
-
- /**
- * Pins the site on its current or a given index.
- * @param aIndex The pinned index (optional).
- * @return true if link changed type after pin
- */
- pin: function Site_pin(aIndex) {
- if (typeof aIndex == "undefined")
- aIndex = this.cell.index;
-
- this._updateAttributes(true);
- let changed = gPinnedLinks.pin(this._link, aIndex);
- if (changed) {
- // render site again
- this._render();
- }
- return changed;
- },
-
- /**
- * Unpins the site and calls the given callback when done.
- */
- unpin: function Site_unpin() {
- if (this.isPinned()) {
- this._updateAttributes(false);
- gPinnedLinks.unpin(this._link);
- gUpdater.updateGrid();
- }
- },
-
- /**
- * Checks whether this site is pinned.
- * @return Whether this site is pinned.
- */
- isPinned: function Site_isPinned() {
- return gPinnedLinks.isPinned(this._link);
- },
-
- /**
- * Blocks the site (removes it from the grid) and calls the given callback
- * when done.
- */
- block: function Site_block() {
- if (!gBlockedLinks.isBlocked(this._link)) {
- gUndoDialog.show(this);
- gBlockedLinks.block(this._link);
- gUpdater.updateGrid();
- }
- },
-
- /**
- * Gets the DOM node specified by the given query selector.
- * @param aSelector The query selector.
- * @return The DOM node we found.
- */
- _querySelector: function Site_querySelector(aSelector) {
- return this.node.querySelector(aSelector);
- },
-
- /**
- * Updates attributes for all nodes which status depends on this site being
- * pinned or unpinned.
- * @param aPinned Whether this site is now pinned or unpinned.
- */
- _updateAttributes: function (aPinned) {
- let control = this._querySelector(".newtab-control-pin");
-
- if (aPinned) {
- this.node.setAttribute("pinned", true);
- control.setAttribute("title", newTabString("unpin"));
- } else {
- this.node.removeAttribute("pinned");
- control.setAttribute("title", newTabString("pin"));
- }
- },
-
- _newTabString: function(str, substrArr) {
- let regExp = /%[0-9]\$S/g;
- let matches;
- while ((matches = regExp.exec(str))) {
- let match = matches[0];
- let index = match.charAt(1); // Get the digit in the regExp.
- str = str.replace(match, substrArr[index - 1]);
- }
- return str;
- },
-
- /**
- * Checks for and modifies link at campaign end time
- */
- _checkLinkEndTime: function Site_checkLinkEndTime() {
- if (this.link.endTime && this.link.endTime < Date.now()) {
- let oldUrl = this.url;
- // chop off the path part from url
- this.link.url = Services.io.newURI(this.url, null, null).resolve("/");
- // clear supplied images - this triggers thumbnail download for new url
- delete this.link.imageURI;
- // remove endTime to avoid further time checks
- delete this.link.endTime;
- gPinnedLinks.replace(oldUrl, this.link);
- }
- },
-
- /**
- * Renders the site's data (fills the HTML fragment).
- */
- _render: function Site_render() {
- // first check for end time, as it may modify the link
- this._checkLinkEndTime();
- // setup display variables
- let url = this.url;
- let title = this.link.type == "history" ? this.link.baseDomain :
- this.title;
- let tooltip = (this.title == url ? this.title : this.title + "\n" + url);
-
- let link = this._querySelector(".newtab-link");
- link.setAttribute("title", tooltip);
- link.setAttribute("href", url);
- this.node.setAttribute("type", this.link.type);
-
- let titleNode = this._querySelector(".newtab-title");
- titleNode.textContent = title;
- if (this.link.titleBgColor) {
- titleNode.style.backgroundColor = this.link.titleBgColor;
- }
-
- if (this.isPinned())
- this._updateAttributes(true);
- // Capture the page if the thumbnail is missing, which will cause page.js
- // to be notified and call our refreshThumbnail() method.
- this.captureIfMissing();
- // but still display whatever thumbnail might be available now.
- this.refreshThumbnail();
- },
-
- /**
- * Called when the site's tab becomes visible for the first time.
- * Since the newtab may be preloaded long before it's displayed,
- * check for changed conditions and re-render if needed
- */
- onFirstVisible: function Site_onFirstVisible() {
- if (this.link.endTime && this.link.endTime < Date.now()) {
- // site needs to change landing url and background image
- this._render();
- }
- else {
- this.captureIfMissing();
- }
- },
-
- /**
- * Captures the site's thumbnail in the background, but only if there's no
- * existing thumbnail and the page allows background captures.
- */
- captureIfMissing: function Site_captureIfMissing() {
- if (!document.hidden && !this.link.imageURI) {
- BackgroundPageThumbs.captureIfMissing(this.url);
- }
- },
-
- /**
- * Refreshes the thumbnail for the site.
- */
- refreshThumbnail: function Site_refreshThumbnail() {
- let link = this.link;
-
- let thumbnail = this._querySelector(".newtab-thumbnail.thumbnail");
- if (link.bgColor) {
- thumbnail.style.backgroundColor = link.bgColor;
- }
- let uri = link.imageURI || PageThumbs.getThumbnailURL(this.url);
- thumbnail.style.backgroundImage = 'url("' + uri + '")';
-
- if (THUMBNAIL_PLACEHOLDER_ENABLED &&
- link.type == "history" &&
- link.baseDomain) {
- let placeholder = this._querySelector(".newtab-thumbnail.placeholder");
- let charCodeSum = 0;
- for (let c of link.baseDomain) {
- charCodeSum += c.charCodeAt(0);
- }
- const COLORS = 16;
- let hue = Math.round((charCodeSum % COLORS) / COLORS * 360);
- placeholder.style.backgroundColor = "hsl(" + hue + ",80%,40%)";
- placeholder.textContent = link.baseDomain.substr(0,1).toUpperCase();
- }
- },
-
- _ignoreHoverEvents: function(element) {
- element.addEventListener("mouseover", () => {
- this.cell.node.setAttribute("ignorehover", "true");
- });
- element.addEventListener("mouseout", () => {
- this.cell.node.removeAttribute("ignorehover");
- });
- },
-
- /**
- * Adds event handlers for the site and its buttons.
- */
- _addEventHandlers: function Site_addEventHandlers() {
- // Register drag-and-drop event handlers.
- this._node.addEventListener("dragstart", this, false);
- this._node.addEventListener("dragend", this, false);
- this._node.addEventListener("mouseover", this, false);
- },
-
- /**
- * Speculatively opens a connection to the current site.
- */
- _speculativeConnect: function Site_speculativeConnect() {
- let sc = Services.io.QueryInterface(Ci.nsISpeculativeConnect);
- let uri = Services.io.newURI(this.url, null, null);
- try {
- // This can throw for certain internal URLs, when they wind up in
- // about:newtab. Be sure not to propagate the error.
- sc.speculativeConnect(uri, null);
- } catch (e) {}
- },
-
- /**
- * Record interaction with site using telemetry.
- */
- _recordSiteClicked: function Site_recordSiteClicked(aIndex) {
- if (Services.prefs.prefHasUserValue("browser.newtabpage.rows") ||
- Services.prefs.prefHasUserValue("browser.newtabpage.columns") ||
- aIndex > 8) {
- // We only want to get indices for the default configuration, everything
- // else goes in the same bucket.
- aIndex = 9;
- }
- Services.telemetry.getHistogramById("NEWTAB_PAGE_SITE_CLICKED")
- .add(aIndex);
- },
-
- _toggleLegalText: function(buttonClass, explanationTextClass) {
- let button = this._querySelector(buttonClass);
- if (button.hasAttribute("active")) {
- let explain = this._querySelector(explanationTextClass);
- explain.parentNode.removeChild(explain);
-
- button.removeAttribute("active");
- }
- },
-
- /**
- * Handles site click events.
- */
- onClick: function Site_onClick(aEvent) {
- let action;
- let pinned = this.isPinned();
- let tileIndex = this.cell.index;
- let {button, target} = aEvent;
-
- // Handle tile/thumbnail link click
- if (target.classList.contains("newtab-link") ||
- target.parentElement.classList.contains("newtab-link")) {
- // Record for primary and middle clicks
- if (button == 0 || button == 1) {
- this._recordSiteClicked(tileIndex);
- action = "click";
- }
- }
- // Only handle primary clicks for the remaining targets
- else if (button == 0) {
- aEvent.preventDefault();
- if (target.classList.contains("newtab-control-block")) {
- this.block();
- action = "block";
- }
- else if (pinned && target.classList.contains("newtab-control-pin")) {
- this.unpin();
- action = "unpin";
- }
- else if (!pinned && target.classList.contains("newtab-control-pin")) {
- if (this.pin()) {
- // link has changed - update rest of the pages
- gAllPages.update(gPage);
- }
- action = "pin";
- }
- }
- },
-
- /**
- * Handles all site events.
- */
- handleEvent: function Site_handleEvent(aEvent) {
- switch (aEvent.type) {
- case "mouseover":
- this._node.removeEventListener("mouseover", this, false);
- this._speculativeConnect();
- break;
- case "dragstart":
- gDrag.start(this, aEvent);
- break;
- case "dragend":
- gDrag.end(this, aEvent);
- break;
- }
- }
-};
diff --git a/components/newtab/transformations.js b/components/newtab/transformations.js
deleted file mode 100644
index f7db0ad..0000000
--- a/components/newtab/transformations.js
+++ /dev/null
@@ -1,270 +0,0 @@
-#ifdef 0
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-#endif
-
-/**
- * This singleton allows to transform the grid by repositioning a site's node
- * in the DOM and by showing or hiding the node. It additionally provides
- * convenience methods to work with a site's DOM node.
- */
-var gTransformation = {
- /**
- * Returns the width of the left and top border of a cell. We need to take it
- * into account when measuring and comparing site and cell positions.
- */
- get _cellBorderWidths() {
- let cstyle = window.getComputedStyle(gGrid.cells[0].node, null);
- let widths = {
- left: parseInt(cstyle.getPropertyValue("border-left-width")),
- top: parseInt(cstyle.getPropertyValue("border-top-width"))
- };
-
- // Cache this value, overwrite the getter.
- Object.defineProperty(this, "_cellBorderWidths",
- {value: widths, enumerable: true});
-
- return widths;
- },
-
- /**
- * Gets a DOM node's position.
- * @param aNode The DOM node.
- * @return A Rect instance with the position.
- */
- getNodePosition: function Transformation_getNodePosition(aNode) {
- let {left, top, width, height} = aNode.getBoundingClientRect();
- return new Rect(left + scrollX, top + scrollY, width, height);
- },
-
- /**
- * Fades a given node from zero to full opacity.
- * @param aNode The node to fade.
- * @param aCallback The callback to call when finished.
- */
- fadeNodeIn: function Transformation_fadeNodeIn(aNode, aCallback) {
- this._setNodeOpacity(aNode, 1, function () {
- // Clear the style property.
- aNode.style.opacity = "";
-
- if (aCallback)
- aCallback();
- });
- },
-
- /**
- * Fades a given node from full to zero opacity.
- * @param aNode The node to fade.
- * @param aCallback The callback to call when finished.
- */
- fadeNodeOut: function Transformation_fadeNodeOut(aNode, aCallback) {
- this._setNodeOpacity(aNode, 0, aCallback);
- },
-
- /**
- * Fades a given site from zero to full opacity.
- * @param aSite The site to fade.
- * @param aCallback The callback to call when finished.
- */
- showSite: function Transformation_showSite(aSite, aCallback) {
- this.fadeNodeIn(aSite.node, aCallback);
- },
-
- /**
- * Fades a given site from full to zero opacity.
- * @param aSite The site to fade.
- * @param aCallback The callback to call when finished.
- */
- hideSite: function Transformation_hideSite(aSite, aCallback) {
- this.fadeNodeOut(aSite.node, aCallback);
- },
-
- /**
- * Allows to set a site's position.
- * @param aSite The site to re-position.
- * @param aPosition The desired position for the given site.
- */
- setSitePosition: function Transformation_setSitePosition(aSite, aPosition) {
- let style = aSite.node.style;
- let {top, left} = aPosition;
-
- style.top = top + "px";
- style.left = left + "px";
- },
-
- /**
- * Freezes a site in its current position by positioning it absolute.
- * @param aSite The site to freeze.
- */
- freezeSitePosition: function Transformation_freezeSitePosition(aSite) {
- if (this._isFrozen(aSite))
- return;
-
- let style = aSite.node.style;
- let comp = getComputedStyle(aSite.node, null);
- style.width = comp.getPropertyValue("width");
- style.height = comp.getPropertyValue("height");
-
- aSite.node.setAttribute("frozen", "true");
- this.setSitePosition(aSite, this.getNodePosition(aSite.node));
- },
-
- /**
- * Unfreezes a site by removing its absolute positioning.
- * @param aSite The site to unfreeze.
- */
- unfreezeSitePosition: function Transformation_unfreezeSitePosition(aSite) {
- if (!this._isFrozen(aSite))
- return;
-
- let style = aSite.node.style;
- style.left = style.top = style.width = style.height = "";
- aSite.node.removeAttribute("frozen");
- },
-
- /**
- * Slides the given site to the target node's position.
- * @param aSite The site to move.
- * @param aTarget The slide target.
- * @param aOptions Set of options (see below).
- * unfreeze - unfreeze the site after sliding
- * callback - the callback to call when finished
- */
- slideSiteTo: function Transformation_slideSiteTo(aSite, aTarget, aOptions) {
- let currentPosition = this.getNodePosition(aSite.node);
- let targetPosition = this.getNodePosition(aTarget.node)
- let callback = aOptions && aOptions.callback;
-
- let self = this;
-
- function finish() {
- if (aOptions && aOptions.unfreeze)
- self.unfreezeSitePosition(aSite);
-
- if (callback)
- callback();
- }
-
- // We need to take the width of a cell's border into account.
- targetPosition.left += this._cellBorderWidths.left;
- targetPosition.top += this._cellBorderWidths.top;
-
- // Nothing to do here if the positions already match.
- if (currentPosition.left == targetPosition.left &&
- currentPosition.top == targetPosition.top) {
- finish();
- } else {
- this.setSitePosition(aSite, targetPosition);
- this._whenTransitionEnded(aSite.node, ["left", "top"], finish);
- }
- },
-
- /**
- * Rearranges a given array of sites and moves them to their new positions or
- * fades in/out new/removed sites.
- * @param aSites An array of sites to rearrange.
- * @param aOptions Set of options (see below).
- * unfreeze - unfreeze the site after rearranging
- * callback - the callback to call when finished
- */
- rearrangeSites: function Transformation_rearrangeSites(aSites, aOptions) {
- let batch = [];
- let cells = gGrid.cells;
- let callback = aOptions && aOptions.callback;
- let unfreeze = aOptions && aOptions.unfreeze;
-
- aSites.forEach(function (aSite, aIndex) {
- // Do not re-arrange empty cells or the dragged site.
- if (!aSite || aSite == gDrag.draggedSite)
- return;
-
- batch.push(new Promise(resolve => {
- if (!cells[aIndex]) {
- // The site disappeared from the grid, hide it.
- this.hideSite(aSite, resolve);
- } else if (this._getNodeOpacity(aSite.node) != 1) {
- // The site disappeared before but is now back, show it.
- this.showSite(aSite, resolve);
- } else {
- // The site's position has changed, move it around.
- this._moveSite(aSite, aIndex, {unfreeze: unfreeze, callback: resolve});
- }
- }));
- }, this);
-
- if (callback) {
- Promise.all(batch).then(callback);
- }
- },
-
- /**
- * Listens for the 'transitionend' event on a given node and calls the given
- * callback.
- * @param aNode The node that is transitioned.
- * @param aProperties The properties we'll wait to be transitioned.
- * @param aCallback The callback to call when finished.
- */
- _whenTransitionEnded:
- function Transformation_whenTransitionEnded(aNode, aProperties, aCallback) {
-
- let props = new Set(aProperties);
- aNode.addEventListener("transitionend", function onEnd(e) {
- if (props.has(e.propertyName)) {
- aNode.removeEventListener("transitionend", onEnd);
- aCallback();
- }
- });
- },
-
- /**
- * Gets a given node's opacity value.
- * @param aNode The node to get the opacity value from.
- * @return The node's opacity value.
- */
- _getNodeOpacity: function Transformation_getNodeOpacity(aNode) {
- let cstyle = window.getComputedStyle(aNode, null);
- return cstyle.getPropertyValue("opacity");
- },
-
- /**
- * Sets a given node's opacity.
- * @param aNode The node to set the opacity value for.
- * @param aOpacity The opacity value to set.
- * @param aCallback The callback to call when finished.
- */
- _setNodeOpacity:
- function Transformation_setNodeOpacity(aNode, aOpacity, aCallback) {
-
- if (this._getNodeOpacity(aNode) == aOpacity) {
- if (aCallback)
- aCallback();
- } else {
- if (aCallback) {
- this._whenTransitionEnded(aNode, ["opacity"], aCallback);
- }
-
- aNode.style.opacity = aOpacity;
- }
- },
-
- /**
- * Moves a site to the cell with the given index.
- * @param aSite The site to move.
- * @param aIndex The target cell's index.
- * @param aOptions Options that are directly passed to slideSiteTo().
- */
- _moveSite: function Transformation_moveSite(aSite, aIndex, aOptions) {
- this.freezeSitePosition(aSite);
- this.slideSiteTo(aSite, gGrid.cells[aIndex], aOptions);
- },
-
- /**
- * Checks whether a site is currently frozen.
- * @param aSite The site to check.
- * @return Whether the given site is frozen.
- */
- _isFrozen: function Transformation_isFrozen(aSite) {
- return aSite.node.hasAttribute("frozen");
- }
-};
diff --git a/components/newtab/undo.js b/components/newtab/undo.js
deleted file mode 100644
index b856914..0000000
--- a/components/newtab/undo.js
+++ /dev/null
@@ -1,116 +0,0 @@
-#ifdef 0
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-#endif
-
-/**
- * Dialog allowing to undo the removal of single site or to completely restore
- * the grid's original state.
- */
-var gUndoDialog = {
- /**
- * The undo dialog's timeout in miliseconds.
- */
- HIDE_TIMEOUT_MS: 15000,
-
- /**
- * Contains undo information.
- */
- _undoData: null,
-
- /**
- * Initializes the undo dialog.
- */
- init: function UndoDialog_init() {
- this._undoContainer = document.getElementById("newtab-undo-container");
- this._undoContainer.addEventListener("click", this, false);
- this._undoButton = document.getElementById("newtab-undo-button");
- this._undoCloseButton = document.getElementById("newtab-undo-close-button");
- this._undoRestoreButton = document.getElementById("newtab-undo-restore-button");
- },
-
- /**
- * Shows the undo dialog.
- * @param aSite The site that just got removed.
- */
- show: function UndoDialog_show(aSite) {
- if (this._undoData)
- clearTimeout(this._undoData.timeout);
-
- this._undoData = {
- index: aSite.cell.index,
- wasPinned: aSite.isPinned(),
- blockedLink: aSite.link,
- timeout: setTimeout(this.hide.bind(this), this.HIDE_TIMEOUT_MS)
- };
-
- this._undoContainer.removeAttribute("undo-disabled");
- this._undoButton.removeAttribute("tabindex");
- this._undoCloseButton.removeAttribute("tabindex");
- this._undoRestoreButton.removeAttribute("tabindex");
- },
-
- /**
- * Hides the undo dialog.
- */
- hide: function UndoDialog_hide() {
- if (!this._undoData)
- return;
-
- clearTimeout(this._undoData.timeout);
- this._undoData = null;
- this._undoContainer.setAttribute("undo-disabled", "true");
- this._undoButton.setAttribute("tabindex", "-1");
- this._undoCloseButton.setAttribute("tabindex", "-1");
- this._undoRestoreButton.setAttribute("tabindex", "-1");
- },
-
- /**
- * The undo dialog event handler.
- * @param aEvent The event to handle.
- */
- handleEvent: function UndoDialog_handleEvent(aEvent) {
- switch (aEvent.target.id) {
- case "newtab-undo-button":
- this._undo();
- break;
- case "newtab-undo-restore-button":
- this._undoAll();
- break;
- case "newtab-undo-close-button":
- this.hide();
- break;
- }
- },
-
- /**
- * Undo the last blocked site.
- */
- _undo: function UndoDialog_undo() {
- if (!this._undoData)
- return;
-
- let {index, wasPinned, blockedLink} = this._undoData;
- gBlockedLinks.unblock(blockedLink);
-
- if (wasPinned) {
- gPinnedLinks.pin(blockedLink, index);
- }
-
- gUpdater.updateGrid();
- this.hide();
- },
-
- /**
- * Undo all blocked sites.
- */
- _undoAll: function UndoDialog_undoAll() {
- NewTabUtils.undoAll(function() {
- gUpdater.updateGrid();
- this.hide();
- }.bind(this));
- }
-};
-
-gUndoDialog.init();
diff --git a/components/newtab/updater.js b/components/newtab/updater.js
deleted file mode 100644
index 2bab74d..0000000
--- a/components/newtab/updater.js
+++ /dev/null
@@ -1,177 +0,0 @@
-#ifdef 0
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-#endif
-
-/**
- * This singleton provides functionality to update the current grid to a new
- * set of pinned and blocked sites. It adds, moves and removes sites.
- */
-var gUpdater = {
- /**
- * Updates the current grid according to its pinned and blocked sites.
- * This removes old, moves existing and creates new sites to fill gaps.
- * @param aCallback The callback to call when finished.
- */
- updateGrid: function Updater_updateGrid(aCallback) {
- let links = gLinks.getLinks().slice(0, gGrid.cells.length);
-
- // Find all sites that remain in the grid.
- let sites = this._findRemainingSites(links);
-
- // Remove sites that are no longer in the grid.
- this._removeLegacySites(sites, () => {
- // Freeze all site positions so that we can move their DOM nodes around
- // without any visual impact.
- this._freezeSitePositions(sites);
-
- // Move the sites' DOM nodes to their new position in the DOM. This will
- // have no visual effect as all the sites have been frozen and will
- // remain in their current position.
- this._moveSiteNodes(sites);
-
- // Now it's time to animate the sites actually moving to their new
- // positions.
- this._rearrangeSites(sites, () => {
- // Try to fill empty cells and finish.
- this._fillEmptyCells(links, aCallback);
-
- // Update other pages that might be open to keep them synced.
- gAllPages.update(gPage);
- });
- });
- },
-
- /**
- * Takes an array of links and tries to correlate them to sites contained in
- * the current grid. If no corresponding site can be found (i.e. the link is
- * new and a site will be created) then just set it to null.
- * @param aLinks The array of links to find sites for.
- * @return Array of sites mapped to the given links (can contain null values).
- */
- _findRemainingSites: function Updater_findRemainingSites(aLinks) {
- let map = {};
-
- // Create a map to easily retrieve the site for a given URL.
- gGrid.sites.forEach(function (aSite) {
- if (aSite)
- map[aSite.url] = aSite;
- });
-
- // Map each link to its corresponding site, if any.
- return aLinks.map(function (aLink) {
- return aLink && (aLink.url in map) && map[aLink.url];
- });
- },
-
- /**
- * Freezes the given sites' positions.
- * @param aSites The array of sites to freeze.
- */
- _freezeSitePositions: function Updater_freezeSitePositions(aSites) {
- aSites.forEach(function (aSite) {
- if (aSite)
- gTransformation.freezeSitePosition(aSite);
- });
- },
-
- /**
- * Moves the given sites' DOM nodes to their new positions.
- * @param aSites The array of sites to move.
- */
- _moveSiteNodes: function Updater_moveSiteNodes(aSites) {
- let cells = gGrid.cells;
-
- // Truncate the given array of sites to not have more sites than cells.
- // This can happen when the user drags a bookmark (or any other new kind
- // of link) onto the grid.
- let sites = aSites.slice(0, cells.length);
-
- sites.forEach(function (aSite, aIndex) {
- let cell = cells[aIndex];
- let cellSite = cell.site;
-
- // The site's position didn't change.
- if (!aSite || cellSite != aSite) {
- let cellNode = cell.node;
-
- // Empty the cell if necessary.
- if (cellSite)
- cellNode.removeChild(cellSite.node);
-
- // Put the new site in place, if any.
- if (aSite)
- cellNode.appendChild(aSite.node);
- }
- }, this);
- },
-
- /**
- * Rearranges the given sites and slides them to their new positions.
- * @param aSites The array of sites to re-arrange.
- * @param aCallback The callback to call when finished.
- */
- _rearrangeSites: function Updater_rearrangeSites(aSites, aCallback) {
- let options = {callback: aCallback, unfreeze: true};
- gTransformation.rearrangeSites(aSites, options);
- },
-
- /**
- * Removes all sites from the grid that are not in the given links array or
- * exceed the grid.
- * @param aSites The array of sites remaining in the grid.
- * @param aCallback The callback to call when finished.
- */
- _removeLegacySites: function Updater_removeLegacySites(aSites, aCallback) {
- let batch = [];
-
- // Delete sites that were removed from the grid.
- gGrid.sites.forEach(function (aSite) {
- // The site must be valid and not in the current grid.
- if (!aSite || aSites.indexOf(aSite) != -1)
- return;
-
- batch.push(new Promise(resolve => {
- // Fade out the to-be-removed site.
- gTransformation.hideSite(aSite, function () {
- let node = aSite.node;
-
- // Remove the site from the DOM.
- node.parentNode.removeChild(node);
- resolve();
- });
- }));
- });
-
- Promise.all(batch).then(aCallback);
- },
-
- /**
- * Tries to fill empty cells with new links if available.
- * @param aLinks The array of links.
- * @param aCallback The callback to call when finished.
- */
- _fillEmptyCells: function Updater_fillEmptyCells(aLinks, aCallback) {
- let {cells, sites} = gGrid;
-
- // Find empty cells and fill them.
- Promise.all(sites.map((aSite, aIndex) => {
- if (aSite || !aLinks[aIndex])
- return null;
-
- return new Promise(resolve => {
- // Create the new site and fade it in.
- let site = gGrid.createSite(aLinks[aIndex], cells[aIndex]);
-
- // Set the site's initial opacity to zero.
- site.node.style.opacity = 0;
-
- // Flush all style changes for the dynamically inserted site to make
- // the fade-in transition work.
- window.getComputedStyle(site.node).opacity;
- gTransformation.showSite(site, resolve);
- });
- })).then(aCallback).catch(console.exception);
- }
-};
diff --git a/components/nsAboutRedirector.js b/components/nsAboutRedirector.js
deleted file mode 100644
index 4d99a78..0000000
--- a/components/nsAboutRedirector.js
+++ /dev/null
@@ -1,114 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-var Ci = Components.interfaces;
-var Cr = Components.results;
-var Cu = Components.utils;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-
-// See: netwerk/protocol/about/nsIAboutModule.idl
-const URI_SAFE_FOR_UNTRUSTED_CONTENT = Ci.nsIAboutModule.URI_SAFE_FOR_UNTRUSTED_CONTENT;
-const ALLOW_SCRIPT = Ci.nsIAboutModule.ALLOW_SCRIPT;
-const HIDE_FROM_ABOUTABOUT = Ci.nsIAboutModule.HIDE_FROM_ABOUTABOUT;
-const MAKE_LINKABLE = Ci.nsIAboutModule.MAKE_LINKABLE;
-
-function AboutRedirector() {}
-AboutRedirector.prototype = {
- classDescription: "Browser about: Redirector",
- classID: Components.ID("{8cc51368-6aa0-43e8-b762-bde9b9fd828c}"),
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIAboutModule]),
-
- // Each entry in the map has the key as the part after the "about:" and the
- // value as a record with url and flags entries. Note that each addition here
- // should be coupled with a corresponding addition in BrowserComponents.manifest.
- _redirMap: {
- "certerror": {
- url: "chrome://browser/content/certerror/aboutCertError.xhtml",
- flags: (URI_SAFE_FOR_UNTRUSTED_CONTENT | ALLOW_SCRIPT | HIDE_FROM_ABOUTABOUT)
- },
- "downloads": {
- url: "chrome://browser/content/downloads/contentAreaDownloadsView.xul",
- flags: ALLOW_SCRIPT
- },
- "feeds": {
- url: "chrome://browser/content/feeds/subscribe.xhtml",
- flags: (URI_SAFE_FOR_UNTRUSTED_CONTENT | ALLOW_SCRIPT | HIDE_FROM_ABOUTABOUT)
- },
- "home": {
- url: "chrome://browser/content/abouthome/aboutHome.xhtml",
- flags: (URI_SAFE_FOR_UNTRUSTED_CONTENT | MAKE_LINKABLE | ALLOW_SCRIPT)
- },
- "newtab": {
- url: "chrome://browser/content/newtab/newTab.xhtml",
- flags: ALLOW_SCRIPT
- },
- "palemoon": {
- url: "chrome://browser/content/palemoon.xhtml",
- flags: (URI_SAFE_FOR_UNTRUSTED_CONTENT | HIDE_FROM_ABOUTABOUT)
- },
- "permissions": {
- url: "chrome://browser/content/permissions/aboutPermissions.xul",
- flags: ALLOW_SCRIPT
- },
- "privatebrowsing": {
- url: "chrome://browser/content/aboutPrivateBrowsing.xhtml",
- flags: ALLOW_SCRIPT
- },
- "rights": {
- url: "chrome://global/content/aboutRights.xhtml",
- flags: (URI_SAFE_FOR_UNTRUSTED_CONTENT | MAKE_LINKABLE | ALLOW_SCRIPT)
- },
- "sessionrestore": {
- url: "chrome://browser/content/aboutSessionRestore.xhtml",
- flags: ALLOW_SCRIPT
- },
-#ifdef MOZ_SERVICES_SYNC
- "sync-progress": {
- url: "chrome://browser/content/sync/progress.xhtml",
- flags: ALLOW_SCRIPT
- },
- "sync-tabs": {
- url: "chrome://browser/content/sync/aboutSyncTabs.xul",
- flags: ALLOW_SCRIPT
- },
-#endif
- },
-
- /**
- * Gets the module name from the given URI.
- */
- _getModuleName: function AboutRedirector__getModuleName(aURI) {
- // Strip out the first ? or #, and anything following it
- let name = (/[^?#]+/.exec(aURI.path))[0];
- return name.toLowerCase();
- },
-
- getURIFlags: function(aURI) {
- let name = this._getModuleName(aURI);
- if (!(name in this._redirMap))
- throw Cr.NS_ERROR_ILLEGAL_VALUE;
- return this._redirMap[name].flags;
- },
-
- newChannel: function(aURI, aLoadInfo) {
- let name = this._getModuleName(aURI);
- if (!(name in this._redirMap))
- throw Cr.NS_ERROR_ILLEGAL_VALUE;
-
- let newURI = Services.io.newURI(this._redirMap[name].url, null, null);
- let channel = Services.io.newChannelFromURIWithLoadInfo(newURI, aLoadInfo);
- channel.originalURI = aURI;
-
- if (this._redirMap[name].flags & Ci.nsIAboutModule.URI_SAFE_FOR_UNTRUSTED_CONTENT) {
- let principal = Services.scriptSecurityManager.getNoAppCodebasePrincipal(aURI);
- channel.owner = principal;
- }
-
- return channel;
- }
-};
-
-var NSGetFactory = XPCOMUtils.generateNSGetFactory([AboutRedirector]);
diff --git a/components/nsBrowserContentHandler.js b/components/nsBrowserContentHandler.js
deleted file mode 100644
index e7f1414..0000000
--- a/components/nsBrowserContentHandler.js
+++ /dev/null
@@ -1,803 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
-Components.utils.import("resource://gre/modules/Services.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
- "resource://gre/modules/PrivateBrowsingUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "RecentWindow",
- "resource:///modules/RecentWindow.jsm");
-
-const nsISupports = Components.interfaces.nsISupports;
-
-const nsIBrowserDOMWindow = Components.interfaces.nsIBrowserDOMWindow;
-const nsIBrowserHandler = Components.interfaces.nsIBrowserHandler;
-const nsIBrowserHistory = Components.interfaces.nsIBrowserHistory;
-const nsIChannel = Components.interfaces.nsIChannel;
-const nsICommandLine = Components.interfaces.nsICommandLine;
-const nsICommandLineHandler = Components.interfaces.nsICommandLineHandler;
-const nsIContentHandler = Components.interfaces.nsIContentHandler;
-const nsIDocShellTreeItem = Components.interfaces.nsIDocShellTreeItem;
-const nsIDOMChromeWindow = Components.interfaces.nsIDOMChromeWindow;
-const nsIDOMWindow = Components.interfaces.nsIDOMWindow;
-const nsIFileURL = Components.interfaces.nsIFileURL;
-const nsIInterfaceRequestor = Components.interfaces.nsIInterfaceRequestor;
-const nsINetUtil = Components.interfaces.nsINetUtil;
-const nsIPrefBranch = Components.interfaces.nsIPrefBranch;
-const nsIPrefLocalizedString = Components.interfaces.nsIPrefLocalizedString;
-const nsISupportsString = Components.interfaces.nsISupportsString;
-const nsIURIFixup = Components.interfaces.nsIURIFixup;
-const nsIWebNavigation = Components.interfaces.nsIWebNavigation;
-const nsIWindowMediator = Components.interfaces.nsIWindowMediator;
-const nsIWindowWatcher = Components.interfaces.nsIWindowWatcher;
-const nsIWebNavigationInfo = Components.interfaces.nsIWebNavigationInfo;
-const nsIBrowserSearchService = Components.interfaces.nsIBrowserSearchService;
-const nsICommandLineValidator = Components.interfaces.nsICommandLineValidator;
-
-const NS_BINDING_ABORTED = Components.results.NS_BINDING_ABORTED;
-const NS_ERROR_WONT_HANDLE_CONTENT = 0x805d0001;
-const NS_ERROR_ABORT = Components.results.NS_ERROR_ABORT;
-
-const URI_INHERITS_SECURITY_CONTEXT = Components.interfaces.nsIHttpProtocolHandler
- .URI_INHERITS_SECURITY_CONTEXT;
-
-function shouldLoadURI(aURI) {
- if (aURI && !aURI.schemeIs("chrome"))
- return true;
-
- dump("*** Preventing external load of chrome: URI into browser window\n");
- dump(" Use -chrome <uri> instead\n");
- return false;
-}
-
-function resolveURIInternal(aCmdLine, aArgument) {
- var uri = aCmdLine.resolveURI(aArgument);
- var urifixup = Components.classes["@mozilla.org/docshell/urifixup;1"]
- .getService(nsIURIFixup);
-
- if (!(uri instanceof nsIFileURL)) {
- return urifixup.createFixupURI(aArgument,
- urifixup.FIXUP_FLAG_FIX_SCHEME_TYPOS);
- }
-
- try {
- if (uri.file.exists())
- return uri;
- }
- catch (e) {
- Components.utils.reportError(e);
- }
-
- // We have interpreted the argument as a relative file URI, but the file
- // doesn't exist. Try URI fixup heuristics: see bug 290782.
-
- try {
- uri = urifixup.createFixupURI(aArgument, 0);
- }
- catch (e) {
- Components.utils.reportError(e);
- }
-
- return uri;
-}
-
-var gFirstWindow = false;
-
-const OVERRIDE_NONE = 0;
-const OVERRIDE_NEW_PROFILE = 1;
-const OVERRIDE_NEW_MSTONE = 2;
-const OVERRIDE_NEW_BUILD_ID = 3;
-/**
- * Determines whether a home page override is needed.
- * Returns:
- * OVERRIDE_NEW_PROFILE if this is the first run with a new profile.
- * OVERRIDE_NEW_MSTONE if this is the first run with a build with a different
- * Goanna milestone (i.e. right after an upgrade).
- * OVERRIDE_NEW_BUILD_ID if this is the first run with a new build ID of the
- * same Goanna milestone (i.e. after a nightly upgrade).
- * OVERRIDE_NONE otherwise.
- */
-function needHomepageOverride(prefb) {
- var savedmstone = prefb.getCharPref("browser.startup.homepage_override.mstone", "");
-
- if (savedmstone == "ignore")
- return OVERRIDE_NONE;
-
- var mstone = Services.appinfo.platformVersion;
-
- var savedBuildID = prefb.getCharPref("browser.startup.homepage_override.buildID", "");
-
- var buildID = Services.appinfo.platformBuildID;
-
- if (mstone != savedmstone) {
- // Bug 462254. Previous releases had a default pref to suppress the EULA
- // agreement if the platform's installer had already shown one. Now with
- // about:rights we've removed the EULA stuff and default pref, but we need
- // a way to make existing profiles retain the default that we removed.
- if (savedmstone)
- prefb.setBoolPref("browser.rights.3.shown", true);
-
- prefb.setCharPref("browser.startup.homepage_override.mstone", mstone);
- prefb.setCharPref("browser.startup.homepage_override.buildID", buildID);
- return (savedmstone ? OVERRIDE_NEW_MSTONE : OVERRIDE_NEW_PROFILE);
- }
-
- if (buildID != savedBuildID) {
- prefb.setCharPref("browser.startup.homepage_override.buildID", buildID);
- return OVERRIDE_NEW_BUILD_ID;
- }
-
- return OVERRIDE_NONE;
-}
-
-/**
- * Gets the override page for the first run after the application has been
- * updated.
- * @param defaultOverridePage
- * The default override page.
- * @return The override page.
- */
-function getPostUpdateOverridePage(defaultOverridePage) {
- var um = Components.classes["@mozilla.org/updates/update-manager;1"]
- .getService(Components.interfaces.nsIUpdateManager);
- try {
- // If the updates.xml file is deleted then getUpdateAt will throw.
- var update = um.getUpdateAt(0)
- .QueryInterface(Components.interfaces.nsIPropertyBag);
- } catch (e) {
- // This should never happen.
- Components.utils.reportError("Unable to find update: " + e);
- return defaultOverridePage;
- }
-
- let actions = update.getProperty("actions");
- // When the update doesn't specify actions fallback to the original behavior
- // of displaying the default override page.
- if (!actions)
- return defaultOverridePage;
-
- // The existence of silent or the non-existence of showURL in the actions both
- // mean that an override page should not be displayed.
- if (actions.indexOf("silent") != -1 || actions.indexOf("showURL") == -1)
- return "";
-
- return update.getProperty("openURL") || defaultOverridePage;
-}
-
-// Flag used to indicate that the arguments to openWindow can be passed directly.
-const NO_EXTERNAL_URIS = 1;
-
-function openWindow(parent, url, target, features, args, noExternalArgs) {
- var wwatch = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
- .getService(nsIWindowWatcher);
-
- if (noExternalArgs == NO_EXTERNAL_URIS) {
- // Just pass in the defaultArgs directly
- var argstring;
- if (args) {
- argstring = Components.classes["@mozilla.org/supports-string;1"]
- .createInstance(nsISupportsString);
- argstring.data = args;
- }
-
- return wwatch.openWindow(parent, url, target, features, argstring);
- }
-
- // Pass an array to avoid the browser "|"-splitting behavior.
- var argArray = Components.classes["@mozilla.org/supports-array;1"]
- .createInstance(Components.interfaces.nsISupportsArray);
-
- // add args to the arguments array
- var stringArgs = null;
- if (args instanceof Array) // array
- stringArgs = args;
- else if (args) // string
- stringArgs = [args];
-
- if (stringArgs) {
- // put the URIs into argArray
- var uriArray = Components.classes["@mozilla.org/supports-array;1"]
- .createInstance(Components.interfaces.nsISupportsArray);
- stringArgs.forEach(function (uri) {
- var sstring = Components.classes["@mozilla.org/supports-string;1"]
- .createInstance(nsISupportsString);
- sstring.data = uri;
- uriArray.AppendElement(sstring);
- });
- argArray.AppendElement(uriArray);
- } else {
- argArray.AppendElement(null);
- }
-
- // Pass these as null to ensure that we always trigger the "single URL"
- // behavior in browser.js's gBrowserInit.onLoad (which handles the window
- // arguments)
- argArray.AppendElement(null); // charset
- argArray.AppendElement(null); // referer
- argArray.AppendElement(null); // postData
- argArray.AppendElement(null); // allowThirdPartyFixup
-
- return wwatch.openWindow(parent, url, target, features, argArray);
-}
-
-function openPreferences() {
- var features = "chrome,titlebar,toolbar,centerscreen,dialog=no";
- var url = "chrome://browser/content/preferences/preferences.xul";
-
- var win = getMostRecentWindow("Browser:Preferences");
- if (win) {
- win.focus();
- } else {
- openWindow(null, url, "_blank", features);
- }
-}
-
-function getMostRecentWindow(aType) {
- var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
- .getService(nsIWindowMediator);
- return wm.getMostRecentWindow(aType);
-}
-
-function doSearch(searchTerm, cmdLine) {
- var ss = Components.classes["@mozilla.org/browser/search-service;1"]
- .getService(nsIBrowserSearchService);
-
- var submission = ss.defaultEngine.getSubmission(searchTerm);
-
- // fill our nsISupportsArray with uri-as-wstring, null, null, postData
- var sa = Components.classes["@mozilla.org/supports-array;1"]
- .createInstance(Components.interfaces.nsISupportsArray);
-
- var wuri = Components.classes["@mozilla.org/supports-string;1"]
- .createInstance(Components.interfaces.nsISupportsString);
- wuri.data = submission.uri.spec;
-
- sa.AppendElement(wuri);
- sa.AppendElement(null);
- sa.AppendElement(null);
- sa.AppendElement(submission.postData);
-
- // XXXbsmedberg: use handURIToExistingBrowser to obey tabbed-browsing
- // preferences, but need nsIBrowserDOMWindow extensions
-
- var wwatch = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
- .getService(nsIWindowWatcher);
-
- return wwatch.openWindow(null, gBrowserContentHandler.chromeURL,
- "_blank",
- "chrome,dialog=no,all" +
- gBrowserContentHandler.getFeatures(cmdLine),
- sa);
-}
-
-function nsBrowserContentHandler() {
-}
-nsBrowserContentHandler.prototype = {
- classID: Components.ID("{5d0ce354-df01-421a-83fb-7ead0990c24e}"),
-
- _xpcom_factory: {
- createInstance: function bch_factory_ci(outer, iid) {
- if (outer)
- throw Components.results.NS_ERROR_NO_AGGREGATION;
- return gBrowserContentHandler.QueryInterface(iid);
- }
- },
-
- /* helper functions */
-
- mChromeURL : null,
-
- get chromeURL() {
- if (this.mChromeURL) {
- return this.mChromeURL;
- }
-
- var prefb = Components.classes["@mozilla.org/preferences-service;1"]
- .getService(nsIPrefBranch);
- this.mChromeURL = prefb.getCharPref("browser.chromeURL");
-
- return this.mChromeURL;
- },
-
- /* nsISupports */
- QueryInterface : XPCOMUtils.generateQI([nsICommandLineHandler,
- nsIBrowserHandler,
- nsIContentHandler,
- nsICommandLineValidator]),
-
- /* nsICommandLineHandler */
- handle : function bch_handle(cmdLine) {
- if (cmdLine.handleFlag("browser", false)) {
- // Passing defaultArgs, so use NO_EXTERNAL_URIS
- openWindow(null, this.chromeURL, "_blank",
- "chrome,dialog=no,all" + this.getFeatures(cmdLine),
- this.defaultArgs, NO_EXTERNAL_URIS);
- cmdLine.preventDefault = true;
- }
-
- try {
- var remoteCommand = cmdLine.handleFlagWithParam("remote", true);
- }
- catch (e) {
- throw NS_ERROR_ABORT;
- }
-
- if (remoteCommand != null) {
- try {
- var a = /^\s*(\w+)\(([^\)]*)\)\s*$/.exec(remoteCommand);
- var remoteVerb;
- if (a) {
- remoteVerb = a[1].toLowerCase();
- var remoteParams = [];
- var sepIndex = a[2].lastIndexOf(",");
- if (sepIndex == -1)
- remoteParams[0] = a[2];
- else {
- remoteParams[0] = a[2].substring(0, sepIndex);
- remoteParams[1] = a[2].substring(sepIndex + 1);
- }
- }
-
- switch (remoteVerb) {
- case "openurl":
- case "openfile":
- // openURL(<url>)
- // openURL(<url>,new-window)
- // openURL(<url>,new-tab)
-
- // First param is the URL, second param (if present) is the "target"
- // (tab, window)
- var url = remoteParams[0];
- var target = nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW;
- if (remoteParams[1]) {
- var targetParam = remoteParams[1].toLowerCase()
- .replace(/^\s*|\s*$/g, "");
- if (targetParam == "new-tab")
- target = nsIBrowserDOMWindow.OPEN_NEWTAB;
- else if (targetParam == "new-window")
- target = nsIBrowserDOMWindow.OPEN_NEWWINDOW;
- else {
- // The "target" param isn't one of our supported values, so
- // assume it's part of a URL that contains commas.
- url += "," + remoteParams[1];
- }
- }
-
- var uri = resolveURIInternal(cmdLine, url);
- handURIToExistingBrowser(uri, target, cmdLine);
- break;
-
- case "xfedocommand":
- // xfeDoCommand(openBrowser)
- if (remoteParams[0].toLowerCase() != "openbrowser")
- throw NS_ERROR_ABORT;
-
- // Passing defaultArgs, so use NO_EXTERNAL_URIS
- openWindow(null, this.chromeURL, "_blank",
- "chrome,dialog=no,all" + this.getFeatures(cmdLine),
- this.defaultArgs, NO_EXTERNAL_URIS);
- break;
-
- default:
- // Somebody sent us a remote command we don't know how to process:
- // just abort.
- throw "Unknown remote command.";
- }
-
- cmdLine.preventDefault = true;
- }
- catch (e) {
- Components.utils.reportError(e);
- // If we had a -remote flag but failed to process it, throw
- // NS_ERROR_ABORT so that the xremote code knows to return a failure
- // back to the handling code.
- throw NS_ERROR_ABORT;
- }
- }
-
- var uriparam;
- try {
- while ((uriparam = cmdLine.handleFlagWithParam("new-window", false))) {
- var uri = resolveURIInternal(cmdLine, uriparam);
- if (!shouldLoadURI(uri))
- continue;
- openWindow(null, this.chromeURL, "_blank",
- "chrome,dialog=no,all" + this.getFeatures(cmdLine),
- uri.spec);
- cmdLine.preventDefault = true;
- }
- }
- catch (e) {
- Components.utils.reportError(e);
- }
-
- try {
- while ((uriparam = cmdLine.handleFlagWithParam("new-tab", false))) {
- var uri = resolveURIInternal(cmdLine, uriparam);
- handURIToExistingBrowser(uri, nsIBrowserDOMWindow.OPEN_NEWTAB, cmdLine);
- cmdLine.preventDefault = true;
- }
- }
- catch (e) {
- Components.utils.reportError(e);
- }
-
- var chromeParam = cmdLine.handleFlagWithParam("chrome", false);
- if (chromeParam) {
-
- // Handle the old preference dialog URL separately (bug 285416)
- if (chromeParam == "chrome://browser/content/pref/pref.xul") {
- openPreferences();
- cmdLine.preventDefault = true;
- } else try {
- // only load URIs which do not inherit chrome privs
- var features = "chrome,dialog=no,all" + this.getFeatures(cmdLine);
- var uri = resolveURIInternal(cmdLine, chromeParam);
- var netutil = Components.classes["@mozilla.org/network/util;1"]
- .getService(nsINetUtil);
- if (!netutil.URIChainHasFlags(uri, URI_INHERITS_SECURITY_CONTEXT)) {
- openWindow(null, uri.spec, "_blank", features);
- cmdLine.preventDefault = true;
- }
- }
- catch (e) {
- Components.utils.reportError(e);
- }
- }
- if (cmdLine.handleFlag("preferences", false)) {
- openPreferences();
- cmdLine.preventDefault = true;
- }
- if (cmdLine.handleFlag("silent", false))
- cmdLine.preventDefault = true;
-
- try {
- var privateWindowParam = cmdLine.handleFlagWithParam("private-window", false);
- if (privateWindowParam) {
- let resolvedURI = resolveURIInternal(cmdLine, privateWindowParam);
- handURIToExistingBrowser(resolvedURI, nsIBrowserDOMWindow.OPEN_NEWTAB, cmdLine, true);
- cmdLine.preventDefault = true;
- }
- } catch (e) {
- if (e.result != Components.results.NS_ERROR_INVALID_ARG) {
- throw e;
- }
- // NS_ERROR_INVALID_ARG is thrown when flag exists, but has no param.
- if (cmdLine.handleFlag("private-window", false)) {
- openWindow(null, this.chromeURL, "_blank",
- "chrome,dialog=no,private,all" + this.getFeatures(cmdLine),
- "about:privatebrowsing");
- cmdLine.preventDefault = true;
- }
- }
-
- var searchParam = cmdLine.handleFlagWithParam("search", false);
- if (searchParam) {
- doSearch(searchParam, cmdLine);
- cmdLine.preventDefault = true;
- }
-
- // The global PB Service consumes this flag, so only eat it in per-window
- // PB builds.
- if (cmdLine.handleFlag("private", false)) {
- PrivateBrowsingUtils.enterTemporaryAutoStartMode();
- }
-
- var fileParam = cmdLine.handleFlagWithParam("file", false);
- if (fileParam) {
- var file = cmdLine.resolveFile(fileParam);
- var ios = Components.classes["@mozilla.org/network/io-service;1"]
- .getService(Components.interfaces.nsIIOService);
- var uri = ios.newFileURI(file);
- openWindow(null, this.chromeURL, "_blank",
- "chrome,dialog=no,all" + this.getFeatures(cmdLine),
- uri.spec);
- cmdLine.preventDefault = true;
- }
-
-#ifdef XP_WIN
- // Handle "? searchterm" for Windows Vista start menu integration
- for (var i = cmdLine.length - 1; i >= 0; --i) {
- var param = cmdLine.getArgument(i);
- if (param.match(/^\? /)) {
- cmdLine.removeArguments(i, i);
- cmdLine.preventDefault = true;
-
- searchParam = param.substr(2);
- doSearch(searchParam, cmdLine);
- }
- }
-#endif
- },
-
- helpInfo : " --browser Open a browser window.\n" +
- " --new-window <url> Open <url> in a new window.\n" +
- " --new-tab <url> Open <url> in a new tab.\n" +
- " --private-window <url> Open <url> in a new private window.\n" +
-#ifdef XP_WIN
- " --preferences Open Options dialog.\n" +
-#else
- " --preferences Open Preferences dialog.\n" +
-#endif
- " --search <term> Search <term> with your default search engine.\n",
-
- /* nsIBrowserHandler */
-
- get defaultArgs() {
- var prefb = Components.classes["@mozilla.org/preferences-service;1"]
- .getService(nsIPrefBranch);
-
- if (!gFirstWindow) {
- gFirstWindow = true;
- if (PrivateBrowsingUtils.isInTemporaryAutoStartMode) {
- return "about:privatebrowsing";
- }
- }
-
- var overridePage = "";
- var haveUpdateSession = false;
- try {
- // Read the old value of homepage_override.mstone before
- // needHomepageOverride updates it, so that we can later add it to the
- // URL if we do end up showing an overridePage. This makes it possible
- // to have the overridePage's content vary depending on the version we're
- // upgrading from.
- let old_mstone = Services.prefs.getCharPref("browser.startup.homepage_override.mstone", "unknown");
- let override = needHomepageOverride(prefb);
- if (override != OVERRIDE_NONE) {
- switch (override) {
- case OVERRIDE_NEW_PROFILE:
- // New profile.
- overridePage = Services.urlFormatter.formatURLPref("startup.homepage_welcome_url");
- break;
- case OVERRIDE_NEW_MSTONE:
- // Check whether we have a session to restore. If we do, we assume
- // that this is an "update" session.
- var ss = Components.classes["@mozilla.org/browser/sessionstartup;1"]
- .getService(Components.interfaces.nsISessionStartup);
- haveUpdateSession = ss.doRestore();
- overridePage = Services.urlFormatter.formatURLPref("startup.homepage_override_url");
- if (prefb.prefHasUserValue("app.update.postupdate"))
- overridePage = getPostUpdateOverridePage(overridePage);
-
- overridePage = overridePage.replace("%OLD_VERSION%", old_mstone);
- break;
- }
- }
- } catch (ex) {}
-
- // formatURLPref might return "about:blank" if getting the pref fails
- if (overridePage == "about:blank")
- overridePage = "";
-
- var startPage = "";
- try {
- var choice = prefb.getIntPref("browser.startup.page");
- if (choice == 1 || choice == 3)
- startPage = this.startPage;
- } catch (e) {
- Components.utils.reportError(e);
- }
-
- // Only show the startPage if we're not restoring an update session.
- if (overridePage && startPage && !haveUpdateSession)
- return overridePage + "|" + startPage;
-
- return overridePage || startPage || "about:logopage";
- },
-
- get startPage() {
- var uri = Services.prefs.getComplexValue("browser.startup.homepage",
- nsIPrefLocalizedString).data;
- if (!uri) {
- Services.prefs.clearUserPref("browser.startup.homepage");
- uri = Services.prefs.getComplexValue("browser.startup.homepage",
- nsIPrefLocalizedString).data;
- }
- return uri;
- },
-
- mFeatures : null,
-
- getFeatures : function bch_features(cmdLine) {
- if (this.mFeatures === null) {
- this.mFeatures = "";
-
- try {
- var width = cmdLine.handleFlagWithParam("width", false);
- var height = cmdLine.handleFlagWithParam("height", false);
-
- if (width)
- this.mFeatures += ",width=" + width;
- if (height)
- this.mFeatures += ",height=" + height;
- }
- catch (e) {
- }
-
- // The global PB Service consumes this flag, so only eat it in per-window
- // PB builds.
- if (PrivateBrowsingUtils.isInTemporaryAutoStartMode) {
- this.mFeatures = ",private";
- }
- }
-
- return this.mFeatures;
- },
-
- /* nsIContentHandler */
-
- handleContent : function bch_handleContent(contentType, context, request) {
- try {
- var webNavInfo = Components.classes["@mozilla.org/webnavigation-info;1"]
- .getService(nsIWebNavigationInfo);
- if (!webNavInfo.isTypeSupported(contentType, null)) {
- throw NS_ERROR_WONT_HANDLE_CONTENT;
- }
- } catch (e) {
- throw NS_ERROR_WONT_HANDLE_CONTENT;
- }
-
- request.QueryInterface(nsIChannel);
- handURIToExistingBrowser(request.URI,
- nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW, null);
- request.cancel(NS_BINDING_ABORTED);
- },
-
- /* nsICommandLineValidator */
- validate : function bch_validate(cmdLine) {
- // Other handlers may use osint so only handle the osint flag if the url
- // flag is also present and the command line is valid.
- var osintFlagIdx = cmdLine.findFlag("osint", false);
- var urlFlagIdx = cmdLine.findFlag("url", false);
- if (urlFlagIdx > -1 && (osintFlagIdx > -1 ||
- cmdLine.state == nsICommandLine.STATE_REMOTE_EXPLICIT)) {
- var urlParam = cmdLine.getArgument(urlFlagIdx + 1);
- if (cmdLine.length != urlFlagIdx + 2 || /firefoxurl:/.test(urlParam))
- throw NS_ERROR_ABORT;
- cmdLine.handleFlag("osint", false)
- }
- },
-};
-var gBrowserContentHandler = new nsBrowserContentHandler();
-
-function handURIToExistingBrowser(uri, location, cmdLine, forcePrivate)
-{
- if (!shouldLoadURI(uri))
- return;
-
- // Unless using a private window is forced, open external links in private
- // windows only if we're in perma-private mode.
- var allowPrivate = forcePrivate || PrivateBrowsingUtils.permanentPrivateBrowsing;
- var navWin = RecentWindow.getMostRecentBrowserWindow({private: allowPrivate});
- if (!navWin) {
- // if we couldn't load it in an existing window, open a new one
- var features = "chrome,dialog=no,all" + gBrowserContentHandler.getFeatures(cmdLine);
- if (forcePrivate) {
- features += ",private";
- }
- openWindow(null, gBrowserContentHandler.chromeURL, "_blank", features, uri.spec);
- return;
- }
-
- var navNav = navWin.QueryInterface(nsIInterfaceRequestor)
- .getInterface(nsIWebNavigation);
- var rootItem = navNav.QueryInterface(nsIDocShellTreeItem).rootTreeItem;
- var rootWin = rootItem.QueryInterface(nsIInterfaceRequestor)
- .getInterface(nsIDOMWindow);
- var bwin = rootWin.QueryInterface(nsIDOMChromeWindow).browserDOMWindow;
- bwin.openURI(uri, null, location,
- nsIBrowserDOMWindow.OPEN_EXTERNAL);
-}
-
-function nsDefaultCommandLineHandler() {
-}
-
-nsDefaultCommandLineHandler.prototype = {
- classID: Components.ID("{47cd0651-b1be-4a0f-b5c4-10e5a573ef71}"),
-
- /* nsISupports */
- QueryInterface : function dch_QI(iid) {
- if (!iid.equals(nsISupports) &&
- !iid.equals(nsICommandLineHandler))
- throw Components.results.NS_ERROR_NO_INTERFACE;
-
- return this;
- },
-
-#ifdef XP_WIN
- _haveProfile: false,
-#endif
-
- /* nsICommandLineHandler */
- handle : function dch_handle(cmdLine) {
- var urilist = [];
-
-#ifdef XP_WIN
- // If we don't have a profile selected yet (e.g. the Profile Manager is
- // displayed) we will crash if we open an url and then select a profile. To
- // prevent this handle all url command line flags and set the command line's
- // preventDefault to true to prevent the display of the ui. The initial
- // command line will be retained when nsAppRunner calls LaunchChild though
- // urls launched after the initial launch will be lost.
- if (!this._haveProfile) {
- try {
- // This will throw when a profile has not been selected.
- var fl = Components.classes["@mozilla.org/file/directory_service;1"]
- .getService(Components.interfaces.nsIProperties);
- var dir = fl.get("ProfD", Components.interfaces.nsILocalFile);
- this._haveProfile = true;
- }
- catch (e) {
- while ((ar = cmdLine.handleFlagWithParam("url", false))) { }
- cmdLine.preventDefault = true;
- }
- }
-#endif
-
- try {
- var ar;
- while ((ar = cmdLine.handleFlagWithParam("url", false))) {
- var uri = resolveURIInternal(cmdLine, ar);
- urilist.push(uri);
- }
- }
- catch (e) {
- Components.utils.reportError(e);
- }
-
- let count = cmdLine.length;
-
- for (let i = 0; i < count; ++i) {
- var curarg = cmdLine.getArgument(i);
- if (curarg.match(/^-/)) {
- Components.utils.reportError("Warning: unrecognized command line flag " + curarg + "\n");
- // To emulate the pre-nsICommandLine behavior, we ignore
- // the argument after an unrecognized flag.
- ++i;
- } else {
- try {
- urilist.push(resolveURIInternal(cmdLine, curarg));
- }
- catch (e) {
- Components.utils.reportError("Error opening URI '" + curarg + "' from the command line: " + e + "\n");
- }
- }
- }
-
- if (urilist.length) {
- if (cmdLine.state != nsICommandLine.STATE_INITIAL_LAUNCH &&
- urilist.length == 1) {
- // Try to find an existing window and load our URI into the
- // current tab, new tab, or new window as prefs determine.
- try {
- handURIToExistingBrowser(urilist[0], nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW, cmdLine);
- return;
- }
- catch (e) {
- }
- }
-
- var URLlist = urilist.filter(shouldLoadURI).map(function (u) u.spec);
- if (URLlist.length) {
- openWindow(null, gBrowserContentHandler.chromeURL, "_blank",
- "chrome,dialog=no,all" + gBrowserContentHandler.getFeatures(cmdLine),
- URLlist);
- }
-
- }
- else if (!cmdLine.preventDefault) {
- // Passing defaultArgs, so use NO_EXTERNAL_URIS
- openWindow(null, gBrowserContentHandler.chromeURL, "_blank",
- "chrome,dialog=no,all" + gBrowserContentHandler.getFeatures(cmdLine),
- gBrowserContentHandler.defaultArgs, NO_EXTERNAL_URIS);
- }
- },
-
- helpInfo : "",
-};
-
-var components = [nsBrowserContentHandler, nsDefaultCommandLineHandler];
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
diff --git a/components/nsBrowserGlue.js b/components/nsBrowserGlue.js
deleted file mode 100644
index e8eefa4..0000000
--- a/components/nsBrowserGlue.js
+++ /dev/null
@@ -1,1867 +0,0 @@
-# -*- indent-tabs-mode: nil -*-
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-const Ci = Components.interfaces;
-const Cc = Components.classes;
-const Cr = Components.results;
-const Cu = Components.utils;
-
-const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-
-// Define Lazy Service Getters
-XPCOMUtils.defineLazyServiceGetter(this, "AlertsService",
- "@mozilla.org/alerts-service;1", "nsIAlertsService");
-
-// Define Lazy Module Getters
-[
- ["AddonManager", "resource://gre/modules/AddonManager.jsm"],
- ["NetUtil", "resource://gre/modules/NetUtil.jsm"],
- ["UserAgentOverrides", "resource://gre/modules/UserAgentOverrides.jsm"],
- ["FileUtils", "resource://gre/modules/FileUtils.jsm"],
- ["PlacesUtils", "resource://gre/modules/PlacesUtils.jsm"],
- ["BookmarkHTMLUtils", "resource://gre/modules/BookmarkHTMLUtils.jsm"],
- ["BookmarkJSONUtils", "resource://gre/modules/BookmarkJSONUtils.jsm"],
- ["PageThumbs", "resource://gre/modules/PageThumbs.jsm"],
- ["NewTabUtils", "resource://gre/modules/NewTabUtils.jsm"],
- ["BrowserNewTabPreloader", "resource:///modules/BrowserNewTabPreloader.jsm"],
-#ifdef MOZ_WEBRTC
- ["webrtcUI", "resource:///modules/webrtcUI.jsm"],
-#endif
- ["PrivateBrowsingUtils", "resource://gre/modules/PrivateBrowsingUtils.jsm"],
- ["RecentWindow", "resource:///modules/RecentWindow.jsm"],
- ["Task", "resource://gre/modules/Task.jsm"],
- ["PlacesBackups", "resource://gre/modules/PlacesBackups.jsm"],
- ["OS", "resource://gre/modules/osfile.jsm"],
- ["LoginManagerParent", "resource://gre/modules/LoginManagerParent.jsm"],
- ["FormValidationHandler", "resource:///modules/FormValidationHandler.jsm"],
- ["AutoCompletePopup", "resource:///modules/AutoCompletePopup.jsm"],
- ["DateTimePickerHelper", "resource://gre/modules/DateTimePickerHelper.jsm"],
- ["ShellService", "resource:///modules/ShellService.jsm"],
-].forEach(([name, resource]) => XPCOMUtils.defineLazyModuleGetter(this, name, resource));
-
-// Define Lazy Getters
-
-XPCOMUtils.defineLazyGetter(this, "gBrandBundle", function() {
- return Services.strings.createBundle('chrome://branding/locale/brand.properties');
-});
-
-XPCOMUtils.defineLazyGetter(this, "gBrowserBundle", function() {
- return Services.strings.createBundle('chrome://browser/locale/browser.properties');
-});
-
-const PREF_PLUGINS_NOTIFYUSER = "plugins.update.notifyUser";
-const PREF_PLUGINS_UPDATEURL = "plugins.update.url";
-
-// We try to backup bookmarks at idle times, to avoid doing that at shutdown.
-// Number of idle seconds before trying to backup bookmarks. 15 minutes.
-const BOOKMARKS_BACKUP_IDLE_TIME = 15 * 60;
-// Minimum interval in milliseconds between backups.
-const BOOKMARKS_BACKUP_INTERVAL = 86400 * 1000;
-// Maximum number of backups to create. Old ones will be purged.
-const BOOKMARKS_BACKUP_MAX_BACKUPS = 10;
-
-// Factory object
-const BrowserGlueServiceFactory = {
- _instance: null,
- createInstance: function BGSF_createInstance(outer, iid) {
- if (outer != null)
- throw Components.results.NS_ERROR_NO_AGGREGATION;
- return this._instance == null ?
- this._instance = new BrowserGlue() : this._instance;
- }
-};
-
-// Constructor
-
-function BrowserGlue() {
- XPCOMUtils.defineLazyServiceGetter(this, "_idleService",
- "@mozilla.org/widget/idleservice;1",
- "nsIIdleService");
-
- XPCOMUtils.defineLazyGetter(this, "_distributionCustomizer", function() {
- Cu.import("resource:///modules/distribution.js");
- return new DistributionCustomizer();
- });
-
- XPCOMUtils.defineLazyGetter(this, "_sanitizer",
- function() {
- let sanitizerScope = {};
- Services.scriptloader.loadSubScript("chrome://browser/content/sanitize.js", sanitizerScope);
- return sanitizerScope.Sanitizer;
- });
-
- this._init();
-}
-
-#ifndef XP_MACOSX
-# OS X has the concept of zero-window sessions and therefore ignores the
-# browser-lastwindow-close-* topics.
-#define OBSERVE_LASTWINDOW_CLOSE_TOPICS 1
-#endif
-
-BrowserGlue.prototype = {
- _saveSession: false,
- _isIdleObserver: false,
- _isPlacesInitObserver: false,
- _isPlacesLockedObserver: false,
- _isPlacesShutdownObserver: false,
- _isPlacesDatabaseLocked: false,
- _migrationImportsDefaultBookmarks: false,
-
- _setPrefToSaveSession: function BG__setPrefToSaveSession(aForce) {
- if (!this._saveSession && !aForce)
- return;
-
- Services.prefs.setBoolPref("browser.sessionstore.resume_session_once", true);
-
- // This method can be called via [NSApplication terminate:] on Mac, which
- // ends up causing prefs not to be flushed to disk, so we need to do that
- // explicitly here. See bug 497652.
- Services.prefs.savePrefFile(null);
- },
-
-#ifdef MOZ_SERVICES_SYNC
- _setSyncAutoconnectDelay: function BG__setSyncAutoconnectDelay() {
- // Assume that a non-zero value for services.sync.autoconnectDelay should override
- if (Services.prefs.prefHasUserValue("services.sync.autoconnectDelay")) {
- let prefDelay = Services.prefs.getIntPref("services.sync.autoconnectDelay");
-
- if (prefDelay > 0)
- return;
- }
-
- // delays are in seconds
- const MAX_DELAY = 300;
- let delay = 3;
- let browserEnum = Services.wm.getEnumerator("navigator:browser");
- while (browserEnum.hasMoreElements()) {
- delay += browserEnum.getNext().gBrowser.tabs.length;
- }
- delay = delay <= MAX_DELAY ? delay : MAX_DELAY;
-
- Cu.import("resource://services-sync/main.js");
- Weave.Service.scheduler.delayedAutoConnect(delay);
- },
-#endif
-
- // nsIObserver implementation
- observe: function BG_observe(subject, topic, data) {
- switch (topic) {
- case "notifications-open-settings":
- this._openPermissions(subject);
- break;
- case "prefservice:after-app-defaults":
- this._onAppDefaults();
- break;
- case "final-ui-startup":
- this._finalUIStartup();
- break;
- case "browser-delayed-startup-finished":
- this._onFirstWindowLoaded();
- Services.obs.removeObserver(this, "browser-delayed-startup-finished");
- break;
- case "sessionstore-windows-restored":
- this._onWindowsRestored();
- break;
- case "browser:purge-session-history":
- // reset the console service's error buffer
- Services.console.logStringMessage(null); // clear the console (in case it's open)
- Services.console.reset();
- break;
- case "quit-application-requested":
- this._onQuitRequest(subject, data);
- break;
- case "quit-application-granted":
- // This pref must be set here because SessionStore will use its value
- // on quit-application.
- this._setPrefToSaveSession();
- try {
- let appStartup = Cc["@mozilla.org/toolkit/app-startup;1"].
- getService(Ci.nsIAppStartup);
- appStartup.trackStartupCrashEnd();
- } catch (e) {
- Cu.reportError("Could not end startup crash tracking in quit-application-granted: " + e);
- }
- DateTimePickerHelper.uninit();
- break;
-#ifdef OBSERVE_LASTWINDOW_CLOSE_TOPICS
- case "browser-lastwindow-close-requested":
- // The application is not actually quitting, but the last full browser
- // window is about to be closed.
- this._onQuitRequest(subject, "lastwindow");
- break;
- case "browser-lastwindow-close-granted":
- this._setPrefToSaveSession();
- break;
-#endif
-#ifdef MOZ_SERVICES_SYNC
- case "weave:service:ready":
- this._setSyncAutoconnectDelay();
- break;
- case "weave:engine:clients:display-uri":
- this._onDisplaySyncURI(subject);
- break;
-#endif
- case "session-save":
- this._setPrefToSaveSession(true);
- subject.QueryInterface(Ci.nsISupportsPRBool);
- subject.data = true;
- break;
- case "places-init-complete":
- if (!this._migrationImportsDefaultBookmarks)
- this._initPlaces(false);
-
- Services.obs.removeObserver(this, "places-init-complete");
- this._isPlacesInitObserver = false;
- // no longer needed, since history was initialized completely.
- Services.obs.removeObserver(this, "places-database-locked");
- this._isPlacesLockedObserver = false;
- break;
- case "places-database-locked":
- this._isPlacesDatabaseLocked = true;
- // Stop observing, so further attempts to load history service
- // will not show the prompt.
- Services.obs.removeObserver(this, "places-database-locked");
- this._isPlacesLockedObserver = false;
- break;
- case "places-shutdown":
- if (this._isPlacesShutdownObserver) {
- Services.obs.removeObserver(this, "places-shutdown");
- this._isPlacesShutdownObserver = false;
- }
- // places-shutdown is fired when the profile is about to disappear.
- this._onPlacesShutdown();
- break;
- case "idle":
- if ((this._idleService.idleTime > BOOKMARKS_BACKUP_IDLE_TIME * 1000) &&
- this._shouldBackupBookmarks())
- this._backupBookmarks();
- break;
- case "distribution-customization-complete":
- Services.obs.removeObserver(this, "distribution-customization-complete");
- // Customization has finished, we don't need the customizer anymore.
- delete this._distributionCustomizer;
- break;
- case "browser-glue-test": // used by tests
- if (data == "post-update-notification") {
- if (Services.prefs.prefHasUserValue("app.update.postupdate"))
- this._showUpdateNotification();
- }
- else if (data == "force-ui-migration") {
- this._migrateUI();
- }
- else if (data == "force-distribution-customization") {
- this._distributionCustomizer.applyPrefDefaults();
- this._distributionCustomizer.applyCustomizations();
- // To apply distribution bookmarks use "places-init-complete".
- }
- else if (data == "force-places-init") {
- this._initPlaces(false);
- }
- break;
- case "initial-migration-will-import-default-bookmarks":
- this._migrationImportsDefaultBookmarks = true;
- break;
- case "initial-migration-did-import-default-bookmarks":
- this._initPlaces(true);
- break;
- case "handle-xul-text-link":
- let linkHandled = subject.QueryInterface(Ci.nsISupportsPRBool);
- if (!linkHandled.data) {
- let win = this.getMostRecentBrowserWindow();
- if (win) {
- data = JSON.parse(data);
- win.openUILinkIn(data.href, "tab");
- linkHandled.data = true;
- }
- }
- break;
- case "profile-before-change":
- this._onProfileShutdown();
- break;
- case "browser-search-engine-modified":
- if (data != "engine-default" && data != "engine-current") {
- break;
- }
- // Enforce that the search service's defaultEngine is always equal to
- // its currentEngine. The search service will notify us any time either
- // of them are changed (either by directly setting the relevant prefs,
- // i.e. if add-ons try to change this directly, or if the
- // nsIBrowserSearchService setters are called).
- // No need to initialize the search service, since it's guaranteed to be
- // initialized already when this notification fires.
- let ss = Services.search;
- if (ss.currentEngine.name == ss.defaultEngine.name)
- return;
- if (data == "engine-current")
- ss.defaultEngine = ss.currentEngine;
- else
- ss.currentEngine = ss.defaultEngine;
- break;
- case "browser-search-service":
- if (data != "init-complete")
- return;
- Services.obs.removeObserver(this, "browser-search-service");
- this._syncSearchEngines();
- break;
- }
- },
-
- _syncSearchEngines: function () {
- // Only do this if the search service is already initialized. This function
- // gets called in finalUIStartup and from a browser-search-service observer,
- // to catch both cases (search service initialization occurring before and
- // after final-ui-startup)
- if (Services.search.isInitialized) {
- Services.search.defaultEngine = Services.search.currentEngine;
- }
- },
-
- // initialization (called on application startup)
- _init: function BG__init() {
- let os = Services.obs;
- os.addObserver(this, "notifications-open-settings", false);
- os.addObserver(this, "prefservice:after-app-defaults", false);
- os.addObserver(this, "final-ui-startup", false);
- os.addObserver(this, "browser-delayed-startup-finished", false);
- os.addObserver(this, "sessionstore-windows-restored", false);
- os.addObserver(this, "browser:purge-session-history", false);
- os.addObserver(this, "quit-application-requested", false);
- os.addObserver(this, "quit-application-granted", false);
-#ifdef OBSERVE_LASTWINDOW_CLOSE_TOPICS
- os.addObserver(this, "browser-lastwindow-close-requested", false);
- os.addObserver(this, "browser-lastwindow-close-granted", false);
-#endif
-#ifdef MOZ_SERVICES_SYNC
- os.addObserver(this, "weave:service:ready", false);
- os.addObserver(this, "weave:engine:clients:display-uri", false);
-#endif
- os.addObserver(this, "session-save", false);
- os.addObserver(this, "places-init-complete", false);
- this._isPlacesInitObserver = true;
- os.addObserver(this, "places-database-locked", false);
- this._isPlacesLockedObserver = true;
- os.addObserver(this, "distribution-customization-complete", false);
- os.addObserver(this, "places-shutdown", false);
- this._isPlacesShutdownObserver = true;
- os.addObserver(this, "handle-xul-text-link", false);
- os.addObserver(this, "profile-before-change", false);
- os.addObserver(this, "browser-search-engine-modified", false);
- os.addObserver(this, "browser-search-service", false);
- },
-
- // cleanup (called on application shutdown)
- _dispose: function BG__dispose() {
- let os = Services.obs;
- os.removeObserver(this, "notifications-open-settings");
- os.removeObserver(this, "prefservice:after-app-defaults");
- os.removeObserver(this, "final-ui-startup");
- os.removeObserver(this, "sessionstore-windows-restored");
- os.removeObserver(this, "browser:purge-session-history");
- os.removeObserver(this, "quit-application-requested");
- os.removeObserver(this, "quit-application-granted");
-#ifdef OBSERVE_LASTWINDOW_CLOSE_TOPICS
- os.removeObserver(this, "browser-lastwindow-close-requested");
- os.removeObserver(this, "browser-lastwindow-close-granted");
-#endif
-#ifdef MOZ_SERVICES_SYNC
- os.removeObserver(this, "weave:service:ready");
- os.removeObserver(this, "weave:engine:clients:display-uri");
-#endif
- os.removeObserver(this, "session-save");
- if (this._isIdleObserver)
- this._idleService.removeIdleObserver(this, BOOKMARKS_BACKUP_IDLE_TIME);
- if (this._isPlacesInitObserver)
- os.removeObserver(this, "places-init-complete");
- if (this._isPlacesLockedObserver)
- os.removeObserver(this, "places-database-locked");
- if (this._isPlacesShutdownObserver)
- os.removeObserver(this, "places-shutdown");
- os.removeObserver(this, "handle-xul-text-link");
- os.removeObserver(this, "profile-before-change");
- os.removeObserver(this, "browser-search-engine-modified");
- try {
- os.removeObserver(this, "browser-search-service");
- // may have already been removed by the observer
- } catch (ex) {}
- },
-
- _onAppDefaults: function BG__onAppDefaults() {
- // apply distribution customizations (prefs)
- // other customizations are applied in _finalUIStartup()
- this._distributionCustomizer.applyPrefDefaults();
- },
-
- // runs on startup, before the first command line handler is invoked
- // (i.e. before the first window is opened)
- _finalUIStartup: function BG__finalUIStartup() {
- this._sanitizer.onStartup();
- // check if we're in safe mode
- if (Services.appinfo.inSafeMode) {
- Services.ww.openWindow(null, "chrome://browser/content/safeMode.xul",
- "_blank", "chrome,centerscreen,modal,resizable=no", null);
- }
-
- // apply distribution customizations
- // prefs are applied in _onAppDefaults()
- this._distributionCustomizer.applyCustomizations();
-
- // handle any UI migration
- this._migrateUI();
-
- this._setUpUserAgentOverrides();
-
- this._syncSearchEngines();
-
- PageThumbs.init();
- NewTabUtils.init();
- BrowserNewTabPreloader.init();
-#ifdef MOZ_WEBRTC
- webrtcUI.init();
-#endif
- FormValidationHandler.init();
-
- AutoCompletePopup.init();
-
- LoginManagerParent.init();
-
- Services.obs.notifyObservers(null, "browser-ui-startup-complete", "");
- },
-
- _setUpUserAgentOverrides: function BG__setUpUserAgentOverrides() {
- UserAgentOverrides.init();
-
- if (Services.prefs.getBoolPref("general.useragent.complexOverride.moodle")) {
- UserAgentOverrides.addComplexOverride(function (aHttpChannel, aOriginalUA) {
- let cookies;
- try {
- cookies = aHttpChannel.getRequestHeader("Cookie");
- } catch (e) { /* no cookie sent */ }
- if (cookies && cookies.indexOf("MoodleSession") > -1)
- return aOriginalUA.replace(/Goanna\/[^ ]*/, "Goanna/20100101");
- return null;
- });
- }
- },
-
- _trackSlowStartup: function () {
- if (Services.startup.interrupted ||
- Services.prefs.getBoolPref("browser.slowStartup.notificationDisabled"))
- return;
-
- let currentTime = Date.now() - Services.startup.getStartupInfo().process;
- let averageTime = 0;
- let samples = 0;
- try {
- averageTime = Services.prefs.getIntPref("browser.slowStartup.averageTime");
- samples = Services.prefs.getIntPref("browser.slowStartup.samples");
- } catch (e) { }
-
- averageTime = (averageTime * samples + currentTime) / ++samples;
-
- if (samples >= Services.prefs.getIntPref("browser.slowStartup.maxSamples")) {
- if (averageTime > Services.prefs.getIntPref("browser.slowStartup.timeThreshold"))
- this._showSlowStartupNotification();
- averageTime = 0;
- samples = 0;
- }
-
- Services.prefs.setIntPref("browser.slowStartup.averageTime", averageTime);
- Services.prefs.setIntPref("browser.slowStartup.samples", samples);
- },
-
- _showSlowStartupNotification: function () {
- let win = this.getMostRecentBrowserWindow();
- if (!win)
- return;
-
- let productName = gBrandBundle.GetStringFromName("brandFullName");
- let message = win.gNavigatorBundle.getFormattedString("slowStartup.message", [productName]);
-
- let buttons = [
- {
- label: win.gNavigatorBundle.getString("slowStartup.helpButton.label"),
- accessKey: win.gNavigatorBundle.getString("slowStartup.helpButton.accesskey"),
- callback: function () {
- win.openUILinkIn(Services.prefs.getCharPref("browser.slowstartup.help.url"), "tab");
- }
- },
- {
- label: win.gNavigatorBundle.getString("slowStartup.disableNotificationButton.label"),
- accessKey: win.gNavigatorBundle.getString("slowStartup.disableNotificationButton.accesskey"),
- callback: function () {
- Services.prefs.setBoolPref("browser.slowStartup.notificationDisabled", true);
- }
- }
- ];
-
- let nb = win.document.getElementById("global-notificationbox");
- nb.appendNotification(message, "slow-startup",
- "chrome://browser/skin/slowStartup-16.png",
- nb.PRIORITY_INFO_LOW, buttons);
- },
-
- // the first browser window has finished initializing
- _onFirstWindowLoaded: function BG__onFirstWindowLoaded() {
-#ifdef XP_WIN
- // For windows seven, initialize the jump list module.
- 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:///modules/WindowsJumpLists.jsm", temp);
- temp.WinTaskbarJumpList.startup();
- }
-#endif
-
- DateTimePickerHelper.init();
-
- this._trackSlowStartup();
- },
-
- /**
- * Profile shutdown handler (contains profile cleanup routines).
- * All components depending on Places should be shut down in
- * _onPlacesShutdown() and not here.
- */
- _onProfileShutdown: function BG__onProfileShutdown() {
- BrowserNewTabPreloader.uninit();
- UserAgentOverrides.uninit();
-#ifdef MOZ_WEBRTC
- webrtcUI.uninit();
-#endif
- FormValidationHandler.uninit();
- AutoCompletePopup.uninit();
- this._dispose();
- },
-
- // All initial windows have opened.
- _onWindowsRestored: function BG__onWindowsRestored() {
- // Show update notification, if needed.
- if (Services.prefs.prefHasUserValue("app.update.postupdate"))
- this._showUpdateNotification();
-
- // Load the "more info" page for a locked places.sqlite
- // This property is set earlier by places-database-locked topic.
- if (this._isPlacesDatabaseLocked) {
- this._showPlacesLockedNotificationBox();
- }
-
- // For any add-ons that were installed disabled and can be enabled offer
- // them to the user.
- let changedIDs = AddonManager.getStartupChanges(AddonManager.STARTUP_CHANGE_INSTALLED);
- if (changedIDs.length > 0) {
- let win = this.getMostRecentBrowserWindow();
- AddonManager.getAddonsByIDs(changedIDs, function(aAddons) {
- aAddons.forEach(function(aAddon) {
- // If the add-on isn't user disabled or can't be enabled then skip it.
- if (!aAddon.userDisabled || !(aAddon.permissions & AddonManager.PERM_CAN_ENABLE))
- return;
-
- win.openUILinkIn("about:newaddon?id=" + aAddon.id, "tab");
- })
- });
- }
-
- // Perform default browser checking.
- if (ShellService) {
- let shouldCheck = ShellService.shouldCheckDefaultBrowser;
-
- const skipDefaultBrowserCheck =
- Services.prefs.getBoolPref("browser.shell.skipDefaultBrowserCheckOnFirstRun") &&
- Services.prefs.getBoolPref("browser.shell.skipDefaultBrowserCheck");
-
- const usePromptLimit = false;
- let promptCount =
- usePromptLimit ? Services.prefs.getIntPref("browser.shell.defaultBrowserCheckCount") : 0;
-
- let willRecoverSession = false;
- try {
- let 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 */ }
-
- // startup check, check all assoc
- let isDefault = false;
- let isDefaultError = false;
- try {
- isDefault = ShellService.isDefaultBrowser(true, false);
- } catch (ex) {
- isDefaultError = true;
- }
-
- if (isDefault) {
- let now = (Math.floor(Date.now() / 1000)).toString();
- Services.prefs.setCharPref("browser.shell.mostRecentDateSetAsDefault", now);
- }
-
- let willPrompt = shouldCheck && !isDefault && !willRecoverSession;
-
- // Skip the "Set Default Browser" check during first-run or after the
- // browser has been run a few times.
- if (willPrompt) {
- Services.tm.mainThread.dispatch(function() {
- var win = this.getMostRecentBrowserWindow();
- var brandBundle = win.document.getElementById("bundle_brand");
- var shellBundle = win.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]);
- var checkEveryTime = { value: shouldCheck };
- var ps = Services.prompt;
- var rv = ps.confirmEx(win, promptTitle, promptMessage,
- ps.STD_YES_NO_BUTTONS,
- null, null, null, checkboxLabel, checkEveryTime);
- if (rv == 0) {
- var claimAllTypes = true;
-#ifdef XP_WIN
- try {
- // In Windows 8+, the UI for selecting default protocol is much
- // nicer than the UI for setting file type associations. So we
- // only show the protocol association screen on Windows 8.
- // Windows 8 is version 6.2.
- let version = Services.sysinfo.getProperty("version");
- claimAllTypes = (parseFloat(version) < 6.2);
- } catch (ex) { }
-#endif
- ShellService.setDefaultBrowser(claimAllTypes, false);
- }
- ShellService.shouldCheckDefaultBrowser = checkEveryTime.value;
- }.bind(this), Ci.nsIThread.DISPATCH_NORMAL);
- }
- }
- },
-
- _onQuitRequest: function BG__onQuitRequest(aCancelQuit, aQuitType) {
- // If user has already dismissed quit request, then do nothing
- if ((aCancelQuit instanceof Ci.nsISupportsPRBool) && aCancelQuit.data)
- return;
-
- // There are several cases where we won't show a dialog here:
- // 1. There is only 1 tab open in 1 window
- // 2. The session will be restored at startup, indicated by
- // browser.startup.page == 3 or browser.sessionstore.resume_session_once == true
- // 3. browser.warnOnQuit == false
- // 4. The browser is currently in Private Browsing mode
- // 5. The browser will be restarted.
- //
- // Otherwise these are the conditions and the associated dialogs that will be shown:
- // 1. aQuitType == "lastwindow" or "quit" and browser.showQuitWarning == true
- // - The quit dialog will be shown
- // 2. aQuitType == "lastwindow" && browser.tabs.warnOnClose == true
- // - The "closing multiple tabs" dialog will be shown
- //
- // aQuitType == "lastwindow" is overloaded. "lastwindow" is used to indicate
- // "the last window is closing but we're not quitting (a non-browser window is open)"
- // and also "we're quitting by closing the last window".
-
- if (aQuitType == "restart")
- return;
-
- var windowcount = 0;
- var pagecount = 0;
- var browserEnum = Services.wm.getEnumerator("navigator:browser");
- let allWindowsPrivate = true;
- while (browserEnum.hasMoreElements()) {
- windowcount++;
-
- var browser = browserEnum.getNext();
- if (!PrivateBrowsingUtils.isWindowPrivate(browser))
- allWindowsPrivate = false;
- var tabbrowser = browser.document.getElementById("content");
- if (tabbrowser)
- pagecount += tabbrowser.browsers.length - tabbrowser._numPinnedTabs;
- }
-
- this._saveSession = false;
- if (pagecount < 2)
- return;
-
- if (!aQuitType)
- aQuitType = "quit";
-
- // browser.warnOnQuit is a hidden global boolean to override all quit prompts
- // browser.showQuitWarning specifically covers quitting
- // browser.tabs.warnOnClose is the global "warn when closing multiple tabs" pref
-
- var sessionWillBeRestored = Services.prefs.getIntPref("browser.startup.page") == 3 ||
- Services.prefs.getBoolPref("browser.sessionstore.resume_session_once");
- if (sessionWillBeRestored || !Services.prefs.getBoolPref("browser.warnOnQuit"))
- return;
-
- let win = Services.wm.getMostRecentWindow("navigator:browser");
-
- // On last window close or quit && showQuitWarning, we want to show the
- // quit warning.
- if (!Services.prefs.getBoolPref("browser.showQuitWarning")) {
- if (aQuitType == "lastwindow") {
- // If aQuitType is "lastwindow" and we aren't showing the quit warning,
- // we should show the window closing warning instead. warnAboutClosing
- // tabs checks browser.tabs.warnOnClose and returns if it's ok to close
- // the window. It doesn't actually close the window.
- aCancelQuit.data =
- !win.gBrowser.warnAboutClosingTabs(win.gBrowser.closingTabsEnum.ALL);
- }
- return;
- }
-
- let prompt = Services.prompt;
- let quitBundle = Services.strings.createBundle("chrome://browser/locale/quitDialog.properties");
-
- let appName = gBrandBundle.GetStringFromName("brandShortName");
- let quitDialogTitle = quitBundle.formatStringFromName("quitDialogTitle",
- [appName], 1);
- let neverAskText = quitBundle.GetStringFromName("neverAsk2");
- let neverAsk = {value: false};
-
- let choice;
- if (allWindowsPrivate) {
- let text = quitBundle.formatStringFromName("messagePrivate", [appName], 1);
- let flags = prompt.BUTTON_TITLE_IS_STRING * prompt.BUTTON_POS_0 +
- prompt.BUTTON_TITLE_IS_STRING * prompt.BUTTON_POS_1 +
- prompt.BUTTON_POS_0_DEFAULT;
- choice = prompt.confirmEx(win, quitDialogTitle, text, flags,
- quitBundle.GetStringFromName("quitTitle"),
- quitBundle.GetStringFromName("cancelTitle"),
- null,
- neverAskText, neverAsk);
-
- // The order of the buttons differs between the prompt.confirmEx calls
- // here so we need to fix this for proper handling below.
- if (choice == 0) {
- choice = 2;
- }
- } else {
- let text = quitBundle.formatStringFromName(
- windowcount == 1 ? "messageNoWindows" : "message", [appName], 1);
- let flags = prompt.BUTTON_TITLE_IS_STRING * prompt.BUTTON_POS_0 +
- prompt.BUTTON_TITLE_IS_STRING * prompt.BUTTON_POS_1 +
- prompt.BUTTON_TITLE_IS_STRING * prompt.BUTTON_POS_2 +
- prompt.BUTTON_POS_0_DEFAULT;
- choice = prompt.confirmEx(win, quitDialogTitle, text, flags,
- quitBundle.GetStringFromName("saveTitle"),
- quitBundle.GetStringFromName("cancelTitle"),
- quitBundle.GetStringFromName("quitTitle"),
- neverAskText, neverAsk);
- }
-
- switch (choice) {
- case 2: // Quit
- if (neverAsk.value)
- Services.prefs.setBoolPref("browser.showQuitWarning", false);
- break;
- case 1: // Cancel
- aCancelQuit.QueryInterface(Ci.nsISupportsPRBool);
- aCancelQuit.data = true;
- break;
- case 0: // Save & Quit
- this._saveSession = true;
- if (neverAsk.value) {
- // always save state when shutting down
- Services.prefs.setIntPref("browser.startup.page", 3);
- }
- break;
- }
- },
-
- _showUpdateNotification: function BG__showUpdateNotification() {
- Services.prefs.clearUserPref("app.update.postupdate");
-
- var um = Cc["@mozilla.org/updates/update-manager;1"].
- getService(Ci.nsIUpdateManager);
- try {
- // If the updates.xml file is deleted then getUpdateAt will throw.
- var update = um.getUpdateAt(0).QueryInterface(Ci.nsIPropertyBag);
- }
- catch (e) {
- // This should never happen.
- Cu.reportError("Unable to find update: " + e);
- return;
- }
-
- var actions = update.getProperty("actions");
- if (!actions || actions.indexOf("silent") != -1)
- return;
-
- var formatter = Cc["@mozilla.org/toolkit/URLFormatterService;1"].
- getService(Ci.nsIURLFormatter);
- var appName = gBrandBundle.GetStringFromName("brandShortName");
-
- function getNotifyString(aPropData) {
- var propValue = update.getProperty(aPropData.propName);
- if (!propValue) {
- if (aPropData.prefName)
- propValue = formatter.formatURLPref(aPropData.prefName);
- else if (aPropData.stringParams)
- propValue = gBrowserBundle.formatStringFromName(aPropData.stringName,
- aPropData.stringParams,
- aPropData.stringParams.length);
- else
- propValue = gBrowserBundle.GetStringFromName(aPropData.stringName);
- }
- return propValue;
- }
-
- if (actions.indexOf("showNotification") != -1) {
- let text = getNotifyString({propName: "notificationText",
- stringName: "puNotifyText",
- stringParams: [appName]});
- let url = getNotifyString({propName: "notificationURL",
- prefName: "startup.homepage_override_url"});
- let label = getNotifyString({propName: "notificationButtonLabel",
- stringName: "pu.notifyButton.label"});
- let key = getNotifyString({propName: "notificationButtonAccessKey",
- stringName: "pu.notifyButton.accesskey"});
-
- let win = this.getMostRecentBrowserWindow();
- let notifyBox = win.gBrowser.getNotificationBox();
-
- let buttons = [
- {
- label: label,
- accessKey: key,
- popup: null,
- callback: function(aNotificationBar, aButton) {
- win.openUILinkIn(url, "tab");
- }
- }
- ];
-
- let notification = notifyBox.appendNotification(text, "post-update-notification",
- null, notifyBox.PRIORITY_INFO_LOW,
- buttons);
- notification.persistence = -1; // Until user closes it
- }
-
- if (actions.indexOf("showAlert") == -1)
- return;
-
- let title = getNotifyString({propName: "alertTitle",
- stringName: "puAlertTitle",
- stringParams: [appName]});
- let text = getNotifyString({propName: "alertText",
- stringName: "puAlertText",
- stringParams: [appName]});
- let url = getNotifyString({propName: "alertURL",
- prefName: "startup.homepage_override_url"});
-
- var self = this;
- function clickCallback(subject, topic, data) {
- // This callback will be called twice but only once with this topic
- if (topic != "alertclickcallback")
- return;
- let win = self.getMostRecentBrowserWindow();
- win.openUILinkIn(data, "tab");
- }
-
- try {
- // This will throw NS_ERROR_NOT_AVAILABLE if the notification cannot
- // be displayed per the idl.
- AlertsService.showAlertNotification(null, title, text,
- true, url, clickCallback);
- }
- catch (e) {
- Cu.reportError(e);
- }
- },
-
- _showPluginUpdatePage: function BG__showPluginUpdatePage() {
- // Pale Moon: disable this functionality from BrowserGlue, people are
- // already notified if they visit a page with an outdated plugin, and
- // they can check properly from the plugins page as well.
-
-// Services.prefs.setBoolPref(PREF_PLUGINS_NOTIFYUSER, false);
-//
-// var formatter = Cc["@mozilla.org/toolkit/URLFormatterService;1"].
-// getService(Ci.nsIURLFormatter);
-// var updateUrl = formatter.formatURLPref(PREF_PLUGINS_UPDATEURL);
-//
-// var win = this.getMostRecentBrowserWindow();
-// win.openUILinkIn(updateUrl, "tab");
- },
-
- /**
- * Initialize Places
- * - imports the bookmarks html file if bookmarks database is empty, try to
- * restore bookmarks from a JSON/JSONLZ4 backup if the backend indicates
- * that the database was corrupt.
- *
- * These prefs can be set up by the frontend:
- *
- * WARNING: setting these preferences to true will overwite existing bookmarks
- *
- * - browser.places.importBookmarksHTML
- * Set to true will import the bookmarks.html file from the profile folder.
- * - browser.places.smartBookmarksVersion
- * Set during HTML import to indicate that Smart Bookmarks were created.
- * Set to -1 to disable Smart Bookmarks creation.
- * Set to 0 to restore current Smart Bookmarks.
- * - browser.bookmarks.restore_default_bookmarks
- * Set to true by safe-mode dialog to indicate we must restore default
- * bookmarks.
- */
- _initPlaces: function BG__initPlaces(aInitialMigrationPerformed) {
- // We must instantiate the history service since it will tell us if we
- // need to import or restore bookmarks due to first-run, corruption or
- // forced migration (due to a major schema change).
- // If the database is corrupt or has been newly created we should
- // import bookmarks.
- var dbStatus = PlacesUtils.history.databaseStatus;
- var importBookmarks = !aInitialMigrationPerformed &&
- (dbStatus == PlacesUtils.history.DATABASE_STATUS_CREATE ||
- dbStatus == PlacesUtils.history.DATABASE_STATUS_CORRUPT);
-
- // Check if user or an extension has required to import bookmarks.html
- var importBookmarksHTML = false;
- try {
- importBookmarksHTML =
- Services.prefs.getBoolPref("browser.places.importBookmarksHTML");
- if (importBookmarksHTML)
- importBookmarks = true;
- } catch(ex) {}
-
- Task.spawn(function() {
- // Check if Safe Mode or the user has required to restore bookmarks from
- // default profile's bookmarks.html
- var restoreDefaultBookmarks = false;
- try {
- restoreDefaultBookmarks =
- Services.prefs.getBoolPref("browser.bookmarks.restore_default_bookmarks");
- if (restoreDefaultBookmarks) {
- // Ensure that we already have a bookmarks backup for today.
- if (this._shouldBackupBookmarks())
- yield this._backupBookmarks();
- importBookmarks = true;
- }
- } catch(ex) {}
-
- // If the user did not require to restore default bookmarks, or import
- // from bookmarks.html, we will try to restore from JSON/JSONLZ4
- if (importBookmarks && !restoreDefaultBookmarks && !importBookmarksHTML) {
- // get latest JSON/JSONLZ4 backup
- var bookmarksBackupFile = yield PlacesBackups.getMostRecentBackup();
- if (bookmarksBackupFile) {
- // restore from JSON/JSONLZ4 backup
- yield BookmarkJSONUtils.importFromFile(bookmarksBackupFile, true);
- importBookmarks = false;
- }
- else {
- // We have created a new database but we don't have any backup available
- importBookmarks = true;
- if (yield OS.File.exists(BookmarkHTMLUtils.defaultPath)) {
- // If bookmarks.html is available in current profile import it...
- importBookmarksHTML = true;
- }
- else {
- // ...otherwise we will restore defaults
- restoreDefaultBookmarks = true;
- }
- }
- }
-
- // If bookmarks are not imported, then initialize smart bookmarks. This
- // happens during a common startup.
- // Otherwise, if any kind of import runs, smart bookmarks creation should be
- // delayed till the import operations has finished. Not doing so would
- // cause them to be overwritten by the newly imported bookmarks.
- if (!importBookmarks) {
- // Now apply distribution customized bookmarks.
- // This should always run after Places initialization.
- try {
- this._distributionCustomizer.applyBookmarks();
- this.ensurePlacesDefaultQueriesInitialized();
- } catch (e) {
- Cu.reportError(e);
- }
- }
- else {
- // An import operation is about to run.
- // Don't try to recreate smart bookmarks if autoExportHTML is true or
- // smart bookmarks are disabled.
- var autoExportHTML = Services.prefs.getBoolPref("browser.bookmarks.autoExportHTML", false);
- var smartBookmarksVersion = Services.prefs.getIntPref("browser.places.smartBookmarksVersion", 0);
- if (!autoExportHTML && smartBookmarksVersion != -1)
- Services.prefs.setIntPref("browser.places.smartBookmarksVersion", 0);
-
- var bookmarksUrl = null;
- if (restoreDefaultBookmarks) {
- // User wants to restore bookmarks.html file from default profile folder
- bookmarksUrl = "resource:///defaults/profile/bookmarks.html";
- }
- else if (yield OS.File.exists(BookmarkHTMLUtils.defaultPath)) {
- bookmarksUrl = OS.Path.toFileURI(BookmarkHTMLUtils.defaultPath);
- }
-
- if (bookmarksUrl) {
- // Import from bookmarks.html file.
- try {
- BookmarkHTMLUtils.importFromURL(bookmarksUrl, true).then(null,
- function onFailure() {
- Cu.reportError(
- new Error("Bookmarks.html file could be corrupt."));
- }
- ).then(
- function onComplete() {
- try {
- // Now apply distribution customized bookmarks.
- // This should always run after Places initialization.
- this._distributionCustomizer.applyBookmarks();
- // Ensure that smart bookmarks are created once the operation
- // is complete.
- this.ensurePlacesDefaultQueriesInitialized();
- } catch (e) {
- Cu.reportError(e);
- }
- }.bind(this)
- );
- } catch (e) {
- Cu.reportError(
- new Error("Bookmarks.html file could be corrupt." + "\n" +
- e.message));
- }
- }
- else {
- Cu.reportError(new Error("Unable to find bookmarks.html file."));
- }
-
- // See #1083:
- // "Delete all bookmarks except for backups" in Safe Mode doesn't work
- var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
- let observer = {
- "observe": function() {
- delete observer.timer;
- // Reset preferences, so we won't try to import again at next run
- if (importBookmarksHTML) {
- Services.prefs.setBoolPref("browser.places.importBookmarksHTML", false);
- }
- if (restoreDefaultBookmarks) {
- Services.prefs.setBoolPref("browser.bookmarks.restore_default_bookmarks",
- false);
- }
- },
- "timer": timer,
- };
- timer.init(observer, 100, Ci.nsITimer.TYPE_ONE_SHOT);
- }
-
- // Initialize bookmark archiving on idle.
- // Once a day, either on idle or shutdown, bookmarks are backed up.
- if (!this._isIdleObserver) {
- this._idleService.addIdleObserver(this, BOOKMARKS_BACKUP_IDLE_TIME);
- this._isIdleObserver = true;
- }
-
- }.bind(this)).catch(ex => {
- Cu.reportError(ex);
- }).then(result => {
- // NB: deliberately after the catch so that we always do this, even if
- // we threw halfway through initializing in the Task above.
- Services.obs.notifyObservers(null, "places-browser-init-complete", "");
- });
- },
-
- /**
- * Places shut-down tasks
- * - back up bookmarks if needed.
- * - export bookmarks as HTML, if so configured.
- * - finalize components depending on Places.
- */
- _onPlacesShutdown: function BG__onPlacesShutdown() {
- this._sanitizer.onShutdown();
- PageThumbs.uninit();
-
- if (this._isIdleObserver) {
- this._idleService.removeIdleObserver(this, BOOKMARKS_BACKUP_IDLE_TIME);
- this._isIdleObserver = false;
- }
-
- let waitingForBackupToComplete = true;
- if (this._shouldBackupBookmarks()) {
- waitingForBackupToComplete = false;
- this._backupBookmarks().then(
- function onSuccess() {
- waitingForBackupToComplete = true;
- },
- function onFailure() {
- Cu.reportError("Unable to backup bookmarks.");
- waitingForBackupToComplete = true;
- }
- );
- }
-
- // Backup bookmarks to bookmarks.html to support apps that depend
- // on the legacy format.
- let waitingForHTMLExportToComplete = true;
- // If this fails to get the preference value, we don't export.
- if (Services.prefs.getBoolPref("browser.bookmarks.autoExportHTML")) {
- // Exceptionally, since this is a non-default setting and HTML format is
- // discouraged in favor of the JSON/JSONLZ4 backups, we spin the event
- // loop on shutdown, to wait for the export to finish. We cannot safely
- // spin the event loop on shutdown until we include a watchdog to prevent
- // potential hangs (bug 518683). The asynchronous shutdown operations
- // will then be handled by a shutdown service (bug 435058).
- waitingForHTMLExportToComplete = false;
- BookmarkHTMLUtils.exportToFile(BookmarkHTMLUtils.defaultPath).then(
- function onSuccess() {
- waitingForHTMLExportToComplete = true;
- },
- function onFailure() {
- Cu.reportError("Unable to auto export html.");
- waitingForHTMLExportToComplete = true;
- }
- );
- }
-
- let thread = Services.tm.currentThread;
- while (!waitingForBackupToComplete || !waitingForHTMLExportToComplete) {
- thread.processNextEvent(true);
- }
- },
-
- /**
- * Determine whether to backup bookmarks or not.
- * @return true if bookmarks should be backed up, false if not.
- */
- _shouldBackupBookmarks: function BG__shouldBackupBookmarks() {
- let lastBackupFile = PlacesBackups.getMostRecent();
-
- // Should backup bookmarks if there are no backups or the maximum interval between
- // backups elapsed.
- return (!lastBackupFile ||
- new Date() - PlacesBackups.getDateForFile(lastBackupFile) > BOOKMARKS_BACKUP_INTERVAL);
- },
-
- /**
- * Backup bookmarks.
- */
- _backupBookmarks: function BG__backupBookmarks() {
- return Task.spawn(function() {
- // Backup bookmarks if there are no backups or the maximum interval between
- // backups elapsed.
- let maxBackups = BOOKMARKS_BACKUP_MAX_BACKUPS;
- try {
- maxBackups = Services.prefs.getIntPref("browser.bookmarks.max_backups");
- }
- catch(ex) { /* Use default. */ }
-
- yield PlacesBackups.create(maxBackups); // Don't force creation.
- });
- },
-
- /**
- * Show the notificationBox for a locked places database.
- */
- _showPlacesLockedNotificationBox: function BG__showPlacesLockedNotificationBox() {
- var applicationName = gBrandBundle.GetStringFromName("brandShortName");
- var placesBundle = Services.strings.createBundle("chrome://browser/locale/places/places.properties");
- var title = placesBundle.GetStringFromName("lockPrompt.title");
- var text = placesBundle.formatStringFromName("lockPrompt.text", [applicationName], 1);
- var buttonText = placesBundle.GetStringFromName("lockPromptInfoButton.label");
- var accessKey = placesBundle.GetStringFromName("lockPromptInfoButton.accessKey");
-
- var helpTopic = "places-locked";
- var url = Cc["@mozilla.org/toolkit/URLFormatterService;1"].
- getService(Components.interfaces.nsIURLFormatter).
- formatURLPref("app.support.baseURL");
- url += helpTopic;
-
- var win = this.getMostRecentBrowserWindow();
-
- var buttons = [
- {
- label: buttonText,
- accessKey: accessKey,
- popup: null,
- callback: function(aNotificationBar, aButton) {
- win.openUILinkIn(url, "tab");
- }
- }
- ];
-
- var notifyBox = win.gBrowser.getNotificationBox();
- var notification = notifyBox.appendNotification(text, title, null,
- notifyBox.PRIORITY_CRITICAL_MEDIUM,
- buttons);
- notification.persistence = -1; // Until user closes it
- },
-
- _migrateUI: function BG__migrateUI() {
- const UI_VERSION = 20;
- const BROWSER_DOCURL = "chrome://browser/content/browser.xul#";
- let currentUIVersion = 0;
- try {
- currentUIVersion = Services.prefs.getIntPref("browser.migration.version");
- } catch(ex) {}
- if (currentUIVersion >= UI_VERSION)
- return;
-
- this._rdf = Cc["@mozilla.org/rdf/rdf-service;1"].getService(Ci.nsIRDFService);
- this._dataSource = this._rdf.GetDataSource("rdf:local-store");
- this._dirty = false;
-
- if (currentUIVersion < 2) {
- // This code adds the customizable bookmarks button.
- let currentsetResource = this._rdf.GetResource("currentset");
- let toolbarResource = this._rdf.GetResource(BROWSER_DOCURL + "nav-bar");
- let currentset = this._getPersist(toolbarResource, currentsetResource);
- // Need to migrate only if toolbar is customized and the element is not found.
- if (currentset &&
- currentset.indexOf("bookmarks-menu-button-container") == -1) {
- currentset += ",bookmarks-menu-button-container";
- this._setPersist(toolbarResource, currentsetResource, currentset);
- }
- }
-
-#ifndef MOZ_JXR
- // Until JPEG-XR decoder is implemented (UXP #144)
- if (currentUIVersion < 19) {
- try {
- let ihaPref = "image.http.accept";
- let ihaValue = Services.prefs.getCharPref(ihaPref);
- if (ihaValue.includes("image/jxr,")) {
- Services.prefs.setCharPref(ihaPref, ihaValue.replace("image/jxr,", ""));
- } else if (ihaValue.includes("image/jxr")) {
- Services.prefs.clearUserPref(ihaPref);
- }
- }
- catch (ex) {}
- }
-#endif
-
- if (currentUIVersion < 20) {
- // HPKP change of UI preference; reset enforcement level
- Services.prefs.clearUserPref("security.cert_pinning.eforcement_level");
- }
-
- // Update the migration version.
- Services.prefs.setIntPref("browser.migration.version", UI_VERSION);
- },
-
- _hasExistingNotificationPermission: function BG__hasExistingNotificationPermission() {
- let enumerator = Services.perms.enumerator;
- while (enumerator.hasMoreElements()) {
- let permission = enumerator.getNext().QueryInterface(Ci.nsIPermission);
- if (permission.type == "desktop-notification") {
- return true;
- }
- }
- return false;
- },
-
- _notifyNotificationsUpgrade: function BG__notifyNotificationsUpgrade() {
- if (!this._hasExistingNotificationPermission()) {
- return;
- }
- function clickCallback(subject, topic, data) {
- if (topic != "alertclickcallback")
- return;
- let win = RecentWindow.getMostRecentBrowserWindow();
- win.openUILinkIn(data, "tab");
- }
- // Show the application icon for XUL notifications. We assume system-level
- // notifications will include their own icon.
- let imageURL = this._hasSystemAlertsService() ? "" :
- "chrome://branding/content/about-logo.png";
- let title = gBrowserBundle.GetStringFromName("webNotifications.upgradeTitle");
- let text = gBrowserBundle.GetStringFromName("webNotifications.upgradeBody");
- let url = Services.urlFormatter.formatURLPref("browser.push.warning.infoURL");
-
- try {
- AlertsService.showAlertNotification(imageURL, title, text,
- true, url, clickCallback);
- }
- catch (e) {
- Cu.reportError(e);
- }
- },
-
- _openPermissions: function(aPrincipal) {
- var win = this.getMostRecentBrowserWindow();
- var url = "about:permissions";
- try {
- url = url + "?filter=" + aPrincipal.URI.host;
- }
- catch (e) {}
- win.openUILinkIn(url, "tab");
- },
-
- _hasSystemAlertsService: function() {
- try {
- return !!Cc["@mozilla.org/system-alerts-service;1"].getService(
- Ci.nsIAlertsService);
- } catch (e) {}
- return false;
- },
-
- _getPersist: function BG__getPersist(aSource, aProperty) {
- var target = this._dataSource.GetTarget(aSource, aProperty, true);
- if (target instanceof Ci.nsIRDFLiteral)
- return target.Value;
- return null;
- },
-
- _setPersist: function BG__setPersist(aSource, aProperty, aTarget) {
- this._dirty = true;
- try {
- var oldTarget = this._dataSource.GetTarget(aSource, aProperty, true);
- if (oldTarget) {
- if (aTarget)
- this._dataSource.Change(aSource, aProperty, oldTarget, this._rdf.GetLiteral(aTarget));
- else
- this._dataSource.Unassert(aSource, aProperty, oldTarget);
- }
- else {
- this._dataSource.Assert(aSource, aProperty, this._rdf.GetLiteral(aTarget), true);
- }
-
- // Add the entry to the persisted set for this document if it's not there.
- // This code is mostly borrowed from XULDocument::Persist.
- let docURL = aSource.ValueUTF8.split("#")[0];
- let docResource = this._rdf.GetResource(docURL);
- let persistResource = this._rdf.GetResource("http://home.netscape.com/NC-rdf#persist");
- if (!this._dataSource.HasAssertion(docResource, persistResource, aSource, true)) {
- this._dataSource.Assert(docResource, persistResource, aSource, true);
- }
- }
- catch(ex) {}
- },
-
- // ------------------------------
- // public nsIBrowserGlue members
- // ------------------------------
-
- sanitize: function BG_sanitize(aParentWindow) {
- this._sanitizer.sanitize(aParentWindow);
- },
-
- ensurePlacesDefaultQueriesInitialized:
- function BG_ensurePlacesDefaultQueriesInitialized() {
- // This is actual version of the smart bookmarks, must be increased every
- // time smart bookmarks change.
- // When adding a new smart bookmark below, its newInVersion property must
- // be set to the version it has been added in, we will compare its value
- // to users' smartBookmarksVersion and add new smart bookmarks without
- // recreating old deleted ones.
- const SMART_BOOKMARKS_VERSION = 4;
- const SMART_BOOKMARKS_ANNO = "Places/SmartBookmark";
- const SMART_BOOKMARKS_PREF = "browser.places.smartBookmarksVersion";
-
- // TODO bug 399268: should this be a pref?
- const MAX_RESULTS = 10;
-
- // Get current smart bookmarks version. If not set, create them.
- let smartBookmarksCurrentVersion = Services.prefs.getIntPref(SMART_BOOKMARKS_PREF, 0);
-
- // If version is current or smart bookmarks are disabled, just bail out.
- if (smartBookmarksCurrentVersion == -1 ||
- smartBookmarksCurrentVersion >= SMART_BOOKMARKS_VERSION) {
- return;
- }
-
- let batch = {
- runBatched: function BG_EPDQI_runBatched() {
- let menuIndex = 0;
- let toolbarIndex = 0;
- let bundle = Services.strings.createBundle("chrome://browser/locale/places/places.properties");
-
- let smartBookmarks = {
- MostVisited: {
- title: bundle.GetStringFromName("mostVisitedTitle"),
- uri: NetUtil.newURI("place:sort=" +
- Ci.nsINavHistoryQueryOptions.SORT_BY_VISITCOUNT_DESCENDING +
- "&maxResults=" + MAX_RESULTS),
- parent: PlacesUtils.toolbarFolderId,
- position: toolbarIndex++,
- newInVersion: 1
- },
- RecentlyBookmarked: {
- title: bundle.GetStringFromName("recentlyBookmarkedTitle"),
- uri: NetUtil.newURI("place:folder=BOOKMARKS_MENU" +
- "&folder=UNFILED_BOOKMARKS" +
- "&folder=TOOLBAR" +
- "&queryType=" +
- Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS +
- "&sort=" +
- Ci.nsINavHistoryQueryOptions.SORT_BY_DATEADDED_DESCENDING +
- "&maxResults=" + MAX_RESULTS +
- "&excludeQueries=1"),
- parent: PlacesUtils.bookmarksMenuFolderId,
- position: menuIndex++,
- newInVersion: 1
- },
- RecentTags: {
- title: bundle.GetStringFromName("recentTagsTitle"),
- uri: NetUtil.newURI("place:"+
- "type=" +
- Ci.nsINavHistoryQueryOptions.RESULTS_AS_TAG_QUERY +
- "&sort=" +
- Ci.nsINavHistoryQueryOptions.SORT_BY_LASTMODIFIED_DESCENDING +
- "&maxResults=" + MAX_RESULTS),
- parent: PlacesUtils.bookmarksMenuFolderId,
- position: menuIndex++,
- newInVersion: 1
- }
- };
-
- // Set current itemId, parent and position if Smart Bookmark exists,
- // we will use these informations to create the new version at the same
- // position.
- let smartBookmarkItemIds = PlacesUtils.annotations.getItemsWithAnnotation(SMART_BOOKMARKS_ANNO);
- smartBookmarkItemIds.forEach(function (itemId) {
- let queryId = PlacesUtils.annotations.getItemAnnotation(itemId, SMART_BOOKMARKS_ANNO);
- if (queryId in smartBookmarks) {
- let smartBookmark = smartBookmarks[queryId];
- smartBookmark.itemId = itemId;
- smartBookmark.parent = PlacesUtils.bookmarks.getFolderIdForItem(itemId);
- smartBookmark.position = PlacesUtils.bookmarks.getItemIndex(itemId);
- }
- else {
- // We don't remove old Smart Bookmarks because user could still
- // find them useful, or could have personalized them.
- // Instead we remove the Smart Bookmark annotation.
- PlacesUtils.annotations.removeItemAnnotation(itemId, SMART_BOOKMARKS_ANNO);
- }
- });
-
- for (let queryId in smartBookmarks) {
- let smartBookmark = smartBookmarks[queryId];
-
- // We update or create only changed or new smart bookmarks.
- // Also we respect user choices, so we won't try to create a smart
- // bookmark if it has been removed.
- if (smartBookmarksCurrentVersion > 0 &&
- smartBookmark.newInVersion <= smartBookmarksCurrentVersion &&
- !smartBookmark.itemId)
- continue;
-
- // Remove old version of the smart bookmark if it exists, since it
- // will be replaced in place.
- if (smartBookmark.itemId) {
- PlacesUtils.bookmarks.removeItem(smartBookmark.itemId);
- }
-
- // Create the new smart bookmark and store its updated itemId.
- smartBookmark.itemId =
- PlacesUtils.bookmarks.insertBookmark(smartBookmark.parent,
- smartBookmark.uri,
- smartBookmark.position,
- smartBookmark.title);
- PlacesUtils.annotations.setItemAnnotation(smartBookmark.itemId,
- SMART_BOOKMARKS_ANNO,
- queryId, 0,
- PlacesUtils.annotations.EXPIRE_NEVER);
- }
-
- // If we are creating all Smart Bookmarks from ground up, add a
- // separator below them in the bookmarks menu.
- if (smartBookmarksCurrentVersion == 0 &&
- smartBookmarkItemIds.length == 0) {
- let id = PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.bookmarksMenuFolderId,
- menuIndex);
- // Don't add a separator if the menu was empty or there is one already.
- if (id != -1 &&
- PlacesUtils.bookmarks.getItemType(id) != PlacesUtils.bookmarks.TYPE_SEPARATOR) {
- PlacesUtils.bookmarks.insertSeparator(PlacesUtils.bookmarksMenuFolderId,
- menuIndex);
- }
- }
- }
- };
-
- try {
- PlacesUtils.bookmarks.runInBatchMode(batch, null);
- }
- catch(ex) {
- Components.utils.reportError(ex);
- }
- finally {
- Services.prefs.setIntPref(SMART_BOOKMARKS_PREF, SMART_BOOKMARKS_VERSION);
- Services.prefs.savePrefFile(null);
- }
- },
-
- // this returns the most recent non-popup browser window
- getMostRecentBrowserWindow: function BG_getMostRecentBrowserWindow() {
- return RecentWindow.getMostRecentBrowserWindow();
- },
-
-#ifdef MOZ_SERVICES_SYNC
- /**
- * Called as an observer when Sync's "display URI" notification is fired.
- *
- * We open the received URI in a background tab.
- *
- * Eventually, this will likely be replaced by a more robust tab syncing
- * feature. This functionality is considered somewhat evil by UX because it
- * opens a new tab automatically without any prompting. However, it is a
- * lesser evil than sending a tab to a specific device (from e.g. Fennec)
- * and having nothing happen on the receiving end.
- */
- _onDisplaySyncURI: function _onDisplaySyncURI(data) {
- try {
- let tabbrowser = RecentWindow.getMostRecentBrowserWindow({private: false}).gBrowser;
-
- // The payload is wrapped weirdly because of how Sync does notifications.
- tabbrowser.addTab(data.wrappedJSObject.object.uri);
- } catch (ex) {
- Cu.reportError("Error displaying tab received by Sync: " + ex);
- }
- },
-#endif
-
- // for XPCOM
- classID: Components.ID("{eab9012e-5f74-4cbc-b2b5-a590235513cc}"),
-
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
- Ci.nsISupportsWeakReference,
- Ci.nsIBrowserGlue]),
-
- // redefine the default factory for XPCOMUtils
- _xpcom_factory: BrowserGlueServiceFactory,
-}
-
-function ContentPermissionPrompt() {}
-
-ContentPermissionPrompt.prototype = {
- classID: Components.ID("{d8903bf6-68d5-4e97-bcd1-e4d3012f721a}"),
-
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPermissionPrompt]),
-
- _getChromeWindow: function CPP_getChromeWindow(aWindow) {
- var chromeWin = aWindow
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsIDocShellTreeItem)
- .rootTreeItem
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIDOMWindow)
- .QueryInterface(Ci.nsIDOMChromeWindow);
- return chromeWin;
- },
-
- _getBrowserForRequest: function (aRequest) {
- let requestingWindow = aRequest.window.top;
- // find the requesting browser or iframe
- let browser = requestingWindow.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsIDocShell)
- .chromeEventHandler;
- return browser;
- },
-
- /**
- * Show a permission prompt.
- *
- * @param aRequest The permission request.
- * @param aMessage The message to display on the prompt.
- * @param aPermission The type of permission to prompt.
- * @param aActions An array of actions of the form:
- * [main action, secondary actions, ...]
- * Actions are of the form { stringId, action, expireType, callback }
- * Permission is granted if action is null or ALLOW_ACTION.
- * @param aNotificationId The id of the PopupNotification.
- * @param aAnchorId The id for the PopupNotification anchor.
- * @param aOptions Options for the PopupNotification
- */
- _showPrompt: function CPP_showPrompt(aRequest, aMessage, aPermission, aActions,
- aNotificationId, aAnchorId, aOptions) {
- function onFullScreen() {
- popup.remove();
- }
-
- var requestingWindow = aRequest.window.top;
- var chromeWin = this._getChromeWindow(requestingWindow).wrappedJSObject;
- var browser = chromeWin.gBrowser.getBrowserForDocument(requestingWindow.document);
- if (!browser) {
- // find the requesting browser or iframe
- browser = requestingWindow.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsIDocShell)
- .chromeEventHandler;
- }
- var requestPrincipal = aRequest.principal;
-
- // Transform the prompt actions into PopupNotification actions.
- var popupNotificationActions = [];
- for (var i = 0; i < aActions.length; i++) {
- let promptAction = aActions[i];
-
- // Don't offer action in PB mode if the action remembers permission for more than a session.
- if (PrivateBrowsingUtils.isWindowPrivate(chromeWin) &&
- promptAction.expireType != Ci.nsIPermissionManager.EXPIRE_SESSION &&
- promptAction.action) {
- continue;
- }
-
- var action = {
- label: gBrowserBundle.GetStringFromName(promptAction.stringId),
- accessKey: gBrowserBundle.GetStringFromName(promptAction.stringId + ".accesskey"),
- callback: function() {
- if (promptAction.callback) {
- promptAction.callback();
- }
-
- // Remember permissions.
- if (promptAction.action) {
- Services.perms.addFromPrincipal(requestPrincipal, aPermission,
- promptAction.action, promptAction.expireType);
- }
-
- // Grant permission if action is null or ALLOW_ACTION.
- if (!promptAction.action || promptAction.action == Ci.nsIPermissionManager.ALLOW_ACTION) {
- aRequest.allow();
- } else {
- aRequest.cancel();
- }
- },
- };
-
- popupNotificationActions.push(action);
- }
-
- var mainAction = popupNotificationActions.length ?
- popupNotificationActions[0] : null;
- var secondaryActions = popupNotificationActions.splice(1);
-
- if (aRequest.type == "pointerLock") {
- // If there's no mainAction, this is the autoAllow warning prompt.
- let autoAllow = !mainAction;
-
- if (!aOptions)
- aOptions = {};
-
- aOptions.removeOnDismissal = autoAllow;
- aOptions.eventCallback = type => {
- if (type == "removed") {
- browser.removeEventListener("mozfullscreenchange", onFullScreen, true);
- if (autoAllow) {
- aRequest.allow();
- }
- }
- }
-
- }
-
- var popup = chromeWin.PopupNotifications.show(browser, aNotificationId, aMessage, aAnchorId,
- mainAction, secondaryActions, aOptions);
- if (aRequest.type == "pointerLock") {
- // pointerLock is automatically allowed in fullscreen mode (and revoked
- // upon exit), so if the page enters fullscreen mode after requesting
- // pointerLock (but before the user has granted permission), we should
- // remove the now-impotent notification.
- browser.addEventListener("mozfullscreenchange", onFullScreen, true);
- }
- },
-
- _promptGeo : function(aRequest) {
- var requestingURI = aRequest.principal.URI;
-
- var message;
-
- // Share location action.
- var actions = [{
- stringId: "geolocation.shareLocation",
- action: null,
- expireType: null,
- callback: function() {
- // Telemetry stub (left here for safety and compatibility reasons)
- },
- }];
-
- if (requestingURI.schemeIs("file")) {
- message = gBrowserBundle.formatStringFromName("geolocation.shareWithFile",
- [requestingURI.path], 1);
- } else {
- message = gBrowserBundle.formatStringFromName("geolocation.shareWithSite",
- [requestingURI.host], 1);
- // Always share location action.
- actions.push({
- stringId: "geolocation.alwaysShareLocation",
- action: Ci.nsIPermissionManager.ALLOW_ACTION,
- expireType: null,
- callback: function() {
- // Telemetry stub (left here for safety and compatibility reasons)
- },
- });
-
- // Never share location action.
- actions.push({
- stringId: "geolocation.neverShareLocation",
- action: Ci.nsIPermissionManager.DENY_ACTION,
- expireType: null,
- callback: function() {
- // Telemetry stub (left here for safety and compatibility reasons)
- },
- });
- }
-
- var options = {
- learnMoreURL: Services.urlFormatter.formatURLPref("browser.geolocation.warning.infoURL"),
- };
-
- this._showPrompt(aRequest, message, "geo", actions, "geolocation",
- "geo-notification-icon", options);
- },
-
- _promptWebNotifications : function(aRequest) {
- var requestingURI = aRequest.principal.URI;
-
- var message = gBrowserBundle.formatStringFromName("webNotifications.showFromSite",
- [requestingURI.host], 1);
-
- var actions;
-
- var browser = this._getBrowserForRequest(aRequest);
- // Only show "allow for session" in PB mode, we don't
- // support "allow for session" in non-PB mode.
- if (PrivateBrowsingUtils.isBrowserPrivate(browser)) {
- actions = [
- {
- stringId: "webNotifications.showForSession",
- action: Ci.nsIPermissionManager.ALLOW_ACTION,
- expireType: Ci.nsIPermissionManager.EXPIRE_SESSION,
- callback: function() {},
- },
- ];
- } else {
- actions = [
- {
- stringId: "webNotifications.showForSession",
- action: Ci.nsIPermissionManager.ALLOW_ACTION,
- expireType: Ci.nsIPermissionManager.EXPIRE_SESSION,
- callback: function() {},
- },
- {
- stringId: "webNotifications.alwaysShow",
- action: Ci.nsIPermissionManager.ALLOW_ACTION,
- expireType: null,
- callback: function() {},
- },
- {
- stringId: "webNotifications.neverShow",
- action: Ci.nsIPermissionManager.DENY_ACTION,
- expireType: null,
- callback: function() {},
- },
- ];
- }
- var options = {
- learnMoreURL: Services.urlFormatter.formatURLPref("browser.push.warning.infoURL"),
- };
-
- this._showPrompt(aRequest, message, "desktop-notification", actions,
- "web-notifications",
- "web-notifications-notification-icon", options);
- },
-
- _promptPointerLock: function CPP_promtPointerLock(aRequest, autoAllow) {
- let requestingURI = aRequest.principal.URI;
-
- let originString = requestingURI.schemeIs("file") ? requestingURI.path : requestingURI.host;
- let message = gBrowserBundle.formatStringFromName(autoAllow ?
- "pointerLock.autoLock.title2" : "pointerLock.title2",
- [originString], 1);
- // If this is an autoAllow info prompt, offer no actions.
- // _showPrompt() will allow the request when it's dismissed.
- let actions = [];
- if (!autoAllow) {
- actions = [
- {
- stringId: "pointerLock.allow2",
- action: null,
- expireType: null,
- callback: function() {},
- },
- {
- stringId: "pointerLock.alwaysAllow",
- action: Ci.nsIPermissionManager.ALLOW_ACTION,
- expireType: null,
- callback: function() {},
- },
- {
- stringId: "pointerLock.neverAllow",
- action: Ci.nsIPermissionManager.DENY_ACTION,
- expireType: null,
- callback: function() {},
- },
- ];
- }
-
- this._showPrompt(aRequest, message, "pointerLock", actions, "pointerLock",
- "pointerLock-notification-icon", null);
- },
-
- prompt: function CPP_prompt(request) {
- // Only allow exactly one permission rquest here.
- let types = request.types.QueryInterface(Ci.nsIArray);
- if (types.length != 1) {
- request.cancel();
- return;
- }
- let perm = types.queryElementAt(0, Ci.nsIContentPermissionType);
-
- const kFeatureKeys = { "geolocation" : "geo",
- "desktop-notification" : "desktop-notification",
- "pointerLock" : "pointerLock",
- };
-
- // Make sure that we support the request.
- if (!(perm.type in kFeatureKeys)) {
- return;
- }
-
- var requestingPrincipal = request.principal;
- var requestingURI = requestingPrincipal.URI;
-
- // Ignore requests from non-nsIStandardURLs
- if (!(requestingURI instanceof Ci.nsIStandardURL))
- return;
-
- var autoAllow = false;
- var permissionKey = kFeatureKeys[perm.type];
- var result = Services.perms.testExactPermissionFromPrincipal(requestingPrincipal, permissionKey);
-
- if (result == Ci.nsIPermissionManager.DENY_ACTION) {
- request.cancel();
- return;
- }
-
- if (result == Ci.nsIPermissionManager.ALLOW_ACTION) {
- autoAllow = true;
- // For pointerLock, we still want to show a warning prompt.
- if (request.type != "pointerLock") {
- request.allow();
- return;
- }
- }
-
- // Show the prompt.
- switch (perm.type) {
- case "geolocation":
- this._promptGeo(request);
- break;
- case "desktop-notification":
- this._promptWebNotifications(request);
- break;
- case "pointerLock":
- this._promptPointerLock(request, autoAllow);
- break;
- }
- },
-
-};
-
-var components = [BrowserGlue, ContentPermissionPrompt];
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
diff --git a/components/nsIBrowserGlue.idl b/components/nsIBrowserGlue.idl
deleted file mode 100644
index 1bb82a9..0000000
--- a/components/nsIBrowserGlue.idl
+++ /dev/null
@@ -1,47 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-interface nsIDOMWindow;
-
-/**
- * nsIBrowserGlue is a dirty and rather fluid interface to host shared utility
- * methods used by browser UI code, but which are not local to a browser window.
- * The component implementing this interface is meant to be a singleton
- * (service) and should progressively replace some of the shared "glue" code
- * scattered in browser/base/content (e.g. bits of utilOverlay.js,
- * contentAreaUtils.js, globalOverlay.js, browser.js), avoiding dynamic
- * inclusion and initialization of a ton of JS code for *each* window.
- * Dued to its nature and origin, this interface won't probably be the most
- * elegant or stable in the mozilla codebase, but its aim is rather pragmatic:
- * 1) reducing the performance overhead which affects browser window load;
- * 2) allow global hooks (e.g. startup and shutdown observers) which survive
- * browser windows to accomplish browser-related activities, such as shutdown
- * sanitization (see bug #284086)
- *
- */
-
-[scriptable, uuid(781df699-17dc-4237-b3d7-876ddb7085e3)]
-interface nsIBrowserGlue : nsISupports
-{
- /**
- * Deletes privacy sensitive data according to user preferences
- *
- * @param aParentWindow an optionally null window which is the parent of the
- * sanitization dialog
- *
- */
- void sanitize(in nsIDOMWindow aParentWindow);
-
- /**
- * Add Smart Bookmarks special queries to bookmarks menu and toolbar folder.
- */
- void ensurePlacesDefaultQueriesInitialized();
-
- /**
- * Gets the most recent window that's a browser (but not a popup)
- */
- nsIDOMWindow getMostRecentBrowserWindow();
-};
diff --git a/components/nsIBrowserHandler.idl b/components/nsIBrowserHandler.idl
deleted file mode 100644
index 74292f9..0000000
--- a/components/nsIBrowserHandler.idl
+++ /dev/null
@@ -1,20 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-interface nsICommandLine;
-
-[scriptable, uuid(8D3F5A9D-118D-4548-A137-CF7718679069)]
-interface nsIBrowserHandler : nsISupports
-{
- attribute AUTF8String startPage;
- attribute AUTF8String defaultArgs;
-
- /**
- * Extract the width and height specified on the command line, if present.
- * @return A feature string with a prepended comma, e.g. ",width=500,height=400"
- */
- AUTF8String getFeatures(in nsICommandLine aCmdLine);
-};
diff --git a/components/pageinfo/feeds.js b/components/pageinfo/feeds.js
deleted file mode 100644
index 468d8c1..0000000
--- a/components/pageinfo/feeds.js
+++ /dev/null
@@ -1,59 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-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, "feed" in rels);
- 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");
- openUILinkIn(listbox.selectedItem.getAttribute("feedURL"), "current",
- { ignoreAlt: true });
-}
-
-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);
-}
diff --git a/components/pageinfo/feeds.xml b/components/pageinfo/feeds.xml
deleted file mode 100644
index 782c05a..0000000
--- a/components/pageinfo/feeds.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!DOCTYPE bindings [
- <!ENTITY % pageInfoDTD SYSTEM "chrome://browser/locale/pageInfo.dtd">
- %pageInfoDTD;
-]>
-
-<bindings id="feedBindings"
- xmlns="http://www.mozilla.org/xbl"
- xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:xbl="http://www.mozilla.org/xbl">
-
- <binding id="feed" extends="chrome://global/content/bindings/richlistbox.xml#richlistitem">
- <content>
- <xul:vbox flex="1">
- <xul:hbox flex="1">
- <xul:textbox flex="1" readonly="true" xbl:inherits="value=name"
- class="feedTitle"/>
- <xul:label xbl:inherits="value=type"/>
- </xul:hbox>
- <xul:vbox>
- <xul:vbox align="start">
- <xul:hbox>
- <xul:label xbl:inherits="value=feedURL,tooltiptext=feedURL" class="text-link" flex="1"
- onclick="openUILink(this.value, event);" crop="end"/>
- </xul:hbox>
- </xul:vbox>
- </xul:vbox>
- <xul:hbox flex="1" class="feed-subscribe">
- <xul:spacer flex="1"/>
- <xul:button label="&feedSubscribe;" accesskey="&feedSubscribe.accesskey;"
- oncommand="onSubscribeFeed()"/>
- </xul:hbox>
- </xul:vbox>
- </content>
- </binding>
-</bindings>
diff --git a/components/pageinfo/jar.mn b/components/pageinfo/jar.mn
deleted file mode 100644
index 229f991..0000000
--- a/components/pageinfo/jar.mn
+++ /dev/null
@@ -1,13 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-browser.jar:
-* content/browser/pageinfo/pageInfo.xul
- content/browser/pageinfo/pageInfo.js
- content/browser/pageinfo/pageInfo.css
- content/browser/pageinfo/pageInfo.xml
- content/browser/pageinfo/feeds.js
- content/browser/pageinfo/feeds.xml
- content/browser/pageinfo/permissions.js
- content/browser/pageinfo/security.js \ No newline at end of file
diff --git a/components/pageinfo/moz.build b/components/pageinfo/moz.build
deleted file mode 100644
index 2d64d50..0000000
--- a/components/pageinfo/moz.build
+++ /dev/null
@@ -1,8 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-JAR_MANIFESTS += ['jar.mn']
-
diff --git a/components/pageinfo/pageInfo.css b/components/pageinfo/pageInfo.css
deleted file mode 100644
index 622b56b..0000000
--- a/components/pageinfo/pageInfo.css
+++ /dev/null
@@ -1,26 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-
-#viewGroup > radio {
- -moz-binding: url("chrome://browser/content/pageinfo/pageInfo.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;
-}
-
-#thepreviewimage {
- display: block;
-/* This following entry can be removed when Bug 522850 is fixed. */
- min-width: 1px;
-}
diff --git a/components/pageinfo/pageInfo.js b/components/pageinfo/pageInfo.js
deleted file mode 100644
index 600174a..0000000
--- a/components/pageinfo/pageInfo.js
+++ /dev/null
@@ -1,1286 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-var Cu = Components.utils;
-Cu.import("resource://gre/modules/LoadContextInfo.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-
-//******** define a js object to implement nsITreeView
-function pageInfoTreeView(treeid, 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.treeid = treeid;
- this.copycol = copycol;
- this.rows = 0;
- this.tree = null;
- this.data = [ ];
- this.selection = null;
- this.sortcol = -1;
- this.sortdir = false;
-}
-
-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);
- }
- },
-
- onPageMediaSort : function(columnname)
- {
- var tree = document.getElementById(this.treeid);
- var treecol = tree.columns.getNamedColumn(columnname);
-
- this.sortdir =
- gTreeUtils.sort(
- tree,
- this,
- this.data,
- treecol.index,
- function textComparator(a, b) { return a.toLowerCase().localeCompare(b.toLowerCase()); },
- this.sortcol,
- this.sortdir
- );
-
- this.sortcol = treecol.index;
- },
-
- getRowProperties: function(row) { return ""; },
- getCellProperties: function(row, column) { return ""; },
- getColumnProperties: function(column) { return ""; },
- 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('metatree', COPYCOL_META_CONTENT);
-var gImageView = new pageInfoTreeView('imagetree', COPYCOL_IMAGE);
-
-gImageView.getCellProperties = function(row, col) {
- var data = gImageView.data[row];
- var item = gImageView.data[row][COL_IMAGE_NODE];
- var props = "";
- if (!checkProtocol(data) ||
- item instanceof HTMLEmbedElement ||
- (item instanceof HTMLObjectElement && !item.type.startsWith("image/")))
- props += "broken";
-
- if (col.element.id == "image-address")
- props += " ltr";
-
- return props;
-};
-
-gImageView.getCellText = function(row, column) {
- var value = this.data[row][column.index];
- if (column.index == COL_IMAGE_SIZE) {
- if (value == -1) {
- return gStrings.unknown;
- } else {
- var kbSize = Number(Math.round(value / 1024 * 100) / 100);
- return gBundle.getFormattedString("mediaFileSize", [kbSize]);
- }
- }
- return value || "";
-};
-
-gImageView.onPageMediaSort = function(columnname) {
- var tree = document.getElementById(this.treeid);
- var treecol = tree.columns.getNamedColumn(columnname);
-
- var comparator;
- if (treecol.index == COL_IMAGE_SIZE || treecol.index == COL_IMAGE_COUNT) {
- comparator = function numComparator(a, b) { return a - b; };
- } else {
- comparator = function textComparator(a, b) { return a.toLowerCase().localeCompare(b.toLowerCase()); };
- }
-
- this.sortdir =
- gTreeUtils.sort(
- tree,
- this,
- this.data,
- treecol.index,
- comparator,
- this.sortcol,
- this.sortdir
- );
-
- this.sortcol = treecol.index;
-};
-
-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 nsICacheStorageService = Components.interfaces.nsICacheStorageService;
-const nsICacheStorage = Components.interfaces.nsICacheStorage;
-const cacheService = Components.classes["@mozilla.org/netwerk/cache-storage-service;1"].getService(nsICacheStorageService);
-
-var loadContextInfo = LoadContextInfo.fromLoadContext(
- window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
- .getInterface(Components.interfaces.nsIWebNavigation)
- .QueryInterface(Components.interfaces.nsILoadContext), false);
-var diskStorage = cacheService.diskCacheStorage(loadContextInfo, 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
-function getClipboardHelper() {
- try {
- return Components.classes["@mozilla.org/widget/clipboardhelper;1"].getService(Components.interfaces.nsIClipboardHelper);
- } catch(e) {
- // do nothing, later code will handle the error
- }
-}
-const gClipboardHelper = getClipboardHelper();
-
-// 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 = [ ];
-
-// These functions are called once when an image preview is shown.
-var onImagePreviewShown = [ ];
-
-/* 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.mediaBorderImg = gBundle.getString("mediaBorderImg");
- gStrings.mediaListImg = gBundle.getString("mediaListImg");
- gStrings.mediaCursor = gBundle.getString("mediaCursor");
- gStrings.mediaObject = gBundle.getString("mediaObject");
- gStrings.mediaEmbed = gBundle.getString("mediaEmbed");
- gStrings.mediaLink = gBundle.getString("mediaLink");
- gStrings.mediaInput = gBundle.getString("mediaInput");
- gStrings.mediaVideo = gBundle.getString("mediaVideo");
- gStrings.mediaAudio = gBundle.getString("mediaAudio");
-
- 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);
-
- // Make sure the page info window gets focus even if a doorhanger might
- // otherwise (async) steal it.
- window.focus();
-}
-
-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(gDocument.nodePrincipal);
-
- /* 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 openCacheEntry(key, cb)
-{
- var checkCacheListener = {
- onCacheEntryCheck: function(entry, appCache) {
- return Components.interfaces.nsICacheEntryOpenCallback.ENTRY_WANTED;
- },
- onCacheEntryAvailable: function(entry, isNew, appCache, status) {
- cb(entry);
- },
- get mainThreadOnly() { return true; }
- };
- diskStorage.asyncOpenURI(Services.io.newURI(key, null, null), "", nsICacheStorage.OPEN_READONLY, checkCacheListener);
-}
-
-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.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(/#.*$/, "");
- openCacheEntry(cacheKey, function(cacheEntry) {
- var sizeText;
- if (cacheEntry) {
- var pageSize = cacheEntry.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);
- gFrameList.shift();
- setTimeout(doGrab, 10, iterator);
- onFinished.push(selectImage);
- }
- else
- onFinished.forEach(function(func) { func(); });
-}
-
-function doGrab(iterator)
-{
- for (var i = 0; i < 500; ++i)
- if (!iterator.nextNode()) {
- processFrames();
- return;
- }
-
- setTimeout(doGrab, 10, 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;
- var row = [url, type, -1, alt, 1, elem, isBg];
- gImageView.addRow(row);
-
- // Fill in cache data asynchronously
- openCacheEntry(url, function(cacheEntry) {
- // The data at row[2] corresponds to the data size.
- if (cacheEntry) {
- row[2] = cacheEntry.dataSize;
- // Invalidate the row to trigger a repaint.
- gImageView.tree.invalidateRow(gImageView.data.indexOf(row));
- }
- });
-
- // 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 images defined in CSS (e.g. background, borders), any node may have multiple
- var computedStyle = elem.ownerDocument.defaultView.getComputedStyle(elem, "");
-
- if (computedStyle) {
- var addImgFunc = function (label, val) {
- if (val.primitiveType == CSSPrimitiveValue.CSS_URI) {
- addImage(val.getStringValue(), label, gStrings.notSet, elem, true);
- }
- else if (val.primitiveType == CSSPrimitiveValue.CSS_STRING) {
- // This is for -moz-image-rect.
- // TODO: Reimplement once bug 714757 is fixed
- var strVal = val.getStringValue();
- if (strVal.search(/^.*url\(\"?/) > -1) {
- url = strVal.replace(/^.*url\(\"?/,"").replace(/\"?\).*$/,"");
- addImage(url, label, gStrings.notSet, elem, true);
- }
- }
- else if (val.cssValueType == CSSValue.CSS_VALUE_LIST) {
- // recursively resolve multiple nested CSS value lists
- for (var i = 0; i < val.length; i++)
- addImgFunc(label, val.item(i));
- }
- };
-
- addImgFunc(gStrings.mediaBGImg, computedStyle.getPropertyCSSValue("background-image"));
- addImgFunc(gStrings.mediaBorderImg, computedStyle.getPropertyCSSValue("border-image-source"));
- addImgFunc(gStrings.mediaListImg, computedStyle.getPropertyCSSValue("list-style-image"));
- addImgFunc(gStrings.mediaCursor, computedStyle.getPropertyCSSValue("cursor"));
- }
-
- // 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);
- 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) { }
- }
- else if (elem instanceof HTMLVideoElement) {
- addImage(elem.currentSrc, gStrings.mediaVideo, "", elem, false);
- }
- else if (elem instanceof HTMLAudioElement) {
- addImage(elem.currentSrc, gStrings.mediaAudio, "", elem, false);
- }
- 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 getSelectedRows(tree)
-{
- 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 <= end.value; v++)
- rowArray.push(v);
- }
-
- return rowArray;
-}
-
-function getSelectedRow(tree)
-{
- var rows = getSelectedRows(tree);
- return (rows.length == 1) ? rows[0] : -1;
-}
-
-function selectSaveFolder(aCallback)
-{
- const nsILocalFile = Components.interfaces.nsILocalFile;
- const nsIFilePicker = Components.interfaces.nsIFilePicker;
- let titleText = gBundle.getString("mediaSelectFolder");
- let fp = Components.classes["@mozilla.org/filepicker;1"].
- createInstance(nsIFilePicker);
- let fpCallback = function fpCallback_done(aResult) {
- if (aResult == nsIFilePicker.returnOK) {
- aCallback(fp.file.QueryInterface(nsILocalFile));
- } else {
- aCallback(null);
- }
- };
-
- fp.init(window, titleText, nsIFilePicker.modeGetFolder);
- fp.appendFilters(nsIFilePicker.filterAll);
- try {
- let prefs = Components.classes[PREFERENCES_CONTRACTID].
- getService(Components.interfaces.nsIPrefBranch);
- let initialDir = prefs.getComplexValue("browser.download.dir", nsILocalFile);
- if (initialDir) {
- fp.displayDirectory = initialDir;
- }
- } catch (ex) {
- }
- fp.open(fpCallback);
-}
-
-function saveMedia()
-{
- var tree = document.getElementById("imagetree");
- var rowArray = getSelectedRows(tree);
- if (rowArray.length == 1) {
- var row = rowArray[0];
- var item = gImageView.data[row][COL_IMAGE_NODE];
- var url = gImageView.data[row][COL_IMAGE_ADDRESS];
-
- if (url) {
- var titleKey = "SaveImageTitle";
-
- if (item instanceof HTMLVideoElement)
- titleKey = "SaveVideoTitle";
- else if (item instanceof HTMLAudioElement)
- titleKey = "SaveAudioTitle";
-
- saveURL(url, null, titleKey, false, false, makeURI(item.baseURI), gDocument);
- }
- } else {
- selectSaveFolder(function(aDirectory) {
- if (aDirectory) {
- var saveAnImage = function(aURIString, aChosenData, aBaseURI) {
- internalSave(aURIString, null, null, null, null, false, "SaveImageTitle",
- aChosenData, aBaseURI, gDocument);
- };
-
- for (var i = 0; i < rowArray.length; i++) {
- var v = rowArray[i];
- var dir = aDirectory.clone();
- var item = gImageView.data[v][COL_IMAGE_NODE];
- var uriString = gImageView.data[v][COL_IMAGE_ADDRESS];
- var uri = makeURI(uriString);
-
- try {
- uri.QueryInterface(Components.interfaces.nsIURL);
- dir.append(decodeURIComponent(uri.fileName));
- } catch(ex) {
- /* data: uris */
- }
-
- if (i == 0) {
- saveAnImage(uriString, new AutoChosen(dir, uri), makeURI(item.baseURI));
- } else {
- // This delay is a hack which prevents the download manager
- // from opening many times. See bug 377339.
- setTimeout(saveAnImage, 200, uriString, new AutoChosen(dir, uri),
- makeURI(item.baseURI));
- }
- }
- }
- });
- }
-}
-
-function onBlockImage()
-{
- var permissionManager = Components.classes[PERMISSION_CONTRACTID]
- .getService(nsIPermissionManager);
-
- var checkbox = document.getElementById("blockImage");
- var uri = makeURI(document.getElementById("imageurltext").value);
- if (checkbox.checked)
- permissionManager.add(uri, "image", nsIPermissionManager.DENY_ACTION);
- else
- permissionManager.remove(uri, "image");
-}
-
-function onImageSelect()
-{
- var previewBox = document.getElementById("mediaPreviewBox");
- var mediaSaveBox = document.getElementById("mediaSaveBox");
- var splitter = document.getElementById("mediaSplitter");
- var tree = document.getElementById("imagetree");
- var count = tree.view.selection.count;
- if (count == 0) {
- previewBox.collapsed = true;
- mediaSaveBox.collapsed = true;
- splitter.collapsed = true;
- tree.flex = 1;
- }
- else if (count > 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(getSelectedRows(tree)[0]);
- }
-}
-
-function makePreview(row)
-{
- var imageTree = document.getElementById("imagetree");
- var item = gImageView.data[row][COL_IMAGE_NODE];
- var url = gImageView.data[row][COL_IMAGE_ADDRESS];
- var isBG = gImageView.data[row][COL_IMAGE_BG];
- var isAudio = false;
-
- setItemValue("imageurltext", url);
-
- var imageText;
- if (!isBG &&
- !(item instanceof SVGImageElement) &&
- !(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(/#.*$/, "");
- openCacheEntry(cacheKey, function(cacheEntry) {
- // find out the file size
- var sizeText;
- if (cacheEntry) {
- var imageSize = cacheEntry.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(cacheEntry);
-
- // if we have a data url, get the MIME type from the url
- if (!mimeType && url.startsWith("data:")) {
- let dataMimeType = /^data:(image\/[^;,]+)/i.exec(url);
- if (dataMimeType)
- mimeType = dataMimeType[1].toLowerCase();
- }
-
- var imageType;
- if (mimeType) {
- // We found the type, try to display it nicely
- let imageMimeType = /^image\/(.*)/i.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");
-
- var isProtocolAllowed = checkProtocol(gImageView.data[row]);
-
- var newImage = new Image;
- newImage.id = "thepreviewimage";
- var physWidth = 0, physHeight = 0;
- var width = 0, height = 0;
-
- if ((item instanceof HTMLLinkElement || item instanceof HTMLInputElement ||
- item instanceof HTMLImageElement ||
- item instanceof SVGImageElement ||
- (item instanceof HTMLObjectElement && mimeType && mimeType.startsWith("image/")) || 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;
- }
-
- if (item instanceof SVGImageElement) {
- newImage.width = item.width.baseVal.value;
- newImage.height = item.height.baseVal.value;
- }
-
- width = newImage.width;
- height = newImage.height;
-
- document.getElementById("theimagecontainer").collapsed = false
- document.getElementById("brokenimagecontainer").collapsed = true;
- }
- else if (item instanceof HTMLVideoElement && isProtocolAllowed) {
- newImage = document.createElementNS("http://www.w3.org/1999/xhtml", "video");
- newImage.id = "thepreviewimage";
- newImage.src = url;
- newImage.controls = true;
- width = physWidth = item.videoWidth;
- height = physHeight = item.videoHeight;
-
- document.getElementById("theimagecontainer").collapsed = false;
- document.getElementById("brokenimagecontainer").collapsed = true;
- }
- else if (item instanceof HTMLAudioElement && isProtocolAllowed) {
- newImage = new Audio;
- newImage.id = "thepreviewimage";
- newImage.src = url;
- newImage.controls = true;
- isAudio = true;
-
- document.getElementById("theimagecontainer").collapsed = false;
- document.getElementById("brokenimagecontainer").collapsed = true;
- }
- else {
- // fallback image for protocols not allowed (e.g., javascript:)
- // or elements not [yet] handled (e.g., object, embed).
- document.getElementById("brokenimagecontainer").collapsed = false;
- document.getElementById("theimagecontainer").collapsed = true;
- }
-
- var imageSize = "";
- if (url && !isAudio) {
- 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);
-
- onImagePreviewShown.forEach(function(func) { func(); });
- });
-}
-
-function makeBlockImage(url)
-{
- var permissionManager = Components.classes[PERMISSION_CONTRACTID]
- .getService(nsIPermissionManager);
- var prefs = Components.classes[PREFERENCES_CONTRACTID]
- .getService(Components.interfaces.nsIPrefBranch);
-
- 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 = getSelectedRow(imageTree);
- var item = gImageView.data[row][COL_IMAGE_NODE];
- var url = gImageView.data[row][COL_IMAGE_ADDRESS];
- if (permission.matchesURI(makeURI(url), true)) {
- 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 <= max.value; row++) {
- view.performActionOnRow("copy", row);
-
- tmp = elem.getAttribute("copybuffer");
- if (tmp)
- text.push(tmp);
- elem.removeAttribute("copybuffer");
- }
- }
- gClipboardHelper.copyString(text.join("\n"), document);
- }
-}
-
-function doSelectAll()
-{
- var elem = document.commandDispatcher.focusedElement;
-
- if (elem && "treeBoxObject" in elem)
- elem.view.selection.selectAll();
-}
-
-function selectImage()
-{
- if (!gImageElement)
- return;
-
- var tree = document.getElementById("imagetree");
- for (var i = 0; i < tree.view.rowCount; i++) {
- if (gImageElement == gImageView.data[i][COL_IMAGE_NODE] &&
- !gImageView.data[i][COL_IMAGE_BG]) {
- tree.view.selection.select(i);
- tree.treeBoxObject.ensureRowIsVisible(i);
- tree.focus();
- return;
- }
- }
-}
-
-function checkProtocol(img)
-{
- var url = img[COL_IMAGE_ADDRESS];
- return /^data:image\//i.test(url) ||
- /^(https?|ftp|file|about|chrome|resource):/.test(url);
-}
diff --git a/components/pageinfo/pageInfo.xml b/components/pageinfo/pageInfo.xml
deleted file mode 100644
index 20d3300..0000000
--- a/components/pageinfo/pageInfo.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-
-<bindings id="pageInfoBindings"
- xmlns="http://www.mozilla.org/xbl"
- xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:xbl="http://www.mozilla.org/xbl">
-
- <!-- based on preferences.xml paneButton -->
- <binding id="viewbutton" extends="chrome://global/content/bindings/radio.xml#radio">
- <content>
- <xul:image class="viewButtonIcon" xbl:inherits="src"/>
- <xul:label class="viewButtonLabel" xbl:inherits="value=label"/>
- </content>
- <implementation implements="nsIAccessibleProvider">
- <property name="accessibleType" readonly="true">
- <getter>
- <![CDATA[
- return Components.interfaces.nsIAccessibleProvider.XULListitem;
- ]]>
- </getter>
- </property>
- </implementation>
- </binding>
-
-</bindings>
diff --git a/components/pageinfo/pageInfo.xul b/components/pageinfo/pageInfo.xul
deleted file mode 100644
index c7c486a..0000000
--- a/components/pageinfo/pageInfo.xul
+++ /dev/null
@@ -1,507 +0,0 @@
-<?xml version="1.0"?>
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-<?xml-stylesheet href="chrome://browser/content/pageinfo/pageInfo.css" type="text/css"?>
-<?xml-stylesheet href="chrome://browser/skin/pageInfo.css" type="text/css"?>
-
-<!DOCTYPE window [
- <!ENTITY % pageInfoDTD SYSTEM "chrome://browser/locale/pageInfo.dtd">
- %pageInfoDTD;
-]>
-
-#ifdef XP_MACOSX
-<?xul-overlay href="chrome://browser/content/macBrowserOverlay.xul"?>
-#endif
-
-<window id="main-window"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- windowtype="Browser:page-info"
- onload="onLoadPageInfo()"
- onunload="onUnloadPageInfo()"
- align="stretch"
- screenX="10" screenY="10"
- width="&pageInfoWindow.width;" height="&pageInfoWindow.height;"
- persist="screenX screenY width height sizemode">
-
- <script type="application/javascript" src="chrome://global/content/globalOverlay.js"/>
- <script type="application/javascript" src="chrome://global/content/contentAreaUtils.js"/>
- <script type="application/javascript" src="chrome://global/content/treeUtils.js"/>
- <script type="application/javascript" src="chrome://browser/content/pageinfo/pageInfo.js"/>
- <script type="application/javascript" src="chrome://browser/content/pageinfo/feeds.js"/>
- <script type="application/javascript" src="chrome://browser/content/pageinfo/permissions.js"/>
- <script type="application/javascript" src="chrome://browser/content/pageinfo/security.js"/>
- <script type="application/javascript" src="chrome://browser/content/utilityOverlay.js"/>
-
- <stringbundleset id="pageinfobundleset">
- <stringbundle id="pageinfobundle" src="chrome://browser/locale/pageInfo.properties"/>
- <stringbundle id="pkiBundle" src="chrome://pippki/locale/pippki.properties"/>
- <stringbundle id="browserBundle" src="chrome://browser/locale/browser.properties"/>
- </stringbundleset>
-
- <commandset id="pageInfoCommandSet">
- <command id="cmd_close" oncommand="window.close();"/>
- <command id="cmd_help" oncommand="doHelpButton();"/>
- <command id="cmd_copy" oncommand="doCopy();"/>
- <command id="cmd_selectall" oncommand="doSelectAll();"/>
-
- <!-- permissions tab -->
- <command id="cmd_imageDef" oncommand="onCheckboxClick('image');"/>
- <command id="cmd_popupDef" oncommand="onCheckboxClick('popup');"/>
- <command id="cmd_cookieDef" oncommand="onCheckboxClick('cookie');"/>
- <command id="cmd_desktop-notificationDef" oncommand="onCheckboxClick('desktop-notification');"/>
- <command id="cmd_installDef" oncommand="onCheckboxClick('install');"/>
- <command id="cmd_geoDef" oncommand="onCheckboxClick('geo');"/>
- <command id="cmd_pluginsDef" oncommand="onCheckboxClick('plugins');"/>
- <command id="cmd_imageToggle" oncommand="onRadioClick('image');"/>
- <command id="cmd_popupToggle" oncommand="onRadioClick('popup');"/>
- <command id="cmd_cookieToggle" oncommand="onRadioClick('cookie');"/>
- <command id="cmd_desktop-notificationToggle" oncommand="onRadioClick('desktop-notification');"/>
- <command id="cmd_installToggle" oncommand="onRadioClick('install');"/>
- <command id="cmd_geoToggle" oncommand="onRadioClick('geo');"/>
- <command id="cmd_pluginsToggle" oncommand="onPluginRadioClick(event);"/>
- </commandset>
-
- <keyset id="pageInfoKeySet">
- <key key="&closeWindow.key;" modifiers="accel" command="cmd_close"/>
- <key keycode="VK_ESCAPE" command="cmd_close"/>
-#ifdef XP_MACOSX
- <key key="." modifiers="meta" command="cmd_close"/>
-#else
- <key keycode="VK_F1" command="cmd_help"/>
-#endif
- <key key="&copy.key;" modifiers="accel" command="cmd_copy"/>
- <key key="&selectall.key;" modifiers="accel" command="cmd_selectall"/>
- <key key="&selectall.key;" modifiers="alt" command="cmd_selectall"/>
- </keyset>
-
- <menupopup id="picontext">
- <menuitem id="menu_selectall" label="&selectall.label;" command="cmd_selectall" accesskey="&selectall.accesskey;"/>
- <menuitem id="menu_copy" label="&copy.label;" command="cmd_copy" accesskey="&copy.accesskey;"/>
- </menupopup>
-
- <windowdragbox id="topBar" class="viewGroupWrapper">
- <radiogroup id="viewGroup" class="chromeclass-toolbar" orient="horizontal">
- <radio id="generalTab" label="&generalTab;" accesskey="&generalTab.accesskey;"
- oncommand="showTab('general');"/>
- <radio id="mediaTab" label="&mediaTab;" accesskey="&mediaTab.accesskey;"
- oncommand="showTab('media');" hidden="true"/>
- <radio id="feedTab" label="&feedTab;" accesskey="&feedTab.accesskey;"
- oncommand="showTab('feed');" hidden="true"/>
- <radio id="permTab" label="&permTab;" accesskey="&permTab.accesskey;"
- oncommand="showTab('perm');"/>
- <radio id="securityTab" label="&securityTab;" accesskey="&securityTab.accesskey;"
- oncommand="showTab('security');"/>
- <!-- Others added by overlay -->
- </radiogroup>
- </windowdragbox>
-
- <deck id="mainDeck" flex="1">
- <!-- General page information -->
- <vbox id="generalPanel">
- <textbox class="header" readonly="true" id="titletext"/>
- <grid id="generalGrid">
- <columns>
- <column/>
- <column class="gridSeparator"/>
- <column flex="1"/>
- </columns>
- <rows id="generalRows">
- <row id="generalURLRow">
- <label control="urltext" value="&generalURL;"/>
- <separator/>
- <textbox readonly="true" id="urltext"/>
- </row>
- <row id="generalSeparatorRow1">
- <separator class="thin"/>
- </row>
- <row id="generalTypeRow">
- <label control="typetext" value="&generalType;"/>
- <separator/>
- <textbox readonly="true" id="typetext"/>
- </row>
- <row id="generalModeRow">
- <label control="modetext" value="&generalMode;"/>
- <separator/>
- <textbox readonly="true" crop="end" id="modetext"/>
- </row>
- <row id="generalEncodingRow">
- <label control="encodingtext" value="&generalEncoding;"/>
- <separator/>
- <textbox readonly="true" id="encodingtext"/>
- </row>
- <row id="generalSizeRow">
- <label control="sizetext" value="&generalSize;"/>
- <separator/>
- <textbox readonly="true" id="sizetext"/>
- </row>
- <row id="generalReferrerRow">
- <label control="refertext" value="&generalReferrer;"/>
- <separator/>
- <textbox readonly="true" id="refertext"/>
- </row>
- <row id="generalSeparatorRow2">
- <separator class="thin"/>
- </row>
- <row id="generalModifiedRow">
- <label control="modifiedtext" value="&generalModified;"/>
- <separator/>
- <textbox readonly="true" id="modifiedtext"/>
- </row>
- </rows>
- </grid>
- <separator class="thin"/>
- <groupbox id="metaTags" flex="1" class="collapsable treebox">
- <caption id="metaTagsCaption" onclick="toggleGroupbox('metaTags');"/>
- <tree id="metatree" flex="1" hidecolumnpicker="true" contextmenu="picontext">
- <treecols>
- <treecol id="meta-name" label="&generalMetaName;"
- persist="width" flex="1"
- onclick="gMetaView.onPageMediaSort('meta-name');"/>
- <splitter class="tree-splitter"/>
- <treecol id="meta-content" label="&generalMetaContent;"
- persist="width" flex="4"
- onclick="gMetaView.onPageMediaSort('meta-content');"/>
- </treecols>
- <treechildren id="metatreechildren" flex="1"/>
- </tree>
- </groupbox>
- <groupbox id="securityBox">
- <caption id="securityBoxCaption" label="&securityHeader;"/>
- <description id="general-security-identity" class="header"/>
- <description id="general-security-privacy" class="header"/>
- <hbox id="securityDetailsButtonBox" align="right">
- <button id="security-view-details" label="&generalSecurityDetails;"
- accesskey="&generalSecurityDetails.accesskey;"
- oncommand="onClickMore();"/>
- </hbox>
- </groupbox>
- </vbox>
-
- <!-- Media information -->
- <vbox id="mediaPanel">
- <tree id="imagetree" onselect="onImageSelect();" contextmenu="picontext"
- ondragstart="onBeginLinkDrag(event,'image-address','image-alt')">
- <treecols>
- <treecol sortSeparators="true" primary="true" persist="width" flex="10"
- width="10" id="image-address" label="&mediaAddress;"
- onclick="gImageView.onPageMediaSort('image-address');"/>
- <splitter class="tree-splitter"/>
- <treecol sortSeparators="true" persist="hidden width" flex="2"
- width="2" id="image-type" label="&mediaType;"
- onclick="gImageView.onPageMediaSort('image-type');"/>
- <splitter class="tree-splitter"/>
- <treecol sortSeparators="true" hidden="true" persist="hidden width" flex="2"
- width="2" id="image-size" label="&mediaSize;" value="size"
- onclick="gImageView.onPageMediaSort('image-size');"/>
- <splitter class="tree-splitter"/>
- <treecol sortSeparators="true" hidden="true" persist="hidden width" flex="4"
- width="4" id="image-alt" label="&mediaAltHeader;"
- onclick="gImageView.onPageMediaSort('image-alt');"/>
- <splitter class="tree-splitter"/>
- <treecol sortSeparators="true" hidden="true" persist="hidden width" flex="1"
- width="1" id="image-count" label="&mediaCount;"
- onclick="gImageView.onPageMediaSort('image-count');"/>
- </treecols>
- <treechildren id="imagetreechildren" flex="1"/>
- </tree>
- <splitter orient="vertical" id="mediaSplitter"/>
- <vbox flex="1" id="mediaPreviewBox" collapsed="true">
- <grid id="mediaGrid">
- <columns>
- <column id="mediaLabelColumn"/>
- <column class="gridSeparator"/>
- <column flex="1"/>
- </columns>
- <rows id="mediaRows">
- <row id="mediaLocationRow">
- <label control="imageurltext" value="&mediaLocation;"/>
- <separator/>
- <textbox readonly="true" id="imageurltext"/>
- </row>
- <row id="mediaTypeRow">
- <label control="imagetypetext" value="&generalType;"/>
- <separator/>
- <textbox readonly="true" id="imagetypetext"/>
- </row>
- <row id="mediaSizeRow">
- <label control="imagesizetext" value="&generalSize;"/>
- <separator/>
- <textbox readonly="true" id="imagesizetext"/>
- </row>
- <row id="mediaDimensionRow">
- <label control="imagedimensiontext" value="&mediaDimension;"/>
- <separator/>
- <textbox readonly="true" id="imagedimensiontext"/>
- </row>
- <row id="mediaTextRow">
- <label control="imagetext" value="&mediaText;"/>
- <separator/>
- <textbox readonly="true" id="imagetext"/>
- </row>
- <row id="mediaLongdescRow">
- <label control="imagelongdesctext" value="&mediaLongdesc;"/>
- <separator/>
- <textbox readonly="true" id="imagelongdesctext"/>
- </row>
- </rows>
- </grid>
- <hbox id="imageSaveBox" align="end">
- <vbox id="blockImageBox">
- <checkbox id="blockImage" hidden="true" oncommand="onBlockImage()"
- accesskey="&mediaBlockImage.accesskey;"/>
- <label control="thepreviewimage" value="&mediaPreview;" class="header"/>
- </vbox>
- <spacer id="imageSaveBoxSpacer" flex="1"/>
- <button label="&mediaSaveAs;" accesskey="&mediaSaveAs.accesskey;"
- icon="save" id="imagesaveasbutton"
- oncommand="saveMedia();"/>
- </hbox>
- <vbox id="imagecontainerbox" class="inset iframe" flex="1" pack="center">
- <hbox id="theimagecontainer" pack="center">
- <image id="thepreviewimage"/>
- </hbox>
- <hbox id="brokenimagecontainer" pack="center" collapsed="true">
- <image id="brokenimage" src="resource://gre-resources/broken-image.png"/>
- </hbox>
- </vbox>
- </vbox>
- <hbox id="mediaSaveBox" collapsed="true">
- <spacer id="mediaSaveBoxSpacer" flex="1"/>
- <button label="&mediaSaveAs;" accesskey="&mediaSaveAs2.accesskey;"
- icon="save" id="mediasaveasbutton"
- oncommand="saveMedia();"/>
- </hbox>
- </vbox>
-
- <!-- Feeds -->
- <vbox id="feedPanel">
- <richlistbox id="feedListbox" flex="1"/>
- </vbox>
-
- <!-- Permissions -->
- <vbox id="permPanel">
- <hbox id="permHostBox">
- <label value="&permissionsFor;" control="hostText" />
- <textbox id="hostText" class="header" readonly="true"
- crop="end" flex="1"/>
- </hbox>
-
- <vbox id="permList" flex="1">
- <vbox class="permission" id="permImageRow">
- <label class="permissionLabel" id="permImageLabel"
- value="&permImage;" control="imageRadioGroup"/>
- <hbox id="permImageBox" role="group" aria-labelledby="permImageLabel">
- <checkbox id="imageDef" command="cmd_imageDef" label="&permUseDefault;"/>
- <spacer flex="1"/>
- <radiogroup id="imageRadioGroup" orient="horizontal">
- <radio id="image#1" command="cmd_imageToggle" label="&permAllow;"/>
- <radio id="image#2" command="cmd_imageToggle" label="&permBlock;"/>
- </radiogroup>
- </hbox>
- </vbox>
- <vbox class="permission" id="permPopupRow">
- <label class="permissionLabel" id="permPopupLabel"
- value="&permPopup;" control="popupRadioGroup"/>
- <hbox id="permPopupBox" role="group" aria-labelledby="permPopupLabel">
- <checkbox id="popupDef" command="cmd_popupDef" label="&permUseDefault;"/>
- <spacer flex="1"/>
- <radiogroup id="popupRadioGroup" orient="horizontal">
- <radio id="popup#1" command="cmd_popupToggle" label="&permAllow;"/>
- <radio id="popup#2" command="cmd_popupToggle" label="&permBlock;"/>
- </radiogroup>
- </hbox>
- </vbox>
- <vbox class="permission" id="permCookieRow">
- <label class="permissionLabel" id="permCookieLabel"
- value="&permCookie;" control="cookieRadioGroup"/>
- <hbox id="permCookieBox" role="group" aria-labelledby="permCookieLabel">
- <checkbox id="cookieDef" command="cmd_cookieDef" label="&permUseDefault;"/>
- <spacer flex="1"/>
- <radiogroup id="cookieRadioGroup" orient="horizontal">
- <radio id="cookie#1" command="cmd_cookieToggle" label="&permAllow;"/>
- <radio id="cookie#8" command="cmd_cookieToggle" label="&permAllowSession;"/>
- <radio id="cookie#9" command="cmd_cookieToggle" label="&permAllowFirstPartyOnly;"/>
- <radio id="cookie#2" command="cmd_cookieToggle" label="&permBlock;"/>
- </radiogroup>
- </hbox>
- </vbox>
- <vbox class="permission" id="permNotificationRow">
- <label class="permissionLabel" id="permNotificationLabel"
- value="&permNotifications;" control="desktop-notificationRadioGroup"/>
- <hbox role="group" aria-labelledby="permNotificationLabel">
- <checkbox id="desktop-notificationDef" command="cmd_desktop-notificationDef" label="&permUseDefault;"/>
- <spacer flex="1"/>
- <radiogroup id="desktop-notificationRadioGroup" orient="horizontal">
- <radio id="desktop-notification#0" command="cmd_desktop-notificationToggle" label="&permAskAlways;"/>
- <radio id="desktop-notification#1" command="cmd_desktop-notificationToggle" label="&permAllow;"/>
- <radio id="desktop-notification#2" command="cmd_desktop-notificationToggle" label="&permBlock;"/>
- </radiogroup>
- </hbox>
- </vbox>
- <vbox class="permission" id="permInstallRow">
- <label class="permissionLabel" id="permInstallLabel"
- value="&permInstall;" control="installRadioGroup"/>
- <hbox id="permInstallBox" role="group" aria-labelledby="permInstallLabel">
- <checkbox id="installDef" command="cmd_installDef" label="&permUseDefault;"/>
- <spacer flex="1"/>
- <radiogroup id="installRadioGroup" orient="horizontal">
- <radio id="install#1" command="cmd_installToggle" label="&permAllow;"/>
- <radio id="install#2" command="cmd_installToggle" label="&permBlock;"/>
- </radiogroup>
- </hbox>
- </vbox>
- <vbox class="permission" id="permGeoRow" >
- <label class="permissionLabel" id="permGeoLabel"
- value="&permGeo;" control="geoRadioGroup"/>
- <hbox id="permGeoBox" role="group" aria-labelledby="permGeoLabel">
- <checkbox id="geoDef" command="cmd_geoDef" label="&permAskAlways;"/>
- <spacer flex="1"/>
- <radiogroup id="geoRadioGroup" orient="horizontal">
- <radio id="geo#1" command="cmd_geoToggle" label="&permAllow;"/>
- <radio id="geo#2" command="cmd_geoToggle" label="&permBlock;"/>
- </radiogroup>
- </hbox>
- </vbox>
- <vbox class="permission" id="permPluginsRow">
- <label class="permissionLabel" id="permPluginsLabel"
- value="&permPlugins;" control="pluginsRadioGroup"/>
- <hbox id="permPluginTemplate" role="group" aria-labelledby="permPluginsLabel" align="baseline">
- <label class="permPluginTemplateLabel"/>
- <spacer flex="1"/>
- <radiogroup class="permPluginTemplateRadioGroup" orient="horizontal" command="cmd_pluginsToggle">
- <radio class="permPluginTemplateRadioDefault" label="&permUseDefault;"/>
- <radio class="permPluginTemplateRadioAsk" label="&permAskAlways;"/>
- <radio class="permPluginTemplateRadioAllow" label="&permAllow;"/>
- <radio class="permPluginTemplateRadioBlock" label="&permBlock;"/>
- </radiogroup>
- </hbox>
- </vbox>
- </vbox>
- </vbox>
-
- <!-- Security & Privacy -->
- <vbox id="securityPanel">
- <!-- Identity Section -->
- <groupbox id="security-identity-groupbox" flex="1">
- <caption id="security-identity" label="&securityView.identity.header;"/>
- <grid id="security-identity-grid" flex="1">
- <columns>
- <column/>
- <column flex="1"/>
- </columns>
- <rows id="security-identity-rows">
- <!-- Domain -->
- <row id="security-identity-domain-row">
- <label id="security-identity-domain-label"
- class="fieldLabel"
- value="&securityView.identity.domain;"
- control="security-identity-domain-value"/>
- <textbox id="security-identity-domain-value"
- class="fieldValue" readonly="true"/>
- </row>
- <!-- Owner -->
- <row id="security-identity-owner-row">
- <label id="security-identity-owner-label"
- class="fieldLabel"
- value="&securityView.identity.owner;"
- control="security-identity-owner-value"/>
- <textbox id="security-identity-owner-value"
- class="fieldValue" readonly="true"/>
- </row>
- <!-- Verifier -->
- <row id="security-identity-verifier-row">
- <label id="security-identity-verifier-label"
- class="fieldLabel"
- value="&securityView.identity.verifier;"
- control="security-identity-verifier-value"/>
- <textbox id="security-identity-verifier-value"
- class="fieldValue" readonly="true" />
- </row>
- </rows>
- </grid>
- <spacer flex="1"/>
- <!-- Cert button -->
- <hbox id="security-view-cert-box" pack="end">
- <button id="security-view-cert" label="&securityView.certView;"
- accesskey="&securityView.accesskey;"
- oncommand="security.viewCert();"/>
- </hbox>
- </groupbox>
-
- <!-- Privacy & History section -->
- <groupbox id="security-privacy-groupbox" flex="1">
- <caption id="security-privacy" label="&securityView.privacy.header;" />
- <grid id="security-privacy-grid">
- <columns>
- <column flex="1"/>
- <column flex="1"/>
- </columns>
- <rows id="security-privacy-rows">
- <!-- History -->
- <row id="security-privacy-history-row">
- <label id="security-privacy-history-label"
- control="security-privacy-history-value"
- class="fieldLabel">&securityView.privacy.history;</label>
- <textbox id="security-privacy-history-value"
- class="fieldValue"
- value="&securityView.unknown;"
- readonly="true"/>
- </row>
- <!-- Cookies -->
- <row id="security-privacy-cookies-row">
- <label id="security-privacy-cookies-label"
- control="security-privacy-cookies-value"
- class="fieldLabel">&securityView.privacy.cookies;</label>
- <hbox id="security-privacy-cookies-box" align="center">
- <textbox id="security-privacy-cookies-value"
- class="fieldValue"
- value="&securityView.unknown;"
- flex="1"
- readonly="true"/>
- <button id="security-view-cookies"
- label="&securityView.privacy.viewCookies;"
- accesskey="&securityView.privacy.viewCookies.accessKey;"
- oncommand="security.viewCookies();"/>
- </hbox>
- </row>
- <!-- Passwords -->
- <row id="security-privacy-passwords-row">
- <label id="security-privacy-passwords-label"
- control="security-privacy-passwords-value"
- class="fieldLabel">&securityView.privacy.passwords;</label>
- <hbox id="security-privacy-passwords-box" align="center">
- <textbox id="security-privacy-passwords-value"
- class="fieldValue"
- value="&securityView.unknown;"
- flex="1"
- readonly="true"/>
- <button id="security-view-password"
- label="&securityView.privacy.viewPasswords;"
- accesskey="&securityView.privacy.viewPasswords.accessKey;"
- oncommand="security.viewPasswords();"/>
- </hbox>
- </row>
- </rows>
- </grid>
- </groupbox>
-
- <!-- Technical Details section -->
- <groupbox id="security-technical-groupbox" flex="1">
- <caption id="security-technical" label="&securityView.technical.header;" />
- <vbox id="security-technical-box" flex="1">
- <label id="security-technical-shortform" class="fieldValue"/>
- <description id="security-technical-longform1" class="fieldLabel"/>
- <description id="security-technical-longform2" class="fieldLabel"/>
- </vbox>
- </groupbox>
- </vbox>
- <!-- Others added by overlay -->
- </deck>
-
-#ifdef XP_MACOSX
-#include ../../base/content/browserMountPoints.inc
-#endif
-
-</window>
diff --git a/components/pageinfo/permissions.js b/components/pageinfo/permissions.js
deleted file mode 100644
index 4f8382f..0000000
--- a/components/pageinfo/permissions.js
+++ /dev/null
@@ -1,341 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-const UNKNOWN = nsIPermissionManager.UNKNOWN_ACTION; // 0
-const ALLOW = nsIPermissionManager.ALLOW_ACTION; // 1
-const DENY = nsIPermissionManager.DENY_ACTION; // 2
-const SESSION = nsICookiePermission.ACCESS_SESSION; // 8
-
-const IMAGE_DENY = 2;
-
-const COOKIE_DENY = 2;
-const COOKIE_SESSION = 2;
-
-var gPermURI;
-var gPermPrincipal;
-var gPrefs;
-var gUsageRequest;
-
-var gPermObj = {
- image: function getImageDefaultPermission()
- {
- if (gPrefs.getIntPref("permissions.default.image") == IMAGE_DENY) {
- return DENY;
- }
- return ALLOW;
- },
- popup: function getPopupDefaultPermission()
- {
- if (gPrefs.getBoolPref("dom.disable_open_during_load")) {
- return DENY;
- }
- return ALLOW;
- },
- cookie: function getCookieDefaultPermission()
- {
- if (gPrefs.getIntPref("network.cookie.cookieBehavior") == COOKIE_DENY) {
- return DENY;
- }
- if (gPrefs.getIntPref("network.cookie.lifetimePolicy") == COOKIE_SESSION) {
- return SESSION;
- }
- return ALLOW;
- },
- "desktop-notification": function getNotificationDefaultPermission()
- {
- if (!gPrefs.getBoolPref("dom.webnotifications.enabled")) {
- return DENY;
- }
- return UNKNOWN;
- },
- install: function getInstallDefaultPermission()
- {
- if (Services.prefs.getBoolPref("xpinstall.whitelist.required")) {
- return DENY;
- }
- return ALLOW;
- },
- geo: function getGeoDefaultPermissions()
- {
- if (!gPrefs.getBoolPref("geo.enabled")) {
- return DENY;
- }
- return ALLOW;
- },
- plugins: function getPluginsDefaultPermissions()
- {
- return UNKNOWN;
- },
-};
-
-var permissionObserver = {
- observe: function (aSubject, aTopic, aData)
- {
- if (aTopic == "perm-changed") {
- var permission = aSubject.QueryInterface(
- Components.interfaces.nsIPermission);
- if (permission.matchesURI(gPermURI, true)) {
- if (permission.type in gPermObj)
- initRow(permission.type);
- else if (permission.type.startsWith("plugin"))
- setPluginsRadioState();
- }
- }
- }
-};
-
-function onLoadPermission(principal)
-{
- gPrefs = Components.classes[PREFERENCES_CONTRACTID]
- .getService(Components.interfaces.nsIPrefBranch);
-
- var uri = gDocument.documentURIObject;
- var permTab = document.getElementById("permTab");
- if (/^https?$/.test(uri.scheme)) {
- gPermURI = uri;
- gPermPrincipal = principal;
- var hostText = document.getElementById("hostText");
- hostText.value = gPermURI.prePath;
-
- 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");
-
- if (gUsageRequest) {
- gUsageRequest.cancel();
- gUsageRequest = null;
- }
-}
-
-function initRow(aPartId)
-{
- if (aPartId == "plugins") {
- initPluginsRow();
- return;
- }
-
- var permissionManager = Components.classes[PERMISSION_CONTRACTID]
- .getService(nsIPermissionManager);
-
- var checkbox = document.getElementById(aPartId + "Def");
- var command = document.getElementById("cmd_" + aPartId + "Toggle");
- // Desktop Notification, Geolocation and PointerLock permission consumers
- // use testExactPermission, not testPermission.
- var perm;
- if (aPartId == "desktop-notification" || aPartId == "geo" || aPartId == "pointerLock")
- perm = permissionManager.testExactPermission(gPermURI, aPartId);
- else
- 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, aPartId);
- command.setAttribute("disabled", "true");
- var perm = gPermObj[aPartId]();
- setRadioState(aPartId, perm);
- }
- else {
- onRadioClick(aPartId);
- command.removeAttribute("disabled");
- }
-}
-
-function onPluginRadioClick(aEvent) {
- onRadioClick(aEvent.originalTarget.getAttribute("id").split('#')[0]);
-}
-
-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];
- if (permission == UNKNOWN) {
- permissionManager.remove(gPermURI, aPartId);
- } else {
- permissionManager.add(gPermURI, aPartId, permission);
- }
-}
-
-function setRadioState(aPartId, aValue)
-{
- var radio = document.getElementById(aPartId + "#" + aValue);
- radio.radioGroup.selectedItem = radio;
-}
-
-// XXX copied this from browser-plugins.js - is there a way to share?
-function makeNicePluginName(aName) {
- 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"
- // Do this by first stripping the numbers, etc. off the end, and then
- // removing "Plugin" (and then trimming to get rid of any whitespace).
- // (Otherwise, something like "Java(TM) Plug-in 1.7.0_07" gets mangled)
- let newName = aName.replace(/[\s\d\.\-\_\(\)]+$/, "").replace(/\bplug-?in\b/i, "").trim();
- return newName;
-}
-
-function fillInPluginPermissionTemplate(aPermissionString, aPluginObject) {
- let permPluginTemplate = document.getElementById("permPluginTemplate")
- .cloneNode(true);
- permPluginTemplate.setAttribute("permString", aPermissionString);
- permPluginTemplate.setAttribute("tooltiptext", aPluginObject.description);
- let attrs = [];
- attrs.push([".permPluginTemplateLabel", "value", aPluginObject.name]);
- attrs.push([".permPluginTemplateRadioGroup", "id", aPermissionString + "RadioGroup"]);
- attrs.push([".permPluginTemplateRadioDefault", "id", aPermissionString + "#0"]);
- let permPluginTemplateRadioAsk = ".permPluginTemplateRadioAsk";
- if (Services.prefs.getBoolPref("plugins.click_to_play") ||
- aPluginObject.vulnerable) {
- attrs.push([permPluginTemplateRadioAsk, "id", aPermissionString + "#3"]);
- } else {
- permPluginTemplate.querySelector(permPluginTemplateRadioAsk)
- .setAttribute("disabled", "true");
- }
- attrs.push([".permPluginTemplateRadioAllow", "id", aPermissionString + "#1"]);
- attrs.push([".permPluginTemplateRadioBlock", "id", aPermissionString + "#2"]);
-
- for (let attr of attrs) {
- permPluginTemplate.querySelector(attr[0]).setAttribute(attr[1], attr[2]);
- }
-
- return permPluginTemplate;
-}
-
-function clearPluginPermissionTemplate() {
- let permPluginTemplate = document.getElementById("permPluginTemplate");
- permPluginTemplate.hidden = true;
- permPluginTemplate.removeAttribute("permString");
- permPluginTemplate.removeAttribute("tooltiptext");
- document.querySelector(".permPluginTemplateLabel").removeAttribute("value");
- document.querySelector(".permPluginTemplateRadioGroup").removeAttribute("id");
- document.querySelector(".permPluginTemplateRadioAsk").removeAttribute("id");
- document.querySelector(".permPluginTemplateRadioAllow").removeAttribute("id");
- document.querySelector(".permPluginTemplateRadioBlock").removeAttribute("id");
-}
-
-function initPluginsRow() {
- let vulnerableLabel = document.getElementById("browserBundle")
- .getString("pluginActivateVulnerable.label");
- let pluginHost = Components.classes["@mozilla.org/plugin/host;1"]
- .getService(Components.interfaces.nsIPluginHost);
- let tags = pluginHost.getPluginTags();
-
- let permissionMap = new Map();
-
- for (let plugin of tags) {
- if (plugin.disabled) {
- continue;
- }
- for (let mimeType of plugin.getMimeTypes()) {
- if (mimeType == "application/x-shockwave-flash" && plugin.name != "Shockwave Flash") {
- continue;
- }
- let permString = pluginHost.getPermissionStringForType(mimeType);
- if (!permissionMap.has(permString)) {
- let name = makeNicePluginName(plugin.name) + " " + plugin.version;
- let vulnerable = false;
- if (permString.startsWith("plugin-vulnerable:")) {
- name += " \u2014 " + vulnerableLabel;
- vulnerable = true;
- }
- permissionMap.set(permString, {
- "name": name,
- "description": plugin.description,
- "vulnerable": vulnerable
- });
- }
- }
- }
-
- // Tycho:
- // let entries = [
- // {
- // "permission": item[0],
- // "obj": item[1],
- // }
- // for (item of permissionMap)
- // ];
- let entries = [];
- for (let item of permissionMap) {
- entries.push({
- "permission": item[0],
- "obj": item[1]
- });
- }
- entries.sort(function(a, b) {
- return ((a.obj.name < b.obj.name) ? -1 : (a.obj.name == b.obj.name ? 0 : 1));
- });
-
- // Tycho:
- // let permissionEntries = [
- // fillInPluginPermissionTemplate(p.permission, p.obj) for (p of entries)
- // ];
- let permissionEntries = [];
- entries.forEach(function (p) {
- permissionEntries.push(fillInPluginPermissionTemplate(p.permission, p.obj));
- });
-
- let permPluginsRow = document.getElementById("permPluginsRow");
- clearPluginPermissionTemplate();
- if (permissionEntries.length < 1) {
- permPluginsRow.hidden = true;
- return;
- }
-
- for (let permissionEntry of permissionEntries) {
- permPluginsRow.appendChild(permissionEntry);
- }
-
- setPluginsRadioState();
-}
-
-function setPluginsRadioState() {
- var permissionManager = Components.classes[PERMISSION_CONTRACTID]
- .getService(nsIPermissionManager);
- let box = document.getElementById("permPluginsRow");
- for (let permissionEntry of box.childNodes) {
- if (permissionEntry.hasAttribute("permString")) {
- let permString = permissionEntry.getAttribute("permString");
- let permission = permissionManager.testPermission(gPermURI, permString);
- setRadioState(permString, permission);
- }
- }
-}
diff --git a/components/pageinfo/security.js b/components/pageinfo/security.js
deleted file mode 100644
index e791ab9..0000000
--- a/components/pageinfo/security.js
+++ /dev/null
@@ -1,378 +0,0 @@
-/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-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 isMixed =
- (ui.state & (Components.interfaces.nsIWebProgressListener.STATE_LOADED_MIXED_ACTIVE_CONTENT |
- Components.interfaces.nsIWebProgressListener.STATE_LOADED_MIXED_DISPLAY_CONTENT));
- 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,
- encryptionSuite : undefined,
- version: undefined,
- isBroken : isBroken,
- isMixed : isMixed,
- isEV : isEV,
- cert : cert,
- fullLocation : gWindow.location
- };
-
- var version;
- try {
- retval.encryptionAlgorithm = status.cipherName;
- retval.encryptionStrength = status.secretKeyLength;
- retval.encryptionSuite = status.cipherSuite;
- version = status.protocolVersion;
- }
- catch (e) {
- }
-
- switch (version) {
- case nsISSLStatus.SSL_VERSION_3:
- retval.version = "SSL 3";
- break;
- case nsISSLStatus.TLS_VERSION_1:
- retval.version = "TLS 1.0";
- break;
- case nsISSLStatus.TLS_VERSION_1_1:
- retval.version = "TLS 1.1";
- break;
- case nsISSLStatus.TLS_VERSION_1_2:
- retval.version = "TLS 1.2"
- break;
- case nsISSLStatus.TLS_VERSION_1_3:
- retval.version = "TLS 1.3"
- break;
- }
-
- return retval;
- } else {
- return {
- hostName : hName,
- cAName : "",
- encryptionAlgorithm : "",
- encryptionStrength : 0,
- encryptionSuite : "",
- version: "",
- isBroken : isBroken,
- isMixed : isMixed,
- 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) {
- if (info.isMixed) {
- hdr = pkiBundle.getString("pageInfo_MixedContent");
- } else {
- hdr = pkiBundle.getFormattedString("pageInfo_BrokenEncryption",
- [info.encryptionAlgorithm,
- info.encryptionStrength + "",
- info.version]);
- }
- msg1 = pkiBundle.getString("pageInfo_Privacy_Broken1");
- msg2 = pkiBundle.getString("pageInfo_Privacy_None2");
- }
- else if (info.encryptionStrength > 0) {
- hdr = pkiBundle.getFormattedString("pageInfo_EncryptionWithBitsAndProtocol",
- [info.encryptionAlgorithm,
- info.encryptionStrength + "",
- info.version]);
- msg1 = pkiBundle.getString("pageInfo_Privacy_Encrypted1");
- msg2 = pkiBundle.getString("pageInfo_Privacy_Encrypted2");
- security._cert = info.cert;
- }
- 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;
- var cc = result.root.childCount;
- result.root.containerOpen = false;
- return cc;
-}
diff --git a/components/permissions/aboutPermissions.css b/components/permissions/aboutPermissions.css
deleted file mode 100644
index d73b6a8..0000000
--- a/components/permissions/aboutPermissions.css
+++ /dev/null
@@ -1,11 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-.site {
- -moz-binding: url("chrome://browser/content/permissions/aboutPermissions.xml#site");
-}
-
-.pluginPermission {
- -moz-binding: url("chrome://browser/content/permissions/aboutPermissions.xml#pluginPermission");
-}
diff --git a/components/permissions/aboutPermissions.js b/components/permissions/aboutPermissions.js
deleted file mode 100644
index 421b65a..0000000
--- a/components/permissions/aboutPermissions.js
+++ /dev/null
@@ -1,1335 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-var Ci = Components.interfaces;
-var Cc = Components.classes;
-var Cu = Components.utils;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/DownloadUtils.jsm");
-Cu.import("resource://gre/modules/AddonManager.jsm");
-Cu.import("resource://gre/modules/NetUtil.jsm");
-Cu.import("resource://gre/modules/ForgetAboutSite.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
- "resource://gre/modules/PluralForm.jsm");
-
-var gSecMan = Cc["@mozilla.org/scriptsecuritymanager;1"].
- getService(Ci.nsIScriptSecurityManager);
-
-var gFaviconService = Cc["@mozilla.org/browser/favicon-service;1"].
- getService(Ci.nsIFaviconService);
-
-var gPlacesDatabase = Cc["@mozilla.org/browser/nav-history-service;1"].
- getService(Ci.nsPIPlacesDatabase).
- DBConnection.
- clone(true);
-
-var gSitesStmt = gPlacesDatabase.createAsyncStatement(
- "SELECT url " +
- "FROM moz_places " +
- "WHERE rev_host > '.' " +
- "AND visit_count > 0 " +
- "GROUP BY rev_host " +
- "ORDER BY MAX(frecency) DESC " +
- "LIMIT :limit");
-
-var gVisitStmt = gPlacesDatabase.createAsyncStatement(
- "SELECT SUM(visit_count) AS count " +
- "FROM moz_places " +
- "WHERE rev_host = :rev_host");
-
-var gFlash = {
- name: "Shockwave Flash",
- betterName: "Adobe Flash",
- type: "application/x-shockwave-flash",
-};
-
-// XXX:
-// Is there a better way to do this rather than this hacky comparison?
-// Copied this from toolkit/components/passwordmgr/crypto-SDR.js
-const MASTER_PASSWORD_MESSAGE = "User canceled master password entry";
-
-/**
- * Permission types that should be tested with testExactPermission, as opposed
- * to testPermission. This is based on what consumers use to test these
- * permissions.
- */
-const TEST_EXACT_PERM_TYPES = ["desktop-notification", "geo", "pointerLock"];
-
-/**
- * Site object represents a single site, uniquely identified by a principal.
- */
-function Site(principal) {
- this.principal = principal;
- this.listitem = null;
-}
-
-Site.prototype = {
- /**
- * Gets the favicon to use for the site. The callback only gets called if
- * a favicon is found for either the http URI or the https URI.
- *
- * @param aCallback
- * A callback function that takes a favicon image URL as a parameter.
- */
- getFavicon: function(aCallback) {
- function invokeCallback(aFaviconURI) {
- try {
- // Use getFaviconLinkForIcon to get image data from the database instead
- // of using the favicon URI to fetch image data over the network.
- aCallback(gFaviconService.getFaviconLinkForIcon(aFaviconURI).spec);
- } catch (e) {
- Cu.reportError("AboutPermissions: " + e);
- }
- }
-
- // Get the favicon for the origin
- gFaviconService.getFaviconURLForPage(this.principal.URI, function (aURI) {
- if (aURI) {
- invokeCallback(aURI);
- }
- }.bind(this));
- },
-
- /**
- * Gets the number of history visits for the site.
- *
- * @param aCallback
- * A function that takes the visit count (a number) as a parameter.
- */
- getVisitCount: function(aCallback) {
- // XXX This won't be a very reliable system, as it will count both http: and https: visits
- // Unfortunately, I don't think that there is a much better way to do it right now.
- let rev_host = this.principal.URI.host.split("").reverse().join("") + ".";
- gVisitStmt.params.rev_host = rev_host;
- gVisitStmt.executeAsync({
- handleResult: function(aResults) {
- let row = aResults.getNextRow();
- let count = row.getResultByName("count") || 0;
- try {
- aCallback(count);
- } catch (e) {
- Cu.reportError("AboutPermissions: " + e);
- }
- },
- handleError: function(aError) {
- Cu.reportError("AboutPermissions: " + aError);
- },
- handleCompletion: function(aReason) {
- }
- });
- },
-
- /**
- * Gets the permission value stored for a specified permission type.
- *
- * @param aType
- * The permission type string stored in permission manager.
- * e.g. "cookie", "geo", "popup", "image"
- * @param aResultObj
- * An object that stores the permission value set for aType.
- *
- * @return A boolean indicating whether or not a permission is set.
- */
- getPermission: function(aType, aResultObj) {
- // Password saving isn't a nsIPermissionManager permission type, so handle
- // it seperately.
- if (aType == "password") {
- aResultObj.value = this.loginSavingEnabled
- ? Ci.nsIPermissionManager.ALLOW_ACTION
- : Ci.nsIPermissionManager.DENY_ACTION;
- return true;
- }
-
- let permissionValue;
- if (TEST_EXACT_PERM_TYPES.indexOf(aType) == -1) {
- permissionValue = Services.perms.testPermissionFromPrincipal(this.principal, aType);
- } else {
- permissionValue = Services.perms.testExactPermissionFromPrincipal(this.principal, aType);
- }
- aResultObj.value = permissionValue;
-
- if (aType.startsWith("plugin")) {
- if (permissionValue == Ci.nsIPermissionManager.PROMPT_ACTION) {
- aResultObj.value = Ci.nsIPermissionManager.UNKNOWN_ACTION;
- return true;
- }
- }
-
- return permissionValue != Ci.nsIPermissionManager.UNKNOWN_ACTION;
- },
-
- /**
- * Sets a permission for the site given a permission type and value.
- *
- * @param aType
- * The permission type string stored in permission manager.
- * e.g. "cookie", "geo", "popup", "image"
- * @param aPerm
- * The permission value to set for the permission type. This should
- * be one of the constants defined in nsIPermissionManager.
- */
- setPermission: function(aType, aPerm) {
- // Password saving isn't a nsIPermissionManager permission type, so handle
- // it seperately.
- if (aType == "password") {
- this.loginSavingEnabled = aPerm == Ci.nsIPermissionManager.ALLOW_ACTION;
- return;
- }
-
- if (aType.startsWith("plugin")) {
- if (aPerm == Ci.nsIPermissionManager.UNKNOWN_ACTION) {
- aPerm = Ci.nsIPermissionManager.PROMPT_ACTION;
- }
- }
-
- Services.perms.addFromPrincipal(this.principal, aType, aPerm);
- },
-
- /**
- * Clears a user-set permission value for the site given a permission type.
- *
- * @param aType
- * The permission type string stored in permission manager.
- * e.g. "cookie", "geo", "popup", "image"
- */
- clearPermission: function(aType) {
- Services.perms.removeFromPrincipal(this.principal, aType);
- },
-
- /**
- * Gets logins stored for the site.
- *
- * @return An array of the logins stored for the site.
- */
- get logins() {
- try {
- let logins = Services.logins.findLogins({},
- this.principal.originNoSuffix, "", "");
- return logins;
- } catch (e) {
- if (!e.message.includes(MASTER_PASSWORD_MESSAGE)) {
- Cu.reportError("AboutPermissions: " + e);
- }
- return [];
- }
- },
-
- get loginSavingEnabled() {
- // Only say that login saving is blocked if it is blocked for both
- // http and https.
- try {
- return Services.logins.getLoginSavingEnabled(this.principal.originNoSuffix);
- } catch (e) {
- if (!e.message.includes(MASTER_PASSWORD_MESSAGE)) {
- Cu.reportError("AboutPermissions: " + e);
- }
- return false;
- }
- },
-
- set loginSavingEnabled(isEnabled) {
- try {
- Services.logins.setLoginSavingEnabled(this.principal.originNoSuffix, isEnabled);
- } catch (e) {
- if (!e.message.includes(MASTER_PASSWORD_MESSAGE)) {
- Cu.reportError("AboutPermissions: " + e);
- }
- }
- },
-
- /**
- * Gets cookies stored for the site and base domain.
- *
- * @return An array of the cookies set for the site and base domain.
- */
- get cookies() {
- let cookies = [];
- let enumerator = Services.cookies.enumerator;
- while (enumerator.hasMoreElements()) {
- let cookie = enumerator.getNext().QueryInterface(Ci.nsICookie2);
- if (cookie.host.hasRootDomain(
- AboutPermissions.domainFromHost(this.principal.URI.host))) {
- cookies.push(cookie);
- }
- }
- return cookies;
- },
-
- /**
- * Removes a set of specific cookies from the browser.
- */
- clearCookies: function() {
- this.cookies.forEach(function(aCookie) {
- Services.cookies.remove(aCookie.host, aCookie.name, aCookie.path, false,
- aCookie.originAttributes);
- });
- },
-
- /**
- * Removes all data from the browser corresponding to the site.
- */
- forgetSite: function() {
- // XXX This removes data for an entire domain, rather than just
- // an origin. This may produce confusing results, as data will
- // be cleared for the http:// as well as the https:// domain
- // if you try to forget the https:// site.
- ForgetAboutSite.removeDataFromDomain(this.principal.URI.host)
- .catch(Cu.reportError);
- }
-}
-
-/**
- * PermissionDefaults object keeps track of default permissions for sites based
- * on global preferences.
- *
- * Inspired by pageinfo/permissions.js
- */
-var PermissionDefaults = {
- UNKNOWN: Ci.nsIPermissionManager.UNKNOWN_ACTION, // 0
- ALLOW: Ci.nsIPermissionManager.ALLOW_ACTION, // 1
- DENY: Ci.nsIPermissionManager.DENY_ACTION, // 2
- SESSION: Ci.nsICookiePermission.ACCESS_SESSION, // 8
-
- get password() {
- if (Services.prefs.getBoolPref("signon.rememberSignons")) {
- return this.ALLOW;
- }
- return this.DENY;
- },
- set password(aValue) {
- let value = (aValue != this.DENY);
- Services.prefs.setBoolPref("signon.rememberSignons", value);
- },
-
- IMAGE_ALLOW: 1,
- IMAGE_DENY: 2,
- IMAGE_ALLOW_FIRST_PARTY_ONLY: 3,
-
- get image() {
- if (Services.prefs.getIntPref("permissions.default.image")
- == this.IMAGE_DENY) {
- return this.IMAGE_DENY;
- } else if (Services.prefs.getIntPref("permissions.default.image")
- == this.IMAGE_ALLOW_FIRST_PARTY_ONLY) {
- return this.IMAGE_ALLOW_FIRST_PARTY_ONLY;
- }
- return this.IMAGE_ALLOW;
- },
- set image(aValue) {
- let value = this.IMAGE_ALLOW;
- if (aValue == this.IMAGE_DENY) {
- value = this.IMAGE_DENY;
- } else if (aValue == this.IMAGE_ALLOW_FIRST_PARTY_ONLY) {
- value = this.IMAGE_ALLOW_FIRST_PARTY_ONLY;
- }
- Services.prefs.setIntPref("permissions.default.image", value);
- },
-
- get popup() {
- if (Services.prefs.getBoolPref("dom.disable_open_during_load")) {
- return this.DENY;
- }
- return this.ALLOW;
- },
- set popup(aValue) {
- let value = (aValue == this.DENY);
- Services.prefs.setBoolPref("dom.disable_open_during_load", value);
- },
-
- // For use with network.cookie.* prefs.
- COOKIE_ACCEPT: 0,
- COOKIE_DENY: 2,
- COOKIE_NORMAL: 0,
- COOKIE_SESSION: 2,
-
- get cookie() {
- if (Services.prefs.getIntPref("network.cookie.cookieBehavior")
- == this.COOKIE_DENY) {
- return this.DENY;
- }
-
- if (Services.prefs.getIntPref("network.cookie.lifetimePolicy")
- == this.COOKIE_SESSION) {
- return this.SESSION;
- }
- return this.ALLOW;
- },
- set cookie(aValue) {
- let value = (aValue == this.DENY) ? this.COOKIE_DENY : this.COOKIE_ACCEPT;
- Services.prefs.setIntPref("network.cookie.cookieBehavior", value);
-
- let lifetimeValue = aValue == this.SESSION ? this.COOKIE_SESSION :
- this.COOKIE_NORMAL;
- Services.prefs.setIntPref("network.cookie.lifetimePolicy", lifetimeValue);
- },
-
- get ["desktop-notification"]() {
- if (!Services.prefs.getBoolPref("dom.webnotifications.enabled")) {
- return this.DENY;
- }
- // We always ask for permission to enable notifications for a specific
- // site, so there is no global ALLOW.
- return this.UNKNOWN;
- },
- set ["desktop-notification"](aValue) {
- let value = (aValue != this.DENY);
- Services.prefs.setBoolPref("dom.webnotifications.enabled", value);
- },
-
- get install() {
- if (Services.prefs.getBoolPref("xpinstall.whitelist.required")) {
- return this.DENY;
- }
- return this.ALLOW;
- },
- set install(aValue) {
- let value = (aValue == this.DENY);
- Services.prefs.setBoolPref("xpinstall.whitelist.required", value);
- },
-
- get geo() {
- if (!Services.prefs.getBoolPref("geo.enabled")) {
- return this.DENY;
- }
- // We always ask for permission to share location with a specific site,
- // so there is no global ALLOW.
- return this.UNKNOWN;
- },
- set geo(aValue) {
- let value = (aValue != this.DENY);
- Services.prefs.setBoolPref("geo.enabled", value);
- },
-}
-
-/**
- * AboutPermissions manages the about:permissions page.
- */
-var AboutPermissions = {
- /**
- * Maximum number of sites to return from the places database.
- */
- PLACES_SITES_LIMIT_MAX: 100,
-
- /**
- * When adding sites to the dom sites-list, divide workload into intervals.
- */
- LIST_BUILD_DELAY: 100, // delay between intervals
-
- /**
- * Stores a mapping of origin strings to Site objects.
- */
- _sites: {},
-
- /**
- * Using a getter for sitesFilter to avoid races with tests.
- */
- get sitesFilter () {
- delete this.sitesFilter;
- return this.sitesFilter = document.getElementById("sites-filter");
- },
-
- sitesList: null,
- _selectedSite: null,
-
- /**
- * For testing, track initializations so we can send notifications.
- */
- _initPlacesDone: false,
- _initServicesDone: false,
-
- /**
- * This reflects the permissions that we expose in the UI. These correspond
- * to permission type strings in the permission manager, PermissionDefaults,
- * and element ids in aboutPermissions.xul.
- *
- * Potential future additions: "sts/use", "sts/subd"
- */
- _supportedPermissions: ["password", "image", "popup", "cookie",
- "desktop-notification", "install", "geo"],
-
- /**
- * Permissions that don't have a global "Allow" option.
- */
- _noGlobalAllow: ["desktop-notification", "geo"],
-
- /**
- * Permissions that don't have a global "Deny" option.
- */
- _noGlobalDeny: [],
-
- _stringBundleBrowser: Services.strings
- .createBundle("chrome://browser/locale/browser.properties"),
-
- _stringBundleAboutPermissions: Services.strings.createBundle(
- "chrome://browser/locale/permissions/aboutPermissions.properties"),
-
- _initPart1: function() {
- this.initPluginList();
- this.cleanupPluginList();
-
- this.getSitesFromPlaces();
-
- this.enumerateServicesGenerator = this.getEnumerateServicesGenerator();
- setTimeout(this.enumerateServicesDriver.bind(this), this.LIST_BUILD_DELAY);
- },
-
- _initPart2: function() {
- this._supportedPermissions.forEach(function(aType) {
- this.updatePermission(aType);
- }, this);
- },
-
- /**
- * Called on page load.
- */
- init: function() {
- this.sitesList = document.getElementById("sites-list");
-
- this._initPart1();
-
- // Attach observers in case data changes while the page is open.
- Services.prefs.addObserver("signon.rememberSignons", this, false);
- Services.prefs.addObserver("permissions.default.image", this, false);
- Services.prefs.addObserver("dom.disable_open_during_load", this, false);
- Services.prefs.addObserver("network.cookie.", this, false);
- Services.prefs.addObserver("dom.webnotifications.enabled", this, false);
- Services.prefs.addObserver("xpinstall.whitelist.required", this, false);
- Services.prefs.addObserver("geo.enabled", this, false);
- Services.prefs.addObserver("plugins.click_to_play", this, false);
- Services.prefs.addObserver("permissions.places-sites-limit", this, false);
-
- Services.obs.addObserver(this, "perm-changed", false);
- Services.obs.addObserver(this, "passwordmgr-storage-changed", false);
- Services.obs.addObserver(this, "cookie-changed", false);
- Services.obs.addObserver(this, "browser:purge-domain-data", false);
- Services.obs.addObserver(this, "plugin-info-updated", false);
- Services.obs.addObserver(this, "plugin-list-updated", false);
- Services.obs.addObserver(this, "blocklist-updated", false);
-
- this._observersInitialized = true;
- Services.obs.notifyObservers(null, "browser-permissions-preinit", null);
-
- this._initPart2();
-
- // Process about:permissions?filter=<string>
- // About URIs don't support query params, so do this manually
- var loc = document.location.href;
- var matches = /[?&]filter\=([^&]+)/i.exec(loc);
- if (matches) {
- this.sitesFilter.value = decodeURIComponent(matches[1]);
- }
- },
-
- sitesReload: function() {
- Object.getOwnPropertyNames(this._sites).forEach(function(prop) {
- AboutPermissions.deleteFromSitesList(prop);
- });
- this._initPart1();
- this._initPart2();
- },
-
- // XXX copied this from browser-plugins.js - is there a way to share?
- // Map the plugin's name to a filtered version more suitable for user UI.
- makeNicePluginName: function(aName) {
- if (aName == gFlash.name) {
- return gFlash.betterName;
- }
-
- // Clean up the plugin name by stripping off any trailing version numbers
- // or "plugin". EG, "Foo Bar Plugin 1.23_02" --> "Foo Bar"
- // Do this by first stripping the numbers, etc. off the end, and then
- // removing "Plugin" (and then trimming to get rid of any whitespace).
- // (Otherwise, something like "Java(TM) Plug-in 1.7.0_07" gets mangled.)
- let newName = aName.replace(
- /[\s\d\.\-\_\(\)]+$/, "").replace(/\bplug-?in\b/i, "").trim();
- return newName;
- },
-
- initPluginList: function() {
- let pluginHost = Cc["@mozilla.org/plugin/host;1"]
- .getService(Ci.nsIPluginHost);
- let tags = pluginHost.getPluginTags();
-
- let permissionMap = new Map();
-
- let permissionEntries = [];
- let XUL_NS =
- "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
- for (let plugin of tags) {
- for (let mimeType of plugin.getMimeTypes()) {
- if ((mimeType == gFlash.type) && (plugin.name != gFlash.name)) {
- continue;
- }
- let permString = pluginHost.getPermissionStringForType(mimeType);
- if (!permissionMap.has(permString)) {
- let permissionEntry = document.createElementNS(XUL_NS, "box");
- permissionEntry.setAttribute("label",
- this.makeNicePluginName(plugin.name)
- + " " + plugin.version);
- permissionEntry.setAttribute("tooltiptext", plugin.description);
- permissionEntry.setAttribute("vulnerable", "");
- permissionEntry.setAttribute("mimeType", mimeType);
- permissionEntry.setAttribute("permString", permString);
- permissionEntry.setAttribute("class", "pluginPermission");
- permissionEntry.setAttribute("id", permString + "-entry");
- // If the plugin is disabled, it makes no sense to change its
- // click-to-play status, so don't add it.
- if (plugin.disabled) {
- permissionEntry.hidden = true;
- } else {
- permissionEntry.hidden = false;
- }
- permissionEntries.push(permissionEntry);
- this._supportedPermissions.push(permString);
- this._noGlobalDeny.push(permString);
- Object.defineProperty(PermissionDefaults, permString, {
- get: function() {
- if ((Services.prefs.getBoolPref("plugins.click_to_play") &&
- plugin.clicktoplay) ||
- permString.startsWith("plugin-vulnerable:")) {
- return PermissionDefaults.UNKNOWN;
- }
- return PermissionDefaults.ALLOW;
- },
- set: function(aValue) {
- this.clicktoplay = (aValue == PermissionDefaults.UNKNOWN);
- }.bind(plugin),
- configurable: true
- });
- permissionMap.set(permString, "");
- }
- }
- }
-
- if (permissionEntries.length > 0) {
- permissionEntries.sort(function(entryA, entryB) {
- let labelA = entryA.getAttribute("label");
- let labelB = entryB.getAttribute("label");
- return ((labelA < labelB) ? -1 : (labelA == labelB ? 0 : 1));
- });
- }
-
- let pluginsBox = document.getElementById("plugins-box");
- while (pluginsBox.hasChildNodes()) {
- pluginsBox.removeChild(pluginsBox.firstChild);
- }
- for (let permissionEntry of permissionEntries) {
- pluginsBox.appendChild(permissionEntry);
- }
- },
-
- cleanupPluginList: function() {
- let pluginsPrefItem = document.getElementById("plugins-pref-item");
- let pluginsBox = document.getElementById("plugins-box");
- let pluginsBoxEmpty = true;
- let pluginsBoxSibling = pluginsBox.firstChild;
- while (pluginsBoxSibling) {
- if (!pluginsBoxSibling.hidden) {
- pluginsBoxEmpty = false;
- break;
- }
- pluginsBoxSibling = pluginsBoxSibling.nextSibling;
- }
- if (pluginsBoxEmpty) {
- pluginsPrefItem.collapsed = true;
- } else {
- pluginsPrefItem.collapsed = false;
- }
- },
-
- /**
- * Called on page unload.
- */
- cleanUp: function() {
- if (this._observersInitialized) {
- Services.prefs.removeObserver("signon.rememberSignons", this, false);
- Services.prefs.removeObserver("permissions.default.image", this, false);
- Services.prefs.removeObserver("dom.disable_open_during_load", this, false);
- Services.prefs.removeObserver("network.cookie.", this, false);
- Services.prefs.removeObserver("dom.webnotifications.enabled", this, false);
- Services.prefs.removeObserver("xpinstall.whitelist.required", this, false);
- Services.prefs.removeObserver("geo.enabled", this, false);
- Services.prefs.removeObserver("plugins.click_to_play", this, false);
- Services.prefs.removeObserver("permissions.places-sites-limit", this, false);
-
- Services.obs.removeObserver(this, "perm-changed");
- Services.obs.removeObserver(this, "passwordmgr-storage-changed");
- Services.obs.removeObserver(this, "cookie-changed");
- Services.obs.removeObserver(this, "browser:purge-domain-data");
- Services.obs.removeObserver(this, "plugin-info-updated");
- Services.obs.removeObserver(this, "plugin-list-updated");
- Services.obs.removeObserver(this, "blocklist-updated");
- }
-
- gSitesStmt.finalize();
- gVisitStmt.finalize();
- gPlacesDatabase.asyncClose(null);
- },
-
- observe: function(aSubject, aTopic, aData) {
- switch(aTopic) {
- case "perm-changed":
- // Permissions changes only affect individual sites.
- if (!this._selectedSite) {
- break;
- }
- // aSubject is null when nsIPermisionManager::removeAll() is called.
- if (!aSubject) {
- this._supportedPermissions.forEach(function(aType) {
- this.updatePermission(aType);
- }, this);
- break;
- }
- let permission = aSubject.QueryInterface(Ci.nsIPermission);
- // We can't compare selectedSite.principal and permission.principal here
- // because we need to handle the case where a parent domain was changed
- // in a way that affects the subdomain.
- if (this._supportedPermissions.indexOf(permission.type) != -1) {
- this.updatePermission(permission.type);
- }
- break;
- case "nsPref:changed":
- if (aData == "permissions.places-sites-limit") {
- this.sitesReload();
- return;
- }
- let plugin = false;
- if (aData.startsWith("plugin")) {
- plugin = true;
- }
- if (plugin) {
- this.initPluginList();
- }
- this._supportedPermissions.forEach(function(aType) {
- if (!plugin || (plugin && aType.startsWith("plugin"))) {
- this.updatePermission(aType);
- }
- }, this);
- if (plugin) {
- this.cleanupPluginList();
- }
- break;
- case "passwordmgr-storage-changed":
- this.updatePermission("password");
- if (this._selectedSite) {
- this.updatePasswordsCount();
- }
- break;
- case "cookie-changed":
- if (this._selectedSite) {
- this.updateCookiesCount();
- }
- break;
- case "browser:purge-domain-data":
- this.deleteFromSitesList(aData);
- break;
- case "plugin-info-updated":
- case "plugin-list-updated":
- case "blocklist-updated":
- this.initPluginList();
- this._supportedPermissions.forEach(function(aType) {
- if (aType.startsWith("plugin")) {
- this.updatePermission(aType);
- }
- }, this);
- this.cleanupPluginList();
- break;
- }
- },
-
- /**
- * Creates Site objects for the top-frecency sites in the places database
- * and stores them in _sites.
- * The number of sites created is controlled by _placesSitesLimit.
- */
- getSitesFromPlaces: function() {
- let _placesSitesLimit = Services.prefs.getIntPref(
- "permissions.places-sites-limit");
- if (_placesSitesLimit <= 0) {
- return;
- }
- if (_placesSitesLimit > this.PLACES_SITES_LIMIT_MAX) {
- _placesSitesLimit = this.PLACES_SITES_LIMIT_MAX;
- }
-
- gSitesStmt.params.limit = _placesSitesLimit;
- gSitesStmt.executeAsync({
- handleResult: function(aResults) {
- AboutPermissions.startSitesListBatch();
- let row;
- while (row = aResults.getNextRow()) {
- let spec = row.getResultByName("url");
- let uri = NetUtil.newURI(spec);
- let principal = gSecMan.getNoAppCodebasePrincipal(uri);
-
- AboutPermissions.addPrincipal(principal);
- }
- AboutPermissions.endSitesListBatch();
- },
- handleError: function(aError) {
- Cu.reportError("AboutPermissions: " + aError);
- },
- handleCompletion: function(aReason) {
- // Notify oberservers for testing purposes.
- AboutPermissions._initPlacesDone = true;
- if (AboutPermissions._initServicesDone) {
- Services.obs.notifyObservers(
- null, "browser-permissions-initialized", null);
- }
- }
- });
- },
-
- /**
- * Drives getEnumerateServicesGenerator to work in intervals.
- */
- enumerateServicesDriver: function() {
- if (this.enumerateServicesGenerator.next()) {
- // Build top sitesList items faster so that the list never seems sparse
- let delay = Math.min(this.sitesList.itemCount * 5, this.LIST_BUILD_DELAY);
- setTimeout(this.enumerateServicesDriver.bind(this), delay);
- } else {
- this.enumerateServicesGenerator.close();
- this._initServicesDone = true;
- if (this._initPlacesDone) {
- Services.obs.notifyObservers(
- null, "browser-permissions-initialized", null);
- }
- }
- },
-
- /**
- * Finds sites that have non-default permissions and creates Site objects
- * for them if they are not already stored in _sites.
- */
- getEnumerateServicesGenerator: function() {
- let itemCnt = 1;
- let schemeChrome = "chrome";
-
- try {
- let logins = Services.logins.getAllLogins();
- logins.forEach(function(aLogin) {
- try {
- // aLogin.hostname is a string in origin URL format
- // (e.g. "http://foo.com").
- // newURI will throw for add-ons logins stored in chrome:// URIs
- // i.e.: "chrome://weave" (Sync)
- if (!aLogin.hostname.startsWith(schemeChrome + ":")) {
- let uri = NetUtil.newURI(aLogin.hostname);
- let principal = gSecMan.getNoAppCodebasePrincipal(uri);
- this.addPrincipal(principal);
- }
- } catch (e) {
- Cu.reportError("AboutPermissions: " + e);
- }
- itemCnt++;
- }, this);
-
- let disabledHosts = Services.logins.getAllDisabledHosts();
- disabledHosts.forEach(function(aHostname) {
- try {
- // aHostname is a string in origin URL format (e.g. "http://foo.com").
- // newURI will throw for add-ons logins stored in chrome:// URIs
- // i.e.: "chrome://weave" (Sync)
- if (!aHostname.startsWith(schemeChrome + ":")) {
- let uri = NetUtil.newURI(aHostname);
- let principal = gSecMan.getNoAppCodebasePrincipal(uri);
- this.addPrincipal(principal);
- }
- } catch (e) {
- Cu.reportError("AboutPermissions: " + e);
- }
- itemCnt++;
- }, this);
- } catch (e) {
- if (!e.message.includes(MASTER_PASSWORD_MESSAGE)) {
- Cu.reportError("AboutPermissions: " + e);
- }
- }
-
- let enumerator = Services.perms.enumerator;
- while (enumerator.hasMoreElements()) {
- let permission = enumerator.getNext().QueryInterface(Ci.nsIPermission);
- // Only include sites with exceptions set for supported permission types.
- if (this._supportedPermissions.indexOf(permission.type) != -1) {
- this.addPrincipal(permission.principal);
- }
- itemCnt++;
- }
-
- yield false;
- },
-
- /**
- * Creates a new Site and adds it to _sites if it's not already there.
- *
- * @param aPrincipal
- * A principal.
- */
- addPrincipal: function(aPrincipal) {
- if (aPrincipal.origin in this._sites) {
- return;
- }
- let site = new Site(aPrincipal);
- this._sites[aPrincipal.origin] = site;
- this.addToSitesList(site);
- },
-
- /**
- * Populates sites-list richlistbox with data from Site object.
- *
- * @param aSite
- * A Site object.
- */
- addToSitesList: function(aSite) {
- let item = document.createElement("richlistitem");
- item.setAttribute("class", "site");
- item.setAttribute("value", aSite.principal.origin);
-
- aSite.getFavicon(function(aURL) {
- item.setAttribute("favicon", aURL);
- });
- aSite.listitem = item;
-
- // Make sure to only display relevant items when list is filtered.
- let filterValue = this.sitesFilter.value.toLowerCase();
- item.collapsed = aSite.principal.origin.toLowerCase().indexOf(filterValue) == -1;
-
- (this._listFragment || this.sitesList).appendChild(item);
- },
-
- startSitesListBatch: function() {
- if (!this._listFragment)
- this._listFragment = document.createDocumentFragment();
- },
-
- endSitesListBatch: function() {
- if (this._listFragment) {
- this.sitesList.appendChild(this._listFragment);
- this._listFragment = null;
- }
- },
-
- /**
- * Hides sites in richlistbox based on search text in sites-filter textbox.
- */
- filterSitesList: function() {
- let siteItems = this.sitesList.children;
- let filterValue = this.sitesFilter.value.toLowerCase();
-
- if (filterValue == "") {
- for (let i = 0, iLen = siteItems.length; i < iLen; i++) {
- siteItems[i].collapsed = false;
- }
- return;
- }
-
- for (let i = 0, iLen = siteItems.length; i < iLen; i++) {
- let siteValue = siteItems[i].value.toLowerCase();
- siteItems[i].collapsed = siteValue.indexOf(filterValue) == -1;
- }
- },
-
- /**
- * Removes all evidence of the selected site. The "forget this site" observer
- * will call deleteFromSitesList to update the UI.
- */
- forgetSite: function() {
- this._selectedSite.forgetSite();
- },
-
- /**
- * Deletes sites for a host and all of its sub-domains. Removes these sites
- * from _sites and removes their corresponding elements from the DOM.
- *
- * @param aHost
- * The host string corresponding to the site to delete.
- */
- deleteFromSitesList: function(aHost) {
- for (let origin in this._sites) {
- let site = this._sites[origin];
- if (site.principal.URI.host.hasRootDomain(aHost)) {
- if (site == this._selectedSite) {
- // Replace site-specific interface with "All Sites" interface.
- this.sitesList.selectedItem =
- document.getElementById("all-sites-item");
- }
-
- this.sitesList.removeChild(site.listitem);
- delete this._sites[site.principal.origin];
- }
- }
- },
-
- /**
- * Shows interface for managing site-specific permissions.
- */
- onSitesListSelect: function(event) {
- if (event.target.selectedItem.id == "all-sites-item") {
- // Clear the header label value from the previously selected site.
- document.getElementById("site-label").value = "";
- this.manageDefaultPermissions();
- return;
- }
-
- let origin = event.target.value;
- let site = this._selectedSite = this._sites[origin];
- document.getElementById("site-label").value = origin;
- document.getElementById("header-deck").selectedPanel =
- document.getElementById("site-header");
-
- this.updateVisitCount();
- this.updatePermissionsBox();
- },
-
- /**
- * Shows interface for managing default permissions. This corresponds to
- * the "All Sites" list item.
- */
- manageDefaultPermissions: function() {
- this._selectedSite = null;
-
- document.getElementById("header-deck").selectedPanel =
- document.getElementById("defaults-header");
-
- this.updatePermissionsBox();
- },
-
- /**
- * Updates permissions interface based on selected site.
- */
- updatePermissionsBox: function() {
- this._supportedPermissions.forEach(function(aType) {
- this.updatePermission(aType);
- }, this);
-
- this.updatePasswordsCount();
- this.updateCookiesCount();
- },
-
- /**
- * Sets menulist for a given permission to the correct state, based on
- * the stored permission.
- *
- * @param aType
- * The permission type string stored in permission manager.
- * e.g. "cookie", "geo", "popup", "image"
- */
- updatePermission: function(aType) {
- let allowItem = document.getElementById(
- aType + "-" + PermissionDefaults.ALLOW);
- allowItem.hidden = !this._selectedSite &&
- this._noGlobalAllow.indexOf(aType) != -1;
- let denyItem = document.getElementById(
- aType + "-" + PermissionDefaults.DENY);
- denyItem.hidden = !this._selectedSite &&
- this._noGlobalDeny.indexOf(aType) != -1;
-
- let permissionMenulist = document.getElementById(aType + "-menulist");
- let permissionSetDefault = document.getElementById(aType + "-set-default");
- let permissionValue;
- let permissionDefault;
- let pluginPermissionEntry;
- let elementsPrefSetDefault = document.querySelectorAll(".pref-set-default");
- if (!this._selectedSite) {
- let _visibility = "collapse";
- for (let i = 0, iLen = elementsPrefSetDefault.length; i < iLen; i++) {
- elementsPrefSetDefault[i].style.visibility = _visibility;
- }
- permissionSetDefault.style.visibility = _visibility;
- // If there is no selected site, we are updating the default permissions
- // interface.
- permissionValue = PermissionDefaults[aType];
- permissionDefault = permissionValue;
- if (aType == "image") {
- // (aType + "-3") corresponds to ALLOW_FIRST_PARTY_ONLY,
- // which is reserved for global preferences only.
- document.getElementById(aType + "-3").hidden = false;
- } else if (aType == "cookie") {
- // (aType + "-9") corresponds to ALLOW_FIRST_PARTY_ONLY,
- // which is reserved for site-specific preferences only.
- document.getElementById(aType + "-9").hidden = true;
- } else if (aType.startsWith("plugin")) {
- pluginPermissionEntry = document.getElementById(aType + "-entry");
- pluginPermissionEntry.setAttribute("vulnerable", "");
- let vulnerable = false;
- if (pluginPermissionEntry.isBlocklisted()) {
- permissionMenulist.disabled = true;
- permissionMenulist.setAttribute("tooltiptext",
- AboutPermissions._stringBundleAboutPermissions
- .GetStringFromName("pluginBlocklisted"));
- vulnerable = true;
- } else {
- permissionMenulist.disabled = false;
- permissionMenulist.setAttribute("tooltiptext", "");
- }
- if (Services.prefs.getBoolPref("plugins.click_to_play") || vulnerable) {
- document.getElementById(aType + "-0").disabled = false;
- } else {
- document.getElementById(aType + "-0").disabled = true;
- }
- }
- } else {
- let _visibility = "visible";
- for (let i = 0, iLen = elementsPrefSetDefault.length; i < iLen; i++) {
- elementsPrefSetDefault[i].style.visibility = _visibility;
- }
- permissionSetDefault.style.visibility = _visibility;
- permissionDefault = PermissionDefaults[aType];
- if (aType == "image") {
- document.getElementById(aType + "-3").hidden = true;
- } else if (aType == "cookie") {
- document.getElementById(aType + "-9").hidden = false;
- } else if (aType.startsWith("plugin")) {
- pluginPermissionEntry = document.getElementById(aType + "-entry");
- let permString = pluginPermissionEntry.getAttribute("permString");
- let vulnerable = false;
- if (permString.startsWith("plugin-vulnerable:")) {
- let nameVulnerable = " \u2014 "
- + AboutPermissions._stringBundleBrowser
- .GetStringFromName("pluginActivateVulnerable.label");
- pluginPermissionEntry.setAttribute("vulnerable", nameVulnerable);
- vulnerable = true;
- }
- if (Services.prefs.getBoolPref("plugins.click_to_play") || vulnerable) {
- document.getElementById(aType + "-0").disabled = false;
- } else {
- document.getElementById(aType + "-0").disabled = true;
- }
- permissionMenulist.disabled = false;
- permissionMenulist.setAttribute("tooltiptext", "");
- }
- let result = {};
- permissionValue = this._selectedSite.getPermission(aType, result) ?
- result.value : permissionDefault;
- }
-
- if (aType == "image") {
- if (document.getElementById(aType + "-" + permissionValue).hidden) {
- // ALLOW
- permissionValue = 1;
- }
- }
- if (aType.startsWith("plugin")) {
- if (document.getElementById(aType + "-" + permissionValue).disabled) {
- // ALLOW
- permissionValue = 1;
- }
- }
-
- if (!aType.startsWith("plugin")) {
- let _elementDefault = document.getElementById(aType + "-default");
- if (!this._selectedSite || (permissionValue == permissionDefault)) {
- _elementDefault.setAttribute("value", "");
- } else {
- _elementDefault.setAttribute("value", "*");
- }
- } else {
- let _elementDefaultVisibility;
- if (!this._selectedSite || (permissionValue == permissionDefault)) {
- _elementDefaultVisibility = false;
- } else {
- _elementDefaultVisibility = true;
- }
- pluginPermissionEntry.setDefaultVisibility(_elementDefaultVisibility);
- }
-
- permissionMenulist.selectedItem = document.getElementById(
- aType + "-" + permissionValue);
- },
-
- onPermissionCommand: function(event, _default) {
- let pluginHost = Cc["@mozilla.org/plugin/host;1"]
- .getService(Ci.nsIPluginHost);
- let permissionMimeType = event.currentTarget.getAttribute("mimeType");
- let permissionType = event.currentTarget.getAttribute("type");
- let permissionValue = event.target.value;
-
- if (!this._selectedSite) {
- if (permissionType.startsWith("plugin")) {
- let addonValue = AddonManager.STATE_ASK_TO_ACTIVATE;
- switch(permissionValue) {
- case "1":
- addonValue = false;
- break;
- case "2":
- addonValue = true;
- break;
- }
-
- AddonManager.getAddonsByTypes(["plugin"], function(addons) {
- for (let addon of addons) {
- for (let type of addon.pluginMimeTypes) {
- if ((type.type == gFlash.type) && (addon.name != gFlash.name)) {
- continue;
- }
- if (type.type.toLowerCase() == permissionMimeType.toLowerCase()) {
- addon.userDisabled = addonValue;
- return;
- }
- }
- }
- });
- } else {
- // If there is no selected site, we are setting the default permission.
- PermissionDefaults[permissionType] = permissionValue;
- }
- } else {
- if (_default) {
- this._selectedSite.clearPermission(permissionType);
- } else {
- this._selectedSite.setPermission(permissionType, permissionValue);
- }
- }
- },
-
- updateVisitCount: function() {
- this._selectedSite.getVisitCount(function(aCount) {
- let visitForm = AboutPermissions._stringBundleAboutPermissions
- .GetStringFromName("visitCount");
- let visitLabel = PluralForm.get(aCount, visitForm)
- .replace("#1", aCount);
- document.getElementById("site-visit-count").value = visitLabel;
- });
- },
-
- updatePasswordsCount: function() {
- if (!this._selectedSite) {
- document.getElementById("passwords-count").hidden = true;
- document.getElementById("passwords-manage-all-button").hidden = false;
- return;
- }
-
- let passwordsCount = this._selectedSite.logins.length;
- let passwordsForm = this._stringBundleAboutPermissions
- .GetStringFromName("passwordsCount");
- let passwordsLabel = PluralForm.get(passwordsCount, passwordsForm)
- .replace("#1", passwordsCount);
-
- document.getElementById("passwords-label").value = passwordsLabel;
- document.getElementById("passwords-manage-button").disabled =
- (passwordsCount < 1);
- document.getElementById("passwords-manage-all-button").hidden = true;
- document.getElementById("passwords-count").hidden = false;
- },
-
- /**
- * Opens password manager dialog.
- */
- managePasswords: function() {
- let selectedOrigin = "";
- if (this._selectedSite) {
- selectedOrigin = this._selectedSite.principal.URI.prePath;
- }
-
- let win = Services.wm.getMostRecentWindow("Toolkit:PasswordManager");
- if (win) {
- win.setFilter(selectedOrigin);
- win.focus();
- } else {
- window.openDialog("chrome://passwordmgr/content/passwordManager.xul",
- "Toolkit:PasswordManager", "",
- {filterString : selectedOrigin});
- }
- },
-
- domainFromHost: function(aHost) {
- let domain = aHost;
- try {
- domain = Services.eTLD.getBaseDomainFromHost(aHost);
- } catch (e) {
- // getBaseDomainFromHost will fail if the host is an IP address
- // or is empty.
- }
-
- return domain;
- },
-
- updateCookiesCount: function() {
- if (!this._selectedSite) {
- document.getElementById("cookies-count").hidden = true;
- document.getElementById("cookies-clear-all-button").hidden = false;
- document.getElementById("cookies-manage-all-button").hidden = false;
- return;
- }
-
- let cookiesCount = this._selectedSite.cookies.length;
- let cookiesForm = this._stringBundleAboutPermissions
- .GetStringFromName("cookiesCount");
- let cookiesLabel = PluralForm.get(cookiesCount, cookiesForm)
- .replace("#1", cookiesCount);
-
- document.getElementById("cookies-label").value = cookiesLabel;
- document.getElementById("cookies-clear-button").disabled =
- (cookiesCount < 1);
- document.getElementById("cookies-manage-button").disabled =
- (cookiesCount < 1);
- document.getElementById("cookies-clear-all-button").hidden = true;
- document.getElementById("cookies-manage-all-button").hidden = true;
- document.getElementById("cookies-count").hidden = false;
- },
-
- /**
- * Clears cookies for the selected site and base domain.
- */
- clearCookies: function() {
- if (!this._selectedSite) {
- return;
- }
- let site = this._selectedSite;
- site.clearCookies(site.cookies);
- this.updateCookiesCount();
- },
-
- /**
- * Opens cookie manager dialog.
- */
- manageCookies: function() {
- // Cookies are stored by-host, and thus we filter the cookie window
- // using only the host of the selected principal's origin
- let selectedHost = "";
- let selectedDomain = "";
- if (this._selectedSite) {
- selectedHost = this._selectedSite.principal.URI.host;
- selectedDomain = this.domainFromHost(selectedHost);
- }
-
- let win = Services.wm.getMostRecentWindow("Browser:Cookies");
- if (win) {
- win.gCookiesWindow.setFilter(selectedDomain);
- win.focus();
- } else {
- window.openDialog("chrome://browser/content/preferences/cookies.xul",
- "Browser:Cookies", "", {filterString : selectedDomain});
- }
- },
-
- /**
- * Focusses the filter box.
- */
- focusFilterBox: function() {
- this.sitesFilter.focus();
- }
-}
-
-// See toolkit/forgetaboutsite/ForgetAboutSite.jsm
-String.prototype.hasRootDomain = function(aDomain) {
- let index = this.indexOf(aDomain);
- if (index == -1) {
- return false;
- }
-
- if (this == aDomain) {
- return true;
- }
-
- let prevChar = this[index - 1];
- return (index == (this.length - aDomain.length)) &&
- (prevChar == "." || prevChar == "/");
-}
diff --git a/components/permissions/aboutPermissions.xml b/components/permissions/aboutPermissions.xml
deleted file mode 100644
index 2932ea0..0000000
--- a/components/permissions/aboutPermissions.xml
+++ /dev/null
@@ -1,113 +0,0 @@
-<?xml version="1.0"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!DOCTYPE bindings [
-<!ENTITY % aboutPermissionsDTD SYSTEM "chrome://browser/locale/permissions/aboutPermissions.dtd" >
-%aboutPermissionsDTD;
-]>
-
-<bindings xmlns="http://www.mozilla.org/xbl"
- xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:xbl="http://www.mozilla.org/xbl">
- <binding id="site" extends="chrome://global/content/bindings/richlistbox.xml#richlistitem">
- <content>
- <xul:hbox class="site-container" align="center" flex="1">
- <xul:image xbl:inherits="src=favicon" class="site-favicon"/>
- <xul:label xbl:inherits="value,selected" class="site-domain" crop="end" flex="1"/>
- </xul:hbox>
- </content>
- </binding>
-
- <binding id="pluginPermission">
- <content>
- <xul:hbox flex="1" align="baseline">
- <xul:label xbl:inherits="value=label" class="plugins-label"/>
- <xul:label xbl:inherits="value=vulnerable" class="plugins-vulnerable"/>
- <xul:label xbl:inherits="value=default" anonid="plugins-default" class="plugins-default"/>
- <xul:spacer flex="1"/>
- <xul:menulist anonid="plugins-menulist"
- class="pref-menulist"
- oncommand="AboutPermissions.onPermissionCommand(event, false);">
- <xul:menupopup>
- <xul:menuitem anonid="ask" value="0" label="&permission.alwaysAsk;"/>
- <xul:menuitem anonid="allow" value="1" label="&permission.allow;"/>
- <xul:menuitem anonid="block" value="2" label="&permission.block;"/>
- </xul:menupopup>
- </xul:menulist>
- <xul:button xbl:inherits="value=set-default"
- anonid="plugins-set-default"
- class="pref-set-default"
- label="&permission.default;"
- oncommand="AboutPermissions.onPermissionCommand(event, true);"/>
- </xul:hbox>
- </content>
- <implementation>
- <constructor><![CDATA[
- let mimeType = this.getAttribute("mimeType");
- let permString = this.getAttribute("permString");
- let menulist = document.getAnonymousElementByAttribute(this, "anonid", "plugins-menulist");
- menulist.setAttribute("id", permString + "-menulist");
- menulist.setAttribute("mimeType", mimeType);
- menulist.setAttribute("type", permString);
- let askitem = document.getAnonymousElementByAttribute(this, "anonid", "ask");
- askitem.setAttribute("id", permString + "-0");
- let allowitem = document.getAnonymousElementByAttribute(this, "anonid", "allow");
- allowitem.setAttribute("id", permString + "-1");
- let blockitem = document.getAnonymousElementByAttribute(this, "anonid", "block");
- blockitem.setAttribute("id", permString + "-2");
- let _default = document.getAnonymousElementByAttribute(this, "anonid", "plugins-default");
- this.setDefaultVisibility(false);
- _default.setAttribute("value", "*");
- let _setDefault = document.getAnonymousElementByAttribute(this, "anonid", "plugins-set-default");
- _setDefault.setAttribute("id", permString + "-set-default");
- _setDefault.setAttribute("class", "pref-set-default");
- _setDefault.setAttribute("type", permString);
- ]]>
- </constructor>
- <method name="setDefaultVisibility">
- <parameter name="visibility" />
- <body><![CDATA[
- let _default = document.getAnonymousElementByAttribute(this, "anonid", "plugins-default");
- if (visibility) {
- _default.style.visibility = "visible";
- } else {
- _default.style.visibility = "hidden";
- }
- ]]>
- </body>
- </method>
- <method name="isClickToPlay">
- <body><![CDATA[
- let pluginHost = Components.classes["@mozilla.org/plugin/host;1"]
- .getService(Components.interfaces.nsIPluginHost);
- let mimeType = this.getAttribute("mimeType");
- return (pluginHost.getStateForType(mimeType)
- == Components.interfaces.nsIPluginTag.STATE_CLICKTOPLAY);
- ]]>
- </body>
- </method>
- <method name="isBlocklisted">
- <body><![CDATA[
- let pluginHost = Components.classes["@mozilla.org/plugin/host;1"]
- .getService(Components.interfaces.nsIPluginHost);
- let blocklistService = Components.classes["@mozilla.org/extensions/blocklist;1"]
- .getService(Components.interfaces.nsIBlocklistService);
- let mimeType = this.getAttribute("mimeType");
- let tags = pluginHost.getPluginTags();
- let blocklistState = Components.interfaces.nsIBlocklistService.STATE_NOT_BLOCKED;
- for (let plugin of tags) {
- if (plugin.getMimeTypes()[0] == mimeType) {
- blocklistState = blocklistService.getPluginBlocklistState(plugin);
- break;
- }
- }
- return (blocklistState == Components.interfaces.nsIBlocklistService.STATE_VULNERABLE_UPDATE_AVAILABLE ||
- blocklistState == Components.interfaces.nsIBlocklistService.STATE_VULNERABLE_NO_UPDATE);
- ]]>
- </body>
- </method>
- </implementation>
- </binding>
-</bindings>
diff --git a/components/permissions/aboutPermissions.xul b/components/permissions/aboutPermissions.xul
deleted file mode 100644
index dfee147..0000000
--- a/components/permissions/aboutPermissions.xul
+++ /dev/null
@@ -1,313 +0,0 @@
-<?xml version="1.0"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
-<?xml-stylesheet href="chrome://browser/content/permissions/aboutPermissions.css"?>
-<?xml-stylesheet href="chrome://browser/skin/permissions/aboutPermissions.css"?>
-
-<!DOCTYPE page [
-<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd" >
-%brandDTD;
-<!ENTITY % aboutPermissionsDTD SYSTEM "chrome://browser/locale/permissions/aboutPermissions.dtd" >
-%aboutPermissionsDTD;
-]>
-
-<page xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:xhtml="http://www.w3.org/1999/xhtml"
- id="permissions-page" title="&permissionsManager.title;"
- onload="AboutPermissions.init();"
- onunload="AboutPermissions.cleanUp();"
- disablefastfind="true"
- role="application">
-
- <script type="application/javascript"
- src="chrome://browser/content/permissions/aboutPermissions.js"/>
-
- <keyset>
- <key key="&focusSearch.key;" modifiers="accel" oncommand="AboutPermissions.focusFilterBox();"/>
- </keyset>
-
- <hbox id="permissions-header">
- <label id="permissions-pagetitle">&permissionsManager.title;</label>
- </hbox>
- <hbox flex="1" id="permissions-content" class="main-content">
-
- <vbox id="sites-box">
- <button id="sites-reload"
- label="&permissions.sitesReload;"
- oncommand="AboutPermissions.sitesReload();"/>
- <textbox id="sites-filter"
- emptytext="&sites.search;"
- oncommand="AboutPermissions.filterSitesList();"
- type="search"/>
- <richlistbox id="sites-list"
- flex="1"
- class="list"
- onselect="AboutPermissions.onSitesListSelect(event);">
- <richlistitem id="all-sites-item"
- class="site"
- value="&sites.allSites;"/>
- </richlistbox>
- </vbox>
-
- <vbox id="permissions-box" flex="1">
-
- <deck id="header-deck">
- <hbox id="site-header" class="pref-item" align="center">
- <description id="site-description">
- &header.site.start;<label id="site-label"/>&header.site.end;
- </description>
- <label id="site-visit-count"/>
- <spacer flex="1"/>
- <button id="forget-site-button"
- label="&permissions.forgetSite;"
- oncommand="AboutPermissions.forgetSite();"/>
- </hbox>
-
- <hbox id="defaults-header" class="pref-item" align="center">
- <description id="defaults-description">
- &header.defaults;
- </description>
- </hbox>
- </deck>
-
- <!-- Passwords -->
- <hbox id="password-pref-item"
- class="pref-item" align="top">
- <image class="pref-icon" type="password"/>
- <vbox>
- <hbox>
- <label class="pref-title" value="&password.label;"/>
- <label id="password-default" class="pref-default" value="*"/>
- </hbox>
- <hbox align="center">
- <menulist id="password-menulist"
- class="pref-menulist"
- type="password"
- oncommand="AboutPermissions.onPermissionCommand(event, false);">
- <menupopup>
- <menuitem id="password-1" value="1" label="&permission.allow;"/>
- <menuitem id="password-2" value="2" label="&permission.block;"/>
- </menupopup>
- </menulist>
- <button id="password-set-default"
- class="pref-set-default"
- label="&permission.default;"
- type="password"
- oncommand="AboutPermissions.onPermissionCommand(event, true);"/>
- <button id="passwords-manage-all-button"
- label="&password.manage;"
- oncommand="AboutPermissions.managePasswords();"/>
- </hbox>
- <hbox id="passwords-count" align="center">
- <label id="passwords-label"/>
- <button id="passwords-manage-button"
- label="&password.manage;"
- oncommand="AboutPermissions.managePasswords();"/>
- </hbox>
- </vbox>
- </hbox>
-
- <!-- Image Blocking -->
- <hbox id="image-pref-item"
- class="pref-item" align="top">
- <image class="pref-icon" type="image"/>
- <vbox>
- <hbox>
- <label class="pref-title" value="&image.label;"/>
- <label id="image-default" class="pref-default" value="*"/>
- </hbox>
- <hbox>
- <menulist id="image-menulist"
- class="pref-menulist"
- type="image"
- oncommand="AboutPermissions.onPermissionCommand(event, false);">
- <menupopup>
- <menuitem id="image-1" value="1" label="&permission.allow;"/>
- <menuitem id="image-2" value="2" label="&permission.block;"/>
- <menuitem id="image-3" value="3" label="&permission.allowFirstPartyOnly;"/>
- </menupopup>
- </menulist>
- <button id="image-set-default"
- class="pref-set-default"
- label="&permission.default;"
- type="image"
- oncommand="AboutPermissions.onPermissionCommand(event, true);"/>
- </hbox>
- </vbox>
- </hbox>
-
- <!-- Pop-up Blocking -->
- <hbox id="popup-pref-item"
- class="pref-item" align="top">
- <image class="pref-icon" type="popup"/>
- <vbox>
- <hbox>
- <label class="pref-title" value="&popup.label;"/>
- <label id="popup-default" class="pref-default" value="*"/>
- </hbox>
- <hbox>
- <menulist id="popup-menulist"
- class="pref-menulist"
- type="popup"
- oncommand="AboutPermissions.onPermissionCommand(event, false);">
- <menupopup>
- <menuitem id="popup-1" value="1" label="&permission.allow;"/>
- <menuitem id="popup-2" value="2" label="&permission.block;"/>
- </menupopup>
- </menulist>
- <button id="popup-set-default"
- class="pref-set-default"
- label="&permission.default;"
- type="popup"
- oncommand="AboutPermissions.onPermissionCommand(event, true);"/>
- </hbox>
- </vbox>
- </hbox>
-
- <!-- Cookies -->
- <hbox id="cookie-pref-item"
- class="pref-item" align="top">
- <image class="pref-icon" type="cookie"/>
- <vbox>
- <hbox>
- <label class="pref-title" value="&cookie.label;"/>
- <label id="cookie-default" class="pref-default" value="*"/>
- </hbox>
- <hbox align="center">
- <menulist id="cookie-menulist"
- class="pref-menulist"
- type="cookie"
- oncommand="AboutPermissions.onPermissionCommand(event, false);">
- <menupopup>
- <menuitem id="cookie-1" value="1" label="&permission.allow;"/>
- <menuitem id="cookie-8" value="8" label="&permission.allowForSession;"/>
- <menuitem id="cookie-9" value="9" label="&permission.allowFirstPartyOnly;"/>
- <menuitem id="cookie-2" value="2" label="&permission.block;"/>
- </menupopup>
- </menulist>
- <button id="cookie-set-default"
- class="pref-set-default"
- label="&permission.default;"
- type="cookie"
- oncommand="AboutPermissions.onPermissionCommand(event, true);"/>
- <button id="cookies-clear-all-button"
- label="&cookie.removeAll;"
- oncommand="Services.cookies.removeAll();"/>
- <button id="cookies-manage-all-button"
- label="&cookie.manage;"
- oncommand="AboutPermissions.manageCookies();"/>
- </hbox>
- <hbox id="cookies-count" align="center">
- <label id="cookies-label"/>
- <button id="cookies-clear-button"
- label="&cookie.remove;"
- oncommand="AboutPermissions.clearCookies();"/>
- <button id="cookies-manage-button"
- label="&cookie.manage;"
- oncommand="AboutPermissions.manageCookies();"/>
- </hbox>
- </vbox>
- </hbox>
-
- <!-- Desktop Notifications -->
- <hbox id="desktop-notification-pref-item"
- class="pref-item" align="top">
- <image class="pref-icon" type="desktop-notification"/>
- <vbox>
- <hbox>
- <label class="pref-title" value="&desktop-notification.label;"/>
- <label id="desktop-notification-default" class="pref-default" value="*"/>
- </hbox>
- <hbox>
- <menulist id="desktop-notification-menulist"
- class="pref-menulist"
- type="desktop-notification"
- oncommand="AboutPermissions.onPermissionCommand(event, false);">
- <menupopup>
- <menuitem id="desktop-notification-0" value="0" label="&permission.alwaysAsk;"/>
- <menuitem id="desktop-notification-1" value="1" label="&permission.allow;"/>
- <menuitem id="desktop-notification-2" value="2" label="&permission.block;"/>
- </menupopup>
- </menulist>
- <button id="desktop-notification-set-default"
- class="pref-set-default"
- label="&permission.default;"
- type="desktop-notification"
- oncommand="AboutPermissions.onPermissionCommand(event, true);"/>
- </hbox>
- </vbox>
- </hbox>
-
- <!-- Addons Blocking -->
- <hbox id="install-pref-item"
- class="pref-item" align="top">
- <image class="pref-icon" type="install"/>
- <vbox>
- <hbox>
- <label class="pref-title" value="&install.label;"/>
- <label id="install-default" class="pref-default" value="*"/>
- </hbox>
- <hbox>
- <menulist id="install-menulist"
- class="pref-menulist"
- type="install"
- oncommand="AboutPermissions.onPermissionCommand(event, false);">
- <menupopup>
- <menuitem id="install-1" value="1" label="&permission.allow;"/>
- <menuitem id="install-2" value="2" label="&permission.block;"/>
- </menupopup>
- </menulist>
- <button id="install-set-default"
- class="pref-set-default"
- label="&permission.default;"
- type="install"
- oncommand="AboutPermissions.onPermissionCommand(event, true);"/>
- </hbox>
- </vbox>
- </hbox>
-
- <!-- Geolocation -->
- <hbox id="geo-pref-item"
- class="pref-item" align="top">
- <image class="pref-icon" type="geo"/>
- <vbox>
- <hbox>
- <label class="pref-title" value="&geo.label;"/>
- <label id="geo-default" class="pref-default" value="*"/>
- </hbox>
- <hbox>
- <menulist id="geo-menulist"
- class="pref-menulist"
- type="geo"
- oncommand="AboutPermissions.onPermissionCommand(event, false);">
- <menupopup>
- <menuitem id="geo-0" value="0" label="&permission.alwaysAsk;"/>
- <menuitem id="geo-1" value="1" label="&permission.allow;"/>
- <menuitem id="geo-2" value="2" label="&permission.block;"/>
- </menupopup>
- </menulist>
- <button id="geo-set-default"
- class="pref-set-default"
- label="&permission.default;"
- type="geo"
- oncommand="AboutPermissions.onPermissionCommand(event, true);"/>
- </hbox>
- </vbox>
- </hbox>
-
- <!-- Opt-in activation of Plug-ins -->
- <hbox id="plugins-pref-item"
- class="pref-item" align="top">
- <image class="pref-icon" type="plugins"/>
- <vbox>
- <label class="pref-title" value="&plugins.label;"/>
- <vbox id="plugins-box"/>
- </vbox>
- </hbox>
- </vbox>
- </hbox>
-
-</page>
diff --git a/components/permissions/jar.mn b/components/permissions/jar.mn
deleted file mode 100644
index c788938..0000000
--- a/components/permissions/jar.mn
+++ /dev/null
@@ -1,9 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-browser.jar:
- content/browser/permissions/aboutPermissions.xul
- content/browser/permissions/aboutPermissions.js
- content/browser/permissions/aboutPermissions.css
- content/browser/permissions/aboutPermissions.xml
diff --git a/components/permissions/moz.build b/components/permissions/moz.build
deleted file mode 100644
index 3bbe672..0000000
--- a/components/permissions/moz.build
+++ /dev/null
@@ -1,7 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-JAR_MANIFESTS += ['jar.mn']
diff --git a/components/places/PlacesUIUtils.jsm b/components/places/PlacesUIUtils.jsm
deleted file mode 100644
index e3a9e13..0000000
--- a/components/places/PlacesUIUtils.jsm
+++ /dev/null
@@ -1,1373 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-this.EXPORTED_SYMBOLS = ["PlacesUIUtils"];
-
-var Ci = Components.interfaces;
-var Cc = Components.classes;
-var Cr = Components.results;
-var Cu = Components.utils;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
- "resource://gre/modules/PluralForm.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
- "resource://gre/modules/PrivateBrowsingUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "RecentWindow",
- "resource:///modules/RecentWindow.jsm");
-
-XPCOMUtils.defineLazyGetter(this, "PlacesUtils", function() {
- Cu.import("resource://gre/modules/PlacesUtils.jsm");
- return PlacesUtils;
-});
-
-this.PlacesUIUtils = {
- ORGANIZER_LEFTPANE_VERSION: 7,
- ORGANIZER_FOLDER_ANNO: "PlacesOrganizer/OrganizerFolder",
- ORGANIZER_QUERY_ANNO: "PlacesOrganizer/OrganizerQuery",
-
- LOAD_IN_SIDEBAR_ANNO: "bookmarkProperties/loadInSidebar",
- DESCRIPTION_ANNO: "bookmarkProperties/description",
-
- TYPE_TAB_DROP: "application/x-moz-tabbrowser-tab",
-
- /**
- * Makes a URI from a spec, and do fixup
- * @param aSpec
- * The string spec of the URI
- * @returns A URI object for the spec.
- */
- createFixedURI: function PUIU_createFixedURI(aSpec) {
- return URIFixup.createFixupURI(aSpec, Ci.nsIURIFixup.FIXUP_FLAG_NONE);
- },
-
- getFormattedString: function PUIU_getFormattedString(key, params) {
- return bundle.formatStringFromName(key, params, params.length);
- },
-
- /**
- * Get a localized plural string for the specified key name and numeric value
- * substituting parameters.
- *
- * @param aKey
- * String, key for looking up the localized string in the bundle
- * @param aNumber
- * Number based on which the final localized form is looked up
- * @param aParams
- * Array whose items will substitute #1, #2,... #n parameters
- * in the string.
- *
- * @see https://developer.mozilla.org/en/Localization_and_Plurals
- * @return The localized plural string.
- */
- getPluralString: function PUIU_getPluralString(aKey, aNumber, aParams) {
- let str = PluralForm.get(aNumber, bundle.GetStringFromName(aKey));
-
- // Replace #1 with aParams[0], #2 with aParams[1], and so on.
- return str.replace(/\#(\d+)/g, function (matchedId, matchedNumber) {
- let param = aParams[parseInt(matchedNumber, 10) - 1];
- return param !== undefined ? param : matchedId;
- });
- },
-
- getString: function PUIU_getString(key) {
- return bundle.GetStringFromName(key);
- },
-
- get _copyableAnnotations() [
- this.DESCRIPTION_ANNO,
- this.LOAD_IN_SIDEBAR_ANNO,
- PlacesUtils.POST_DATA_ANNO,
- PlacesUtils.READ_ONLY_ANNO,
- ],
-
- /**
- * Get a transaction for copying a uri item (either a bookmark or a history
- * entry) 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
- * @return A nsITransaction object that performs the copy.
- *
- * @note Since a copy creates a completely new item, only some internal
- * annotations are synced from the old one.
- * @see this._copyableAnnotations for the list of copyable annotations.
- */
- _getURIItemCopyTransaction:
- function PUIU__getURIItemCopyTransaction(aData, aContainer, aIndex)
- {
- let transactions = [];
- if (aData.dateAdded) {
- transactions.push(
- new PlacesEditItemDateAddedTransaction(null, aData.dateAdded)
- );
- }
- if (aData.lastModified) {
- transactions.push(
- new PlacesEditItemLastModifiedTransaction(null, aData.lastModified)
- );
- }
-
- let keyword = aData.keyword || null;
- let annos = [];
- if (aData.annos) {
- annos = aData.annos.filter(function (aAnno) {
- return this._copyableAnnotations.indexOf(aAnno.name) != -1;
- }, this);
- }
-
- return new PlacesCreateBookmarkTransaction(PlacesUtils._uri(aData.uri),
- aContainer, aIndex, aData.title,
- keyword, annos, transactions);
- },
-
- /**
- * 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
- * @return A nsITransaction object that will perform the copy.
- *
- * @note Since a copy creates a completely new item, only some internal
- * annotations are synced from the old one.
- * @see this._copyableAnnotations for the list of copyable annotations.
- */
- _getFolderCopyTransaction(aData, aContainer, aIndex) {
- function getChildItemsTransactions(aRoot) {
- let transactions = [];
- let index = aIndex;
- for (let i = 0; i < aRoot.childCount; ++i) {
- let child = aRoot.getChild(i);
- // Temporary hacks until we switch to PlacesTransactions.jsm.
- let isLivemark =
- PlacesUtils.annotations.itemHasAnnotation(child.itemId,
- PlacesUtils.LMANNO_FEEDURI);
- let [node] = PlacesUtils.unwrapNodes(
- PlacesUtils.wrapNode(child, PlacesUtils.TYPE_X_MOZ_PLACE, isLivemark),
- PlacesUtils.TYPE_X_MOZ_PLACE
- );
-
- // 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 for 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) {
- transactions.push(
- PlacesUIUtils._getLivemarkCopyTransaction(node, aContainer, index)
- );
- }
- else {
- transactions.push(
- PlacesUIUtils._getFolderCopyTransaction(node, aContainer, index)
- );
- }
- }
- else if (node.type == PlacesUtils.TYPE_X_MOZ_PLACE_SEPARATOR) {
- transactions.push(new PlacesCreateSeparatorTransaction(-1, index));
- }
- else if (node.type == PlacesUtils.TYPE_X_MOZ_PLACE) {
- transactions.push(
- PlacesUIUtils._getURIItemCopyTransaction(node, -1, index)
- );
- }
- else {
- throw new Error("Unexpected item under a bookmarks folder");
- }
- }
- return transactions;
- }
-
- if (aContainer == PlacesUtils.tagsFolderId) { // Copying into a tag folder.
- let transactions = [];
- if (!aData.livemark && aData.type == PlacesUtils.TYPE_X_MOZ_PLACE_CONTAINER) {
- let {root} = PlacesUtils.getFolderContents(aData.id, false, false);
- let urls = PlacesUtils.getURLsForContainerNode(root);
- root.containerOpen = false;
- for (let { uri } of urls) {
- transactions.push(
- new PlacesTagURITransaction(NetUtil.newURI(uri), [aData.title])
- );
- }
- }
- return new PlacesAggregatedTransaction("addTags", transactions);
- }
-
- if (aData.livemark && aData.annos) { // Copying a livemark.
- return this._getLivemarkCopyTransaction(aData, aContainer, aIndex);
- }
-
- let {root} = PlacesUtils.getFolderContents(aData.id, false, false);
- let transactions = getChildItemsTransactions(root);
- root.containerOpen = false;
-
- if (aData.dateAdded) {
- transactions.push(
- new PlacesEditItemDateAddedTransaction(null, aData.dateAdded)
- );
- }
- if (aData.lastModified) {
- transactions.push(
- new PlacesEditItemLastModifiedTransaction(null, aData.lastModified)
- );
- }
-
- let annos = [];
- if (aData.annos) {
- annos = aData.annos.filter(function (aAnno) {
- return this._copyableAnnotations.indexOf(aAnno.name) != -1;
- }, this);
- }
-
- return new PlacesCreateFolderTransaction(aData.title, aContainer, aIndex,
- annos, transactions);
- },
-
- /**
- * Gets a transaction for copying a live bookmark item from one container to
- * another.
- *
- * @param aData
- * Unwrapped live bookmarkmark data
- * @param aContainer
- * The container we are copying into
- * @param aIndex
- * The index in the destination container to insert the new items
- * @return A nsITransaction object that will perform the copy.
- *
- * @note Since a copy creates a completely new item, only some internal
- * annotations are synced from the old one.
- * @see this._copyableAnnotations for the list of copyable annotations.
- */
- _getLivemarkCopyTransaction:
- function PUIU__getLivemarkCopyTransaction(aData, aContainer, aIndex)
- {
- if (!aData.livemark || !aData.annos) {
- throw new Error("node is not a livemark");
- }
-
- let feedURI, siteURI;
- let annos = [];
- if (aData.annos) {
- annos = aData.annos.filter(function (aAnno) {
- if (aAnno.name == PlacesUtils.LMANNO_FEEDURI) {
- feedURI = PlacesUtils._uri(aAnno.value);
- }
- else if (aAnno.name == PlacesUtils.LMANNO_SITEURI) {
- siteURI = PlacesUtils._uri(aAnno.value);
- }
- return this._copyableAnnotations.indexOf(aAnno.name) != -1
- }, this);
- }
-
- return new PlacesCreateLivemarkTransaction(feedURI, siteURI, aData.title,
- aContainer, aIndex, annos);
- },
-
- /**
- * Test if a bookmark item = a live bookmark item.
- *
- * @param aItemId
- * item identifier
- * @return true if a live bookmark item, false otherwise.
- *
- * @note Maybe this should be removed later, see bug 1072833.
- */
- _isLivemark:
- function PUIU__isLivemark(aItemId)
- {
- // Since this check may be done on each dragover event, it's worth maintaining
- // a cache.
- let self = PUIU__isLivemark;
- if (!("ids" in self)) {
- const LIVEMARK_ANNO = PlacesUtils.LMANNO_FEEDURI;
-
- let idsVec = PlacesUtils.annotations.getItemsWithAnnotation(LIVEMARK_ANNO);
- self.ids = new Set(idsVec);
-
- let obs = Object.freeze({
- QueryInterface: XPCOMUtils.generateQI(Ci.nsIAnnotationObserver),
-
- onItemAnnotationSet(itemId, annoName) {
- if (annoName == LIVEMARK_ANNO)
- self.ids.add(itemId);
- },
-
- onItemAnnotationRemoved(itemId, annoName) {
- // If annoName is set to an empty string, the item is gone.
- if (annoName == LIVEMARK_ANNO || annoName == "")
- self.ids.delete(itemId);
- },
-
- onPageAnnotationSet() { },
- onPageAnnotationRemoved() { },
- });
- PlacesUtils.annotations.addObserver(obs);
- PlacesUtils.registerShutdownFunction(() => {
- PlacesUtils.annotations.removeObserver(obs);
- });
- }
- return self.ids.has(aItemId);
- },
-
- /**
- * 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 PUIU_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 new PlacesMoveItemTransaction(data.id, container, index);
- break;
- case PlacesUtils.TYPE_X_MOZ_PLACE:
- if (copy || data.id == -1) { // Id is -1 if the place is not bookmarked.
- return this._getURIItemCopyTransaction(data, container, index);
- }
-
- // Otherwise move the item.
- return new PlacesMoveItemTransaction(data.id, container, index);
- break;
- case PlacesUtils.TYPE_X_MOZ_PLACE_SEPARATOR:
- if (copy) {
- // There is no data in a separator, so copying it just amounts to
- // inserting a new separator.
- return new PlacesCreateSeparatorTransaction(container, index);
- }
-
- // Otherwise move the item.
- return new PlacesMoveItemTransaction(data.id, container, index);
- break;
- default:
- if (type == PlacesUtils.TYPE_X_MOZ_URL ||
- type == PlacesUtils.TYPE_UNICODE ||
- type == this.TYPE_TAB_DROP) {
- let title = type != PlacesUtils.TYPE_UNICODE ? data.title
- : data.uri;
- return new PlacesCreateBookmarkTransaction(PlacesUtils._uri(data.uri),
- container, index, title);
- }
- }
- return null;
- },
-
- /**
- * 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 aWindow
- * Owner window for the new dialog.
- *
- * @see documentation at the top of bookmarkProperties.js
- * @return true if any transaction has been performed, false otherwise.
- */
- showBookmarkDialog:
- function PUIU_showBookmarkDialog(aInfo, aParentWindow) {
- // Preserve size attributes differently based on the fact the dialog has
- // a folder picker or not, since it needs more horizontal space than the
- // other controls.
- let hasFolderPicker = !("hiddenRows" in aInfo) ||
- aInfo.hiddenRows.indexOf("folderPicker") == -1;
- // Use a different chrome url to persist different sizes.
- let dialogURL = hasFolderPicker ?
- "chrome://browser/content/places/bookmarkProperties2.xul" :
- "chrome://browser/content/places/bookmarkProperties.xul";
-
- let features = "centerscreen,chrome,modal,resizable=yes";
- aParentWindow.openDialog(dialogURL, "", features, aInfo);
- return ("performed" in aInfo && aInfo.performed);
- },
-
- _getTopBrowserWin: function PUIU__getTopBrowserWin() {
- return RecentWindow.getMostRecentBrowserWindow();
- },
-
- /**
- * 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 PUIU_getViewForNode(aNode) {
- let node = aNode;
-
- // The view for a <menu> of which its associated menupopup is a places
- // view, is the menupopup.
- if (node.localName == "menu" && !node._placesNode &&
- node.lastChild._placesView)
- return node.lastChild._placesView;
-
- while (node instanceof Ci.nsIDOMElement) {
- if (node._placesView)
- return node._placesView;
- if (node.localName == "tree" && node.getAttribute("type") == "places")
- return node;
-
- node = node.parentNode;
- }
-
- return null;
- },
-
- /**
- * By calling this before visiting an URL, the visit will be associated to a
- * TRANSITION_TYPED transition (if there is no 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 this is not called visits will be marked as
- * TRANSITION_LINK.
- */
- markPageAsTyped: function PUIU_markPageAsTyped(aURL) {
- PlacesUtils.history.markPageAsTyped(this.createFixedURI(aURL));
- },
-
- /**
- * By calling this before visiting an URL, the visit will be associated to a
- * TRANSITION_BOOKMARK transition.
- * This is used when visiting pages from the bookmarks menu,
- * personal toolbar, and bookmarks from within the places organizer.
- * If this is not called visits will be marked as TRANSITION_LINK.
- */
- markPageAsFollowedBookmark: function PUIU_markPageAsFollowedBookmark(aURL) {
- PlacesUtils.history.markPageAsFollowedBookmark(this.createFixedURI(aURL));
- },
-
- /**
- * By calling this before visiting an URL, any visit in frames will be
- * associated to a TRANSITION_FRAMED_LINK transition.
- * This is actually used to distinguish user-initiated visits in frames
- * so automatic visits can be correctly ignored.
- */
- markPageAsFollowedLink: function PUIU_markPageAsFollowedLink(aURL) {
- PlacesUtils.history.markPageAsFollowedLink(this.createFixedURI(aURL));
- },
-
- /**
- * Allows opening of javascript/data URI only if the given node is
- * bookmarked (see bug 224521).
- * @param aURINode
- * a URI node
- * @param aWindow
- * a window on which a potential error alert is shown on.
- * @return true if it's safe to open the node in the browser, false otherwise.
- *
- */
- checkURLSecurity: function PUIU_checkURLSecurity(aURINode, aWindow) {
- if (PlacesUtils.nodeIsBookmark(aURINode))
- return true;
-
- 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 errorStr = this.getString("load-js-data-url-error");
- Services.prompt.alert(aWindow, brandShortName, errorStr);
- return false;
- }
- return true;
- },
-
- /**
- * Get the description associated with a document, as specified in a <META>
- * 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 PUIU_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 PUIU_getItemDescription(aItemId) {
- if (PlacesUtils.annotations.itemHasAnnotation(aItemId, this.DESCRIPTION_ANNO))
- return PlacesUtils.annotations.getItemAnnotation(aItemId, this.DESCRIPTION_ANNO);
- return "";
- },
-
- /**
- * Check whether or not the given node represents a removable entry (either in
- * history or in bookmarks).
- *
- * @param aNode
- * a node, except the root node of a query.
- * @return true if the aNode represents a removable entry, false otherwise.
- */
- canUserRemove: function (aNode) {
- let parentNode = aNode.parent;
- if (!parentNode)
- throw new Error("canUserRemove doesn't accept root nodes");
-
- // If it's not a bookmark, we can remove it unless it's a child of a
- // livemark.
- if (aNode.itemId == -1) {
- // Rather than executing a db query, checking the existence of the feedURI
- // annotation, detect livemark children by the fact that they are the only
- // direct non-bookmark children of bookmark folders.
- return !PlacesUtils.nodeIsFolder(parentNode);
- }
-
- // Generally it's always possible to remove children of a query.
- if (PlacesUtils.nodeIsQuery(parentNode))
- return true;
-
- // Otherwise it has to be a child of an editable folder.
- return !this.isContentsReadOnly(parentNode);
- },
-
- /**
- * DO NOT USE THIS API IN ADDONS. IT IS VERY LIKELY TO CHANGE WHEN THE SWITCH
- * TO GUIDS IS COMPLETE (BUG 1071511).
- *
- * Check whether or not the given node or item-id points to a folder which
- * should not be modified by the user (i.e. its children should be unremovable
- * and unmovable, new children should be disallowed, etc).
- * These semantics are not inherited, meaning that read-only folder may
- * contain editable items (for instance, the places root is read-only, but all
- * of its direct children aren't).
- *
- * You should only pass folder item ids or folder nodes for aNodeOrItemId.
- * While this is only enforced for the node case (if an item id of a separator
- * or a bookmark is passed, false is returned), it's considered the caller's
- * job to ensure that it checks a folder.
- * Also note that folder-shortcuts should only be passed as result nodes.
- * Otherwise they are just treated as bookmarks (i.e. false is returned).
- *
- * @param aNodeOrItemId
- * any item id or result node.
- * @throws if aNodeOrItemId is neither an item id nor a folder result node.
- * @note livemark "folders" are considered read-only (but see bug 1072833).
- * @return true if aItemId points to a read-only folder, false otherwise.
- */
- isContentsReadOnly: function (aNodeOrItemId) {
- let itemId;
- if (typeof(aNodeOrItemId) == "number") {
- itemId = aNodeOrItemId;
- }
- else if (PlacesUtils.nodeIsFolder(aNodeOrItemId)) {
- itemId = PlacesUtils.getConcreteItemId(aNodeOrItemId);
- }
- else {
- throw new Error("invalid value for aNodeOrItemId");
- }
-
- if (itemId == PlacesUtils.placesRootId || this._isLivemark(itemId))
- return true;
-
- // leftPaneFolderId, and as a result, allBookmarksFolderId, is a lazy getter
- // performing at least a synchronous DB query (and on its very first call
- // in a fresh profile, it also creates the entire structure).
- // Therefore we don't want to this function, which is called very often by
- // isCommandEnabled, to ever be the one that invokes it first, especially
- // because isCommandEnabled may be called way before the left pane folder is
- // even created (for example, if the user only uses the bookmarks menu or
- // toolbar for managing bookmarks). To do so, we avoid comparing to those
- // special folder if the lazy getter is still in place. This is safe merely
- // because the only way to access the left pane contents goes through
- // "resolving" the leftPaneFolderId getter.
- if ("get" in Object.getOwnPropertyDescriptor(this, "leftPaneFolderId"))
- return false;
-
- return itemId == this.leftPaneFolderId ||
- itemId == this.allBookmarksFolderId;
- },
-
- /**
- * Gives the user a chance to cancel loading lots of tabs at once
- */
- _confirmOpenInTabs:
- function PUIU__confirmOpenInTabs(numTabsToOpen, aWindow) {
- const WARN_ON_OPEN_PREF = "browser.tabs.warnOnOpen";
- var reallyOpen = true;
-
- if (Services.prefs.getBoolPref(WARN_ON_OPEN_PREF)) {
- if (numTabsToOpen >= Services.prefs.getIntPref("browser.tabs.maxOpenBeforeWarn")) {
- // 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 = Services.prompt.confirmEx(
- aWindow,
- this.getString("tabs.openWarningTitle"),
- this.getFormattedString(messageKey, [numTabsToOpen, brandShortName]),
- (Services.prompt.BUTTON_TITLE_IS_STRING * Services.prompt.BUTTON_POS_0) +
- (Services.prompt.BUTTON_TITLE_CANCEL * Services.prompt.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)
- Services.prefs.setBoolPref(WARN_ON_OPEN_PREF, false);
- }
- }
-
- return reallyOpen;
- },
-
- /** aItemsToOpen needs to be an array of objects of the form:
- * {uri: string, isBookmark: boolean}
- */
- _openTabset: function PUIU__openTabset(aItemsToOpen, aEvent, aWindow) {
- if (!aItemsToOpen.length)
- return;
-
- // Prefer the caller window if it's a browser window, otherwise use
- // the top browser window.
- var browserWindow = null;
- browserWindow =
- aWindow && aWindow.document.documentElement.getAttribute("windowtype") == "navigator:browser" ?
- aWindow : this._getTopBrowserWin();
-
- var urls = [];
- let skipMarking = browserWindow && PrivateBrowsingUtils.isWindowPrivate(browserWindow);
- for (let item of aItemsToOpen) {
- urls.push(item.uri);
- if (skipMarking) {
- continue;
- }
-
- if (item.isBookmark)
- this.markPageAsFollowedBookmark(item.uri);
- else
- this.markPageAsTyped(item.uri);
- }
-
- // whereToOpenLink doesn't return "window" when there's no browser window
- // open (Bug 630255).
- var where = browserWindow ?
- browserWindow.whereToOpenLink(aEvent, false, true) : "window";
- if (where == "window") {
- // There is no browser window open, thus open a new one.
- var uriList = PlacesUtils.toISupportsString(urls.join("|"));
- var args = Cc["@mozilla.org/supports-array;1"].
- createInstance(Ci.nsISupportsArray);
- args.AppendElement(uriList);
- browserWindow = Services.ww.openWindow(aWindow,
- "chrome://browser/content/browser.xul",
- null, "chrome,dialog=no,all", args);
- return;
- }
-
- var loadInBackground = where == "tabshifted" ? true : false;
- // For consistency, we want all the bookmarks to open in new tabs, instead
- // of having one of them replace the currently focused tab. Hence we call
- // loadTabs with aReplace set to false.
- browserWindow.gBrowser.loadTabs(urls, loadInBackground, false);
- },
-
- openLiveMarkNodesInTabs:
- function PUIU_openLiveMarkNodesInTabs(aNode, aEvent, aView) {
- let window = aView.ownerWindow;
-
- PlacesUtils.livemarks.getLivemark({id: aNode.itemId})
- .then(aLivemark => {
- urlsToOpen = [];
-
- let nodes = aLivemark.getNodesForContainer(aNode);
- for (let node of nodes) {
- urlsToOpen.push({uri: node.uri, isBookmark: false});
- }
-
- if (this._confirmOpenInTabs(urlsToOpen.length, window)) {
- this._openTabset(urlsToOpen, aEvent, window);
- }
- }, Cu.reportError);
- },
-
- openContainerNodeInTabs:
- function PUIU_openContainerInTabs(aNode, aEvent, aView) {
- let window = aView.ownerWindow;
-
- let urlsToOpen = PlacesUtils.getURLsForContainerNode(aNode);
- if (this._confirmOpenInTabs(urlsToOpen.length, window)) {
- this._openTabset(urlsToOpen, aEvent, window);
- }
- },
-
- openURINodesInTabs: function PUIU_openURINodesInTabs(aNodes, aEvent, aView) {
- let window = aView.ownerWindow;
-
- let 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, window);
- },
-
- /**
- * 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.
- * @param aView
- * The controller associated with aNode.
- */
- openNodeWithEvent:
- function PUIU_openNodeWithEvent(aNode, aEvent, aView) {
- let window = aView.ownerWindow;
- this._openNodeIn(aNode, window.whereToOpenLink(aEvent, false, true), window);
- },
-
- /**
- * Loads the node's URL in the appropriate tab or window or as a
- * web panel.
- * see also openUILinkIn
- */
- openNodeIn: function PUIU_openNodeIn(aNode, aWhere, aView, aPrivate) {
- let window = aView.ownerWindow;
- this._openNodeIn(aNode, aWhere, window, aPrivate);
- },
-
- _openNodeIn: function PUIU_openNodeIn(aNode, aWhere, aWindow, aPrivate=false) {
- if (aNode && PlacesUtils.nodeIsURI(aNode) &&
- this.checkURLSecurity(aNode, aWindow)) {
- let isBookmark = PlacesUtils.nodeIsBookmark(aNode);
-
- if (!PrivateBrowsingUtils.isWindowPrivate(aWindow)) {
- 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, this.LOAD_IN_SIDEBAR_ANNO)) {
- let browserWin = this._getTopBrowserWin();
- if (browserWin) {
- browserWin.openWebPanel(aNode.title, aNode.uri);
- return;
- }
- }
- }
- aWindow.openUILinkIn(aNode.uri, aWhere, {
- inBackground: Services.prefs.getBoolPref("browser.tabs.loadBookmarksInBackground"),
- private: aPrivate,
- });
- }
- },
-
- /**
- * 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 PUIU_guessUrlSchemeForUI(aUrlString) {
- return aUrlString.substr(0, aUrlString.indexOf(":"));
- },
-
- getBestTitle: function PUIU_getBestTitle(aNode, aDoNotCutTitle) {
- var title;
- if (!aNode.title && PlacesUtils.nodeIsURI(aNode)) {
- // 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
- if (aDoNotCutTitle) {
- title = host + uri.path;
- } else {
- 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() {
- let leftPaneRoot = -1;
- let allBookmarksId;
-
- // Shortcuts to services.
- let bs = PlacesUtils.bookmarks;
- let as = PlacesUtils.annotations;
-
- // This is the list of the left pane queries.
- let queries = {
- "PlacesRoot": { title: "" },
- "History": { title: this.getString("OrganizerQueryHistory") },
- "Downloads": { title: this.getString("OrganizerQueryDownloads") },
- "Tags": { title: this.getString("OrganizerQueryTags") },
- "AllBookmarks": { title: this.getString("OrganizerQueryAllBookmarks") },
- "BookmarksToolbar":
- { title: null,
- concreteTitle: PlacesUtils.getString("BookmarksToolbarFolderTitle"),
- concreteId: PlacesUtils.toolbarFolderId },
- "BookmarksMenu":
- { title: null,
- concreteTitle: PlacesUtils.getString("BookmarksMenuFolderTitle"),
- concreteId: PlacesUtils.bookmarksMenuFolderId },
- "UnfiledBookmarks":
- { title: null,
- concreteTitle: PlacesUtils.getString("UnsortedBookmarksFolderTitle"),
- concreteId: PlacesUtils.unfiledBookmarksFolderId },
- };
- // All queries but PlacesRoot.
- const EXPECTED_QUERY_COUNT = 7;
-
- // Removes an item and associated annotations, ignoring eventual errors.
- function safeRemoveItem(aItemId) {
- try {
- if (as.itemHasAnnotation(aItemId, PlacesUIUtils.ORGANIZER_QUERY_ANNO) &&
- !(as.getItemAnnotation(aItemId, PlacesUIUtils.ORGANIZER_QUERY_ANNO) in queries)) {
- // Some extension annotated their roots with our query annotation,
- // so we should not delete them.
- return;
- }
- // removeItemAnnotation does not check if item exists, nor the anno,
- // so this is safe to do.
- as.removeItemAnnotation(aItemId, PlacesUIUtils.ORGANIZER_FOLDER_ANNO);
- as.removeItemAnnotation(aItemId, PlacesUIUtils.ORGANIZER_QUERY_ANNO);
- // This will throw if the annotation is an orphan.
- bs.removeItem(aItemId);
- }
- catch(e) { /* orphan anno */ }
- }
-
- // Returns true if item really exists, false otherwise.
- function itemExists(aItemId) {
- try {
- bs.getItemIndex(aItemId);
- return true;
- }
- catch(e) {
- return false;
- }
- }
-
- // Get all items marked as being the left pane folder.
- let items = as.getItemsWithAnnotation(this.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(safeRemoveItem);
- }
- else if (items.length == 1 && items[0] != -1) {
- leftPaneRoot = items[0];
- // Check that organizer left pane root is valid.
- let version = as.getItemAnnotation(leftPaneRoot, this.ORGANIZER_FOLDER_ANNO);
- if (version != this.ORGANIZER_LEFTPANE_VERSION ||
- !itemExists(leftPaneRoot)) {
- // Invalid root, we must rebuild the left pane.
- safeRemoveItem(leftPaneRoot);
- leftPaneRoot = -1;
- }
- }
-
- 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 = {};
-
- let items = as.getItemsWithAnnotation(this.ORGANIZER_QUERY_ANNO);
- // While looping through queries we will also check for their validity.
- let queriesCount = 0;
- for (let i = 0; i < items.length; i++) {
- let queryName = as.getItemAnnotation(items[i], this.ORGANIZER_QUERY_ANNO);
-
- // Some extension did use our annotation to decorate their items
- // with icons, so we should check only our elements, to avoid dataloss.
- if (!(queryName in queries))
- continue;
-
- let query = queries[queryName];
- query.itemId = items[i];
-
- if (!itemExists(query.itemId)) {
- // Orphan annotation, bail out and create a new left pane root.
- break;
- }
-
- // Check that all queries have valid parents.
- let parentId = bs.getFolderIdForItem(query.itemId);
- if (items.indexOf(parentId) == -1 && parentId != leftPaneRoot) {
- // The parent is not part of the left pane, bail out and create a new
- // left pane root.
- break;
- }
-
- // Titles could have been corrupted or the user could have changed his
- // locale. Check title and eventually fix it.
- if (bs.getItemTitle(query.itemId) != query.title)
- bs.setItemTitle(query.itemId, query.title);
- if ("concreteId" in query) {
- if (bs.getItemTitle(query.concreteId) != query.concreteTitle)
- bs.setItemTitle(query.concreteId, query.concreteTitle);
- }
-
- // Add the query to our cache.
- this.leftPaneQueries[queryName] = query.itemId;
- queriesCount++;
- }
-
- if (queriesCount != EXPECTED_QUERY_COUNT) {
- // Queries number is wrong, so the left pane must be corrupt.
- // Note: we can't just remove the leftPaneRoot, because some query could
- // have a bad parent, so we have to remove all items one by one.
- items.forEach(safeRemoveItem);
- safeRemoveItem(leftPaneRoot);
- }
- else {
- // Everything is fine, return the current left pane folder.
- delete this.leftPaneFolderId;
- return this.leftPaneFolderId = leftPaneRoot;
- }
- }
-
- // Create a new left pane folder.
- 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,
- queries[aQueryName].title);
- // Mark as special organizer query.
- as.setItemAnnotation(itemId, PlacesUIUtils.ORGANIZER_QUERY_ANNO, aQueryName,
- 0, as.EXPIRE_NEVER);
- // We should never backup this, since it changes between profiles.
- as.setItemAnnotation(itemId, PlacesUtils.EXCLUDE_FROM_BACKUP_ANNO, 1,
- 0, as.EXPIRE_NEVER);
- // Add to the queries map.
- PlacesUIUtils.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,
- queries[aFolderName].title,
- bs.DEFAULT_INDEX);
- // We should never backup this, since it changes between profiles.
- as.setItemAnnotation(folderId, PlacesUtils.EXCLUDE_FROM_BACKUP_ANNO, 1,
- 0, as.EXPIRE_NEVER);
-
- if (aIsRoot) {
- // Mark as special left pane root.
- as.setItemAnnotation(folderId, PlacesUIUtils.ORGANIZER_FOLDER_ANNO,
- PlacesUIUtils.ORGANIZER_LEFTPANE_VERSION,
- 0, as.EXPIRE_NEVER);
- }
- else {
- // Mark as special organizer folder.
- as.setItemAnnotation(folderId, PlacesUIUtils.ORGANIZER_QUERY_ANNO, aFolderName,
- 0, as.EXPIRE_NEVER);
- PlacesUIUtils.leftPaneQueries[aFolderName] = folderId;
- }
- return folderId;
- },
-
- runBatched: function CB_runBatched(aUserData) {
- delete PlacesUIUtils.leftPaneQueries;
- PlacesUIUtils.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.
- this.create_query("Downloads", leftPaneRoot,
- "place:transition=" +
- Ci.nsINavHistoryService.TRANSITION_DOWNLOAD +
- "&sort=" +
- Ci.nsINavHistoryQueryOptions.SORT_BY_DATE_DESCENDING);
-
- // 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);
- // Maybe: PlacesUtils.bookmarks.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 PUIU_getLeftPaneQueryNameFromId(aItemId) {
- var queryName = "";
- // If the let pane hasn't been built, use the annotation service
- // directly, to avoid building the left pane too early.
- if (Object.getOwnPropertyDescriptor(this, "leftPaneFolderId").value === undefined) {
- try {
- queryName = PlacesUtils.annotations.
- getItemAnnotation(aItemId, this.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;
- },
-
- /**
- * Returns the passed URL with a #moz-resolution fragment
- * for the specified dimensions and devicePixelRatio.
- *
- * @param aWindow
- * A window from where we want to get the device
- * pixel Ratio
- *
- * @param aURL
- * The URL where we should add the fragment
- *
- * @param aWidth
- * The target image width
- *
- * @param aHeight
- * The target image height
- *
- * @return The URL with the fragment at the end
- */
- getImageURLForResolution:
- function PUIU_getImageURLForResolution(aWindow, aURL, aWidth, aHeight) {
- return aURL;
- }
-};
-
-XPCOMUtils.defineLazyServiceGetter(PlacesUIUtils, "RDF",
- "@mozilla.org/rdf/rdf-service;1",
- "nsIRDFService");
-
-XPCOMUtils.defineLazyGetter(PlacesUIUtils, "localStore", function() {
- return PlacesUIUtils.RDF.GetDataSource("rdf:local-store");
-});
-
-XPCOMUtils.defineLazyGetter(PlacesUIUtils, "ellipsis", function() {
- return Services.prefs.getComplexValue("intl.ellipsis",
- Ci.nsIPrefLocalizedString).data;
-});
-
-XPCOMUtils.defineLazyServiceGetter(this, "URIFixup",
- "@mozilla.org/docshell/urifixup;1",
- "nsIURIFixup");
-
-XPCOMUtils.defineLazyGetter(this, "bundle", function() {
- const PLACES_STRING_BUNDLE_URI =
- "chrome://browser/locale/places/places.properties";
- return Cc["@mozilla.org/intl/stringbundle;1"].
- getService(Ci.nsIStringBundleService).
- createBundle(PLACES_STRING_BUNDLE_URI);
-});
-
-XPCOMUtils.defineLazyServiceGetter(this, "focusManager",
- "@mozilla.org/focus-manager;1",
- "nsIFocusManager");
-
-/**
- * This is a compatibility shim for old PUIU.ptm users.
- *
- * If you're looking for transactions and writing new code using them, directly
- * use the transactions objects exported by the PlacesUtils.jsm module.
- *
- * This object will be removed once enough users are converted to the new API.
- */
-XPCOMUtils.defineLazyGetter(PlacesUIUtils, "ptm", function() {
- // Ensure PlacesUtils is imported in scope.
- PlacesUtils;
-
- return {
- aggregateTransactions: function(aName, aTransactions)
- new PlacesAggregatedTransaction(aName, aTransactions),
-
- createFolder: function(aName, aContainer, aIndex, aAnnotations,
- aChildItemsTransactions)
- new PlacesCreateFolderTransaction(aName, aContainer, aIndex, aAnnotations,
- aChildItemsTransactions),
-
- createItem: function(aURI, aContainer, aIndex, aTitle, aKeyword,
- aAnnotations, aChildTransactions)
- new PlacesCreateBookmarkTransaction(aURI, aContainer, aIndex, aTitle,
- aKeyword, aAnnotations,
- aChildTransactions),
-
- createSeparator: function(aContainer, aIndex)
- new PlacesCreateSeparatorTransaction(aContainer, aIndex),
-
- createLivemark: function(aFeedURI, aSiteURI, aName, aContainer, aIndex,
- aAnnotations)
- new PlacesCreateLivemarkTransaction(aFeedURI, aSiteURI, aName, aContainer,
- aIndex, aAnnotations),
-
- moveItem: function(aItemId, aNewContainer, aNewIndex)
- new PlacesMoveItemTransaction(aItemId, aNewContainer, aNewIndex),
-
- removeItem: function(aItemId)
- new PlacesRemoveItemTransaction(aItemId),
-
- editItemTitle: function(aItemId, aNewTitle)
- new PlacesEditItemTitleTransaction(aItemId, aNewTitle),
-
- editBookmarkURI: function(aItemId, aNewURI)
- new PlacesEditBookmarkURITransaction(aItemId, aNewURI),
-
- setItemAnnotation: function(aItemId, aAnnotationObject)
- new PlacesSetItemAnnotationTransaction(aItemId, aAnnotationObject),
-
- setPageAnnotation: function(aURI, aAnnotationObject)
- new PlacesSetPageAnnotationTransaction(aURI, aAnnotationObject),
-
- editBookmarkKeyword: function(aItemId, aNewKeyword)
- new PlacesEditBookmarkKeywordTransaction(aItemId, aNewKeyword),
-
- editBookmarkPostData: function(aItemId, aPostData)
- new PlacesEditBookmarkPostDataTransaction(aItemId, aPostData),
-
- editLivemarkSiteURI: function(aLivemarkId, aSiteURI)
- new PlacesEditLivemarkSiteURITransaction(aLivemarkId, aSiteURI),
-
- editLivemarkFeedURI: function(aLivemarkId, aFeedURI)
- new PlacesEditLivemarkFeedURITransaction(aLivemarkId, aFeedURI),
-
- editItemDateAdded: function(aItemId, aNewDateAdded)
- new PlacesEditItemDateAddedTransaction(aItemId, aNewDateAdded),
-
- editItemLastModified: function(aItemId, aNewLastModified)
- new PlacesEditItemLastModifiedTransaction(aItemId, aNewLastModified),
-
- sortFolderByName: function(aFolderId)
- new PlacesSortFolderByNameTransaction(aFolderId),
-
- tagURI: function(aURI, aTags)
- new PlacesTagURITransaction(aURI, aTags),
-
- untagURI: function(aURI, aTags)
- new PlacesUntagURITransaction(aURI, aTags),
-
- /**
- * Transaction for setting/unsetting Load-in-sidebar annotation.
- *
- * @param aBookmarkId
- * id of the bookmark where to set Load-in-sidebar annotation.
- * @param aLoadInSidebar
- * boolean value.
- * @returns nsITransaction object.
- */
- setLoadInSidebar: function(aItemId, aLoadInSidebar)
- {
- let annoObj = { name: PlacesUIUtils.LOAD_IN_SIDEBAR_ANNO,
- type: Ci.nsIAnnotationService.TYPE_INT32,
- flags: 0,
- value: aLoadInSidebar,
- expires: Ci.nsIAnnotationService.EXPIRE_NEVER };
- return new PlacesSetItemAnnotationTransaction(aItemId, annoObj);
- },
-
- /**
- * Transaction for editing the description of a bookmark or a folder.
- *
- * @param aItemId
- * id of the item to edit.
- * @param aDescription
- * new description.
- * @returns nsITransaction object.
- */
- editItemDescription: function(aItemId, aDescription)
- {
- let annoObj = { name: PlacesUIUtils.DESCRIPTION_ANNO,
- type: Ci.nsIAnnotationService.TYPE_STRING,
- flags: 0,
- value: aDescription,
- expires: Ci.nsIAnnotationService.EXPIRE_NEVER };
- return new PlacesSetItemAnnotationTransaction(aItemId, annoObj);
- },
-
- ////////////////////////////////////////////////////////////////////////////
- //// nsITransactionManager forwarders.
-
- beginBatch: function()
- PlacesUtils.transactionManager.beginBatch(null),
-
- endBatch: function()
- PlacesUtils.transactionManager.endBatch(false),
-
- doTransaction: function(txn)
- PlacesUtils.transactionManager.doTransaction(txn),
-
- undoTransaction: function()
- PlacesUtils.transactionManager.undoTransaction(),
-
- redoTransaction: function()
- PlacesUtils.transactionManager.redoTransaction(),
-
- get numberOfUndoItems()
- PlacesUtils.transactionManager.numberOfUndoItems,
- get numberOfRedoItems()
- PlacesUtils.transactionManager.numberOfRedoItems,
- get maxTransactionCount()
- PlacesUtils.transactionManager.maxTransactionCount,
- set maxTransactionCount(val)
- PlacesUtils.transactionManager.maxTransactionCount = val,
-
- clear: function()
- PlacesUtils.transactionManager.clear(),
-
- peekUndoStack: function()
- PlacesUtils.transactionManager.peekUndoStack(),
-
- peekRedoStack: function()
- PlacesUtils.transactionManager.peekRedoStack(),
-
- getUndoStack: function()
- PlacesUtils.transactionManager.getUndoStack(),
-
- getRedoStack: function()
- PlacesUtils.transactionManager.getRedoStack(),
-
- AddListener: function(aListener)
- PlacesUtils.transactionManager.AddListener(aListener),
-
- RemoveListener: function(aListener)
- PlacesUtils.transactionManager.RemoveListener(aListener)
- }
-});
diff --git a/components/places/content/bookmarkProperties.js b/components/places/content/bookmarkProperties.js
deleted file mode 100644
index e1d1077..0000000
--- a/components/places/content/bookmarkProperties.js
+++ /dev/null
@@ -1,675 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/**
- * 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.
- */
-
-Components.utils.import('resource://gre/modules/XPCOMUtils.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
- "resource://gre/modules/PrivateBrowsingUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "Task",
- "resource://gre/modules/Task.jsm");
-
-const BOOKMARK_ITEM = 0;
-const BOOKMARK_FOLDER = 1;
-const LIVEMARK_CONTAINER = 2;
-
-const ACTION_EDIT = 0;
-const ACTION_ADD = 1;
-
-var elementsHeight = new Map();
-
-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);
- 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,
- PlacesUIUtils.LOAD_IN_SIDEBAR_ANNO);
- break;
-
- case "folder":
- this._itemType = BOOKMARK_FOLDER;
- PlacesUtils.livemarks.getLivemark({ id: this._itemId })
- .then(aLivemark => {
- this._itemType = LIVEMARK_CONTAINER;
- this._feedURI = aLivemark.feedURI;
- this._siteURI = aLivemark.siteURI;
- this._fillEditProperties();
-
- let acceptButton = document.documentElement.getButton("accept");
- acceptButton.disabled = !this._inputIsValid();
-
- let newHeight = window.outerHeight +
- this._element("descriptionField").boxObject.height;
- window.resizeTo(window.outerWidth, newHeight);
- }, () => undefined);
-
- break;
- }
-
- // Description
- if (PlacesUtils.annotations
- .itemHasAnnotation(this._itemId, PlacesUIUtils.DESCRIPTION_ANNO)) {
- this._description = PlacesUtils.annotations
- .getItemAnnotation(this._itemId,
- PlacesUIUtils.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: Task.async(function* BPP_onDialogLoad() {
- this._determineItemInfo();
-
- document.title = this._getDialogTitle();
- var acceptButton = document.documentElement.getButton("accept");
- acceptButton.label = this._getAcceptLabel();
-
- // Do not use sizeToContent, otherwise, due to bug 90276, the dialog will
- // grow at every opening.
- // Since elements can be uncollapsed asynchronously, we must observe their
- // mutations and resize the dialog using a cached element size.
- this._height = window.outerHeight;
- this._mutationObserver = new MutationObserver(mutations => {
- for (let mutation of mutations) {
- let target = mutation.target;
- let id = target.id;
- if (!/^editBMPanel_.*(Row|Checkbox)$/.test(id))
- continue;
-
- let collapsed = target.getAttribute("collapsed") === "true";
- let wasCollapsed = mutation.oldValue === "true";
- if (collapsed == wasCollapsed)
- continue;
-
- if (collapsed) {
- this._height -= elementsHeight.get(id);
- elementsHeight.delete(id);
- } else {
- elementsHeight.set(id, target.boxObject.height);
- this._height += elementsHeight.get(id);
- }
- window.resizeTo(window.outerWidth, this._height);
- }
- });
-
- this._mutationObserver.observe(document,
- { subtree: true,
- attributeOldValue: true,
- attributeFilter: ["collapsed"] });
-
- // Some controls are flexible and we want to update their cached size when
- // the dialog is resized.
- window.addEventListener("resize", this);
-
- this._beginBatch();
-
- switch (this._action) {
- case ACTION_EDIT:
- this._fillEditProperties();
- acceptButton.disabled = this._readOnly;
- break;
- case ACTION_ADD:
- yield this._fillAddProperties();
- // if this is an uri related dialog disable accept button until
- // the user fills an uri value.
- if (this._itemType == BOOKMARK_ITEM)
- acceptButton.disabled = !this._inputIsValid();
- break;
- }
-
- 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);
- }
- }
-
- // Ensure the Name Picker textbox is focused on load
- var namePickerElem = document.getElementById('editBMPanel_namePicker');
- namePickerElem.focus();
- namePickerElem.select();
- }),
-
- // nsIDOMEventListener
- 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 "resize":
- for (let [id, oldHeight] of elementsHeight) {
- let newHeight = document.getElementById(id).boxObject.height;
- this._height += - oldHeight + newHeight;
- elementsHeight.set(id, newHeight);
- }
- break;
- }
- },
-
- _beginBatch: function BPP__beginBatch() {
- if (this._batching)
- return;
-
- PlacesUtils.transactionManager.beginBatch(null);
- this._batching = true;
- },
-
- _endBatch: function BPP__endBatch() {
- if (!this._batching)
- return;
-
- PlacesUtils.transactionManager.endBatch(false);
- this._batching = false;
- },
-
- _fillEditProperties: function BPP__fillEditProperties() {
- gEditItemOverlay.initPanel(this._itemId,
- { hiddenRows: this._hiddenRows,
- forceReadOnly: this._readOnly });
- },
-
- _fillAddProperties: Task.async(function* BPP__fillAddProperties() {
- yield 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.
- this._mutationObserver.disconnect();
- delete this._mutationObserver;
-
- window.removeEventListener("resize", this);
-
- // Calling removeEventListener with arguments which do not identify any
- // currently registered EventListener on the EventTarget has no effect.
- 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);
- 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);
- this._endBatch();
- PlacesUtils.transactionManager.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;
-
- 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) {
- 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) {
- let annoObj = { name : PlacesUIUtils.DESCRIPTION_ANNO,
- type : Ci.nsIAnnotationService.TYPE_STRING,
- flags : 0,
- value : this._description,
- expires: Ci.nsIAnnotationService.EXPIRE_NEVER };
- let editItemTxn = new PlacesSetItemAnnotationTransaction(-1, annoObj);
- childTransactions.push(editItemTxn);
- }
-
- if (this._loadInSidebar) {
- let annoObj = { name : PlacesUIUtils.LOAD_IN_SIDEBAR_ANNO,
- value : true };
- let setLoadTxn = new PlacesSetItemAnnotationTransaction(-1, annoObj);
- childTransactions.push(setLoadTxn);
- }
-
- if (this._postData) {
- let postDataTxn = new PlacesEditBookmarkPostDataTransaction(-1, this._postData);
- childTransactions.push(postDataTxn);
- }
-
- //XXX TODO: this should be in a transaction!
- if (this._charSet && !PrivateBrowsingUtils.isWindowPrivate(window))
- PlacesUtils.setCharsetForURI(this._uri, this._charSet);
-
- let createTxn = new PlacesCreateBookmarkTransaction(this._uri,
- aContainer,
- aIndex,
- this._title,
- this._keyword,
- annotations,
- childTransactions);
-
- return new PlacesAggregatedTransaction(this._getDialogTitle(),
- [createTxn]);
- },
-
- /**
- * 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);
- var createTxn = new PlacesCreateBookmarkTransaction(uri, -1,
- PlacesUtils.bookmarks.DEFAULT_INDEX,
- title);
- transactions.push(createTxn);
- }
- 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 new PlacesCreateFolderTransaction(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 new PlacesCreateLivemarkTransaction(this._feedURI, this._siteURI,
- this._title,
- aContainer, aIndex);
- },
-
- /**
- * Dialog-accept code-path for creating a new item (any type)
- */
- _createNewItem: Task.async(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);
- }
-
- PlacesUtils.transactionManager.doTransaction(txn);
- // This is a temporary hack until we use PlacesTransactions.jsm
- if (txn._promise) {
- yield txn._promise;
- }
-
- let folderGuid = yield PlacesUtils.promiseItemGuid(container);
- let bm = yield PlacesUtils.bookmarks.fetch({
- parentGuid: folderGuid,
- index: index
- });
- this._itemId = yield PlacesUtils.promiseItemId(bm.guid);
- })
-};
diff --git a/components/places/content/bookmarkProperties.xul b/components/places/content/bookmarkProperties.xul
deleted file mode 100644
index 2c04f8b..0000000
--- a/components/places/content/bookmarkProperties.xul
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0"?>
-
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<?xml-stylesheet href="chrome://global/skin/"?>
-<?xml-stylesheet href="chrome://browser/skin/places/editBookmarkOverlay.css"?>
-<?xml-stylesheet href="chrome://browser/skin/places/places.css"?>
-<?xml-stylesheet href="chrome://browser/content/places/places.css"?>
-
-<?xul-overlay href="chrome://browser/content/places/placesOverlay.xul"?>
-<?xul-overlay href="chrome://browser/content/places/editBookmarkOverlay.xul"?>
-
-<!DOCTYPE dialog [
- <!ENTITY % editBookmarkOverlayDTD SYSTEM "chrome://browser/locale/places/editBookmarkOverlay.dtd">
- %editBookmarkOverlayDTD;
-]>
-
-<dialog id="bookmarkproperties"
- buttons="accept, cancel"
- buttoniconaccept="save"
- ondialogaccept="BookmarkPropertiesPanel.onDialogAccept();"
- ondialogcancel="BookmarkPropertiesPanel.onDialogCancel();"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- onload="BookmarkPropertiesPanel.onDialogLoad();"
- onunload="BookmarkPropertiesPanel.onDialogUnload();"
- style="min-width: 30em;"
- persist="screenX screenY width">
-
- <stringbundleset id="stringbundleset">
- <stringbundle id="stringBundle"
- src="chrome://browser/locale/places/bookmarkProperties.properties"/>
- </stringbundleset>
-
- <script type="application/javascript"
- src="chrome://browser/content/places/editBookmarkOverlay.js"/>
- <script type="application/javascript"
- src="chrome://browser/content/places/bookmarkProperties.js"/>
-
-<vbox id="editBookmarkPanelContent"/>
-
-</dialog>
diff --git a/components/places/content/bookmarksPanel.js b/components/places/content/bookmarksPanel.js
deleted file mode 100644
index c964bd0..0000000
--- a/components/places/content/bookmarksPanel.js
+++ /dev/null
@@ -1,25 +0,0 @@
-/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-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);
diff --git a/components/places/content/bookmarksPanel.xul b/components/places/content/bookmarksPanel.xul
deleted file mode 100644
index 45744bb..0000000
--- a/components/places/content/bookmarksPanel.xul
+++ /dev/null
@@ -1,55 +0,0 @@
-<?xml version="1.0"?> <!-- -*- Mode: SGML; indent-tabs-mode: nil; -*- -->
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
-<?xml-stylesheet href="chrome://browser/content/places/places.css"?>
-<?xml-stylesheet href="chrome://browser/skin/places/places.css"?>
-<?xul-overlay href="chrome://global/content/editMenuOverlay.xul"?>
-<?xul-overlay href="chrome://browser/content/places/placesOverlay.xul"?>
-
-<!DOCTYPE page SYSTEM "chrome://browser/locale/places/places.dtd">
-
-<page id="bookmarksPanel"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- onload="init();"
- onunload="SidebarUtils.setMouseoverURL('');">
-
- <script type="application/javascript"
- src="chrome://browser/content/bookmarks/sidebarUtils.js"/>
- <script type="application/javascript"
- src="chrome://browser/content/bookmarks/bookmarksPanel.js"/>
-
- <commandset id="placesCommands"/>
- <commandset id="editMenuCommands"/>
- <keyset id="placesCommandKeys"/>
- <menupopup id="placesContext"/>
-
- <!-- Bookmarks and history tooltip -->
- <tooltip id="bhTooltip"/>
-
- <hbox id="sidebar-search-container" align="center">
- <label id="sidebar-search-label"
- value="&search.label;" accesskey="&search.accesskey;" control="search-box"/>
- <textbox id="search-box" flex="1" type="search" class="compact"
- aria-controls="bookmarks-view"
- oncommand="searchBookmarks(this.value);"/>
- </hbox>
-
- <tree id="bookmarks-view" class="sidebar-placesTree" type="places"
- flex="1"
- hidecolumnpicker="true"
- context="placesContext"
- onkeypress="SidebarUtils.handleTreeKeyPress(event);"
- onclick="SidebarUtils.handleTreeClick(this, event, true);"
- onmousemove="SidebarUtils.handleTreeMouseMove(event);"
- onmouseout="SidebarUtils.setMouseoverURL('');">
- <treecols>
- <treecol id="title" flex="1" primary="true" hideheader="true"/>
- </treecols>
- <treechildren id="bookmarks-view-children" view="bookmarks-view"
- class="sidebar-placesTreechildren" flex="1" tooltip="bhTooltip"/>
- </tree>
-</page>
diff --git a/components/places/content/browserPlacesViews.js b/components/places/content/browserPlacesViews.js
deleted file mode 100644
index 8b90dd2..0000000
--- a/components/places/content/browserPlacesViews.js
+++ /dev/null
@@ -1,1754 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
-Components.utils.import("resource://gre/modules/Services.jsm");
-
-/**
- * The base view implements everything that's common to the toolbar and
- * menu views.
- */
-function PlacesViewBase(aPlace) {
- this.place = aPlace;
- this._controller = new PlacesController(this);
- this._viewElt.controllers.appendController(this._controller);
-}
-
-PlacesViewBase.prototype = {
- // The xul element that holds the entire view.
- _viewElt: null,
- get viewElt() this._viewElt,
-
- get associatedElement() this._viewElt,
-
- get controllers() this._viewElt.controllers,
-
- // The xul element that represents the root container.
- _rootElt: null,
-
- // Set to true for views that are represented by native widgets (i.e.
- // the native mac menu).
- _nativeView: false,
-
- QueryInterface: XPCOMUtils.generateQI(
- [Components.interfaces.nsINavHistoryResultObserver,
- Components.interfaces.nsISupportsWeakReference]),
-
- _place: "",
- get place() this._place,
- set place(val) {
- this._place = val;
-
- let history = PlacesUtils.history;
- let queries = { }, options = { };
- history.queryStringToQueries(val, queries, { }, options);
- if (!queries.value.length)
- queries.value = [history.getNewQuery()];
-
- let result = history.executeQueries(queries.value, queries.value.length,
- options.value);
- result.addObserver(this, false);
- return val;
- },
-
- _result: null,
- get result() this._result,
- set result(val) {
- if (this._result == val)
- return val;
-
- if (this._result) {
- this._result.removeObserver(this);
- this._resultNode.containerOpen = false;
- }
-
- if (this._rootElt.localName == "menupopup")
- this._rootElt._built = false;
-
- this._result = val;
- if (val) {
- this._resultNode = val.root;
- this._rootElt._placesNode = this._resultNode;
- this._domNodes = new Map();
- this._domNodes.set(this._resultNode, this._rootElt);
-
- // This calls _rebuild through invalidateContainer.
- this._resultNode.containerOpen = true;
- }
- else {
- this._resultNode = null;
- delete this._domNodes;
- }
-
- return val;
- },
-
- /**
- * Gets the DOM node used for the given places node.
- *
- * @param aPlacesNode
- * a places result node.
- * @throws if there is no DOM node set for aPlacesNode.
- */
- _getDOMNodeForPlacesNode:
- function PVB__getDOMNodeForPlacesNode(aPlacesNode) {
- let node = this._domNodes.get(aPlacesNode, null);
- if (!node) {
- throw new Error("No DOM node set for aPlacesNode.\nnode.type: " +
- aPlacesNode.type + ". node.parent: " + aPlacesNode);
- }
- return node;
- },
-
- get controller() this._controller,
-
- get selType() "single",
- selectItems: function() { },
- selectAll: function() { },
-
- get selectedNode() {
- if (this._contextMenuShown) {
- let anchor = this._contextMenuShown.triggerNode;
- if (!anchor)
- return null;
-
- if (anchor._placesNode)
- return this._rootElt == anchor ? null : anchor._placesNode;
-
- anchor = anchor.parentNode;
- return this._rootElt == anchor ? null : (anchor._placesNode || null);
- }
- return null;
- },
-
- get hasSelection() this.selectedNode != null,
-
- get selectedNodes() {
- let selectedNode = this.selectedNode;
- return selectedNode ? [selectedNode] : [];
- },
-
- get removableSelectionRanges() {
- // On static content the current selectedNode would be the selection's
- // parent node. We don't want to allow removing a node when the
- // selection is not explicit.
- if (document.popupNode &&
- (document.popupNode == "menupopup" || !document.popupNode._placesNode))
- return [];
-
- return [this.selectedNodes];
- },
-
- get draggableSelection() [this._draggedElt],
-
- get insertionPoint() {
- // There is no insertion point for history queries, so bail out now and
- // save a lot of work when updating commands.
- let resultNode = this._resultNode;
- if (PlacesUtils.nodeIsQuery(resultNode) &&
- PlacesUtils.asQuery(resultNode).queryOptions.queryType ==
- Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY)
- return null;
-
- // By default, the insertion point is at the top level, at the end.
- let index = PlacesUtils.bookmarks.DEFAULT_INDEX;
- let container = this._resultNode;
- let orientation = Ci.nsITreeView.DROP_BEFORE;
- let isTag = false;
-
- let selectedNode = this.selectedNode;
- if (selectedNode) {
- let popup = document.popupNode;
- if (!popup._placesNode || popup._placesNode == this._resultNode ||
- popup._placesNode.itemId == -1) {
- // If a static menuitem is selected, or if the root node is selected,
- // the insertion point is inside the folder, at the end.
- container = selectedNode;
- orientation = Ci.nsITreeView.DROP_ON;
- }
- else {
- // In all other cases the insertion point is before that node.
- container = selectedNode.parent;
- index = container.getChildIndex(selectedNode);
- isTag = PlacesUtils.nodeIsTagQuery(container);
- }
- }
-
- if (PlacesControllerDragHelper.disallowInsertion(container))
- return null;
-
- return new InsertionPoint(PlacesUtils.getConcreteItemId(container),
- index, orientation, isTag);
- },
-
- buildContextMenu: function PVB_buildContextMenu(aPopup) {
- this._contextMenuShown = aPopup;
- window.updateCommands("places");
- return this.controller.buildContextMenu(aPopup);
- },
-
- destroyContextMenu: function PVB_destroyContextMenu(aPopup) {
- this._contextMenuShown = null;
- },
-
- _cleanPopup: function PVB_cleanPopup(aPopup, aDelay) {
- // Remove Places nodes from the popup.
- let child = aPopup._startMarker;
- while (child.nextSibling != aPopup._endMarker) {
- let sibling = child.nextSibling;
- if (sibling._placesNode && !aDelay) {
- aPopup.removeChild(sibling);
- }
- else if (sibling._placesNode && aDelay) {
- // HACK (bug 733419): the popups originating from the OS X native
- // menubar don't live-update while open, thus we don't clean it
- // until the next popupshowing, to avoid zombie menuitems.
- if (!aPopup._delayedRemovals)
- aPopup._delayedRemovals = [];
- aPopup._delayedRemovals.push(sibling);
- child = child.nextSibling;
- }
- else {
- child = child.nextSibling;
- }
- }
- },
-
- _rebuildPopup: function PVB__rebuildPopup(aPopup) {
- let resultNode = aPopup._placesNode;
- if (!resultNode.containerOpen)
- return;
-
- if (this.controller.hasCachedLivemarkInfo(resultNode)) {
- this._setEmptyPopupStatus(aPopup, false);
- aPopup._built = true;
- this._populateLivemarkPopup(aPopup);
- return;
- }
-
- this._cleanPopup(aPopup);
-
- let cc = resultNode.childCount;
- if (cc > 0) {
- this._setEmptyPopupStatus(aPopup, false);
-
- for (let i = 0; i < cc; ++i) {
- let child = resultNode.getChild(i);
- this._insertNewItemToPopup(child, aPopup, null);
- }
- }
- else {
- this._setEmptyPopupStatus(aPopup, true);
- }
- aPopup._built = true;
- },
-
- _removeChild: function PVB__removeChild(aChild) {
- // If document.popupNode pointed to this child, null it out,
- // otherwise controller's command-updating may rely on the removed
- // item still being "selected".
- if (document.popupNode == aChild)
- document.popupNode = null;
-
- aChild.parentNode.removeChild(aChild);
- },
-
- _setEmptyPopupStatus:
- function PVB__setEmptyPopupStatus(aPopup, aEmpty) {
- if (!aPopup._emptyMenuitem) {
- let label = PlacesUIUtils.getString("bookmarksMenuEmptyFolder");
- aPopup._emptyMenuitem = document.createElement("menuitem");
- aPopup._emptyMenuitem.setAttribute("label", label);
- aPopup._emptyMenuitem.setAttribute("disabled", true);
- }
-
- if (aEmpty) {
- aPopup.setAttribute("emptyplacesresult", "true");
- // Don't add the menuitem if there is static content.
- if (!aPopup._startMarker.previousSibling &&
- !aPopup._endMarker.nextSibling)
- aPopup.insertBefore(aPopup._emptyMenuitem, aPopup._endMarker);
- }
- else {
- aPopup.removeAttribute("emptyplacesresult");
- try {
- aPopup.removeChild(aPopup._emptyMenuitem);
- } catch (ex) {}
- }
- },
-
- _createMenuItemForPlacesNode:
- function PVB__createMenuItemForPlacesNode(aPlacesNode) {
- this._domNodes.delete(aPlacesNode);
-
- let element;
- let type = aPlacesNode.type;
- if (type == Ci.nsINavHistoryResultNode.RESULT_TYPE_SEPARATOR) {
- element = document.createElement("menuseparator");
- }
- else {
- let itemId = aPlacesNode.itemId;
- if (type == Ci.nsINavHistoryResultNode.RESULT_TYPE_URI) {
- element = document.createElement("menuitem");
- element.className = "menuitem-iconic bookmark-item menuitem-with-favicon";
- element.setAttribute("scheme",
- PlacesUIUtils.guessUrlSchemeForUI(aPlacesNode.uri));
- }
- else if (PlacesUtils.containerTypes.indexOf(type) != -1) {
- element = document.createElement("menu");
- element.setAttribute("container", "true");
-
- if (aPlacesNode.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_QUERY) {
- element.setAttribute("query", "true");
- if (PlacesUtils.nodeIsTagQuery(aPlacesNode))
- element.setAttribute("tagContainer", "true");
- else if (PlacesUtils.nodeIsDay(aPlacesNode))
- element.setAttribute("dayContainer", "true");
- else if (PlacesUtils.nodeIsHost(aPlacesNode))
- element.setAttribute("hostContainer", "true");
- }
- else if (itemId != -1) {
- PlacesUtils.livemarks.getLivemark({ id: itemId })
- .then(aLivemark => {
- element.setAttribute("livemark", "true");
-#ifdef XP_MACOSX
- // OS X native menubar doesn't track list-style-images since
- // it doesn't have a frame (bug 733415). Thus enforce updating.
- element.setAttribute("image", "");
- element.removeAttribute("image");
-#endif
- this.controller.cacheLivemarkInfo(aPlacesNode, aLivemark);
- }, () => undefined);
- }
-
- let popup = document.createElement("menupopup");
- popup._placesNode = PlacesUtils.asContainer(aPlacesNode);
-
- if (!this._nativeView) {
- popup.setAttribute("placespopup", "true");
- }
-
-#ifdef XP_MACOSX
- // No context menu on mac.
- popup.setAttribute("context", "placesContext");
-#endif
- element.appendChild(popup);
- element.className = "menu-iconic bookmark-item";
-
- this._domNodes.set(aPlacesNode, popup);
- }
- else
- throw "Unexpected node";
-
- element.setAttribute("label", PlacesUIUtils.getBestTitle(aPlacesNode));
-
- let icon = aPlacesNode.icon;
- if (icon)
- element.setAttribute("image",
- PlacesUIUtils.getImageURLForResolution(window, icon));
- }
-
- element._placesNode = aPlacesNode;
- if (!this._domNodes.has(aPlacesNode))
- this._domNodes.set(aPlacesNode, element);
-
- return element;
- },
-
- _insertNewItemToPopup:
- function PVB__insertNewItemToPopup(aNewChild, aPopup, aBefore) {
- let element = this._createMenuItemForPlacesNode(aNewChild);
- let before = aBefore || aPopup._endMarker;
- aPopup.insertBefore(element, before);
- return element;
- },
-
- _setLivemarkSiteURIMenuItem:
- function PVB__setLivemarkSiteURIMenuItem(aPopup) {
- let livemarkInfo = this.controller.getCachedLivemarkInfo(aPopup._placesNode);
- let siteUrl = livemarkInfo && livemarkInfo.siteURI ?
- livemarkInfo.siteURI.spec : null;
- if (!siteUrl && aPopup._siteURIMenuitem) {
- aPopup.removeChild(aPopup._siteURIMenuitem);
- aPopup._siteURIMenuitem = null;
- aPopup.removeChild(aPopup._siteURIMenuseparator);
- aPopup._siteURIMenuseparator = null;
- }
- else if (siteUrl && !aPopup._siteURIMenuitem) {
- // Add "Open (Feed Name)" menuitem.
- aPopup._siteURIMenuitem = document.createElement("menuitem");
- aPopup._siteURIMenuitem.className = "openlivemarksite-menuitem";
- aPopup._siteURIMenuitem.setAttribute("targetURI", siteUrl);
- aPopup._siteURIMenuitem.setAttribute("oncommand",
- "openUILink(this.getAttribute('targetURI'), 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.
- aPopup._siteURIMenuitem.setAttribute("onclick",
- "checkForMiddleClick(this, event); event.stopPropagation();");
- let label =
- PlacesUIUtils.getFormattedString("menuOpenLivemarkOrigin.label",
- [aPopup.parentNode.getAttribute("label")])
- aPopup._siteURIMenuitem.setAttribute("label", label);
- aPopup.insertBefore(aPopup._siteURIMenuitem, aPopup._startMarker);
-
- aPopup._siteURIMenuseparator = document.createElement("menuseparator");
- aPopup.insertBefore(aPopup._siteURIMenuseparator, aPopup._startMarker);
- }
- },
-
- /**
- * Add, update or remove the livemark status menuitem.
- * @param aPopup
- * The livemark container popup
- * @param aStatus
- * The livemark status
- */
- _setLivemarkStatusMenuItem:
- function PVB_setLivemarkStatusMenuItem(aPopup, aStatus) {
- let statusMenuitem = aPopup._statusMenuitem;
- if (!statusMenuitem) {
- // Create the status menuitem and cache it in the popup object.
- statusMenuitem = document.createElement("menuitem");
- statusMenuitem.className = "livemarkstatus-menuitem";
- statusMenuitem.setAttribute("disabled", true);
- aPopup._statusMenuitem = statusMenuitem;
- }
-
- if (aStatus == Ci.mozILivemark.STATUS_LOADING ||
- aStatus == Ci.mozILivemark.STATUS_FAILED) {
- // Status has changed, update the cached status menuitem.
- let stringId = aStatus == Ci.mozILivemark.STATUS_LOADING ?
- "bookmarksLivemarkLoading" : "bookmarksLivemarkFailed";
- statusMenuitem.setAttribute("label", PlacesUIUtils.getString(stringId));
- if (aPopup._startMarker.nextSibling != statusMenuitem)
- aPopup.insertBefore(statusMenuitem, aPopup._startMarker.nextSibling);
- }
- else {
- // The livemark has finished loading.
- if (aPopup._statusMenuitem.parentNode == aPopup)
- aPopup.removeChild(aPopup._statusMenuitem);
- }
- },
-
- toggleCutNode: function PVB_toggleCutNode(aPlacesNode, aValue) {
- let elt = this._getDOMNodeForPlacesNode(aPlacesNode);
-
- // We may get the popup for menus, but we need the menu itself.
- if (elt.localName == "menupopup")
- elt = elt.parentNode;
- if (aValue)
- elt.setAttribute("cutting", "true");
- else
- elt.removeAttribute("cutting");
- },
-
- nodeURIChanged: function PVB_nodeURIChanged(aPlacesNode, aURIString) {
- let elt = this._getDOMNodeForPlacesNode(aPlacesNode);
-
- // Here we need the <menu>.
- if (elt.localName == "menupopup")
- elt = elt.parentNode;
-
- elt.setAttribute("scheme", PlacesUIUtils.guessUrlSchemeForUI(aURIString));
- },
-
- nodeIconChanged: function PVB_nodeIconChanged(aPlacesNode) {
- let elt = this._getDOMNodeForPlacesNode(aPlacesNode);
-
- // There's no UI representation for the root node, thus there's nothing to
- // be done when the icon changes.
- if (elt == this._rootElt)
- return;
-
- // Here we need the <menu>.
- if (elt.localName == "menupopup")
- elt = elt.parentNode;
-
- let icon = aPlacesNode.icon;
- if (!icon)
- elt.removeAttribute("image");
- else if (icon != elt.getAttribute("image"))
- elt.setAttribute("image",
- PlacesUIUtils.getImageURLForResolution(window, icon));
- },
-
- nodeAnnotationChanged:
- function PVB_nodeAnnotationChanged(aPlacesNode, aAnno) {
- let elt = this._getDOMNodeForPlacesNode(aPlacesNode);
-
- // All livemarks have a feedURI, so use it as our indicator of a livemark
- // being modified.
- if (aAnno == PlacesUtils.LMANNO_FEEDURI) {
- let menu = elt.parentNode;
- if (!menu.hasAttribute("livemark")) {
- menu.setAttribute("livemark", "true");
-#ifdef XP_MACOSX
- // OS X native menubar doesn't track list-style-images since
- // it doesn't have a frame (bug 733415). Thus enforce updating.
- menu.setAttribute("image", "");
- menu.removeAttribute("image");
-#endif
- }
-
- PlacesUtils.livemarks.getLivemark({ id: aPlacesNode.itemId })
- .then(aLivemark => {
- // Controller will use this to build the meta data for the node.
- this.controller.cacheLivemarkInfo(aPlacesNode, aLivemark);
- this.invalidateContainer(aPlacesNode);
- }, () => undefined);
- }
- },
-
- nodeTitleChanged:
- function PVB_nodeTitleChanged(aPlacesNode, aNewTitle) {
- let elt = this._getDOMNodeForPlacesNode(aPlacesNode);
-
- // There's no UI representation for the root node, thus there's
- // nothing to be done when the title changes.
- if (elt == this._rootElt)
- return;
-
- // Here we need the <menu>.
- if (elt.localName == "menupopup")
- elt = elt.parentNode;
-
- if (!aNewTitle && elt.localName != "toolbarbutton") {
- // Many users consider toolbars as shortcuts containers, so explicitly
- // allow empty labels on toolbarbuttons. For any other element try to be
- // smarter, guessing a title from the uri.
- elt.setAttribute("label", PlacesUIUtils.getBestTitle(aPlacesNode));
- }
- else {
- elt.setAttribute("label", aNewTitle);
- }
- },
-
- nodeRemoved:
- function PVB_nodeRemoved(aParentPlacesNode, aPlacesNode, aIndex) {
- let parentElt = this._getDOMNodeForPlacesNode(aParentPlacesNode);
- let elt = this._getDOMNodeForPlacesNode(aPlacesNode);
-
- // Here we need the <menu>.
- if (elt.localName == "menupopup")
- elt = elt.parentNode;
-
- if (parentElt._built) {
- parentElt.removeChild(elt);
-
- // Figure out if we need to show the "<Empty>" menu-item.
- // TODO Bug 517701: This doesn't seem to handle the case of an empty
- // root.
- if (parentElt._startMarker.nextSibling == parentElt._endMarker)
- this._setEmptyPopupStatus(parentElt, true);
- }
- },
-
- nodeHistoryDetailsChanged:
- function PVB_nodeHistoryDetailsChanged(aPlacesNode, aTime, aCount) {
- if (aPlacesNode.parent &&
- this.controller.hasCachedLivemarkInfo(aPlacesNode.parent)) {
- // Find the node in the parent.
- let popup = this._getDOMNodeForPlacesNode(aPlacesNode.parent);
- for (let child = popup._startMarker.nextSibling;
- child != popup._endMarker;
- child = child.nextSibling) {
- if (child._placesNode && child._placesNode.uri == aPlacesNode.uri) {
- if (aCount)
- child.setAttribute("visited", "true");
- else
- child.removeAttribute("visited");
- break;
- }
- }
- }
- },
-
- nodeTagsChanged: function() { },
- nodeDateAddedChanged: function() { },
- nodeLastModifiedChanged: function() { },
- nodeKeywordChanged: function() { },
- sortingChanged: function() { },
- batching: function() { },
-
- nodeInserted:
- function PVB_nodeInserted(aParentPlacesNode, aPlacesNode, aIndex) {
- let parentElt = this._getDOMNodeForPlacesNode(aParentPlacesNode);
- if (!parentElt._built)
- return;
-
- let index = Array.indexOf(parentElt.childNodes, parentElt._startMarker) +
- aIndex + 1;
- this._insertNewItemToPopup(aPlacesNode, parentElt,
- parentElt.childNodes[index]);
- this._setEmptyPopupStatus(parentElt, false);
- },
-
- nodeMoved:
- function PBV_nodeMoved(aPlacesNode,
- aOldParentPlacesNode, aOldIndex,
- aNewParentPlacesNode, 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 old-parent == new-parent.
- let elt = this._getDOMNodeForPlacesNode(aPlacesNode);
-
- // Here we need the <menu>.
- if (elt.localName == "menupopup")
- elt = elt.parentNode;
-
- // If our root node is a folder, it might be moved. There's nothing
- // we need to do in that case.
- if (elt == this._rootElt)
- return;
-
- let parentElt = this._getDOMNodeForPlacesNode(aNewParentPlacesNode);
- if (parentElt._built) {
- // Move the node.
- parentElt.removeChild(elt);
- let index = Array.indexOf(parentElt.childNodes, parentElt._startMarker) +
- aNewIndex + 1;
- parentElt.insertBefore(elt, parentElt.childNodes[index]);
- }
- },
-
- containerStateChanged:
- function PVB_containerStateChanged(aPlacesNode, aOldState, aNewState) {
- if (aNewState == Ci.nsINavHistoryContainerResultNode.STATE_OPENED ||
- aNewState == Ci.nsINavHistoryContainerResultNode.STATE_CLOSED) {
- this.invalidateContainer(aPlacesNode);
-
- if (PlacesUtils.nodeIsFolder(aPlacesNode)) {
- let queryOptions = PlacesUtils.asQuery(this._result.root).queryOptions;
- if (queryOptions.excludeItems) {
- return;
- }
-
- PlacesUtils.livemarks.getLivemark({ id: aPlacesNode.itemId })
- .then(aLivemark => {
- let shouldInvalidate =
- !this.controller.hasCachedLivemarkInfo(aPlacesNode);
- this.controller.cacheLivemarkInfo(aPlacesNode, aLivemark);
- if (aNewState == Ci.nsINavHistoryContainerResultNode.STATE_OPENED) {
- aLivemark.registerForUpdates(aPlacesNode, this);
- // Prioritize the current livemark.
- aLivemark.reload();
- PlacesUtils.livemarks.reloadLivemarks();
- if (shouldInvalidate)
- this.invalidateContainer(aPlacesNode);
- }
- else {
- aLivemark.unregisterForUpdates(aPlacesNode);
- }
- }, () => undefined);
- }
- }
- },
-
- _populateLivemarkPopup: function PVB__populateLivemarkPopup(aPopup)
- {
- this._setLivemarkSiteURIMenuItem(aPopup);
- // Show the loading status only if there are no entries yet.
- if (aPopup._startMarker.nextSibling == aPopup._endMarker)
- this._setLivemarkStatusMenuItem(aPopup, Ci.mozILivemark.STATUS_LOADING);
-
- PlacesUtils.livemarks.getLivemark({ id: aPopup._placesNode.itemId })
- .then(aLivemark => {
- let placesNode = aPopup._placesNode;
- if (!placesNode.containerOpen)
- return;
-
- if (aLivemark.status != Ci.mozILivemark.STATUS_LOADING)
- this._setLivemarkStatusMenuItem(aPopup, aLivemark.status);
- this._cleanPopup(aPopup,
- this._nativeView && aPopup.parentNode.hasAttribute("open"));
-
- let children = aLivemark.getNodesForContainer(placesNode);
- for (let i = 0; i < children.length; i++) {
- let child = children[i];
- this.nodeInserted(placesNode, child, i);
- if (child.accessCount)
- this._getDOMNodeForPlacesNode(child).setAttribute("visited", true);
- else
- this._getDOMNodeForPlacesNode(child).removeAttribute("visited");
- }
- }, Components.utils.reportError);
- },
-
- invalidateContainer: function PVB_invalidateContainer(aPlacesNode) {
- let elt = this._getDOMNodeForPlacesNode(aPlacesNode);
- elt._built = false;
-
- // If the menupopup is open we should live-update it.
- if (elt.parentNode.open)
- this._rebuildPopup(elt);
- },
-
- uninit: function PVB_uninit() {
- if (this._result) {
- this._result.removeObserver(this);
- this._resultNode.containerOpen = false;
- this._resultNode = null;
- this._result = null;
- }
-
- if (this._controller) {
- this._controller.terminate();
- // Removing the controller will fail if it is already no longer there.
- // This can happen if the view element was removed/reinserted without
- // our knowledge. There is no way to check for that having happened
- // without the possibility of an exception. :-(
- try {
- this._viewElt.controllers.removeController(this._controller);
- } catch (ex) {
- } finally {
- this._controller = null;
- }
- }
-
- delete this._viewElt._placesView;
- },
-
- get isRTL() {
- if ("_isRTL" in this)
- return this._isRTL;
-
- return this._isRTL = document.defaultView
- .getComputedStyle(this.viewElt, "")
- .direction == "rtl";
- },
-
- get ownerWindow() window,
-
- /**
- * Adds an "Open All in Tabs" menuitem to the bottom of the popup.
- * @param aPopup
- * a Places popup.
- */
- _mayAddCommandsItems: function PVB__mayAddCommandsItems(aPopup) {
- // The command items are never added to the root popup.
- if (aPopup == this._rootElt)
- return;
-
- let hasMultipleURIs = false;
-
- // Check if the popup contains at least 2 menuitems with places nodes.
- // We don't currently support opening multiple uri nodes when they are not
- // populated by the result.
- if (aPopup._placesNode.childCount > 0) {
- let currentChild = aPopup.firstChild;
- let numURINodes = 0;
- while (currentChild) {
- if (currentChild.localName == "menuitem" && currentChild._placesNode) {
- if (++numURINodes == 2)
- break;
- }
- currentChild = currentChild.nextSibling;
- }
- hasMultipleURIs = numURINodes > 1;
- }
-
- let isLiveMark = false;
- if (this.controller.hasCachedLivemarkInfo(aPopup._placesNode)) {
- hasMultipleURIs = true;
- isLiveMark = true;
- }
-
- if (!hasMultipleURIs) {
- // We don't have to show any option.
- if (aPopup._endOptOpenAllInTabs) {
- aPopup.removeChild(aPopup._endOptOpenAllInTabs);
- aPopup._endOptOpenAllInTabs = null;
-
- aPopup.removeChild(aPopup._endOptSeparator);
- aPopup._endOptSeparator = null;
- }
- }
- else if (!aPopup._endOptOpenAllInTabs) {
- // Create a separator before options.
- aPopup._endOptSeparator = document.createElement("menuseparator");
- aPopup._endOptSeparator.className = "bookmarks-actions-menuseparator";
- aPopup.appendChild(aPopup._endOptSeparator);
-
- // Add the "Open All in Tabs" menuitem.
- aPopup._endOptOpenAllInTabs = document.createElement("menuitem");
- aPopup._endOptOpenAllInTabs.className = "openintabs-menuitem";
- if (isLiveMark) {
- aPopup._endOptOpenAllInTabs.setAttribute("oncommand",
- "PlacesUIUtils.openLiveMarkNodesInTabs(this.parentNode._placesNode, event, " +
- "PlacesUIUtils.getViewForNode(this));");
- } else {
- aPopup._endOptOpenAllInTabs.setAttribute("oncommand",
- "PlacesUIUtils.openContainerNodeInTabs(this.parentNode._placesNode, event, " +
- "PlacesUIUtils.getViewForNode(this));");
- }
- aPopup._endOptOpenAllInTabs.setAttribute("onclick",
- "checkForMiddleClick(this, event); event.stopPropagation();");
- aPopup._endOptOpenAllInTabs.setAttribute("label",
- gNavigatorBundle.getString("menuOpenAllInTabs.label"));
- aPopup.appendChild(aPopup._endOptOpenAllInTabs);
- }
- },
-
- _ensureMarkers: function PVB__ensureMarkers(aPopup) {
- if (aPopup._startMarker)
- return;
-
- // _startMarker is an hidden menuseparator that lives before places nodes.
- aPopup._startMarker = document.createElement("menuseparator");
- aPopup._startMarker.hidden = true;
- aPopup.insertBefore(aPopup._startMarker, aPopup.firstChild);
-
- // _endMarker is an hidden menuseparator that lives after places nodes.
- aPopup._endMarker = document.createElement("menuseparator");
- aPopup._endMarker.hidden = true;
- aPopup.appendChild(aPopup._endMarker);
-
- // Move the markers to the right position.
- let firstNonStaticNodeFound = false;
- for (let i = 0; i < aPopup.childNodes.length; i++) {
- let child = aPopup.childNodes[i];
- // Menus that have static content at the end, but are initially empty,
- // use a special "builder" attribute to figure out where to start
- // inserting places nodes.
- if (child.getAttribute("builder") == "end") {
- aPopup.insertBefore(aPopup._endMarker, child);
- break;
- }
-
- if (child._placesNode && !firstNonStaticNodeFound) {
- firstNonStaticNodeFound = true;
- aPopup.insertBefore(aPopup._startMarker, child);
- }
- }
- if (!firstNonStaticNodeFound) {
- aPopup.insertBefore(aPopup._startMarker, aPopup._endMarker);
- }
- },
-
- _onPopupShowing: function PVB__onPopupShowing(aEvent) {
- // Avoid handling popupshowing of inner views.
- let popup = aEvent.originalTarget;
-
- this._ensureMarkers(popup);
-
- // Remove any delayed element, see _cleanPopup for details.
- if ("_delayedRemovals" in popup) {
- while (popup._delayedRemovals.length > 0) {
- popup.removeChild(popup._delayedRemovals.shift());
- }
- }
-
- if (popup._placesNode && PlacesUIUtils.getViewForNode(popup) == this) {
- if (!popup._placesNode.containerOpen)
- popup._placesNode.containerOpen = true;
- if (!popup._built)
- this._rebuildPopup(popup);
-
- this._mayAddCommandsItems(popup);
- }
- },
-
- _addEventListeners:
- function PVB__addEventListeners(aObject, aEventNames, aCapturing) {
- for (let i = 0; i < aEventNames.length; i++) {
- aObject.addEventListener(aEventNames[i], this, aCapturing);
- }
- },
-
- _removeEventListeners:
- function PVB__removeEventListeners(aObject, aEventNames, aCapturing) {
- for (let i = 0; i < aEventNames.length; i++) {
- aObject.removeEventListener(aEventNames[i], this, aCapturing);
- }
- },
-};
-
-function PlacesToolbar(aPlace) {
- let startTime = Date.now();
- // Add some smart getters for our elements.
- let thisView = this;
- [
- ["_viewElt", "PlacesToolbar"],
- ["_rootElt", "PlacesToolbarItems"],
- ["_dropIndicator", "PlacesToolbarDropIndicator"],
- ["_chevron", "PlacesChevron"],
- ["_chevronPopup", "PlacesChevronPopup"]
- ].forEach(function (elementGlobal) {
- let [name, id] = elementGlobal;
- thisView.__defineGetter__(name, function () {
- let element = document.getElementById(id);
- if (!element)
- return null;
-
- delete thisView[name];
- return thisView[name] = element;
- });
- });
-
- this._viewElt._placesView = this;
-
- this._addEventListeners(this._viewElt, this._cbEvents, false);
- this._addEventListeners(this._rootElt, ["popupshowing", "popuphidden"], true);
- this._addEventListeners(this._rootElt, ["overflow", "underflow"], true);
- this._addEventListeners(window, ["resize", "unload"], false);
-
- // If personal-bookmarks has been dragged to the tabs toolbar,
- // we have to track addition and removals of tabs, to properly
- // recalculate the available space for bookmarks.
- // TODO (bug 734730): Use a performant mutation listener when available.
- if (this._viewElt.parentNode.parentNode == document.getElementById("TabsToolbar")) {
- this._addEventListeners(gBrowser.tabContainer, ["TabOpen", "TabClose"], false);
- }
-
- PlacesViewBase.call(this, aPlace);
-}
-
-PlacesToolbar.prototype = {
- __proto__: PlacesViewBase.prototype,
-
- _cbEvents: ["dragstart", "dragover", "dragexit", "dragend", "drop",
- "mousemove", "mouseover", "mouseout"],
-
- QueryInterface: function PT_QueryInterface(aIID) {
- if (aIID.equals(Ci.nsIDOMEventListener) ||
- aIID.equals(Ci.nsITimerCallback))
- return this;
-
- return PlacesViewBase.prototype.QueryInterface.apply(this, arguments);
- },
-
- uninit: function PT_uninit() {
- this._removeEventListeners(this._viewElt, this._cbEvents, false);
- this._removeEventListeners(this._rootElt, ["popupshowing", "popuphidden"],
- true);
- this._removeEventListeners(this._rootElt, ["overflow", "underflow"], true);
- this._removeEventListeners(window, ["resize", "unload"], false);
- this._removeEventListeners(gBrowser.tabContainer, ["TabOpen", "TabClose"], false);
-
- PlacesViewBase.prototype.uninit.apply(this, arguments);
- },
-
- _openedMenuButton: null,
- _allowPopupShowing: true,
-
- _rebuild: function PT__rebuild() {
- // Clear out references to existing nodes, since they will be removed
- // and re-added.
- if (this._overFolder.elt)
- this._clearOverFolder();
-
- this._openedMenuButton = null;
- while (this._rootElt.hasChildNodes()) {
- this._rootElt.removeChild(this._rootElt.firstChild);
- }
-
- let cc = this._resultNode.childCount;
- for (let i = 0; i < cc; ++i) {
- this._insertNewItem(this._resultNode.getChild(i), null);
- }
-
- if (this._chevronPopup.hasAttribute("type")) {
- // Chevron has already been initialized, but since we are forcing
- // a rebuild of the toolbar, it has to be rebuilt.
- // Otherwise, it will be initialized when the toolbar overflows.
- this._chevronPopup.place = this.place;
- }
- },
-
- _insertNewItem:
- function PT__insertNewItem(aChild, aBefore) {
- this._domNodes.delete(aChild);
-
- let type = aChild.type;
- let button;
- if (type == Ci.nsINavHistoryResultNode.RESULT_TYPE_SEPARATOR) {
- button = document.createElement("toolbarseparator");
- }
- else {
- button = document.createElement("toolbarbutton");
- button.className = "bookmark-item";
- button.setAttribute("label", aChild.title || "");
- let icon = aChild.icon;
- if (icon)
- button.setAttribute("image",
- PlacesUIUtils.getImageURLForResolution(window, icon));
-
- if (PlacesUtils.containerTypes.indexOf(type) != -1) {
- button.setAttribute("type", "menu");
- button.setAttribute("container", "true");
-
- if (PlacesUtils.nodeIsQuery(aChild)) {
- button.setAttribute("query", "true");
- if (PlacesUtils.nodeIsTagQuery(aChild))
- button.setAttribute("tagContainer", "true");
- }
- else if (PlacesUtils.nodeIsFolder(aChild)) {
- PlacesUtils.livemarks.getLivemark({ id: aChild.itemId })
- .then(aLivemark => {
- button.setAttribute("livemark", "true");
- this.controller.cacheLivemarkInfo(aChild, aLivemark);
- }, () => undefined);
- }
-
- let popup = document.createElement("menupopup");
- popup.setAttribute("placespopup", "true");
- button.appendChild(popup);
- popup._placesNode = PlacesUtils.asContainer(aChild);
-#ifndef XP_MACOSX
- popup.setAttribute("context", "placesContext");
-#endif
-
- this._domNodes.set(aChild, popup);
- }
- else if (PlacesUtils.nodeIsURI(aChild)) {
- button.setAttribute("scheme",
- PlacesUIUtils.guessUrlSchemeForUI(aChild.uri));
- }
- }
-
- button._placesNode = aChild;
- if (!this._domNodes.has(aChild))
- this._domNodes.set(aChild, button);
-
- if (aBefore)
- this._rootElt.insertBefore(button, aBefore);
- else
- this._rootElt.appendChild(button);
- },
-
- _updateChevronPopupNodesVisibility:
- function PT__updateChevronPopupNodesVisibility() {
- for (let i = 0, node = this._chevronPopup._startMarker.nextSibling;
- node != this._chevronPopup._endMarker;
- i++, node = node.nextSibling) {
- node.hidden = this._rootElt.childNodes[i].style.visibility != "hidden";
- }
- },
-
- _onChevronPopupShowing:
- function PT__onChevronPopupShowing(aEvent) {
- // Handle popupshowing only for the chevron popup, not for nested ones.
- if (aEvent.target != this._chevronPopup)
- return;
-
- if (!this._chevron._placesView)
- this._chevron._placesView = new PlacesMenu(aEvent, this.place);
-
- this._updateChevronPopupNodesVisibility();
- },
-
- handleEvent: function PT_handleEvent(aEvent) {
- switch (aEvent.type) {
- case "unload":
- this.uninit();
- break;
- case "resize":
- // This handler updates nodes visibility in both the toolbar
- // and the chevron popup when a window resize does not change
- // the overflow status of the toolbar.
- this.updateChevron();
- break;
- case "overflow":
- if (aEvent.target != aEvent.currentTarget)
- return;
-
- // Ignore purely vertical overflows.
- if (aEvent.detail == 0)
- return;
-
- // Attach the popup binding to the chevron popup if it has not yet
- // been initialized.
- if (!this._chevronPopup.hasAttribute("type")) {
- this._chevronPopup.setAttribute("place", this.place);
- this._chevronPopup.setAttribute("type", "places");
- }
- this._chevron.collapsed = false;
- this.updateChevron();
- break;
- case "underflow":
- if (aEvent.target != aEvent.currentTarget)
- return;
-
- // Ignore purely vertical underflows.
- if (aEvent.detail == 0)
- return;
-
- this.updateChevron();
- this._chevron.collapsed = true;
- break;
- case "TabOpen":
- case "TabClose":
- this.updateChevron();
- break;
- case "dragstart":
- this._onDragStart(aEvent);
- break;
- case "dragover":
- this._onDragOver(aEvent);
- break;
- case "dragexit":
- this._onDragExit(aEvent);
- break;
- case "dragend":
- this._onDragEnd(aEvent);
- break;
- case "drop":
- this._onDrop(aEvent);
- break;
- case "mouseover":
- this._onMouseOver(aEvent);
- break;
- case "mousemove":
- this._onMouseMove(aEvent);
- break;
- case "mouseout":
- this._onMouseOut(aEvent);
- break;
- case "popupshowing":
- this._onPopupShowing(aEvent);
- break;
- case "popuphidden":
- this._onPopupHidden(aEvent);
- break;
- default:
- throw "Trying to handle unexpected event.";
- }
- },
-
- updateChevron: function PT_updateChevron() {
- // If the chevron is collapsed there's nothing to update.
- if (this._chevron.collapsed)
- return;
-
- // Update the chevron on a timer. This will avoid repeated work when
- // lot of changes happen in a small timeframe.
- if (this._updateChevronTimer)
- this._updateChevronTimer.cancel();
-
- this._updateChevronTimer = this._setTimer(100);
- },
-
- _updateChevronTimerCallback: function PT__updateChevronTimerCallback() {
- let scrollRect = this._rootElt.getBoundingClientRect();
- let childOverflowed = false;
- for (let i = 0; i < this._rootElt.childNodes.length; i++) {
- let child = this._rootElt.childNodes[i];
- // Once a child overflows, all the next ones will.
- if (!childOverflowed) {
- let childRect = child.getBoundingClientRect();
- childOverflowed = this.isRTL ? (childRect.left < scrollRect.left)
- : (childRect.right > 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();
- },
-
- nodeInserted:
- function PT_nodeInserted(aParentPlacesNode, aPlacesNode, aIndex) {
- let parentElt = this._getDOMNodeForPlacesNode(aParentPlacesNode);
- if (parentElt == this._rootElt) {
- let children = this._rootElt.childNodes;
- this._insertNewItem(aPlacesNode,
- aIndex < children.length ? children[aIndex] : null);
- this.updateChevron();
- return;
- }
-
- PlacesViewBase.prototype.nodeInserted.apply(this, arguments);
- },
-
- nodeRemoved:
- function PT_nodeRemoved(aParentPlacesNode, aPlacesNode, aIndex) {
- let parentElt = this._getDOMNodeForPlacesNode(aParentPlacesNode);
- let elt = this._getDOMNodeForPlacesNode(aPlacesNode);
-
- // Here we need the <menu>.
- if (elt.localName == "menupopup")
- elt = elt.parentNode;
-
- if (parentElt == this._rootElt) {
- this._removeChild(elt);
- this.updateChevron();
- return;
- }
-
- PlacesViewBase.prototype.nodeRemoved.apply(this, arguments);
- },
-
- nodeMoved:
- function PT_nodeMoved(aPlacesNode,
- aOldParentPlacesNode, aOldIndex,
- aNewParentPlacesNode, aNewIndex) {
- let parentElt = this._getDOMNodeForPlacesNode(aNewParentPlacesNode);
- if (parentElt == this._rootElt) {
- // Container is on the toolbar.
-
- // Move the element.
- let elt = this._getDOMNodeForPlacesNode(aPlacesNode);
-
- // Here we need the <menu>.
- if (elt.localName == "menupopup")
- elt = elt.parentNode;
-
- this._removeChild(elt);
- this._rootElt.insertBefore(elt, this._rootElt.childNodes[aNewIndex]);
-
- // The chevron view may get nodeMoved after the toolbar. In such a case,
- // we should ensure (by manually swapping menuitems) that the actual nodes
- // are in the final position before updateChevron tries to updates their
- // visibility, or the chevron may go out of sync.
- // Luckily updateChevron runs on a timer, so, by the time it updates
- // nodes, the menu has already handled the notification.
-
- this.updateChevron();
- return;
- }
-
- PlacesViewBase.prototype.nodeMoved.apply(this, arguments);
- },
-
- nodeAnnotationChanged:
- function PT_nodeAnnotationChanged(aPlacesNode, aAnno) {
- let elt = this._getDOMNodeForPlacesNode(aPlacesNode);
- if (elt == this._rootElt)
- return;
-
- // We're notified for the menupopup, not the containing toolbarbutton.
- if (elt.localName == "menupopup")
- elt = elt.parentNode;
-
- if (elt.parentNode == this._rootElt) {
- // Node is on the toolbar.
-
- // All livemarks have a feedURI, so use it as our indicator.
- if (aAnno == PlacesUtils.LMANNO_FEEDURI) {
- elt.setAttribute("livemark", true);
-
- PlacesUtils.livemarks.getLivemark({ id: aPlacesNode.itemId })
- .then(aLivemark => {
- this.controller.cacheLivemarkInfo(aPlacesNode, aLivemark);
- this.invalidateContainer(aPlacesNode);
- }, Components.utils.reportError);
- }
- }
- else {
- // Node is in a submenu.
- PlacesViewBase.prototype.nodeAnnotationChanged.apply(this, arguments);
- }
- },
-
- nodeTitleChanged: function PT_nodeTitleChanged(aPlacesNode, aNewTitle) {
- let elt = this._getDOMNodeForPlacesNode(aPlacesNode);
-
- // There's no UI representation for the root node, thus there's
- // nothing to be done when the title changes.
- if (elt == this._rootElt)
- return;
-
- PlacesViewBase.prototype.nodeTitleChanged.apply(this, arguments);
-
- // Here we need the <menu>.
- if (elt.localName == "menupopup")
- elt = elt.parentNode;
-
- if (elt.parentNode == this._rootElt) {
- // Node is on the toolbar
- this.updateChevron();
- }
- },
-
- invalidateContainer: function PT_invalidateContainer(aPlacesNode) {
- let elt = this._getDOMNodeForPlacesNode(aPlacesNode);
- if (elt == this._rootElt) {
- // Container is the toolbar itself.
- this._rebuild();
- return;
- }
-
- PlacesViewBase.prototype.invalidateContainer.apply(this, arguments);
- },
-
- _overFolder: { elt: null,
- openTimer: null,
- hoverTime: 350,
- closeTimer: null },
-
- _clearOverFolder: function PT__clearOverFolder() {
- // The mouse is no longer dragging over the stored menubutton.
- // Close the menubutton, clear out drag styles, and clear all
- // timers for opening/closing it.
- if (this._overFolder.elt && this._overFolder.elt.lastChild) {
- if (!this._overFolder.elt.lastChild.hasAttribute("dragover")) {
- this._overFolder.elt.lastChild.hidePopup();
- }
- this._overFolder.elt.removeAttribute("dragover");
- this._overFolder.elt = null;
- }
- if (this._overFolder.openTimer) {
- this._overFolder.openTimer.cancel();
- this._overFolder.openTimer = null;
- }
- if (this._overFolder.closeTimer) {
- this._overFolder.closeTimer.cancel();
- this._overFolder.closeTimer = null;
- }
- },
-
- /**
- * This function returns information about where to drop when dragging over
- * the toolbar. The returned object has the following properties:
- * - ip: the insertion point for the bookmarks service.
- * - beforeIndex: child index to drop before, for the drop indicator.
- * - folderElt: the folder to drop into, if applicable.
- */
- _getDropPoint: function PT__getDropPoint(aEvent) {
- let result = this.result;
- if (!PlacesUtils.nodeIsFolder(this._resultNode))
- return null;
-
- let dropPoint = { ip: null, beforeIndex: null, folderElt: null };
- let elt = aEvent.target;
- if (elt._placesNode && elt != this._rootElt &&
- elt.localName != "menupopup") {
- let eltRect = elt.getBoundingClientRect();
- let eltIndex = Array.indexOf(this._rootElt.childNodes, elt);
- if (PlacesUtils.nodeIsFolder(elt._placesNode) &&
- !PlacesUIUtils.isContentsReadOnly(elt._placesNode)) {
- // This is a folder.
- // If we are in the middle of it, drop inside it.
- // Otherwise, drop before it, with regards to RTL mode.
- let threshold = eltRect.width * 0.25;
- if (this.isRTL ? (aEvent.clientX > eltRect.right - threshold)
- : (aEvent.clientX < eltRect.left + threshold)) {
- // Drop before this folder.
- dropPoint.ip =
- new InsertionPoint(PlacesUtils.getConcreteItemId(this._resultNode),
- eltIndex, Ci.nsITreeView.DROP_BEFORE);
- dropPoint.beforeIndex = eltIndex;
- }
- else if (this.isRTL ? (aEvent.clientX > eltRect.left + threshold)
- : (aEvent.clientX < eltRect.right - threshold)) {
- // Drop inside this folder.
- dropPoint.ip =
- new InsertionPoint(PlacesUtils.getConcreteItemId(elt._placesNode),
- -1, Ci.nsITreeView.DROP_ON,
- PlacesUtils.nodeIsTagQuery(elt._placesNode));
- dropPoint.beforeIndex = eltIndex;
- dropPoint.folderElt = elt;
- }
- else {
- // Drop after this folder.
- let beforeIndex =
- (eltIndex == this._rootElt.childNodes.length - 1) ?
- -1 : eltIndex + 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 = eltRect.width * 0.5;
- if (this.isRTL ? (aEvent.clientX > eltRect.left + threshold)
- : (aEvent.clientX < eltRect.left + threshold)) {
- // Drop before this bookmark.
- dropPoint.ip =
- new InsertionPoint(PlacesUtils.getConcreteItemId(this._resultNode),
- eltIndex, Ci.nsITreeView.DROP_BEFORE);
- dropPoint.beforeIndex = eltIndex;
- }
- else {
- // Drop after this bookmark.
- let beforeIndex =
- eltIndex == this._rootElt.childNodes.length - 1 ?
- -1 : eltIndex + 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;
- },
-
- _setTimer: function PT_setTimer(aTime) {
- let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
- timer.initWithCallback(this, aTime, timer.TYPE_ONE_SHOT);
- return timer;
- },
-
- notify: function PT_notify(aTimer) {
- if (aTimer == this._updateChevronTimer) {
- this._updateChevronTimer = null;
- this._updateChevronTimerCallback();
- }
-
- // * Timer to turn off indicator bar.
- else if (aTimer == this._ibTimer) {
- this._dropIndicator.collapsed = true;
- this._ibTimer = null;
- }
-
- // * Timer to open a menubutton that's being dragged over.
- else if (aTimer == this._overFolder.openTimer) {
- // Set the autoopen attribute on the folder's menupopup so that
- // the menu will automatically close when the mouse drags off of it.
- this._overFolder.elt.lastChild.setAttribute("autoopened", "true");
- this._overFolder.elt.open = true;
- this._overFolder.openTimer = null;
- }
-
- // * Timer to close a menubutton that's been dragged off of.
- else if (aTimer == this._overFolder.closeTimer) {
- // Close the menubutton if we are not dragging over it or one of
- // its children. The autoopened attribute will let the menu know to
- // close later if the menu is still being dragged over.
- let currentPlacesNode = PlacesControllerDragHelper.currentDropTarget;
- let inHierarchy = false;
- while (currentPlacesNode) {
- if (currentPlacesNode == this._rootElt) {
- inHierarchy = true;
- break;
- }
- currentPlacesNode = currentPlacesNode.parentNode;
- }
- // The _clearOverFolder() function will close the menu for
- // _overFolder.elt. So null it out if we don't want to close it.
- if (inHierarchy)
- this._overFolder.elt = null;
-
- // Clear out the folder and all associated timers.
- this._clearOverFolder();
- }
- },
-
- _onMouseOver: function PT__onMouseOver(aEvent) {
- let button = aEvent.target;
- if (button.parentNode == this._rootElt && button._placesNode &&
- PlacesUtils.nodeIsURI(button._placesNode))
- window.XULBrowserWindow.setOverLink(aEvent.target._placesNode.uri, null);
- },
-
- _onMouseOut: function PT__onMouseOut(aEvent) {
- window.XULBrowserWindow.setOverLink("", null);
- },
-
- _cleanupDragDetails: function PT__cleanupDragDetails() {
- // Called on dragend and drop.
- PlacesControllerDragHelper.currentDropTarget = null;
- this._draggedElt = null;
- if (this._ibTimer)
- this._ibTimer.cancel();
-
- this._dropIndicator.collapsed = true;
- },
-
- _onDragStart: function PT__onDragStart(aEvent) {
- // Sub menus have their own d&d handlers.
- let draggedElt = aEvent.target;
- if (draggedElt.parentNode != this._rootElt || !draggedElt._placesNode)
- return;
-
- if (draggedElt.localName == "toolbarbutton" &&
- draggedElt.getAttribute("type") == "menu") {
- // If the drag gesture on a container is toward down we open instead
- // of dragging.
- let translateY = this._cachedMouseMoveEvent.clientY - aEvent.clientY;
- let translateX = this._cachedMouseMoveEvent.clientX - aEvent.clientX;
- if ((translateY) >= Math.abs(translateX/2)) {
- // Don't start the drag.
- aEvent.preventDefault();
- // Open the menu.
- draggedElt.open = true;
- return;
- }
-
- // If the menu is open, close it.
- if (draggedElt.open) {
- draggedElt.lastChild.hidePopup();
- draggedElt.open = false;
- }
- }
-
- // Activate the view and cache the dragged element.
- this._draggedElt = draggedElt._placesNode;
- this._rootElt.focus();
-
- this._controller.setDataTransfer(aEvent);
- aEvent.stopPropagation();
- },
-
- _onDragOver: function PT__onDragOver(aEvent) {
- // Cache the dataTransfer
- PlacesControllerDragHelper.currentDropTarget = aEvent.target;
- let dt = aEvent.dataTransfer;
-
- let dropPoint = this._getDropPoint(aEvent);
- if (!dropPoint || !dropPoint.ip ||
- !PlacesControllerDragHelper.canDrop(dropPoint.ip, dt)) {
- this._dropIndicator.collapsed = true;
- aEvent.stopPropagation();
- return;
- }
-
- if (this._ibTimer) {
- this._ibTimer.cancel();
- this._ibTimer = null;
- }
-
- if (dropPoint.folderElt || aEvent.originalTarget == this._chevron) {
- // Dropping over a menubutton or chevron button.
- // Set styles and timer to open relative menupopup.
- let overElt = dropPoint.folderElt || this._chevron;
- if (this._overFolder.elt != overElt) {
- this._clearOverFolder();
- this._overFolder.elt = overElt;
- this._overFolder.openTimer = this._setTimer(this._overFolder.hoverTime);
- }
- if (!this._overFolder.elt.hasAttribute("dragover"))
- this._overFolder.elt.setAttribute("dragover", "true");
-
- this._dropIndicator.collapsed = true;
- }
- else {
- // Dragging over a normal toolbarbutton,
- // show indicator bar and move it to the appropriate drop point.
- let ind = this._dropIndicator;
- let halfInd = ind.clientWidth / 2;
- let translateX;
- if (this.isRTL) {
- halfInd = Math.ceil(halfInd);
- translateX = 0 - this._rootElt.getBoundingClientRect().right - halfInd;
- if (this._rootElt.firstChild) {
- if (dropPoint.beforeIndex == -1)
- translateX += this._rootElt.lastChild.getBoundingClientRect().left;
- else {
- translateX += this._rootElt.childNodes[dropPoint.beforeIndex]
- .getBoundingClientRect().right;
- }
- }
- }
- else {
- halfInd = Math.floor(halfInd);
- translateX = 0 - this._rootElt.getBoundingClientRect().left +
- halfInd;
- if (this._rootElt.firstChild) {
- if (dropPoint.beforeIndex == -1)
- translateX += this._rootElt.lastChild.getBoundingClientRect().right;
- else {
- translateX += this._rootElt.childNodes[dropPoint.beforeIndex]
- .getBoundingClientRect().left;
- }
- }
- }
-
- ind.style.transform = "translate(" + Math.round(translateX) + "px)";
- ind.style.MozMarginStart = (-ind.clientWidth) + "px";
- ind.collapsed = false;
-
- // Clear out old folder information.
- this._clearOverFolder();
- }
-
- aEvent.preventDefault();
- aEvent.stopPropagation();
- },
-
- _onDrop: function PT__onDrop(aEvent) {
- PlacesControllerDragHelper.currentDropTarget = aEvent.target;
-
- let dropPoint = this._getDropPoint(aEvent);
- if (dropPoint && dropPoint.ip) {
- PlacesControllerDragHelper.onDrop(dropPoint.ip, aEvent.dataTransfer)
- aEvent.preventDefault();
- }
-
- this._cleanupDragDetails();
- aEvent.stopPropagation();
- },
-
- _onDragExit: function PT__onDragExit(aEvent) {
- PlacesControllerDragHelper.currentDropTarget = null;
-
- // Set timer to turn off indicator bar (if we turn it off
- // here, dragenter might be called immediately after, creating
- // flicker).
- if (this._ibTimer)
- this._ibTimer.cancel();
- this._ibTimer = this._setTimer(10);
-
- // If we hovered over a folder, close it now.
- if (this._overFolder.elt)
- this._overFolder.closeTimer = this._setTimer(this._overFolder.hoverTime);
- },
-
- _onDragEnd: function PT_onDragEnd(aEvent) {
- this._cleanupDragDetails();
- },
-
- _onPopupShowing: function PT__onPopupShowing(aEvent) {
- if (!this._allowPopupShowing) {
- this._allowPopupShowing = true;
- aEvent.preventDefault();
- return;
- }
-
- let parent = aEvent.target.parentNode;
- if (parent.localName == "toolbarbutton")
- this._openedMenuButton = parent;
-
- PlacesViewBase.prototype._onPopupShowing.apply(this, arguments);
- },
-
- _onPopupHidden: function PT__onPopupHidden(aEvent) {
- let popup = aEvent.target;
- let placesNode = popup._placesNode;
- // Avoid handling popuphidden of inner views
- if (placesNode && PlacesUIUtils.getViewForNode(popup) == this) {
- // UI performance: folder queries are cheap, keep the resultnode open
- // so we don't rebuild its contents whenever the popup is reopened.
- // Though, we want to always close feed containers so their expiration
- // status will be checked at next opening.
- if (!PlacesUtils.nodeIsFolder(placesNode) ||
- this.controller.hasCachedLivemarkInfo(placesNode)) {
- placesNode.containerOpen = false;
- }
- }
-
- let parent = popup.parentNode;
- if (parent.localName == "toolbarbutton") {
- this._openedMenuButton = null;
- // Clear the dragover attribute if present, if we are dragging into a
- // folder in the hierachy of current opened popup we don't clear
- // this attribute on clearOverFolder. See Notify for closeTimer.
- if (parent.hasAttribute("dragover"))
- parent.removeAttribute("dragover");
- }
- },
-
- _onMouseMove: function PT__onMouseMove(aEvent) {
- // Used in dragStart to prevent dragging folders when dragging down.
- this._cachedMouseMoveEvent = aEvent;
-
- if (this._openedMenuButton == null ||
- PlacesControllerDragHelper.getSession())
- return;
-
- let target = aEvent.originalTarget;
- if (this._openedMenuButton != target &&
- target.localName == "toolbarbutton" &&
- target.type == "menu") {
- this._openedMenuButton.open = false;
- target.open = true;
- }
- }
-};
-
-/**
- * View for Places menus. This object should be created during the first
- * popupshowing that's dispatched on the menu.
- */
-function PlacesMenu(aPopupShowingEvent, aPlace) {
- this._rootElt = aPopupShowingEvent.target; // <menupopup>
- this._viewElt = this._rootElt.parentNode; // <menu>
- this._viewElt._placesView = this;
- this._addEventListeners(this._rootElt, ["popupshowing", "popuphidden"], true);
- this._addEventListeners(window, ["unload"], false);
-
-#ifdef XP_MACOSX
- // Must walk up to support views in sub-menus, like Bookmarks Toolbar menu.
- for (let elt = this._viewElt.parentNode; elt; elt = elt.parentNode) {
- if (elt.localName == "menubar") {
- this._nativeView = true;
- break;
- }
- }
-#endif
-
- PlacesViewBase.call(this, aPlace);
- this._onPopupShowing(aPopupShowingEvent);
-}
-
-PlacesMenu.prototype = {
- __proto__: PlacesViewBase.prototype,
-
- QueryInterface: function PM_QueryInterface(aIID) {
- if (aIID.equals(Ci.nsIDOMEventListener))
- return this;
-
- return PlacesViewBase.prototype.QueryInterface.apply(this, arguments);
- },
-
- _removeChild: function PM_removeChild(aChild) {
- PlacesViewBase.prototype._removeChild.apply(this, arguments);
- },
-
- uninit: function PM_uninit() {
- this._removeEventListeners(this._rootElt, ["popupshowing", "popuphidden"],
- true);
- this._removeEventListeners(window, ["unload"], false);
-
- PlacesViewBase.prototype.uninit.apply(this, arguments);
- },
-
- handleEvent: function PM_handleEvent(aEvent) {
- switch (aEvent.type) {
- case "unload":
- this.uninit();
- break;
- case "popupshowing":
- this._onPopupShowing(aEvent);
- break;
- case "popuphidden":
- this._onPopupHidden(aEvent);
- break;
- }
- },
-
- _onPopupHidden: function PM__onPopupHidden(aEvent) {
- // Avoid handling popuphidden of inner views.
- let popup = aEvent.originalTarget;
- let placesNode = popup._placesNode;
- if (!placesNode || PlacesUIUtils.getViewForNode(popup) != this)
- return;
-
- // UI performance: folder queries are cheap, keep the resultnode open
- // so we don't rebuild its contents whenever the popup is reopened.
- // Though, we want to always close feed containers so their expiration
- // status will be checked at next opening.
- if (!PlacesUtils.nodeIsFolder(placesNode) ||
- this.controller.hasCachedLivemarkInfo(placesNode))
- placesNode.containerOpen = false;
-
- // The autoopened attribute is set for folders which have been
- // automatically opened when dragged over. Turn off this attribute
- // when the folder closes because it is no longer applicable.
- popup.removeAttribute("autoopened");
- popup.removeAttribute("dragstart");
- }
-};
-
diff --git a/components/places/content/controller.js b/components/places/content/controller.js
deleted file mode 100644
index f4e272e..0000000
--- a/components/places/content/controller.js
+++ /dev/null
@@ -1,1895 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
-Components.utils.import("resource://gre/modules/ForgetAboutSite.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
- "resource://gre/modules/NetUtil.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
- "resource://gre/modules/PrivateBrowsingUtils.jsm");
-
-// XXXmano: we should move most/all of these constants to PlacesUtils
-const ORGANIZER_ROOT_BOOKMARKS = "place:folder=BOOKMARKS_MENU&excludeItems=1&queryType=1";
-
-// 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 give some breath
-// to the main-thread.
-const REMOVE_PAGES_CHUNKLEN = 300;
-
-/**
- * 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;
- XPCOMUtils.defineLazyServiceGetter(this, "clipboard",
- "@mozilla.org/widget/clipboard;1",
- "nsIClipboard");
- XPCOMUtils.defineLazyGetter(this, "profileName", function () {
- return Services.dirsvc.get("ProfD", Ci.nsIFile).leafName;
- });
-
- this._cachedLivemarkInfoObjects = new Map();
-}
-
-PlacesController.prototype = {
- /**
- * The places view.
- */
- _view: null,
-
- QueryInterface: XPCOMUtils.generateQI([
- Ci.nsIClipboardOwner
- ]),
-
- // nsIClipboardOwner
- LosingOwnership: function PC_LosingOwnership (aXferable) {
- this.cutNodes = [];
- },
-
- terminate: function PC_terminate() {
- this._releaseClipboardOwnership();
- },
-
- supportsCommand: function PC_supportsCommand(aCommand) {
- // 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);
- },
-
- isCommandEnabled: function PC_isCommandEnabled(aCommand) {
- switch (aCommand) {
- case "cmd_undo":
- return PlacesUtils.transactionManager.numberOfUndoItems > 0;
- case "cmd_redo":
- return PlacesUtils.transactionManager.numberOfRedoItems > 0;
- case "cmd_cut":
- case "placesCmd_cut":
- case "placesCmd_moveBookmarks":
- for (let node of this._view.selectedNodes) {
- // If selection includes history nodes or tags-as-bookmark, disallow
- // cutting.
- if (node.itemId == -1 ||
- (node.parent && PlacesUtils.nodeIsTagQuery(node.parent))) {
- return false;
- }
- }
- // Otherwise fall through to the cmd_delete check.
- case "cmd_delete":
- case "placesCmd_delete":
- case "placesCmd_deleteDataHost":
- return this._hasRemovableSelection();
- 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") {
- let rootNode = this._view.result.root;
- if (rootNode.containerOpen && rootNode.childCount > 0)
- return true;
- }
- return false;
- case "placesCmd_open":
- case "placesCmd_open:window":
- case "placesCmd_open:privatewindow":
- 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() &&
- !PlacesUtils.asQuery(this._view.result.root).queryOptions.excludeItems &&
- this._view.result.sortingMode ==
- Ci.nsINavHistoryQueryOptions.SORT_BY_NONE;
- case "placesCmd_show:info":
- var selectedNode = this._view.selectedNode;
- return selectedNode && PlacesUtils.getConcreteItemId(selectedNode) != -1
- case "placesCmd_reload":
- // Livemark containers
- var selectedNode = this._view.selectedNode;
- return selectedNode && this.hasCachedLivemarkInfo(selectedNode);
- case "placesCmd_sortBy:name":
- var selectedNode = this._view.selectedNode;
- return selectedNode &&
- PlacesUtils.nodeIsFolder(selectedNode) &&
- !PlacesUIUtils.isContentsReadOnly(selectedNode) &&
- this._view.result.sortingMode ==
- Ci.nsINavHistoryQueryOptions.SORT_BY_NONE;
- case "placesCmd_createBookmark":
- var node = this._view.selectedNode;
- return node && PlacesUtils.nodeIsURI(node) && node.itemId == -1;
- case "placesCmd_openParentFolder":
- return true;
- default:
- return false;
- }
- },
-
- doCommand: function PC_doCommand(aCommand) {
- switch (aCommand) {
- case "cmd_undo":
- PlacesUtils.transactionManager.undoTransaction();
- break;
- case "cmd_redo":
- PlacesUtils.transactionManager.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 = NetUtil.newURI(this._view.selectedNode.uri).host;
- ForgetAboutSite.removeDataFromDomain(host)
- .catch(Components.utils.reportError);
- break;
- case "cmd_selectAll":
- this.selectAll();
- break;
- case "placesCmd_open":
- PlacesUIUtils.openNodeIn(this._view.selectedNode, "current", this._view);
- break;
- case "placesCmd_open:window":
- PlacesUIUtils.openNodeIn(this._view.selectedNode, "window", this._view);
- break;
- case "placesCmd_open:privatewindow":
- PlacesUIUtils.openNodeIn(this._view.selectedNode, "window", this._view, true);
- break;
- case "placesCmd_open:tab":
- PlacesUIUtils.openNodeIn(this._view.selectedNode, "tab", this._view);
- 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_sortBy:name":
- this.sortFolderByName();
- break;
- case "placesCmd_createBookmark":
- let node = this._view.selectedNode;
- PlacesUIUtils.showBookmarkDialog({ action: "add"
- , type: "bookmark"
- , hiddenRows: [ "description"
- , "keyword"
- , "location"
- , "loadInSidebar" ]
- , uri: NetUtil.newURI(node.uri)
- , title: node.title
- }, window.top);
- break;
- case "placesCmd_openParentFolder":
- this.openParentFolder();
- 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.
- * @returns true if all nodes in the selection can be removed,
- * false otherwise.
- */
- _hasRemovableSelection() {
- var ranges = this._view.removableSelectionRanges;
- if (!ranges.length)
- return false;
-
- var root = this._view.result.root;
-
- 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 (!PlacesUIUtils.canUserRemove(nodes[i]))
- 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);
- },
-
- /**
- * 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 = this.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.init(null);
-
- 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 bookmark
- * "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
- * "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!
- */
- _buildSelectionMetadata: function PC__buildSelectionMetadata() {
- var metadata = [];
- var nodes = this._view.selectedNodes;
-
- 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 (PlacesUtils.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_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:
- nodeData["link"] = true;
- uri = NetUtil.newURI(node.uri);
- if (PlacesUtils.nodeIsBookmark(node)) {
- nodeData["bookmark"] = true;
- var parentNode = node.parent;
- if (parentNode) {
- if (PlacesUtils.nodeIsTagQuery(parentNode))
- nodeData["tagChild"] = true;
- }
- } else {
- var parentNode = node.parent;
- if (parentNode) {
- if (this.hasCachedLivemarkInfo(parentNode))
- nodeData["livemarkChild"] = true;
- }
- }
- break;
- }
-
- // annotations
- if (uri) {
- let names = PlacesUtils.annotations.getPageAnnotationNames(uri);
- for (let j = 0; j < names.length; ++j)
- nodeData[names[j]] = true;
- }
-
- // For items also include the item-specific annotations
- if (node.itemId != -1) {
- let names = PlacesUtils.annotations
- .getItemAnnotationNames(node.itemId);
- for (let 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) {
- selectiontype = "single|multiple";
- }
- var selectionTypes = selectiontype.split("|");
- if (selectionTypes.indexOf("any") != -1) {
- return true;
- }
- var count = aMetaData.length;
- if (count > 1 && selectionTypes.indexOf("multiple") == -1)
- return false;
- if (count == 1 && selectionTypes.indexOf("single") == -1)
- return false;
- // NB: if there is no selection, we show the item if (and only if)
- // the selectiontype includes 'none' - the metadata list will be
- // empty so none of the other criteria will apply anyway.
- if (count == 0)
- return selectionTypes.indexOf("none") != -1;
-
- var forceHideAttr = aMenuItem.getAttribute("forcehideselection");
- if (forceHideAttr) {
- var forceHideRules = forceHideAttr.split("|");
- for (let i = 0; i < aMetaData.length; ++i) {
- for (let j = 0; j < forceHideRules.length; ++j) {
- if (forceHideRules[j] in aMetaData[i])
- return false;
- }
- }
- }
-
- var selectionAttr = aMenuItem.getAttribute("selection");
- if (!selectionAttr) {
- return !aMenuItem.hidden;
- }
-
- 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;
- },
-
- /**
- * 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, or to "none" if the menuitems should be
- * visible for if there are no selected nodes, or to a |-separated
- * combination of these.
- * If the attribute is not set or set to an invalid value, the menu-item
- * may be visible irrespective of the 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 usableItemCount = 0;
- 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");
- // Show the "Open Containing Folder" menu-item only when the context is
- // in the Library or in the Sidebar, and only when there's no insertion
- // point.
- var hideParentFolderItem = item.id == "placesContext_openParentFolder" &&
- (!/tree/i.test(this._view.localName) || ip);
- var hideIfPrivate = item.getAttribute("hideifprivatebrowsing") == "true" &&
- PrivateBrowsingUtils.isWindowPrivate(window);
- var shouldHideItem = hideIfNoIP || hideIfPrivate || hideParentFolderItem ||
- !this._shouldShowMenuItem(item, metadata);
- item.hidden = item.disabled = shouldHideItem;
-
- if (!item.hidden) {
- visibleItemsBeforeSep = true;
- usableItemCount++;
-
- // 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 (usableItemCount > 0) {
- var openContainerInTabsItem = document.getElementById("placesContext_openContainer:tabs");
- if (!openContainerInTabsItem.hidden) {
- var containerToUse = this._view.selectedNode || this._view.result.root;
- if (PlacesUtils.nodeIsContainer(containerToUse)) {
- if (!PlacesUtils.hasChildURIs(containerToUse, true)) {
- openContainerInTabsItem.disabled = true;
- // Ensure that we don't display the menu if nothing is enabled:
- usableItemCount--;
- }
- }
- }
- }
-
- return usableItemCount > 0;
- },
-
- /**
- * 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.showBookmarkDialog({ action: "edit"
- , type: itemType
- , itemId: itemId
- , readOnly: isRootItem
- , hiddenRows: [ "folderPicker" ]
- }, window.top);
- },
-
- /**
- * 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) {
- let itemId = selectedNode.itemId;
- PlacesUtils.livemarks.getLivemark({ id: itemId })
- .then(aLivemark => {
- aLivemark.reload(true);
- }, Components.utils.reportError);
- }
- },
-
- /**
- * Opens the links in the selected folder, or the selected links in new tabs.
- */
- openSelectionInTabs: function PC_openLinksInTabs(aEvent) {
- var node = this._view.selectedNode;
- var nodes = this._view.selectedNodes;
- // In the case of no selection, open the root node:
- if (!node && !nodes.length) {
- node = this._view.result.root;
- }
- if (node && PlacesUtils.nodeIsContainer(node))
- PlacesUIUtils.openContainerNodeInTabs(node, aEvent, this._view);
- else
- PlacesUIUtils.openURINodesInTabs(nodes, aEvent, this._view);
- },
-
- /**
- * 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) {
- let ip = this._view.insertionPoint;
- if (!ip)
- throw Cr.NS_ERROR_NOT_AVAILABLE;
-
- let performed =
- PlacesUIUtils.showBookmarkDialog({ action: "add"
- , type: aType
- , defaultInsertionPoint: ip
- , hiddenRows: [ "folderPicker" ]
- }, window.top);
- if (performed) {
- // Select the new item.
- let 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 = new PlacesCreateSeparatorTransaction(ip.itemId, ip.index);
- PlacesUtils.transactionManager.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.selectedNodes);
- },
-
- /**
- * Sort the selected folder by name.
- */
- sortFolderByName: function PC_sortFolderByName() {
- var itemId = PlacesUtils.getConcreteItemId(this._view.selectedNode);
- var txn = new PlacesSortFolderByNameTransaction(itemId);
- PlacesUtils.transactionManager.doTransaction(txn);
- },
-
- /**
- * Open the parent folder for the selected bookmarks search result.
- */
- openParentFolder: function PC_openParentFolder() {
- var view;
- if (!document.popupNode) {
- view = document.commandDispatcher.focusedElement;
- } else {
- view = PlacesUIUtils.getViewForNode(document.popupNode); // XULElement
- }
- if (!view || view.getAttribute("type") != "places")
- return;
- var node = view.selectedNode; // nsINavHistoryResultNode
- var aItemId = node.itemId;
- var aFolderItemId = this.getParentFolderByItemId(aItemId);
- if (aFolderItemId)
- this.selectFolderByItemId(view, aFolderItemId, aItemId);
- },
-
- getParentFolderByItemId: function PC_getParentFolderByItemId(aItemId) {
- var bmsvc = Components.classes["@mozilla.org/browser/nav-bookmarks-service;1"].
- getService(Components.interfaces.nsINavBookmarksService);
- var parentFolderId = bmsvc.getFolderIdForItem(aItemId);
-
- return parentFolderId;
- },
-
- selectItems2: function PC_selectItems2(view, aIDs) {
- var ids = aIDs; // Don't manipulate the caller's array.
-
- // Array of nodes found by findNodes which are to be selected
- var nodes = [];
-
- // Array of nodes found by findNodes which should be opened
- var nodesToOpen = [];
-
- // A set of URIs of container-nodes that were previously searched,
- // and thus shouldn't be searched again. This is empty at the initial
- // start of the recursion and gets filled in as the recursion
- // progresses.
- var nodesURIChecked = [];
-
- /**
- * Recursively search through a node's children for items
- * with the given IDs. When a matching item is found, remove its ID
- * from the IDs array, and add the found node to the nodes dictionary.
- *
- * NOTE: This method will leave open any node that had matching items
- * in its subtree.
- */
- function findNodes(node) {
- var foundOne = false;
- // See if node matches an ID we wanted; add to results.
- // For simple folder queries, check both itemId and the concrete
- // item id.
- var index = ids.indexOf(node.itemId);
- if (index == -1 &&
- node.type == Components.interfaces.nsINavHistoryResultNode.RESULT_TYPE_FOLDER_SHORTCUT) {
- index = ids.indexOf(PlacesUtils.asQuery(node).folderItemId); //xxx Bug 556739 3.7a5pre
- }
-
- if (index != -1) {
- nodes.push(node);
- foundOne = true;
- ids.splice(index, 1);
- }
-
- if (ids.length == 0 || !PlacesUtils.nodeIsContainer(node) ||
- nodesURIChecked.indexOf(node.uri) != -1)
- return foundOne;
-
- nodesURIChecked.push(node.uri);
- PlacesUtils.asContainer(node); // xxx Bug 556739 3.7a6pre
-
- // Remember the beginning state so that we can re-close
- // this node if we don't find any additional results here.
- var previousOpenness = node.containerOpen;
- node.containerOpen = true;
- for (var child = 0; child < node.childCount && ids.length > 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;
- } // findNodes
-
- // Disable notifications while looking for nodes.
- let result = view.result;
- let didSuppressNotifications = result.suppressNotifications;
- if (!didSuppressNotifications)
- result.suppressNotifications = true
- try {
- findNodes(view.result.root);
- }
- finally {
- if (!didSuppressNotifications)
- result.suppressNotifications = false;
- }
-
- // For all the nodes we've found, highlight the corresponding
- // index in the tree.
- var resultview = view.view;
- var selection = resultview.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++) {
- if (PlacesUtils.nodeIsContainer(nodes[i]))
- continue;
-
- var index = resultview.treeIndexForNode(nodes[i]);
- selection.rangedSelect(index, index, true);
- }
- selection.selectEventsSuppressed = false;
- },
-
- selectFolderByItemId: function PC_selectFolderByItemId(view, aFolderItemId, aItemId) {
- // Library
- if (view.getAttribute("id") == "placeContent") {
- view = document.getElementById("placesList");
- // Select a folder node in folder pane.
- this.selectItems2(view, [aFolderItemId]);
- view.selectItems([aFolderItemId]);
- if (view.currentIndex)
- view.treeBoxObject.ensureRowIsVisible(view.currentIndex);
- // Reselect child node.
- setTimeout(function(aItemId, view) {
- var aView = view.ownerDocument.getElementById("placeContent");
- aView.selectItems([aItemId]);
- if (aView.currentIndex)
- aView.treeBoxObject.ensureRowIsVisible(aView.currentIndex);
- }, 0, aItemId, view);
- return;
- }
-
- // Bookmarks Sidebar
- if (!view)
- return;
- view.place = view.place;
-
- if ('FlatBookmarksOverlay' in window) {
- var sidebarwin = view.ownerDocument.defaultView;
- var searchBox = sidebarwin.document.getElementById("search-box");
- searchBox.value = "";
- searchBox.doCommand();
- sidebarwin.FlatBookmarks._setTreePlace(sidebarwin.FlatBookmarks._makePlaceForFolder(aFolderItemId));
- view.selectItems([aItemId]);
- var tbo = view.treeBoxObject;
- tbo.ensureRowIsVisible(view.currentIndex);
- view.focus();
- return;
- }
-
- view.findNode = function flatChildNodes(node, aIDs) {
- var ids = aIDs; // Don't manipulate the caller's array.
-
- // Array of nodes found by findNodes which are to be selected
- var nodes = [];
-
- // Array of nodes found by findNodes which should be opened
- var nodesToOpen = [];
-
- // A set of URIs of container-nodes that were previously searched,
- // and thus shouldn't be searched again. This is empty at the initial
- // start of the recursion and gets filled in as the recursion
- // progresses.
- var nodesURIChecked = [];
-
- /**
- * Recursively search through a node's children for items
- * with the given IDs. When a matching item is found, remove its ID
- * from the IDs array, and add the found node to the nodes dictionary.
- *
- * NOTE: This method will leave open any node that had matching items
- * in its subtree.
- */
- function findNodes(node) {
- var foundOne = false;
- // See if node matches an ID we wanted; add to results.
- // For simple folder queries, check both itemId and the concrete
- // item id.
- var index = ids.indexOf(node.itemId);
- if (index == -1 &&
- node.type == Components.interfaces.nsINavHistoryResultNode.RESULT_TYPE_FOLDER_SHORTCUT) {
- index = ids.indexOf(PlacesUtils.asQuery(node).folderItemId); // xxx Bug 556739 3.7a5pre
- }
-
- if (index != -1) {
- nodes.push(node);
- foundOne = true;
- ids.splice(index, 1);
- }
-
- if (ids.length == 0 || !PlacesUtils.nodeIsContainer(node) ||
- nodesURIChecked.indexOf(node.uri) != -1)
- return foundOne;
-
- nodesURIChecked.push(node.uri);
- PlacesUtils.asContainer(node); // xxx Bug 556739 3.7a6pre
- // Remember the beginning state so that we can re-close
- // this node if we don't find any additional results here.
- var previousOpenness = node.containerOpen;
- node.containerOpen = true;
- for (var child = 0; child < node.childCount && ids.length > 0;
- child++) {
- var childNode = node.getChild(child);
- if (PlacesUtils.nodeIsQuery(childNode))
- continue;
- 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;
- } // findNodes
-
- // Disable notifications while looking for nodes.
- let result = this.result;
- let didSuppressNotifications = result.suppressNotifications;
- if (!didSuppressNotifications)
- result.suppressNotifications = true
- try {
- findNodes(this.result.root);
- }
- finally {
- if (!didSuppressNotifications)
- result.suppressNotifications = false;
- }
-
- // Open nodes containing found items.
- for (var i = 0; i < nodesToOpen.length; i++) {
- nodesToOpen[i].containerOpen = true;
- }
- return nodes;
- }; // findNode
-
- // For all the nodes we've found, highlight the corresponding
- // index in the tree.
- var resultview = view.view;
- var selection = view.view.selection;
- selection.selectEventsSuppressed = true;
- selection.clearSelection();
- var nodes = view.findNode(view.result.root, [aFolderItemId]);
- if (nodes.length > 0) {
- var index = resultview.treeIndexForNode(nodes[0]);
- nodes = view.findNode(nodes[0], [aItemId]);
- if (nodes.length > 0) {
- index = resultview.treeIndexForNode(nodes[0]);
- selection.rangedSelect(index, index, true);
- }
- }
- selection.selectEventsSuppressed = false;
-
- var tbo = view.treeBoxObject;
- tbo.ensureRowIsVisible(view.currentIndex);
- view.focus();
- return;
- },
-
- /**
- * 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 = NetUtil.newURI(node.uri);
- let txn = new PlacesUntagURITransaction(uri, [tagItemId]);
- transactions.push(txn);
- }
- else if (PlacesUtils.nodeIsTagQuery(node) && node.parent &&
- PlacesUtils.nodeIsQuery(node.parent) &&
- PlacesUtils.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++) {
- let txn = new PlacesUntagURITransaction(URIs[j], [tag]);
- transactions.push(txn);
- }
- }
- else if (PlacesUtils.nodeIsURI(node) &&
- PlacesUtils.nodeIsQuery(node.parent) &&
- PlacesUtils.asQuery(node.parent).queryOptions.queryType ==
- Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY) {
- // This is a uri node inside an history query.
- PlacesUtils.bhistory.removePage(NetUtil.newURI(node.uri));
- // History deletes are not undoable, so we don't have a transaction.
- }
- else if (node.itemId == -1 &&
- PlacesUtils.nodeIsQuery(node) &&
- PlacesUtils.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);
- }
- let txn = new PlacesRemoveItemTransaction(node.itemId);
- transactions.push(txn);
- }
- }
- },
-
- /**
- * Removes the set of selected ranges from bookmarks.
- * @param txnName
- * See |remove|.
- */
- _removeRowsFromBookmarks: function PC__removeRowsFromBookmarks(txnName) {
- var ranges = this._view.removableSelectionRanges;
- var transactions = [];
- var removedFolders = [];
-
- for (var i = 0; i < ranges.length; i++)
- this._removeRange(ranges[i], transactions, removedFolders);
-
- if (transactions.length > 0) {
- var txn = new PlacesAggregatedTransaction(txnName, transactions);
- PlacesUtils.transactionManager.doTransaction(txn);
- }
- },
-
- /**
- * Removes the set of selected ranges from history.
- *
- * @note history deletes are not undoable.
- */
- _removeRowsFromHistory: function PC__removeRowsFromHistory() {
- let nodes = this._view.selectedNodes;
- let URIs = [];
- for (let i = 0; i < nodes.length; ++i) {
- let node = nodes[i];
- if (PlacesUtils.nodeIsURI(node)) {
- let uri = NetUtil.newURI(node.uri);
- // Avoid duplicates.
- if (URIs.indexOf(uri) < 0) {
- URIs.push(uri);
- }
- }
- else if (PlacesUtils.nodeIsQuery(node) &&
- PlacesUtils.asQuery(node).queryOptions.queryType ==
- Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY) {
- this._removeHistoryContainer(node);
- }
- }
-
- // Do removal in chunks to give some breath to main-thread.
- function pagesChunkGenerator(aURIs) {
- while (aURIs.length) {
- let URIslice = aURIs.splice(0, REMOVE_PAGES_CHUNKLEN);
- PlacesUtils.bhistory.removePages(URIslice, URIslice.length);
- Services.tm.mainThread.dispatch(function() {
- try {
- gen.next();
- } catch (ex if ex instanceof StopIteration) {}
- }, Ci.nsIThread.DISPATCH_NORMAL);
- yield;
- }
- }
- let gen = pagesChunkGenerator(URIs);
- gen.next();
- },
-
- /**
- * Removes history visits for an history container node.
- * @param [in] aContainerNode
- * The container node to remove.
- *
- * @note history deletes are not undoable.
- */
- _removeHistoryContainer: function PC__removeHistoryContainer(aContainerNode) {
- if (PlacesUtils.nodeIsHost(aContainerNode)) {
- // Site container.
- PlacesUtils.bhistory.removePagesFromHost(aContainerNode.title, true);
- }
- else if (PlacesUtils.nodeIsDay(aContainerNode)) {
- // Day container.
- let query = aContainerNode.getQueries()[0];
- let beginTime = query.beginTime;
- let 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.
- PlacesUtils.bhistory.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())
- return;
-
- NS_ASSERT(aTxnName !== undefined, "Must supply Transaction Name");
-
- var root = this._view.result.root;
-
- if (PlacesUtils.nodeIsFolder(root))
- this._removeRowsFromBookmarks(aTxnName);
- else if (PlacesUtils.nodeIsQuery(root)) {
- var queryType = PlacesUtils.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) {
- let dt = aEvent.dataTransfer;
- let doCopy = ["copyLink", "copy", "link"].indexOf(dt.effectAllowed) != -1;
-
- let result = this._view.result;
- let didSuppressNotifications = result.suppressNotifications;
- if (!didSuppressNotifications)
- result.suppressNotifications = true;
-
- function addData(type, index, feedURI) {
- let wrapNode = PlacesUtils.wrapNode(node, type, feedURI);
- dt.mozSetDataAt(type, wrapNode, index);
- }
-
- function addURIData(index, feedURI) {
- addData(PlacesUtils.TYPE_X_MOZ_URL, index, feedURI);
- addData(PlacesUtils.TYPE_UNICODE, index, feedURI);
- addData(PlacesUtils.TYPE_HTML, index, feedURI);
- }
-
- try {
- let nodes = this._view.draggableSelection;
- for (let i = 0; i < nodes.length; ++i) {
- var node = nodes[i];
-
- // 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
- let livemarkInfo = this.getCachedLivemarkInfo(node);
- if (livemarkInfo) {
- addURIData(i, livemarkInfo.feedURI.spec);
- }
- else if (node.uri) {
- addURIData(i);
- }
- }
- }
- finally {
- if (!didSuppressNotifications)
- result.suppressNotifications = false;
- }
- },
-
- get clipboardAction () {
- let action = {};
- let actionOwner;
- try {
- let xferable = Cc["@mozilla.org/widget/transferable;1"].
- createInstance(Ci.nsITransferable);
- xferable.init(null);
- xferable.addDataFlavor(PlacesUtils.TYPE_X_MOZ_PLACE_ACTION)
- this.clipboard.getData(xferable, Ci.nsIClipboard.kGlobalClipboard);
- xferable.getTransferData(PlacesUtils.TYPE_X_MOZ_PLACE_ACTION, action, {});
- [action, actionOwner] =
- action.value.QueryInterface(Ci.nsISupportsString).data.split(",");
- } catch(ex) {
- // Paste from external sources don't have any associated action, just
- // fallback to a copy action.
- return "copy";
- }
- // For cuts also check who inited the action, since cuts across different
- // instances should instead be handled as copies (The sources are not
- // available for this instance).
- if (action == "cut" && actionOwner != this.profileName)
- action = "copy";
-
- return action;
- },
-
- _releaseClipboardOwnership: function PC__releaseClipboardOwnership() {
- if (this.cutNodes.length > 0) {
- // This clears the logical clipboard, doesn't remove data.
- this.clipboard.emptyClipboard(Ci.nsIClipboard.kGlobalClipboard);
- }
- },
-
- _clearClipboard: function PC__clearClipboard() {
- let xferable = Cc["@mozilla.org/widget/transferable;1"].
- createInstance(Ci.nsITransferable);
- xferable.init(null);
- // Empty transferables may cause crashes, so just add an unknown type.
- const TYPE = "text/x-moz-place-empty";
- xferable.addDataFlavor(TYPE);
- xferable.setTransferData(TYPE, PlacesUtils.toISupportsString(""), 0);
- this.clipboard.setData(xferable, null, Ci.nsIClipboard.kGlobalClipboard);
- },
-
- _populateClipboard: function PC__populateClipboard(aNodes, aAction) {
- // This order is _important_! It controls how this and other applications
- // select data to be inserted based on type.
- let contents = [
- { type: PlacesUtils.TYPE_X_MOZ_PLACE, entries: [] },
- { type: PlacesUtils.TYPE_X_MOZ_URL, entries: [] },
- { type: PlacesUtils.TYPE_HTML, entries: [] },
- { type: PlacesUtils.TYPE_UNICODE, entries: [] },
- ];
-
- // Avoid handling descendants of a copied node, the transactions take care
- // of them automatically.
- let copiedFolders = [];
- aNodes.forEach(function (node) {
- if (this._shouldSkipNode(node, copiedFolders))
- return;
- if (PlacesUtils.nodeIsFolder(node))
- copiedFolders.push(node);
-
- let livemarkInfo = this.getCachedLivemarkInfo(node);
- let feedURI = livemarkInfo && livemarkInfo.feedURI.spec;
-
- contents.forEach(function (content) {
- content.entries.push(
- PlacesUtils.wrapNode(node, content.type, feedURI)
- );
- });
- }, this);
-
- function addData(type, data) {
- xferable.addDataFlavor(type);
- xferable.setTransferData(type, PlacesUtils.toISupportsString(data),
- data.length * 2);
- }
-
- let xferable = Cc["@mozilla.org/widget/transferable;1"].
- createInstance(Ci.nsITransferable);
- xferable.init(null);
- let hasData = false;
- // This order matters here! It controls how this and other applications
- // select data to be inserted based on type.
- contents.forEach(function (content) {
- if (content.entries.length > 0) {
- hasData = true;
- let glue =
- content.type == PlacesUtils.TYPE_X_MOZ_PLACE ? "," : PlacesUtils.endl;
- addData(content.type, content.entries.join(glue));
- }
- });
-
- // Track the exected action in the xferable. This must be the last flavor
- // since it's the least preferred one.
- // Enqueue a unique instance identifier to distinguish operations across
- // concurrent instances of the application.
- addData(PlacesUtils.TYPE_X_MOZ_PLACE_ACTION, aAction + "," + this.profileName);
-
- if (hasData) {
- this.clipboard.setData(xferable,
- this.cutNodes.length > 0 ? this : null,
- Ci.nsIClipboard.kGlobalClipboard);
- }
- },
-
- _cutNodes: [],
- get cutNodes() this._cutNodes,
- set cutNodes(aNodes) {
- let self = this;
- function updateCutNodes(aValue) {
- self._cutNodes.forEach(function (aNode) {
- self._view.toggleCutNode(aNode, aValue);
- });
- }
-
- updateCutNodes(false);
- this._cutNodes = aNodes;
- updateCutNodes(true);
- return aNodes;
- },
-
- /**
- * Copy Bookmarks and Folders to the clipboard
- */
- copy: function PC_copy() {
- let result = this._view.result;
- let didSuppressNotifications = result.suppressNotifications;
- if (!didSuppressNotifications)
- result.suppressNotifications = true;
- try {
- this._populateClipboard(this._view.selectedNodes, "copy");
- }
- finally {
- if (!didSuppressNotifications)
- result.suppressNotifications = false;
- }
- },
-
- /**
- * Cut Bookmarks and Folders to the clipboard
- */
- cut: function PC_cut() {
- let result = this._view.result;
- let didSuppressNotifications = result.suppressNotifications;
- if (!didSuppressNotifications)
- result.suppressNotifications = true;
- try {
- this._populateClipboard(this._view.selectedNodes, "cut");
- this.cutNodes = this._view.selectedNodes;
- }
- finally {
- if (!didSuppressNotifications)
- result.suppressNotifications = false;
- }
- },
-
- /**
- * Paste Bookmarks and Folders from the clipboard
- */
- paste: function PC_paste() {
- // No reason to proceed if there isn't a valid insertion point.
- let ip = this._view.insertionPoint;
- if (!ip)
- throw Cr.NS_ERROR_NOT_AVAILABLE;
-
- let action = this.clipboardAction;
-
- let xferable = Cc["@mozilla.org/widget/transferable;1"].
- createInstance(Ci.nsITransferable);
- xferable.init(null);
- // This order matters here! It controls the preferred flavors for this
- // paste operation.
- [ PlacesUtils.TYPE_X_MOZ_PLACE,
- PlacesUtils.TYPE_X_MOZ_URL,
- PlacesUtils.TYPE_UNICODE,
- ].forEach(function (type) xferable.addDataFlavor(type));
-
- this.clipboard.getData(xferable, Ci.nsIClipboard.kGlobalClipboard);
-
- // Now get the clipboard contents, in the best available flavor.
- let data = {}, type = {}, items = [];
- try {
- xferable.getAnyTransferData(type, data, {});
- data = data.value.QueryInterface(Ci.nsISupportsString).data;
- type = type.value;
- items = PlacesUtils.unwrapNodes(data, type);
- } catch(ex) {
- // No supported data exists or nodes unwrap failed, just bail out.
- return;
- }
-
- let transactions = [];
- let insertionIndex = ip.index;
- for (let i = 0; i < items.length; ++i) {
- if (ip.isTag) {
- // Pasting into a tag container means tagging the item, regardless of
- // the requested action.
- let tagTxn = new PlacesTagURITransaction(NetUtil.newURI(items[i].uri),
- [ip.itemId]);
- transactions.push(tagTxn);
- continue;
- }
-
- // Adjust index to make sure items are pasted in the correct position.
- // If index is DEFAULT_INDEX, items are just appended.
- if (ip.index != PlacesUtils.bookmarks.DEFAULT_INDEX)
- insertionIndex = ip.index + i;
-
- transactions.push(
- PlacesUIUtils.makeTransaction(items[i], type, ip.itemId,
- insertionIndex, action == "copy")
- );
- }
-
- let aggregatedTxn = new PlacesAggregatedTransaction("Paste", transactions);
- PlacesUtils.transactionManager.doTransaction(aggregatedTxn);
-
- // Cut/past operations are not repeatable, so clear the clipboard.
- if (action == "cut") {
- this._clearClipboard();
- }
-
- // Select the pasted items, they should be consecutive.
- let insertedNodeIds = [];
- for (let 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);
- },
-
- /**
- * Cache the livemark info for a node. This allows the controller and the
- * views to treat the given node as a livemark.
- * @param aNode
- * a places result node.
- * @param aLivemarkInfo
- * a mozILivemarkInfo object.
- */
- cacheLivemarkInfo: function PC_cacheLivemarkInfo(aNode, aLivemarkInfo) {
- this._cachedLivemarkInfoObjects.set(aNode, aLivemarkInfo);
- },
-
- /**
- * Returns whether or not there's cached mozILivemarkInfo object for a node.
- * @param aNode
- * a places result node.
- * @return true if there's a cached mozILivemarkInfo object for
- * aNode, false otherwise.
- */
- hasCachedLivemarkInfo: function PC_hasCachedLivemarkInfo(aNode)
- this._cachedLivemarkInfoObjects.has(aNode),
-
- /**
- * Returns the cached livemark info for a node, if set by cacheLivemarkInfo,
- * null otherwise.
- * @param aNode
- * a places result node.
- * @return the mozILivemarkInfo object for aNode, if set, null otherwise.
- */
- getCachedLivemarkInfo: function PC_getCachedLivemarkInfo(aNode)
- this._cachedLivemarkInfoObjects.get(aNode, null)
-};
-
-/**
- * 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,
-
- /**
- * 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) {
- let 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() {
- return this.dragService.getCurrentSession();
- },
-
- /**
- * Extract the first accepted flavor from a list of flavors.
- * @param aFlavors
- * The flavors list of type nsIDOMDOMStringList.
- */
- getFirstValidFlavor: function PCDH_getFirstValidFlavor(aFlavors) {
- for (let i = 0; i < aFlavors.length; i++) {
- if (this.GENERIC_VIEW_DROP_TYPES.indexOf(aFlavors[i]) != -1)
- return aFlavors[i];
- }
-
- // If no supported flavor is found, check if data includes text/plain
- // contents. If so, request them as text/unicode, a conversion will happen
- // automatically.
- if (aFlavors.contains("text/plain")) {
- return PlacesUtils.TYPE_UNICODE;
- }
-
- 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, dt) {
- let dropCount = dt.mozItemCount;
-
- // Check every dragged item.
- for (let i = 0; i < dropCount; i++) {
- let flavor = this.getFirstValidFlavor(dt.mozTypesAt(i));
- if (!flavor)
- return false;
-
- // Urls can be dropped on any insertionpoint.
- // XXXmano: remember that 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;
-
- let data = dt.mozGetDataAt(flavor, i);
- let dragged;
- try {
- 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 ||
- (dragged.uri && dragged.uri.startsWith("place:")) ))
- 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 ||
- (dragged.uri && dragged.uri.startsWith("place:")) ) {
- let 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) {
- // Only bookmark items are movable.
- if (aNode.itemId == -1)
- return false;
-
- // Once tags and bookmarked are divorced, the tag-query check should be
- // removed.
- let parentNode = aNode.parent;
- return parentNode != null &&
- !(PlacesUtils.nodeIsFolder(parentNode) &&
- PlacesUIUtils.isContentsReadOnly(parentNode)) &&
- !PlacesUtils.nodeIsTagQuery(parentNode);
- },
-
- /**
- * 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, dt) {
- let doCopy = ["copy", "link"].indexOf(dt.dropEffect) != -1;
-
- let transactions = [];
- let dropCount = dt.mozItemCount;
- let movedCount = 0;
- for (let i = 0; i < dropCount; ++i) {
- let flavor = this.getFirstValidFlavor(dt.mozTypesAt(i));
- if (!flavor)
- return;
-
- let data = dt.mozGetDataAt(flavor, i);
- let 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) {
- let uri = data.linkedBrowser.currentURI;
- let spec = uri ? uri.spec : "about:blank";
- let title = data.label;
- unwrapped = { uri: spec,
- title: data.label,
- type: PlacesUtils.TYPE_X_MOZ_URL};
- }
- else
- throw("bogus data was passed as a tab");
-
- let 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.
- let 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) {
- let uri = NetUtil.newURI(unwrapped.uri);
- let tagItemId = insertionPoint.itemId;
- let tagTxn = new PlacesTagURITransaction(uri, [tagItemId]);
- transactions.push(tagTxn);
- }
- else {
- transactions.push(PlacesUIUtils.makeTransaction(unwrapped,
- flavor, insertionPoint.itemId,
- index, doCopy));
- }
- }
-
- let txn = new PlacesAggregatedTransaction("DropItems", transactions);
- PlacesUtils.transactionManager.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 and editable folders.
- return !PlacesUtils.nodeIsTagQuery(aContainer) &&
- (!PlacesUtils.nodeIsFolder(aContainer) ||
- PlacesUIUtils.isContentsReadOnly(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],
-};
-
-
-XPCOMUtils.defineLazyServiceGetter(PlacesControllerDragHelper, "dragService",
- "@mozilla.org/widget/dragservice;1",
- "nsIDragService");
-
-function goUpdatePlacesCommands() {
- // Get the controller for one of the places commands.
- var placesController = doGetPlacesControllerForCommand("placesCmd_open");
- function updatePlacesCommand(aCommand) {
- goSetCommandEnabled(aCommand, placesController &&
- placesController.isCommandEnabled(aCommand));
- }
-
- updatePlacesCommand("placesCmd_open");
- updatePlacesCommand("placesCmd_open:window");
- updatePlacesCommand("placesCmd_open:privatewindow");
- 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_sortBy:name");
- updatePlacesCommand("placesCmd_openParentFolder");
- updatePlacesCommand("placesCmd_cut");
- updatePlacesCommand("placesCmd_copy");
- updatePlacesCommand("placesCmd_paste");
- updatePlacesCommand("placesCmd_delete");
-}
-
-function doGetPlacesControllerForCommand(aCommand)
-{
- // A context menu may be built for non-focusable views. Thus, we first try
- // to look for a view associated with document.popupNode
- let popupNode;
- try {
- popupNode = document.popupNode;
- } catch (e) {
- // The document went away (bug 797307).
- return null;
- }
- if (popupNode) {
- let view = PlacesUIUtils.getViewForNode(popupNode);
- if (view && view._contextMenuShown)
- return view.controllers.getControllerForCommand(aCommand);
- }
-
- // When we're not building a context menu, only focusable views
- // are possible. Thus, we can safely use the command dispatcher.
- let controller = top.document.commandDispatcher
- .getControllerForCommand(aCommand);
- if (controller)
- return controller;
-
- return null;
-}
-
-function goDoPlacesCommand(aCommand)
-{
- let controller = doGetPlacesControllerForCommand(aCommand);
- if (controller && controller.isCommandEnabled(aCommand))
- controller.doCommand(aCommand);
-}
-
diff --git a/components/places/content/downloadsViewOverlay.xul b/components/places/content/downloadsViewOverlay.xul
deleted file mode 100644
index 8e2d775..0000000
--- a/components/places/content/downloadsViewOverlay.xul
+++ /dev/null
@@ -1,47 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<?xul-overlay href="chrome://browser/content/downloads/allDownloadsViewOverlay.xul"?>
-
-<!DOCTYPE overlay [
-<!ENTITY % downloadsDTD SYSTEM "chrome://browser/locale/downloads/downloads.dtd">
-%downloadsDTD;
-]>
-
-<overlay id="downloadsViewOverlay"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-
- <script type="application/javascript"><![CDATA[
- const DOWNLOADS_QUERY = "place:transition=" +
- Components.interfaces.nsINavHistoryService.TRANSITION_DOWNLOAD +
- "&sort=" +
- Components.interfaces.nsINavHistoryQueryOptions.SORT_BY_DATE_DESCENDING;
-
- ContentArea.setContentViewForQueryString(DOWNLOADS_QUERY,
- function() new DownloadsPlacesView(document.getElementById("downloadsRichListBox"), false),
- { showDetailsPane: false,
- toolbarSet: "back-button, forward-button, organizeButton, clearDownloadsButton, libraryToolbarSpacer, searchFilter" });
- ]]></script>
-
- <window id="places">
- <commandset id="downloadCommands"/>
- <menupopup id="downloadsContextMenu"/>
- </window>
-
- <deck id="placesViewsDeck">
- <richlistbox id="downloadsRichListBox"/>
- </deck>
-
- <toolbar id="placesToolbar">
- <toolbarbutton id="clearDownloadsButton"
-#ifdef XP_MACOSX
- class="tabbable"
-#endif
- insertbefore="libraryToolbarSpacer"
- label="&clearDownloadsButton.label;"
- command="downloadsCmd_clearDownloads"
- tooltiptext="&clearDownloadsButton.tooltip;"/>
- </toolbar>
-
-</overlay>
diff --git a/components/places/content/editBookmarkOverlay.js b/components/places/content/editBookmarkOverlay.js
deleted file mode 100644
index 69d7d32..0000000
--- a/components/places/content/editBookmarkOverlay.js
+++ /dev/null
@@ -1,1063 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-const LAST_USED_ANNO = "bookmarkPropertiesDialog/folderLastUsed";
-const MAX_FOLDER_ITEM_IN_MENU_LIST = 5;
-
-var gEditItemOverlay = {
- _uri: null,
- _itemId: -1,
- _itemIds: [],
- _uris: [],
- _tags: [],
- _allTags: [],
- _keyword: null,
- _multiEdit: false,
- _itemType: -1,
- _readOnly: false,
- _hiddenRows: [],
- _onPanelReady: false,
- _observersAdded: false,
- _staticFoldersListBuilt: false,
- _initialized: false,
- _titleOverride: "",
-
- // 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, this._hiddenRows.length);
- // force-read-only
- this._readOnly = aInfo && aInfo.forceReadOnly;
- this._titleOverride = aInfo && aInfo.titleOverride ? aInfo.titleOverride
- : "";
- this._onPanelReady = aInfo && aInfo.onPanelReady;
- },
-
- _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 (Array.isArray(aFor)) {
- 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;
- // We can't store information on invalid itemIds.
- this._readOnly = this._readOnly || this._itemId == -1;
-
- 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);
- this._keyword = PlacesUtils.bookmarks.getKeywordForBookmark(this._itemId);
- this._initTextField("keywordField", this._keyword);
- this._element("loadInSidebarCheckbox").checked =
- PlacesUtils.annotations.itemHasAnnotation(this._itemId,
- PlacesUIUtils.LOAD_IN_SIDEBAR_ANNO);
- }
- else {
- this._uri = null;
- this._isLivemark = false;
- PlacesUtils.livemarks.getLivemark({id: this._itemId })
- .then(aLivemark => {
- this._isLivemark = true;
- this._initTextField("feedLocationField", aLivemark.feedURI.spec, true);
- this._initTextField("siteLocationField", aLivemark.siteURI ? aLivemark.siteURI.spec : "", true);
- this._showHideRows();
- }, () => undefined);
- }
-
- // 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;
- 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]);
- }
- this._allTags = this._getCommonTags();
- this._initTextField("tagsField", this._allTags.join(", "), false);
- this._element("itemsCountText").value =
- PlacesUIUtils.getPluralString("detailsPane.itemsCountLabel",
- this._itemIds.length,
- [this._itemIds.length]);
- }
-
- // tags selector
- this._rebuildTagsSelectorList();
- }
-
- // name picker
- this._initNamePicker();
-
- this._showHideRows();
-
- // observe changes
- if (!this._observersAdded) {
- // Single bookmarks observe any change. History entries and multiEdit
- // observe only tags changes, through bookmarks.
- if (this._itemId != -1 || this._uri || this._multiEdit)
- PlacesUtils.bookmarks.addObserver(this, false);
-
- this._element("namePicker").addEventListener("blur", this);
- this._element("locationField").addEventListener("blur", this);
- this._element("tagsField").addEventListener("blur", this);
- this._element("keywordField").addEventListener("blur", this);
- this._element("descriptionField").addEventListener("blur", this);
- window.addEventListener("unload", this, false);
- this._observersAdded = true;
- }
-
- let focusElement = () => {
- this._initialized = true;
- };
-
- if (this._onPanelReady) {
- this._onPanelReady(focusElement);
- } else {
- focusElement();
- }
- },
-
- /**
- * Finds tags that are in common among this._tags entries that track tags
- * for each selected uri.
- * The tags arrays should be kept up-to-date for this to work properly.
- *
- * @return array of common tags for the selected uris.
- */
- _getCommonTags: function() {
- return this._tags[0].filter(
- function (aTag) this._tags.every(
- function (aTags) aTags.indexOf(aTag) != -1
- ), this
- );
- },
-
- _initTextField: function(aTextFieldId, aValue, aReadOnly) {
- var field = this._element(aTextFieldId);
- field.readOnly = aReadOnly !== undefined ? aReadOnly : this._readOnly;
-
- if (field.value != aValue) {
- field.value = aValue;
- this._editorTransactionManagerClear(field);
- }
- },
-
- /**
- * 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 <= 6);
- this._folderMenuList.disabled = this._readOnly;
- },
-
- QueryInterface: function EIO_QueryInterface(aIID) {
- if (aIID.equals(Ci.nsIDOMEventListener) ||
- aIID.equals(Ci.nsINavBookmarkObserver) ||
- aIID.equals(Ci.nsISupports))
- return this;
-
- throw Cr.NS_ERROR_NO_INTERFACE;
- },
-
- _element: function EIO__element(aID) {
- return document.getElementById("editBMPanel_" + aID);
- },
-
- _editorTransactionManagerClear: function EIO__editorTransactionManagerClear(aItem) {
- // Clear the editor's undo stack
- let transactionManager;
- try {
- transactionManager = aItem.editor.transactionManager;
- } catch (e) {
- // When retrieving the transaction manager, editor may be null resulting
- // in a TypeError. Additionally, the transaction manager may not
- // exist yet, which causes access to it to throw NS_ERROR_FAILURE.
- // In either event, the transaction manager doesn't exist it, so we
- // don't need to worry about clearing it.
- if (!(e instanceof TypeError) && e.result != Cr.NS_ERROR_FAILURE) {
- throw e;
- }
- }
- if (transactionManager) {
- transactionManager.clear();
- }
- },
-
- _getItemStaticTitle: function EIO__getItemStaticTitle() {
- if (this._titleOverride)
- return this._titleOverride;
-
- let title = "";
- if (this._itemId == -1) {
- title = PlacesUtils.history.getPageTitle(this._uri);
- }
- else {
- title = PlacesUtils.bookmarks.getItemTitle(this._itemId);
- }
- return title;
- },
-
- _initNamePicker: function EIO_initNamePicker() {
- var namePicker = this._element("namePicker");
- namePicker.value = this._getItemStaticTitle();
- namePicker.readOnly = this._readOnly;
- this._editorTransactionManagerClear(namePicker);
- },
-
- 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 || this._uri || this._multiEdit)
- PlacesUtils.bookmarks.removeObserver(this);
-
- this._element("namePicker").removeEventListener("blur", this);
- this._element("locationField").removeEventListener("blur", this);
- this._element("tagsField").removeEventListener("blur", this);
- this._element("keywordField").removeEventListener("blur", this);
- this._element("descriptionField").removeEventListener("blur", this);
-
- this._observersAdded = false;
- }
-
- this._itemId = -1;
- this._uri = null;
- this._uris = [];
- this._tags = [];
- this._allTags = [];
- this._itemIds = [];
- this._multiEdit = false;
- this._firstEditedField = "";
- this._initialized = false;
- this._titleOverride = "";
- this._readOnly = 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) {
- let untagTxn = new PlacesUntagURITransaction(this._uri, tagsToRemove);
- txns.push(untagTxn);
- }
- if (tagsToAdd.length > 0) {
- let tagTxn = new PlacesTagURITransaction(this._uri, tagsToAdd);
- txns.push(tagTxn);
- }
-
- if (txns.length > 0) {
- let aggregate = new PlacesAggregatedTransaction("Update tags", txns);
- PlacesUtils.transactionManager.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 (let i = 0; i < this._uris.length; i++) {
- if (tagsToAdd[i].length > 0) {
- let tagTxn = new PlacesTagURITransaction(this._uris[i],
- tagsToAdd[i]);
- txns.push(tagTxn);
- }
- }
- }
- if (tagsToRemove.length > 0) {
- for (let i = 0; i < this._uris.length; i++) {
- let untagTxn = new PlacesUntagURITransaction(this._uris[i],
- tagsToRemove);
- txns.push(untagTxn);
- }
- }
-
- if (txns.length > 0) {
- let aggregate = new PlacesAggregatedTransaction("Update tags", txns);
- PlacesUtils.transactionManager.doTransaction(aggregate);
-
- this._allTags = tags;
- this._tags = [];
- for (let 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;
- },
-
- onNamePickerBlur: function EIO_onNamePickerBlur() {
- if (this._itemId == -1)
- return;
-
- var namePicker = this._element("namePicker")
-
- // Here we update either the item title or its cached static title
- var newTitle = namePicker.value;
- if (!newTitle &&
- PlacesUtils.bookmarks.getFolderIdForItem(this._itemId) == PlacesUtils.tagsFolderId) {
- // We don't allow setting an empty title for a tag, restore the old one.
- this._initNamePicker();
- }
- else if (this._getItemStaticTitle() != newTitle) {
- this._mayUpdateFirstEditField("namePicker");
- let txn = new PlacesEditItemTitleTransaction(this._itemId, newTitle);
- PlacesUtils.transactionManager.doTransaction(txn);
- }
- },
-
- onDescriptionFieldBlur: function EIO_onDescriptionFieldBlur() {
- var description = this._element("descriptionField").value;
- if (description != PlacesUIUtils.getItemDescription(this._itemId)) {
- var annoObj = { name : PlacesUIUtils.DESCRIPTION_ANNO,
- type : Ci.nsIAnnotationService.TYPE_STRING,
- flags : 0,
- value : description,
- expires: Ci.nsIAnnotationService.EXPIRE_NEVER };
- var txn = new PlacesSetItemAnnotationTransaction(this._itemId, annoObj);
- PlacesUtils.transactionManager.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 = new PlacesEditBookmarkURITransaction(this._itemId, uri);
- PlacesUtils.transactionManager.doTransaction(txn);
- this._uri = uri;
- }
- },
-
- onKeywordFieldBlur: function EIO_onKeywordFieldBlur() {
- let oldKeyword = this._keyword;
- let keyword = this._keyword = this._element("keywordField").value;
- if (keyword != oldKeyword) {
- let txn = new PlacesEditBookmarkKeywordTransaction(this._itemId,
- keyword,
- null,
- oldKeyword);
- PlacesUtils.transactionManager.doTransaction(txn);
- }
- },
-
- onLoadInSidebarCheckboxCommand:
- function EIO_onLoadInSidebarCheckboxCommand() {
- let annoObj = { name : PlacesUIUtils.LOAD_IN_SIDEBAR_ANNO };
- if (this._element("loadInSidebarCheckbox").checked)
- annoObj.value = true;
- let txn = new PlacesSetItemAnnotationTransaction(this._itemId, annoObj);
- PlacesUtils.transactionManager.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 (let i = 0; i < menupopup.childNodes.length; i++) {
- if ("folderId" in menupopup.childNodes[i] &&
- 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 = new PlacesMoveItemTransaction(this._itemId,
- container,
- PlacesUtils.bookmarks.DEFAULT_INDEX);
- PlacesUtils.transactionManager.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;
- let annoTxn = new PlacesSetItemAnnotationTransaction(folderId, anno);
- txns.push(annoTxn);
- }
-
- // Mark folder as recently used
- anno = this._getLastUsedAnnotationObject(true);
- let annoTxn = new PlacesSetItemAnnotationTransaction(aFolderId, anno);
- txns.push(annoTxn);
-
- let aggregate = new PlacesAggregatedTransaction("Update last used folders", txns);
- PlacesUtils.transactionManager.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;
-
- // Save the current scroll position and restore it after the rebuild.
- let firstIndex = tagsSelector.getIndexOfFirstVisibleRow();
- let selectedIndex = tagsSelector.selectedIndex;
- let selectedTag = selectedIndex >= 0 ? tagsSelector.selectedItem.label
- : null;
-
- 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);
- if (selectedTag === tag)
- selectedIndex = tagsSelector.getIndexOfItem(elt);
- }
-
- // Restore position.
- // The listbox allows to scroll only if the required offset doesn't
- // overflow its capacity, thus need to adjust the index for removals.
- firstIndex =
- Math.min(firstIndex,
- tagsSelector.itemCount - tagsSelector.getNumberOfVisibleRows());
- tagsSelector.scrollToIndex(firstIndex);
- if (selectedIndex >= 0 && tagsSelector.itemCount > 0) {
- selectedIndex = Math.min(selectedIndex, tagsSelector.itemCount - 1);
- tagsSelector.selectedIndex = selectedIndex;
- tagsSelector.ensureIndexIsVisible(selectedIndex);
- }
- },
-
- 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;
- }
- },
-
- /**
- * Splits "tagsField" element value, returning an array of valid tag strings.
- *
- * @return Array of tag strings found in the field value.
- */
- _getTagsArrayFromTagField: function EIO__getTagsArrayFromTagField() {
- let tags = this._element("tagsField").value;
- return tags.trim()
- .split(/\s*,\s*/) // Split on commas and remove spaces.
- .filter(function (tag) tag.length > 0); // Kill empty 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 = new PlacesCreateFolderTransaction(defaultLabel, ip.itemId, ip.index);
- PlacesUtils.transactionManager.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 "blur":
- let replaceFn = (str, firstLetter) => firstLetter.toUpperCase();
- let nodeName = aEvent.target.id.replace(/editBMPanel_(\w)/, replaceFn);
- this["on" + nodeName + "Blur"]();
- break;
- case "unload":
- this.uninitPanel(false);
- break;
- }
- },
-
- // nsINavBookmarkObserver
- onItemChanged: function EIO_onItemChanged(aItemId, aProperty,
- aIsAnnotationProperty, aValue,
- aLastModified, aItemType) {
- if (aProperty == "tags") {
- // Tags case is special, since they should be updated if either:
- // - the notification is for the edited bookmark
- // - the notification is for the edited history entry
- // - the notification is for one of edited uris
- let shouldUpdateTagsField = this._itemId == aItemId;
- if (this._itemId == -1 || this._multiEdit) {
- // Check if the changed uri is part of the modified ones.
- let changedURI = PlacesUtils.bookmarks.getBookmarkURI(aItemId);
- let uris = this._multiEdit ? this._uris : [this._uri];
- uris.forEach(function (aURI, aIndex) {
- if (aURI.equals(changedURI)) {
- shouldUpdateTagsField = true;
- if (this._multiEdit) {
- this._tags[aIndex] = PlacesUtils.tagging.getTagsForURI(this._uris[aIndex]);
- }
- }
- }, this);
- }
-
- if (shouldUpdateTagsField) {
- if (this._multiEdit) {
- this._allTags = this._getCommonTags();
- this._initTextField("tagsField", this._allTags.join(", "), false);
- }
- else {
- let tags = PlacesUtils.tagging.getTagsForURI(this._uri).join(", ");
- this._initTextField("tagsField", tags, false);
- }
- }
-
- // Any tags change should be reflected in the tags selector.
- this._rebuildTagsSelectorList();
- return;
- }
-
- 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 (let i = 0; i < menupopup.childNodes.length; i++) {
- if ("folderId" in menupopup.childNodes[i] &&
- menupopup.childNodes[i].folderId == aItemId) {
- menupopup.childNodes[i].label = aValue;
- break;
- }
- }
- }
-
- return;
- }
-
- switch (aProperty) {
- case "title":
- var namePicker = this._element("namePicker");
- if (namePicker.value != aValue) {
- namePicker.value = aValue;
- this._editorTransactionManagerClear(namePicker);
- }
- 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();
- this._initTextField("tagsField",
- PlacesUtils.tagging
- .getTagsForURI(this._uri).join(", "),
- false);
- this._rebuildTagsSelectorList();
- }
- break;
- case "keyword":
- this._keyword = PlacesUtils.bookmarks.getKeywordForBookmark(this._itemId);
- this._initTextField("keywordField", this._keyword);
- break;
- case PlacesUIUtils.DESCRIPTION_ANNO:
- this._initTextField("descriptionField",
- PlacesUIUtils.getItemDescription(this._itemId));
- break;
- case PlacesUIUtils.LOAD_IN_SIDEBAR_ANNO:
- this._element("loadInSidebarCheckbox").checked =
- PlacesUtils.annotations.itemHasAnnotation(this._itemId,
- PlacesUIUtils.LOAD_IN_SIDEBAR_ANNO);
- break;
- case PlacesUtils.LMANNO_FEEDURI:
- let feedURISpec =
- PlacesUtils.annotations.getItemAnnotation(this._itemId,
- PlacesUtils.LMANNO_FEEDURI);
- this._initTextField("feedLocationField", feedURISpec, true);
- break;
- case PlacesUtils.LMANNO_SITEURI:
- let siteURISpec = "";
- try {
- siteURISpec =
- PlacesUtils.annotations.getItemAnnotation(this._itemId,
- PlacesUtils.LMANNO_SITEURI);
- } catch (ex) {}
- this._initTextField("siteLocationField", siteURISpec, true);
- 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, aParentId, aIndex, aItemType,
- aURI) {
- this._lastNewItem = aItemId;
- },
-
- onItemRemoved: function() { },
- onBeginUpdateBatch: function() { },
- onEndUpdateBatch: function() { },
- onItemVisited: function() { },
-};
diff --git a/components/places/content/editBookmarkOverlay.xul b/components/places/content/editBookmarkOverlay.xul
deleted file mode 100644
index 196369d..0000000
--- a/components/places/content/editBookmarkOverlay.xul
+++ /dev/null
@@ -1,228 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!DOCTYPE overlay [
-<!ENTITY % editBookmarkOverlayDTD SYSTEM "chrome://browser/locale/places/editBookmarkOverlay.dtd">
-%editBookmarkOverlayDTD;
-]>
-
-<?xml-stylesheet href="chrome://browser/skin/places/editBookmarkOverlay.css"?>
-<?xml-stylesheet href="chrome://browser/skin/places/places.css"?>
-
-<overlay id="editBookmarkOverlay"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-
- <vbox id="editBookmarkPanelContent" flex="1">
- <broadcaster id="paneElementsBroadcaster"/>
-
- <hbox id="editBMPanel_selectionCount" hidden="true" pack="center">
- <label id="editBMPanel_itemsCountText"/>
- </hbox>
-
- <grid id="editBookmarkPanelGrid" flex="1">
- <columns id="editBMPanel_columns">
- <column id="editBMPanel_labelColumn" />
- <column flex="1" id="editBMPanel_editColumn" />
- </columns>
- <rows id="editBMPanel_rows">
- <row id="editBMPanel_nameRow"
- align="center"
- collapsed="true">
- <label value="&editBookmarkOverlay.name.label;"
- class="editBMPanel_rowLabel"
- accesskey="&editBookmarkOverlay.name.accesskey;"
- control="editBMPanel_namePicker"
- observes="paneElementsBroadcaster"/>
- <textbox id="editBMPanel_namePicker"
- observes="paneElementsBroadcaster"/>
- </row>
-
- <row id="editBMPanel_locationRow"
- align="center"
- collapsed="true">
- <label value="&editBookmarkOverlay.location.label;"
- class="editBMPanel_rowLabel"
- accesskey="&editBookmarkOverlay.location.accesskey;"
- control="editBMPanel_locationField"
- observes="paneElementsBroadcaster"/>
- <textbox id="editBMPanel_locationField"
- class="uri-element"
- observes="paneElementsBroadcaster"/>
- </row>
-
- <row id="editBMPanel_feedLocationRow"
- align="center"
- collapsed="true">
- <label value="&editBookmarkOverlay.feedLocation.label;"
- class="editBMPanel_rowLabel"
- accesskey="&editBookmarkOverlay.feedLocation.accesskey;"
- control="editBMPanel_feedLocationField"
- observes="paneElementsBroadcaster"/>
- <textbox id="editBMPanel_feedLocationField"
- class="uri-element"
- observes="paneElementsBroadcaster"/>
- </row>
-
- <row id="editBMPanel_siteLocationRow"
- align="center"
- collapsed="true">
- <label value="&editBookmarkOverlay.siteLocation.label;"
- class="editBMPanel_rowLabel"
- accesskey="&editBookmarkOverlay.siteLocation.accesskey;"
- control="editBMPanel_siteLocationField"
- observes="paneElementsBroadcaster"/>
- <textbox id="editBMPanel_siteLocationField"
- class="uri-element"
- observes="paneElementsBroadcaster"/>
- </row>
-
- <row id="editBMPanel_folderRow"
- align="center"
- collapsed="true">
- <label value="&editBookmarkOverlay.folder.label;"
- class="editBMPanel_rowLabel"
- control="editBMPanel_folderMenuList"
- observes="paneElementsBroadcaster"/>
- <hbox flex="1" align="center">
- <menulist id="editBMPanel_folderMenuList"
- class="folder-icon"
- flex="1"
- oncommand="gEditItemOverlay.onFolderMenuListCommand(event);"
- observes="paneElementsBroadcaster">
- <menupopup>
- <!-- Static item for special folders -->
- <menuitem id="editBMPanel_toolbarFolderItem"
- class="menuitem-iconic folder-icon"/>
- <menuitem id="editBMPanel_bmRootItem"
- class="menuitem-iconic folder-icon"/>
- <menuitem id="editBMPanel_unfiledRootItem"
- class="menuitem-iconic folder-icon"/>
- <menuseparator id="editBMPanel_chooseFolderSeparator"/>
- <menuitem id="editBMPanel_chooseFolderMenuItem"
- label="&editBookmarkOverlay.choose.label;"
- class="menuitem-iconic folder-icon"/>
- <menuseparator id="editBMPanel_foldersSeparator" hidden="true"/>
- </menupopup>
- </menulist>
- <button id="editBMPanel_foldersExpander"
- class="expander-down"
- tooltiptext="&editBookmarkOverlay.foldersExpanderDown.tooltip;"
- tooltiptextdown="&editBookmarkOverlay.foldersExpanderDown.tooltip;"
- tooltiptextup="&editBookmarkOverlay.expanderUp.tooltip;"
- oncommand="gEditItemOverlay.toggleFolderTreeVisibility();"
- observes="paneElementsBroadcaster"/>
- </hbox>
- </row>
-
- <row id="editBMPanel_folderTreeRow"
- collapsed="true"
- flex="1">
- <spacer/>
- <vbox flex="1">
- <tree id="editBMPanel_folderTree"
- flex="1"
- class="placesTree"
- type="places"
- height="150"
- minheight="150"
- editable="true"
- onselect="gEditItemOverlay.onFolderTreeSelect();"
- hidecolumnpicker="true"
- observes="paneElementsBroadcaster">
- <treecols>
- <treecol anonid="title" flex="1" primary="true" hideheader="true"/>
- </treecols>
- <treechildren flex="1"/>
- </tree>
-
- <hbox id="editBMPanel_newFolderBox">
- <button label="&editBookmarkOverlay.newFolderButton.label;"
- id="editBMPanel_newFolderButton"
- accesskey="&editBookmarkOverlay.newFolderButton.accesskey;"
- oncommand="gEditItemOverlay.newFolder();"/>
- </hbox>
- </vbox>
- </row>
-
- <row id="editBMPanel_tagsRow"
- align="center"
- collapsed="true">
- <label value="&editBookmarkOverlay.tags.label;"
- class="editBMPanel_rowLabel"
- accesskey="&editBookmarkOverlay.tags.accesskey;"
- control="editBMPanel_tagsField"
- observes="paneElementsBroadcaster"/>
- <hbox flex="1" align="center">
- <textbox id="editBMPanel_tagsField"
- type="autocomplete"
- class="padded"
- flex="1"
- autocompletesearch="places-tag-autocomplete"
- completedefaultindex="true"
- tabscrolling="true"
- showcommentcolumn="true"
- observes="paneElementsBroadcaster"
- placeholder="&editBookmarkOverlay.tagsEmptyDesc.label;"/>
- <button id="editBMPanel_tagsSelectorExpander"
- class="expander-down"
- tooltiptext="&editBookmarkOverlay.tagsExpanderDown.tooltip;"
- tooltiptextdown="&editBookmarkOverlay.tagsExpanderDown.tooltip;"
- tooltiptextup="&editBookmarkOverlay.expanderUp.tooltip;"
- oncommand="gEditItemOverlay.toggleTagsSelector();"
- observes="paneElementsBroadcaster"/>
- </hbox>
- </row>
-
- <row id="editBMPanel_tagsSelectorRow"
- align="center"
- collapsed="true">
- <spacer/>
- <listbox id="editBMPanel_tagsSelector"
- height="150"
- observes="paneElementsBroadcaster"/>
- </row>
-
- <row id="editBMPanel_keywordRow"
- align="center"
- collapsed="true">
- <observes element="additionalInfoBroadcaster" attribute="hidden"/>
- <label value="&editBookmarkOverlay.keyword.label;"
- class="editBMPanel_rowLabel"
- accesskey="&editBookmarkOverlay.keyword.accesskey;"
- control="editBMPanel_keywordField"
- observes="paneElementsBroadcaster"/>
- <textbox id="editBMPanel_keywordField"
- observes="paneElementsBroadcaster"/>
- </row>
-
- <row id="editBMPanel_descriptionRow"
- collapsed="true">
- <observes element="additionalInfoBroadcaster" attribute="hidden"/>
- <label value="&editBookmarkOverlay.description.label;"
- class="editBMPanel_rowLabel"
- accesskey="&editBookmarkOverlay.description.accesskey;"
- control="editBMPanel_descriptionField"
- observes="paneElementsBroadcaster"/>
- <textbox id="editBMPanel_descriptionField"
- multiline="true"
- observes="paneElementsBroadcaster"/>
- </row>
- </rows>
- </grid>
-
- <checkbox id="editBMPanel_loadInSidebarCheckbox"
- collapsed="true"
- label="&editBookmarkOverlay.loadInSidebar.label;"
- accesskey="&editBookmarkOverlay.loadInSidebar.accesskey;"
- oncommand="gEditItemOverlay.onLoadInSidebarCheckboxCommand();"
- observes="paneElementsBroadcaster">
- <observes element="additionalInfoBroadcaster" attribute="hidden"/>
- </checkbox>
-
- <!-- If the ids are changing or additional fields are being added, be sure
- to sync the values in places.js -->
- <broadcaster id="additionalInfoBroadcaster"/>
-
- </vbox>
-</overlay>
diff --git a/components/places/content/history-panel.js b/components/places/content/history-panel.js
deleted file mode 100644
index cda39dd..0000000
--- a/components/places/content/history-panel.js
+++ /dev/null
@@ -1,91 +0,0 @@
-/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-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_FRECENCY_DESCENDING;
- resultType = NHQO.RESULTS_AS_URI;
- }
- }
-
- options.sortingMode = sortingMode;
- options.resultType = resultType;
- options.includeHidden = !!aInput;
-
- // 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);
diff --git a/components/places/content/history-panel.xul b/components/places/content/history-panel.xul
deleted file mode 100644
index d1c875a..0000000
--- a/components/places/content/history-panel.xul
+++ /dev/null
@@ -1,95 +0,0 @@
-<?xml version="1.0"?> <!-- -*- Mode: xml; indent-tabs-mode: nil; -*- -->
-
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-<?xml-stylesheet href="chrome://browser/content/places/places.css"?>
-<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
-<?xml-stylesheet href="chrome://browser/skin/places/places.css"?>
-
-<?xul-overlay href="chrome://global/content/editMenuOverlay.xul"?>
-<?xul-overlay href="chrome://browser/content/places/placesOverlay.xul"?>
-
-<!DOCTYPE page [
-<!ENTITY % placesDTD SYSTEM "chrome://browser/locale/places/places.dtd">
-%placesDTD;
-]>
-
-<!-- we need to keep id="history-panel" for upgrade and switching
- between versions of the browser -->
-
-<page id="history-panel" orient="vertical"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- onload="HistorySidebarInit();"
- onunload="SidebarUtils.setMouseoverURL('');">
-
- <script type="application/javascript"
- src="chrome://browser/content/bookmarks/sidebarUtils.js"/>
- <script type="application/javascript"
- src="chrome://browser/content/places/history-panel.js"/>
-
- <commandset id="editMenuCommands"/>
- <commandset id="placesCommands"/>
-
- <keyset id="editMenuKeys">
-#ifdef XP_MACOSX
- <key id="key_delete2" keycode="VK_BACK" command="cmd_delete"/>
-#endif
- </keyset>
-
- <!-- required to overlay the context menu -->
- <menupopup id="placesContext"/>
-
- <!-- Bookmarks and history tooltip -->
- <tooltip id="bhTooltip"/>
-
- <hbox id="sidebar-search-container" align="center">
- <label id="sidebar-search-label"
- value="&find.label;" accesskey="&find.accesskey;"
- control="search-box"/>
- <textbox id="search-box" flex="1" type="search" class="compact"
- aria-controls="historyTree"
- oncommand="searchHistory(this.value);"/>
- <button id="viewButton" style="min-width:0px !important;" type="menu"
- label="&view.label;" accesskey="&view.accesskey;" selectedsort="day"
- persist="selectedsort">
- <menupopup>
- <menuitem id="bydayandsite" label="&byDayAndSite.label;"
- accesskey="&byDayAndSite.accesskey;" type="radio"
- oncommand="this.parentNode.parentNode.setAttribute('selectedsort', 'dayandsite'); GroupBy('dayandsite');"/>
- <menuitem id="bysite" label="&bySite.label;"
- accesskey="&bySite.accesskey;" type="radio"
- oncommand="this.parentNode.parentNode.setAttribute('selectedsort', 'site'); GroupBy('site');"/>
- <menuitem id="byday" label="&byDate.label;"
- accesskey="&byDate.accesskey;"
- type="radio"
- oncommand="this.parentNode.parentNode.setAttribute('selectedsort', 'day'); GroupBy('day');"/>
- <menuitem id="byvisited" label="&byMostVisited.label;"
- accesskey="&byMostVisited.accesskey;"
- type="radio"
- oncommand="this.parentNode.parentNode.setAttribute('selectedsort', 'visited'); GroupBy('visited');"/>
- <menuitem id="bylastvisited" label="&byLastVisited.label;"
- accesskey="&byLastVisited.accesskey;"
- type="radio"
- oncommand="this.parentNode.parentNode.setAttribute('selectedsort', 'lastvisited'); GroupBy('lastvisited');"/>
- </menupopup>
- </button>
- </hbox>
-
- <tree id="historyTree"
- class="sidebar-placesTree"
- flex="1"
- type="places"
- context="placesContext"
- hidecolumnpicker="true"
- onkeypress="SidebarUtils.handleTreeKeyPress(event);"
- onclick="SidebarUtils.handleTreeClick(this, event, true);"
- onmousemove="SidebarUtils.handleTreeMouseMove(event);"
- onmouseout="SidebarUtils.setMouseoverURL('');">
- <treecols>
- <treecol id="title" flex="1" primary="true" hideheader="true"/>
- </treecols>
- <treechildren class="sidebar-placesTreechildren" flex="1" tooltip="bhTooltip"/>
- </tree>
-</page>
diff --git a/components/places/content/menu.xml b/components/places/content/menu.xml
deleted file mode 100644
index d4041ec..0000000
--- a/components/places/content/menu.xml
+++ /dev/null
@@ -1,488 +0,0 @@
-<?xml version="1.0"?>
-
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-<bindings id="placesMenuBindings"
- xmlns="http://www.mozilla.org/xbl"
- xmlns:xbl="http://www.mozilla.org/xbl"
- xmlns:html="http://www.w3.org/1999/xhtml"
- xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-
- <binding id="places-popup-base"
- extends="chrome://global/content/bindings/popup.xml#popup">
- <content>
- <xul:hbox flex="1">
- <xul:vbox class="menupopup-drop-indicator-bar" hidden="true">
- <xul:image class="menupopup-drop-indicator" mousethrough="always"/>
- </xul:vbox>
- <xul:arrowscrollbox class="popup-internal-box" flex="1" orient="vertical"
- smoothscroll="false">
- <children/>
- </xul:arrowscrollbox>
- </xul:hbox>
- </content>
-
- <implementation>
-
- <field name="_indicatorBar">
- document.getAnonymousElementByAttribute(this, "class",
- "menupopup-drop-indicator-bar");
- </field>
-
- <field name="_scrollBox">
- document.getAnonymousElementByAttribute(this, "class",
- "popup-internal-box");
- </field>
-
- <!-- This is the view that manage the popup -->
- <field name="_rootView">PlacesUIUtils.getViewForNode(this);</field>
-
- <!-- Check if we should hide the drop indicator for the target -->
- <method name="_hideDropIndicator">
- <parameter name="aEvent"/>
- <body><![CDATA[
- let target = aEvent.target;
-
- // Don't draw the drop indicator outside of markers.
- // The markers are hidden, since otherwise sometimes popups acquire
- // scrollboxes on OS X, so we can't use them directly.
- let firstChildTop = this._startMarker.nextSibling.boxObject.y;
- let lastChildBottom = this._endMarker.previousSibling.boxObject.y +
- this._endMarker.previousSibling.boxObject.height;
- let betweenMarkers = target.boxObject.y >= firstChildTop ||
- target.boxObject.y <= lastChildBottom;
-
- // Hide the dropmarker if current node is not a Places node.
- return !(target && target._placesNode && betweenMarkers);
- ]]></body>
- </method>
-
- <!-- This function returns information about where to drop when
- dragging over this popup insertion point -->
- <method name="_getDropPoint">
- <parameter name="aEvent"/>
- <body><![CDATA[
- // Can't drop if the menu isn't a folder
- let resultNode = this._placesNode;
-
- if (!PlacesUtils.nodeIsFolder(resultNode) ||
- PlacesControllerDragHelper.disallowInsertion(resultNode)) {
- return null;
- }
-
- var dropPoint = { ip: null, folderElt: null };
-
- // The element we are dragging over
- let elt = aEvent.target;
- if (elt.localName == "menupopup")
- elt = elt.parentNode;
-
- // Calculate positions taking care of arrowscrollbox
- let eventY = aEvent.layerY;
- let scrollbox = this._scrollBox;
- let scrollboxOffset = scrollbox.scrollBoxObject.y -
- (scrollbox.boxObject.y - this.boxObject.y);
- let eltY = elt.boxObject.y - scrollboxOffset;
- let eltHeight = elt.boxObject.height;
-
- if (!elt._placesNode) {
- // If we are dragging over a non places node drop at the end.
- dropPoint.ip = new InsertionPoint(
- PlacesUtils.getConcreteItemId(resultNode),
- -1,
- Ci.nsITreeView.DROP_ON);
- // We can set folderElt if we are dropping over a static menu that
- // has an internal placespopup.
- let isMenu = elt.localName == "menu" ||
- (elt.localName == "toolbarbutton" &&
- elt.getAttribute("type") == "menu");
- if (isMenu && elt.lastChild &&
- elt.lastChild.hasAttribute("placespopup"))
- dropPoint.folderElt = elt;
- return dropPoint;
- }
- if ((PlacesUtils.nodeIsFolder(elt._placesNode) &&
- !PlacesUIUtils.isContentsReadOnly(elt._placesNode)) ||
- PlacesUtils.nodeIsTagQuery(elt._placesNode)) {
- // This is a folder or a tag container.
- if (eventY - eltY < eltHeight * 0.20) {
- // If mouse is in the top part of the element, drop above folder.
- dropPoint.ip = new InsertionPoint(
- PlacesUtils.getConcreteItemId(resultNode),
- -1,
- Ci.nsITreeView.DROP_BEFORE,
- PlacesUtils.nodeIsTagQuery(elt._placesNode),
- elt._placesNode.itemId);
- return dropPoint;
- }
- else if (eventY - eltY < eltHeight * 0.80) {
- // If mouse is in the middle of the element, drop inside folder.
- dropPoint.ip = new InsertionPoint(
- PlacesUtils.getConcreteItemId(elt._placesNode),
- -1,
- Ci.nsITreeView.DROP_ON,
- PlacesUtils.nodeIsTagQuery(elt._placesNode));
- dropPoint.folderElt = elt;
- return dropPoint;
- }
- }
- else if (eventY - eltY <= eltHeight / 2) {
- // This is a non-folder node or a readonly folder.
- // If the mouse is above the middle, drop above this item.
- dropPoint.ip = new InsertionPoint(
- PlacesUtils.getConcreteItemId(resultNode),
- -1,
- Ci.nsITreeView.DROP_BEFORE,
- PlacesUtils.nodeIsTagQuery(elt._placesNode),
- elt._placesNode.itemId);
- return dropPoint;
- }
-
- // Drop below the item.
- dropPoint.ip = new InsertionPoint(
- PlacesUtils.getConcreteItemId(resultNode),
- -1,
- Ci.nsITreeView.DROP_AFTER,
- PlacesUtils.nodeIsTagQuery(elt._placesNode),
- elt._placesNode.itemId);
- return dropPoint;
- ]]></body>
- </method>
-
- <!-- Sub-menus should be opened when the mouse drags over them, and closed
- when the mouse drags off. The overFolder object manages opening and
- closing of folders when the mouse hovers. -->
- <field name="_overFolder"><![CDATA[({
- _self: this,
- _folder: {elt: null,
- openTimer: null,
- hoverTime: 350,
- closeTimer: null},
- _closeMenuTimer: null,
-
- get elt() {
- return this._folder.elt;
- },
- set elt(val) {
- return this._folder.elt = val;
- },
-
- get openTimer() {
- return this._folder.openTimer;
- },
- set openTimer(val) {
- return this._folder.openTimer = val;
- },
-
- get hoverTime() {
- return this._folder.hoverTime;
- },
- set hoverTime(val) {
- return this._folder.hoverTime = val;
- },
-
- get closeTimer() {
- return this._folder.closeTimer;
- },
- set closeTimer(val) {
- return this._folder.closeTimer = val;
- },
-
- get closeMenuTimer() {
- return this._closeMenuTimer;
- },
- set closeMenuTimer(val) {
- return this._closeMenuTimer = val;
- },
-
- setTimer: function OF__setTimer(aTime) {
- var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
- timer.initWithCallback(this, aTime, timer.TYPE_ONE_SHOT);
- return timer;
- },
-
- notify: function OF__notify(aTimer) {
- // Function to process all timer notifications.
-
- if (aTimer == this._folder.openTimer) {
- // Timer to open a submenu that's being dragged over.
- this._folder.elt.lastChild.setAttribute("autoopened", "true");
- this._folder.elt.lastChild.showPopup(this._folder.elt);
- this._folder.openTimer = null;
- }
-
- else if (aTimer == this._folder.closeTimer) {
- // Timer to close a submenu that's been dragged off of.
- // Only close the submenu if the mouse isn't being dragged over any
- // of its child menus.
- var draggingOverChild = PlacesControllerDragHelper
- .draggingOverChildNode(this._folder.elt);
- if (draggingOverChild)
- this._folder.elt = null;
- this.clear();
-
- // Close any parent folders which aren't being dragged over.
- // (This is necessary because of the above code that keeps a folder
- // open while its children are being dragged over.)
- if (!draggingOverChild)
- this.closeParentMenus();
- }
-
- else if (aTimer == this.closeMenuTimer) {
- // Timer to close this menu after the drag exit.
- var popup = this._self;
- // if we are no more dragging we can leave the menu open to allow
- // for better D&D bookmark organization
- if (PlacesControllerDragHelper.getSession() &&
- !PlacesControllerDragHelper.draggingOverChildNode(popup.parentNode)) {
- popup.hidePopup();
- // Close any parent menus that aren't being dragged over;
- // otherwise they'll stay open because they couldn't close
- // while this menu was being dragged over.
- this.closeParentMenus();
- }
- this._closeMenuTimer = null;
- }
- },
-
- // Helper function to close all parent menus of this menu,
- // as long as none of the parent's children are currently being
- // dragged over.
- closeParentMenus: function OF__closeParentMenus() {
- var popup = this._self;
- var parent = popup.parentNode;
- while (parent) {
- if (parent.localName == "menupopup" && parent._placesNode) {
- if (PlacesControllerDragHelper.draggingOverChildNode(parent.parentNode))
- break;
- parent.hidePopup();
- }
- parent = parent.parentNode;
- }
- },
-
- // The mouse is no longer dragging over the stored menubutton.
- // Close the menubutton, clear out drag styles, and clear all
- // timers for opening/closing it.
- clear: function OF__clear() {
- if (this._folder.elt && this._folder.elt.lastChild) {
- if (!this._folder.elt.lastChild.hasAttribute("dragover"))
- this._folder.elt.lastChild.hidePopup();
- // remove menuactive style
- this._folder.elt.removeAttribute("_moz-menuactive");
- this._folder.elt = null;
- }
- if (this._folder.openTimer) {
- this._folder.openTimer.cancel();
- this._folder.openTimer = null;
- }
- if (this._folder.closeTimer) {
- this._folder.closeTimer.cancel();
- this._folder.closeTimer = null;
- }
- }
- })]]></field>
-
- <method name="_cleanupDragDetails">
- <body><![CDATA[
- // Called on dragend and drop.
- PlacesControllerDragHelper.currentDropTarget = null;
- this._rootView._draggedElt = null;
- this.removeAttribute("dragover");
- this.removeAttribute("dragstart");
- this._indicatorBar.hidden = true;
- ]]></body>
- </method>
-
- </implementation>
-
- <handlers>
- <handler event="DOMMenuItemActive"><![CDATA[
- let elt = event.target;
- if (elt.parentNode != this)
- return;
-
-#ifdef XP_MACOSX
- // XXX: The following check is a temporary hack until bug 420033 is
- // resolved.
- let parentElt = elt.parent;
- while (parentElt) {
- if (parentElt.id == "bookmarksMenuPopup" ||
- parentElt.id == "goPopup")
- return;
-
- parentElt = parentElt.parentNode;
- }
-#endif
-
- if (window.XULBrowserWindow) {
- let elt = event.target;
- let placesNode = elt._placesNode;
-
- var linkURI;
- if (placesNode && PlacesUtils.nodeIsURI(placesNode))
- linkURI = placesNode.uri;
- else if (elt.hasAttribute("targetURI"))
- linkURI = elt.getAttribute("targetURI");
-
- if (linkURI)
- window.XULBrowserWindow.setOverLink(linkURI, null);
- }
- ]]></handler>
-
- <handler event="DOMMenuItemInactive"><![CDATA[
- let elt = event.target;
- if (elt.parentNode != this)
- return;
-
- if (window.XULBrowserWindow)
- window.XULBrowserWindow.setOverLink("", null);
- ]]></handler>
-
- <handler event="dragstart"><![CDATA[
- if (!event.target._placesNode)
- return;
-
- let draggedElt = event.target._placesNode;
-
- // Force a copy action if parent node is a query or we are dragging a
- // not-removable node.
- if (!PlacesControllerDragHelper.canMoveNode(draggedElt))
- event.dataTransfer.effectAllowed = "copyLink";
-
- // Activate the view and cache the dragged element.
- this._rootView._draggedElt = draggedElt;
- this._rootView.controller.setDataTransfer(event);
- this.setAttribute("dragstart", "true");
- event.stopPropagation();
- ]]></handler>
-
- <handler event="drop"><![CDATA[
- PlacesControllerDragHelper.currentDropTarget = event.target;
-
- let dropPoint = this._getDropPoint(event);
- if (dropPoint && dropPoint.ip) {
- PlacesControllerDragHelper.onDrop(dropPoint.ip, event.dataTransfer);
- event.preventDefault();
- }
-
- this._cleanupDragDetails();
- event.stopPropagation();
- ]]></handler>
-
- <handler event="dragover"><![CDATA[
- PlacesControllerDragHelper.currentDropTarget = event.target;
- let dt = event.dataTransfer;
-
- let dropPoint = this._getDropPoint(event);
- if (!dropPoint || !dropPoint.ip ||
- !PlacesControllerDragHelper.canDrop(dropPoint.ip, dt)) {
- this._indicatorBar.hidden = true;
- event.stopPropagation();
- return;
- }
-
- // Mark this popup as being dragged over.
- this.setAttribute("dragover", "true");
-
- if (dropPoint.folderElt) {
- // We are dragging over a folder.
- // _overFolder should take the care of opening it on a timer.
- if (this._overFolder.elt &&
- this._overFolder.elt != dropPoint.folderElt) {
- // We are dragging over a new folder, let's clear old values
- this._overFolder.clear();
- }
- if (!this._overFolder.elt) {
- this._overFolder.elt = dropPoint.folderElt;
- // Create the timer to open this folder.
- this._overFolder.openTimer = this._overFolder
- .setTimer(this._overFolder.hoverTime);
- }
- // Since we are dropping into a folder set the corresponding style.
- dropPoint.folderElt.setAttribute("_moz-menuactive", true);
- }
- else {
- // We are not dragging over a folder.
- // Clear out old _overFolder information.
- this._overFolder.clear();
- }
-
- // Autoscroll the popup strip if we drag over the scroll buttons.
- let anonid = event.originalTarget.getAttribute('anonid');
- let scrollDir = anonid == "scrollbutton-up" ? -1 :
- anonid == "scrollbutton-down" ? 1 : 0;
- if (scrollDir != 0) {
- this._scrollBox.scrollByIndex(scrollDir, false);
- }
-
- // Check if we should hide the drop indicator for this target.
- if (dropPoint.folderElt || this._hideDropIndicator(event)) {
- this._indicatorBar.hidden = true;
- event.preventDefault();
- event.stopPropagation();
- return;
- }
-
- // We should display the drop indicator relative to the arrowscrollbox.
- let sbo = this._scrollBox.scrollBoxObject;
- let newMarginTop = 0;
- if (scrollDir == 0) {
- let elt = this.firstChild;
- while (elt && event.screenY > elt.boxObject.screenY +
- elt.boxObject.height / 2)
- elt = elt.nextSibling;
- newMarginTop = elt ? elt.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;
-
- event.preventDefault();
- event.stopPropagation();
- ]]></handler>
-
- <handler event="dragexit"><![CDATA[
- PlacesControllerDragHelper.currentDropTarget = null;
- this.removeAttribute("dragover");
-
- // If we have not moved to a valid new target clear the drop indicator
- // this happens when moving out of the popup.
- let target = event.relatedTarget;
- if (!target)
- this._indicatorBar.hidden = true;
-
- // Close any folder being hovered over
- if (this._overFolder.elt) {
- this._overFolder.closeTimer = this._overFolder
- .setTimer(this._overFolder.hoverTime);
- }
-
- // The autoopened attribute is set when this folder was automatically
- // opened after the user dragged over it. If this attribute is set,
- // auto-close the folder on drag exit.
- // We should also try to close this popup if the drag has started
- // from here, the timer will check if we are dragging over a child.
- if (this.hasAttribute("autoopened") ||
- this.hasAttribute("dragstart")) {
- this._overFolder.closeMenuTimer = this._overFolder
- .setTimer(this._overFolder.hoverTime);
- }
-
- event.stopPropagation();
- ]]></handler>
-
- <handler event="dragend"><![CDATA[
- this._cleanupDragDetails();
- ]]></handler>
-
- </handlers>
- </binding>
-</bindings>
diff --git a/components/places/content/moveBookmarks.js b/components/places/content/moveBookmarks.js
deleted file mode 100644
index 964604f..0000000
--- a/components/places/content/moveBookmarks.js
+++ /dev/null
@@ -1,54 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-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;
-
- let txn = new PlacesMoveItemTransaction(this._nodes[i].itemId,
- selectedFolderID,
- PlacesUtils.bookmarks.DEFAULT_INDEX);
- transactions.push(txn);
- }
-
- if (transactions.length != 0) {
- let txn = new PlacesAggregatedTransaction("Move Items", transactions);
- PlacesUtils.transactionManager.doTransaction(txn);
- }
- },
-
- newFolder: function MBD_newFolder() {
- // The command is disabled when the tree is not focused
- this.foldersTree.focus();
- goDoCommand("placesCmd_new:folder");
- }
-};
diff --git a/components/places/content/moveBookmarks.xul b/components/places/content/moveBookmarks.xul
deleted file mode 100644
index b6e75f3..0000000
--- a/components/places/content/moveBookmarks.xul
+++ /dev/null
@@ -1,53 +0,0 @@
-<?xml version="1.0"?>
-
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<?xml-stylesheet href="chrome://global/skin/"?>
-<?xml-stylesheet href="chrome://browser/skin/places/places.css"?>
-<?xml-stylesheet href="chrome://browser/content/places/places.css"?>
-
-<?xul-overlay href="chrome://browser/content/places/placesOverlay.xul"?>
-
-<!DOCTYPE window [
- <!ENTITY % moveBookmarksDTD SYSTEM "chrome://browser/locale/places/moveBookmarks.dtd">
- %moveBookmarksDTD;
-]>
-
-<dialog id="moveBookmarkDialog"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- ondialogaccept="return gMoveBookmarksDialog.onOK(event);"
- title="&window.title;"
- onload="gMoveBookmarksDialog.init();"
- style="&window.style;"
- screenX="24"
- screenY="24"
- persist="screenX screenY width height">
-
- <script type="application/javascript"
- src="chrome://browser/content/places/moveBookmarks.js"/>
-
- <hbox flex="1">
- <label id="movetolabel" value="&moveTo.label;" control="foldersTree"/>
- <hbox flex="1">
- <tree id="foldersTree"
- class="placesTree"
- flex="1"
- type="places"
- seltype="single"
- hidecolumnpicker="true">
- <treecols>
- <treecol id="title" flex="1" primary="true" hideheader="true"/>
- </treecols>
- <treechildren id="placesListChildren" view="placesList" flex="1"/>
- </tree>
- <vbox>
- <button id="newFolderButton"
- label="&newFolderButton.label;"
- accesskey="&newFolderButton.accesskey;"
- oncommand="gMoveBookmarksDialog.newFolder();"/>
- </vbox>
- </hbox>
- </hbox>
-</dialog>
diff --git a/components/places/content/organizer.css b/components/places/content/organizer.css
deleted file mode 100644
index 47b1832..0000000
--- a/components/places/content/organizer.css
+++ /dev/null
@@ -1,7 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#searchFilter {
- width: 23em;
-}
diff --git a/components/places/content/places.css b/components/places/content/places.css
deleted file mode 100644
index 5151cca..0000000
--- a/components/places/content/places.css
+++ /dev/null
@@ -1,16 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-tree[type="places"] {
- -moz-binding: url("chrome://browser/content/places/tree.xml#places-tree");
-}
-
-.toolbar-drop-indicator {
- position: relative;
- z-index: 1;
-}
-
-menupopup[placespopup="true"] {
- -moz-binding: url("chrome://browser/content/places/menu.xml#places-popup-base");
-}
diff --git a/components/places/content/places.js b/components/places/content/places.js
deleted file mode 100644
index 40dbcb9..0000000
--- a/components/places/content/places.js
+++ /dev/null
@@ -1,1553 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "Task",
- "resource://gre/modules/Task.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "BookmarkJSONUtils",
- "resource://gre/modules/BookmarkJSONUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "PlacesBackups",
- "resource://gre/modules/PlacesBackups.jsm");
-
-const RESTORE_FILEPICKER_FILTER_EXT = "*.json;*.jsonlz4";
-
-var PlacesOrganizer = {
- _places: 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" || aQueryName == "History")
- PlacesUtils.asContainer(this._places.selectedNode).containerOpen = true;
- },
-
- init: function PO_init() {
- ContentArea.init();
-
- this._places = document.getElementById("placesList");
- this._initFolderTree();
-
- var leftPaneSelection = "AllBookmarks"; // default to all-bookmarks
- if (window.arguments && window.arguments[0])
- leftPaneSelection = window.arguments[0];
-
- this.selectLeftPaneQuery(leftPaneSelection);
- if (leftPaneSelection == "History") {
- let historyNode = this._places.selectedNode;
- if (historyNode.childCount > 0)
- this._places.selectNode(historyNode.getChild(0));
- }
- // clear the back-stack
- this._backHistory.splice(0, this._backHistory.length);
- document.getElementById("OrganizerCommand:Back").setAttribute("disabled", true);
-
- // Set up the search UI.
- PlacesSearchBox.init();
-
- window.addEventListener("AppCommand", this, true);
-#ifdef XP_MACOSX
- // 1. Map Edit->Find command to OrganizerCommand_find:all. Need to map
- // both the menuitem and the Find key.
- var findMenuItem = document.getElementById("menu_find");
- findMenuItem.setAttribute("command", "OrganizerCommand_find:all");
- var findKey = document.getElementById("key_find");
- findKey.setAttribute("command", "OrganizerCommand_find:all");
-
- // 2. Disable some keybindings from browser.xul
- var elements = ["cmd_handleBackspace", "cmd_handleShiftBackspace"];
- for (var i=0; i < elements.length; i++) {
- document.getElementById(elements[i]).setAttribute("disabled", "true");
- }
-
- // 3. Disable the keyboard shortcut for the History menu back/forward
- // in order to support those in the Library
- var historyMenuBack = document.getElementById("historyMenuBack");
- historyMenuBack.removeAttribute("key");
- var historyMenuForward = document.getElementById("historyMenuForward");
- historyMenuForward.removeAttribute("key");
-#endif
-
- // remove the "Properties" context-menu item, we've our own details pane
- document.getElementById("placesContext")
- .removeChild(document.getElementById("placesContext_show:info"));
-
- ContentArea.focus();
- },
-
- QueryInterface: function PO_QueryInterface(aIID) {
- if (aIID.equals(Components.interfaces.nsIDOMEventListener) ||
- aIID.equals(Components.interfaces.nsISupports))
- return this;
-
- throw new Components.Exception("", 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._forwardHistory.length);
- }
-
- 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
- ContentArea.currentPlace = aLocation;
- }
- this.updateDetailsPane();
-
- // 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 = PlacesUtils.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 (ContentArea.currentPlace != placeURI || !resetSearchBox) {
- ContentArea.currentPlace = placeURI;
- PlacesSearchBox.hideSearchUI();
- this.location = node.uri;
- }
-
- // Update the selected folder title where it appears in the UI: the folder
- // scope button, 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);
- 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);
- this.updateDetailsPane();
- },
-
- /**
- * Sets the search scope based on aNode's properties.
- * @param aNode
- * the node to set up scope from
- */
- _setSearchScopeForNode: function PO__setScopeForNode(aNode) {
- let itemId = aNode.itemId;
-
- // Set default buttons status.
- let bookmarksButton = document.getElementById("scopeBarAll");
- bookmarksButton.hidden = false;
- let downloadsButton = document.getElementById("scopeBarDownloads");
- downloadsButton.hidden = true;
-
- if (PlacesUtils.nodeIsHistoryContainer(aNode) ||
- itemId == PlacesUIUtils.leftPaneQueries["History"]) {
- PlacesQueryBuilder.setScope("history");
- }
- else if (itemId == PlacesUIUtils.leftPaneQueries["Downloads"]) {
- downloadsButton.hidden = false;
- bookmarksButton.hidden = true;
- PlacesQueryBuilder.setScope("downloads");
- }
- else {
- // Default to All Bookmarks for all other nodes, per bug 469437.
- PlacesQueryBuilder.setScope("bookmarks");
- }
-
- // Enable or disable the folder scope button.
- let folderButton = document.getElementById("scopeBarFolder");
- folderButton.hidden = !PlacesUtils.nodeIsFolder(aNode) ||
- itemId == PlacesUIUtils.allBookmarksFolderId;
- },
-
- /**
- * Handle clicks on the places list.
- * 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.
- */
- onPlacesListClick: function PO_onPlacesListClick(aEvent) {
- // Only handle clicks on tree children.
- if (aEvent.target.localName != "treechildren")
- return;
-
- let node = this._places.selectedNode;
- if (node) {
- let middleClick = aEvent.button == 1 && aEvent.detail == 1;
- if (middleClick && PlacesUtils.nodeIsContainer(node)) {
- // 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, this._places);
- }
- }
- },
-
- /**
- * Handle focus changes on the places list and the current content view.
- */
- updateDetailsPane: function PO_updateDetailsPane() {
- if (!ContentArea.currentViewOptions.showDetailsPane)
- return;
- let view = PlacesUIUtils.getViewForNode(document.activeElement);
- if (view) {
- let selectedNodes = view.selectedNode ?
- [view.selectedNode] : view.selectedNodes;
- 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);
- },
-
- /**
- * Returns the options associated with the query currently loaded in the
- * main places pane.
- */
- getCurrentOptions: function PO_getCurrentOptions() {
- return PlacesUtils.asQuery(ContentArea.currentView.result.root).queryOptions;
- },
-
- /**
- * Returns the queries associated with the query currently loaded in the
- * main places pane.
- */
- getCurrentQueries: function PO_getCurrentQueries() {
- return PlacesUtils.asQuery(ContentArea.currentView.result.root).getQueries();
- },
-
- /**
- * Open a file-picker and import the selected file into the bookmarks store
- */
- importFromFile: function PO_importFromFile() {
- let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
- let fpCallback = function fpCallback_done(aResult) {
- if (aResult != Ci.nsIFilePicker.returnCancel && fp.fileURL) {
- Components.utils.import("resource://gre/modules/BookmarkHTMLUtils.jsm");
- BookmarkHTMLUtils.importFromURL(fp.fileURL.spec, false)
- .then(null, Components.utils.reportError);
- }
- };
-
- fp.init(window, PlacesUIUtils.getString("SelectImport"),
- Ci.nsIFilePicker.modeOpen);
- fp.appendFilters(Ci.nsIFilePicker.filterHTML);
- fp.open(fpCallback);
- },
-
- /**
- * Allows simple exporting of bookmarks.
- */
- exportBookmarks: function PO_exportBookmarks() {
- let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
- let fpCallback = function fpCallback_done(aResult) {
- if (aResult != Ci.nsIFilePicker.returnCancel) {
- Components.utils.import("resource://gre/modules/BookmarkHTMLUtils.jsm");
- BookmarkHTMLUtils.exportToFile(fp.file.path)
- .then(null, Components.utils.reportError);
- }
- };
-
- fp.init(window, PlacesUIUtils.getString("EnterExport"),
- Ci.nsIFilePicker.modeSave);
- fp.appendFilters(Ci.nsIFilePicker.filterHTML);
- fp.defaultString = "bookmarks.html";
- fp.open(fpCallback);
- },
-
- /**
- * Populates the restore menu with the dates of the backups available.
- */
- populateRestoreMenu: function PO_populateRestoreMenu() {
- let restorePopup = document.getElementById("fileRestorePopup");
-
- let 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);
-
- Task.spawn(function() {
- let backupFiles = yield PlacesBackups.getBackupFiles();
- if (backupFiles.length == 0)
- return;
-
- // Populate menu with backups.
- for (let i = 0; i < backupFiles.length; i++) {
- let fileSize = (yield OS.File.stat(backupFiles[i])).size;
- let [size, unit] = DownloadUtils.convertByteUnits(fileSize);
- let sizeString = PlacesUtils.getFormattedString("backupFileSizeText",
- [size, unit]);
- let sizeInfo;
- let bookmarkCount = PlacesBackups.getBookmarkCountForFile(backupFiles[i]);
- if (bookmarkCount != null) {
- sizeInfo = " (" + sizeString + " - " +
- PlacesUIUtils.getPluralString("detailsPane.itemsCountLabel",
- bookmarkCount,
- [bookmarkCount]) +
- ")";
- } else {
- sizeInfo = " (" + sizeString + ")";
- }
-
- let backupDate = PlacesBackups.getDateForFile(backupFiles[i]);
- let m = restorePopup.insertBefore(document.createElement("menuitem"),
- document.getElementById("restoreFromFile"));
- m.setAttribute("label",
- dateSvc.FormatDate("",
- Ci.nsIScriptableDateFormat.dateFormatLong,
- backupDate.getFullYear(),
- backupDate.getMonth() + 1,
- backupDate.getDate()) +
- sizeInfo);
- m.setAttribute("value", OS.Path.basename(backupFiles[i]));
- m.setAttribute("oncommand",
- "PlacesOrganizer.onRestoreMenuItemClick(this);");
- }
-
- // Add the restoreFromFile item.
- restorePopup.insertBefore(document.createElement("menuseparator"),
- document.getElementById("restoreFromFile"));
- });
- },
-
- /**
- * Called when a menuitem is selected from the restore menu.
- */
- onRestoreMenuItemClick: function PO_onRestoreMenuItemClick(aMenuItem) {
- Task.spawn(function() {
- let backupName = aMenuItem.getAttribute("value");
- let backupFilePaths = yield PlacesBackups.getBackupFiles();
- for (let backupFilePath of backupFilePaths) {
- if (OS.Path.basename(backupFilePath) == backupName) {
- PlacesOrganizer.restoreBookmarksFromFile(new FileUtils.File(backupFilePath));
- break;
- }
- }
- });
- },
-
- /**
- * 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() {
- let dirSvc = Cc["@mozilla.org/file/directory_service;1"].
- getService(Ci.nsIProperties);
- let backupsDir = dirSvc.get("Desk", Ci.nsILocalFile);
- let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
- let fpCallback = function fpCallback_done(aResult) {
- if (aResult != Ci.nsIFilePicker.returnCancel) {
- this.restoreBookmarksFromFile(fp.file);
- }
- }.bind(this);
-
- fp.init(window, PlacesUIUtils.getString("bookmarksRestoreTitle"),
- Ci.nsIFilePicker.modeOpen);
- fp.appendFilter(PlacesUIUtils.getString("bookmarksRestoreFilterName"),
- RESTORE_FILEPICKER_FILTER_EXT);
- fp.appendFilters(Ci.nsIFilePicker.filterAll);
- fp.displayDirectory = backupsDir;
- fp.open(fpCallback);
- },
-
- /**
- * Restores bookmarks from a JSON file.
- */
- restoreBookmarksFromFile: function PO_restoreBookmarksFromFile(aFile) {
- // check file extension
- let filePath = aFile.path;
- if (!filePath.toLowerCase().endsWith("json") &&
- !filePath.toLowerCase().endsWith("jsonlz4")) {
- 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;
-
- Task.spawn(function() {
- try {
- yield BookmarkJSONUtils.importFromFile(aFile.path, true);
- } catch(ex) {
- PlacesOrganizer._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() {
- let dirSvc = Cc["@mozilla.org/file/directory_service;1"].
- getService(Ci.nsIProperties);
- let backupsDir = dirSvc.get("Desk", Ci.nsILocalFile);
- let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
- let fpCallback = function fpCallback_done(aResult) {
- if (aResult != Ci.nsIFilePicker.returnCancel) {
- BookmarkJSONUtils.exportToFile(fp.file.path);
- }
- };
-
- fp.init(window, PlacesUIUtils.getString("bookmarksBackupTitle"),
- Ci.nsIFilePicker.modeSave);
- fp.appendFilter(PlacesUIUtils.getString("bookmarksRestoreFilterName"),
- RESTORE_FILEPICKER_FILTER_EXT);
- fp.defaultString = PlacesBackups.getFilenameForDate();
- fp.displayDirectory = backupsDir;
- fp.open(fpCallback);
- },
-
- _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) && !aNode._feedURI) {
- 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;
- },
-
- _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
- , titleOverride: aSelectedNode.title
- });
-
- // 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.getPluralString("detailsPane.itemsCountLabel",
- aNodeList.length, [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;
- let selectItemDesc = document.getElementById("selectItemDescription");
- let itemsCountLabel = document.getElementById("itemsCountText");
- let itemsCount = 0;
- if (ContentArea.currentView.result) {
- let rootNode = ContentArea.currentView.result.root;
- if (rootNode.containerOpen)
- itemsCount = rootNode.childCount;
- }
- if (itemsCount == 0) {
- selectItemDesc.hidden = true;
- itemsCountLabel.value = PlacesUIUtils.getString("detailsPane.noItems");
- }
- else {
- selectItemDesc.hidden = false;
- itemsCountLabel.value =
- PlacesUIUtils.getPluralString("detailsPane.itemsCountLabel",
- itemsCount, [itemsCount]);
- }
- }
- },
-
- // 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();
- var queries = this.getCurrentQueries();
-
- 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.
- // XXX - 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 = new PlacesCreateBookmarkTransaction(placeURI,
- PlacesUtils.bookmarksMenuFolderId,
- PlacesUtils.bookmarks.DEFAULT_INDEX,
- input.value);
- PlacesUtils.transactionManager.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.
- // XXX this might be to jumpy, maybe should search for "", so results
- // are ungrouped, and search box not reset
- if (filterString == "") {
- PO.onPlaceSelected(false);
- return;
- }
-
- let currentView = ContentArea.currentView;
- let currentOptions = PO.getCurrentOptions();
-
- // Search according to the current scope and folders, which were set by
- // PQB_setScope()
- switch (PlacesSearchBox.filterCollection) {
- case "collection":
- currentView.applyFilter(filterString, this.folders);
- break;
- case "bookmarks":
- currentView.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.RESULTS_AS_URI;
- options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY;
- options.includeHidden = true;
- currentView.load([query], options);
- }
- else {
- currentView.applyFilter(filterString, null, true);
- }
- break;
- case "downloads":
- if (currentView == ContentTree.view) {
- let query = PlacesUtils.history.getNewQuery();
- query.searchTerms = filterString;
- query.setTransitions([Ci.nsINavHistoryService.TRANSITION_DOWNLOAD], 1);
- let options = currentOptions.clone();
- // Make sure we're getting uri results.
- options.resultType = currentOptions.RESULTS_AS_URI;
- options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY;
- options.includeHidden = true;
- currentView.load([query], options);
- }
- else {
- // The new downloads view doesn't use places for searching downloads.
- currentView.searchTerm = filterString;
- }
- break;
- default:
- throw new Components.Exception("Invalid filterCollection on search",
- Components.results.NS_ERROR_INVALID_ARG);
- }
-
- PlacesSearchBox.showSearchUI();
-
- // Update the details panel
- PlacesOrganizer.updateDetailsPane();
- },
-
- /**
- * Finds across all history, downloads or all bookmarks.
- */
- findAll: function PSB_findAll() {
- switch (this.filterCollection) {
- case "history":
- PlacesQueryBuilder.setScope("history");
- break;
- case "downloads":
- PlacesQueryBuilder.setScope("downloads");
- break;
- default:
- PlacesQueryBuilder.setScope("bookmarks");
- break;
- }
- this.focus();
- },
-
- /**
- * Updates the display with the title of the current collection.
- * @param aTitle
- * The title of the current collection.
- */
- updateCollectionTitle: function PSB_updateCollectionTitle(aTitle) {
- let title = "";
- // This is needed when a user performs a folder-specific search
- // using the scope bar, removes the search-string, and unfocuses
- // the search box, at least until the removal of the scope bar.
- if (aTitle) {
- title = PlacesUIUtils.getFormattedString("searchCurrentDefault",
- [aTitle]);
- }
- else {
- switch (this.filterCollection) {
- case "history":
- title = PlacesUIUtils.getString("searchHistory");
- break;
- case "downloads":
- title = PlacesUIUtils.getString("searchDownloads");
- break;
- default:
- title = PlacesUIUtils.getString("searchBookmarks");
- }
- }
- this.searchFilter.placeholder = title;
- },
-
- /**
- * 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;
- },
-
- hideSearchUI: function PSB_hideSearchUI() {
- var searchModifiers = document.getElementById("searchModifiers");
- searchModifiers.hidden = true;
- }
-};
-
-/**
- * Functions and data for advanced query builder
- */
-var PlacesQueryBuilder = {
-
- queries: [],
- queryOptions: null,
-
- /**
- * 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 "scopeBarDownloads":
- this.setScope("downloads");
- break;
- case "scopeBarAll":
- this.setScope("bookmarks");
- break;
- default:
- throw new Components.Exception("Invalid search scope button ID",
- Components.results.NS_ERROR_INVALID_ARG);
- 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", "downloads" 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;
- case "downloads":
- filterCollection = "downloads";
- scopeButtonId = "scopeBarDownloads";
- break;
- default:
- throw new Components.Exception("Invalid search scope",
- Components.results.NS_ERROR_INVALID_ARG);
- 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;
- if (popup.parentNode && (popup.parentNode.id == "viewSort")) {
- switch (column.id) {
- case "placesContentParentFolder":
- continue;
- case "placesContentParentFolderPath":
- continue;
- }
- }
- 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").result;
- 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: PlacesUIUtils.DESCRIPTION_ANNO }
- };
-
- // Make sure we have a valid column.
- if (!colLookupTable.hasOwnProperty(columnId))
- throw new Components.Exception("Invalid column",
- Components.results.NS_ERROR_INVALID_ARG);
-
- // 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];
- }
-}
-
-var ContentArea = {
- _specialViews: new Map(),
-
- init: function CA_init() {
- this._deck = document.getElementById("placesViewsDeck");
- this._toolbar = document.getElementById("placesToolbar");
- ContentTree.init();
- this._setupView();
- },
-
- /**
- * Gets the content view to be used for loading the given query.
- * If a custom view was set by setContentViewForQueryString, that
- * view would be returned, else the default tree view is returned
- *
- * @param aQueryString
- * a query string
- * @return the view to be used for loading aQueryString.
- */
- getContentViewForQueryString:
- function CA_getContentViewForQueryString(aQueryString) {
- try {
- if (this._specialViews.has(aQueryString)) {
- let { view, options } = this._specialViews.get(aQueryString);
- if (typeof view == "function") {
- view = view();
- this._specialViews.set(aQueryString, { view: view, options: options });
- }
- return view;
- }
- }
- catch(ex) {
- Components.utils.reportError(ex);
- }
- return ContentTree.view;
- },
-
- /**
- * Sets a custom view to be used rather than the default places tree
- * whenever the given query is selected in the left pane.
- * @param aQueryString
- * a query string
- * @param aView
- * Either the custom view or a function that will return the view
- * the first (and only) time it's called.
- * @param [optional] aOptions
- * Object defining special options for the view.
- * @see ContentTree.viewOptions for supported options and default values.
- */
- setContentViewForQueryString:
- function CA_setContentViewForQueryString(aQueryString, aView, aOptions) {
- if (!aQueryString ||
- typeof aView != "object" && typeof aView != "function")
- throw new Components.Exception("Invalid arguments",
- Components.results.NS_ERROR_INVALID_ARG);
-
- this._specialViews.set(aQueryString, { view: aView,
- options: aOptions || new Object() });
- },
-
- get currentView() PlacesUIUtils.getViewForNode(this._deck.selectedPanel),
- set currentView(aNewView) {
- let oldView = this.currentView;
- if (oldView != aNewView) {
- this._deck.selectedPanel = aNewView.associatedElement;
-
- // If the content area inactivated view was focused, move focus
- // to the new view.
- if (document.activeElement == oldView.associatedElement)
- aNewView.associatedElement.focus();
- }
- return aNewView;
- },
-
- get currentPlace() this.currentView.place,
- set currentPlace(aQueryString) {
- let oldView = this.currentView;
- let newView = this.getContentViewForQueryString(aQueryString);
- newView.place = aQueryString;
- if (oldView != newView) {
- oldView.active = false;
- this.currentView = newView;
- this._setupView();
- newView.active = true;
- }
- return aQueryString;
- },
-
- /**
- * Applies view options.
- */
- _setupView: function CA__setupView() {
- let options = this.currentViewOptions;
-
- // showDetailsPane.
- let detailsDeck = document.getElementById("detailsDeck");
- detailsDeck.hidden = !options.showDetailsPane;
-
- // toolbarSet.
- for (let elt of this._toolbar.childNodes) {
- // On Windows and Linux the menu buttons are menus wrapped in a menubar.
- if (elt.id == "placesMenu") {
- for (let menuElt of elt.childNodes) {
- menuElt.hidden = options.toolbarSet.indexOf(menuElt.id) == -1;
- }
- }
- else {
- elt.hidden = options.toolbarSet.indexOf(elt.id) == -1;
- }
- }
- },
-
- /**
- * Options for the current view.
- *
- * @see ContentTree.viewOptions for supported options and default values.
- */
- get currentViewOptions() {
- // Use ContentTree options as default.
- let viewOptions = ContentTree.viewOptions;
- if (this._specialViews.has(this.currentPlace)) {
- let { view, options } = this._specialViews.get(this.currentPlace);
- for (let option in options) {
- viewOptions[option] = options[option];
- }
- }
- return viewOptions;
- },
-
- focus: function() {
- this._deck.selectedPanel.focus();
- }
-};
-
-var ContentTree = {
- init: function CT_init() {
- this._view = document.getElementById("placeContent");
- },
-
- get view() this._view,
-
- get viewOptions() Object.seal({
- showDetailsPane: true,
- toolbarSet: "back-button, forward-button, organizeButton, viewMenu, maintenanceButton, libraryToolbarSpacer, searchFilter"
- }),
-
- openSelectedNode: function CT_openSelectedNode(aEvent) {
- let view = this.view;
- PlacesUIUtils.openNodeWithEvent(view.selectedNode, aEvent, view);
- },
-
- onClick: function CT_onClick(aEvent) {
- let node = this.view.selectedNode;
- if (node) {
- let doubleClick = aEvent.button == 0 && aEvent.detail == 2;
- let middleClick = aEvent.button == 1 && aEvent.detail == 1;
- if (PlacesUtils.nodeIsURI(node) && (doubleClick || middleClick)) {
- // Open associated uri in the browser.
- this.openSelectedNode(aEvent);
- }
- else if (middleClick && PlacesUtils.nodeIsContainer(node)) {
- // 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(node, aEvent, this.view);
- }
- }
- },
-
- onKeyPress: function CT_onKeyPress(aEvent) {
- if (aEvent.keyCode == KeyEvent.DOM_VK_RETURN)
- this.openSelectedNode(aEvent);
- }
-};
diff --git a/components/places/content/places.xul b/components/places/content/places.xul
deleted file mode 100644
index 92e8a70..0000000
--- a/components/places/content/places.xul
+++ /dev/null
@@ -1,471 +0,0 @@
-<?xml version="1.0"?>
-
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-<?xml-stylesheet href="chrome://browser/content/places/places.css"?>
-<?xml-stylesheet href="chrome://browser/content/places/organizer.css"?>
-
-<?xml-stylesheet href="chrome://global/skin/"?>
-<?xml-stylesheet href="chrome://browser/skin/places/places.css"?>
-<?xml-stylesheet href="chrome://browser/skin/places/organizer.css"?>
-
-<?xul-overlay href="chrome://browser/content/places/editBookmarkOverlay.xul"?>
-
-#ifdef XP_MACOSX
-<?xul-overlay href="chrome://browser/content/macBrowserOverlay.xul"?>
-#else
-<?xul-overlay href="chrome://browser/content/baseMenuOverlay.xul"?>
-<?xul-overlay href="chrome://global/content/editMenuOverlay.xul"?>
-<?xul-overlay href="chrome://browser/content/places/placesOverlay.xul"?>
-#endif
-
-<!DOCTYPE window [
-<!ENTITY % placesDTD SYSTEM "chrome://browser/locale/places/places.dtd">
-%placesDTD;
-<!ENTITY % editMenuOverlayDTD SYSTEM "chrome://global/locale/editMenuOverlay.dtd">
-%editMenuOverlayDTD;
-<!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd">
-%browserDTD;
-]>
-
-<window id="places"
- title="&places.library.title;"
- windowtype="Places:Organizer"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml"
- onload="PlacesOrganizer.init();"
- onunload="PlacesOrganizer.destroy();"
- width="&places.library.width;" height="&places.library.height;"
- screenX="10" screenY="10"
- toggletoolbar="true"
- persist="width height screenX screenY sizemode">
-
- <script type="application/javascript"
- src="chrome://browser/content/places/places.js"/>
- <script type="application/javascript"
- src="chrome://browser/content/utilityOverlay.js"/>
- <script type="application/javascript"
- src="chrome://browser/content/places/editBookmarkOverlay.js"/>
-
- <stringbundleset id="placesStringSet">
- <stringbundle id="brandStrings" src="chrome://branding/locale/brand.properties"/>
- </stringbundleset>
-
-#ifdef XP_MACOSX
-#include ../../../base/content/browserMountPoints.inc
-#else
- <commandset id="editMenuCommands"/>
- <commandset id="placesCommands"/>
-#endif
- <keyset id="placesCommandKeys"/>
-
- <commandset id="organizerCommandSet">
- <command id="OrganizerCommand_find:all"
- oncommand="PlacesSearchBox.findAll();"/>
- <command id="OrganizerCommand_export"
- oncommand="PlacesOrganizer.exportBookmarks();"/>
- <command id="OrganizerCommand_import"
- oncommand="PlacesOrganizer.importFromFile();"/>
- <command id="OrganizerCommand_backup"
- oncommand="PlacesOrganizer.backupBookmarks();"/>
- <command id="OrganizerCommand_restoreFromFile"
- oncommand="PlacesOrganizer.onRestoreBookmarksFromFile();"/>
- <command id="OrganizerCommand_search:save"
- oncommand="PlacesOrganizer.saveSearch();"/>
- <command id="OrganizerCommand_search:moreCriteria"
- oncommand="PlacesQueryBuilder.addRow();"/>
- <command id="OrganizerCommand:Back"
- oncommand="PlacesOrganizer.back();"/>
- <command id="OrganizerCommand:Forward"
- oncommand="PlacesOrganizer.forward();"/>
- </commandset>
-
- <keyset id="placesOrganizerKeyset">
- <!-- Instantiation Keys -->
- <key id="placesKey_close" key="&cmd.close.key;" modifiers="accel"
- oncommand="close();"/>
-
- <!-- Command Keys -->
- <key id="placesKey_find:all"
- command="OrganizerCommand_find:all"
- key="&cmd.find.key;"
- modifiers="accel"/>
-
- <!-- Back/Forward Keys Support -->
-#ifndef XP_MACOSX
- <key id="placesKey_goBackKb"
- keycode="VK_LEFT"
- command="OrganizerCommand:Back"
- modifiers="alt"/>
- <key id="placesKey_goForwardKb"
- keycode="VK_RIGHT"
- command="OrganizerCommand:Forward"
- modifiers="alt"/>
-#else
- <key id="placesKey_goBackKb"
- keycode="VK_LEFT"
- command="OrganizerCommand:Back"
- modifiers="accel"/>
- <key id="placesKey_goForwardKb"
- keycode="VK_RIGHT"
- command="OrganizerCommand:Forward"
- modifiers="accel"/>
-#endif
-#ifdef XP_UNIX
- <key id="placesKey_goBackKb2"
- key="&goBackCmd.commandKey;"
- command="OrganizerCommand:Back"
- modifiers="accel"/>
- <key id="placesKey_goForwardKb2"
- key="&goForwardCmd.commandKey;"
- command="OrganizerCommand:Forward"
- modifiers="accel"/>
-#endif
- </keyset>
-
- <keyset id="editMenuKeys">
-#ifdef XP_MACOSX
- <key id="key_delete2" keycode="VK_BACK" command="cmd_delete"/>
-#endif
- </keyset>
-
- <popupset id="placesPopupset">
- <menupopup id="placesContext"/>
- <menupopup id="placesColumnsContext"
- onpopupshowing="ViewMenu.fillWithColumns(event, null, null, 'checkbox', null);"
- oncommand="ViewMenu.showHideColumn(event.target); event.stopPropagation();"/>
- </popupset>
-
- <toolbox id="placesToolbox">
- <toolbar class="chromeclass-toolbar" id="placesToolbar" align="center">
- <toolbarbutton id="back-button"
- command="OrganizerCommand:Back"
- tooltiptext="&backButton.tooltip;"
- disabled="true"/>
-
- <toolbarbutton id="forward-button"
- command="OrganizerCommand:Forward"
- tooltiptext="&forwardButton.tooltip;"
- disabled="true"/>
-
-#ifdef XP_MACOSX
- <toolbarbutton type="menu" class="tabbable"
- onpopupshowing="document.getElementById('placeContent').focus()"
-#else
- <menubar id="placesMenu">
- <menu accesskey="&organize.accesskey;" class="menu-iconic"
-#endif
- id="organizeButton" label="&organize.label;"
- tooltiptext="&organize.tooltip;">
- <menupopup id="organizeButtonPopup">
- <menuitem id="newbookmark"
- command="placesCmd_new:bookmark"
- label="&cmd.new_bookmark.label;"
- accesskey="&cmd.new_bookmark.accesskey;"/>
- <menuitem id="newfolder"
- command="placesCmd_new:folder"
- label="&cmd.new_folder.label;"
- accesskey="&cmd.new_folder.accesskey;"/>
- <menuitem id="newseparator"
- command="placesCmd_new:separator"
- label="&cmd.new_separator.label;"
- accesskey="&cmd.new_separator.accesskey;"/>
-
-#ifndef XP_MACOSX
- <menuseparator id="orgUndoSeparator"/>
-
- <menuitem id="orgUndo"
- command="cmd_undo"
- label="&undoCmd.label;"
- key="key_undo"
- accesskey="&undoCmd.accesskey;"/>
- <menuitem id="orgRedo"
- command="cmd_redo"
- label="&redoCmd.label;"
- key="key_redo"
- accesskey="&redoCmd.accesskey;"/>
-
- <menuseparator id="orgCutSeparator"/>
-
- <menuitem id="orgCut"
- command="cmd_cut"
- label="&cutCmd.label;"
- key="key_cut"
- accesskey="&cutCmd.accesskey;"
- selection="separator|link|folder|mixed"/>
- <menuitem id="orgCopy"
- command="cmd_copy"
- label="&copyCmd.label;"
- key="key_copy"
- accesskey="&copyCmd.accesskey;"
- selection="separator|link|folder|mixed"/>
- <menuitem id="orgPaste"
- command="cmd_paste"
- label="&pasteCmd.label;"
- key="key_paste"
- accesskey="&pasteCmd.accesskey;"
- selection="mutable"/>
- <menuitem id="orgDelete"
- command="cmd_delete"
- label="&deleteCmd.label;"
- key="key_delete"
- accesskey="&deleteCmd.accesskey;"/>
-
- <menuseparator id="selectAllSeparator"/>
-
- <menuitem id="orgSelectAll"
- command="cmd_selectAll"
- label="&selectAllCmd.label;"
- key="key_selectAll"
- accesskey="&selectAllCmd.accesskey;"/>
-
-#endif
- <menuseparator id="orgMoveSeparator"/>
-
- <menuitem id="orgMoveBookmarks"
- command="placesCmd_moveBookmarks"
- label="&cmd.moveBookmarks.label;"
- accesskey="&cmd.moveBookmarks.accesskey;"/>
-#ifdef XP_MACOSX
- <menuitem id="orgDelete"
- command="cmd_delete"
- label="&deleteCmd.label;"
- key="key_delete"
- accesskey="&deleteCmd.accesskey;"/>
-#else
- <menuseparator id="orgCloseSeparator"/>
-
- <menuitem id="orgClose"
- key="placesKey_close"
- label="&file.close.label;"
- accesskey="&file.close.accesskey;"
- oncommand="close();"/>
-#endif
- </menupopup>
-#ifdef XP_MACOSX
- </toolbarbutton>
- <toolbarbutton type="menu" class="tabbable"
-#else
- </menu>
- <menu accesskey="&views.accesskey;" class="menu-iconic"
-#endif
- id="viewMenu" label="&views.label;"
- tooltiptext="&views.tooltip;">
- <menupopup id="viewMenuPopup">
-
- <menu id="viewColumns"
- label="&view.columns.label;" accesskey="&view.columns.accesskey;">
- <menupopup onpopupshowing="ViewMenu.fillWithColumns(event, null, null, 'checkbox', null);"
- oncommand="ViewMenu.showHideColumn(event.target); event.stopPropagation();"/>
- </menu>
-
- <menu id="viewSort" label="&view.sort.label;"
- accesskey="&view.sort.accesskey;">
- <menupopup onpopupshowing="ViewMenu.populateSortMenu(event);"
- oncommand="ViewMenu.setSortColumn(event.target.column, null);">
- <menuitem id="viewUnsorted" type="radio" name="columns"
- label="&view.unsorted.label;" accesskey="&view.unsorted.accesskey;"
- oncommand="ViewMenu.setSortColumn(null, null);"/>
- <menuseparator id="directionSeparator"/>
- <menuitem id="viewSortAscending" type="radio" name="direction"
- label="&view.sortAscending.label;" accesskey="&view.sortAscending.accesskey;"
- oncommand="ViewMenu.setSortColumn(null, 'ascending'); event.stopPropagation();"/>
- <menuitem id="viewSortDescending" type="radio" name="direction"
- label="&view.sortDescending.label;" accesskey="&view.sortDescending.accesskey;"
- oncommand="ViewMenu.setSortColumn(null, 'descending'); event.stopPropagation();"/>
- </menupopup>
- </menu>
- </menupopup>
-#ifdef XP_MACOSX
- </toolbarbutton>
- <toolbarbutton type="menu" class="tabbable"
-#else
- </menu>
- <menu accesskey="&maintenance.accesskey;" class="menu-iconic"
-#endif
- id="maintenanceButton" label="&maintenance.label;"
- tooltiptext="&maintenance.tooltip;">
- <menupopup id="maintenanceButtonPopup">
- <menuitem id="backupBookmarks"
- command="OrganizerCommand_backup"
- label="&cmd.backup.label;"
- accesskey="&cmd.backup.accesskey;"/>
- <menu id="fileRestoreMenu" label="&cmd.restore2.label;"
- accesskey="&cmd.restore2.accesskey;">
- <menupopup id="fileRestorePopup" onpopupshowing="PlacesOrganizer.populateRestoreMenu();">
- <menuitem id="restoreFromFile"
- command="OrganizerCommand_restoreFromFile"
- label="&cmd.restoreFromFile.label;"
- accesskey="&cmd.restoreFromFile.accesskey;"/>
- </menupopup>
- </menu>
- <menuseparator/>
- <menuitem id="fileImport"
- command="OrganizerCommand_import"
- label="&importBookmarksFromHTML.label;"
- accesskey="&importBookmarksFromHTML.accesskey;"/>
- <menuitem id="fileExport"
- command="OrganizerCommand_export"
- label="&exportBookmarksToHTML.label;"
- accesskey="&exportBookmarksToHTML.accesskey;"/>
- </menupopup>
-#ifdef XP_MACOSX
- </toolbarbutton>
-#else
- </menu>
- </menubar>
-#endif
-
- <spacer id="libraryToolbarSpacer" flex="1"/>
-
- <textbox id="searchFilter"
- clickSelectsAll="true"
- type="search"
- aria-controls="placeContent"
- oncommand="PlacesSearchBox.search(this.value);"
- collection="bookmarks">
- </textbox>
- </toolbar>
- </toolbox>
-
- <hbox flex="1" id="placesView">
- <tree id="placesList"
- class="plain placesTree"
- type="places"
- hidecolumnpicker="true" context="placesContext"
- onselect="PlacesOrganizer.onPlaceSelected(true);"
- onclick="PlacesOrganizer.onPlacesListClick(event);"
- onfocus="PlacesOrganizer.updateDetailsPane(event);"
- seltype="single"
- persist="width"
- width="200"
- minwidth="100"
- maxwidth="400">
- <treecols>
- <treecol anonid="title" flex="1" primary="true" hideheader="true"/>
- </treecols>
- <treechildren flex="1"/>
- </tree>
- <splitter collapse="none" persist="state"></splitter>
- <vbox id="contentView" flex="4">
- <toolbox id="searchModifiers" hidden="true">
- <toolbar id="organizerScopeBar" class="chromeclass-toolbar" align="center">
- <label id="scopeBarTitle" value="&search.in.label;"/>
- <toolbarbutton id="scopeBarAll" class="small-margin"
- type="radio" group="scopeBar"
- oncommand="PlacesQueryBuilder.onScopeSelected(this);"
- label="&search.scopeBookmarks.label;"
- accesskey="&search.scopeBookmarks.accesskey;"/>
- <toolbarbutton id="scopeBarHistory" class="small-margin"
- type="radio" group="scopeBar"
- oncommand="PlacesQueryBuilder.onScopeSelected(this);"
- label="&search.scopeHistory.label;"
- accesskey="&search.scopeHistory.accesskey;"/>
- <toolbarbutton id="scopeBarDownloads" class="small-margin"
- type="radio" group="scopeBar"
- oncommand="PlacesQueryBuilder.onScopeSelected(this);"
- label="&search.scopeDownloads.label;"
- accesskey="&search.scopeDownloads.accesskey;"/>
- <toolbarbutton id="scopeBarFolder" class="small-margin"
- type="radio" group="scopeBar"
- oncommand="PlacesQueryBuilder.onScopeSelected(this);"
- accesskey="&search.scopeFolder.accesskey;"
- emptytitle="&search.scopeFolder.label;" flex="1"/>
- <!-- The folder scope button should flex but not take up more room
- than its label needs. The only simple way to do that is to
- set a really big flex on the spacer, e.g., 2^31 - 1. -->
- <spacer flex="2147483647"/>
- <button id="saveSearch" class="small-margin"
- label="&saveSearch.label;" accesskey="&saveSearch.accesskey;"
- command="OrganizerCommand_search:save"/>
- </toolbar>
- </toolbox>
- <deck id="placesViewsDeck"
- selectedIndex="0"
- flex="1">
- <tree id="placeContent"
- class="plain placesTree"
- context="placesContext"
- hidecolumnpicker="true"
- flex="1"
- type="places"
- flatList="true"
- selectfirstnode="true"
- enableColumnDrag="true"
- onfocus="PlacesOrganizer.updateDetailsPane(event)"
- onselect="PlacesOrganizer.updateDetailsPane(event)"
- onkeypress="ContentTree.onKeyPress(event);"
- onopenflatcontainer="PlacesOrganizer.openFlatContainer(aContainer);">
- <treecols id="placeContentColumns" context="placesColumnsContext">
- <treecol label="&col.name.label;" id="placesContentTitle" anonid="title" flex="5" primary="true" ordinal="1"
- persist="width hidden ordinal sortActive sortDirection"/>
- <splitter class="tree-splitter"/>
- <treecol label="&col.tags.label;" id="placesContentTags" anonid="tags" flex="2"
- persist="width hidden ordinal sortActive sortDirection"/>
- <splitter class="tree-splitter"/>
- <treecol label="&col.url.label;" id="placesContentUrl" anonid="url" flex="5"
- persist="width hidden ordinal sortActive sortDirection"/>
- <splitter class="tree-splitter"/>
- <treecol label="&col.lastvisit.label;" id="placesContentDate" anonid="date" flex="1" hidden="true"
- persist="width hidden ordinal sortActive sortDirection"/>
- <splitter class="tree-splitter"/>
- <treecol label="&col.visitcount.label;" id="placesContentVisitCount" anonid="visitCount" flex="1" hidden="true"
- persist="width hidden ordinal sortActive sortDirection"/>
- <splitter class="tree-splitter"/>
- <treecol label="&col.keyword.label;" id="placesContentKeyword" anonid="keyword" flex="1" hidden="true"
- persist="width hidden ordinal sortActive sortDirection"/>
- <splitter class="tree-splitter"/>
- <treecol label="&col.description.label;" id="placesContentDescription" anonid="description" flex="1" hidden="true"
- persist="width hidden ordinal sortActive sortDirection"/>
- <splitter class="tree-splitter"/>
- <treecol label="&col.dateadded.label;" id="placesContentDateAdded" anonid="dateAdded" flex="1" hidden="true"
- persist="width hidden ordinal sortActive sortDirection"/>
- <splitter class="tree-splitter"/>
- <treecol label="&col.lastmodified.label;" id="placesContentLastModified" anonid="lastModified" flex="1" hidden="true"
- persist="width hidden ordinal sortActive sortDirection"/>
- <splitter class="tree-splitter"/>
- <treecol label="&col.parentfolder.label;" id="placesContentParentFolder" anonid="parentFolder" flex="1" hidden="true"
- persist="width hidden ordinal"/>
- <splitter class="tree-splitter"/>
- <treecol label="&col.parentfolderpath.label;" id="placesContentParentFolderPath" anonid="parentFolderPath" flex="1" hidden="true"
- persist="width hidden ordinal"/>
- </treecols>
- <treechildren flex="1" onclick="ContentTree.onClick(event);"/>
- </tree>
- </deck>
- <deck id="detailsDeck" style="height: 11em;">
- <vbox id="itemsCountBox" align="center">
- <spacer flex="3"/>
- <label id="itemsCountText"/>
- <spacer flex="1"/>
- <description id="selectItemDescription">
- &detailsPane.selectAnItemText.description;
- </description>
- <spacer flex="3"/>
- </vbox>
- <vbox id="infoBox" minimal="true">
- <vbox id="editBookmarkPanelContent" flex="1"/>
- <hbox id="infoBoxExpanderWrapper" align="center">
-
- <button type="image" id="infoBoxExpander"
- class="expander-down"
- oncommand="PlacesOrganizer.toggleAdditionalInfoFields();"
- observes="paneElementsBroadcaster"/>
-
- <label id="infoBoxExpanderLabel"
- lesslabel="&detailsPane.less.label;"
- lessaccesskey="&detailsPane.less.accesskey;"
- morelabel="&detailsPane.more.label;"
- moreaccesskey="&detailsPane.more.accesskey;"
- value="&detailsPane.more.label;"
- accesskey="&detailsPane.more.accesskey;"
- control="infoBoxExpander"/>
-
- </hbox>
- </vbox>
- </deck>
- </vbox>
- </hbox>
-</window>
diff --git a/components/places/content/placesOverlay.xul b/components/places/content/placesOverlay.xul
deleted file mode 100644
index 59115a5..0000000
--- a/components/places/content/placesOverlay.xul
+++ /dev/null
@@ -1,247 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!DOCTYPE overlay [
-<!ENTITY % placesDTD SYSTEM "chrome://browser/locale/places/places.dtd">
-%placesDTD;
-<!ENTITY % editMenuOverlayDTD SYSTEM "chrome://global/locale/editMenuOverlay.dtd">
-%editMenuOverlayDTD;
-]>
-
-<overlay id="placesOverlay"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-
- <script type="application/javascript"
- src="chrome://global/content/globalOverlay.js"/>
- <script type="application/javascript"
- src="chrome://browser/content/utilityOverlay.js"/>
- <script type="application/javascript"><![CDATA[
- // TODO: Bug 406371.
- // A bunch of browser code depends on us defining these, sad but true :(
- var Cc = Components.classes;
- var Ci = Components.interfaces;
- var Cr = Components.results;
-
- Components.utils.import("resource://gre/modules/PlacesUtils.jsm");
- Components.utils.import("resource:///modules/PlacesUIUtils.jsm");
- ]]></script>
- <script type="application/javascript"
- src="chrome://browser/content/places/controller.js"/>
- <script type="application/javascript"
- src="chrome://browser/content/places/treeView.js"/>
-
- <!-- Bookmarks and history tooltip -->
- <tooltip id="bhTooltip" noautohide="true"
- onpopupshowing="return window.top.BookmarksEventHandler.fillInBHTooltip(document, event)">
- <vbox id="bhTooltipTextBox" flex="1">
- <label id="bhtTitleText" class="tooltip-label" />
- <label id="bhtUrlText" crop="center" class="tooltip-label" />
- </vbox>
- </tooltip>
-
- <commandset id="placesCommands"
- commandupdater="true"
- events="focus,sort,places"
- oncommandupdate="goUpdatePlacesCommands();">
- <command id="placesCmd_open"
- oncommand="goDoPlacesCommand('placesCmd_open');"/>
- <command id="placesCmd_open:window"
- oncommand="goDoPlacesCommand('placesCmd_open:window');"/>
- <command id="placesCmd_open:privatewindow"
- oncommand="goDoPlacesCommand('placesCmd_open:privatewindow');"/>
- <command id="placesCmd_open:tab"
- oncommand="goDoPlacesCommand('placesCmd_open:tab');"/>
-
- <command id="placesCmd_new:bookmark"
- oncommand="goDoPlacesCommand('placesCmd_new:bookmark');"/>
- <command id="placesCmd_new:livemark"
- oncommand="goDoPlacesCommand('placesCmd_new:livemark');"/>
- <command id="placesCmd_new:folder"
- oncommand="goDoPlacesCommand('placesCmd_new:folder');"/>
- <command id="placesCmd_new:separator"
- oncommand="goDoPlacesCommand('placesCmd_new:separator');"/>
- <command id="placesCmd_show:info"
- oncommand="goDoPlacesCommand('placesCmd_show:info');"/>
- <command id="placesCmd_rename"
- oncommand="goDoPlacesCommand('placesCmd_show:info');"
- observes="placesCmd_show:info"/>
- <command id="placesCmd_reload"
- oncommand="goDoPlacesCommand('placesCmd_reload');"/>
- <command id="placesCmd_sortBy:name"
- oncommand="goDoPlacesCommand('placesCmd_sortBy:name');"/>
- <command id="placesCmd_moveBookmarks"
- oncommand="goDoPlacesCommand('placesCmd_moveBookmarks');"/>
- <command id="placesCmd_deleteDataHost"
- oncommand="goDoPlacesCommand('placesCmd_deleteDataHost');"/>
- <command id="placesCmd_createBookmark"
- oncommand="goDoPlacesCommand('placesCmd_createBookmark');"/>
- <command id="placesCmd_openParentFolder"
- oncommand="goDoPlacesCommand('placesCmd_openParentFolder');"/>
-
- <!-- Special versions of cut/copy/paste/delete which check for an open context menu. -->
- <command id="placesCmd_cut"
- oncommand="goDoPlacesCommand('placesCmd_cut');"/>
- <command id="placesCmd_copy"
- oncommand="goDoPlacesCommand('placesCmd_copy');"/>
- <command id="placesCmd_paste"
- oncommand="goDoPlacesCommand('placesCmd_paste');"/>
- <command id="placesCmd_delete"
- oncommand="goDoPlacesCommand('placesCmd_delete');"/>
- </commandset>
-
- <keyset id="placesCommandKeys">
- <key id="key_placesCmd_openParentFolder"
- keycode="VK_F1"
- command="placesCmd_openParentFolder"
- modifiers="accel,shift"/>
- </keyset>
-
- <menupopup id="placesContext"
- onpopupshowing="this._view = PlacesUIUtils.getViewForNode(document.popupNode);
- return this._view.buildContextMenu(this);"
- onpopuphiding="this._view.destroyContextMenu();">
- <menuitem id="placesContext_open"
- command="placesCmd_open"
- label="&cmd.open.label;"
- accesskey="&cmd.open.accesskey;"
- default="true"
- selectiontype="single"
- selection="link"/>
- <menuitem id="placesContext_open:newtab"
- command="placesCmd_open:tab"
- label="&cmd.open_tab.label;"
- accesskey="&cmd.open_tab.accesskey;"
- selectiontype="single"
- selection="link"/>
- <menuitem id="placesContext_openContainer:tabs"
- oncommand="var view = PlacesUIUtils.getViewForNode(document.popupNode);
- view.controller.openSelectionInTabs(event);"
- onclick="checkForMiddleClick(this, event);"
- label="&cmd.open_all_in_tabs.label;"
- accesskey="&cmd.open_all_in_tabs.accesskey;"
- selectiontype="single"
- selection="folder|host|query"/>
- <menuitem id="placesContext_openLinks:tabs"
- oncommand="var view = PlacesUIUtils.getViewForNode(document.popupNode);
- view.controller.openSelectionInTabs(event);"
- onclick="checkForMiddleClick(this, event);"
- label="&cmd.open_all_in_tabs.label;"
- accesskey="&cmd.open_all_in_tabs.accesskey;"
- selectiontype="multiple"
- selection="link"/>
- <menuitem id="placesContext_open:newwindow"
- command="placesCmd_open:window"
- label="&cmd.open_window.label;"
- accesskey="&cmd.open_window.accesskey;"
- selectiontype="single"
- selection="link"/>
- <menuitem id="placesContext_open:newprivatewindow"
- command="placesCmd_open:privatewindow"
- label="&cmd.open_private_window.label;"
- accesskey="&cmd.open_private_window.accesskey;"
- selectiontype="single"
- selection="link"
- hideifprivatebrowsing="true"/>
- <menuseparator id="placesContext_openSeparator"/>
- <menuitem id="placesContext_new:bookmark"
- command="placesCmd_new:bookmark"
- label="&cmd.new_bookmark.label;"
- accesskey="&cmd.new_bookmark.accesskey;"
- selectiontype="any"
- hideifnoinsertionpoint="true"/>
- <menuitem id="placesContext_new:folder"
- command="placesCmd_new:folder"
- label="&cmd.new_folder.label;"
- accesskey="&cmd.context_new_folder.accesskey;"
- selectiontype="any"
- hideifnoinsertionpoint="true"/>
- <menuitem id="placesContext_new:separator"
- command="placesCmd_new:separator"
- label="&cmd.new_separator.label;"
- accesskey="&cmd.new_separator.accesskey;"
- closemenu="single"
- selectiontype="any"
- hideifnoinsertionpoint="true"/>
- <menuseparator id="placesContext_newSeparator"/>
- <menuitem id="placesContext_createBookmark"
- command="placesCmd_createBookmark"
- label="&cmd.bookmarkLink.label;"
- accesskey="&cmd.bookmarkLink.accesskey;"
- selection="link"
- forcehideselection="bookmark|tagChild"/>
- <menuitem id="placesContext_cut"
- command="placesCmd_cut"
- label="&cutCmd.label;"
- accesskey="&cutCmd.accesskey;"
- closemenu="single"
- selection="bookmark|folder|separator|query"
- forcehideselection="tagChild|livemarkChild"/>
- <menuitem id="placesContext_copy"
- command="placesCmd_copy"
- label="&copyCmd.label;"
- closemenu="single"
- accesskey="&copyCmd.accesskey;"/>
- <menuitem id="placesContext_paste"
- command="placesCmd_paste"
- label="&pasteCmd.label;"
- closemenu="single"
- accesskey="&pasteCmd.accesskey;"
- selectiontype="any"
- hideifnoinsertionpoint="true"/>
- <menuseparator id="placesContext_editSeparator"/>
- <menuitem id="placesContext_delete"
- command="placesCmd_delete"
- label="&deleteCmd.label;"
- accesskey="&deleteCmd.accesskey;"
- closemenu="single"
- selection="bookmark|tagChild|folder|query|dynamiccontainer|separator|host"/>
- <menuitem id="placesContext_delete_history"
- command="placesCmd_delete"
- label="&cmd.delete.label;"
- accesskey="&cmd.delete.accesskey;"
- closemenu="single"
- selection="link"
- forcehideselection="bookmark|livemarkChild"/>
- <menuitem id="placesContext_deleteHost"
- command="placesCmd_deleteDataHost"
- label="&cmd.deleteDomainData.label;"
- accesskey="&cmd.deleteDomainData.accesskey;"
- closemenu="single"
- selection="link|host"
- selectiontype="single"
- hideifprivatebrowsing="true"
- forcehideselection="bookmark|livemarkChild"/>
- <menuseparator id="placesContext_deleteSeparator"/>
- <menuitem id="placesContext_reload"
- command="placesCmd_reload"
- label="&cmd.reloadLivebookmark.label;"
- accesskey="&cmd.reloadLivebookmark.accesskey;"
- closemenu="single"
- selection="livemark/feedURI"/>
- <menuitem id="placesContext_sortBy:name"
- command="placesCmd_sortBy:name"
- label="&cmd.sortby_name.label;"
- accesskey="&cmd.context_sortby_name.accesskey;"
- closemenu="single"
- selection="folder"/>
- <menuseparator id="placesContext_sortSeparator"/>
- <menuitem id="placesContext_openParentFolder"
- command="placesCmd_openParentFolder"
- label="&cmd.openParentFolder.label;"
- key="key_placesCmd_openParentFolder"
- accesskey="&cmd.openParentFolder.accesskey;"
- selectiontype="single"
- selection="bookmark"
- forcehideselection="livemarkChild|livemark/feedURI|PlacesOrganizer/OrganizerQuery"/>
- <menuseparator id="placesContext_parentFolderSeparator"/>
- <menuitem id="placesContext_show:info"
- command="placesCmd_show:info"
- label="&cmd.properties.label;"
- accesskey="&cmd.properties.accesskey;"
- selection="bookmark|folder|query"
- forcehideselection="livemarkChild"/>
- </menupopup>
-
-</overlay>
diff --git a/components/places/content/sidebarUtils.js b/components/places/content/sidebarUtils.js
deleted file mode 100644
index 06ed537..0000000
--- a/components/places/content/sidebarUtils.js
+++ /dev/null
@@ -1,108 +0,0 @@
-# -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-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 cell = tbo.getCellAt(aEvent.clientX, aEvent.clientY);
-
- if (cell.row == -1 || cell.childElt == "twisty")
- return;
-
- var mouseInGutter = false;
- if (aGutterSelect) {
- var rect = tbo.getCoordsForCellItem(cell.row, cell.col, "image");
- // 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 > rect.x;
- else
- mouseInGutter = aEvent.clientX < rect.x;
- }
-
-#ifdef XP_MACOSX
- var modifKey = aEvent.metaKey || aEvent.shiftKey;
-#else
- var modifKey = aEvent.ctrlKey || aEvent.shiftKey;
-#endif
-
- var isContainer = tbo.view.isContainer(cell.row);
- var openInTabs = isContainer &&
- (aEvent.button == 1 ||
- (aEvent.button == 0 && modifKey)) &&
- PlacesUtils.hasChildURIs(tbo.view.nodeForTreeIndex(cell.row), true);
-
- if (aEvent.button == 0 && isContainer && !openInTabs) {
- tbo.view.toggleOpenState(cell.row);
- return;
- }
- else if (!mouseInGutter && openInTabs &&
- aEvent.originalTarget.localName == "treechildren") {
- tbo.view.selection.select(cell.row);
- PlacesUIUtils.openContainerNodeInTabs(aTree.selectedNode, aEvent, aTree);
- }
- 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(cell.row);
- PlacesUIUtils.openNodeWithEvent(aTree.selectedNode, aEvent, aTree);
- }
- },
-
- handleTreeKeyPress: function SU_handleTreeKeyPress(aEvent) {
- // XXX Bug 627901: Post Fx4, this method should take a tree parameter.
- let tree = aEvent.target;
- let node = tree.selectedNode;
- if (node) {
- if (aEvent.keyCode == KeyEvent.DOM_VK_RETURN)
- PlacesUIUtils.openNodeWithEvent(node, aEvent, tree);
- }
- },
-
- /**
- * 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 cell = tbo.getCellAt(aEvent.clientX, aEvent.clientY);
-
- // cell.row 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 moused-over URL in these cases.
- if (cell.row != -1) {
- var node = tree.view.nodeForTreeIndex(cell.row);
- if (PlacesUtils.nodeIsURI(node))
- this.setMouseoverURL(node.uri);
- else
- this.setMouseoverURL("");
- }
- else
- this.setMouseoverURL("");
- },
-
- setMouseoverURL: function SU_setMouseoverURL(aURL) {
- // When the browser window is closed with an open sidebar, the sidebar
- // unload event happens after the browser's one. In this case
- // top.XULBrowserWindow has been nullified already.
- if (top.XULBrowserWindow) {
- top.XULBrowserWindow.setOverLink(aURL, null);
- }
- }
-};
diff --git a/components/places/content/tree.xml b/components/places/content/tree.xml
deleted file mode 100644
index 05b0169..0000000
--- a/components/places/content/tree.xml
+++ /dev/null
@@ -1,789 +0,0 @@
-<?xml version="1.0"?>
-
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<bindings id="placesTreeBindings"
- xmlns="http://www.mozilla.org/xbl"
- xmlns:xbl="http://www.mozilla.org/xbl"
- xmlns:html="http://www.w3.org/1999/xhtml"
- xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-
- <binding id="places-tree" extends="chrome://global/content/bindings/tree.xml#tree">
- <implementation>
- <constructor><![CDATA[
- // Force an initial build.
- if (this.place)
- this.place = this.place;
- ]]></constructor>
-
- <destructor><![CDATA[
- // Break the treeviewer->result->treeviewer cycle.
- // Note: unsetting the result's viewer also unsets
- // the viewer's reference to our treeBoxObject.
- var result = this.result;
- if (result) {
- result.root.containerOpen = false;
- }
-
- // Unregister the controllber before unlinking the view, otherwise it
- // may still try to update commands on a view with a null result.
- if (this._controller) {
- this._controller.terminate();
- this.controllers.removeController(this._controller);
- }
-
- this.view = null;
- ]]></destructor>
-
- <property name="controller"
- readonly="true"
- onget="return this._controller"/>
-
- <!-- overriding -->
- <property name="view">
- <getter><![CDATA[
- try {
- return this.treeBoxObject.view.wrappedJSObject;
- }
- catch(e) {
- return null;
- }
- ]]></getter>
- <setter><![CDATA[
- return this.treeBoxObject.view = val;
- ]]></setter>
- </property>
-
- <property name="associatedElement"
- readonly="true"
- onget="return this"/>
-
- <method name="applyFilter">
- <parameter name="filterString"/>
- <parameter name="folderRestrict"/>
- <parameter name="includeHidden"/>
- <body><![CDATA[
- // preserve grouping
- var queryNode = PlacesUtils.asQuery(this.result.root);
- var options = queryNode.queryOptions.clone();
-
- // Make sure we're getting uri results.
- // We do not yet support searching into grouped queries or into
- // tag containers, so we must fall to the default case.
- if (PlacesUtils.nodeIsHistoryContainer(queryNode) ||
- options.resultType == options.RESULTS_AS_TAG_QUERY ||
- options.resultType == options.RESULTS_AS_TAG_CONTENTS)
- options.resultType = options.RESULTS_AS_URI;
-
- var query = PlacesUtils.history.getNewQuery();
- query.searchTerms = filterString;
-
- if (folderRestrict) {
- query.setFolders(folderRestrict, folderRestrict.length);
- options.queryType = options.QUERY_TYPE_BOOKMARKS;
- }
-
- options.includeHidden = !!includeHidden;
-
- this.load([query], options);
- ]]></body>
- </method>
-
- <method name="load">
- <parameter name="queries"/>
- <parameter name="options"/>
- <body><![CDATA[
- let result = PlacesUtils.history
- .executeQueries(queries, queries.length,
- options);
- let callback;
- if (this.flatList) {
- let onOpenFlatContainer = this.onOpenFlatContainer;
- if (onOpenFlatContainer)
- callback = new Function("aContainer", onOpenFlatContainer);
- }
-
- if (!this._controller) {
- this._controller = new PlacesController(this);
- this.controllers.appendController(this._controller);
- }
-
- let treeView = new PlacesTreeView(this.flatList, callback, this._controller);
-
- // Observer removal is done within the view itself. When the tree
- // goes away, treeboxobject calls view.setTree(null), which then
- // calls removeObserver.
- result.addObserver(treeView, false);
- this.view = treeView;
-
- if (this.getAttribute("selectfirstnode") == "true" && treeView.rowCount > 0) {
- treeView.selection.select(0);
- }
-
- this._cachedInsertionPoint = undefined;
- ]]></body>
- </method>
-
- <property name="flatList">
- <getter><![CDATA[
- return this.getAttribute("flatList") == "true";
- ]]></getter>
- <setter><![CDATA[
- if (this.flatList != val) {
- this.setAttribute("flatList", val);
- // reload with the last place set
- if (this.place)
- this.place = this.place;
- }
- return val;
- ]]></setter>
- </property>
-
- <property name="onOpenFlatContainer">
- <getter><![CDATA[
- return this.getAttribute("onopenflatcontainer");
- ]]></getter>
- <setter><![CDATA[
- if (this.onOpenFlatContainer != val) {
- this.setAttribute("onopenflatcontainer", val);
- // reload with the last place set
- if (this.place)
- this.place = this.place;
- }
- return val;
- ]]></setter>
- </property>
-
- <!--
- Causes a particular node represented by the specified placeURI to be
- selected in the tree. All containers above the node in the hierarchy
- will be opened, so that the node is visible.
- -->
- <method name="selectPlaceURI">
- <parameter name="placeURI"/>
- <body><![CDATA[
- // Do nothing if a node matching the given uri is already selected
- if (this.hasSelection && this.selectedNode.uri == placeURI)
- return;
-
- function findNode(container, placeURI, nodesURIChecked) {
- var containerURI = container.uri;
- if (containerURI == placeURI)
- return container;
- if (nodesURIChecked.indexOf(containerURI) != -1)
- return null;
-
- // never check the contents of the same query
- nodesURIChecked.push(containerURI);
-
- var wasOpen = container.containerOpen;
- if (!wasOpen)
- container.containerOpen = true;
- for (var i = 0; i < container.childCount; ++i) {
- var child = container.getChild(i);
- var childURI = child.uri;
- if (childURI == placeURI)
- return child;
- else if (PlacesUtils.nodeIsContainer(child)) {
- var nested = findNode(PlacesUtils.asContainer(child), placeURI, nodesURIChecked);
- if (nested)
- return nested;
- }
- }
-
- if (!wasOpen)
- container.containerOpen = false;
-
- return null;
- }
-
- var container = this.result.root;
- NS_ASSERT(container, "No result, cannot select place URI!");
- if (!container)
- return;
-
- var child = findNode(container, placeURI, []);
- if (child)
- this.selectNode(child);
- else {
- // If the specified child could not be located, clear the selection
- var selection = this.view.selection;
- selection.clearSelection();
- }
- ]]></body>
- </method>
-
- <!--
- Causes a particular node to be selected in the tree, resulting in all
- containers above the node in the hierarchy to be opened, so that the
- node is visible.
- -->
- <method name="selectNode">
- <parameter name="node"/>
- <body><![CDATA[
- var view = this.view;
-
- var parent = node.parent;
- if (parent && !parent.containerOpen) {
- // Build a list of all of the nodes that are the parent of this one
- // in the result.
- var parents = [];
- var root = this.result.root;
- while (parent && parent != root) {
- parents.push(parent);
- parent = parent.parent;
- }
-
- // Walk the list backwards (opening from the root of the hierarchy)
- // opening each folder as we go.
- for (var i = parents.length - 1; i >= 0; --i) {
- var index = view.treeIndexForNode(parents[i]);
- if (index != Ci.nsINavHistoryResultTreeViewer.INDEX_INVISIBLE &&
- view.isContainer(index) && !view.isContainerOpen(index))
- view.toggleOpenState(index);
- }
- // Select the specified node...
- }
-
- var index = view.treeIndexForNode(node);
- if (index == Ci.nsINavHistoryResultTreeViewer.INDEX_INVISIBLE)
- return;
-
- view.selection.select(index);
- // ... and ensure it's visible, not scrolled off somewhere.
- this.treeBoxObject.ensureRowIsVisible(index);
- ]]></body>
- </method>
-
- <!-- nsIPlacesView -->
- <property name="result">
- <getter><![CDATA[
- try {
- return this.view.QueryInterface(Ci.nsINavHistoryResultObserver).result;
- }
- catch (e) {
- return null;
- }
- ]]></getter>
- </property>
-
- <!-- nsIPlacesView -->
- <property name="place">
- <getter><![CDATA[
- return this.getAttribute("place");
- ]]></getter>
- <setter><![CDATA[
- this.setAttribute("place", val);
-
- var queriesRef = { };
- var queryCountRef = { };
- var optionsRef = { };
- PlacesUtils.history.queryStringToQueries(val, queriesRef, queryCountRef, optionsRef);
- if (queryCountRef.value == 0)
- queriesRef.value = [PlacesUtils.history.getNewQuery()];
- if (!optionsRef.value)
- optionsRef.value = PlacesUtils.history.getNewQueryOptions();
-
- this.load(queriesRef.value, optionsRef.value);
-
- return val;
- ]]></setter>
- </property>
-
- <!-- nsIPlacesView -->
- <property name="hasSelection">
- <getter><![CDATA[
- return this.view && this.view.selection.count >= 1;
- ]]></getter>
- </property>
-
- <!-- nsIPlacesView -->
- <property name="selectedNodes">
- <getter><![CDATA[
- let nodes = [];
- if (!this.hasSelection)
- return nodes;
-
- let selection = this.view.selection;
- let rc = selection.getRangeCount();
- let resultview = this.view;
- for (let i = 0; i < rc; ++i) {
- let min = { }, max = { };
- selection.getRangeAt(i, min, max);
-
- for (let j = min.value; j <= max.value; ++j)
- nodes.push(resultview.nodeForTreeIndex(j));
- }
- return nodes;
- ]]></getter>
- </property>
-
- <method name="toggleCutNode">
- <parameter name="aNode"/>
- <parameter name="aValue"/>
- <body><![CDATA[
- this.view.toggleCutNode(aNode, aValue);
- ]]></body>
- </method>
-
- <!-- nsIPlacesView -->
- <property name="removableSelectionRanges">
- <getter><![CDATA[
- // This property exists in addition to selectedNodes because it
- // encodes selection ranges (which only occur in list views) into
- // the return value. For each removed range, the index at which items
- // will be re-inserted upon the remove transaction being performed is
- // the first index of the range, so that the view updates correctly.
- //
- // For example, if we remove rows 2,3,4 and 7,8 from a list, when we
- // undo that operation, if we insert what was at row 3 at row 3 again,
- // it will show up _after_ the item that was at row 5. So we need to
- // insert all items at row 2, and the tree view will update correctly.
- //
- // Also, this function collapses the selection to remove redundant
- // data, e.g. when deleting this selection:
- //
- // http://www.foo.com/
- // (-) Some Folder
- // http://www.bar.com/
- //
- // ... returning http://www.bar.com/ as part of the selection is
- // redundant because it is implied by removing "Some Folder". We
- // filter out all such redundancies since some partial amount of
- // the folder's children may be selected.
- //
- let nodes = [];
- if (!this.hasSelection)
- return nodes;
-
- var selection = this.view.selection;
- var rc = selection.getRangeCount();
- var resultview = this.view;
- // This list is kept independently of the range selected (i.e. OUTSIDE
- // the for loop) since the row index of a container is unique for the
- // entire view, and we could have some really wacky selection and we
- // don't want to blow up.
- var containers = { };
- for (var i = 0; i < rc; ++i) {
- var range = [];
- var min = { }, max = { };
- selection.getRangeAt(i, min, max);
-
- for (var j = min.value; j <= max.value; ++j) {
- if (this.view.isContainer(j))
- containers[j] = true;
- if (!(this.view.getParentIndex(j) in containers))
- range.push(resultview.nodeForTreeIndex(j));
- }
- nodes.push(range);
- }
- return nodes;
- ]]></getter>
- </property>
-
- <!-- nsIPlacesView -->
- <property name="draggableSelection"
- onget="return this.selectedNodes"/>
-
- <!-- nsIPlacesView -->
- <property name="selectedNode">
- <getter><![CDATA[
- var view = this.view;
- if (!view || view.selection.count != 1)
- return null;
-
- var selection = view.selection;
- var min = { }, max = { };
- selection.getRangeAt(0, min, max);
-
- return this.view.nodeForTreeIndex(min.value);
- ]]></getter>
- </property>
-
- <!-- nsIPlacesView -->
- <property name="insertionPoint">
- <getter><![CDATA[
- // invalidated on selection and focus changes
- if (this._cachedInsertionPoint !== undefined)
- return this._cachedInsertionPoint;
-
- // there is no insertion point for history queries
- // so bail out now and save a lot of work when updating commands
- var resultNode = this.result.root;
- if (PlacesUtils.nodeIsQuery(resultNode) &&
- PlacesUtils.asQuery(resultNode).queryOptions.queryType ==
- Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY)
- return this._cachedInsertionPoint = null;
-
- var orientation = Ci.nsITreeView.DROP_BEFORE;
- // If there is no selection, insert at the end of the container.
- if (!this.hasSelection) {
- var index = this.view.rowCount - 1;
- this._cachedInsertionPoint =
- this._getInsertionPoint(index, orientation);
- return this._cachedInsertionPoint;
- }
-
- // This is a two-part process. The first part is determining the drop
- // orientation.
- // * The default orientation is to drop _before_ the selected item.
- // * If the selected item is a container, the default orientation
- // is to drop _into_ that container.
- //
- // Warning: It may be tempting to use tree indexes in this code, but
- // you must not, since the tree is nested and as your tree
- // index may change when folders before you are opened and
- // closed. You must convert your tree index to a node, and
- // then use getChildIndex to find your absolute index in
- // the parent container instead.
- //
- var resultView = this.view;
- var selection = resultView.selection;
- var rc = selection.getRangeCount();
- var min = { }, max = { };
- selection.getRangeAt(rc - 1, min, max);
-
- // If the sole selection is a container, and we are not in
- // a flatlist, insert into it.
- // Note that this only applies to _single_ selections,
- // if the last element within a multi-selection is a
- // container, insert _adjacent_ to the selection.
- //
- // If the sole selection is the bookmarks toolbar folder, we insert
- // into it even if it is not opened
- var itemId =
- PlacesUtils.getConcreteItemId(resultView.nodeForTreeIndex(max.value));
- if (selection.count == 1 && resultView.isContainer(max.value) &&
- !this.flatList)
- orientation = Ci.nsITreeView.DROP_ON;
-
- this._cachedInsertionPoint =
- this._getInsertionPoint(max.value, orientation);
- return this._cachedInsertionPoint;
- ]]></getter>
- </property>
-
- <method name="_getInsertionPoint">
- <parameter name="index"/>
- <parameter name="orientation"/>
- <body><![CDATA[
- var result = this.result;
- var resultview = this.view;
- var container = result.root;
- var dropNearItemId = -1;
- NS_ASSERT(container, "null container");
- // 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 = resultview.nodeForTreeIndex(index);
- if (resultview.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 item is an open container and the user is
- // trying to drag into it as a first item, really insert into it.
- container = lastSelected;
- orientation = Ci.nsITreeView.DROP_ON;
- index = 0;
- }
- else {
- // Use the last-selected node's container.
- container = lastSelected.parent;
-
- // See comment in the treeView.js's copy of this method
- if (!container || !container.containerOpen)
- return null;
-
- // Avoid the potentially expensive call to getChildIndex
- // if we know this container doesn't allow insertion
- if (PlacesControllerDragHelper.disallowInsertion(container))
- return null;
-
- var queryOptions = PlacesUtils.asQuery(result.root).queryOptions;
- if (queryOptions.sortingMode !=
- Ci.nsINavHistoryQueryOptions.SORT_BY_NONE) {
- // If we are within a sorted view, insert at the end
- 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 = container.getChildIndex(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);
- ]]></body>
- </method>
-
- <!-- nsIPlacesView -->
- <method name="selectAll">
- <body><![CDATA[
- this.view.selection.selectAll();
- ]]></body>
- </method>
-
- <!-- This method will select the first node in the tree that matches
- each given item id. It will open any parent nodes that it needs
- to in order to show the selected items.
- -->
- <method name="selectItems">
- <parameter name="aIDs"/>
- <parameter name="aOpenContainers"/>
- <body><![CDATA[
- // By default, we do search and select within containers which were
- // closed (note that containers in which nodes were not found are
- // closed).
- if (aOpenContainers === undefined)
- aOpenContainers = true;
-
- var ids = aIDs; // don't manipulate the caller's array
-
- // Array of nodes found by findNodes which are to be selected
- var nodes = [];
-
- // Array of nodes found by findNodes which should be opened
- var nodesToOpen = [];
-
- // A set of URIs of container-nodes that were previously searched,
- // and thus shouldn't be searched again. This is empty at the initial
- // start of the recursion and gets filled in as the recursion
- // progresses.
- var nodesURIChecked = [];
-
- /**
- * Recursively search through a node's children for items
- * with the given IDs. When a matching item is found, remove its ID
- * from the IDs array, and add the found node to the nodes dictionary.
- *
- * NOTE: This method will leave open any node that had matching items
- * in its subtree.
- */
- function findNodes(node) {
- var foundOne = false;
- // See if node matches an ID we wanted; add to results.
- // For simple folder queries, check both itemId and the concrete
- // item id.
- var index = ids.indexOf(node.itemId);
- if (index == -1 &&
- node.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER_SHORTCUT)
- index = ids.indexOf(PlacesUtils.asQuery(node).folderItemId);
-
- if (index != -1) {
- nodes.push(node);
- foundOne = true;
- ids.splice(index, 1);
- }
-
- if (ids.length == 0 || !PlacesUtils.nodeIsContainer(node) ||
- nodesURIChecked.indexOf(node.uri) != -1)
- return foundOne;
-
- PlacesUtils.asContainer(node);
- if (!aOpenContainers && !node.containerOpen)
- return foundOne;
-
- nodesURIChecked.push(node.uri);
-
- // Remember the beginning state so that we can re-close
- // this node if we don't find any additional results here.
- var previousOpenness = node.containerOpen;
- node.containerOpen = true;
- for (var child = 0; child < node.childCount && ids.length > 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;
- }
-
- // Disable notifications while looking for nodes.
- let result = this.result;
- let didSuppressNotifications = result.suppressNotifications;
- if (!didSuppressNotifications)
- result.suppressNotifications = true
- try {
- findNodes(this.result.root);
- }
- finally {
- if (!didSuppressNotifications)
- result.suppressNotifications = false;
- }
-
- // 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]);
- if (index == Ci.nsINavHistoryResultTreeViewer.INDEX_INVISIBLE)
- continue;
- selection.rangedSelect(index, index, true);
- }
- selection.selectEventsSuppressed = false;
- ]]></body>
- </method>
-
- <field name="_contextMenuShown">false</field>
-
- <method name="buildContextMenu">
- <parameter name="aPopup"/>
- <body><![CDATA[
- this._contextMenuShown = true;
- return this.controller.buildContextMenu(aPopup);
- ]]></body>
- </method>
-
- <method name="destroyContextMenu">
- <parameter name="aPopup"/>
- this._contextMenuShown = false;
- <body/>
- </method>
-
- <property name="ownerWindow"
- readonly="true"
- onget="return window;"/>
-
- <field name="_active">true</field>
- <property name="active"
- onget="return this._active"
- onset="return this._active = val"/>
-
- </implementation>
- <handlers>
- <handler event="focus"><![CDATA[
- this._cachedInsertionPoint = undefined;
-
- // See select handler. We need the sidebar's places commandset to be
- // updated as well
- document.commandDispatcher.updateCommands("focus");
- ]]></handler>
- <handler event="select"><![CDATA[
- this._cachedInsertionPoint = undefined;
-
- // This additional complexity is here for the sidebars
- var win = window;
- while (true) {
- win.document.commandDispatcher.updateCommands("focus");
- if (win == window.top)
- break;
-
- win = win.parent;
- }
- ]]></handler>
-
- <handler event="dragstart"><![CDATA[
- if (event.target.localName != "treechildren")
- return;
-
- let nodes = this.selectedNodes;
- for (let i = 0; i < nodes.length; i++) {
- let node = nodes[i];
-
- // Disallow dragging the root node of a tree.
- if (!node.parent) {
- event.preventDefault();
- event.stopPropagation();
- return;
- }
-
- // If this node is child of a readonly container (e.g. a livemark)
- // or cannot be moved, we must force a copy.
- if (!PlacesControllerDragHelper.canMoveNode(node)) {
- event.dataTransfer.effectAllowed = "copyLink";
- break;
- }
- }
-
- this._controller.setDataTransfer(event);
- event.stopPropagation();
- ]]></handler>
-
- <handler event="dragover"><![CDATA[
- if (event.target.localName != "treechildren")
- return;
-
- let cell = this.treeBoxObject.getCellAt(event.clientX, event.clientY);
- let node = cell.row != -1 ?
- this.view.nodeForTreeIndex(cell.row) :
- this.result.root;
- // cache the dropTarget for the view
- PlacesControllerDragHelper.currentDropTarget = node;
-
- // We have to calculate the orientation since view.canDrop will use
- // it and we want to be consistent with the dropfeedback.
- let tbo = this.treeBoxObject;
- let rowHeight = tbo.rowHeight;
- let eventY = event.clientY - tbo.treeBody.boxObject.y -
- rowHeight * (cell.row - tbo.getFirstVisibleRow());
-
- let orientation = Ci.nsITreeView.DROP_BEFORE;
-
- if (cell.row == -1) {
- // If the row is not valid we try to insert inside the resultNode.
- orientation = Ci.nsITreeView.DROP_ON;
- }
- else if (PlacesUtils.nodeIsContainer(node) &&
- eventY > 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;
- }
-
- if (!this.view.canDrop(cell.row, orientation, event.dataTransfer))
- return;
-
- event.preventDefault();
- event.stopPropagation();
- ]]></handler>
-
- <handler event="dragend"><![CDATA[
- PlacesControllerDragHelper.currentDropTarget = null;
- ]]></handler>
-
- </handlers>
- </binding>
-
-</bindings>
diff --git a/components/places/content/treeView.js b/components/places/content/treeView.js
deleted file mode 100644
index aba7314..0000000
--- a/components/places/content/treeView.js
+++ /dev/null
@@ -1,1770 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-Components.utils.import('resource://gre/modules/XPCOMUtils.jsm');
-
-const PTV_interfaces = [Ci.nsITreeView,
- Ci.nsINavHistoryResultObserver,
- Ci.nsINavHistoryResultTreeViewer,
- Ci.nsISupportsWeakReference];
-
-function PlacesTreeView(aFlatList, aOnOpenFlatContainer, aController) {
- this._tree = null;
- this._result = null;
- this._selection = null;
- this._rootNode = null;
- this._rows = [];
- this._flatList = aFlatList;
- this._openContainerCallback = aOnOpenFlatContainer;
- this._controller = aController;
-}
-
-PlacesTreeView.prototype = {
- get wrappedJSObject() this,
-
- __dateService: null,
- get _dateService() {
- if (!this.__dateService) {
- this.__dateService = Cc["@mozilla.org/intl/scriptabledateformat;1"].
- getService(Ci.nsIScriptableDateFormat);
- }
- return this.__dateService;
- },
-
- QueryInterface: XPCOMUtils.generateQI(PTV_interfaces),
-
- // Bug 761494:
- // ----------
- // Some addons use methods from nsINavHistoryResultObserver and
- // nsINavHistoryResultTreeViewer, without QIing to these interfaces first.
- // That's not a problem when the view is retrieved through the
- // <tree>.view getter (which returns the wrappedJSObject of this object),
- // it raises an issue when the view retrieved through the treeBoxObject.view
- // getter. Thus, to avoid breaking addons, the interfaces are prefetched.
- classInfo: XPCOMUtils.generateCI({ interfaces: PTV_interfaces }),
-
- /**
- * This is called once both the result and the tree are set.
- */
- _finishInit: function PTV__finishInit() {
- let selection = this.selection;
- if (selection)
- selection.selectEventsSuppressed = true;
-
- if (!this._rootNode.containerOpen) {
- // This triggers containerStateChanged 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;
- },
-
- /**
- * Plain Container: container result nodes which may never include sub
- * hierarchies.
- *
- * When the rows array is constructed, we don't set the children of plain
- * containers. Instead, we keep placeholders for these children. We then
- * build these children lazily as the tree asks us for information about each
- * row. Luckily, the tree doesn't ask about rows outside the visible area.
- *
- * @see _getNodeForRow and _getRowForNode for the actual magic.
- *
- * @note It's guaranteed that all containers are listed in the rows
- * elements array. It's also guaranteed that separators (if they're not
- * filtered, see below) are listed in the visible elements array, because
- * bookmark folders are never built lazily, as described above.
- *
- * @param aContainer
- * A container result node.
- *
- * @return true if aContainer is a plain container, false otherwise.
- */
- _isPlainContainer: function PTV__isPlainContainer(aContainer) {
- // Livemarks are always plain containers.
- if (this._controller.hasCachedLivemarkInfo(aContainer))
- return true;
-
- // We don't know enough about non-query containers.
- if (!(aContainer instanceof Ci.nsINavHistoryQueryResultNode))
- return false;
-
- switch (aContainer.queryOptions.resultType) {
- case Ci.nsINavHistoryQueryOptions.RESULTS_AS_DATE_QUERY:
- case Ci.nsINavHistoryQueryOptions.RESULTS_AS_SITE_QUERY:
- case Ci.nsINavHistoryQueryOptions.RESULTS_AS_DATE_SITE_QUERY:
- case Ci.nsINavHistoryQueryOptions.RESULTS_AS_TAG_QUERY:
- return false;
- }
-
- // If it's a folder, it's not a plain container.
- let nodeType = aContainer.type;
- return nodeType != Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER &&
- nodeType != Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER_SHORTCUT;
- },
-
- /**
- * Gets the row number for a given node. Assumes that the given node is
- * visible (i.e. it's not an obsolete node).
- *
- * @param aNode
- * A result node. Do not pass an obsolete node, or any
- * node which isn't supposed to be in the tree (e.g. separators in
- * sorted trees).
- * @param [optional] aForceBuild
- * @see _isPlainContainer.
- * If true, the row will be computed even if the node still isn't set
- * in our rows array.
- * @param [optional] aParentRow
- * The row of aNode's parent. Ignored for the root node.
- * @param [optional] aNodeIndex
- * The index of aNode in its parent. Only used if aParentRow is
- * set too.
- *
- * @throws if aNode is invisible.
- * @note If aParentRow and aNodeIndex are passed and parent is a plain
- * container, this method will just return a calculated row value, without
- * making assumptions on existence of the node at that position.
- * @return aNode's row if it's in the rows list or if aForceBuild is set, -1
- * otherwise.
- */
- _getRowForNode:
- function PTV__getRowForNode(aNode, aForceBuild, aParentRow, aNodeIndex) {
- if (aNode == this._rootNode)
- throw new Error("The root node is never visible");
-
- // A node is removed form the view either if it has no parent or if its
- // root-ancestor is not the root node (in which case that's the node
- // for which nodeRemoved was called).
- // Tycho: let ancestors = [x for (x of PlacesUtils.nodeAncestors(aNode))];
- let ancestors = [];
- for (let x of PlacesUtils.nodeAncestors(aNode)) {
- ancestors.push(x);
- }
-
- if (ancestors.length == 0 ||
- ancestors[ancestors.length - 1] != this._rootNode) {
- throw new Error("Removed node passed to _getRowForNode");
- }
-
- // Ensure that the entire chain is open, otherwise that node is invisible.
- for (let ancestor of ancestors) {
- if (!ancestor.containerOpen)
- throw new Error("Invisible node passed to _getRowForNode");
- }
-
- // Non-plain containers are initially built with their contents.
- let parent = aNode.parent;
- let parentIsPlain = this._isPlainContainer(parent);
- if (!parentIsPlain) {
- if (parent == this._rootNode)
- return this._rows.indexOf(aNode);
-
- return this._rows.indexOf(aNode, aParentRow);
- }
-
- let row = -1;
- let useNodeIndex = typeof(aNodeIndex) == "number";
- if (parent == this._rootNode) {
- if (aNode instanceof Ci.nsINavHistoryResultNode) {
- row = useNodeIndex ? aNodeIndex : this._rootNode.getChildIndex(aNode);
- }
- } else if (useNodeIndex && typeof(aParentRow) == "number") {
- // If we have both the row of the parent node, and the node's index, we
- // can avoid searching the rows array if the parent is a plain container.
- row = aParentRow + aNodeIndex + 1;
- } else {
- // Look for the node in the nodes array. Start the search at the parent
- // row. If the parent row isn't passed, we'll pass undefined to indexOf,
- // which is fine.
- row = this._rows.indexOf(aNode, aParentRow);
- if (row == -1 && aForceBuild) {
- let parentRow = typeof(aParentRow) == "number" ? aParentRow
- : this._getRowForNode(parent);
- row = parentRow + parent.getChildIndex(aNode) + 1;
- }
- }
-
- if (row != -1)
- this._rows[row] = aNode;
-
- return row;
- },
-
- /**
- * Given a row, finds and returns the parent details of the associated node.
- *
- * @param aChildRow
- * Row number.
- * @return [parentNode, parentRow]
- */
- _getParentByChildRow: function PTV__getParentByChildRow(aChildRow) {
- let node = this._getNodeForRow(aChildRow);
- let parent = (node === null) ? this._rootNode : node.parent;
-
- // The root node is never visible
- if (parent == this._rootNode)
- return [this._rootNode, -1];
-
- let parentRow = this._rows.lastIndexOf(parent, aChildRow - 1);
- return [parent, parentRow];
- },
-
- /**
- * Gets the node at a given row.
- */
- _getNodeForRow: function PTV__getNodeForRow(aRow) {
- if (aRow < 0) {
- return null;
- }
-
- let node = this._rows[aRow];
- if (node !== undefined)
- return node;
-
- // Find the nearest node.
- let rowNode, row;
- for (let i = aRow - 1; i >= 0 && rowNode === undefined; i--) {
- rowNode = this._rows[i];
- row = i;
- }
-
- // If there's no container prior to the given row, it's a child of
- // the root node (remember: all containers are listed in the rows array).
- if (!rowNode)
- return this._rows[aRow] = this._rootNode.getChild(aRow);
-
- // Unset elements may exist only in plain containers. Thus, if the nearest
- // node is a container, it's the row's parent, otherwise, it's a sibling.
- if (rowNode instanceof Ci.nsINavHistoryContainerResultNode)
- return this._rows[aRow] = rowNode.getChild(aRow - row - 1);
-
- let [parent, parentRow] = this._getParentByChildRow(row);
- return this._rows[aRow] = parent.getChild(aRow - parentRow - 1);
- },
-
- /**
- * This takes a container and recursively appends our rows array per its
- * contents. Assumes that the rows arrays has no rows for the given
- * container.
- *
- * @param [in] aContainer
- * A container result node.
- * @param [in] aFirstChildRow
- * The first row at which nodes may be inserted to the row array.
- * In other words, that's aContainer's row + 1.
- * @param [out] aToOpen
- * An array of containers to open once the build is done.
- *
- * @return the number of rows which were inserted.
- */
- _buildVisibleSection:
- function PTV__buildVisibleSection(aContainer, aFirstChildRow, aToOpen)
- {
- // There's nothing to do if the container is closed.
- if (!aContainer.containerOpen)
- return 0;
-
- // Inserting the new elements into the rows array in one shot (by
- // Array.concat) is faster than resizing the array (by splice) on each loop
- // iteration.
- let cc = aContainer.childCount;
- let newElements = new Array(cc);
- this._rows = this._rows.splice(0, aFirstChildRow)
- .concat(newElements, this._rows);
-
- if (this._isPlainContainer(aContainer))
- return cc;
-
- const openLiteral = PlacesUIUtils.RDF.GetResource("http://home.netscape.com/NC-rdf#open");
- const trueLiteral = PlacesUIUtils.RDF.GetLiteral("true");
- let sortingMode = this._result.sortingMode;
-
- let rowsInserted = 0;
- for (let i = 0; i < cc; i++) {
- let curChild = aContainer.getChild(i);
- let curChildType = curChild.type;
-
- let row = aFirstChildRow + rowsInserted;
-
- // Don't display separators when sorted.
- if (curChildType == Ci.nsINavHistoryResultNode.RESULT_TYPE_SEPARATOR) {
- if (sortingMode != Ci.nsINavHistoryQueryOptions.SORT_BY_NONE) {
- // Remove the element for the filtered separator.
- // Notice that the rows array was initially resized to include all
- // children.
- this._rows.splice(row, 1);
- continue;
- }
- }
-
- this._rows[row] = curChild;
- rowsInserted++;
-
- // Recursively do containers.
- if (!this._flatList &&
- curChild instanceof Ci.nsINavHistoryContainerResultNode &&
- !this._controller.hasCachedLivemarkInfo(curChild)) {
- let resource = this._getResourceForNode(curChild);
- let isopen = resource != null &&
- PlacesUIUtils.localStore.HasAssertion(resource,
- openLiteral,
- trueLiteral, true);
- if (isopen != curChild.containerOpen)
- aToOpen.push(curChild);
- else if (curChild.containerOpen && curChild.childCount > 0)
- rowsInserted += this._buildVisibleSection(curChild, row + 1, aToOpen);
- }
- }
-
- return rowsInserted;
- },
-
- /**
- * 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.
- */
- _countVisibleRowsForNodeAtRow:
- function PTV__countVisibleRowsForNodeAtRow(aNodeRow) {
- let node = this._rows[aNodeRow];
-
- // If it's not listed yet, we know that it's a leaf node (instanceof also
- // null-checks).
- if (!(node instanceof Ci.nsINavHistoryContainerResultNode))
- return 1;
-
- let outerLevel = node.indentLevel;
- for (let i = aNodeRow + 1; i < this._rows.length; i++) {
- let rowNode = this._rows[i];
- if (rowNode && rowNode.indentLevel <= outerLevel)
- return i - aNodeRow;
- }
-
- // This node plus its children take up the bottom of the list.
- return this._rows.length - aNodeRow;
- },
-
- _getSelectedNodesInRange:
- function PTV__getSelectedNodesInRange(aFirstRow, aLastRow) {
- let selection = this.selection;
- let rc = selection.getRangeCount();
- if (rc == 0)
- return [];
-
- // The visible-area borders are needed for checking whether a
- // selected row is also visible.
- let firstVisibleRow = this._tree.getFirstVisibleRow();
- let lastVisibleRow = this._tree.getLastVisibleRow();
-
- let nodesInfo = [];
- for (let rangeIndex = 0; rangeIndex < rc; rangeIndex++) {
- let min = { }, max = { };
- selection.getRangeAt(rangeIndex, min, max);
-
- // If this range does not overlap the replaced chunk, we don't need to
- // persist the selection.
- if (max.value < aFirstRow || min.value > aLastRow)
- continue;
-
- let firstRow = Math.max(min.value, aFirstRow);
- let lastRow = Math.min(max.value, aLastRow);
- for (let i = firstRow; i <= lastRow; i++) {
- nodesInfo.push({
- node: this._rows[i],
- oldRow: i,
- wasVisible: i >= firstVisibleRow && i <= lastVisibleRow
- });
- }
- }
-
- return nodesInfo;
- },
-
- /**
- * Tries to find an equivalent node for a node which was removed. We first
- * look for the original node, in case it was just relocated. Then, if we
- * that node was not found, we look for a node that has the same itemId, uri
- * and time values.
- *
- * @param aUpdatedContainer
- * An ancestor of the node which was removed. It does not have to be
- * its direct parent.
- * @param aOldNode
- * The node which was removed.
- *
- * @return the row number of an equivalent node for aOldOne, if one was
- * found, -1 otherwise.
- */
- _getNewRowForRemovedNode:
- function PTV__getNewRowForRemovedNode(aUpdatedContainer, aOldNode) {
- if (aOldNode == undefined) {
- return -1;
- }
- let parent = aOldNode.parent;
- if (parent) {
- // If the node's parent is still set, the node is not obsolete
- // and we should just find out its new position.
- // However, if any of the node's ancestor is closed, the node is
- // invisible.
- let ancestors = PlacesUtils.nodeAncestors(aOldNode);
- for (let ancestor of ancestors) {
- if (!ancestor.containerOpen)
- return -1;
- }
-
- return this._getRowForNode(aOldNode, true);
- }
-
- // There's a broken edge case here.
- // If a visit appears in two queries, and the second one was
- // the old node, we'll select the first one after refresh. There's
- // nothing we could do about that, because aOldNode.parent is
- // gone by the time invalidateContainer is called.
- let newNode = aUpdatedContainer.findNodeByDetails(aOldNode.uri,
- aOldNode.time,
- aOldNode.itemId,
- true);
- if (!newNode)
- return -1;
-
- return this._getRowForNode(newNode, true);
- },
-
- /**
- * Restores a given selection state as near as possible to the original
- * selection state.
- *
- * @param aNodesInfo
- * The persisted selection state as returned by
- * _getSelectedNodesInRange.
- * @param aUpdatedContainer
- * The container which was updated.
- */
- _restoreSelection:
- function PTV__restoreSelection(aNodesInfo, aUpdatedContainer) {
- if (aNodesInfo.length == 0)
- return;
-
- let selection = this.selection;
-
- // Attempt to ensure that previously-visible selection will be visible
- // if it's re-selected. However, we can only ensure that for one row.
- let scrollToRow = -1;
- for (let i = 0; i < aNodesInfo.length; i++) {
- let nodeInfo = aNodesInfo[i];
- let row = this._getNewRowForRemovedNode(aUpdatedContainer,
- nodeInfo.node);
- // Select the found node, if any.
- if (row != -1) {
- selection.rangedSelect(row, row, true);
- if (nodeInfo.wasVisible && scrollToRow == -1)
- scrollToRow = row;
- }
- }
-
- // If only one node was previously selected and there's no selection now,
- // select the node at its old row, if any.
- if (aNodesInfo.length == 1 && selection.count == 0) {
- let row = Math.min(aNodesInfo[0].oldRow, this._rows.length - 1);
- if (row != -1) {
- selection.rangedSelect(row, row, true);
- if (aNodesInfo[0].wasVisible && scrollToRow == -1)
- scrollToRow = aNodesInfo[0].oldRow;
- }
- }
-
- if (scrollToRow != -1)
- this._tree.ensureRowIsVisible(scrollToRow);
- },
-
- _convertPRTimeToString: function PTV__convertPRTimeToString(aTime) {
- const MS_PER_MINUTE = 60000;
- const MS_PER_DAY = 86400000;
- let timeMs = 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, notice midnight
- // can have a different offset during DST-change days.
- let dateObj = new Date();
- let now = dateObj.getTime() - dateObj.getTimezoneOffset() * MS_PER_MINUTE;
- let midnight = now - (now % MS_PER_DAY);
- midnight += new Date(midnight).getTimezoneOffset() * MS_PER_MINUTE;
-
- let dateFormat = timeMs >= midnight ?
- Ci.nsIScriptableDateFormat.dateFormatNone :
- Ci.nsIScriptableDateFormat.dateFormatShort;
-
- let timeObj = new Date(timeMs);
- 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,
- COLUMN_TYPE_PARENTFOLDER: 10,
- COLUMN_TYPE_PARENTFOLDERPATH: 11,
-
- _getColumnType: function PTV__getColumnType(aColumn) {
- let 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;
- case "parentFolder":
- return this.COLUMN_TYPE_PARENTFOLDER;
- case "parentFolderPath":
- return this.COLUMN_TYPE_PARENTFOLDERPATH;
- }
- 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 == PlacesUIUtils.DESCRIPTION_ANNO)
- return [this.COLUMN_TYPE_DESCRIPTION, false];
- break;
- case Ci.nsINavHistoryQueryOptions.SORT_BY_ANNOTATION_DESCENDING:
- if (this._result.sortingAnnotation == PlacesUIUtils.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];
- },
-
- // nsINavHistoryResultObserver
- nodeInserted: function PTV_nodeInserted(aParentNode, aNode, aNewIndex) {
- NS_ASSERT(this._result, "Got a notification but have no result!");
- if (!this._tree || !this._result)
- return;
-
- // Bail out for hidden separators.
- if (PlacesUtils.nodeIsSeparator(aNode) && this.isSorted())
- return;
-
- let parentRow;
- if (aParentNode != this._rootNode) {
- parentRow = this._getRowForNode(aParentNode);
-
- // Update parent when inserting the first item, since twisty has changed.
- if (aParentNode.childCount == 1)
- this._tree.invalidateRow(parentRow);
- }
-
- // Compute the new row number of the node.
- let row = -1;
- let cc = aParentNode.childCount;
- if (aNewIndex == 0 || this._isPlainContainer(aParentNode) || cc == 0) {
- // We don't need to worry about sub hierarchies of the parent node
- // if it's a plain container, or if the new node is its first child.
- if (aParentNode == this._rootNode)
- row = aNewIndex;
- else
- row = parentRow + aNewIndex + 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.
- let separatorsAreHidden = PlacesUtils.nodeIsSeparator(aNode) &&
- this.isSorted();
- for (let i = aNewIndex + 1; i < cc; i++) {
- let node = aParentNode.getChild(i);
- if (!separatorsAreHidden || PlacesUtils.nodeIsSeparator(node)) {
- // The children have not been shifted so the next item will have what
- // should be our index.
- row = this._getRowForNode(node, false, parentRow, i);
- break;
- }
- }
- if (row < 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).
- let prevChild = aParentNode.getChild(aNewIndex - 1);
- let prevIndex = this._getRowForNode(prevChild, false, parentRow,
- aNewIndex - 1);
- row = prevIndex + this._countVisibleRowsForNodeAtRow(prevIndex);
- }
- }
-
- this._rows.splice(row, 0, aNode);
- this._tree.rowCountChanged(row, 1);
-
- if (PlacesUtils.nodeIsContainer(aNode) &&
- PlacesUtils.asContainer(aNode).containerOpen) {
- this.invalidateContainer(aNode);
- }
- },
-
- /**
- * 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 || !this._result)
- return;
-
- // XXX bug 517701: We don't know what to do when the root node is removed.
- if (aNode == this._rootNode)
- throw Cr.NS_ERROR_NOT_IMPLEMENTED;
-
- // Bail out for hidden separators.
- if (PlacesUtils.nodeIsSeparator(aNode) && this.isSorted())
- return;
-
- let parentRow = aParentNode == this._rootNode ?
- undefined : this._getRowForNode(aParentNode, true);
- let oldRow = this._getRowForNode(aNode, true, parentRow, aOldIndex);
- if (oldRow < 0)
- throw Cr.NS_ERROR_UNEXPECTED;
-
- // If the node was exclusively selected, the node next to it will be
- // selected.
- let selectNext = false;
- let selection = this.selection;
- if (selection.getRangeCount() == 1) {
- let min = { }, max = { };
- selection.getRangeAt(0, min, max);
- if (min.value == max.value &&
- this.nodeForTreeIndex(min.value) == aNode)
- selectNext = true;
- }
-
- // Remove the node and its children, if any.
- let count = this._countVisibleRowsForNodeAtRow(oldRow);
- this._rows.splice(oldRow, count);
- this._tree.rowCountChanged(oldRow, -count);
-
- // Redraw the parent if its twisty state has changed.
- if (aParentNode != this._rootNode && !aParentNode.hasChildren) {
- let parentRow = oldRow - 1;
- this._tree.invalidateRow(parentRow);
- }
-
- // Restore selection if the node was exclusively selected.
- if (!selectNext)
- return;
-
- // Restore selection.
- let rowToSelect = Math.min(oldRow, this._rows.length - 1);
- if (rowToSelect != -1)
- this.selection.rangedSelect(rowToSelect, rowToSelect, true);
- },
-
- nodeMoved:
- function PTV_nodeMoved(aNode, aOldParent, aOldIndex, aNewParent, aNewIndex) {
- NS_ASSERT(this._result, "Got a notification but have no result!");
- if (!this._tree || !this._result)
- return;
-
- // Bail out for hidden separators.
- if (PlacesUtils.nodeIsSeparator(aNode) && this.isSorted())
- return;
-
- // Note that at this point the node has already been moved by the backend,
- // so we must give hints to _getRowForNode to get the old row position.
- let oldParentRow = aOldParent == this._rootNode ?
- undefined : this._getRowForNode(aOldParent, true);
- let oldRow = this._getRowForNode(aNode, true, oldParentRow, aOldIndex);
- if (oldRow < 0)
- throw Cr.NS_ERROR_UNEXPECTED;
-
- // If this node is a container it could take up more than one row.
- let count = this._countVisibleRowsForNodeAtRow(oldRow);
-
- // Persist selection state.
- let nodesToReselect =
- this._getSelectedNodesInRange(oldRow, oldRow + count);
- if (nodesToReselect.length > 0)
- this.selection.selectEventsSuppressed = true;
-
- // Redraw the parent if its twisty state has changed.
- if (aOldParent != this._rootNode && !aOldParent.hasChildren) {
- let parentRow = oldRow - 1;
- this._tree.invalidateRow(parentRow);
- }
-
- // Remove node and its children, if any, from the old position.
- this._rows.splice(oldRow, count);
- this._tree.rowCountChanged(oldRow, -count);
-
- // Insert the node into the new position.
- this.nodeInserted(aNewParent, aNode, aNewIndex);
-
- // Restore selection.
- if (nodesToReselect.length > 0) {
- this._restoreSelection(nodesToReselect, aNewParent);
- this.selection.selectEventsSuppressed = false;
- }
- },
-
- _invalidateCellValue: function PTV__invalidateCellValue(aNode,
- aColumnType) {
- NS_ASSERT(this._result, "Got a notification but have no result!");
- if (!this._tree || !this._result)
- return;
-
- // Nothing to do for the root node.
- if (aNode == this._rootNode)
- return;
-
- let row = this._getRowForNode(aNode);
- if (row == -1)
- return;
-
- let column = this._findColumnByType(aColumnType);
- if (column && !column.element.hidden)
- this._tree.invalidateCell(row, 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(row, lastModifiedColumn);
- }
- },
-
- _populateLivemarkContainer: function PTV__populateLivemarkContainer(aNode) {
- PlacesUtils.livemarks.getLivemark({ id: aNode.itemId })
- .then(aLivemark => {
- let placesNode = aNode;
- // Need to check containerOpen since getLivemark is async.
- if (!placesNode.containerOpen)
- return;
-
- let children = aLivemark.getNodesForContainer(placesNode);
- for (let i = 0; i < children.length; i++) {
- let child = children[i];
- this.nodeInserted(placesNode, child, i);
- }
- }, Components.utils.reportError);
- },
-
- 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) {
- if (aNode.parent && this._controller.hasCachedLivemarkInfo(aNode.parent)) {
- // Find the node in the parent.
- let parentRow = this._flatList ? 0 : this._getRowForNode(aNode.parent);
- for (let i = parentRow; i < this._rows.length; i++) {
- let child = this.nodeForTreeIndex(i);
- if (child.uri == aNode.uri) {
- this._cellProperties.delete(child);
- this._invalidateCellValue(child, this.COLUMN_TYPE_TITLE);
- break;
- }
- }
- return;
- }
-
- 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 == PlacesUIUtils.DESCRIPTION_ANNO) {
- this._invalidateCellValue(aNode, this.COLUMN_TYPE_DESCRIPTION);
- }
- else if (aAnno == PlacesUtils.LMANNO_FEEDURI) {
- PlacesUtils.livemarks.getLivemark({ id: aNode.itemId })
- .then(aLivemark => {
- this._controller.cacheLivemarkInfo(aNode, aLivemark);
- let properties = this._cellProperties.get(aNode);
- this._cellProperties.set(aNode, properties += " livemark");
- // The livemark attribute is set as a cell property on the title cell.
- this._invalidateCellValue(aNode, this.COLUMN_TYPE_TITLE);
- }, Components.utils.reportError);
- }
- },
-
- 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);
- },
-
- containerStateChanged:
- function PTV_containerStateChanged(aNode, aOldState, aNewState) {
- this.invalidateContainer(aNode);
-
- if (PlacesUtils.nodeIsFolder(aNode) ||
- (this._flatList && aNode == this._rootNode)) {
- let queryOptions = PlacesUtils.asQuery(this._rootNode).queryOptions;
- if (queryOptions.excludeItems) {
- return;
- }
- if (aNode.itemId != -1) { // run when there's a valid node id
- PlacesUtils.livemarks.getLivemark({ id: aNode.itemId })
- .then(aLivemark => {
- let shouldInvalidate =
- !this._controller.hasCachedLivemarkInfo(aNode);
- this._controller.cacheLivemarkInfo(aNode, aLivemark);
- if (aNewState == Components.interfaces.nsINavHistoryContainerResultNode.STATE_OPENED) {
- aLivemark.registerForUpdates(aNode, this);
- // Prioritize the current livemark.
- aLivemark.reload();
- PlacesUtils.livemarks.reloadLivemarks();
- if (shouldInvalidate)
- this.invalidateContainer(aNode);
- }
- else {
- aLivemark.unregisterForUpdates(aNode);
- }
- }, () => undefined);
- }
- }
- },
-
- invalidateContainer: function PTV_invalidateContainer(aContainer) {
- NS_ASSERT(this._result, "Need to have a result to update");
- if (!this._tree)
- return;
-
- let startReplacement, replaceCount;
- if (aContainer == this._rootNode) {
- startReplacement = 0;
- replaceCount = this._rows.length;
-
- // If the root node is now closed, the tree is empty.
- if (!this._rootNode.containerOpen) {
- this._rows = [];
- if (replaceCount)
- this._tree.rowCountChanged(startReplacement, -replaceCount);
-
- return;
- }
- }
- else {
- // Update the twisty state.
- let row = this._getRowForNode(aContainer);
- this._tree.invalidateRow(row);
-
- // We don't replace the container node itself, so we should decrease the
- // replaceCount by 1.
- startReplacement = row + 1;
- replaceCount = this._countVisibleRowsForNodeAtRow(row) - 1;
- }
-
- // Persist selection state.
- let nodesToReselect =
- this._getSelectedNodesInRange(startReplacement,
- startReplacement + replaceCount);
-
- // Now update the number of elements.
- this.selection.selectEventsSuppressed = true;
-
- // First remove the old elements
- this._rows.splice(startReplacement, replaceCount);
-
- // If the container is now closed, we're done.
- if (!aContainer.containerOpen) {
- let oldSelectionCount = this.selection.count;
- if (replaceCount)
- this._tree.rowCountChanged(startReplacement, -replaceCount);
-
- // Select the row next to the closed container if any of its
- // children were selected, and nothing else is selected.
- if (nodesToReselect.length > 0 &&
- nodesToReselect.length == oldSelectionCount) {
- this.selection.rangedSelect(startReplacement, startReplacement, true);
- this._tree.ensureRowIsVisible(startReplacement);
- }
-
- this.selection.selectEventsSuppressed = false;
- return;
- }
-
- // Otherwise, start a batch first.
- this._tree.beginUpdateBatch();
- if (replaceCount)
- this._tree.rowCountChanged(startReplacement, -replaceCount);
-
- let toOpenElements = [];
- let elementsAddedCount = this._buildVisibleSection(aContainer,
- startReplacement,
- toOpenElements);
- if (elementsAddedCount)
- this._tree.rowCountChanged(startReplacement, elementsAddedCount);
-
- if (!this._flatList) {
- // Now, open any containers that were persisted.
- for (let i = 0; i < toOpenElements.length; i++) {
- let item = toOpenElements[i];
- let 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;
- }
- }
-
- if (this._controller.hasCachedLivemarkInfo(aContainer)) {
- let queryOptions = PlacesUtils.asQuery(this._result.root).queryOptions;
- if (!queryOptions.excludeItems) {
- this._populateLivemarkContainer(aContainer);
- }
- }
-
- this._tree.endUpdateBatch();
-
- // Restore selection.
- this._restoreSelection(nodesToReselect, aContainer);
- this.selection.selectEventsSuppressed = false;
- },
-
- _columns: [],
- _findColumnByType: function PTV__findColumnByType(aColumnType) {
- if (this._columns[aColumnType])
- return this._columns[aColumnType];
-
- let columns = this._tree.columns;
- let colCount = columns.count;
- for (let 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");
-
- let columns = this._tree.columns;
-
- // Clear old sorting indicator.
- let 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;
-
- let [desiredColumn, desiredIsDescending] =
- this._sortTypeToColumnType(aSortingMode);
- let colCount = columns.count;
- let column = this._findColumnByType(desiredColumn);
- if (column) {
- let sortDir = desiredIsDescending ? "descending" : "ascending";
- column.element.setAttribute("sortDirection", sortDir);
- }
- },
-
- _inBatchMode: false,
- batching: function PTV__batching(aToggleMode) {
- if (this._inBatchMode != aToggleMode) {
- this._inBatchMode = this.selection.selectEventsSuppressed = aToggleMode;
- if (this._inBatchMode) {
- this._tree.beginUpdateBatch();
- }
- else {
- this._tree.endUpdateBatch();
- }
- }
- },
-
- get result() this._result,
- set result(val) {
- if (this._result) {
- this._result.removeObserver(this);
- this._rootNode.containerOpen = false;
- }
-
- if (val) {
- this._result = val;
- this._rootNode = this._result.root;
- this._cellProperties = new Map();
- this._cuttingNodes = new Set();
- }
- else if (this._result) {
- delete this._result;
- delete this._rootNode;
- delete this._cellProperties;
- delete this._cuttingNodes;
- }
-
- // 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._rows.length)
- throw Cr.NS_ERROR_INVALID_ARG;
-
- return this._getNodeForRow(aIndex);
- },
-
- treeIndexForNode: function PTV_treeNodeForIndex(aNode) {
- // The API allows passing invisible nodes.
- try {
- return this._getRowForNode(aNode, true);
- }
- catch(ex) { }
-
- return Ci.nsINavHistoryResultTreeViewer.INDEX_INVISIBLE;
- },
-
- _getResourceForNode: function PTV_getResourceForNode(aNode)
- {
- let 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() this._rows.length,
- get selection() this._selection,
- set selection(val) this._selection = val,
-
- getRowProperties: function() { return ""; },
-
- getCellProperties:
- function PTV_getCellProperties(aRow, aColumn) {
- // for anonid-trees, we need to add the column-type manually
- var props = "";
- let columnType = aColumn.element.getAttribute("anonid");
- if (columnType)
- props += columnType;
- else
- columnType = aColumn.id;
-
- // Set the "ltr" property on url cells
- if (columnType == "url")
- props += " ltr";
-
- if (columnType != "title")
- return props;
-
- let node = this._getNodeForRow(aRow);
-
- if (this._cuttingNodes.has(node)) {
- props += " cutting";
- }
-
- let properties = this._cellProperties.get(node);
- if (properties === undefined) {
- properties = "";
- let itemId = node.itemId;
- let nodeType = node.type;
- if (PlacesUtils.containerTypes.indexOf(nodeType) != -1) {
- if (nodeType == Ci.nsINavHistoryResultNode.RESULT_TYPE_QUERY) {
- properties += " query";
- if (PlacesUtils.nodeIsTagQuery(node))
- properties += " tagContainer";
- else if (PlacesUtils.nodeIsDay(node))
- properties += " dayContainer";
- else if (PlacesUtils.nodeIsHost(node))
- properties += " hostContainer";
- }
- else if (nodeType == Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER ||
- nodeType == Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER_SHORTCUT) {
- if (this._controller.hasCachedLivemarkInfo(node)) {
- properties += " livemark";
- }
- else {
- PlacesUtils.livemarks.getLivemark({ id: node.itemId })
- .then(aLivemark => {
- this._controller.cacheLivemarkInfo(node, aLivemark);
- let props = this._cellProperties.get(node);
- this._cellProperties.set(node, props += " livemark");
- // The livemark attribute is set as a cell property on the title cell.
- this._invalidateCellValue(node, this.COLUMN_TYPE_TITLE);
- }, () => undefined);
- }
- }
-
- if (itemId != -1) {
- let queryName = PlacesUIUtils.getLeftPaneQueryNameFromId(itemId);
- if (queryName)
- properties += " OrganizerQuery_" + queryName;
- }
- }
- else if (nodeType == Ci.nsINavHistoryResultNode.RESULT_TYPE_SEPARATOR)
- properties += " separator";
- else if (PlacesUtils.nodeIsURI(node)) {
- properties += " " + PlacesUIUtils.guessUrlSchemeForUI(node.uri);
-
- if (this._controller.hasCachedLivemarkInfo(node.parent)) {
- properties += " livemarkItem";
- if (node.accessCount) {
- properties += " visited";
- }
- }
- }
-
- this._cellProperties.set(node, properties);
- }
-
- return props + " " + properties;
- },
-
- getColumnProperties: function(aColumn) { return ""; },
-
- isContainer: function PTV_isContainer(aRow) {
- // Only leaf nodes aren't listed in the rows array.
- let node = this._rows[aRow];
- if (node === undefined)
- return false;
-
- 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)) {
- let parent = node.parent;
- if ((PlacesUtils.nodeIsQuery(parent) ||
- PlacesUtils.nodeIsFolder(parent)) &&
- !PlacesUtils.asQuery(node).hasChildren)
- return PlacesUtils.asQuery(parent).queryOptions.expandQueries;
- }
- return true;
- }
- return false;
- },
-
- isContainerOpen: function PTV_isContainerOpen(aRow) {
- if (this._flatList)
- return false;
-
- // All containers are listed in the rows array.
- return this._rows[aRow].containerOpen;
- },
-
- isContainerEmpty: function PTV_isContainerEmpty(aRow) {
- if (this._flatList)
- return true;
-
- let node = this._rows[aRow];
- if (this._controller.hasCachedLivemarkInfo(node)) {
- let queryOptions = PlacesUtils.asQuery(this._result.root).queryOptions;
- return queryOptions.excludeItems;
- }
-
- // All containers are listed in the rows array.
- return !node.hasChildren;
- },
-
- isSeparator: function PTV_isSeparator(aRow) {
- // All separators are listed in the rows array.
- let node = this._rows[aRow];
- return node && PlacesUtils.nodeIsSeparator(node);
- },
-
- isSorted: function PTV_isSorted() {
- return this._result.sortingMode !=
- Ci.nsINavHistoryQueryOptions.SORT_BY_NONE;
- },
-
- canDrop: function PTV_canDrop(aRow, aOrientation, aDataTransfer) {
- if (!this._result)
- throw Cr.NS_ERROR_UNEXPECTED;
-
- // Drop position into a sorted treeview would be wrong.
- if (this.isSorted())
- return false;
-
- let ip = this._getInsertionPoint(aRow, aOrientation);
- return ip && PlacesControllerDragHelper.canDrop(ip, aDataTransfer);
- },
-
- _getInsertionPoint: function PTV__getInsertionPoint(index, orientation) {
- let container = this._result.root;
- let 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) {
- let 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.
- container = lastSelected.parent;
-
- // During its Drag & Drop operation, the tree code closes-and-opens
- // containers very often (part of the XUL "spring-loaded folders"
- // implementation). And in certain cases, we may reach a closed
- // container here. However, we can simply bail out when this happens,
- // because we would then be back here in less than a millisecond, when
- // the container had been reopened.
- if (!container || !container.containerOpen)
- return null;
-
- // Avoid the potentially expensive call to getChildIndex
- // if we know this container doesn't allow insertion.
- if (PlacesControllerDragHelper.disallowInsertion(container))
- return null;
-
- let queryOptions = PlacesUtils.asQuery(this._result.root).queryOptions;
- if (queryOptions.sortingMode !=
- Ci.nsINavHistoryQueryOptions.SORT_BY_NONE) {
- // If we are within a sorted view, insert at the end.
- 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 {
- let lsi = container.getChildIndex(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, aDataTransfer) {
- // 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.
- let ip = this._getInsertionPoint(aRow, aOrientation);
- if (ip)
- PlacesControllerDragHelper.onDrop(ip, aDataTransfer);
-
- PlacesControllerDragHelper.currentDropTarget = null;
- },
-
- getParentIndex: function PTV_getParentIndex(aRow) {
- let [parentNode, parentRow] = this._getParentByChildRow(aRow);
- return parentRow;
- },
-
- hasNextSibling: function PTV_hasNextSibling(aRow, aAfterIndex) {
- if (aRow == this._rows.length - 1) {
- // The last row has no sibling.
- return false;
- }
-
- let node = this._rows[aRow];
- if (node === undefined || this._isPlainContainer(node.parent)) {
- // The node is a child of a plain container.
- // If the next row is either unset or has the same parent,
- // it's a sibling.
- let nextNode = this._rows[aRow + 1];
- return (nextNode == undefined || nextNode.parent == node.parent);
- }
-
- let thisLevel = node.indentLevel;
- for (let i = aAfterIndex + 1; i < this._rows.length; ++i) {
- let rowNode = this._getNodeForRow(i);
- let nextLevel = rowNode.indentLevel;
- if (nextLevel == thisLevel)
- return true;
- if (nextLevel < thisLevel)
- break;
- }
-
- return false;
- },
-
- getLevel: function(aRow) this._getNodeForRow(aRow).indentLevel,
-
- getImageSrc: function PTV_getImageSrc(aRow, aColumn) {
- // Only the title column has an image.
- if (this._getColumnType(aColumn) != this.COLUMN_TYPE_TITLE)
- return "";
-
- return this._getNodeForRow(aRow).icon;
- },
-
- getProgressMode: function(aRow, aColumn) { },
- getCellValue: function(aRow, aColumn) { },
-
- getCellText: function PTV_getCellText(aRow, aColumn) {
- let node = this._getNodeForRow(aRow);
- switch (this._getColumnType(aColumn)) {
- 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, true);
- 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, PlacesUIUtils.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 "";
- case this.COLUMN_TYPE_PARENTFOLDER:
- if (PlacesUtils.nodeIsQuery(node.parent) &&
- PlacesUtils.asQuery(node.parent).queryOptions.queryType ==
- Components.interfaces.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY && node.uri)
- return "";
- var bmsvc = Components.classes["@mozilla.org/browser/nav-bookmarks-service;1"].
- getService(Components.interfaces.nsINavBookmarksService);
- var rowId = node.itemId;
- try {
- var parentFolderId = bmsvc.getFolderIdForItem(rowId);
- var folderTitle = bmsvc.getItemTitle(parentFolderId);
- } catch(ex) {
- var folderTitle = "";
- }
- return folderTitle;
- case this.COLUMN_TYPE_PARENTFOLDERPATH:
- if (PlacesUtils.nodeIsQuery(node.parent) &&
- PlacesUtils.asQuery(node.parent).queryOptions.queryType ==
- Components.interfaces.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY && node.uri)
- return "";
- var bmsvc = Components.classes["@mozilla.org/browser/nav-bookmarks-service;1"].
- getService(Components.interfaces.nsINavBookmarksService);
- var rowId = node.itemId;
- try {
- var FolderId;
- var parentFolderId = bmsvc.getFolderIdForItem(rowId);
- var folderTitle = bmsvc.getItemTitle(parentFolderId);
- while ((FolderId = bmsvc.getFolderIdForItem(parentFolderId))) {
- if (FolderId == parentFolderId)
- break;
- parentFolderId = FolderId;
- var text = bmsvc.getItemTitle(parentFolderId);
- if (!text)
- break;
- folderTitle = text + " /"+ folderTitle;
- }
- folderTitle = folderTitle.replace(/^\s/,"");
- } catch(ex) {
- var folderTitle = "";
- }
- return folderTitle;
- }
- return "";
- },
-
- setTree: function PTV_setTree(aTree) {
- // If we are replacing the tree during a batch, there is a concrete risk
- // that the treeView goes out of sync, thus it's safer to end the batch now.
- // This is a no-op if we are not batching.
- this.batching(false);
-
- let 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.removeObserver(this);
- this._rootNode.containerOpen = false;
- }
- }
- if (aTree)
- this._finishInit();
- }
- },
-
- toggleOpenState: function PTV_toggleOpenState(aRow) {
- if (!this._result)
- throw Cr.NS_ERROR_UNEXPECTED;
-
- let node = this._rows[aRow];
- if (this._flatList && this._openContainerCallback) {
- this._openContainerCallback(node);
- return;
- }
-
- // Persist containers open status, but never persist livemarks.
- if (!this._controller.hasCachedLivemarkInfo(node)) {
- let 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.
- let allowTriState = PlacesUtils.nodeIsFolder(this._result.root);
-
- let oldSort = this._result.sortingMode;
- let oldSortingAnnotation = this._result.sortingAnnotation;
- let newSort;
- let newSortingAnnotation = "";
- const NHQO = Ci.nsINavHistoryQueryOptions;
- switch (this._getColumnType(aColumn)) {
- 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 == PlacesUIUtils.DESCRIPTION_ANNO) {
- newSort = NHQO.SORT_BY_ANNOTATION_DESCENDING;
- newSortingAnnotation = PlacesUIUtils.DESCRIPTION_ANNO;
- }
- else if (allowTriState &&
- oldSort == NHQO.SORT_BY_ANNOTATION_DESCENDING &&
- oldSortingAnnotation == PlacesUIUtils.DESCRIPTION_ANNO)
- newSort = NHQO.SORT_BY_NONE;
- else {
- newSort = NHQO.SORT_BY_ANNOTATION_ASCENDING;
- newSortingAnnotation = PlacesUIUtils.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;
- case this.COLUMN_TYPE_PARENTFOLDER:
- return;
-
- break;
- case this.COLUMN_TYPE_PARENTFOLDERPATH:
- return;
-
- 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;
-
- let node = this._rows[aRow];
- if (!node) {
- Cu.reportError("isEditable called for an unbuilt row.");
- return false;
- }
- let itemId = node.itemId;
-
- // Only bookmark-nodes are editable. Fortunately, this check also takes
- // care of livemark children.
- if (itemId == -1)
- return false;
-
- // The following items are also not editable, even though they are bookmark
- // items.
- // * places-roots
- // * the left pane special folders and queries (those are place: uri
- // bookmarks)
- // * separators
- //
- // Note that concrete itemIds aren't used intentionally. For example, we
- // have no reason to disallow renaming a shortcut to the Bookmarks Toolbar,
- // except for the one under All Bookmarks.
- if (PlacesUtils.nodeIsSeparator(node) || PlacesUtils.isRootItem(itemId))
- return false;
-
- let parentId = PlacesUtils.getConcreteItemId(node.parent);
- if (parentId == PlacesUIUtils.leftPaneFolderId ||
- parentId == PlacesUIUtils.allBookmarksFolderId) {
- // Note that the for the time being this is the check that actually
- // blocks renaming places "roots", and not the isRootItem check above.
- // That's because places root are only exposed through folder shortcuts
- // descendants of the left pane folder.
- return false;
- }
-
- return true;
- },
-
- setCellText: function PTV_setCellText(aRow, aColumn, aText) {
- // We may only get here if the cell is editable.
- let node = this._rows[aRow];
- if (node.title != aText) {
- let txn = new PlacesEditItemTitleTransaction(node.itemId, aText);
- PlacesUtils.transactionManager.doTransaction(txn);
- }
- },
-
- toggleCutNode: function PTV_toggleCutNode(aNode, aValue) {
- let currentVal = this._cuttingNodes.has(aNode);
- if (currentVal != aValue) {
- if (aValue)
- this._cuttingNodes.add(aNode);
- else
- this._cuttingNodes.delete(aNode);
-
- this._invalidateCellValue(aNode, this.COLUMN_TYPE_TITLE);
- }
- },
-
- selectionChanged: function() { },
- cycleCell: function(aRow, aColumn) { },
- isSelectable: function(aRow, aColumn) { return false; },
- performAction: function(aAction) { },
- performActionOnRow: function(aAction, aRow) { },
- performActionOnCell: function(aAction, aRow, aColumn) { }
-};
diff --git a/components/places/jar.mn b/components/places/jar.mn
deleted file mode 100644
index 41222e1..0000000
--- a/components/places/jar.mn
+++ /dev/null
@@ -1,34 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-browser.jar:
-% overlay chrome://browser/content/places/places.xul chrome://browser/content/places/downloadsViewOverlay.xul
-# Provide another URI for the bookmarkProperties dialog so we can persist the
-# attributes separately
- content/browser/places/bookmarkProperties2.xul (content/bookmarkProperties.xul)
-* content/browser/places/places.xul (content/places.xul)
-* content/browser/places/places.js (content/places.js)
- content/browser/places/places.css (content/places.css)
- content/browser/places/organizer.css (content/organizer.css)
- content/browser/places/bookmarkProperties.xul (content/bookmarkProperties.xul)
- content/browser/places/bookmarkProperties.js (content/bookmarkProperties.js)
- content/browser/places/placesOverlay.xul (content/placesOverlay.xul)
-* content/browser/places/menu.xml (content/menu.xml)
- content/browser/places/tree.xml (content/tree.xml)
- content/browser/places/controller.js (content/controller.js)
- content/browser/places/treeView.js (content/treeView.js)
-* content/browser/places/browserPlacesViews.js (content/browserPlacesViews.js)
-# keep the Places version of the history sidebar at history/history-panel.xul
-# to prevent having to worry about between versions of the browser
-* content/browser/history/history-panel.xul (content/history-panel.xul)
- content/browser/places/history-panel.js (content/history-panel.js)
-# ditto for the bookmarks sidebar
- content/browser/bookmarks/bookmarksPanel.xul (content/bookmarksPanel.xul)
- content/browser/bookmarks/bookmarksPanel.js (content/bookmarksPanel.js)
-* content/browser/bookmarks/sidebarUtils.js (content/sidebarUtils.js)
- content/browser/places/moveBookmarks.xul (content/moveBookmarks.xul)
- content/browser/places/moveBookmarks.js (content/moveBookmarks.js)
- content/browser/places/editBookmarkOverlay.xul (content/editBookmarkOverlay.xul)
- content/browser/places/editBookmarkOverlay.js (content/editBookmarkOverlay.js)
-* content/browser/places/downloadsViewOverlay.xul (content/downloadsViewOverlay.xul)
diff --git a/components/places/moz.build b/components/places/moz.build
deleted file mode 100644
index f8b0d12..0000000
--- a/components/places/moz.build
+++ /dev/null
@@ -1,9 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-JAR_MANIFESTS += ['jar.mn']
-
-EXTRA_JS_MODULES += [ 'PlacesUIUtils.jsm' ]
diff --git a/components/preferences/advanced.js b/components/preferences/advanced.js
deleted file mode 100644
index aab58b3..0000000
--- a/components/preferences/advanced.js
+++ /dev/null
@@ -1,755 +0,0 @@
-# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-// Load DownloadUtils module for convertByteUnits
-Components.utils.import("resource://gre/modules/DownloadUtils.jsm");
-Components.utils.import("resource://gre/modules/ctypes.jsm");
-Components.utils.import("resource://gre/modules/Services.jsm");
-Components.utils.import("resource://gre/modules/LoadContextInfo.jsm");
-Components.utils.import("resource://gre/modules/BrowserUtils.jsm");
-
-var gAdvancedPane = {
- _inited: false,
-
- /**
- * Brings the appropriate tab to the front and initializes various bits of UI.
- */
- init: function ()
- {
- this._inited = true;
- var advancedPrefs = document.getElementById("advancedPrefs");
-
- var extraArgs = window.arguments[1];
- if (extraArgs && extraArgs["advancedTab"]){
- advancedPrefs.selectedTab = document.getElementById(extraArgs["advancedTab"]);
- } else {
- var preference = document.getElementById("browser.preferences.advanced.selectedTabIndex");
- if (preference.value !== null)
- advancedPrefs.selectedIndex = preference.value;
- }
-
-#ifdef HAVE_SHELL_SERVICE
- this.updateSetDefaultBrowser();
-#ifdef XP_WIN
- // In Windows 8 we launch the control panel since it's the only
- // way to get all file type association prefs. So we don't know
- // when the user will select the default. We refresh here periodically
- // in case the default changes. On other Windows OS's defaults can also
- // be set while the prefs are open.
- window.setInterval(this.updateSetDefaultBrowser, 1000);
-#endif
-#endif
-
-#ifdef MOZ_UPDATER
- this.updateReadPrefs();
-#endif
- this.updateOfflineAppsPermissions();
- this.updateOfflineApps();
-
- this.updateActualCacheSize();
- this.updateActualAppCacheSize();
-
- // Notify observers that the UI is now ready
- Services.obs.notifyObservers(window, "advanced-pane-loaded", null);
- },
-
- /**
- * Stores the identity of the current tab in preferences so that the selected
- * tab can be persisted between openings of the preferences window.
- */
- tabSelectionChanged: function ()
- {
- if (!this._inited)
- return;
- var advancedPrefs = document.getElementById("advancedPrefs");
- var preference = document.getElementById("browser.preferences.advanced.selectedTabIndex");
- preference.valueFromPreferences = advancedPrefs.selectedIndex;
- },
-
- // GENERAL TAB
-
- /*
- * Preferences:
- *
- * accessibility.browsewithcaret
- * - true enables keyboard navigation and selection within web pages using a
- * visible caret, false uses normal keyboard navigation with no caret
- * accessibility.typeaheadfind
- * - when set to true, typing outside text areas and input boxes will
- * automatically start searching for what's typed within the current
- * document; when set to false, no search action happens
- * general.autoScroll
- * - when set to true, clicking the scroll wheel on the mouse activates a
- * mouse mode where moving the mouse down scrolls the document downward with
- * speed correlated with the distance of the cursor from the original
- * position at which the click occurred (and likewise with movement upward);
- * if false, this behavior is disabled
- * general.smoothScroll
- * - set to true to enable finer page scrolling than line-by-line on page-up,
- * page-down, and other such page movements
- * layout.spellcheckDefault
- * - an integer:
- * 0 disables spellchecking
- * 1 enables spellchecking, but only for multiline text fields
- * 2 enables spellchecking for all text fields
- */
-
- /**
- * Stores the original value of the spellchecking preference to enable proper
- * restoration if unchanged (since we're mapping a tristate onto a checkbox).
- */
- _storedSpellCheck: 0,
-
- /**
- * Returns true if any spellchecking is enabled and false otherwise, caching
- * the current value to enable proper pref restoration if the checkbox is
- * never changed.
- */
- readCheckSpelling: function ()
- {
- var pref = document.getElementById("layout.spellcheckDefault");
- this._storedSpellCheck = pref.value;
-
- return (pref.value != 0);
- },
-
- /**
- * Returns the value of the spellchecking preference represented by UI,
- * preserving the preference's "hidden" value if the preference is
- * unchanged and represents a value not strictly allowed in UI.
- */
- writeCheckSpelling: function ()
- {
- var checkbox = document.getElementById("checkSpelling");
- return checkbox.checked ? (this._storedSpellCheck == 2 ? 2 : 1) : 0;
- },
-
- /**
- * security.OCSP.enabled is an integer value for legacy reasons.
- * A value of 1 means OCSP is enabled. Any other value means it is disabled.
- */
- readEnableOCSP: function ()
- {
- var preference = document.getElementById("security.OCSP.enabled");
- // This is the case if the preference is the default value.
- if (preference.value === undefined) {
- return true;
- }
- return preference.value == 1;
- },
-
- /**
- * See documentation for readEnableOCSP.
- */
- writeEnableOCSP: function ()
- {
- var checkbox = document.getElementById("enableOCSP");
- return checkbox.checked ? 1 : 0;
- },
-
- /**
- * When the user toggles the layers.acceleration.disabled pref,
- * sync its new value to the gfx.direct2d.disabled pref too.
- */
- updateHardwareAcceleration: function()
- {
-#ifdef XP_WIN
- var fromPref = document.getElementById("layers.acceleration.disabled");
- var toPref = document.getElementById("gfx.direct2d.disabled");
- toPref.value = fromPref.value;
-#endif
- },
-
- // DATA CHOICES TAB
-
- /**
- * opening links behind a modal dialog is poor form. Work around flawed text-link handling here.
- */
- openTextLink: function (evt) {
- let where = Services.prefs.getBoolPref("browser.preferences.instantApply") ? "tab" : "window";
- openUILinkIn(evt.target.getAttribute("href"), where);
- evt.preventDefault();
- },
-
- /**
- * Set up or hide the Learn More links for various data collection options
- */
- _setupLearnMoreLink: function (pref, element) {
- // set up the Learn More link with the correct URL
- let url = Services.prefs.getCharPref(pref);
- let el = document.getElementById(element);
-
- if (url) {
- el.setAttribute("href", url);
- } else {
- el.setAttribute("hidden", "true");
- }
- },
-
- // NETWORK TAB
-
- /*
- * Preferences:
- *
- * browser.cache.disk.capacity
- * - the size of the browser cache in KB
- * - Only used if browser.cache.disk.smart_size.enabled is disabled
- */
-
- /**
- * Displays a dialog in which proxy settings may be changed.
- */
- showConnections: function ()
- {
- document.documentElement.openSubDialog("chrome://browser/content/preferences/connection.xul",
- "", null);
- },
-
- // Retrieves the amount of space currently used by disk cache
- updateActualCacheSize: function ()
- {
- var sum = 0;
- function updateUI(consumption) {
- var actualSizeLabel = document.getElementById("actualDiskCacheSize");
- var sizeStrings = DownloadUtils.convertByteUnits(consumption);
- var prefStrBundle = document.getElementById("bundlePreferences");
- var sizeStr = prefStrBundle.getFormattedString("actualDiskCacheSize", sizeStrings);
- actualSizeLabel.value = sizeStr;
- }
-
- Visitor.prototype = {
- expected: 0,
- sum: 0,
- QueryInterface: function listener_qi(iid) {
- if (iid.equals(Components.interfaces.nsISupports) ||
- iid.equals(Components.interfaces.nsICacheStorageVisitor)) {
- return this;
- }
- throw Components.results.NS_ERROR_NO_INTERFACE;
- },
- onCacheStorageInfo: function(num, consumption)
- {
- this.sum += consumption;
- if (!--this.expected)
- updateUI(this.sum);
- }
- };
- function Visitor(callbacksExpected) {
- this.expected = callbacksExpected;
- }
-
- var cacheService =
- Components.classes["@mozilla.org/netwerk/cache-storage-service;1"]
- .getService(Components.interfaces.nsICacheStorageService);
- // non-anonymous
- var storage1 = cacheService.diskCacheStorage(LoadContextInfo.default, false);
- // anonymous
- var storage2 = cacheService.diskCacheStorage(LoadContextInfo.anonymous, false);
-
- // expect 2 callbacks
- var visitor = new Visitor(2);
- storage1.asyncVisitStorage(visitor, false /* Do not walk entries */);
- storage2.asyncVisitStorage(visitor, false /* Do not walk entries */);
- },
-
- // Retrieves the amount of space currently used by offline cache
- updateActualAppCacheSize: function ()
- {
- var visitor = {
- onCacheStorageInfo: function (aEntryCount, aConsumption, aCapacity, aDiskDirectory)
- {
- var actualSizeLabel = document.getElementById("actualAppCacheSize");
- var sizeStrings = DownloadUtils.convertByteUnits(aConsumption);
- var prefStrBundle = document.getElementById("bundlePreferences");
- var sizeStr = prefStrBundle.getFormattedString("actualAppCacheSize", sizeStrings);
- actualSizeLabel.value = sizeStr;
- }
- };
-
- var cacheService =
- Components.classes["@mozilla.org/netwerk/cache-storage-service;1"]
- .getService(Components.interfaces.nsICacheStorageService);
- var storage = cacheService.appCacheStorage(LoadContextInfo.default, null);
- storage.asyncVisitStorage(visitor, false);
- },
-
- updateCacheSizeUI: function (smartSizeEnabled)
- {
- document.getElementById("useCacheBefore").disabled = smartSizeEnabled;
- document.getElementById("cacheSize").disabled = smartSizeEnabled;
- document.getElementById("useCacheAfter").disabled = smartSizeEnabled;
- },
-
- readSmartSizeEnabled: function ()
- {
- // The smart_size.enabled preference element is inverted="true", so its
- // value is the opposite of the actual pref value
- var disabled = document.getElementById("browser.cache.disk.smart_size.enabled").value;
- this.updateCacheSizeUI(!disabled);
- },
-
- /**
- * Converts the cache size from units of KB to units of MB and returns that
- * value.
- */
- readCacheSize: function ()
- {
- var preference = document.getElementById("browser.cache.disk.capacity");
- return preference.value / 1024;
- },
-
- /**
- * Converts the cache size as specified in UI (in MB) to KB and returns that
- * value.
- */
- writeCacheSize: function ()
- {
- var cacheSize = document.getElementById("cacheSize");
- var intValue = parseInt(cacheSize.value, 10);
- return isNaN(intValue) ? 0 : intValue * 1024;
- },
-
- /**
- * Clears the cache.
- */
- clearCache: function ()
- {
- var cache = Components.classes["@mozilla.org/netwerk/cache-storage-service;1"]
- .getService(Components.interfaces.nsICacheStorageService);
- try {
- cache.clear();
- } catch(ex) {}
- this.updateActualCacheSize();
- },
-
- /**
- * Clears the application cache.
- */
- clearOfflineAppCache: function ()
- {
- Components.utils.import("resource:///modules/offlineAppCache.jsm");
- OfflineAppCacheHelper.clear();
-
- this.updateActualAppCacheSize();
- this.updateOfflineApps();
- },
-
- updateOfflineAppsPermissions: function()
- {
- var permPref = document.getElementById("offline-apps.permissions");
- var allowPref = document.getElementById("offline-apps.allow_by_default");
- var notifyPref = document.getElementById("browser.offline-apps.notify");
- switch (permPref.value) {
- case 0: allowPref.value = false;
- notifyPref.value = false;
- break;
- case 1: allowPref.value = false;
- notifyPref.value = true;
- break;
- case 2: allowPref.value = true;
- notifyPref.value = true;
- break;
- default: console.error("Preference error: Invalid value ",permPref.value," for offline app permissions - resetting to default.");
- permPref.value = 2;
- allowPref.value = true;
- notifyPref.value = true;
- }
- // Set state of "Exceptions" button accordingly.
- var button = document.getElementById("offlineNotifyExceptions");
- button.disabled = !allowPref.value && !notifyPref.value;
- },
-
- showOfflineExceptions: function()
- {
- var bundlePreferences = document.getElementById("bundlePreferences");
- var params = { blockVisible : false,
- sessionVisible : false,
- allowVisible : false,
- prefilledHost : "",
- permissionType : "offline-app",
- manageCapability : Components.interfaces.nsIPermissionManager.DENY_ACTION,
- windowTitle : bundlePreferences.getString("offlinepermissionstitle"),
- introText : bundlePreferences.getString("offlinepermissionstext") };
- document.documentElement.openWindow("Browser:Permissions",
- "chrome://browser/content/preferences/permissions.xul",
- "", params);
- },
-
- // XXX: duplicated in browser.js
- _getOfflineAppUsage: function (perm, 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 (perm.matchesURI(uri, true)) {
- var cache = cacheService.getActiveCache(groups[i]);
- usage += cache.usage;
- }
- }
-
- return usage;
- },
-
- /**
- * Updates the list of offline applications
- */
- updateOfflineApps: function ()
- {
- var pm = Components.classes["@mozilla.org/permissionmanager;1"]
- .getService(Components.interfaces.nsIPermissionManager);
-
- var list = document.getElementById("offlineAppsList");
- while (list.firstChild) {
- list.removeChild(list.firstChild);
- }
-
- var cacheService = Components.classes["@mozilla.org/network/application-cache-service;1"].
- getService(Components.interfaces.nsIApplicationCacheService);
- var groups = cacheService.getGroups();
-
- var bundle = document.getElementById("bundlePreferences");
-
- var enumerator = pm.enumerator;
- while (enumerator.hasMoreElements()) {
- var perm = enumerator.getNext().QueryInterface(Components.interfaces.nsIPermission);
- 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("origin", perm.principal.origin);
- var converted = DownloadUtils.
- convertByteUnits(this._getOfflineAppUsage(perm, 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 origin = item.getAttribute("origin");
- var principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(origin);
-
- 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", [principal.URI.prePath]);
- var confirm = bundle.getString("offlineAppRemoveConfirm");
- var result = prompts.confirmEx(window, title, prompt, flags, confirm,
- null, null, null, {});
- if (result != 0)
- return;
-
- // get the permission
- var pm = Components.classes["@mozilla.org/permissionmanager;1"]
- .getService(Components.interfaces.nsIPermissionManager);
- var perm = pm.getPermissionObject(principal, "offline-app", true);
- if (perm) {
- // clear offline cache entries
- try {
- var cacheService = Components.classes["@mozilla.org/network/application-cache-service;1"].
- getService(Components.interfaces.nsIApplicationCacheService);
- var groups = cacheService.getGroups();
- for (var i = 0; i < groups.length; i++) {
- var uri = Services.io.newURI(groups[i], null, null);
- if (perm.matchesURI(uri, true)) {
- var cache = cacheService.getActiveCache(groups[i]);
- cache.discard();
- }
- }
- } catch (e) {}
-
- pm.removePermission(perm);
- }
- list.removeChild(item);
- gAdvancedPane.offlineAppSelected();
- this.updateActualAppCacheSize();
- },
-
- // 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
- */
-
-#ifdef MOZ_UPDATER
- /**
- * Selects the item of the radiogroup, and sets the warnIncompatible checkbox
- * based on the pref values and locked states.
- *
- * UI state matrix for update preference conditions
- *
- * UI Components: Preferences
- * Radiogroup i = app.update.enabled
- * Warn before disabling extensions checkbox ii = app.update.auto
- * iii = app.update.mode
- *
- * Disabled states:
- * Element pref value locked disabled
- * radiogroup i t/f f false
- * i t/f *t* *true*
- * ii t/f f false
- * ii t/f *t* *true*
- * iii 0/1/2 t/f false
- * warnIncompatible i t f false
- * i t *t* *true*
- * i *f* t/f *true*
- * ii t f false
- * ii t *t* *true*
- * ii *f* t/f *true*
- * iii 0/1/2 f false
- * iii 0/1/2 *t* *true*
- */
- updateReadPrefs: function ()
- {
- var enabledPref = document.getElementById("app.update.enabled");
- var autoPref = document.getElementById("app.update.auto");
- var radiogroup = document.getElementById("updateRadioGroup");
-
- if (!enabledPref.value) // Don't care for autoPref.value in this case.
- radiogroup.value="manual"; // 3. Never check for updates.
- else if (autoPref.value) // enabledPref.value && autoPref.value
- radiogroup.value="auto"; // 1. Automatically install updates for Desktop only
- else // enabledPref.value && !autoPref.value
- radiogroup.value="checkOnly"; // 2. Check, but let me choose
-
- var canCheck = Components.classes["@mozilla.org/updates/update-service;1"].
- getService(Components.interfaces.nsIApplicationUpdateService).
- canCheckForUpdates;
- // canCheck is false if the enabledPref is false and locked,
- // or the binary platform or OS version is not known.
- // A locked pref is sufficient to disable the radiogroup.
- radiogroup.disabled = !canCheck || enabledPref.locked || autoPref.locked;
-
- var modePref = document.getElementById("app.update.mode");
- var warnIncompatible = document.getElementById("warnIncompatible");
- // the warnIncompatible checkbox value is set by readAddonWarn
- warnIncompatible.disabled = radiogroup.disabled || modePref.locked ||
- !enabledPref.value || !autoPref.value;
- },
-
- /**
- * Sets the pref values based on the selected item of the radiogroup,
- * and sets the disabled state of the warnIncompatible checkbox accordingly.
- */
- updateWritePrefs: function ()
- {
- var enabledPref = document.getElementById("app.update.enabled");
- var autoPref = document.getElementById("app.update.auto");
- var radiogroup = document.getElementById("updateRadioGroup");
- switch (radiogroup.value) {
- case "auto": // 1. Automatically install updates for Desktop only
- enabledPref.value = true;
- autoPref.value = true;
- break;
- case "checkOnly": // 2. Check, but let me choose
- enabledPref.value = true;
- autoPref.value = false;
- break;
- case "manual": // 3. Never check for updates.
- enabledPref.value = false;
- autoPref.value = false;
- }
-
- var warnIncompatible = document.getElementById("warnIncompatible");
- var modePref = document.getElementById("app.update.mode");
- warnIncompatible.disabled = enabledPref.locked || !enabledPref.value ||
- autoPref.locked || !autoPref.value ||
- modePref.locked;
-
- },
-
- /**
- * 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.mode 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 warn = preference.value != 0;
- gAdvancedPane._modePreference = warn ? preference.value : 1;
- return warn;
- },
-
- /**
- * 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);
- },
-#endif
-
- // CERTIFICATES TAB
-
- /*
- * Preferences:
- *
- * 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 from which the user can manage his security devices.
- */
- showSecurityDevices: function ()
- {
- document.documentElement.openWindow("mozilla:devicemanager",
- "chrome://pippki/content/device_manager.xul",
- "", null);
- }
-#ifdef HAVE_SHELL_SERVICE
- ,
-
- // 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
- */
-
- /**
- * Show button for setting browser as default browser or information that
- * browser is already the default browser.
- */
- updateSetDefaultBrowser: function()
- {
- let shellSvc = getShellService();
- let setDefaultPane = document.getElementById("setDefaultPane");
- if (!shellSvc) {
- setDefaultPane.hidden = true;
- document.getElementById("alwaysCheckDefault").disabled = true;
- return;
- }
- let selectedIndex =
- shellSvc.isDefaultBrowser(false, true) ? 1 : 0;
- setDefaultPane.selectedIndex = selectedIndex;
- },
-
- /**
- * Set browser as the operating system default browser.
- */
- setDefaultBrowser: function()
- {
- let shellSvc = getShellService();
- if (!shellSvc)
- return;
- try {
- let claimAllTypes = true;
-#ifdef XP_WIN
- // In Windows 8+, the UI for selecting default protocol is much
- // nicer than the UI for setting file type associations. So we
- // only show the protocol association screen on Windows 8+.
- // Windows 8 is version 6.2.
- let version = Services.sysinfo.getProperty("version");
- claimAllTypes = (parseFloat(version) < 6.2);
-#endif
- shellSvc.setDefaultBrowser(claimAllTypes, false);
- } catch (ex) {
- Cu.reportError(ex);
- return;
- }
- let selectedIndex =
- shellSvc.isDefaultBrowser(false, true) ? 1 : 0;
- document.getElementById("setDefaultPane").selectedIndex = selectedIndex;
- }
-#endif
-};
diff --git a/components/preferences/advanced.xul b/components/preferences/advanced.xul
deleted file mode 100644
index e5f3bb1..0000000
--- a/components/preferences/advanced.xul
+++ /dev/null
@@ -1,465 +0,0 @@
-<?xml version="1.0"?>
-
-# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-<!DOCTYPE overlay [
-<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
-%brandDTD;
-<!ENTITY % advancedDTD SYSTEM "chrome://browser/locale/preferences/advanced.dtd">
-%advancedDTD;
-<!ENTITY % privacyDTD SYSTEM "chrome://browser/locale/preferences/privacy.dtd">
-%privacyDTD;
-]>
-
-<overlay id="AdvancedPaneOverlay"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-
- <prefpane id="paneAdvanced" onpaneload="gAdvancedPane.init();">
-
- <preferences id="advancedPreferences">
- <preference id="browser.preferences.advanced.selectedTabIndex"
- name="browser.preferences.advanced.selectedTabIndex"
- type="int"/>
-
- <!--XXX button prefs -->
-
- <!-- General tab -->
- <preference id="accessibility.typeaheadfind" name="accessibility.typeaheadfind" type="bool"/>
-
- <preference id="general.autoScroll" name="general.autoScroll" type="bool"/>
- <preference id="general.smoothScroll" name="general.smoothScroll" type="bool"/>
- <preference id="layers.acceleration.disabled" name="layers.acceleration.disabled" type="bool" inverted="true"
- onchange="gAdvancedPane.updateHardwareAcceleration()"/>
-#ifdef XP_WIN
- <preference id="gfx.direct2d.disabled" name="gfx.direct2d.disabled" type="bool" inverted="true"/>
-#endif
- <preference id="layout.spellcheckDefault" name="layout.spellcheckDefault" type="int"/>
-
-#ifdef HAVE_SHELL_SERVICE
- <preference id="browser.shell.checkDefaultBrowser"
- name="browser.shell.checkDefaultBrowser"
- type="bool"/>
-
- <preference id="pref.general.disable_button.default_browser"
- name="pref.general.disable_button.default_browser"
- type="bool"/>
-#endif
- <preference id="pref.general.compatmode" name="general.useragent.compatMode" type="int"/>
-
- <preference id="pref.general.captiveportal" name="network.captive-portal-service.enabled" type="bool"/>
-
- <!-- Network tab -->
- <preference id="browser.cache.disk.capacity" name="browser.cache.disk.capacity" type="int"/>
-
- <preference id="browser.cache.disk.smart_size.enabled"
- name="browser.cache.disk.smart_size.enabled"
- inverted="true"
- type="bool"/>
-
- <preference id="offline-apps.permissions" name="offline-apps.permissions" type="int"
- onchange="gAdvancedPane.updateOfflineAppsPermissions()"/>
- <preference id="browser.offline-apps.notify" name="browser.offline-apps.notify" type="bool"/>
- <preference id="offline-apps.allow_by_default" name="offline-apps.allow_by_default" type="bool"/>
-
- <!-- Update tab -->
-#ifdef MOZ_UPDATER
- <preference id="app.update.enabled" name="app.update.enabled" type="bool"/>
- <preference id="app.update.auto" name="app.update.auto" type="bool"/>
- <preference id="app.update.mode" name="app.update.mode" type="int"/>
-
- <preference id="app.update.disable_button.showUpdateHistory"
- name="app.update.disable_button.showUpdateHistory"
- type="bool"/>
-#endif
-
- <preference id="browser.search.update" name="browser.search.update" type="bool"/>
-
- <!-- Certificates tab -->
- <preference id="security.default_personal_cert" name="security.default_personal_cert" type="string"/>
-
- <preference id="security.disable_button.openCertManager"
- name="security.disable_button.openCertManager"
- type="bool"/>
- <preference id="security.disable_button.openDeviceManager"
- name="security.disable_button.openDeviceManager"
- type="bool"/>
- <preference id="security.OCSP.enabled"
- name="security.OCSP.enabled"
- type="int"/>
- <preference id="security.OCSP.require"
- name="security.OCSP.require"
- type="bool"/>
-
- <!-- Pale Moon: smooth scrolling tab -->
- <preference id="general.smoothScroll.lines" name="general.smoothScroll.lines" type="bool"/>
- <preference id="general.smoothScroll.lines.durationMinMS" name="general.smoothScroll.lines.durationMinMS" type="int"/>
- <preference id="general.smoothScroll.lines.durationMaxMS" name="general.smoothScroll.lines.durationMaxMS" type="int"/>
- <preference id="general.smoothScroll.pages" name="general.smoothScroll.pages" type="bool"/>
- <preference id="general.smoothScroll.pages.durationMinMS" name="general.smoothScroll.pages.durationMinMS" type="int"/>
- <preference id="general.smoothScroll.pages.durationMaxMS" name="general.smoothScroll.pages.durationMaxMS" type="int"/>
- <preference id="general.smoothScroll.mouseWheel" name="general.smoothScroll.mouseWheel" type="bool"/>
- <preference id="general.smoothScroll.mouseWheel.durationMinMS" name="general.smoothScroll.mouseWheel.durationMinMS" type="int"/>
- <preference id="general.smoothScroll.mouseWheel.durationMaxMS" name="general.smoothScroll.mouseWheel.durationMaxMS" type="int"/>
- <preference id="general.smoothScroll.scrollbars" name="general.smoothScroll.scrollbars" type="bool"/>
- <preference id="general.smoothScroll.scrollbars.durationMinMS" name="general.smoothScroll.scrollbars.durationMinMS" type="int"/>
- <preference id="general.smoothScroll.scrollbars.durationMaxMS" name="general.smoothScroll.scrollbars.durationMaxMS" type="int"/>
-
- <preference id="mousewheel.default.delta_multiplier_y" name="mousewheel.default.delta_multiplier_y" type="int"/>
- </preferences>
-
-#ifdef HAVE_SHELL_SERVICE
- <stringbundle id="bundleShell" src="chrome://browser/locale/shellservice.properties"/>
- <stringbundle id="bundleBrand" src="chrome://branding/locale/brand.properties"/>
-#endif
- <stringbundle id="bundlePreferences" src="chrome://browser/locale/preferences/preferences.properties"/>
-
- <script type="application/javascript" src="chrome://browser/content/preferences/advanced.js"/>
-
- <tabbox id="advancedPrefs" flex="1"
- onselect="gAdvancedPane.tabSelectionChanged();">
-
- <tabs id="tabsElement">
- <tab id="generalTab" label="&generalTab.label;" helpTopic="prefs-advanced-general"/>
- <tab id="networkTab" label="&networkTab.label;" helpTopic="prefs-advanced-network"/>
- <tab id="updateTab" label="&updateTab.label;" helpTopic="prefs-advanced-update"/>
- <tab id="encryptionTab" label="&certificateTab.label;" helpTopic="prefs-advanced-encryption"/>
- <tab id="scrollparamTab" label="&scrollparamTab.label;" helpTopic="prefs-advanced-scrollparams"/>
- </tabs>
-
- <tabpanels flex="1">
-
- <!-- General -->
- <tabpanel id="generalPanel" orient="vertical">
-
- <!-- Accessibility -->
- <groupbox id="accessibilityGroup" align="start">
- <caption label="&accessibility.label;"/>
-
- <checkbox id="searchStartTyping"
- label="&searchStartTyping.label;"
- accesskey="&searchStartTyping.accesskey;"
- preference="accessibility.typeaheadfind"/>
- </groupbox>
-
- <!-- Browsing -->
- <groupbox id="browsingGroup" align="start">
- <caption label="&browsing.label;"/>
-
- <checkbox id="useAutoScroll"
- label="&useAutoScroll.label;"
- accesskey="&useAutoScroll.accesskey;"
- preference="general.autoScroll"/>
- <checkbox id="allowHWAccel"
- label="&allowHWAccel.label;"
- accesskey="&allowHWAccel.accesskey;"
- preference="layers.acceleration.disabled"/>
- <checkbox id="checkSpelling"
- label="&checkSpelling.label;"
- accesskey="&checkSpelling.accesskey;"
- onsyncfrompreference="return gAdvancedPane.readCheckSpelling();"
- onsynctopreference="return gAdvancedPane.writeCheckSpelling();"
- preference="layout.spellcheckDefault"/>
- </groupbox>
-
-#ifdef HAVE_SHELL_SERVICE
- <!-- System Defaults -->
- <groupbox id="systemDefaultsGroup" orient="vertical">
- <caption label="&systemDefaults.label;"/>
-
- <checkbox id="alwaysCheckDefault" preference="browser.shell.checkDefaultBrowser"
- label="&alwaysCheckDefault.label;" accesskey="&alwaysCheckDefault.accesskey;"
- flex="1"/>
- <hbox class="indent">
- <deck id="setDefaultPane">
- <button id="setDefaultButton"
- label="&setDefault.label;" accesskey="&setDefault.accesskey;"
- oncommand="gAdvancedPane.setDefaultBrowser();"
- preference="pref.general.disable_button.default_browser"/>
- <description>&isDefault.label;</description>
- </deck>
- </hbox>
- </groupbox>
-#endif
- <!-- User Agent compatibility -->
- <groupbox id="UACompatGroup" orient="vertical">
- <caption label="&UACompatGroup.label;"/>
- <hbox align="center">
- <label id="UACompat" control="UACompat-menu">&UACompat.label;</label>
- <menulist id="UACompat-menu" preference="pref.general.compatmode" sizetopopup="always">
- <menupopup>
- <menuitem label="&UACompat.Native;" value="0" />
- <menuitem label="&UACompat.Gecko;" value="1" />
- <menuitem label="&UACompat.Firefox;" value="2" />
- </menupopup>
- </menulist>
- </hbox>
- </groupbox>
-
- <!-- Captive portal detection -->
- <groupbox id="captivePortalGroup" orient="vertical">
- <caption label="&captivePortalGroup.label;"/>
- <checkbox id="captivePortalDetect"
- label="&captivePortalDetect.label;"
- preference="pref.general.captiveportal"/>
- </groupbox>
-
- </tabpanel>
-
- <!-- Network -->
- <tabpanel id="networkPanel" orient="vertical">
-
- <!-- Connection -->
- <groupbox id="connectionGroup">
- <caption label="&connection.label;"/>
-
- <hbox align="center">
- <description flex="1" control="connectionSettings">&connectionDesc.label;</description>
- <button id="connectionSettings" icon="network" label="&connectionSettings.label;"
- accesskey="&connectionSettings.accesskey;"
- oncommand="gAdvancedPane.showConnections();"/>
- </hbox>
- </groupbox>
-
- <!-- Cache -->
- <groupbox id="cacheGroup">
- <caption label="&httpCache.label;"/>
-
- <hbox align="center">
- <label id="actualDiskCacheSize" flex="1"/>
- <button id="clearCacheButton" icon="clear"
- label="&clearCacheNow.label;" accesskey="&clearCacheNow.accesskey;"
- oncommand="gAdvancedPane.clearCache();"/>
- </hbox>
- <checkbox preference="browser.cache.disk.smart_size.enabled"
- id="allowSmartSize" flex="1"
- onsyncfrompreference="return gAdvancedPane.readSmartSizeEnabled();"
- label="&overrideSmartCacheSize.label;"
- accesskey="&overrideSmartCacheSize.accesskey;"/>
- <hbox align="center" class="indent">
- <label id="useCacheBefore" control="cacheSize"
- accesskey="&limitCacheSizeBefore.accesskey;"
- value="&limitCacheSizeBefore.label;"/>
- <textbox id="cacheSize" type="number" size="4" max="1024"
- preference="browser.cache.disk.capacity"
- onsyncfrompreference="return gAdvancedPane.readCacheSize();"
- onsynctopreference="return gAdvancedPane.writeCacheSize();"
- aria-labelledby="useCacheBefore cacheSize useCacheAfter"/>
- <label id="useCacheAfter" flex="1">&limitCacheSizeAfter.label;</label>
- </hbox>
- </groupbox>
-
- <!-- Offline apps -->
- <groupbox id="offlineGroup">
- <caption label="&offlineStorage2.label;"/>
-
- <hbox align="center">
- <label id="actualAppCacheSize" flex="1"/>
- <button id="clearOfflineAppCacheButton" icon="clear"
- label="&clearOfflineAppCacheNow.label;" accesskey="&clearOfflineAppCacheNow.accesskey;"
- oncommand="gAdvancedPane.clearOfflineAppCache();"/>
- </hbox>
- <label id="offlineAppsPermsLabel">&offlineAppsPermissions.label;</label>
- <hbox align="center">
- <menulist id="offlineAppsPerms-menu" preference="offline-apps.permissions" sizetopopup="always">
- <menupopup>
- <menuitem label="&offlineAppsPermissions.Allow;" value="2" />
- <menuitem label="&offlineAppsPermissions.Ask;" value="1" />
- <menuitem label="&offlineAppsPermissions.Deny;" value="0" />
- </menupopup>
- </menulist>
- <spacer flex="1"/>
- <button id="offlineNotifyExceptions"
- label="&offlineNotifyExceptions.label;"
- accesskey="&offlineNotifyExceptions.accesskey;"
- oncommand="gAdvancedPane.showOfflineExceptions();"/>
- </hbox>
- <hbox>
- <vbox flex="1">
- <label id="offlineAppsListLabel">&offlineAppsList2.label;</label>
- <listbox id="offlineAppsList"
- style="height: &offlineAppsList.height;;"
- flex="1"
- aria-labelledby="offlineAppsListLabel"
- onselect="gAdvancedPane.offlineAppSelected(event);">
- </listbox>
- </vbox>
- <vbox pack="end">
- <button id="offlineAppsListRemove"
- disabled="true"
- label="&offlineAppsListRemove.label;"
- accesskey="&offlineAppsListRemove.accesskey;"
- oncommand="gAdvancedPane.removeOfflineApp();"/>
- </vbox>
- </hbox>
- </groupbox>
- </tabpanel>
-
- <!-- Update -->
- <tabpanel id="updatePanel" orient="vertical">
-#ifdef MOZ_UPDATER
- <groupbox id="updateApp">
- <caption label="&updateApp.label;"/>
- <radiogroup id="updateRadioGroup"
- oncommand="gAdvancedPane.updateWritePrefs();">
- <radio id="autoDesktop"
- value="auto"
- label="&updateAuto1.label;"
- accesskey="&updateAuto1.accesskey;"/>
- <hbox class="indent">
- <checkbox id="warnIncompatible"
- label="&updateAutoAddonWarn.label;"
- accesskey="&updateAutoAddonWarn.accesskey;"
- preference="app.update.mode"
- onsyncfrompreference="return gAdvancedPane.readAddonWarn();"
- onsynctopreference="return gAdvancedPane.writeAddonWarn();"/>
- </hbox>
- <radio value="checkOnly"
- label="&updateCheck.label;"
- accesskey="&updateCheck.accesskey;"/>
- <radio value="manual"
- label="&updateManual.label;"
- accesskey="&updateManual.accesskey;"/>
- </radiogroup>
-
- <hbox>
- <button id="showUpdateHistory"
- label="&updateHistory.label;"
- accesskey="&updateHistory.accesskey;"
- preference="app.update.disable_button.showUpdateHistory"
- oncommand="gAdvancedPane.showUpdates();"/>
- </hbox>
- </groupbox>
-#endif
- <groupbox id="updateOthers">
- <caption label="&updateOthers.label;"/>
- <checkbox id="enableSearchUpdate"
- label="&enableSearchUpdate.label;"
- accesskey="&enableSearchUpdate.accesskey;"
- preference="browser.search.update"/>
- </groupbox>
- </tabpanel>
-
- <!-- Certificates -->
- <tabpanel id="encryptionPanel" orient="vertical">
-
- <!--
- The values on these radio buttons may look like l12y issues, but
- they're not - this preference uses *those strings* as its values.
- I KID YOU NOT.
- -->
-
- <groupbox>
- <caption label="&certGroup.label;"/>
- <description id="CertSelectionDesc" control="certSelection">&certSelection.description;</description>
- <radiogroup id="certSelection" orient="horizontal" preftype="string"
- preference="security.default_personal_cert"
- aria-labelledby="CertSelectionDesc">
- <radio label="&certs.auto;" accesskey="&certs.auto.accesskey;"
- value="Select Automatically"/>
- <radio label="&certs.ask;" accesskey="&certs.ask.accesskey;"
- value="Ask Every Time"/>
- </radiogroup>
- </groupbox>
- <groupbox>
- <caption label="&ocspGroup.label;"/>
- <checkbox id="enableOCSP"
- label="&enableOCSP.label;"
- accesskey="&enableOCSP.accesskey;"
- onsyncfrompreference="return gAdvancedPane.readEnableOCSP();"
- onsynctopreference="return gAdvancedPane.writeEnableOCSP();"
- preference="security.OCSP.enabled"/>
- <checkbox id="requireOCSP"
- label="&requireOCSP.label;"
- accesskey="&requireOCSP.accesskey;"
- preference="security.OCSP.require"/>
- </groupbox>
-
- <separator/>
-
- <hbox>
- <button id="viewCertificatesButton"
- label="&viewCerts.label;" accesskey="&viewCerts.accesskey;"
- oncommand="gAdvancedPane.showCertificates();"
- preference="security.disable_button.openCertManager"/>
- <button id="viewSecurityDevicesButton"
- label="&viewSecurityDevices.label;" accesskey="&viewSecurityDevices.accesskey;"
- oncommand="gAdvancedPane.showSecurityDevices();"
- preference="security.disable_button.openDeviceManager"/>
- </hbox>
- </tabpanel>
-
- <!-- Pale Moon: Scrolling tab -->
- <tabpanel id="scrollparamTab" orient="vertical">
-
- <checkbox id="useSmoothScrolling"
- label="&useSmoothScrolling.label;"
- accesskey="&useSmoothScrolling.accesskey;"
- preference="general.smoothScroll"/>
-
- <label>&smoothscroll.explain.label;</label>
-
- <groupbox>
- <caption label="&smoothscroll.params.label;"/>
-
- <checkbox label="&smoothscroll.mousewheel.label;" preference="general.smoothScroll.mouseWheel"/>
- <hbox align="center" class="indent">
- <label value="&smoothscroll.mousewheel.duration;"/>
- <textbox type="number" size="3" max="500"
- preference="general.smoothScroll.mouseWheel.durationMinMS"/>
- <label>&smoothscroll.to;</label>
- <textbox type="number" size="4" max="2000"
- preference="general.smoothScroll.mouseWheel.durationMaxMS"/>
- <label flex="1">ms.</label>
- </hbox>
-
- <checkbox label="&smoothscroll.arrowkeys.label;" preference="general.smoothScroll.lines"/>
- <hbox align="center" class="indent">
- <label value="&smoothscroll.arrowkeys.duration;"/>
- <textbox type="number" size="3" max="500"
- preference="general.smoothScroll.lines.durationMinMS"/>
- <label>&smoothscroll.to;</label>
- <textbox type="number" size="4" max="2000"
- preference="general.smoothScroll.lines.durationMaxMS"/>
- <label flex="1">ms.</label>
- </hbox>
-
- <checkbox label="&smoothscroll.pagekeys.label;" preference="general.smoothScroll.pages"/>
- <hbox align="center" class="indent">
- <label value="&smoothscroll.pagekeys.duration;"/>
- <textbox type="number" size="3" max="500"
- preference="general.smoothScroll.pages.durationMinMS"/>
- <label>&smoothscroll.to;</label>
- <textbox type="number" size="4" max="2000"
- preference="general.smoothScroll.pages.durationMaxMS"/>
- <label flex="1">ms.</label>
- </hbox>
-
- <checkbox label="&smoothscroll.scrollbar.label;" preference="general.smoothScroll.scrollbars"/>
- <hbox align="center" class="indent">
- <label value="&smoothscroll.scrollbar.duration;"/>
- <textbox type="number" size="3" max="500"
- preference="general.smoothScroll.scrollbars.durationMinMS"/>
- <label>&smoothscroll.to;</label>
- <textbox type="number" size="4" max="2000"
- preference="general.smoothScroll.scrollbars.durationMaxMS"/>
- <label flex="1">ms.</label>
- </hbox>
-
- <hbox align="center">
- <label value="&smoothscroll.overall.yspeed.label;"/>
- <textbox type="number" size="3" min="1" max="999"
- preference="mousewheel.default.delta_multiplier_y"/>
- <label flex="1">%.</label>
- </hbox>
- </groupbox>
- </tabpanel>
- <!-- end Smooth scrolling tab -->
-
- </tabpanels>
- </tabbox>
- </prefpane>
-
-</overlay>
diff --git a/components/preferences/applicationManager.js b/components/preferences/applicationManager.js
deleted file mode 100644
index 5213183..0000000
--- a/components/preferences/applicationManager.js
+++ /dev/null
@@ -1,102 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifdef XP_MACOSX
-var Cc = Components.classes;
-var Ci = Components.interfaces;
-#endif
-
-var gAppManagerDialog = {
- _removed: [],
-
- init: function appManager_init() {
- this.handlerInfo = window.arguments[0];
-
- var bundle = document.getElementById("appManagerBundle");
- var contentText;
- if (this.handlerInfo.type == TYPE_MAYBE_FEED)
- contentText = bundle.getString("handleWebFeeds");
- else {
- var description = gApplicationsPane._describeType(this.handlerInfo);
- var key =
- (this.handlerInfo.wrappedHandlerInfo instanceof Ci.nsIMIMEInfo) ? "handleFile"
- : "handleProtocol";
- contentText = bundle.getFormattedString(key, [description]);
- }
- contentText = bundle.getFormattedString("descriptionApplications", [contentText]);
- document.getElementById("appDescription").textContent = contentText;
-
- var list = document.getElementById("appList");
- var apps = this.handlerInfo.possibleApplicationHandlers.enumerate();
- while (apps.hasMoreElements()) {
- let app = apps.getNext();
- if (!gApplicationsPane.isValidHandlerApp(app))
- continue;
-
- app.QueryInterface(Ci.nsIHandlerApp);
- var item = list.appendItem(app.name);
- item.setAttribute("image", gApplicationsPane._getIconURLForHandlerApp(app));
- item.className = "listitem-iconic";
- item.app = app;
- }
-
- list.selectedIndex = 0;
- },
-
- onOK: function appManager_onOK() {
- if (!this._removed.length) {
- // return early to avoid calling the |store| method.
- return;
- }
-
- for (var i = 0; i < this._removed.length; ++i)
- this.handlerInfo.removePossibleApplicationHandler(this._removed[i]);
-
- this.handlerInfo.store();
- },
-
- onCancel: function appManager_onCancel() {
- // do nothing
- },
-
- remove: function appManager_remove() {
- var list = document.getElementById("appList");
- this._removed.push(list.selectedItem.app);
- var index = list.selectedIndex;
- list.removeItemAt(index);
- if (list.getRowCount() == 0) {
- // The list is now empty, make the bottom part disappear
- document.getElementById("appDetails").hidden = true;
- }
- else {
- // Select the item at the same index, if we removed the last
- // item of the list, select the previous item
- if (index == list.getRowCount())
- --index;
- list.selectedIndex = index;
- }
- },
-
- onSelect: function appManager_onSelect() {
- var list = document.getElementById("appList");
- if (!list.selectedItem) {
- document.getElementById("remove").disabled = true;
- return;
- }
- document.getElementById("remove").disabled = false;
- var app = list.selectedItem.app;
- var address = "";
- if (app instanceof Ci.nsILocalHandlerApp)
- address = app.executable.path;
- else if (app instanceof Ci.nsIWebHandlerApp)
- address = app.uriTemplate;
- else if (app instanceof Ci.nsIWebContentHandlerInfo)
- address = app.uri;
- document.getElementById("appLocation").value = address;
- var bundle = document.getElementById("appManagerBundle");
- var appType = app instanceof Ci.nsILocalHandlerApp ? "descriptionLocalApp"
- : "descriptionWebApp";
- document.getElementById("appType").value = bundle.getString(appType);
- }
-};
diff --git a/components/preferences/applicationManager.xul b/components/preferences/applicationManager.xul
deleted file mode 100644
index b5605c2..0000000
--- a/components/preferences/applicationManager.xul
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<?xml-stylesheet href="chrome://global/skin/"?>
-
-<!DOCTYPE dialog SYSTEM "chrome://browser/locale/preferences/applicationManager.dtd">
-
-<dialog id="appManager"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- buttons="accept,cancel"
- onload="gAppManagerDialog.init();"
- ondialogaccept="gAppManagerDialog.onOK();"
- ondialogcancel="gAppManagerDialog.onCancel();"
- title="&appManager.title;"
- style="&appManager.style;"
- persist="screenX screenY">
-
- <script type="application/javascript"
- src="chrome://browser/content/utilityOverlay.js"/>
- <script type="application/javascript"
- src="chrome://browser/content/preferences/applicationManager.js"/>
- <script type="application/javascript"
- src="chrome://browser/content/preferences/applications.js"/>
-
- <commandset id="appManagerCommandSet">
- <command id="cmd_remove"
- oncommand="gAppManagerDialog.remove();"
- disabled="true"/>
- </commandset>
-
- <keyset id="appManagerKeyset">
- <key id="delete" keycode="VK_DELETE" command="cmd_remove"/>
- </keyset>
-
- <stringbundleset id="appManagerBundleset">
- <stringbundle id="appManagerBundle"
- src="chrome://browser/locale/preferences/applicationManager.properties"/>
- </stringbundleset>
-
- <description id="appDescription"/>
- <separator class="thin"/>
- <hbox flex="1">
- <listbox id="appList" onselect="gAppManagerDialog.onSelect();" flex="1"/>
- <vbox>
- <button id="remove"
- label="&remove.label;"
- accesskey="&remove.accesskey;"
- command="cmd_remove"/>
- <spacer flex="1"/>
- </vbox>
- </hbox>
- <vbox id="appDetails">
- <separator class="thin"/>
- <label id="appType"/>
- <textbox id="appLocation" readonly="true" class="plain"/>
- </vbox>
-</dialog>
diff --git a/components/preferences/applications.js b/components/preferences/applications.js
deleted file mode 100644
index d06f9f9..0000000
--- a/components/preferences/applications.js
+++ /dev/null
@@ -1,1890 +0,0 @@
-/*
-# -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
-
-//****************************************************************************//
-// Constants & Enumeration Values
-
-var Cc = Components.classes;
-var Ci = Components.interfaces;
-var Cr = Components.results;
-
-Components.utils.import('resource://gre/modules/Services.jsm');
-
-const TYPE_MAYBE_FEED = "application/vnd.mozilla.maybe.feed";
-const TYPE_MAYBE_VIDEO_FEED = "application/vnd.mozilla.maybe.video.feed";
-const TYPE_MAYBE_AUDIO_FEED = "application/vnd.mozilla.maybe.audio.feed";
-
-const PREF_DISABLED_PLUGIN_TYPES = "plugin.disable_full_page_plugin_for_types";
-
-// Preferences that affect which entries to show in the list.
-const PREF_SHOW_PLUGINS_IN_LIST = "browser.download.show_plugins_in_list";
-const PREF_HIDE_PLUGINS_WITHOUT_EXTENSIONS =
- "browser.download.hide_plugins_without_extensions";
-
-/*
- * Preferences where we store handling information about the feed type.
- *
- * browser.feeds.handler
- * - "bookmarks", "reader" (clarified further using the .default preference),
- * or "ask" -- indicates the default handler being used to process feeds;
- * "bookmarks" is obsolete; to specify that the handler is bookmarks,
- * set browser.feeds.handler.default to "bookmarks";
- *
- * browser.feeds.handler.default
- * - "bookmarks", "client" or "web" -- indicates the chosen feed reader used
- * to display feeds, either transiently (i.e., when the "use as default"
- * checkbox is unchecked, corresponds to when browser.feeds.handler=="ask")
- * or more permanently (i.e., the item displayed in the dropdown in Feeds
- * preferences)
- *
- * browser.feeds.handler.webservice
- * - the URL of the currently selected web service used to read feeds
- *
- * browser.feeds.handlers.application
- * - nsILocalFile, stores the current client-side feed reading app if one has
- * been chosen
- */
-const PREF_FEED_SELECTED_APP = "browser.feeds.handlers.application";
-const PREF_FEED_SELECTED_WEB = "browser.feeds.handlers.webservice";
-const PREF_FEED_SELECTED_ACTION = "browser.feeds.handler";
-const PREF_FEED_SELECTED_READER = "browser.feeds.handler.default";
-
-const PREF_VIDEO_FEED_SELECTED_APP = "browser.videoFeeds.handlers.application";
-const PREF_VIDEO_FEED_SELECTED_WEB = "browser.videoFeeds.handlers.webservice";
-const PREF_VIDEO_FEED_SELECTED_ACTION = "browser.videoFeeds.handler";
-const PREF_VIDEO_FEED_SELECTED_READER = "browser.videoFeeds.handler.default";
-
-const PREF_AUDIO_FEED_SELECTED_APP = "browser.audioFeeds.handlers.application";
-const PREF_AUDIO_FEED_SELECTED_WEB = "browser.audioFeeds.handlers.webservice";
-const PREF_AUDIO_FEED_SELECTED_ACTION = "browser.audioFeeds.handler";
-const PREF_AUDIO_FEED_SELECTED_READER = "browser.audioFeeds.handler.default";
-
-// The nsHandlerInfoAction enumeration values in nsIHandlerInfo identify
-// the actions the application can take with content of various types.
-// But since nsIHandlerInfo doesn't support plugins, there's no value
-// identifying the "use plugin" action, so we use this constant instead.
-const kActionUsePlugin = 5;
-
-/*
-#ifdef MOZ_WIDGET_GTK
-*/
-const ICON_URL_APP = "moz-icon://dummy.exe?size=16";
-/*
-#else
-*/
-const ICON_URL_APP = "chrome://browser/skin/preferences/application.png";
-/*
-#endif
-*/
-
-// For CSS. Can be one of "ask", "save", "plugin" or "feed". If absent, the icon URL
-// was set by us to a custom handler icon and CSS should not try to override it.
-const APP_ICON_ATTR_NAME = "appHandlerIcon";
-
-//****************************************************************************//
-// Utilities
-
-function getFileDisplayName(file) {
-#ifdef XP_WIN
- if (file instanceof Ci.nsILocalFileWin) {
- try {
- return file.getVersionInfoField("FileDescription");
- } catch (e) {}
- }
-#endif
-#ifdef XP_MACOSX
- if (file instanceof Ci.nsILocalFileMac) {
- try {
- return file.bundleDisplayName;
- } catch (e) {}
- }
-#endif
- return file.leafName;
-}
-
-function getLocalHandlerApp(aFile) {
- var localHandlerApp = Cc["@mozilla.org/uriloader/local-handler-app;1"].
- createInstance(Ci.nsILocalHandlerApp);
- localHandlerApp.name = getFileDisplayName(aFile);
- localHandlerApp.executable = aFile;
-
- return localHandlerApp;
-}
-
-/**
- * An enumeration of items in a JS array.
- *
- * FIXME: use ArrayConverter once it lands (bug 380839).
- *
- * @constructor
- */
-function ArrayEnumerator(aItems) {
- this._index = 0;
- this._contents = aItems;
-}
-
-ArrayEnumerator.prototype = {
- _index: 0,
-
- hasMoreElements: function() {
- return this._index < this._contents.length;
- },
-
- getNext: function() {
- return this._contents[this._index++];
- }
-};
-
-function isFeedType(t) {
- return t == TYPE_MAYBE_FEED || t == TYPE_MAYBE_VIDEO_FEED || t == TYPE_MAYBE_AUDIO_FEED;
-}
-
-//****************************************************************************//
-// HandlerInfoWrapper
-
-/**
- * This object wraps nsIHandlerInfo with some additional functionality
- * the Applications prefpane needs to display and allow modification of
- * the list of handled types.
- *
- * We create an instance of this wrapper for each entry we might display
- * in the prefpane, and we compose the instances from various sources,
- * including plugins and the handler service.
- *
- * We don't implement all the original nsIHandlerInfo functionality,
- * just the stuff that the prefpane needs.
- *
- * In theory, all of the custom functionality in this wrapper should get
- * pushed down into nsIHandlerInfo eventually.
- */
-function HandlerInfoWrapper(aType, aHandlerInfo) {
- this._type = aType;
- this.wrappedHandlerInfo = aHandlerInfo;
-}
-
-HandlerInfoWrapper.prototype = {
- // The wrapped nsIHandlerInfo object. In general, this object is private,
- // but there are a couple cases where callers access it directly for things
- // we haven't (yet?) implemented, so we make it a public property.
- wrappedHandlerInfo: null,
-
-
- //**************************************************************************//
- // Convenience Utils
-
- _handlerSvc: Cc["@mozilla.org/uriloader/handler-service;1"].
- getService(Ci.nsIHandlerService),
-
- _prefSvc: Cc["@mozilla.org/preferences-service;1"].
- getService(Ci.nsIPrefBranch),
-
- _categoryMgr: Cc["@mozilla.org/categorymanager;1"].
- getService(Ci.nsICategoryManager),
-
- element: function(aID) {
- return document.getElementById(aID);
- },
-
-
- //**************************************************************************//
- // nsIHandlerInfo
-
- // The MIME type or protocol scheme.
- _type: null,
- get type() {
- return this._type;
- },
-
- get description() {
- if (this.wrappedHandlerInfo.description)
- return this.wrappedHandlerInfo.description;
-
- if (this.primaryExtension) {
- var extension = this.primaryExtension.toUpperCase();
- return this.element("bundlePreferences").getFormattedString("fileEnding",
- [extension]);
- }
-
- return this.type;
- },
-
- get preferredApplicationHandler() {
- return this.wrappedHandlerInfo.preferredApplicationHandler;
- },
-
- set preferredApplicationHandler(aNewValue) {
- this.wrappedHandlerInfo.preferredApplicationHandler = aNewValue;
-
- // Make sure the preferred handler is in the set of possible handlers.
- if (aNewValue)
- this.addPossibleApplicationHandler(aNewValue)
- },
-
- get possibleApplicationHandlers() {
- return this.wrappedHandlerInfo.possibleApplicationHandlers;
- },
-
- addPossibleApplicationHandler: function(aNewHandler) {
- var possibleApps = this.possibleApplicationHandlers.enumerate();
- while (possibleApps.hasMoreElements()) {
- if (possibleApps.getNext().equals(aNewHandler))
- return;
- }
- this.possibleApplicationHandlers.appendElement(aNewHandler, false);
- },
-
- removePossibleApplicationHandler: function(aHandler) {
- var defaultApp = this.preferredApplicationHandler;
- if (defaultApp && aHandler.equals(defaultApp)) {
- // If the app we remove was the default app, we must make sure
- // it won't be used anymore
- this.alwaysAskBeforeHandling = true;
- this.preferredApplicationHandler = null;
- }
-
- var handlers = this.possibleApplicationHandlers;
- for (var i = 0; i < handlers.length; ++i) {
- var handler = handlers.queryElementAt(i, Ci.nsIHandlerApp);
- if (handler.equals(aHandler)) {
- handlers.removeElementAt(i);
- break;
- }
- }
- },
-
- get hasDefaultHandler() {
- return this.wrappedHandlerInfo.hasDefaultHandler;
- },
-
- get defaultDescription() {
- return this.wrappedHandlerInfo.defaultDescription;
- },
-
- // What to do with content of this type.
- get preferredAction() {
- // If we have an enabled plugin, then the action is to use that plugin.
- if (this.pluginName && !this.isDisabledPluginType)
- return kActionUsePlugin;
-
- // If the action is to use a helper app, but we don't have a preferred
- // handler app, then switch to using the system default, if any; otherwise
- // fall back to saving to disk, which is the default action in nsMIMEInfo.
- // Note: "save to disk" is an invalid value for protocol info objects,
- // but the alwaysAskBeforeHandling getter will detect that situation
- // and always return true in that case to override this invalid value.
- if (this.wrappedHandlerInfo.preferredAction == Ci.nsIHandlerInfo.useHelperApp &&
- !gApplicationsPane.isValidHandlerApp(this.preferredApplicationHandler)) {
- if (this.wrappedHandlerInfo.hasDefaultHandler)
- return Ci.nsIHandlerInfo.useSystemDefault;
- else
- return Ci.nsIHandlerInfo.saveToDisk;
- }
-
- return this.wrappedHandlerInfo.preferredAction;
- },
-
- set preferredAction(aNewValue) {
- // If the action is to use the plugin,
- // we must set the preferred action to "save to disk".
- // But only if it's not currently the preferred action.
- if ((aNewValue == kActionUsePlugin) &&
- (this.preferredAction != Ci.nsIHandlerInfo.saveToDisk)) {
- aNewValue = Ci.nsIHandlerInfo.saveToDisk;
- }
-
- // We don't modify the preferred action if the new action is to use a plugin
- // because handler info objects don't understand our custom "use plugin"
- // value. Also, leaving it untouched means that we can automatically revert
- // to the old setting if the user ever removes the plugin.
-
- if (aNewValue != kActionUsePlugin)
- this.wrappedHandlerInfo.preferredAction = aNewValue;
- },
-
- get alwaysAskBeforeHandling() {
- // If this type is handled only by a plugin, we can't trust the value
- // in the handler info object, since it'll be a default based on the absence
- // of any user configuration, and the default in that case is to always ask,
- // even though we never ask for content handled by a plugin, so special case
- // plugin-handled types by returning false here.
- if (this.pluginName && this.handledOnlyByPlugin)
- return false;
-
- // If this is a protocol type and the preferred action is "save to disk",
- // which is invalid for such types, then return true here to override that
- // action. This could happen when the preferred action is to use a helper
- // app, but the preferredApplicationHandler is invalid, and there isn't
- // a default handler, so the preferredAction getter returns save to disk
- // instead.
- if (!(this.wrappedHandlerInfo instanceof Ci.nsIMIMEInfo) &&
- this.preferredAction == Ci.nsIHandlerInfo.saveToDisk)
- return true;
-
- return this.wrappedHandlerInfo.alwaysAskBeforeHandling;
- },
-
- set alwaysAskBeforeHandling(aNewValue) {
- this.wrappedHandlerInfo.alwaysAskBeforeHandling = aNewValue;
- },
-
-
- //**************************************************************************//
- // nsIMIMEInfo
-
- // The primary file extension associated with this type, if any.
- //
- // XXX Plugin objects contain an array of MimeType objects with "suffixes"
- // properties; if this object has an associated plugin, shouldn't we check
- // those properties for an extension?
- get primaryExtension() {
- try {
- if (this.wrappedHandlerInfo instanceof Ci.nsIMIMEInfo &&
- this.wrappedHandlerInfo.primaryExtension)
- return this.wrappedHandlerInfo.primaryExtension
- } catch(ex) {}
-
- return null;
- },
-
-
- //**************************************************************************//
- // Plugin Handling
-
- // A plugin that can handle this type, if any.
- //
- // Note: just because we have one doesn't mean it *will* handle the type.
- // That depends on whether or not the type is in the list of types for which
- // plugin handling is disabled.
- plugin: null,
-
- // Whether or not this type is only handled by a plugin or is also handled
- // by some user-configured action as specified in the handler info object.
- //
- // Note: we can't just check if there's a handler info object for this type,
- // because OS and user configuration is mixed up in the handler info object,
- // so we always need to retrieve it for the OS info and can't tell whether
- // it represents only OS-default information or user-configured information.
- //
- // FIXME: once handler info records are broken up into OS-provided records
- // and user-configured records, stop using this boolean flag and simply
- // check for the presence of a user-configured record to determine whether
- // or not this type is only handled by a plugin. Filed as bug 395142.
- handledOnlyByPlugin: undefined,
-
- get isDisabledPluginType() {
- return this._getDisabledPluginTypes().indexOf(this.type) != -1;
- },
-
- _getDisabledPluginTypes: function() {
- var types = "";
-
- if (this._prefSvc.prefHasUserValue(PREF_DISABLED_PLUGIN_TYPES))
- types = this._prefSvc.getCharPref(PREF_DISABLED_PLUGIN_TYPES);
-
- // Only split if the string isn't empty so we don't end up with an array
- // containing a single empty string.
- if (types != "")
- return types.split(",");
-
- return [];
- },
-
- disablePluginType: function() {
- var disabledPluginTypes = this._getDisabledPluginTypes();
-
- if (disabledPluginTypes.indexOf(this.type) == -1)
- disabledPluginTypes.push(this.type);
-
- this._prefSvc.setCharPref(PREF_DISABLED_PLUGIN_TYPES,
- disabledPluginTypes.join(","));
-
- // Update the category manager so existing browser windows update.
- this._categoryMgr.deleteCategoryEntry("Goanna-Content-Viewers",
- this.type,
- false);
- },
-
- enablePluginType: function() {
- var disabledPluginTypes = this._getDisabledPluginTypes();
-
- var type = this.type;
- disabledPluginTypes = disabledPluginTypes.filter(function(v) v != type);
-
- this._prefSvc.setCharPref(PREF_DISABLED_PLUGIN_TYPES,
- disabledPluginTypes.join(","));
-
- // Update the category manager so existing browser windows update.
- this._categoryMgr.
- addCategoryEntry("Goanna-Content-Viewers",
- this.type,
- "@mozilla.org/content/plugin/document-loader-factory;1",
- false,
- true);
- },
-
-
- //**************************************************************************//
- // Storage
-
- store: function() {
- this._handlerSvc.store(this.wrappedHandlerInfo);
- },
-
-
- //**************************************************************************//
- // Icons
-
- get smallIcon() {
- return this._getIcon(16);
- },
-
- _getIcon: function(aSize) {
- if (this.primaryExtension)
- return "moz-icon://goat." + this.primaryExtension + "?size=" + aSize;
-
- if (this.wrappedHandlerInfo instanceof Ci.nsIMIMEInfo)
- return "moz-icon://goat?size=" + aSize + "&contentType=" + this.type;
-
- // FIXME: consider returning some generic icon when we can't get a URL for
- // one (for example in the case of protocol schemes). Filed as bug 395141.
- return null;
- }
-
-};
-
-
-//****************************************************************************//
-// Feed Handler Info
-
-/**
- * This object implements nsIHandlerInfo for the feed types. It's a separate
- * object because we currently store handling information for the feed type
- * in a set of preferences rather than the nsIHandlerService-managed datastore.
- *
- * This object inherits from HandlerInfoWrapper in order to get functionality
- * that isn't special to the feed type.
- *
- * XXX Should we inherit from HandlerInfoWrapper? After all, we override
- * most of that wrapper's properties and methods, and we have to dance around
- * the fact that the wrapper expects to have a wrappedHandlerInfo, which we
- * don't provide.
- */
-
-function FeedHandlerInfo(aMIMEType) {
- HandlerInfoWrapper.call(this, aMIMEType, null);
-}
-
-FeedHandlerInfo.prototype = {
- __proto__: HandlerInfoWrapper.prototype,
-
- //**************************************************************************//
- // Convenience Utils
-
- _converterSvc:
- Cc["@mozilla.org/embeddor.implemented/web-content-handler-registrar;1"].
- getService(Ci.nsIWebContentConverterService),
-
- _shellSvc:
-#ifdef HAVE_SHELL_SERVICE
- getShellService(),
-#else
- null,
-#endif
-
-
- //**************************************************************************//
- // nsIHandlerInfo
-
- get description() {
- return this.element("bundlePreferences").getString(this._appPrefLabel);
- },
-
- get preferredApplicationHandler() {
- switch (this.element(this._prefSelectedReader).value) {
- case "client":
- var file = this.element(this._prefSelectedApp).value;
- if (file)
- return getLocalHandlerApp(file);
-
- return null;
-
- case "web":
- var uri = this.element(this._prefSelectedWeb).value;
- if (!uri)
- return null;
- return this._converterSvc.getWebContentHandlerByURI(this.type, uri);
-
- case "bookmarks":
- default:
- // When the pref is set to bookmarks, we handle feeds internally,
- // we don't forward them to a local or web handler app, so there is
- // no preferred handler.
- return null;
- }
- },
-
- set preferredApplicationHandler(aNewValue) {
- if (aNewValue instanceof Ci.nsILocalHandlerApp) {
- this.element(this._prefSelectedApp).value = aNewValue.executable;
- this.element(this._prefSelectedReader).value = "client";
- }
- else if (aNewValue instanceof Ci.nsIWebContentHandlerInfo) {
- this.element(this._prefSelectedWeb).value = aNewValue.uri;
- this.element(this._prefSelectedReader).value = "web";
- // Make the web handler be the new "auto handler" for feeds.
- // Note: we don't have to unregister the auto handler when the user picks
- // a non-web handler (local app, Live Bookmarks, etc.) because the service
- // only uses the "auto handler" when the selected reader is a web handler.
- // We also don't have to unregister it when the user turns on "always ask"
- // (i.e. preview in browser), since that also overrides the auto handler.
- this._converterSvc.setAutoHandler(this.type, aNewValue);
- }
- },
-
- _possibleApplicationHandlers: null,
-
- get possibleApplicationHandlers() {
- if (this._possibleApplicationHandlers)
- return this._possibleApplicationHandlers;
-
- // A minimal implementation of nsIMutableArray. It only supports the two
- // methods its callers invoke, namely appendElement and nsIArray::enumerate.
- this._possibleApplicationHandlers = {
- _inner: [],
- _removed: [],
-
- QueryInterface: function(aIID) {
- if (aIID.equals(Ci.nsIMutableArray) ||
- aIID.equals(Ci.nsIArray) ||
- aIID.equals(Ci.nsISupports))
- return this;
-
- throw Cr.NS_ERROR_NO_INTERFACE;
- },
-
- get length() {
- return this._inner.length;
- },
-
- enumerate: function() {
- return new ArrayEnumerator(this._inner);
- },
-
- appendElement: function(aHandlerApp, aWeak) {
- this._inner.push(aHandlerApp);
- },
-
- removeElementAt: function(aIndex) {
- this._removed.push(this._inner[aIndex]);
- this._inner.splice(aIndex, 1);
- },
-
- queryElementAt: function(aIndex, aInterface) {
- return this._inner[aIndex].QueryInterface(aInterface);
- }
- };
-
- // Add the selected local app if it's different from the OS default handler.
- // Unlike for other types, we can store only one local app at a time for the
- // feed type, since we store it in a preference that historically stores
- // only a single path. But we display all the local apps the user chooses
- // while the prefpane is open, only dropping the list when the user closes
- // the prefpane, for maximum usability and consistency with other types.
- var preferredAppFile = this.element(this._prefSelectedApp).value;
- if (preferredAppFile) {
- let preferredApp = getLocalHandlerApp(preferredAppFile);
- let defaultApp = this._defaultApplicationHandler;
- if (!defaultApp || !defaultApp.equals(preferredApp))
- this._possibleApplicationHandlers.appendElement(preferredApp, false);
- }
-
- // Add the registered web handlers. There can be any number of these.
- var webHandlers = this._converterSvc.getContentHandlers(this.type);
- for each (let webHandler in webHandlers)
- this._possibleApplicationHandlers.appendElement(webHandler, false);
-
- return this._possibleApplicationHandlers;
- },
-
- __defaultApplicationHandler: undefined,
- get _defaultApplicationHandler() {
- if (typeof this.__defaultApplicationHandler != "undefined")
- return this.__defaultApplicationHandler;
-
- var defaultFeedReader = null;
-#ifdef HAVE_SHELL_SERVICE
- try {
- defaultFeedReader = this._shellSvc.defaultFeedReader;
- }
- catch(ex) {
- // no default reader or _shellSvc is null
- }
-#endif
-
- if (defaultFeedReader) {
- let handlerApp = Cc["@mozilla.org/uriloader/local-handler-app;1"].
- createInstance(Ci.nsIHandlerApp);
- handlerApp.name = getFileDisplayName(defaultFeedReader);
- handlerApp.QueryInterface(Ci.nsILocalHandlerApp);
- handlerApp.executable = defaultFeedReader;
-
- this.__defaultApplicationHandler = handlerApp;
- }
- else {
- this.__defaultApplicationHandler = null;
- }
-
- return this.__defaultApplicationHandler;
- },
-
- get hasDefaultHandler() {
-#ifdef HAVE_SHELL_SERVICE
- try {
- if (this._shellSvc.defaultFeedReader)
- return true;
- }
- catch(ex) {
- // no default reader or _shellSvc is null
- }
-#endif
-
- return false;
- },
-
- get defaultDescription() {
- if (this.hasDefaultHandler)
- return this._defaultApplicationHandler.name;
-
- // Should we instead return null?
- return "";
- },
-
- // What to do with content of this type.
- get preferredAction() {
- switch (this.element(this._prefSelectedAction).value) {
-
- case "bookmarks":
- return Ci.nsIHandlerInfo.handleInternally;
-
- case "reader": {
- let preferredApp = this.preferredApplicationHandler;
- let defaultApp = this._defaultApplicationHandler;
-
- // If we have a valid preferred app, return useSystemDefault if it's
- // the default app; otherwise return useHelperApp.
- if (gApplicationsPane.isValidHandlerApp(preferredApp)) {
- if (defaultApp && defaultApp.equals(preferredApp))
- return Ci.nsIHandlerInfo.useSystemDefault;
-
- return Ci.nsIHandlerInfo.useHelperApp;
- }
-
- // The pref is set to "reader", but we don't have a valid preferred app.
- // What do we do now? Not sure this is the best option (perhaps we
- // should direct the user to the default app, if any), but for now let's
- // direct the user to live bookmarks.
- return Ci.nsIHandlerInfo.handleInternally;
- }
-
- // If the action is "ask", then alwaysAskBeforeHandling will override
- // the action, so it doesn't matter what we say it is, it just has to be
- // something that doesn't cause the controller to hide the type.
- case "ask":
- default:
- return Ci.nsIHandlerInfo.handleInternally;
- }
- },
-
- set preferredAction(aNewValue) {
- switch (aNewValue) {
-
- case Ci.nsIHandlerInfo.handleInternally:
- this.element(this._prefSelectedReader).value = "bookmarks";
- break;
-
- case Ci.nsIHandlerInfo.useHelperApp:
- this.element(this._prefSelectedAction).value = "reader";
- // The controller has already set preferredApplicationHandler
- // to the new helper app.
- break;
-
- case Ci.nsIHandlerInfo.useSystemDefault:
- this.element(this._prefSelectedAction).value = "reader";
- this.preferredApplicationHandler = this._defaultApplicationHandler;
- break;
- }
- },
-
- get alwaysAskBeforeHandling() {
- return this.element(this._prefSelectedAction).value == "ask";
- },
-
- set alwaysAskBeforeHandling(aNewValue) {
- if (aNewValue == true)
- this.element(this._prefSelectedAction).value = "ask";
- else
- this.element(this._prefSelectedAction).value = "reader";
- },
-
- // Whether or not we are currently storing the action selected by the user.
- // We use this to suppress notification-triggered updates to the list when
- // we make changes that may spawn such updates, specifically when we change
- // the action for the feed type, which results in feed preference updates,
- // which spawn "pref changed" notifications that would otherwise cause us
- // to rebuild the view unnecessarily.
- _storingAction: false,
-
-
- //**************************************************************************//
- // nsIMIMEInfo
-
- get primaryExtension() {
- return "xml";
- },
-
-
- //**************************************************************************//
- // Storage
-
- // Changes to the preferred action and handler take effect immediately
- // (we write them out to the preferences right as they happen),
- // so we when the controller calls store() after modifying the handlers,
- // the only thing we need to store is the removal of possible handlers
- // XXX Should we hold off on making the changes until this method gets called?
- store: function() {
- for each (let app in this._possibleApplicationHandlers._removed) {
- if (app instanceof Ci.nsILocalHandlerApp) {
- let pref = this.element(PREF_FEED_SELECTED_APP);
- var preferredAppFile = pref.value;
- if (preferredAppFile) {
- let preferredApp = getLocalHandlerApp(preferredAppFile);
- if (app.equals(preferredApp))
- pref.reset();
- }
- }
- else {
- app.QueryInterface(Ci.nsIWebContentHandlerInfo);
- this._converterSvc.removeContentHandler(app.contentType, app.uri);
- }
- }
- this._possibleApplicationHandlers._removed = [];
- },
-
-
- //**************************************************************************//
- // Icons
-
- get smallIcon() {
- return this._smallIcon;
- }
-
-};
-
-var feedHandlerInfo = {
- __proto__: new FeedHandlerInfo(TYPE_MAYBE_FEED),
- _prefSelectedApp: PREF_FEED_SELECTED_APP,
- _prefSelectedWeb: PREF_FEED_SELECTED_WEB,
- _prefSelectedAction: PREF_FEED_SELECTED_ACTION,
- _prefSelectedReader: PREF_FEED_SELECTED_READER,
- _smallIcon: "chrome://browser/skin/feeds/feedIcon16.png",
- _appPrefLabel: "webFeed"
-}
-
-var videoFeedHandlerInfo = {
- __proto__: new FeedHandlerInfo(TYPE_MAYBE_VIDEO_FEED),
- _prefSelectedApp: PREF_VIDEO_FEED_SELECTED_APP,
- _prefSelectedWeb: PREF_VIDEO_FEED_SELECTED_WEB,
- _prefSelectedAction: PREF_VIDEO_FEED_SELECTED_ACTION,
- _prefSelectedReader: PREF_VIDEO_FEED_SELECTED_READER,
- _smallIcon: "chrome://browser/skin/feeds/videoFeedIcon16.png",
- _appPrefLabel: "videoPodcastFeed"
-}
-
-var audioFeedHandlerInfo = {
- __proto__: new FeedHandlerInfo(TYPE_MAYBE_AUDIO_FEED),
- _prefSelectedApp: PREF_AUDIO_FEED_SELECTED_APP,
- _prefSelectedWeb: PREF_AUDIO_FEED_SELECTED_WEB,
- _prefSelectedAction: PREF_AUDIO_FEED_SELECTED_ACTION,
- _prefSelectedReader: PREF_AUDIO_FEED_SELECTED_READER,
- _smallIcon: "chrome://browser/skin/feeds/audioFeedIcon16.png",
- _appPrefLabel: "audioPodcastFeed"
-}
-
-/**
- * InternalHandlerInfoWrapper provides a basic mechanism to create an internal
- * mime type handler that can be enabled/disabled in the applications preference
- * menu.
- */
-function InternalHandlerInfoWrapper(aMIMEType) {
- var mimeSvc = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
- var handlerInfo = mimeSvc.getFromTypeAndExtension(aMIMEType, null);
-
- HandlerInfoWrapper.call(this, aMIMEType, handlerInfo);
-}
-
-InternalHandlerInfoWrapper.prototype = {
- __proto__: HandlerInfoWrapper.prototype,
-
- // Override store so we so we can notify any code listening for registration
- // or unregistration of this handler.
- store: function() {
- HandlerInfoWrapper.prototype.store.call(this);
- Services.obs.notifyObservers(null, this._handlerChanged, null);
- },
-
- get enabled() {
- throw Cr.NS_ERROR_NOT_IMPLEMENTED;
- },
-
- get description() {
- return this.element("bundlePreferences").getString(this._appPrefLabel);
- }
-};
-
-//****************************************************************************//
-// Prefpane Controller
-
-var gApplicationsPane = {
- // The set of types the app knows how to handle. A hash of HandlerInfoWrapper
- // objects, indexed by type.
- _handledTypes: {},
-
- // The list of types we can show, sorted by the sort column/direction.
- // An array of HandlerInfoWrapper objects. We build this list when we first
- // load the data and then rebuild it when users change a pref that affects
- // what types we can show or change the sort column/direction.
- // Note: this isn't necessarily the list of types we *will* show; if the user
- // provides a filter string, we'll only show the subset of types in this list
- // that match that string.
- _visibleTypes: [],
-
- // A count of the number of times each visible type description appears.
- // We use these counts to determine whether or not to annotate descriptions
- // with their types to distinguish duplicate descriptions from each other.
- // A hash of integer counts, indexed by string description.
- _visibleTypeDescriptionCount: {},
-
-
- //**************************************************************************//
- // Convenience & Performance Shortcuts
-
- // These get defined by init().
- _brandShortName : null,
- _prefsBundle : null,
- _list : null,
- _filter : null,
-
- _prefSvc : Cc["@mozilla.org/preferences-service;1"].
- getService(Ci.nsIPrefBranch),
-
- _mimeSvc : Cc["@mozilla.org/mime;1"].
- getService(Ci.nsIMIMEService),
-
- _helperAppSvc : Cc["@mozilla.org/uriloader/external-helper-app-service;1"].
- getService(Ci.nsIExternalHelperAppService),
-
- _handlerSvc : Cc["@mozilla.org/uriloader/handler-service;1"].
- getService(Ci.nsIHandlerService),
-
- _ioSvc : Cc["@mozilla.org/network/io-service;1"].
- getService(Ci.nsIIOService),
-
-
- //**************************************************************************//
- // Initialization & Destruction
-
- init: function() {
- // Initialize shortcuts to some commonly accessed elements & values.
- this._brandShortName =
- document.getElementById("bundleBrand").getString("brandShortName");
- this._prefsBundle = document.getElementById("bundlePreferences");
- this._list = document.getElementById("handlersView");
- this._filter = document.getElementById("filter");
-
- // Observe preferences that influence what we display so we can rebuild
- // the view when they change.
- this._prefSvc.addObserver(PREF_SHOW_PLUGINS_IN_LIST, this, false);
- this._prefSvc.addObserver(PREF_HIDE_PLUGINS_WITHOUT_EXTENSIONS, this, false);
- this._prefSvc.addObserver(PREF_FEED_SELECTED_APP, this, false);
- this._prefSvc.addObserver(PREF_FEED_SELECTED_WEB, this, false);
- this._prefSvc.addObserver(PREF_FEED_SELECTED_ACTION, this, false);
- this._prefSvc.addObserver(PREF_FEED_SELECTED_READER, this, false);
-
- this._prefSvc.addObserver(PREF_VIDEO_FEED_SELECTED_APP, this, false);
- this._prefSvc.addObserver(PREF_VIDEO_FEED_SELECTED_WEB, this, false);
- this._prefSvc.addObserver(PREF_VIDEO_FEED_SELECTED_ACTION, this, false);
- this._prefSvc.addObserver(PREF_VIDEO_FEED_SELECTED_READER, this, false);
-
- this._prefSvc.addObserver(PREF_AUDIO_FEED_SELECTED_APP, this, false);
- this._prefSvc.addObserver(PREF_AUDIO_FEED_SELECTED_WEB, this, false);
- this._prefSvc.addObserver(PREF_AUDIO_FEED_SELECTED_ACTION, this, false);
- this._prefSvc.addObserver(PREF_AUDIO_FEED_SELECTED_READER, this, false);
-
-
- // Listen for window unload so we can remove our preference observers.
- window.addEventListener("unload", this, false);
-
- // Figure out how we should be sorting the list. We persist sort settings
- // across sessions, so we can't assume the default sort column/direction.
- // XXX should we be using the XUL sort service instead?
- if (document.getElementById("actionColumn").hasAttribute("sortDirection")) {
- this._sortColumn = document.getElementById("actionColumn");
- // The typeColumn element always has a sortDirection attribute,
- // either because it was persisted or because the default value
- // from the xul file was used. If we are sorting on the other
- // column, we should remove it.
- document.getElementById("typeColumn").removeAttribute("sortDirection");
- }
- else
- this._sortColumn = document.getElementById("typeColumn");
-
- // Load the data and build the list of handlers.
- // By doing this in a timeout, we let the preferences dialog resize itself
- // to an appropriate size before we add a bunch of items to the list.
- // Otherwise, if there are many items, and the Applications prefpane
- // is the one that gets displayed when the user first opens the dialog,
- // the dialog might stretch too much in an attempt to fit them all in.
- // XXX Shouldn't we perhaps just set a max-height on the richlistbox?
- var _delayedPaneLoad = function(self) {
- self._loadData();
- self._rebuildVisibleTypes();
- self._sortVisibleTypes();
- self._rebuildView();
-
- // Notify observers that the UI is now ready
- Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService).
- notifyObservers(window, "app-handler-pane-loaded", null);
- }
- setTimeout(_delayedPaneLoad, 0, this);
- },
-
- destroy: function() {
- window.removeEventListener("unload", this, false);
- this._prefSvc.removeObserver(PREF_SHOW_PLUGINS_IN_LIST, this);
- this._prefSvc.removeObserver(PREF_HIDE_PLUGINS_WITHOUT_EXTENSIONS, this);
- this._prefSvc.removeObserver(PREF_FEED_SELECTED_APP, this);
- this._prefSvc.removeObserver(PREF_FEED_SELECTED_WEB, this);
- this._prefSvc.removeObserver(PREF_FEED_SELECTED_ACTION, this);
- this._prefSvc.removeObserver(PREF_FEED_SELECTED_READER, this);
-
- this._prefSvc.removeObserver(PREF_VIDEO_FEED_SELECTED_APP, this);
- this._prefSvc.removeObserver(PREF_VIDEO_FEED_SELECTED_WEB, this);
- this._prefSvc.removeObserver(PREF_VIDEO_FEED_SELECTED_ACTION, this);
- this._prefSvc.removeObserver(PREF_VIDEO_FEED_SELECTED_READER, this);
-
- this._prefSvc.removeObserver(PREF_AUDIO_FEED_SELECTED_APP, this);
- this._prefSvc.removeObserver(PREF_AUDIO_FEED_SELECTED_WEB, this);
- this._prefSvc.removeObserver(PREF_AUDIO_FEED_SELECTED_ACTION, this);
- this._prefSvc.removeObserver(PREF_AUDIO_FEED_SELECTED_READER, this);
- },
-
-
- //**************************************************************************//
- // nsISupports
-
- QueryInterface: function(aIID) {
- if (aIID.equals(Ci.nsIObserver) ||
- aIID.equals(Ci.nsIDOMEventListener ||
- aIID.equals(Ci.nsISupports)))
- return this;
-
- throw Cr.NS_ERROR_NO_INTERFACE;
- },
-
-
- //**************************************************************************//
- // nsIObserver
-
- observe: function (aSubject, aTopic, aData) {
- // Rebuild the list when there are changes to preferences that influence
- // whether or not to show certain entries in the list.
- if (aTopic == "nsPref:changed" && !this._storingAction) {
- // These two prefs alter the list of visible types, so we have to rebuild
- // that list when they change.
- if (aData == PREF_SHOW_PLUGINS_IN_LIST ||
- aData == PREF_HIDE_PLUGINS_WITHOUT_EXTENSIONS) {
- this._rebuildVisibleTypes();
- this._sortVisibleTypes();
- }
-
- // All the prefs we observe can affect what we display, so we rebuild
- // the view when any of them changes.
- this._rebuildView();
- }
- },
-
-
- //**************************************************************************//
- // nsIDOMEventListener
-
- handleEvent: function(aEvent) {
- if (aEvent.type == "unload") {
- this.destroy();
- }
- },
-
-
- //**************************************************************************//
- // Composed Model Construction
-
- _loadData: function() {
- this._loadFeedHandler();
- this._loadPluginHandlers();
- this._loadApplicationHandlers();
- },
-
- _loadFeedHandler: function() {
- this._handledTypes[TYPE_MAYBE_FEED] = feedHandlerInfo;
- feedHandlerInfo.handledOnlyByPlugin = false;
-
- this._handledTypes[TYPE_MAYBE_VIDEO_FEED] = videoFeedHandlerInfo;
- videoFeedHandlerInfo.handledOnlyByPlugin = false;
-
- this._handledTypes[TYPE_MAYBE_AUDIO_FEED] = audioFeedHandlerInfo;
- audioFeedHandlerInfo.handledOnlyByPlugin = false;
- },
-
- /**
- * Load the set of handlers defined by plugins.
- *
- * Note: if there's more than one plugin for a given MIME type, we assume
- * the last one is the one that the application will use. That may not be
- * correct, but it's how we've been doing it for years.
- *
- * Perhaps we should instead query navigator.mimeTypes for the set of types
- * supported by the application and then get the plugin from each MIME type's
- * enabledPlugin property. But if there's a plugin for a type, we need
- * to know about it even if it isn't enabled, since we're going to give
- * the user an option to enable it.
- *
- * Also note that enabledPlugin does not get updated when
- * plugin.disable_full_page_plugin_for_types changes, so even if we could use
- * enabledPlugin to get the plugin that would be used, we'd still need to
- * check the pref ourselves to find out if it's enabled.
- */
- _loadPluginHandlers: function() {
- "use strict";
-
- let mimeTypes = navigator.mimeTypes;
-
- for (let mimeType of mimeTypes) {
- let handlerInfoWrapper;
- if (mimeType.type in this._handledTypes) {
- handlerInfoWrapper = this._handledTypes[mimeType.type];
- } else {
- let wrappedHandlerInfo =
- this._mimeSvc.getFromTypeAndExtension(mimeType.type, null);
- handlerInfoWrapper = new HandlerInfoWrapper(mimeType.type, wrappedHandlerInfo);
- handlerInfoWrapper.handledOnlyByPlugin = true;
- this._handledTypes[mimeType.type] = handlerInfoWrapper;
- }
- handlerInfoWrapper.pluginName = mimeType.enabledPlugin.name;
- }
- },
-
- /**
- * Load the set of handlers defined by the application datastore.
- */
- _loadApplicationHandlers: function() {
- var wrappedHandlerInfos = this._handlerSvc.enumerate();
- while (wrappedHandlerInfos.hasMoreElements()) {
- let wrappedHandlerInfo =
- wrappedHandlerInfos.getNext().QueryInterface(Ci.nsIHandlerInfo);
- let type = wrappedHandlerInfo.type;
-
- let handlerInfoWrapper;
- if (type in this._handledTypes)
- handlerInfoWrapper = this._handledTypes[type];
- else {
- handlerInfoWrapper = new HandlerInfoWrapper(type, wrappedHandlerInfo);
- this._handledTypes[type] = handlerInfoWrapper;
- }
-
- handlerInfoWrapper.handledOnlyByPlugin = false;
- }
- },
-
-
- //**************************************************************************//
- // View Construction
-
- _rebuildVisibleTypes: function() {
- // Reset the list of visible types and the visible type description counts.
- this._visibleTypes = [];
- this._visibleTypeDescriptionCount = {};
-
- // Get the preferences that help determine what types to show.
- var showPlugins = this._prefSvc.getBoolPref(PREF_SHOW_PLUGINS_IN_LIST);
- var hidePluginsWithoutExtensions =
- this._prefSvc.getBoolPref(PREF_HIDE_PLUGINS_WITHOUT_EXTENSIONS);
-
- for (let type in this._handledTypes) {
- let handlerInfo = this._handledTypes[type];
-
- // Hide plugins without associated extensions if so prefed so we don't
- // show a whole bunch of obscure types handled by plugins on Mac.
- // Note: though protocol types don't have extensions, we still show them;
- // the pref is only meant to be applied to MIME types, since plugins are
- // only associated with MIME types.
- // FIXME: should we also check the "suffixes" property of the plugin?
- // Filed as bug 395135.
- if (hidePluginsWithoutExtensions && handlerInfo.handledOnlyByPlugin &&
- handlerInfo.wrappedHandlerInfo instanceof Ci.nsIMIMEInfo &&
- !handlerInfo.primaryExtension)
- continue;
-
- // Hide types handled only by plugins if so prefed.
- if (handlerInfo.handledOnlyByPlugin && !showPlugins)
- continue;
-
- // We couldn't find any reason to exclude the type, so include it.
- this._visibleTypes.push(handlerInfo);
-
- if (handlerInfo.description in this._visibleTypeDescriptionCount)
- this._visibleTypeDescriptionCount[handlerInfo.description]++;
- else
- this._visibleTypeDescriptionCount[handlerInfo.description] = 1;
- }
- },
-
- _rebuildView: function() {
- // Clear the list of entries.
- while (this._list.childNodes.length > 1)
- this._list.removeChild(this._list.lastChild);
-
- var visibleTypes = this._visibleTypes;
-
- // If the user is filtering the list, then only show matching types.
- if (this._filter.value)
- visibleTypes = visibleTypes.filter(this._matchesFilter, this);
-
- for each (let visibleType in visibleTypes) {
- let item = document.createElement("richlistitem");
- item.setAttribute("type", visibleType.type);
- item.setAttribute("typeDescription", this._describeType(visibleType));
- if (visibleType.smallIcon)
- item.setAttribute("typeIcon", visibleType.smallIcon);
- item.setAttribute("actionDescription",
- this._describePreferredAction(visibleType));
-
- if (!this._setIconClassForPreferredAction(visibleType, item)) {
- item.setAttribute("actionIcon",
- this._getIconURLForPreferredAction(visibleType));
- }
-
- this._list.appendChild(item);
- }
-
- this._selectLastSelectedType();
- },
-
- _matchesFilter: function(aType) {
- var filterValue = this._filter.value.toLowerCase();
- return this._describeType(aType).toLowerCase().indexOf(filterValue) != -1 ||
- this._describePreferredAction(aType).toLowerCase().indexOf(filterValue) != -1;
- },
-
- /**
- * Describe, in a human-readable fashion, the type represented by the given
- * handler info object. Normally this is just the description provided by
- * the info object, but if more than one object presents the same description,
- * then we annotate the duplicate descriptions with the type itself to help
- * users distinguish between those types.
- *
- * @param aHandlerInfo {nsIHandlerInfo} the type being described
- * @returns {string} a description of the type
- */
- _describeType: function(aHandlerInfo) {
- if (this._visibleTypeDescriptionCount[aHandlerInfo.description] > 1)
- return this._prefsBundle.getFormattedString("typeDescriptionWithType",
- [aHandlerInfo.description,
- aHandlerInfo.type]);
-
- return aHandlerInfo.description;
- },
-
- /**
- * Describe, in a human-readable fashion, the preferred action to take on
- * the type represented by the given handler info object.
- *
- * XXX Should this be part of the HandlerInfoWrapper interface? It would
- * violate the separation of model and view, but it might make more sense
- * nonetheless (f.e. it would make sortTypes easier).
- *
- * @param aHandlerInfo {nsIHandlerInfo} the type whose preferred action
- * is being described
- * @returns {string} a description of the action
- */
- _describePreferredAction: function(aHandlerInfo) {
- // alwaysAskBeforeHandling overrides the preferred action, so if that flag
- // is set, then describe that behavior instead. For most types, this is
- // the "alwaysAsk" string, but for the feed type we show something special.
- if (aHandlerInfo.alwaysAskBeforeHandling) {
- if (isFeedType(aHandlerInfo.type))
- return this._prefsBundle.getFormattedString("previewInApp",
- [this._brandShortName]);
- else
- return this._prefsBundle.getString("alwaysAsk");
- }
-
- switch (aHandlerInfo.preferredAction) {
- case Ci.nsIHandlerInfo.saveToDisk:
- return this._prefsBundle.getString("saveFile");
-
- case Ci.nsIHandlerInfo.useHelperApp:
- var preferredApp = aHandlerInfo.preferredApplicationHandler;
- var name;
- if (preferredApp instanceof Ci.nsILocalHandlerApp)
- name = getFileDisplayName(preferredApp.executable);
- else
- name = preferredApp.name;
- return this._prefsBundle.getFormattedString("useApp", [name]);
-
- case Ci.nsIHandlerInfo.handleInternally:
- // For the feed type, handleInternally means live bookmarks.
- if (isFeedType(aHandlerInfo.type)) {
- return this._prefsBundle.getFormattedString("addLiveBookmarksInApp",
- [this._brandShortName]);
- }
-
- if (aHandlerInfo instanceof InternalHandlerInfoWrapper) {
- return this._prefsBundle.getFormattedString("previewInApp",
- [this._brandShortName]);
- }
-
- // For other types, handleInternally looks like either useHelperApp
- // or useSystemDefault depending on whether or not there's a preferred
- // handler app.
- if (this.isValidHandlerApp(aHandlerInfo.preferredApplicationHandler))
- return aHandlerInfo.preferredApplicationHandler.name;
-
- return aHandlerInfo.defaultDescription;
-
- // XXX Why don't we say the app will handle the type internally?
- // Is it because the app can't actually do that? But if that's true,
- // then why would a preferredAction ever get set to this value
- // in the first place?
-
- case Ci.nsIHandlerInfo.useSystemDefault:
- return this._prefsBundle.getFormattedString("useDefault",
- [aHandlerInfo.defaultDescription]);
-
- case kActionUsePlugin:
- return this._prefsBundle.getFormattedString("usePluginIn",
- [aHandlerInfo.pluginName,
- this._brandShortName]);
- }
- },
-
- _selectLastSelectedType: function() {
- // If the list is disabled by the pref.downloads.disable_button.edit_actions
- // preference being locked, then don't select the type, as that would cause
- // it to appear selected, with a different background and an actions menu
- // that makes it seem like you can choose an action for the type.
- if (this._list.disabled)
- return;
-
- var lastSelectedType = this._list.getAttribute("lastSelectedType");
- if (!lastSelectedType)
- return;
-
- var item = this._list.getElementsByAttribute("type", lastSelectedType)[0];
- if (!item)
- return;
-
- this._list.selectedItem = item;
- },
-
- /**
- * Whether or not the given handler app is valid.
- *
- * @param aHandlerApp {nsIHandlerApp} the handler app in question
- *
- * @returns {boolean} whether or not it's valid
- */
- isValidHandlerApp: function(aHandlerApp) {
- if (!aHandlerApp)
- return false;
-
- if (aHandlerApp instanceof Ci.nsILocalHandlerApp)
- return this._isValidHandlerExecutable(aHandlerApp.executable);
-
- if (aHandlerApp instanceof Ci.nsIWebHandlerApp)
- return aHandlerApp.uriTemplate;
-
- if (aHandlerApp instanceof Ci.nsIWebContentHandlerInfo)
- return aHandlerApp.uri;
-
- return false;
- },
-
- _isValidHandlerExecutable: function(aExecutable) {
- return aExecutable &&
- aExecutable.exists() &&
- aExecutable.isExecutable() &&
-// XXXben - we need to compare this with the running instance executable
-// just don't know how to do that via script...
-// XXXmano TBD: can probably add this to nsIShellService
-#ifdef XP_WIN
-#expand aExecutable.leafName != "__MOZ_APP_NAME__.exe";
-#else
-#ifdef XP_MACOSX
-#expand aExecutable.leafName != "__MOZ_MACBUNDLE_NAME__";
-#else
-#expand aExecutable.leafName != "__MOZ_APP_NAME__-bin";
-#endif
-#endif
- },
-
- /**
- * Rebuild the actions menu for the selected entry. Gets called by
- * the richlistitem constructor when an entry in the list gets selected.
- */
- rebuildActionsMenu: function() {
- var typeItem = this._list.selectedItem;
- var handlerInfo = this._handledTypes[typeItem.type];
- var menu =
- document.getAnonymousElementByAttribute(typeItem, "class", "actionsMenu");
- var menuPopup = menu.menupopup;
-
- // Clear out existing items.
- while (menuPopup.hasChildNodes())
- menuPopup.removeChild(menuPopup.lastChild);
-
- // Add the "Preview in Firefox" option for optional internal handlers.
- if (handlerInfo instanceof InternalHandlerInfoWrapper) {
- var internalMenuItem = document.createElement("menuitem");
- internalMenuItem.setAttribute("action", Ci.nsIHandlerInfo.handleInternally);
- let label = this._prefsBundle.getFormattedString("previewInApp",
- [this._brandShortName]);
- internalMenuItem.setAttribute("label", label);
- internalMenuItem.setAttribute("tooltiptext", label);
- internalMenuItem.setAttribute(APP_ICON_ATTR_NAME, "ask");
- menuPopup.appendChild(internalMenuItem);
- }
-
- {
- var askMenuItem = document.createElement("menuitem");
- askMenuItem.setAttribute("action", Ci.nsIHandlerInfo.alwaysAsk);
- let label;
- if (isFeedType(handlerInfo.type))
- label = this._prefsBundle.getFormattedString("previewInApp",
- [this._brandShortName]);
- else
- label = this._prefsBundle.getString("alwaysAsk");
- askMenuItem.setAttribute("label", label);
- askMenuItem.setAttribute("tooltiptext", label);
- askMenuItem.setAttribute(APP_ICON_ATTR_NAME, "ask");
- menuPopup.appendChild(askMenuItem);
- }
-
- // Create a menu item for saving to disk.
- // Note: this option isn't available to protocol types, since we don't know
- // what it means to save a URL having a certain scheme to disk, nor is it
- // available to feeds, since the feed code doesn't implement the capability.
- if ((handlerInfo.wrappedHandlerInfo instanceof Ci.nsIMIMEInfo) &&
- !isFeedType(handlerInfo.type)) {
- var saveMenuItem = document.createElement("menuitem");
- saveMenuItem.setAttribute("action", Ci.nsIHandlerInfo.saveToDisk);
- let label = this._prefsBundle.getString("saveFile");
- saveMenuItem.setAttribute("label", label);
- saveMenuItem.setAttribute("tooltiptext", label);
- saveMenuItem.setAttribute(APP_ICON_ATTR_NAME, "save");
- menuPopup.appendChild(saveMenuItem);
- }
-
- // If this is the feed type, add a Live Bookmarks item.
- if (isFeedType(handlerInfo.type)) {
- var internalMenuItem = document.createElement("menuitem");
- internalMenuItem.setAttribute("action", Ci.nsIHandlerInfo.handleInternally);
- let label = this._prefsBundle.getFormattedString("addLiveBookmarksInApp",
- [this._brandShortName]);
- internalMenuItem.setAttribute("label", label);
- internalMenuItem.setAttribute("tooltiptext", label);
- internalMenuItem.setAttribute(APP_ICON_ATTR_NAME, "feed");
- menuPopup.appendChild(internalMenuItem);
- }
-
- // Add a separator to distinguish these items from the helper app items
- // that follow them.
- let menuItem = document.createElement("menuseparator");
- menuPopup.appendChild(menuItem);
-
- // Create a menu item for the OS default application, if any.
- if (handlerInfo.hasDefaultHandler) {
- var defaultMenuItem = document.createElement("menuitem");
- defaultMenuItem.setAttribute("action", Ci.nsIHandlerInfo.useSystemDefault);
- let label = this._prefsBundle.getFormattedString("useDefault",
- [handlerInfo.defaultDescription]);
- defaultMenuItem.setAttribute("label", label);
- defaultMenuItem.setAttribute("tooltiptext", handlerInfo.defaultDescription);
- defaultMenuItem.setAttribute("image", this._getIconURLForSystemDefault(handlerInfo));
-
- menuPopup.appendChild(defaultMenuItem);
- }
-
- // Create menu items for possible handlers.
- let preferredApp = handlerInfo.preferredApplicationHandler;
- let possibleApps = handlerInfo.possibleApplicationHandlers.enumerate();
- var possibleAppMenuItems = [];
- while (possibleApps.hasMoreElements()) {
- let possibleApp = possibleApps.getNext();
- if (!this.isValidHandlerApp(possibleApp))
- continue;
-
- let menuItem = document.createElement("menuitem");
- menuItem.setAttribute("action", Ci.nsIHandlerInfo.useHelperApp);
- let label;
- if (possibleApp instanceof Ci.nsILocalHandlerApp)
- label = getFileDisplayName(possibleApp.executable);
- else
- label = possibleApp.name;
- label = this._prefsBundle.getFormattedString("useApp", [label]);
- menuItem.setAttribute("label", label);
- menuItem.setAttribute("tooltiptext", label);
- menuItem.setAttribute("image", this._getIconURLForHandlerApp(possibleApp));
-
- // Attach the handler app object to the menu item so we can use it
- // to make changes to the datastore when the user selects the item.
- menuItem.handlerApp = possibleApp;
-
- menuPopup.appendChild(menuItem);
- possibleAppMenuItems.push(menuItem);
- }
-
- // Create a menu item for the plugin.
- if (handlerInfo.pluginName) {
- var pluginMenuItem = document.createElement("menuitem");
- pluginMenuItem.setAttribute("action", kActionUsePlugin);
- let label = this._prefsBundle.getFormattedString("usePluginIn",
- [handlerInfo.pluginName,
- this._brandShortName]);
- pluginMenuItem.setAttribute("label", label);
- pluginMenuItem.setAttribute("tooltiptext", label);
- pluginMenuItem.setAttribute(APP_ICON_ATTR_NAME, "plugin");
- menuPopup.appendChild(pluginMenuItem);
- }
-
- // Create a menu item for selecting a local application.
-#ifdef XP_WIN
- // On Windows, selecting an application to open another application
- // would be meaningless so we special case executables.
- var executableType = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService)
- .getTypeFromExtension("exe");
- if (handlerInfo.type != executableType)
-#endif
- {
- let menuItem = document.createElement("menuitem");
- menuItem.setAttribute("oncommand", "gApplicationsPane.chooseApp(event)");
- let label = this._prefsBundle.getString("useOtherApp");
- menuItem.setAttribute("label", label);
- menuItem.setAttribute("tooltiptext", label);
- menuPopup.appendChild(menuItem);
- }
-
- // Create a menu item for managing applications.
- if (possibleAppMenuItems.length) {
- let menuItem = document.createElement("menuseparator");
- menuPopup.appendChild(menuItem);
- menuItem = document.createElement("menuitem");
- menuItem.setAttribute("oncommand", "gApplicationsPane.manageApp(event)");
- menuItem.setAttribute("label", this._prefsBundle.getString("manageApp"));
- menuPopup.appendChild(menuItem);
- }
-
- // Select the item corresponding to the preferred action. If the always
- // ask flag is set, it overrides the preferred action. Otherwise we pick
- // the item identified by the preferred action (when the preferred action
- // is to use a helper app, we have to pick the specific helper app item).
- if (handlerInfo.alwaysAskBeforeHandling)
- menu.selectedItem = askMenuItem;
- else switch (handlerInfo.preferredAction) {
- case Ci.nsIHandlerInfo.handleInternally:
- menu.selectedItem = internalMenuItem;
- break;
- case Ci.nsIHandlerInfo.useSystemDefault:
- menu.selectedItem = defaultMenuItem;
- break;
- case Ci.nsIHandlerInfo.useHelperApp:
- if (preferredApp)
- menu.selectedItem =
- possibleAppMenuItems.filter(function(v) v.handlerApp.equals(preferredApp))[0];
- break;
- case kActionUsePlugin:
- menu.selectedItem = pluginMenuItem;
- break;
- case Ci.nsIHandlerInfo.saveToDisk:
- menu.selectedItem = saveMenuItem;
- break;
- }
- },
-
-
- //**************************************************************************//
- // Sorting & Filtering
-
- _sortColumn: null,
-
- /**
- * Sort the list when the user clicks on a column header.
- */
- sort: function (event) {
- var column = event.target;
-
- // If the user clicked on a new sort column, remove the direction indicator
- // from the old column.
- if (this._sortColumn && this._sortColumn != column)
- this._sortColumn.removeAttribute("sortDirection");
-
- this._sortColumn = column;
-
- // Set (or switch) the sort direction indicator.
- if (column.getAttribute("sortDirection") == "ascending")
- column.setAttribute("sortDirection", "descending");
- else
- column.setAttribute("sortDirection", "ascending");
-
- this._sortVisibleTypes();
- this._rebuildView();
- },
-
- /**
- * Sort the list of visible types by the current sort column/direction.
- */
- _sortVisibleTypes: function() {
- if (!this._sortColumn)
- return;
-
- var t = this;
-
- function sortByType(a, b) {
- return t._describeType(a).toLowerCase().
- localeCompare(t._describeType(b).toLowerCase());
- }
-
- function sortByAction(a, b) {
- return t._describePreferredAction(a).toLowerCase().
- localeCompare(t._describePreferredAction(b).toLowerCase());
- }
-
- switch (this._sortColumn.getAttribute("value")) {
- case "type":
- this._visibleTypes.sort(sortByType);
- break;
- case "action":
- this._visibleTypes.sort(sortByAction);
- break;
- }
-
- if (this._sortColumn.getAttribute("sortDirection") == "descending")
- this._visibleTypes.reverse();
- },
-
- /**
- * Filter the list when the user enters a filter term into the filter field.
- */
- filter: function() {
- this._rebuildView();
- },
-
- focusFilterBox: function() {
- this._filter.focus();
- this._filter.select();
- },
-
-
- //**************************************************************************//
- // Changes
-
- onSelectAction: function(aActionItem) {
- this._storingAction = true;
-
- try {
- this._storeAction(aActionItem);
- }
- finally {
- this._storingAction = false;
- }
- },
-
- _storeAction: function(aActionItem) {
- var typeItem = this._list.selectedItem;
- var handlerInfo = this._handledTypes[typeItem.type];
-
- let action = parseInt(aActionItem.getAttribute("action"));
-
- // Set the plugin state if we're enabling or disabling a plugin.
- if (action == kActionUsePlugin)
- handlerInfo.enablePluginType();
- else if (handlerInfo.pluginName && !handlerInfo.isDisabledPluginType)
- handlerInfo.disablePluginType();
-
- // Set the preferred application handler.
- // We leave the existing preferred app in the list when we set
- // the preferred action to something other than useHelperApp so that
- // legacy datastores that don't have the preferred app in the list
- // of possible apps still include the preferred app in the list of apps
- // the user can choose to handle the type.
- if (action == Ci.nsIHandlerInfo.useHelperApp)
- handlerInfo.preferredApplicationHandler = aActionItem.handlerApp;
-
- // Set the "always ask" flag.
- if (action == Ci.nsIHandlerInfo.alwaysAsk)
- handlerInfo.alwaysAskBeforeHandling = true;
- else
- handlerInfo.alwaysAskBeforeHandling = false;
-
- // Set the preferred action.
- handlerInfo.preferredAction = action;
-
- handlerInfo.store();
-
- // Make sure the handler info object is flagged to indicate that there is
- // now some user configuration for the type.
- handlerInfo.handledOnlyByPlugin = false;
-
- // Update the action label and image to reflect the new preferred action.
- typeItem.setAttribute("actionDescription",
- this._describePreferredAction(handlerInfo));
- if (!this._setIconClassForPreferredAction(handlerInfo, typeItem)) {
- typeItem.setAttribute("actionIcon",
- this._getIconURLForPreferredAction(handlerInfo));
- }
- },
-
- manageApp: function(aEvent) {
- // Don't let the normal "on select action" handler get this event,
- // as we handle it specially ourselves.
- aEvent.stopPropagation();
-
- var typeItem = this._list.selectedItem;
- var handlerInfo = this._handledTypes[typeItem.type];
-
- document.documentElement.openSubDialog("chrome://browser/content/preferences/applicationManager.xul",
- "", handlerInfo);
-
- // Rebuild the actions menu so that we revert to the previous selection,
- // or "Always ask" if the previous default application has been removed
- this.rebuildActionsMenu();
-
- // update the richlistitem too. Will be visible when selecting another row
- typeItem.setAttribute("actionDescription",
- this._describePreferredAction(handlerInfo));
- if (!this._setIconClassForPreferredAction(handlerInfo, typeItem)) {
- typeItem.setAttribute("actionIcon",
- this._getIconURLForPreferredAction(handlerInfo));
- }
- },
-
- chooseApp: function(aEvent) {
- // Don't let the normal "on select action" handler get this event,
- // as we handle it specially ourselves.
- aEvent.stopPropagation();
-
- var handlerApp;
- let chooseAppCallback = function(aHandlerApp) {
- // Rebuild the actions menu whether the user picked an app or canceled.
- // If they picked an app, we want to add the app to the menu and select it.
- // If they canceled, we want to go back to their previous selection.
- this.rebuildActionsMenu();
-
- // If the user picked a new app from the menu, select it.
- if (aHandlerApp) {
- let typeItem = this._list.selectedItem;
- let actionsMenu =
- document.getAnonymousElementByAttribute(typeItem, "class", "actionsMenu");
- let menuItems = actionsMenu.menupopup.childNodes;
- for (let i = 0; i < menuItems.length; i++) {
- let menuItem = menuItems[i];
- if (menuItem.handlerApp && menuItem.handlerApp.equals(aHandlerApp)) {
- actionsMenu.selectedIndex = i;
- this.onSelectAction(menuItem);
- break;
- }
- }
- }
- }.bind(this);
-
-#ifdef XP_WIN
- var params = {};
- var handlerInfo = this._handledTypes[this._list.selectedItem.type];
-
- if (isFeedType(handlerInfo.type)) {
- // MIME info will be null, create a temp object.
- params.mimeInfo = this._mimeSvc.getFromTypeAndExtension(handlerInfo.type,
- handlerInfo.primaryExtension);
- } else {
- params.mimeInfo = handlerInfo.wrappedHandlerInfo;
- }
-
- params.title = this._prefsBundle.getString("fpTitleChooseApp");
- params.description = handlerInfo.description;
- params.filename = null;
- params.handlerApp = null;
-
- window.openDialog("chrome://global/content/appPicker.xul", null,
- "chrome,modal,centerscreen,titlebar,dialog=yes",
- params);
-
- if (this.isValidHandlerApp(params.handlerApp)) {
- handlerApp = params.handlerApp;
-
- // Add the app to the type's list of possible handlers.
- handlerInfo.addPossibleApplicationHandler(handlerApp);
- }
-
- chooseAppCallback(handlerApp);
-#else
- let winTitle = this._prefsBundle.getString("fpTitleChooseApp");
- let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
- let fpCallback = function fpCallback_done(aResult) {
- if (aResult == Ci.nsIFilePicker.returnOK && fp.file &&
- this._isValidHandlerExecutable(fp.file)) {
- handlerApp = Cc["@mozilla.org/uriloader/local-handler-app;1"].
- createInstance(Ci.nsILocalHandlerApp);
- handlerApp.name = getFileDisplayName(fp.file);
- handlerApp.executable = fp.file;
-
- // Add the app to the type's list of possible handlers.
- let handlerInfo = this._handledTypes[this._list.selectedItem.type];
- handlerInfo.addPossibleApplicationHandler(handlerApp);
-
- chooseAppCallback(handlerApp);
- }
- }.bind(this);
-
- // Prompt the user to pick an app. If they pick one, and it's a valid
- // selection, then add it to the list of possible handlers.
- fp.init(window, winTitle, Ci.nsIFilePicker.modeOpen);
- fp.appendFilters(Ci.nsIFilePicker.filterApps);
- fp.open(fpCallback);
-#endif
- },
-
- // Mark which item in the list was last selected so we can reselect it
- // when we rebuild the list or when the user returns to the prefpane.
- onSelectionChanged: function() {
- if (this._list.selectedItem)
- this._list.setAttribute("lastSelectedType",
- this._list.selectedItem.getAttribute("type"));
- },
-
- _setIconClassForPreferredAction: function(aHandlerInfo, aElement) {
- // If this returns true, the attribute that CSS sniffs for was set to something
- // so you shouldn't manually set an icon URI.
- // This removes the existing actionIcon attribute if any, even if returning false.
- aElement.removeAttribute("actionIcon");
-
- if (aHandlerInfo.alwaysAskBeforeHandling) {
- aElement.setAttribute(APP_ICON_ATTR_NAME, "ask");
- return true;
- }
-
- switch (aHandlerInfo.preferredAction) {
- case Ci.nsIHandlerInfo.saveToDisk:
- aElement.setAttribute(APP_ICON_ATTR_NAME, "save");
- return true;
-
- case Ci.nsIHandlerInfo.handleInternally:
- if (isFeedType(aHandlerInfo.type)) {
- aElement.setAttribute(APP_ICON_ATTR_NAME, "feed");
- return true;
- } else if (aHandlerInfo instanceof InternalHandlerInfoWrapper) {
- aElement.setAttribute(APP_ICON_ATTR_NAME, "ask");
- return true;
- }
- break;
-
- case kActionUsePlugin:
- aElement.setAttribute(APP_ICON_ATTR_NAME, "plugin");
- return true;
- }
- aElement.removeAttribute(APP_ICON_ATTR_NAME);
- return false;
- },
-
- _getIconURLForPreferredAction: function(aHandlerInfo) {
- switch (aHandlerInfo.preferredAction) {
- case Ci.nsIHandlerInfo.useSystemDefault:
- return this._getIconURLForSystemDefault(aHandlerInfo);
-
- case Ci.nsIHandlerInfo.useHelperApp:
- let preferredApp = aHandlerInfo.preferredApplicationHandler;
- if (this.isValidHandlerApp(preferredApp))
- return this._getIconURLForHandlerApp(preferredApp);
- break;
-
- // This should never happen, but if preferredAction is set to some weird
- // value, then fall back to the generic application icon.
- default:
- return ICON_URL_APP;
- }
- },
-
- _getIconURLForHandlerApp: function(aHandlerApp) {
- if (aHandlerApp instanceof Ci.nsILocalHandlerApp)
- return this._getIconURLForFile(aHandlerApp.executable);
-
- if (aHandlerApp instanceof Ci.nsIWebHandlerApp)
- return this._getIconURLForWebApp(aHandlerApp.uriTemplate);
-
- if (aHandlerApp instanceof Ci.nsIWebContentHandlerInfo)
- return this._getIconURLForWebApp(aHandlerApp.uri)
-
- // We know nothing about other kinds of handler apps.
- return "";
- },
-
- _getIconURLForFile: function(aFile) {
- var fph = this._ioSvc.getProtocolHandler("file").
- QueryInterface(Ci.nsIFileProtocolHandler);
- var urlSpec = fph.getURLSpecFromFile(aFile);
-
- return "moz-icon://" + urlSpec + "?size=16";
- },
-
- _getIconURLForWebApp: function(aWebAppURITemplate) {
- var uri = this._ioSvc.newURI(aWebAppURITemplate, null, null);
-
- // Unfortunately we can't use the favicon service to get the favicon,
- // because the service looks for a record with the exact URL we give it, and
- // users won't have such records for URLs they don't visit, and users won't
- // visit the handler's URL template, they'll only visit URLs derived from
- // that template (i.e. with %s in the template replaced by the URL of the
- // content being handled).
-
- if (/^https?$/.test(uri.scheme) && this._prefSvc.getBoolPref("browser.chrome.favicons"))
- return uri.prePath + "/favicon.ico";
-
- return "";
- },
-
- _getIconURLForSystemDefault: function(aHandlerInfo) {
- // Handler info objects for MIME types on some OSes implement a property bag
- // interface from which we can get an icon for the default app, so if we're
- // dealing with a MIME type on one of those OSes, then try to get the icon.
- if ("wrappedHandlerInfo" in aHandlerInfo) {
- let wrappedHandlerInfo = aHandlerInfo.wrappedHandlerInfo;
-
- if (wrappedHandlerInfo instanceof Ci.nsIMIMEInfo &&
- wrappedHandlerInfo instanceof Ci.nsIPropertyBag) {
- try {
- let url = wrappedHandlerInfo.getProperty("defaultApplicationIconURL");
- if (url)
- return url + "?size=16";
- }
- catch(ex) {}
- }
- }
-
- // If this isn't a MIME type object on an OS that supports retrieving
- // the icon, or if we couldn't retrieve the icon for some other reason,
- // then use a generic icon.
- return ICON_URL_APP;
- }
-
-};
diff --git a/components/preferences/applications.xul b/components/preferences/applications.xul
deleted file mode 100644
index 2e6fa54..0000000
--- a/components/preferences/applications.xul
+++ /dev/null
@@ -1,99 +0,0 @@
-<?xml version="1.0"?>
-
-<!-- -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- -->
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!DOCTYPE overlay [
- <!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
- <!ENTITY % applicationsDTD SYSTEM "chrome://browser/locale/preferences/applications.dtd">
- %brandDTD;
- %applicationsDTD;
-]>
-
-<overlay id="ApplicationsPaneOverlay"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-
- <prefpane id="paneApplications"
- onpaneload="gApplicationsPane.init();"
- flex="1"
- helpTopic="prefs-applications">
-
- <preferences id="feedsPreferences">
- <preference id="browser.feeds.handler"
- name="browser.feeds.handler"
- type="string"/>
- <preference id="browser.feeds.handler.default"
- name="browser.feeds.handler.default"
- type="string"/>
- <preference id="browser.feeds.handlers.application"
- name="browser.feeds.handlers.application"
- type="file"/>
- <preference id="browser.feeds.handlers.webservice"
- name="browser.feeds.handlers.webservice"
- type="string"/>
-
- <preference id="browser.videoFeeds.handler"
- name="browser.videoFeeds.handler"
- type="string"/>
- <preference id="browser.videoFeeds.handler.default"
- name="browser.videoFeeds.handler.default"
- type="string"/>
- <preference id="browser.videoFeeds.handlers.application"
- name="browser.videoFeeds.handlers.application"
- type="file"/>
- <preference id="browser.videoFeeds.handlers.webservice"
- name="browser.videoFeeds.handlers.webservice"
- type="string"/>
-
- <preference id="browser.audioFeeds.handler"
- name="browser.audioFeeds.handler"
- type="string"/>
- <preference id="browser.audioFeeds.handler.default"
- name="browser.audioFeeds.handler.default"
- type="string"/>
- <preference id="browser.audioFeeds.handlers.application"
- name="browser.audioFeeds.handlers.application"
- type="file"/>
- <preference id="browser.audioFeeds.handlers.webservice"
- name="browser.audioFeeds.handlers.webservice"
- type="string"/>
-
- <preference id="pref.downloads.disable_button.edit_actions"
- name="pref.downloads.disable_button.edit_actions"
- type="bool"/>
- </preferences>
-
- <script type="application/javascript" src="chrome://browser/content/preferences/applications.js"/>
-
- <keyset>
- <key key="&focusSearch1.key;" modifiers="accel" oncommand="gApplicationsPane.focusFilterBox();"/>
- <key key="&focusSearch2.key;" modifiers="accel" oncommand="gApplicationsPane.focusFilterBox();"/>
- </keyset>
-
- <hbox>
- <textbox id="filter" flex="1"
- type="search"
- placeholder="&filter.emptytext;"
- aria-controls="handlersView"
- oncommand="gApplicationsPane.filter();"/>
- </hbox>
-
- <separator class="thin"/>
-
- <richlistbox id="handlersView" orient="vertical" persist="lastSelectedType"
- preference="pref.downloads.disable_button.edit_actions"
- onselect="gApplicationsPane.onSelectionChanged();">
- <listheader equalsize="always" style="border: 0; padding: 0; -moz-appearance: none;">
- <treecol id="typeColumn" label="&typeColumn.label;" value="type"
- accesskey="&typeColumn.accesskey;" persist="sortDirection"
- flex="1" onclick="gApplicationsPane.sort(event);"
- sortDirection="ascending"/>
- <treecol id="actionColumn" label="&actionColumn2.label;" value="action"
- accesskey="&actionColumn2.accesskey;" persist="sortDirection"
- flex="1" onclick="gApplicationsPane.sort(event);"/>
- </listheader>
- </richlistbox>
- </prefpane>
-</overlay>
diff --git a/components/preferences/colors.xul b/components/preferences/colors.xul
deleted file mode 100644
index f2109ae..0000000
--- a/components/preferences/colors.xul
+++ /dev/null
@@ -1,102 +0,0 @@
-<?xml version="1.0"?>
-
-# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
-#ifdef XP_MACOSX
-<?xml-stylesheet href="chrome://browser/skin/preferences/preferences.css"?>
-#endif
-
-<!DOCTYPE prefwindow SYSTEM "chrome://browser/locale/preferences/colors.dtd" >
-
-<prefwindow id="ColorsDialog" type="child"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- title="&colorsDialog.title;"
- dlgbuttons="accept,cancel,help"
- ondialoghelp="openPrefsHelp()"
-#ifdef XP_MACOSX
- style="width: &window.macWidth; !important;">
-#else
- style="width: &window.width; !important;">
-#endif
-
- <script type="application/javascript" src="chrome://browser/content/utilityOverlay.js"/>
- <prefpane id="ColorsDialogPane"
- helpTopic="prefs-fonts-and-colors">
-
- <preferences>
- <preference id="browser.display.document_color_use" name="browser.display.document_color_use" type="int"/>
- <preference id="browser.anchor_color" name="browser.anchor_color" type="string"/>
- <preference id="browser.visited_color" name="browser.visited_color" type="string"/>
- <preference id="browser.underline_anchors" name="browser.underline_anchors" type="bool"/>
- <preference id="browser.display.foreground_color" name="browser.display.foreground_color" type="string"/>
- <preference id="browser.display.background_color" name="browser.display.background_color" type="string"/>
- <preference id="browser.display.use_system_colors" name="browser.display.use_system_colors" type="bool"/>
- </preferences>
-
- <hbox>
- <groupbox flex="1">
- <caption label="&color;"/>
- <hbox align="center">
- <label value="&textColor.label;" accesskey="&textColor.accesskey;" control="foregroundtextmenu"/>
- <spacer flex="1"/>
- <colorpicker type="button" id="foregroundtextmenu" palettename="standard"
- preference="browser.display.foreground_color"/>
- </hbox>
- <hbox align="center" style="margin-top: 5px">
- <label value="&backgroundColor.label;" accesskey="&backgroundColor.accesskey;" control="backgroundmenu"/>
- <spacer flex="1"/>
- <colorpicker type="button" id="backgroundmenu" palettename="standard"
- preference="browser.display.background_color"/>
- </hbox>
- <separator class="thin"/>
- <hbox align="center">
- <checkbox id="browserUseSystemColors" label="&useSystemColors.label;" accesskey="&useSystemColors.accesskey;"
- preference="browser.display.use_system_colors"/>
- </hbox>
- </groupbox>
-
- <groupbox flex="1">
- <caption label="&links;"/>
- <hbox align="center">
- <label value="&linkColor.label;" accesskey="&linkColor.accesskey;" control="unvisitedlinkmenu"/>
- <spacer flex="1"/>
- <colorpicker type="button" id="unvisitedlinkmenu" palettename="standard"
- preference="browser.anchor_color"/>
- </hbox>
- <hbox align="center" style="margin-top: 5px">
- <label value="&visitedLinkColor.label;" accesskey="&visitedLinkColor.accesskey;" control="visitedlinkmenu"/>
- <spacer flex="1"/>
- <colorpicker type="button" id="visitedlinkmenu" palettename="standard"
- preference="browser.visited_color"/>
- </hbox>
- <separator class="thin"/>
- <hbox align="center">
- <checkbox id="browserUnderlineAnchors" label="&underlineLinks.label;" accesskey="&underlineLinks.accesskey;"
- preference="browser.underline_anchors"/>
- </hbox>
- </groupbox>
- </hbox>
-#ifdef XP_WIN
- <vbox align="start">
-#else
- <vbox>
-#endif
- <label accesskey="&overridePageColors.accesskey;"
- control="useDocumentColors">&overridePageColors.label;</label>
- <menulist id="useDocumentColors" preference="browser.display.document_color_use">
- <menupopup>
- <menuitem label="&overridePageColors.always.label;"
- value="2" id="documentColorAlways"/>
- <menuitem label="&overridePageColors.auto.label;"
- value="0" id="documentColorAutomatic"/>
- <menuitem label="&overridePageColors.never.label;"
- value="1" id="documentColorNever"/>
- </menupopup>
- </menulist>
- </vbox>
- </prefpane>
-</prefwindow>
diff --git a/components/preferences/connection.js b/components/preferences/connection.js
deleted file mode 100644
index da038c9..0000000
--- a/components/preferences/connection.js
+++ /dev/null
@@ -1,200 +0,0 @@
-/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-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"];
- 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;
- }
- }
-
- this.sanitizeNoProxiesPref();
-
- 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 autologinProxyPref = document.getElementById("signon.autologin.proxy");
- autologinProxyPref.disabled = proxyTypePref.value == 0;
-
- var noProxiesPref = document.getElementById("network.proxy.no_proxies_on");
- noProxiesPref.disabled = proxyTypePref.value == 0;
-
- var autoconfigURLPref = document.getElementById("network.proxy.autoconfig_url");
- autoconfigURLPref.disabled = proxyTypePref.value != 2;
-
- this.updateReloadButton();
- },
-
- updateDNSPref: function ()
- {
- var socksVersionPref = document.getElementById("network.proxy.socks_version");
- var socksDNSPref = document.getElementById("network.proxy.socks_remote_dns");
- var proxyTypePref = document.getElementById("network.proxy.type");
- var isDefinitelySocks4 = !socksVersionPref.disabled && socksVersionPref.value == 4;
- socksDNSPref.disabled = (isDefinitelySocks4 || proxyTypePref.value == 0);
- return undefined;
- },
-
- 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"];
- 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;
- this.updateDNSPref();
- 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) {}
- },
-
- sanitizeNoProxiesPref: function()
- {
- var noProxiesPref = document.getElementById("network.proxy.no_proxies_on");
- // replace substrings of ; and \n with commas if they're neither immediately
- // preceded nor followed by a valid separator character
- noProxiesPref.value = noProxiesPref.value.replace(/([^, \n;])[;\n]+(?![,\n;])/g, '$1,');
- // replace any remaining ; and \n since some may follow commas, etc.
- noProxiesPref.value = noProxiesPref.value.replace(/[;\n]/g, '');
- },
-
- 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;
- }
-};
diff --git a/components/preferences/connection.xul b/components/preferences/connection.xul
deleted file mode 100644
index e6079dd..0000000
--- a/components/preferences/connection.xul
+++ /dev/null
@@ -1,164 +0,0 @@
-<?xml version="1.0"?>
-
-# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-<!DOCTYPE prefwindow SYSTEM "chrome://browser/locale/preferences/connection.dtd">
-
-<?xml-stylesheet href="chrome://global/skin/"?>
-
-<prefwindow id="ConnectionsDialog" type="child"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- title="&connectionsDialog.title;"
- dlgbuttons="accept,cancel,help"
- onbeforeaccept="return gConnectionsDialog.beforeAccept();"
- onload="gConnectionsDialog.checkForSystemProxy();"
- ondialoghelp="openPrefsHelp()"
-#ifdef XP_MACOSX
- style="width: &window.macWidth; !important;">
-#else
- style="width: &window.width; !important;">
-#endif
-
- <script type="application/javascript" src="chrome://browser/content/utilityOverlay.js"/>
-
- <prefpane id="ConnectionsDialogPane"
- helpTopic="prefs-connection-settings">
-
- <preferences>
- <preference id="network.proxy.type" name="network.proxy.type" type="int"
- onchange="gConnectionsDialog.proxyTypeChanged();"/>
- <preference id="network.proxy.http" name="network.proxy.http" type="string"/>
- <preference id="network.proxy.http_port" name="network.proxy.http_port" type="int"/>
- <preference id="network.proxy.ftp" name="network.proxy.ftp" type="string"/>
- <preference id="network.proxy.ftp_port" name="network.proxy.ftp_port" type="int"/>
- <preference id="network.proxy.ssl" name="network.proxy.ssl" type="string"/>
- <preference id="network.proxy.ssl_port" name="network.proxy.ssl_port" type="int"/>
- <preference id="network.proxy.socks" name="network.proxy.socks" type="string"/>
- <preference id="network.proxy.socks_port" name="network.proxy.socks_port" type="int"/>
- <preference id="network.proxy.socks_version" name="network.proxy.socks_version" type="int"
- onchange="gConnectionsDialog.updateDNSPref();"/>
- <preference id="network.proxy.socks_remote_dns" name="network.proxy.socks_remote_dns" type="bool"/>
- <preference id="network.proxy.no_proxies_on" name="network.proxy.no_proxies_on" type="string"/>
- <preference id="network.proxy.autoconfig_url" name="network.proxy.autoconfig_url" type="string"/>
- <preference id="network.proxy.share_proxy_settings" name="network.proxy.share_proxy_settings" type="bool"/>
- <preference id="signon.autologin.proxy" name="signon.autologin.proxy" type="bool"/>
- <preference id="pref.advanced.proxies.disable_button.reload"
- name="pref.advanced.proxies.disable_button.reload" type="bool"/>
- <preference id="network.proxy.backup.ftp" name="network.proxy.backup.ftp" type="string"/>
- <preference id="network.proxy.backup.ftp_port" name="network.proxy.backup.ftp_port" type="int"/>
- <preference id="network.proxy.backup.ssl" name="network.proxy.backup.ssl" type="string"/>
- <preference id="network.proxy.backup.ssl_port" name="network.proxy.backup.ssl_port" type="int"/>
- <preference id="network.proxy.backup.socks" name="network.proxy.backup.socks" type="string"/>
- <preference id="network.proxy.backup.socks_port" name="network.proxy.backup.socks_port" type="int"/>
- </preferences>
-
- <script type="application/javascript" src="chrome://browser/content/preferences/connection.js"/>
-
- <stringbundle id="preferencesBundle" src="chrome://browser/locale/preferences/preferences.properties"/>
-
- <groupbox>
- <caption label="&proxyTitle.label;"/>
-
- <radiogroup id="networkProxyType" preference="network.proxy.type"
- onsyncfrompreference="return gConnectionsDialog.readProxyType();">
- <radio value="0" label="&noProxyTypeRadio.label;" accesskey="&noProxyTypeRadio.accesskey;"/>
- <radio value="4" label="&WPADTypeRadio.label;" accesskey="&WPADTypeRadio.accesskey;"/>
- <radio value="5" label="&systemTypeRadio.label;" accesskey="&systemTypeRadio.accesskey;" id="systemPref" hidden="true"/>
- <radio value="1" label="&manualTypeRadio.label;" accesskey="&manualTypeRadio.accesskey;"/>
- <grid class="indent" flex="1">
- <columns>
- <column/>
- <column flex="1"/>
- </columns>
- <rows>
- <row align="center">
- <hbox pack="end">
- <label value="&http.label;" accesskey="&http.accesskey;" control="networkProxyHTTP"/>
- </hbox>
- <hbox align="center">
- <textbox id="networkProxyHTTP" flex="1"
- preference="network.proxy.http" onsyncfrompreference="return gConnectionsDialog.readHTTPProxyServer();"/>
- <label value="&port.label;" accesskey="&HTTPport.accesskey;" control="networkProxyHTTP_Port"/>
- <textbox id="networkProxyHTTP_Port" type="number" max="65535" size="5"
- preference="network.proxy.http_port" onsyncfrompreference="return gConnectionsDialog.readHTTPProxyPort();"/>
- </hbox>
- </row>
- <row>
- <hbox/>
- <hbox>
- <checkbox id="shareAllProxies" label="&shareproxy.label;" accesskey="&shareproxy.accesskey;"
- preference="network.proxy.share_proxy_settings"
- onsyncfrompreference="return gConnectionsDialog.updateProtocolPrefs();"/>
- </hbox>
- </row>
- <row align="center">
- <hbox pack="end">
- <label value="&ssl.label;" accesskey="&ssl.accesskey;" control="networkProxySSL"/>
- </hbox>
- <hbox align="center">
- <textbox id="networkProxySSL" flex="1" preference="network.proxy.ssl"
- onsyncfrompreference="return gConnectionsDialog.readProxyProtocolPref('ssl', false);"/>
- <label value="&port.label;" accesskey="&SSLport.accesskey;" control="networkProxySSL_Port"/>
- <textbox id="networkProxySSL_Port" type="number" max="65535" size="5" preference="network.proxy.ssl_port"
- onsyncfrompreference="return gConnectionsDialog.readProxyProtocolPref('ssl', true);"/>
- </hbox>
- </row>
- <row align="center">
- <hbox pack="end">
- <label value="&ftp.label;" accesskey="&ftp.accesskey;" control="networkProxyFTP"/>
- </hbox>
- <hbox align="center">
- <textbox id="networkProxyFTP" flex="1" preference="network.proxy.ftp"
- onsyncfrompreference="return gConnectionsDialog.readProxyProtocolPref('ftp', false);"/>
- <label value="&port.label;" accesskey="&FTPport.accesskey;" control="networkProxyFTP_Port"/>
- <textbox id="networkProxyFTP_Port" type="number" max="65535" size="5" preference="network.proxy.ftp_port"
- onsyncfrompreference="return gConnectionsDialog.readProxyProtocolPref('ftp', true);"/>
- </hbox>
- </row>
- <row align="center">
- <hbox pack="end">
- <label value="&socks.label;" accesskey="&socks.accesskey;" control="networkProxySOCKS"/>
- </hbox>
- <hbox align="center">
- <textbox id="networkProxySOCKS" flex="1" preference="network.proxy.socks"
- onsyncfrompreference="return gConnectionsDialog.readProxyProtocolPref('socks', false);"/>
- <label value="&port.label;" accesskey="&SOCKSport.accesskey;" control="networkProxySOCKS_Port"/>
- <textbox id="networkProxySOCKS_Port" type="number" max="65535" size="5" preference="network.proxy.socks_port"
- onsyncfrompreference="return gConnectionsDialog.readProxyProtocolPref('socks', true);"/>
- </hbox>
- </row>
- <row>
- <spacer/>
- <radiogroup id="networkProxySOCKSVersion" orient="horizontal"
- preference="network.proxy.socks_version">
- <radio id="networkProxySOCKSVersion4" value="4" label="&socks4.label;" accesskey="&socks4.accesskey;"/>
- <radio id="networkProxySOCKSVersion5" value="5" label="&socks5.label;" accesskey="&socks5.accesskey;"/>
- </radiogroup>
- </row>
- </rows>
- </grid>
- <radio value="2" label="&autoTypeRadio.label;" accesskey="&autoTypeRadio.accesskey;"/>
- <hbox class="indent" flex="1" align="center">
- <textbox id="networkProxyAutoconfigURL" flex="1" preference="network.proxy.autoconfig_url"
- oninput="gConnectionsDialog.updateReloadButton();"/>
- <button id="autoReload" icon="refresh"
- label="&reload.label;" accesskey="&reload.accesskey;"
- oncommand="gConnectionsDialog.reloadPAC();"
- preference="pref.advanced.proxies.disable_button.reload"/>
- </hbox>
- </radiogroup>
- <separator class="thin"/>
- <label value="&noproxy.label;" accesskey="&noproxy.accesskey;" control="networkProxyNone"/>
- <textbox id="networkProxyNone" preference="network.proxy.no_proxies_on" multiline="true" rows="2"/>
- <label value="&noproxyExplain.label;" control="networkProxyNone"/>
- <checkbox id="autologinProxy" preference="signon.autologin.proxy"
- label="&autologinproxy.label;" accesskey="&autologinproxy.accesskey;"
- tooltiptext="&autologinproxy.tooltip;"/>
- <checkbox id="networkProxySOCKSRemoteDNS" preference="network.proxy.socks_remote_dns"
- label="&socksRemoteDNS.label;" accesskey="&socksRemoteDNS.accesskey;"/>
- </groupbox>
- </prefpane>
-</prefwindow>
diff --git a/components/preferences/content.js b/components/preferences/content.js
deleted file mode 100644
index 5ae84c2..0000000
--- a/components/preferences/content.js
+++ /dev/null
@@ -1,187 +0,0 @@
-/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-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;
- },
-
- /**
- * Utility function to enable/disable the checkboxes for MSE options depending
- * on the value of media.mediasource.enabled.
- */
- updateMSE: function ()
- {
- var checkboxMSEMP4 = document.getElementById('videoMSEMP4');
- var checkboxMSEWebM = document.getElementById('videoMSEWebM');
- var preference = document.getElementById('media.mediasource.enabled');
- checkboxMSEMP4.disabled = preference.value != true;
- checkboxMSEWebM.disabled = preference.value != true;
- },
-
- // BEGIN UI CODE
-
- /*
- * Preferences:
- *
- * dom.disable_open_during_load
- * - true if popups are blocked by default, false otherwise
- */
-
- // POP-UPS
-
- /**
- * Displays the popup exceptions dialog where specific site popup preferences
- * can be set.
- */
- showPopupExceptions: function ()
- {
- var bundlePreferences = document.getElementById("bundlePreferences");
- var params = { blockVisible: false, sessionVisible: false, allowVisible: true, prefilledHost: "", permissionType: "popup" };
- params.windowTitle = bundlePreferences.getString("popuppermissionstitle");
- params.introText = bundlePreferences.getString("popuppermissionstext");
- document.documentElement.openWindow("Browser:Permissions",
- "chrome://browser/content/preferences/permissions.xul",
- "", params);
- },
-
-
- // 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);
- }
-};
diff --git a/components/preferences/content.xul b/components/preferences/content.xul
deleted file mode 100644
index 23d942e..0000000
--- a/components/preferences/content.xul
+++ /dev/null
@@ -1,171 +0,0 @@
-<?xml version="1.0"?>
-
-<!-- -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -->
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!DOCTYPE overlay [
- <!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
- <!ENTITY % contentDTD SYSTEM "chrome://browser/locale/preferences/content.dtd">
- %brandDTD;
- %contentDTD;
-]>
-
-<overlay id="ContentPaneOverlay"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-
- <prefpane id="paneContent"
- onpaneload="gContentPane.init();"
- helpTopic="prefs-content">
-
- <preferences id="contentPreferences">
- <!--XXX buttons prefs -->
-
- <!-- POPUPS, IMAGES -->
- <preference id="dom.disable_open_during_load" name="dom.disable_open_during_load" type="bool"/>
- <preference id="permissions.default.image" name="permissions.default.image" type="int"/>
-
- <!-- FONTS -->
- <preference id="font.language.group"
- name="font.language.group"
- type="wstring"
- onchange="gContentPane._rebuildFonts();"/>
-
- <!-- VIDEO -->
- <preference id="media.mediasource.enabled" name="media.mediasource.enabled" type="bool"/>
- <preference id="media.mediasource.mp4.enabled" name="media.mediasource.mp4.enabled" type="bool"/>
- <preference id="media.mediasource.webm.enabled" name="media.mediasource.webm.enabled" type="bool"/>
-
- </preferences>
-
- <script type="application/javascript" src="chrome://mozapps/content/preferences/fontbuilder.js"/>
- <script type="application/javascript" src="chrome://browser/content/preferences/content.js"/>
-
- <stringbundle id="bundlePreferences" src="chrome://browser/locale/preferences/preferences.properties"/>
-
- <!-- various checkboxes, font-fu -->
- <groupbox id="miscGroup">
- <grid id="contentGrid">
- <columns>
- <column flex="1"/>
- <column/>
- </columns>
- <rows id="contentRows-1">
- <row id="popupPolicyRow">
- <vbox align="start">
- <checkbox id="popupPolicy" preference="dom.disable_open_during_load"
- label="&blockPopups.label;" accesskey="&blockPopups.accesskey;"
- onsyncfrompreference="return gContentPane.updateButtons('popupPolicyButton',
- 'dom.disable_open_during_load');"/>
- </vbox>
- <button id="popupPolicyButton" label="&popupExceptions.label;"
- oncommand="gContentPane.showPopupExceptions();"
- accesskey="&popupExceptions.accesskey;"/>
- </row>
- <row id="enableImagesRow">
- <hbox align="center">
- <label id="loadImages" control="loadImages-menu">&loadImages.label;</label>
- <menulist id="loadImages-menu" preference="permissions.default.image" sizetopopup="always">
- <menupopup>
- <menuitem label="&loadImages.always;" value="1" />
- <menuitem label="&loadImages.never;" value="2" />
- <menuitem label="&loadImages.no3rdparty;" value="3" />
- </menupopup>
- </menulist>
- </hbox>
- </row>
- </rows>
- </grid>
- </groupbox>
-
- <!-- Fonts and Colors -->
- <groupbox id="fontsGroup">
- <caption label="&fontsAndColors.label;"/>
-
- <grid id="fontsGrid">
- <columns>
- <column flex="1"/>
- <column/>
- </columns>
- <rows id="fontsRows">
- <row id="fontRow">
- <hbox align="center">
- <label control="defaultFont" accesskey="&defaultFont.accesskey;">&defaultFont.label;</label>
- <menulist id="defaultFont" flex="1"/>
- <label control="defaultFontSize" accesskey="&defaultSize.accesskey;">&defaultSize.label;</label>
- <menulist id="defaultFontSize">
- <menupopup>
- <menuitem value="9" label="9"/>
- <menuitem value="10" label="10"/>
- <menuitem value="11" label="11"/>
- <menuitem value="12" label="12"/>
- <menuitem value="13" label="13"/>
- <menuitem value="14" label="14"/>
- <menuitem value="15" label="15"/>
- <menuitem value="16" label="16"/>
- <menuitem value="17" label="17"/>
- <menuitem value="18" label="18"/>
- <menuitem value="20" label="20"/>
- <menuitem value="22" label="22"/>
- <menuitem value="24" label="24"/>
- <menuitem value="26" label="26"/>
- <menuitem value="28" label="28"/>
- <menuitem value="30" label="30"/>
- <menuitem value="32" label="32"/>
- <menuitem value="34" label="34"/>
- <menuitem value="36" label="36"/>
- <menuitem value="40" label="40"/>
- <menuitem value="44" label="44"/>
- <menuitem value="48" label="48"/>
- <menuitem value="56" label="56"/>
- <menuitem value="64" label="64"/>
- <menuitem value="72" label="72"/>
- </menupopup>
- </menulist>
- </hbox>
- <button id="advancedFonts" icon="select-font"
- label="&advancedFonts.label;"
- accesskey="&advancedFonts.accesskey;"
- oncommand="gContentPane.configureFonts();"/>
- </row>
- <row id="colorsRow">
- <hbox/>
- <button id="colors" icon="select-color"
- label="&colors.label;"
- accesskey="&colors.accesskey;"
- oncommand="gContentPane.configureColors();"/>
- </row>
- </rows>
- </grid>
- </groupbox>
-
- <!-- Languages -->
- <groupbox id="languagesGroup">
- <caption label="&languages.label;"/>
-
- <hbox id="languagesBox" align="center">
- <description flex="1" control="chooseLanguage">&chooseLanguage.label;</description>
- <button id="chooseLanguage"
- label="&chooseButton.label;"
- accesskey="&chooseButton.accesskey;"
- oncommand="gContentPane.showLanguages();"/>
- </hbox>
- </groupbox>
-
- <!-- Video -->
- <groupbox id="videoGroup">
- <caption label="&video.label;"/>
-
- <checkbox id="videoMSE" preference="media.mediasource.enabled"
- label="&videoMSE.label;" accesskey="&videoMSE.accesskey;"
- onsyncfrompreference="gContentPane.updateMSE();"/>
- <checkbox class="indent" id="videoMSEMP4" preference="media.mediasource.mp4.enabled"
- label="&videoMSEMP4.label;" accesskey="&videoMSEMP4.accesskey;"/>
- <checkbox class="indent" id="videoMSEWebM" preference="media.mediasource.webm.enabled"
- label="&videoMSEWebM.label;" accesskey="&videoMSEWebM.accesskey;"/>
- </groupbox>
-
- </prefpane>
-
-</overlay>
diff --git a/components/preferences/cookies.js b/components/preferences/cookies.js
deleted file mode 100644
index 4fa47ee..0000000
--- a/components/preferences/cookies.js
+++ /dev/null
@@ -1,948 +0,0 @@
-/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-const nsICookie = Components.interfaces.nsICookie;
-
-Components.utils.import("resource://gre/modules/PluralForm.jsm");
-
-var gCookiesWindow = {
- _cm : Components.classes["@mozilla.org/cookiemanager;1"]
- .getService(Components.interfaces.nsICookieManager),
- _ds : Components.classes["@mozilla.org/intl/scriptabledateformat;1"]
- .getService(Components.interfaces.nsIScriptableDateFormat),
- _hosts : {},
- _hostOrder : [],
- _tree : null,
- _bundle : null,
-
- init: function () {
- var os = Components.classes["@mozilla.org/observer-service;1"]
- .getService(Components.interfaces.nsIObserverService);
- os.addObserver(this, "cookie-changed", false);
- os.addObserver(this, "perm-changed", false);
-
- this._bundle = document.getElementById("bundlePreferences");
- this._tree = document.getElementById("cookiesList");
-
- let removeAllCookies = document.getElementById("removeAllCookies");
- removeAllCookies.setAttribute("accesskey", this._bundle.getString("removeAllCookies.accesskey"));
- let removeSelectedCookies = document.getElementById("removeSelectedCookies");
- removeSelectedCookies.setAttribute("accesskey", this._bundle.getString("removeSelectedCookies.accesskey"));
-
- this._populateList(true);
-
- document.getElementById("filter").focus();
- },
-
- uninit: function () {
- var os = Components.classes["@mozilla.org/observer-service;1"]
- .getService(Components.interfaces.nsIObserverService);
- os.removeObserver(this, "cookie-changed");
- os.removeObserver(this, "perm-changed");
- },
-
- _populateList: function (aInitialLoad) {
- this._loadCookies();
- this._tree.view = this._view;
- if (aInitialLoad)
- this.sort("rawHost");
- if (this._view.rowCount > 0)
- this._tree.view.selection.select(0);
-
- if (aInitialLoad) {
- if ("arguments" in window &&
- window.arguments[0] &&
- window.arguments[0].filterString)
- this.setFilter(window.arguments[0].filterString);
- }
- else {
- if (document.getElementById("filter").value != "")
- this.filter();
- }
-
- this._updateRemoveAllButton();
-
- this._saveState();
- },
-
- _cookieEquals: function (aCookieA, aCookieB, aStrippedHost) {
- return aCookieA.rawHost == aStrippedHost &&
- aCookieA.name == aCookieB.name &&
- aCookieA.path == aCookieB.path &&
- ChromeUtils.isOriginAttributesEqual(aCookieA.originAttributes,
- aCookieB.originAttributes);
- },
-
- observe: function (aCookie, aTopic, aData) {
- if (aTopic != "cookie-changed")
- return;
-
- if (aCookie instanceof Components.interfaces.nsICookie) {
- var strippedHost = this._makeStrippedHost(aCookie.host);
- if (aData == "changed")
- this._handleCookieChanged(aCookie, strippedHost);
- else if (aData == "added")
- this._handleCookieAdded(aCookie, strippedHost);
- }
- else if (aData == "cleared") {
- this._hosts = {};
- this._hostOrder = [];
-
- var oldRowCount = this._view._rowCount;
- this._view._rowCount = 0;
- this._tree.treeBoxObject.rowCountChanged(0, -oldRowCount);
- this._view.selection.clearSelection();
- this._updateRemoveAllButton();
- }
- else if (aData == "reload") {
- // first, clear any existing entries
- this.observe(aCookie, aTopic, "cleared");
-
- // then, reload the list
- this._populateList(false);
- }
-
- // We don't yet handle aData == "deleted" - it's a less common case
- // and is rather complicated as selection tracking is difficult
- },
-
- _handleCookieChanged: function (changedCookie, strippedHost) {
- var rowIndex = 0;
- var cookieItem = null;
- if (!this._view._filtered) {
- for (var i = 0; i < this._hostOrder.length; ++i) { // (var host in this._hosts) {
- ++rowIndex;
- var hostItem = this._hosts[this._hostOrder[i]]; // var hostItem = this._hosts[host];
- if (this._hostOrder[i] == strippedHost) { // host == strippedHost) {
- // Host matches, look for the cookie within this Host collection
- // and update its data
- for (var j = 0; j < hostItem.cookies.length; ++j) {
- ++rowIndex;
- var currCookie = hostItem.cookies[j];
- if (this._cookieEquals(currCookie, changedCookie, strippedHost)) {
- currCookie.value = changedCookie.value;
- currCookie.isSecure = changedCookie.isSecure;
- currCookie.isDomain = changedCookie.isDomain;
- currCookie.expires = changedCookie.expires;
- cookieItem = currCookie;
- break;
- }
- }
- }
- else if (hostItem.open)
- rowIndex += hostItem.cookies.length;
- }
- }
- else {
- // Just walk the filter list to find the item. It doesn't matter that
- // we don't update the main Host collection when we do this, because
- // when the filter is reset the Host collection is rebuilt anyway.
- for (rowIndex = 0; rowIndex < this._view._filterSet.length; ++rowIndex) {
- currCookie = this._view._filterSet[rowIndex];
- if (this._cookieEquals(currCookie, changedCookie, strippedHost)) {
- currCookie.value = changedCookie.value;
- currCookie.isSecure = changedCookie.isSecure;
- currCookie.isDomain = changedCookie.isDomain;
- currCookie.expires = changedCookie.expires;
- cookieItem = currCookie;
- break;
- }
- }
- }
-
- // Make sure the tree display is up to date...
- this._tree.treeBoxObject.invalidateRow(rowIndex);
- // ... and if the cookie is selected, update the displayed metadata too
- if (cookieItem != null && this._view.selection.currentIndex == rowIndex)
- this._updateCookieData(cookieItem);
- },
-
- _handleCookieAdded: function (changedCookie, strippedHost) {
- var rowCountImpact = 0;
- var addedHost = { value: 0 };
- this._addCookie(strippedHost, changedCookie, addedHost);
- if (!this._view._filtered) {
- // The Host collection for this cookie already exists, and it's not open,
- // so don't increment the rowCountImpact becaues the user is not going to
- // see the additional rows as they're hidden.
- if (addedHost.value || this._hosts[strippedHost].open)
- ++rowCountImpact;
- }
- else {
- // We're in search mode, and the cookie being added matches
- // the search condition, so add it to the list.
- var c = this._makeCookieObject(strippedHost, changedCookie);
- if (this._cookieMatchesFilter(c)) {
- this._view._filterSet.push(this._makeCookieObject(strippedHost, changedCookie));
- ++rowCountImpact;
- }
- }
- // Now update the tree display at the end (we could/should re run the sort
- // if any to get the position correct.)
- var oldRowCount = this._rowCount;
- this._view._rowCount += rowCountImpact;
- this._tree.treeBoxObject.rowCountChanged(oldRowCount - 1, rowCountImpact);
-
- this._updateRemoveAllButton();
- },
-
- _view: {
- _filtered : false,
- _filterSet : [],
- _filterValue: "",
- _rowCount : 0,
- _cacheValid : 0,
- _cacheItems : [],
- get rowCount() {
- return this._rowCount;
- },
-
- _getItemAtIndex: function (aIndex) {
- if (this._filtered)
- return this._filterSet[aIndex];
-
- var start = 0;
- var count = 0, hostIndex = 0;
-
- var cacheIndex = Math.min(this._cacheValid, aIndex);
- if (cacheIndex > 0) {
- var cacheItem = this._cacheItems[cacheIndex];
- start = cacheItem['start'];
- count = hostIndex = cacheItem['count'];
- }
-
- for (var i = start; i < gCookiesWindow._hostOrder.length; ++i) { // var host in gCookiesWindow._hosts) {
- var currHost = gCookiesWindow._hosts[gCookiesWindow._hostOrder[i]]; // gCookiesWindow._hosts[host];
- if (!currHost) continue;
- if (count == aIndex)
- return currHost;
- hostIndex = count;
-
- var cacheEntry = { 'start' : i, 'count' : count };
- var cacheStart = count;
-
- if (currHost.open) {
- if (count < aIndex && aIndex <= (count + currHost.cookies.length)) {
- // We are looking for an entry within this host's children,
- // enumerate them looking for the index.
- ++count;
- for (var i = 0; i < currHost.cookies.length; ++i) {
- if (count == aIndex) {
- var cookie = currHost.cookies[i];
- cookie.parentIndex = hostIndex;
- return cookie;
- }
- ++count;
- }
- }
- else {
- // A host entry was open, but we weren't looking for an index
- // within that host entry's children, so skip forward over the
- // entry's children. We need to add one to increment for the
- // host value too.
- count += currHost.cookies.length + 1;
- }
- }
- else
- ++count;
-
- for (var j = cacheStart; j < count; j++)
- this._cacheItems[j] = cacheEntry;
- this._cacheValid = count - 1;
- }
- return null;
- },
-
- _removeItemAtIndex: function (aIndex, aCount) {
- var removeCount = aCount === undefined ? 1 : aCount;
- if (this._filtered) {
- // remove the cookies from the unfiltered set so that they
- // don't reappear when the filter is changed. See bug 410863.
- for (var i = aIndex; i < aIndex + removeCount; ++i) {
- var item = this._filterSet[i];
- var parent = gCookiesWindow._hosts[item.rawHost];
- for (var j = 0; j < parent.cookies.length; ++j) {
- if (item == parent.cookies[j]) {
- parent.cookies.splice(j, 1);
- break;
- }
- }
- }
- this._filterSet.splice(aIndex, removeCount);
- return;
- }
-
- var item = this._getItemAtIndex(aIndex);
- if (!item) return;
- this._invalidateCache(aIndex - 1);
- if (item.container) {
- gCookiesWindow._hosts[item.rawHost] = null;
- } else {
- var parent = this._getItemAtIndex(item.parentIndex);
- for (var i = 0; i < parent.cookies.length; ++i) {
- var cookie = parent.cookies[i];
- if (item.rawHost == cookie.rawHost &&
- item.name == cookie.name &&
- item.path == cookie.path &&
- ChromeUtils.isOriginAttributesEqual(item.originAttributes,
- cookie.originAttributes)) {
- parent.cookies.splice(i, removeCount);
- }
- }
- }
- },
-
- _invalidateCache: function (aIndex) {
- this._cacheValid = Math.min(this._cacheValid, aIndex);
- },
-
- getCellText: function (aIndex, aColumn) {
- if (!this._filtered) {
- var item = this._getItemAtIndex(aIndex);
- if (!item)
- return "";
- if (aColumn.id == "domainCol")
- return item.rawHost;
- else if (aColumn.id == "nameCol")
- return item.name;
- }
- else {
- if (aColumn.id == "domainCol")
- return this._filterSet[aIndex].rawHost;
- else if (aColumn.id == "nameCol")
- return this._filterSet[aIndex].name;
- }
- return "";
- },
-
- _selection: null,
- get selection () { return this._selection; },
- set selection (val) { this._selection = val; return val; },
- getRowProperties: function (aIndex) { return ""; },
- getCellProperties: function (aIndex, aColumn) { return ""; },
- getColumnProperties: function (aColumn) { return ""; },
- isContainer: function (aIndex) {
- if (!this._filtered) {
- var item = this._getItemAtIndex(aIndex);
- if (!item) return false;
- return item.container;
- }
- return false;
- },
- isContainerOpen: function (aIndex) {
- if (!this._filtered) {
- var item = this._getItemAtIndex(aIndex);
- if (!item) return false;
- return item.open;
- }
- return false;
- },
- isContainerEmpty: function (aIndex) {
- if (!this._filtered) {
- var item = this._getItemAtIndex(aIndex);
- if (!item) return false;
- return item.cookies.length == 0;
- }
- return false;
- },
- isSeparator: function (aIndex) { return false; },
- isSorted: function (aIndex) { return false; },
- canDrop: function (aIndex, aOrientation) { return false; },
- drop: function (aIndex, aOrientation) {},
- getParentIndex: function (aIndex) {
- if (!this._filtered) {
- var item = this._getItemAtIndex(aIndex);
- // If an item has no parent index (i.e. it is at the top level) this
- // function MUST return -1 otherwise we will go into an infinite loop.
- // Containers are always top level items in the cookies tree, so make
- // sure to return the appropriate value here.
- if (!item || item.container) return -1;
- return item.parentIndex;
- }
- return -1;
- },
- hasNextSibling: function (aParentIndex, aIndex) {
- if (!this._filtered) {
- // |aParentIndex| appears to be bogus, but we can get the real
- // parent index by getting the entry for |aIndex| and reading the
- // parentIndex field.
- // The index of the last item in this host collection is the
- // index of the parent + the size of the host collection, and
- // aIndex has a next sibling if it is less than this value.
- var item = this._getItemAtIndex(aIndex);
- if (item) {
- if (item.container) {
- for (var i = aIndex + 1; i < this.rowCount; ++i) {
- var subsequent = this._getItemAtIndex(i);
- if (subsequent.container)
- return true;
- }
- return false;
- }
- else {
- var parent = this._getItemAtIndex(item.parentIndex);
- if (parent && parent.container)
- return aIndex < item.parentIndex + parent.cookies.length;
- }
- }
- }
- return aIndex < this.rowCount - 1;
- },
- hasPreviousSibling: function (aIndex) {
- if (!this._filtered) {
- var item = this._getItemAtIndex(aIndex);
- if (!item) return false;
- var parent = this._getItemAtIndex(item.parentIndex);
- if (parent && parent.container)
- return aIndex > item.parentIndex + 1;
- }
- return aIndex > 0;
- },
- getLevel: function (aIndex) {
- if (!this._filtered) {
- var item = this._getItemAtIndex(aIndex);
- if (!item) return 0;
- return item.level;
- }
- return 0;
- },
- getImageSrc: function (aIndex, aColumn) {},
- getProgressMode: function (aIndex, aColumn) {},
- getCellValue: function (aIndex, aColumn) {},
- setTree: function (aTree) {},
- toggleOpenState: function (aIndex) {
- if (!this._filtered) {
- var item = this._getItemAtIndex(aIndex);
- if (!item) return;
- this._invalidateCache(aIndex);
- var multiplier = item.open ? -1 : 1;
- var delta = multiplier * item.cookies.length;
- this._rowCount += delta;
- item.open = !item.open;
- gCookiesWindow._tree.treeBoxObject.rowCountChanged(aIndex + 1, delta);
- gCookiesWindow._tree.treeBoxObject.invalidateRow(aIndex);
- }
- },
- cycleHeader: function (aColumn) {},
- selectionChanged: function () {},
- cycleCell: function (aIndex, aColumn) {},
- isEditable: function (aIndex, aColumn) {
- return false;
- },
- isSelectable: function (aIndex, aColumn) {
- return false;
- },
- setCellValue: function (aIndex, aColumn, aValue) {},
- setCellText: function (aIndex, aColumn, aValue) {},
- performAction: function (aAction) {},
- performActionOnRow: function (aAction, aIndex) {},
- performActionOnCell: function (aAction, aindex, aColumn) {}
- },
-
- _makeStrippedHost: function (aHost) {
- var formattedHost = aHost.charAt(0) == "." ? aHost.substring(1, aHost.length) : aHost;
- return formattedHost.substring(0, 4) == "www." ? formattedHost.substring(4, formattedHost.length) : formattedHost;
- },
-
- _addCookie: function (aStrippedHost, aCookie, aHostCount) {
- if (!(aStrippedHost in this._hosts) || !this._hosts[aStrippedHost]) {
- this._hosts[aStrippedHost] = { cookies : [],
- rawHost : aStrippedHost,
- level : 0,
- open : false,
- container : true };
- this._hostOrder.push(aStrippedHost);
- ++aHostCount.value;
- }
-
- var c = this._makeCookieObject(aStrippedHost, aCookie);
- this._hosts[aStrippedHost].cookies.push(c);
- },
-
- _makeCookieObject: function (aStrippedHost, aCookie) {
- var host = aCookie.host;
- var formattedHost = host.charAt(0) == "." ? host.substring(1, host.length) : host;
- var c = { name : aCookie.name,
- value : aCookie.value,
- isDomain : aCookie.isDomain,
- host : aCookie.host,
- rawHost : aStrippedHost,
- path : aCookie.path,
- isSecure : aCookie.isSecure,
- expires : aCookie.expires,
- level : 1,
- container : false,
- originAttributes: aCookie.originAttributes };
- return c;
- },
-
- _loadCookies: function () {
- var e = this._cm.enumerator;
- var hostCount = { value: 0 };
- this._hosts = {};
- this._hostOrder = [];
- while (e.hasMoreElements()) {
- var cookie = e.getNext();
- if (cookie && cookie instanceof Components.interfaces.nsICookie) {
- var strippedHost = this._makeStrippedHost(cookie.host);
- this._addCookie(strippedHost, cookie, hostCount);
- }
- else
- break;
- }
- this._view._rowCount = hostCount.value;
- },
-
- formatExpiresString: function (aExpires) {
- if (aExpires) {
- var date = new Date(1000 * aExpires);
- return this._ds.FormatDateTime("", this._ds.dateFormatLong,
- this._ds.timeFormatSeconds,
- date.getFullYear(),
- date.getMonth() + 1,
- date.getDate(),
- date.getHours(),
- date.getMinutes(),
- date.getSeconds());
- }
- return this._bundle.getString("expireAtEndOfSession");
- },
-
- _updateCookieData: function (aItem) {
- var seln = this._view.selection;
- var ids = ["name", "value", "host", "path", "isSecure", "expires"];
- var properties;
-
- if (aItem && !aItem.container && seln.count > 0) {
- properties = { name: aItem.name, value: aItem.value, host: aItem.host,
- path: aItem.path, expires: this.formatExpiresString(aItem.expires),
- isDomain: aItem.isDomain ? this._bundle.getString("domainColon")
- : this._bundle.getString("hostColon"),
- isSecure: aItem.isSecure ? this._bundle.getString("forSecureOnly")
- : this._bundle.getString("forAnyConnection") };
- for (var i = 0; i < ids.length; ++i)
- document.getElementById(ids[i]).disabled = false;
- }
- else {
- var noneSelected = this._bundle.getString("noCookieSelected");
- properties = { name: noneSelected, value: noneSelected, host: noneSelected,
- path: noneSelected, expires: noneSelected,
- isSecure: noneSelected };
- for (i = 0; i < ids.length; ++i)
- document.getElementById(ids[i]).disabled = true;
- }
- for (var property in properties)
- document.getElementById(property).value = properties[property];
- },
-
- onCookieSelected: function () {
- var properties, item;
- var seln = this._tree.view.selection;
- var hasRows = this._tree.view.rowCount > 0;
- var hasSelection = seln.count > 0;
- if (!this._view._filtered)
- item = this._view._getItemAtIndex(seln.currentIndex);
- else
- item = this._view._filterSet[seln.currentIndex];
-
- this._updateCookieData(item);
-
- var rangeCount = seln.getRangeCount();
- var selectedCookieCount = 0;
- for (var i = 0; i < rangeCount; ++i) {
- var min = {}; var max = {};
- seln.getRangeAt(i, min, max);
- for (var j = min.value; j <= max.value; ++j) {
- item = this._view._getItemAtIndex(j);
- if (!item) continue;
- if (item.container && !item.open)
- selectedCookieCount += item.cookies.length;
- else if (!item.container)
- ++selectedCookieCount;
- }
- }
- var item = this._view._getItemAtIndex(seln.currentIndex);
- if (item && seln.count == 1 && item.container && item.open)
- selectedCookieCount += 2;
-
- let buttonLabel = this._bundle.getString("removeSelectedCookies.label");
- let removeSelectedCookies = document.getElementById("removeSelectedCookies");
- removeSelectedCookies.label = PluralForm.get(selectedCookieCount, buttonLabel)
- .replace("#1", selectedCookieCount);
-
- removeSelectedCookies.disabled = !hasRows || !hasSelection;
- },
-
- performDeletion: function gCookiesWindow_performDeletion(deleteItems) {
- var psvc = Components.classes["@mozilla.org/preferences-service;1"]
- .getService(Components.interfaces.nsIPrefBranch);
- var blockFutureCookies = false;
- if (psvc.prefHasUserValue("network.cookie.blockFutureCookies"))
- blockFutureCookies = psvc.getBoolPref("network.cookie.blockFutureCookies");
- for (var i = 0; i < deleteItems.length; ++i) {
- var item = deleteItems[i];
- this._cm.remove(item.host, item.name, item.path,
- blockFutureCookies, item.originAttributes);
- }
- },
-
- deleteCookie: function () {
- // Selection Notes
- // - Selection always moves to *NEXT* adjacent item unless item
- // is last child at a given level in which case it moves to *PREVIOUS*
- // item
- //
- // Selection Cases (Somewhat Complicated)
- //
- // 1) Single cookie selected, host has single child
- // v cnn.com
- // //// cnn.com ///////////// goksdjf@ ////
- // > atwola.com
- //
- // Before SelectedIndex: 1 Before RowCount: 3
- // After SelectedIndex: 0 After RowCount: 1
- //
- // 2) Host selected, host open
- // v goats.com ////////////////////////////
- // goats.com sldkkfjl
- // goat.scom flksj133
- // > atwola.com
- //
- // Before SelectedIndex: 0 Before RowCount: 4
- // After SelectedIndex: 0 After RowCount: 1
- //
- // 3) Host selected, host closed
- // > goats.com ////////////////////////////
- // > atwola.com
- //
- // Before SelectedIndex: 0 Before RowCount: 2
- // After SelectedIndex: 0 After RowCount: 1
- //
- // 4) Single cookie selected, host has many children
- // v goats.com
- // goats.com sldkkfjl
- // //// goats.com /////////// flksjl33 ////
- // > atwola.com
- //
- // Before SelectedIndex: 2 Before RowCount: 4
- // After SelectedIndex: 1 After RowCount: 3
- //
- // 5) Single cookie selected, host has many children
- // v goats.com
- // //// goats.com /////////// flksjl33 ////
- // goats.com sldkkfjl
- // > atwola.com
- //
- // Before SelectedIndex: 1 Before RowCount: 4
- // After SelectedIndex: 1 After RowCount: 3
- var seln = this._view.selection;
- var tbo = this._tree.treeBoxObject;
-
- if (seln.count < 1) return;
-
- var nextSelected = 0;
- var rowCountImpact = 0;
- var deleteItems = [];
- if (!this._view._filtered) {
- var ci = seln.currentIndex;
- nextSelected = ci;
- var invalidateRow = -1;
- var item = this._view._getItemAtIndex(ci);
- if (item.container) {
- rowCountImpact -= (item.open ? item.cookies.length : 0) + 1;
- deleteItems = deleteItems.concat(item.cookies);
- if (!this._view.hasNextSibling(-1, ci))
- --nextSelected;
- this._view._removeItemAtIndex(ci);
- }
- else {
- var parent = this._view._getItemAtIndex(item.parentIndex);
- --rowCountImpact;
- if (parent.cookies.length == 1) {
- --rowCountImpact;
- deleteItems.push(item);
- if (!this._view.hasNextSibling(-1, ci))
- --nextSelected;
- if (!this._view.hasNextSibling(-1, item.parentIndex))
- --nextSelected;
- this._view._removeItemAtIndex(item.parentIndex);
- invalidateRow = item.parentIndex;
- }
- else {
- deleteItems.push(item);
- if (!this._view.hasNextSibling(-1, ci))
- --nextSelected;
- this._view._removeItemAtIndex(ci);
- }
- }
- this._view._rowCount += rowCountImpact;
- tbo.rowCountChanged(ci, rowCountImpact);
- if (invalidateRow != -1)
- tbo.invalidateRow(invalidateRow);
- }
- else {
- var rangeCount = seln.getRangeCount();
- // Traverse backwards through selections to avoid messing
- // up the indices when they are deleted.
- // See bug 388079.
- for (var i = rangeCount - 1; i >= 0; --i) {
- var min = {}; var max = {};
- seln.getRangeAt(i, min, max);
- nextSelected = min.value;
- for (var j = min.value; j <= max.value; ++j) {
- deleteItems.push(this._view._getItemAtIndex(j));
- if (!this._view.hasNextSibling(-1, max.value))
- --nextSelected;
- }
- var delta = max.value - min.value + 1;
- this._view._removeItemAtIndex(min.value, delta);
- rowCountImpact = -1 * delta;
- this._view._rowCount += rowCountImpact;
- tbo.rowCountChanged(min.value, rowCountImpact);
- }
- }
-
- this.performDeletion(deleteItems);
-
- if (nextSelected < 0)
- seln.clearSelection();
- else {
- seln.select(nextSelected);
- this._tree.focus();
- }
- },
-
- deleteAllCookies: function () {
- if (this._view._filtered) {
- var rowCount = this._view.rowCount;
- var deleteItems = [];
- for (var index = 0; index < rowCount; index++) {
- deleteItems.push(this._view._getItemAtIndex(index));
- }
- this._view._removeItemAtIndex(0, rowCount);
- this._view._rowCount = 0;
- this._tree.treeBoxObject.rowCountChanged(0, -rowCount);
- this.performDeletion(deleteItems);
- }
- else {
- this._cm.removeAll();
- }
- this._updateRemoveAllButton();
- this.focusFilterBox();
- },
-
- onCookieKeyPress: function (aEvent) {
- if (aEvent.keyCode == KeyEvent.DOM_VK_DELETE
-#ifdef XP_MACOSX
- || aEvent.keyCode == KeyEvent.DOM_VK_BACK_SPACE
-#endif
- ) {
- this.deleteCookie();
- }
- },
-
- _lastSortProperty : "",
- _lastSortAscending: false,
- sort: function (aProperty) {
- var ascending = (aProperty == this._lastSortProperty) ? !this._lastSortAscending : true;
- // Sort the Non-Filtered Host Collections
- if (aProperty == "rawHost") {
- function sortByHost(a, b) {
- return a.toLowerCase().localeCompare(b.toLowerCase());
- }
- this._hostOrder.sort(sortByHost);
- if (!ascending)
- this._hostOrder.reverse();
- }
-
- function sortByProperty(a, b) {
- return a[aProperty].toLowerCase().localeCompare(b[aProperty].toLowerCase());
- }
- for (var host in this._hosts) {
- var cookies = this._hosts[host].cookies;
- cookies.sort(sortByProperty);
- if (!ascending)
- cookies.reverse();
- }
- // Sort the Filtered List, if in Filtered mode
- if (this._view._filtered) {
- this._view._filterSet.sort(sortByProperty);
- if (!ascending)
- this._view._filterSet.reverse();
- }
-
- // Adjust the Sort Indicator
- var domainCol = document.getElementById("domainCol");
- var nameCol = document.getElementById("nameCol");
- var sortOrderString = ascending ? "ascending" : "descending";
- if (aProperty == "rawHost") {
- domainCol.setAttribute("sortDirection", sortOrderString);
- nameCol.removeAttribute("sortDirection");
- }
- else {
- nameCol.setAttribute("sortDirection", sortOrderString);
- domainCol.removeAttribute("sortDirection");
- }
-
- this._view._invalidateCache(0);
- this._view.selection.clearSelection();
- if (this._view.rowCount > 0) {
- this._view.selection.select(0);
- }
- this._tree.treeBoxObject.invalidate();
- this._tree.treeBoxObject.ensureRowIsVisible(0);
-
- this._lastSortAscending = ascending;
- this._lastSortProperty = aProperty;
- },
-
- clearFilter: function () {
- // Revert to single-select in the tree
- this._tree.setAttribute("seltype", "single");
-
- // Clear the Tree Display
- this._view._filtered = false;
- this._view._rowCount = 0;
- this._tree.treeBoxObject.rowCountChanged(0, -this._view._filterSet.length);
- this._view._filterSet = [];
-
- // Just reload the list to make sure deletions are respected
- this._loadCookies();
- this._tree.view = this._view;
-
- // Restore sort order
- var sortby = this._lastSortProperty;
- if (sortby == "") {
- this._lastSortAscending = false;
- this.sort("rawHost");
- }
- else {
- this._lastSortAscending = !this._lastSortAscending;
- this.sort(sortby);
- }
-
- // Restore open state
- for (var i = 0; i < this._openIndices.length; ++i)
- this._view.toggleOpenState(this._openIndices[i]);
- this._openIndices = [];
-
- // Restore selection
- this._view.selection.clearSelection();
- for (i = 0; i < this._lastSelectedRanges.length; ++i) {
- var range = this._lastSelectedRanges[i];
- this._view.selection.rangedSelect(range.min, range.max, true);
- }
- this._lastSelectedRanges = [];
-
- document.getElementById("cookiesIntro").value = this._bundle.getString("cookiesAll");
- this._updateRemoveAllButton();
- },
-
- _cookieMatchesFilter: function (aCookie) {
- return aCookie.rawHost.indexOf(this._view._filterValue) != -1 ||
- aCookie.name.indexOf(this._view._filterValue) != -1 ||
- aCookie.value.indexOf(this._view._filterValue) != -1;
- },
-
- _filterCookies: function (aFilterValue) {
- this._view._filterValue = aFilterValue;
- var cookies = [];
- for (var i = 0; i < gCookiesWindow._hostOrder.length; ++i) { //var host in gCookiesWindow._hosts) {
- var currHost = gCookiesWindow._hosts[gCookiesWindow._hostOrder[i]]; // gCookiesWindow._hosts[host];
- if (!currHost) continue;
- for (var j = 0; j < currHost.cookies.length; ++j) {
- var cookie = currHost.cookies[j];
- if (this._cookieMatchesFilter(cookie))
- cookies.push(cookie);
- }
- }
- return cookies;
- },
-
- _lastSelectedRanges: [],
- _openIndices: [],
- _saveState: function () {
- // Save selection
- var seln = this._view.selection;
- this._lastSelectedRanges = [];
- var rangeCount = seln.getRangeCount();
- for (var i = 0; i < rangeCount; ++i) {
- var min = {}; var max = {};
- seln.getRangeAt(i, min, max);
- this._lastSelectedRanges.push({ min: min.value, max: max.value });
- }
-
- // Save open states
- this._openIndices = [];
- for (i = 0; i < this._view.rowCount; ++i) {
- var item = this._view._getItemAtIndex(i);
- if (item && item.container && item.open)
- this._openIndices.push(i);
- }
- },
-
- _updateRemoveAllButton: function gCookiesWindow__updateRemoveAllButton() {
- let removeAllCookies = document.getElementById("removeAllCookies");
- removeAllCookies.disabled = this._view._rowCount == 0;
-
- let labelStringID = "removeAllCookies.label";
- let accessKeyStringID = "removeAllCookies.accesskey";
- if (this._view._filtered) {
- labelStringID = "removeAllShownCookies.label";
- accessKeyStringID = "removeAllShownCookies.accesskey";
- }
- removeAllCookies.setAttribute("label", this._bundle.getString(labelStringID));
- removeAllCookies.setAttribute("accesskey", this._bundle.getString(accessKeyStringID));
- },
-
- filter: function () {
- var filter = document.getElementById("filter").value;
- if (filter == "") {
- gCookiesWindow.clearFilter();
- return;
- }
- var view = gCookiesWindow._view;
- view._filterSet = gCookiesWindow._filterCookies(filter);
- if (!view._filtered) {
- // Save Display Info for the Non-Filtered mode when we first
- // enter Filtered mode.
- gCookiesWindow._saveState();
- view._filtered = true;
- }
- // Move to multi-select in the tree
- gCookiesWindow._tree.setAttribute("seltype", "multiple");
-
- // Clear the display
- var oldCount = view._rowCount;
- view._rowCount = 0;
- gCookiesWindow._tree.treeBoxObject.rowCountChanged(0, -oldCount);
- // Set up the filtered display
- view._rowCount = view._filterSet.length;
- gCookiesWindow._tree.treeBoxObject.rowCountChanged(0, view.rowCount);
-
- // if the view is not empty then select the first item
- if (view.rowCount > 0)
- view.selection.select(0);
-
- document.getElementById("cookiesIntro").value = gCookiesWindow._bundle.getString("cookiesFiltered");
- this._updateRemoveAllButton();
- },
-
- setFilter: function (aFilterString) {
- document.getElementById("filter").value = aFilterString;
- this.filter();
- },
-
- focusFilterBox: function () {
- var filter = document.getElementById("filter");
- filter.focus();
- filter.select();
- },
-
- onWindowKeyPress: function (aEvent) {
- if (aEvent.keyCode == KeyEvent.DOM_VK_ESCAPE)
- window.close();
- }
-};
diff --git a/components/preferences/cookies.xul b/components/preferences/cookies.xul
deleted file mode 100644
index 60725e9..0000000
--- a/components/preferences/cookies.xul
+++ /dev/null
@@ -1,106 +0,0 @@
-<?xml version="1.0"?>
-
-# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
-<?xml-stylesheet href="chrome://browser/skin/preferences/preferences.css" type="text/css"?>
-
-<!DOCTYPE dialog SYSTEM "chrome://browser/locale/preferences/cookies.dtd" >
-
-<window id="CookiesDialog" windowtype="Browser:Cookies"
- class="windowDialog" title="&window.title;"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- style="width: &window.width;;"
- onload="gCookiesWindow.init();"
- onunload="gCookiesWindow.uninit();"
- persist="screenX screenY width height"
- onkeypress="gCookiesWindow.onWindowKeyPress(event);">
-
- <script src="chrome://browser/content/preferences/cookies.js"/>
-
- <stringbundle id="bundlePreferences"
- src="chrome://browser/locale/preferences/preferences.properties"/>
-
- <keyset>
- <key key="&windowClose.key;" modifiers="accel" oncommand="window.close();"/>
- <key key="&focusSearch1.key;" modifiers="accel" oncommand="gCookiesWindow.focusFilterBox();"/>
- <key key="&focusSearch2.key;" modifiers="accel" oncommand="gCookiesWindow.focusFilterBox();"/>
- </keyset>
-
- <vbox flex="1" class="contentPane">
- <hbox align="center">
- <label accesskey="&filter.accesskey;" control="filter">&filter.label;</label>
- <textbox type="search" id="filter" flex="1"
- aria-controls="cookiesList"
- oncommand="gCookiesWindow.filter();"/>
- </hbox>
- <separator class="thin"/>
- <label control="cookiesList" id="cookiesIntro" value="&cookiesonsystem.label;"/>
- <separator class="thin"/>
- <tree id="cookiesList" flex="1" style="height: 10em;"
- onkeypress="gCookiesWindow.onCookieKeyPress(event)"
- onselect="gCookiesWindow.onCookieSelected();"
- hidecolumnpicker="true" seltype="single">
- <treecols>
- <treecol id="domainCol" label="&cookiedomain.label;" flex="2" primary="true"
- persist="width" onclick="gCookiesWindow.sort('rawHost');"/>
- <splitter class="tree-splitter"/>
- <treecol id="nameCol" label="&cookiename.label;" flex="1"
- persist="width"
- onclick="gCookiesWindow.sort('name');"/>
- </treecols>
- <treechildren id="cookiesChildren"/>
- </tree>
- <hbox id="cookieInfoBox">
- <grid flex="1" id="cookieInfoGrid">
- <columns>
- <column/>
- <column flex="1"/>
- </columns>
- <rows>
- <row align="center">
- <hbox pack="end"><label id="nameLabel" control="name" value="&props.name.label;"/></hbox>
- <textbox id="name" readonly="true" class="plain"/>
- </row>
- <row align="center">
- <hbox pack="end"><label id="valueLabel" control="value" value="&props.value.label;"/></hbox>
- <textbox id="value" readonly="true" class="plain"/>
- </row>
- <row align="center">
- <hbox pack="end"><label id="isDomain" control="host" value="&props.domain.label;"/></hbox>
- <textbox id="host" readonly="true" class="plain"/>
- </row>
- <row align="center">
- <hbox pack="end"><label id="pathLabel" control="path" value="&props.path.label;"/></hbox>
- <textbox id="path" readonly="true" class="plain"/>
- </row>
- <row align="center">
- <hbox pack="end"><label id="isSecureLabel" control="isSecure" value="&props.secure.label;"/></hbox>
- <textbox id="isSecure" readonly="true" class="plain"/>
- </row>
- <row align="center">
- <hbox pack="end"><label id="expiresLabel" control="expires" value="&props.expires.label;"/></hbox>
- <textbox id="expires" readonly="true" class="plain"/>
- </row>
- </rows>
- </grid>
- </hbox>
- </vbox>
- <hbox align="end">
- <hbox class="actionButtons" flex="1">
- <button id="removeSelectedCookies" disabled="true" icon="clear"
- oncommand="gCookiesWindow.deleteCookie();"/>
- <button id="removeAllCookies" disabled="true" icon="clear"
- oncommand="gCookiesWindow.deleteAllCookies();"/>
- <spacer flex="1"/>
-#ifndef XP_MACOSX
- <button oncommand="close();" icon="close"
- label="&button.close.label;" accesskey="&button.close.accesskey;"/>
-#endif
- </hbox>
- <resizer type="window" dir="bottomend"/>
- </hbox>
-</window>
diff --git a/components/preferences/fonts.js b/components/preferences/fonts.js
deleted file mode 100644
index e9f93a2..0000000
--- a/components/preferences/fonts.js
+++ /dev/null
@@ -1,144 +0,0 @@
-/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-// browser.display.languageList LOCK ALL when LOCKED
-
-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;
- },
-
- 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;
- },
-
- onBeforeAccept: function ()
- {
- // Only care in in-content prefs
- if (!window.frameElement) {
- return true;
- }
-
- let preferences = document.querySelectorAll("preference[id*='font.minimum-size']");
- // It would be good if we could avoid touching languages the pref pages won't use, but
- // unfortunately the language group APIs (deducing language groups from language codes)
- // are C++ - only. So we just check all the things the user touched:
- // Don't care about anything up to 24px, or if this value is the same as set previously:
- preferences = Array.filter(preferences, prefEl => {
- return prefEl.value > 24 && prefEl.value != prefEl.valueFromPreferences;
- });
- if (!preferences.length) {
- return;
- }
-
- let strings = document.getElementById("bundlePreferences");
- let title = strings.getString("veryLargeMinimumFontTitle");
- let confirmLabel = strings.getString("acceptVeryLargeMinimumFont");
- let warningMessage = strings.getString("veryLargeMinimumFontWarning");
- let {Services} = Components.utils.import("resource://gre/modules/Services.jsm", {});
- let flags = Services.prompt.BUTTON_POS_1 * Services.prompt.BUTTON_TITLE_CANCEL |
- Services.prompt.BUTTON_POS_0 * Services.prompt.BUTTON_TITLE_IS_STRING |
- Services.prompt.BUTTON_POS_1_DEFAULT;
- let buttonChosen = Services.prompt.confirmEx(window, title, warningMessage, flags, confirmLabel, null, "", "", {});
- return buttonChosen == 0;
- },
-};
-
diff --git a/components/preferences/fonts.xul b/components/preferences/fonts.xul
deleted file mode 100644
index 97c6869..0000000
--- a/components/preferences/fonts.xul
+++ /dev/null
@@ -1,279 +0,0 @@
-<?xml version="1.0"?>
-
-# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
-#ifdef XP_MACOSX
-<?xml-stylesheet href="chrome://browser/skin/preferences/preferences.css"?>
-#endif
-
-<!DOCTYPE prefwindow SYSTEM "chrome://browser/locale/preferences/fonts.dtd" >
-
-<prefwindow id="FontsDialog" type="child"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- title="&fontsDialog.title;"
- dlgbuttons="accept,cancel,help"
- ondialoghelp="openPrefsHelp()"
- onbeforeaccept="return gFontsDialog.onBeforeAccept();"
- style="">
-
- <script type="application/javascript" src="chrome://browser/content/utilityOverlay.js"/>
-
- <prefpane id="FontsDialogPane"
- class="largeDialogContainer"
- helpTopic="prefs-fonts-and-colors">
-
- <preferences id="fontPreferences">
- <preference id="font.language.group" name="font.language.group" type="wstring"/>
- <preference id="browser.display.use_document_fonts"
- name="browser.display.use_document_fonts"
- type="int"/>
- <preference id="intl.charset.fallback.override" name="intl.charset.fallback.override" type="string"/>
- </preferences>
-
- <stringbundle id="bundlePreferences" src="chrome://browser/locale/preferences/preferences.properties"/>
- <script type="application/javascript" src="chrome://mozapps/content/preferences/fontbuilder.js"/>
- <script type="application/javascript" src="chrome://browser/content/preferences/fonts.js"/>
-
- <!-- Fonts for: [ Language ] -->
- <groupbox>
- <caption>
- <hbox align="center">
- <label accesskey="&language.accesskey;" control="selectLangs">&language.label;</label>
- </hbox>
- <menulist id="selectLangs" preference="font.language.group"
- onsyncfrompreference="return gFontsDialog.readFontLanguageGroup();">
- <menupopup>
- <menuitem value="ar" label="&font.langGroup.arabic;"/>
- <menuitem value="x-armn" label="&font.langGroup.armenian;"/>
- <menuitem value="x-beng" label="&font.langGroup.bengali;"/>
- <menuitem value="zh-CN" label="&font.langGroup.simpl-chinese;"/>
- <menuitem value="zh-HK" label="&font.langGroup.trad-chinese-hk;"/>
- <menuitem value="zh-TW" label="&font.langGroup.trad-chinese;"/>
- <menuitem value="x-cyrillic" label="&font.langGroup.cyrillic;"/>
- <menuitem value="x-devanagari" label="&font.langGroup.devanagari;"/>
- <menuitem value="x-ethi" label="&font.langGroup.ethiopic;"/>
- <menuitem value="x-geor" label="&font.langGroup.georgian;"/>
- <menuitem value="el" label="&font.langGroup.el;"/>
- <menuitem value="x-gujr" label="&font.langGroup.gujarati;"/>
- <menuitem value="x-guru" label="&font.langGroup.gurmukhi;"/>
- <menuitem value="he" label="&font.langGroup.hebrew;"/>
- <menuitem value="ja" label="&font.langGroup.japanese;"/>
- <menuitem value="x-knda" label="&font.langGroup.kannada;"/>
- <menuitem value="x-khmr" label="&font.langGroup.khmer;"/>
- <menuitem value="ko" label="&font.langGroup.korean;"/>
- <menuitem value="x-western" label="&font.langGroup.latin;"/>
- <menuitem value="x-mlym" label="&font.langGroup.malayalam;"/>
- <menuitem value="x-orya" label="&font.langGroup.oriya;"/>
- <menuitem value="x-sinh" label="&font.langGroup.sinhala;"/>
- <menuitem value="x-tamil" label="&font.langGroup.tamil;"/>
- <menuitem value="x-telu" label="&font.langGroup.telugu;"/>
- <menuitem value="th" label="&font.langGroup.thai;"/>
- <menuitem value="x-tibt" label="&font.langGroup.tibetan;"/>
- <menuitem value="x-cans" label="&font.langGroup.canadian;"/>
- <menuitem value="x-unicode" label="&font.langGroup.other;"/>
- </menupopup>
- </menulist>
- </caption>
-
- <grid>
- <columns>
- <column/>
- <column flex="1"/>
- <column/>
- <column/>
- </columns>
-
- <rows>
- <row>
- <separator class="thin"/>
- </row>
-
- <row align="center">
- <hbox align="center" pack="end">
- <label accesskey="&proportional.accesskey;" control="defaultFontType">&proportional.label;</label>
- </hbox>
- <menulist id="defaultFontType" flex="1" style="width: 0px;">
- <menupopup>
- <menuitem value="serif" label="&useDefaultFontSerif.label;"/>
- <menuitem value="sans-serif" label="&useDefaultFontSansSerif.label;"/>
- </menupopup>
- </menulist>
- <hbox align="center" pack="end">
- <label value="&size.label;"
- accesskey="&sizeProportional.accesskey;"
- control="sizeVar"/>
- </hbox>
- <menulist id="sizeVar">
- <menupopup>
- <menuitem value="9" label="9"/>
- <menuitem value="10" label="10"/>
- <menuitem value="11" label="11"/>
- <menuitem value="12" label="12"/>
- <menuitem value="13" label="13"/>
- <menuitem value="14" label="14"/>
- <menuitem value="15" label="15"/>
- <menuitem value="16" label="16"/>
- <menuitem value="17" label="17"/>
- <menuitem value="18" label="18"/>
- <menuitem value="20" label="20"/>
- <menuitem value="22" label="22"/>
- <menuitem value="24" label="24"/>
- <menuitem value="26" label="26"/>
- <menuitem value="28" label="28"/>
- <menuitem value="30" label="30"/>
- <menuitem value="32" label="32"/>
- <menuitem value="34" label="34"/>
- <menuitem value="36" label="36"/>
- <menuitem value="40" label="40"/>
- <menuitem value="44" label="44"/>
- <menuitem value="48" label="48"/>
- <menuitem value="56" label="56"/>
- <menuitem value="64" label="64"/>
- <menuitem value="72" label="72"/>
- </menupopup>
- </menulist>
- </row>
- <row align="center">
- <hbox align="center" pack="end">
- <label accesskey="&serif.accesskey;" control="serif">&serif.label;</label>
- </hbox>
- <menulist id="serif" flex="1" style="width: 0px;"
- onsyncfrompreference="return gFontsDialog.readFontSelection(document.getElementById('serif'));"/>
- <spacer/>
- </row>
- <row align="center">
- <hbox align="center" pack="end">
- <label accesskey="&sans-serif.accesskey;" control="sans-serif">&sans-serif.label;</label>
- </hbox>
- <menulist id="sans-serif" flex="1" style="width: 0px;"
- onsyncfrompreference="return gFontsDialog.readFontSelection(document.getElementById('sans-serif'));"/>
- <spacer/>
- </row>
- <row align="center">
- <hbox align="center" pack="end">
- <label accesskey="&monospace.accesskey;" control="monospace">&monospace.label;</label>
- </hbox>
- <menulist id="monospace" flex="1" style="width: 0px;" crop="right"
- onsyncfrompreference="return gFontsDialog.readFontSelection(document.getElementById('monospace'));"/>
- <hbox align="center" pack="end">
- <label value="&size.label;"
- accesskey="&sizeMonospace.accesskey;"
- control="sizeMono"/>
- </hbox>
- <menulist id="sizeMono">
- <menupopup>
- <menuitem value="9" label="9"/>
- <menuitem value="10" label="10"/>
- <menuitem value="11" label="11"/>
- <menuitem value="12" label="12"/>
- <menuitem value="13" label="13"/>
- <menuitem value="14" label="14"/>
- <menuitem value="15" label="15"/>
- <menuitem value="16" label="16"/>
- <menuitem value="17" label="17"/>
- <menuitem value="18" label="18"/>
- <menuitem value="20" label="20"/>
- <menuitem value="22" label="22"/>
- <menuitem value="24" label="24"/>
- <menuitem value="26" label="26"/>
- <menuitem value="28" label="28"/>
- <menuitem value="30" label="30"/>
- <menuitem value="32" label="32"/>
- <menuitem value="34" label="34"/>
- <menuitem value="36" label="36"/>
- <menuitem value="40" label="40"/>
- <menuitem value="44" label="44"/>
- <menuitem value="48" label="48"/>
- <menuitem value="56" label="56"/>
- <menuitem value="64" label="64"/>
- <menuitem value="72" label="72"/>
- </menupopup>
- </menulist>
- </row>
- </rows>
- </grid>
- <separator class="thin"/>
- <hbox flex="1">
- <spacer flex="1"/>
- <hbox align="center" pack="end">
- <label accesskey="&minSize.accesskey;" control="minSize">&minSize.label;</label>
- <menulist id="minSize">
- <menupopup>
- <menuitem value="0" label="&minSize.none;"/>
- <menuitem value="9" label="9"/>
- <menuitem value="10" label="10"/>
- <menuitem value="11" label="11"/>
- <menuitem value="12" label="12"/>
- <menuitem value="13" label="13"/>
- <menuitem value="14" label="14"/>
- <menuitem value="15" label="15"/>
- <menuitem value="16" label="16"/>
- <menuitem value="17" label="17"/>
- <menuitem value="18" label="18"/>
- <menuitem value="20" label="20"/>
- <menuitem value="22" label="22"/>
- <menuitem value="24" label="24"/>
- <menuitem value="26" label="26"/>
- <menuitem value="28" label="28"/>
- <menuitem value="30" label="30"/>
- <menuitem value="32" label="32"/>
- <menuitem value="34" label="34"/>
- <menuitem value="36" label="36"/>
- <menuitem value="40" label="40"/>
- <menuitem value="44" label="44"/>
- <menuitem value="48" label="48"/>
- <menuitem value="56" label="56"/>
- <menuitem value="64" label="64"/>
- <menuitem value="72" label="72"/>
- </menupopup>
- </menulist>
- </hbox>
- </hbox>
- <separator/>
- <separator class="groove"/>
- <hbox>
- <checkbox id="useDocumentFonts"
- label="&allowPagesToUse.label;" accesskey="&allowPagesToUse.accesskey;"
- preference="browser.display.use_document_fonts"
- onsyncfrompreference="return gFontsDialog.readUseDocumentFonts();"
- onsynctopreference="return gFontsDialog.writeUseDocumentFonts();"/>
- </hbox>
- </groupbox>
-
- <!-- Character Encoding -->
- <groupbox>
- <caption label="&languages.customize.Fallback.grouplabel;"/>
- <description>&languages.customize.Fallback.desc;</description>
- <hbox align="center">
- <label value="&languages.customize.Fallback.label;"
- accesskey="&languages.customize.Fallback.accesskey;"
- control="DefaultCharsetList"/>
- <menulist id="DefaultCharsetList" preference="intl.charset.fallback.override">
- <menupopup>
- <menuitem label="&languages.customize.Fallback.auto;" value="*"/>
- <menuitem label="&languages.customize.Fallback.utf8;" value="UTF-8"/>
- <menuitem label="&languages.customize.Fallback.arabic;" value="windows-1256"/>
- <menuitem label="&languages.customize.Fallback.baltic;" value="windows-1257"/>
- <menuitem label="&languages.customize.Fallback.ceiso;" value="ISO-8859-2"/>
- <menuitem label="&languages.customize.Fallback.cewindows;" value="windows-1250"/>
- <menuitem label="&languages.customize.Fallback.simplified;" value="gbk"/>
- <menuitem label="&languages.customize.Fallback.traditional;" value="Big5"/>
- <menuitem label="&languages.customize.Fallback.cyrillic;" value="windows-1251"/>
- <menuitem label="&languages.customize.Fallback.greek;" value="ISO-8859-7"/>
- <menuitem label="&languages.customize.Fallback.hebrew;" value="windows-1255"/>
- <menuitem label="&languages.customize.Fallback.japanese;" value="Shift_JIS"/>
- <menuitem label="&languages.customize.Fallback.korean;" value="EUC-KR"/>
- <menuitem label="&languages.customize.Fallback.thai;" value="windows-874"/>
- <menuitem label="&languages.customize.Fallback.turkish;" value="windows-1254"/>
- <menuitem label="&languages.customize.Fallback.vietnamese;" value="windows-1258"/>
- <menuitem label="&languages.customize.Fallback.other;" value="windows-1252"/>
- </menupopup>
- </menulist>
- </hbox>
- </groupbox>
- </prefpane>
-</prefwindow>
diff --git a/components/preferences/handlers.css b/components/preferences/handlers.css
deleted file mode 100644
index 9a1d474..0000000
--- a/components/preferences/handlers.css
+++ /dev/null
@@ -1,25 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-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");
-}
diff --git a/components/preferences/handlers.xml b/components/preferences/handlers.xml
deleted file mode 100644
index 5fb915c..0000000
--- a/components/preferences/handlers.xml
+++ /dev/null
@@ -1,81 +0,0 @@
-<?xml version="1.0"?>
-
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!DOCTYPE overlay [
- <!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
- <!ENTITY % applicationsDTD SYSTEM "chrome://browser/locale/preferences/applications.dtd">
- %brandDTD;
- %applicationsDTD;
-]>
-
-<bindings id="handlerBindings"
- xmlns="http://www.mozilla.org/xbl"
- xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:xbl="http://www.mozilla.org/xbl">
-
- <binding id="handler-base" extends="chrome://global/content/bindings/richlistbox.xml#richlistitem">
- <implementation>
- <property name="type" readonly="true">
- <getter>
- return this.getAttribute("type");
- </getter>
- </property>
- </implementation>
- </binding>
-
- <binding id="handler" extends="chrome://browser/content/preferences/handlers.xml#handler-base">
- <content>
- <xul:hbox flex="1" equalsize="always">
- <xul:hbox flex="1" align="center" xbl:inherits="tooltiptext=typeDescription">
- <xul:image src="moz-icon://goat?size=16" class="typeIcon"
- xbl:inherits="src=typeIcon" height="16" width="16"/>
- <xul:label flex="1" crop="end" xbl:inherits="value=typeDescription"/>
- </xul:hbox>
- <xul:hbox flex="1" align="center" xbl:inherits="tooltiptext=actionDescription">
- <xul:image xbl:inherits="src=actionIcon" height="16" width="16" class="actionIcon"/>
- <xul:label flex="1" crop="end" xbl:inherits="value=actionDescription"/>
- </xul:hbox>
- </xul:hbox>
- </content>
- </binding>
-
- <binding id="handler-selected" extends="chrome://browser/content/preferences/handlers.xml#handler-base">
- <content>
- <xul:hbox flex="1" equalsize="always">
- <xul:hbox flex="1" align="center" xbl:inherits="tooltiptext=typeDescription">
- <xul:image src="moz-icon://goat?size=16" class="typeIcon"
- xbl:inherits="src=typeIcon" height="16" width="16"/>
- <xul:label flex="1" crop="end" xbl:inherits="value=typeDescription"/>
- </xul:hbox>
- <xul:hbox flex="1">
- <xul:menulist class="actionsMenu" flex="1" crop="end" selectedIndex="1"
- xbl:inherits="tooltiptext=actionDescription"
- oncommand="gApplicationsPane.onSelectAction(event.originalTarget)">
- <xul:menupopup/>
- </xul:menulist>
- </xul:hbox>
- </xul:hbox>
- </content>
-
- <implementation>
- <constructor>
- gApplicationsPane.rebuildActionsMenu();
- </constructor>
- </implementation>
-
- </binding>
-
- <binding id="offlineapp"
- extends="chrome://global/content/bindings/listbox.xml#listitem">
- <content>
- <children>
- <xul:listcell xbl:inherits="label=origin"/>
- <xul:listcell xbl:inherits="label=usage"/>
- </children>
- </content>
- </binding>
-
-</bindings>
diff --git a/components/preferences/jar.mn b/components/preferences/jar.mn
deleted file mode 100644
index 6e143de..0000000
--- a/components/preferences/jar.mn
+++ /dev/null
@@ -1,44 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-browser.jar:
-* content/browser/preferences/advanced.xul
-* content/browser/preferences/advanced.js
- content/browser/preferences/applications.xul
-* content/browser/preferences/applications.js
- content/browser/preferences/applicationManager.xul
-* content/browser/preferences/applicationManager.js
-* content/browser/preferences/colors.xul
-* content/browser/preferences/cookies.xul
-* content/browser/preferences/cookies.js
- content/browser/preferences/content.xul
- content/browser/preferences/content.js
-* content/browser/preferences/connection.xul
- content/browser/preferences/connection.js
-* content/browser/preferences/fonts.xul
- content/browser/preferences/fonts.js
- content/browser/preferences/handlers.xml
- content/browser/preferences/handlers.css
-* content/browser/preferences/languages.xul
- content/browser/preferences/languages.js
-* content/browser/preferences/main.xul
- content/browser/preferences/main.js
- content/browser/preferences/newtaburl.js
- content/browser/preferences/permissions.xul
-* content/browser/preferences/permissions.js
-* content/browser/preferences/preferences.xul
- content/browser/preferences/privacy.xul
- content/browser/preferences/privacy.js
- content/browser/preferences/sanitize.xul
- content/browser/preferences/sanitize.js
- content/browser/preferences/security.xul
- content/browser/preferences/security.js
- content/browser/preferences/selectBookmark.xul
- content/browser/preferences/selectBookmark.js
-#ifdef MOZ_SERVICES_SYNC
- content/browser/preferences/sync.xul
- content/browser/preferences/sync.js
-#endif
-* content/browser/preferences/tabs.xul
-* content/browser/preferences/tabs.js
diff --git a/components/preferences/languages.js b/components/preferences/languages.js
deleted file mode 100644
index 8d2b394..0000000
--- a/components/preferences/languages.js
+++ /dev/null
@@ -1,304 +0,0 @@
-/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-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 {
- arrayOfPrefs.unshift(selectedID);
- preference.value = arrayOfPrefs.join(",");
- }
-
- this._acceptLanguages[selectedID] = true;
- this._availableLanguages.selectedItem = null;
-
- // Rebuild 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;
- }
- }
-};
-
diff --git a/components/preferences/languages.xul b/components/preferences/languages.xul
deleted file mode 100644
index 6fd8232..0000000
--- a/components/preferences/languages.xul
+++ /dev/null
@@ -1,98 +0,0 @@
-<?xml version="1.0"?>
-
-# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-<!DOCTYPE prefwindow SYSTEM "chrome://browser/locale/preferences/languages.dtd">
-
-<?xml-stylesheet href="chrome://global/skin/"?>
-#ifdef XP_MACOSX
-<?xml-stylesheet href="chrome://browser/skin/preferences/preferences.css"?>
-#endif
-
-<prefwindow id="LanguagesDialog" type="child"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- title="&languages.customize.Header;"
- dlgbuttons="accept,cancel,help"
- ondialoghelp="openPrefsHelp()"
- style="width: &window.width;;">
-
- <script type="application/javascript" src="chrome://browser/content/utilityOverlay.js"/>
-
- <prefpane id="LanguagesDialogPane"
- onpaneload="gLanguagesDialog.init();"
- helpTopic="prefs-languages">
-
- <preferences>
- <preference id="intl.accept_languages" name="intl.accept_languages" type="wstring"/>
- <preference id="pref.browser.language.disable_button.up"
- name="pref.browser.language.disable_button.up"
- type="bool"/>
- <preference id="pref.browser.language.disable_button.down"
- name="pref.browser.language.disable_button.down"
- type="bool"/>
- <preference id="pref.browser.language.disable_button.remove"
- name="pref.browser.language.disable_button.remove"
- type="bool"/>
- </preferences>
-
- <script type="application/javascript" src="chrome://browser/content/preferences/languages.js"/>
-
- <stringbundleset id="languageSet">
- <stringbundle id="bundleRegions" src="chrome://global/locale/regionNames.properties"/>
- <stringbundle id="bundleLanguages" src="chrome://global/locale/languageNames.properties"/>
- <stringbundle id="bundlePreferences" src="chrome://browser/locale/preferences/preferences.properties"/>
- <stringbundle id="bundleAccepted" src="resource://gre/res/language.properties"/>
- </stringbundleset>
-
- <description>&languages.customize.prefLangDescript;</description>
- <label>&languages.customize.active.label;</label>
- <grid flex="1">
- <columns>
- <column flex="1"/>
- <column/>
- </columns>
- <rows>
- <row flex="1">
- <listbox id="activeLanguages" flex="1" rows="6"
- seltype="multiple" onselect="gLanguagesDialog.onLanguageSelect();"
- preference="intl.accept_languages"
- onsyncfrompreference="return gLanguagesDialog.readAcceptLanguages();"
- onsynctopreference="return gLanguagesDialog.writeAcceptLanguages();"/>
- <vbox>
- <button id="up" class="up" oncommand="gLanguagesDialog.moveUp();" disabled="true"
- label="&languages.customize.moveUp.label;"
- accesskey="&languages.customize.moveUp.accesskey;"
- preference="pref.browser.language.disable_button.up"/>
- <button id="down" class="down" oncommand="gLanguagesDialog.moveDown();" disabled="true"
- label="&languages.customize.moveDown.label;"
- accesskey="&languages.customize.moveDown.accesskey;"
- preference="pref.browser.language.disable_button.down"/>
- <button id="remove" oncommand="gLanguagesDialog.removeLanguage();" disabled="true"
- label="&languages.customize.deleteButton.label;"
- accesskey="&languages.customize.deleteButton.accesskey;"
- preference="pref.browser.language.disable_button.remove"/>
- </vbox>
- </row>
- <row>
- <separator class="thin"/>
- </row>
- <row>
- <menulist id="availableLanguages" oncommand="gLanguagesDialog.onAvailableLanguageSelect();"
- label="&languages.customize.selectLanguage.label;"
- label2="&languages.customize.selectLanguage.label;">
- <menupopup id="availableLanguagesPopup"/>
- </menulist>
- <button id="addButton" oncommand="gLanguagesDialog.addLanguage();" disabled="true"
- label="&languages.customize.addButton.label;"
- accesskey="&languages.customize.addButton.accesskey;"/>
- </row>
- </rows>
- </grid>
- <separator/>
- <separator/>
- </prefpane>
-</prefwindow>
-
diff --git a/components/preferences/main.js b/components/preferences/main.js
deleted file mode 100644
index 07e09ff..0000000
--- a/components/preferences/main.js
+++ /dev/null
@@ -1,473 +0,0 @@
-/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "DownloadsCommon",
- "resource:///modules/DownloadsCommon.jsm");
-
-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.bind(this), false);
-
- this.updateBrowserStartupLastSession();
-
- this.setupDownloadsWindowOptions();
-
- // Notify observers that the UI is now ready
- Components.classes["@mozilla.org/observer-service;1"]
- .getService(Components.interfaces.nsIObserverService)
- .notifyObservers(window, "main-pane-loaded", null);
- },
-
- setupDownloadsWindowOptions: function ()
- {
- let showWhenDownloading = document.getElementById("showWhenDownloading");
- let closeWhenDone = document.getElementById("closeWhenDone");
-
- // These radio buttons should be hidden when the Downloads Panel is enabled.
- let shouldHide = !DownloadsCommon.useToolkitUI;
- showWhenDownloading.hidden = shouldHide;
- closeWhenDone.hidden = shouldHide;
- },
-
- // 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.
- */
-
- syncFromHomePref: function ()
- {
- let homePref = document.getElementById("browser.startup.homepage");
-
- // If the pref is set to about:home, set the value to "" to show the
- // placeholder text (about:home title).
- if (homePref.value.toLowerCase() == "about:home")
- return "";
-
- // If the pref is actually "", show a blank page. The actual home page
- // loading code treats them the same, and we don't want the placeholder text
- // to be shown.
- if (homePref.value == "")
- return "about:logopage";
-
- // Otherwise, show the actual pref value.
- return undefined;
- },
-
- syncToHomePref: function (value)
- {
- // If the value is "", use about:home.
- if (value == "")
- return "about:home";
-
- // Otherwise, use the actual textbox value.
- return undefined;
- },
-
- /**
- * 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 ()
- {
- let homePage = document.getElementById("browser.startup.homepage");
- let tabs = this._getTabsForHomePage();
- function getTabURI(t) t.linkedBrowser.currentURI.spec;
-
- // FIXME Bug 244192: using dangerous "|" joiner!
- if (tabs.length)
- homePage.value = tabs.map(getTabURI).join("|");
- },
-
- /**
- * 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");
-
- // XXX still using dangerous "|" joiner!
- homePage.value = rv.urls.join("|");
- }
- },
-
- /**
- * Switches the "Use Current Page" button between its singular and plural
- * forms.
- */
- _updateUseCurrentButton: function () {
- let useCurrent = document.getElementById("useCurrent");
-
- let tabs = this._getTabsForHomePage();
- if (tabs.length > 1)
- useCurrent.label = useCurrent.getAttribute("label2");
- else
- 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 = !tabs.length
- },
-
- _getTabsForHomePage: function ()
- {
- var win;
- var tabs = [];
- 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") {
- // We should only include visible & non-pinned tabs
- tabs = win.gBrowser.visibleTabs.slice(win.gBrowser._numPinnedTabs);
- }
-
- return tabs;
- },
-
- /**
- * 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;
-
- let bundlePreferences = document.getElementById("bundlePreferences");
- let title = bundlePreferences.getString("chooseDownloadFolderTitle");
- let folderListPref = document.getElementById("browser.download.folderList");
- let currentDirPref = this._indexToFolder(folderListPref.value); // file
- let defDownloads = this._indexToFolder(1); // file
- let fp = Components.classes["@mozilla.org/filepicker;1"].
- createInstance(nsIFilePicker);
- let fpCallback = function fpCallback_done(aResult) {
- if (aResult == nsIFilePicker.returnOK) {
- let file = fp.file.QueryInterface(nsILocalFile);
- let downloadDirPref = document.getElementById("browser.download.dir");
-
- downloadDirPref.value = file;
- 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.
- }
- }.bind(this);
-
- fp.init(window, title, nsIFilePicker.modeGetFolder);
- fp.appendFilters(nsIFilePicker.filterAll);
- // 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);
- }
- fp.open(fpCallback);
- },
-
- /**
- * 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");
-
- // 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) {
- // '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(this._getDownloadsFolder("Desktop"));
- }
- 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;
- }
- },
-
- /**
- * Hide/show the "Show my windows and tabs from last time" option based
- * on the value of the browser.privatebrowsing.autostart pref.
- */
- updateBrowserStartupLastSession: function()
- {
- let pbAutoStartPref = document.getElementById("browser.privatebrowsing.autostart");
- let startupPref = document.getElementById("browser.startup.page");
- let menu = document.getElementById("browserStartupPage");
- let option = document.getElementById("browserStartupLastSession");
- if (pbAutoStartPref.value) {
- option.setAttribute("disabled", "true");
- if (option.selected) {
- menu.selectedItem = document.getElementById("browserStartupHomePage");
- }
- } else {
- option.removeAttribute("disabled");
- startupPref.updateElements(); // select the correct index in the startup menulist
- }
- }
-};
diff --git a/components/preferences/main.xul b/components/preferences/main.xul
deleted file mode 100644
index bb51947..0000000
--- a/components/preferences/main.xul
+++ /dev/null
@@ -1,188 +0,0 @@
-<?xml version="1.0"?>
-
-# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-<!DOCTYPE overlay [
- <!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
- <!ENTITY % mainDTD SYSTEM "chrome://browser/locale/preferences/main.dtd">
- <!ENTITY % aboutHomeDTD SYSTEM "chrome://browser/locale/aboutHome.dtd">
- %brandDTD;
- %mainDTD;
- %aboutHomeDTD;
-]>
-
-<overlay id="MainPaneOverlay"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-
- <prefpane id="paneMain"
- onpaneload="gMainPane.init();"
- helpTopic="prefs-main">
-
- <script type="application/javascript" src="chrome://browser/content/preferences/main.js"/>
-
- <preferences id="mainPreferences">
- <!-- XXX Button preferences -->
-
- <!-- Startup -->
- <preference id="browser.startup.page"
- name="browser.startup.page"
- type="int"/>
- <preference id="browser.startup.homepage"
- name="browser.startup.homepage"
- type="wstring"/>
-
- <preference id="pref.browser.homepage.disable_button.current_page"
- name="pref.browser.homepage.disable_button.current_page"
- type="bool"/>
- <preference id="pref.browser.homepage.disable_button.bookmark_page"
- name="pref.browser.homepage.disable_button.bookmark_page"
- type="bool"/>
- <preference id="pref.browser.homepage.disable_button.restore_default"
- name="pref.browser.homepage.disable_button.restore_default"
- type="bool"/>
-
- <preference id="browser.privatebrowsing.autostart"
- name="browser.privatebrowsing.autostart"
- type="bool"
- onchange="gMainPane.updateBrowserStartupLastSession();"/>
-
- <!-- Downloads -->
- <preference id="browser.download.manager.showWhenStarting"
- name="browser.download.manager.showWhenStarting"
- type="bool"
- onchange="gMainPane.showDownloadsWhenStartingPrefChanged();"/>
- <preference id="browser.download.manager.closeWhenDone"
- name="browser.download.manager.closeWhenDone"
- type="bool"/>
- <preference id="browser.download.useDownloadDir"
- name="browser.download.useDownloadDir"
- type="bool"/>
- <preference id="browser.download.dir"
- name="browser.download.dir"
- type="file"
- onchange="gMainPane.displayDownloadDirPref();"/>
- <preference id="browser.download.folderList" name="browser.download.folderList" type="int"/>
- <preference id="browser.download.useToolkitUI" name="browser.download.useToolkitUI" type="bool" />
-#ifdef XP_WIN
- <preference id="browser.download.saveZoneInformation" name="browser.download.saveZoneInformation" type="int" />
-#endif
-
- </preferences>
-
- <stringbundle id="bundlePreferences" src="chrome://browser/locale/preferences/preferences.properties"/>
-
- <!-- Startup -->
- <groupbox id="startupGroup">
- <caption label="&startup.label;"/>
-
- <hbox align="center">
- <label value="&startupPage.label;" accesskey="&startupPage.accesskey;"
- control="browserStartupPage"/>
- <menulist id="browserStartupPage" preference="browser.startup.page">
- <menupopup>
- <menuitem label="&startupHomePage.label;" value="1" id="browserStartupHomePage"/>
- <menuitem label="&startupBlankPage.label;" value="0" id="browserStartupBlank"/>
- <menuitem label="&startupLastSession.label;" value="3" id="browserStartupLastSession"/>
- </menupopup>
- </menulist>
- </hbox>
- <separator class="thin"/>
- <hbox align="center">
- <label value="&homepage.label;" accesskey="&homepage.accesskey;" control="browserHomePage"/>
- <textbox id="browserHomePage" class="padded uri-element" flex="1"
- type="autocomplete" autocompletesearch="history"
- onsyncfrompreference="return gMainPane.syncFromHomePref();"
- onsynctopreference="return gMainPane.syncToHomePref(this.value);"
- oninput="gNewtabUrl.writeNewtabUrl(null, this.value);"
- placeholder="&abouthome.pageTitle;"
- preference="browser.startup.homepage"/>
- </hbox>
- <hbox align="center" pack="end">
- <button label="" accesskey="&useCurrentPage.accesskey;"
- label1="&useCurrentPage.label;"
- label2="&useMultiple.label;"
- oncommand="gMainPane.setHomePageToCurrent(); gNewtabUrl.writeNewtabUrl();"
- id="useCurrent"
- preference="pref.browser.homepage.disable_button.current_page"/>
- <button label="&chooseBookmark.label;" accesskey="&chooseBookmark.accesskey;"
- oncommand="gMainPane.setHomePageToBookmark(); gNewtabUrl.writeNewtabUrl();"
- id="useBookmark"
- preference="pref.browser.homepage.disable_button.bookmark_page"/>
- <button label="&restoreDefault.label;" accesskey="&restoreDefault.accesskey;"
- oncommand="gMainPane.restoreDefaultHomePage(); gNewtabUrl.writeNewtabUrl();"
- id="restoreDefaultHomePage"
- preference="pref.browser.homepage.disable_button.restore_default"/>
- </hbox>
- </groupbox>
-
- <!-- Downloads -->
- <groupbox id="downloadsGroup">
- <caption label="&downloads.label;"/>
-
- <checkbox id="showWhenDownloading" label="&showWhenDownloading.label;"
- accesskey="&showWhenDownloading.accesskey;"
- preference="browser.download.manager.showWhenStarting"
- onsyncfrompreference="return gMainPane.readShowDownloadsWhenStarting();"/>
- <checkbox id="closeWhenDone" label="&closeWhenDone.label;"
- accesskey="&closeWhenDone.accesskey;" class="indent"
- preference="browser.download.manager.closeWhenDone"/>
-
- <separator class="thin"/>
-
- <radiogroup id="saveWhere"
- preference="browser.download.useDownloadDir"
- onsyncfrompreference="return gMainPane.readUseDownloadDir();">
- <hbox id="saveToRow">
- <radio id="saveTo" value="true"
- label="&saveTo.label;"
- accesskey="&saveTo.accesskey;"
- aria-labelledby="saveTo downloadFolder"/>
- <filefield id="downloadFolder" flex="1"
- preference="browser.download.folderList"
- preference-editable="true"
- aria-labelledby="saveTo"
- onsyncfrompreference="return gMainPane.displayDownloadDirPref();"
- onsynctopreference="return gMainPane.getFolderListPref()"/>
- <button id="chooseFolder" oncommand="gMainPane.chooseFolder();"
-#ifdef XP_MACOSX
- accesskey="&chooseFolderMac.accesskey;"
- label="&chooseFolderMac.label;"
-#else
- accesskey="&chooseFolderWin.accesskey;"
- label="&chooseFolderWin.label;"
-#endif
- preference="browser.download.folderList"
- onsynctopreference="return gMainPane.getFolderListPref();"/>
- </hbox>
- <radio id="alwaysAsk" value="false"
- label="&alwaysAsk.label;"
- accesskey="&alwaysAsk.accesskey;"/>
- </radiogroup>
-#if 0
-<!-- Disabled for now -- ToolkitUI DM is nonfunctional. -->
- <checkbox id="classicDownloadWindow"
- preference="browser.download.useToolkitUI"
- label="&toolkit.classic.download.window.label;" />
-#endif
-#ifdef XP_WIN
- <hbox align="center">
- <label id="zoneInfoLabel" control="zoneInfo-menu">&zoneInfo.label;</label>
- <menulist id="zoneInfo-menu"
- preference="browser.download.saveZoneInformation"
- sizetopopup="always">
- <menupopup>
- <menuitem label="&zoneInfo.never;" value="0" />
- <menuitem label="&zoneInfo.always;" value="1" />
- <menuitem label="&zoneInfo.system;" value="2" />
- </menupopup>
- </menulist>
- </hbox>
-#endif
- </groupbox>
-
- </prefpane>
-
-</overlay>
diff --git a/components/preferences/moz.build b/components/preferences/moz.build
deleted file mode 100644
index 31fddae..0000000
--- a/components/preferences/moz.build
+++ /dev/null
@@ -1,14 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-
-for var in ('MOZ_APP_NAME', 'MOZ_MACBUNDLE_NAME'):
- DEFINES[var] = CONFIG[var]
-
-if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk2', 'gtk3', 'cocoa'):
- DEFINES['HAVE_SHELL_SERVICE'] = 1
-
-JAR_MANIFESTS += ['jar.mn'] \ No newline at end of file
diff --git a/components/preferences/newtaburl.js b/components/preferences/newtaburl.js
deleted file mode 100644
index 3c82df8..0000000
--- a/components/preferences/newtaburl.js
+++ /dev/null
@@ -1,102 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-var gNewtabUrl = {
- /**
- * Writes browser.newtab.url with the appropriate value.
- * If the choice is "my home page", get and sanitize
- * the browser home page URL to make it suitable for newtab use.
- *
- * Called from prefwindow ondialogaccept in preferences.xul,
- * newtabPage oncommand in tabs.xul, browserHomePage oninput,
- * useCurrent, useBookmark and restoreDefaultHomePage oncommand
- * in main.xul to consider instantApply.
- */
- writeNewtabUrl: function(newtabUrlChoice, browserHomepageUrl) {
- try {
- if (newtabUrlChoice) {
- if (Services.prefs.getBoolPref("browser.preferences.instantApply")) {
- newtabUrlChoice = parseInt(newtabUrlChoice);
- } else {
- return;
- }
- } else {
- if (this.newtabUrlChoiceIsSet) {
- newtabUrlChoice = Services.prefs.getIntPref("browser.newtab.choice");
- } else {
- newtabUrlChoice = this.getNewtabChoice();
- }
- }
- if (browserHomepageUrl || browserHomepageUrl == "") {
- if (Services.prefs.getBoolPref("browser.preferences.instantApply")) {
- if (browserHomepageUrl == "") {
- browserHomepageUrl = "about:home";
- }
- } else {
- return;
- }
- } else {
- browserHomepageUrl = Services.prefs.getComplexValue("browser.startup.homepage",
- Components.interfaces.nsIPrefLocalizedString).data;
- }
- let newtabUrlPref = Services.prefs.getCharPref("browser.newtab.url");
- switch (newtabUrlChoice) {
- case 1:
- newtabUrlPref = "about:logopage";
- break;
- case 2:
- newtabUrlPref = Services.prefs.getDefaultBranch("browser.")
- .getComplexValue("startup.homepage",
- Components.interfaces.nsIPrefLocalizedString).data;
- break;
- case 3:
- // If url is a pipe-delimited set of pages, just take the first one.
- let newtabUrlSanitizedPref=browserHomepageUrl.split("|")[0];
- // XXX: do we need extra sanitation here, e.g. for invalid URLs?
- Services.prefs.setCharPref("browser.newtab.myhome", newtabUrlSanitizedPref);
- newtabUrlPref = newtabUrlSanitizedPref;
- break;
- case 4:
- newtabUrlPref = "about:newtab";
- break;
- default:
- // In case of any other value it's a custom URL, consider instantApply.
- if (this.newtabPageCustom) {
- newtabUrlPref = this.newtabPageCustom;
- }
- }
- Services.prefs.setCharPref("browser.newtab.url",newtabUrlPref);
- } catch(e) { console.error(e); }
- },
-
- /**
- * Determines the value of browser.newtab.choice based
- * on the value of browser.newtab.url
- *
- * @returns the value of browser.newtab.choice
- */
- getNewtabChoice: function() {
- let newtabUrlPref = Services.prefs.getCharPref("browser.newtab.url");
- let browserHomepageUrl = Services.prefs.getComplexValue("browser.startup.homepage",
- Components.interfaces.nsIPrefLocalizedString).data;
- let newtabUrlSanitizedPref = browserHomepageUrl.split("|")[0];
- let defaultStartupHomepage = Services.prefs.getDefaultBranch("browser.")
- .getComplexValue("startup.homepage",
- Components.interfaces.nsIPrefLocalizedString).data;
- switch (newtabUrlPref) {
- case "about:logopage":
- return 1;
- case defaultStartupHomepage:
- return 2;
- case newtabUrlSanitizedPref:
- return 3;
- case "about:newtab":
- return 4;
- default: // Custom URL entered.
- // We need this to consider instantApply.
- this.newtabPageCustom = newtabUrlPref;
- return 0;
- }
- }
-};
diff --git a/components/preferences/permissions.js b/components/preferences/permissions.js
deleted file mode 100644
index 4b1bf41..0000000
--- a/components/preferences/permissions.js
+++ /dev/null
@@ -1,463 +0,0 @@
-/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-Components.utils.import("resource://gre/modules/Services.jsm");
-
-const nsIPermissionManager = Components.interfaces.nsIPermissionManager;
-const nsICookiePermission = Components.interfaces.nsICookiePermission;
-
-const NOTIFICATION_FLUSH_PERMISSIONS = "flush-pending-permissions";
-
-function Permission(principal, type, capability)
-{
- this.principal = principal;
- this.origin = principal.origin;
- this.type = type;
- this.capability = capability;
-}
-
-var gPermissionManager = {
- _type : "",
- _permissions : [],
- _permissionsToAdd : new Map(),
- _permissionsToDelete : new Map(),
- _bundle : null,
- _tree : null,
- _observerRemoved : false,
-
- _view: {
- _rowCount: 0,
- get rowCount()
- {
- return this._rowCount;
- },
- getCellText: function (aRow, aColumn)
- {
- if (aColumn.id == "siteCol")
- return gPermissionManager._permissions[aRow].origin;
- 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){ return ""; },
- getColumnProperties: function(column){ return ""; },
- getCellProperties: function(row,column){
- if (column.element.getAttribute("id") == "siteCol")
- return "ltr";
-
- return "";
- }
- },
-
- _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_ALLOW_FIRST_PARTY_ONLY:
- stringKey = "canAccessFirstParty";
- break;
- case nsICookiePermission.ACCESS_SESSION:
- stringKey = "canSession";
- break;
- }
- return this._bundle.getString(stringKey);
- },
-
- addPermission: function (aCapability)
- {
- var textbox = document.getElementById("url");
- var input_url = textbox.value.replace(/^\s*/, ""); // trim any leading space
- let principal;
- try {
- // The origin accessor on the principal object will throw if the
- // principal doesn't have a canonical origin representation. This will
- // help catch cases where the URI parser parsed something like
- // `localhost:8080` as having the scheme `localhost`, rather than being
- // an invalid URI. A canonical origin representation is required by the
- // permission manager for storage, so this won't prevent any valid
- // permissions from being entered by the user.
- let uri;
- try {
- uri = Services.io.newURI(input_url, null, null);
- principal = Services.scriptSecurityManager.getNoAppCodebasePrincipal(uri);
- // If we have ended up with an unknown scheme, the following will throw.
- principal.origin;
- } catch(ex) {
- uri = Services.io.newURI("http://" + input_url, null, null);
- principal = Services.scriptSecurityManager.getNoAppCodebasePrincipal(uri);
- // If we have ended up with an unknown scheme, the following will throw.
- principal.origin;
- }
- } catch(ex) {
- var message = this._bundle.getString("invalidURI");
- var title = this._bundle.getString("invalidURITitle");
- Services.prompt.alert(window, title, message);
- return;
- }
-
- var capabilityString = this._getCapabilityString(aCapability);
-
- // check whether the permission already exists, if not, add it
- let permissionExists = false;
- let capabilityExists = false;
- for (var i = 0; i < this._permissions.length; ++i) {
- if (this._permissions[i].principal.equals(principal)) {
- permissionExists = true;
- capabilityExists = this._permissions[i].capability == capabilityString;
- if (!capabilityExists) {
- this._permissions[i].capability = capabilityString;
- }
- break;
- }
- }
-
-
- let permissionParams = {principal: principal, type: this._type, capability: aCapability};
- if (!permissionExists) {
- this._permissionsToAdd.set(principal.origin, permissionParams);
- this._addPermission(permissionParams);
- }
- else if (!capabilityExists) {
- this._permissionsToAdd.set(principal.origin, permissionParams);
- this._handleCapabilityChange();
- }
-
- 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;
- },
-
- _removePermission: function(aPermission)
- {
- this._removePermissionFromList(aPermission.principal);
-
- // If this permission was added during this session, let's remove
- // it from the pending adds list to prevent calls to the
- // permission manager.
- let isNewPermission = this._permissionsToAdd.delete(aPermission.principal.origin);
-
- if (!isNewPermission) {
- this._permissionsToDelete.set(aPermission.principal.origin, aPermission);
- }
-
- },
-
- _handleCapabilityChange: function ()
- {
- // 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 == "statusCol") {
- this._resortPermissions();
- }
- this._tree.treeBoxObject.invalidate();
- },
-
- _addPermission: function(aPermission)
- {
- this._addPermissionToList(aPermission);
- ++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.
- this._resortPermissions();
- },
-
- _resortPermissions: function()
- {
- gTreeUtils.sort(this._tree, this._view, this._permissions,
- this._lastPermissionSortColumn,
- this._permissionsComparator,
- this._lastPermissionSortColumn,
- !this._lastPermissionSortAscending); // keep sort direction
- },
-
- onHostInput: function (aSiteField)
- {
- document.getElementById("btnSession").disabled = !aSiteField.value;
- document.getElementById("btnBlock").disabled = !aSiteField.value;
- document.getElementById("btnAllow").disabled = !aSiteField.value;
- },
-
- onWindowKeyPress: function (aEvent)
- {
- if (aEvent.keyCode == KeyEvent.DOM_VK_ESCAPE)
- window.close();
- },
-
- 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;
-
- let treecols = document.getElementsByTagName("treecols")[0];
- treecols.addEventListener("click", event => {
- if (event.target.nodeName != "treecol" || event.button != 0) {
- return;
- }
-
- let sortField = event.target.getAttribute("data-field-name");
- if (!sortField) {
- return;
- }
-
- gPermissionManager.onPermissionSort(sortField);
- });
-
- Services.obs.notifyObservers(null, NOTIFICATION_FLUSH_PERMISSIONS, this._type);
- Services.obs.addObserver(this, "perm-changed", false);
-
- this._loadPermissions();
-
- urlField.focus();
- },
-
- uninit: function ()
- {
- if (!this._observerRemoved) {
- Services.obs.removeObserver(this, "perm-changed");
-
- this._observerRemoved = true;
- }
- },
-
- observe: function (aSubject, aTopic, aData)
- {
- if (aTopic == "perm-changed") {
- var permission = aSubject.QueryInterface(Components.interfaces.nsIPermission);
-
- // Ignore unrelated permission types.
- if (permission.type != this._type)
- return;
-
- if (aData == "added") {
- this._addPermission(permission);
- }
- else if (aData == "changed") {
- for (var i = 0; i < this._permissions.length; ++i) {
- if (permission.matches(this._permissions[i].principal, true)) {
- this._permissions[i].capability = this._getCapabilityString(permission.capability);
- break;
- }
- }
- this._handleCapabilityChange();
- }
- else if (aData == "deleted") {
- this._removePermissionFromList(permission.principal);
- }
- }
- },
-
- 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._removePermission(p);
- }
- 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._removePermission(p);
- }
- document.getElementById("removePermission").disabled = true;
- document.getElementById("removeAllPermissions").disabled = true;
- },
-
- onPermissionKeyPress: function (aEvent)
- {
- if (aEvent.keyCode == KeyEvent.DOM_VK_DELETE
-#ifdef XP_MACOSX
- || aEvent.keyCode == KeyEvent.DOM_VK_BACK_SPACE
-#endif
- ) {
- this.onPermissionDeleted();
- }
- },
-
- _lastPermissionSortColumn: "",
- _lastPermissionSortAscending: false,
- _permissionsComparator : function (a, b)
- {
- return a.toLowerCase().localeCompare(b.toLowerCase());
- },
-
-
- onPermissionSort: function (aColumn)
- {
- this._lastPermissionSortAscending = gTreeUtils.sort(this._tree,
- this._view,
- this._permissions,
- aColumn,
- this._permissionsComparator,
- this._lastPermissionSortColumn,
- this._lastPermissionSortAscending);
- this._lastPermissionSortColumn = aColumn;
- },
-
- onApplyChanges: function()
- {
- // Stop observing permission changes since we are about
- // to write out the pending adds/deletes and don't need
- // to update the UI
- this.uninit();
-
- for (let permissionParams of this._permissionsToAdd.values()) {
- Services.perms.addFromPrincipal(permissionParams.principal, permissionParams.type, permissionParams.capability);
- }
-
- for (let p of this._permissionsToDelete.values()) {
- Services.perms.removeFromPrincipal(p.principal, p.type);
- }
-
- window.close();
- },
-
- _loadPermissions: function ()
- {
- this._tree = document.getElementById("permissionsTree");
- this._permissions = [];
-
- // load permissions into a table
- var count = 0;
- var enumerator = Services.perms.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.view = this._view;
- this.onPermissionSort("origin");
-
- // 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 principal = aPermission.principal;
- var capabilityString = this._getCapabilityString(aPermission.capability);
- var p = new Permission(principal,
- aPermission.type,
- capabilityString);
- this._permissions.push(p);
- }
- },
-
- _removePermissionFromList: function (aPrincipal)
- {
- for (let i = 0; i < this._permissions.length; ++i) {
- if (this._permissions[i].principal.equals(aPrincipal)) {
- this._permissions.splice(i, 1);
- this._view._rowCount--;
- this._tree.treeBoxObject.rowCountChanged(this._view.rowCount - 1, -1);
- this._tree.treeBoxObject.invalidate();
- break;
- }
- }
- },
-
- setOrigin: function (aOrigin)
- {
- document.getElementById("url").value = aOrigin;
- }
-};
-
-function setOrigin(aOrigin)
-{
- gPermissionManager.setOrigin(aOrigin);
-}
-
-function initWithParams(aParams)
-{
- gPermissionManager.init(aParams);
-}
-
diff --git a/components/preferences/permissions.xul b/components/preferences/permissions.xul
deleted file mode 100644
index 33806cc..0000000
--- a/components/preferences/permissions.xul
+++ /dev/null
@@ -1,85 +0,0 @@
-<?xml version="1.0"?>
-
-<!-- -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -->
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
-<?xml-stylesheet href="chrome://browser/skin/preferences/preferences.css" type="text/css"?>
-
-<!DOCTYPE dialog SYSTEM "chrome://browser/locale/preferences/permissions.dtd" >
-
-<window id="PermissionsDialog" class="windowDialog"
- windowtype="Browser:Permissions"
- title="&window.title;"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- style="width: &window.width;;"
- onload="gPermissionManager.onLoad();"
- onunload="gPermissionManager.uninit();"
- persist="screenX screenY width height"
- onkeypress="gPermissionManager.onWindowKeyPress(event);">
-
- <script src="chrome://global/content/treeUtils.js"/>
- <script src="chrome://browser/content/preferences/permissions.js"/>
-
- <stringbundle id="bundlePreferences"
- src="chrome://browser/locale/preferences/preferences.properties"/>
-
- <keyset>
- <key key="&windowClose.key;" modifiers="accel" oncommand="window.close();"/>
- </keyset>
-
- <vbox class="contentPane" flex="1">
- <description id="permissionsText" control="url"/>
- <separator class="thin"/>
- <label id="urlLabel" control="url" value="&address.label;" accesskey="&address.accesskey;"/>
- <hbox align="start">
- <textbox id="url" flex="1"
- oninput="gPermissionManager.onHostInput(event.target);"
- onkeypress="gPermissionManager.onHostKeyPress(event);"/>
- </hbox>
- <hbox pack="end">
- <button id="btnBlock" disabled="true" label="&block.label;" accesskey="&block.accesskey;"
- oncommand="gPermissionManager.addPermission(nsIPermissionManager.DENY_ACTION);"/>
- <button id="btnSession" disabled="true" label="&session.label;" accesskey="&session.accesskey;"
- oncommand="gPermissionManager.addPermission(nsICookiePermission.ACCESS_SESSION);"/>
- <button id="btnAllow" disabled="true" label="&allow.label;" default="true" accesskey="&allow.accesskey;"
- oncommand="gPermissionManager.addPermission(nsIPermissionManager.ALLOW_ACTION);"/>
- </hbox>
- <separator class="thin"/>
- <tree id="permissionsTree" flex="1" style="height: 18em;"
- hidecolumnpicker="true"
- onkeypress="gPermissionManager.onPermissionKeyPress(event)"
- onselect="gPermissionManager.onPermissionSelected();">
- <treecols>
- <treecol id="siteCol" label="&treehead.sitename.label;" flex="3"
- data-field-name="origin" persist="width"/>
- <splitter class="tree-splitter"/>
- <treecol id="statusCol" label="&treehead.status.label;" flex="1"
- data-field-name="capability" persist="width"/>
- </treecols>
- <treechildren/>
- </tree>
- </vbox>
- <vbox>
- <hbox class="actionButtons" align="left" flex="1">
- <button id="removePermission" disabled="true"
- accesskey="&removepermission.accesskey;"
- icon="remove" label="&removepermission.label;"
- oncommand="gPermissionManager.onPermissionDeleted();"/>
- <button id="removeAllPermissions"
- icon="clear" label="&removeallpermissions.label;"
- accesskey="&removeallpermissions.accesskey;"
- oncommand="gPermissionManager.onAllPermissionsDeleted();"/>
- </hbox>
- <spacer flex="1"/>
- <hbox class="actionButtons" align="right" flex="1">
- <button oncommand="close();" icon="close"
- label="&button.cancel.label;" accesskey="&button.cancel.accesskey;" />
- <button id="btnApplyChanges" oncommand="gPermissionManager.onApplyChanges();" icon="save"
- label="&button.ok.label;" accesskey="&button.ok.accesskey;"/>
- </hbox>
- <resizer type="window" dir="bottomend"/>
- </vbox>
-</window>
diff --git a/components/preferences/preferences.xul b/components/preferences/preferences.xul
deleted file mode 100644
index a1d9c8c..0000000
--- a/components/preferences/preferences.xul
+++ /dev/null
@@ -1,92 +0,0 @@
-<?xml version="1.0"?>
-
-# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-<?xml-stylesheet href="chrome://global/skin/global.css"?>
-<?xml-stylesheet href="chrome://mozapps/content/preferences/preferences.css"?>
-<?xml-stylesheet href="chrome://browser/skin/preferences/preferences.css"?>
-
-<!-- XXX This should be in applications.xul, but bug 393953 means putting it
- - there causes the Applications pane not to work the first time you open
- - the Preferences dialog in a browsing session, so we work around the problem
- - by putting it here instead.
- -->
-<?xml-stylesheet href="chrome://browser/content/preferences/handlers.css"?>
-<?xml-stylesheet href="chrome://browser/skin/preferences/applications.css"?>
-
-<!DOCTYPE prefwindow [
-<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
-<!ENTITY % preferencesDTD SYSTEM "chrome://browser/locale/preferences/preferences.dtd">
-%brandDTD;
-%preferencesDTD;
-]>
-
-#ifdef XP_WIN
-#define USE_WIN_TITLE_STYLE
-#endif
-
-#ifdef XP_MACOSX
-<?xul-overlay href="chrome://browser/content/macBrowserOverlay.xul"?>
-#endif
-
-<prefwindow type="prefwindow"
- id="BrowserPreferences"
- windowtype="Browser:Preferences"
- ondialoghelp="openPrefsHelp()"
-#ifdef USE_WIN_TITLE_STYLE
- title="&prefWindow.titleWin;"
-#else
-#ifdef XP_UNIX
-#ifndef XP_MACOSX
- title="&prefWindow.titleGNOME;"
-#endif
-#endif
-#endif
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-#ifdef USE_WIN_TITLE_STYLE
- style="&prefWinMinSize.styleWin2;"
-#else
-#ifdef XP_MACOSX
- style="&prefWinMinSize.styleMac;"
-#else
- style="&prefWinMinSize.styleGNOME;"
-#endif
-#endif
- onunload="if (typeof gSecurityPane != 'undefined') gSecurityPane.syncAddonSecurityLevel();"
- ondialogaccept="gNewtabUrl.writeNewtabUrl();">
-
- <script type="application/javascript" src="chrome://browser/content/utilityOverlay.js"/>
- <script type="application/javascript" src="chrome://browser/content/preferences/newtaburl.js"/>
-
- <stringbundle id="bundleBrand" src="chrome://branding/locale/brand.properties"/>
- <stringbundle id="bundlePreferences"
- src="chrome://browser/locale/preferences/preferences.properties"/>
-
- <prefpane id="paneMain" label="&paneGeneral.title;"
- src="chrome://browser/content/preferences/main.xul"/>
- <prefpane id="paneTabs" label="&paneTabs.title;"
- src="chrome://browser/content/preferences/tabs.xul"/>
- <prefpane id="paneContent" label="&paneContent.title;"
- src="chrome://browser/content/preferences/content.xul"/>
- <prefpane id="paneApplications" label="&paneApplications.title;"
- src="chrome://browser/content/preferences/applications.xul"/>
- <prefpane id="panePrivacy" label="&panePrivacy.title;"
- src="chrome://browser/content/preferences/privacy.xul"/>
- <prefpane id="paneSecurity" label="&paneSecurity.title;"
- src="chrome://browser/content/preferences/security.xul"/>
-#ifdef MOZ_SERVICES_SYNC
- <prefpane id="paneSync" label="&paneSync.title;"
- src="chrome://browser/content/preferences/sync.xul"/>
-#endif
- <prefpane id="paneAdvanced" label="&paneAdvanced.title;"
- src="chrome://browser/content/preferences/advanced.xul"/>
-
-#ifdef XP_MACOSX
-#include ../../base/content/browserMountPoints.inc
-#endif
-
-</prefwindow>
-
diff --git a/components/preferences/privacy.js b/components/preferences/privacy.js
deleted file mode 100644
index e2a871a..0000000
--- a/components/preferences/privacy.js
+++ /dev/null
@@ -1,485 +0,0 @@
-/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-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,
-
- /**
- * Whether the prompt to restart Firefox should appear when changing the autostart pref.
- */
- _shouldPromptForRestart: true,
-
- /**
- * Sets up the UI for the number of days of history to keep, and updates the
- * label of the "Clear Now..." button.
- * Also restores the previously selected tab or tab index passed as argument.
- */
- init: function ()
- {
- this._inited = true;
- var privacyPrefs = document.getElementById("privacyPrefs");
-
- var extraArgs = window.arguments[1];
- if (extraArgs && extraArgs["privacyTab"]){
- privacyPrefs.selectedTab = document.getElementById(extraArgs["privacyTab"]);
- } else {
- var preference = document.getElementById("browser.preferences.privacy.selectedTabIndex");
- if (preference.value !== null)
- privacyPrefs.selectedIndex = preference.value;
- }
-
- this._updateSanitizeSettingsButton();
- this.initializeHistoryMode();
- this.updateHistoryModePane();
- this.updatePrivacyMicroControls();
- this.initAutoStartPrivateBrowsingReverter();
- },
-
- /**
- * Stores the identity of the current tab in preferences so that the selected
- * tab can be persisted between openings of the preferences window.
- */
- tabSelectionChanged: function ()
- {
- if (!this._inited)
- return;
- var privacyPrefs = document.getElementById("privacyPrefs");
- var preference = document.getElementById("browser.preferences.privacy.selectedTabIndex");
- preference.valueFromPreferences = privacyPrefs.selectedIndex;
- },
-
- // 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: [
- "places.history.enabled",
- "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: [
- "rememberHistory",
- "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":
- if (pref.value)
- pref.value = false;
-
- // select the remember history option
- document.getElementById("places.history.enabled").value = true;
-
- // 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":
- if (!pref.value)
- 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);
-
- const Ci = Components.interfaces;
- // adjust the cookie controls status
- this.readAcceptCookies();
- let lifetimePolicy = document.getElementById("network.cookie.lifetimePolicy").value;
- if (lifetimePolicy != Ci.nsICookieService.ACCEPT_NORMALLY &&
- lifetimePolicy != Ci.nsICookieService.ACCEPT_SESSION &&
- lifetimePolicy != Ci.nsICookieService.ACCEPT_FOR_N_DAYS) {
- lifetimePolicy = Ci.nsICookieService.ACCEPT_NORMALLY;
- }
- document.getElementById("keepCookiesUntil").value = disabled ? 2 : lifetimePolicy;
-
- // 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("rememberHistory").checked = disabled ? false :
- document.getElementById("places.history.enabled").value;
- document.getElementById("rememberForms").checked = disabled ? false :
- document.getElementById("browser.formfill.enable").value;
-
- if (!disabled) {
- // adjust the Settings button for sanitizeOnShutdown
- this._updateSanitizeSettingsButton();
- }
- }
- },
-
- // PRIVATE BROWSING
-
- /**
- * Initialize the starting state for the auto-start private browsing mode pref reverter.
- */
- initAutoStartPrivateBrowsingReverter: function PPP_initAutoStartPrivateBrowsingReverter()
- {
- let mode = document.getElementById("historyMode");
- let autoStart = document.getElementById("privateBrowsingAutoStart");
- this._lastMode = mode.selectedIndex;
- this._lastCheckState = autoStart.hasAttribute('checked');
- },
-
- _lastMode: null,
- _lasCheckState: null,
- updateAutostart: function PPP_updateAutostart() {
- let mode = document.getElementById("historyMode");
- let autoStart = document.getElementById("privateBrowsingAutoStart");
- let pref = document.getElementById("browser.privatebrowsing.autostart");
- if ((mode.value == "custom" && this._lastCheckState == autoStart.checked) ||
- (mode.value == "remember" && !this._lastCheckState) ||
- (mode.value == "dontremember" && this._lastCheckState)) {
- // These are all no-op changes, so we don't need to prompt.
- this._lastMode = mode.selectedIndex;
- this._lastCheckState = autoStart.hasAttribute('checked');
- return;
- }
-
- if (!this._shouldPromptForRestart) {
- // We're performing a revert. Just let it happen.
- return;
- }
-
- const Cc = Components.classes, Ci = Components.interfaces;
- let brandName = document.getElementById("bundleBrand").getString("brandShortName");
- let bundle = document.getElementById("bundlePreferences");
- let msg = bundle.getFormattedString(autoStart.checked ?
- "featureEnableRequiresRestart" : "featureDisableRequiresRestart",
- [brandName]);
- let title = bundle.getFormattedString("shouldRestartTitle", [brandName]);
- let prompts = Cc["@mozilla.org/embedcomp/prompt-service;1"].getService(Ci.nsIPromptService);
- let shouldProceed = prompts.confirm(window, title, msg)
- if (shouldProceed) {
- let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"]
- .createInstance(Ci.nsISupportsPRBool);
- Services.obs.notifyObservers(cancelQuit, "quit-application-requested",
- "restart");
- shouldProceed = !cancelQuit.data;
-
- if (shouldProceed) {
- pref.value = autoStart.hasAttribute('checked');
- document.documentElement.acceptDialog();
- let appStartup = Cc["@mozilla.org/toolkit/app-startup;1"]
- .getService(Ci.nsIAppStartup);
- appStartup.quit(Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart);
- return;
- }
- }
-
- this._shouldPromptForRestart = false;
-
- if (this._lastCheckState) {
- autoStart.checked = "checked";
- } else {
- autoStart.removeAttribute('checked');
- }
- mode.selectedIndex = this._lastMode;
- mode.doCommand();
-
- this._shouldPromptForRestart = true;
- },
-
- // HISTORY
-
- /*
- * Preferences:
- *
- * places.history.enabled
- * - whether history is enabled or not
- * browser.formfill.enable
- * - true if entries in forms and the search bar should be saved, false
- * otherwise
- */
-
- // COOKIES
-
- /*
- * Preferences:
- *
- * network.cookie.cookieBehavior
- * - determines how the browser should handle cookies:
- * 0 means enable all cookies
- * 1 means reject all third party cookies
- * 2 means disable all cookies
- * 3 means reject third party cookies unless at least one is already set for the eTLD
- * see netwerk/cookie/src/nsCookieService.cpp for details
- * network.cookie.lifetimePolicy
- * - determines how long cookies are stored:
- * 0 means keep cookies until they expire
- * 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 acceptThirdPartyLabel = document.getElementById("acceptThirdPartyLabel");
- var acceptThirdPartyMenu = document.getElementById("acceptThirdPartyMenu");
- 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);
-
- acceptThirdPartyLabel.disabled = acceptThirdPartyMenu.disabled = !acceptCookies;
- keepUntil.disabled = menu.disabled = this._autoStartPrivateBrowsing || !acceptCookies;
-
- return acceptCookies;
- },
-
- /**
- * 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 acceptThirdPartyMenu = document.getElementById("acceptThirdPartyMenu");
-
- // if we're enabling cookies, automatically select 'accept third party always'
- if (accept.checked)
- acceptThirdPartyMenu.selectedIndex = 0;
-
- return accept.checked ? 0 : 2;
- },
-
- /**
- * Converts between network.cookie.cookieBehavior and the third-party cookie UI
- */
- readAcceptThirdPartyCookies: function ()
- {
- var pref = document.getElementById("network.cookie.cookieBehavior");
- switch (pref.value)
- {
- case 0:
- return "always";
- case 1:
- return "never";
- case 2:
- return "never";
- case 3:
- return "visited";
- default:
- return undefined;
- }
- },
-
- writeAcceptThirdPartyCookies: function ()
- {
- var accept = document.getElementById("acceptThirdPartyMenu").selectedItem;
- switch (accept.value)
- {
- case "always":
- return 0;
- case "visited":
- return 3;
- case "never":
- return 1;
- default:
- return undefined;
- }
- },
-
- /**
- * 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;
- Services.obs.notifyObservers(null, "clear-private-data", null);
- },
-
- /**
- * 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;
- }
-
-};
diff --git a/components/preferences/privacy.xul b/components/preferences/privacy.xul
deleted file mode 100644
index d2f8106..0000000
--- a/components/preferences/privacy.xul
+++ /dev/null
@@ -1,273 +0,0 @@
-<?xml version="1.0"?>
-
-<!-- -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -->
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!DOCTYPE overlay [
-<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
-<!ENTITY % privacyDTD SYSTEM "chrome://browser/locale/preferences/privacy.dtd">
-%brandDTD;
-%privacyDTD;
-]>
-
-<overlay id="PrivacyPaneOverlay"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml">
-
- <prefpane id="panePrivacy"
- onpaneload="gPrivacyPane.init();"
- helpTopic="prefs-privacy">
-
- <preferences id="privacyPreferences">
-
- <preference id="browser.preferences.privacy.selectedTabIndex"
- name="browser.preferences.privacy.selectedTabIndex"
- type="int"/>
-
- <!-- Tracking -->
- <preference id="privacy.donottrackheader.enabled"
- name="privacy.donottrackheader.enabled"
- type="bool"/>
-
- <!-- XXX button prefs -->
- <preference id="pref.privacy.disable_button.cookie_exceptions"
- name="pref.privacy.disable_button.cookie_exceptions"
- type="bool"/>
- <preference id="pref.privacy.disable_button.view_cookies"
- name="pref.privacy.disable_button.view_cookies"
- type="bool"/>
-
- <!-- Location Bar -->
- <preference id="browser.urlbar.autocomplete.enabled"
- name="browser.urlbar.autocomplete.enabled"
- type="bool"/>
- <preference id="browser.urlbar.suggest.bookmark"
- name="browser.urlbar.suggest.bookmark"
- type="bool"/>
- <preference id="browser.urlbar.suggest.history"
- name="browser.urlbar.suggest.history"
- type="bool"/>
- <preference id="browser.urlbar.suggest.openpage"
- name="browser.urlbar.suggest.openpage"
- type="bool"/>
-
- <!-- History -->
- <preference id="places.history.enabled"
- name="places.history.enabled"
- type="bool"/>
- <preference id="browser.formfill.enable"
- name="browser.formfill.enable"
- type="bool"/>
-
- <!-- Cookies -->
- <preference id="network.cookie.cookieBehavior" name="network.cookie.cookieBehavior" type="int"/>
- <preference id="network.cookie.lifetimePolicy" name="network.cookie.lifetimePolicy" type="int"/>
- <preference id="network.cookie.blockFutureCookies" name="network.cookie.blockFutureCookies" type="bool"/>
-
- <!-- Clear Private Data -->
- <preference id="privacy.sanitize.sanitizeOnShutdown"
- name="privacy.sanitize.sanitizeOnShutdown"
- onchange="gPrivacyPane._updateSanitizeSettingsButton();"
- type="bool"/>
- <preference id="privacy.sanitize.timeSpan"
- name="privacy.sanitize.timeSpan"
- type="int"/>
-
- <!-- Private Browsing -->
- <preference id="browser.privatebrowsing.autostart"
- name="browser.privatebrowsing.autostart"
- onchange="gPrivacyPane.updatePrivacyMicroControls();"
- type="bool"/>
-
- </preferences>
-
- <stringbundle id="bundlePreferences" src="chrome://browser/locale/preferences/preferences.properties"/>
-
- <script type="application/javascript" src="chrome://browser/content/preferences/privacy.js"/>
-
- <tabbox id="privacyPrefs" flex="1"
- onselect="gPrivacyPane.tabSelectionChanged();">
-
- <tabs id="tabsElement">
- <tab id="historyTab" label="&history.label;"/>
- <tab id="trackingTab" label="&tracking.label;"/>
- <tab id="locationBarTab" label="&locationBar.label;"/>
- </tabs>
-
- <tabpanels flex="1">
-
- <!-- History -->
- <tabpanel id="historyPanel" orient="vertical">
-
- <hbox align="center">
- <label id="historyModeLabel"
- control="historyMode"
- accesskey="&historyHeader.pre.accesskey;">&historyHeader.pre.label;</label>
- <menulist id="historyMode"
- oncommand="gPrivacyPane.updateHistoryModePane();
- gPrivacyPane.updateHistoryModePrefs();
- gPrivacyPane.updatePrivacyMicroControls();
- gPrivacyPane.updateAutostart();">
- <menupopup>
- <menuitem label="&historyHeader.remember.label;" value="remember"/>
- <menuitem label="&historyHeader.dontremember.label;" value="dontremember"/>
- <menuitem label="&historyHeader.custom.label;" value="custom"/>
- </menupopup>
- </menulist>
- <label>&historyHeader.post.label;</label>
- </hbox>
-
- <deck id="historyPane">
- <vbox align="center" id="historyRememberPane">
- <hbox align="center" flex="1">
- <spacer flex="1" class="indent"/>
- <vbox flex="2">
- <description>&rememberDescription.label;</description>
- <separator/>
- <description>&rememberActions.pre.label;<html:a
- class="inline-link" href="#"
- onclick="gPrivacyPane.clearPrivateDataNow(false); return false;"
- >&rememberActions.clearHistory.label;</html:a>&rememberActions.middle.label;<html:a
- class="inline-link" href="#"
- onclick="gPrivacyPane.showCookies(); return false;"
- >&rememberActions.removeCookies.label;</html:a>&rememberActions.post.label;</description>
- </vbox>
- <spacer flex="1" class="indent"/>
- </hbox>
- </vbox>
- <vbox align="center" id="historyDontRememberPane">
- <hbox align="center" flex="1">
- <spacer flex="1" class="indent"/>
- <vbox flex="2">
- <description>&dontrememberDescription.label;</description>
- <separator/>
- <description>&dontrememberActions.pre.label;<html:a
- class="inline-link" href="#"
- onclick="gPrivacyPane.clearPrivateDataNow(true); return false;"
- >&dontrememberActions.clearHistory.label;</html:a>&dontrememberActions.post.label;</description>
- </vbox>
- <spacer flex="1" class="indent"/>
- </hbox>
- </vbox>
- <vbox id="historyCustomPane">
- <separator class="thin"/>
- <checkbox id="privateBrowsingAutoStart" class="indent"
- label="&privateBrowsingPermanent2.label;"
- accesskey="&privateBrowsingPermanent2.accesskey;"
- preference="browser.privatebrowsing.autostart"
- oncommand="gPrivacyPane.updateAutostart()"/>
-
- <vbox class="indent">
- <vbox class="indent">
- <checkbox id="rememberHistory"
- label="&rememberHistory2.label;"
- accesskey="&rememberHistory2.accesskey;"
- preference="places.history.enabled"/>
- <checkbox id="rememberForms"
- label="&rememberSearchForm.label;"
- accesskey="&rememberSearchForm.accesskey;"
- preference="browser.formfill.enable"/>
-
- <hbox id="cookiesBox">
- <checkbox id="acceptCookies" label="&acceptCookies.label;" flex="1"
- preference="network.cookie.cookieBehavior"
- accesskey="&acceptCookies.accesskey;"
- onsyncfrompreference="return gPrivacyPane.readAcceptCookies();"
- onsynctopreference="return gPrivacyPane.writeAcceptCookies();"/>
- <button id="cookieExceptions" oncommand="gPrivacyPane.showCookieExceptions();"
- label="&cookieExceptions.label;" accesskey="&cookieExceptions.accesskey;"
- preference="pref.privacy.disable_button.cookie_exceptions"/>
- </hbox>
-
- <hbox id="acceptThirdPartyRow" class="indent">
- <hbox id="acceptThirdPartyBox" align="center">
- <label id="acceptThirdPartyLabel" control="acceptThirdPartyMenu"
- accesskey="&acceptThirdParty.pre.accesskey;">&acceptThirdParty.pre.label;</label>
- <menulist id="acceptThirdPartyMenu" preference="network.cookie.cookieBehavior"
- onsyncfrompreference="return gPrivacyPane.readAcceptThirdPartyCookies();"
- onsynctopreference="return gPrivacyPane.writeAcceptThirdPartyCookies();">
- <menupopup>
- <menuitem label="&acceptThirdParty.always.label;" value="always"/>
- <menuitem label="&acceptThirdParty.visited.label;" value="visited"/>
- <menuitem label="&acceptThirdParty.never.label;" value="never"/>
- </menupopup>
- </menulist>
- </hbox>
- </hbox>
-
- <hbox id="keepRow" class="indent">
- <hbox id="keepBox" align="center">
- <label id="keepUntil"
- control="keepCookiesUntil"
- accesskey="&keepUntil.accesskey;">&keepUntil.label;</label>
- <menulist id="keepCookiesUntil"
- preference="network.cookie.lifetimePolicy">
- <menupopup>
- <menuitem label="&expire.label;" value="0"/>
- <menuitem label="&close.label;" value="2"/>
- </menupopup>
- </menulist>
- </hbox>
- <hbox flex="1"/>
- <button id="showCookiesButton"
- label="&showCookies.label;" accesskey="&showCookies.accesskey;"
- oncommand="gPrivacyPane.showCookies();"
- preference="pref.privacy.disable_button.view_cookies"/>
- </hbox>
-
- <hbox id="clearDataBox" align="center">
- <checkbox id="alwaysClear" flex="1"
- preference="privacy.sanitize.sanitizeOnShutdown"
- label="&clearOnClose.label;"
- accesskey="&clearOnClose.accesskey;"/>
- <button id="clearDataSettings" label="&clearOnCloseSettings.label;"
- accesskey="&clearOnCloseSettings.accesskey;"
- oncommand="gPrivacyPane.showClearPrivateDataSettings();"/>
- </hbox>
- </vbox>
- </vbox>
- </vbox>
- </deck>
-
- </tabpanel>
-
- <!-- Tracking -->
- <tabpanel id="trackingPanel" orient="vertical">
-
- <checkbox id="privacyDoNotTrackCheckbox"
- label="&dntTrackingNotOkay.label2;"
- accesskey="&dntTrackingNotOkay.accesskey;"
- preference="privacy.donottrackheader.enabled"/>
- <separator class="thin"/>
- <label class="text-link" id="doNotTrackInfo"
- href="https://www.mozilla.org/dnt"
- value="&doNotTrackInfo.label;"/>
-
- </tabpanel>
-
- <!-- Location Bar -->
- <tabpanel id="locatioBarPanel" orient="vertical">
-
- <label id="locationBarSuggestionLabel">&locbar.suggest.label;</label>
-
- <vbox id="tabPrefsBox" align="start" flex="1">
- <checkbox id="historySuggestion" label="&locbar.history.label;"
- accesskey="&locbar.history.accesskey;"
- preference="browser.urlbar.suggest.history"/>
- <checkbox id="bookmarkSuggestion" label="&locbar.bookmarks.label;"
- accesskey="&locbar.bookmarks.accesskey;"
- preference="browser.urlbar.suggest.bookmark"/>
- <checkbox id="openpageSuggestion" label="&locbar.openpage.label;"
- accesskey="&locbar.openpage.accesskey;"
- preference="browser.urlbar.suggest.openpage"/>
- </vbox>
-
- </tabpanel>
-
- </tabpanels>
- </tabbox>
- </prefpane>
-
-</overlay>
diff --git a/components/preferences/sanitize.js b/components/preferences/sanitize.js
deleted file mode 100644
index 15e6f58..0000000
--- a/components/preferences/sanitize.js
+++ /dev/null
@@ -1,12 +0,0 @@
-/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-var gSanitizeDialog = Object.freeze({
- onClearHistoryChanged: function () {
- let downloadsPref = document.getElementById("privacy.clearOnShutdown.downloads");
- let historyPref = document.getElementById("privacy.clearOnShutdown.history");
- downloadsPref.value = historyPref.value;
- }
-});
diff --git a/components/preferences/sanitize.xul b/components/preferences/sanitize.xul
deleted file mode 100644
index 829b5df..0000000
--- a/components/preferences/sanitize.xul
+++ /dev/null
@@ -1,108 +0,0 @@
-<?xml version="1.0"?>
-
-<!-- -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -->
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<?xml-stylesheet href="chrome://global/skin/"?>
-<?xml-stylesheet href="chrome://browser/skin/preferences/preferences.css" type="text/css"?>
-
-<!DOCTYPE dialog [
- <!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
- <!ENTITY % sanitizeDTD SYSTEM "chrome://browser/locale/sanitize.dtd">
- %brandDTD;
- %sanitizeDTD;
-]>
-
-<prefwindow id="SanitizeDialog" type="child"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- dlgbuttons="accept,cancel,help"
- ondialoghelp="openPrefsHelp()"
- style="width: &dialog.width2;;"
- title="&sanitizePrefs2.title;"
- onload="gSanitizeDialog.onClearHistoryChanged();">
-
- <script type="application/javascript" src="chrome://browser/content/utilityOverlay.js"/>
- <script type="application/javascript" src="chrome://browser/content/preferences/sanitize.js"/>
-
- <prefpane id="SanitizeDialogPane"
- helpTopic="prefs-clear-private-data">
-
- <preferences>
- <preference id="privacy.clearOnShutdown.history" name="privacy.clearOnShutdown.history" type="bool"
- onchange="return gSanitizeDialog.onClearHistoryChanged();"/>
- <preference id="privacy.clearOnShutdown.formdata" name="privacy.clearOnShutdown.formdata" type="bool"/>
- <preference id="privacy.clearOnShutdown.passwords" name="privacy.clearOnShutdown.passwords" type="bool"/>
- <preference id="privacy.clearOnShutdown.downloads" name="privacy.clearOnShutdown.downloads" type="bool"/>
- <preference id="privacy.clearOnShutdown.cookies" name="privacy.clearOnShutdown.cookies" type="bool"/>
- <preference id="privacy.clearOnShutdown.cache" name="privacy.clearOnShutdown.cache" type="bool"/>
- <preference id="privacy.clearOnShutdown.offlineApps" name="privacy.clearOnShutdown.offlineApps" type="bool"/>
- <preference id="privacy.clearOnShutdown.sessions" name="privacy.clearOnShutdown.sessions" type="bool"/>
- <preference id="privacy.clearOnShutdown.siteSettings" name="privacy.clearOnShutdown.siteSettings" type="bool"/>
- <preference id="privacy.clearOnShutdown.connectivityData" name="privacy.clearOnShutdown.connectivityData" type="bool"/>
- </preferences>
-
- <description>&clearDataSettings2.label;</description>
-
- <groupbox orient="horizontal">
- <caption label="&historySection.label;"/>
- <grid flex="1">
- <columns>
- <column style="width: &column.width2;"/>
- <column flex="1"/>
- </columns>
- <rows>
- <row>
- <checkbox label="&itemHistoryAndDownloads.label;"
- accesskey="&itemHistoryAndDownloads.accesskey;"
- preference="privacy.clearOnShutdown.history"/>
- <checkbox label="&itemCookies.label;"
- accesskey="&itemCookies.accesskey;"
- preference="privacy.clearOnShutdown.cookies"/>
- </row>
- <row>
- <checkbox label="&itemActiveLogins.label;"
- accesskey="&itemActiveLogins.accesskey;"
- preference="privacy.clearOnShutdown.sessions"/>
- <checkbox label="&itemCache.label;"
- accesskey="&itemCache.accesskey;"
- preference="privacy.clearOnShutdown.cache"/>
- </row>
- <row>
- <checkbox label="&itemFormSearchHistory.label;"
- accesskey="&itemFormSearchHistory.accesskey;"
- preference="privacy.clearOnShutdown.formdata"/>
- </row>
- </rows>
- </grid>
- </groupbox>
- <groupbox orient="horizontal">
- <caption label="&dataSection.label;"/>
- <grid flex="1">
- <columns>
- <column style="width: &column.width2;"/>
- <column flex="1"/>
- </columns>
- <rows>
- <row>
- <checkbox label="&itemPasswords.label;"
- accesskey="&itemPasswords.accesskey;"
- preference="privacy.clearOnShutdown.passwords"/>
- <checkbox label="&itemOfflineApps.label;"
- accesskey="&itemOfflineApps.accesskey;"
- preference="privacy.clearOnShutdown.offlineApps"/>
- </row>
- <row>
- <checkbox label="&itemSitePreferences.label;"
- accesskey="&itemSitePreferences.accesskey;"
- preference="privacy.clearOnShutdown.siteSettings"/>
- <checkbox label="&itemConnectivityData.label;"
- accesskey="&itemConnectivityData.accesskey;"
- preference="privacy.clearOnShutdown.connectivityData"/>
- </row>
- </rows>
- </grid>
- </groupbox>
- </prefpane>
-</prefwindow>
diff --git a/components/preferences/security.js b/components/preferences/security.js
deleted file mode 100644
index a0f283d..0000000
--- a/components/preferences/security.js
+++ /dev/null
@@ -1,251 +0,0 @@
-/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-XPCOMUtils.defineLazyModuleGetter(this, "LoginHelper",
- "resource://gre/modules/LoginHelper.jsm");
-
-Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
-
-var gSecurityPane = {
- _pane: null,
-
- /**
- * Initializes 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"
- },
-
- /**
- * Ensures that the blocklist is enabled/disabled appropriately based on level
- */
- addonLevelNeedsSync: function()
- {
- Services.prefs.setBoolPref("extensions.blocklist.level.updated", true);
- },
- // called from preferences window onunload.
- syncAddonSecurityLevel: function()
- {
- if (Services.prefs.getBoolPref("extensions.blocklist.level.updated") == true) {
- Services.prefs.setBoolPref("extensions.blocklist.level.updated", false);
- var secLevel = Services.prefs.getIntPref("extensions.blocklist.level");
- Services.prefs.setBoolPref("extensions.blocklist.enabled",
- !(secLevel == 99));
- }
- },
-
- // 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. When browser is set to start in Private
- * Browsing mode, the "Remember passwords" UI is useless, so we disable it.
- */
- readSavePasswords: function ()
- {
- var pref = document.getElementById("signon.rememberSignons");
- var excepts = document.getElementById("passwordExceptions");
-
- if (PrivateBrowsingUtils.permanentPrivateBrowsing) {
- document.getElementById("savePasswords").disabled = true;
- excepts.disabled = true;
- return false;
- } else {
- 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 ()
- {
- let bundlePrefs = document.getElementById("bundlePreferences");
- let params = {
- blockVisible: true,
- sessionVisible: false,
- allowVisible: false,
- hideStatusColumn: true,
- prefilledHost: "",
- permissionType: "login-saving",
- windowTitle: bundlePrefs.getString("savedLoginsExceptions_title"),
- introText: bundlePrefs.getString("savedLoginsExceptions_desc")
- };
-
- document.documentElement.openWindow("Toolkit:PasswordManagerExceptions",
- "chrome://browser/content/preferences/permissions.xul",
- null, params);
- },
-
- /**
- * 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 = !LoginHelper.isMasterPasswordSet();
-
- var button = document.getElementById("changeMasterPassword");
- button.disabled = noMP;
-
- var checkbox = document.getElementById("useMasterPassword");
- checkbox.checked = !noMP;
- },
-
- /**
- * 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);
- },
-
- /**
- * Updates the HPKP enforcement level to the proper value depending on checkbox
- * state.
- */
- updateHPKPPref: function() {
- let checkbox = document.getElementById("enableHPKP");
- let HPKPpref = document.getElementById("security.cert_pinning.enforcement_level");
-
- if (checkbox.checked) {
- HPKPpref.value = 2;
- } else {
- HPKPpref.value = 0;
- }
- }
-};
diff --git a/components/preferences/security.xul b/components/preferences/security.xul
deleted file mode 100644
index bae6cca..0000000
--- a/components/preferences/security.xul
+++ /dev/null
@@ -1,181 +0,0 @@
-<?xml version="1.0"?>
-
-<!-- -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -->
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!DOCTYPE overlay [
- <!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
- <!ENTITY % securityDTD SYSTEM "chrome://browser/locale/preferences/security.dtd">
- %brandDTD;
- %securityDTD;
-]>
-
-<overlay id="SecurityPaneOverlay"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-
- <prefpane id="paneSecurity"
- onpaneload="gSecurityPane.init();"
- helpTopic="prefs-security">
-
- <preferences id="securityPreferences">
- <!-- XXX buttons -->
- <preference id="pref.privacy.disable_button.view_passwords"
- name="pref.privacy.disable_button.view_passwords"
- type="bool"/>
- <preference id="pref.privacy.disable_button.view_passwords_exceptions"
- name="pref.privacy.disable_button.view_passwords_exceptions"
- type="bool"/>
-
- <!-- Add-ons, malware, phishing -->
- <preference id="xpinstall.whitelist.required"
- name="xpinstall.whitelist.required"
- type="bool"/>
- <preference id="extensions.blocklist.level"
- name="extensions.blocklist.level"
- onchange="gSecurityPane.addonLevelNeedsSync();"
- type="int"/>
-
- <!-- Passwords -->
- <preference id="signon.rememberSignons" name="signon.rememberSignons" type="bool"/>
- <preference id="signon.autofillForms" name="signon.autofillForms" type="bool"/>
-
- <!-- Security Protocols -->
-
- <preference id="network.stricttransportsecurity.enabled"
- name="network.stricttransportsecurity.enabled"
- type="bool"/>
-
- <!-- Opportunistic Encryption -->
-
- <preference id="network.http.upgrade-insecure-requests"
- name="network.http.upgrade-insecure-requests"
- type="bool"/>
- <preference id="network.http.altsvc.oe"
- name="network.http.altsvc.oe"
- type="bool"/>
-
- <!-- XSS Filter -->
- <!--
- <preference id="security.xssfilter.enable" name="security.xssfilter.enable" type="bool"/>
- -->
-
- </preferences>
-
- <script type="application/javascript" src="chrome://browser/content/preferences/security.js"/>
-
- <stringbundle id="bundlePreferences" src="chrome://browser/locale/preferences/preferences.properties"/>
-
- <!-- addons, forgery (phishing) UI -->
- <groupbox id="addonsSecurityGroup">
- <caption label="&addons.label;"/>
-
- <hbox id="addonInstallBox">
- <checkbox id="warnAddonInstall" flex="1"
- label="&warnAddonInstall.label;"
- accesskey="&warnAddonInstall.accesskey;"
- preference="xpinstall.whitelist.required"
- onsyncfrompreference="return gSecurityPane.readWarnAddonInstall();"/>
- <button id="addonExceptions"
- label="&addonExceptions.label;"
- accesskey="&addonExceptions.accesskey;"
- oncommand="gSecurityPane.showAddonExceptions();"/>
- </hbox>
- <hbox id="addonSecuritySettingsBox" flex="1">
- <vbox>
- <label id="addonSecurity" control="addonsecurity-menu">&addonSecuritylevel;</label>
- <menulist id="addonsecurity-menu" preference="extensions.blocklist.level" sizetopopup="always">
- <menupopup>
- <menuitem label="&addonSecurityLevel_Off;" value="99" />
- <menuitem label="&addonSecurityLevel_Low;" value="3" />
- <menuitem label="&addonSecurityLevel_High;" value="2" />
- <menuitem label="&addonSecurityLevel_Extreme;" value="1" />
- </menupopup>
- </menulist>
- </vbox>
- </hbox>
- </groupbox>
-
- <!-- Passwords -->
- <groupbox id="passwordsGroup" orient="vertical">
- <caption label="&passwords.label;"/>
-
- <hbox id="savePasswordsBox">
- <checkbox id="savePasswords" flex="1"
- label="&rememberPasswords.label;" accesskey="&rememberPasswords.accesskey;"
- preference="signon.rememberSignons"
- onsyncfrompreference="return gSecurityPane.readSavePasswords();"/>
- <button id="passwordExceptions"
- label="&passwordExceptions.label;"
- accesskey="&passwordExceptions.accesskey;"
- oncommand="gSecurityPane.showPasswordExceptions();"
- preference="pref.privacy.disable_button.view_passwords_exceptions"/>
- </hbox>
- <checkbox id="autofillPasswords" flex="1"
- label="&autofillPasswords.label;" accesskey="&autofillPasswords.accesskey;"
- preference="signon.autofillForms"/>
- <hbox id="masterPasswordBox">
- <checkbox id="useMasterPassword" flex="1"
- oncommand="gSecurityPane.updateMasterPasswordButton();"
- label="&useMasterPassword.label;"
- accesskey="&useMasterPassword.accesskey;"/>
- <button id="changeMasterPassword"
- label="&changeMasterPassword.label;"
- accesskey="&changeMasterPassword.accesskey;"
- oncommand="gSecurityPane.changeMasterPassword();"/>
- </hbox>
-
- <hbox id="showPasswordsBox">
- <spacer flex="1"/>
- <button id="showPasswords"
- label="&savedPasswords.label;" accesskey="&savedPasswords.accesskey;"
- oncommand="gSecurityPane.showPasswords();"
- preference="pref.privacy.disable_button.view_passwords"/>
- </hbox>
- </groupbox>
-
- <!-- Security protocols -->
- <groupbox id="SecProtoGroup">
- <caption label="&SecProto.label;"/>
-
- <vbox id="SecProtoBox" align="start" flex="1">
- <checkbox id="enableHSTS"
- label="&enableHSTS.label;"
- accesskey="&enableHSTS.accesskey;"
- preference="network.stricttransportsecurity.enabled" />
- <checkbox id="enableHPKP"
- label="&enableHPKP.label;"
- accesskey="&enableHPKP.accesskey;"
- preference="security.cert_pinning.hpkp.enabled"/>
- </vbox>
- </groupbox>
-
- <groupbox id="OpportunisticEncryption">
- <caption label="&OpEnc.label;"/>
- <checkbox id="enableUIROpEnc"
- label="&enableUIROpEnc.label;"
- preference="network.http.upgrade-insecure-requests" />
- <checkbox id="enableAltSvcOpEnc"
- label="&enableAltSvcOpEnc.label;"
- preference="network.http.altsvc.oe" />
- </groupbox>
-
- <!-- XSS Filter -->
- <!--
- <groupbox id="XSSFiltGroup">
- <caption label="&XSSFilt.label;"/>
-
- <hbox id="XSSFiltBox">
- <checkbox id="enableXSSFilt" flex="1"
- label="&enableXSSFilt.label;"
- accesskey="&enableXSSFilt.accesskey;"
- preference="security.xssfilter.enable" />
- </hbox>
-
- </groupbox>
- -->
-
- </prefpane>
-
-</overlay>
diff --git a/components/preferences/selectBookmark.js b/components/preferences/selectBookmark.js
deleted file mode 100644
index c7ce022..0000000
--- a/components/preferences/selectBookmark.js
+++ /dev/null
@@ -1,83 +0,0 @@
-//* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/**
- * 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);
- }
- }
- contents.containerOpen = false;
- }
- else {
- urls.push(selectedNode.uri);
- names.push(selectedNode.title);
- }
- window.arguments[0].urls = urls;
- window.arguments[0].names = names;
- }
-};
diff --git a/components/preferences/selectBookmark.xul b/components/preferences/selectBookmark.xul
deleted file mode 100644
index 5547534..0000000
--- a/components/preferences/selectBookmark.xul
+++ /dev/null
@@ -1,44 +0,0 @@
-<?xml version="1.0"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-
-<?xml-stylesheet href="chrome://browser/content/places/places.css"?>
-
-<?xml-stylesheet href="chrome://global/skin/"?>
-<?xml-stylesheet href="chrome://browser/skin/places/places.css"?>
-
-<?xul-overlay href="chrome://browser/content/places/placesOverlay.xul"?>
-
-<!DOCTYPE dialog SYSTEM "chrome://browser/locale/preferences/selectBookmark.dtd">
-
-<dialog id="selectBookmarkDialog"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- title="&selectBookmark.title;" style="width: 32em;"
- persist="screenX screenY width height" screenX="24" screenY="24"
- onload="SelectBookmarkDialog.init();"
- ondialogaccept="SelectBookmarkDialog.accept();">
-
- <script type="application/javascript"
- src="chrome://browser/content/preferences/selectBookmark.js"/>
-
- <description>&selectBookmark.label;</description>
-
- <separator class="thin"/>
-
- <tree id="bookmarks" flex="1" type="places"
- style="height: 15em;"
- hidecolumnpicker="true"
- seltype="single"
- ondblclick="SelectBookmarkDialog.onItemDblClick();"
- onselect="SelectBookmarkDialog.selectionChanged();">
- <treecols>
- <treecol id="title" flex="1" primary="true" hideheader="true"/>
- </treecols>
- <treechildren id="bookmarksChildren" flex="1"/>
- </tree>
-
- <separator class="thin"/>
-
-</dialog>
diff --git a/components/preferences/sync.js b/components/preferences/sync.js
deleted file mode 100644
index f29728d..0000000
--- a/components/preferences/sync.js
+++ /dev/null
@@ -1,192 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-Components.utils.import("resource://services-sync/main.js");
-Components.utils.import("resource://gre/modules/Services.jsm");
-
-const PAGE_NO_ACCOUNT = 0;
-const PAGE_HAS_ACCOUNT = 1;
-const PAGE_NEEDS_UPDATE = 2;
-
-var gSyncPane = {
- _stringBundle: null,
- prefArray: ["engine.bookmarks", "engine.passwords", "engine.prefs",
- "engine.tabs", "engine.history"],
-
- get page() {
- return document.getElementById("weavePrefsDeck").selectedIndex;
- },
-
- set page(val) {
- document.getElementById("weavePrefsDeck").selectedIndex = val;
- },
-
- get _usingCustomServer() {
- return Weave.Svc.Prefs.isSet("serverURL");
- },
-
- needsUpdate: function () {
- this.page = PAGE_NEEDS_UPDATE;
- let label = document.getElementById("loginError");
- label.value = Weave.Utils.getErrorString(Weave.Status.login);
- label.className = "error";
- },
-
- init: function () {
- // If the Service hasn't finished initializing, wait for it.
- let xps = Components.classes["@mozilla.org/weave/service;1"]
- .getService(Components.interfaces.nsISupports)
- .wrappedJSObject;
-
- if (xps.ready) {
- this._init();
- return;
- }
-
- let onUnload = function () {
- window.removeEventListener("unload", onUnload, false);
- try {
- Services.obs.removeObserver(onReady, "weave:service:ready");
- } catch (e) {}
- };
-
- let onReady = function () {
- Services.obs.removeObserver(onReady, "weave:service:ready");
- window.removeEventListener("unload", onUnload, false);
- this._init();
- }.bind(this);
-
- Services.obs.addObserver(onReady, "weave:service:ready", false);
- window.addEventListener("unload", onUnload, false);
-
- xps.ensureLoaded();
- },
-
- _init: function () {
- let topics = ["weave:service:login:error",
- "weave:service:login:finish",
- "weave:service:start-over",
- "weave:service:setup-complete",
- "weave:service:logout:finish"];
-
- // Add the observers now and remove them on unload
- //XXXzpao This should use Services.obs.* but Weave's Obs does nice handling
- // of `this`. Fix in a followup. (bug 583347)
- topics.forEach(function (topic) {
- Weave.Svc.Obs.add(topic, this.updateWeavePrefs, this);
- }, this);
- window.addEventListener("unload", function() {
- topics.forEach(function (topic) {
- Weave.Svc.Obs.remove(topic, this.updateWeavePrefs, this);
- }, gSyncPane);
- }, false);
-
- this._stringBundle =
- Services.strings.createBundle("chrome://browser/locale/preferences/preferences.properties");
- this.updateWeavePrefs();
- },
-
- updateWeavePrefs: function () {
- if (Weave.Status.service == Weave.CLIENT_NOT_CONFIGURED ||
- Weave.Svc.Prefs.get("firstSync", "") == "notReady") {
- this.page = PAGE_NO_ACCOUNT;
- } else if (Weave.Status.login == Weave.LOGIN_FAILED_INVALID_PASSPHRASE ||
- Weave.Status.login == Weave.LOGIN_FAILED_LOGIN_REJECTED) {
- this.needsUpdate();
- } else {
- this.page = PAGE_HAS_ACCOUNT;
- document.getElementById("accountName").value = Weave.Service.identity.account;
- document.getElementById("syncComputerName").value = Weave.Service.clientsEngine.localName;
- document.getElementById("tosPP").hidden = this._usingCustomServer;
- }
- },
-
- startOver: function (showDialog) {
- if (showDialog) {
- let flags = Services.prompt.BUTTON_POS_0 * Services.prompt.BUTTON_TITLE_IS_STRING +
- Services.prompt.BUTTON_POS_1 * Services.prompt.BUTTON_TITLE_CANCEL +
- Services.prompt.BUTTON_POS_1_DEFAULT;
- let buttonChoice =
- Services.prompt.confirmEx(window,
- this._stringBundle.GetStringFromName("syncUnlink.title"),
- this._stringBundle.GetStringFromName("syncUnlink.label"),
- flags,
- this._stringBundle.GetStringFromName("syncUnlinkConfirm.label"),
- null, null, null, {});
-
- // If the user selects cancel, just bail
- if (buttonChoice == 1) {
- return;
- }
- }
-
- Weave.Service.startOver();
- this.updateWeavePrefs();
- },
-
- updatePass: function () {
- if (Weave.Status.login == Weave.LOGIN_FAILED_LOGIN_REJECTED) {
- gSyncUtils.changePassword();
- } else {
- gSyncUtils.updatePassphrase();
- }
- },
-
- resetPass: function () {
- if (Weave.Status.login == Weave.LOGIN_FAILED_LOGIN_REJECTED) {
- gSyncUtils.resetPassword();
- } else {
- gSyncUtils.resetPassphrase();
- }
- },
-
- /**
- * Invoke the Sync setup wizard.
- *
- * @param wizardType
- * Indicates type of wizard to launch:
- * null -- regular set up wizard
- * "pair" -- pair a device first
- * "reset" -- reset sync
- */
- openSetup: function (wizardType) {
- let win = Services.wm.getMostRecentWindow("Weave:AccountSetup");
- if (win) {
- win.focus();
- } else {
- window.openDialog("chrome://browser/content/sync/setup.xul",
- "weaveSetup", "centerscreen,chrome,resizable=no",
- wizardType);
- }
- },
-
- openQuotaDialog: function () {
- let win = Services.wm.getMostRecentWindow("Sync:ViewQuota");
- if (win) {
- win.focus();
- } else {
- window.openDialog("chrome://browser/content/sync/quota.xul", "",
- "centerscreen,chrome,dialog,modal");
- }
- },
-
- openAddDevice: function () {
- if (!Weave.Utils.ensureMPUnlocked()) {
- return;
- }
-
- let win = Services.wm.getMostRecentWindow("Sync:AddDevice");
- if (win) {
- win.focus();
- } else {
- window.openDialog("chrome://browser/content/sync/addDevice.xul",
- "syncAddDevice", "centerscreen,chrome,resizable=no");
- }
- },
-
- resetSync: function () {
- this.openSetup("reset");
- },
-};
-
diff --git a/components/preferences/sync.xul b/components/preferences/sync.xul
deleted file mode 100644
index 52f5a95..0000000
--- a/components/preferences/sync.xul
+++ /dev/null
@@ -1,178 +0,0 @@
-<?xml version="1.0"?>
-
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!DOCTYPE overlay [
-<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
-<!ENTITY % syncBrandDTD SYSTEM "chrome://browser/locale/syncBrand.dtd">
-<!ENTITY % syncDTD SYSTEM "chrome://browser/locale/preferences/sync.dtd">
-%brandDTD;
-%syncBrandDTD;
-%syncDTD;
-]>
-
-<overlay id="SyncPaneOverlay"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml">
-
- <prefpane id="paneSync"
- helpTopic="prefs-weave"
- onpaneload="gSyncPane.init()">
-
- <preferences>
-<!-- <preference id="engine.addons" name="services.sync.engine.addons" type="bool"/> -->
- <preference id="engine.bookmarks" name="services.sync.engine.bookmarks" type="bool"/>
- <preference id="engine.history" name="services.sync.engine.history" type="bool"/>
- <preference id="engine.tabs" name="services.sync.engine.tabs" type="bool"/>
- <preference id="engine.prefs" name="services.sync.engine.prefs" type="bool"/>
- <preference id="engine.passwords" name="services.sync.engine.passwords" type="bool"/>
- </preferences>
-
-
- <script type="application/javascript"
- src="chrome://browser/content/preferences/sync.js"/>
- <script type="application/javascript"
- src="chrome://browser/content/sync/utils.js"/>
-
-
- <deck id="weavePrefsDeck">
- <vbox id="noAccount" align="center">
- <spacer flex="1"/>
- <description id="syncDesc">
- &weaveDesc.label;
- </description>
- <separator/>
- <label class="text-link"
- onclick="event.stopPropagation(); gSyncPane.openSetup(null);"
- value="&setupButton.label;"/>
- <separator/>
- <label class="text-link"
- onclick="event.stopPropagation(); gSyncPane.openSetup('pair');"
- value="&pairDevice.label;"/>
- <spacer flex="3"/>
- </vbox>
-
- <vbox id="hasAccount">
- <groupbox class="syncGroupBox">
- <!-- label is set to account name -->
- <caption id="accountCaption" align="center">
- <image id="accountCaptionImage"/>
- <label id="accountName" value=""/>
- </caption>
-
- <hbox>
- <button type="menu"
- label="&manageAccount.label;"
- accesskey="&manageAccount.accesskey;">
- <menupopup>
- <menuitem label="&viewQuota.label;"
- oncommand="gSyncPane.openQuotaDialog();"/>
- <menuseparator/>
- <menuitem label="&changePassword2.label;"
- oncommand="gSyncUtils.changePassword();"/>
- <menuitem label="&myRecoveryKey.label;"
- oncommand="gSyncUtils.resetPassphrase();"/>
- <menuseparator/>
- <menuitem label="&resetSync2.label;"
- oncommand="gSyncPane.resetSync();"/>
- </menupopup>
- </button>
- </hbox>
-
- <hbox>
- <label id="syncAddDeviceLabel"
- class="text-link"
- onclick="gSyncPane.openAddDevice(); return false;"
- value="&pairDevice.label;"/>
- </hbox>
-
- <vbox>
- <label value="&syncMy.label;" />
- <richlistbox id="syncEnginesList"
- orient="vertical"
- onselect="if (this.selectedCount) this.clearSelection();">
-<!-- <richlistitem>
- <checkbox label="&engine.addons.label;"
- accesskey="&engine.addons.accesskey;"
- preference="engine.addons"/>
- </richlistitem> -->
- <richlistitem>
- <checkbox label="&engine.bookmarks.label;"
- accesskey="&engine.bookmarks.accesskey;"
- preference="engine.bookmarks"/>
- </richlistitem>
- <richlistitem>
- <checkbox label="&engine.passwords.label;"
- accesskey="&engine.passwords.accesskey;"
- preference="engine.passwords"/>
- </richlistitem>
- <richlistitem>
- <checkbox label="&engine.prefs.label;"
- accesskey="&engine.prefs.accesskey;"
- preference="engine.prefs"/>
- </richlistitem>
- <richlistitem>
- <checkbox label="&engine.history.label;"
- accesskey="&engine.history.accesskey;"
- preference="engine.history"/>
- </richlistitem>
- <richlistitem>
- <checkbox label="&engine.tabs.label;"
- accesskey="&engine.tabs.accesskey;"
- preference="engine.tabs"/>
- </richlistitem>
- </richlistbox>
- </vbox>
- </groupbox>
-
- <groupbox class="syncGroupBox">
- <grid>
- <columns>
- <column/>
- <column flex="1"/>
- </columns>
- <rows>
- <row align="center">
- <label value="&syncDeviceName.label;"
- accesskey="&syncDeviceName.accesskey;"
- control="syncComputerName"/>
- <textbox id="syncComputerName"
- onchange="gSyncUtils.changeName(this)"/>
- </row>
- </rows>
- </grid>
- <hbox>
- <label class="text-link"
- onclick="gSyncPane.startOver(true); return false;"
- value="&unlinkDevice.label;"/>
- </hbox>
- </groupbox>
- <hbox id="tosPP" pack="center">
- <label class="text-link"
- onclick="event.stopPropagation();gSyncUtils.openToS();"
- value="&prefs.tosLink.label;"/>
- <label class="text-link"
- onclick="event.stopPropagation();gSyncUtils.openPrivacyPolicy();"
- value="&prefs.ppLink.label;"/>
- </hbox>
- </vbox>
-
- <vbox id="needsUpdate" align="center" pack="center">
- <hbox>
- <label id="loginError" value=""/>
- <label class="text-link"
- onclick="gSyncPane.updatePass(); return false;"
- value="&updatePass.label;"/>
- <label class="text-link"
- onclick="gSyncPane.resetPass(); return false;"
- value="&resetPass.label;"/>
- </hbox>
- <label class="text-link"
- onclick="gSyncPane.startOver(true); return false;"
- value="&unlinkDevice.label;"/>
- </vbox>
- </deck>
- </prefpane>
-</overlay>
diff --git a/components/preferences/tabs.js b/components/preferences/tabs.js
deleted file mode 100644
index b09cb60..0000000
--- a/components/preferences/tabs.js
+++ /dev/null
@@ -1,90 +0,0 @@
-# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-var gTabsPane = {
-
- /*
- * Preferences:
- *
- * browser.link.open_newwindow
- * - determines where pages which would open in a new window are opened:
- * 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.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
- * browser.taskbar.previews.enable
- * - true if tabs are to be shown in the Windows 7 taskbar
- */
-
- /**
- * Initialize any platform-specific UI.
- */
- init: function () {
-#ifdef XP_WIN
- const Cc = Components.classes;
- const Ci = Components.interfaces;
- try {
- let sysInfo = Cc["@mozilla.org/system-info;1"].
- getService(Ci.nsIPropertyBag2);
- let ver = parseFloat(sysInfo.getProperty("version"));
- let showTabsInTaskbar = document.getElementById("showTabsInTaskbar");
- showTabsInTaskbar.hidden = ver < 6.1;
- } catch (ex) {}
-#endif
- // Set the proper value in the newtab drop-down.
- gTabsPane.readNewtabUrl();
- },
-
- /**
- * Pale Moon: synchronize warnOnClose and warnOnCloseOtherTabs
- */
- syncWarnOnClose: function() {
- var warnOnClosePref = document.getElementById("browser.tabs.warnOnClose");
- var warnOnCloseOtherPref = document.getElementById("browser.tabs.warnOnCloseOtherTabs");
- warnOnCloseOtherPref.value = warnOnClosePref.value;
- },
-
- /**
- * 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;
- },
-
- /**
- * Determines the value of the New Tab display drop-down based
- * on the value of browser.newtab.url.
- */
- readNewtabUrl: function() {
- let newtabUrlChoice = document.getElementById("browser.newtab.choice");
- newtabUrlChoice.value = gNewtabUrl.getNewtabChoice();
- if (newtabUrlChoice.value == 0) {
- document.getElementById("newtabPageCustom").hidden = false;
- }
- gNewtabUrl.newtabUrlChoiceIsSet = true;
- }
-};
diff --git a/components/preferences/tabs.xul b/components/preferences/tabs.xul
deleted file mode 100644
index 64529d6..0000000
--- a/components/preferences/tabs.xul
+++ /dev/null
@@ -1,102 +0,0 @@
-<?xml version="1.0"?>
-
-# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-<!DOCTYPE overlay [
-<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
-%brandDTD;
-<!ENTITY % tabsDTD SYSTEM "chrome://browser/locale/preferences/tabs.dtd">
-%tabsDTD;
-]>
-
-<overlay id="TabsPaneOverlay"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-
- <prefpane id="paneTabs"
- onpaneload="gTabsPane.init();"
- helpTopic="prefs-tabs">
-
- <preferences id="tabsPreferences">
- <preference id="browser.link.open_newwindow" name="browser.link.open_newwindow" type="int"/>
- <preference id="browser.tabs.autoHide" name="browser.tabs.autoHide" type="bool" inverted="true"/>
- <preference id="browser.tabs.loadInBackground" name="browser.tabs.loadInBackground" type="bool" inverted="true"/>
- <preference id="browser.tabs.warnOnClose" name="browser.tabs.warnOnClose" type="bool"
- onchange="gTabsPane.syncWarnOnClose();"/>
- <preference id="browser.tabs.warnOnCloseOtherTabs" name="browser.tabs.warnOnCloseOtherTabs" type="bool"/>
- <preference id="browser.tabs.warnOnOpen" name="browser.tabs.warnOnOpen" type="bool"/>
- <preference id="browser.sessionstore.restore_on_demand" name="browser.sessionstore.restore_on_demand" type="bool"/>
-#ifdef XP_WIN
- <preference id="browser.taskbar.previews.enable" name="browser.taskbar.previews.enable" type="bool"/>
-#endif
- <preference id="browser.tabs.insertRelatedAfterCurrent" name="browser.tabs.insertRelatedAfterCurrent" type="bool"/>
- <preference id="browser.search.context.loadInBackground" name="browser.search.context.loadInBackground" type="bool" inverted="true"/>
- <preference id="browser.tabs.closeWindowWithLastTab" name="browser.tabs.closeWindowWithLastTab" type="bool"/>
- <preference id="browser.ctrlTab.previews" name="browser.ctrlTab.previews" type="bool"/>
-
- <preference id="browser.newtab.url" name="browser.newtab.url" type="string"/>
- <preference id="browser.newtab.myhome" name="browser.newtab.myhome" type="string"/>
- <preference id="browser.newtab.choice" name="browser.newtab.choice" type="int"/>
- </preferences>
-
- <script type="application/javascript" src="chrome://browser/content/preferences/tabs.js"/>
-
- <!-- XXX flex below is a hack because wrapping checkboxes don't reflow
- properly; see bug 349098 -->
- <vbox id="tabPrefsBox" align="start" flex="1">
- <checkbox id="linkTargeting" label="&newWindowsAsTabs.label;"
- accesskey="&newWindowsAsTabs.accesskey;"
- preference="browser.link.open_newwindow"
- onsyncfrompreference="return gTabsPane.readLinkTarget();"
- onsynctopreference="return gTabsPane.writeLinkTarget();"/>
- <checkbox id="warnCloseMultiple" label="&warnCloseMultipleTabs.label;"
- accesskey="&warnCloseMultipleTabs.accesskey;"
- preference="browser.tabs.warnOnClose"/>
- <checkbox id="warnOpenMany" label="&warnOpenManyTabs.label;"
- accesskey="&warnOpenManyTabs.accesskey;"
- preference="browser.tabs.warnOnOpen"/>
- <checkbox id="showTabBar" label="&showTabBar.label;"
- accesskey="&showTabBar.accesskey;"
- preference="browser.tabs.autoHide"/>
- <checkbox id="restoreOnDemand" label="&restoreTabsOnDemand.label;"
- accesskey="&restoreTabsOnDemand.accesskey;"
- preference="browser.sessionstore.restore_on_demand"/>
- <checkbox id="switchToNewTabs" label="&switchToNewTabs.label;"
- accesskey="&switchToNewTabs.accesskey;"
- preference="browser.tabs.loadInBackground"/>
-#ifdef XP_WIN
- <checkbox id="showTabsInTaskbar" label="&showTabsInTaskbar.label;"
- accesskey="&showTabsInTaskbar.accesskey;"
- preference="browser.taskbar.previews.enable"/>
-#endif
-<!-- Pale Moon additions -->
- <checkbox id="insertRelatedAfterCurrent" label="&insertRelatedAfterCurrent.label;"
- preference="browser.tabs.insertRelatedAfterCurrent"/>
- <checkbox id="contextLoadInBackground" label="&contextLoadInBackground.label;"
- preference="browser.search.context.loadInBackground"/>
- <checkbox id="closeWindowWithLastTab" label="&closeWindowWithLastTab.label;"
- preference="browser.tabs.closeWindowWithLastTab"/>
- <checkbox id="showTabPreviews" label="&showTabPreviews.label;"
- preference="browser.ctrlTab.previews"/>
- <hbox align="center">
- <label value="&newtabPage.label;"/>
- <menulist
- id="newtabPage"
- preference="browser.newtab.choice"
- oncommand="gNewtabUrl.writeNewtabUrl(event.target.value);">
- <menupopup>
- <menuitem label="&newtabPage.custom.label;" value="0" id="newtabPageCustom" hidden="true" />
- <menuitem label="&newtabPage.blank.label;" value="1" />
- <menuitem label="&newtabPage.home.label;" value="2" />
- <menuitem label="&newtabPage.myhome.label;" value="3" />
- <menuitem label="&newtabPage.quickdial.label;" value="4" />
- </menupopup>
- </menulist>
- </hbox>
- </vbox>
-
- </prefpane>
-
-</overlay>
diff --git a/components/privatebrowsing/content/aboutPrivateBrowsing.xhtml b/components/privatebrowsing/content/aboutPrivateBrowsing.xhtml
deleted file mode 100644
index 95744cf..0000000
--- a/components/privatebrowsing/content/aboutPrivateBrowsing.xhtml
+++ /dev/null
@@ -1,156 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
--->
-<!DOCTYPE html [
- <!ENTITY % htmlDTD PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">
- %htmlDTD;
- <!ENTITY % netErrorDTD SYSTEM "chrome://global/locale/netError.dtd">
- %netErrorDTD;
- <!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd">
- %globalDTD;
- <!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd">
- %browserDTD;
-#ifdef XP_MACOSX
- <!ENTITY basePBMenu.label "&fileMenu.label;">
-#else
- <!ENTITY basePBMenu.label "<span class='appMenuButton'>&brandShortName;</span><span class='fileMenu'>&fileMenu.label;</span>">
-#endif
- <!ENTITY % privatebrowsingpageDTD SYSTEM "chrome://browser/locale/aboutPrivateBrowsing.dtd">
- %privatebrowsingpageDTD;
-]>
-
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <link rel="stylesheet" href="chrome://global/skin/netError.css" type="text/css" media="all"/>
- <link rel="stylesheet" href="chrome://browser/skin/aboutPrivateBrowsing.css" type="text/css" media="all"/>
- <style type="text/css"><![CDATA[
- body.normal .showPrivate,
- body.private .showNormal {
- display: none;
- }
- body.appMenuButtonVisible .fileMenu {
- display: none;
- }
- body.appMenuButtonInvisible .appMenuButton {
- display: none;
- }
- ]]></style>
- <script type="application/javascript;version=1.7"><![CDATA[
- const Cc = Components.classes;
- const Ci = Components.interfaces;
-
- Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
-
- if (!PrivateBrowsingUtils.isWindowPrivate(window)) {
- document.title = "]]>&privatebrowsingpage.title.normal;<![CDATA[";
- setFavIcon("chrome://global/skin/icons/question-16.png");
- } else {
-#ifndef XP_MACOSX
- document.title = "]]>&privatebrowsingpage.title;<![CDATA[";
-#endif
- setFavIcon("chrome://browser/skin/Privacy-16.png");
- }
-
- var mainWindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsIDocShellTreeItem)
- .rootTreeItem
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIDOMWindow);
-
- // Focus the location bar
- mainWindow.focusAndSelectUrlBar();
-
- function setFavIcon(url) {
- var icon = document.createElement("link");
- icon.setAttribute("rel", "icon");
- icon.setAttribute("type", "image/png");
- icon.setAttribute("href", url);
- var head = document.getElementsByTagName("head")[0];
- head.insertBefore(icon, head.firstChild);
- }
-
- document.addEventListener("DOMContentLoaded", function () {
- if (!PrivateBrowsingUtils.isWindowPrivate(window)) {
- document.body.setAttribute("class", "normal");
- }
-
- // Set up the help link
- let moreInfoURL = Cc["@mozilla.org/toolkit/URLFormatterService;1"].
- getService(Ci.nsIURLFormatter).
- formatURLPref("app.support.baseURL");
- let moreInfoLink = document.getElementById("moreInfoLink");
- if (moreInfoLink)
- moreInfoLink.setAttribute("href", moreInfoURL + "private-browsing");
-
- // Show the correct menu structure based on whether the App Menu button is
- // shown or not.
- var menuBar = mainWindow.document.getElementById("toolbar-menubar");
- var appMenuButtonIsVisible = menuBar.getAttribute("autohide") == "true";
- document.body.classList.add(appMenuButtonIsVisible ? "appMenuButtonVisible" :
- "appMenuButtonInvisible");
- }, false);
-
- function openPrivateWindow() {
- mainWindow.OpenBrowserWindow({private: true});
- }
- ]]></script>
- </head>
-
- <body dir="&locale.dir;"
- class="private">
-
- <!-- PAGE CONTAINER (for styling purposes only) -->
- <div id="errorPageContainer">
-
- <!-- Error Title -->
- <div id="errorTitle">
- <h1 id="errorTitleText" class="showPrivate">&privatebrowsingpage.title;</h1>
- <h1 id="errorTitleTextNormal" class="showNormal">&privatebrowsingpage.title.normal;</h1>
- </div>
-
- <!-- LONG CONTENT (the section most likely to require scrolling) -->
- <div id="errorLongContent">
-
- <!-- Short Description -->
- <div id="errorShortDesc">
- <p id="errorShortDescText" class="showPrivate">&privatebrowsingpage.perwindow.issueDesc;</p>
- <p id="errorShortDescTextNormal" class="showNormal">&privatebrowsingpage.perwindow.issueDesc.normal;</p>
- </div>
-
- <!-- Long Description -->
- <div id="errorLongDesc">
- <p id="errorLongDescText">&privatebrowsingpage.perwindow.description;</p>
- </div>
-
- <!-- Start Private Browsing -->
- <div id="startPrivateBrowsingDesc" class="showNormal">
- <button xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- id="startPrivateBrowsing" label="&privatebrowsingpage.openPrivateWindow.label;"
- accesskey="&privatebrowsingpage.openPrivateWindow.accesskey;"
- oncommand="openPrivateWindow();"/>
- </div>
-
- <!-- Footer -->
- <div id="footerDesc">
- <p id="footerText" class="showPrivate">&privatebrowsingpage.howToStop3;</p>
- <p id="footerTextNormal" class="showNormal">&privatebrowsingpage.howToStart3;</p>
- </div>
-
- <!-- More Info -->
- <div id="moreInfo" class="showPrivate">
- <p id="moreInfoText">
- &privatebrowsingpage.moreInfo;
- </p>
- <p id="moreInfoLinkContainer">
- <a id="moreInfoLink" target="_blank">&privatebrowsingpage.learnMore;</a>
- </p>
- </div>
- </div>
- </div>
-
- </body>
-</html>
diff --git a/components/privatebrowsing/jar.mn b/components/privatebrowsing/jar.mn
deleted file mode 100644
index 75e985c..0000000
--- a/components/privatebrowsing/jar.mn
+++ /dev/null
@@ -1,6 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-browser.jar:
-* content/browser/aboutPrivateBrowsing.xhtml (content/aboutPrivateBrowsing.xhtml)
diff --git a/components/privatebrowsing/moz.build b/components/privatebrowsing/moz.build
deleted file mode 100644
index c97072b..0000000
--- a/components/privatebrowsing/moz.build
+++ /dev/null
@@ -1,7 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-JAR_MANIFESTS += ['jar.mn'] \ No newline at end of file
diff --git a/components/search/content/engineManager.js b/components/search/content/engineManager.js
deleted file mode 100644
index 993d48b..0000000
--- a/components/search/content/engineManager.js
+++ /dev/null
@@ -1,492 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
-Components.utils.import("resource://gre/modules/Services.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
- "resource://gre/modules/PlacesUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "Task",
- "resource://gre/modules/Task.jsm");
-
-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 suggestEnabled = Services.prefs.getBoolPref(BROWSER_SUGGEST_PREF);
- document.getElementById("enableSuggest").checked = suggestEnabled;
-
- var tree = document.getElementById("engineList");
- tree.view = gEngineView;
-
- Services.obs.addObserver(this, "browser-search-engine-modified", false);
- },
-
- destroy: function engineManager_destroy() {
- // Remove the observer
- Services.obs.removeObserver(this, "browser-search-engine-modified");
- },
-
- 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();
- gEngineView.invalidate();
- break;
- case "engine-removed":
- case "engine-current":
- case "engine-default":
- // Not relevant
- break;
- }
- }
- },
-
- onOK: function engineManager_onOK() {
- // Set the preference
- var newSuggestEnabled = document.getElementById("enableSuggest").checked;
- Services.prefs.setBoolPref(BROWSER_SUGGEST_PREF, newSuggestEnabled);
-
- // Commit the changes
- gEngineView._engineStore.commit();
- },
-
- 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(gEngineView.currentIndex);
- 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: Task.async(function* engineManager_editKeyword() {
- var selectedEngine = gEngineView.selectedEngine;
- if (!selectedEngine)
- return;
-
- var alias = { value: selectedEngine.alias };
- var strings = document.getElementById("engineManagerBundle");
- var title = strings.getString("editTitle");
- var msg = strings.getFormattedString("editMsg", [selectedEngine.name]);
-
- while (Services.prompt.prompt(window, title, msg, alias, null, {})) {
- var bduplicate = false;
- var eduplicate = false;
- var dupName = "";
-
- if (alias.value != "") {
- // Check for duplicates in Places keywords.
- bduplicate = !!(yield PlacesUtils.keywords.fetch(alias.value));
-
- // 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;
- dupName = engine.name;
- 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", [dupName]);
-
- Services.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,
- // the latter is true when the selected is first and last at the same time.
- var lastSelected = (gEngineView.selectedIndex == gEngineView.lastIndex);
- var firstSelected = (gEngineView.selectedIndex == 0);
- var noSelection = (gEngineView.selectedIndex == -1);
-
- document.getElementById("cmd_remove")
- .setAttribute("disabled", noSelection ||
- (firstSelected && lastSelected));
-
- document.getElementById("cmd_moveup")
- .setAttribute("disabled", noSelection || firstSelected);
-
- document.getElementById("cmd_movedown")
- .setAttribute("disabled", noSelection || 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() {
- Services.search.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() {
- Services.search.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;
- Services.search.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() {
- this._engines = Services.search.getVisibleEngines().map(this._cloneEngine);
- this._defaultEngines = Services.search.getDefaultEngines().map(this._cloneEngine);
-
- this._ops = [];
-
- // check if we need to disable the restore defaults button
- var someHidden = this._defaultEngines.some(function (e) 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_cloneEngine(aEngine) {
- var clonedObj={};
- for (var i in aEngine)
- clonedObj[i] = aEngine[i];
- clonedObj.originalEngine = aEngine;
- return clonedObj;
- },
-
- // 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 currentEngine = this._cloneEngine(Services.search.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)
- Services.search.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 (dataTransfer) {
- return parseInt(dataTransfer.getData(ENGINE_FLAVOR));
- },
-
- // 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, dataTransfer) {
- var sourceIndex = this.getSourceIndexFromDrag(dataTransfer);
- return (sourceIndex != -1 &&
- sourceIndex != targetIndex &&
- sourceIndex != targetIndex + orientation);
- },
-
- drop: function(dropIndex, orientation, dataTransfer) {
- var sourceIndex = this.getSourceIndexFromDrag(dataTransfer);
- 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.select(dropIndex);
- },
-
- selection: null,
- getRowProperties: function(index) { return ""; },
- getCellProperties: function(index, column) { return ""; },
- getColumnProperties: function(column) { return ""; },
- 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) { }
-};
diff --git a/components/search/content/engineManager.xul b/components/search/content/engineManager.xul
deleted file mode 100644
index 1152ef8..0000000
--- a/components/search/content/engineManager.xul
+++ /dev/null
@@ -1,93 +0,0 @@
-<?xml version="1.0"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<?xml-stylesheet href="chrome://global/skin/"?>
-<?xml-stylesheet href="chrome://browser/skin/engineManager.css"?>
-
-<!DOCTYPE dialog SYSTEM "chrome://browser/locale/engineManager.dtd">
-
-<dialog id="engineManager"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- buttons="accept,cancel,extra2"
- buttonlabelextra2="&restoreDefaults.label;"
- buttonaccesskeyextra2="&restoreDefaults.accesskey;"
- onload="gEngineManagerDialog.init();"
- onunload="gEngineManagerDialog.destroy();"
- ondialogaccept="gEngineManagerDialog.onOK();"
- ondialogextra2="gEngineManagerDialog.onRestoreDefaults();"
- title="&engineManager.title;"
- style="&engineManager.style;"
- persist="screenX screenY width height"
- windowtype="Browser:SearchManager">
-
- <script type="application/javascript"
- src="chrome://browser/content/search/engineManager.js"/>
-
- <commandset id="engineManagerCommandSet">
- <command id="cmd_remove"
- oncommand="gEngineManagerDialog.remove();"
- disabled="true"/>
- <command id="cmd_moveup"
- oncommand="gEngineManagerDialog.bump(1);"
- disabled="true"/>
- <command id="cmd_movedown"
- oncommand="gEngineManagerDialog.bump(-1);"
- disabled="true"/>
- <command id="cmd_editkeyword"
- oncommand="gEngineManagerDialog.editKeyword().catch(Components.utils.reportError);"
- disabled="true"/>
- </commandset>
-
- <keyset id="engineManagerKeyset">
- <key id="delete" keycode="VK_DELETE" command="cmd_remove"/>
- </keyset>
-
- <stringbundleset id="engineManagerBundleset">
- <stringbundle id="engineManagerBundle" src="chrome://browser/locale/engineManager.properties"/>
- </stringbundleset>
-
- <description>&engineManager.intro;</description>
- <separator class="thin"/>
- <hbox flex="1">
- <tree id="engineList" flex="1" rows="10" hidecolumnpicker="true"
- seltype="single" onselect="gEngineManagerDialog.onSelect();">
- <treechildren id="engineChildren" flex="1"
- ondragstart="onDragEngineStart(event);"/>
- <treecols>
- <treecol id="engineName" flex="4" label="&columnLabel.name;"/>
- <treecol id="engineKeyword" flex="1" label="&columnLabel.keyword;"/>
- </treecols>
- </tree>
- <vbox>
- <spacer flex="1"/>
- <button id="edit"
- label="&edit.label;"
- accesskey="&edit.accesskey;"
- command="cmd_editkeyword"/>
- <button id="up"
- label="&up.label;"
- accesskey="&up.accesskey;"
- command="cmd_moveup"/>
- <button id="down"
- label="&dn.label;"
- accesskey="&dn.accesskey;"
- command="cmd_movedown"/>
- <spacer flex="1"/>
- <button id="remove"
- label="&remove.label;"
- accesskey="&remove.accesskey;"
- command="cmd_remove"/>
- </vbox>
- </hbox>
- <hbox>
- <checkbox id="enableSuggest"
- label="&enableSuggest.label;"
- accesskey="&enableSuggest.accesskey;"/>
- </hbox>
- <hbox>
- <label id="addEngines" class="text-link" value="&addEngine.label;"
- onclick="if (event.button == 0) { gEngineManagerDialog.loadAddEngines(); }"/>
- </hbox>
-</dialog>
diff --git a/components/search/content/search.xml b/components/search/content/search.xml
deleted file mode 100644
index 0c33b15..0000000
--- a/components/search/content/search.xml
+++ /dev/null
@@ -1,837 +0,0 @@
-<?xml version="1.0"?>
-# -*- Mode: HTML -*-
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-<!DOCTYPE bindings [
-<!ENTITY % searchBarDTD SYSTEM "chrome://browser/locale/searchbar.dtd" >
-%searchBarDTD;
-<!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd">
-%browserDTD;
-]>
-
-<bindings id="SearchBindings"
- xmlns="http://www.mozilla.org/xbl"
- xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:xbl="http://www.mozilla.org/xbl">
-
- <binding id="searchbar">
- <resources>
- <stylesheet src="chrome://browser/content/search/searchbarBindings.css"/>
- <stylesheet src="chrome://browser/skin/searchbar.css"/>
- </resources>
- <content>
- <xul:stringbundle src="chrome://browser/locale/search.properties"
- anonid="searchbar-stringbundle"/>
-
- <xul:textbox class="searchbar-textbox"
- anonid="searchbar-textbox"
- type="autocomplete"
- flex="1"
- autocompletepopup="PopupAutoComplete"
- autocompletesearch="search-autocomplete"
- autocompletesearchparam="searchbar-history"
- timeout="250"
- maxrows="10"
- completeselectedindex="true"
- showcommentcolumn="true"
- tabscrolling="true"
- xbl:inherits="disabled,disableautocomplete,searchengine,src,newlines">
- <xul:box>
- <xul:button class="searchbar-engine-button"
- type="menu"
- anonid="searchbar-engine-button">
- <xul:image class="searchbar-engine-image" xbl:inherits="src"/>
- <xul:image class="searchbar-dropmarker-image"/>
- <xul:menupopup class="searchbar-popup"
- anonid="searchbar-popup">
- <xul:menuseparator/>
- <xul:menuitem class="open-engine-manager"
- anonid="open-engine-manager"
- label="&cmd_engineManager.label;"
- oncommand="openManager(event);"/>
- </xul:menupopup>
- </xul:button>
- </xul:box>
- <xul:hbox class="search-go-container">
- <xul:image class="search-go-button"
- anonid="search-go-button"
- onclick="handleSearchCommand(event);"
- tooltiptext="&searchEndCap.label;"/>
- </xul:hbox>
- </xul:textbox>
- </content>
-
- <implementation implements="nsIObserver">
- <constructor><![CDATA[
- if (this.parentNode.parentNode.localName == "toolbarpaletteitem")
- return;
- // Make sure we rebuild the popup in onpopupshowing
- this._needToBuildPopup = true;
-
- var os =
- Components.classes["@mozilla.org/observer-service;1"]
- .getService(Components.interfaces.nsIObserverService);
- os.addObserver(this, "browser-search-engine-modified", false);
-
- this._initialized = true;
-
- this.searchService.init((function search_init_cb(aStatus) {
- // Bail out if the binding has been destroyed
- if (!this._initialized)
- return;
-
- if (Components.isSuccessCode(aStatus)) {
- // Refresh the display (updating icon, etc)
- this.updateDisplay();
- } else {
- Components.utils.reportError("Cannot initialize search service, bailing out: " + aStatus);
- }
- }).bind(this));
- ]]></constructor>
-
- <destructor><![CDATA[
- if (this._initialized) {
- this._initialized = false;
-
- var os = Components.classes["@mozilla.org/observer-service;1"]
- .getService(Components.interfaces.nsIObserverService);
- os.removeObserver(this, "browser-search-engine-modified");
- }
-
- // Make sure to break the cycle from _textbox to us. Otherwise we leak
- // the world. But make sure it's actually pointing to us.
- if (this._textbox.mController.input == this)
- this._textbox.mController.input = null;
- ]]></destructor>
-
- <field name="_stringBundle">document.getAnonymousElementByAttribute(this,
- "anonid", "searchbar-stringbundle");</field>
- <field name="_textbox">document.getAnonymousElementByAttribute(this,
- "anonid", "searchbar-textbox");</field>
- <field name="_popup">document.getAnonymousElementByAttribute(this,
- "anonid", "searchbar-popup");</field>
- <field name="_ss">null</field>
- <field name="_engines">null</field>
- <field name="FormHistory" readonly="true">
- (Components.utils.import("resource://gre/modules/FormHistory.jsm", {})).FormHistory;
- </field>
-
- <property name="engines" readonly="true">
- <getter><![CDATA[
- if (!this._engines)
- this._engines = this.searchService.getVisibleEngines();
- return this._engines;
- ]]></getter>
- </property>
-
- <field name="searchButton">document.getAnonymousElementByAttribute(this,
- "anonid", "searchbar-engine-button");</field>
-
- <property name="currentEngine">
- <setter><![CDATA[
- let ss = this.searchService;
- ss.defaultEngine = ss.currentEngine = val;
- return val;
- ]]></setter>
- <getter><![CDATA[
- var currentEngine = this.searchService.currentEngine;
- // Return a dummy engine if there is no currentEngine
- return currentEngine || {name: "", uri: null};
- ]]></getter>
- </property>
-
- <!-- textbox is used by sanitize.js to clear the undo history when
- clearing form information. -->
- <property name="textbox" readonly="true"
- onget="return this._textbox;"/>
-
- <property name="searchService" readonly="true">
- <getter><![CDATA[
- if (!this._ss) {
- const nsIBSS = Components.interfaces.nsIBrowserSearchService;
- this._ss =
- Components.classes["@mozilla.org/browser/search-service;1"]
- .getService(nsIBSS);
- }
- return this._ss;
- ]]></getter>
- </property>
-
- <property name="value" onget="return this._textbox.value;"
- onset="return this._textbox.value = val;"/>
-
- <method name="focus">
- <body><![CDATA[
- this._textbox.focus();
- ]]></body>
- </method>
-
- <method name="select">
- <body><![CDATA[
- this._textbox.select();
- ]]></body>
- </method>
-
- <method name="observe">
- <parameter name="aEngine"/>
- <parameter name="aTopic"/>
- <parameter name="aVerb"/>
- <body><![CDATA[
- if (aTopic == "browser-search-engine-modified") {
- switch (aVerb) {
- case "engine-removed":
- this.offerNewEngine(aEngine);
- break;
- case "engine-added":
- this.hideNewEngine(aEngine);
- break;
- case "engine-current":
- // The current engine was changed. Rebuilding the menu appears to
- // confuse its idea of whether it should be open when it's just
- // been clicked, so we force it to close now.
- this._popup.hidePopup();
- break;
- case "engine-changed":
- // An engine was removed (or hidden) or added, or an icon was
- // changed. Do nothing special.
- }
-
- // Make sure the engine list is refetched next time it's needed
- this._engines = null;
-
- // Rebuild the popup and update the display after any modification.
- this.rebuildPopup();
- this.updateDisplay();
- }
- ]]></body>
- </method>
-
- <!-- There are two seaprate lists of search engines, whose uses intersect
- in this file. The search service (nsIBrowserSearchService and
- nsSearchService.js) maintains a list of Engine objects which is used to
- populate the searchbox list of available engines and to perform queries.
- That list is accessed here via this.SearchService, and it's that sort of
- Engine that is passed to this binding's observer as aEngine.
-
- In addition, browser.js fills two lists of autodetected search engines
- (browser.engines and browser.hiddenEngines) as properties of
- mCurrentBrowser. Those lists contain unnamed JS objects of the form
- { uri:, title:, icon: }, and that's what the searchbar uses to determine
- whether to show any "Add <EngineName>" menu items in the drop-down.
-
- The two types of engines are currently related by their identifying
- titles (the Engine object's 'name'), although that may change; see bug
- 335102. -->
-
- <!-- If the engine that was just removed from the searchbox list was
- autodetected on this page, move it to each browser's active list so it
- will be offered to be added again. -->
- <method name="offerNewEngine">
- <parameter name="aEngine"/>
- <body><![CDATA[
- var allbrowsers = getBrowser().mPanelContainer.childNodes;
- for (var tab = 0; tab < allbrowsers.length; tab++) {
- var browser = getBrowser().getBrowserAtIndex(tab);
- if (browser.hiddenEngines) {
- // XXX This will need to be changed when engines are identified by
- // URL rather than title; see bug 335102.
- var removeTitle = aEngine.wrappedJSObject.name;
- for (var i = 0; i < browser.hiddenEngines.length; i++) {
- if (browser.hiddenEngines[i].title == removeTitle) {
- if (!browser.engines)
- browser.engines = [];
- browser.engines.push(browser.hiddenEngines[i]);
- browser.hiddenEngines.splice(i, 1);
- break;
- }
- }
- }
- }
- ]]></body>
- </method>
-
- <!-- If the engine that was just added to the searchbox list was
- autodetected on this page, move it to each browser's hidden list so it is
- no longer offered to be added. -->
- <method name="hideNewEngine">
- <parameter name="aEngine"/>
- <body><![CDATA[
- var allbrowsers = getBrowser().mPanelContainer.childNodes;
- for (var tab = 0; tab < allbrowsers.length; tab++) {
- var browser = getBrowser().getBrowserAtIndex(tab);
- if (browser.engines) {
- // XXX This will need to be changed when engines are identified by
- // URL rather than title; see bug 335102.
- var removeTitle = aEngine.wrappedJSObject.name;
- for (var i = 0; i < browser.engines.length; i++) {
- if (browser.engines[i].title == removeTitle) {
- if (!browser.hiddenEngines)
- browser.hiddenEngines = [];
- browser.hiddenEngines.push(browser.engines[i]);
- browser.engines.splice(i, 1);
- break;
- }
- }
- }
- }
- ]]></body>
- </method>
-
- <method name="setIcon">
- <parameter name="element"/>
- <parameter name="uri"/>
- <body><![CDATA[
- element.setAttribute("src", uri);
- ]]></body>
- </method>
-
- <method name="updateDisplay">
- <body><![CDATA[
- var uri = this.currentEngine.iconURI;
- this.setIcon(this, uri ? uri.spec : "");
-
- var name = this.currentEngine.name;
- var text = this._stringBundle.getFormattedString("searchtip", [name]);
- this._textbox.placeholder = name;
- this._textbox.label = text;
- this._textbox.tooltipText = text;
- ]]></body>
- </method>
-
- <!-- Rebuilds the dynamic portion of the popup menu (i.e., the menu items
- for new search engines that can be added to the available list). This
- is called each time the popup is shown.
- -->
- <method name="rebuildPopupDynamic">
- <body><![CDATA[
- // We might not have added the main popup items yet, do that first
- // if needed.
- if (this._needToBuildPopup)
- this.rebuildPopup();
-
- var popup = this._popup;
- // Clear any addengine menuitems, including addengine-item entries and
- // the addengine-separator. Work backward to avoid invalidating the
- // indexes as items are removed.
- var items = popup.childNodes;
- for (var i = items.length - 1; i >= 0; i--) {
- if (items[i].classList.contains("addengine-item") ||
- items[i].classList.contains("addengine-separator"))
- 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)
- this.setIcon(menuitem, engineInfo.icon);
- menuitem.setAttribute("title", engineInfo.title);
- popup.insertBefore(menuitem, insertLocation);
- }
- }
- ]]></body>
- </method>
-
- <!-- Rebuilds the list of visible search engines in the menu. Does not remove
- or update any dynamic entries (i.e., "Add this engine" items) nor the
- Manage Engines item. This is called by the observer when the list of
- visible engines, or the currently selected engine, has changed.
- -->
- <method name="rebuildPopup">
- <body><![CDATA[
- var popup = this._popup;
-
- // Clear the popup, down to the first separator
- while (popup.firstChild && popup.firstChild.localName != "menuseparator")
- popup.removeChild(popup.firstChild);
-
- const kXULNS =
- "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
-
- var engines = this.engines;
- for (var i = engines.length - 1; i >= 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 menuitem-with-favicon");
- // 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)
- this.setIcon(menuitem, engines[i].iconURI.spec);
- popup.insertBefore(menuitem, popup.firstChild);
- menuitem.engine = engines[i];
- }
-
- this._needToBuildPopup = false;
- ]]></body>
- </method>
-
- <method name="openManager">
- <parameter name="aEvent"/>
- <body><![CDATA[
- var wm =
- Components.classes["@mozilla.org/appshell/window-mediator;1"]
- .getService(Components.interfaces.nsIWindowMediator);
-
- var window = wm.getMostRecentWindow("Browser:SearchManager");
- if (window)
- window.focus()
- else {
- setTimeout(function () {
- openDialog("chrome://browser/content/search/engineManager.xul",
- "_blank", "chrome,dialog,modal,centerscreen,resizable");
- }, 0);
- }
- ]]></body>
- </method>
-
- <method name="selectEngine">
- <parameter name="aEvent"/>
- <parameter name="isNextEngine"/>
- <body><![CDATA[
- // Find the new index
- var newIndex = this.engines.indexOf(this.currentEngine);
- newIndex += isNextEngine ? 1 : -1;
-
- if (newIndex >= 0 && newIndex < this.engines.length) {
- this.currentEngine = this.engines[newIndex];
- }
-
- aEvent.preventDefault();
- aEvent.stopPropagation();
- ]]></body>
- </method>
-
- <method name="handleSearchCommand">
- <parameter name="aEvent"/>
- <body><![CDATA[
- var textBox = this._textbox;
- var textValue = textBox.value;
-
- var where = "current";
- if (aEvent && aEvent.originalTarget.getAttribute("anonid") == "search-go-button") {
- if (aEvent.button == 2)
- return;
- where = whereToOpenLink(aEvent, false, true);
- }
- else {
- var newTabPref = textBox._prefBranch.getBoolPref("browser.search.openintab");
- if ((aEvent && aEvent.altKey) ^ newTabPref)
- where = "tab";
- }
-
- this.doSearch(textValue, where);
- ]]></body>
- </method>
-
- <method name="doSearch">
- <parameter name="aData"/>
- <parameter name="aWhere"/>
- <body><![CDATA[
- var textBox = this._textbox;
-
- // Save the current value in the form history
- if (aData && !PrivateBrowsingUtils.isWindowPrivate(window)) {
- this.FormHistory.update(
- { op : "bump",
- fieldname : textBox.getAttribute("autocompletesearchparam"),
- value : aData },
- { handleError : function(aError) {
- Components.utils.reportError("Saving search to form history failed: " + aError.message);
- }});
- }
-
- // null parameter below specifies HTML response for search
- var submission = this.currentEngine.getSubmission(aData);
- openUILinkIn(submission.uri.spec, aWhere, null, submission.postData);
- ]]></body>
- </method>
- </implementation>
-
- <handlers>
- <handler event="command"><![CDATA[
- const target = event.originalTarget;
- if (target.engine) {
- this.currentEngine = target.engine;
- } else if (target.classList.contains("addengine-item")) {
- var searchService =
- Components.classes["@mozilla.org/browser/search-service;1"]
- .getService(Components.interfaces.nsIBrowserSearchService);
- // We only detect OpenSearch files
- var type = Components.interfaces.nsISearchEngine.DATA_XML;
- // Select the installed engine if the installation succeeds
- var installCallback = {
- onSuccess: engine => this.currentEngine = engine
- }
- searchService.addEngine(target.getAttribute("uri"), type,
- target.getAttribute("src"), false,
- installCallback);
- }
- else
- return;
-
- this.focus();
- this.select();
- ]]></handler>
-
- <handler event="popupshowing" action="this.rebuildPopupDynamic();"/>
-
- <handler event="DOMMouseScroll"
- phase="capturing"
- modifiers="accel"
- action="this.selectEngine(event, (event.detail > 0));"/>
-
- <handler event="focus">
- <![CDATA[
- // Speculatively connect to the current engine's search URI (and
- // suggest URI, if different) to reduce request latency
-
- const SUGGEST_TYPE = "application/x-suggestions+json";
- var engine = this.currentEngine;
- var connector =
- Services.io.QueryInterface(Components.interfaces.nsISpeculativeConnect);
- var searchURI = engine.getSubmission("dummy").uri;
- let callbacks = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
- .getInterface(Components.interfaces.nsIWebNavigation)
- .QueryInterface(Components.interfaces.nsILoadContext);
- connector.speculativeConnect(searchURI, callbacks);
-
- if (engine.supportsResponseType(SUGGEST_TYPE)) {
- var suggestURI = engine.getSubmission("dummy", SUGGEST_TYPE).uri;
- if (suggestURI.prePath != searchURI.prePath)
- connector.speculativeConnect(suggestURI, callbacks);
- }
- ]]></handler>
- </handlers>
- </binding>
-
- <binding id="searchbar-textbox"
- extends="chrome://global/content/bindings/autocomplete.xml#autocomplete">
- <implementation implements="nsIObserver">
- <constructor><![CDATA[
- const kXULNS =
- "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
-
- if (document.getBindingParent(this).parentNode.parentNode.localName ==
- "toolbarpaletteitem")
- return;
-
- // Initialize fields
- this._stringBundle = document.getBindingParent(this)._stringBundle;
- this._prefBranch =
- Components.classes["@mozilla.org/preferences-service;1"]
- .getService(Components.interfaces.nsIPrefBranch);
- this._suggestEnabled =
- this._prefBranch.getBoolPref("browser.search.suggest.enabled");
- this._clickSelectsAll =
- this._prefBranch.getBoolPref("browser.urlbar.clickSelectsAll");
-
- this.setAttribute("clickSelectsAll", this._clickSelectsAll);
-
- // Add items to context menu and attach controller to handle them
- var textBox = document.getAnonymousElementByAttribute(this,
- "anonid", "textbox-input-box");
- var cxmenu = document.getAnonymousElementByAttribute(textBox,
- "anonid", "input-box-contextmenu");
- var pasteAndSearch;
- cxmenu.addEventListener("popupshowing", function() {
- if (!pasteAndSearch)
- return;
- var controller = document.commandDispatcher.getControllerForCommand("cmd_paste");
- var enabled = controller.isCommandEnabled("cmd_paste");
- if (enabled)
- pasteAndSearch.removeAttribute("disabled");
- else
- pasteAndSearch.setAttribute("disabled", "true");
- }, false);
-
- var element, label, akey;
-
- element = document.createElementNS(kXULNS, "menuseparator");
- cxmenu.appendChild(element);
-
- var insertLocation = cxmenu.firstChild;
- while (insertLocation.nextSibling &&
- insertLocation.getAttribute("cmd") != "cmd_paste")
- insertLocation = insertLocation.nextSibling;
- if (insertLocation) {
- element = document.createElementNS(kXULNS, "menuitem");
- label = this._stringBundle.getString("cmd_pasteAndSearch");
- element.setAttribute("label", label);
- element.setAttribute("anonid", "paste-and-search");
- element.setAttribute("oncommand",
- "BrowserSearch.searchBar.select(); goDoCommand('cmd_paste'); BrowserSearch.searchBar.handleSearchCommand();");
- cxmenu.insertBefore(element, insertLocation.nextSibling);
- pasteAndSearch = element;
- }
-
- element = document.createElementNS(kXULNS, "menuitem");
- label = this._stringBundle.getString("cmd_clearHistory");
- akey = this._stringBundle.getString("cmd_clearHistory_accesskey");
- element.setAttribute("label", label);
- element.setAttribute("accesskey", akey);
- element.setAttribute("cmd", "cmd_clearhistory");
- cxmenu.appendChild(element);
-
- element = document.createElementNS(kXULNS, "menuitem");
- label = this._stringBundle.getString("cmd_showSuggestions");
- akey = this._stringBundle.getString("cmd_showSuggestions_accesskey");
- element.setAttribute("anonid", "toggle-suggest-item");
- element.setAttribute("label", label);
- element.setAttribute("accesskey", akey);
- element.setAttribute("cmd", "cmd_togglesuggest");
- element.setAttribute("type", "checkbox");
- element.setAttribute("checked", this._suggestEnabled);
- element.setAttribute("autocheck", "false");
- this._suggestMenuItem = element;
- cxmenu.appendChild(element);
-
- this.controllers.appendController(this.searchbarController);
-
- // Add observer for suggest preference
- var prefs = Components.classes["@mozilla.org/preferences-service;1"]
- .getService(Components.interfaces.nsIPrefBranch);
- prefs.addObserver("browser.search.suggest.enabled", this, false);
- prefs.addObserver("browser.urlbar.clickSelectsAll", this, false);
- ]]></constructor>
-
- <destructor><![CDATA[
- var prefs = Components.classes["@mozilla.org/preferences-service;1"]
- .getService(Components.interfaces.nsIPrefBranch);
- prefs.removeObserver("browser.search.suggest.enabled", this);
- prefs.removeObserver("browser.urlbar.clickSelectsAll", this);
-
- // Because XBL and the customize toolbar code interacts poorly,
- // there may not be anything to remove here
- try {
- this.controllers.removeController(this.searchbarController);
- } catch (ex) { }
- ]]></destructor>
-
- <field name="_stringBundle"/>
- <field name="_prefBranch"/>
- <field name="_suggestMenuItem"/>
- <field name="_suggestEnabled"/>
- <field name="_clickSelectsAll"/>
-
- <!--
- This overrides the searchParam property in autocomplete.xml. We're
- hijacking this property as a vehicle for delivering the privacy
- information about the window into the guts of nsSearchSuggestions.
-
- Note that the setter is the same as the parent. We were not sure whether
- we can override just the getter. If that proves to be the case, the setter
- can be removed.
- -->
- <property name="searchParam"
- onget="return this.getAttribute('autocompletesearchparam') +
- (PrivateBrowsingUtils.isWindowPrivate(window) ? '|private' : '');"
- onset="this.setAttribute('autocompletesearchparam', val); return val;"/>
-
- <!--
- This method overrides the autocomplete binding's openPopup (essentially
- duplicating the logic from the autocomplete popup binding's
- openAutocompletePopup method), modifying it so that the popup is aligned with
- the inner textbox, but sized to not extend beyond the search bar border.
- -->
- <method name="openPopup">
- <body><![CDATA[
- var popup = this.popup;
- if (!popup.mPopupOpen) {
- // Initially the panel used for the searchbar (PopupAutoComplete
- // in browser.xul) is hidden to avoid impacting startup / new
- // window performance. The base binding's openPopup would normally
- // call the overriden openAutocompletePopup in urlbarBindings.xml's
- // browser-autocomplete-result-popup binding to unhide the popup,
- // but since we're overriding openPopup we need to unhide the panel
- // ourselves.
- popup.hidden = false;
-
- popup.mInput = this;
- popup.view = this.controller.QueryInterface(Components.interfaces.nsITreeView);
- popup.invalidate();
-
- popup.showCommentColumn = this.showCommentColumn;
- popup.showImageColumn = this.showImageColumn;
-
- document.popupNode = null;
-
- const isRTL = getComputedStyle(this, "").direction == "rtl";
-
- var outerRect = this.getBoundingClientRect();
- var innerRect = this.inputField.getBoundingClientRect();
- if (isRTL) {
- var width = innerRect.right - outerRect.left;
- } else {
- var width = outerRect.right - innerRect.left;
- }
- popup.setAttribute("width", width > 100 ? width : 100);
-
- var yOffset = outerRect.bottom - innerRect.bottom;
- popup.openPopup(this.inputField, "after_start", 0, yOffset, false, false);
- }
- ]]></body>
- </method>
-
- <method name="observe">
- <parameter name="aSubject"/>
- <parameter name="aTopic"/>
- <parameter name="aData"/>
- <body><![CDATA[
- if (aTopic == "nsPref:changed") {
- switch (aData) {
- case "browser.search.suggest.enabled":
- this._suggestEnabled = this._prefBranch.getBoolPref(aData);
- this._suggestMenuItem.setAttribute("checked", this._suggestEnabled);
- break;
- case "browser.urlbar.clickSelectsAll":
- this._clickSelectsAll = this._prefBranch.getBoolPref(aData);
- this.setAttribute("clickSelectsAll", this._clickSelectsAll);
- break;
- }
- }
- ]]></body>
- </method>
-
- <method name="openSearch">
- <body>
- <![CDATA[
- // Don't open search popup if history popup is open
- if (!this.popupOpen) {
- document.getBindingParent(this).searchButton.open = true;
- return false;
- }
- return true;
- ]]>
- </body>
- </method>
-
- <!-- override |onTextEntered| in autocomplete.xml -->
- <method name="onTextEntered">
- <parameter name="aEvent"/>
- <body><![CDATA[
- var evt = aEvent || this.mEnterEvent;
- document.getBindingParent(this).handleSearchCommand(evt);
- this.mEnterEvent = null;
- ]]></body>
- </method>
-
- <!-- nsIController -->
- <field name="searchbarController" readonly="true"><![CDATA[({
- _self: this,
- supportsCommand: function(aCommand) {
- return aCommand == "cmd_clearhistory" ||
- aCommand == "cmd_togglesuggest";
- },
-
- isCommandEnabled: function(aCommand) {
- return true;
- },
-
- doCommand: function (aCommand) {
- switch (aCommand) {
- case "cmd_clearhistory":
- var param = this._self.getAttribute("autocompletesearchparam");
-
- let searchBar = this._self.parentNode;
-
- BrowserSearch.searchBar.FormHistory.update({ op : "remove", fieldname : param }, null);
- this._self.value = "";
- break;
- case "cmd_togglesuggest":
- // The pref observer will update _suggestEnabled and the menu
- // checkmark.
- this._self._prefBranch.setBoolPref("browser.search.suggest.enabled",
- !this._self._suggestEnabled);
- break;
- default:
- // do nothing with unrecognized command
- }
- }
- })]]></field>
- </implementation>
-
- <handlers>
- <handler event="keypress" keycode="VK_UP" modifiers="accel"
- phase="capturing"
- action="document.getBindingParent(this).selectEngine(event, false);"/>
-
- <handler event="keypress" keycode="VK_DOWN" modifiers="accel"
- phase="capturing"
- action="document.getBindingParent(this).selectEngine(event, true);"/>
-
- <handler event="keypress" keycode="VK_DOWN" modifiers="alt"
- phase="capturing"
- action="return this.openSearch();"/>
-
- <handler event="keypress" keycode="VK_UP" modifiers="alt"
- phase="capturing"
- action="return this.openSearch();"/>
-
-#ifndef XP_MACOSX
- <handler event="keypress" keycode="VK_F4"
- phase="capturing"
- action="return this.openSearch();"/>
-#endif
-
- <handler event="dragover">
- <![CDATA[
- var types = event.dataTransfer.types;
- if (types.contains("text/plain") || types.contains("text/x-moz-text-internal"))
- event.preventDefault();
- ]]>
- </handler>
-
- <handler event="drop">
- <![CDATA[
- var dataTransfer = event.dataTransfer;
- var data = dataTransfer.getData("text/plain");
- if (!data)
- data = dataTransfer.getData("text/x-moz-text-internal");
- if (data) {
- event.preventDefault();
- this.value = data;
- this.onTextEntered(event);
- }
- ]]>
- </handler>
-
- </handlers>
- </binding>
-</bindings>
diff --git a/components/search/content/searchbarBindings.css b/components/search/content/searchbarBindings.css
deleted file mode 100644
index b20e215..0000000
--- a/components/search/content/searchbarBindings.css
+++ /dev/null
@@ -1,13 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-@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;
-}
diff --git a/components/search/jar.mn b/components/search/jar.mn
deleted file mode 100644
index e6c42f9..0000000
--- a/components/search/jar.mn
+++ /dev/null
@@ -1,9 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-browser.jar:
-* content/browser/search/search.xml (content/search.xml)
- content/browser/search/searchbarBindings.css (content/searchbarBindings.css)
- content/browser/search/engineManager.xul (content/engineManager.xul)
- content/browser/search/engineManager.js (content/engineManager.js)
diff --git a/components/search/moz.build b/components/search/moz.build
deleted file mode 100644
index c97072b..0000000
--- a/components/search/moz.build
+++ /dev/null
@@ -1,7 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-JAR_MANIFESTS += ['jar.mn'] \ No newline at end of file
diff --git a/components/sessionstore/DocumentUtils.jsm b/components/sessionstore/DocumentUtils.jsm
deleted file mode 100644
index 6b3f729..0000000
--- a/components/sessionstore/DocumentUtils.jsm
+++ /dev/null
@@ -1,230 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-this.EXPORTED_SYMBOLS = [ "DocumentUtils" ];
-
-const Cu = Components.utils;
-const Ci = Components.interfaces;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource:///modules/sessionstore/XPathGenerator.jsm");
-
-this.DocumentUtils = {
- /**
- * Obtain form data for a DOMDocument instance.
- *
- * The returned object has 2 keys, "id" and "xpath". Each key holds an object
- * which further defines form data.
- *
- * The "id" object maps element IDs to values. The "xpath" object maps the
- * XPath of an element to its value.
- *
- * @param aDocument
- * DOMDocument instance to obtain form data for.
- * @return object
- * Form data encoded in an object.
- */
- getFormData: function DocumentUtils_getFormData(aDocument) {
- let formNodes = aDocument.evaluate(
- XPathGenerator.restorableFormNodes,
- aDocument,
- XPathGenerator.resolveNS,
- Ci.nsIDOMXPathResult.UNORDERED_NODE_ITERATOR_TYPE, null
- );
-
- let node;
- let ret = {id: {}, xpath: {}};
-
- // Limit the number of XPath expressions for performance reasons. See
- // bug 477564.
- const MAX_TRAVERSED_XPATHS = 100;
- let generatedCount = 0;
-
- while (node = formNodes.iterateNext()) {
- let nId = node.id;
- let hasDefaultValue = true;
- let value;
-
- // Only generate a limited number of XPath expressions for perf reasons
- // (cf. bug 477564)
- if (!nId && generatedCount > MAX_TRAVERSED_XPATHS) {
- continue;
- }
-
- if (node instanceof Ci.nsIDOMHTMLInputElement ||
- node instanceof Ci.nsIDOMHTMLTextAreaElement) {
- switch (node.type) {
- case "checkbox":
- case "radio":
- value = node.checked;
- hasDefaultValue = value == node.defaultChecked;
- break;
- case "file":
- value = { type: "file", fileList: node.mozGetFileNameArray() };
- hasDefaultValue = !value.fileList.length;
- break;
- default: // text, textarea
- value = node.value;
- hasDefaultValue = value == node.defaultValue;
- break;
- }
- } else if (!node.multiple) {
- // <select>s without the multiple attribute are hard to determine the
- // default value, so assume we don't have the default.
- hasDefaultValue = false;
- value = { selectedIndex: node.selectedIndex, value: node.value };
- } else {
- // <select>s with the multiple attribute are easier to determine the
- // default value since each <option> has a defaultSelected
- let options = Array.map(node.options, function(aOpt, aIx) {
- let oSelected = aOpt.selected;
- hasDefaultValue = hasDefaultValue && (oSelected == aOpt.defaultSelected);
- return oSelected ? aOpt.value : -1;
- });
- value = options.filter(function(aIx) aIx !== -1);
- }
-
- // In order to reduce XPath generation (which is slow), we only save data
- // for form fields that have been changed. (cf. bug 537289)
- if (!hasDefaultValue) {
- if (nId) {
- ret.id[nId] = value;
- } else {
- generatedCount++;
- ret.xpath[XPathGenerator.generate(node)] = value;
- }
- }
- }
-
- return ret;
- },
-
- /**
- * Merges form data on a document from previously obtained data.
- *
- * This is the inverse of getFormData(). The data argument is the same object
- * type which is returned by getFormData(): an object containing the keys
- * "id" and "xpath" which are each objects mapping element identifiers to
- * form values.
- *
- * Where the document has existing form data for an element, the value
- * will be replaced. Where the document has a form element but no matching
- * data in the passed object, the element is untouched.
- *
- * @param aDocument
- * DOMDocument instance to which to restore form data.
- * @param aData
- * Object defining form data.
- */
- mergeFormData: function DocumentUtils_mergeFormData(aDocument, aData) {
- if ("xpath" in aData) {
- for each (let [xpath, value] in Iterator(aData.xpath)) {
- let node = XPathGenerator.resolve(aDocument, xpath);
-
- if (node) {
- this.restoreFormValue(node, value, aDocument);
- }
- }
- }
-
- if ("id" in aData) {
- for each (let [id, value] in Iterator(aData.id)) {
- let node = aDocument.getElementById(id);
-
- if (node) {
- this.restoreFormValue(node, value, aDocument);
- }
- }
- }
- },
-
- /**
- * Low-level function to restore a form value to a DOMNode.
- *
- * If you want a higher-level interface, see mergeFormData().
- *
- * When the value is changed, the function will fire the appropriate DOM
- * events.
- *
- * @param aNode
- * DOMNode to set form value on.
- * @param aValue
- * Value to set form element to.
- * @param aDocument [optional]
- * DOMDocument node belongs to. If not defined, node.ownerDocument
- * is used.
- */
- restoreFormValue: function DocumentUtils_restoreFormValue(aNode, aValue, aDocument) {
- aDocument = aDocument || aNode.ownerDocument;
-
- let eventType;
-
- if (typeof aValue == "string" && aNode.type != "file") {
- // Don't dispatch an input event if there is no change.
- if (aNode.value == aValue) {
- return;
- }
-
- aNode.value = aValue;
- eventType = "input";
- } else if (typeof aValue == "boolean") {
- // Don't dispatch a change event for no change.
- if (aNode.checked == aValue) {
- return;
- }
-
- aNode.checked = aValue;
- eventType = "change";
- } else if (typeof aValue == "number") {
- // handle select backwards compatibility, example { "#id" : index }
- // We saved the value blindly since selects take more work to determine
- // default values. So now we should check to avoid unnecessary events.
- if (aNode.selectedIndex == aValue) {
- return;
- }
-
- if (aValue < aNode.options.length) {
- aNode.selectedIndex = aValue;
- eventType = "change";
- }
- } else if (aValue && aValue.selectedIndex >= 0 && aValue.value) {
- // handle select new format
-
- // Don't dispatch a change event for no change
- if (aNode.options[aNode.selectedIndex].value == aValue.value) {
- return;
- }
-
- // find first option with matching aValue if possible
- for (let i = 0; i < aNode.options.length; i++) {
- if (aNode.options[i].value == aValue.value) {
- aNode.selectedIndex = i;
- break;
- }
- }
- eventType = "change";
- } else if (aValue && aValue.fileList && aValue.type == "file" &&
- aNode.type == "file") {
- aNode.mozSetFileNameArray(aValue.fileList, aValue.fileList.length);
- eventType = "input";
- } else if (aValue && typeof aValue.indexOf == "function" && aNode.options) {
- Array.forEach(aNode.options, function(opt, index) {
- // don't worry about malformed options with same values
- opt.selected = aValue.indexOf(opt.value) > -1;
-
- // Only fire the event here if this wasn't selected by default
- if (!opt.defaultSelected) {
- eventType = "change";
- }
- });
- }
-
- // Fire events for this node if applicable
- if (eventType) {
- let event = aDocument.createEvent("UIEvents");
- event.initUIEvent(eventType, true, true, aDocument.defaultView, 0);
- aNode.dispatchEvent(event);
- }
- }
-};
diff --git a/components/sessionstore/SessionStorage.jsm b/components/sessionstore/SessionStorage.jsm
deleted file mode 100644
index 64aef35..0000000
--- a/components/sessionstore/SessionStorage.jsm
+++ /dev/null
@@ -1,165 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
-* License, v. 2.0. If a copy of the MPL was not distributed with this file,
-* You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-this.EXPORTED_SYMBOLS = ["SessionStorage"];
-
-const Cu = Components.utils;
-
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "SessionStore",
- "resource:///modules/sessionstore/SessionStore.jsm");
-
-this.SessionStorage = {
- /**
- * Updates all sessionStorage "super cookies"
- * @param aDocShell
- * That tab's docshell (containing the sessionStorage)
- * @param aFullData
- * always return privacy sensitive data (use with care)
- */
- serialize: function ssto_serialize(aDocShell, aFullData) {
- return DomStorage.read(aDocShell, aFullData);
- },
-
- /**
- * Restores all sessionStorage "super cookies".
- * @param aDocShell
- * A tab's docshell (containing the sessionStorage)
- * @param aStorageData
- * Storage data to be restored
- */
- deserialize: function ssto_deserialize(aDocShell, aStorageData) {
- DomStorage.write(aDocShell, aStorageData);
- }
-};
-
-Object.freeze(SessionStorage);
-
-var DomStorage = {
- /**
- * Reads all session storage data from the given docShell.
- * @param aDocShell
- * A tab's docshell (containing the sessionStorage)
- * @param aFullData
- * Always return privacy sensitive data (use with care)
- */
- read: function DomStorage_read(aDocShell, aFullData) {
- let data = {};
- let isPinned = aDocShell.isAppTab;
- let shistory = aDocShell.sessionHistory;
-
- for (let i = 0; i < shistory.count; i++) {
- let principal = History.getPrincipalForEntry(shistory, i, aDocShell);
- if (!principal)
- continue;
-
- // Check if we're allowed to store sessionStorage data.
- let isHTTPS = principal.URI && principal.URI.schemeIs("https");
- if (aFullData || SessionStore.checkPrivacyLevel(isHTTPS, isPinned)) {
- let origin = principal.extendedOrigin;
-
- // Don't read a host twice.
- if (!(origin in data)) {
- let originData = this._readEntry(principal, aDocShell);
- if (Object.keys(originData).length) {
- data[origin] = originData;
- }
- }
- }
- }
-
- return data;
- },
-
- /**
- * Writes session storage data to the given tab.
- * @param aDocShell
- * A tab's docshell (containing the sessionStorage)
- * @param aStorageData
- * Storage data to be restored
- */
- write: function DomStorage_write(aDocShell, aStorageData) {
- for (let [host, data] in Iterator(aStorageData)) {
- let uri = Services.io.newURI(host, null, null);
- let principal = Services.scriptSecurityManager.getDocShellCodebasePrincipal(uri, aDocShell);
- let storageManager = aDocShell.QueryInterface(Components.interfaces.nsIDOMStorageManager);
- let window = aDocShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
- .getInterface(Components.interfaces.nsIDOMWindow);
-
- // There is no need to pass documentURI, it's only used to fill documentURI property of
- // domstorage event, which in this case has no consumer. Prevention of events in case
- // of missing documentURI will be solved in a followup bug to bug 600307.
- try {
- let storage = storageManager.createStorage(window, principal, "", aDocShell.usePrivateBrowsing);
- } catch(e) {
- Cu.reportError(e);
- }
-
- for (let [key, value] in Iterator(data)) {
- try {
- storage.setItem(key, value);
- } catch (e) {
- // throws e.g. for URIs that can't have sessionStorage
- Cu.reportError(e);
- }
- }
- }
- },
-
- /**
- * Reads an entry in the session storage data contained in a tab's history.
- * @param aURI
- * That history entry uri
- * @param aDocShell
- * A tab's docshell (containing the sessionStorage)
- */
- _readEntry: function DomStorage_readEntry(aPrincipal, aDocShell) {
- let hostData = {};
- let storage;
-
- try {
- let storageManager = aDocShell.QueryInterface(Components.interfaces.nsIDOMStorageManager);
- storage = storageManager.getStorage(aPrincipal);
- } catch (e) {
- // sessionStorage might throw if it's turned off, see bug 458954
- }
-
- if (storage && storage.length) {
- for (let i = 0; i < storage.length; i++) {
- try {
- let key = storage.key(i);
- hostData[key] = storage.getItem(key);
- } catch (e) {
- // This currently throws for secured items (cf. bug 442048).
- }
- }
- }
-
- return hostData;
- }
-};
-
-var History = {
- /**
- * Returns a given history entry's URI.
- * @param aHistory
- * That tab's session history
- * @param aIndex
- * The history entry's index
- * @param aDocShell
- * That tab's docshell
- */
- getPrincipalForEntry: function History_getPrincipalForEntry(aHistory,
- aIndex,
- aDocShell) {
- try {
- return Services.scriptSecurityManager.getDocShellCodebasePrincipal(
- aHistory.getEntryAtIndex(aIndex, false).URI, aDocShell);
- } catch (e) {
- // This might throw for some reason.
- }
- },
-};
diff --git a/components/sessionstore/SessionStore.jsm b/components/sessionstore/SessionStore.jsm
deleted file mode 100644
index e19a578..0000000
--- a/components/sessionstore/SessionStore.jsm
+++ /dev/null
@@ -1,4786 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-this.EXPORTED_SYMBOLS = ["SessionStore"];
-
-const Cu = Components.utils;
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-const Cr = Components.results;
-
-const STATE_STOPPED = 0;
-const STATE_RUNNING = 1;
-const STATE_QUITTING = -1;
-
-const STATE_STOPPED_STR = "stopped";
-const STATE_RUNNING_STR = "running";
-
-const TAB_STATE_NEEDS_RESTORE = 1;
-const TAB_STATE_RESTORING = 2;
-
-const PRIVACY_NONE = 0;
-const PRIVACY_ENCRYPTED = 1;
-const PRIVACY_FULL = 2;
-
-const NOTIFY_WINDOWS_RESTORED = "sessionstore-windows-restored";
-const NOTIFY_BROWSER_STATE_RESTORED = "sessionstore-browser-state-restored";
-
-// Default maximum number of tabs to restore simultaneously. Controlled by
-// the browser.sessionstore.max_concurrent_tabs pref.
-const DEFAULT_MAX_CONCURRENT_TAB_RESTORES = 3;
-
-// global notifications observed
-const OBSERVING = [
- "domwindowopened", "domwindowclosed",
- "quit-application-requested", "quit-application-granted",
- "browser-lastwindow-close-granted",
- "quit-application", "browser:purge-session-history",
- "browser:purge-domain-data"
-];
-
-// XUL Window properties to (re)store
-// Restored in restoreDimensions()
-const WINDOW_ATTRIBUTES = ["width", "height", "screenX", "screenY", "sizemode"];
-
-// Hideable window features to (re)store
-// Restored in restoreWindowFeatures()
-const WINDOW_HIDEABLE_FEATURES = [
- "menubar", "toolbar", "locationbar", "personalbar", "statusbar", "scrollbars"
-];
-
-const MESSAGES = [
- // The content script tells us that its form data (or that of one of its
- // subframes) might have changed. This can be the contents or values of
- // standard form fields or of ContentEditables.
- "SessionStore:input",
-
- // The content script has received a pageshow event. This happens when a
- // page is loaded from bfcache without any network activity, i.e. when
- // clicking the back or forward button.
- "SessionStore:pageshow"
-];
-
-// These are tab events that we listen to.
-const TAB_EVENTS = [
- "TabOpen", "TabClose", "TabSelect", "TabShow", "TabHide", "TabPinned",
- "TabUnpinned"
-];
-
-#ifndef XP_WIN
-#define BROKEN_WM_Z_ORDER
-#endif
-
-Cu.import("resource://gre/modules/Services.jsm", this);
-Cu.import("resource://gre/modules/XPCOMUtils.jsm", this);
-// debug.js adds NS_ASSERT. cf. bug 669196
-Cu.import("resource://gre/modules/debug.js", this);
-Cu.import("resource://gre/modules/osfile.jsm", this);
-Cu.import("resource://gre/modules/PrivateBrowsingUtils.jsm", this);
-Cu.import("resource://gre/modules/Promise.jsm", this);
-
-XPCOMUtils.defineLazyServiceGetter(this, "gSessionStartup",
- "@mozilla.org/browser/sessionstartup;1", "nsISessionStartup");
-XPCOMUtils.defineLazyServiceGetter(this, "gScreenManager",
- "@mozilla.org/gfx/screenmanager;1", "nsIScreenManager");
-
-// List of docShell capabilities to (re)store. These are automatically
-// retrieved from a given docShell if not already collected before.
-// This is made so they're automatically in sync with all nsIDocShell.allow*
-// properties.
-var gDocShellCapabilities = (function () {
- let caps;
-
- return docShell => {
- if (!caps) {
- let keys = Object.keys(docShell);
- caps = keys.filter(k => k.startsWith("allow")).map(k => k.slice(5));
- }
-
- return caps;
- };
-})();
-
-XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
- "resource://gre/modules/NetUtil.jsm");
-
-#ifdef MOZ_DEVTOOLS
-XPCOMUtils.defineLazyModuleGetter(this, "ScratchpadManager",
- "resource://devtools/client/scratchpad/scratchpad-manager.jsm");
-
-Object.defineProperty(this, "HUDService", {
- get: function HUDService_getter() {
- let devtools = Cu.import("resource://devtools/shared/Loader.jsm", {}).devtools;
- return devtools.require("devtools/client/webconsole/hudservice").HUDService;
- },
- configurable: true,
- enumerable: true
-});
-#endif
-
-XPCOMUtils.defineLazyModuleGetter(this, "DocumentUtils",
- "resource:///modules/sessionstore/DocumentUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "SessionStorage",
- "resource:///modules/sessionstore/SessionStorage.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "_SessionFile",
- "resource:///modules/sessionstore/_SessionFile.jsm");
-
-function debug(aMsg) {
- aMsg = ("SessionStore: " + aMsg).replace(/\S{80}/g, "$&\n");
- Services.console.logStringMessage(aMsg);
-}
-
-this.SessionStore = {
- get promiseInitialized() {
- return SessionStoreInternal.promiseInitialized.promise;
- },
-
- get canRestoreLastSession() {
- return SessionStoreInternal.canRestoreLastSession;
- },
-
- set canRestoreLastSession(val) {
- SessionStoreInternal.canRestoreLastSession = val;
- },
-
- init: function ss_init(aWindow) {
- return SessionStoreInternal.init(aWindow);
- },
-
- getBrowserState: function ss_getBrowserState() {
- return SessionStoreInternal.getBrowserState();
- },
-
- setBrowserState: function ss_setBrowserState(aState) {
- SessionStoreInternal.setBrowserState(aState);
- },
-
- getWindowState: function ss_getWindowState(aWindow) {
- return SessionStoreInternal.getWindowState(aWindow);
- },
-
- setWindowState: function ss_setWindowState(aWindow, aState, aOverwrite) {
- SessionStoreInternal.setWindowState(aWindow, aState, aOverwrite);
- },
-
- getTabState: function ss_getTabState(aTab) {
- return SessionStoreInternal.getTabState(aTab);
- },
-
- setTabState: function ss_setTabState(aTab, aState) {
- SessionStoreInternal.setTabState(aTab, aState);
- },
-
- duplicateTab: function ss_duplicateTab(aWindow, aTab, aDelta) {
- return SessionStoreInternal.duplicateTab(aWindow, aTab, aDelta);
- },
-
- getClosedTabCount: function ss_getClosedTabCount(aWindow) {
- return SessionStoreInternal.getClosedTabCount(aWindow);
- },
-
- getClosedTabData: function ss_getClosedTabDataAt(aWindow) {
- return SessionStoreInternal.getClosedTabData(aWindow);
- },
-
- undoCloseTab: function ss_undoCloseTab(aWindow, aIndex) {
- return SessionStoreInternal.undoCloseTab(aWindow, aIndex);
- },
-
- forgetClosedTab: function ss_forgetClosedTab(aWindow, aIndex) {
- return SessionStoreInternal.forgetClosedTab(aWindow, aIndex);
- },
-
- getClosedWindowCount: function ss_getClosedWindowCount() {
- return SessionStoreInternal.getClosedWindowCount();
- },
-
- getClosedWindowData: function ss_getClosedWindowData() {
- return SessionStoreInternal.getClosedWindowData();
- },
-
- undoCloseWindow: function ss_undoCloseWindow(aIndex) {
- return SessionStoreInternal.undoCloseWindow(aIndex);
- },
-
- forgetClosedWindow: function ss_forgetClosedWindow(aIndex) {
- return SessionStoreInternal.forgetClosedWindow(aIndex);
- },
-
- getWindowValue: function ss_getWindowValue(aWindow, aKey) {
- return SessionStoreInternal.getWindowValue(aWindow, aKey);
- },
-
- setWindowValue: function ss_setWindowValue(aWindow, aKey, aStringValue) {
- SessionStoreInternal.setWindowValue(aWindow, aKey, aStringValue);
- },
-
- deleteWindowValue: function ss_deleteWindowValue(aWindow, aKey) {
- SessionStoreInternal.deleteWindowValue(aWindow, aKey);
- },
-
- getTabValue: function ss_getTabValue(aTab, aKey) {
- return SessionStoreInternal.getTabValue(aTab, aKey);
- },
-
- setTabValue: function ss_setTabValue(aTab, aKey, aStringValue) {
- SessionStoreInternal.setTabValue(aTab, aKey, aStringValue);
- },
-
- deleteTabValue: function ss_deleteTabValue(aTab, aKey) {
- SessionStoreInternal.deleteTabValue(aTab, aKey);
- },
-
- persistTabAttribute: function ss_persistTabAttribute(aName) {
- SessionStoreInternal.persistTabAttribute(aName);
- },
-
- restoreLastSession: function ss_restoreLastSession() {
- SessionStoreInternal.restoreLastSession();
- },
-
- checkPrivacyLevel: function ss_checkPrivacyLevel(aIsHTTPS, aUseDefaultPref) {
- return SessionStoreInternal.checkPrivacyLevel(aIsHTTPS, aUseDefaultPref);
- }
-};
-
-// Freeze the SessionStore object. We don't want anyone to modify it.
-Object.freeze(SessionStore);
-
-var SessionStoreInternal = {
- QueryInterface: XPCOMUtils.generateQI([
- Ci.nsIDOMEventListener,
- Ci.nsIObserver,
- Ci.nsISupportsWeakReference
- ]),
-
- // set default load state
- _loadState: STATE_STOPPED,
-
- // During the initial restore and setBrowserState calls tracks the number of
- // windows yet to be restored
- _restoreCount: -1,
-
- // whether a setBrowserState call is in progress
- _browserSetState: false,
-
- // time in milliseconds (Date.now()) when the session was last written to file
- _lastSaveTime: 0,
-
- // time in milliseconds when the session was started (saved across sessions),
- // defaults to now if no session was restored or timestamp doesn't exist
- _sessionStartTime: Date.now(),
-
- // states for all currently opened windows
- _windows: {},
-
- // internal states for all open windows (data we need to associate,
- // but not write to disk)
- _internalWindows: {},
-
- // states for all recently closed windows
- _closedWindows: [],
-
- // not-"dirty" windows usually don't need to have their data updated
- _dirtyWindows: {},
-
- // collection of session states yet to be restored
- _statesToRestore: {},
-
- // counts the number of crashes since the last clean start
- _recentCrashes: 0,
-
- // whether the last window was closed and should be restored
- _restoreLastWindow: false,
-
- // number of tabs currently restoring
- _tabsRestoringCount: 0,
-
- // max number of tabs to restore concurrently
- _maxConcurrentTabRestores: DEFAULT_MAX_CONCURRENT_TAB_RESTORES,
-
- // whether restored tabs load cached versions or force a reload
- _cacheBehavior: 0,
-
- // The state from the previous session (after restoring pinned tabs). This
- // state is persisted and passed through to the next session during an app
- // restart to make the third party add-on warning not trash the deferred
- // session
- _lastSessionState: null,
-
- // When starting Firefox with a single private window, this is the place
- // where we keep the session we actually wanted to restore in case the user
- // decides to later open a non-private window as well.
- _deferredInitialState: null,
-
- // A promise resolved once initialization is complete
- _promiseInitialization: Promise.defer(),
-
- // Whether session has been initialized
- _sessionInitialized: false,
-
- // True if session store is disabled by multi-process browsing.
- // See bug 516755.
- _disabledForMultiProcess: false,
-
- // The original "sessionstore.resume_session_once" preference value before it
- // was modified by saveState. saveState will set the
- // "sessionstore.resume_session_once" to true when the
- // the "sessionstore.resume_from_crash" preference is false (crash recovery
- // is disabled) so that pinned tabs will be restored in the case of a
- // crash. This variable is used to restore the original value so the
- // previous session is not always restored when
- // "sessionstore.resume_from_crash" is true.
- _resume_session_once_on_shutdown: null,
-
- /**
- * A promise fulfilled once initialization is complete.
- */
- get promiseInitialized() {
- return this._promiseInitialization;
- },
-
- /* ........ Public Getters .............. */
- get canRestoreLastSession() {
- return this._lastSessionState;
- },
-
- set canRestoreLastSession(val) {
- this._lastSessionState = null;
- },
-
- /* ........ Global Event Handlers .............. */
-
- /**
- * Initialize the component
- */
- initService: function ssi_initService() {
- if (this._sessionInitialized) {
- return;
- }
- OBSERVING.forEach(function(aTopic) {
- Services.obs.addObserver(this, aTopic, true);
- }, this);
-
- this._initPrefs();
-
- this._disabledForMultiProcess = false;
-
- // this pref is only read at startup, so no need to observe it
- this._sessionhistory_max_entries =
- this._prefBranch.getIntPref("sessionhistory.max_entries");
-
- gSessionStartup.onceInitialized.then(
- this.initSession.bind(this)
- );
- },
-
- initSession: function ssi_initSession() {
- let ss = gSessionStartup;
- try {
- if (ss.doRestore() ||
- ss.sessionType == Ci.nsISessionStartup.DEFER_SESSION)
- this._initialState = ss.state;
- }
- catch(ex) { dump(ex + "\n"); } // no state to restore, which is ok
-
- if (this._initialState) {
- try {
- // If we're doing a DEFERRED session, then we want to pull pinned tabs
- // out so they can be restored.
- if (ss.sessionType == Ci.nsISessionStartup.DEFER_SESSION) {
- let [iniState, remainingState] = this._prepDataForDeferredRestore(this._initialState);
- // If we have a iniState with windows, that means that we have windows
- // with app tabs to restore.
- if (iniState.windows.length)
- this._initialState = iniState;
- else
- this._initialState = null;
- if (remainingState.windows.length)
- this._lastSessionState = remainingState;
- }
- else {
- // Get the last deferred session in case the user still wants to
- // restore it
- this._lastSessionState = this._initialState.lastSessionState;
-
- let lastSessionCrashed =
- this._initialState.session && this._initialState.session.state &&
- this._initialState.session.state == STATE_RUNNING_STR;
- if (lastSessionCrashed) {
- this._recentCrashes = (this._initialState.session &&
- this._initialState.session.recentCrashes || 0) + 1;
-
- if (this._needsRestorePage(this._initialState, this._recentCrashes)) {
- // replace the crashed session with a restore-page-only session
- let pageData = {
- url: "about:sessionrestore",
- formdata: {
- id: { "sessionData": this._initialState },
- xpath: {}
- }
- };
- this._initialState = { windows: [{ tabs: [{ entries: [pageData] }] }] };
- }
- }
-
- // Load the session start time from the previous state
- this._sessionStartTime = this._initialState.session &&
- this._initialState.session.startTime ||
- this._sessionStartTime;
-
- // make sure that at least the first window doesn't have anything hidden
- delete this._initialState.windows[0].hidden;
- // Since nothing is hidden in the first window, it cannot be a popup
- delete this._initialState.windows[0].isPopup;
- // We don't want to minimize and then open a window at startup.
- if (this._initialState.windows[0].sizemode == "minimized")
- this._initialState.windows[0].sizemode = "normal";
- // clear any lastSessionWindowID attributes since those don't matter
- // during normal restore
- this._initialState.windows.forEach(function(aWindow) {
- delete aWindow.__lastSessionWindowID;
- });
- }
- }
- catch (ex) { debug("The session file is invalid: " + ex); }
- }
-
- // A Lazy getter for the sessionstore.js backup promise.
- XPCOMUtils.defineLazyGetter(this, "_backupSessionFileOnce", function () {
- return _SessionFile.createBackupCopy();
- });
-
- // at this point, we've as good as resumed the session, so we can
- // clear the resume_session_once flag, if it's set
- if (this._loadState != STATE_QUITTING &&
- this._prefBranch.getBoolPref("sessionstore.resume_session_once"))
- this._prefBranch.setBoolPref("sessionstore.resume_session_once", false);
-
- this._initEncoding();
-
- // Session is ready.
- this._sessionInitialized = true;
- this._promiseInitialization.resolve();
- },
-
- _initEncoding : function ssi_initEncoding() {
- // The (UTF-8) encoder used to write to files.
- XPCOMUtils.defineLazyGetter(this, "_writeFileEncoder", function () {
- return new TextEncoder();
- });
- },
-
- _initPrefs : function() {
- XPCOMUtils.defineLazyGetter(this, "_prefBranch", function () {
- return Services.prefs.getBranch("browser.");
- });
-
- // minimal interval between two save operations (in milliseconds)
- XPCOMUtils.defineLazyGetter(this, "_interval", function () {
- // used often, so caching/observing instead of fetching on-demand
- this._prefBranch.addObserver("sessionstore.interval", this, true);
- return this._prefBranch.getIntPref("sessionstore.interval");
- });
-
- // when crash recovery is disabled, session data is not written to disk
- XPCOMUtils.defineLazyGetter(this, "_resume_from_crash", function () {
- // get crash recovery state from prefs and allow for proper reaction to state changes
- this._prefBranch.addObserver("sessionstore.resume_from_crash", this, true);
- return this._prefBranch.getBoolPref("sessionstore.resume_from_crash");
- });
-
- this._max_tabs_undo = this._prefBranch.getIntPref("sessionstore.max_tabs_undo");
- this._prefBranch.addObserver("sessionstore.max_tabs_undo", this, true);
-
- this._max_windows_undo = this._prefBranch.getIntPref("sessionstore.max_windows_undo");
- this._prefBranch.addObserver("sessionstore.max_windows_undo", this, true);
-
- // Straight-up collect the following one-time prefs
- this._maxConcurrentTabRestores =
- Services.prefs.getIntPref("browser.sessionstore.max_concurrent_tabs");
- // ensure a sane value for concurrency, ignore and set default otherwise
- if (this._maxConcurrentTabRestores < 1 || this._maxConcurrentTabRestores > 10) {
- this._maxConcurrentTabRestores = DEFAULT_MAX_CONCURRENT_TAB_RESTORES;
- }
- this._cacheBehavior =
- Services.prefs.getIntPref("browser.sessionstore.cache_behavior");
-
- },
-
- _initWindow: function ssi_initWindow(aWindow) {
- if (aWindow) {
- this.onLoad(aWindow);
- } else if (this._loadState == STATE_STOPPED) {
- // If init is being called with a null window, it's possible that we
- // just want to tell sessionstore that a session is live (as is the case
- // with starting Firefox with -private, for example; see bug 568816),
- // so we should mark the load state as running to make sure that
- // things like setBrowserState calls will succeed in restoring the session.
- this._loadState = STATE_RUNNING;
- }
- },
-
- /**
- * Start tracking a window.
- *
- * This function also initializes the component if it is not
- * initialized yet.
- */
- init: function ssi_init(aWindow) {
- let self = this;
- this.initService();
- return this._promiseInitialization.promise.then(
- function onSuccess() {
- self._initWindow(aWindow);
- }
- );
- },
-
- /**
- * Called on application shutdown, after notifications:
- * quit-application-granted, quit-application
- */
- _uninit: function ssi_uninit() {
- // save all data for session resuming
- if (this._sessionInitialized)
- this.saveState(true);
-
- // clear out priority queue in case it's still holding refs
- TabRestoreQueue.reset();
-
- // Make sure to break our cycle with the save timer
- if (this._saveTimer) {
- this._saveTimer.cancel();
- this._saveTimer = null;
- }
- },
-
- /**
- * Handle notifications
- */
- observe: function ssi_observe(aSubject, aTopic, aData) {
- if (this._disabledForMultiProcess)
- return;
-
- switch (aTopic) {
- case "domwindowopened": // catch new windows
- this.onOpen(aSubject);
- break;
- case "domwindowclosed": // catch closed windows
- this.onClose(aSubject);
- break;
- case "quit-application-requested":
- this.onQuitApplicationRequested();
- break;
- case "quit-application-granted":
- this.onQuitApplicationGranted();
- break;
- case "browser-lastwindow-close-granted":
- this.onLastWindowCloseGranted();
- break;
- case "quit-application":
- this.onQuitApplication(aData);
- break;
- case "browser:purge-session-history": // catch sanitization
- this.onPurgeSessionHistory();
- break;
- case "browser:purge-domain-data":
- this.onPurgeDomainData(aData);
- break;
- case "nsPref:changed": // catch pref changes
- this.onPrefChange(aData);
- break;
- case "timer-callback": // timer call back for delayed saving
- this.onTimerCallback();
- break;
- }
- },
-
- /**
- * This method handles incoming messages sent by the session store content
- * script and thus enables communication with OOP tabs.
- */
- receiveMessage: function ssi_receiveMessage(aMessage) {
- var browser = aMessage.target;
- var win = browser.ownerDocument.defaultView;
-
- switch (aMessage.name) {
- case "SessionStore:pageshow":
- this.onTabLoad(win, browser);
- break;
- case "SessionStore:input":
- this.onTabInput(win, browser);
- break;
- default:
- debug("received unknown message '" + aMessage.name + "'");
- break;
- }
-
- this._clearRestoringWindows();
- },
-
- /* ........ Window Event Handlers .............. */
-
- /**
- * Implement nsIDOMEventListener for handling various window and tab events
- */
- handleEvent: function ssi_handleEvent(aEvent) {
- if (this._disabledForMultiProcess)
- return;
-
- var win = aEvent.currentTarget.ownerDocument.defaultView;
- switch (aEvent.type) {
- case "load":
- // If __SS_restore_data is set, then we need to restore the document
- // (form data, scrolling, etc.). This will only happen when a tab is
- // first restored.
- let browser = aEvent.currentTarget;
- if (browser.__SS_restore_data)
- this.restoreDocument(win, browser, aEvent);
- this.onTabLoad(win, browser);
- break;
- case "TabOpen":
- this.onTabAdd(win, aEvent.originalTarget);
- break;
- case "TabClose":
- // aEvent.detail determines if the tab was closed by moving to a different window
- if (!aEvent.detail)
- this.onTabClose(win, aEvent.originalTarget);
- this.onTabRemove(win, aEvent.originalTarget);
- break;
- case "TabSelect":
- this.onTabSelect(win);
- break;
- case "TabShow":
- this.onTabShow(win, aEvent.originalTarget);
- break;
- case "TabHide":
- this.onTabHide(win, aEvent.originalTarget);
- break;
- case "TabPinned":
- case "TabUnpinned":
- this.saveStateDelayed(win);
- break;
- }
-
- this._clearRestoringWindows();
- },
-
- /**
- * If it's the first window load since app start...
- * - determine if we're reloading after a crash or a forced-restart
- * - restore window state
- * - restart downloads
- * Set up event listeners for this window's tabs
- * @param aWindow
- * Window reference
- */
- onLoad: function ssi_onLoad(aWindow) {
- // return if window has already been initialized
- if (aWindow && aWindow.__SSi && this._windows[aWindow.__SSi])
- return;
-
- // ignore non-browser windows and windows opened while shutting down
- if (aWindow.document.documentElement.getAttribute("windowtype") != "navigator:browser" ||
- this._loadState == STATE_QUITTING)
- return;
-
- // assign it a unique identifier (timestamp)
- aWindow.__SSi = "window" + Date.now();
-
- // and create its data object
- this._windows[aWindow.__SSi] = { tabs: [], selected: 0, _closedTabs: [], busy: false };
-
- // and create its internal data object
- this._internalWindows[aWindow.__SSi] = { hosts: {} }
-
- let isPrivateWindow = false;
- if (PrivateBrowsingUtils.isWindowPrivate(aWindow))
- this._windows[aWindow.__SSi].isPrivate = isPrivateWindow = true;
- if (!this._isWindowLoaded(aWindow))
- this._windows[aWindow.__SSi]._restoring = true;
- if (!aWindow.toolbar.visible)
- this._windows[aWindow.__SSi].isPopup = true;
-
- // perform additional initialization when the first window is loading
- if (this._loadState == STATE_STOPPED) {
- this._loadState = STATE_RUNNING;
- this._lastSaveTime = Date.now();
-
- // restore a crashed session resp. resume the last session if requested
- if (this._initialState) {
- if (isPrivateWindow) {
- // We're starting with a single private window. Save the state we
- // actually wanted to restore so that we can do it later in case
- // the user opens another, non-private window.
- this._deferredInitialState = gSessionStartup.state;
- delete this._initialState;
-
- // Nothing to restore now, notify observers things are complete.
- Services.obs.notifyObservers(null, NOTIFY_WINDOWS_RESTORED, "");
- } else {
- // make sure that the restored tabs are first in the window
- this._initialState._firstTabs = true;
- this._restoreCount = this._initialState.windows ? this._initialState.windows.length : 0;
- this.restoreWindow(aWindow, this._initialState,
- this._isCmdLineEmpty(aWindow, this._initialState));
- delete this._initialState;
-
- // _loadState changed from "stopped" to "running"
- // force a save operation so that crashes happening during startup are correctly counted
- this.saveState(true);
- }
- }
- else {
- // Nothing to restore, notify observers things are complete.
- Services.obs.notifyObservers(null, NOTIFY_WINDOWS_RESTORED, "");
-
- // the next delayed save request should execute immediately
- this._lastSaveTime -= this._interval;
- }
- }
- // this window was opened by _openWindowWithState
- else if (!this._isWindowLoaded(aWindow)) {
- let followUp = this._statesToRestore[aWindow.__SS_restoreID].windows.length == 1;
- this.restoreWindow(aWindow, this._statesToRestore[aWindow.__SS_restoreID], true, followUp);
- }
- // The user opened another, non-private window after starting up with
- // a single private one. Let's restore the session we actually wanted to
- // restore at startup.
- else if (this._deferredInitialState && !isPrivateWindow &&
- aWindow.toolbar.visible) {
-
- this._deferredInitialState._firstTabs = true;
- this._restoreCount = this._deferredInitialState.windows ?
- this._deferredInitialState.windows.length : 0;
- this.restoreWindow(aWindow, this._deferredInitialState, false);
- this._deferredInitialState = null;
- }
- else if (this._restoreLastWindow && aWindow.toolbar.visible &&
- this._closedWindows.length && !isPrivateWindow) {
-
- // default to the most-recently closed window
- // don't use popup windows
- let closedWindowState = null;
- let closedWindowIndex;
- for (let i = 0; i < this._closedWindows.length; i++) {
- // Take the first non-popup, point our object at it, and break out.
- if (!this._closedWindows[i].isPopup) {
- closedWindowState = this._closedWindows[i];
- closedWindowIndex = i;
- break;
- }
- }
-
- if (closedWindowState) {
- let newWindowState;
-#ifndef XP_MACOSX
- if (!this._doResumeSession()) {
-#endif
- // We want to split the window up into pinned tabs and unpinned tabs.
- // Pinned tabs should be restored. If there are any remaining tabs,
- // they should be added back to _closedWindows.
- // We'll cheat a little bit and reuse _prepDataForDeferredRestore
- // even though it wasn't built exactly for this.
- let [appTabsState, normalTabsState] =
- this._prepDataForDeferredRestore({ windows: [closedWindowState] });
-
- // These are our pinned tabs, which we should restore
- if (appTabsState.windows.length) {
- newWindowState = appTabsState.windows[0];
- delete newWindowState.__lastSessionWindowID;
- }
-
- // In case there were no unpinned tabs, remove the window from _closedWindows
- if (!normalTabsState.windows.length) {
- this._closedWindows.splice(closedWindowIndex, 1);
- }
- // Or update _closedWindows with the modified state
- else {
- delete normalTabsState.windows[0].__lastSessionWindowID;
- this._closedWindows[closedWindowIndex] = normalTabsState.windows[0];
- }
-#ifndef XP_MACOSX
- }
- else {
- // If we're just restoring the window, make sure it gets removed from
- // _closedWindows.
- this._closedWindows.splice(closedWindowIndex, 1);
- newWindowState = closedWindowState;
- delete newWindowState.hidden;
- }
-#endif
- if (newWindowState) {
- // Ensure that the window state isn't hidden
- this._restoreCount = 1;
- let state = { windows: [newWindowState] };
- this.restoreWindow(aWindow, state, this._isCmdLineEmpty(aWindow, state));
- }
- }
- // we actually restored the session just now.
- this._prefBranch.setBoolPref("sessionstore.resume_session_once", false);
- }
- if (this._restoreLastWindow && aWindow.toolbar.visible) {
- // always reset (if not a popup window)
- // we don't want to restore a window directly after, for example,
- // undoCloseWindow was executed.
- this._restoreLastWindow = false;
- }
-
- var tabbrowser = aWindow.gBrowser;
-
- // add tab change listeners to all already existing tabs
- for (let i = 0; i < tabbrowser.tabs.length; i++) {
- this.onTabAdd(aWindow, tabbrowser.tabs[i], true);
- }
- // notification of tab add/remove/selection/show/hide
- TAB_EVENTS.forEach(function(aEvent) {
- tabbrowser.tabContainer.addEventListener(aEvent, this, true);
- }, this);
- },
-
- /**
- * On window open
- * @param aWindow
- * Window reference
- */
- onOpen: function ssi_onOpen(aWindow) {
- var _this = this;
- aWindow.addEventListener("load", function(aEvent) {
- aEvent.currentTarget.removeEventListener("load", arguments.callee, false);
- _this.onLoad(aEvent.currentTarget);
- }, false);
- return;
- },
-
- /**
- * On window close...
- * - remove event listeners from tabs
- * - save all window data
- * @param aWindow
- * Window reference
- */
- onClose: function ssi_onClose(aWindow) {
- // this window was about to be restored - conserve its original data, if any
- let isFullyLoaded = this._isWindowLoaded(aWindow);
- if (!isFullyLoaded) {
- if (!aWindow.__SSi)
- aWindow.__SSi = "window" + Date.now();
- this._windows[aWindow.__SSi] = this._statesToRestore[aWindow.__SS_restoreID];
- delete this._statesToRestore[aWindow.__SS_restoreID];
- delete aWindow.__SS_restoreID;
- }
-
- // ignore windows not tracked by SessionStore
- if (!aWindow.__SSi || !this._windows[aWindow.__SSi]) {
- return;
- }
-
- // notify that the session store will stop tracking this window so that
- // extensions can store any data about this window in session store before
- // that's not possible anymore
- let event = aWindow.document.createEvent("Events");
- event.initEvent("SSWindowClosing", true, false);
- aWindow.dispatchEvent(event);
-
- if (this.windowToFocus && this.windowToFocus == aWindow) {
- delete this.windowToFocus;
- }
-
- var tabbrowser = aWindow.gBrowser;
-
- TAB_EVENTS.forEach(function(aEvent) {
- tabbrowser.tabContainer.removeEventListener(aEvent, this, true);
- }, this);
-
- // remove the progress listener for this window
- tabbrowser.removeTabsProgressListener(gRestoreTabsProgressListener);
-
- let winData = this._windows[aWindow.__SSi];
- if (this._loadState == STATE_RUNNING) { // window not closed during a regular shut-down
- // update all window data for a last time
- this._collectWindowData(aWindow);
-
- if (isFullyLoaded) {
- winData.title = aWindow.content.document.title || tabbrowser.selectedTab.label;
- winData.title = this._replaceLoadingTitle(winData.title, tabbrowser,
- tabbrowser.selectedTab);
- let windows = {};
- windows[aWindow.__SSi] = winData;
- this._updateCookies(windows);
- }
-
-#ifndef XP_MACOSX
- // Until we decide otherwise elsewhere, this window is part of a series
- // of closing windows to quit.
- winData._shouldRestore = true;
-#endif
-
- // Save the window if it has multiple tabs or a single saveable tab and
- // it's not private.
- if (!winData.isPrivate && (winData.tabs.length > 1 ||
- (winData.tabs.length == 1 && this._shouldSaveTabState(winData.tabs[0])))) {
- // we don't want to save the busy state
- delete winData.busy;
-
- this._closedWindows.unshift(winData);
- this._capClosedWindows();
- }
-
- // clear this window from the list
- delete this._windows[aWindow.__SSi];
- delete this._internalWindows[aWindow.__SSi];
-
- // save the state without this window to disk
- this.saveStateDelayed();
- }
-
- for (let i = 0; i < tabbrowser.tabs.length; i++) {
- this.onTabRemove(aWindow, tabbrowser.tabs[i], true);
- }
-
- // Cache the window state until it is completely gone.
- DyingWindowCache.set(aWindow, winData);
-
- delete aWindow.__SSi;
- },
-
- /**
- * On quit application requested
- */
- onQuitApplicationRequested: function ssi_onQuitApplicationRequested() {
- // get a current snapshot of all windows
- this._forEachBrowserWindow(function(aWindow) {
- this._collectWindowData(aWindow);
- });
- // we must cache this because _getMostRecentBrowserWindow will always
- // return null by the time quit-application occurs
- var activeWindow = this._getMostRecentBrowserWindow();
- if (activeWindow)
- this.activeWindowSSiCache = activeWindow.__SSi || "";
- this._dirtyWindows = [];
- },
-
- /**
- * On quit application granted
- */
- onQuitApplicationGranted: function ssi_onQuitApplicationGranted() {
- // freeze the data at what we've got (ignoring closing windows)
- this._loadState = STATE_QUITTING;
- },
-
- /**
- * On last browser window close
- */
- onLastWindowCloseGranted: function ssi_onLastWindowCloseGranted() {
- // last browser window is quitting.
- // remember to restore the last window when another browser window is opened
- // do not account for pref(resume_session_once) at this point, as it might be
- // set by another observer getting this notice after us
- this._restoreLastWindow = true;
- },
-
- /**
- * On quitting application
- * @param aData
- * String type of quitting
- */
- onQuitApplication: function ssi_onQuitApplication(aData) {
- if (aData == "restart") {
- this._prefBranch.setBoolPref("sessionstore.resume_session_once", true);
- // The browser:purge-session-history notification fires after the
- // quit-application notification so unregister the
- // browser:purge-session-history notification to prevent clearing
- // session data on disk on a restart. It is also unnecessary to
- // perform any other sanitization processing on a restart as the
- // browser is about to exit anyway.
- Services.obs.removeObserver(this, "browser:purge-session-history");
- }
- else if (this._resume_session_once_on_shutdown != null) {
- // if the sessionstore.resume_session_once preference was changed by
- // saveState because crash recovery is disabled then restore the
- // preference back to the value it was prior to that. This will prevent
- // SessionStore from always restoring the session when crash recovery is
- // disabled.
- this._prefBranch.setBoolPref("sessionstore.resume_session_once",
- this._resume_session_once_on_shutdown);
- }
-
- if (aData != "restart") {
- // Throw away the previous session on shutdown
- this._lastSessionState = null;
- }
-
- this._loadState = STATE_QUITTING; // just to be sure
- this._uninit();
- },
-
- /**
- * On purge of session history
- */
- onPurgeSessionHistory: function ssi_onPurgeSessionHistory() {
- var _this = this;
- _SessionFile.wipe();
- // If the browser is shutting down, simply return after clearing the
- // session data on disk as this notification fires after the
- // quit-application notification so the browser is about to exit.
- if (this._loadState == STATE_QUITTING)
- return;
- this._lastSessionState = null;
- let openWindows = {};
- this._forEachBrowserWindow(function(aWindow) {
- Array.forEach(aWindow.gBrowser.tabs, function(aTab) {
- delete aTab.linkedBrowser.__SS_data;
- delete aTab.linkedBrowser.__SS_tabStillLoading;
- delete aTab.linkedBrowser.__SS_formDataSaved;
- delete aTab.linkedBrowser.__SS_hostSchemeData;
- if (aTab.linkedBrowser.__SS_restoreState)
- this._resetTabRestoringState(aTab);
- }, this);
- openWindows[aWindow.__SSi] = true;
- });
- // also clear all data about closed tabs and windows
- for (let ix in this._windows) {
- if (ix in openWindows) {
- this._windows[ix]._closedTabs = [];
- }
- else {
- delete this._windows[ix];
- delete this._internalWindows[ix];
- }
- }
- // also clear all data about closed windows
- this._closedWindows = [];
- // give the tabbrowsers a chance to clear their histories first
- var win = this._getMostRecentBrowserWindow();
- if (win)
- win.setTimeout(function() { _this.saveState(true); }, 0);
- else if (this._loadState == STATE_RUNNING)
- this.saveState(true);
- // Delete the private browsing backed up state, if any
- if ("_stateBackup" in this)
- delete this._stateBackup;
-
- this._clearRestoringWindows();
- },
-
- /**
- * On purge of domain data
- * @param aData
- * String domain data
- */
- onPurgeDomainData: function ssi_onPurgeDomainData(aData) {
- // does a session history entry contain a url for the given domain?
- function containsDomain(aEntry) {
- try {
- if (this._getURIFromString(aEntry.url).host.hasRootDomain(aData))
- return true;
- }
- catch (ex) { /* url had no host at all */ }
- return aEntry.children && aEntry.children.some(containsDomain, this);
- }
- // remove all closed tabs containing a reference to the given domain
- for (let ix in this._windows) {
- let closedTabs = this._windows[ix]._closedTabs;
- for (let i = closedTabs.length - 1; i >= 0; i--) {
- if (closedTabs[i].state.entries.some(containsDomain, this))
- closedTabs.splice(i, 1);
- }
- }
- // remove all open & closed tabs containing a reference to the given
- // domain in closed windows
- for (let ix = this._closedWindows.length - 1; ix >= 0; ix--) {
- let closedTabs = this._closedWindows[ix]._closedTabs;
- let openTabs = this._closedWindows[ix].tabs;
- let openTabCount = openTabs.length;
- for (let i = closedTabs.length - 1; i >= 0; i--)
- if (closedTabs[i].state.entries.some(containsDomain, this))
- closedTabs.splice(i, 1);
- for (let j = openTabs.length - 1; j >= 0; j--) {
- if (openTabs[j].entries.some(containsDomain, this)) {
- openTabs.splice(j, 1);
- if (this._closedWindows[ix].selected > j)
- this._closedWindows[ix].selected--;
- }
- }
- if (openTabs.length == 0) {
- this._closedWindows.splice(ix, 1);
- }
- else if (openTabs.length != openTabCount) {
- // Adjust the window's title if we removed an open tab
- let selectedTab = openTabs[this._closedWindows[ix].selected - 1];
- // some duplication from restoreHistory - make sure we get the correct title
- let activeIndex = (selectedTab.index || selectedTab.entries.length) - 1;
- if (activeIndex >= selectedTab.entries.length)
- activeIndex = selectedTab.entries.length - 1;
- this._closedWindows[ix].title = selectedTab.entries[activeIndex].title;
- }
- }
- if (this._loadState == STATE_RUNNING)
- this.saveState(true);
-
- this._clearRestoringWindows();
- },
-
- /**
- * On preference change
- * @param aData
- * String preference changed
- */
- onPrefChange: function ssi_onPrefChange(aData) {
- switch (aData) {
- // if the user decreases the max number of closed tabs they want
- // preserved update our internal states to match that max
- case "sessionstore.max_tabs_undo":
- this._max_tabs_undo = this._prefBranch.getIntPref("sessionstore.max_tabs_undo");
- for (let ix in this._windows) {
- this._windows[ix]._closedTabs.splice(this._max_tabs_undo, this._windows[ix]._closedTabs.length);
- }
- break;
- case "sessionstore.max_windows_undo":
- this._max_windows_undo = this._prefBranch.getIntPref("sessionstore.max_windows_undo");
- this._capClosedWindows();
- break;
- case "sessionstore.interval":
- this._interval = this._prefBranch.getIntPref("sessionstore.interval");
- // reset timer and save
- if (this._saveTimer) {
- this._saveTimer.cancel();
- this._saveTimer = null;
- }
- this.saveStateDelayed(null, -1);
- break;
- case "sessionstore.resume_from_crash":
- this._resume_from_crash = this._prefBranch.getBoolPref("sessionstore.resume_from_crash");
- // restore original resume_session_once preference if set in saveState
- if (this._resume_session_once_on_shutdown != null) {
- this._prefBranch.setBoolPref("sessionstore.resume_session_once",
- this._resume_session_once_on_shutdown);
- this._resume_session_once_on_shutdown = null;
- }
- // either create the file with crash recovery information or remove it
- // (when _loadState is not STATE_RUNNING, that file is used for session resuming instead)
- if (!this._resume_from_crash)
- _SessionFile.wipe();
- this.saveState(true);
- break;
- }
- },
-
- /**
- * On timer callback
- */
- onTimerCallback: function ssi_onTimerCallback() {
- this._saveTimer = null;
- this.saveState();
- },
-
- /**
- * set up listeners for a new tab
- * @param aWindow
- * Window reference
- * @param aTab
- * Tab reference
- * @param aNoNotification
- * bool Do not save state if we're updating an existing tab
- */
- onTabAdd: function ssi_onTabAdd(aWindow, aTab, aNoNotification) {
- let browser = aTab.linkedBrowser;
- browser.addEventListener("load", this, true);
-
- let mm = browser.messageManager;
- MESSAGES.forEach(msg => mm.addMessageListener(msg, this));
-
- if (!aNoNotification) {
- this.saveStateDelayed(aWindow);
- }
- },
-
- /**
- * remove listeners for a tab
- * @param aWindow
- * Window reference
- * @param aTab
- * Tab reference
- * @param aNoNotification
- * bool Do not save state if we're updating an existing tab
- */
- onTabRemove: function ssi_onTabRemove(aWindow, aTab, aNoNotification) {
- let browser = aTab.linkedBrowser;
- browser.removeEventListener("load", this, true);
-
- let mm = browser.messageManager;
- MESSAGES.forEach(msg => mm.removeMessageListener(msg, this));
-
- delete browser.__SS_data;
- delete browser.__SS_tabStillLoading;
- delete browser.__SS_formDataSaved;
- delete browser.__SS_hostSchemeData;
-
- // If this tab was in the middle of restoring or still needs to be restored,
- // we need to reset that state. If the tab was restoring, we will attempt to
- // restore the next tab.
- let previousState = browser.__SS_restoreState;
- if (previousState) {
- this._resetTabRestoringState(aTab);
- if (previousState == TAB_STATE_RESTORING)
- this.restoreNextTab();
- }
-
- if (!aNoNotification) {
- this.saveStateDelayed(aWindow);
- }
- },
-
- /**
- * When a tab closes, collect its properties
- * @param aWindow
- * Window reference
- * @param aTab
- * Tab reference
- */
- onTabClose: function ssi_onTabClose(aWindow, aTab) {
- // notify the tabbrowser that the tab state will be retrieved for the last time
- // (so that extension authors can easily set data on soon-to-be-closed tabs)
- var event = aWindow.document.createEvent("Events");
- event.initEvent("SSTabClosing", true, false);
- aTab.dispatchEvent(event);
-
- // don't update our internal state if we don't have to
- if (this._max_tabs_undo == 0) {
- return;
- }
-
- // make sure that the tab related data is up-to-date
- var tabState = this._collectTabData(aTab);
- this._updateTextAndScrollDataForTab(aWindow, aTab.linkedBrowser, tabState);
-
- // store closed-tab data for undo
- if (this._shouldSaveTabState(tabState)) {
- let tabTitle = aTab.label;
- let tabbrowser = aWindow.gBrowser;
- tabTitle = this._replaceLoadingTitle(tabTitle, tabbrowser, aTab);
-
- this._windows[aWindow.__SSi]._closedTabs.unshift({
- state: tabState,
- title: tabTitle,
- image: tabbrowser.getIcon(aTab),
- pos: aTab._tPos
- });
- var length = this._windows[aWindow.__SSi]._closedTabs.length;
- if (length > this._max_tabs_undo)
- this._windows[aWindow.__SSi]._closedTabs.splice(this._max_tabs_undo, length - this._max_tabs_undo);
- }
- },
-
- /**
- * When a tab loads, save state.
- * @param aWindow
- * Window reference
- * @param aBrowser
- * Browser reference
- */
- onTabLoad: function ssi_onTabLoad(aWindow, aBrowser) {
- // react on "load" and solitary "pageshow" events (the first "pageshow"
- // following "load" is too late for deleting the data caches)
- // It's possible to get a load event after calling stop on a browser (when
- // overwriting tabs). We want to return early if the tab hasn't been restored yet.
- if (aBrowser.__SS_restoreState &&
- aBrowser.__SS_restoreState == TAB_STATE_NEEDS_RESTORE) {
- return;
- }
-
- delete aBrowser.__SS_data;
- delete aBrowser.__SS_tabStillLoading;
- delete aBrowser.__SS_formDataSaved;
- this.saveStateDelayed(aWindow);
-
- },
-
- /**
- * Called when a browser sends the "input" notification
- * @param aWindow
- * Window reference
- * @param aBrowser
- * Browser reference
- */
- onTabInput: function ssi_onTabInput(aWindow, aBrowser) {
- // deleting __SS_formDataSaved will cause us to recollect form data
- delete aBrowser.__SS_formDataSaved;
-
- this.saveStateDelayed(aWindow, 3000);
- },
-
- /**
- * When a tab is selected, save session data
- * @param aWindow
- * Window reference
- */
- onTabSelect: function ssi_onTabSelect(aWindow) {
- if (this._loadState == STATE_RUNNING) {
- this._windows[aWindow.__SSi].selected = aWindow.gBrowser.tabContainer.selectedIndex;
-
- let tab = aWindow.gBrowser.selectedTab;
- // If __SS_restoreState is still on the browser and it is
- // TAB_STATE_NEEDS_RESTORE, then then we haven't restored
- // this tab yet. Explicitly call restoreTab to kick off the restore.
- if (tab.linkedBrowser.__SS_restoreState &&
- tab.linkedBrowser.__SS_restoreState == TAB_STATE_NEEDS_RESTORE)
- this.restoreTab(tab);
-
- }
- },
-
- onTabShow: function ssi_onTabShow(aWindow, aTab) {
- // If the tab hasn't been restored yet, move it into the right bucket
- if (aTab.linkedBrowser.__SS_restoreState &&
- aTab.linkedBrowser.__SS_restoreState == TAB_STATE_NEEDS_RESTORE) {
- TabRestoreQueue.hiddenToVisible(aTab);
-
- // let's kick off tab restoration again to ensure this tab gets restored
- // with "restore_hidden_tabs" == false (now that it has become visible)
- this.restoreNextTab();
- }
-
- // Default delay of 2 seconds gives enough time to catch multiple TabShow
- // events due to changing groups in Panorama.
- this.saveStateDelayed(aWindow);
- },
-
- onTabHide: function ssi_onTabHide(aWindow, aTab) {
- // If the tab hasn't been restored yet, move it into the right bucket
- if (aTab.linkedBrowser.__SS_restoreState &&
- aTab.linkedBrowser.__SS_restoreState == TAB_STATE_NEEDS_RESTORE) {
- TabRestoreQueue.visibleToHidden(aTab);
- }
-
- // Default delay of 2 seconds gives enough time to catch multiple TabHide
- // events due to changing groups in Panorama.
- this.saveStateDelayed(aWindow);
- },
-
- /* ........ nsISessionStore API .............. */
-
- getBrowserState: function ssi_getBrowserState() {
- return this._toJSONString(this._getCurrentState());
- },
-
- setBrowserState: function ssi_setBrowserState(aState) {
- this._handleClosedWindows();
-
- try {
- var state = JSON.parse(aState);
- }
- catch (ex) { /* invalid state object - don't restore anything */ }
- if (!state || !state.windows)
- throw (Components.returnCode = Cr.NS_ERROR_INVALID_ARG);
-
- this._browserSetState = true;
-
- // Make sure the priority queue is emptied out
- this._resetRestoringState();
-
- var window = this._getMostRecentBrowserWindow();
- if (!window) {
- this._restoreCount = 1;
- this._openWindowWithState(state);
- return;
- }
-
- // close all other browser windows
- this._forEachBrowserWindow(function(aWindow) {
- if (aWindow != window) {
- aWindow.close();
- this.onClose(aWindow);
- }
- });
-
- // make sure closed window data isn't kept
- this._closedWindows = [];
-
- // determine how many windows are meant to be restored
- this._restoreCount = state.windows ? state.windows.length : 0;
-
- // restore to the given state
- this.restoreWindow(window, state, true);
- },
-
- getWindowState: function ssi_getWindowState(aWindow) {
- if ("__SSi" in aWindow) {
- return this._toJSONString(this._getWindowState(aWindow));
- }
-
- if (DyingWindowCache.has(aWindow)) {
- let data = DyingWindowCache.get(aWindow);
- return this._toJSONString({ windows: [data] });
- }
-
- throw (Components.returnCode = Cr.NS_ERROR_INVALID_ARG);
- },
-
- setWindowState: function ssi_setWindowState(aWindow, aState, aOverwrite) {
- if (!aWindow.__SSi)
- throw (Components.returnCode = Cr.NS_ERROR_INVALID_ARG);
-
- this.restoreWindow(aWindow, aState, aOverwrite);
- },
-
- getTabState: function ssi_getTabState(aTab) {
- if (!aTab.ownerDocument || !aTab.ownerDocument.defaultView.__SSi)
- throw (Components.returnCode = Cr.NS_ERROR_INVALID_ARG);
-
- var tabState = this._collectTabData(aTab);
-
- var window = aTab.ownerDocument.defaultView;
- this._updateTextAndScrollDataForTab(window, aTab.linkedBrowser, tabState);
-
- return this._toJSONString(tabState);
- },
-
- setTabState: function ssi_setTabState(aTab, aState) {
- var tabState = JSON.parse(aState);
- if (!tabState.entries || !aTab.ownerDocument || !aTab.ownerDocument.defaultView.__SSi)
- throw (Components.returnCode = Cr.NS_ERROR_INVALID_ARG);
-
- var window = aTab.ownerDocument.defaultView;
- this._setWindowStateBusy(window);
- this.restoreHistoryPrecursor(window, [aTab], [tabState], 0, 0, 0);
- },
-
- duplicateTab: function ssi_duplicateTab(aWindow, aTab, aDelta) {
- if (!aTab.ownerDocument || !aTab.ownerDocument.defaultView.__SSi ||
- !aWindow.getBrowser)
- throw (Components.returnCode = Cr.NS_ERROR_INVALID_ARG);
-
- var tabState = this._collectTabData(aTab, true);
- var sourceWindow = aTab.ownerDocument.defaultView;
- this._updateTextAndScrollDataForTab(sourceWindow, aTab.linkedBrowser, tabState, true);
- tabState.index += aDelta;
- tabState.index = Math.max(1, Math.min(tabState.index, tabState.entries.length));
- tabState.pinned = false;
-
- this._setWindowStateBusy(aWindow);
- let newTab = aTab == aWindow.gBrowser.selectedTab ?
- aWindow.gBrowser.addTab(null, {relatedToCurrent: true, ownerTab: aTab}) :
- aWindow.gBrowser.addTab();
-
- this.restoreHistoryPrecursor(aWindow, [newTab], [tabState], 0, 0, 0,
- true /* Load this tab right away. */);
-
- return newTab;
- },
-
- getClosedTabCount: function ssi_getClosedTabCount(aWindow) {
- if ("__SSi" in aWindow) {
- return this._windows[aWindow.__SSi]._closedTabs.length;
- }
-
- if (DyingWindowCache.has(aWindow)) {
- return DyingWindowCache.get(aWindow)._closedTabs.length;
- }
-
- throw (Components.returnCode = Cr.NS_ERROR_INVALID_ARG);
- },
-
- getClosedTabData: function ssi_getClosedTabDataAt(aWindow) {
- if ("__SSi" in aWindow) {
- return this._toJSONString(this._windows[aWindow.__SSi]._closedTabs);
- }
-
- if (DyingWindowCache.has(aWindow)) {
- let data = DyingWindowCache.get(aWindow);
- return this._toJSONString(data._closedTabs);
- }
-
- throw (Components.returnCode = Cr.NS_ERROR_INVALID_ARG);
- },
-
- undoCloseTab: function ssi_undoCloseTab(aWindow, aIndex) {
- if (!aWindow.__SSi)
- throw (Components.returnCode = Cr.NS_ERROR_INVALID_ARG);
-
- var closedTabs = this._windows[aWindow.__SSi]._closedTabs;
-
- // default to the most-recently closed tab
- aIndex = aIndex || 0;
- if (!(aIndex in closedTabs))
- throw (Components.returnCode = Cr.NS_ERROR_INVALID_ARG);
-
- // fetch the data of closed tab, while removing it from the array
- let closedTab = closedTabs.splice(aIndex, 1).shift();
- let closedTabState = closedTab.state;
-
- this._setWindowStateBusy(aWindow);
- // create a new tab
- let tabbrowser = aWindow.gBrowser;
- let tab = tabbrowser.addTab();
-
- // restore tab content
- this.restoreHistoryPrecursor(aWindow, [tab], [closedTabState], 1, 0, 0);
-
- // restore the tab's position
- tabbrowser.moveTabTo(tab, closedTab.pos);
-
- // focus the tab's content area (bug 342432)
- tab.linkedBrowser.focus();
-
- return tab;
- },
-
- forgetClosedTab: function ssi_forgetClosedTab(aWindow, aIndex) {
- if (!aWindow.__SSi)
- throw (Components.returnCode = Cr.NS_ERROR_INVALID_ARG);
-
- var closedTabs = this._windows[aWindow.__SSi]._closedTabs;
-
- // default to the most-recently closed tab
- aIndex = aIndex || 0;
- if (!(aIndex in closedTabs))
- throw (Components.returnCode = Cr.NS_ERROR_INVALID_ARG);
-
- // remove closed tab from the array
- closedTabs.splice(aIndex, 1);
- },
-
- getClosedWindowCount: function ssi_getClosedWindowCount() {
- return this._closedWindows.length;
- },
-
- getClosedWindowData: function ssi_getClosedWindowData() {
- return this._toJSONString(this._closedWindows);
- },
-
- undoCloseWindow: function ssi_undoCloseWindow(aIndex) {
- if (!(aIndex in this._closedWindows))
- throw (Components.returnCode = Cr.NS_ERROR_INVALID_ARG);
-
- // reopen the window
- let state = { windows: this._closedWindows.splice(aIndex, 1) };
- let window = this._openWindowWithState(state);
- this.windowToFocus = window;
- return window;
- },
-
- forgetClosedWindow: function ssi_forgetClosedWindow(aIndex) {
- // default to the most-recently closed window
- aIndex = aIndex || 0;
- if (!(aIndex in this._closedWindows))
- throw (Components.returnCode = Cr.NS_ERROR_INVALID_ARG);
-
- // remove closed window from the array
- this._closedWindows.splice(aIndex, 1);
- },
-
- getWindowValue: function ssi_getWindowValue(aWindow, aKey) {
- if ("__SSi" in aWindow) {
- var data = this._windows[aWindow.__SSi].extData || {};
- return data[aKey] || "";
- }
-
- if (DyingWindowCache.has(aWindow)) {
- let data = DyingWindowCache.get(aWindow).extData || {};
- return data[aKey] || "";
- }
-
- throw (Components.returnCode = Cr.NS_ERROR_INVALID_ARG);
- },
-
- setWindowValue: function ssi_setWindowValue(aWindow, aKey, aStringValue) {
- if (aWindow.__SSi) {
- if (!this._windows[aWindow.__SSi].extData) {
- this._windows[aWindow.__SSi].extData = {};
- }
- this._windows[aWindow.__SSi].extData[aKey] = aStringValue;
- this.saveStateDelayed(aWindow);
- }
- else {
- throw (Components.returnCode = Cr.NS_ERROR_INVALID_ARG);
- }
- },
-
- deleteWindowValue: function ssi_deleteWindowValue(aWindow, aKey) {
- if (aWindow.__SSi && this._windows[aWindow.__SSi].extData &&
- this._windows[aWindow.__SSi].extData[aKey])
- delete this._windows[aWindow.__SSi].extData[aKey];
- },
-
- getTabValue: function ssi_getTabValue(aTab, aKey) {
- let data = {};
- if (aTab.__SS_extdata) {
- data = aTab.__SS_extdata;
- }
- else if (aTab.linkedBrowser.__SS_data && aTab.linkedBrowser.__SS_data.extData) {
- // If the tab hasn't been fully restored, get the data from the to-be-restored data
- data = aTab.linkedBrowser.__SS_data.extData;
- }
- return data[aKey] || "";
- },
-
- setTabValue: function ssi_setTabValue(aTab, aKey, aStringValue) {
- // If the tab hasn't been restored, then set the data there, otherwise we
- // could lose newly added data.
- let saveTo;
- if (aTab.__SS_extdata) {
- saveTo = aTab.__SS_extdata;
- }
- else if (aTab.linkedBrowser.__SS_data && aTab.linkedBrowser.__SS_data.extData) {
- saveTo = aTab.linkedBrowser.__SS_data.extData;
- }
- else {
- aTab.__SS_extdata = {};
- saveTo = aTab.__SS_extdata;
- }
- saveTo[aKey] = aStringValue;
- this.saveStateDelayed(aTab.ownerDocument.defaultView);
- },
-
- deleteTabValue: function ssi_deleteTabValue(aTab, aKey) {
- // We want to make sure that if data is accessed early, we attempt to delete
- // that data from __SS_data as well. Otherwise we'll throw in cases where
- // data can be set or read.
- let deleteFrom;
- if (aTab.__SS_extdata) {
- deleteFrom = aTab.__SS_extdata;
- }
- else if (aTab.linkedBrowser.__SS_data && aTab.linkedBrowser.__SS_data.extData) {
- deleteFrom = aTab.linkedBrowser.__SS_data.extData;
- }
-
- if (deleteFrom && deleteFrom[aKey])
- delete deleteFrom[aKey];
- },
-
- persistTabAttribute: function ssi_persistTabAttribute(aName) {
- if (TabAttributes.persist(aName)) {
- this.saveStateDelayed();
- }
- },
-
- /**
- * Restores the session state stored in _lastSessionState. This will attempt
- * to merge data into the current session. If a window was opened at startup
- * with pinned tab(s), then the remaining data from the previous session for
- * that window will be opened into that winddow. Otherwise new windows will
- * be opened.
- */
- restoreLastSession: function ssi_restoreLastSession() {
- // Use the public getter since it also checks PB mode
- if (!this.canRestoreLastSession)
- throw (Components.returnCode = Cr.NS_ERROR_FAILURE);
-
- // First collect each window with its id...
- let windows = {};
- this._forEachBrowserWindow(function(aWindow) {
- if (aWindow.__SS_lastSessionWindowID)
- windows[aWindow.__SS_lastSessionWindowID] = aWindow;
- });
-
- let lastSessionState = this._lastSessionState;
-
- // This shouldn't ever be the case...
- if (!lastSessionState.windows.length)
- throw (Components.returnCode = Cr.NS_ERROR_UNEXPECTED);
-
- // We're technically doing a restore, so set things up so we send the
- // notification when we're done. We want to send "sessionstore-browser-state-restored".
- this._restoreCount = lastSessionState.windows.length;
- this._browserSetState = true;
-
- // We want to re-use the last opened window instead of opening a new one in
- // the case where it's "empty" and not associated with a window in the session.
- // We will do more processing via _prepWindowToRestoreInto if we need to use
- // the lastWindow.
- let lastWindow = this._getMostRecentBrowserWindow();
- let canUseLastWindow = lastWindow &&
- !lastWindow.__SS_lastSessionWindowID;
-
- // Restore into windows or open new ones as needed.
- for (let i = 0; i < lastSessionState.windows.length; i++) {
- let winState = lastSessionState.windows[i];
- let lastSessionWindowID = winState.__lastSessionWindowID;
- // delete lastSessionWindowID so we don't add that to the window again
- delete winState.__lastSessionWindowID;
-
- // See if we can use an open window. First try one that is associated with
- // the state we're trying to restore and then fallback to the last selected
- // window.
- let windowToUse = windows[lastSessionWindowID];
- if (!windowToUse && canUseLastWindow) {
- windowToUse = lastWindow;
- canUseLastWindow = false;
- }
-
- let [canUseWindow, canOverwriteTabs] = this._prepWindowToRestoreInto(windowToUse);
-
- // If there's a window already open that we can restore into, use that
- if (canUseWindow) {
- // Since we're not overwriting existing tabs, we want to merge _closedTabs,
- // putting existing ones first. Then make sure we're respecting the max pref.
- if (winState._closedTabs && winState._closedTabs.length) {
- let curWinState = this._windows[windowToUse.__SSi];
- curWinState._closedTabs = curWinState._closedTabs.concat(winState._closedTabs);
- curWinState._closedTabs.splice(this._prefBranch.getIntPref("sessionstore.max_tabs_undo"), curWinState._closedTabs.length);
- }
-
- // Restore into that window - pretend it's a followup since we'll already
- // have a focused window.
- //XXXzpao This is going to merge extData together (taking what was in
- // winState over what is in the window already. The hack we have
- // in _preWindowToRestoreInto will prevent most (all?) Panorama
- // weirdness but we will still merge other extData.
- // Bug 588217 should make this go away by merging the group data.
- this.restoreWindow(windowToUse, { windows: [winState] }, canOverwriteTabs, true);
- }
- else {
- this._openWindowWithState({ windows: [winState] });
- }
- }
-
- // Merge closed windows from this session with ones from last session
- if (lastSessionState._closedWindows) {
- this._closedWindows = this._closedWindows.concat(lastSessionState._closedWindows);
- this._capClosedWindows();
- }
-
-#ifdef MOZ_DEVTOOLS
- // Scratchpad
- if (lastSessionState.scratchpads) {
- ScratchpadManager.restoreSession(lastSessionState.scratchpads);
- }
-
- // The Browser Console
- if (lastSessionState.browserConsole) {
- HUDService.restoreBrowserConsoleSession();
- }
-#endif
-
- // Set data that persists between sessions
- this._recentCrashes = lastSessionState.session &&
- lastSessionState.session.recentCrashes || 0;
- this._sessionStartTime = lastSessionState.session &&
- lastSessionState.session.startTime ||
- this._sessionStartTime;
-
- this._lastSessionState = null;
- },
-
- /**
- * See if aWindow is usable for use when restoring a previous session via
- * restoreLastSession. If usable, prepare it for use.
- *
- * @param aWindow
- * the window to inspect & prepare
- * @returns [canUseWindow, canOverwriteTabs]
- * canUseWindow: can the window be used to restore into
- * canOverwriteTabs: all of the current tabs are home pages and we
- * can overwrite them
- */
- _prepWindowToRestoreInto: function ssi_prepWindowToRestoreInto(aWindow) {
- if (!aWindow)
- return [false, false];
-
- let event = aWindow.document.createEvent("Events");
- event.initEvent("SSRestoreIntoWindow", true, true);
-
- // Check if we can use the window.
- if (!aWindow.dispatchEvent(event))
- return [false, false];
-
- // We might be able to overwrite the existing tabs instead of just adding
- // the previous session's tabs to the end. This will be set if possible.
- let canOverwriteTabs = false;
-
- // Look at the open tabs in comparison to home pages. If all the tabs are
- // home pages then we'll end up overwriting all of them. Otherwise we'll
- // just close the tabs that match home pages. Tabs with the about:blank
- // URI will always be overwritten.
- let homePages = ["about:blank"];
- let removableTabs = [];
- let tabbrowser = aWindow.gBrowser;
- let normalTabsLen = tabbrowser.tabs.length - tabbrowser._numPinnedTabs;
- let startupPref = this._prefBranch.getIntPref("startup.page");
- if (startupPref == 1)
- homePages = homePages.concat(aWindow.gHomeButton.getHomePage().split("|"));
-
- for (let i = tabbrowser._numPinnedTabs; i < tabbrowser.tabs.length; i++) {
- let tab = tabbrowser.tabs[i];
- if (homePages.indexOf(tab.linkedBrowser.currentURI.spec) != -1) {
- removableTabs.push(tab);
- }
- }
-
- if (tabbrowser.tabs.length == removableTabs.length) {
- canOverwriteTabs = true;
- }
- else {
- // If we're not overwriting all of the tabs, then close the home tabs.
- for (let i = removableTabs.length - 1; i >= 0; i--) {
- tabbrowser.removeTab(removableTabs.pop(), { animate: false });
- }
- }
-
- return [true, canOverwriteTabs];
- },
-
- /* ........ Saving Functionality .............. */
-
- /**
- * Store all session data for a window
- * @param aWindow
- * Window reference
- */
- _saveWindowHistory: function ssi_saveWindowHistory(aWindow) {
- var tabbrowser = aWindow.gBrowser;
- var tabs = tabbrowser.tabs;
- var tabsData = this._windows[aWindow.__SSi].tabs = [];
-
- for (var i = 0; i < tabs.length; i++)
- tabsData.push(this._collectTabData(tabs[i]));
-
- this._windows[aWindow.__SSi].selected = tabbrowser.mTabBox.selectedIndex + 1;
- },
-
- /**
- * Collect data related to a single tab
- * @param aTab
- * tabbrowser tab
- * @param aFullData
- * always return privacy sensitive data (use with care)
- * @returns object
- */
- _collectTabData: function ssi_collectTabData(aTab, aFullData) {
- var tabData = { entries: [], lastAccessed: aTab.lastAccessed };
- var browser = aTab.linkedBrowser;
-
- if (!browser || !browser.currentURI)
- // can happen when calling this function right after .addTab()
- return tabData;
- else if (browser.__SS_data && browser.__SS_tabStillLoading) {
- // use the data to be restored when the tab hasn't been completely loaded
- tabData = browser.__SS_data;
- if (aTab.pinned)
- tabData.pinned = true;
- else
- delete tabData.pinned;
- tabData.hidden = aTab.hidden;
-
- // If __SS_extdata is set then we'll use that since it might be newer.
- if (aTab.__SS_extdata)
- tabData.extData = aTab.__SS_extdata;
- // If it exists but is empty then a key was likely deleted. In that case just
- // delete extData.
- if (tabData.extData && !Object.keys(tabData.extData).length)
- delete tabData.extData;
- return tabData;
- }
-
- var history = null;
- try {
- history = browser.sessionHistory;
- }
- catch (ex) { } // this could happen if we catch a tab during (de)initialization
-
- // Limit number of back/forward button history entries to save
- let oldest, newest;
- let maxSerializeBack = this._prefBranch.getIntPref("sessionstore.max_serialize_back");
- if (maxSerializeBack >= 0) {
- oldest = Math.max(0, history.index - maxSerializeBack);
- } else { // History.getEntryAtIndex(0, ...) is the oldest.
- oldest = 0;
- }
- let maxSerializeFwd = this._prefBranch.getIntPref("sessionstore.max_serialize_forward");
- if (maxSerializeFwd >= 0) {
- newest = Math.min(history.count - 1, history.index + maxSerializeFwd);
- } else { // History.getEntryAtIndex(history.count - 1, ...) is the newest.
- newest = history.count - 1;
- }
-
- // XXXzeniko anchor navigation doesn't reset __SS_data, so we could reuse
- // data even when we shouldn't (e.g. Back, different anchor)
- // Warning: this is required to save form data and scrolling position!
- if (history && browser.__SS_data &&
- browser.__SS_data.entries[history.index] &&
- browser.__SS_data.entries[history.index].url == browser.currentURI.spec &&
- history.index < this._sessionhistory_max_entries - 1 && !aFullData) {
- try {
- tabData.entries = browser.__SS_data.entries.slice(oldest, newest + 1);
- }
- catch (ex) {
- // No errors are expected above, but we use try-catch to keep sessionstore.js safe
- NS_ASSERT(false, "SessionStore failed to slice history from browser.__SS_data");
- }
-
- // Set the one-based index of the currently active tab, ensuring it isn't out of bounds
- tabData.index = Math.min(history.index - oldest + 1, tabData.entries.length);
- }
- else if (history && history.count > 0) {
- browser.__SS_hostSchemeData = [];
- try {
- for (var j = oldest; j <= newest; j++) {
- let entry = this._serializeHistoryEntry(history.getEntryAtIndex(j, false),
- aFullData, aTab.pinned, browser.__SS_hostSchemeData);
- tabData.entries.push(entry);
- }
- }
- catch (ex) {
- // In some cases, getEntryAtIndex will throw. This seems to be due to
- // history.count being higher than it should be. By doing this in a
- // try-catch, we'll update history to where it breaks, assert for
- // non-release builds, and still save sessionstore.js.
- NS_ASSERT(false, "SessionStore failed gathering complete history " +
- "for the focused window/tab. See bug 669196.");
- }
-
- // Set the one-based index of the currently active tab, ensuring it isn't out of bounds
- tabData.index = Math.min(history.index - oldest + 1, tabData.entries.length);
-
- // make sure not to cache privacy sensitive data which shouldn't get out
- if (!aFullData)
- browser.__SS_data = tabData;
- }
- else if (browser.currentURI.spec != "about:blank" ||
- browser.contentDocument.body.hasChildNodes()) {
- tabData.entries[0] = { url: browser.currentURI.spec };
- tabData.index = 1;
- }
-
- // If there is a userTypedValue set, then either the user has typed something
- // in the URL bar, or a new tab was opened with a URI to load. userTypedClear
- // is used to indicate whether the tab was in some sort of loading state with
- // userTypedValue.
- if (browser.userTypedValue) {
- tabData.userTypedValue = browser.userTypedValue;
- // We always used to keep track of the loading state as an integer, where
- // '0' indicated the user had typed since the last load (or no load was
- // ongoing), and any positive value indicated we had started a load since
- // the last time the user typed in the URL bar. Mimic this to keep the
- // session store representation in sync, even though we now represent this
- // more explicitly:
- tabData.userTypedClear = browser.didStartLoadSinceLastUserTyping() ? 1 : 0;
- } else {
- delete tabData.userTypedValue;
- delete tabData.userTypedClear;
- }
-
- if (aTab.pinned)
- tabData.pinned = true;
- else
- delete tabData.pinned;
- tabData.hidden = aTab.hidden;
-
- var disallow = [];
- for (let cap of gDocShellCapabilities(browser.docShell))
- if (!browser.docShell["allow" + cap])
- disallow.push(cap);
- if (disallow.length > 0)
- tabData.disallow = disallow.join(",");
- else if (tabData.disallow)
- delete tabData.disallow;
-
- // Save tab attributes.
- tabData.attributes = TabAttributes.get(aTab);
-
- // Store the tab icon.
- let tabbrowser = aTab.ownerDocument.defaultView.gBrowser;
- tabData.image = tabbrowser.getIcon(aTab);
-
- if (aTab.__SS_extdata)
- tabData.extData = aTab.__SS_extdata;
- else if (tabData.extData)
- delete tabData.extData;
-
- if (history && browser.docShell instanceof Ci.nsIDocShell) {
- let storageData = SessionStorage.serialize(browser.docShell, aFullData)
- if (Object.keys(storageData).length)
- tabData.storage = storageData;
- }
-
- return tabData;
- },
-
- /**
- * Get an object that is a serialized representation of a History entry
- * Used for data storage
- * @param aEntry
- * nsISHEntry instance
- * @param aFullData
- * always return privacy sensitive data (use with care)
- * @param aIsPinned
- * the tab is pinned and should be treated differently for privacy
- * @param aHostSchemeData
- * an array of objects with host & scheme keys
- * @returns object
- */
- _serializeHistoryEntry:
- function ssi_serializeHistoryEntry(aEntry, aFullData, aIsPinned, aHostSchemeData) {
- var entry = { url: aEntry.URI.spec };
-
- try {
- // throwing is expensive, we know that about: pages will throw
- if (entry.url.indexOf("about:") != 0)
- aHostSchemeData.push({ host: aEntry.URI.host, scheme: aEntry.URI.scheme });
- }
- catch (ex) {
- // We just won't attempt to get cookies for this entry.
- }
-
- if (aEntry.title && aEntry.title != entry.url) {
- entry.title = aEntry.title;
- }
- if (aEntry.isSubFrame) {
- entry.subframe = true;
- }
- if (!(aEntry instanceof Ci.nsISHEntry)) {
- return entry;
- }
-
- var cacheKey = aEntry.cacheKey;
- if (cacheKey && cacheKey instanceof Ci.nsISupportsPRUint32 &&
- cacheKey.data != 0) {
- // XXXbz would be better to have cache keys implement
- // nsISerializable or something.
- entry.cacheKey = cacheKey.data;
- }
- entry.ID = aEntry.ID;
- entry.docshellID = aEntry.docshellID;
-
- if (aEntry.referrerURI)
- entry.referrer = aEntry.referrerURI.spec;
-
- if (aEntry.srcdocData)
- entry.srcdocData = aEntry.srcdocData;
-
- if (aEntry.isSrcdocEntry)
- entry.isSrcdocEntry = aEntry.isSrcdocEntry;
-
- if (aEntry.contentType)
- entry.contentType = aEntry.contentType;
-
- var x = {}, y = {};
- aEntry.getScrollPosition(x, y);
- if (x.value != 0 || y.value != 0)
- entry.scroll = x.value + "," + y.value;
-
- try {
- var prefPostdata = this._prefBranch.getIntPref("sessionstore.postdata");
- if (aEntry.postData && (aFullData || prefPostdata &&
- this.checkPrivacyLevel(aEntry.URI.schemeIs("https"), aIsPinned))) {
- aEntry.postData.QueryInterface(Ci.nsISeekableStream).
- seek(Ci.nsISeekableStream.NS_SEEK_SET, 0);
- var stream = Cc["@mozilla.org/binaryinputstream;1"].
- createInstance(Ci.nsIBinaryInputStream);
- stream.setInputStream(aEntry.postData);
- var postBytes = stream.readByteArray(stream.available());
- var postdata = String.fromCharCode.apply(null, postBytes);
- if (aFullData || prefPostdata == -1 ||
- postdata.replace(/^(Content-.*\r\n)+(\r\n)*/, "").length <=
- prefPostdata) {
- // We can stop doing base64 encoding once our serialization into JSON
- // is guaranteed to handle all chars in strings, including embedded
- // nulls.
- entry.postdata_b64 = btoa(postdata);
- }
- }
- }
- catch (ex) { debug(ex); } // POSTDATA is tricky - especially since some extensions don't get it right
-
- if (aEntry.triggeringPrincipal) {
- // Not catching anything specific here, just possible errors
- // from writeCompoundObject and the like.
- try {
- var binaryStream = Cc["@mozilla.org/binaryoutputstream;1"].
- createInstance(Ci.nsIObjectOutputStream);
- var pipe = Cc["@mozilla.org/pipe;1"].createInstance(Ci.nsIPipe);
- pipe.init(false, false, 0, 0xffffffff, null);
- binaryStream.setOutputStream(pipe.outputStream);
- binaryStream.writeCompoundObject(aEntry.triggeringPrincipal, Ci.nsIPrincipal, true);
- binaryStream.close();
-
- // Now we want to read the data from the pipe's input end and encode it.
- var scriptableStream = Cc["@mozilla.org/binaryinputstream;1"].
- createInstance(Ci.nsIBinaryInputStream);
- scriptableStream.setInputStream(pipe.inputStream);
- var triggeringPrincipalBytes =
- scriptableStream.readByteArray(scriptableStream.available());
- // We can stop doing base64 encoding once our serialization into JSON
- // is guaranteed to handle all chars in strings, including embedded
- // nulls.
- entry.triggeringPrincipal_b64 = btoa(String.fromCharCode.apply(null, triggeringPrincipalBytes));
- }
- catch (ex) { debug(ex); }
- }
-
- entry.docIdentifier = aEntry.BFCacheEntry.ID;
-
- if (aEntry.stateData != null) {
- entry.structuredCloneState = aEntry.stateData.getDataAsBase64();
- entry.structuredCloneVersion = aEntry.stateData.formatVersion;
- }
-
- if (!(aEntry instanceof Ci.nsISHContainer)) {
- return entry;
- }
-
- if (aEntry.childCount > 0) {
- let children = [];
- for (var i = 0; i < aEntry.childCount; i++) {
- var child = aEntry.GetChildAt(i);
-
- if (child) {
- // don't try to restore framesets containing wyciwyg URLs (cf. bug 424689 and bug 450595)
- if (child.URI.schemeIs("wyciwyg")) {
- children = [];
- break;
- }
-
- children.push(this._serializeHistoryEntry(child, aFullData,
- aIsPinned, aHostSchemeData));
- }
- }
-
- if (children.length)
- entry.children = children;
- }
-
- return entry;
- },
-
- /**
- * go through all tabs and store the current scroll positions
- * and innerHTML content of WYSIWYG editors
- * @param aWindow
- * Window reference
- */
- _updateTextAndScrollData: function ssi_updateTextAndScrollData(aWindow) {
- var browsers = aWindow.gBrowser.browsers;
- this._windows[aWindow.__SSi].tabs.forEach(function (tabData, i) {
- try {
- this._updateTextAndScrollDataForTab(aWindow, browsers[i], tabData);
- }
- catch (ex) { debug(ex); } // get as much data as possible, ignore failures (might succeed the next time)
- }, this);
- },
-
- /**
- * go through all frames and store the current scroll positions
- * and innerHTML content of WYSIWYG editors
- * @param aWindow
- * Window reference
- * @param aBrowser
- * single browser reference
- * @param aTabData
- * tabData object to add the information to
- * @param aFullData
- * always return privacy sensitive data (use with care)
- */
- _updateTextAndScrollDataForTab:
- function ssi_updateTextAndScrollDataForTab(aWindow, aBrowser, aTabData, aFullData) {
- // we shouldn't update data for incompletely initialized tabs
- if (aBrowser.__SS_data && aBrowser.__SS_tabStillLoading)
- return;
-
- var tabIndex = (aTabData.index || aTabData.entries.length) - 1;
- // entry data needn't exist for tabs just initialized with an incomplete session state
- if (!aTabData.entries[tabIndex])
- return;
-
- let selectedPageStyle = aBrowser.markupDocumentViewer.authorStyleDisabled ? "_nostyle" :
- this._getSelectedPageStyle(aBrowser.contentWindow);
- if (selectedPageStyle)
- aTabData.pageStyle = selectedPageStyle;
- else if (aTabData.pageStyle)
- delete aTabData.pageStyle;
-
- this._updateTextAndScrollDataForFrame(aWindow, aBrowser.contentWindow,
- aTabData.entries[tabIndex],
- !aBrowser.__SS_formDataSaved, aFullData,
- !!aTabData.pinned);
- aBrowser.__SS_formDataSaved = true;
- if (aBrowser.currentURI.spec == "about:config")
- aTabData.entries[tabIndex].formdata = {
- id: {
- "textbox": aBrowser.contentDocument.getElementById("textbox").value
- },
- xpath: {}
- };
- },
-
- /**
- * go through all subframes and store all form data, the current
- * scroll positions and innerHTML content of WYSIWYG editors
- * @param aWindow
- * Window reference
- * @param aContent
- * frame reference
- * @param aData
- * part of a tabData object to add the information to
- * @param aUpdateFormData
- * update all form data for this tab
- * @param aFullData
- * always return privacy sensitive data (use with care)
- * @param aIsPinned
- * the tab is pinned and should be treated differently for privacy
- */
- _updateTextAndScrollDataForFrame:
- function ssi_updateTextAndScrollDataForFrame(aWindow, aContent, aData,
- aUpdateFormData, aFullData, aIsPinned) {
- for (var i = 0; i < aContent.frames.length; i++) {
- if (aData.children && aData.children[i])
- this._updateTextAndScrollDataForFrame(aWindow, aContent.frames[i],
- aData.children[i], aUpdateFormData,
- aFullData, aIsPinned);
- }
- var isHTTPS = this._getURIFromString((aContent.parent || aContent).
- document.location.href).schemeIs("https");
- let isAboutSR = aContent.top.document.location.href == "about:sessionrestore";
- if (aFullData || this.checkPrivacyLevel(isHTTPS, aIsPinned) || isAboutSR) {
- if (aFullData || aUpdateFormData) {
- let formData = DocumentUtils.getFormData(aContent.document);
-
- // We want to avoid saving data for about:sessionrestore as a string.
- // Since it's stored in the form as stringified JSON, stringifying further
- // causes an explosion of escape characters. cf. bug 467409
- if (formData && isAboutSR) {
- formData.id["sessionData"] = JSON.parse(formData.id["sessionData"]);
- }
-
- if (Object.keys(formData.id).length ||
- Object.keys(formData.xpath).length) {
- aData.formdata = formData;
- } else if (aData.formdata) {
- delete aData.formdata;
- }
- }
-
- // designMode is undefined e.g. for XUL documents (as about:config)
- if ((aContent.document.designMode || "") == "on" && aContent.document.body)
- aData.innerHTML = aContent.document.body.innerHTML;
- }
-
- // get scroll position from nsIDOMWindowUtils, since it allows avoiding a
- // flush of layout
- let domWindowUtils = aContent.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIDOMWindowUtils);
- let scrollX = {}, scrollY = {};
- domWindowUtils.getScrollXY(false, scrollX, scrollY);
- aData.scroll = scrollX.value + "," + scrollY.value;
- },
-
- /**
- * determine the title of the currently enabled style sheet (if any)
- * and recurse through the frameset if necessary
- * @param aContent is a frame reference
- * @returns the title style sheet determined to be enabled (empty string if none)
- */
- _getSelectedPageStyle: function ssi_getSelectedPageStyle(aContent) {
- const forScreen = /(?:^|,)\s*(?:all|screen)\s*(?:,|$)/i;
- for (let i = 0; i < aContent.document.styleSheets.length; i++) {
- let ss = aContent.document.styleSheets[i];
- let media = ss.media.mediaText;
- if (!ss.disabled && ss.title && (!media || forScreen.test(media)))
- return ss.title
- }
- for (let i = 0; i < aContent.frames.length; i++) {
- let selectedPageStyle = this._getSelectedPageStyle(aContent.frames[i]);
- if (selectedPageStyle)
- return selectedPageStyle;
- }
- return "";
- },
-
- /**
- * extract the base domain from a history entry and its children
- * @param aEntry
- * the history entry, serialized
- * @param aHosts
- * the hash that will be used to store hosts eg, { hostname: true }
- * @param aCheckPrivacy
- * should we check the privacy level for https
- * @param aIsPinned
- * is the entry we're evaluating for a pinned tab; used only if
- * aCheckPrivacy
- */
- _extractHostsForCookiesFromEntry:
- function ssi_extractHostsForCookiesFromEntry(aEntry, aHosts, aCheckPrivacy, aIsPinned) {
-
- let host = aEntry._host,
- scheme = aEntry._scheme;
-
- // If host & scheme aren't defined, then we are likely here in the startup
- // process via _splitCookiesFromWindow. In that case, we'll turn aEntry.url
- // into an nsIURI and get host/scheme from that. This will throw for about:
- // urls in which case we don't need to do anything.
- if (!host && !scheme) {
- try {
- let uri = this._getURIFromString(aEntry.url);
- host = uri.host;
- scheme = uri.scheme;
- this._extractHostsForCookiesFromHostScheme(host, scheme, aHosts, aCheckPrivacy, aIsPinned);
- }
- catch(ex) { }
- }
-
- if (aEntry.children) {
- aEntry.children.forEach(function(entry) {
- this._extractHostsForCookiesFromEntry(entry, aHosts, aCheckPrivacy, aIsPinned);
- }, this);
- }
- },
-
- /**
- * extract the base domain from a host & scheme
- * @param aHost
- * the host of a uri (usually via nsIURI.host)
- * @param aScheme
- * the scheme of a uri (usually via nsIURI.scheme)
- * @param aHosts
- * the hash that will be used to store hosts eg, { hostname: true }
- * @param aCheckPrivacy
- * should we check the privacy level for https
- * @param aIsPinned
- * is the entry we're evaluating for a pinned tab; used only if
- * aCheckPrivacy
- */
- _extractHostsForCookiesFromHostScheme:
- function ssi_extractHostsForCookiesFromHostScheme(aHost, aScheme, aHosts, aCheckPrivacy, aIsPinned) {
- // host and scheme may not be set (for about: urls for example), in which
- // case testing scheme will be sufficient.
- if (/https?/.test(aScheme) && !aHosts[aHost] &&
- (!aCheckPrivacy ||
- this.checkPrivacyLevel(aScheme == "https", aIsPinned))) {
- // By setting this to true or false, we can determine when looking at
- // the host in _updateCookies if we should check for privacy.
- aHosts[aHost] = aIsPinned;
- }
- else if (aScheme == "file") {
- aHosts[aHost] = true;
- }
- },
-
- /**
- * store all hosts for a URL
- * @param aWindow
- * Window reference
- */
- _updateCookieHosts: function ssi_updateCookieHosts(aWindow) {
- var hosts = this._internalWindows[aWindow.__SSi].hosts = {};
-
- // Since _updateCookiesHosts is only ever called for open windows during a
- // session, we can call into _extractHostsForCookiesFromHostScheme directly
- // using data that is attached to each browser.
- for (let i = 0; i < aWindow.gBrowser.tabs.length; i++) {
- let tab = aWindow.gBrowser.tabs[i];
- let hostSchemeData = tab.linkedBrowser.__SS_hostSchemeData || [];
- for (let j = 0; j < hostSchemeData.length; j++) {
- this._extractHostsForCookiesFromHostScheme(hostSchemeData[j].host,
- hostSchemeData[j].scheme,
- hosts, true, tab.pinned);
- }
- }
- },
-
- /**
- * Serialize cookie data
- * @param aWindows
- * JS object containing window data references
- * { id: winData, etc. }
- */
- _updateCookies: function ssi_updateCookies(aWindows) {
- function addCookieToHash(aHash, aHost, aPath, aName, aCookie) {
- // lazily build up a 3-dimensional hash, with
- // aHost, aPath, and aName as keys
- if (!aHash[aHost])
- aHash[aHost] = {};
- if (!aHash[aHost][aPath])
- aHash[aHost][aPath] = {};
- aHash[aHost][aPath][aName] = aCookie;
- }
-
- var jscookies = {};
- var _this = this;
- // MAX_EXPIRY should be 2^63-1, but JavaScript can't handle that precision
- var MAX_EXPIRY = Math.pow(2, 62);
-
- for (let [id, window] in Iterator(aWindows)) {
- window.cookies = [];
- let internalWindow = this._internalWindows[id];
- if (!internalWindow.hosts)
- return;
- for (var [host, isPinned] in Iterator(internalWindow.hosts)) {
- let list;
- try {
- list = Services.cookies.getCookiesFromHost(host, {});
- }
- catch (ex) {
- debug("getCookiesFromHost failed. Host: " + host);
- }
- while (list && list.hasMoreElements()) {
- var cookie = list.getNext().QueryInterface(Ci.nsICookie2);
- // window._hosts will only have hosts with the right privacy rules,
- // so there is no need to do anything special with this call to
- // checkPrivacyLevel.
- if (cookie.isSession && _this.checkPrivacyLevel(cookie.isSecure, isPinned)) {
- // use the cookie's host, path, and name as keys into a hash,
- // to make sure we serialize each cookie only once
- if (!(cookie.host in jscookies &&
- cookie.path in jscookies[cookie.host] &&
- cookie.name in jscookies[cookie.host][cookie.path])) {
- var jscookie = { "host": cookie.host, "value": cookie.value };
- // only add attributes with non-default values (saving a few bits)
- if (cookie.path) jscookie.path = cookie.path;
- if (cookie.name) jscookie.name = cookie.name;
- if (cookie.isSecure) jscookie.secure = true;
- if (cookie.isHttpOnly) jscookie.httponly = true;
- if (cookie.expiry < MAX_EXPIRY) jscookie.expiry = cookie.expiry;
-
- addCookieToHash(jscookies, cookie.host, cookie.path, cookie.name, jscookie);
- }
- window.cookies.push(jscookies[cookie.host][cookie.path][cookie.name]);
- }
- }
- }
-
- // don't include empty cookie sections
- if (!window.cookies.length)
- delete window.cookies;
- }
- },
-
- /**
- * Store window dimensions, visibility, sidebar
- * @param aWindow
- * Window reference
- */
- _updateWindowFeatures: function ssi_updateWindowFeatures(aWindow) {
- var winData = this._windows[aWindow.__SSi];
-
- WINDOW_ATTRIBUTES.forEach(function(aAttr) {
- winData[aAttr] = this._getWindowDimension(aWindow, aAttr);
- }, this);
-
- var hidden = WINDOW_HIDEABLE_FEATURES.filter(function(aItem) {
- return aWindow[aItem] && !aWindow[aItem].visible;
- });
- if (hidden.length != 0)
- winData.hidden = hidden.join(",");
- else if (winData.hidden)
- delete winData.hidden;
-
- var sidebar = aWindow.document.getElementById("sidebar-box").getAttribute("sidebarcommand");
- if (sidebar)
- winData.sidebar = sidebar;
- else if (winData.sidebar)
- delete winData.sidebar;
- },
-
- /**
- * gather session data as object
- * @param aUpdateAll
- * Bool update all windows
- * @param aPinnedOnly
- * Bool collect pinned tabs only
- * @returns object
- */
- _getCurrentState: function ssi_getCurrentState(aUpdateAll, aPinnedOnly) {
- this._handleClosedWindows();
-
- var activeWindow = this._getMostRecentBrowserWindow();
-
- if (this._loadState == STATE_RUNNING) {
- // update the data for all windows with activities since the last save operation
- this._forEachBrowserWindow(function(aWindow) {
- if (!this._isWindowLoaded(aWindow)) // window data is still in _statesToRestore
- return;
- if (aUpdateAll || this._dirtyWindows[aWindow.__SSi] || aWindow == activeWindow) {
- this._collectWindowData(aWindow);
- }
- else { // always update the window features (whose change alone never triggers a save operation)
- this._updateWindowFeatures(aWindow);
- }
- });
- this._dirtyWindows = [];
- }
-
- // collect the data for all windows
- var total = [], windows = {}, ids = [];
- var nonPopupCount = 0;
- var ix;
- for (ix in this._windows) {
- if (this._windows[ix]._restoring) // window data is still in _statesToRestore
- continue;
- total.push(this._windows[ix]);
- ids.push(ix);
- windows[ix] = this._windows[ix];
- if (!this._windows[ix].isPopup)
- nonPopupCount++;
- }
- this._updateCookies(windows);
-
- // collect the data for all windows yet to be restored
- for (ix in this._statesToRestore) {
- for each (let winData in this._statesToRestore[ix].windows) {
- total.push(winData);
- if (!winData.isPopup)
- nonPopupCount++;
- }
- }
-
- // shallow copy this._closedWindows to preserve current state
- let lastClosedWindowsCopy = this._closedWindows.slice();
-
-#ifndef XP_MACOSX
- // If no non-popup browser window remains open, return the state of the last
- // closed window(s). We only want to do this when we're actually "ending"
- // the session.
- //XXXzpao We should do this for _restoreLastWindow == true, but that has
- // its own check for popups. c.f. bug 597619
- if (nonPopupCount == 0 && lastClosedWindowsCopy.length > 0 &&
- this._loadState == STATE_QUITTING) {
- // prepend the last non-popup browser window, so that if the user loads more tabs
- // at startup we don't accidentally add them to a popup window
- do {
- total.unshift(lastClosedWindowsCopy.shift())
- } while (total[0].isPopup && lastClosedWindowsCopy.length > 0)
- }
-#endif
-
- if (aPinnedOnly) {
- // perform a deep copy so that existing session variables are not changed.
- total = JSON.parse(this._toJSONString(total));
- total = total.filter(function (win) {
- win.tabs = win.tabs.filter(function (tab) tab.pinned);
- // remove closed tabs
- win._closedTabs = [];
- // correct selected tab index if it was stripped out
- if (win.selected > win.tabs.length)
- win.selected = 1;
- return win.tabs.length > 0;
- });
- if (total.length == 0)
- return null;
-
- lastClosedWindowsCopy = [];
- }
-
- if (activeWindow) {
- this.activeWindowSSiCache = activeWindow.__SSi || "";
- }
- ix = ids.indexOf(this.activeWindowSSiCache);
- // We don't want to restore focus to a minimized window or a window which had all its
- // tabs stripped out (doesn't exist).
- if (ix != -1 && total[ix] && total[ix].sizemode == "minimized")
- ix = -1;
-
- let session = {
- state: this._loadState == STATE_RUNNING ? STATE_RUNNING_STR : STATE_STOPPED_STR,
- lastUpdate: Date.now(),
- startTime: this._sessionStartTime,
- recentCrashes: this._recentCrashes
- };
-
- var scratchpads = null;
- var browserConsole = null;
-#ifdef MOZ_DEVTOOLS
- // Scratchpad
- // get open Scratchpad window states too
- scratchpads = ScratchpadManager.getSessionState();
-
- // The Browser Console
- browserConsole = HUDService.getBrowserConsoleSessionState();
-#endif
-
- return {
- windows: total,
- selectedWindow: ix + 1,
- _closedWindows: lastClosedWindowsCopy,
-#ifdef MOZ_DEVTOOLS
- session: session,
- scratchpads: scratchpads,
- browserConsole: browserConsole
-#else
- session: session
-#endif
- };
- },
-
- /**
- * serialize session data for a window
- * @param aWindow
- * Window reference
- * @returns string
- */
- _getWindowState: function ssi_getWindowState(aWindow) {
- if (!this._isWindowLoaded(aWindow))
- return this._statesToRestore[aWindow.__SS_restoreID];
-
- if (this._loadState == STATE_RUNNING) {
- this._collectWindowData(aWindow);
- }
-
- var winData = this._windows[aWindow.__SSi];
- let windows = {};
- windows[aWindow.__SSi] = winData;
- this._updateCookies(windows);
-
- return { windows: [winData] };
- },
-
- _collectWindowData: function ssi_collectWindowData(aWindow) {
- if (!this._isWindowLoaded(aWindow))
- return;
-
- // update the internal state data for this window
- this._saveWindowHistory(aWindow);
- this._updateTextAndScrollData(aWindow);
- this._updateCookieHosts(aWindow);
- this._updateWindowFeatures(aWindow);
-
- // Make sure we keep __SS_lastSessionWindowID around for cases like entering
- // or leaving PB mode.
- if (aWindow.__SS_lastSessionWindowID)
- this._windows[aWindow.__SSi].__lastSessionWindowID =
- aWindow.__SS_lastSessionWindowID;
-
- this._dirtyWindows[aWindow.__SSi] = false;
- },
-
- /* ........ Restoring Functionality .............. */
-
- /**
- * restore features to a single window
- * @param aWindow
- * Window reference
- * @param aState
- * JS object or its eval'able source
- * @param aOverwriteTabs
- * bool overwrite existing tabs w/ new ones
- * @param aFollowUp
- * bool this isn't the restoration of the first window
- */
- restoreWindow: function ssi_restoreWindow(aWindow, aState, aOverwriteTabs, aFollowUp) {
- if (!aFollowUp) {
- this.windowToFocus = aWindow;
- }
- // initialize window if necessary
- if (aWindow && (!aWindow.__SSi || !this._windows[aWindow.__SSi]))
- this.onLoad(aWindow);
-
- try {
- var root = typeof aState == "string" ? JSON.parse(aState) : aState;
- if (!root.windows[0]) {
- this._sendRestoreCompletedNotifications();
- return; // nothing to restore
- }
- }
- catch (ex) { // invalid state object - don't restore anything
- debug(ex);
- this._sendRestoreCompletedNotifications();
- return;
- }
-
- // We're not returning from this before we end up calling restoreHistoryPrecursor
- // for this window, so make sure we send the SSWindowStateBusy event.
- this._setWindowStateBusy(aWindow);
-
- if (root._closedWindows)
- this._closedWindows = root._closedWindows;
-
- var winData;
- if (!root.selectedWindow || root.selectedWindow > root.windows.length) {
- root.selectedWindow = 0;
- }
-
- // open new windows for all further window entries of a multi-window session
- // (unless they don't contain any tab data)
- for (var w = 1; w < root.windows.length; w++) {
- winData = root.windows[w];
- if (winData && winData.tabs && winData.tabs[0]) {
- var window = this._openWindowWithState({ windows: [winData] });
- if (w == root.selectedWindow - 1) {
- this.windowToFocus = window;
- }
- }
- }
- winData = root.windows[0];
- if (!winData.tabs) {
- winData.tabs = [];
- }
- // don't restore a single blank tab when we've had an external
- // URL passed in for loading at startup (cf. bug 357419)
- else if (root._firstTabs && !aOverwriteTabs && winData.tabs.length == 1 &&
- (!winData.tabs[0].entries || winData.tabs[0].entries.length == 0)) {
- winData.tabs = [];
- }
-
- var tabbrowser = aWindow.gBrowser;
- var openTabCount = aOverwriteTabs ? tabbrowser.browsers.length : -1;
- var newTabCount = winData.tabs.length;
- var tabs = [];
-
- // disable smooth scrolling while adding, moving, removing and selecting tabs
- var tabstrip = tabbrowser.tabContainer.mTabstrip;
- var smoothScroll = tabstrip.smoothScroll;
- tabstrip.smoothScroll = false;
-
- // unpin all tabs to ensure they are not reordered in the next loop
- if (aOverwriteTabs) {
- for (let t = tabbrowser._numPinnedTabs - 1; t > -1; t--)
- tabbrowser.unpinTab(tabbrowser.tabs[t]);
- }
-
- // make sure that the selected tab won't be closed in order to
- // prevent unnecessary flickering
- if (aOverwriteTabs && tabbrowser.selectedTab._tPos >= newTabCount)
- tabbrowser.moveTabTo(tabbrowser.selectedTab, newTabCount - 1);
-
- let numVisibleTabs = 0;
-
- for (var t = 0; t < newTabCount; t++) {
- tabs.push(t < openTabCount ?
- tabbrowser.tabs[t] :
- tabbrowser.addTab("about:blank",
- {skipAnimation: true,
- skipBackgroundNotify: true}));
- // when resuming at startup: add additionally requested pages to the end
- if (!aOverwriteTabs && root._firstTabs) {
- tabbrowser.moveTabTo(tabs[t], t);
- }
-
- if (winData.tabs[t].pinned)
- tabbrowser.pinTab(tabs[t]);
-
- if (winData.tabs[t].hidden) {
- tabbrowser.hideTab(tabs[t]);
- }
- else {
- tabbrowser.showTab(tabs[t]);
- numVisibleTabs++;
- }
- }
-
- // if all tabs to be restored are hidden, make the first one visible
- if (!numVisibleTabs && winData.tabs.length) {
- winData.tabs[0].hidden = false;
- tabbrowser.showTab(tabs[0]);
- }
-
- // If overwriting tabs, we want to reset each tab's "restoring" state. Since
- // we're overwriting those tabs, they should no longer be restoring. The
- // tabs will be rebuilt and marked if they need to be restored after loading
- // state (in restoreHistoryPrecursor).
- if (aOverwriteTabs) {
- for (let i = 0; i < tabbrowser.tabs.length; i++) {
- if (tabbrowser.browsers[i].__SS_restoreState)
- this._resetTabRestoringState(tabbrowser.tabs[i]);
- }
- }
-
- // We want to set up a counter on the window that indicates how many tabs
- // in this window are unrestored. This will be used in restoreNextTab to
- // determine if gRestoreTabsProgressListener should be removed from the window.
- // If we aren't overwriting existing tabs, then we want to add to the existing
- // count in case there are still tabs restoring.
- if (!aWindow.__SS_tabsToRestore)
- aWindow.__SS_tabsToRestore = 0;
- if (aOverwriteTabs)
- aWindow.__SS_tabsToRestore = newTabCount;
- else
- aWindow.__SS_tabsToRestore += newTabCount;
-
- // We want to correlate the window with data from the last session, so
- // assign another id if we have one. Otherwise clear so we don't do
- // anything with it.
- delete aWindow.__SS_lastSessionWindowID;
- if (winData.__lastSessionWindowID)
- aWindow.__SS_lastSessionWindowID = winData.__lastSessionWindowID;
-
- // when overwriting tabs, remove all superflous ones
- if (aOverwriteTabs && newTabCount < openTabCount) {
- Array.slice(tabbrowser.tabs, newTabCount, openTabCount)
- .forEach(tabbrowser.removeTab, tabbrowser);
- }
-
- if (aOverwriteTabs) {
- this.restoreWindowFeatures(aWindow, winData);
- delete this._windows[aWindow.__SSi].extData;
- }
- if (winData.cookies) {
- this.restoreCookies(winData.cookies);
- }
- if (winData.extData) {
- if (!this._windows[aWindow.__SSi].extData) {
- this._windows[aWindow.__SSi].extData = {};
- }
- for (var key in winData.extData) {
- this._windows[aWindow.__SSi].extData[key] = winData.extData[key];
- }
- }
- if (aOverwriteTabs || root._firstTabs) {
- this._windows[aWindow.__SSi]._closedTabs = winData._closedTabs || [];
- }
-
- this.restoreHistoryPrecursor(aWindow, tabs, winData.tabs,
- (aOverwriteTabs ? (parseInt(winData.selected) || 1) : 0), 0, 0);
-
-#ifdef MOZ_DEVTOOLS
- if (aState.scratchpads) {
- ScratchpadManager.restoreSession(aState.scratchpads);
- }
-
- // The Browser Console
- if (aState.browserConsole) {
- HUDService.restoreBrowserConsoleSession();
- }
-
-#endif
- // set smoothScroll back to the original value
- tabstrip.smoothScroll = smoothScroll;
-
- this._sendRestoreCompletedNotifications();
- },
-
- /**
- * Sets the tabs restoring order with the following priority:
- * Selected tab, pinned tabs, optimized visible tabs, other visible tabs and
- * hidden tabs.
- * @param aTabBrowser
- * Tab browser object
- * @param aTabs
- * Array of tab references
- * @param aTabData
- * Array of tab data
- * @param aSelectedTab
- * Index of selected tab (1 is first tab, 0 no selected tab)
- */
- _setTabsRestoringOrder : function ssi__setTabsRestoringOrder(
- aTabBrowser, aTabs, aTabData, aSelectedTab) {
-
- // Store the selected tab. Need to substract one to get the index in aTabs.
- let selectedTab;
- if (aSelectedTab > 0 && aTabs[aSelectedTab - 1]) {
- selectedTab = aTabs[aSelectedTab - 1];
- }
-
- // Store the pinned tabs and hidden tabs.
- let pinnedTabs = [];
- let pinnedTabsData = [];
- let hiddenTabs = [];
- let hiddenTabsData = [];
- if (aTabs.length > 1) {
- for (let t = aTabs.length - 1; t >= 0; t--) {
- if (aTabData[t].pinned) {
- pinnedTabs.unshift(aTabs.splice(t, 1)[0]);
- pinnedTabsData.unshift(aTabData.splice(t, 1)[0]);
- } else if (aTabData[t].hidden) {
- hiddenTabs.unshift(aTabs.splice(t, 1)[0]);
- hiddenTabsData.unshift(aTabData.splice(t, 1)[0]);
- }
- }
- }
-
- // Optimize the visible tabs only if there is a selected tab.
- if (selectedTab) {
- let selectedTabIndex = aTabs.indexOf(selectedTab);
- if (selectedTabIndex > 0) {
- let scrollSize = aTabBrowser.tabContainer.mTabstrip.scrollClientSize;
- let tabWidth = aTabs[0].getBoundingClientRect().width;
- let maxVisibleTabs = Math.ceil(scrollSize / tabWidth);
- if (maxVisibleTabs < aTabs.length) {
- let firstVisibleTab = 0;
- let nonVisibleTabsCount = aTabs.length - maxVisibleTabs;
- if (nonVisibleTabsCount >= selectedTabIndex) {
- // Selected tab is leftmost since we scroll to it when possible.
- firstVisibleTab = selectedTabIndex;
- } else {
- // Selected tab is rightmost or no more room to scroll right.
- firstVisibleTab = nonVisibleTabsCount;
- }
- aTabs = aTabs.splice(firstVisibleTab, maxVisibleTabs).concat(aTabs);
- aTabData =
- aTabData.splice(firstVisibleTab, maxVisibleTabs).concat(aTabData);
- }
- }
- }
-
- // Merge the stored tabs in order.
- aTabs = pinnedTabs.concat(aTabs, hiddenTabs);
- aTabData = pinnedTabsData.concat(aTabData, hiddenTabsData);
-
- // Load the selected tab to the first position and select it.
- if (selectedTab) {
- let selectedTabIndex = aTabs.indexOf(selectedTab);
- if (selectedTabIndex > 0) {
- aTabs = aTabs.splice(selectedTabIndex, 1).concat(aTabs);
- aTabData = aTabData.splice(selectedTabIndex, 1).concat(aTabData);
- }
- aTabBrowser.selectedTab = selectedTab;
- }
-
- return [aTabs, aTabData];
- },
-
- /**
- * Manage history restoration for a window
- * @param aWindow
- * Window to restore the tabs into
- * @param aTabs
- * Array of tab references
- * @param aTabData
- * Array of tab data
- * @param aSelectTab
- * Index of selected tab
- * @param aIx
- * Index of the next tab to check readyness for
- * @param aCount
- * Counter for number of times delaying b/c browser or history aren't ready
- * @param aRestoreImmediately
- * Flag to indicate whether the given set of tabs aTabs should be
- * restored/loaded immediately even if restore_on_demand = true
- */
- restoreHistoryPrecursor:
- function ssi_restoreHistoryPrecursor(aWindow, aTabs, aTabData, aSelectTab,
- aIx, aCount, aRestoreImmediately = false) {
- var tabbrowser = aWindow.gBrowser;
-
- // make sure that all browsers and their histories are available
- // - if one's not, resume this check in 100ms (repeat at most 10 times)
- for (var t = aIx; t < aTabs.length; t++) {
- try {
- if (!tabbrowser.getBrowserForTab(aTabs[t]).webNavigation.sessionHistory) {
- throw new Error();
- }
- }
- catch (ex) { // in case browser or history aren't ready yet
- if (aCount < 10) {
- var restoreHistoryFunc = function(self) {
- self.restoreHistoryPrecursor(aWindow, aTabs, aTabData, aSelectTab,
- aIx, aCount + 1, aRestoreImmediately);
- }
- aWindow.setTimeout(restoreHistoryFunc, 100, this);
- return;
- }
- }
- }
-
- if (!this._isWindowLoaded(aWindow)) {
- // from now on, the data will come from the actual window
- delete this._statesToRestore[aWindow.__SS_restoreID];
- delete aWindow.__SS_restoreID;
- delete this._windows[aWindow.__SSi]._restoring;
-
- // It's important to set the window state to dirty so that
- // we collect their data for the first time when saving state.
- this._dirtyWindows[aWindow.__SSi] = true;
- }
-
- if (aTabs.length == 0) {
- // this is normally done in restoreHistory() but as we're returning early
- // here we need to take care of it.
- this._setWindowStateReady(aWindow);
- return;
- }
-
- // Sets the tabs restoring order.
- [aTabs, aTabData] =
- this._setTabsRestoringOrder(tabbrowser, aTabs, aTabData, aSelectTab);
-
- // Prepare the tabs so that they can be properly restored. We'll pin/unpin
- // and show/hide tabs as necessary. We'll also set the labels, user typed
- // value, and attach a copy of the tab's data in case we close it before
- // it's been restored.
- for (t = 0; t < aTabs.length; t++) {
- let tab = aTabs[t];
- let browser = tabbrowser.getBrowserForTab(tab);
- let tabData = aTabData[t];
-
- if (tabData.pinned)
- tabbrowser.pinTab(tab);
- else
- tabbrowser.unpinTab(tab);
-
- if (tabData.hidden)
- tabbrowser.hideTab(tab);
- else
- tabbrowser.showTab(tab);
-
- if ("attributes" in tabData) {
- // Ensure that we persist tab attributes restored from previous sessions.
- Object.keys(tabData.attributes).forEach(a => TabAttributes.persist(a));
- }
-
- browser.__SS_tabStillLoading = true;
-
- // keep the data around to prevent dataloss in case
- // a tab gets closed before it's been properly restored
- browser.__SS_data = tabData;
- browser.__SS_restoreState = TAB_STATE_NEEDS_RESTORE;
- browser.setAttribute("pending", "true");
- tab.setAttribute("pending", "true");
-
- // Make sure that set/getTabValue will set/read the correct data by
- // wiping out any current value in tab.__SS_extdata.
- delete tab.__SS_extdata;
-
- if (!tabData.entries || tabData.entries.length == 0) {
- // make sure to blank out this tab's content
- // (just purging the tab's history won't be enough)
- browser.contentDocument.location = "about:blank";
- continue;
- }
-
- browser.stop(); // in case about:blank isn't done yet
-
- // wall-paper fix for bug 439675: make sure that the URL to be loaded
- // is always visible in the address bar
- let activeIndex = (tabData.index || tabData.entries.length) - 1;
- let activePageData = tabData.entries[activeIndex] || null;
- let uri = activePageData ? activePageData.url || null : null;
- browser.userTypedValue = uri;
-
- // Also make sure currentURI is set so that switch-to-tab works before
- // the tab is restored. We'll reset this to about:blank when we try to
- // restore the tab to ensure that docshell doeesn't get confused.
- if (uri)
- browser.docShell.setCurrentURI(this._getURIFromString(uri));
-
- // If the page has a title, set it.
- if (activePageData) {
- if (activePageData.title) {
- tab.label = activePageData.title;
- tab.crop = "end";
- } else if (activePageData.url != "about:blank") {
- tab.label = activePageData.url;
- tab.crop = "center";
- }
- }
- }
-
- // helper hashes for ensuring unique frame IDs and unique document
- // identifiers.
- var idMap = { used: {} };
- var docIdentMap = {};
- this.restoreHistory(aWindow, aTabs, aTabData, idMap, docIdentMap,
- aRestoreImmediately);
- },
-
- /**
- * Restore history for a window
- * @param aWindow
- * Window reference
- * @param aTabs
- * Array of tab references
- * @param aTabData
- * Array of tab data
- * @param aIdMap
- * Hash for ensuring unique frame IDs
- * @param aRestoreImmediately
- * Flag to indicate whether the given set of tabs aTabs should be
- * restored/loaded immediately even if restore_on_demand = true
- */
- restoreHistory:
- function ssi_restoreHistory(aWindow, aTabs, aTabData, aIdMap, aDocIdentMap,
- aRestoreImmediately) {
- var _this = this;
- // if the tab got removed before being completely restored, then skip it
- while (aTabs.length > 0 && !(this._canRestoreTabHistory(aTabs[0]))) {
- aTabs.shift();
- aTabData.shift();
- }
- if (aTabs.length == 0) {
- // At this point we're essentially ready for consumers to read/write data
- // via the sessionstore API so we'll send the SSWindowStateReady event.
- this._setWindowStateReady(aWindow);
- return; // no more tabs to restore
- }
-
- var tab = aTabs.shift();
- var tabData = aTabData.shift();
-
- var browser = aWindow.gBrowser.getBrowserForTab(tab);
- var history = browser.webNavigation.sessionHistory;
-
- if (history.count > 0) {
- history.PurgeHistory(history.count);
- }
- history.QueryInterface(Ci.nsISHistoryInternal);
-
- browser.__SS_shistoryListener = new SessionStoreSHistoryListener(tab);
- history.addSHistoryListener(browser.__SS_shistoryListener);
-
- if (!tabData.entries) {
- tabData.entries = [];
- }
- if (tabData.extData) {
- tab.__SS_extdata = {};
- for (let key in tabData.extData)
- tab.__SS_extdata[key] = tabData.extData[key];
- }
- else
- delete tab.__SS_extdata;
-
- for (var i = 0; i < tabData.entries.length; i++) {
- //XXXzpao Wallpaper patch for bug 514751
- if (!tabData.entries[i].url)
- continue;
- history.addEntry(this._deserializeHistoryEntry(tabData.entries[i],
- aIdMap, aDocIdentMap), true);
- }
-
- // make sure to reset the capabilities and attributes, in case this tab gets reused
- let disallow = new Set(tabData.disallow && tabData.disallow.split(","));
- for (let cap of gDocShellCapabilities(browser.docShell))
- browser.docShell["allow" + cap] = !disallow.has(cap);
-
- // Restore tab attributes.
- if ("attributes" in tabData) {
- TabAttributes.set(tab, tabData.attributes);
- }
-
- // Restore the tab icon.
- if ("image" in tabData) {
- // Using null as the loadingPrincipal because serializing
- // the principal would be overkill. Within SetIcon we
- // default to the systemPrincipal if aLoadingPrincipal is
- // null which will allow the favicon to load.
- aWindow.gBrowser.setIcon(tab, tabData.image, null);
- }
-
- if (tabData.storage && browser.docShell instanceof Ci.nsIDocShell)
- SessionStorage.deserialize(browser.docShell, tabData.storage);
-
- // notify the tabbrowser that the tab chrome has been restored
- var event = aWindow.document.createEvent("Events");
- event.initEvent("SSTabRestoring", true, false);
- tab.dispatchEvent(event);
-
- // Restore the history in the next tab
- aWindow.setTimeout(function(){
- _this.restoreHistory(aWindow, aTabs, aTabData, aIdMap, aDocIdentMap,
- aRestoreImmediately);
- }, 0);
-
- // This could cause us to ignore max_concurrent_tabs pref a bit, but
- // it ensures each window will have its selected tab loaded.
- if (aRestoreImmediately || aWindow.gBrowser.selectedBrowser == browser) {
- this.restoreTab(tab);
- }
- else {
- TabRestoreQueue.add(tab);
- this.restoreNextTab();
- }
- },
-
- /**
- * Restores the specified tab. If the tab can't be restored (eg, no history or
- * calling gotoIndex fails), then state changes will be rolled back.
- * This method will check if gTabsProgressListener is attached to the tab's
- * window, ensuring that we don't get caught without one.
- * This method removes the session history listener right before starting to
- * attempt a load. This will prevent cases of "stuck" listeners.
- * If this method returns false, then it is up to the caller to decide what to
- * do. In the common case (restoreNextTab), we will want to then attempt to
- * restore the next tab. In the other case (selecting the tab, reloading the
- * tab), the caller doesn't actually want to do anything if no page is loaded.
- *
- * @param aTab
- * the tab to restore
- *
- * @returns true/false indicating whether or not a load actually happened
- */
- restoreTab: function ssi_restoreTab(aTab) {
- let window = aTab.ownerDocument.defaultView;
- let browser = aTab.linkedBrowser;
- let tabData = browser.__SS_data;
-
- // There are cases within where we haven't actually started a load. In that
- // that case we'll reset state changes we made and return false to the caller
- // can handle appropriately.
- let didStartLoad = false;
-
- // Make sure that the tabs progress listener is attached to this window
- this._ensureTabsProgressListener(window);
-
- // Make sure that this tab is removed from the priority queue.
- TabRestoreQueue.remove(aTab);
-
- // Increase our internal count.
- this._tabsRestoringCount++;
-
- // Set this tab's state to restoring
- browser.__SS_restoreState = TAB_STATE_RESTORING;
- browser.removeAttribute("pending");
- aTab.removeAttribute("pending");
-
- // Remove the history listener, since we no longer need it once we start restoring
- this._removeSHistoryListener(aTab);
-
- let activeIndex = (tabData.index || tabData.entries.length) - 1;
- if (activeIndex >= tabData.entries.length)
- activeIndex = tabData.entries.length - 1;
- // Reset currentURI. This creates a new session history entry with a new
- // doc identifier, so we need to explicitly save and restore the old doc
- // identifier (corresponding to the SHEntry at activeIndex) below.
- browser.webNavigation.setCurrentURI(this._getURIFromString("about:blank"));
- // Attach data that will be restored on "load" event, after tab is restored.
- if (activeIndex > -1) {
- // restore those aspects of the currently active documents which are not
- // preserved in the plain history entries (mainly scroll state and text data)
- browser.__SS_restore_data = tabData.entries[activeIndex] || {};
- browser.__SS_restore_pageStyle = tabData.pageStyle || "";
- browser.__SS_restore_tab = aTab;
- didStartLoad = true;
- try {
- // In order to work around certain issues in session history, we need to
- // force session history to update its internal index and call reload
- // instead of gotoIndex. See bug 597315.
- browser.webNavigation.sessionHistory.getEntryAtIndex(activeIndex, true);
- browser.webNavigation.sessionHistory.reloadCurrentEntry();
- // If the user prefers it, bypass cache and always load from the network.
- let flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
- switch (this._cacheBehavior) {
- case 2: // hard refresh
- flags = Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_PROXY |
- Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE;
- browser.webNavigation.reload(flags);
- break;
- case 1: // soft refresh
- browser.webNavigation.reload(flags);
- break;
- default: // 0 or other: use cache, so do nothing.
- break;
- }
- }
- catch (ex) {
- // ignore page load errors
- aTab.removeAttribute("busy");
- didStartLoad = false;
- }
- }
-
- // Handle userTypedValue. Setting userTypedValue seems to update gURLbar
- // as needed. Calling loadURI will cancel form filling in restoreDocument
- if (tabData.userTypedValue) {
- browser.userTypedValue = tabData.userTypedValue;
- if (tabData.userTypedClear) {
- // Make it so that we'll enter restoreDocument on page load. We will
- // fire SSTabRestored from there. We don't have any form data to restore
- // so we can just set the URL to null.
- browser.__SS_restore_data = { url: null };
- browser.__SS_restore_tab = aTab;
- if (didStartLoad)
- browser.stop();
- didStartLoad = true;
- browser.loadURIWithFlags(tabData.userTypedValue,
- Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP);
- }
- }
-
- // If we didn't start a load, then we won't reset this tab through the usual
- // channel (via the progress listener), so reset the tab ourselves. We will
- // also send SSTabRestored since this tab has technically been restored.
- if (!didStartLoad) {
- this._sendTabRestoredNotification(aTab);
- this._resetTabRestoringState(aTab);
- }
-
- return didStartLoad;
- },
-
- /**
- * This _attempts_ to restore the next available tab. If the restore fails,
- * then we will attempt the next one.
- * There are conditions where this won't do anything:
- * if we're in the process of quitting
- * if there are no tabs to restore
- * if we have already reached the limit for number of tabs to restore
- */
- restoreNextTab: function ssi_restoreNextTab() {
- // If we call in here while quitting, we don't actually want to do anything
- if (this._loadState == STATE_QUITTING)
- return;
-
- // Don't exceed the maximum number of concurrent tab restores.
- if (this._tabsRestoringCount >= this._maxConcurrentTabRestores)
- return;
-
- let tab = TabRestoreQueue.shift();
- if (tab) {
- let didStartLoad = this.restoreTab(tab);
- // If we don't start a load in the restored tab (eg, no entries) then we
- // want to attempt to restore the next tab.
- if (!didStartLoad)
- this.restoreNextTab();
- }
- },
-
- /**
- * expands serialized history data into a session-history-entry instance
- * @param aEntry
- * Object containing serialized history data for a URL
- * @param aIdMap
- * Hash for ensuring unique frame IDs
- * @returns nsISHEntry
- */
- _deserializeHistoryEntry:
- function ssi_deserializeHistoryEntry(aEntry, aIdMap, aDocIdentMap) {
-
- var shEntry = Cc["@mozilla.org/browser/session-history-entry;1"].
- createInstance(Ci.nsISHEntry);
-
- shEntry.setURI(this._getURIFromString(aEntry.url));
- shEntry.setTitle(aEntry.title || aEntry.url);
- if (aEntry.subframe)
- shEntry.setIsSubFrame(aEntry.subframe || false);
- shEntry.loadType = Ci.nsIDocShellLoadInfo.loadHistory;
- if (aEntry.contentType)
- shEntry.contentType = aEntry.contentType;
- if (aEntry.referrer)
- shEntry.referrerURI = this._getURIFromString(aEntry.referrer);
- if (aEntry.isSrcdocEntry)
- shEntry.srcdocData = aEntry.srcdocData;
-
- if (aEntry.cacheKey) {
- var cacheKey = Cc["@mozilla.org/supports-PRUint32;1"].
- createInstance(Ci.nsISupportsPRUint32);
- cacheKey.data = aEntry.cacheKey;
- shEntry.cacheKey = cacheKey;
- }
-
- if (aEntry.ID) {
- // get a new unique ID for this frame (since the one from the last
- // start might already be in use)
- var id = aIdMap[aEntry.ID] || 0;
- if (!id) {
- for (id = Date.now(); id in aIdMap.used; id++);
- aIdMap[aEntry.ID] = id;
- aIdMap.used[id] = true;
- }
- shEntry.ID = id;
- }
-
- if (aEntry.docshellID)
- shEntry.docshellID = aEntry.docshellID;
-
- if (aEntry.structuredCloneState && aEntry.structuredCloneVersion) {
- shEntry.stateData =
- Cc["@mozilla.org/docshell/structured-clone-container;1"].
- createInstance(Ci.nsIStructuredCloneContainer);
-
- shEntry.stateData.initFromBase64(aEntry.structuredCloneState,
- aEntry.structuredCloneVersion);
- }
-
- if (aEntry.scroll) {
- var scrollPos = (aEntry.scroll || "0,0").split(",");
- scrollPos = [parseInt(scrollPos[0]) || 0, parseInt(scrollPos[1]) || 0];
- shEntry.setScrollPosition(scrollPos[0], scrollPos[1]);
- }
-
- if (aEntry.postdata_b64) {
- var postdata = atob(aEntry.postdata_b64);
- var stream = Cc["@mozilla.org/io/string-input-stream;1"].
- createInstance(Ci.nsIStringInputStream);
- stream.setData(postdata, postdata.length);
- shEntry.postData = stream;
- }
-
- let childDocIdents = {};
- if (aEntry.docIdentifier) {
- // If we have a serialized document identifier, try to find an SHEntry
- // which matches that doc identifier and adopt that SHEntry's
- // BFCacheEntry. If we don't find a match, insert shEntry as the match
- // for the document identifier.
- let matchingEntry = aDocIdentMap[aEntry.docIdentifier];
- if (!matchingEntry) {
- matchingEntry = {shEntry: shEntry, childDocIdents: childDocIdents};
- aDocIdentMap[aEntry.docIdentifier] = matchingEntry;
- }
- else {
- shEntry.adoptBFCacheEntry(matchingEntry.shEntry);
- childDocIdents = matchingEntry.childDocIdents;
- }
- }
-
- // The field aEntry.owner_b64 got renamed to aEntry.triggeringPricipal_b64 in
- // Bug 1286472. To remain backward compatible we still have to support that
- // field for a few cycles before we can remove it within Bug 1289785.
- if (aEntry.owner_b64) {
- aEntry.triggeringPrincipal_b64 = aEntry.owner_b64;
- delete aEntry.owner_b64;
- }
-
- if (aEntry.triggeringPrincipal_b64) {
- var triggeringPrincipalInput = Cc["@mozilla.org/io/string-input-stream;1"].
- createInstance(Ci.nsIStringInputStream);
- var binaryData = atob(aEntry.triggeringPrincipal_b64);
- triggeringPrincipalInput.setData(binaryData, binaryData.length);
- var binaryStream = Cc["@mozilla.org/binaryinputstream;1"].
- createInstance(Ci.nsIObjectInputStream);
- binaryStream.setInputStream(triggeringPrincipalInput);
- try { // Catch possible deserialization exceptions
- shEntry.triggeringPrincipal = binaryStream.readObject(true);
- } catch (ex) { debug(ex); }
- }
-
- if (aEntry.children && shEntry instanceof Ci.nsISHContainer) {
- for (var i = 0; i < aEntry.children.length; i++) {
- //XXXzpao Wallpaper patch for bug 514751
- if (!aEntry.children[i].url)
- continue;
-
- // We're getting sessionrestore.js files with a cycle in the
- // doc-identifier graph, likely due to bug 698656. (That is, we have
- // an entry where doc identifier A is an ancestor of doc identifier B,
- // and another entry where doc identifier B is an ancestor of A.)
- //
- // If we were to respect these doc identifiers, we'd create a cycle in
- // the SHEntries themselves, which causes the docshell to loop forever
- // when it looks for the root SHEntry.
- //
- // So as a hack to fix this, we restrict the scope of a doc identifier
- // to be a node's siblings and cousins, and pass childDocIdents, not
- // aDocIdents, to _deserializeHistoryEntry. That is, we say that two
- // SHEntries with the same doc identifier have the same document iff
- // they have the same parent or their parents have the same document.
-
- shEntry.AddChild(this._deserializeHistoryEntry(aEntry.children[i], aIdMap,
- childDocIdents), i);
- }
- }
-
- return shEntry;
- },
-
- /**
- * Restore properties to a loaded document
- */
- restoreDocument: function ssi_restoreDocument(aWindow, aBrowser, aEvent) {
- // wait for the top frame to be loaded completely
- if (!aEvent || !aEvent.originalTarget || !aEvent.originalTarget.defaultView ||
- aEvent.originalTarget.defaultView != aEvent.originalTarget.defaultView.top) {
- return;
- }
-
- // always call this before injecting content into a document!
- function hasExpectedURL(aDocument, aURL)
- !aURL || aURL.replace(/#.*/, "") == aDocument.location.href.replace(/#.*/, "");
-
- let selectedPageStyle = aBrowser.__SS_restore_pageStyle;
- function restoreTextDataAndScrolling(aContent, aData, aPrefix) {
- if (aData.formdata && hasExpectedURL(aContent.document, aData.url)) {
- let formdata = aData.formdata;
-
- // handle backwards compatibility
- // this is a migration from pre-firefox 15. cf. bug 742051
- if (!("xpath" in formdata || "id" in formdata)) {
- formdata = { xpath: {}, id: {} };
-
- for each (let [key, value] in Iterator(aData.formdata)) {
- if (key.charAt(0) == "#") {
- formdata.id[key.slice(1)] = value;
- } else {
- formdata.xpath[key] = value;
- }
- }
- }
-
- // for about:sessionrestore we saved the field as JSON to avoid
- // nested instances causing humongous sessionstore.js files.
- // cf. bug 467409
- if (aData.url == "about:sessionrestore" &&
- "sessionData" in formdata.id &&
- typeof formdata.id["sessionData"] == "object") {
- formdata.id["sessionData"] =
- JSON.stringify(formdata.id["sessionData"]);
- }
-
- // update the formdata
- aData.formdata = formdata;
- // merge the formdata
- DocumentUtils.mergeFormData(aContent.document, formdata);
- }
-
- if (aData.innerHTML) {
- aWindow.setTimeout(function() {
- if (aContent.document.designMode == "on" &&
- hasExpectedURL(aContent.document, aData.url) &&
- aContent.document.body) {
- aContent.document.body.innerHTML = aData.innerHTML;
- }
- }, 0);
- }
- var match;
- if (aData.scroll && (match = /(\d+),(\d+)/.exec(aData.scroll)) != null) {
- aContent.scrollTo(match[1], match[2]);
- }
- Array.forEach(aContent.document.styleSheets, function(aSS) {
- aSS.disabled = aSS.title && aSS.title != selectedPageStyle;
- });
- for (var i = 0; i < aContent.frames.length; i++) {
- if (aData.children && aData.children[i] &&
- hasExpectedURL(aContent.document, aData.url)) {
- restoreTextDataAndScrolling(aContent.frames[i], aData.children[i], aPrefix + i + "|");
- }
- }
- }
-
- // don't restore text data and scrolling state if the user has navigated
- // away before the loading completed (except for in-page navigation)
- if (hasExpectedURL(aEvent.originalTarget, aBrowser.__SS_restore_data.url)) {
- var content = aEvent.originalTarget.defaultView;
- restoreTextDataAndScrolling(content, aBrowser.__SS_restore_data, "");
- aBrowser.markupDocumentViewer.authorStyleDisabled = selectedPageStyle == "_nostyle";
- }
-
- // notify the tabbrowser that this document has been completely restored
- this._sendTabRestoredNotification(aBrowser.__SS_restore_tab);
-
- delete aBrowser.__SS_restore_data;
- delete aBrowser.__SS_restore_pageStyle;
- delete aBrowser.__SS_restore_tab;
- },
-
- /**
- * Restore visibility and dimension features to a window
- * @param aWindow
- * Window reference
- * @param aWinData
- * Object containing session data for the window
- */
- restoreWindowFeatures: function ssi_restoreWindowFeatures(aWindow, aWinData) {
- var hidden = (aWinData.hidden)?aWinData.hidden.split(","):[];
- WINDOW_HIDEABLE_FEATURES.forEach(function(aItem) {
- aWindow[aItem].visible = hidden.indexOf(aItem) == -1;
- });
-
- if (aWinData.isPopup) {
- this._windows[aWindow.__SSi].isPopup = true;
- if (aWindow.gURLBar) {
- aWindow.gURLBar.readOnly = true;
- aWindow.gURLBar.setAttribute("enablehistory", "false");
- }
- }
- else {
- delete this._windows[aWindow.__SSi].isPopup;
- if (aWindow.gURLBar) {
- aWindow.gURLBar.readOnly = false;
- aWindow.gURLBar.setAttribute("enablehistory", "true");
- }
- }
-
- var _this = this;
- aWindow.setTimeout(function() {
- _this.restoreDimensions.apply(_this, [aWindow,
- +aWinData.width || 0,
- +aWinData.height || 0,
- "screenX" in aWinData ? +aWinData.screenX : NaN,
- "screenY" in aWinData ? +aWinData.screenY : NaN,
- aWinData.sizemode || "", aWinData.sidebar || ""]);
- }, 0);
- },
-
- /**
- * Restore a window's dimensions
- * @param aWidth
- * Window width
- * @param aHeight
- * Window height
- * @param aLeft
- * Window left
- * @param aTop
- * Window top
- * @param aSizeMode
- * Window size mode (eg: maximized)
- * @param aSidebar
- * Sidebar command
- */
- restoreDimensions: function ssi_restoreDimensions(aWindow, aWidth, aHeight, aLeft, aTop, aSizeMode, aSidebar) {
- var win = aWindow;
- var _this = this;
- function win_(aName) { return _this._getWindowDimension(win, aName); }
-
- // Find available space on the screen where this window is being placed
- let screen = gScreenManager.screenForRect(aLeft, aTop, aWidth, aHeight);
- if (screen && !this._prefBranch.getBoolPref("sessionstore.exactPos")) {
- let screenLeft = {}, screenTop = {}, screenWidth = {}, screenHeight = {};
- screen.GetAvailRectDisplayPix(screenLeft, screenTop, screenWidth, screenHeight);
-
- // Screen X/Y are based on the origin of the screen's desktop-pixel coordinate space
- let screenLeftCss = screenLeft.value;
- let screenTopCss = screenTop.value;
-
- // Convert the screen's device pixel dimensions to CSS px dimensions
- screen.GetAvailRect(screenLeft, screenTop, screenWidth, screenHeight);
- let cssToDevScale = screen.defaultCSSScaleFactor;
- let screenRightCss = screenLeftCss + screenWidth.value / cssToDevScale;
- let screenBottomCss = screenTopCss + screenHeight.value / cssToDevScale;
-
- // Pull the window within the screen's bounds.
- // First, ensure the left edge is on-screen
- if (aLeft < screenLeftCss) {
- aLeft = screenLeftCss;
- }
- // Then check the resulting right edge, and reduce it if necessary.
- let right = aLeft + aWidth;
- if (right > screenRightCss) {
- right = screenRightCss;
- // See if we can move the left edge leftwards to maintain width.
- if (aLeft > screenLeftCss) {
- aLeft = Math.max(right - aWidth, screenLeftCss);
- }
- }
- // Finally, update aWidth to account for the adjusted left and right edges.
- aWidth = right - aLeft;
-
- // Do the same in the vertical dimension.
- // First, ensure the top edge is on-screen
- if (aTop < screenTopCss) {
- aTop = screenTopCss;
- }
- // Then check the resulting right edge, and reduce it if necessary.
- let bottom = aTop + aHeight;
- if (bottom > screenBottomCss) {
- bottom = screenBottomCss;
- // See if we can move the top edge upwards to maintain height.
- if (aTop > screenTopCss) {
- aTop = Math.max(bottom - aHeight, screenTopCss);
- }
- }
- // Finally, update aHeight to account for the adjusted top and bottom edges.
- aHeight = bottom - aTop;
- }
-
- // Only modify those aspects which aren't correct yet
- if (!isNaN(aLeft) && !isNaN(aTop) && (aLeft != win_("screenX") || aTop != win_("screenY"))) {
- aWindow.moveTo(aLeft, aTop);
- }
- if (aWidth && aHeight && (aWidth != win_("width") || aHeight != win_("height"))) {
- // Don't resize the window if it's currently maximized and we would
- // maximize it again shortly after.
- if (aSizeMode != "maximized" || win_("sizemode") != "maximized") {
- aWindow.resizeTo(aWidth, aHeight);
- }
- }
-
- // Restore window state
- if (aSizeMode && win_("sizemode") != aSizeMode)
- {
- switch (aSizeMode)
- {
- case "maximized":
- aWindow.maximize();
- break;
- case "minimized":
- aWindow.minimize();
- break;
- case "normal":
- aWindow.restore();
- break;
- }
- }
- var sidebar = aWindow.document.getElementById("sidebar-box");
- if (sidebar.getAttribute("sidebarcommand") != aSidebar) {
- aWindow.toggleSidebar(aSidebar);
- }
- // since resizing/moving a window brings it to the foreground,
- // we might want to re-focus the last focused window
- if (this.windowToFocus) {
- this.windowToFocus.focus();
- }
- },
-
- /**
- * Restores cookies
- * @param aCookies
- * Array of cookie objects
- */
- restoreCookies: function ssi_restoreCookies(aCookies) {
- // MAX_EXPIRY should be 2^63-1, but JavaScript can't handle that precision
- var MAX_EXPIRY = Math.pow(2, 62);
- for (let i = 0; i < aCookies.length; i++) {
- var cookie = aCookies[i];
- try {
- Services.cookies.add(cookie.host, cookie.path || "", cookie.name || "",
- cookie.value, !!cookie.secure, !!cookie.httponly, true,
- "expiry" in cookie ? cookie.expiry : MAX_EXPIRY, {});
- }
- catch (ex) { Cu.reportError(ex); } // don't let a single cookie stop recovering
- }
- },
-
- /* ........ Disk Access .............. */
-
- /**
- * save state delayed by N ms
- * marks window as dirty (i.e. data update can't be skipped)
- * @param aWindow
- * Window reference
- * @param aDelay
- * Milliseconds to delay
- */
- saveStateDelayed: function ssi_saveStateDelayed(aWindow, aDelay) {
- if (aWindow) {
- this._dirtyWindows[aWindow.__SSi] = true;
- }
-
- if (!this._saveTimer) {
- // interval until the next disk operation is allowed
- var minimalDelay = this._lastSaveTime + this._interval - Date.now();
-
- // if we have to wait, set a timer, otherwise saveState directly
- aDelay = Math.max(minimalDelay, aDelay || 2000);
- if (aDelay > 0) {
- this._saveTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
- this._saveTimer.init(this, aDelay, Ci.nsITimer.TYPE_ONE_SHOT);
- }
- else {
- this.saveState();
- }
- }
- },
-
- /**
- * save state to disk
- * @param aUpdateAll
- * Bool update all windows
- */
- saveState: function ssi_saveState(aUpdateAll) {
- // If crash recovery is disabled, we only want to resume with pinned tabs
- // if we crash.
- let pinnedOnly = this._loadState == STATE_RUNNING && !this._resume_from_crash;
-
- var oState = this._getCurrentState(aUpdateAll, pinnedOnly);
- if (!oState) {
- return;
- }
-
- // Forget about private windows.
- for (let i = oState.windows.length - 1; i >= 0; i--) {
- if (oState.windows[i].isPrivate) {
- oState.windows.splice(i, 1);
- if (oState.selectedWindow >= i) {
- oState.selectedWindow--;
- }
- }
- }
-
- for (let i = oState._closedWindows.length - 1; i >= 0; i--) {
- if (oState._closedWindows[i].isPrivate) {
- oState._closedWindows.splice(i, 1);
- }
- }
-
-#ifndef XP_MACOSX
- // We want to restore closed windows that are marked with _shouldRestore.
- // We're doing this here because we want to control this only when saving
- // the file.
- while (oState._closedWindows.length) {
- let i = oState._closedWindows.length - 1;
- if (oState._closedWindows[i]._shouldRestore) {
- delete oState._closedWindows[i]._shouldRestore;
- oState.windows.unshift(oState._closedWindows.pop());
- }
- else {
- // We only need to go until we hit !needsRestore since we're going in reverse
- break;
- }
- }
-#endif
-
- if (pinnedOnly) {
- // Save original resume_session_once preference for when quiting browser,
- // otherwise session will be restored next time browser starts and we
- // only want it to be restored in the case of a crash.
- if (this._resume_session_once_on_shutdown == null) {
- this._resume_session_once_on_shutdown =
- this._prefBranch.getBoolPref("sessionstore.resume_session_once");
- this._prefBranch.setBoolPref("sessionstore.resume_session_once", true);
- // flush the preference file so preference will be saved in case of a crash
- Services.prefs.savePrefFile(null);
- }
- }
-
- // Persist the last session if we deferred restoring it
- if (this._lastSessionState)
- oState.lastSessionState = this._lastSessionState;
-
- // Make sure that we keep the previous session if we started with a single
- // private window and no non-private windows have been opened, yet.
- if (this._deferredInitialState) {
- oState.windows = this._deferredInitialState.windows || [];
- }
-
- this._saveStateObject(oState);
- },
-
- /**
- * write a state object to disk
- */
- _saveStateObject: function ssi_saveStateObject(aStateObj) {
- let data = this._toJSONString(aStateObj);
-
- let stateString = this._createSupportsString(data);
- Services.obs.notifyObservers(stateString, "sessionstore-state-write", "");
- data = stateString.data;
-
- // Don't touch the file if an observer has deleted all state data.
- if (!data) {
- return;
- }
-
- let promise;
- // If "sessionstore.resume_from_crash" is true, attempt to backup the
- // session file first, before writing to it.
- if (this._resume_from_crash) {
- // Note that we do not have race conditions here as _SessionFile
- // guarantees that any I/O operation is completed before proceeding to
- // the next I/O operation.
- // Note backup happens only once, on initial save.
- promise = this._backupSessionFileOnce;
- } else {
- promise = Promise.resolve();
- }
-
- // Attempt to write to the session file (potentially, depending on
- // "sessionstore.resume_from_crash" preference, after successful backup).
- promise = promise.then(function onSuccess() {
- // Write (atomically) to a session file, using a tmp file.
- return _SessionFile.write(data);
- });
-
- // Once the session file is successfully updated, save the time stamp of the
- // last save and notify the observers.
- promise = promise.then(() => {
- this._lastSaveTime = Date.now();
- Services.obs.notifyObservers(null, "sessionstore-state-write-complete",
- "");
- });
- },
-
- /* ........ Auxiliary Functions .............. */
-
- // Wrap a string as a nsISupports
- _createSupportsString: function ssi_createSupportsString(aData) {
- let string = Cc["@mozilla.org/supports-string;1"]
- .createInstance(Ci.nsISupportsString);
- string.data = aData;
- return string;
- },
-
- /**
- * call a callback for all currently opened browser windows
- * (might miss the most recent one)
- * @param aFunc
- * Callback each window is passed to
- */
- _forEachBrowserWindow: function ssi_forEachBrowserWindow(aFunc) {
- var windowsEnum = Services.wm.getEnumerator("navigator:browser");
-
- while (windowsEnum.hasMoreElements()) {
- var window = windowsEnum.getNext();
- if (window.__SSi && !window.closed) {
- aFunc.call(this, window);
- }
- }
- },
-
- /**
- * Returns most recent window
- * @returns Window reference
- */
- _getMostRecentBrowserWindow: function ssi_getMostRecentBrowserWindow() {
- var win = Services.wm.getMostRecentWindow("navigator:browser");
- if (!win)
- return null;
- if (!win.closed)
- return win;
-
-#ifdef BROKEN_WM_Z_ORDER
- win = null;
- var windowsEnum = Services.wm.getEnumerator("navigator:browser");
- // this is oldest to newest, so this gets a bit ugly
- while (windowsEnum.hasMoreElements()) {
- let nextWin = windowsEnum.getNext();
- if (!nextWin.closed)
- win = nextWin;
- }
- return win;
-#else
- var windowsEnum =
- Services.wm.getZOrderDOMWindowEnumerator("navigator:browser", true);
- while (windowsEnum.hasMoreElements()) {
- win = windowsEnum.getNext();
- if (!win.closed)
- return win;
- }
- return null;
-#endif
- },
-
- /**
- * Calls onClose for windows that are determined to be closed but aren't
- * destroyed yet, which would otherwise cause getBrowserState and
- * setBrowserState to treat them as open windows.
- */
- _handleClosedWindows: function ssi_handleClosedWindows() {
- var windowsEnum = Services.wm.getEnumerator("navigator:browser");
-
- while (windowsEnum.hasMoreElements()) {
- var window = windowsEnum.getNext();
- if (window.closed) {
- this.onClose(window);
- }
- }
- },
-
- /**
- * open a new browser window for a given session state
- * called when restoring a multi-window session
- * @param aState
- * Object containing session data
- */
- _openWindowWithState: function ssi_openWindowWithState(aState) {
- var argString = Cc["@mozilla.org/supports-string;1"].
- createInstance(Ci.nsISupportsString);
- argString.data = "";
-
- // Build feature string
- let features = "chrome,dialog=no,macsuppressanimation,all";
- let winState = aState.windows[0];
- WINDOW_ATTRIBUTES.forEach(function(aFeature) {
- // Use !isNaN as an easy way to ignore sizemode and check for numbers
- if (aFeature in winState && !isNaN(winState[aFeature]))
- features += "," + aFeature + "=" + winState[aFeature];
- });
-
- if (winState.isPrivate) {
- features += ",private";
- }
-
- var window =
- Services.ww.openWindow(null, this._prefBranch.getCharPref("chromeURL"),
- "_blank", features, argString);
-
- do {
- var ID = "window" + Math.random();
- } while (ID in this._statesToRestore);
- this._statesToRestore[(window.__SS_restoreID = ID)] = aState;
-
- return window;
- },
-
- /**
- * Whether or not to resume session, if not recovering from a crash.
- * @returns bool
- */
- _doResumeSession: function ssi_doResumeSession() {
- return this._prefBranch.getIntPref("startup.page") == 3 ||
- this._prefBranch.getBoolPref("sessionstore.resume_session_once");
- },
-
- /**
- * whether the user wants to load any other page at startup
- * (except the homepage) - needed for determining whether to overwrite the current tabs
- * C.f.: nsBrowserContentHandler's defaultArgs implementation.
- * @returns bool
- */
- _isCmdLineEmpty: function ssi_isCmdLineEmpty(aWindow, aState) {
- var pinnedOnly = aState.windows &&
- aState.windows.every(function (win)
- win.tabs.every(function (tab) tab.pinned));
-
- let hasFirstArgument = aWindow.arguments && aWindow.arguments[0];
- if (!pinnedOnly) {
- let defaultArgs = Cc["@mozilla.org/browser/clh;1"].
- getService(Ci.nsIBrowserHandler).defaultArgs;
- if (aWindow.arguments &&
- aWindow.arguments[0] &&
- aWindow.arguments[0] == defaultArgs)
- hasFirstArgument = false;
- }
-
- return !hasFirstArgument;
- },
-
- /**
- * don't save sensitive data if the user doesn't want to
- * (distinguishes between encrypted and non-encrypted sites)
- * @param aIsHTTPS
- * Bool is encrypted
- * @param aUseDefaultPref
- * don't do normal check for deferred
- * @returns bool
- */
- checkPrivacyLevel: function ssi_checkPrivacyLevel(aIsHTTPS, aUseDefaultPref) {
- let pref = "sessionstore.privacy_level";
- // If we're in the process of quitting and we're not autoresuming the session
- // then we should treat it as a deferred session. We have a different privacy
- // pref for that case.
- if (!aUseDefaultPref && this._loadState == STATE_QUITTING && !this._doResumeSession())
- pref = "sessionstore.privacy_level_deferred";
- return this._prefBranch.getIntPref(pref) < (aIsHTTPS ? PRIVACY_ENCRYPTED : PRIVACY_FULL);
- },
-
- /**
- * on popup windows, the XULWindow's attributes seem not to be set correctly
- * we use thus JSDOMWindow attributes for sizemode and normal window attributes
- * (and hope for reasonable values when maximized/minimized - since then
- * outerWidth/outerHeight aren't the dimensions of the restored window)
- * @param aWindow
- * Window reference
- * @param aAttribute
- * String sizemode | width | height | other window attribute
- * @returns string
- */
- _getWindowDimension: function ssi_getWindowDimension(aWindow, aAttribute) {
- if (aAttribute == "sizemode") {
- switch (aWindow.windowState) {
- case aWindow.STATE_FULLSCREEN:
- case aWindow.STATE_MAXIMIZED:
- return "maximized";
- case aWindow.STATE_MINIMIZED:
- return "minimized";
- default:
- return "normal";
- }
- }
-
- var dimension;
- switch (aAttribute) {
- case "width":
- dimension = aWindow.outerWidth;
- break;
- case "height":
- dimension = aWindow.outerHeight;
- break;
- default:
- dimension = aAttribute in aWindow ? aWindow[aAttribute] : "";
- break;
- }
-
- if (aWindow.windowState == aWindow.STATE_NORMAL) {
- return dimension;
- }
- return aWindow.document.documentElement.getAttribute(aAttribute) || dimension;
- },
-
- /**
- * Get nsIURI from string
- * @param string
- * @returns nsIURI
- */
- _getURIFromString: function ssi_getURIFromString(aString) {
- return Services.io.newURI(aString, null, null);
- },
-
- /**
- * @param aState is a session state
- * @param aRecentCrashes is the number of consecutive crashes
- * @returns whether a restore page will be needed for the session state
- */
- _needsRestorePage: function ssi_needsRestorePage(aState, aRecentCrashes) {
- const SIX_HOURS_IN_MS = 6 * 60 * 60 * 1000;
-
- // don't display the page when there's nothing to restore
- let winData = aState.windows || null;
- if (!winData || winData.length == 0)
- return false;
-
- // don't wrap a single about:sessionrestore page
- if (winData.length == 1 && winData[0].tabs &&
- winData[0].tabs.length == 1 && winData[0].tabs[0].entries &&
- winData[0].tabs[0].entries.length == 1 &&
- winData[0].tabs[0].entries[0].url == "about:sessionrestore")
- return false;
-
- // don't automatically restore in Safe Mode
- if (Services.appinfo.inSafeMode)
- return true;
-
- let max_resumed_crashes =
- this._prefBranch.getIntPref("sessionstore.max_resumed_crashes");
- let sessionAge = aState.session && aState.session.lastUpdate &&
- (Date.now() - aState.session.lastUpdate);
-
- return max_resumed_crashes != -1 &&
- (aRecentCrashes > max_resumed_crashes ||
- sessionAge && sessionAge >= SIX_HOURS_IN_MS);
- },
-
- /**
- * Determine if the tab state we're passed is something we should save. This
- * is used when closing a tab or closing a window with a single tab
- *
- * @param aTabState
- * The current tab state
- * @returns boolean
- */
- _shouldSaveTabState: function ssi_shouldSaveTabState(aTabState) {
- // If the tab has only a transient about: history entry, no other
- // session history, and no userTypedValue, then we don't actually want to
- // store this tab's data.
- return aTabState.entries.length &&
- !(aTabState.entries.length == 1 &&
- (aTabState.entries[0].url == "about:blank" ||
- aTabState.entries[0].url == "about:newtab") &&
- !aTabState.userTypedValue);
- },
-
- /**
- * Determine if we can restore history into this tab.
- * This will be false when a tab has been removed (usually between
- * restoreHistoryPrecursor && restoreHistory) or if the tab is still marked
- * as loading.
- *
- * @param aTab
- * @returns boolean
- */
- _canRestoreTabHistory: function ssi_canRestoreTabHistory(aTab) {
- return aTab.parentNode && aTab.linkedBrowser &&
- aTab.linkedBrowser.__SS_tabStillLoading;
- },
-
- /**
- * This is going to take a state as provided at startup (via
- * nsISessionStartup.state) and split it into 2 parts. The first part
- * (defaultState) will be a state that should still be restored at startup,
- * while the second part (state) is a state that should be saved for later.
- * defaultState will be comprised of windows with only pinned tabs, extracted
- * from state. It will contain the cookies that go along with the history
- * entries in those tabs. It will also contain window position information.
- *
- * defaultState will be restored at startup. state will be placed into
- * this._lastSessionState and will be kept in case the user explicitly wants
- * to restore the previous session (publicly exposed as restoreLastSession).
- *
- * @param state
- * The state, presumably from nsISessionStartup.state
- * @returns [defaultState, state]
- */
- _prepDataForDeferredRestore: function ssi_prepDataForDeferredRestore(state) {
- // Make sure that we don't modify the global state as provided by
- // nsSessionStartup.state. Converting the object to a JSON string and
- // parsing it again is the easiest way to do that, although not the most
- // efficient one. Deferred sessions that don't have automatic session
- // restore enabled tend to be a lot smaller though so that this shouldn't
- // be a big perf hit.
- state = JSON.parse(JSON.stringify(state));
-
- let defaultState = { windows: [], selectedWindow: 1 };
-
- state.selectedWindow = state.selectedWindow || 1;
-
- // Look at each window, remove pinned tabs, adjust selectedindex,
- // remove window if necessary.
- for (let wIndex = 0; wIndex < state.windows.length;) {
- let window = state.windows[wIndex];
- window.selected = window.selected || 1;
- // We're going to put the state of the window into this object
- let pinnedWindowState = { tabs: [], cookies: []};
- for (let tIndex = 0; tIndex < window.tabs.length;) {
- if (window.tabs[tIndex].pinned) {
- // Adjust window.selected
- if (tIndex + 1 < window.selected)
- window.selected -= 1;
- else if (tIndex + 1 == window.selected)
- pinnedWindowState.selected = pinnedWindowState.tabs.length + 2;
- // + 2 because the tab isn't actually in the array yet
-
- // Now add the pinned tab to our window
- pinnedWindowState.tabs =
- pinnedWindowState.tabs.concat(window.tabs.splice(tIndex, 1));
- // We don't want to increment tIndex here.
- continue;
- }
- tIndex++;
- }
-
- // At this point the window in the state object has been modified (or not)
- // We want to build the rest of this new window object if we have pinnedTabs.
- if (pinnedWindowState.tabs.length) {
- // First get the other attributes off the window
- WINDOW_ATTRIBUTES.forEach(function(attr) {
- if (attr in window) {
- pinnedWindowState[attr] = window[attr];
- delete window[attr];
- }
- });
- // We're just copying position data into the pinned window.
- // Not copying over:
- // - _closedTabs
- // - extData
- // - isPopup
- // - hidden
-
- // Assign a unique ID to correlate the window to be opened with the
- // remaining data
- window.__lastSessionWindowID = pinnedWindowState.__lastSessionWindowID
- = "" + Date.now() + Math.random();
-
- // Extract the cookies that belong with each pinned tab
- this._splitCookiesFromWindow(window, pinnedWindowState);
-
- // Actually add this window to our defaultState
- defaultState.windows.push(pinnedWindowState);
- // Remove the window from the state if it doesn't have any tabs
- if (!window.tabs.length) {
- if (wIndex + 1 <= state.selectedWindow)
- state.selectedWindow -= 1;
- else if (wIndex + 1 == state.selectedWindow)
- defaultState.selectedIndex = defaultState.windows.length + 1;
-
- state.windows.splice(wIndex, 1);
- // We don't want to increment wIndex here.
- continue;
- }
-
-
- }
- wIndex++;
- }
-
- return [defaultState, state];
- },
-
- /**
- * Splits out the cookies from aWinState into aTargetWinState based on the
- * tabs that are in aTargetWinState.
- * This alters the state of aWinState and aTargetWinState.
- */
- _splitCookiesFromWindow:
- function ssi_splitCookiesFromWindow(aWinState, aTargetWinState) {
- if (!aWinState.cookies || !aWinState.cookies.length)
- return;
-
- // Get the hosts for history entries in aTargetWinState
- let cookieHosts = {};
- aTargetWinState.tabs.forEach(function(tab) {
- tab.entries.forEach(function(entry) {
- this._extractHostsForCookiesFromEntry(entry, cookieHosts, false);
- }, this);
- }, this);
-
- // By creating a regex we reduce overhead and there is only one loop pass
- // through either array (cookieHosts and aWinState.cookies).
- let hosts = Object.keys(cookieHosts).join("|").replace("\\.", "\\.", "g");
- // If we don't actually have any hosts, then we don't want to do anything.
- if (!hosts.length)
- return;
- let cookieRegex = new RegExp(".*(" + hosts + ")");
- for (let cIndex = 0; cIndex < aWinState.cookies.length;) {
- if (cookieRegex.test(aWinState.cookies[cIndex].host)) {
- aTargetWinState.cookies =
- aTargetWinState.cookies.concat(aWinState.cookies.splice(cIndex, 1));
- continue;
- }
- cIndex++;
- }
- },
-
- /**
- * Converts a JavaScript object into a JSON string
- * (see http://www.json.org/ for more information).
- *
- * The inverse operation consists of JSON.parse(JSON_string).
- *
- * @param aJSObject is the object to be converted
- * @returns the object's JSON representation
- */
- _toJSONString: function ssi_toJSONString(aJSObject) {
- return JSON.stringify(aJSObject);
- },
-
- _sendRestoreCompletedNotifications: function ssi_sendRestoreCompletedNotifications() {
- // not all windows restored, yet
- if (this._restoreCount > 1) {
- this._restoreCount--;
- return;
- }
-
- // observers were already notified
- if (this._restoreCount == -1)
- return;
-
- // This was the last window restored at startup, notify observers.
- Services.obs.notifyObservers(null,
- this._browserSetState ? NOTIFY_BROWSER_STATE_RESTORED : NOTIFY_WINDOWS_RESTORED,
- "");
-
- this._browserSetState = false;
- this._restoreCount = -1;
- },
-
- /**
- * Set the given window's busy state
- * @param aWindow the window
- * @param aValue the window's busy state
- */
- _setWindowStateBusyValue:
- function ssi_changeWindowStateBusyValue(aWindow, aValue) {
-
- this._windows[aWindow.__SSi].busy = aValue;
-
- // Keep the to-be-restored state in sync because that is returned by
- // getWindowState() as long as the window isn't loaded, yet.
- if (!this._isWindowLoaded(aWindow)) {
- let stateToRestore = this._statesToRestore[aWindow.__SS_restoreID].windows[0];
- stateToRestore.busy = aValue;
- }
- },
-
- /**
- * Set the given window's state to 'not busy'.
- * @param aWindow the window
- */
- _setWindowStateReady: function ssi_setWindowStateReady(aWindow) {
- this._setWindowStateBusyValue(aWindow, false);
- this._sendWindowStateEvent(aWindow, "Ready");
- },
-
- /**
- * Set the given window's state to 'busy'.
- * @param aWindow the window
- */
- _setWindowStateBusy: function ssi_setWindowStateBusy(aWindow) {
- this._setWindowStateBusyValue(aWindow, true);
- this._sendWindowStateEvent(aWindow, "Busy");
- },
-
- /**
- * Dispatch an SSWindowState_____ event for the given window.
- * @param aWindow the window
- * @param aType the type of event, SSWindowState will be prepended to this string
- */
- _sendWindowStateEvent: function ssi_sendWindowStateEvent(aWindow, aType) {
- let event = aWindow.document.createEvent("Events");
- event.initEvent("SSWindowState" + aType, true, false);
- aWindow.dispatchEvent(event);
- },
-
- /**
- * Dispatch the SSTabRestored event for the given tab.
- * @param aTab the which has been restored
- */
- _sendTabRestoredNotification: function ssi_sendTabRestoredNotification(aTab) {
- let event = aTab.ownerDocument.createEvent("Events");
- event.initEvent("SSTabRestored", true, false);
- aTab.dispatchEvent(event);
- },
-
- /**
- * @param aWindow
- * Window reference
- * @returns whether this window's data is still cached in _statesToRestore
- * because it's not fully loaded yet
- */
- _isWindowLoaded: function ssi_isWindowLoaded(aWindow) {
- return !aWindow.__SS_restoreID;
- },
-
- /**
- * Replace "Loading..." with the tab label (with minimal side-effects)
- * @param aString is the string the title is stored in
- * @param aTabbrowser is a tabbrowser object, containing aTab
- * @param aTab is the tab whose title we're updating & using
- *
- * @returns aString that has been updated with the new title
- */
- _replaceLoadingTitle : function ssi_replaceLoadingTitle(aString, aTabbrowser, aTab) {
- if (aString == aTabbrowser.mStringBundle.getString("tabs.connecting")) {
- aTabbrowser.setTabTitle(aTab);
- [aString, aTab.label] = [aTab.label, aString];
- }
- return aString;
- },
-
- /**
- * Resize this._closedWindows to the value of the pref, except in the case
- * where we don't have any non-popup windows on Windows and Linux. Then we must
- * resize such that we have at least one non-popup window.
- */
- _capClosedWindows : function ssi_capClosedWindows() {
- if (this._closedWindows.length <= this._max_windows_undo)
- return;
- let spliceTo = this._max_windows_undo;
-#ifndef XP_MACOSX
- let normalWindowIndex = 0;
- // try to find a non-popup window in this._closedWindows
- while (normalWindowIndex < this._closedWindows.length &&
- !!this._closedWindows[normalWindowIndex].isPopup)
- normalWindowIndex++;
- if (normalWindowIndex >= this._max_windows_undo)
- spliceTo = normalWindowIndex + 1;
-#endif
- this._closedWindows.splice(spliceTo, this._closedWindows.length);
- },
-
- _clearRestoringWindows: function ssi_clearRestoringWindows() {
- for (let i = 0; i < this._closedWindows.length; i++) {
- delete this._closedWindows[i]._shouldRestore;
- }
- },
-
- /**
- * Reset state to prepare for a new session state to be restored.
- */
- _resetRestoringState: function ssi_initRestoringState() {
- TabRestoreQueue.reset();
- this._tabsRestoringCount = 0;
- },
-
- /**
- * Reset the restoring state for a particular tab. This will be called when
- * removing a tab or when a tab needs to be reset (it's being overwritten).
- *
- * @param aTab
- * The tab that will be "reset"
- */
- _resetTabRestoringState: function ssi_resetTabRestoringState(aTab) {
- let window = aTab.ownerDocument.defaultView;
- let browser = aTab.linkedBrowser;
-
- // Keep the tab's previous state for later in this method
- let previousState = browser.__SS_restoreState;
-
- // The browser is no longer in any sort of restoring state.
- delete browser.__SS_restoreState;
-
- aTab.removeAttribute("pending");
- browser.removeAttribute("pending");
-
- // We want to decrement window.__SS_tabsToRestore here so that we always
- // decrement it AFTER a tab is done restoring or when a tab gets "reset".
- window.__SS_tabsToRestore--;
-
- // Remove the progress listener if we should.
- this._removeTabsProgressListener(window);
-
- if (previousState == TAB_STATE_RESTORING) {
- if (this._tabsRestoringCount)
- this._tabsRestoringCount--;
- }
- else if (previousState == TAB_STATE_NEEDS_RESTORE) {
- // Make sure the session history listener is removed. This is normally
- // done in restoreTab, but this tab is being removed before that gets called.
- this._removeSHistoryListener(aTab);
-
- // Make sure that the tab is removed from the list of tabs to restore.
- // Again, this is normally done in restoreTab, but that isn't being called
- // for this tab.
- TabRestoreQueue.remove(aTab);
- }
- },
-
- /**
- * Add the tabs progress listener to the window if it isn't already
- *
- * @param aWindow
- * The window to add our progress listener to
- */
- _ensureTabsProgressListener: function ssi_ensureTabsProgressListener(aWindow) {
- let tabbrowser = aWindow.gBrowser;
- if (tabbrowser.mTabsProgressListeners.indexOf(gRestoreTabsProgressListener) == -1)
- tabbrowser.addTabsProgressListener(gRestoreTabsProgressListener);
- },
-
- /**
- * Attempt to remove the tabs progress listener from the window.
- *
- * @param aWindow
- * The window from which to remove our progress listener from
- */
- _removeTabsProgressListener: function ssi_removeTabsProgressListener(aWindow) {
- // If there are no tabs left to restore (or restoring) in this window, then
- // we can safely remove the progress listener from this window.
- if (!aWindow.__SS_tabsToRestore)
- aWindow.gBrowser.removeTabsProgressListener(gRestoreTabsProgressListener);
- },
-
- /**
- * Remove the session history listener from the tab's browser if there is one.
- *
- * @param aTab
- * The tab who's browser to remove the listener
- */
- _removeSHistoryListener: function ssi_removeSHistoryListener(aTab) {
- let browser = aTab.linkedBrowser;
- if (browser.__SS_shistoryListener) {
- browser.webNavigation.sessionHistory.
- removeSHistoryListener(browser.__SS_shistoryListener);
- delete browser.__SS_shistoryListener;
- }
- }
-};
-
-/**
- * Priority queue that keeps track of a list of tabs to restore and returns
- * the tab we should restore next, based on priority rules. We decide between
- * pinned, visible and hidden tabs in that and FIFO order. Hidden tabs are only
- * restored with restore_hidden_tabs=true.
- */
-var TabRestoreQueue = {
- // The separate buckets used to store tabs.
- tabs: {priority: [], visible: [], hidden: []},
-
- // Preferences used by the TabRestoreQueue to determine which tabs
- // are restored automatically and which tabs will be on-demand.
- prefs: {
- // Lazy getter that returns whether tabs are restored on demand.
- get restoreOnDemand() {
- let updateValue = () => {
- let value = Services.prefs.getBoolPref(PREF);
- let definition = {value: value, configurable: true};
- Object.defineProperty(this, "restoreOnDemand", definition);
- return value;
- }
-
- const PREF = "browser.sessionstore.restore_on_demand";
- Services.prefs.addObserver(PREF, updateValue, false);
- return updateValue();
- },
-
- // Lazy getter that returns whether pinned tabs are restored on demand.
- get restorePinnedTabsOnDemand() {
- let updateValue = () => {
- let value = Services.prefs.getBoolPref(PREF);
- let definition = {value: value, configurable: true};
- Object.defineProperty(this, "restorePinnedTabsOnDemand", definition);
- return value;
- }
-
- const PREF = "browser.sessionstore.restore_pinned_tabs_on_demand";
- Services.prefs.addObserver(PREF, updateValue, false);
- return updateValue();
- },
-
- // Lazy getter that returns whether we should restore hidden tabs.
- get restoreHiddenTabs() {
- let updateValue = () => {
- let value = Services.prefs.getBoolPref(PREF);
- let definition = {value: value, configurable: true};
- Object.defineProperty(this, "restoreHiddenTabs", definition);
- return value;
- }
-
- const PREF = "browser.sessionstore.restore_hidden_tabs";
- Services.prefs.addObserver(PREF, updateValue, false);
- return updateValue();
- }
- },
-
- // Resets the queue and removes all tabs.
- reset: function () {
- this.tabs = {priority: [], visible: [], hidden: []};
- },
-
- // Adds a tab to the queue and determines its priority bucket.
- add: function (tab) {
- let {priority, hidden, visible} = this.tabs;
-
- if (tab.pinned) {
- priority.push(tab);
- } else if (tab.hidden) {
- hidden.push(tab);
- } else {
- visible.push(tab);
- }
- },
-
- // Removes a given tab from the queue, if it's in there.
- remove: function (tab) {
- let {priority, hidden, visible} = this.tabs;
-
- // We'll always check priority first since we don't
- // have an indicator if a tab will be there or not.
- let set = priority;
- let index = set.indexOf(tab);
-
- if (index == -1) {
- set = tab.hidden ? hidden : visible;
- index = set.indexOf(tab);
- }
-
- if (index > -1) {
- set.splice(index, 1);
- }
- },
-
- // Returns and removes the tab with the highest priority.
- shift: function () {
- let set;
- let {priority, hidden, visible} = this.tabs;
-
- let {restoreOnDemand, restorePinnedTabsOnDemand} = this.prefs;
- let restorePinned = !(restoreOnDemand && restorePinnedTabsOnDemand);
- if (restorePinned && priority.length) {
- set = priority;
- } else if (!restoreOnDemand) {
- if (visible.length) {
- set = visible;
- } else if (this.prefs.restoreHiddenTabs && hidden.length) {
- set = hidden;
- }
- }
-
- return set && set.shift();
- },
-
- // Moves a given tab from the 'hidden' to the 'visible' bucket.
- hiddenToVisible: function (tab) {
- let {hidden, visible} = this.tabs;
- let index = hidden.indexOf(tab);
-
- if (index > -1) {
- hidden.splice(index, 1);
- visible.push(tab);
- } else {
- throw new Error("restore queue: hidden tab not found");
- }
- },
-
- // Moves a given tab from the 'visible' to the 'hidden' bucket.
- visibleToHidden: function (tab) {
- let {visible, hidden} = this.tabs;
- let index = visible.indexOf(tab);
-
- if (index > -1) {
- visible.splice(index, 1);
- hidden.push(tab);
- } else {
- throw new Error("restore queue: visible tab not found");
- }
- }
-};
-
-// A map storing a closed window's state data until it goes aways (is GC'ed).
-// This ensures that API clients can still read (but not write) states of
-// windows they still hold a reference to but we don't.
-var DyingWindowCache = {
- _data: new WeakMap(),
-
- has: function (window) {
- return this._data.has(window);
- },
-
- get: function (window) {
- return this._data.get(window);
- },
-
- set: function (window, data) {
- this._data.set(window, data);
- },
-
- remove: function (window) {
- this._data.delete(window);
- }
-};
-
-// A set of tab attributes to persist. We will read a given list of tab
-// attributes when collecting tab data and will re-set those attributes when
-// the given tab data is restored to a new tab.
-var TabAttributes = {
- _attrs: new Set(),
-
- // We never want to directly read or write those attributes.
- // 'image' should not be accessed directly but handled by using the
- // gBrowser.getIcon()/setIcon() methods.
- // 'pending' is used internal by sessionstore and managed accordingly.
- // 'skipbackgroundnotify' is used internal by tabbrowser.xml.
- _skipAttrs: new Set(["image", "pending", "skipbackgroundnotify"]),
-
- persist: function (name) {
- if (this._attrs.has(name) || this._skipAttrs.has(name)) {
- return false;
- }
-
- this._attrs.add(name);
- return true;
- },
-
- get: function (tab) {
- let data = {};
-
- for (let name of this._attrs) {
- if (tab.hasAttribute(name)) {
- data[name] = tab.getAttribute(name);
- }
- }
-
- return data;
- },
-
- set: function (tab, data = {}) {
- // Clear attributes.
- for (let name of this._attrs) {
- tab.removeAttribute(name);
- }
-
- // Set attributes.
- for (let name in data) {
- tab.setAttribute(name, data[name]);
- }
- }
-};
-
-// This is used to help meter the number of restoring tabs. This is the control
-// point for telling the next tab to restore. It gets attached to each gBrowser
-// via gBrowser.addTabsProgressListener
-var gRestoreTabsProgressListener = {
- onStateChange: function(aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) {
- // Ignore state changes on browsers that we've already restored and state
- // changes that aren't applicable.
- if (aBrowser.__SS_restoreState &&
- aBrowser.__SS_restoreState == TAB_STATE_RESTORING &&
- aStateFlags & Ci.nsIWebProgressListener.STATE_STOP &&
- aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK &&
- aStateFlags & Ci.nsIWebProgressListener.STATE_IS_WINDOW) {
- // We need to reset the tab before starting the next restore.
- let win = aBrowser.ownerDocument.defaultView;
- let tab = win.gBrowser.getTabForBrowser(aBrowser);
- SessionStoreInternal._resetTabRestoringState(tab);
- SessionStoreInternal.restoreNextTab();
- }
- }
-};
-
-// A SessionStoreSHistoryListener will be attached to each browser before it is
-// restored. We need to catch reloads that occur before the tab is restored
-// because otherwise, docShell will reload an old URI (usually about:blank).
-function SessionStoreSHistoryListener(aTab) {
- this.tab = aTab;
-}
-SessionStoreSHistoryListener.prototype = {
- QueryInterface: XPCOMUtils.generateQI([
- Ci.nsISHistoryListener,
- Ci.nsISupportsWeakReference
- ]),
- browser: null,
- OnHistoryNewEntry: function(aNewURI) { },
- OnHistoryGoBack: function(aBackURI) { return true; },
- OnHistoryGoForward: function(aForwardURI) { return true; },
- OnHistoryGotoIndex: function(aIndex, aGotoURI) { return true; },
- OnHistoryPurge: function(aNumEntries) { return true; },
- OnHistoryReload: function(aReloadURI, aReloadFlags) {
- // On reload, we want to make sure that session history loads the right
- // URI. In order to do that, we will juet call restoreTab. That will remove
- // the history listener and load the right URI.
- SessionStoreInternal.restoreTab(this.tab);
- // Returning false will stop the load that docshell is attempting.
- return false;
- }
-}
-
-// See toolkit/forgetaboutsite/ForgetAboutSite.jsm
-String.prototype.hasRootDomain = function hasRootDomain(aDomain) {
- let index = this.indexOf(aDomain);
- if (index == -1)
- return false;
-
- if (this == aDomain)
- return true;
-
- let prevChar = this[index - 1];
- return (index == (this.length - aDomain.length)) &&
- (prevChar == "." || prevChar == "/");
-}
diff --git a/components/sessionstore/XPathGenerator.jsm b/components/sessionstore/XPathGenerator.jsm
deleted file mode 100644
index 83ff2b8..0000000
--- a/components/sessionstore/XPathGenerator.jsm
+++ /dev/null
@@ -1,97 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-this.EXPORTED_SYMBOLS = ["XPathGenerator"];
-
-this.XPathGenerator = {
- // these two hashes should be kept in sync
- namespaceURIs: { "xhtml": "http://www.w3.org/1999/xhtml" },
- namespacePrefixes: { "http://www.w3.org/1999/xhtml": "xhtml" },
-
- /**
- * Generates an approximate XPath query to an (X)HTML node
- */
- generate: function sss_xph_generate(aNode) {
- // have we reached the document node already?
- if (!aNode.parentNode)
- return "";
-
- // Access localName, namespaceURI just once per node since it's expensive.
- let nNamespaceURI = aNode.namespaceURI;
- let nLocalName = aNode.localName;
-
- let prefix = this.namespacePrefixes[nNamespaceURI] || null;
- let tag = (prefix ? prefix + ":" : "") + this.escapeName(nLocalName);
-
- // stop once we've found a tag with an ID
- if (aNode.id)
- return "//" + tag + "[@id=" + this.quoteArgument(aNode.id) + "]";
-
- // count the number of previous sibling nodes of the same tag
- // (and possible also the same name)
- let count = 0;
- let nName = aNode.name || null;
- for (let n = aNode; (n = n.previousSibling); )
- if (n.localName == nLocalName && n.namespaceURI == nNamespaceURI &&
- (!nName || n.name == nName))
- count++;
-
- // recurse until hitting either the document node or an ID'd node
- return this.generate(aNode.parentNode) + "/" + tag +
- (nName ? "[@name=" + this.quoteArgument(nName) + "]" : "") +
- (count ? "[" + (count + 1) + "]" : "");
- },
-
- /**
- * Resolves an XPath query generated by XPathGenerator.generate
- */
- resolve: function sss_xph_resolve(aDocument, aQuery) {
- let xptype = Components.interfaces.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE;
- return aDocument.evaluate(aQuery, aDocument, this.resolveNS, xptype, null).singleNodeValue;
- },
-
- /**
- * Namespace resolver for the above XPath resolver
- */
- resolveNS: function sss_xph_resolveNS(aPrefix) {
- return XPathGenerator.namespaceURIs[aPrefix] || null;
- },
-
- /**
- * @returns valid XPath for the given node (usually just the local name itself)
- */
- escapeName: function sss_xph_escapeName(aName) {
- // we can't just use the node's local name, if it contains
- // special characters (cf. bug 485482)
- return /^\w+$/.test(aName) ? aName :
- "*[local-name()=" + this.quoteArgument(aName) + "]";
- },
-
- /**
- * @returns a properly quoted string to insert into an XPath query
- */
- quoteArgument: function sss_xph_quoteArgument(aArg) {
- return !/'/.test(aArg) ? "'" + aArg + "'" :
- !/"/.test(aArg) ? '"' + aArg + '"' :
- "concat('" + aArg.replace(/'+/g, "',\"$&\",'") + "')";
- },
-
- /**
- * @returns an XPath query to all savable form field nodes
- */
- get restorableFormNodes() {
- // for a comprehensive list of all available <INPUT> types see
- // http://mxr.mozilla.org/mozilla-central/search?string=kInputTypeTable
- let ignoreTypes = ["password", "hidden", "button", "image", "submit", "reset"];
- // XXXzeniko work-around until lower-case has been implemented (bug 398389)
- let toLowerCase = '"ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz"';
- let ignore = "not(translate(@type, " + toLowerCase + ")='" +
- ignoreTypes.join("' or translate(@type, " + toLowerCase + ")='") + "')";
- let formNodesXPath = "//textarea|//select|//xhtml:textarea|//xhtml:select|" +
- "//input[" + ignore + "]|//xhtml:input[" + ignore + "]";
-
- delete this.restorableFormNodes;
- return (this.restorableFormNodes = formNodesXPath);
- }
-};
diff --git a/components/sessionstore/_SessionFile.jsm b/components/sessionstore/_SessionFile.jsm
deleted file mode 100644
index 62b4d16..0000000
--- a/components/sessionstore/_SessionFile.jsm
+++ /dev/null
@@ -1,314 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-this.EXPORTED_SYMBOLS = ["_SessionFile"];
-
-/**
- * Implementation of all the disk I/O required by the session store.
- * This is a private API, meant to be used only by the session store.
- * It will change. Do not use it for any other purpose.
- *
- * Note that this module implicitly depends on one of two things:
- * 1. either the asynchronous file I/O system enqueues its requests
- * and never attempts to simultaneously execute two I/O requests on
- * the files used by this module from two distinct threads; or
- * 2. the clients of this API are well-behaved and do not place
- * concurrent requests to the files used by this module.
- *
- * Otherwise, we could encounter bugs, especially under Windows,
- * e.g. if a request attempts to write sessionstore.js while
- * another attempts to copy that file.
- *
- * This implementation uses OS.File, which guarantees property 1.
- */
-
-const Cu = Components.utils;
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/osfile.jsm");
-Cu.import("resource://gre/modules/Promise.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
- "resource://gre/modules/NetUtil.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
- "resource://gre/modules/FileUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "Task",
- "resource://gre/modules/Task.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "console",
- "resource://gre/modules/Console.jsm");
-
-// An encoder to UTF-8.
-XPCOMUtils.defineLazyGetter(this, "gEncoder", function () {
- return new TextEncoder();
-});
-// A decoder.
-XPCOMUtils.defineLazyGetter(this, "gDecoder", function () {
- return new TextDecoder();
-});
-
-this._SessionFile = {
- /**
- * A promise fulfilled once initialization (either synchronous or
- * asynchronous) is complete.
- */
- promiseInitialized: function SessionFile_initialized() {
- return SessionFileInternal.promiseInitialized;
- },
- /**
- * Read the contents of the session file, asynchronously.
- */
- read: function SessionFile_read() {
- return SessionFileInternal.read();
- },
- /**
- * Read the contents of the session file, synchronously.
- */
- syncRead: function SessionFile_syncRead() {
- return SessionFileInternal.syncRead();
- },
- /**
- * Write the contents of the session file, asynchronously.
- */
- write: function SessionFile_write(aData) {
- return SessionFileInternal.write(aData);
- },
- /**
- * Create a backup copy, asynchronously.
- */
- createBackupCopy: function SessionFile_createBackupCopy() {
- return SessionFileInternal.createBackupCopy();
- },
- /**
- * Wipe the contents of the session file, asynchronously.
- */
- wipe: function SessionFile_wipe() {
- return SessionFileInternal.wipe();
- }
-};
-
-Object.freeze(_SessionFile);
-
-/**
- * Utilities for dealing with promises and Task.jsm
- */
-const TaskUtils = {
- /**
- * Add logging to a promise.
- *
- * @param {Promise} promise
- * @return {Promise} A promise behaving as |promise|, but with additional
- * logging in case of uncaught error.
- */
- captureErrors: function captureErrors(promise) {
- return promise.then(
- null,
- function onError(reason) {
- console.error("Uncaught asynchronous error:", reason);
- throw reason;
- }
- );
- },
- /**
- * Spawn a new Task from a generator.
- *
- * This function behaves as |Task.spawn|, with the exception that it
- * adds logging in case of uncaught error. For more information, see
- * the documentation of |Task.jsm|.
- *
- * @param {generator} gen Some generator.
- * @return {Promise} A promise built from |gen|, with the same semantics
- * as |Task.spawn(gen)|.
- */
- spawn: function spawn(gen) {
- return this.captureErrors(Task.spawn(gen));
- }
-};
-
-var SessionFileInternal = {
- /**
- * A promise fulfilled once initialization is complete
- */
- promiseInitialized: Promise.defer(),
-
- /**
- * The path to sessionstore.js
- */
- path: OS.Path.join(OS.Constants.Path.profileDir, "sessionstore.js"),
-
- /**
- * The path to sessionstore.bak
- */
- backupPath: OS.Path.join(OS.Constants.Path.profileDir, "sessionstore.bak"),
-
- /**
- * Utility function to safely read a file synchronously.
- * @param aPath
- * A path to read the file from.
- * @returns string if successful, undefined otherwise.
- */
- readAuxSync: function ssfi_readAuxSync(aPath) {
- let text;
- try {
- let file = new FileUtils.File(aPath);
- let chan = NetUtil.newChannel({
- uri: NetUtil.newURI(file),
- loadUsingSystemPrincipal: true
- });
- let stream = chan.open();
- text = NetUtil.readInputStreamToString(stream, stream.available(),
- {charset: "utf-8"});
- } catch (e if e.result == Components.results.NS_ERROR_FILE_NOT_FOUND) {
- // Ignore exceptions about non-existent files.
- } catch (ex) {
- // Any other error.
- console.error("Uncaught error:", ex);
- } finally {
- return text;
- }
- },
-
- /**
- * Read the sessionstore file synchronously.
- *
- * This function is meant to serve as a fallback in case of race
- * between a synchronous usage of the API and asynchronous
- * initialization.
- *
- * In case if sessionstore.js file does not exist or is corrupted (something
- * happened between backup and write), attempt to read the sessionstore.bak
- * instead.
- */
- syncRead: function ssfi_syncRead() {
- // First read the sessionstore.js.
- let text = this.readAuxSync(this.path);
- if (typeof text === "undefined") {
- // If sessionstore.js does not exist or is corrupted, read sessionstore.bak.
- text = this.readAuxSync(this.backupPath);
- }
- return text || "";
- },
-
- /**
- * Utility function to safely read a file asynchronously.
- * @param aPath
- * A path to read the file from.
- * @param aReadOptions
- * Read operation options.
- * |outExecutionDuration| option will be reused and can be
- * incrementally updated by the worker process.
- * @returns string if successful, undefined otherwise.
- */
- readAux: function ssfi_readAux(aPath, aReadOptions) {
- let self = this;
- return TaskUtils.spawn(function () {
- let text;
- try {
- let bytes = yield OS.File.read(aPath, undefined, aReadOptions);
- text = gDecoder.decode(bytes);
- } catch (ex if self._isNoSuchFile(ex)) {
- // Ignore exceptions about non-existent files.
- } catch (ex) {
- // Any other error.
- console.error("Uncaught error - with the file: " + self.path, ex);
- }
- throw new Task.Result(text);
- });
- },
-
- /**
- * Read the sessionstore file asynchronously.
- *
- * In case sessionstore.js file does not exist or is corrupted (something
- * happened between backup and write), attempt to read the sessionstore.bak
- * instead.
- */
- read: function ssfi_read() {
- let self = this;
- return TaskUtils.spawn(function task() {
- // Specify |outExecutionDuration| option to hold the combined duration of
- // the asynchronous reads off the main thread (of both sessionstore.js and
- // sessionstore.bak, if necessary). If sessionstore.js does not exist or
- // is corrupted, |outExecutionDuration| will register the time it took to
- // attempt to read the file. It will then be subsequently incremented by
- // the read time of sessionsore.bak.
- let readOptions = {
- outExecutionDuration: null
- };
- // First read the sessionstore.js.
- let text = yield self.readAux(self.path, readOptions);
- if (typeof text === "undefined") {
- // If sessionstore.js does not exist or is corrupted, read the
- // sessionstore.bak.
- text = yield self.readAux(self.backupPath, readOptions);
- }
- // Return either the content of the sessionstore.bak if it was read
- // successfully or an empty string otherwise.
- throw new Task.Result(text || "");
- });
- },
-
- write: function ssfi_write(aData) {
- let refObj = {};
- let self = this;
- return TaskUtils.spawn(function task() {
- let bytes = gEncoder.encode(aData);
-
- try {
- let promise = OS.File.writeAtomic(self.path, bytes, {tmpPath: self.path + ".tmp"});
- yield promise;
- } catch (ex) {
- console.error("Could not write session state file: " + self.path, ex);
- }
- });
- },
-
- createBackupCopy: function ssfi_createBackupCopy() {
- let backupCopyOptions = {
- outExecutionDuration: null
- };
- let self = this;
- return TaskUtils.spawn(function task() {
- try {
- yield OS.File.move(self.path, self.backupPath, backupCopyOptions);
- } catch (ex if self._isNoSuchFile(ex)) {
- // Ignore exceptions about non-existent files.
- } catch (ex) {
- console.error("Could not backup session state file: " + self.path, ex);
- throw ex;
- }
- });
- },
-
- wipe: function ssfi_wipe() {
- let self = this;
- return TaskUtils.spawn(function task() {
- try {
- yield OS.File.remove(self.path);
- } catch (ex if self._isNoSuchFile(ex)) {
- // Ignore exceptions about non-existent files.
- } catch (ex) {
- console.error("Could not remove session state file: " + self.path, ex);
- throw ex;
- }
-
- try {
- yield OS.File.remove(self.backupPath);
- } catch (ex if self._isNoSuchFile(ex)) {
- // Ignore exceptions about non-existent files.
- } catch (ex) {
- console.error("Could not remove session state backup file: " + self.path, ex);
- throw ex;
- }
- });
- },
-
- _isNoSuchFile: function ssfi_isNoSuchFile(aReason) {
- return aReason instanceof OS.File.Error && aReason.becauseNoSuchFile;
- }
-};
diff --git a/components/sessionstore/content/aboutSessionRestore.js b/components/sessionstore/content/aboutSessionRestore.js
deleted file mode 100644
index 2b6f9ea..0000000
--- a/components/sessionstore/content/aboutSessionRestore.js
+++ /dev/null
@@ -1,320 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-var Cc = Components.classes;
-var Ci = Components.interfaces;
-var Cu = Components.utils;
-
-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) {
- document.getElementById("errorTryAgain").disabled = true;
- return;
- }
-
- // remove unneeded braces (added for compatibility with Firefox 2.0 and 3.0)
- if (sessionData.value.charAt(0) == '(')
- sessionData.value = sessionData.value.slice(1, -1);
- try {
- gStateObject = JSON.parse(sessionData.value);
- }
- catch (exJSON) {
- var s = new Cu.Sandbox("about:blank", {sandboxName: 'aboutSessionRestore'});
- gStateObject = Cu.evalInSandbox("(" + sessionData.value + ")", s);
- // If we couldn't parse the string with JSON.parse originally, make sure
- // that the value in the textbox will be parsable.
- sessionData.value = JSON.stringify(gStateObject);
- }
-
- // 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);
-
- 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 (let tab of 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 = JSON.stringify(gStateObject);
-
- 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.tabs.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.tabs[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:logopage");
- else
- getBrowserWindow().BrowserHome();
-}
-
-function onListClick(aEvent) {
- // don't react to right-clicks
- if (aEvent.button == 2)
- return;
-
- if (!treeView.treeBox) {
- return;
- }
- var cell = treeView.treeBox.getCellAt(aEvent.clientX, aEvent.clientY);
- if (cell.col) {
- // Restore this specific tab in the same window for middle/double/accel clicking
- // on a tab's title.
-#ifdef XP_MACOSX
- let accelKey = aEvent.metaKey;
-#else
- let accelKey = aEvent.ctrlKey;
-#endif
- if ((aEvent.button == 1 || aEvent.button == 0 && aEvent.detail == 2 || accelKey) &&
- cell.col.id == "title" &&
- !treeView.isContainer(cell.row)) {
- restoreSingleTab(cell.row, aEvent.shiftKey);
- aEvent.stopPropagation();
- }
- else if (cell.col.id == "restore")
- toggleRowChecked(cell.row);
- }
-}
-
-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 (let tab of 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];
- // ensure tab would be visible on the tabstrip.
- tabState.hidden = false;
- ss.setTabState(newTab, JSON.stringify(tabState));
-
- // 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 = {
- 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; },
- canDrop: function(idx, orientation, dt) { 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)
- return this.getLevel(t) == thisLevel;
- return false;
- },
-
- toggleOpenState: function(idx) {
- if (!this.isContainer(idx))
- return;
- var item = gTreeData[idx];
- if (item.open) {
- // remove this window's tab rows from the view
- var thisLevel = this.getLevel(idx);
- for (var t = idx + 1; t < gTreeData.length && 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) {
- if (column.id == "restore" && this.isContainer(idx) && gTreeData[idx].checked === 0)
- return "partial";
- if (column.id == "title")
- return this.getImageSrc(idx, column) ? "icon" : "noicon";
-
- return "";
- },
-
- getRowProperties: function(idx) {
- var winState = gTreeData[idx].parent || gTreeData[idx];
- if (winState.ix % 2 != 0)
- return "alternate";
-
- return "";
- },
-
- 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) { return ""; }
-};
diff --git a/components/sessionstore/content/aboutSessionRestore.xhtml b/components/sessionstore/content/aboutSessionRestore.xhtml
deleted file mode 100644
index 6b22250..0000000
--- a/components/sessionstore/content/aboutSessionRestore.xhtml
+++ /dev/null
@@ -1,94 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
--->
-<!DOCTYPE html [
- <!ENTITY % htmlDTD PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">
- %htmlDTD;
- <!ENTITY % netErrorDTD SYSTEM "chrome://global/locale/netError.dtd">
- %netErrorDTD;
- <!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd">
- %globalDTD;
- <!ENTITY % restorepageDTD SYSTEM "chrome://browser/locale/aboutSessionRestore.dtd">
- %restorepageDTD;
-]>
-
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title>&restorepage.tabtitle;</title>
- <link rel="stylesheet" href="chrome://global/skin/netError.css" type="text/css" media="all"/>
- <link rel="stylesheet" href="chrome://browser/skin/aboutSessionRestore.css" type="text/css" media="all"/>
- <link rel="icon" type="image/png" href="chrome://global/skin/icons/warning-16.png"/>
-
- <script type="application/javascript;version=1.8" src="chrome://browser/content/aboutSessionRestore.js"/>
- </head>
-
- <body dir="&locale.dir;">
-
- <!-- PAGE CONTAINER (for styling purposes only) -->
- <div id="errorPageContainer">
-
- <!-- Error Title -->
- <div id="errorTitle">
- <h1 id="errorTitleText">&restorepage.errorTitle;</h1>
- </div>
-
- <!-- LONG CONTENT (the section most likely to require scrolling) -->
- <div id="errorLongContent">
-
- <!-- Short Description -->
- <div id="errorShortDesc">
- <p id="errorShortDescText">&restorepage.problemDesc;</p>
- </div>
-
- <!-- Long Description (Note: See netError.dtd for used XHTML tags) -->
- <div id="errorLongDesc">
- <p>&restorepage.tryThis;</p>
- <ul>
- <li>&restorepage.restoreSome;</li>
- <li>&restorepage.startNew;</li>
- </ul>
- </div>
-
- <!-- Short Description -->
- <div id="errorTrailerDesc">
- <tree xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- id="tabList" flex="1" seltype="single" hidecolumnpicker="true"
- onclick="onListClick(event);" onkeydown="onListKeyDown(event);"
- _window_label="&restorepage.windowLabel;">
- <treecols>
- <treecol cycler="true" id="restore" type="checkbox" label="&restorepage.restoreHeader;"/>
- <splitter class="tree-splitter"/>
- <treecol primary="true" id="title" label="&restorepage.listHeader;" flex="1"/>
- </treecols>
- <treechildren flex="1"/>
- </tree>
- </div>
- </div>
-
- <!-- Buttons -->
- <hbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" id="buttons">
-#ifdef XP_UNIX
- <button id="errorCancel" label="&restorepage.closeButton;"
- accesskey="&restorepage.close.access;"
- oncommand="startNewSession();"/>
- <button id="errorTryAgain" label="&restorepage.tryagainButton;"
- accesskey="&restorepage.restore.access;"
- oncommand="restoreSession();"/>
-#else
- <button id="errorTryAgain" label="&restorepage.tryagainButton;"
- accesskey="&restorepage.restore.access;"
- oncommand="restoreSession();"/>
- <button id="errorCancel" label="&restorepage.closeButton;"
- accesskey="&restorepage.close.access;"
- oncommand="startNewSession();"/>
-#endif
- </hbox>
- <!-- holds the session data for when the tab is closed -->
- <input type="text" id="sessionData" style="display: none;"/>
- </div>
-
- </body>
-</html>
diff --git a/components/sessionstore/content/content-sessionStore.js b/components/sessionstore/content/content-sessionStore.js
deleted file mode 100644
index e3e956e..0000000
--- a/components/sessionstore/content/content-sessionStore.js
+++ /dev/null
@@ -1,40 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-function debug(msg) {
- Services.console.logStringMessage("SessionStoreContent: " + msg);
-}
-
-/**
- * Listens for and handles content events that we need for the
- * session store service to be notified of state changes in content.
- */
-var EventListener = {
-
- DOM_EVENTS: [
- "pageshow", "change", "input"
- ],
-
- init: function () {
- this.DOM_EVENTS.forEach(e => addEventListener(e, this, true));
- },
-
- handleEvent: function (event) {
- switch (event.type) {
- case "pageshow":
- if (event.persisted)
- sendAsyncMessage("SessionStore:pageshow");
- break;
- case "input":
- case "change":
- sendAsyncMessage("SessionStore:input");
- break;
- default:
- debug("received unknown event '" + event.type + "'");
- break;
- }
- }
-};
-
-EventListener.init();
diff --git a/components/sessionstore/jar.mn b/components/sessionstore/jar.mn
deleted file mode 100644
index 825b00f..0000000
--- a/components/sessionstore/jar.mn
+++ /dev/null
@@ -1,8 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-browser.jar:
-* content/browser/aboutSessionRestore.xhtml (content/aboutSessionRestore.xhtml)
-* content/browser/aboutSessionRestore.js (content/aboutSessionRestore.js)
- content/browser/content-sessionStore.js (content/content-sessionStore.js)
diff --git a/components/sessionstore/moz.build b/components/sessionstore/moz.build
deleted file mode 100644
index 84278da..0000000
--- a/components/sessionstore/moz.build
+++ /dev/null
@@ -1,29 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-JAR_MANIFESTS += ['jar.mn']
-
-XPIDL_SOURCES += [
- 'nsISessionStartup.idl',
- 'nsISessionStore.idl',
-]
-
-XPIDL_MODULE = 'sessionstore'
-
-EXTRA_COMPONENTS += [
- 'nsSessionStartup.js',
- 'nsSessionStore.js',
- 'nsSessionStore.manifest',
-]
-
-EXTRA_JS_MODULES.sessionstore = [
- '_SessionFile.jsm',
- 'DocumentUtils.jsm',
- 'SessionStorage.jsm',
- 'XPathGenerator.jsm',
-]
-
-EXTRA_PP_JS_MODULES.sessionstore += ['SessionStore.jsm'] \ No newline at end of file
diff --git a/components/sessionstore/nsISessionStartup.idl b/components/sessionstore/nsISessionStartup.idl
deleted file mode 100644
index a8e786d..0000000
--- a/components/sessionstore/nsISessionStartup.idl
+++ /dev/null
@@ -1,59 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-/**
- * nsISessionStore keeps track of the current browsing state - i.e.
- * tab history, cookies, scroll state, form data, POSTDATA and window features
- * - and allows to restore everything into one window.
- */
-
-[scriptable, uuid(51f4b9f0-f3d2-11e2-bb62-2c24dd830245)]
-interface nsISessionStartup: nsISupports
-{
- /**
- * Return a promise that is resolved once initialization
- * is complete.
- */
- readonly attribute jsval onceInitialized;
-
- // Get session state
- readonly attribute jsval state;
-
- /**
- * Determines whether there is a pending session restore and makes sure that
- * we're initialized before returning. If we're not yet this will read the
- * session file synchronously.
- */
- boolean doRestore();
-
- /**
- * Returns whether we will restore a session that ends up replacing the
- * homepage. The browser uses this to not start loading the homepage if
- * we're going to stop its load anyway shortly after.
- *
- * This is meant to be an optimization for the average case that loading the
- * session file finishes before we may want to start loading the default
- * homepage. Should this be called before the session file has been read it
- * will just return false.
- */
- readonly attribute bool willOverrideHomepage;
-
- /**
- * What type of session we're restoring.
- * NO_SESSION There is no data available from the previous session
- * RECOVER_SESSION The last session crashed. It will either be restored or
- * about:sessionrestore will be shown.
- * RESUME_SESSION The previous session should be restored at startup
- * DEFER_SESSION The previous session is fine, but it shouldn't be restored
- * without explicit action (with the exception of pinned tabs)
- */
- const unsigned long NO_SESSION = 0;
- const unsigned long RECOVER_SESSION = 1;
- const unsigned long RESUME_SESSION = 2;
- const unsigned long DEFER_SESSION = 3;
-
- readonly attribute unsigned long sessionType;
-};
diff --git a/components/sessionstore/nsISessionStore.idl b/components/sessionstore/nsISessionStore.idl
deleted file mode 100644
index 0490772..0000000
--- a/components/sessionstore/nsISessionStore.idl
+++ /dev/null
@@ -1,206 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-interface nsIDOMWindow;
-interface nsIDOMNode;
-
-/**
- * nsISessionStore keeps track of the current browsing state - i.e.
- * tab history, cookies, scroll state, form data, POSTDATA and window features
- * - and allows to restore everything into one browser window.
- *
- * The nsISessionStore API operates mostly on browser windows and the tabbrowser
- * tabs contained in them:
- *
- * * "Browser windows" are those DOM windows having loaded
- * chrome://browser/content/browser.xul . From overlays you can just pass the
- * global |window| object to the API, though (or |top| from a sidebar).
- * From elsewhere you can get browser windows through the nsIWindowMediator
- * by looking for "navigator:browser" windows.
- *
- * * "Tabbrowser tabs" are all the child nodes of a browser window's
- * |gBrowser.tabContainer| such as e.g. |gBrowser.selectedTab|.
- */
-
-[scriptable, uuid(43ec216b-f002-4424-bfc5-fc555c87dbc4)]
-interface nsISessionStore : nsISupports
-{
- /**
- * Initialize the service
- */
- jsval init(in nsIDOMWindow aWindow);
-
- /**
- * Is it possible to restore the previous session. Will always be false when
- * in Private Browsing mode.
- */
- attribute boolean canRestoreLastSession;
-
- /**
- * Restore the previous session if possible. This will not overwrite the
- * current session. Instead the previous session will be merged into the
- * current session. Current windows will be reused if they were windows that
- * pinned tabs were previously restored into. New windows will be opened as
- * needed.
- *
- * Note: This will throw if there is no previous state to restore. Check with
- * canRestoreLastSession first to avoid thrown errors.
- */
- void restoreLastSession();
-
- /**
- * Get the current browsing state.
- * @returns a JSON string representing the session state.
- */
- AString getBrowserState();
-
- /**
- * Set the browsing state.
- * This will immediately restore the state of the whole application to the state
- * passed in, *replacing* the current session.
- *
- * @param aState is a JSON string representing the session state.
- */
- void setBrowserState(in AString aState);
-
- /**
- * @param aWindow is the browser window whose state is to be returned.
- *
- * @returns a JSON string representing a session state with only one window.
- */
- AString getWindowState(in nsIDOMWindow aWindow);
-
- /**
- * @param aWindow is the browser window whose state is to be set.
- * @param aState is a JSON string representing a session state.
- * @param aOverwrite boolean overwrite existing tabs
- */
- void setWindowState(in nsIDOMWindow aWindow, in AString aState, in boolean aOverwrite);
-
- /**
- * @param aTab is the tabbrowser tab whose state is to be returned.
- *
- * @returns a JSON string representing the state of the tab
- * (note: doesn't contain cookies - if you need them, use getWindowState instead).
- */
- AString getTabState(in nsIDOMNode aTab);
-
- /**
- * @param aTab is the tabbrowser tab whose state is to be set.
- * @param aState is a JSON string representing a session state.
- */
- void setTabState(in nsIDOMNode aTab, in AString aState);
-
- /**
- * Duplicates a given tab as thoroughly as possible.
- *
- * @param aWindow is the browser window into which the tab will be duplicated.
- * @param aTab is the tabbrowser tab to duplicate (can be from a different window).
- * @param aDelta is the offset to the history entry to load in the duplicated tab.
- * @returns a reference to the newly created tab.
- */
- nsIDOMNode duplicateTab(in nsIDOMWindow aWindow, in nsIDOMNode aTab,
- [optional] in long aDelta);
-
- /**
- * Get the number of restore-able tabs for a browser window
- */
- unsigned long getClosedTabCount(in nsIDOMWindow aWindow);
-
- /**
- * Get closed tab data
- *
- * @param aWindow is the browser window for which to get closed tab data
- * @returns a JSON string representing the list of closed tabs.
- */
- AString getClosedTabData(in nsIDOMWindow aWindow);
-
- /**
- * @param aWindow is the browser window to reopen a closed tab in.
- * @param aIndex is the index of the tab to be restored (FIFO ordered).
- * @returns a reference to the reopened tab.
- */
- nsIDOMNode undoCloseTab(in nsIDOMWindow aWindow, in unsigned long aIndex);
-
- /**
- * @param aWindow is the browser window associated with the closed tab.
- * @param aIndex is the index of the closed tab to be removed (FIFO ordered).
- */
- nsIDOMNode forgetClosedTab(in nsIDOMWindow aWindow, in unsigned long aIndex);
-
- /**
- * Get the number of restore-able windows
- */
- unsigned long getClosedWindowCount();
-
- /**
- * Get closed windows data
- *
- * @returns a JSON string representing the list of closed windows.
- */
- AString getClosedWindowData();
-
- /**
- * @param aIndex is the index of the windows to be restored (FIFO ordered).
- * @returns the nsIDOMWindow object of the reopened window
- */
- nsIDOMWindow undoCloseWindow(in unsigned long aIndex);
-
- /**
- * @param aIndex is the index of the closed window to be removed (FIFO ordered).
- *
- * @throws NS_ERROR_INVALID_ARG
- * when aIndex does not map to a closed window
- */
- nsIDOMNode forgetClosedWindow(in unsigned long aIndex);
-
- /**
- * @param aWindow is the window to get the value for.
- * @param aKey is the value's name.
- *
- * @returns A string value or an empty string if none is set.
- */
- AString getWindowValue(in nsIDOMWindow aWindow, in AString aKey);
-
- /**
- * @param aWindow is the browser window to set the value for.
- * @param aKey is the value's name.
- * @param aStringValue is the value itself (use JSON.stringify/parse before setting JS objects).
- */
- void setWindowValue(in nsIDOMWindow aWindow, in AString aKey, in AString aStringValue);
-
- /**
- * @param aWindow is the browser window to get the value for.
- * @param aKey is the value's name.
- */
- void deleteWindowValue(in nsIDOMWindow aWindow, in AString aKey);
-
- /**
- * @param aTab is the tabbrowser tab to get the value for.
- * @param aKey is the value's name.
- *
- * @returns A string value or an empty string if none is set.
- */
- AString getTabValue(in nsIDOMNode aTab, in AString aKey);
-
- /**
- * @param aTab is the tabbrowser tab to set the value for.
- * @param aKey is the value's name.
- * @param aStringValue is the value itself (use JSON.stringify/parse before setting JS objects).
- */
- void setTabValue(in nsIDOMNode aTab, in AString aKey, in AString aStringValue);
-
- /**
- * @param aTab is the tabbrowser tab to get the value for.
- * @param aKey is the value's name.
- */
- void deleteTabValue(in nsIDOMNode aTab, in AString aKey);
-
- /**
- * @param aName is the name of the attribute to save/restore for all tabbrowser tabs.
- */
- void persistTabAttribute(in AString aName);
-};
diff --git a/components/sessionstore/nsSessionStartup.js b/components/sessionstore/nsSessionStartup.js
deleted file mode 100644
index 04037c1..0000000
--- a/components/sessionstore/nsSessionStartup.js
+++ /dev/null
@@ -1,296 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/**
- * Session Storage and Restoration
- *
- * Overview
- * This service reads user's session file at startup, and makes a determination
- * as to whether the session should be restored. It will restore the session
- * under the circumstances described below. If the auto-start Private Browsing
- * mode is active, however, the session is never restored.
- *
- * Crash Detection
- * The session file stores a session.state property, that
- * indicates whether the browser is currently running. When the browser shuts
- * down, the field is changed to "stopped". At startup, this field is read, and
- * if its value is "running", then it's assumed that the browser had previously
- * crashed, or at the very least that something bad happened, and that we should
- * restore the session.
- *
- * Forced Restarts
- * In the event that a restart is required due to application update or extension
- * installation, set the browser.sessionstore.resume_session_once pref to true,
- * and the session will be restored the next time the browser starts.
- *
- * Always Resume
- * This service will always resume the session if the integer pref
- * browser.startup.page is set to 3.
- */
-
-/* :::::::: Constants and Helpers ::::::::::::::: */
-
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-const Cr = Components.results;
-const Cu = Components.utils;
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
-Cu.import("resource://gre/modules/Promise.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "_SessionFile",
- "resource:///modules/sessionstore/_SessionFile.jsm");
-
-const STATE_RUNNING_STR = "running";
-
-function debug(aMsg) {
- aMsg = ("SessionStartup: " + aMsg).replace(/\S{80}/g, "$&\n");
- Services.console.logStringMessage(aMsg);
-}
-
-var gOnceInitializedDeferred = Promise.defer();
-
-/* :::::::: The Service ::::::::::::::: */
-
-function SessionStartup() {
-}
-
-SessionStartup.prototype = {
-
- // the state to restore at startup
- _initialState: null,
- _sessionType: Ci.nsISessionStartup.NO_SESSION,
- _initialized: false,
-
-/* ........ Global Event Handlers .............. */
-
- /**
- * Initialize the component
- */
- init: function sss_init() {
- // do not need to initialize anything in auto-started private browsing sessions
- if (PrivateBrowsingUtils.permanentPrivateBrowsing) {
- this._initialized = true;
- gOnceInitializedDeferred.resolve();
- return;
- }
-
- if (Services.prefs.getBoolPref("browser.sessionstore.resume_session_once") ||
- Services.prefs.getIntPref("browser.startup.page") == 3) {
- this._ensureInitialized();
- } else {
- _SessionFile.read().then(
- this._onSessionFileRead.bind(this)
- );
- }
- },
-
- // Wrap a string as a nsISupports
- _createSupportsString: function ssfi_createSupportsString(aData) {
- let string = Cc["@mozilla.org/supports-string;1"]
- .createInstance(Ci.nsISupportsString);
- string.data = aData;
- return string;
- },
-
- _onSessionFileRead: function sss_onSessionFileRead(aStateString) {
- if (this._initialized) {
- // Initialization is complete, nothing else to do
- return;
- }
- try {
- this._initialized = true;
-
- // Let observers modify the state before it is used
- let supportsStateString = this._createSupportsString(aStateString);
- Services.obs.notifyObservers(supportsStateString, "sessionstore-state-read", "");
- aStateString = supportsStateString.data;
-
- // No valid session found.
- if (!aStateString) {
- this._sessionType = Ci.nsISessionStartup.NO_SESSION;
- return;
- }
-
- // parse the session state into a JS object
- // remove unneeded braces (added for compatibility with Firefox 2.0 and 3.0)
- if (aStateString.charAt(0) == '(')
- aStateString = aStateString.slice(1, -1);
- let corruptFile = false;
- try {
- this._initialState = JSON.parse(aStateString);
- }
- catch (ex) {
- debug("The session file contained un-parse-able JSON: " + ex);
- // This is not valid JSON, but this might still be valid JavaScript,
- // as used in FF2/FF3, so we need to eval.
- // evalInSandbox will throw if aStateString is not parse-able.
- try {
- var s = new Cu.Sandbox("about:blank", {sandboxName: 'nsSessionStartup'});
- this._initialState = Cu.evalInSandbox("(" + aStateString + ")", s);
- } catch(ex) {
- debug("The session file contained un-eval-able JSON: " + ex);
- corruptFile = true;
- }
- }
- let doResumeSessionOnce = Services.prefs.getBoolPref("browser.sessionstore.resume_session_once");
- let doResumeSession = doResumeSessionOnce ||
- Services.prefs.getIntPref("browser.startup.page") == 3;
-
- // If this is a normal restore then throw away any previous session
- if (!doResumeSessionOnce)
- delete this._initialState.lastSessionState;
-
- let resumeFromCrash = Services.prefs.getBoolPref("browser.sessionstore.resume_from_crash");
- let lastSessionCrashed =
- this._initialState && this._initialState.session &&
- this._initialState.session.state &&
- this._initialState.session.state == STATE_RUNNING_STR;
-
- // set the startup type
- if (lastSessionCrashed && resumeFromCrash)
- this._sessionType = Ci.nsISessionStartup.RECOVER_SESSION;
- else if (!lastSessionCrashed && doResumeSession)
- this._sessionType = Ci.nsISessionStartup.RESUME_SESSION;
- else if (this._initialState)
- this._sessionType = Ci.nsISessionStartup.DEFER_SESSION;
- else
- this._initialState = null; // reset the state
-
- Services.obs.addObserver(this, "sessionstore-windows-restored", true);
-
- if (this._sessionType != Ci.nsISessionStartup.NO_SESSION)
- Services.obs.addObserver(this, "browser:purge-session-history", true);
-
- } finally {
- // We're ready. Notify everyone else.
- Services.obs.notifyObservers(null, "sessionstore-state-finalized", "");
- gOnceInitializedDeferred.resolve();
- }
- },
-
- /**
- * Handle notifications
- */
- observe: function sss_observe(aSubject, aTopic, aData) {
- switch (aTopic) {
- case "app-startup":
- Services.obs.addObserver(this, "final-ui-startup", true);
- Services.obs.addObserver(this, "quit-application", true);
- break;
- case "final-ui-startup":
- Services.obs.removeObserver(this, "final-ui-startup");
- Services.obs.removeObserver(this, "quit-application");
- this.init();
- break;
- case "quit-application":
- // no reason for initializing at this point (cf. bug 409115)
- Services.obs.removeObserver(this, "final-ui-startup");
- Services.obs.removeObserver(this, "quit-application");
- if (this._sessionType != Ci.nsISessionStartup.NO_SESSION)
- Services.obs.removeObserver(this, "browser:purge-session-history");
- break;
- case "sessionstore-windows-restored":
- Services.obs.removeObserver(this, "sessionstore-windows-restored");
- // free _initialState after nsSessionStore is done with it
- this._initialState = null;
- break;
- case "browser:purge-session-history":
- Services.obs.removeObserver(this, "browser:purge-session-history");
- // reset all state on sanitization
- this._sessionType = Ci.nsISessionStartup.NO_SESSION;
- break;
- }
- },
-
-/* ........ Public API ................*/
-
- get onceInitialized() {
- return gOnceInitializedDeferred.promise;
- },
-
- /**
- * Get the session state as a jsval
- */
- get state() {
- this._ensureInitialized();
- return this._initialState;
- },
-
- /**
- * Determines whether there is a pending session restore and makes sure that
- * we're initialized before returning. If we're not yet this will read the
- * session file synchronously.
- * @returns bool
- */
- doRestore: function sss_doRestore() {
- this._ensureInitialized();
- return this._willRestore();
- },
-
- /**
- * Determines whether there is a pending session restore.
- * @returns bool
- */
- _willRestore: function () {
- return this._sessionType == Ci.nsISessionStartup.RECOVER_SESSION ||
- this._sessionType == Ci.nsISessionStartup.RESUME_SESSION;
- },
-
- /**
- * Returns whether we will restore a session that ends up replacing the
- * homepage. The browser uses this to not start loading the homepage if
- * we're going to stop its load anyway shortly after.
- *
- * This is meant to be an optimization for the average case that loading the
- * session file finishes before we may want to start loading the default
- * homepage. Should this be called before the session file has been read it
- * will just return false.
- *
- * @returns bool
- */
- get willOverrideHomepage() {
- if (this._initialState && this._willRestore()) {
- let windows = this._initialState.windows || null;
- // If there are valid windows with not only pinned tabs, signal that we
- // will override the default homepage by restoring a session.
- return windows && windows.some(w => w.tabs.some(t => !t.pinned));
- }
- return false;
- },
-
- /**
- * Get the type of pending session store, if any.
- */
- get sessionType() {
- this._ensureInitialized();
- return this._sessionType;
- },
-
- // Ensure that initialization is complete.
- // If initialization is not complete yet, fall back to a synchronous
- // initialization and kill ongoing asynchronous initialization
- _ensureInitialized: function sss__ensureInitialized() {
- try {
- if (this._initialized) {
- // Initialization is complete, nothing else to do
- return;
- }
- let contents = _SessionFile.syncRead();
- this._onSessionFileRead(contents);
- } catch(ex) {
- debug("ensureInitialized: could not read session " + ex + ", " + ex.stack);
- throw ex;
- }
- },
-
- /* ........ QueryInterface .............. */
- QueryInterface : XPCOMUtils.generateQI([Ci.nsIObserver,
- Ci.nsISupportsWeakReference,
- Ci.nsISessionStartup]),
- classID: Components.ID("{ec7a6c20-e081-11da-8ad9-0800200c9a66}")
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([SessionStartup]);
diff --git a/components/sessionstore/nsSessionStore.js b/components/sessionstore/nsSessionStore.js
deleted file mode 100644
index 38713d5..0000000
--- a/components/sessionstore/nsSessionStore.js
+++ /dev/null
@@ -1,37 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/**
- * Session Storage and Restoration
- *
- * Overview
- * This service keeps track of a user's session, storing the various bits
- * required to return the browser to its current state. The relevant data is
- * stored in memory, and is periodically saved to disk in a file in the
- * profile directory. The service is started at first window load, in
- * delayedStartup, and will restore the session from the data received from
- * the nsSessionStartup service.
- */
-
-const Cu = Components.utils;
-const Ci = Components.interfaces;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource:///modules/sessionstore/SessionStore.jsm");
-
-function SessionStoreService() {}
-
-// The SessionStore module's object is frozen. We need to modify our prototype
-// and add some properties so let's just copy the SessionStore object.
-Object.keys(SessionStore).forEach(function (aName) {
- let desc = Object.getOwnPropertyDescriptor(SessionStore, aName);
- Object.defineProperty(SessionStoreService.prototype, aName, desc);
-});
-
-SessionStoreService.prototype.classID =
- Components.ID("{5280606b-2510-4fe0-97ef-9b5a22eafe6b}");
-SessionStoreService.prototype.QueryInterface =
- XPCOMUtils.generateQI([Ci.nsISessionStore]);
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([SessionStoreService]);
diff --git a/components/sessionstore/nsSessionStore.manifest b/components/sessionstore/nsSessionStore.manifest
deleted file mode 100644
index b136b41..0000000
--- a/components/sessionstore/nsSessionStore.manifest
+++ /dev/null
@@ -1,18 +0,0 @@
-# WebappRT doesn't need these instructions, and they don't necessarily work
-# with it, but it does use a GRE directory that the GRE shares with Firefox,
-# so in order to prevent the instructions from being processed for WebappRT,
-# we need to restrict them to the applications that depend on them, i.e.:
-#
-# b2g: {3c2e2abc-06d4-11e1-ac3b-374f68613e61}
-# browser: {8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}
-# mobile/android: {aa3c5121-dab2-40e2-81ca-7ea25febc110}
-# mobile/xul: {a23983c0-fd0e-11dc-95ff-0800200c9a66}
-#
-# In theory we should do this for all these instructions, but in practice it is
-# sufficient to do it for the app-startup one, and the file is simpler that way.
-
-component {5280606b-2510-4fe0-97ef-9b5a22eafe6b} nsSessionStore.js
-contract @mozilla.org/browser/sessionstore;1 {5280606b-2510-4fe0-97ef-9b5a22eafe6b}
-component {ec7a6c20-e081-11da-8ad9-0800200c9a66} nsSessionStartup.js
-contract @mozilla.org/browser/sessionstartup;1 {ec7a6c20-e081-11da-8ad9-0800200c9a66}
-category app-startup nsSessionStartup service,@mozilla.org/browser/sessionstartup;1 application={3c2e2abc-06d4-11e1-ac3b-374f68613e61} application={8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4} application={aa3c5121-dab2-40e2-81ca-7ea25febc110} application={a23983c0-fd0e-11dc-95ff-0800200c9a66}
diff --git a/components/shell/ShellService.jsm b/components/shell/ShellService.jsm
deleted file mode 100644
index 74632b6..0000000
--- a/components/shell/ShellService.jsm
+++ /dev/null
@@ -1,114 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
-* License, v. 2.0. If a copy of the MPL was not distributed with this file,
-* You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-this.EXPORTED_SYMBOLS = ["ShellService"];
-
-const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
-
-Cu.import("resource://gre/modules/AppConstants.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "WindowsRegistry",
- "resource://gre/modules/WindowsRegistry.jsm");
-
-/**
- * Internal functionality to save and restore the docShell.allow* properties.
- */
-var ShellServiceInternal = {
- /**
- * Used to determine whether or not to offer "Set as desktop background"
- * functionality. Even if shell service is available it is not
- * guaranteed that it is able to set the background for every desktop
- * which is especially true for Linux with its many different desktop
- * environments.
- */
- get canSetDesktopBackground() {
- if (AppConstants.platform == "win" ||
- AppConstants.platform == "macosx") {
- return true;
- }
-
- if (AppConstants.platform == "linux") {
- if (this.shellService) {
- let linuxShellService = this.shellService
- .QueryInterface(Ci.nsIGNOMEShellService);
- return linuxShellService.canSetDesktopBackground;
- }
- }
-
- return false;
- },
-
- /**
- * Used to determine whether or not to show a "Set Default Browser"
- * query dialog. This attribute is true if the application is starting
- * up and "browser.shell.checkDefaultBrowser" is true, otherwise it
- * is false.
- */
- _checkedThisSession: false,
- get shouldCheckDefaultBrowser() {
- // If we've already checked, the browser has been started and this is a
- // new window open, and we don't want to check again.
- if (this._checkedThisSession) {
- return false;
- }
-
- if (!Services.prefs.getBoolPref("browser.shell.checkDefaultBrowser")) {
- return false;
- }
-
- if (AppConstants.platform == "win") {
- let optOutValue = WindowsRegistry.readRegKey(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
- "Software\\Mozilla\\PaleMoon",
- "DefaultBrowserOptOut");
- WindowsRegistry.removeRegKey(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
- "Software\\Mozilla\\PaleMoon",
- "DefaultBrowserOptOut");
- if (optOutValue == "True") {
- Services.prefs.setBoolPref("browser.shell.checkDefaultBrowser", false);
- return false;
- }
- }
-
- return true;
- },
-
- set shouldCheckDefaultBrowser(shouldCheck) {
- Services.prefs.setBoolPref("browser.shell.checkDefaultBrowser", !!shouldCheck);
- },
-
- isDefaultBrowser(startupCheck, forAllTypes) {
- // If this is the first browser window, maintain internal state that we've
- // checked this session (so that subsequent window opens don't show the
- // default browser dialog).
- if (startupCheck) {
- this._checkedThisSession = true;
- }
- if (this.shellService) {
- return this.shellService.isDefaultBrowser(startupCheck, forAllTypes);
- }
- return false;
- }
-};
-
-XPCOMUtils.defineLazyServiceGetter(ShellServiceInternal, "shellService",
- "@mozilla.org/browser/shell-service;1", Ci.nsIShellService);
-
-/**
- * The external API exported by this module.
- */
-this.ShellService = new Proxy(ShellServiceInternal, {
- get(target, name) {
- if (name in target) {
- return target[name];
- }
- if (target.shellService) {
- return target.shellService[name];
- }
- Services.console.logStringMessage(`${name} not found in ShellService: ${target.shellService}`);
- return undefined;
- }
-});
diff --git a/components/shell/content/setDesktopBackground.js b/components/shell/content/setDesktopBackground.js
deleted file mode 100644
index 53cc70d..0000000
--- a/components/shell/content/setDesktopBackground.js
+++ /dev/null
@@ -1,214 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-Components.utils.import("resource://gre/modules/AppConstants.jsm");
-
-var Ci = Components.interfaces;
-
-var gSetBackground = {
- _position : AppConstants.platform == "macosx" ? "STRETCH" : "",
- _backgroundColor : AppConstants.platform != "macosx" ? 0 : undefined,
- _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;
- if (AppConstants.platform == "macosx") {
- document.documentElement.getButton("accept").hidden = true;
- }
- if (this._screenWidth / this._screenHeight >= 1.6)
- document.getElementById("monitor").setAttribute("aspectratio", "16:10");
-
- if (AppConstants.platform == "win") {
- // Hide fill + fit options if < Win7 since they don't work.
- var version = Components.classes["@mozilla.org/system-info;1"]
- .getService(Ci.nsIPropertyBag2)
- .getProperty("version");
- var isWindows7OrHigher = (parseFloat(version) >= 6.1);
- if (!isWindows7OrHigher) {
- document.getElementById("fillPosition").hidden = true;
- document.getElementById("fitPosition").hidden = true;
- }
- }
-
- // 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);
-
- if (AppConstants.platform != "macosx") {
- this._initColor();
- } else {
- // Make sure to reset the button state in case the user has already
- // set an image as their desktop background.
- var setDesktopBackground = document.getElementById("setDesktopBackground");
- setDesktopBackground.hidden = false;
- var bundle = document.getElementById("backgroundBundle");
- setDesktopBackground.label = bundle.getString("DesktopBackgroundSet");
- setDesktopBackground.disabled = false;
-
- document.getElementById("showDesktopPreferences").hidden = true;
- }
- this.updatePosition();
- },
-
- setDesktopBackground: function ()
- {
- if (AppConstants.platform != "macosx") {
- document.persist("menuPosition", "value");
- this._shell.desktopBackgroundColor = this._hexStringToLong(this._backgroundColor);
- } else {
- Components.classes["@mozilla.org/observer-service;1"]
- .getService(Ci.nsIObserverService)
- .addObserver(this, "shell:desktop-background-changed", false);
-
- var bundle = document.getElementById("backgroundBundle");
- var setDesktopBackground = document.getElementById("setDesktopBackground");
- setDesktopBackground.disabled = true;
- setDesktopBackground.label = bundle.getString("DesktopBackgroundDownloading");
- }
- this._shell.setDesktopBackground(this._image,
- Ci.nsIShellService["BACKGROUND_" + this._position]);
- },
-
- updatePosition: function ()
- {
- var ctx = this._canvas.getContext("2d");
- ctx.clearRect(0, 0, this._screenWidth, this._screenHeight);
-
- if (AppConstants.platform != "macosx") {
- this._position = document.getElementById("menuPosition").value;
- }
-
- switch (this._position) {
- case "TILE":
- ctx.save();
- ctx.fillStyle = ctx.createPattern(this._image, "repeat");
- ctx.fillRect(0, 0, this._screenWidth, this._screenHeight);
- ctx.restore();
- break;
- case "STRETCH":
- ctx.drawImage(this._image, 0, 0, this._screenWidth, this._screenHeight);
- break;
- case "CENTER": {
- let x = (this._screenWidth - this._image.naturalWidth) / 2;
- let y = (this._screenHeight - this._image.naturalHeight) / 2;
- ctx.drawImage(this._image, x, y);
- break;
- }
- case "FILL": {
- // Try maxing width first, overflow height.
- let widthRatio = this._screenWidth / this._image.naturalWidth;
- let width = this._image.naturalWidth * widthRatio;
- let height = this._image.naturalHeight * widthRatio;
- if (height < this._screenHeight) {
- // Height less than screen, max height and overflow width.
- let heightRatio = this._screenHeight / this._image.naturalHeight;
- width = this._image.naturalWidth * heightRatio;
- height = this._image.naturalHeight * heightRatio;
- }
- let x = (this._screenWidth - width) / 2;
- let y = (this._screenHeight - height) / 2;
- ctx.drawImage(this._image, x, y, width, height);
- break;
- }
- case "FIT": {
- // Try maxing width first, top and bottom borders.
- let widthRatio = this._screenWidth / this._image.naturalWidth;
- let width = this._image.naturalWidth * widthRatio;
- let height = this._image.naturalHeight * widthRatio;
- let x = 0;
- let y = (this._screenHeight - height) / 2;
- if (height > this._screenHeight) {
- // Height overflow, maximise height, side borders.
- let heightRatio = this._screenHeight / this._image.naturalHeight;
- width = this._image.naturalWidth * heightRatio;
- height = this._image.naturalHeight * heightRatio;
- x = (this._screenWidth - width) / 2;
- y = 0;
- }
- ctx.drawImage(this._image, x, y, width, height);
- break;
- }
- }
- }
-};
-
-if (AppConstants.platform != "macosx") {
- gSetBackground["_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;
- };
-
- gSetBackground["updateColor"] = function (aColor)
- {
- this._backgroundColor = aColor;
- this._canvas.style.backgroundColor = aColor;
- };
-
- // Converts a color string in the format "#RRGGBB" to an integer.
- gSetBackground["_hexStringToLong"] = function (aString)
- {
- return parseInt(aString.substring(1, 3), 16) << 16 |
- parseInt(aString.substring(3, 5), 16) << 8 |
- parseInt(aString.substring(5, 7), 16);
- };
-
- gSetBackground["_rgbToHex"] = function (aR, aG, aB)
- {
- return "#" + [aR, aG, aB].map(aInt => aInt.toString(16).replace(/^(.)$/, "0$1"))
- .join("").toUpperCase();
- };
-} else {
- gSetBackground["observe"] = function (aSubject, aTopic, aData)
- {
- if (aTopic == "shell:desktop-background-changed") {
- document.getElementById("setDesktopBackground").hidden = true;
- document.getElementById("showDesktopPreferences").hidden = false;
-
- Components.classes["@mozilla.org/observer-service;1"]
- .getService(Ci.nsIObserverService)
- .removeObserver(this, "shell:desktop-background-changed");
- }
- };
-
- gSetBackground["showDesktopPrefs"] = function()
- {
- this._shell.openApplication(Ci.nsIMacShellService.APPLICATION_DESKTOP);
- };
-}
diff --git a/components/shell/content/setDesktopBackground.xul b/components/shell/content/setDesktopBackground.xul
deleted file mode 100644
index d7d4079..0000000
--- a/components/shell/content/setDesktopBackground.xul
+++ /dev/null
@@ -1,84 +0,0 @@
-<?xml version="1.0"?> <!-- -*- Mode: HTML -*- -->
-
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
-<?xml-stylesheet href="chrome://browser/skin/setDesktopBackground.css" type="text/css"?>
-
-<!DOCTYPE dialog SYSTEM "chrome://browser/locale/setDesktopBackground.dtd">
-
-#ifdef XP_MACOSX
-<?xul-overlay href="chrome://browser/content/macBrowserOverlay.xul"?>
-#endif
-
-<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml"
- windowtype="Shell:SetDesktopBackground"
-#ifndef XP_MACOSX
- buttons="accept,cancel"
-#else
- buttons="accept"
-#endif
- buttonlabelaccept="&setDesktopBackground.title;"
- onload="gSetBackground.load();"
- ondialogaccept="gSetBackground.setDesktopBackground();"
- title="&setDesktopBackground.title;"
- style="width: 30em;">
-
- <stringbundle id="backgroundBundle"
- src="chrome://browser/locale/shellservice.properties"/>
- <script type="application/javascript" src="chrome://browser/content/utilityOverlay.js"/>
- <script type="application/javascript" src="chrome://browser/content/setDesktopBackground.js"/>
- <script type="application/javascript" src="chrome://global/content/contentAreaUtils.js"/>
-
-#ifndef XP_MACOSX
- <hbox align="center">
- <label value="&position.label;"/>
- <menulist id="menuPosition"
- label="&position.label;"
- oncommand="gSetBackground.updatePosition();">
- <menupopup>
- <menuitem label="&center.label;" value="CENTER"/>
- <menuitem label="&tile.label;" value="TILE"/>
- <menuitem label="&stretch.label;" value="STRETCH"/>
- <menuitem label="&fill.label;" value="FILL" id="fillPosition"/>
- <menuitem label="&fit.label;" value="FIT" id="fitPosition"/>
- </menupopup>
- </menulist>
- <spacer flex="1"/>
- <label value="&color.label;"/>
- <colorpicker id="desktopColor"
- type="button"
- onchange="gSetBackground.updateColor(this.color);"/>
- </hbox>
-#endif
- <groupbox align="center">
- <caption label="&preview.label;"/>
- <stack>
- <!-- if width and height are not present, they default to 300x150 and stretch the stack -->
- <html:canvas id="screen" width="1" height="1"/>
- <image id="monitor"/>
- </stack>
- </groupbox>
-
-#ifdef XP_MACOSX
- <separator/>
-
- <hbox align="right">
- <button id="setDesktopBackground"
- label="&setDesktopBackground.title;"
- oncommand="gSetBackground.setDesktopBackground();"/>
- <button id="showDesktopPreferences"
- label="&openDesktopPrefs.label;"
- oncommand="gSetBackground.showDesktopPrefs();"
- hidden="true"/>
- </hbox>
-#endif
-
-#ifdef XP_MACOSX
-#include ../../../base/content/browserMountPoints.inc
-#endif
-
-</dialog>
diff --git a/components/shell/jar.mn b/components/shell/jar.mn
deleted file mode 100644
index 0864e1b..0000000
--- a/components/shell/jar.mn
+++ /dev/null
@@ -1,7 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-browser.jar:
-* content/browser/setDesktopBackground.xul (content/setDesktopBackground.xul)
- content/browser/setDesktopBackground.js (content/setDesktopBackground.js)
diff --git a/components/shell/moz.build b/components/shell/moz.build
deleted file mode 100644
index 16bffd7..0000000
--- a/components/shell/moz.build
+++ /dev/null
@@ -1,40 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-JAR_MANIFESTS += ['jar.mn']
-
-XPIDL_SOURCES += ['nsIShellService.idl']
-
-if CONFIG['OS_ARCH'] == 'WINNT':
- XPIDL_SOURCES += ['nsIWindowsShellService.idl']
-elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
- XPIDL_SOURCES += ['nsIMacShellService.idl']
-elif 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
- XPIDL_SOURCES += ['nsIGNOMEShellService.idl']
-
-XPIDL_MODULE = 'shellservice'
-
-if CONFIG['OS_ARCH'] == 'WINNT':
- SOURCES += ['nsWindowsShellService.cpp']
-elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
- SOURCES += ['nsMacShellService.cpp']
-elif 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
- SOURCES += ['nsGNOMEShellService.cpp']
-
-if SOURCES:
- FINAL_LIBRARY = 'browsercomps'
-
-EXTRA_COMPONENTS += [
- 'nsSetDefaultBrowser.js',
- 'nsSetDefaultBrowser.manifest',
-]
-
-EXTRA_JS_MODULES += ['ShellService.jsm']
-
-for var in ('MOZ_APP_NAME', 'MOZ_APP_VERSION'):
- DEFINES[var] = '"%s"' % CONFIG[var]
-
-CXXFLAGS += CONFIG['TK_CFLAGS']
diff --git a/components/shell/nsGNOMEShellService.cpp b/components/shell/nsGNOMEShellService.cpp
deleted file mode 100644
index 9bc5f59..0000000
--- a/components/shell/nsGNOMEShellService.cpp
+++ /dev/null
@@ -1,637 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/ArrayUtils.h"
-
-#include "nsCOMPtr.h"
-#include "nsGNOMEShellService.h"
-#include "nsShellService.h"
-#include "nsIServiceManager.h"
-#include "nsIFile.h"
-#include "nsIProperties.h"
-#include "nsDirectoryServiceDefs.h"
-#include "nsIPrefService.h"
-#include "prenv.h"
-#include "nsStringAPI.h"
-#include "nsIGConfService.h"
-#include "nsIGIOService.h"
-#include "nsIGSettingsService.h"
-#include "nsIStringBundle.h"
-#include "nsIOutputStream.h"
-#include "nsIProcess.h"
-#include "nsServiceManagerUtils.h"
-#include "nsComponentManagerUtils.h"
-#include "nsIDOMHTMLImageElement.h"
-#include "nsIImageLoadingContent.h"
-#include "imgIRequest.h"
-#include "imgIContainer.h"
-#include "mozilla/Sprintf.h"
-#if defined(MOZ_WIDGET_GTK)
-#include "nsIImageToPixbuf.h"
-#endif
-#include "nsXULAppAPI.h"
-
-#include <glib.h>
-#include <glib-object.h>
-#include <gtk/gtk.h>
-#include <gdk/gdk.h>
-#include <gdk-pixbuf/gdk-pixbuf.h>
-#include <limits.h>
-#include <stdlib.h>
-
-using namespace mozilla;
-
-struct ProtocolAssociation
-{
- const char *name;
- bool essential;
-};
-
-struct MimeTypeAssociation
-{
- const char *mimeType;
- const char *extensions;
-};
-
-static const ProtocolAssociation appProtocols[] = {
- { "http", true },
- { "https", true },
- { "ftp", false },
- { "chrome", false }
-};
-
-static const MimeTypeAssociation appTypes[] = {
- { "text/html", "htm html shtml" },
- { "application/xhtml+xml", "xhtml xht" }
-};
-
-// GConf registry key constants
-#define DG_BACKGROUND "/desktop/gnome/background"
-
-static const char kDesktopImageKey[] = DG_BACKGROUND "/picture_filename";
-static const char kDesktopOptionsKey[] = DG_BACKGROUND "/picture_options";
-static const char kDesktopDrawBGKey[] = DG_BACKGROUND "/draw_background";
-static const char kDesktopColorKey[] = DG_BACKGROUND "/primary_color";
-
-static const char kDesktopBGSchema[] = "org.gnome.desktop.background";
-static const char kDesktopImageGSKey[] = "picture-uri";
-static const char kDesktopOptionGSKey[] = "picture-options";
-static const char kDesktopDrawBGGSKey[] = "draw-background";
-static const char kDesktopColorGSKey[] = "primary-color";
-
-nsresult
-nsGNOMEShellService::Init()
-{
- nsresult rv;
-
- // GConf, GSettings or GIO _must_ be available, or we do not allow
- // CreateInstance to succeed.
-
- nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
- nsCOMPtr<nsIGIOService> giovfs =
- do_GetService(NS_GIOSERVICE_CONTRACTID);
- nsCOMPtr<nsIGSettingsService> gsettings =
- do_GetService(NS_GSETTINGSSERVICE_CONTRACTID);
-
- if (!gconf && !giovfs && !gsettings)
- return NS_ERROR_NOT_AVAILABLE;
-
- // Check G_BROKEN_FILENAMES. If it's set, then filenames in glib use
- // the locale encoding. If it's not set, they use UTF-8.
- mUseLocaleFilenames = PR_GetEnv("G_BROKEN_FILENAMES") != nullptr;
-
- if (GetAppPathFromLauncher())
- return NS_OK;
-
- nsCOMPtr<nsIProperties> dirSvc
- (do_GetService("@mozilla.org/file/directory_service;1"));
- NS_ENSURE_TRUE(dirSvc, NS_ERROR_NOT_AVAILABLE);
-
- nsCOMPtr<nsIFile> appPath;
- rv = dirSvc->Get(XRE_EXECUTABLE_FILE, NS_GET_IID(nsIFile),
- getter_AddRefs(appPath));
- NS_ENSURE_SUCCESS(rv, rv);
-
- return appPath->GetNativePath(mAppPath);
-}
-
-NS_IMPL_ISUPPORTS(nsGNOMEShellService, nsIGNOMEShellService, nsIShellService)
-
-bool
-nsGNOMEShellService::GetAppPathFromLauncher()
-{
- gchar *tmp;
-
- const char *launcher = PR_GetEnv("MOZ_APP_LAUNCHER");
- if (!launcher)
- return false;
-
- if (g_path_is_absolute(launcher)) {
- mAppPath = launcher;
- tmp = g_path_get_basename(launcher);
- gchar *fullpath = g_find_program_in_path(tmp);
- if (fullpath && mAppPath.Equals(fullpath))
- mAppIsInPath = true;
- g_free(fullpath);
- } else {
- tmp = g_find_program_in_path(launcher);
- if (!tmp)
- return false;
- mAppPath = tmp;
- mAppIsInPath = true;
- }
-
- g_free(tmp);
- return true;
-}
-
-bool
-nsGNOMEShellService::KeyMatchesAppName(const char *aKeyValue) const
-{
-
- gchar *commandPath;
- if (mUseLocaleFilenames) {
- gchar *nativePath = g_filename_from_utf8(aKeyValue, -1,
- nullptr, nullptr, nullptr);
- if (!nativePath) {
- NS_ERROR("Error converting path to filesystem encoding");
- return false;
- }
-
- commandPath = g_find_program_in_path(nativePath);
- g_free(nativePath);
- } else {
- commandPath = g_find_program_in_path(aKeyValue);
- }
-
- if (!commandPath)
- return false;
-
- bool matches = mAppPath.Equals(commandPath);
- g_free(commandPath);
- return matches;
-}
-
-bool
-nsGNOMEShellService::CheckHandlerMatchesAppName(const nsACString &handler) const
-{
- gint argc;
- gchar **argv;
- nsAutoCString command(handler);
-
- // The string will be something of the form: [/path/to/]browser "%s"
- // We want to remove all of the parameters and get just the binary name.
-
- if (g_shell_parse_argv(command.get(), &argc, &argv, nullptr) && argc > 0) {
- command.Assign(argv[0]);
- g_strfreev(argv);
- }
-
- if (!KeyMatchesAppName(command.get()))
- return false; // the handler is set to another app
-
- return true;
-}
-
-NS_IMETHODIMP
-nsGNOMEShellService::IsDefaultBrowser(bool aStartupCheck,
- bool aForAllTypes,
- bool* aIsDefaultBrowser)
-{
- *aIsDefaultBrowser = false;
-
- nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
- nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID);
-
- bool enabled;
- nsAutoCString handler;
- nsCOMPtr<nsIGIOMimeApp> gioApp;
-
- for (unsigned int i = 0; i < ArrayLength(appProtocols); ++i) {
- if (!appProtocols[i].essential)
- continue;
-
- if (gconf) {
- handler.Truncate();
- gconf->GetAppForProtocol(nsDependentCString(appProtocols[i].name),
- &enabled, handler);
-
- if (!CheckHandlerMatchesAppName(handler) || !enabled)
- return NS_OK; // the handler is disabled or set to another app
- }
-
- if (giovfs) {
- handler.Truncate();
- giovfs->GetAppForURIScheme(nsDependentCString(appProtocols[i].name),
- getter_AddRefs(gioApp));
- if (!gioApp)
- return NS_OK;
-
- gioApp->GetCommand(handler);
-
- if (!CheckHandlerMatchesAppName(handler))
- return NS_OK; // the handler is set to another app
- }
- }
-
- *aIsDefaultBrowser = true;
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGNOMEShellService::SetDefaultBrowser(bool aClaimAllTypes,
- bool aForAllUsers)
-{
-#ifdef DEBUG
- if (aForAllUsers)
- NS_WARNING("Setting the default browser for all users is not yet supported");
-#endif
-
- nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
- nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID);
- if (gconf) {
- nsAutoCString appKeyValue;
- if (mAppIsInPath) {
- // mAppPath is in the users path, so use only the basename as the launcher
- gchar *tmp = g_path_get_basename(mAppPath.get());
- appKeyValue = tmp;
- g_free(tmp);
- } else {
- appKeyValue = mAppPath;
- }
-
- appKeyValue.AppendLiteral(" %s");
-
- for (unsigned int i = 0; i < ArrayLength(appProtocols); ++i) {
- if (appProtocols[i].essential || aClaimAllTypes) {
- gconf->SetAppForProtocol(nsDependentCString(appProtocols[i].name),
- appKeyValue);
- }
- }
- }
-
- if (giovfs) {
- nsresult rv;
- nsCOMPtr<nsIStringBundleService> bundleService =
- do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<nsIStringBundle> brandBundle;
- rv = bundleService->CreateBundle(BRAND_PROPERTIES, getter_AddRefs(brandBundle));
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsString brandShortName;
- brandBundle->GetStringFromName(u"brandShortName",
- getter_Copies(brandShortName));
-
- // use brandShortName as the application id.
- NS_ConvertUTF16toUTF8 id(brandShortName);
- nsCOMPtr<nsIGIOMimeApp> appInfo;
- rv = giovfs->CreateAppFromCommand(mAppPath,
- id,
- getter_AddRefs(appInfo));
- NS_ENSURE_SUCCESS(rv, rv);
-
- // set handler for the protocols
- for (unsigned int i = 0; i < ArrayLength(appProtocols); ++i) {
- if (appProtocols[i].essential || aClaimAllTypes) {
- appInfo->SetAsDefaultForURIScheme(nsDependentCString(appProtocols[i].name));
- }
- }
-
- // set handler for .html and xhtml files and MIME types:
- if (aClaimAllTypes) {
- // Add mime types for html, xhtml extension and set app to just created appinfo.
- for (unsigned int i = 0; i < ArrayLength(appTypes); ++i) {
- appInfo->SetAsDefaultForMimeType(nsDependentCString(appTypes[i].mimeType));
- appInfo->SetAsDefaultForFileExtensions(nsDependentCString(appTypes[i].extensions));
- }
- }
- }
-
- nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
- if (prefs) {
- (void) prefs->SetBoolPref(PREF_CHECKDEFAULTBROWSER, true);
- // Reset the number of times the dialog should be shown
- // before it is silenced.
- (void) prefs->SetIntPref(PREF_DEFAULTBROWSERCHECKCOUNT, 0);
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGNOMEShellService::GetCanSetDesktopBackground(bool* aResult)
-{
- // setting desktop background is currently only supported
- // for Gnome or desktops using the same GSettings and GConf keys
- const char* gnomeSession = getenv("GNOME_DESKTOP_SESSION_ID");
- if (gnomeSession) {
- *aResult = true;
- } else {
- *aResult = false;
- }
-
- return NS_OK;
-}
-
-static nsresult
-WriteImage(const nsCString& aPath, imgIContainer* aImage)
-{
-#if !defined(MOZ_WIDGET_GTK)
- return NS_ERROR_NOT_AVAILABLE;
-#else
- nsCOMPtr<nsIImageToPixbuf> imgToPixbuf =
- do_GetService("@mozilla.org/widget/image-to-gdk-pixbuf;1");
- if (!imgToPixbuf)
- return NS_ERROR_NOT_AVAILABLE;
-
- GdkPixbuf* pixbuf = imgToPixbuf->ConvertImageToPixbuf(aImage);
- if (!pixbuf)
- return NS_ERROR_NOT_AVAILABLE;
-
- gboolean res = gdk_pixbuf_save(pixbuf, aPath.get(), "png", nullptr, nullptr);
-
- g_object_unref(pixbuf);
- return res ? NS_OK : NS_ERROR_FAILURE;
-#endif
-}
-
-NS_IMETHODIMP
-nsGNOMEShellService::SetDesktopBackground(nsIDOMElement* aElement,
- int32_t aPosition)
-{
- nsresult rv;
- nsCOMPtr<nsIImageLoadingContent> imageContent = do_QueryInterface(aElement, &rv);
- if (!imageContent) return rv;
-
- // get the image container
- nsCOMPtr<imgIRequest> request;
- rv = imageContent->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
- getter_AddRefs(request));
- if (!request) return rv;
- nsCOMPtr<imgIContainer> container;
- rv = request->GetImage(getter_AddRefs(container));
- if (!container) return rv;
-
- // Set desktop wallpaper filling style
- nsAutoCString options;
- if (aPosition == BACKGROUND_TILE)
- options.AssignLiteral("wallpaper");
- else if (aPosition == BACKGROUND_STRETCH)
- options.AssignLiteral("stretched");
- else if (aPosition == BACKGROUND_FILL)
- options.AssignLiteral("zoom");
- else if (aPosition == BACKGROUND_FIT)
- options.AssignLiteral("scaled");
- else
- options.AssignLiteral("centered");
-
- // Write the background file to the home directory.
- nsAutoCString filePath(PR_GetEnv("HOME"));
-
- // get the product brand name from localized strings
- nsString brandName;
- nsCID bundleCID = NS_STRINGBUNDLESERVICE_CID;
- nsCOMPtr<nsIStringBundleService> bundleService(do_GetService(bundleCID));
- if (bundleService) {
- nsCOMPtr<nsIStringBundle> brandBundle;
- rv = bundleService->CreateBundle(BRAND_PROPERTIES,
- getter_AddRefs(brandBundle));
- if (NS_SUCCEEDED(rv) && brandBundle) {
- rv = brandBundle->GetStringFromName(u"brandShortName",
- getter_Copies(brandName));
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
-
- // build the file name
- filePath.Append('/');
- filePath.Append(NS_ConvertUTF16toUTF8(brandName));
- filePath.AppendLiteral("_wallpaper.png");
-
- // write the image to a file in the home dir
- rv = WriteImage(filePath, container);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Try GSettings first. If we don't have GSettings or the right schema, fall back
- // to using GConf instead. Note that if GSettings works ok, the changes get
- // mirrored to GConf by the gsettings->gconf bridge in gnome-settings-daemon
- nsCOMPtr<nsIGSettingsService> gsettings =
- do_GetService(NS_GSETTINGSSERVICE_CONTRACTID);
- if (gsettings) {
- nsCOMPtr<nsIGSettingsCollection> background_settings;
- gsettings->GetCollectionForSchema(
- NS_LITERAL_CSTRING(kDesktopBGSchema), getter_AddRefs(background_settings));
- if (background_settings) {
- gchar *file_uri = g_filename_to_uri(filePath.get(), nullptr, nullptr);
- if (!file_uri)
- return NS_ERROR_FAILURE;
-
- background_settings->SetString(NS_LITERAL_CSTRING(kDesktopOptionGSKey),
- options);
-
- background_settings->SetString(NS_LITERAL_CSTRING(kDesktopImageGSKey),
- nsDependentCString(file_uri));
- g_free(file_uri);
- background_settings->SetBoolean(NS_LITERAL_CSTRING(kDesktopDrawBGGSKey),
- true);
- return rv;
- }
- }
-
- // if the file was written successfully, set it as the system wallpaper
- nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
-
- if (gconf) {
- gconf->SetString(NS_LITERAL_CSTRING(kDesktopOptionsKey), options);
-
- // Set the image to an empty string first to force a refresh
- // (since we could be writing a new image on top of an existing
- // PaleMoon_wallpaper.png and nautilus doesn't monitor the file for changes)
- gconf->SetString(NS_LITERAL_CSTRING(kDesktopImageKey),
- EmptyCString());
-
- gconf->SetString(NS_LITERAL_CSTRING(kDesktopImageKey), filePath);
- gconf->SetBool(NS_LITERAL_CSTRING(kDesktopDrawBGKey), true);
- }
-
- return rv;
-}
-
-#define COLOR_16_TO_8_BIT(_c) ((_c) >> 8)
-#define COLOR_8_TO_16_BIT(_c) ((_c) << 8 | (_c))
-
-NS_IMETHODIMP
-nsGNOMEShellService::GetDesktopBackgroundColor(uint32_t *aColor)
-{
- nsCOMPtr<nsIGSettingsService> gsettings =
- do_GetService(NS_GSETTINGSSERVICE_CONTRACTID);
- nsCOMPtr<nsIGSettingsCollection> background_settings;
- nsAutoCString background;
-
- if (gsettings) {
- gsettings->GetCollectionForSchema(
- NS_LITERAL_CSTRING(kDesktopBGSchema), getter_AddRefs(background_settings));
- if (background_settings) {
- background_settings->GetString(NS_LITERAL_CSTRING(kDesktopColorGSKey),
- background);
- }
- }
-
- if (!background_settings) {
- nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
- if (gconf)
- gconf->GetString(NS_LITERAL_CSTRING(kDesktopColorKey), background);
- }
-
- if (background.IsEmpty()) {
- *aColor = 0;
- return NS_OK;
- }
-
- GdkColor color;
- gboolean success = gdk_color_parse(background.get(), &color);
-
- NS_ENSURE_TRUE(success, NS_ERROR_FAILURE);
-
- *aColor = COLOR_16_TO_8_BIT(color.red) << 16 |
- COLOR_16_TO_8_BIT(color.green) << 8 |
- COLOR_16_TO_8_BIT(color.blue);
- return NS_OK;
-}
-
-static void
-ColorToCString(uint32_t aColor, nsCString& aResult)
-{
- // The #rrrrggggbbbb format is used to match gdk_color_to_string()
- char *buf = aResult.BeginWriting(13);
- if (!buf)
- return;
-
- uint16_t red = COLOR_8_TO_16_BIT((aColor >> 16) & 0xff);
- uint16_t green = COLOR_8_TO_16_BIT((aColor >> 8) & 0xff);
- uint16_t blue = COLOR_8_TO_16_BIT(aColor & 0xff);
-
- snprintf(buf, 14, "#%04x%04x%04x", red, green, blue);
-}
-
-NS_IMETHODIMP
-nsGNOMEShellService::SetDesktopBackgroundColor(uint32_t aColor)
-{
- NS_ASSERTION(aColor <= 0xffffff, "aColor has extra bits");
- nsAutoCString colorString;
- ColorToCString(aColor, colorString);
-
- nsCOMPtr<nsIGSettingsService> gsettings =
- do_GetService(NS_GSETTINGSSERVICE_CONTRACTID);
- if (gsettings) {
- nsCOMPtr<nsIGSettingsCollection> background_settings;
- gsettings->GetCollectionForSchema(
- NS_LITERAL_CSTRING(kDesktopBGSchema), getter_AddRefs(background_settings));
- if (background_settings) {
- background_settings->SetString(NS_LITERAL_CSTRING(kDesktopColorGSKey),
- colorString);
- return NS_OK;
- }
- }
-
- nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
-
- if (gconf) {
- gconf->SetString(NS_LITERAL_CSTRING(kDesktopColorKey), colorString);
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGNOMEShellService::OpenApplication(int32_t aApplication)
-{
- nsAutoCString scheme;
- if (aApplication == APPLICATION_MAIL)
- scheme.AssignLiteral("mailto");
- else if (aApplication == APPLICATION_NEWS)
- scheme.AssignLiteral("news");
- else
- return NS_ERROR_NOT_AVAILABLE;
-
- nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID);
- if (giovfs) {
- nsCOMPtr<nsIGIOMimeApp> gioApp;
- giovfs->GetAppForURIScheme(scheme, getter_AddRefs(gioApp));
- if (gioApp)
- return gioApp->Launch(EmptyCString());
- }
-
- nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
- if (!gconf)
- return NS_ERROR_FAILURE;
-
- bool enabled;
- nsAutoCString appCommand;
- gconf->GetAppForProtocol(scheme, &enabled, appCommand);
-
- if (!enabled)
- return NS_ERROR_FAILURE;
-
- // XXX we don't currently handle launching a terminal window.
- // If the handler requires a terminal, bail.
- bool requiresTerminal;
- gconf->HandlerRequiresTerminal(scheme, &requiresTerminal);
- if (requiresTerminal)
- return NS_ERROR_FAILURE;
-
- // Perform shell argument expansion
- int argc;
- char **argv;
- if (!g_shell_parse_argv(appCommand.get(), &argc, &argv, nullptr))
- return NS_ERROR_FAILURE;
-
- char **newArgv = new char*[argc + 1];
- int newArgc = 0;
-
- // Run through the list of arguments. Copy all of them to the new
- // argv except for %s, which we skip.
- for (int i = 0; i < argc; ++i) {
- if (strcmp(argv[i], "%s") != 0)
- newArgv[newArgc++] = argv[i];
- }
-
- newArgv[newArgc] = nullptr;
-
- gboolean err = g_spawn_async(nullptr, newArgv, nullptr, G_SPAWN_SEARCH_PATH,
- nullptr, nullptr, nullptr, nullptr);
-
- g_strfreev(argv);
- delete[] newArgv;
-
- return err ? NS_OK : NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-nsGNOMEShellService::OpenApplicationWithURI(nsIFile* aApplication, const nsACString& aURI)
-{
- nsresult rv;
- nsCOMPtr<nsIProcess> process =
- do_CreateInstance("@mozilla.org/process/util;1", &rv);
- if (NS_FAILED(rv))
- return rv;
-
- rv = process->Init(aApplication);
- if (NS_FAILED(rv))
- return rv;
-
- const nsCString spec(aURI);
- const char* specStr = spec.get();
- return process->Run(false, &specStr, 1);
-}
-
-NS_IMETHODIMP
-nsGNOMEShellService::GetDefaultFeedReader(nsIFile** _retval)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
diff --git a/components/shell/nsGNOMEShellService.h b/components/shell/nsGNOMEShellService.h
deleted file mode 100644
index a7b0038..0000000
--- a/components/shell/nsGNOMEShellService.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef nsgnomeshellservice_h____
-#define nsgnomeshellservice_h____
-
-#include "nsIGNOMEShellService.h"
-#include "nsStringAPI.h"
-#include "mozilla/Attributes.h"
-
-class nsGNOMEShellService final : public nsIGNOMEShellService
-{
-public:
- nsGNOMEShellService() : mAppIsInPath(false) { }
-
- NS_DECL_ISUPPORTS
- NS_DECL_NSISHELLSERVICE
- NS_DECL_NSIGNOMESHELLSERVICE
-
- nsresult Init();
-
-private:
- ~nsGNOMEShellService() {}
-
- bool KeyMatchesAppName(const char *aKeyValue) const;
- bool CheckHandlerMatchesAppName(const nsACString& handler) const;
-
- bool GetAppPathFromLauncher();
- bool mUseLocaleFilenames;
- nsCString mAppPath;
- bool mAppIsInPath;
-};
-
-#endif // nsgnomeshellservice_h____
diff --git a/components/shell/nsIGNOMEShellService.idl b/components/shell/nsIGNOMEShellService.idl
deleted file mode 100644
index 842ce5e..0000000
--- a/components/shell/nsIGNOMEShellService.idl
+++ /dev/null
@@ -1,19 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsIShellService.idl"
-
-[scriptable, uuid(2ce5c803-edcd-443d-98eb-ceba86d02d13)]
-interface nsIGNOMEShellService : nsIShellService
-{
- /**
- * Used to determine whether or not to offer "Set as desktop background"
- * functionality. Even if shell service is available it is not
- * guaranteed that it is able to set the background for every desktop
- * which is especially true for Linux with its many different desktop
- * environments.
- */
- readonly attribute boolean canSetDesktopBackground;
-};
-
diff --git a/components/shell/nsIMacShellService.idl b/components/shell/nsIMacShellService.idl
deleted file mode 100644
index 6a532bb..0000000
--- a/components/shell/nsIMacShellService.idl
+++ /dev/null
@@ -1,15 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsIShellService.idl"
-
-[scriptable, uuid(387fdc80-0077-4b60-a0d9-d9e80a83ba64)]
-interface nsIMacShellService : nsIShellService
-{
- const long APPLICATION_KEYCHAIN_ACCESS = 2;
- const long APPLICATION_NETWORK = 3;
- const long APPLICATION_DESKTOP = 4;
-};
-
diff --git a/components/shell/nsIShellService.idl b/components/shell/nsIShellService.idl
deleted file mode 100644
index 3e7e94b..0000000
--- a/components/shell/nsIShellService.idl
+++ /dev/null
@@ -1,95 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-interface nsIDOMElement;
-interface nsIFile;
-
-[scriptable, uuid(2d1a95e4-5bd8-4eeb-b0a8-c1455fd2a357)]
-interface nsIShellService : nsISupports
-{
- /**
- * Determines whether or not Firefox is the "Default Browser."
- * This is simply whether or not Firefox is registered to handle
- * http links.
- *
- * @param aStartupCheck true if this is the check being performed
- * by the first browser window at startup,
- * false otherwise.
- * @param aForAllTypes true if the check should be made for HTTP and HTML.
- * false if the check should be made for HTTP only.
- * This parameter may be ignored on some platforms.
- */
- boolean isDefaultBrowser(in boolean aStartupCheck,
- [optional] in boolean aForAllTypes);
-
- /**
- * Registers Firefox as the "Default Browser."
- *
- * @param aClaimAllTypes Register Firefox as the handler for
- * additional protocols (ftp, chrome etc)
- * and web documents (.html, .xhtml etc).
- * @param aForAllUsers Whether or not Firefox should attempt
- * to become the default browser for all
- * users on a multi-user system.
- */
- void setDefaultBrowser(in boolean aClaimAllTypes, in boolean aForAllUsers);
-
- /**
- * Flags for positioning/sizing of the Desktop Background image.
- */
- const long BACKGROUND_TILE = 1;
- const long BACKGROUND_STRETCH = 2;
- const long BACKGROUND_CENTER = 3;
- const long BACKGROUND_FILL = 4;
- const long BACKGROUND_FIT = 5;
-
- /**
- * Sets the desktop background image using either the HTML <IMG>
- * element supplied or the background image of the element supplied.
- *
- * @param aImageElement Either a HTML <IMG> element or an element with
- * a background image from which to source the
- * background image.
- * @param aPosition How to place the image on the desktop
- */
- void setDesktopBackground(in nsIDOMElement aElement, in long aPosition);
-
- /**
- * Constants identifying applications that can be opened with
- * openApplication.
- */
- const long APPLICATION_MAIL = 0;
- const long APPLICATION_NEWS = 1;
-
- /**
- * Opens the application specified. If more than one application of the
- * given type is available on the system, the default or "preferred"
- * application is used.
- */
- void openApplication(in long aApplication);
-
- /**
- * The desktop background color, visible when no background image is
- * used, or if the background image is centered and does not fill the
- * entire screen. A rgb value, where (r << 16 | g << 8 | b)
- */
- attribute unsigned long desktopBackgroundColor;
-
- /**
- * Opens an application with a specific URI to load.
- * @param application
- * The application file (or bundle directory, on OS X)
- * @param uri
- * The uri to be loaded by the application
- */
- void openApplicationWithURI(in nsIFile aApplication, in ACString aURI);
-
- /**
- * The default system handler for web feeds
- */
- readonly attribute nsIFile defaultFeedReader;
-};
diff --git a/components/shell/nsIWindowsShellService.idl b/components/shell/nsIWindowsShellService.idl
deleted file mode 100644
index 57ed370..0000000
--- a/components/shell/nsIWindowsShellService.idl
+++ /dev/null
@@ -1,17 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsIShellService.idl"
-
-[scriptable, uuid(f8a26b94-49e5-4441-8fbc-315e0b4f22ef)]
-interface nsIWindowsShellService : nsIShellService
-{
- /**
- * Provides the shell service an opportunity to do some Win7+ shortcut
- * maintenance needed on initial startup of the browser.
- */
- void shortcutMaintenance();
-};
-
diff --git a/components/shell/nsMacShellService.cpp b/components/shell/nsMacShellService.cpp
deleted file mode 100644
index d8d6403..0000000
--- a/components/shell/nsMacShellService.cpp
+++ /dev/null
@@ -1,434 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsDirectoryServiceDefs.h"
-#include "nsIDOMElement.h"
-#include "nsIDOMHTMLImageElement.h"
-#include "nsIImageLoadingContent.h"
-#include "nsIDocument.h"
-#include "nsIContent.h"
-#include "nsILocalFileMac.h"
-#include "nsIObserverService.h"
-#include "nsIPrefService.h"
-#include "nsIServiceManager.h"
-#include "nsIStringBundle.h"
-#include "nsIURL.h"
-#include "nsIWebBrowserPersist.h"
-#include "nsMacShellService.h"
-#include "nsIProperties.h"
-#include "nsServiceManagerUtils.h"
-#include "nsShellService.h"
-#include "nsStringAPI.h"
-#include "nsIDocShell.h"
-#include "nsILoadContext.h"
-
-#include <CoreFoundation/CoreFoundation.h>
-#include <ApplicationServices/ApplicationServices.h>
-
-#define NETWORK_PREFPANE NS_LITERAL_CSTRING("/System/Library/PreferencePanes/Network.prefPane")
-#define DESKTOP_PREFPANE NS_LITERAL_CSTRING("/System/Library/PreferencePanes/DesktopScreenEffectsPref.prefPane")
-
-#define SAFARI_BUNDLE_IDENTIFIER "com.apple.Safari"
-
-NS_IMPL_ISUPPORTS(nsMacShellService, nsIMacShellService, nsIShellService, nsIWebProgressListener)
-
-NS_IMETHODIMP
-nsMacShellService::IsDefaultBrowser(bool aStartupCheck,
- bool aForAllTypes,
- bool* aIsDefaultBrowser)
-{
- *aIsDefaultBrowser = false;
-
- CFStringRef firefoxID = ::CFBundleGetIdentifier(::CFBundleGetMainBundle());
- if (!firefoxID) {
- // CFBundleGetIdentifier is expected to return nullptr only if the specified
- // bundle doesn't have a bundle identifier in its plist. In this case, that
- // means a failure, since our bundle does have an identifier.
- return NS_ERROR_FAILURE;
- }
-
- // Get the default http handler's bundle ID (or nullptr if it has not been
- // explicitly set)
- CFStringRef defaultBrowserID = ::LSCopyDefaultHandlerForURLScheme(CFSTR("http"));
- if (defaultBrowserID) {
- *aIsDefaultBrowser = ::CFStringCompare(firefoxID, defaultBrowserID, 0) == kCFCompareEqualTo;
- ::CFRelease(defaultBrowserID);
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsMacShellService::SetDefaultBrowser(bool aClaimAllTypes, bool aForAllUsers)
-{
- // Note: We don't support aForAllUsers on Mac OS X.
-
- CFStringRef firefoxID = ::CFBundleGetIdentifier(::CFBundleGetMainBundle());
- if (!firefoxID) {
- return NS_ERROR_FAILURE;
- }
-
- if (::LSSetDefaultHandlerForURLScheme(CFSTR("http"), firefoxID) != noErr) {
- return NS_ERROR_FAILURE;
- }
- if (::LSSetDefaultHandlerForURLScheme(CFSTR("https"), firefoxID) != noErr) {
- return NS_ERROR_FAILURE;
- }
-
- if (aClaimAllTypes) {
- if (::LSSetDefaultHandlerForURLScheme(CFSTR("ftp"), firefoxID) != noErr) {
- return NS_ERROR_FAILURE;
- }
- if (::LSSetDefaultRoleHandlerForContentType(kUTTypeHTML, kLSRolesAll, firefoxID) != noErr) {
- return NS_ERROR_FAILURE;
- }
- }
-
- nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
- if (prefs) {
- (void) prefs->SetBoolPref(PREF_CHECKDEFAULTBROWSER, true);
- // Reset the number of times the dialog should be shown
- // before it is silenced.
- (void) prefs->SetIntPref(PREF_DEFAULTBROWSERCHECKCOUNT, 0);
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsMacShellService::SetDesktopBackground(nsIDOMElement* aElement,
- int32_t aPosition)
-{
- // Note: We don't support aPosition on OS X.
-
- // Get the image URI:
- nsresult rv;
- nsCOMPtr<nsIImageLoadingContent> imageContent = do_QueryInterface(aElement,
- &rv);
- NS_ENSURE_SUCCESS(rv, rv);
- nsCOMPtr<nsIURI> imageURI;
- rv = imageContent->GetCurrentURI(getter_AddRefs(imageURI));
- NS_ENSURE_SUCCESS(rv, rv);
-
- // We need the referer URI for nsIWebBrowserPersist::saveURI
- nsCOMPtr<nsIContent> content = do_QueryInterface(aElement, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsIURI *docURI = content->OwnerDoc()->GetDocumentURI();
- if (!docURI)
- return NS_ERROR_FAILURE;
-
- // Get the desired image file name
- nsCOMPtr<nsIURL> imageURL(do_QueryInterface(imageURI));
- if (!imageURL) {
- // XXXmano (bug 300293): Non-URL images (e.g. the data: protocol) are not
- // yet supported. What filename should we take here?
- return NS_ERROR_NOT_IMPLEMENTED;
- }
-
- nsAutoCString fileName;
- imageURL->GetFileName(fileName);
- nsCOMPtr<nsIProperties> fileLocator
- (do_GetService("@mozilla.org/file/directory_service;1", &rv));
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Get the current user's "Pictures" folder (That's ~/Pictures):
- fileLocator->Get(NS_OSX_PICTURE_DOCUMENTS_DIR, NS_GET_IID(nsIFile),
- getter_AddRefs(mBackgroundFile));
- if (!mBackgroundFile)
- return NS_ERROR_OUT_OF_MEMORY;
-
- nsAutoString fileNameUnicode;
- CopyUTF8toUTF16(fileName, fileNameUnicode);
-
- // and add the imgage file name itself:
- mBackgroundFile->Append(fileNameUnicode);
-
- // Download the image; the desktop background will be set in OnStateChange()
- nsCOMPtr<nsIWebBrowserPersist> wbp
- (do_CreateInstance("@mozilla.org/embedding/browser/nsWebBrowserPersist;1", &rv));
- NS_ENSURE_SUCCESS(rv, rv);
-
- uint32_t flags = nsIWebBrowserPersist::PERSIST_FLAGS_NO_CONVERSION |
- nsIWebBrowserPersist::PERSIST_FLAGS_REPLACE_EXISTING_FILES |
- nsIWebBrowserPersist::PERSIST_FLAGS_FROM_CACHE;
-
- wbp->SetPersistFlags(flags);
- wbp->SetProgressListener(this);
-
- nsCOMPtr<nsILoadContext> loadContext;
- nsCOMPtr<nsISupports> container = content->OwnerDoc()->GetContainer();
- nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(container);
- if (docShell) {
- loadContext = do_QueryInterface(docShell);
- }
-
- return wbp->SaveURI(imageURI, nullptr,
- docURI, content->OwnerDoc()->GetReferrerPolicy(),
- nullptr, nullptr,
- mBackgroundFile, loadContext);
-}
-
-NS_IMETHODIMP
-nsMacShellService::OnProgressChange(nsIWebProgress* aWebProgress,
- nsIRequest* aRequest,
- int32_t aCurSelfProgress,
- int32_t aMaxSelfProgress,
- int32_t aCurTotalProgress,
- int32_t aMaxTotalProgress)
-{
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsMacShellService::OnLocationChange(nsIWebProgress* aWebProgress,
- nsIRequest* aRequest,
- nsIURI* aLocation,
- uint32_t aFlags)
-{
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsMacShellService::OnStatusChange(nsIWebProgress* aWebProgress,
- nsIRequest* aRequest,
- nsresult aStatus,
- const char16_t* aMessage)
-{
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsMacShellService::OnSecurityChange(nsIWebProgress* aWebProgress,
- nsIRequest* aRequest,
- uint32_t aState)
-{
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsMacShellService::OnStateChange(nsIWebProgress* aWebProgress,
- nsIRequest* aRequest,
- uint32_t aStateFlags,
- nsresult aStatus)
-{
- if (aStateFlags & STATE_STOP) {
- nsCOMPtr<nsIObserverService> os(do_GetService("@mozilla.org/observer-service;1"));
- if (os)
- os->NotifyObservers(nullptr, "shell:desktop-background-changed", nullptr);
-
- bool exists = false;
- mBackgroundFile->Exists(&exists);
- if (!exists)
- return NS_OK;
-
- nsAutoCString nativePath;
- mBackgroundFile->GetNativePath(nativePath);
-
- AEDesc tAEDesc = { typeNull, nil };
- OSErr err = noErr;
- AliasHandle aliasHandle = nil;
- FSRef pictureRef;
- OSStatus status;
-
- // Convert the path into a FSRef
- status = ::FSPathMakeRef((const UInt8*)nativePath.get(), &pictureRef,
- nullptr);
- if (status == noErr) {
- err = ::FSNewAlias(nil, &pictureRef, &aliasHandle);
- if (err == noErr && aliasHandle == nil)
- err = paramErr;
-
- if (err == noErr) {
- // We need the descriptor (based on the picture file reference)
- // for the 'Set Desktop Picture' apple event.
- char handleState = ::HGetState((Handle)aliasHandle);
- ::HLock((Handle)aliasHandle);
- err = ::AECreateDesc(typeAlias, *aliasHandle,
- GetHandleSize((Handle)aliasHandle), &tAEDesc);
- // unlock the alias handler
- ::HSetState((Handle)aliasHandle, handleState);
- ::DisposeHandle((Handle)aliasHandle);
- }
- if (err == noErr) {
- AppleEvent tAppleEvent;
- OSType sig = 'MACS';
- AEBuildError tAEBuildError;
- // Create a 'Set Desktop Pictue' Apple Event
- err = ::AEBuildAppleEvent(kAECoreSuite, kAESetData, typeApplSignature,
- &sig, sizeof(OSType), kAutoGenerateReturnID,
- kAnyTransactionID, &tAppleEvent, &tAEBuildError,
- "'----':'obj '{want:type (prop),form:prop" \
- ",seld:type('dpic'),from:'null'()},data:(@)",
- &tAEDesc);
- if (err == noErr) {
- AppleEvent reply = { typeNull, nil };
- // Sent the event we built, the reply event isn't necessary
- err = ::AESend(&tAppleEvent, &reply, kAENoReply, kAENormalPriority,
- kNoTimeOut, nil, nil);
- ::AEDisposeDesc(&tAppleEvent);
- }
- }
- }
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsMacShellService::OpenApplication(int32_t aApplication)
-{
- nsresult rv = NS_OK;
- CFURLRef appURL = nil;
- OSStatus err = noErr;
-
- switch (aApplication) {
- case nsIShellService::APPLICATION_MAIL:
- {
- CFURLRef tempURL = ::CFURLCreateWithString(kCFAllocatorDefault,
- CFSTR("mailto:"), nullptr);
- err = ::LSGetApplicationForURL(tempURL, kLSRolesAll, nullptr, &appURL);
- ::CFRelease(tempURL);
- }
- break;
- case nsIShellService::APPLICATION_NEWS:
- {
- CFURLRef tempURL = ::CFURLCreateWithString(kCFAllocatorDefault,
- CFSTR("news:"), nullptr);
- err = ::LSGetApplicationForURL(tempURL, kLSRolesAll, nullptr, &appURL);
- ::CFRelease(tempURL);
- }
- break;
- case nsIMacShellService::APPLICATION_KEYCHAIN_ACCESS:
- err = ::LSGetApplicationForInfo('APPL', 'kcmr', nullptr, kLSRolesAll,
- nullptr, &appURL);
- break;
- case nsIMacShellService::APPLICATION_NETWORK:
- {
- nsCOMPtr<nsIFile> lf;
- rv = NS_NewNativeLocalFile(NETWORK_PREFPANE, true, getter_AddRefs(lf));
- NS_ENSURE_SUCCESS(rv, rv);
- bool exists;
- lf->Exists(&exists);
- if (!exists)
- return NS_ERROR_FILE_NOT_FOUND;
- return lf->Launch();
- }
- case nsIMacShellService::APPLICATION_DESKTOP:
- {
- nsCOMPtr<nsIFile> lf;
- rv = NS_NewNativeLocalFile(DESKTOP_PREFPANE, true, getter_AddRefs(lf));
- NS_ENSURE_SUCCESS(rv, rv);
- bool exists;
- lf->Exists(&exists);
- if (!exists)
- return NS_ERROR_FILE_NOT_FOUND;
- return lf->Launch();
- }
- }
-
- if (appURL && err == noErr) {
- err = ::LSOpenCFURLRef(appURL, nullptr);
- rv = err != noErr ? NS_ERROR_FAILURE : NS_OK;
-
- ::CFRelease(appURL);
- }
-
- return rv;
-}
-
-NS_IMETHODIMP
-nsMacShellService::GetDesktopBackgroundColor(uint32_t *aColor)
-{
- // This method and |SetDesktopBackgroundColor| has no meaning on Mac OS X.
- // The mac desktop preferences UI uses pictures for the few solid colors it
- // supports.
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-nsMacShellService::SetDesktopBackgroundColor(uint32_t aColor)
-{
- // This method and |GetDesktopBackgroundColor| has no meaning on Mac OS X.
- // The mac desktop preferences UI uses pictures for the few solid colors it
- // supports.
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-nsMacShellService::OpenApplicationWithURI(nsIFile* aApplication, const nsACString& aURI)
-{
- nsCOMPtr<nsILocalFileMac> lfm(do_QueryInterface(aApplication));
- CFURLRef appURL;
- nsresult rv = lfm->GetCFURL(&appURL);
- if (NS_FAILED(rv))
- return rv;
-
- const nsCString spec(aURI);
- const UInt8* uriString = (const UInt8*)spec.get();
- CFURLRef uri = ::CFURLCreateWithBytes(nullptr, uriString, aURI.Length(),
- kCFStringEncodingUTF8, nullptr);
- if (!uri)
- return NS_ERROR_OUT_OF_MEMORY;
-
- CFArrayRef uris = ::CFArrayCreate(nullptr, (const void**)&uri, 1, nullptr);
- if (!uris) {
- ::CFRelease(uri);
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- LSLaunchURLSpec launchSpec;
- launchSpec.appURL = appURL;
- launchSpec.itemURLs = uris;
- launchSpec.passThruParams = nullptr;
- launchSpec.launchFlags = kLSLaunchDefaults;
- launchSpec.asyncRefCon = nullptr;
-
- OSErr err = ::LSOpenFromURLSpec(&launchSpec, nullptr);
-
- ::CFRelease(uris);
- ::CFRelease(uri);
-
- return err != noErr ? NS_ERROR_FAILURE : NS_OK;
-}
-
-NS_IMETHODIMP
-nsMacShellService::GetDefaultFeedReader(nsIFile** _retval)
-{
- nsresult rv = NS_ERROR_FAILURE;
- *_retval = nullptr;
-
- CFStringRef defaultHandlerID = ::LSCopyDefaultHandlerForURLScheme(CFSTR("feed"));
- if (!defaultHandlerID) {
- defaultHandlerID = ::CFStringCreateWithCString(kCFAllocatorDefault,
- SAFARI_BUNDLE_IDENTIFIER,
- kCFStringEncodingASCII);
- }
-
- CFURLRef defaultHandlerURL = nullptr;
- OSStatus status = ::LSFindApplicationForInfo(kLSUnknownCreator,
- defaultHandlerID,
- nullptr, // inName
- nullptr, // outAppRef
- &defaultHandlerURL);
-
- if (status == noErr && defaultHandlerURL) {
- nsCOMPtr<nsILocalFileMac> defaultReader =
- do_CreateInstance("@mozilla.org/file/local;1", &rv);
- if (NS_SUCCEEDED(rv)) {
- rv = defaultReader->InitWithCFURL(defaultHandlerURL);
- if (NS_SUCCEEDED(rv)) {
- NS_ADDREF(*_retval = defaultReader);
- rv = NS_OK;
- }
- }
-
- ::CFRelease(defaultHandlerURL);
- }
-
- ::CFRelease(defaultHandlerID);
-
- return rv;
-}
diff --git a/components/shell/nsMacShellService.h b/components/shell/nsMacShellService.h
deleted file mode 100644
index db95278..0000000
--- a/components/shell/nsMacShellService.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef nsmacshellservice_h____
-#define nsmacshellservice_h____
-
-#include "nsIMacShellService.h"
-#include "nsIWebProgressListener.h"
-#include "nsIFile.h"
-#include "nsCOMPtr.h"
-
-class nsMacShellService : public nsIMacShellService,
- public nsIWebProgressListener
-{
-public:
- nsMacShellService() {};
-
- NS_DECL_ISUPPORTS
- NS_DECL_NSISHELLSERVICE
- NS_DECL_NSIMACSHELLSERVICE
- NS_DECL_NSIWEBPROGRESSLISTENER
-
-protected:
- virtual ~nsMacShellService() {};
-
-private:
- nsCOMPtr<nsIFile> mBackgroundFile;
-};
-
-#endif // nsmacshellservice_h____
diff --git a/components/shell/nsSetDefaultBrowser.js b/components/shell/nsSetDefaultBrowser.js
deleted file mode 100644
index c7a78c5..0000000
--- a/components/shell/nsSetDefaultBrowser.js
+++ /dev/null
@@ -1,30 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/*
- * --setDefaultBrowser commandline handler
- * Makes the current executable the "default browser".
- */
-
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-Components.utils.import("resource:///modules/ShellService.jsm");
-Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
-
-function nsSetDefaultBrowser() {}
-
-nsSetDefaultBrowser.prototype = {
- handle: function nsSetDefault_handle(aCmdline) {
- if (aCmdline.handleFlag("setDefaultBrowser", false)) {
- ShellService.setDefaultBrowser(true, true);
- }
- },
-
- helpInfo: " --setDefaultBrowser Set this app as the default browser.\n",
-
- classID: Components.ID("{F57899D0-4E2C-4ac6-9E29-50C736103B0C}"),
- QueryInterface: XPCOMUtils.generateQI([Ci.nsICommandLineHandler]),
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([nsSetDefaultBrowser]);
diff --git a/components/shell/nsSetDefaultBrowser.manifest b/components/shell/nsSetDefaultBrowser.manifest
deleted file mode 100644
index bf3c0f0..0000000
--- a/components/shell/nsSetDefaultBrowser.manifest
+++ /dev/null
@@ -1,3 +0,0 @@
-component {F57899D0-4E2C-4ac6-9E29-50C736103B0C} nsSetDefaultBrowser.js
-contract @mozilla.org/browser/default-browser-clh;1 {F57899D0-4E2C-4ac6-9E29-50C736103B0C}
-category command-line-handler m-setdefaultbrowser @mozilla.org/browser/default-browser-clh;1
diff --git a/components/shell/nsShellService.h b/components/shell/nsShellService.h
deleted file mode 100644
index 516a842..0000000
--- a/components/shell/nsShellService.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#define PREF_CHECKDEFAULTBROWSER "browser.shell.checkDefaultBrowser"
-#define PREF_SKIPDEFAULTBROWSERCHECK "browser.shell.skipDefaultBrowserCheck"
-#define PREF_DEFAULTBROWSERCHECKCOUNT "browser.shell.defaultBrowserCheckCount"
-
-#define SHELLSERVICE_PROPERTIES "chrome://browser/locale/shellservice.properties"
-#define BRAND_PROPERTIES "chrome://branding/locale/brand.properties"
-
diff --git a/components/shell/nsWindowsShellService.cpp b/components/shell/nsWindowsShellService.cpp
deleted file mode 100644
index c4039b9..0000000
--- a/components/shell/nsWindowsShellService.cpp
+++ /dev/null
@@ -1,1277 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsWindowsShellService.h"
-
-#include "imgIContainer.h"
-#include "imgIRequest.h"
-#include "mozilla/gfx/2D.h"
-#include "mozilla/RefPtr.h"
-#include "nsIDOMElement.h"
-#include "nsIDOMHTMLImageElement.h"
-#include "nsIImageLoadingContent.h"
-#include "nsIPrefService.h"
-#include "nsIPrefLocalizedString.h"
-#include "nsIServiceManager.h"
-#include "nsIStringBundle.h"
-#include "nsNetUtil.h"
-#include "nsServiceManagerUtils.h"
-#include "nsShellService.h"
-#include "nsIProcess.h"
-#include "nsICategoryManager.h"
-#include "nsBrowserCompsCID.h"
-#include "nsDirectoryServiceUtils.h"
-#include "nsAppDirectoryServiceDefs.h"
-#include "nsDirectoryServiceDefs.h"
-#include "nsIWindowsRegKey.h"
-#include "nsUnicharUtils.h"
-#include "nsIWinTaskbar.h"
-#include "nsISupportsPrimitives.h"
-#include "nsIURLFormatter.h"
-#include "nsThreadUtils.h"
-#include "nsXULAppAPI.h"
-#include "mozilla/WindowsVersion.h"
-
-#include "windows.h"
-#include "shellapi.h"
-
-#ifdef _WIN32_WINNT
-#undef _WIN32_WINNT
-#endif
-#define _WIN32_WINNT 0x0600
-#define INITGUID
-#undef NTDDI_VERSION
-#define NTDDI_VERSION NTDDI_WIN8
-// Needed for access to IApplicationActivationManager
-#include <shlobj.h>
-
-#include <mbstring.h>
-#include <shlwapi.h>
-
-#include <lm.h>
-#undef ACCESS_READ
-
-#ifndef MAX_BUF
-#define MAX_BUF 4096
-#endif
-
-#define REG_SUCCEEDED(val) \
- (val == ERROR_SUCCESS)
-
-#define REG_FAILED(val) \
- (val != ERROR_SUCCESS)
-
-#define NS_TASKBAR_CONTRACTID "@mozilla.org/windows-taskbar;1"
-
-using mozilla::IsWin8OrLater;
-using namespace mozilla;
-using namespace mozilla::gfx;
-
-NS_IMPL_ISUPPORTS(nsWindowsShellService, nsIWindowsShellService, nsIShellService)
-
-static nsresult
-OpenKeyForReading(HKEY aKeyRoot, const nsAString& aKeyName, HKEY* aKey)
-{
- const nsString &flatName = PromiseFlatString(aKeyName);
-
- DWORD res = ::RegOpenKeyExW(aKeyRoot, flatName.get(), 0, KEY_READ, aKey);
- switch (res) {
- case ERROR_SUCCESS:
- break;
- case ERROR_ACCESS_DENIED:
- return NS_ERROR_FILE_ACCESS_DENIED;
- case ERROR_FILE_NOT_FOUND:
- return NS_ERROR_NOT_AVAILABLE;
- }
-
- return NS_OK;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Default Browser Registry Settings
-//
-// The setting of these values are made by an external binary since writing
-// these values may require elevation.
-//
-// - File Extension Mappings
-// -----------------------
-// The following file extensions:
-// .htm .html .shtml .xht .xhtml
-// are mapped like so:
-//
-// HKCU\SOFTWARE\Classes\.<ext>\ (default) REG_SZ PaleMoonHTML
-//
-// as aliases to the class:
-//
-// HKCU\SOFTWARE\Classes\PaleMoonHTML\
-// DefaultIcon (default) REG_SZ <apppath>,1
-// shell\open\command (default) REG_SZ <apppath> -osint -url "%1"
-// shell\open\ddeexec (default) REG_SZ <empty string>
-//
-// - Windows Vista and above Protocol Handler
-//
-// HKCU\SOFTWARE\Classes\PaleMoonURL\ (default) REG_SZ <appname> URL
-// EditFlags REG_DWORD 2
-// FriendlyTypeName REG_SZ <appname> URL
-// DefaultIcon (default) REG_SZ <apppath>,1
-// shell\open\command (default) REG_SZ <apppath> -osint -url "%1"
-// shell\open\ddeexec (default) REG_SZ <empty string>
-//
-// - Protocol Mappings
-// -----------------
-// The following protocols:
-// HTTP, HTTPS, FTP
-// are mapped like so:
-//
-// HKCU\SOFTWARE\Classes\<protocol>\
-// DefaultIcon (default) REG_SZ <apppath>,1
-// shell\open\command (default) REG_SZ <apppath> -osint -url "%1"
-// shell\open\ddeexec (default) REG_SZ <empty string>
-//
-// - Windows Start Menu (XP SP1 and newer)
-// -------------------------------------------------
-// The following keys are set to make PaleMoon appear in the Start Menu as the
-// browser:
-//
-// HKCU\SOFTWARE\Clients\StartMenuInternet\PaleMoon.EXE\
-// (default) REG_SZ <appname>
-// DefaultIcon (default) REG_SZ <apppath>,0
-// InstallInfo HideIconsCommand REG_SZ <uninstpath> /HideShortcuts
-// InstallInfo IconsVisible REG_DWORD 1
-// InstallInfo ReinstallCommand REG_SZ <uninstpath> /SetAsDefaultAppGlobal
-// InstallInfo ShowIconsCommand REG_SZ <uninstpath> /ShowShortcuts
-// shell\open\command (default) REG_SZ <apppath>
-// shell\properties (default) REG_SZ <appname> &Options
-// shell\properties\command (default) REG_SZ <apppath> -preferences
-// shell\safemode (default) REG_SZ <appname> &Safe Mode
-// shell\safemode\command (default) REG_SZ <apppath> -safe-mode
-//
-
-// The values checked are all default values so the value name is not needed.
-typedef struct {
- const char* keyName;
- const char* valueData;
- const char* oldValueData;
-} SETTING;
-
-#define APP_REG_NAME L"Pale Moon"
-#define VAL_FILE_ICON "%APPPATH%,1"
-#define VAL_OPEN "\"%APPPATH%\" -osint -url \"%1\""
-#define OLD_VAL_OPEN "\"%APPPATH%\" -requestPending -osint -url \"%1\""
-#define DI "\\DefaultIcon"
-#define SOC "\\shell\\open\\command"
-#define SOD "\\shell\\open\\ddeexec"
-// Used for updating the FTP protocol handler's shell open command under HKCU.
-#define FTP_SOC L"Software\\Classes\\ftp\\shell\\open\\command"
-
-#define MAKE_KEY_NAME1(PREFIX, MID) \
- PREFIX MID
-
-// The DefaultIcon registry key value should never be used when checking if
-// PaleMoon is the default browser for file handlers since other applications
-// (e.g. MS Office) may modify the DefaultIcon registry key value to add Icon
-// Handlers. see http://msdn2.microsoft.com/en-us/library/aa969357.aspx for
-// more info. The FTP protocol is not checked so advanced users can set the FTP
-// handler to another application and still have PaleMoon check if it is the
-// default HTTP and HTTPS handler.
-// *** Do not add additional checks here unless you skip them when aForAllTypes
-// is false below***.
-static SETTING gSettings[] = {
- // File Handler Class
- // ***keep this as the first entry because when aForAllTypes is not set below
- // it will skip over this check.***
- { MAKE_KEY_NAME1("PaleMoonHTML", SOC), VAL_OPEN, OLD_VAL_OPEN },
-
- // Protocol Handler Class - for Vista and above
- { MAKE_KEY_NAME1("PaleMoonURL", SOC), VAL_OPEN, OLD_VAL_OPEN },
-
- // Protocol Handlers
- { MAKE_KEY_NAME1("HTTP", DI), VAL_FILE_ICON },
- { MAKE_KEY_NAME1("HTTP", SOC), VAL_OPEN, OLD_VAL_OPEN },
- { MAKE_KEY_NAME1("HTTPS", DI), VAL_FILE_ICON },
- { MAKE_KEY_NAME1("HTTPS", SOC), VAL_OPEN, OLD_VAL_OPEN }
-};
-
-// The settings to disable DDE are separate from the default browser settings
-// since they are only checked when PaleMoon is the default browser and if they
-// are incorrect they are fixed without notifying the user.
-static SETTING gDDESettings[] = {
- // File Handler Class
- { MAKE_KEY_NAME1("Software\\Classes\\PaleMoonHTML", SOD) },
-
- // Protocol Handler Class - for Vista and above
- { MAKE_KEY_NAME1("Software\\Classes\\PaleMoonURL", SOD) },
-
- // Protocol Handlers
- { MAKE_KEY_NAME1("Software\\Classes\\FTP", SOD) },
- { MAKE_KEY_NAME1("Software\\Classes\\HTTP", SOD) },
- { MAKE_KEY_NAME1("Software\\Classes\\HTTPS", SOD) }
-};
-
-nsresult
-GetHelperPath(nsAutoString& aPath)
-{
- nsresult rv;
- nsCOMPtr<nsIProperties> directoryService =
- do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<nsIFile> appHelper;
- rv = directoryService->Get(XRE_EXECUTABLE_FILE,
- NS_GET_IID(nsIFile),
- getter_AddRefs(appHelper));
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = appHelper->SetNativeLeafName(NS_LITERAL_CSTRING("uninstall"));
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = appHelper->AppendNative(NS_LITERAL_CSTRING("helper.exe"));
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = appHelper->GetPath(aPath);
-
- aPath.Insert(L'"', 0);
- aPath.Append(L'"');
- return rv;
-}
-
-nsresult
-LaunchHelper(nsAutoString& aPath)
-{
- STARTUPINFOW si = {sizeof(si), 0};
- PROCESS_INFORMATION pi = {0};
-
- if (!CreateProcessW(nullptr, (LPWSTR)aPath.get(), nullptr, nullptr, FALSE,
- 0, nullptr, nullptr, &si, &pi)) {
- return NS_ERROR_FAILURE;
- }
-
- CloseHandle(pi.hProcess);
- CloseHandle(pi.hThread);
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsWindowsShellService::ShortcutMaintenance()
-{
- nsresult rv;
-
- // XXX App ids were updated to a constant install path hash,
- // XXX this code can be removed after a few upgrade cycles.
-
- // Launch helper.exe so it can update the application user model ids on
- // shortcuts in the user's taskbar and start menu. This keeps older pinned
- // shortcuts grouped correctly after major updates. Note, we also do this
- // through the upgrade installer script, however, this is the only place we
- // have a chance to trap links created by users who do control the install/
- // update process of the browser.
-
- nsCOMPtr<nsIWinTaskbar> taskbarInfo =
- do_GetService(NS_TASKBAR_CONTRACTID);
- if (!taskbarInfo) // If we haven't built with win7 sdk features, this fails.
- return NS_OK;
-
- // Avoid if this isn't Win7+
- bool isSupported = false;
- taskbarInfo->GetAvailable(&isSupported);
- if (!isSupported)
- return NS_OK;
-
- nsAutoString appId;
- if (NS_FAILED(taskbarInfo->GetDefaultGroupId(appId)))
- return NS_ERROR_UNEXPECTED;
-
- NS_NAMED_LITERAL_CSTRING(prefName, "browser.taskbar.lastgroupid");
- nsCOMPtr<nsIPrefBranch> prefs =
- do_GetService(NS_PREFSERVICE_CONTRACTID);
- if (!prefs)
- return NS_ERROR_UNEXPECTED;
-
- nsCOMPtr<nsISupportsString> prefString;
- rv = prefs->GetComplexValue(prefName.get(),
- NS_GET_IID(nsISupportsString),
- getter_AddRefs(prefString));
- if (NS_SUCCEEDED(rv)) {
- nsAutoString version;
- prefString->GetData(version);
- if (!version.IsEmpty() && version.Equals(appId)) {
- // We're all good, get out of here.
- return NS_OK;
- }
- }
- // Update the version in prefs
- prefString =
- do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
- if (NS_FAILED(rv))
- return rv;
-
- prefString->SetData(appId);
- rv = prefs->SetComplexValue(prefName.get(),
- NS_GET_IID(nsISupportsString),
- prefString);
- if (NS_FAILED(rv)) {
- NS_WARNING("Couldn't set last user model id!");
- return NS_ERROR_UNEXPECTED;
- }
-
- nsAutoString appHelperPath;
- if (NS_FAILED(GetHelperPath(appHelperPath)))
- return NS_ERROR_UNEXPECTED;
-
- appHelperPath.AppendLiteral(" /UpdateShortcutAppUserModelIds");
-
- return LaunchHelper(appHelperPath);
-}
-
-static bool
-IsAARDefault(const RefPtr<IApplicationAssociationRegistration>& pAAR,
- LPCWSTR aClassName)
-{
- // Make sure the Prog ID matches what we have
- LPWSTR registeredApp;
- bool isProtocol = *aClassName != L'.';
- ASSOCIATIONTYPE queryType = isProtocol ? AT_URLPROTOCOL : AT_FILEEXTENSION;
- HRESULT hr = pAAR->QueryCurrentDefault(aClassName, queryType, AL_EFFECTIVE,
- &registeredApp);
- if (FAILED(hr)) {
- return false;
- }
-
- LPCWSTR progID = isProtocol ? L"PaleMoonURL" : L"PaleMoonHTML";
- bool isDefault = !wcsicmp(registeredApp, progID);
- CoTaskMemFree(registeredApp);
-
- return isDefault;
-}
-
-static void
-IsDefaultBrowserWin8(bool aCheckAllTypes, bool* aIsDefaultBrowser)
-{
- RefPtr<IApplicationAssociationRegistration> pAAR;
- HRESULT hr = CoCreateInstance(CLSID_ApplicationAssociationRegistration,
- nullptr,
- CLSCTX_INPROC,
- IID_IApplicationAssociationRegistration,
- getter_AddRefs(pAAR));
- if (FAILED(hr)) {
- return;
- }
-
- bool res = IsAARDefault(pAAR, L"http");
- if (*aIsDefaultBrowser) {
- *aIsDefaultBrowser = res;
- }
- res = IsAARDefault(pAAR, L".html");
- if (*aIsDefaultBrowser && aCheckAllTypes) {
- *aIsDefaultBrowser = res;
- }
-}
-
-/*
- * Query's the AAR for the default status.
- * This only checks for PaleMoonURL and if aCheckAllTypes is set, then
- * it also checks for PaleMoonHTML. Note that those ProgIDs are shared
- * by all PaleMoon browsers.
-*/
-bool
-nsWindowsShellService::IsDefaultBrowserVista(bool aCheckAllTypes,
- bool* aIsDefaultBrowser)
-{
- RefPtr<IApplicationAssociationRegistration> pAAR;
- HRESULT hr = CoCreateInstance(CLSID_ApplicationAssociationRegistration,
- nullptr,
- CLSCTX_INPROC,
- IID_IApplicationAssociationRegistration,
- getter_AddRefs(pAAR));
- if (FAILED(hr)) {
- return false;
- }
-
- if (aCheckAllTypes) {
- BOOL res;
- hr = pAAR->QueryAppIsDefaultAll(AL_EFFECTIVE,
- APP_REG_NAME,
- &res);
- *aIsDefaultBrowser = res;
- } else if (!IsWin8OrLater()) {
- *aIsDefaultBrowser = IsAARDefault(pAAR, L"http");
- }
-
- return true;
-}
-
-NS_IMETHODIMP
-nsWindowsShellService::IsDefaultBrowser(bool aStartupCheck,
- bool aForAllTypes,
- bool* aIsDefaultBrowser)
-{
- // Assume we're the default unless one of the several checks below tell us
- // otherwise.
- *aIsDefaultBrowser = true;
-
- wchar_t exePath[MAX_BUF];
- if (!::GetModuleFileNameW(0, exePath, MAX_BUF))
- return NS_ERROR_FAILURE;
-
- // Convert the path to a long path since GetModuleFileNameW returns the path
- // that was used to launch PaleMoon which is not necessarily a long path.
- if (!::GetLongPathNameW(exePath, exePath, MAX_BUF))
- return NS_ERROR_FAILURE;
-
- nsAutoString appLongPath(exePath);
-
- HKEY theKey;
- DWORD res;
- nsresult rv;
- wchar_t currValue[MAX_BUF];
-
- SETTING* settings = gSettings;
- if (!aForAllTypes && IsWin8OrLater()) {
- // Skip over the file handler check
- settings++;
- }
-
- SETTING* end = gSettings + sizeof(gSettings) / sizeof(SETTING);
-
- for (; settings < end; ++settings) {
- NS_ConvertUTF8toUTF16 keyName(settings->keyName);
- NS_ConvertUTF8toUTF16 valueData(settings->valueData);
- int32_t offset = valueData.Find("%APPPATH%");
- valueData.Replace(offset, 9, appLongPath);
-
- rv = OpenKeyForReading(HKEY_CLASSES_ROOT, keyName, &theKey);
- if (NS_FAILED(rv)) {
- *aIsDefaultBrowser = false;
- return NS_OK;
- }
-
- ::ZeroMemory(currValue, sizeof(currValue));
- DWORD len = sizeof currValue;
- res = ::RegQueryValueExW(theKey, L"", nullptr, nullptr,
- (LPBYTE)currValue, &len);
- // Close the key that was opened.
- ::RegCloseKey(theKey);
- if (REG_FAILED(res) ||
- _wcsicmp(valueData.get(), currValue)) {
- // Key wasn't set or was set to something other than our registry entry.
- NS_ConvertUTF8toUTF16 oldValueData(settings->oldValueData);
- offset = oldValueData.Find("%APPPATH%");
- oldValueData.Replace(offset, 9, appLongPath);
- // The current registry value doesn't match the current or the old format.
- if (_wcsicmp(oldValueData.get(), currValue)) {
- *aIsDefaultBrowser = false;
- return NS_OK;
- }
-
- res = ::RegOpenKeyExW(HKEY_CLASSES_ROOT, PromiseFlatString(keyName).get(),
- 0, KEY_SET_VALUE, &theKey);
- if (REG_FAILED(res)) {
- // If updating the open command fails try to update it using the helper
- // application when setting PaleMoon as the default browser.
- *aIsDefaultBrowser = false;
- return NS_OK;
- }
-
- const nsString &flatValue = PromiseFlatString(valueData);
- res = ::RegSetValueExW(theKey, L"", 0, REG_SZ,
- (const BYTE *) flatValue.get(),
- (flatValue.Length() + 1) * sizeof(char16_t));
- // Close the key that was created.
- ::RegCloseKey(theKey);
- if (REG_FAILED(res)) {
- // If updating the open command fails try to update it using the helper
- // application when setting PaleMoon as the default browser.
- *aIsDefaultBrowser = false;
- return NS_OK;
- }
- }
- }
-
- // Only check if PaleMoon is the default browser on Vista and above if the
- // previous checks show that PaleMoon is the default browser.
- if (*aIsDefaultBrowser) {
- IsDefaultBrowserVista(aForAllTypes, aIsDefaultBrowser);
- if (IsWin8OrLater()) {
- IsDefaultBrowserWin8(aForAllTypes, aIsDefaultBrowser);
- }
- }
-
- // To handle the case where DDE isn't disabled due for a user because there
- // account didn't perform a PaleMoon update this will check if PaleMoon is the
- // default browser and if dde is disabled for each handler
- // and if it isn't disable it. When PaleMoon is not the default browser the
- // helper application will disable dde for each handler.
- if (*aIsDefaultBrowser && aForAllTypes) {
- // Check ftp settings
-
- end = gDDESettings + sizeof(gDDESettings) / sizeof(SETTING);
-
- for (settings = gDDESettings; settings < end; ++settings) {
- NS_ConvertUTF8toUTF16 keyName(settings->keyName);
-
- rv = OpenKeyForReading(HKEY_CURRENT_USER, keyName, &theKey);
- if (NS_FAILED(rv)) {
- ::RegCloseKey(theKey);
- // If disabling DDE fails try to disable it using the helper
- // application when setting PaleMoon as the default browser.
- *aIsDefaultBrowser = false;
- return NS_OK;
- }
-
- ::ZeroMemory(currValue, sizeof(currValue));
- DWORD len = sizeof currValue;
- res = ::RegQueryValueExW(theKey, L"", nullptr, nullptr,
- (LPBYTE)currValue, &len);
- // Close the key that was opened.
- ::RegCloseKey(theKey);
- if (REG_FAILED(res) || char16_t('\0') != *currValue) {
- // Key wasn't set or was set to something other than our registry entry.
- // Delete the key along with all of its childrean and then recreate it.
- const nsString &flatName = PromiseFlatString(keyName);
- ::SHDeleteKeyW(HKEY_CURRENT_USER, flatName.get());
- res = ::RegCreateKeyExW(HKEY_CURRENT_USER, flatName.get(), 0, nullptr,
- REG_OPTION_NON_VOLATILE, KEY_SET_VALUE,
- nullptr, &theKey, nullptr);
- if (REG_FAILED(res)) {
- // If disabling DDE fails try to disable it using the helper
- // application when setting PaleMoon as the default browser.
- *aIsDefaultBrowser = false;
- return NS_OK;
- }
-
- res = ::RegSetValueExW(theKey, L"", 0, REG_SZ, (const BYTE *) L"",
- sizeof(char16_t));
- // Close the key that was created.
- ::RegCloseKey(theKey);
- if (REG_FAILED(res)) {
- // If disabling DDE fails try to disable it using the helper
- // application when setting PaleMoon as the default browser.
- *aIsDefaultBrowser = false;
- return NS_OK;
- }
- }
- }
-
- // Update the FTP protocol handler's shell open command if it is the old
- // format.
- res = ::RegOpenKeyExW(HKEY_CURRENT_USER, FTP_SOC, 0, KEY_ALL_ACCESS,
- &theKey);
- // Don't update the FTP protocol handler's shell open command when opening
- // its registry key fails under HKCU since it most likely doesn't exist.
- if (NS_FAILED(rv)) {
- return NS_OK;
- }
-
- NS_ConvertUTF8toUTF16 oldValueOpen(OLD_VAL_OPEN);
- int32_t offset = oldValueOpen.Find("%APPPATH%");
- oldValueOpen.Replace(offset, 9, appLongPath);
-
- ::ZeroMemory(currValue, sizeof(currValue));
- DWORD len = sizeof currValue;
- res = ::RegQueryValueExW(theKey, L"", nullptr, nullptr, (LPBYTE)currValue,
- &len);
-
- // Don't update the FTP protocol handler's shell open command when the
- // current registry value doesn't exist or matches the old format.
- if (REG_FAILED(res) ||
- _wcsicmp(oldValueOpen.get(), currValue)) {
- ::RegCloseKey(theKey);
- return NS_OK;
- }
-
- NS_ConvertUTF8toUTF16 valueData(VAL_OPEN);
- valueData.Replace(offset, 9, appLongPath);
- const nsString &flatValue = PromiseFlatString(valueData);
- res = ::RegSetValueExW(theKey, L"", 0, REG_SZ,
- (const BYTE *) flatValue.get(),
- (flatValue.Length() + 1) * sizeof(char16_t));
- // Close the key that was created.
- ::RegCloseKey(theKey);
- // If updating the FTP protocol handlers shell open command fails try to
- // update it using the helper application when setting PaleMoon as the
- // default browser.
- if (REG_FAILED(res)) {
- *aIsDefaultBrowser = false;
- }
- }
-
- return NS_OK;
-}
-
-static nsresult
-DynSHOpenWithDialog(HWND hwndParent, const OPENASINFO *poainfo)
-{
- // shell32.dll is in the knownDLLs list so will always be loaded from the
- // system32 directory.
- static const wchar_t kSehllLibraryName[] = L"shell32.dll";
- HMODULE shellDLL = ::LoadLibraryW(kSehllLibraryName);
- if (!shellDLL) {
- return NS_ERROR_FAILURE;
- }
-
- decltype(SHOpenWithDialog)* SHOpenWithDialogFn =
- (decltype(SHOpenWithDialog)*) GetProcAddress(shellDLL, "SHOpenWithDialog");
-
- if (!SHOpenWithDialogFn) {
- return NS_ERROR_FAILURE;
- }
-
- nsresult rv;
- HRESULT hr = SHOpenWithDialogFn(hwndParent, poainfo);
- if (SUCCEEDED(hr) || (hr == HRESULT_FROM_WIN32(ERROR_CANCELLED))) {
- rv = NS_OK;
- } else {
- rv = NS_ERROR_FAILURE;
- }
- FreeLibrary(shellDLL);
- return rv;
-}
-
-nsresult
-nsWindowsShellService::LaunchControlPanelDefaultsSelectionUI()
-{
- IApplicationAssociationRegistrationUI* pAARUI;
- HRESULT hr = CoCreateInstance(CLSID_ApplicationAssociationRegistrationUI,
- NULL,
- CLSCTX_INPROC,
- IID_IApplicationAssociationRegistrationUI,
- (void**)&pAARUI);
- if (SUCCEEDED(hr)) {
- hr = pAARUI->LaunchAdvancedAssociationUI(APP_REG_NAME);
- pAARUI->Release();
- }
- return SUCCEEDED(hr) ? NS_OK : NS_ERROR_FAILURE;
-}
-
-nsresult
-nsWindowsShellService::LaunchControlPanelDefaultPrograms()
-{
- // Build the path control.exe path safely
- WCHAR controlEXEPath[MAX_PATH + 1] = { '\0' };
- if (!GetSystemDirectoryW(controlEXEPath, MAX_PATH)) {
- return NS_ERROR_FAILURE;
- }
- LPCWSTR controlEXE = L"control.exe";
- if (wcslen(controlEXEPath) + wcslen(controlEXE) >= MAX_PATH) {
- return NS_ERROR_FAILURE;
- }
- if (!PathAppendW(controlEXEPath, controlEXE)) {
- return NS_ERROR_FAILURE;
- }
-
- WCHAR params[] = L"control.exe /name Microsoft.DefaultPrograms /page "
- "pageDefaultProgram\\pageAdvancedSettings?pszAppName=" APP_REG_NAME;
- STARTUPINFOW si = {sizeof(si), 0};
- si.dwFlags = STARTF_USESHOWWINDOW;
- si.wShowWindow = SW_SHOWDEFAULT;
- PROCESS_INFORMATION pi = {0};
- if (!CreateProcessW(controlEXEPath, params, nullptr, nullptr, FALSE,
- 0, nullptr, nullptr, &si, &pi)) {
- return NS_ERROR_FAILURE;
- }
- CloseHandle(pi.hProcess);
- CloseHandle(pi.hThread);
-
- return NS_OK;
-}
-
-static bool
-IsWindowsLogonConnected()
-{
- WCHAR userName[UNLEN + 1];
- DWORD size = ArrayLength(userName);
- if (!GetUserNameW(userName, &size)) {
- return false;
- }
-
- LPUSER_INFO_24 info;
- if (NetUserGetInfo(nullptr, userName, 24, (LPBYTE *)&info)
- != NERR_Success) {
- return false;
- }
- bool connected = info->usri24_internet_identity;
- NetApiBufferFree(info);
-
- return connected;
-}
-
-static bool
-SettingsAppBelievesConnected()
-{
- nsresult rv;
- nsCOMPtr<nsIWindowsRegKey> regKey =
- do_CreateInstance("@mozilla.org/windows-registry-key;1", &rv);
- if (NS_FAILED(rv)) {
- return false;
- }
-
- rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
- NS_LITERAL_STRING("SOFTWARE\\Microsoft\\Windows\\Shell\\Associations"),
- nsIWindowsRegKey::ACCESS_READ);
- if (NS_FAILED(rv)) {
- return false;
- }
-
- uint32_t value;
- rv = regKey->ReadIntValue(NS_LITERAL_STRING("IsConnectedAtLogon"), &value);
- if (NS_FAILED(rv)) {
- return false;
- }
-
- return !!value;
-}
-
-nsresult
-nsWindowsShellService::LaunchModernSettingsDialogDefaultApps()
-{
- if (!IsWindowsBuildOrLater(14965) &&
- !IsWindowsLogonConnected() && SettingsAppBelievesConnected()) {
- // Use the classic Control Panel to work around a bug of older
- // builds of Windows 10.
- return LaunchControlPanelDefaultPrograms();
- }
-
- IApplicationActivationManager* pActivator;
- HRESULT hr = CoCreateInstance(CLSID_ApplicationActivationManager,
- nullptr,
- CLSCTX_INPROC,
- IID_IApplicationActivationManager,
- (void**)&pActivator);
-
- if (SUCCEEDED(hr)) {
- DWORD pid;
- hr = pActivator->ActivateApplication(
- L"windows.immersivecontrolpanel_cw5n1h2txyewy"
- L"!microsoft.windows.immersivecontrolpanel",
- L"page=SettingsPageAppsDefaults", AO_NONE, &pid);
- if (SUCCEEDED(hr)) {
- // Do not check error because we could at least open
- // the "Default apps" setting.
- pActivator->ActivateApplication(
- L"windows.immersivecontrolpanel_cw5n1h2txyewy"
- L"!microsoft.windows.immersivecontrolpanel",
- L"page=SettingsPageAppsDefaults"
- L"&target=SystemSettings_DefaultApps_Browser", AO_NONE, &pid);
- }
- pActivator->Release();
- return SUCCEEDED(hr) ? NS_OK : NS_ERROR_FAILURE;
- }
- return NS_OK;
-}
-
-nsresult
-nsWindowsShellService::InvokeHTTPOpenAsVerb()
-{
- nsCOMPtr<nsIURLFormatter> formatter(
- do_GetService("@mozilla.org/toolkit/URLFormatterService;1"));
- if (!formatter) {
- return NS_ERROR_UNEXPECTED;
- }
-
- nsString urlStr;
- nsresult rv = formatter->FormatURLPref(
- NS_LITERAL_STRING("app.support.baseURL"), urlStr);
- if (NS_FAILED(rv)) {
- return rv;
- }
- if (!StringBeginsWith(urlStr, NS_LITERAL_STRING("https://"))) {
- return NS_ERROR_FAILURE;
- }
- urlStr.AppendLiteral("win10-default-browser");
-
- SHELLEXECUTEINFOW seinfo = { sizeof(SHELLEXECUTEINFOW) };
- seinfo.lpVerb = L"openas";
- seinfo.lpFile = urlStr.get();
- seinfo.nShow = SW_SHOWNORMAL;
- if (!ShellExecuteExW(&seinfo)) {
- return NS_ERROR_FAILURE;
- }
- return NS_OK;
-}
-
-nsresult
-nsWindowsShellService::LaunchHTTPHandlerPane()
-{
- OPENASINFO info;
- info.pcszFile = L"http";
- info.pcszClass = nullptr;
- info.oaifInFlags = OAIF_FORCE_REGISTRATION |
- OAIF_URL_PROTOCOL |
- OAIF_REGISTER_EXT;
- return DynSHOpenWithDialog(nullptr, &info);
-}
-
-NS_IMETHODIMP
-nsWindowsShellService::SetDefaultBrowser(bool aClaimAllTypes, bool aForAllUsers)
-{
- nsAutoString appHelperPath;
- if (NS_FAILED(GetHelperPath(appHelperPath)))
- return NS_ERROR_FAILURE;
-
- if (aForAllUsers) {
- appHelperPath.AppendLiteral(" /SetAsDefaultAppGlobal");
- } else {
- appHelperPath.AppendLiteral(" /SetAsDefaultAppUser");
- }
-
- nsresult rv = LaunchHelper(appHelperPath);
- if (NS_SUCCEEDED(rv) && IsWin8OrLater()) {
- if (aClaimAllTypes) {
- if (IsWin10OrLater()) {
- rv = LaunchModernSettingsDialogDefaultApps();
- } else {
- rv = LaunchControlPanelDefaultsSelectionUI();
- }
- // The above call should never really fail, but just in case
- // fall back to showing the HTTP association screen only.
- if (NS_FAILED(rv)) {
- if (IsWin10OrLater()) {
- rv = InvokeHTTPOpenAsVerb();
- } else {
- rv = LaunchHTTPHandlerPane();
- }
- }
- } else {
- // Windows 10 blocks attempts to load the
- // HTTP Handler association dialog.
- if (IsWin10OrLater()) {
- rv = LaunchModernSettingsDialogDefaultApps();
- } else {
- rv = LaunchHTTPHandlerPane();
- }
-
- // The above call should never really fail, but just in case
- // fall back to showing control panel for all defaults
- if (NS_FAILED(rv)) {
- rv = LaunchControlPanelDefaultsSelectionUI();
- }
- }
- }
-
- nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
- if (prefs) {
- (void) prefs->SetBoolPref(PREF_CHECKDEFAULTBROWSER, true);
- // Reset the number of times the dialog should be shown
- // before it is silenced.
- (void) prefs->SetIntPref(PREF_DEFAULTBROWSERCHECKCOUNT, 0);
- }
-
- return rv;
-}
-
-static nsresult
-WriteBitmap(nsIFile* aFile, imgIContainer* aImage)
-{
- nsresult rv;
-
- RefPtr<SourceSurface> surface =
- aImage->GetFrame(imgIContainer::FRAME_FIRST,
- imgIContainer::FLAG_SYNC_DECODE);
- NS_ENSURE_TRUE(surface, NS_ERROR_FAILURE);
-
- // For either of the following formats we want to set the biBitCount member
- // of the BITMAPINFOHEADER struct to 32, below. For that value the bitmap
- // format defines that the A8/X8 WORDs in the bitmap byte stream be ignored
- // for the BI_RGB value we use for the biCompression member.
- MOZ_ASSERT(surface->GetFormat() == SurfaceFormat::B8G8R8A8 ||
- surface->GetFormat() == SurfaceFormat::B8G8R8X8);
-
- RefPtr<DataSourceSurface> dataSurface = surface->GetDataSurface();
- NS_ENSURE_TRUE(dataSurface, NS_ERROR_FAILURE);
-
- int32_t width = dataSurface->GetSize().width;
- int32_t height = dataSurface->GetSize().height;
- int32_t bytesPerPixel = 4 * sizeof(uint8_t);
- uint32_t bytesPerRow = bytesPerPixel * width;
-
- // initialize these bitmap structs which we will later
- // serialize directly to the head of the bitmap file
- BITMAPINFOHEADER bmi;
- bmi.biSize = sizeof(BITMAPINFOHEADER);
- bmi.biWidth = width;
- bmi.biHeight = height;
- bmi.biPlanes = 1;
- bmi.biBitCount = (WORD)bytesPerPixel*8;
- bmi.biCompression = BI_RGB;
- bmi.biSizeImage = bytesPerRow * height;
- bmi.biXPelsPerMeter = 0;
- bmi.biYPelsPerMeter = 0;
- bmi.biClrUsed = 0;
- bmi.biClrImportant = 0;
-
- BITMAPFILEHEADER bf;
- bf.bfType = 0x4D42; // 'BM'
- bf.bfReserved1 = 0;
- bf.bfReserved2 = 0;
- bf.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
- bf.bfSize = bf.bfOffBits + bmi.biSizeImage;
-
- // get a file output stream
- nsCOMPtr<nsIOutputStream> stream;
- rv = NS_NewLocalFileOutputStream(getter_AddRefs(stream), aFile);
- NS_ENSURE_SUCCESS(rv, rv);
-
- DataSourceSurface::MappedSurface map;
- if (!dataSurface->Map(DataSourceSurface::MapType::READ, &map)) {
- return NS_ERROR_FAILURE;
- }
-
- // write the bitmap headers and rgb pixel data to the file
- rv = NS_ERROR_FAILURE;
- if (stream) {
- uint32_t written;
- stream->Write((const char*)&bf, sizeof(BITMAPFILEHEADER), &written);
- if (written == sizeof(BITMAPFILEHEADER)) {
- stream->Write((const char*)&bmi, sizeof(BITMAPINFOHEADER), &written);
- if (written == sizeof(BITMAPINFOHEADER)) {
- // write out the image data backwards because the desktop won't
- // show bitmaps with negative heights for top-to-bottom
- uint32_t i = map.mStride * height;
- do {
- i -= map.mStride;
- stream->Write(((const char*)map.mData) + i, bytesPerRow, &written);
- if (written == bytesPerRow) {
- rv = NS_OK;
- } else {
- rv = NS_ERROR_FAILURE;
- break;
- }
- } while (i != 0);
- }
- }
-
- stream->Close();
- }
-
- dataSurface->Unmap();
-
- return rv;
-}
-
-NS_IMETHODIMP
-nsWindowsShellService::SetDesktopBackground(nsIDOMElement* aElement,
- int32_t aPosition)
-{
- nsresult rv;
-
- nsCOMPtr<imgIContainer> container;
- nsCOMPtr<nsIDOMHTMLImageElement> imgElement(do_QueryInterface(aElement));
- if (!imgElement) {
- // XXX write background loading stuff!
- return NS_ERROR_NOT_AVAILABLE;
- }
- else {
- nsCOMPtr<nsIImageLoadingContent> imageContent =
- do_QueryInterface(aElement, &rv);
- if (!imageContent)
- return rv;
-
- // get the image container
- nsCOMPtr<imgIRequest> request;
- rv = imageContent->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
- getter_AddRefs(request));
- if (!request)
- return rv;
- rv = request->GetImage(getter_AddRefs(container));
- if (!container)
- return NS_ERROR_FAILURE;
- }
-
- // get the file name from localized strings
- nsCOMPtr<nsIStringBundleService>
- bundleService(do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv));
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<nsIStringBundle> shellBundle;
- rv = bundleService->CreateBundle(SHELLSERVICE_PROPERTIES,
- getter_AddRefs(shellBundle));
- NS_ENSURE_SUCCESS(rv, rv);
-
- // e.g. "Desktop Background.bmp"
- nsString fileLeafName;
- rv = shellBundle->GetStringFromName
- (u"desktopBackgroundLeafNameWin",
- getter_Copies(fileLeafName));
- NS_ENSURE_SUCCESS(rv, rv);
-
- // get the profile root directory
- nsCOMPtr<nsIFile> file;
- rv = NS_GetSpecialDirectory(NS_APP_APPLICATION_REGISTRY_DIR,
- getter_AddRefs(file));
- NS_ENSURE_SUCCESS(rv, rv);
-
- // eventually, the path is "%APPDATA%\Mozilla\PaleMoon\Desktop Background.bmp"
- rv = file->Append(fileLeafName);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsAutoString path;
- rv = file->GetPath(path);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // write the bitmap to a file in the profile directory
- rv = WriteBitmap(file, container);
-
- // if the file was written successfully, set it as the system wallpaper
- if (NS_SUCCEEDED(rv)) {
- nsCOMPtr<nsIWindowsRegKey> regKey =
- do_CreateInstance("@mozilla.org/windows-registry-key;1", &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = regKey->Create(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
- NS_LITERAL_STRING("Control Panel\\Desktop"),
- nsIWindowsRegKey::ACCESS_SET_VALUE);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsAutoString tile;
- nsAutoString style;
- switch (aPosition) {
- case BACKGROUND_TILE:
- style.Assign('0');
- tile.Assign('1');
- break;
- case BACKGROUND_CENTER:
- style.Assign('0');
- tile.Assign('0');
- break;
- case BACKGROUND_STRETCH:
- style.Assign('2');
- tile.Assign('0');
- break;
- case BACKGROUND_FILL:
- style.AssignLiteral("10");
- tile.Assign('0');
- break;
- case BACKGROUND_FIT:
- style.Assign('6');
- tile.Assign('0');
- break;
- }
-
- rv = regKey->WriteStringValue(NS_LITERAL_STRING("TileWallpaper"), tile);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = regKey->WriteStringValue(NS_LITERAL_STRING("WallpaperStyle"), style);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = regKey->Close();
- NS_ENSURE_SUCCESS(rv, rv);
-
- ::SystemParametersInfoW(SPI_SETDESKWALLPAPER, 0, (PVOID)path.get(),
- SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
- }
- return rv;
-}
-
-NS_IMETHODIMP
-nsWindowsShellService::OpenApplication(int32_t aApplication)
-{
- nsAutoString application;
- switch (aApplication) {
- case nsIShellService::APPLICATION_MAIL:
- application.AssignLiteral("Mail");
- break;
- case nsIShellService::APPLICATION_NEWS:
- application.AssignLiteral("News");
- break;
- }
-
- // The Default Client section of the Windows Registry looks like this:
- //
- // Clients\aClient\
- // e.g. aClient = "Mail"...
- // \Mail\(default) = Client Subkey Name
- // \Client Subkey Name
- // \Client Subkey Name\shell\open\command\
- // \Client Subkey Name\shell\open\command\(default) = path to exe
- //
-
- // Find the default application for this class.
- HKEY theKey;
- nsresult rv = OpenKeyForReading(HKEY_CLASSES_ROOT, application, &theKey);
- if (NS_FAILED(rv))
- return rv;
-
- wchar_t buf[MAX_BUF];
- DWORD type, len = sizeof buf;
- DWORD res = ::RegQueryValueExW(theKey, EmptyString().get(), 0,
- &type, (LPBYTE)&buf, &len);
-
- if (REG_FAILED(res) || !*buf)
- return NS_OK;
-
- // Close the key we opened.
- ::RegCloseKey(theKey);
-
- // Find the "open" command
- application.Append('\\');
- application.Append(buf);
- application.AppendLiteral("\\shell\\open\\command");
-
- rv = OpenKeyForReading(HKEY_CLASSES_ROOT, application, &theKey);
- if (NS_FAILED(rv))
- return rv;
-
- ::ZeroMemory(buf, sizeof(buf));
- len = sizeof buf;
- res = ::RegQueryValueExW(theKey, EmptyString().get(), 0,
- &type, (LPBYTE)&buf, &len);
- if (REG_FAILED(res) || !*buf)
- return NS_ERROR_FAILURE;
-
- // Close the key we opened.
- ::RegCloseKey(theKey);
-
- // Look for any embedded environment variables and substitute their
- // values, as |::CreateProcessW| is unable to do this.
- nsAutoString path(buf);
- int32_t end = path.Length();
- int32_t cursor = 0, temp = 0;
- ::ZeroMemory(buf, sizeof(buf));
- do {
- cursor = path.FindChar('%', cursor);
- if (cursor < 0)
- break;
-
- temp = path.FindChar('%', cursor + 1);
- ++cursor;
-
- ::ZeroMemory(&buf, sizeof(buf));
-
- ::GetEnvironmentVariableW(nsAutoString(Substring(path, cursor, temp - cursor)).get(),
- buf, sizeof(buf));
-
- // "+ 2" is to subtract the extra characters used to delimit the environment
- // variable ('%').
- path.Replace((cursor - 1), temp - cursor + 2, nsDependentString(buf));
-
- ++cursor;
- }
- while (cursor < end);
-
- STARTUPINFOW si;
- PROCESS_INFORMATION pi;
-
- ::ZeroMemory(&si, sizeof(STARTUPINFOW));
- ::ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
-
- BOOL success = ::CreateProcessW(nullptr, (LPWSTR)path.get(), nullptr,
- nullptr, FALSE, 0, nullptr, nullptr,
- &si, &pi);
- if (!success)
- return NS_ERROR_FAILURE;
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsWindowsShellService::GetDesktopBackgroundColor(uint32_t* aColor)
-{
- uint32_t color = ::GetSysColor(COLOR_DESKTOP);
- *aColor = (GetRValue(color) << 16) | (GetGValue(color) << 8) | GetBValue(color);
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsWindowsShellService::SetDesktopBackgroundColor(uint32_t aColor)
-{
- int aParameters[2] = { COLOR_BACKGROUND, COLOR_DESKTOP };
- BYTE r = (aColor >> 16);
- BYTE g = (aColor << 16) >> 24;
- BYTE b = (aColor << 24) >> 24;
- COLORREF colors[2] = { RGB(r,g,b), RGB(r,g,b) };
-
- ::SetSysColors(sizeof(aParameters) / sizeof(int), aParameters, colors);
-
- nsresult rv;
- nsCOMPtr<nsIWindowsRegKey> regKey =
- do_CreateInstance("@mozilla.org/windows-registry-key;1", &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = regKey->Create(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
- NS_LITERAL_STRING("Control Panel\\Colors"),
- nsIWindowsRegKey::ACCESS_SET_VALUE);
- NS_ENSURE_SUCCESS(rv, rv);
-
- wchar_t rgb[12];
- _snwprintf(rgb, 12, L"%u %u %u", r, g, b);
-
- rv = regKey->WriteStringValue(NS_LITERAL_STRING("Background"),
- nsDependentString(rgb));
- NS_ENSURE_SUCCESS(rv, rv);
-
- return regKey->Close();
-}
-
-nsWindowsShellService::nsWindowsShellService()
-{
-}
-
-nsWindowsShellService::~nsWindowsShellService()
-{
-}
-
-NS_IMETHODIMP
-nsWindowsShellService::OpenApplicationWithURI(nsIFile* aApplication,
- const nsACString& aURI)
-{
- nsresult rv;
- nsCOMPtr<nsIProcess> process =
- do_CreateInstance("@mozilla.org/process/util;1", &rv);
- if (NS_FAILED(rv))
- return rv;
-
- rv = process->Init(aApplication);
- if (NS_FAILED(rv))
- return rv;
-
- const nsCString spec(aURI);
- const char* specStr = spec.get();
- return process->Run(false, &specStr, 1);
-}
-
-NS_IMETHODIMP
-nsWindowsShellService::GetDefaultFeedReader(nsIFile** _retval)
-{
- *_retval = nullptr;
-
- nsresult rv;
- nsCOMPtr<nsIWindowsRegKey> regKey =
- do_CreateInstance("@mozilla.org/windows-registry-key;1", &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_CLASSES_ROOT,
- NS_LITERAL_STRING("feed\\shell\\open\\command"),
- nsIWindowsRegKey::ACCESS_READ);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsAutoString path;
- rv = regKey->ReadStringValue(EmptyString(), path);
- NS_ENSURE_SUCCESS(rv, rv);
- if (path.IsEmpty())
- return NS_ERROR_FAILURE;
-
- if (path.First() == '"') {
- // Everything inside the quotes
- path = Substring(path, 1, path.FindChar('"', 1) - 1);
- }
- else {
- // Everything up to the first space
- path = Substring(path, 0, path.FindChar(' '));
- }
-
- nsCOMPtr<nsIFile> defaultReader =
- do_CreateInstance("@mozilla.org/file/local;1", &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = defaultReader->InitWithPath(path);
- NS_ENSURE_SUCCESS(rv, rv);
-
- bool exists;
- rv = defaultReader->Exists(&exists);
- NS_ENSURE_SUCCESS(rv, rv);
- if (!exists)
- return NS_ERROR_FAILURE;
-
- NS_ADDREF(*_retval = defaultReader);
- return NS_OK;
-}
diff --git a/components/shell/nsWindowsShellService.h b/components/shell/nsWindowsShellService.h
deleted file mode 100644
index 06c6c3c..0000000
--- a/components/shell/nsWindowsShellService.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef nswindowsshellservice_h____
-#define nswindowsshellservice_h____
-
-#include "nscore.h"
-#include "nsStringAPI.h"
-#include "nsIWindowsShellService.h"
-#include "nsITimer.h"
-
-#include <windows.h>
-#include <ole2.h>
-
-class nsWindowsShellService : public nsIWindowsShellService
-{
- virtual ~nsWindowsShellService();
-
-public:
- nsWindowsShellService();
-
- NS_DECL_ISUPPORTS
- NS_DECL_NSISHELLSERVICE
- NS_DECL_NSIWINDOWSSHELLSERVICE
-
-protected:
- bool IsDefaultBrowserVista(bool aCheckAllTypes, bool* aIsDefaultBrowser);
- nsresult LaunchControlPanelDefaultsSelectionUI();
- nsresult LaunchControlPanelDefaultPrograms();
- nsresult LaunchModernSettingsDialogDefaultApps();
- nsresult InvokeHTTPOpenAsVerb();
- nsresult LaunchHTTPHandlerPane();
-};
-
-#endif // nswindowsshellservice_h____
diff --git a/components/statusbar/Downloads.jsm b/components/statusbar/Downloads.jsm
deleted file mode 100644
index 091fdad..0000000
--- a/components/statusbar/Downloads.jsm
+++ /dev/null
@@ -1,674 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const EXPORTED_SYMBOLS = ["S4EDownloadService"];
-
-const CC = Components.classes;
-const CI = Components.interfaces;
-const CU = Components.utils;
-
-CU.import("resource://gre/modules/Services.jsm");
-CU.import("resource://gre/modules/PluralForm.jsm");
-CU.import("resource://gre/modules/DownloadUtils.jsm");
-CU.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
-CU.import("resource://gre/modules/XPCOMUtils.jsm");
-
-function S4EDownloadService(window, gBrowser, service, getters)
-{
- this._window = window;
- this._gBrowser = gBrowser;
- this._service = service;
- this._getters = getters;
-
- this._handler = new JSTransferHandler(this._window, this);
-}
-
-S4EDownloadService.prototype =
-{
- _window: null,
- _gBrowser: null,
- _service: null,
- _getters: null,
-
- _handler: null,
- _listening: false,
-
- _binding: false,
- _customizing: false,
-
- _lastTime: Infinity,
-
- _dlActive: false,
- _dlPaused: false,
- _dlFinished: false,
-
- _dlCountStr: null,
- _dlTimeStr: null,
-
- _dlProgressAvg: 0,
- _dlProgressMax: 0,
- _dlProgressMin: 0,
- _dlProgressType: "active",
-
- _dlNotifyTimer: 0,
- _dlNotifyGlowTimer: 0,
-
- init: function()
- {
- if(!this._getters.downloadButton)
- {
- this.uninit();
- return;
- }
-
- if(this._listening)
- {
- return;
- }
-
- this._handler.start();
- this._listening = true;
-
- this._lastTime = Infinity;
-
- this.updateBinding();
- this.updateStatus();
- },
-
- uninit: function()
- {
- if(!this._listening)
- {
- return;
- }
-
- this._listening = false;
- this._handler.stop();
-
- this.releaseBinding();
- },
-
- destroy: function()
- {
- this.uninit();
- this._handler.destroy();
-
- ["_window", "_gBrowser", "_service", "_getters", "_handler"].forEach(function(prop)
- {
- delete this[prop];
- }, this);
- },
-
- updateBinding: function()
- {
- if(!this._listening)
- {
- this.releaseBinding();
- return;
- }
-
- switch(this._service.downloadButtonAction)
- {
- case 1: // Default
- this.attachBinding();
- break;
- default:
- this.releaseBinding();
- break;
- }
- },
-
- attachBinding: function()
- {
- if(this._binding)
- {
- return;
- }
-
- let db = this._window.DownloadsButton;
-
- db._getAnchorS4EBackup = db.getAnchor;
- db.getAnchor = this.getAnchor.bind(this);
-
- db._releaseAnchorS4EBackup = db.releaseAnchor;
- db.releaseAnchor = function() {};
-
- this._binding = true;
- },
-
- releaseBinding: function()
- {
- if(!this._binding)
- {
- return;
- }
-
- let db = this._window.DownloadsButton;
-
- db.getAnchor = db._getAnchorS4EBackup;
- db.releaseAnchor = db._releaseAnchorS4EBackup;
-
- this._binding = false;
- },
-
- customizing: function(val)
- {
- this._customizing = val;
- },
-
- updateStatus: function(lastFinished)
- {
- if(!this._getters.downloadButton)
- {
- this.uninit();
- return;
- }
-
- let numActive = 0;
- let numPaused = 0;
- let activeTotalSize = 0;
- let activeTransferred = 0;
- let activeMaxProgress = -Infinity;
- let activeMinProgress = Infinity;
- let pausedTotalSize = 0;
- let pausedTransferred = 0;
- let pausedMaxProgress = -Infinity;
- let pausedMinProgress = Infinity;
- let maxTime = -Infinity;
-
- let dls = ((this.isPrivateWindow) ? this._handler.activePrivateEntries() : this._handler.activeEntries());
- for(let dl of dls)
- {
- if(dl.state == CI.nsIDownloadManager.DOWNLOAD_DOWNLOADING)
- {
- numActive++;
- if(dl.size > 0)
- {
- if(dl.speed > 0)
- {
- maxTime = Math.max(maxTime, (dl.size - dl.transferred) / dl.speed);
- }
-
- activeTotalSize += dl.size;
- activeTransferred += dl.transferred;
-
- let currentProgress = ((dl.transferred * 100) / dl.size);
- activeMaxProgress = Math.max(activeMaxProgress, currentProgress);
- activeMinProgress = Math.min(activeMinProgress, currentProgress);
- }
- }
- else if(dl.state == CI.nsIDownloadManager.DOWNLOAD_PAUSED)
- {
- numPaused++;
- if(dl.size > 0)
- {
- pausedTotalSize += dl.size;
- pausedTransferred += dl.transferred;
-
- let currentProgress = ((dl.transferred * 100) / dl.size);
- pausedMaxProgress = Math.max(pausedMaxProgress, currentProgress);
- pausedMinProgress = Math.min(pausedMinProgress, currentProgress);
- }
- }
- }
-
- if((numActive + numPaused) == 0)
- {
- this._dlActive = false;
- this._dlFinished = lastFinished;
- this.updateButton();
- this._lastTime = Infinity;
- return;
- }
-
- let dlPaused = (numActive == 0);
- let dlStatus = ((dlPaused) ? this._getters.strings.getString("pausedDownloads")
- : this._getters.strings.getString("activeDownloads"));
- let dlCount = ((dlPaused) ? numPaused : numActive);
- let dlTotalSize = ((dlPaused) ? pausedTotalSize : activeTotalSize);
- let dlTransferred = ((dlPaused) ? pausedTransferred : activeTransferred);
- let dlMaxProgress = ((dlPaused) ? pausedMaxProgress : activeMaxProgress);
- let dlMinProgress = ((dlPaused) ? pausedMinProgress : activeMinProgress);
- let dlProgressType = ((dlPaused) ? "paused" : "active");
-
- [this._dlTimeStr, this._lastTime] = DownloadUtils.getTimeLeft(maxTime, this._lastTime);
- this._dlCountStr = PluralForm.get(dlCount, dlStatus).replace("#1", dlCount);
- this._dlProgressAvg = ((dlTotalSize == 0) ? 100 : ((dlTransferred * 100) / dlTotalSize));
- this._dlProgressMax = ((dlTotalSize == 0) ? 100 : dlMaxProgress);
- this._dlProgressMin = ((dlTotalSize == 0) ? 100 : dlMinProgress);
- this._dlProgressType = dlProgressType + ((dlTotalSize == 0) ? "-unknown" : "");
- this._dlPaused = dlPaused;
- this._dlActive = true;
- this._dlFinished = false;
-
- this.updateButton();
- },
-
- updateButton: function()
- {
- let download_button = this._getters.downloadButton;
- let download_tooltip = this._getters.downloadButtonTooltip;
- let download_progress = this._getters.downloadButtonProgress;
- let download_label = this._getters.downloadButtonLabel;
- if(!download_button)
- {
- return;
- }
-
- if(!this._dlActive)
- {
- download_button.collapsed = true;
- download_label.value = download_tooltip.label = this._getters.strings.getString("noDownloads");
-
- download_progress.collapsed = true;
- download_progress.value = 0;
-
- if(this._dlFinished && this._handler.hasPBAPI && !this.isUIShowing)
- {
- this.callAttention(download_button);
- }
- return;
- }
-
- switch(this._service.downloadProgress)
- {
- case 2:
- download_progress.value = this._dlProgressMax;
- break;
- case 3:
- download_progress.value = this._dlProgressMin;
- break;
- default:
- download_progress.value = this._dlProgressAvg;
- break;
- }
- download_progress.setAttribute("pmType", this._dlProgressType);
- download_progress.collapsed = (this._service.downloadProgress == 0);
-
- download_label.value = this.buildString(this._service.downloadLabel);
- download_tooltip.label = this.buildString(this._service.downloadTooltip);
-
- this.clearAttention(download_button);
- download_button.collapsed = false;
- },
-
- callAttention: function(download_button)
- {
- if(this._dlNotifyGlowTimer != 0)
- {
- this._window.clearTimeout(this._dlNotifyGlowTimer);
- this._dlNotifyGlowTimer = 0;
- }
-
- download_button.setAttribute("attention", "true");
-
- if(this._service.downloadNotifyTimeout)
- {
- this._dlNotifyGlowTimer = this._window.setTimeout(function(self, button)
- {
- self._dlNotifyGlowTimer = 0;
- button.removeAttribute("attention");
- }, this._service.downloadNotifyTimeout, this, download_button);
- }
- },
-
- clearAttention: function(download_button)
- {
- if(this._dlNotifyGlowTimer != 0)
- {
- this._window.clearTimeout(this._dlNotifyGlowTimer);
- this._dlNotifyGlowTimer = 0;
- }
-
- download_button.removeAttribute("attention");
- },
-
- notify: function()
- {
- if(this._dlNotifyTimer == 0 && this._service.downloadNotifyAnimate)
- {
- let download_button_anchor = this._getters.downloadButtonAnchor;
- let download_notify_anchor = this._getters.downloadNotifyAnchor;
- if(download_button_anchor)
- {
- if(!download_notify_anchor.style.transform)
- {
- let bAnchorRect = download_button_anchor.getBoundingClientRect();
- let nAnchorRect = download_notify_anchor.getBoundingClientRect();
-
- let translateX = bAnchorRect.left - nAnchorRect.left;
- translateX += .5 * (bAnchorRect.width - nAnchorRect.width);
-
- let translateY = bAnchorRect.top - nAnchorRect.top;
- translateY += .5 * (bAnchorRect.height - nAnchorRect.height);
-
- download_notify_anchor.style.transform = "translate(" + translateX + "px, " + translateY + "px)";
- }
-
- download_notify_anchor.setAttribute("notification", "finish");
- this._dlNotifyTimer = this._window.setTimeout(function(self, anchor)
- {
- self._dlNotifyTimer = 0;
- anchor.removeAttribute("notification");
- anchor.style.transform = "";
- }, 1000, this, download_notify_anchor);
- }
- }
- },
-
- clearFinished: function()
- {
- this._dlFinished = false;
- let download_button = this._getters.downloadButton;
- if(download_button)
- {
- this.clearAttention(download_button);
- }
- },
-
- getAnchor: function(aCallback)
- {
- if(this._customizing)
- {
- aCallback(null);
- return;
- }
-
- aCallback(this._getters.downloadButtonAnchor);
- },
-
- openUI: function(aEvent)
- {
- this.clearFinished();
-
- switch(this._service.downloadButtonAction)
- {
- case 1: // Firefox Default
- this._handler.openUINative();
- break;
- case 2: // Show Library
- this._window.PlacesCommandHook.showPlacesOrganizer("Downloads");
- break;
- case 3: // Show Tab
- let found = this._gBrowser.browsers.some(function(browser, index)
- {
- if("about:downloads" == browser.currentURI.spec)
- {
- this._gBrowser.selectedTab = this._gBrowser.tabContainer.childNodes[index];
- return true;
- }
- }, this);
-
- if(!found)
- {
- this._window.openUILinkIn("about:downloads", "tab");
- }
- break;
- case 4: // External Command
- let command = this._service.downloadButtonActionCommand;
- if(commend)
- {
- this._window.goDoCommand(command);
- }
- break;
- default: // Nothing
- break;
- }
-
- aEvent.stopPropagation();
- },
-
- get isPrivateWindow()
- {
- return this._handler.hasPBAPI && PrivateBrowsingUtils.isWindowPrivate(this._window);
- },
-
- get isUIShowing()
- {
- switch(this._service.downloadButtonAction)
- {
- case 1: // Firefox Default
- return this._handler.isUIShowingNative;
- case 2: // Show Library
- var organizer = Services.wm.getMostRecentWindow("Places:Organizer");
- if(organizer)
- {
- let selectedNode = organizer.PlacesOrganizer._places.selectedNode;
- let downloadsItemId = organizer.PlacesUIUtils.leftPaneQueries["Downloads"];
- return selectedNode && selectedNode.itemId === downloadsItemId;
- }
- return false;
- case 3: // Show tab
- let currentURI = this._gBrowser.currentURI;
- return currentURI && currentURI.spec == "about:downloads";
- default: // Nothing
- return false;
- }
- },
-
- buildString: function(mode)
- {
- switch(mode)
- {
- case 0:
- return this._dlCountStr;
- case 1:
- return ((this._dlPaused) ? this._dlCountStr : this._dlTimeStr);
- default:
- let compStr = this._dlCountStr;
- if(!this._dlPaused)
- {
- compStr += " (" + this._dlTimeStr + ")";
- }
- return compStr;
- }
- }
-};
-
-function JSTransferHandler(window, downloadService)
-{
- this._window = window;
-
- let api = CU.import("resource://gre/modules/Downloads.jsm", {}).Downloads;
-
- this._activePublic = new JSTransferListener(downloadService, api.getList(api.PUBLIC), false);
- this._activePrivate = new JSTransferListener(downloadService, api.getList(api.PRIVATE), true);
-}
-
-JSTransferHandler.prototype =
-{
- _window: null,
- _activePublic: null,
- _activePrivate: null,
-
- destroy: function()
- {
- this._activePublic.destroy();
- this._activePrivate.destroy();
-
- ["_window", "_activePublic", "_activePrivate"].forEach(function(prop)
- {
- delete this[prop];
- }, this);
- },
-
- start: function()
- {
- this._activePublic.start();
- this._activePrivate.start();
- },
-
- stop: function()
- {
- this._activePublic.stop();
- this._activePrivate.stop();
- },
-
- get hasPBAPI()
- {
- return true;
- },
-
- openUINative: function()
- {
- this._window.DownloadsPanel.showPanel();
- },
-
- get isUIShowingNative()
- {
- return this._window.DownloadsPanel.isPanelShowing;
- },
-
- activeEntries: function()
- {
- return this._activePublic.downloads();
- },
-
- activePrivateEntries: function()
- {
- return this._activePrivate.downloads();
- }
-};
-
-function JSTransferListener(downloadService, listPromise, isPrivate)
-{
- this._downloadService = downloadService;
- this._isPrivate = isPrivate;
- this._downloads = new Map();
-
- listPromise.then(this.initList.bind(this)).then(null, CU.reportError);
-}
-
-JSTransferListener.prototype =
-{
- _downloadService: null,
- _list: null,
- _downloads: null,
- _isPrivate: false,
- _wantsStart: false,
-
- initList: function(list)
- {
- this._list = list;
- if(this._wantsStart) {
- this.start();
- }
-
- this._list.getAll().then(this.initDownloads.bind(this)).then(null, CU.reportError);
- },
-
- initDownloads: function(downloads)
- {
- downloads.forEach(function(download)
- {
- this.onDownloadAdded(download);
- }, this);
- },
-
- destroy: function()
- {
- this._downloads.clear();
-
- ["_downloadService", "_list", "_downloads"].forEach(function(prop)
- {
- delete this[prop];
- }, this);
- },
-
- start: function()
- {
- if(!this._list)
- {
- this._wantsStart = true;
- return;
- }
-
- this._list.addView(this);
- },
-
- stop: function()
- {
- if(!this._list)
- {
- this._wantsStart = false;
- return;
- }
-
- this._list.removeView(this);
- },
-
- downloads: function()
- {
- return this._downloads.values();
- },
-
- convertToState: function(dl)
- {
- if(dl.succeeded)
- {
- return CI.nsIDownloadManager.DOWNLOAD_FINISHED;
- }
- if(dl.error && dl.error.becauseBlockedByParentalControls)
- {
- return CI.nsIDownloadManager.DOWNLOAD_BLOCKED_PARENTAL;
- }
- if(dl.error)
- {
- return CI.nsIDownloadManager.DOWNLOAD_FAILED;
- }
- if(dl.canceled && dl.hasPartialData)
- {
- return CI.nsIDownloadManager.DOWNLOAD_PAUSED;
- }
- if(dl.canceled)
- {
- return CI.nsIDownloadManager.DOWNLOAD_CANCELED;
- }
- if(dl.stopped)
- {
- return CI.nsIDownloadManager.DOWNLOAD_NOTSTARTED;
- }
- return CI.nsIDownloadManager.DOWNLOAD_DOWNLOADING;
- },
-
- onDownloadAdded: function(aDownload)
- {
- let dl = this._downloads.get(aDownload);
- if(!dl)
- {
- dl = {};
- this._downloads.set(aDownload, dl);
- }
-
- dl.state = this.convertToState(aDownload);
- dl.size = aDownload.totalBytes;
- dl.speed = aDownload.speed;
- dl.transferred = aDownload.currentBytes;
- },
-
- onDownloadChanged: function(aDownload)
- {
- this.onDownloadAdded(aDownload);
-
- if(this._isPrivate != this._downloadService.isPrivateWindow)
- {
- return;
- }
-
- this._downloadService.updateStatus(aDownload.succeeded);
-
- if(aDownload.succeeded)
- {
- this._downloadService.notify()
- }
- },
-
- onDownloadRemoved: function(aDownload)
- {
- this._downloads.delete(aDownload);
- }
-};
-
diff --git a/components/statusbar/Progress.jsm b/components/statusbar/Progress.jsm
deleted file mode 100644
index 69d55db..0000000
--- a/components/statusbar/Progress.jsm
+++ /dev/null
@@ -1,183 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const EXPORTED_SYMBOLS = ["S4EProgressService"];
-
-const CI = Components.interfaces;
-const CU = Components.utils;
-
-CU.import("resource://gre/modules/XPCOMUtils.jsm");
-
-function S4EProgressService(gBrowser, service, getters, statusService) {
- this._gBrowser = gBrowser;
- this._service = service;
- this._getters = getters;
- this._statusService = statusService;
-
- this._gBrowser.addProgressListener(this);
-}
-
-S4EProgressService.prototype =
-{
- _gBrowser: null,
- _service: null,
- _getters: null,
- _statusService: null,
-
- _busyUI: false,
-
- set value(val)
- {
- let toolbar_progress = this._getters.toolbarProgress;
- if(toolbar_progress)
- {
- toolbar_progress.value = val;
- }
-
- let throbber_progress = this._getters.throbberProgress;
- if(throbber_progress)
- {
- if(val)
- {
- throbber_progress.setAttribute("progress", val);
- }
- else
- {
- throbber_progress.removeAttribute("progress");
- }
- }
- },
-
- set collapsed(val)
- {
- let toolbar_progress = this._getters.toolbarProgress;
- if(toolbar_progress)
- {
- toolbar_progress.collapsed = val;
- }
-
- let throbber_progress = this._getters.throbberProgress;
- if(throbber_progress)
- {
- if(val)
- {
- throbber_progress.removeAttribute("busy");
- }
- else
- {
- throbber_progress.setAttribute("busy", true);
- }
- }
- },
-
- destroy: function()
- {
- this._gBrowser.removeProgressListener(this);
-
- ["_gBrowser", "_service", "_getters", "_statusService"].forEach(function(prop)
- {
- delete this[prop];
- }, this);
- },
-
- onStatusChange: function(aWebProgress, aRequest, aStatus, aMessage)
- {
- this._statusService.setNetworkStatus(aMessage, this._busyUI);
- },
-
- onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus)
- {
- let nsIWPL = CI.nsIWebProgressListener;
-
- if(!this._busyUI
- && aStateFlags & nsIWPL.STATE_START
- && aStateFlags & nsIWPL.STATE_IS_NETWORK
- && !(aStateFlags & nsIWPL.STATE_RESTORING))
- {
- this._busyUI = true;
- this.value = 0;
- this.collapsed = false;
- }
- else if(aStateFlags & nsIWPL.STATE_STOP)
- {
- if(aRequest)
- {
- let msg = "";
- let location;
- if(aRequest instanceof CI.nsIChannel || "URI" in aRequest)
- {
- location = aRequest.URI;
- if(location.spec != "about:blank")
- {
- switch (aStatus)
- {
- case Components.results.NS_BINDING_ABORTED:
- msg = this._getters.strings.getString("nv_stopped");
- break;
- case Components.results.NS_ERROR_NET_TIMEOUT:
- msg = this._getters.strings.getString("nv_timeout");
- break;
- }
- }
- }
-
- if(!msg && (!location || location.spec != "about:blank"))
- {
- msg = this._getters.strings.getString("nv_done");
- }
-
- this._statusService.setDefaultStatus(msg);
- this._statusService.setNetworkStatus("", this._busyUI);
- }
-
- if(this._busyUI)
- {
- this._busyUI = false;
- this.collapsed = true;
- this.value = 0;
- }
- }
- },
-
- onUpdateCurrentBrowser: function(aStateFlags, aStatus, aMessage, aTotalProgress)
- {
- let nsIWPL = CI.nsIWebProgressListener;
- let loadingDone = aStateFlags & nsIWPL.STATE_STOP;
-
- this.onStateChange(
- this._gBrowser.webProgress,
- { URI: this._gBrowser.currentURI },
- ((loadingDone ? nsIWPL.STATE_STOP : nsIWPL.STATE_START) | (aStateFlags & nsIWPL.STATE_IS_NETWORK)),
- aStatus
- );
-
- if(!loadingDone)
- {
- this.onProgressChange(this._gBrowser.webProgress, null, 0, 0, aTotalProgress, 1);
- this.onStatusChange(this._gBrowser.webProgress, null, 0, aMessage);
- }
- },
-
- onProgressChange: function(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress)
- {
- 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.value = percentage;
- }
- },
-
- onProgressChange64: function(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress)
- {
- return this.onProgressChange(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress);
- },
-
- QueryInterface: XPCOMUtils.generateQI([ CI.nsIWebProgressListener, CI.nsIWebProgressListener2 ])
-};
-
diff --git a/components/statusbar/Status.jsm b/components/statusbar/Status.jsm
deleted file mode 100644
index dbdd1fc..0000000
--- a/components/statusbar/Status.jsm
+++ /dev/null
@@ -1,492 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const EXPORTED_SYMBOLS = ["S4EStatusService"];
-
-const CU = Components.utils;
-
-CU.import("resource://gre/modules/Services.jsm");
-CU.import("resource://gre/modules/XPCOMUtils.jsm");
-
-function S4EStatusService(window, service, getters)
-{
- this._window = window;
- this._service = service;
- this._getters = getters;
-
- this._overLinkService = new S4EOverlinkService(this._window, this._service, this);
-}
-
-S4EStatusService.prototype =
-{
- _window: null,
- _service: null,
- _getters: null,
- _overLinkService: null,
-
- _overLink: { val: "", type: "" },
- _network: { val: "", type: "" },
- _networkXHR: { val: "", type: "" },
- _status: { val: "", type: "" },
- _jsStatus: { val: "", type: "" },
- _defaultStatus: { val: "", type: "" },
-
- _isFullScreen: false,
- _isVideo: false,
-
- _statusText: { val: "", type: "" },
- _noUpdate: false,
- _statusChromeTimeoutID: 0,
- _statusContentTimeoutID: 0,
-
- getCompositeStatusText: function()
- {
- return this._statusText.val;
- },
-
- getStatusText: function()
- {
- return this._status.val;
- },
-
- setNetworkStatus: function(status, busy)
- {
- if(busy)
- {
- this._network = { val: status, type: "network" };
- this._networkXHR = { val: "", type: "network xhr" };
- }
- else
- {
- this._networkXHR = { val: status, type: "network xhr" };
- }
- this.updateStatusField();
- },
-
- setStatusText: function(status)
- {
- this._status = { val: status, type: "status chrome" };
- this.updateStatusField();
- },
-
- setJSStatus: function(status)
- {
- this._jsStatus = { val: status, type: "status content" };
- this.updateStatusField();
- },
-
- setJSDefaultStatus: function(status)
- {
- // This was removed from Firefox in Bug 862917
- },
-
- setDefaultStatus: function(status)
- {
- this._defaultStatus = { val: status, type: "status chrome default" };
- this.updateStatusField();
- },
-
- setOverLink: function(link, aAnchor)
- {
- this._overLinkService.update(link, aAnchor);
- },
-
- setOverLinkInternal: function(link, aAnchor)
- {
- let status = this._service.status;
- let statusLinkOver = this._service.statusLinkOver;
-
- if(statusLinkOver)
- {
- link = link.replace(/[\u200e\u200f\u202a\u202b\u202c\u202d\u202e]/g, encodeURIComponent);
- if(status == statusLinkOver)
- {
- this._overLink = { val: link, type: "overLink", anchor: aAnchor };
- this.updateStatusField();
- }
- else
- {
- this.setStatusField(statusLinkOver, { val: link, type: "overLink", anchor: aAnchor }, true);
- }
- }
- },
-
- setNoUpdate: function(nu)
- {
- this._noUpdate = nu;
- },
-
- buildBinding: function() {
-
- // Object.prototype.watch() shim, based on Eli Grey's polyfill
- // object.watch
- if (!this._window.XULBrowserWindow.watch) {
- Object.defineProperty(this._window.XULBrowserWindow, "watch", {
- enumerable: false,
- configurable: true,
- writable: false,
- value: function (prop, handler) {
- var oldval = this[prop],
- newval = oldval,
- getter = function () {
- return newval;
- },
- setter = function (val) {
- oldval = newval;
- return newval = handler.call(this, prop, oldval, val);
- }
- ;
-
- try {
- if (delete this[prop]) { // can't watch constants
- Object.defineProperty(this, prop, {
- get: getter,
- set: setter,
- enumerable: true,
- configurable: true
- });
- }
- } catch(e) {
- // This fails fatally on non-configurable props, so just
- // ignore errors if it does.
- }
- }
- });
- }
-
- // object.unwatch
- if (!this._window.XULBrowserWindow.unwatch) {
- Object.defineProperty(this._window.XULBrowserWindow, "unwatch", {
- enumerable: false,
- configurable: true,
- writable: false,
- value: function (prop) {
- var val = this[prop];
- delete this[prop]; // remove accessors
- this[prop] = val;
- }
- });
- }
-
- let XULBWPropHandler = function(prop, oldval, newval) {
- CU.reportError("Attempt to modify XULBrowserWindow." + prop);
- return oldval;
- };
-
- ["updateStatusField", "onStatusChange"].forEach(function(prop)
- {
- this._window.XULBrowserWindow.unwatch(prop);
- this._window.XULBrowserWindow[prop] = function() {};
- this._window.XULBrowserWindow.watch(prop, XULBWPropHandler);
- }, this);
-
- ["getCompositeStatusText", "getStatusText", "setStatusText", "setJSStatus",
- "setJSDefaultStatus", "setDefaultStatus", "setOverLink"].forEach(function(prop)
- {
- this._window.XULBrowserWindow.unwatch(prop);
- this._window.XULBrowserWindow[prop] = this[prop].bind(this);
- this._window.XULBrowserWindow.watch(prop, XULBWPropHandler);
- }, this);
- },
-
- destroy: function()
- {
- // No need to unbind from the XULBrowserWindow, it's already null at this point
-
- this.clearTimer("_statusChromeTimeoutID");
- this.clearTimer("_statusContentTimeoutID");
-
- this._overLinkService.destroy();
-
- ["_overLink", "_network", "_networkXHR", "_status", "_jsStatus", "_defaultStatus",
- "_statusText", "_window", "_service", "_getters", "_overLinkService"].forEach(function(prop)
- {
- delete this[prop];
- }, this);
- },
-
- buildTextOrder: function()
- {
- this.__defineGetter__("_textOrder", function()
- {
- let textOrder = ["_overLink"];
- if(this._service.statusNetwork)
- {
- textOrder.push("_network");
- if(this._service.statusNetworkXHR)
- {
- textOrder.push("_networkXHR");
- }
- }
- textOrder.push("_status", "_jsStatus");
- if(this._service.statusDefault)
- {
- textOrder.push("_defaultStatus");
- }
-
- delete this._textOrder;
- return this._textOrder = textOrder;
- });
- },
-
- updateStatusField: function(force)
- {
- let text = { val: "", type: "" };
- for(let i = 0; !text.val && i < this._textOrder.length; i++)
- {
- text = this[this._textOrder[i]];
- }
-
- if(this._statusText.val != text.val || force)
- {
- if(this._noUpdate)
- {
- return;
- }
-
- this._statusText = text;
-
- this.setStatusField(this._service.status, text, false);
-
- if(text.val && this._service.statusTimeout)
- {
- this.setTimer(text.type);
- }
- }
- },
-
- setFullScreenState: function(isFullScreen, isVideo)
- {
- this._isFullScreen = isFullScreen;
- this._isVideo = isFullScreen && isVideo;
-
- this.clearStatusField();
- this.updateStatusField(true);
- },
-
- setTimer: function(type)
- {
- let typeArgs = type.split(" ", 3);
-
- if(typeArgs.length < 2 || typeArgs[0] != "status")
- {
- return;
- }
-
- if(typeArgs[1] == "chrome")
- {
- this.clearTimer("_statusChromeTimeoutID");
- this._statusChromeTimeoutID = this._window.setTimeout(function(self, isDefault)
- {
- self._statusChromeTimeoutID = 0;
- if(isDefault)
- {
- self.setDefaultStatus("");
- }
- else
- {
- self.setStatusText("");
- }
- }, this._service.statusTimeout, this, (typeArgs.length == 3 && typeArgs[2] == "default"));
- }
- else
- {
- this.clearTimer("_statusContentTimeoutID");
- this._statusContentTimeoutID = this._window.setTimeout(function(self)
- {
- self._statusContentTimeoutID = 0;
- self.setJSStatus("");
- }, this._service.statusTimeout, this);
- }
- },
-
- clearTimer: function(timerName)
- {
- if(this[timerName] != 0)
- {
- this._window.clearTimeout(this[timerName]);
- this[timerName] = 0;
- }
- },
-
- clearStatusField: function()
- {
- this._getters.statusOverlay.value = "";
-
- let status_label = this._getters.statusWidgetLabel;
- if(status_label)
- {
- status_label.value = "";
- }
-
- },
-
- setStatusField: function(location, text, allowTooltip)
- {
- if(!location)
- {
- return;
- }
-
- let label = null;
-
- if(this._isFullScreen)
- {
- switch(location)
- {
- case 1: // Toolbar
- location = 3
- break;
- case 2: // URL bar
- if(Services.prefs.getBoolPref("browser.fullscreen.autohide"))
- {
- location = 3
- }
- break;
- }
- }
-
- switch(location)
- {
- case 1: // Toolbar
- label = this._getters.statusWidgetLabel;
- break;
- case 2: // URL Bar
- break;
- case 3: // Popup
- default:
- if(this._isVideo)
- {
- return;
- }
- label = this._getters.statusOverlay;
- break;
- }
-
- if(label)
- {
- label.setAttribute("previoustype", label.getAttribute("type"));
- label.setAttribute("type", text.type);
- label.value = text.val;
- label.setAttribute("crop", text.type == "overLink" ? "center" : "end");
- }
- }
-};
-
-function S4EOverlinkService(window, service, statusService) {
- this._window = window;
- this._service = service;
- this._statusService = statusService;
-}
-
-S4EOverlinkService.prototype =
-{
- _window: null,
- _service: null,
- _statusService: null,
-
- _timer: 0,
- _currentLink: { link: "", anchor: null },
- _pendingLink: { link: "", anchor: null },
- _listening: false,
-
- update: function(aLink, aAnchor)
- {
- this.clearTimer();
- this.stopListen();
- this._pendingLink = { link: aLink, anchor: aAnchor };
-
- if(!aLink)
- {
- if(this._window.XULBrowserWindow.hideOverLinkImmediately || !this._service.statusLinkOverDelayHide)
- {
- this._show();
- }
- else
- {
- this._showDelayed();
- }
- }
- else if(this._currentLink.link || !this._service.statusLinkOverDelayShow)
- {
- this._show();
- }
- else
- {
- this._showDelayed();
- this.startListen();
- }
- },
-
- destroy: function()
- {
- this.clearTimer();
- this.stopListen();
-
- ["_currentLink", "_pendingLink", "_statusService", "_window"].forEach(function(prop)
- {
- delete this[prop];
- }, this);
- },
-
- startListen: function()
- {
- if(!this._listening)
- {
- this._window.addEventListener("mousemove", this, true);
- this._listening = true;
- }
- },
-
- stopListen: function()
- {
- if(this._listening)
- {
- this._window.removeEventListener("mousemove", this, true);
- this._listening = false;
- }
- },
-
- clearTimer: function()
- {
- if(this._timer != 0)
- {
- this._window.clearTimeout(this._timer);
- this._timer = 0;
- }
- },
-
- handleEvent: function(event)
- {
- switch(event.type)
- {
- case "mousemove":
- this.clearTimer();
- this._showDelayed();
- }
- },
-
- _showDelayed: function()
- {
- let delay = ((this._pendingLink.link)
- ? this._service.statusLinkOverDelayShow
- : this._service.statusLinkOverDelayHide);
-
- this._timer = this._window.setTimeout(function(self)
- {
- self._timer = 0;
- self._show();
- self.stopListen();
- }, delay, this);
- },
-
- _show: function()
- {
- this._currentLink = this._pendingLink;
- this._statusService.setOverLinkInternal(this._currentLink.link, this._currentLink.anchor);
- }
-};
-
diff --git a/components/statusbar/Status4Evar.jsm b/components/statusbar/Status4Evar.jsm
deleted file mode 100644
index 6400f2e..0000000
--- a/components/statusbar/Status4Evar.jsm
+++ /dev/null
@@ -1,312 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const EXPORTED_SYMBOLS = ["Status4Evar"];
-
-const CC = Components.classes;
-const CI = Components.interfaces;
-const CU = Components.utils;
-
-const s4e_service = CC["@caligonstudios.com/status4evar;1"].getService(CI.nsIStatus4Evar);
-
-CU.import("resource://gre/modules/Services.jsm");
-CU.import("resource://gre/modules/XPCOMUtils.jsm");
-CU.import("resource://gre/modules/AddonManager.jsm");
-
-CU.import("resource:///modules/statusbar/Status.jsm");
-CU.import("resource:///modules/statusbar/Progress.jsm");
-CU.import("resource:///modules/statusbar/Downloads.jsm");
-CU.import("resource:///modules/statusbar/Toolbars.jsm");
-
-function Status4Evar(window, gBrowser, toolbox)
-{
- this._window = window;
- this._toolbox = toolbox;
-
- this.getters = new S4EWindowGetters(this._window);
- this.toolbars = new S4EToolbars(this._window, gBrowser, this._toolbox, s4e_service, this.getters);
- this.statusService = new S4EStatusService(this._window, s4e_service, this.getters);
- this.progressMeter = new S4EProgressService(gBrowser, s4e_service, this.getters, this.statusService);
- this.downloadStatus = new S4EDownloadService(this._window, gBrowser, s4e_service, this.getters);
- this.sizeModeService = new SizeModeService(this._window, gBrowser, this);
-
- this._window.addEventListener("unload", this, false);
-}
-
-Status4Evar.prototype =
-{
- _window: null,
- _toolbox: null,
-
- getters: null,
- toolbars: null,
- statusService: null,
- progressMeter: null,
- downloadStatus: null,
- sizeModeService: null,
-
- setup: function()
- {
- this._toolbox.addEventListener("beforecustomization", this, false);
- this._toolbox.addEventListener("aftercustomization", this, false);
-
- this.toolbars.setup();
- this.updateWindow();
-
- // OMFG HAX! If a page is already loading, fake a network start event
- if(this._window.XULBrowserWindow._busyUI)
- {
- let nsIWPL = CI.nsIWebProgressListener;
- this.progressMeter.onStateChange(0, null, nsIWPL.STATE_START | nsIWPL.STATE_IS_NETWORK, 0);
- }
- },
-
- destroy: function()
- {
- this._window.removeEventListener("unload", this, false);
- this._toolbox.removeEventListener("aftercustomization", this, false);
- this._toolbox.removeEventListener("beforecustomization", this, false);
-
- this.getters.destroy();
- this.statusService.destroy();
- this.downloadStatus.destroy();
- this.progressMeter.destroy();
- this.toolbars.destroy();
- this.sizeModeService.destroy();
-
- ["_window", "_toolbox", "getters", "statusService", "downloadStatus",
- "progressMeter", "toolbars", "sizeModeService"].forEach(function(prop)
- {
- delete this[prop];
- }, this);
- },
-
- handleEvent: function(aEvent)
- {
- switch(aEvent.type)
- {
- case "unload":
- this.destroy();
- break;
- case "beforecustomization":
- this.beforeCustomization();
- break;
- case "aftercustomization":
- this.updateWindow();
- break;
- }
- },
-
- beforeCustomization: function()
- {
- this.toolbars.updateSplitters(false);
- this.toolbars.updateWindowGripper(false);
-
- this.statusService.setNoUpdate(true);
- let status_label = this.getters.statusWidgetLabel;
- if(status_label)
- {
- status_label.value = this.getters.strings.getString("statusText");
- }
-
- this.downloadStatus.customizing(true);
- },
-
- updateWindow: function()
- {
- this.statusService.setNoUpdate(false);
- this.getters.resetGetters();
- this.statusService.buildTextOrder();
- this.statusService.buildBinding();
- this.downloadStatus.init();
- this.downloadStatus.customizing(false);
- this.toolbars.updateSplitters(true);
-
- s4e_service.updateWindow(this._window);
- // This also handles the following:
- // * buildTextOrder()
- // * updateStatusField(true)
- // * updateWindowGripper(true)
- },
-
- launchOptions: function(currentWindow)
- {
- let optionsURL = "chrome://browser/content/statusbar/prefs.xul";
- let windows = Services.wm.getEnumerator(null);
- while (windows.hasMoreElements())
- {
- let win = windows.getNext();
- if (win.document.documentURI == optionsURL)
- {
- win.focus();
- return;
- }
- }
-
- let features = "chrome,titlebar,toolbar,centerscreen";
- try
- {
- let instantApply = Services.prefs.getBoolPref("browser.preferences.instantApply");
- features += instantApply ? ",dialog=no" : ",modal";
- }
- catch(e)
- {
- features += ",modal";
- }
- currentWindow.openDialog(optionsURL, "", features);
- }
-
-};
-
-function S4EWindowGetters(window)
-{
- this._window = window;
-}
-
-S4EWindowGetters.prototype =
-{
- _window: null,
- _getterMap:
- [
- ["addonbar", "addon-bar"],
- ["addonbarCloseButton", "addonbar-closebutton"],
- ["browserBottomBox", "browser-bottombox"],
- ["downloadButton", "status4evar-download-button"],
- ["downloadButtonTooltip", "status4evar-download-tooltip"],
- ["downloadButtonProgress", "status4evar-download-progress-bar"],
- ["downloadButtonLabel", "status4evar-download-label"],
- ["downloadButtonAnchor", "status4evar-download-anchor"],
- ["downloadNotifyAnchor", "status4evar-download-notification-anchor"],
- ["statusBar", "status4evar-status-bar"],
- ["statusWidget", "status4evar-status-widget"],
- ["statusWidgetLabel", "status4evar-status-text"],
- ["strings", "bundle_status4evar"],
- ["throbberProgress", "status4evar-throbber-widget"],
- ["toolbarProgress", "status4evar-progress-bar"]
- ],
-
- resetGetters: function()
- {
- let document = this._window.document;
-
- this._getterMap.forEach(function(getter)
- {
- let [prop, id] = getter;
- delete this[prop];
- this.__defineGetter__(prop, function()
- {
- delete this[prop];
- return this[prop] = document.getElementById(id);
- });
- }, this);
-
- delete this.statusOverlay;
- this.__defineGetter__("statusOverlay", function()
- {
- let so = this._window.XULBrowserWindow.statusTextField;
- if(!so)
- {
- return null;
- }
-
- delete this.statusOverlay;
- return this.statusOverlay = so;
- });
- },
-
- destroy: function()
- {
- this._getterMap.forEach(function(getter)
- {
- let [prop, id] = getter;
- delete this[prop];
- }, this);
-
- ["statusOverlay", "statusOverlay", "_window"].forEach(function(prop)
- {
- delete this[prop];
- }, this);
- }
-};
-
-function SizeModeService(window, gBrowser, s4e)
-{
- this._window = window;
- this._gBrowser = gBrowser;
- this._s4e = s4e;
- this._mm = this._window.messageManager;
-
- this.lastFullScreen = this._window.fullScreen;
- this.lastwindowState = this._window.windowState;
-
- if(s4e_service.advancedStatusDetectFullScreen)
- {
- this._mm.addMessageListener("status4evar@caligonstudios.com:video-detect-answer", this)
- this._mm.loadFrameScript("resource:///modules/statusbar/content-thunk.js", true);
- }
-
- this._window.addEventListener("sizemodechange", this, false);
-}
-
-SizeModeService.prototype =
-{
- _window: null,
- _gBrowser: null,
- _s4e: null,
- _mm: null,
-
- lastFullScreen: null,
- lastwindowState: null,
-
- destroy: function()
- {
- this._window.removeEventListener("sizemodechange", this, false);
-
- if(s4e_service.advancedStatusDetectFullScreen)
- {
- this._mm.removeDelayedFrameScript("resource:///modules/statusbar/content-thunk.js");
- this._mm.removeMessageListener("status4evar@caligonstudios.com:video-detect-answer", this);
- }
-
- ["_window", "_gBrowser", "_s4e", "_mm"].forEach(function(prop)
- {
- delete this[prop];
- }, this);
- },
-
- handleEvent: function(e)
- {
- if(this._window.fullScreen != this.lastFullScreen && s4e_service.advancedStatusDetectFullScreen)
- {
- this.lastFullScreen = this._window.fullScreen;
-
- if(this.lastFullScreen && s4e_service.advancedStatusDetectVideo)
- {
- this._gBrowser.selectedBrowser.messageManager.sendAsyncMessage("status4evar@caligonstudios.com:video-detect");
- }
- else
- {
- this._s4e.statusService.setFullScreenState(this.lastFullScreen, false);
- }
- }
-
- if(this._window.windowState != this.lastwindowState)
- {
- this.lastwindowState = this._window.windowState;
- this._s4e.toolbars.updateWindowGripper(true);
- }
- },
-
- receiveMessage: function(message)
- {
- if(message.name == "status4evar@caligonstudios.com:video-detect-answer")
- {
- this._s4e.statusService.setFullScreenState(this.lastFullScreen, message.data.isVideo);
- }
- },
-
- QueryInterface: XPCOMUtils.generateQI([ CI.nsIDOMEventListener, CI.nsIMessageListener ])
-};
diff --git a/components/statusbar/Toolbars.jsm b/components/statusbar/Toolbars.jsm
deleted file mode 100644
index 321efd0..0000000
--- a/components/statusbar/Toolbars.jsm
+++ /dev/null
@@ -1,221 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const EXPORTED_SYMBOLS = ["S4EToolbars"];
-
-const CI = Components.interfaces;
-const CU = Components.utils;
-
-CU.import("resource://gre/modules/Services.jsm");
-
-function S4EToolbars(window, gBrowser, toolbox, service, getters)
-{
- this._window = window;
- this._toolbox = toolbox;
- this._service = service;
- this._getters = getters;
- this._handler = new ClassicS4EToolbars(this._window, this._toolbox);
-}
-
-S4EToolbars.prototype =
-{
- _window: null,
- _toolbox: null,
- _service: null,
- _getters: null,
-
- _handler: null,
-
- setup: function()
- {
- this.updateSplitters(false);
- this.updateWindowGripper(false);
- this._handler.setup(this._service.firstRun);
- },
-
- destroy: function()
- {
- this._handler.destroy();
-
- ["_window", "_toolbox", "_service", "_getters", "_handler"].forEach(function(prop)
- {
- delete this[prop];
- }, this);
- },
-
- updateSplitters: function(action)
- {
- let document = this._window.document;
-
- let splitter_before = document.getElementById("status4evar-status-splitter-before");
- if(splitter_before)
- {
- splitter_before.parentNode.removeChild(splitter_before);
- }
-
- let splitter_after = document.getElementById("status4evar-status-splitter-after");
- if(splitter_after)
- {
- splitter_after.parentNode.removeChild(splitter_after);
- }
-
- let status = this._getters.statusWidget;
- if(!action || !status)
- {
- return;
- }
-
- let urlbar = document.getElementById("urlbar-container");
- let stop = document.getElementById("stop-button");
- let fullscreenflex = document.getElementById("fullscreenflex");
-
- let nextSibling = status.nextSibling;
- let previousSibling = status.previousSibling;
-
- function getSplitter(splitter, suffix)
- {
- if(!splitter)
- {
- splitter = document.createElement("splitter");
- splitter.id = "status4evar-status-splitter-" + suffix;
- splitter.setAttribute("resizebefore", "flex");
- splitter.setAttribute("resizeafter", "flex");
- splitter.className = "chromeclass-toolbar-additional status4evar-status-splitter";
- }
- return splitter;
- }
-
- if((previousSibling && previousSibling.flex > 0)
- || (urlbar && stop && urlbar.getAttribute("combined") && stop == previousSibling))
- {
- status.parentNode.insertBefore(getSplitter(splitter_before, "before"), status);
- }
-
- if(nextSibling && nextSibling.flex > 0 && nextSibling != fullscreenflex)
- {
- status.parentNode.insertBefore(getSplitter(splitter_after, "after"), nextSibling);
- }
- },
-
- updateWindowGripper: function(action)
- {
- let document = this._window.document;
-
- let gripper = document.getElementById("status4evar-window-gripper");
- let toolbar = this._getters.statusBar || this._getters.addonbar;
-
- if(!action || !toolbar || !this._service.addonbarWindowGripper
- || this._window.windowState != CI.nsIDOMChromeWindow.STATE_NORMAL || toolbar.toolbox.customizing)
- {
- if(gripper)
- {
- gripper.parentNode.removeChild(gripper);
- }
- return;
- }
-
- gripper = this._handler.buildGripper(toolbar, gripper, "status4evar-window-gripper");
-
- toolbar.appendChild(gripper);
- }
-};
-
-function ClassicS4EToolbars(window, toolbox)
-{
- this._window = window;
- this._toolbox = toolbox;
-}
-
-ClassicS4EToolbars.prototype =
-{
- _window: null,
- _toolbox: null,
-
- setup: function(firstRun)
- {
- let document = this._window.document;
-
- let addon_bar = document.getElementById("addon-bar");
- if(addon_bar)
- {
- let baseSet = "addonbar-closebutton"
- + ",status4evar-status-widget"
- + ",status4evar-progress-widget";
-
- // Update the defaultSet
- let defaultSet = baseSet;
- let defaultSetIgnore = ["addonbar-closebutton", "spring", "status-bar"];
- addon_bar.getAttribute("defaultset").split(",").forEach(function(item)
- {
- if(defaultSetIgnore.indexOf(item) == -1)
- {
- defaultSet += "," + item;
- }
- });
- defaultSet += ",status-bar"
- addon_bar.setAttribute("defaultset", defaultSet);
-
- // Update the currentSet
- if(firstRun)
- {
- let isCustomizableToolbar = function(aElt)
- {
- return aElt.localName == "toolbar" && aElt.getAttribute("customizable") == "true";
- }
-
- let isCustomizedAlready = false;
- let toolbars = Array.filter(this._toolbox.childNodes, isCustomizableToolbar).concat(
- Array.filter(this._toolbox.externalToolbars, isCustomizableToolbar));
- toolbars.forEach(function(toolbar)
- {
- if(toolbar.currentSet.indexOf("status4evar") > -1)
- {
- isCustomizedAlready = true;
- }
- });
-
- if(!isCustomizedAlready)
- {
- let currentSet = baseSet;
- let currentSetIgnore = ["addonbar-closebutton", "spring"];
- addon_bar.currentSet.split(",").forEach(function(item)
- {
- if(currentSetIgnore.indexOf(item) == -1)
- {
- currentSet += "," + item;
- }
- });
- addon_bar.currentSet = currentSet;
- addon_bar.setAttribute("currentset", currentSet);
- document.persist(addon_bar.id, "currentset");
- this._window.setToolbarVisibility(addon_bar, true);
- }
- }
- }
- },
-
- destroy: function()
- {
- ["_window", "_toolbox"].forEach(function(prop)
- {
- delete this[prop];
- }, this);
- },
-
- buildGripper: function(toolbar, gripper, id)
- {
- if(!gripper)
- {
- let document = this._window.document;
-
- gripper = document.createElement("resizer");
- gripper.id = id;
- gripper.dir = "bottomend";
- }
-
- return gripper;
- }
-};
diff --git a/components/statusbar/content-thunk.js b/components/statusbar/content-thunk.js
deleted file mode 100644
index fe1fbab..0000000
--- a/components/statusbar/content-thunk.js
+++ /dev/null
@@ -1,23 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-function handleVideoDetect(message)
-{
- let isVideo = false;
-
- let fsEl = content.document.mozFullScreenElement;
- if(fsEl)
- {
- isVideo = (
- fsEl.nodeName == "VIDEO"
- || (fsEl.nodeName == "IFRAME" && fsEl.contentDocument && fsEl.contentDocument.getElementsByTagName("VIDEO").length > 0)
- || fsEl.getElementsByTagName("VIDEO").length > 0
- );
- }
-
- sendAsyncMessage("status4evar@caligonstudios.com:video-detect-answer", {isVideo: isVideo});
-}
-
-addMessageListener("status4evar@caligonstudios.com:video-detect", handleVideoDetect);
-
diff --git a/components/statusbar/content/overlay.css b/components/statusbar/content/overlay.css
deleted file mode 100644
index fd34521..0000000
--- a/components/statusbar/content/overlay.css
+++ /dev/null
@@ -1,14 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
-
-/*
- * Status Popup
- */
-
-statuspanel {
- -moz-binding: url("chrome://browser/content/statusbar/tabbrowser.xml#statuspanel");
-}
-
diff --git a/components/statusbar/content/overlay.js b/components/statusbar/content/overlay.js
deleted file mode 100644
index b868aaf..0000000
--- a/components/statusbar/content/overlay.js
+++ /dev/null
@@ -1,16 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-if(!caligon) var caligon = {};
-
-window.addEventListener("load", function buildS4E()
-{
- window.removeEventListener("load", buildS4E, false);
-
- Components.utils.import("resource:///modules/statusbar/Status4Evar.jsm");
-
- caligon.status4evar = new Status4Evar(window, gBrowser, gNavToolbox);
- caligon.status4evar.setup();
-}, false);
-
diff --git a/components/statusbar/content/overlay.xul b/components/statusbar/content/overlay.xul
deleted file mode 100644
index b9934ee..0000000
--- a/components/statusbar/content/overlay.xul
+++ /dev/null
@@ -1,82 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!DOCTYPE overlay SYSTEM "chrome://browser/locale/statusbar/statusbar-overlay.dtd">
-
-<?xml-stylesheet href="chrome://browser/content/statusbar/overlay.css" type="text/css" ?>
-<?xml-stylesheet href="chrome://browser/skin/statusbar/overlay.css" type="text/css" ?>
-<?xml-stylesheet href="chrome://browser/skin/statusbar/dynamic.css" type="text/css" ?>
-
-<overlay id="status4evar-overlay"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-
- <stringbundleset id="stringbundleset">
- <stringbundle id="bundle_status4evar" src="chrome://browser/locale/statusbar/overlay.properties" />
- </stringbundleset>
-
- <script type="application/javascript" src="chrome://browser/content/statusbar/overlay.js" />
-
- <commandset>
- <command id="S4E:Options" oncommand="caligon.status4evar.launchOptions(window);"/>
- </commandset>
-
- <popupset id="mainPopupSet">
- <hbox id="status4evar-download-notification-container" mousethrough="always">
- <vbox id="status4evar-download-notification-anchor">
- <vbox id="status4evar-download-notification-icon" />
- </vbox>
- </hbox>
- </popupset>
-
- <menupopup id="menu_ToolsPopup">
- <menuitem id="statusbar-options-fx" command="S4E:Options"
- label="&status4evar.menu.options.label;"/>
- </menupopup>
-
- <menupopup id="appmenu_customizeMenu">
- <menuitem id="statusbar-options-app" command="S4E:Options"
- label="&status4evar.menu.options.label;"/>
- </menupopup>
-
- <toolbarpalette id="BrowserToolbarPalette">
- <toolbaritem id="status4evar-status-widget"
- title="&status4evar.status.widget.title;"
- removable="true" flex="1" persist="width" width="100">
- <label id="status4evar-status-text" flex="1" crop="end" value="&status4evar.status.widget.title;" />
- </toolbaritem>
-
- <toolbarbutton id="status4evar-download-button"
- title="&status4evar.download.widget.title;"
- class="toolbarbutton-1 chromeclass-toolbar-additional"
- removable="true" collapsed="true" tooltip="_child"
- oncommand="caligon.status4evar.downloadStatus.openUI(event)">
- <stack id="status4evar-download-anchor" class="toolbarbutton-icon">
- <vbox id="status4evar-download-icon" />
- <vbox pack="end">
- <progressmeter id="status4evar-download-progress-bar" mode="normal" value="0" collapsed="true" min="0" max="100" />
- </vbox>
- </stack>
- <tooltip id="status4evar-download-tooltip" />
- <label id="status4evar-download-label" value="&status4evar.download.widget.title;" class="toolbarbutton-text" crop="right" flex="1" />
- </toolbarbutton>
-
- <toolbaritem id="status4evar-progress-widget"
- title="&status4evar.progress.widget.title;"
- removable="true">
- <progressmeter id="status4evar-progress-bar" class="progressmeter-statusbar"
- mode="normal" value="0" collapsed="true" min="0" max="100" />
- </toolbaritem>
-
- <toolbarbutton id="status4evar-options-button"
- title="&status4evar.options.widget.title;"
- class="toolbarbutton-1 chromeclass-toolbar-additional"
- label="&status4evar.options.widget.label;"
- removable="true" command="S4E:Options" tooltiptext="&status4evar.options.widget.title;" />
- </toolbarpalette>
-
- <statusbar id="status-bar" ordinal="1" />
-</overlay>
-
diff --git a/components/statusbar/content/prefs.css b/components/statusbar/content/prefs.css
deleted file mode 100644
index bafaa61..0000000
--- a/components/statusbar/content/prefs.css
+++ /dev/null
@@ -1,10 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
-
-.css-bg-editor {
- -moz-binding: url("chrome://browser/content/statusbar/prefs.xml#css-bg-editor");
-}
-
diff --git a/components/statusbar/content/prefs.js b/components/statusbar/content/prefs.js
deleted file mode 100644
index 47fd4b6..0000000
--- a/components/statusbar/content/prefs.js
+++ /dev/null
@@ -1,274 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-Components.utils.import("resource://gre/modules/Services.jsm");
-
-var status4evarPrefs =
-{
- get dynamicProgressStyle()
- {
- let styleSheets = window.document.styleSheets;
- for(let i = 0; i < styleSheets.length; i++)
- {
- let styleSheet = styleSheets[i];
- if(styleSheet.href == "chrome://browser/skin/statusbar/dynamic.css")
- {
- delete this.dynamicProgressStyle;
- return this.dynamicProgressStyle = styleSheet;
- }
- }
-
- return null;
- },
-
-//
-// Status timeout management
-//
- get statusTimeoutPref()
- {
- delete this.statusTimeoutPref;
- return this.statusTimeoutPref = document.getElementById("status4evar-pref-status-timeout");
- },
-
- get statusTimeoutCheckbox()
- {
- delete this.statusTimeoutCheckbox;
- return this.statusTimeoutCheckbox = document.getElementById("status4evar-status-timeout-check");
- },
-
- statusTimeoutChanged: function()
- {
- if(this.statusTimeoutPref.value > 0)
- {
- this.statusTimeoutPref.disabled = false;
- this.statusTimeoutCheckbox.checked = true;
- }
- else
- {
- this.statusTimeoutPref.disabled = true;
- this.statusTimeoutCheckbox.checked = false;
- }
- },
-
- statusTimeoutSync: function()
- {
- this.statusTimeoutChanged();
- return undefined;
- },
-
- statusTimeoutToggle: function()
- {
- if(this.statusTimeoutPref.disabled == this.statusTimeoutCheckbox.checked)
- {
- if(this.statusTimeoutCheckbox.checked)
- {
- this.statusTimeoutPref.value = 10;
- }
- else
- {
- this.statusTimeoutPref.value = 0;
- }
- }
- },
-
-//
-// Status network management
-//
- get statusNetworkPref()
- {
- delete this.statusNetworkPref;
- return this.statusNetworkPref = document.getElementById("status4evar-pref-status-network");
- },
-
- get statusNetworkXHRPref()
- {
- delete this.statusNetworkXHRPref;
- return this.statusNetworkXHRPref = document.getElementById("status4evar-pref-status-network-xhr");
- },
-
- statusNetworkChanged: function()
- {
- this.statusNetworkXHRPref.disabled = ! this.statusNetworkPref.value;
- },
-
- statusNetworkSync: function()
- {
- this.statusNetworkChanged();
- return undefined;
- },
-
-//
-// Status Text langth managment
-//
- get textMaxLengthPref()
- {
- delete this.textMaxLengthPref;
- return this.textMaxLengthPref = document.getElementById("status4evar-pref-status-toolbar-maxLength");
- },
-
- get textMaxLengthCheckbox()
- {
- delete this.textMaxLengthCheckbox;
- return this.textMaxLengthCheckbox = document.getElementById("status4evar-status-toolbar-maxLength-check");
- },
-
- textLengthChanged: function()
- {
- if(this.textMaxLengthPref.value > 0)
- {
- this.textMaxLengthPref.disabled = false;
- this.textMaxLengthCheckbox.checked = true;
- }
- else
- {
- this.textMaxLengthPref.disabled = true;
- this.textMaxLengthCheckbox.checked = false;
- }
- },
-
- textLengthSync: function()
- {
- this.textLengthChanged();
- return undefined;
- },
-
- textLengthToggle: function()
- {
- if(this.textMaxLengthPref.disabled == this.textMaxLengthCheckbox.checked)
- {
- if(this.textMaxLengthCheckbox.checked)
- {
- this.textMaxLengthPref.value = 800;
- }
- else
- {
- this.textMaxLengthPref.value = 0;
- }
- }
- },
-
-//
-// Toolbar progress style management
-//
- get progressToolbarStylePref()
- {
- delete this.progressToolbarStylePref;
- return this.progressToolbarStylePref = document.getElementById("status4evar-pref-progress-toolbar-style");
- },
-
- get progressToolbarCSSPref()
- {
- delete this.progressToolbarCSSPref;
- return this.progressToolbarCSSPref = document.getElementById("status4evar-pref-progress-toolbar-css");
- },
-
- get progressToolbarProgress()
- {
- delete this.progressToolbarProgress;
- return this.progressToolbarProgress = document.getElementById("status4evar-progress-bar");
- },
-
- progressToolbarCSSChanged: function()
- {
- if(!this.progressToolbarCSSPref.value)
- {
- this.progressToolbarCSSPref.value = "#33FF33";
- }
- this.dynamicProgressStyle.cssRules[1].style.background = this.progressToolbarCSSPref.value;
- },
-
- progressToolbarStyleChanged: function()
- {
- this.progressToolbarCSSChanged();
- this.progressToolbarCSSPref.disabled = !this.progressToolbarStylePref.value;
- if(this.progressToolbarStylePref.value)
- {
- this.progressToolbarProgress.setAttribute("s4estyle", true);
- }
- else
- {
- this.progressToolbarProgress.removeAttribute("s4estyle");
- }
- },
-
- progressToolbarStyleSync: function()
- {
- this.progressToolbarStyleChanged();
- return undefined;
- },
-
-//
-// Download progress management
-//
- get downloadProgressCheck()
- {
- delete this.downloadProgressCheck;
- return this.downloadProgressCheck = document.getElementById("status4evar-download-progress-check");
- },
-
- get downloadProgressPref()
- {
- delete this.downloadProgressPref;
- return this.downloadProgressPref = document.getElementById("status4evar-pref-download-progress");
- },
-
- get downloadProgressColorActivePref()
- {
- delete this.downloadProgressActiveColorPref;
- return this.downloadProgressActiveColorPref = document.getElementById("status4evar-pref-download-color-active");
- },
-
- get downloadProgressColorPausedPref()
- {
- delete this.downloadProgressPausedColorPref;
- return this.downloadProgressPausedColorPref = document.getElementById("status4evar-pref-download-color-paused");
- },
-
- downloadProgressSync: function()
- {
- let val = this.downloadProgressPref.value;
- this.downloadProgressColorActivePref.disabled = (val == 0);
- this.downloadProgressColorPausedPref.disabled = (val == 0);
- this.downloadProgressPref.disabled = (val == 0);
- this.downloadProgressCheck.checked = (val != 0);
- return ((val == 0) ? 1 : val);
- },
-
- downloadProgressToggle: function()
- {
- let enabled = this.downloadProgressCheck.checked;
- this.downloadProgressPref.value = ((enabled) ? 1 : 0);
- },
-
-//
-// Pref Window load
-//
- get downloadButtonActionCommandPref()
- {
- delete this.downloadButtonActionCommandPref;
- return this.downloadButtonActionCommandPref = document.getElementById("status4evar-pref-download-button-action-command");
- },
-
- get downloadButtonActionThirdPartyItem()
- {
- delete this.downloadButtonActionThirdPartyItem;
- return this.downloadButtonActionThirdPartyItem = document.getElementById("status4evar-download-button-action-menu-thirdparty");
- },
-
- onPrefWindowLoad: function()
- {
- if(!this.downloadButtonActionCommandPref.value)
- {
- this.downloadButtonActionThirdPartyItem.disabled = true;
- }
- },
-
- onPrefWindowUnLoad: function()
- {
- }
-}
-
-var XULBrowserWindow = {
-}
-
diff --git a/components/statusbar/content/prefs.xml b/components/statusbar/content/prefs.xml
deleted file mode 100644
index 44baab1..0000000
--- a/components/statusbar/content/prefs.xml
+++ /dev/null
@@ -1,704 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!DOCTYPE bindings SYSTEM "chrome://browser/locale/statusbar/statusbar-prefs.dtd">
-
-<bindings id="status4evar-prefs-bindings"
- xmlns="http://www.mozilla.org/xbl"
- xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:xbl="http://www.mozilla.org/xbl">
-
- <binding id="css-bg-editor">
- <content sizetopopup="pref">
- <xul:vbox flex="1">
- <xul:deck anonid="css-bg-editor-deck" flex="1">
- <xul:vbox>
- <xul:hbox align="center">
- <xul:label xbl:inherits="disabled">&status4evar.editor.css.color.label;</xul:label>
- <xul:colorpicker anonid="css-bg-editor-color" type="button" onchange="this._editor._buildCSS();" xbl:inherits="disabled" />
- </xul:hbox>
-
- <xul:hbox align="center">
- <xul:label xbl:inherits="disabled">&status4evar.editor.css.image.label;</xul:label>
- <xul:textbox anonid="css-bg-editor-image" readonly="true" flex="1" xbl:inherits="disabled" />
- <xul:button anonid="css-bg-editor-image-browse" label="&status4evar.option.browse;" oncommand="this._editor._imageBrowse();" xbl:inherits="disabled" />
- </xul:hbox>
- <xul:hbox align="center" pack="end">
- <xul:button anonid="css-bg-editor-image-clear" label="&status4evar.option.clear;" oncommand="this._editor._imageClear();" xbl:inherits="disabled=no-image" />
- </xul:hbox>
-
- <xul:hbox>
- <xul:groupbox pack="center">
- <xul:caption label="" />
- <xul:hbox flex="1" align="center">
- <xul:label>X</xul:label>
- </xul:hbox>
- <xul:separator class="groove" orient="horizontal" />
- <xul:hbox flex="1" align="center">
- <xul:label>Y</xul:label>
- </xul:hbox>
- </xul:groupbox>
-
- <xul:groupbox>
- <xul:caption label="&status4evar.editor.css.image.repeat;" xbl:inherits="disabled=no-image" />
- <xul:menulist anonid="css-bg-editor-image-repeat-x" sizetopopup="always" onselect="this._editor._buildCSS();" xbl:inherits="disabled=no-image">
- <xul:menupopup>
- <xul:menuitem label="&status4evar.option.no-repeat;" value="no-repeat" />
- <xul:menuitem label="&status4evar.option.repeat;" value="repeat" />
-<!--
- <xul:menuitem label="&status4evar.option.space;" value="space" />
- <xul:menuitem label="&status4evar.option.round;" value="round" />
--->
- </xul:menupopup>
- </xul:menulist>
- <xul:separator class="groove" orient="horizontal" />
- <xul:menulist anonid="css-bg-editor-image-repeat-y" sizetopopup="always" onselect="this._editor._buildCSS();" xbl:inherits="disabled=no-image">
- <xul:menupopup>
- <xul:menuitem label="&status4evar.option.no-repeat;" value="no-repeat" />
- <xul:menuitem label="&status4evar.option.repeat;" value="repeat" />
-<!--
- <xul:menuitem label="&status4evar.option.space;" value="space" />
- <xul:menuitem label="&status4evar.option.round;" value="round" />
--->
- </xul:menupopup>
- </xul:menulist>
- </xul:groupbox>
-
- <xul:groupbox>
- <xul:caption label="&status4evar.editor.css.image.position;" xbl:inherits="disabled=no-image" />
- <xul:menulist anonid="css-bg-editor-image-position-x" sizetopopup="always" onselect="this._editor._updatePositionX();" xbl:inherits="disabled=no-image">
- <xul:menupopup>
- <xul:menuitem label="&status4evar.option.left;" value="left" />
- <xul:menuitem label="&status4evar.option.center;" value="center" />
- <xul:menuitem label="&status4evar.option.right;" value="right" />
- <xul:menuitem label="&status4evar.option.offset;" value="offset" />
- </xul:menupopup>
- </xul:menulist>
- <xul:separator class="groove" orient="horizontal" />
- <xul:menulist anonid="css-bg-editor-image-position-y" sizetopopup="always" onselect="this._editor._updatePositionY();" xbl:inherits="disabled=no-image">
- <xul:menupopup>
- <xul:menuitem label="&status4evar.option.top;" value="top" />
- <xul:menuitem label="&status4evar.option.center;" value="center" />
- <xul:menuitem label="&status4evar.option.bottom;" value="bottom" />
- <xul:menuitem label="&status4evar.option.offset;" value="offset" />
- </xul:menupopup>
- </xul:menulist>
- </xul:groupbox>
-
- <xul:groupbox>
- <xul:caption label="&status4evar.editor.css.image.offset;" xbl:inherits="disabled=no-image" />
- <xul:hbox>
- <xul:textbox anonid="css-bg-editor-image-offset-x" type="number" size="4" min="-65535" onchange="this._editor._buildCSS();" />
- <xul:menulist anonid="css-bg-editor-image-offset-unit-x" sizetopopup="always" onselect="this._editor._buildCSS();">
- <xul:menupopup>
- <xul:menuitem label="%" value="%" />
- <xul:menuitem label="px" value="px" />
- <xul:menuitem label="em" value="em" />
- <xul:menuitem label="in" value="in" />
- <xul:menuitem label="cm" value="cm" />
- <xul:menuitem label="mm" value="mm" />
- <xul:menuitem label="pt" value="pt" />
- <xul:menuitem label="pc" value="pc" />
- </xul:menupopup>
- </xul:menulist>
- </xul:hbox>
- <xul:separator class="groove" orient="horizontal" />
- <xul:hbox>
- <xul:textbox anonid="css-bg-editor-image-offset-y" type="number" size="4" min="-65535" onchange="this._editor._buildCSS();" />
- <xul:menulist anonid="css-bg-editor-image-offset-unit-y" sizetopopup="always" onselect="this._editor._buildCSS();">
- <xul:menupopup>
- <xul:menuitem label="%" value="%" />
- <xul:menuitem label="px" value="px" />
- <xul:menuitem label="em" value="em" />
- <xul:menuitem label="in" value="in" />
- <xul:menuitem label="cm" value="cm" />
- <xul:menuitem label="mm" value="mm" />
- <xul:menuitem label="pt" value="pt" />
- <xul:menuitem label="pc" value="pc" />
- </xul:menupopup>
- </xul:menulist>
- </xul:hbox>
- </xul:groupbox>
- </xul:hbox>
- </xul:vbox>
-
- <xul:textbox anonid="css-bg-editor-css-text" multiline="true" rows="6" xbl:inherits="disabled" />
- </xul:deck>
- </xul:vbox>
-
- <xul:hbox align="center" pack="end">
- <children includes="progressmeter|toolbox" />
- <xul:label xbl:inherits="disabled">&status4evar.editor.label;</xul:label>
- <xul:menulist anonid="css-bg-editor-mode-menu" sizetopopup="always" onselect="this._editor._updateMode();" xbl:inherits="disabled">
- <xul:menupopup>
- <xul:menuitem label="&status4evar.option.simple;" />
- <xul:menuitem label="&status4evar.option.advanced;" />
- </xul:menupopup>
- </xul:menulist>
- </xul:hbox>
- </content>
-
- <implementation>
- <constructor><![CDATA[
- [
- "_editorColor",
- "_editorImageBrowse",
- "_editorImageClear",
- "_editorImageRepeatX",
- "_editorImageRepeatY",
- "_editorImagePositionX",
- "_editorImagePositionY",
- "_editorImageOffsetX",
- "_editorImageOffsetY",
- "_editorImageOffsetUnitX",
- "_editorImageOffsetUnitY",
- "_editorMode"
- ].forEach(function(prop)
- {
- this[prop]._editor = this;
- }, this);
-
- this.setAdvanced(true, false);
- ]]></constructor>
-
- <destructor><![CDATA[
- ]]></destructor>
-
- <field name="_disableBuildCSS"><![CDATA[
- true
- ]]></field>
-
- <field name="_editorColor" readonly="true"><![CDATA[
- document.getAnonymousElementByAttribute(this, "anonid", "css-bg-editor-color");
- ]]></field>
-
- <field name="_editorCSS" readonly="true"><![CDATA[
- document.getAnonymousElementByAttribute(this, "anonid", "css-bg-editor-css-text");
- ]]></field>
-
- <field name="_editorDeck" readonly="true"><![CDATA[
- document.getAnonymousElementByAttribute(this, "anonid", "css-bg-editor-deck");
- ]]></field>
-
- <field name="_editorImage" readonly="true"><![CDATA[
- document.getAnonymousElementByAttribute(this, "anonid", "css-bg-editor-image");
- ]]></field>
-
- <field name="_editorImageBrowse" readonly="true"><![CDATA[
- document.getAnonymousElementByAttribute(this, "anonid", "css-bg-editor-image-browse");
- ]]></field>
-
- <field name="_editorImageClear" readonly="true"><![CDATA[
- document.getAnonymousElementByAttribute(this, "anonid", "css-bg-editor-image-clear");
- ]]></field>
-
- <field name="_editorImageRepeatX" readonly="true"><![CDATA[
- document.getAnonymousElementByAttribute(this, "anonid", "css-bg-editor-image-repeat-x");
- ]]></field>
-
- <field name="_editorImageRepeatY" readonly="true"><![CDATA[
- document.getAnonymousElementByAttribute(this, "anonid", "css-bg-editor-image-repeat-y");
- ]]></field>
-
- <field name="_editorImagePositionX" readonly="true"><![CDATA[
- document.getAnonymousElementByAttribute(this, "anonid", "css-bg-editor-image-position-x");
- ]]></field>
-
- <field name="_editorImagePositionY" readonly="true"><![CDATA[
- document.getAnonymousElementByAttribute(this, "anonid", "css-bg-editor-image-position-y");
- ]]></field>
-
- <field name="_editorImageOffsetX" readonly="true"><![CDATA[
- document.getAnonymousElementByAttribute(this, "anonid", "css-bg-editor-image-offset-x");
- ]]></field>
-
- <field name="_editorImageOffsetY" readonly="true"><![CDATA[
- document.getAnonymousElementByAttribute(this, "anonid", "css-bg-editor-image-offset-y");
- ]]></field>
-
- <field name="_editorImageOffsetUnitX" readonly="true"><![CDATA[
- document.getAnonymousElementByAttribute(this, "anonid", "css-bg-editor-image-offset-unit-x");
- ]]></field>
-
- <field name="_editorImageOffsetUnitY" readonly="true"><![CDATA[
- document.getAnonymousElementByAttribute(this, "anonid", "css-bg-editor-image-offset-unit-y");
- ]]></field>
-
- <field name="_editorMode" readonly="true"><![CDATA[
- document.getAnonymousElementByAttribute(this, "anonid", "css-bg-editor-mode-menu");
- ]]></field>
-
- <field name="_initialized"><![CDATA[
- false
- ]]></field>
-
- <field name="_reRGB" readonly="true"><![CDATA[
- /^rgb\((\d+), (\d+), (\d+)\)$/
- ]]></field>
-
- <field name="_reURL" readonly="true"><![CDATA[
- /^url\(\s*['"]?(.+?)['"]?\s*\)$/
- ]]></field>
-
- <field name="_reBgPosition" readonly="true"><![CDATA[
- /^(left|center|right)? ?(-?\d+[^\s\d]+)? ?(top|center|bottom)? ?(-?\d+[^\s\d]+)?$/
- ]]></field>
-
- <field name="_reCSSUnit" readonly="true"><![CDATA[
- /^(-?\d+)([^\s\d]+)$/
- ]]></field>
-
- <field name="_strings" readonly="true"><![CDATA[
- document.getElementById("bundle_status4evar");
- ]]></field>
-
- <property name="value">
- <getter><![CDATA[
- return this._editorCSS.value;
- ]]></getter>
- <setter><![CDATA[
- this._editorCSS.value = val;
-
- if(!this._initialized)
- {
- this.setAdvanced(false, false);
- this._initialized = true;
- }
-
- return val;
- ]]></setter>
- </property>
-
- <property name="disabled">
- <getter><![CDATA[
- return this.getAttribute("disabled") == "true";
- ]]></getter>
- <setter><![CDATA[
- if(val)
- {
- this.setAttribute("disabled", "true");
- }
- else
- {
- this.removeAttribute("disabled");
- }
-
- this._updateImageControllDisable();
-
- return val;
- ]]></setter>
- </property>
-
- <method name="setAdvanced">
- <parameter name="aVal"/>
- <parameter name="aPrompt"/>
- <body><![CDATA[
- if(!aVal)
- {
- let success = this._parseCSS();
- if(!success)
- {
- let result = aPrompt && Services.prompt.confirm(window,
- this._strings.getString("simpleEditorTitle"),
- this._strings.getString("simpleEditorMessage"));
- if(result)
- { // Continue to simple mode
- this._buildCSS();
- }
- else
- { // Stay on advanced mode
- aVal = true;
- }
- }
- }
-
- this._disableBuildCSS = aVal;
- this._editorDeck.selectedIndex = ((aVal) ? 1 : 0);
- this._editorMode.selectedIndex = ((aVal) ? 1 : 0);
- ]]></body>
- </method>
-
- <method name="_buildCSS">
- <body><![CDATA[
- if(this._disableBuildCSS)
- {
- return;
- }
-
- let cssVal = this._editorColor.color;
- let imgVal = this._editorImage.value;
- if(imgVal)
- {
- cssVal += " url(\"" + imgVal + "\")";
-
- //
- // Print the background repeat
- //
- let bgRX = this._editorImageRepeatX.value;
- let bgRY = this._editorImageRepeatY.value;
- if(bgRX == "repeat" && bgRY == "no-repeat")
- {
- cssVal += " repeat-x";
- }
- else if(bgRX == "no-repeat" && bgRY == "repeat")
- {
- cssVal += " repeat-y";
- }
- else
- {
- cssVal += " " + bgRX;
- if(bgRX != bgRY)
- {
- cssVal += " " + bgRY;
- }
- }
-
- //
- // Print the background position
- //
- let bgPX = this._editorImagePositionX.value;
- let bgPOX = this._editorImageOffsetX.value;
- if(bgPX != "offset")
- {
- cssVal += " " + bgPX;
- }
- else
- {
- cssVal += " " + bgPOX + this._editorImageOffsetUnitX.value;
- }
-
- let bgPY = this._editorImagePositionY.value;
- let bgPOY = this._editorImageOffsetY.value;
- if(bgPY != "offset")
- {
- cssVal += " " + bgPY;
- }
- else
- {
- cssVal += " " + bgPOY + this._editorImageOffsetUnitY.value;
- }
- }
-
- this._editorCSS.value = cssVal;
-
- let event = document.createEvent("Event");
- event.initEvent("change", true, true);
- this._editorCSS.dispatchEvent(event);
- ]]></body>
- </method>
-
- <method name="_parseCSS">
- <body><![CDATA[
- let retVal = true;
-
- let cssParser = document.createElement("div");
- cssParser.style.background = this._editorCSS.value;
- if(!cssParser.style.background)
- {
- Components.utils.reportError("Error parsing background CSS rule: " + this._editorCSS.value);
- cssParser.style.background = "#33FF33";
- retVal = false;
- }
-
- //
- // Parse the background color
- //
- let bgC = cssParser.style.backgroundColor;
- if(this._reRGB.test(bgC))
- {
- let digits = this._reRGB.exec(bgC);
-
- let red = parseInt(digits[1]);
- let green = parseInt(digits[2]);
- let blue = parseInt(digits[3]);
-
- let rgb = blue | (green << 8) | (red << 16);
- bgC = "#" + rgb.toString(16);
- }
- else
- {
- Components.utils.reportError("Error parsing background-color value: " + bgC);
- bgC = "#33FF33";
- retVal = false;
- }
-
- //
- // Parse the background image
- //
- let bgI = cssParser.style.backgroundImage;
- if(bgI != "none" && !this._reURL.test(bgI))
- {
- Components.utils.reportError("Error parsing background-image value: " + bgI);
- bgI = "none";
- retVal = false;
- }
- bgI = ((bgI != "none") ? this._reURL.exec(bgI)[1].trim() : "");
-
- //
- // Parse the background repeat
- //
- let bgR = cssParser.style.backgroundRepeat.split(" ");
- let bgRX = bgR[0];
- if(bgRX == "repeat-x")
- {
- bgRX = "repeat";
- }
- else if(bgRX == "repeat-y")
- {
- bgRX = "no-repeat";
- }
-
- let bgRY = bgR[bgR.length - 1];
- if(bgRY == "repeat-x")
- {
- bgRY = "no-repeat";
- }
- else if(bgRY == "repeat-y")
- {
- bgRY = "repeat";
- }
-
- //
- // Parse the background position
- //
- let bgP = cssParser.style.backgroundPosition;
- let bgPParts = this._reBgPosition.exec(bgP);
- let bgPValues = new Array();
- for(let i = 1; i <= 4; i++)
- {
- if(bgPParts[i])
- {
- bgPValues.push({
- "value": bgPParts[i],
- "group": i
- });
- }
- }
-
- if(bgPValues.length == 1)
- {
- bgPValues.splice(((bgPValues[0].group == 2) ? 0 : 1), 0, {
- "value": "center",
- "group": ((bgPValues[0].group == 2) ? 0 : 2)
- });
- }
-
- if(bgPValues.length == 2 && bgPValues[1].group == 2)
- {
- bgPValues[1].group = 4;
- }
-
- for(let i = 0; i < 4; i++)
- {
- let group = (i + 1);
- if(bgPValues[i] != undefined && bgPValues[i].group == group)
- {
- continue;
- }
-
- let tmp = "0px";
- switch(i)
- {
- case 0:
- tmp = "offset";
- break;
- case 2:
- tmp = "offset";
- break;
- }
-
- bgPValues.splice(i, 0, {
- "value": tmp,
- "group": group
- });
- }
-
- let bgPOXParts = this._reCSSUnit.exec(bgPValues[1].value);
- let bgPOYParts = this._reCSSUnit.exec(bgPValues[3].value);
-
- //
- // Parse the background size
- //
-
- //
- // Initialize the UI
- //
- let disableBuildCSS = this._disableBuildCSS;
- this._disableBuildCSS = true;
-
- this._editorColor.color = bgC;
- this._editorImage.value = bgI;
- this._editorImageOffsetX.value = bgPOXParts[1];
- this._editorImageOffsetY.value = bgPOYParts[1];
-
- [
- [this._editorImageRepeatX, bgRX, "repeat", "repeat X"],
- [this._editorImageRepeatY, bgRY, "repeat", "repeat Y"],
- [this._editorImagePositionX, bgPValues[0].value, "left", "position X"],
- [this._editorImagePositionY, bgPValues[2].value, "top", "position Y"],
- [this._editorImageOffsetUnitX, bgPOXParts[2], "px", "offset X unit"],
- [this._editorImageOffsetUnitY, bgPOYParts[2], "px", "offset Y unit"]
- ].forEach(function(info)
- {
- if(!this._setSelectedItemSafe(info[0], info[1], info[2]))
- {
- Components.utils.reportError("Error setting " + info[3] + " to " + info[1]);
- retVal = false;
- }
- }, this);
-
- this._updateImageControllDisable();
-
- this._disableBuildCSS = disableBuildCSS;
-
- return retVal;
- ]]></body>
- </method>
-
- <method name="_imageBrowse">
- <body><![CDATA[
- let nsIFilePicker = Components.interfaces.nsIFilePicker;
- let filePicker = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
- filePicker.init(window, this._strings.getString("imageSelectTitle"), nsIFilePicker.modeOpen);
- filePicker.appendFilters(nsIFilePicker.filterImages);
-
- let res = filePicker.show();
- if(res == nsIFilePicker.returnOK)
- {
- this._editorImage.value = Services.io.newFileURI(filePicker.file).spec;
- this._updateImageControllDisable();
- this._buildCSS();
- }
- ]]></body>
- </method>
-
- <method name="_imageClear">
- <body><![CDATA[
- this._editorImage.value = "";
- this._editorImageRepeatX.value = "repeat";
- this._editorImageRepeatY.value = "repeat";
- this._editorImagePositionX.value = "left";
- this._editorImagePositionY.value = "top";
- this._editorImageOffsetX.value = 0;
- this._editorImageOffsetY.value = 0;
- this._editorImageOffsetUnitX.value = "px";
- this._editorImageOffsetUnitY.value = "px";
- this._updateImageControllDisable();
- this._buildCSS();
- ]]></body>
- </method>
-
- <method name="_processEvent">
- <parameter name="event"/>
- <body><![CDATA[
- if(!("css-bg-editor-css-text" == event.originalTarget.getAttribute("anonid")
- || "css-bg-editor-css-text" == document.getBindingParent(event.originalTarget).getAttribute("anonid")))
- {
- event.stopPropagation();
- }
-
- //Components.utils.reportError("Editor event " + event.type + " on " + event.originalTarget.tagName + "::" + event.originalTarget.getAttribute("anonid"));
- ]]></body>
- </method>
-
- <method name="_setSelectedItemSafe">
- <parameter name="aElement"/>
- <parameter name="aValue"/>
- <parameter name="aDefault"/>
- <body><![CDATA[
- aElement.value = aValue;
- if(!aElement.selectedItem || aElement.selectedItem.value != aValue)
- {
- aElement.value = aDefault;
- return false;
- }
- return true;
- ]]></body>
- </method>
-
- <method name="_updateImageControllDisable">
- <body><![CDATA[
- if(this.disabled || !this._editorImage.value)
- {
- this.setAttribute("no-image", "true");
- this._updatePositionOffsetXDisabled(true);
- this._updatePositionOffsetYDisabled(true);
- }
- else
- {
- this.removeAttribute("no-image");
- this._updatePositionOffsetXDisabled(false);
- this._updatePositionOffsetYDisabled(false);
- }
- ]]></body>
- </method>
-
- <method name="_updateMode">
- <body><![CDATA[
- if(this._editorMode.selectedIndex == this._editorDeck.selectedIndex)
- {
- return;
- }
-
- this.setAdvanced(((this._editorMode.selectedIndex == 1) ? true : false), true);
- ]]></body>
- </method>
-
- <method name="_updatePositionOffsetXDisabled">
- <parameter name="aVal"/>
- <body><![CDATA[
- let bgPX = this._editorImagePositionX.value;
- let disableOffsetX = aVal || (bgPX != "offset");// || bgPX == "center");
- this._editorImageOffsetX.disabled = disableOffsetX;
- this._editorImageOffsetUnitX.disabled = disableOffsetX;
- ]]></body>
- </method>
-
- <method name="_updatePositionOffsetYDisabled">
- <parameter name="aVal"/>
- <body><![CDATA[
- let bgPY = this._editorImagePositionY.value;
- var disableOffsetY = aVal || (bgPY != "offset");// || bgPY == "center");
- this._editorImageOffsetY.disabled = disableOffsetY;
- this._editorImageOffsetUnitY.disabled = disableOffsetY;
- ]]></body>
- </method>
-
- <method name="_updatePositionX">
- <body><![CDATA[
- this._updatePositionOffsetXDisabled(false);
- this._buildCSS();
- ]]></body>
- </method>
-
- <method name="_updatePositionY">
- <body><![CDATA[
- this._updatePositionOffsetYDisabled(false);
- this._buildCSS();
- ]]></body>
- </method>
- </implementation>
-
- <handlers>
- <handler event="command"><![CDATA[
- this._processEvent(event);
- ]]></handler>
-
- <handler event="change"><![CDATA[
- this._processEvent(event);
- ]]></handler>
-
- <handler event="input"><![CDATA[
- this._processEvent(event);
- ]]></handler>
-
- <handler event="select"><![CDATA[
- this._processEvent(event);
- ]]></handler>
- </handlers>
- </binding>
-</bindings>
-
diff --git a/components/statusbar/content/prefs.xul b/components/statusbar/content/prefs.xul
deleted file mode 100644
index dd41582..0000000
--- a/components/statusbar/content/prefs.xul
+++ /dev/null
@@ -1,297 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!DOCTYPE prefwindow [
- <!ENTITY % prefsDTD SYSTEM "chrome://browser/locale/statusbar/statusbar-prefs.dtd">
- %prefsDTD;
-]>
-
-<?xml-stylesheet href="chrome://global/skin/config.css" type="text/css" ?>
-<?xml-stylesheet href="chrome://browser/skin/browser.css" type="text/css" ?>
-
-<?xml-stylesheet href="chrome://browser/content/statusbar/overlay.css" type="text/css" ?>
-<?xml-stylesheet href="chrome://browser/skin/statusbar/overlay.css" type="text/css" ?>
-<?xml-stylesheet href="chrome://browser/skin/statusbar/dynamic.css" type="text/css" ?>
-
-<?xml-stylesheet href="chrome://browser/content/statusbar/prefs.css" type="text/css" ?>
-<?xml-stylesheet href="chrome://browser/skin/statusbar/prefs.css" type="text/css" ?>
-
-<prefwindow id="status4evar-prefs" title="&status4evar.window.title;"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- onload="status4evarPrefs.onPrefWindowLoad();" onunload="status4evarPrefs.onPrefWindowUnLoad();">
-
- <stringbundleset id="stringbundleset">
- <stringbundle id="bundle_status4evar" src="chrome://browser/locale/statusbar/prefs.properties" />
- </stringbundleset>
- <script type="application/javascript" src="chrome://browser/content/statusbar/prefs.js" />
-
- <prefpane id="status4evar-pane-status" label="&status4evar.pane.status;">
- <preferences>
- <preference id="status4evar-pref-status" name="status4evar.status" type="int" />
- <preference id="status4evar-pref-status-default" name="status4evar.status.default" type="bool" />
- <preference id="status4evar-pref-status-network" name="status4evar.status.network" type="bool"
- onchange="status4evarPrefs.statusNetworkChanged();" />
- <preference id="status4evar-pref-status-network-xhr" name="status4evar.status.network.xhr" type="bool" />
- <preference id="status4evar-pref-status-timeout" name="status4evar.status.timeout" type="int"
- onchange="status4evarPrefs.statusTimeoutChanged();" />
- <preference id="status4evar-pref-status-linkOver" name="status4evar.status.linkOver" type="int" />
- <preference id="status4evar-pref-status-linkOver-delay-show" name="status4evar.status.linkOver.delay.show" type="int" />
- <preference id="status4evar-pref-status-linkOver-delay-hide" name="status4evar.status.linkOver.delay.hide" type="int" />
- <preference id="status4evar-pref-status-toolbar-maxLength" name="status4evar.status.toolbar.maxLength" type="int"
- onchange="status4evarPrefs.textLengthChanged();" />
- <preference id="status4evar-pref-status-popup-invertMirror" name="status4evar.status.popup.invertMirror" type="bool" />
- <preference id="status4evar-pref-status-popup-mouseMirror" name="status4evar.status.popup.mouseMirror" type="bool" />
- <preference id="toolkit-pref-dom-status-change" name="dom.disable_window_status_change" type="bool" inverted="true" />
- </preferences>
-
- <commandset id="status4evar-commandset-status">
- <command id="status4evar-command-status-timeout" oncommand="status4evarPrefs.statusTimeoutToggle();" />
- <command id="status4evar-command-status-toolbar-maxLength" oncommand="status4evarPrefs.textLengthToggle();" />
- </commandset>
-
- <tabbox id="status4evar-tabbox-status" flex="1">
- <tabs id="status4evar-tabs-status">
- <tab id="status4evar-tab-status-general" label="&status4evar.tab.general;" />
- <tab id="status4evar-tab-status-toolbar" label="&status4evar.tab.toolbar;" />
- <tab id="status4evar-tab-status-popup" label="&status4evar.tab.popup;" />
- </tabs>
-
- <tabpanels id="status4evar-tabpanels-status" flex="1">
- <tabpanel id="status4evar-tabpanel-status-general" orient="vertical">
- <groupbox id="status4evar-status-general-status">
- <caption label="&status4evar.status.general.status.caption;" />
-
- <hbox align="center">
- <label id="status4evar-status-label" control="status4evar-status-menu">&status4evar.status.label;</label>
- <menulist id="status4evar-status-menu" preference="status4evar-pref-status" sizetopopup="always">
- <menupopup>
- <menuitem label="&status4evar.option.none;" value="0" />
- <menuitem label="&status4evar.option.toolbar;" value="1" />
- <menuitem label="&status4evar.option.popup;" value="3" />
- </menupopup>
- </menulist>
- </hbox>
-
- <hbox align="center">
- <checkbox id="status4evar-status-timeout-check" label="&status4evar.status.timeout.label;"
- command="status4evar-command-status-timeout" />
- <textbox id="status4evar-status-timeout-value" preference="status4evar-pref-status-timeout" type="number" size="4"
- onsyncfrompreference="return status4evarPrefs.statusTimeoutSync();" />
- <label id="status4evar-status-timeout-unit">&status4evar.unit.seconds;</label>
- </hbox>
-
- <checkbox id="status4evar-status-default-check" preference="status4evar-pref-status-default" label="&status4evar.status.default.label;" />
-
- <checkbox id="status4evar-status-network-check" preference="status4evar-pref-status-network" label="&status4evar.status.network.label;"
- onsyncfrompreference="return status4evarPrefs.statusNetworkSync();" />
-
- <hbox align="center" class="indent">
- <checkbox id="status4evar-status-network-xhr-check" preference="status4evar-pref-status-network-xhr" label="&status4evar.status.network.xhr.label;" />
- </hbox>
-
- <checkbox id="toolkit-dom-status-change-check" preference="toolkit-pref-dom-status-change" label="&toolkit.dom.status.change.label;" />
- </groupbox>
-
- <groupbox id="status4evar-status-general-linkOver">
- <caption label="&status4evar.status.general.linkOver.caption;" />
-
- <hbox align="center">
- <label id="status4evar-status-linkOver-label" control="status4evar-status-linkOver-menu">&status4evar.status.linkOver.label;</label>
- <menulist id="status4evar-status-linkOver-menu" preference="status4evar-pref-status-linkOver" sizetopopup="always">
- <menupopup>
- <menuitem label="&status4evar.option.none;" value="0" />
- <menuitem label="&status4evar.option.toolbar;" value="1" />
- <menuitem label="&status4evar.option.popup;" value="3" />
- </menupopup>
- </menulist>
- </hbox>
-
- <hbox align="center">
- <label id="status4evar-status-linkOver-delay-show-label" control="status4evar-status-linkOver-delay-show-value">&status4evar.status.linkOver.delay.show.label;</label>
- <textbox id="status4evar-status-linkOver-delay-show-value" preference="status4evar-pref-status-linkOver-delay-show" type="number" size="5" />
- <label id="status4evar-status-linkOver-delay-show-unit">&status4evar.unit.milliseconds;</label>
- </hbox>
-
- <hbox align="center">
- <label id="status4evar-status-linkOver-delay-hide-label" control="status4evar-status-linkOver-delay-hide-value">&status4evar.status.linkOver.delay.hide.label;</label>
- <textbox id="status4evar-status-linkOver-delay-hide-value" preference="status4evar-pref-status-linkOver-delay-hide" type="number" size="5" />
- <label id="status4evar-status-linkOver-delay-hide-unit">&status4evar.unit.milliseconds;</label>
- </hbox>
- </groupbox>
-
- </tabpanel>
-
- <tabpanel id="status4evar-tabpanel-status-toolbar" orient="vertical">
- <hbox align="center">
- <checkbox id="status4evar-status-toolbar-maxLength-check" label="&status4evar.status.toolbar.maxLength.label;"
- command="status4evar-command-status-toolbar-maxLength" />
- <textbox id="status4evar-status-toolbar-maxLength-value" preference="status4evar-pref-status-toolbar-maxLength" type="number" size="4"
- onsyncfrompreference="return status4evarPrefs.textLengthSync();" />
- <label id="status4evar-status-toolbar-maxLength-unit">&status4evar.unit.px;</label>
- </hbox>
- </tabpanel>
-
- <tabpanel id="status4evar-tabpanel-status-popup" orient="vertical">
- <checkbox id="status4evar-status-popup-invertMirror-check" preference="status4evar-pref-status-popup-invertMirror" label="&status4evar.status.popup.invertMirror.label;" />
-
- <checkbox id="status4evar-status-popup-mouseMirror-check" preference="status4evar-pref-status-popup-mouseMirror" label="&status4evar.status.popup.mouseMirror.label;" />
- </tabpanel>
-
- </tabpanels>
- </tabbox>
- </prefpane>
-
- <prefpane id="status4evar-pane-progress" label="&status4evar.pane.progress;">
- <preferences>
- <preference id="status4evar-pref-progress-toolbar-force" name="status4evar.progress.toolbar.force" type="bool" />
- <preference id="status4evar-pref-progress-toolbar-style" name="status4evar.progress.toolbar.style" type="bool"
- onchange="status4evarPrefs.progressToolbarStyleChanged();" />
- <preference id="status4evar-pref-progress-toolbar-css" name="status4evar.progress.toolbar.css" type="string"
- onchange="status4evarPrefs.progressToolbarCSSChanged();" />
- </preferences>
-
- <commandset id="status4evar-commandset-status">
- </commandset>
-
- <checkbox id="status4evar-progress-toolbar-force-check" preference="status4evar-pref-progress-toolbar-force" label="&status4evar.progress.toolbar.force.label;" />
-
- <checkbox id="status4evar-progress-toolbar-style-check" preference="status4evar-pref-progress-toolbar-style" label="&status4evar.progress.style.label;"
- onsyncfrompreference="return status4evarPrefs.progressToolbarStyleSync();" />
-
- <vbox class="css-bg-editor" preference="status4evar-pref-progress-toolbar-css" preference-editable="true" flex="1">
- <progressmeter id="status4evar-progress-bar" value="75" flex="1" />
- </vbox>
- </prefpane>
-
- <prefpane id="status4evar-pane-download" label="&status4evar.pane.download;">
- <preferences>
- <preference id="status4evar-pref-download-button-action" name="status4evar.download.button.action" type="int" />
- <preference id="status4evar-pref-download-color-active" name="status4evar.download.color.active" type="string" />
- <preference id="status4evar-pref-download-color-paused" name="status4evar.download.color.paused" type="string" />
- <preference id="status4evar-pref-download-force" name="status4evar.download.force" type="bool" />
- <preference id="status4evar-pref-download-label" name="status4evar.download.label" type="int" />
- <preference id="status4evar-pref-download-label-force" name="status4evar.download.label.force" type="bool" />
- <preference id="status4evar-pref-download-notify-animate" name="status4evar.download.notify.animate" type="bool" />
- <preference id="status4evar-pref-download-notify-timeout" name="status4evar.download.notify.timeout" type="int" />
- <preference id="status4evar-pref-download-progress" name="status4evar.download.progress" type="int" />
- <preference id="status4evar-pref-download-tooltip" name="status4evar.download.tooltip" type="int" />
-
- <preference id="status4evar-pref-download-button-action-command" name="status4evar.download.button.action.command" type="string"/>
- </preferences>
-
- <commandset id="status4evar-commandset-download">
- <command id="status4evar-command-download-progress" oncommand="status4evarPrefs.downloadProgressToggle();" />
- </commandset>
-
- <checkbox id="status4evar-download-force-check" preference="status4evar-pref-download-force" label="&status4evar.download.force.label;" />
-
- <checkbox id="status4evar-download-label-force-check" preference="status4evar-pref-download-label-force" label="&status4evar.download.label.force.label;" />
-
- <hbox align="center">
- <label id="status4evar-download-label-label" control="status4evar-download-label-menu">&status4evar.download.label.label;</label>
- <menulist id="status4evar-download-label-menu" preference="status4evar-pref-download-label" sizetopopup="always">
- <menupopup>
- <menuitem value="0" label="&status4evar.option.dlcount;" />
- <menuitem value="1" label="&status4evar.option.dltime;" />
- <menuitem value="2" label="&status4evar.option.both;" />
- </menupopup>
- </menulist>
- </hbox>
-
- <hbox align="center">
- <label id="status4evar-download-tooltip-label" control="status4evar-download-tooltip-menu">&status4evar.download.tooltip.label;</label>
- <menulist id="status4evar-download-tooltip-menu" preference="status4evar-pref-download-tooltip" sizetopopup="always">
- <menupopup>
- <menuitem value="0" label="&status4evar.option.dlcount;" />
- <menuitem value="1" label="&status4evar.option.dltime;" />
- <menuitem value="2" label="&status4evar.option.both;" />
- </menupopup>
- </menulist>
- </hbox>
-
- <hbox align="center">
- <label id="status4evar-download-button-action-label" control="status4evar-download-button-action-menu">&status4evar.download.button.action.label;</label>
- <menulist id="status4evar-download-button-action-menu" preference="status4evar-pref-download-button-action" sizetopopup="always">
- <menupopup>
- <menuitem value="0" label="&status4evar.option.nothing;" />
- <menuitem value="1" label="&status4evar.option.firefoxdefault;" />
- <menuitem value="2" label="&status4evar.option.download.library;" />
- <menuitem value="3" label="&status4evar.option.download.tab;" />
- <menuitem value="4" label="&status4evar.option.download.thirdparty;" id="status4evar-download-button-action-menu-thirdparty" />
- </menupopup>
- </menulist>
- </hbox>
-
- <hbox align="center">
- <label id="status4evar-download-notify-timeout-label" control="status4evar-download-notify-timeout-value">&status4evar.download.notify.timeout.label;</label>
- <textbox id="status4evar-download-notify-timeout-value" preference="status4evar-pref-download-notify-timeout" type="number" size="3" />
- <label id="status4evar-download-notify-timeout-unit">&status4evar.unit.seconds;</label>
- </hbox>
-
- <checkbox id="status4evar-download-notify-animate-check" preference="status4evar-pref-download-notify-animate" label="&status4evar.download.notify.animate.label;" />
-
- <checkbox id="status4evar-download-progress-check" command="status4evar-command-download-progress" label="&status4evar.download.progress.label;" />
-
- <vbox class="indent">
- <hbox align="center">
- <radiogroup id="status4evar-download-progress-radiogroup" preference="status4evar-pref-download-progress"
- onsyncfrompreference="return status4evarPrefs.downloadProgressSync();">
- <radio value="1" label="&status4evar.download.progress.average.label;" />
- <radio value="2" label="&status4evar.download.progress.max.label;" />
- <radio value="3" label="&status4evar.download.progress.min.label;" />
- </radiogroup>
- </hbox>
-
- <hbox align="center">
- <label id="status4evar-download-color-active-label" control="status4evar-download-color-active-picker">&status4evar.download.color.active.label;</label>
- <colorpicker id="status4evar-download-color-active-picker" preference="status4evar-pref-download-color-active" type="button" />
- </hbox>
-
- <hbox align="center">
- <label id="status4evar-download-color-paused-label" control="status4evar-download-color-paused-picker">&status4evar.download.color.paused.label;</label>
- <colorpicker id="status4evar-download-color-paused-picker" preference="status4evar-pref-download-color-paused" type="button" />
- </hbox>
- </vbox>
- </prefpane>
-
- <prefpane id="status4evar-pane-addonbar" label="&status4evar.pane.statusbar;">
- <preferences>
- <preference id="status4evar-pref-addonbar-borderStyle" name="status4evar.addonbar.borderStyle" type="bool" />
- <preference id="status4evar-pref-addonbar-closeButton" name="status4evar.addonbar.closeButton" type="bool" />
- <preference id="status4evar-pref-addonbar-windowGripper" name="status4evar.addonbar.windowGripper" type="bool" />
- </preferences>
-
- <checkbox id="status4evar-addonbar-borderStyle-check" preference="status4evar-pref-addonbar-borderStyle" label="&status4evar.addonbar.borderStyle;" />
-
- <checkbox id="status4evar-addonbar-closeButton-check" preference="status4evar-pref-addonbar-closeButton" label="&status4evar.addonbar.closeButton;" />
-
- <checkbox id="status4evar-addonbar-windowGripper-check" preference="status4evar-pref-addonbar-windowGripper" label="&status4evar.addonbar.windowGripper;" />
- </prefpane>
-
- <prefpane id="status4evar-pane-advanced" label="&status4evar.pane.advanced;">
- <preferences>
- <preference id="status4evar-pref-advanced-status-detectFullScreen" name="status4evar.advanced.status.detectFullScreen" type="bool" />
- <preference id="status4evar-pref-advanced-status-detectVideo" name="status4evar.advanced.status.detectVideo" type="bool" />
- <preference id="browser-pref-urlbar-trimming-enabled" name="browser.urlbar.trimURLs" type="bool" />
- </preferences>
-
- <vbox flex="1">
- <groupbox id="status4evar-status-urlbar-builtin">
- <caption label="&status4evar.status.urlbar.firefox.builtin.caption;" />
-
- <checkbox id="browser-urlbar-trimming-enabled-ckeck" preference="browser-pref-urlbar-trimming-enabled" label="&browser.urlbar.trimming.enabled.label;" />
- </groupbox>
-
- <groupbox id="status4evar-advanced-status">
- <caption label="&status4evar.pane.status;" />
-
- <checkbox id="status4evar-advanced-status-detectFullScreen-check" preference="status4evar-pref-advanced-status-detectFullScreen" label="&status4evar.advanced.status.detectFullScreen;" />
- <checkbox id="status4evar-advanced-status-detectVideo-check" preference="status4evar-pref-advanced-status-detectVideo" label="&status4evar.advanced.status.detectVideo;" />
- </groupbox>
- </vbox>
- </prefpane>
-</prefwindow>
-
diff --git a/components/statusbar/content/tabbrowser.xml b/components/statusbar/content/tabbrowser.xml
deleted file mode 100644
index 2f47577..0000000
--- a/components/statusbar/content/tabbrowser.xml
+++ /dev/null
@@ -1,218 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<bindings id="status4evar-bindings"
- xmlns="http://www.mozilla.org/xbl"
- xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:xbl="http://www.mozilla.org/xbl">
-
- <binding id="statuspanel" display="xul:hbox" extends="chrome://browser/content/tabbrowser.xml#statuspanel">
- <implementation>
- <!-- -->
- <!-- Inverted mirror handling -->
- <!-- -->
-
- <field name="_invertMirror"><![CDATA[
- false
- ]]></field>
-
- <property name="invertMirror">
- <setter><![CDATA[
- this._invertMirror = val;
- this.mirror = this._isMirrored;
- return val;
- ]]></setter>
- <getter><![CDATA[
- return this._invertMirror;
- ]]></getter>
- </property>
-
- <!-- -->
- <!-- Mouse mirror handling -->
- <!-- -->
-
- <field name="_mouseMirror"><![CDATA[
- true
- ]]></field>
-
- <field name="_mouseMirrorListen"><![CDATA[
- false
- ]]></field>
-
- <property name="mouseMirror">
- <setter><![CDATA[
- this._mouseMirror = val;
- this.setupMouseMirror(this.value);
- return val;
- ]]></setter>
- <getter><![CDATA[
- return this._mouseMirror;
- ]]></getter>
- </property>
-
- <method name="setupMouseMirror">
- <parameter name="val"/>
- <body><![CDATA[
- if(val && this._mouseMirror)
- {
- this._calcMouseTargetRect();
- if(!this._mouseMirrorListen)
- {
- MousePosTracker.addListener(this);
- this._mouseMirrorListen = true;
- }
- }
- else
- {
- this.mirror = false;
- if(this._mouseMirrorListen)
- {
- MousePosTracker.removeListener(this);
- this._mouseMirrorListen = false;
- }
- }
- ]]></body>
- </method>
-
- <method name="_calcMouseTargetRect">
- <body><![CDATA[
- let alignRight = false;
- let isRTL = (getComputedStyle(document.documentElement).direction == "rtl");
- if((this._invertMirror && !isRTL) || (!this._invertMirror && isRTL))
- {
- alignRight = true;
- }
-
- let rect = this.getBoundingClientRect();
- this._mouseTargetRect =
- {
- top: rect.top,
- bottom: rect.bottom,
- left: ((alignRight) ? window.innerWidth - rect.width : 0),
- right: ((alignRight) ? window.innerWidth : rect.width)
- };
- ]]></body>
- </method>
-
- <method name="onMouseEnter">
- <body><![CDATA[
- this.mirror = true;
- ]]></body>
- </method>
-
- <method name="onMouseLeave">
- <body><![CDATA[
- this.mirror = false;
- ]]></body>
- </method>
-
- <!-- -->
- <!-- Mirror handling -->
- <!-- -->
-
- <field name="_isMirrored"><![CDATA[
- false
- ]]></field>
-
- <property name="mirror">
- <setter><![CDATA[
- this._isMirrored = val;
- if(this._invertMirror)
- {
- val = !val;
- }
-
- this.setBooleanAttr("mirror", val);
- ]]></setter>
- <getter><![CDATA[
- return this._isMirrored;
- ]]></getter>
- </property>
-
- <method name="_mirror">
- <body><![CDATA[
- this.mirror = !this._isMirrored;
- ]]></body>
- </method>
-
- <!-- -->
- <!-- Value handling -->
- <!-- -->
-
- <property name="label">
- <setter><![CDATA[
- if(window.caligon && window.caligon.status4evar)
- {
- window.caligon.status4evar.statusService.setStatusText(val);
- }
- return undefined;
- ]]></setter>
- <getter><![CDATA[
- if(window.caligon && window.caligon.status4evar)
- {
- return window.caligon.status4evar.statusService.getStatusText();
- }
- return "";
- ]]></getter>
- </property>
-
- <property name="value">
- <setter><![CDATA[
- this.setValue(val);
- this.setupMouseMirror(val);
- return val;
- ]]></setter>
- <getter><![CDATA[
- return ((this.hasAttribute("inactive")) ? "" : this.getAttribute("label"));
- ]]></getter>
- </property>
-
- <method name="setValue">
- <parameter name="val"/>
- <body><![CDATA[
- if((this.getAttribute("type") || "").indexOf("network") > -1 && (this.getAttribute("previoustype") || "").indexOf("network") > -1)
- {
- this.style.minWidth = getComputedStyle(this).width;
- }
- else
- {
- this.style.minWidth = "";
- }
-
- if(val)
- {
- this.setAttribute("label", val);
- this.setBooleanAttr("inactive", false);
- }
- else
- {
- this.setBooleanAttr("inactive", true);
- }
- ]]></body>
- </method>
-
- <!-- -->
- <!-- Helpers -->
- <!-- -->
-
- <method name="setBooleanAttr">
- <parameter name="name"/>
- <parameter name="val"/>
- <body><![CDATA[
- if(val)
- {
- this.setAttribute(name, "true");
- }
- else
- {
- this.removeAttribute(name);
- }
- ]]></body>
- </method>
- </implementation>
- </binding>
-</bindings>
-
diff --git a/components/statusbar/jar.mn b/components/statusbar/jar.mn
deleted file mode 100644
index b5a8d09..0000000
--- a/components/statusbar/jar.mn
+++ /dev/null
@@ -1,15 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-browser.jar:
-% overlay chrome://browser/content/browser.xul chrome://browser/content/statusbar/overlay.xul
-% style chrome://global/content/customizeToolbar.xul chrome://browser/skin/statusbar/overlay.css
- content/browser/statusbar/overlay.js (content/overlay.js)
- content/browser/statusbar/prefs.js (content/prefs.js)
- content/browser/statusbar/prefs.xml (content/prefs.xml)
- content/browser/statusbar/tabbrowser.xml (content/tabbrowser.xml)
- content/browser/statusbar/overlay.xul (content/overlay.xul)
- content/browser/statusbar/prefs.xul (content/prefs.xul)
- content/browser/statusbar/overlay.css (content/overlay.css)
- content/browser/statusbar/prefs.css (content/prefs.css) \ No newline at end of file
diff --git a/components/statusbar/moz.build b/components/statusbar/moz.build
deleted file mode 100644
index 0f7f597..0000000
--- a/components/statusbar/moz.build
+++ /dev/null
@@ -1,25 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-JAR_MANIFESTS += [ 'jar.mn' ]
-
-XPIDL_SOURCES += [ 'status4evar.idl' ]
-
-XPIDL_MODULE = 'status4evar'
-
-EXTRA_COMPONENTS += [
- 'status4evar.js',
- 'status4evar.manifest',
-]
-
-EXTRA_JS_MODULES.statusbar = [
- 'content-thunk.js',
- 'Downloads.jsm',
- 'Progress.jsm',
- 'Status.jsm',
- 'Status4Evar.jsm',
- 'Toolbars.jsm',
-] \ No newline at end of file
diff --git a/components/statusbar/status4evar.idl b/components/statusbar/status4evar.idl
deleted file mode 100644
index 534dea3..0000000
--- a/components/statusbar/status4evar.idl
+++ /dev/null
@@ -1,57 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-interface nsIDOMWindow;
-
-[scriptable, uuid(33d0433d-07be-4dc4-87fd-954057310efd)]
-interface nsIStatus4Evar : nsISupports
-{
- readonly attribute boolean addonbarBorderStyle;
- readonly attribute boolean addonbarCloseButton;
- readonly attribute boolean addonbarLegacyShim;
- readonly attribute boolean addonbarWindowGripper;
-
- readonly attribute boolean advancedStatusDetectFullScreen;
- readonly attribute boolean advancedStatusDetectVideo;
-
- readonly attribute long downloadButtonAction;
- readonly attribute ACString downloadButtonActionCommand;
- readonly attribute ACString downloadColorActive;
- readonly attribute ACString downloadColorPaused;
- readonly attribute boolean downloadForce;
- readonly attribute long downloadLabel;
- readonly attribute boolean downloadLabelForce;
- readonly attribute boolean downloadNotifyAnimate;
- readonly attribute long downloadNotifyTimeout;
- readonly attribute long downloadProgress;
- readonly attribute long downloadTooltip;
-
- readonly attribute boolean firstRun;
- readonly attribute boolean firstRunAustralis;
-
- readonly attribute ACString progressToolbarCSS;
- readonly attribute boolean progressToolbarForce;
- readonly attribute boolean progressToolbarStyle;
- readonly attribute boolean progressToolbarStyleAdvanced;
-
- readonly attribute long status;
- readonly attribute boolean statusDefault;
- readonly attribute boolean statusNetwork;
- readonly attribute boolean statusNetworkXHR;
- readonly attribute long statusTimeout;
- readonly attribute long statusLinkOver;
- readonly attribute long statusLinkOverDelayShow;
- readonly attribute long statusLinkOverDelayHide;
-
- readonly attribute long statusToolbarMaxLength;
-
- readonly attribute boolean statusToolbarInvertMirror;
- readonly attribute boolean statusToolbarMouseMirror;
-
- void resetPrefs();
- void updateWindow(in nsIDOMWindow win);
-};
-
diff --git a/components/statusbar/status4evar.js b/components/statusbar/status4evar.js
deleted file mode 100644
index 4aa2e3e..0000000
--- a/components/statusbar/status4evar.js
+++ /dev/null
@@ -1,695 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-// Component constants
-const CC = Components.classes;
-const CI = Components.interfaces;
-const CU = Components.utils;
-
-CU.import("resource://gre/modules/XPCOMUtils.jsm");
-CU.import("resource://gre/modules/Services.jsm");
-
-const CURRENT_MIGRATION = 8;
-
-function Status_4_Evar(){}
-
-Status_4_Evar.prototype =
-{
- classID: Components.ID("{33d0433d-07be-4dc4-87fd-954057310efd}"),
- QueryInterface: XPCOMUtils.generateQI([
- CI.nsISupportsWeakReference,
- CI.nsIObserver,
- CI.nsIStatus4Evar
- ]),
-
- prefs: null,
-
- addonbarBorderStyle: false,
- addonbarCloseButton: false,
- addonbarWindowGripper: true,
-
- advancedStatusDetectFullScreen: true,
- advancedStatusDetectVideo: true,
-
- downloadButtonAction: 1,
- downloadButtonActionCommand: "",
- downloadColorActive: null,
- downloadColorPaused: null,
- downloadForce: false,
- downloadLabel: 0,
- downloadLabelForce: true,
- downloadNotifyAnimate: true,
- downloadNotifyTimeout: 60000,
- downloadProgress: 1,
- downloadTooltip: 1,
-
- firstRun: true,
-
- progressToolbarCSS: null,
- progressToolbarForce: false,
- progressToolbarStyle: false,
-
- status: 1,
- statusDefault: true,
- statusNetwork: true,
- statusTimeout: 10000,
- statusLinkOver: 1,
- statusLinkOverDelayShow: 70,
- statusLinkOverDelayHide: 150,
-
- statusToolbarMaxLength: 0,
-
- statusToolbarInvertMirror: false,
- statusToolbarMouseMirror: true,
-
- pref_registry:
- {
- "addonbar.borderStyle":
- {
- update: function()
- {
- this.addonbarBorderStyle = this.prefs.getBoolPref("addonbar.borderStyle");
- },
- updateWindow: function(win)
- {
- let browser_bottom_box = win.caligon.status4evar.getters.browserBottomBox;
- if(browser_bottom_box)
- {
- this.setBoolElementAttribute(browser_bottom_box, "s4eboarder", this.addonbarBorderStyle);
- }
- }
- },
-
- "addonbar.closeButton":
- {
- update: function()
- {
- this.addonbarCloseButton = this.prefs.getBoolPref("addonbar.closeButton");
- },
- updateWindow: function(win)
- {
- let addonbar_close_button = win.caligon.status4evar.getters.addonbarCloseButton;
- if(addonbar_close_button)
- {
- addonbar_close_button.hidden = !this.addonbarCloseButton;
- }
- }
- },
-
- "addonbar.windowGripper":
- {
- update: function()
- {
- this.addonbarWindowGripper = this.prefs.getBoolPref("addonbar.windowGripper");
- },
- updateWindow: function(win)
- {
- win.caligon.status4evar.toolbars.updateWindowGripper(true);
- }
- },
-
- "advanced.status.detectFullScreen":
- {
- update: function()
- {
- this.advancedStatusDetectFullScreen = this.prefs.getBoolPref("advanced.status.detectFullScreen");
- }
- },
-
- "advanced.status.detectVideo":
- {
- update: function()
- {
- this.advancedStatusDetectVideo = this.prefs.getBoolPref("advanced.status.detectVideo");
- }
- },
-
- "download.button.action":
- {
- update: function()
- {
- this.downloadButtonAction = this.prefs.getIntPref("download.button.action");
- },
- updateWindow: function(win)
- {
- win.caligon.status4evar.downloadStatus.updateBinding();
- }
- },
-
- "download.button.action.command":
- {
- update: function()
- {
- this.downloadButtonActionCommand = this.prefs.getCharPref("download.button.action.command");
- }
- },
-
- "download.color.active":
- {
- update: function()
- {
- this.downloadColorActive = this.prefs.getCharPref("download.color.active");
- },
- updateDynamicStyle: function(sheet)
- {
- sheet.cssRules[2].style.backgroundColor = this.downloadColorActive;
- }
- },
-
- "download.color.paused":
- {
- update: function()
- {
- this.downloadColorPaused = this.prefs.getCharPref("download.color.paused");
- },
- updateDynamicStyle: function(sheet)
- {
- sheet.cssRules[3].style.backgroundColor = this.downloadColorPaused;
- }
- },
-
- "download.force":
- {
- update: function()
- {
- this.downloadForce = this.prefs.getBoolPref("download.force");
- },
- updateWindow: function(win)
- {
- let download_button = win.caligon.status4evar.getters.downloadButton;
- if(download_button)
- {
- this.setBoolElementAttribute(download_button, "forcevisible", this.downloadForce);
- }
-
- let download_notify_anchor = win.caligon.status4evar.getters.downloadNotifyAnchor;
- this.setBoolElementAttribute(download_notify_anchor, "forcevisible", this.downloadForce);
- }
- },
-
- "download.label":
- {
- update: function()
- {
- this.downloadLabel = this.prefs.getIntPref("download.label");
- },
- updateWindow: function(win)
- {
- win.caligon.status4evar.downloadStatus.updateButton();
- }
- },
-
- "download.label.force":
- {
- update: function()
- {
- this.downloadLabelForce = this.prefs.getBoolPref("download.label.force");
- },
- updateWindow: function(win)
- {
- let download_button = win.caligon.status4evar.getters.downloadButton;
- if(download_button)
- {
- this.setBoolElementAttribute(download_button, "forcelabel", this.downloadLabelForce);
- }
- }
- },
-
- "download.notify.animate":
- {
- update: function()
- {
- this.downloadNotifyAnimate = this.prefs.getBoolPref("download.notify.animate");
- }
- },
-
- "download.notify.timeout":
- {
- update: function()
- {
- this.downloadNotifyTimeout = (this.prefs.getIntPref("download.notify.timeout") * 1000);
- }
- },
-
- "download.progress":
- {
- update: function()
- {
- this.downloadProgress = this.prefs.getIntPref("download.progress");
- },
- updateWindow: function(win)
- {
- win.caligon.status4evar.downloadStatus.updateButton();
- }
- },
-
- "download.tooltip":
- {
- update: function()
- {
- this.downloadTooltip = this.prefs.getIntPref("download.tooltip");
- },
- updateWindow: function(win)
- {
- win.caligon.status4evar.downloadStatus.updateButton();
- }
- },
-
- "progress.toolbar.css":
- {
- update: function()
- {
- this.progressToolbarCSS = this.prefs.getCharPref("progress.toolbar.css");
- },
- updateDynamicStyle: function(sheet)
- {
- sheet.cssRules[1].style.background = this.progressToolbarCSS;
- }
- },
-
- "progress.toolbar.force":
- {
- update: function()
- {
- this.progressToolbarForce = this.prefs.getBoolPref("progress.toolbar.force");
- },
- updateWindow: function(win)
- {
- let toolbar_progress = win.caligon.status4evar.getters.toolbarProgress;
- if(toolbar_progress)
- {
- this.setBoolElementAttribute(toolbar_progress, "forcevisible", this.progressToolbarForce);
- }
- }
- },
-
- "progress.toolbar.style":
- {
- update: function()
- {
- this.progressToolbarStyle = this.prefs.getBoolPref("progress.toolbar.style");
- },
- updateWindow: function(win)
- {
- let toolbar_progress = win.caligon.status4evar.getters.toolbarProgress;
- if(toolbar_progress)
- {
- this.setBoolElementAttribute(toolbar_progress, "s4estyle", this.progressToolbarStyle);
- }
- }
- },
-
- "status":
- {
- update: function()
- {
- this.status = this.prefs.getIntPref("status");
- },
- updateWindow: function(win)
- {
- win.caligon.status4evar.statusService.clearStatusField();
- win.caligon.status4evar.statusService.updateStatusField(true);
- }
- },
-
- "status.default":
- {
- update: function()
- {
- this.statusDefault = this.prefs.getBoolPref("status.default");
- },
- updateWindow: function(win)
- {
- win.caligon.status4evar.statusService.buildTextOrder();
- win.caligon.status4evar.statusService.updateStatusField(true);
- }
- },
-
- "status.linkOver":
- {
- update: function()
- {
- this.statusLinkOver = this.prefs.getIntPref("status.linkOver");
- }
- },
-
- "status.linkOver.delay.show":
- {
- update: function()
- {
- this.statusLinkOverDelayShow = this.prefs.getIntPref("status.linkOver.delay.show");
- }
- },
-
- "status.linkOver.delay.hide":
- {
- update: function()
- {
- this.statusLinkOverDelayHide = this.prefs.getIntPref("status.linkOver.delay.hide");
- }
- },
-
- "status.network":
- {
- update: function()
- {
- this.statusNetwork = this.prefs.getBoolPref("status.network");
- },
- updateWindow: function(win)
- {
- win.caligon.status4evar.statusService.buildTextOrder();
- }
- },
-
- "status.network.xhr":
- {
- update: function()
- {
- this.statusNetworkXHR = this.prefs.getBoolPref("status.network.xhr");
- },
- updateWindow: function(win)
- {
- win.caligon.status4evar.statusService.buildTextOrder();
- }
- },
-
- "status.timeout":
- {
- update: function()
- {
- this.statusTimeout = (this.prefs.getIntPref("status.timeout") * 1000);
- },
- updateWindow: function(win)
- {
- win.caligon.status4evar.statusService.updateStatusField(true);
- }
- },
-
- "status.toolbar.maxLength":
- {
- update: function()
- {
- this.statusToolbarMaxLength = this.prefs.getIntPref("status.toolbar.maxLength");
- },
- updateWindow: function(win)
- {
- let status_widget = win.caligon.status4evar.getters.statusWidget;
- if(status_widget)
- {
- status_widget.maxWidth = (this.statusToolbarMaxLength || "");
- }
- }
- },
-
- "status.popup.invertMirror":
- {
- update: function()
- {
- this.statusToolbarInvertMirror = this.prefs.getBoolPref("status.popup.invertMirror");
- },
- updateWindow: function(win)
- {
- let statusOverlay = win.caligon.status4evar.getters.statusOverlay;
- if(statusOverlay)
- {
- statusOverlay.invertMirror = this.statusToolbarInvertMirror;
- }
- }
- },
-
- "status.popup.mouseMirror":
- {
- update: function()
- {
- this.statusToolbarMouseMirror = this.prefs.getBoolPref("status.popup.mouseMirror");
- },
- updateWindow: function(win)
- {
- let statusOverlay = win.caligon.status4evar.getters.statusOverlay;
- if(statusOverlay)
- {
- statusOverlay.mouseMirror = this.statusToolbarMouseMirror;
- }
- }
- }
-
- },
-
- // nsIObserver
- observe: function(subject, topic, data)
- {
- try
- {
- switch(topic)
- {
- case "profile-after-change":
- this.startup();
- break;
- case "quit-application":
- this.shutdown();
- break;
- case "nsPref:changed":
- this.updatePref(data, true);
- break;
- }
- }
- catch(e)
- {
- CU.reportError(e);
- }
- },
-
- startup: function()
- {
- this.prefs = Services.prefs.getBranch("status4evar.").QueryInterface(CI.nsIPrefBranch2);
-
- this.firstRun = this.prefs.getBoolPref("firstRun");
- if(this.firstRun)
- {
- this.prefs.setBoolPref("firstRun", false);
- }
-
- this.migrate();
-
- for(let pref in this.pref_registry)
- {
- let pro = this.pref_registry[pref];
-
- pro.update = pro.update.bind(this);
- if(pro.updateWindow)
- {
- pro.updateWindow = pro.updateWindow.bind(this);
- }
- if(pro.updateDynamicStyle)
- {
- pro.updateDynamicStyle = pro.updateDynamicStyle.bind(this);
- }
-
- this.prefs.addObserver(pref, this, true);
-
- this.updatePref(pref, false);
- }
-
- Services.obs.addObserver(this, "quit-application", true);
- },
-
- shutdown: function()
- {
- Services.obs.removeObserver(this, "quit-application");
-
- for(let pref in this.pref_registry)
- {
- this.prefs.removeObserver(pref, this);
- }
-
- this.prefs = null;
- },
-
- migrate: function()
- {
- if(!this.firstRun)
- {
- let migration = 0;
- try
- {
- migration = this.prefs.getIntPref("migration");
- }
- catch(e) {}
-
- switch(migration)
- {
- case 5:
- this.migrateBoolPref("status.detectFullScreen", "advanced.status.detectFullScreen");
- case 6:
- let oldDownloadAction = this.prefs.getIntPref("download.button.action");
- let newDownloadAction = 1;
- switch(oldDownloadAction)
- {
- case 2:
- newDownloadAction = 1;
- break;
- case 3:
- newDownloadAction = 2;
- break;
- case 4:
- newDownloadAction = 1;
- break;
- }
- this.prefs.setIntPref("download.button.action", newDownloadAction);
- case 7:
- let progressLocation = this.prefs.getIntPref("status");
- if (progressLocation == 2)
- this.prefs.setIntPref("status", 1);
- let linkOverLocation = this.prefs.getIntPref("status.linkOver");
- if (linkOverLocation == 2)
- this.prefs.setIntPref("status.linkOver", 1);
- break;
- case CURRENT_MIGRATION:
- break;
- }
- }
-
- this.prefs.setIntPref("migration", CURRENT_MIGRATION);
- },
-
- migrateBoolPref: function(oldPref, newPref)
- {
- if(this.prefs.prefHasUserValue(oldPref))
- {
- this.prefs.setBoolPref(newPref, this.prefs.getBoolPref(oldPref));
- this.prefs.clearUserPref(oldPref);
- }
- },
-
- migrateIntPref: function(oldPref, newPref)
- {
- if(this.prefs.prefHasUserValue(oldPref))
- {
- this.prefs.setIntPref(newPref, this.prefs.getIntPref(oldPref));
- this.prefs.clearUserPref(oldPref);
- }
- },
-
- migrateCharPref: function(oldPref, newPref)
- {
- if(this.prefs.prefHasUserValue(oldPref))
- {
- this.prefs.setCharPref(newPref, this.prefs.getCharPref(oldPref));
- this.prefs.clearUserPref(oldPref);
- }
- },
-
- updatePref: function(pref, updateWindows)
- {
- if(!(pref in this.pref_registry))
- {
- return;
- }
- let pro = this.pref_registry[pref];
-
- pro.update();
-
- if(updateWindows)
- {
- let windowsEnum = Services.wm.getEnumerator("navigator:browser");
- while(windowsEnum.hasMoreElements())
- {
- this.updateWindow(windowsEnum.getNext(), pro);
- }
- }
-
- if(pro.alsoUpdate)
- {
- pro.alsoUpdate.forEach(function (alsoPref)
- {
- this.updatePref(alsoPref);
- }, this);
- }
- },
-
- // Updtate a browser window
- updateWindow: function(win, pro)
- {
- if(!(win instanceof CI.nsIDOMWindow)
- || !(win.document.documentElement.getAttribute("windowtype") == "navigator:browser"))
- {
- return;
- }
-
- if(pro)
- {
- this.handlePro(win, pro);
- }
- else
- {
- for(let pref in this.pref_registry)
- {
- this.handlePro(win, this.pref_registry[pref]);
- }
- }
- },
-
- handlePro: function(win, pro)
- {
- if(pro.updateWindow)
- {
- pro.updateWindow(win);
- }
-
- if(pro.updateDynamicStyle)
- {
- let styleSheets = win.document.styleSheets;
- for(let i = 0; i < styleSheets.length; i++)
- {
- let styleSheet = styleSheets[i];
- if(styleSheet.href == "chrome://browser/skin/statusbar/dynamic.css")
- {
- pro.updateDynamicStyle(styleSheet);
- break;
- }
- }
- }
- },
-
- setBoolElementAttribute: function(elem, attr, val)
- {
- if(val)
- {
- elem.setAttribute(attr, "true");
- }
- else
- {
- elem.removeAttribute(attr);
- }
- },
-
- setStringElementAttribute: function(elem, attr, val)
- {
- if(val)
- {
- elem.setAttribute(attr, val);
- }
- else
- {
- elem.removeAttribute(attr);
- }
- },
-
- resetPrefs: function()
- {
- let childPrefs = this.prefs.getChildList("");
- childPrefs.forEach(function(pref)
- {
- if(this.prefs.prefHasUserValue(pref))
- {
- this.prefs.clearUserPref(pref);
- }
- }, this);
- }
-};
-
-const NSGetFactory = XPCOMUtils.generateNSGetFactory([Status_4_Evar]);
-
diff --git a/components/statusbar/status4evar.manifest b/components/statusbar/status4evar.manifest
deleted file mode 100644
index 4bcf697..0000000
--- a/components/statusbar/status4evar.manifest
+++ /dev/null
@@ -1,3 +0,0 @@
-component {33d0433d-07be-4dc4-87fd-954057310efd} status4evar.js
-contract @caligonstudios.com/status4evar;1 {33d0433d-07be-4dc4-87fd-954057310efd}
-category profile-after-change Status-4-Evar @caligonstudios.com/status4evar;1
diff --git a/components/sync/aboutSyncTabs-bindings.xml b/components/sync/aboutSyncTabs-bindings.xml
deleted file mode 100644
index e610820..0000000
--- a/components/sync/aboutSyncTabs-bindings.xml
+++ /dev/null
@@ -1,46 +0,0 @@
-<?xml version="1.0"?>
-
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<bindings id="tabBindings"
- xmlns="http://www.mozilla.org/xbl"
- xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:xbl="http://www.mozilla.org/xbl">
-
- <binding id="tab-listing" extends="chrome://global/content/bindings/richlistbox.xml#richlistitem">
- <content>
- <xul:hbox flex="1">
- <xul:vbox pack="start">
- <xul:image class="tabIcon"
- xbl:inherits="src=icon"/>
- </xul:vbox>
- <xul:vbox pack="start" flex="1">
- <xul:label xbl:inherits="value=title,selected"
- crop="end" flex="1" class="title"/>
- <xul:label xbl:inherits="value=url,selected"
- crop="end" flex="1" class="url"/>
- </xul:vbox>
- </xul:hbox>
- </content>
- <handlers>
- <handler event="dblclick" button="0">
- <![CDATA[
- RemoteTabViewer.openSelected();
- ]]>
- </handler>
- </handlers>
- </binding>
-
- <binding id="client-listing" extends="chrome://global/content/bindings/richlistbox.xml#richlistitem">
- <content>
- <xul:hbox pack="start" align="center" onfocus="event.target.blur()" onselect="return false;">
- <xul:image/>
- <xul:label xbl:inherits="value=clientName"
- class="clientName"
- crop="center" flex="1"/>
- </xul:hbox>
- </content>
- </binding>
-</bindings>
diff --git a/components/sync/aboutSyncTabs.css b/components/sync/aboutSyncTabs.css
deleted file mode 100644
index 5a35317..0000000
--- a/components/sync/aboutSyncTabs.css
+++ /dev/null
@@ -1,11 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-richlistitem[type="tab"] {
- -moz-binding: url(chrome://browser/content/sync/aboutSyncTabs-bindings.xml#tab-listing);
-}
-
-richlistitem[type="client"] {
- -moz-binding: url(chrome://browser/content/sync/aboutSyncTabs-bindings.xml#client-listing);
-}
diff --git a/components/sync/aboutSyncTabs.js b/components/sync/aboutSyncTabs.js
deleted file mode 100644
index 410494b..0000000
--- a/components/sync/aboutSyncTabs.js
+++ /dev/null
@@ -1,313 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-var Cu = Components.utils;
-
-Cu.import("resource://services-common/utils.js");
-Cu.import("resource://services-sync/main.js");
-Cu.import("resource:///modules/PlacesUIUtils.jsm");
-Cu.import("resource://gre/modules/PlacesUtils.jsm", this);
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-var RemoteTabViewer = {
- _tabsList: null,
-
- init: function () {
- Services.obs.addObserver(this, "weave:service:login:finish", false);
- Services.obs.addObserver(this, "weave:engine:sync:finish", false);
-
- this._tabsList = document.getElementById("tabsList");
-
- this.buildList(true);
- },
-
- uninit: function () {
- Services.obs.removeObserver(this, "weave:service:login:finish");
- Services.obs.removeObserver(this, "weave:engine:sync:finish");
- },
-
- createItem: function(attrs) {
- let item = document.createElement("richlistitem");
-
- // Copy the attributes from the argument into the item
- for (let attr in attrs) {
- item.setAttribute(attr, attrs[attr]);
- }
-
- if (attrs["type"] == "tab") {
- item.label = attrs.title != "" ? attrs.title : attrs.url;
- }
-
- return item;
- },
-
- filterTabs: function(event) {
- let val = event.target.value.toLowerCase();
- let numTabs = this._tabsList.getRowCount();
- let clientTabs = 0;
- let currentClient = null;
-
- for (let i = 0; i < numTabs; i++) {
- let item = this._tabsList.getItemAtIndex(i);
- let hide = false;
- if (item.getAttribute("type") == "tab") {
- if (!item.getAttribute("url").toLowerCase().includes(val) &&
- !item.getAttribute("title").toLowerCase().includes(val)) {
- hide = true;
- } else {
- clientTabs++;
- }
- }
- else if (item.getAttribute("type") == "client") {
- if (currentClient) {
- if (clientTabs == 0) {
- currentClient.hidden = true;
- }
- }
- currentClient = item;
- clientTabs = 0;
- }
- item.hidden = hide;
- }
- if (clientTabs == 0) {
- currentClient.hidden = true;
- }
- },
-
- openSelected: function() {
- let items = this._tabsList.selectedItems;
- let urls = [];
- for (let i = 0;i < items.length;i++) {
- if (items[i].getAttribute("type") == "tab") {
- urls.push(items[i].getAttribute("url"));
- let index = this._tabsList.getIndexOfItem(items[i]);
- this._tabsList.removeItemAt(index);
- }
- }
- if (urls.length) {
- getTopWin().gBrowser.loadTabs(urls);
- this._tabsList.clearSelection();
- }
- },
-
- bookmarkSingleTab: function() {
- let item = this._tabsList.selectedItems[0];
- let uri = Weave.Utils.makeURI(item.getAttribute("url"));
- let title = item.getAttribute("title");
- PlacesUIUtils.showBookmarkDialog({ action: "add"
- , type: "bookmark"
- , uri: uri
- , title: title
- , hiddenRows: [ "description"
- , "location"
- , "loadInSidebar"
- , "keyword" ]
- }, window.top);
- },
-
- bookmarkSelectedTabs: function() {
- let items = this._tabsList.selectedItems;
- let URIs = [];
- for (let i = 0;i < items.length;i++) {
- if (items[i].getAttribute("type") == "tab") {
- let uri = Weave.Utils.makeURI(items[i].getAttribute("url"));
- if (!uri) {
- continue;
- }
-
- URIs.push(uri);
- }
- }
- if (URIs.length) {
- PlacesUIUtils.showBookmarkDialog({ action: "add"
- , type: "folder"
- , URIList: URIs
- , hiddenRows: [ "description" ]
- }, window.top);
- }
- },
-
- getIcon: function (iconUri, defaultIcon) {
- try {
- let iconURI = Weave.Utils.makeURI(iconUri);
- return PlacesUtils.favicons.getFaviconLinkForIcon(iconURI).spec;
- } catch (ex) {
- // Do nothing.
- }
-
- // Just give the provided default icon or the system's default.
- return defaultIcon || PlacesUtils.favicons.defaultFavicon.spec;
- },
-
- _waitingForBuildList: false,
-
- _buildListRequested: false,
-
- buildList: function (force) {
- if (this._waitingForBuildList) {
- this._buildListRequested = true;
- return;
- }
-
- this._waitingForBuildList = true;
- this._buildListRequested = false;
-
- this._clearTabList();
-
- if (Weave.Service.isLoggedIn && this._refetchTabs(force)) {
- this._generateWeaveTabList();
- } else {
- //XXXzpao We should say something about not being logged in & not having data
- // or tell the appropriate condition. (bug 583344)
- }
-
- function complete() {
- this._waitingForBuildList = false;
- if (this._buildListRequested) {
- CommonUtils.nextTick(this.buildList, this);
- }
- }
-
- complete();
- },
-
- _clearTabList: function () {
- let list = this._tabsList;
-
- // Clear out existing richlistitems
- let count = list.getRowCount();
- if (count > 0) {
- for (let i = count - 1; i >= 0; i--) {
- list.removeItemAt(i);
- }
- }
- },
-
- _generateWeaveTabList: function () {
- let engine = Weave.Service.engineManager.get("tabs");
- let list = this._tabsList;
-
- let seenURLs = new Set();
- let localURLs = engine.getOpenURLs();
-
- for (let [guid, client] in Iterator(engine.getAllClients())) {
- // Create the client node, but don't add it in-case we don't show any tabs
- let appendClient = true;
-
- client.tabs.forEach(function({title, urlHistory, icon}) {
- let url = urlHistory[0];
- if (!url || localURLs.has(url) || seenURLs.has(url)) {
- return;
- }
- seenURLs.add(url);
-
- if (appendClient) {
- let attrs = {
- type: "client",
- clientName: client.clientName,
- class: Weave.Service.clientsEngine.isMobile(client.id) ? "mobile" : "desktop"
- };
- let clientEnt = this.createItem(attrs);
- list.appendChild(clientEnt);
- appendClient = false;
- clientEnt.disabled = true;
- }
- let attrs = {
- type: "tab",
- title: title || url,
- url: url,
- icon: this.getIcon(icon),
- }
- let tab = this.createItem(attrs);
- list.appendChild(tab);
- }, this);
- }
- },
-
- adjustContextMenu: function(event) {
- let mode = "all";
- switch (this._tabsList.selectedItems.length) {
- case 0:
- break;
- case 1:
- mode = "single"
- break;
- default:
- mode = "multiple";
- break;
- }
-
- let menu = document.getElementById("tabListContext");
- let el = menu.firstChild;
- while (el) {
- let showFor = el.getAttribute("showFor");
- if (showFor) {
- el.hidden = showFor != mode && showFor != "all";
- }
-
- el = el.nextSibling;
- }
- },
-
- _refetchTabs: function(force) {
- if (!force) {
- // Don't bother refetching tabs if we already did so recently
- let lastFetch = 0;
- try {
- lastFetch = Services.prefs.getIntPref("services.sync.lastTabFetch");
- }
- catch (e) {
- /* Just use the default value of 0 */
- }
-
- let now = Math.floor(Date.now() / 1000);
- if (now - lastFetch < 30) {
- return false;
- }
- }
-
- // if Clients hasn't synced yet this session, we need to sync it as well.
- if (Weave.Service.clientsEngine.lastSync == 0) {
- Weave.Service.clientsEngine.sync();
- }
-
- // Force a sync only for the tabs engine
- let engine = Weave.Service.engineManager.get("tabs");
- engine.lastModified = null;
- engine.sync();
- Services.prefs.setIntPref("services.sync.lastTabFetch",
- Math.floor(Date.now() / 1000));
-
- return true;
- },
-
- observe: function(subject, topic, data) {
- switch (topic) {
- case "weave:service:login:finish":
- this.buildList(true);
- break;
- case "weave:engine:sync:finish":
- if (subject == "tabs") {
- this.buildList(false);
- }
- break;
- }
- },
-
- handleClick: function(event) {
- if (event.target.getAttribute("type") != "tab") {
- return;
- }
-
-
- if (event.button == 1) {
- let url = event.target.getAttribute("url");
- openUILink(url, event);
- let index = this._tabsList.getIndexOfItem(event.target);
- this._tabsList.removeItemAt(index);
- }
- }
-}
-
diff --git a/components/sync/aboutSyncTabs.xul b/components/sync/aboutSyncTabs.xul
deleted file mode 100644
index a4aa003..0000000
--- a/components/sync/aboutSyncTabs.xul
+++ /dev/null
@@ -1,68 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<?xml-stylesheet href="chrome://browser/skin/" type="text/css"?>
-<?xml-stylesheet href="chrome://browser/skin/aboutSyncTabs.css" type="text/css"?>
-<?xml-stylesheet href="chrome://browser/content/sync/aboutSyncTabs.css" type="text/css"?>
-
-<!DOCTYPE window [
- <!ENTITY % aboutSyncTabsDTD SYSTEM "chrome://browser/locale/aboutSyncTabs.dtd">
- %aboutSyncTabsDTD;
-]>
-
-<window id="tabs-display"
- onload="RemoteTabViewer.init()"
- onunload="RemoteTabViewer.uninit()"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml"
- title="&tabs.otherDevices.label;">
- <script type="application/javascript;version=1.8" src="chrome://browser/content/sync/aboutSyncTabs.js"/>
- <script type="application/javascript" src="chrome://browser/content/utilityOverlay.js"/>
- <html:head>
- <html:link rel="icon" href="chrome://browser/skin/sync-16.png"/>
- </html:head>
-
- <popupset id="contextmenus">
- <menupopup id="tabListContext">
- <menuitem label="&tabs.context.openTab.label;"
- accesskey="&tabs.context.openTab.accesskey;"
- oncommand="RemoteTabViewer.openSelected()"
- showFor="single"/>
- <menuitem label="&tabs.context.bookmarkSingleTab.label;"
- accesskey="&tabs.context.bookmarkSingleTab.accesskey;"
- oncommand="RemoteTabViewer.bookmarkSingleTab(event)"
- showFor="single"/>
- <menuitem label="&tabs.context.openMultipleTabs.label;"
- accesskey="&tabs.context.openMultipleTabs.accesskey;"
- oncommand="RemoteTabViewer.openSelected()"
- showFor="multiple"/>
- <menuitem label="&tabs.context.bookmarkMultipleTabs.label;"
- accesskey="&tabs.context.bookmarkMultipleTabs.accesskey;"
- oncommand="RemoteTabViewer.bookmarkSelectedTabs()"
- showFor="multiple"/>
- <menuseparator/>
- <menuitem label="&tabs.context.refreshList.label;"
- accesskey="&tabs.context.refreshList.accesskey;"
- oncommand="RemoteTabViewer.buildList()"
- showFor="all"/>
- </menupopup>
- </popupset>
- <richlistbox context="tabListContext" id="tabsList" seltype="multiple"
- align="center" flex="1"
- onclick="RemoteTabViewer.handleClick(event)"
- oncontextmenu="RemoteTabViewer.adjustContextMenu(event)">
- <hbox id="headers" align="center">
- <label id="tabsListHeading"
- value="&tabs.otherDevices.label;"/>
- <spacer flex="1"/>
- <textbox type="search"
- emptytext="&tabs.searchText.label;"
- oncommand="RemoteTabViewer.filterTabs(event)"/>
- </hbox>
-
- </richlistbox>
-</window>
-
diff --git a/components/sync/addDevice.js b/components/sync/addDevice.js
deleted file mode 100644
index 0390d43..0000000
--- a/components/sync/addDevice.js
+++ /dev/null
@@ -1,157 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-var Ci = Components.interfaces;
-var Cc = Components.classes;
-var Cu = Components.utils;
-
-Cu.import("resource://services-sync/main.js");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-const PIN_PART_LENGTH = 4;
-
-const ADD_DEVICE_PAGE = 0;
-const SYNC_KEY_PAGE = 1;
-const DEVICE_CONNECTED_PAGE = 2;
-
-var gSyncAddDevice = {
-
- init: function init() {
- this.pin1.setAttribute("maxlength", PIN_PART_LENGTH);
- this.pin2.setAttribute("maxlength", PIN_PART_LENGTH);
- this.pin3.setAttribute("maxlength", PIN_PART_LENGTH);
-
- this.nextFocusEl = {pin1: this.pin2,
- pin2: this.pin3,
- pin3: this.wizard.getButton("next")};
-
- this.throbber = document.getElementById("pairDeviceThrobber");
- this.errorRow = document.getElementById("errorRow");
-
- // Kick off a sync. That way the server will have the most recent data from
- // this computer and it will show up immediately on the new device.
- Weave.Service.scheduler.scheduleNextSync(0);
- },
-
- onPageShow: function onPageShow() {
- this.wizard.getButton("back").hidden = true;
-
- switch (this.wizard.pageIndex) {
- case ADD_DEVICE_PAGE:
- this.onTextBoxInput();
- this.wizard.canRewind = false;
- this.wizard.getButton("next").hidden = false;
- this.pin1.focus();
- break;
- case SYNC_KEY_PAGE:
- this.wizard.canAdvance = false;
- this.wizard.canRewind = true;
- this.wizard.getButton("back").hidden = false;
- this.wizard.getButton("next").hidden = true;
- document.getElementById("weavePassphrase").value =
- Weave.Utils.hyphenatePassphrase(Weave.Service.identity.syncKey);
- break;
- case DEVICE_CONNECTED_PAGE:
- this.wizard.canAdvance = true;
- this.wizard.canRewind = false;
- this.wizard.getButton("cancel").hidden = true;
- break;
- }
- },
-
- onWizardAdvance: function onWizardAdvance() {
- switch (this.wizard.pageIndex) {
- case ADD_DEVICE_PAGE:
- this.startTransfer();
- return false;
- case DEVICE_CONNECTED_PAGE:
- window.close();
- return false;
- }
- return true;
- },
-
- startTransfer: function startTransfer() {
- this.errorRow.hidden = true;
- // When onAbort is called, Weave may already be gone.
- const JPAKE_ERROR_USERABORT = Weave.JPAKE_ERROR_USERABORT;
-
- let self = this;
- let jpakeclient = this._jpakeclient = new Weave.JPAKEClient({
- onPaired: function onPaired() {
- let credentials = {account: Weave.Service.identity.account,
- password: Weave.Service.identity.basicPassword,
- synckey: Weave.Service.identity.syncKey,
- serverURL: Weave.Service.serverURL};
- jpakeclient.sendAndComplete(credentials);
- },
- onComplete: function onComplete() {
- delete self._jpakeclient;
- self.wizard.pageIndex = DEVICE_CONNECTED_PAGE;
-
- // Schedule a Sync for soonish to fetch the data uploaded by the
- // device with which we just paired.
- Weave.Service.scheduler.scheduleNextSync(Weave.Service.scheduler.activeInterval);
- },
- onAbort: function onAbort(error) {
- delete self._jpakeclient;
-
- // Aborted by user, ignore.
- if (error == JPAKE_ERROR_USERABORT) {
- return;
- }
-
- self.errorRow.hidden = false;
- self.throbber.hidden = true;
- self.pin1.value = self.pin2.value = self.pin3.value = "";
- self.pin1.disabled = self.pin2.disabled = self.pin3.disabled = false;
- self.pin1.focus();
- }
- });
- this.throbber.hidden = false;
- this.pin1.disabled = this.pin2.disabled = this.pin3.disabled = true;
- this.wizard.canAdvance = false;
-
- let pin = this.pin1.value + this.pin2.value + this.pin3.value;
- let expectDelay = false;
- jpakeclient.pairWithPIN(pin, expectDelay);
- },
-
- onWizardBack: function onWizardBack() {
- if (this.wizard.pageIndex != SYNC_KEY_PAGE)
- return true;
-
- this.wizard.pageIndex = ADD_DEVICE_PAGE;
- return false;
- },
-
- onWizardCancel: function onWizardCancel() {
- if (this._jpakeclient) {
- this._jpakeclient.abort();
- delete this._jpakeclient;
- }
- return true;
- },
-
- onTextBoxInput: function onTextBoxInput(textbox) {
- if (textbox && textbox.value.length == PIN_PART_LENGTH)
- this.nextFocusEl[textbox.id].focus();
-
- this.wizard.canAdvance = (this.pin1.value.length == PIN_PART_LENGTH
- && this.pin2.value.length == PIN_PART_LENGTH
- && this.pin3.value.length == PIN_PART_LENGTH);
- },
-
- goToSyncKeyPage: function goToSyncKeyPage() {
- this.wizard.pageIndex = SYNC_KEY_PAGE;
- }
-
-};
-// onWizardAdvance() and onPageShow() are run before init() so we'll set
-// these up as lazy getters.
-["wizard", "pin1", "pin2", "pin3"].forEach(function (id) {
- XPCOMUtils.defineLazyGetter(gSyncAddDevice, id, function() {
- return document.getElementById(id);
- });
-});
diff --git a/components/sync/addDevice.xul b/components/sync/addDevice.xul
deleted file mode 100644
index f2371aa..0000000
--- a/components/sync/addDevice.xul
+++ /dev/null
@@ -1,129 +0,0 @@
-<?xml version="1.0"?>
-
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
-<?xml-stylesheet href="chrome://browser/skin/syncSetup.css" type="text/css"?>
-<?xml-stylesheet href="chrome://browser/skin/syncCommon.css" type="text/css"?>
-
-<!DOCTYPE window [
-<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
-<!ENTITY % syncBrandDTD SYSTEM "chrome://browser/locale/syncBrand.dtd">
-<!ENTITY % syncSetupDTD SYSTEM "chrome://browser/locale/syncSetup.dtd">
-%brandDTD;
-%syncBrandDTD;
-%syncSetupDTD;
-]>
-<wizard xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml"
- id="wizard"
- title="&pairDevice.title.label;"
- windowtype="Sync:AddDevice"
- persist="screenX screenY"
- onwizardnext="return gSyncAddDevice.onWizardAdvance();"
- onwizardback="return gSyncAddDevice.onWizardBack();"
- onwizardcancel="gSyncAddDevice.onWizardCancel();"
- onload="gSyncAddDevice.init();">
-
- <script type="application/javascript"
- src="chrome://browser/content/sync/addDevice.js"/>
- <script type="application/javascript"
- src="chrome://browser/content/sync/utils.js"/>
- <script type="application/javascript"
- src="chrome://browser/content/utilityOverlay.js"/>
- <script type="application/javascript"
- src="chrome://global/content/printUtils.js"/>
-
- <wizardpage id="addDevicePage"
- label="&pairDevice.title.label;"
- onpageshow="gSyncAddDevice.onPageShow();">
- <description>
- &pairDevice.dialog.description.label;
- <label class="text-link"
- value="&addDevice.showMeHow.label;"
- href="http://www.palemoon.org/sync/help/easy-setup.shtml"/>
- </description>
- <separator class="groove-thin"/>
- <description>
- &addDevice.dialog.enterCode.label;
- </description>
- <separator class="groove-thin"/>
- <vbox align="center">
- <textbox id="pin1"
- class="pin"
- oninput="gSyncAddDevice.onTextBoxInput(this);"
- onfocus="this.select();"
- />
- <textbox id="pin2"
- class="pin"
- oninput="gSyncAddDevice.onTextBoxInput(this);"
- onfocus="this.select();"
- />
- <textbox id="pin3"
- class="pin"
- oninput="gSyncAddDevice.onTextBoxInput(this);"
- onfocus="this.select();"
- />
- </vbox>
- <separator class="groove-thin"/>
- <vbox id="pairDeviceThrobber" align="center" hidden="true">
- <image/>
- </vbox>
- <hbox id="errorRow" pack="center" hidden="true">
- <image class="statusIcon" status="error"/>
- <label class="status"
- value="&addDevice.dialog.tryAgain.label;"/>
- </hbox>
- <spacer flex="3"/>
- <label class="text-link"
- value="&addDevice.dontHaveDevice.label;"
- onclick="gSyncAddDevice.goToSyncKeyPage();"/>
- </wizardpage>
-
- <!-- Need a non-empty label here, otherwise we get a default label on Mac -->
- <wizardpage id="syncKeyPage"
- label=" "
- onpageshow="gSyncAddDevice.onPageShow();">
- <description>
- &addDevice.dialog.recoveryKey.label;
- </description>
- <spacer/>
-
- <groupbox>
- <label value="&recoveryKeyEntry.label;"
- accesskey="&recoveryKeyEntry.accesskey;"
- control="weavePassphrase"/>
- <textbox id="weavePassphrase"
- readonly="true"/>
- </groupbox>
-
- <groupbox align="center">
- <description>&recoveryKeyBackup.description;</description>
- <hbox>
- <button id="printSyncKeyButton"
- label="&button.syncKeyBackup.print.label;"
- accesskey="&button.syncKeyBackup.print.accesskey;"
- oncommand="gSyncUtils.passphrasePrint('weavePassphrase');"/>
- <button id="saveSyncKeyButton"
- label="&button.syncKeyBackup.save.label;"
- accesskey="&button.syncKeyBackup.save.accesskey;"
- oncommand="gSyncUtils.passphraseSave('weavePassphrase');"/>
- </hbox>
- </groupbox>
- </wizardpage>
-
- <wizardpage id="deviceConnectedPage"
- label="&addDevice.dialog.connected.label;"
- onpageshow="gSyncAddDevice.onPageShow();">
- <vbox align="center">
- <image id="successPageIcon"/>
- </vbox>
- <separator/>
- <description class="normal">
- &addDevice.dialog.successful.label;
- </description>
- </wizardpage>
-
-</wizard>
diff --git a/components/sync/genericChange.js b/components/sync/genericChange.js
deleted file mode 100644
index df66391..0000000
--- a/components/sync/genericChange.js
+++ /dev/null
@@ -1,234 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-var Ci = Components.interfaces;
-var Cc = Components.classes;
-
-Components.utils.import("resource://services-sync/main.js");
-Components.utils.import("resource://gre/modules/Services.jsm");
-
-var Change = {
- _dialog: null,
- _dialogType: null,
- _status: null,
- _statusIcon: null,
- _firstBox: null,
- _secondBox: null,
-
- get _passphraseBox() {
- delete this._passphraseBox;
- return this._passphraseBox = document.getElementById("passphraseBox");
- },
-
- get _currentPasswordInvalid() {
- return Weave.Status.login == Weave.LOGIN_FAILED_LOGIN_REJECTED;
- },
-
- get _updatingPassphrase() {
- return this._dialogType == "UpdatePassphrase";
- },
-
- onLoad: function Change_onLoad() {
- /* Load labels */
- let introText = document.getElementById("introText");
- let introText2 = document.getElementById("introText2");
- let warningText = document.getElementById("warningText");
-
- // load some other elements & info from the window
- this._dialog = document.getElementById("change-dialog");
- this._dialogType = window.arguments[0];
- this._duringSetup = window.arguments[1];
- this._status = document.getElementById("status");
- this._statusIcon = document.getElementById("statusIcon");
- this._statusRow = document.getElementById("statusRow");
- this._firstBox = document.getElementById("textBox1");
- this._secondBox = document.getElementById("textBox2");
-
- this._dialog.getButton("finish").disabled = true;
- this._dialog.getButton("back").hidden = true;
-
- this._stringBundle =
- Services.strings.createBundle("chrome://browser/locale/syncGenericChange.properties");
-
- switch (this._dialogType) {
- case "UpdatePassphrase":
- case "ResetPassphrase":
- document.getElementById("textBox1Row").hidden = true;
- document.getElementById("textBox2Row").hidden = true;
- document.getElementById("passphraseLabel").value
- = this._str("new.recoverykey.label");
- document.getElementById("passphraseSpacer").hidden = false;
-
- if (this._updatingPassphrase) {
- document.getElementById("passphraseHelpBox").hidden = false;
- document.title = this._str("new.recoverykey.title");
- introText.textContent = this._str("new.recoverykey.introText");
- this._dialog.getButton("finish").label
- = this._str("new.recoverykey.acceptButton");
- }
- else {
- document.getElementById("generatePassphraseButton").hidden = false;
- document.getElementById("passphraseBackupButtons").hidden = false;
- let pp = Weave.Service.identity.syncKey;
- if (Weave.Utils.isPassphrase(pp))
- pp = Weave.Utils.hyphenatePassphrase(pp);
- this._passphraseBox.value = pp;
- this._passphraseBox.focus();
- document.title = this._str("change.recoverykey.title");
- introText.textContent = this._str("change.synckey.introText2");
- warningText.textContent = this._str("change.recoverykey.warningText");
- this._dialog.getButton("finish").label
- = this._str("change.recoverykey.acceptButton");
- if (this._duringSetup) {
- this._dialog.getButton("finish").disabled = false;
- }
- }
- break;
- case "ChangePassword":
- document.getElementById("passphraseRow").hidden = true;
- let box1label = document.getElementById("textBox1Label");
- let box2label = document.getElementById("textBox2Label");
- box1label.value = this._str("new.password.label");
-
- if (this._currentPasswordInvalid) {
- document.title = this._str("new.password.title");
- introText.textContent = this._str("new.password.introText");
- this._dialog.getButton("finish").label
- = this._str("new.password.acceptButton");
- document.getElementById("textBox2Row").hidden = true;
- }
- else {
- document.title = this._str("change.password.title");
- box2label.value = this._str("new.password.confirm");
- introText.textContent = this._str("change.password3.introText");
- warningText.textContent = this._str("change.password.warningText");
- this._dialog.getButton("finish").label
- = this._str("change.password.acceptButton");
- }
- break;
- }
- document.getElementById("change-page")
- .setAttribute("label", document.title);
- },
-
- _clearStatus: function _clearStatus() {
- this._status.value = "";
- this._statusIcon.removeAttribute("status");
- },
-
- _updateStatus: function Change__updateStatus(str, state) {
- this._updateStatusWithString(this._str(str), state);
- },
-
- _updateStatusWithString: function Change__updateStatusWithString(string, state) {
- this._statusRow.hidden = false;
- this._status.value = string;
- this._statusIcon.setAttribute("status", state);
-
- let error = state == "error";
- this._dialog.getButton("cancel").disabled = !error;
- this._dialog.getButton("finish").disabled = !error;
- document.getElementById("printSyncKeyButton").disabled = !error;
- document.getElementById("saveSyncKeyButton").disabled = !error;
-
- if (state == "success")
- window.setTimeout(window.close, 1500);
- },
-
- onDialogAccept: function() {
- switch (this._dialogType) {
- case "UpdatePassphrase":
- case "ResetPassphrase":
- return this.doChangePassphrase();
- break;
- case "ChangePassword":
- return this.doChangePassword();
- break;
- }
- },
-
- doGeneratePassphrase: function () {
- let passphrase = Weave.Utils.generatePassphrase();
- this._passphraseBox.value = Weave.Utils.hyphenatePassphrase(passphrase);
- this._dialog.getButton("finish").disabled = false;
- },
-
- doChangePassphrase: function Change_doChangePassphrase() {
- let pp = Weave.Utils.normalizePassphrase(this._passphraseBox.value);
- if (this._updatingPassphrase) {
- Weave.Service.identity.syncKey = pp;
- if (Weave.Service.login()) {
- this._updateStatus("change.recoverykey.success", "success");
- Weave.Service.persistLogin();
- Weave.Service.scheduler.delayedAutoConnect(0);
- }
- else {
- this._updateStatus("new.passphrase.status.incorrect", "error");
- }
- }
- else {
- this._updateStatus("change.recoverykey.label", "active");
-
- if (Weave.Service.changePassphrase(pp))
- this._updateStatus("change.recoverykey.success", "success");
- else
- this._updateStatus("change.recoverykey.error", "error");
- }
-
- return false;
- },
-
- doChangePassword: function Change_doChangePassword() {
- if (this._currentPasswordInvalid) {
- Weave.Service.identity.basicPassword = this._firstBox.value;
- if (Weave.Service.login()) {
- this._updateStatus("change.password.status.success", "success");
- Weave.Service.persistLogin();
- }
- else {
- this._updateStatus("new.password.status.incorrect", "error");
- }
- }
- else {
- this._updateStatus("change.password.status.active", "active");
-
- if (Weave.Service.changePassword(this._firstBox.value))
- this._updateStatus("change.password.status.success", "success");
- else
- this._updateStatus("change.password.status.error", "error");
- }
-
- return false;
- },
-
- validate: function (event) {
- let valid = false;
- let errorString = "";
-
- if (this._dialogType == "ChangePassword") {
- if (this._currentPasswordInvalid)
- [valid, errorString] = gSyncUtils.validatePassword(this._firstBox);
- else
- [valid, errorString] = gSyncUtils.validatePassword(this._firstBox, this._secondBox);
- }
- else {
- //Pale Moon: Enforce minimum length of 8 for allowed custom passphrase
- //and don't restrict it to "out of sync" situations only. People who
- //go to this page generally know what they are doing ;)
- valid = this._passphraseBox.value.length >= 8;
- }
-
- if (errorString == "")
- this._clearStatus();
- else
- this._updateStatusWithString(errorString, "error");
-
- this._statusRow.hidden = valid;
- this._dialog.getButton("finish").disabled = !valid;
- },
-
- _str: function Change__string(str) {
- return this._stringBundle.GetStringFromName(str);
- }
-};
diff --git a/components/sync/genericChange.xul b/components/sync/genericChange.xul
deleted file mode 100644
index 3c0b2cd..0000000
--- a/components/sync/genericChange.xul
+++ /dev/null
@@ -1,123 +0,0 @@
-<?xml version="1.0"?>
-
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
-<?xml-stylesheet href="chrome://browser/skin/syncSetup.css" type="text/css"?>
-<?xml-stylesheet href="chrome://browser/skin/syncCommon.css" type="text/css"?>
-
-<!DOCTYPE window [
-<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
-<!ENTITY % syncBrandDTD SYSTEM "chrome://browser/locale/syncBrand.dtd">
-<!ENTITY % syncSetupDTD SYSTEM "chrome://browser/locale/syncSetup.dtd">
-%brandDTD;
-%syncBrandDTD;
-%syncSetupDTD;
-]>
-<wizard xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml"
- id="change-dialog"
- windowtype="Weave:ChangeSomething"
- persist="screenX screenY"
- onwizardnext="Change.onLoad()"
- onwizardfinish="return Change.onDialogAccept();">
-
- <script type="application/javascript"
- src="chrome://browser/content/sync/genericChange.js"/>
- <script type="application/javascript"
- src="chrome://browser/content/sync/utils.js"/>
- <script type="application/javascript"
- src="chrome://global/content/printUtils.js"/>
-
- <wizardpage id="change-page"
- label="">
-
- <description id="introText">
- </description>
-
- <separator class="thin"/>
-
- <groupbox>
- <grid>
- <columns>
- <column align="right"/>
- <column flex="3"/>
- <column flex="1"/>
- </columns>
- <rows>
- <row id="textBox1Row" align="center">
- <label id="textBox1Label" control="textBox1"/>
- <textbox id="textBox1" type="password" oninput="Change.validate()"/>
- <spacer/>
- </row>
- <row id="textBox2Row" align="center">
- <label id="textBox2Label" control="textBox2"/>
- <textbox id="textBox2" type="password" oninput="Change.validate()"/>
- <spacer/>
- </row>
- </rows>
- </grid>
-
- <vbox id="passphraseRow">
- <hbox flex="1">
- <label id="passphraseLabel" control="passphraseBox"/>
- <spacer flex="1"/>
- <label id="generatePassphraseButton"
- hidden="true"
- value="&syncGenerateNewKey.label;"
- class="text-link inline-link"
- onclick="event.stopPropagation();
- Change.doGeneratePassphrase();"/>
- </hbox>
- <textbox id="passphraseBox"
- flex="1"
- onfocus="this.select()"
- oninput="Change.validate()"/>
- </vbox>
-
- <vbox id="feedback" pack="center">
- <hbox id="statusRow" align="center">
- <image id="statusIcon" class="statusIcon"/>
- <label id="status" class="status" value=" "/>
- </hbox>
- </vbox>
- </groupbox>
-
- <separator class="thin"/>
-
- <hbox id="passphraseBackupButtons"
- hidden="true"
- pack="center">
- <button id="printSyncKeyButton"
- label="&button.syncKeyBackup.print.label;"
- accesskey="&button.syncKeyBackup.print.accesskey;"
- oncommand="gSyncUtils.passphrasePrint('passphraseBox');"/>
- <button id="saveSyncKeyButton"
- label="&button.syncKeyBackup.save.label;"
- accesskey="&button.syncKeyBackup.save.accesskey;"
- oncommand="gSyncUtils.passphraseSave('passphraseBox');"/>
- </hbox>
-
- <vbox id="passphraseHelpBox"
- hidden="true">
- <description>
- &existingRecoveryKey.description;
- <label class="text-link"
- href="http://www.palemoon.org/sync/help/recoverykey.shtml">
- &addDevice.showMeHow.label;
- </label>
- </description>
- </vbox>
-
- <spacer id="passphraseSpacer"
- flex="1"
- hidden="true"/>
-
- <description id="warningText" class="data">
- </description>
-
- <spacer flex="1"/>
- </wizardpage>
-</wizard>
diff --git a/components/sync/jar.mn b/components/sync/jar.mn
deleted file mode 100644
index 3782038..0000000
--- a/components/sync/jar.mn
+++ /dev/null
@@ -1,22 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-browser.jar:
- content/browser/sync/aboutSyncTabs.xul
- content/browser/sync/aboutSyncTabs.js
- content/browser/sync/aboutSyncTabs.css
- content/browser/sync/aboutSyncTabs-bindings.xml
- content/browser/sync/setup.xul
- content/browser/sync/addDevice.js
- content/browser/sync/addDevice.xul
- content/browser/sync/setup.js
- content/browser/sync/genericChange.xul
- content/browser/sync/genericChange.js
- content/browser/sync/key.xhtml
- content/browser/sync/notification.xml
- content/browser/sync/quota.xul
- content/browser/sync/quota.js
- content/browser/sync/utils.js
- content/browser/sync/progress.js
- content/browser/sync/progress.xhtml \ No newline at end of file
diff --git a/components/sync/key.xhtml b/components/sync/key.xhtml
deleted file mode 100644
index 92abf0e..0000000
--- a/components/sync/key.xhtml
+++ /dev/null
@@ -1,54 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!DOCTYPE html [
- <!ENTITY % htmlDTD PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">
- %htmlDTD;
- <!ENTITY % syncBrandDTD SYSTEM "chrome://browser/locale/syncBrand.dtd">
- %syncBrandDTD;
- <!ENTITY % syncKeyDTD SYSTEM "chrome://browser/locale/syncKey.dtd">
- %syncKeyDTD;
- <!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd" >
- %globalDTD;
-]>
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
- <title>&syncKey.page.title;</title>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
- <meta name="robots" content="noindex"/>
- <style type="text/css">
- #synckey { font-size: 150% }
- footer { font-size: 70% }
- /* Bug 575675: Need to have an a:visited rule in a chrome document. */
- a:visited { color: purple; }
- </style>
-</head>
-
-<body dir="&locale.dir;">
-<h1>&syncKey.page.title;</h1>
-
-<p id="synckey" dir="ltr">SYNCKEY</p>
-
-<p>&syncKey.page.description2;</p>
-
-<div id="column1">
- <h2>&syncKey.keepItSecret.heading;</h2>
- <p>&syncKey.keepItSecret.description;</p>
-</div>
-
-<div id="column2">
- <h2>&syncKey.keepItSafe.heading;</h2>
- <p><em>&syncKey.keepItSafe1.description;</em>&syncKey.keepItSafe2.description;<em>&syncKey.keepItSafe3.description;</em>&syncKey.keepItSafe4a.description;</p>
-</div>
-
-<p>&syncKey.findOutMore1.label;<a href="http://www.palemoon.org/sync/">http://www.palemoon.org/sync/</a>&syncKey.findOutMore2.label;</p>
-
-<footer>
- &syncKey.footer1.label;<a id="tosLink" href="termsURL">termsURL</a>&syncKey.footer2.label;<a id="ppLink" href="privacyURL">privacyURL</a>&syncKey.footer3.label;
-</footer>
-
-</body>
-</html>
diff --git a/components/sync/moz.build b/components/sync/moz.build
deleted file mode 100644
index 2d64d50..0000000
--- a/components/sync/moz.build
+++ /dev/null
@@ -1,8 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-JAR_MANIFESTS += ['jar.mn']
-
diff --git a/components/sync/notification.xml b/components/sync/notification.xml
deleted file mode 100644
index 8ac881e..0000000
--- a/components/sync/notification.xml
+++ /dev/null
@@ -1,129 +0,0 @@
-<?xml version="1.0"?>
-
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!DOCTYPE bindings [
-<!ENTITY % notificationDTD SYSTEM "chrome://global/locale/notification.dtd">
-%notificationDTD;
-]>
-
-<bindings id="notificationBindings"
- xmlns="http://www.mozilla.org/xbl"
- xmlns:xbl="http://www.mozilla.org/xbl"
- xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-
- <binding id="notificationbox" extends="chrome://global/content/bindings/notification.xml#notificationbox">
- <content>
- <xul:vbox xbl:inherits="hidden=notificationshidden">
- <xul:spacer/>
- <children includes="notification"/>
- </xul:vbox>
- <children/>
- </content>
-
- <implementation>
- <constructor><![CDATA[
- let temp = {};
- Cu.import("resource://services-common/observers.js", temp);
- temp.Observers.add("weave:notification:added", this.onNotificationAdded, this);
- temp.Observers.add("weave:notification:removed", this.onNotificationRemoved, this);
-
- for each (var notification in Weave.Notifications.notifications)
- this._appendNotification(notification);
- ]]></constructor>
-
- <destructor><![CDATA[
- let temp = {};
- Cu.import("resource://services-common/observers.js", temp);
- temp.Observers.remove("weave:notification:added", this.onNotificationAdded, this);
- temp.Observers.remove("weave:notification:removed", this.onNotificationRemoved, this);
- ]]></destructor>
-
- <method name="onNotificationAdded">
- <parameter name="subject"/>
- <parameter name="data"/>
- <body><![CDATA[
- this._appendNotification(subject);
- ]]></body>
- </method>
-
- <method name="onNotificationRemoved">
- <parameter name="subject"/>
- <parameter name="data"/>
- <body><![CDATA[
- // If the view of the notification hasn't been removed yet, remove it.
- var notifications = this.allNotifications;
- for each (var notification in notifications) {
- if (notification.notification == subject) {
- notification.close();
- break;
- }
- }
- ]]></body>
- </method>
-
- <method name="_appendNotification">
- <parameter name="notification"/>
- <body><![CDATA[
- var node = this.appendNotification(notification.description,
- notification.title,
- notification.iconURL,
- notification.priority,
- notification.buttons);
- node.notification = notification;
- ]]></body>
- </method>
-
- </implementation>
- </binding>
-
- <binding id="notification" extends="chrome://global/content/bindings/notification.xml#notification">
- <content>
- <xul:hbox class="notification-inner outset" flex="1" xbl:inherits="type">
- <xul:toolbarbutton ondblclick="event.stopPropagation();"
- class="messageCloseButton close-icon tabbable"
- xbl:inherits="hidden=hideclose"
- tooltiptext="&closeNotification.tooltip;"
- oncommand="document.getBindingParent(this).close()"/>
- <xul:hbox anonid="details" align="center" flex="1">
- <xul:image anonid="messageImage" class="messageImage" xbl:inherits="src=image,type"/>
- <xul:description anonid="messageText" class="messageText" xbl:inherits="xbl:text=label"/>
-
- <!-- The children are the buttons defined by the notification. -->
- <xul:hbox oncommand="document.getBindingParent(this)._doButtonCommand(event);">
- <children/>
- </xul:hbox>
- </xul:hbox>
- </xul:hbox>
- </content>
- <implementation>
- <!-- Note: this used to be a field, but for some reason it kept getting
- - reset to its default value for TabNotification elements.
- - As a property, that doesn't happen, even though the property stores
- - its value in a JS property |_notification| that is not defined
- - in XBL as a field or property. Maybe this is wrong, but it works.
- -->
- <property name="notification"
- onget="return this._notification"
- onset="this._notification = val; return val;"/>
- <method name="close">
- <body><![CDATA[
- Weave.Notifications.remove(this.notification);
-
- // We should be able to call the base class's close method here
- // to remove the notification element from the notification box,
- // but we can't because of bug 373652, so instead we copied its code
- // and execute it below.
- var control = this.control;
- if (control)
- control.removeNotification(this);
- else
- this.hidden = true;
- ]]></body>
- </method>
- </implementation>
- </binding>
-
-</bindings>
diff --git a/components/sync/progress.js b/components/sync/progress.js
deleted file mode 100644
index 101160f..0000000
--- a/components/sync/progress.js
+++ /dev/null
@@ -1,71 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://services-sync/main.js");
-
-var gProgressBar;
-var gCounter = 0;
-
-function onLoad(event) {
- Services.obs.addObserver(onEngineSync, "weave:engine:sync:finish", false);
- Services.obs.addObserver(onEngineSync, "weave:engine:sync:error", false);
- Services.obs.addObserver(onServiceSync, "weave:service:sync:finish", false);
- Services.obs.addObserver(onServiceSync, "weave:service:sync:error", false);
-
- gProgressBar = document.getElementById('uploadProgressBar');
-
- if (Services.prefs.getPrefType("services.sync.firstSync") != Ci.nsIPrefBranch.PREF_INVALID) {
- gProgressBar.hidden = false;
- }
- else {
- gProgressBar.hidden = true;
- }
-}
-
-function onUnload(event) {
- cleanUpObservers();
-}
-
-function cleanUpObservers() {
- try {
- Services.obs.removeObserver(onEngineSync, "weave:engine:sync:finish");
- Services.obs.removeObserver(onEngineSync, "weave:engine:sync:error");
- Services.obs.removeObserver(onServiceSync, "weave:service:sync:finish");
- Services.obs.removeObserver(onServiceSync, "weave:service:sync:error");
- }
- catch (e) {
- // may be double called by unload & exit. Ignore.
- }
-}
-
-function onEngineSync(subject, topic, data) {
- // The Clients engine syncs first. At this point we don't necessarily know
- // yet how many engines will be enabled, so we'll ignore the Clients engine
- // and evaluate how many engines are enabled when the first "real" engine
- // syncs.
- if (data == "clients") {
- return;
- }
-
- if (!gCounter &&
- Services.prefs.getPrefType("services.sync.firstSync") != Ci.nsIPrefBranch.PREF_INVALID) {
- gProgressBar.max = Weave.Service.engineManager.getEnabled().length;
- }
-
- gCounter += 1;
- gProgressBar.setAttribute("value", gCounter);
-}
-
-function onServiceSync(subject, topic, data) {
- // To address the case where 0 engines are synced, we will fill the
- // progress bar so the user knows that the sync has finished.
- gProgressBar.setAttribute("value", gProgressBar.max);
- cleanUpObservers();
-}
-
-function closeTab() {
- window.close();
-}
diff --git a/components/sync/progress.xhtml b/components/sync/progress.xhtml
deleted file mode 100644
index d403cb2..0000000
--- a/components/sync/progress.xhtml
+++ /dev/null
@@ -1,55 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!DOCTYPE html [
- <!ENTITY % htmlDTD
- PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
- "DTD/xhtml1-strict.dtd">
- %htmlDTD;
- <!ENTITY % syncProgressDTD
- SYSTEM "chrome://browser/locale/syncProgress.dtd">
- %syncProgressDTD;
- <!ENTITY % syncSetupDTD
- SYSTEM "chrome://browser/locale/syncSetup.dtd">
- %syncSetupDTD;
- <!ENTITY % globalDTD
- SYSTEM "chrome://global/locale/global.dtd">
- %globalDTD;
-]>
-
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title>&syncProgress.pageTitle;</title>
-
- <link rel="stylesheet" type="text/css" media="all"
- href="chrome://browser/skin/syncProgress.css"/>
-
- <link rel="icon" type="image/png" id="favicon"
- href="chrome://browser/skin/sync-16.png"/>
-
- <script type="text/javascript;version=1.8"
- src="chrome://browser/content/sync/progress.js"/>
- </head>
- <body onload="onLoad(event)" onunload="onUnload(event)" dir="&locale.dir;">
- <title>&setup.successPage.title;</title>
- <div id="floatingBox" class="main-content">
- <div id="title">
- <h1>&setup.successPage.title;</h1>
- </div>
- <div id="successLogo">
- <img id="brandSyncLogo" src="chrome://browser/skin/sync-128.png" alt="&syncProgress.logoAltText;" />
- </div>
- <div id="loadingText">
- <p id="blurb">&syncProgress.textBlurb; </p>
- </div>
- <div id="progressBar">
- <progress id="uploadProgressBar" value="0"/>
- </div>
- <div id="bottomRow">
- <button id="closeButton" onclick="closeTab()">&syncProgress.closeButton; </button>
- </div>
- </div>
- </body>
-</html>
diff --git a/components/sync/quota.js b/components/sync/quota.js
deleted file mode 100644
index b416a44..0000000
--- a/components/sync/quota.js
+++ /dev/null
@@ -1,247 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-const Ci = Components.interfaces;
-const Cc = Components.classes;
-const Cr = Components.results;
-const Cu = Components.utils;
-
-Cu.import("resource://services-sync/main.js");
-Cu.import("resource://gre/modules/DownloadUtils.jsm");
-
-var gSyncQuota = {
-
- init: function init() {
- this.bundle = document.getElementById("quotaStrings");
- let caption = document.getElementById("treeCaption");
- caption.firstChild.nodeValue = this.bundle.getString("quota.treeCaption.label");
-
- gUsageTreeView.init();
- this.tree = document.getElementById("usageTree");
- this.tree.view = gUsageTreeView;
-
- this.loadData();
- },
-
- loadData: function loadData() {
- this._usage_req = Weave.Service.getStorageInfo(Weave.INFO_COLLECTION_USAGE,
- function (error, usage) {
- delete gSyncQuota._usage_req;
- // displayUsageData handles null values, so no need to check 'error'.
- gUsageTreeView.displayUsageData(usage);
- });
-
- let usageLabel = document.getElementById("usageLabel");
- let bundle = this.bundle;
-
- this._quota_req = Weave.Service.getStorageInfo(Weave.INFO_QUOTA,
- function (error, quota) {
- delete gSyncQuota._quota_req;
-
- if (error) {
- usageLabel.value = bundle.getString("quota.usageError.label");
- return;
- }
- let used = gSyncQuota.convertKB(quota[0]);
- if (!quota[1]) {
- // No quota on the server.
- usageLabel.value = bundle.getFormattedString(
- "quota.usageNoQuota.label", used);
- return;
- }
- let percent = Math.round(100 * quota[0] / quota[1]);
- let total = gSyncQuota.convertKB(quota[1]);
- usageLabel.value = bundle.getFormattedString(
- "quota.usagePercentage.label", [percent].concat(used).concat(total));
- });
- },
-
- onCancel: function onCancel() {
- if (this._usage_req) {
- this._usage_req.abort();
- }
- if (this._quota_req) {
- this._quota_req.abort();
- }
- return true;
- },
-
- onAccept: function onAccept() {
- let engines = gUsageTreeView.getEnginesToDisable();
- for each (let engine in engines) {
- Weave.Service.engineManager.get(engine).enabled = false;
- }
- if (engines.length) {
- // The 'Weave' object will disappear once the window closes.
- let Service = Weave.Service;
- Weave.Utils.nextTick(function() { Service.sync(); });
- }
- return this.onCancel();
- },
-
- convertKB: function convertKB(value) {
- return DownloadUtils.convertByteUnits(value * 1024);
- }
-
-};
-
-var gUsageTreeView = {
-
- _ignored: {keys: true,
- meta: true,
- clients: true},
-
- /*
- * Internal data structures underlaying the tree.
- */
- _collections: [],
- _byname: {},
-
- init: function init() {
- let retrievingLabel = gSyncQuota.bundle.getString("quota.retrieving.label");
- for each (let engine in Weave.Service.engineManager.getEnabled()) {
- if (this._ignored[engine.name])
- continue;
-
- // Some engines use the same pref, which means they can only be turned on
- // and off together. We need to combine them here as well.
- let existing = this._byname[engine.prefName];
- if (existing) {
- existing.engines.push(engine.name);
- continue;
- }
-
- let obj = {name: engine.prefName,
- title: this._collectionTitle(engine),
- engines: [engine.name],
- enabled: true,
- sizeLabel: retrievingLabel};
- this._collections.push(obj);
- this._byname[engine.prefName] = obj;
- }
- },
-
- _collectionTitle: function _collectionTitle(engine) {
- try {
- return gSyncQuota.bundle.getString(
- "collection." + engine.prefName + ".label");
- } catch (ex) {
- return engine.Name;
- }
- },
-
- /*
- * Process the quota information as returned by info/collection_usage.
- */
- displayUsageData: function displayUsageData(data) {
- for each (let coll in this._collections) {
- coll.size = 0;
- // If we couldn't retrieve any data, just blank out the label.
- if (!data) {
- coll.sizeLabel = "";
- continue;
- }
-
- for each (let engineName in coll.engines)
- coll.size += data[engineName] || 0;
- let sizeLabel = "";
- sizeLabel = gSyncQuota.bundle.getFormattedString(
- "quota.sizeValueUnit.label", gSyncQuota.convertKB(coll.size));
- coll.sizeLabel = sizeLabel;
- }
- let sizeColumn = this.treeBox.columns.getNamedColumn("size");
- this.treeBox.invalidateColumn(sizeColumn);
- },
-
- /*
- * Handle click events on the tree.
- */
- onTreeClick: function onTreeClick(event) {
- if (event.button == 2)
- return;
-
- let cell = this.treeBox.getCellAt(event.clientX, event.clientY);
- if (cell.col && cell.col.id == "enabled")
- this.toggle(cell.row);
- },
-
- /*
- * Toggle enabled state of an engine.
- */
- toggle: function toggle(row) {
- // Update the tree
- let collection = this._collections[row];
- collection.enabled = !collection.enabled;
- this.treeBox.invalidateRow(row);
- },
-
- /*
- * Return a list of engines (or rather their pref names) that should be
- * disabled.
- */
- getEnginesToDisable: function getEnginesToDisable() {
- // Tycho: return [coll.name for each (coll in this._collections) if (!coll.enabled)];
- let engines = [];
- for each (let coll in this._collections) {
- if (!coll.enabled) {
- engines.push(coll.name);
- }
- }
- return engines;
- },
-
- // nsITreeView
-
- get rowCount() {
- return this._collections.length;
- },
-
- getRowProperties: function(index) { return ""; },
- getCellProperties: function(row, col) { return ""; },
- getColumnProperties: function(col) { return ""; },
- isContainer: function(index) { return false; },
- isContainerOpen: function(index) { return false; },
- isContainerEmpty: function(index) { return false; },
- isSeparator: function(index) { return false; },
- isSorted: function() { return false; },
- canDrop: function(index, orientation, dataTransfer) { return false; },
- drop: function(row, orientation, dataTransfer) {},
- getParentIndex: function(rowIndex) {},
- hasNextSibling: function(rowIndex, afterIndex) { return false; },
- getLevel: function(index) { return 0; },
- getImageSrc: function(row, col) {},
-
- getCellValue: function(row, col) {
- return this._collections[row].enabled;
- },
-
- getCellText: function getCellText(row, col) {
- let collection = this._collections[row];
- switch (col.id) {
- case "collection":
- return collection.title;
- case "size":
- return collection.sizeLabel;
- default:
- return "";
- }
- },
-
- setTree: function setTree(tree) {
- this.treeBox = tree;
- },
-
- toggleOpenState: function(index) {},
- cycleHeader: function(col) {},
- selectionChanged: function() {},
- cycleCell: function(row, col) {},
- isEditable: function(row, col) { return false; },
- isSelectable: function (row, col) { return false; },
- setCellValue: function(row, col, value) {},
- setCellText: function(row, col, value) {},
- performAction: function(action) {},
- performActionOnRow: function(action, row) {},
- performActionOnCell: function(action, row, col) {}
-
-};
diff --git a/components/sync/quota.xul b/components/sync/quota.xul
deleted file mode 100644
index 99e6ed7..0000000
--- a/components/sync/quota.xul
+++ /dev/null
@@ -1,65 +0,0 @@
-<?xml version="1.0"?>
-
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
-<?xml-stylesheet href="chrome://browser/skin/syncQuota.css"?>
-
-<!DOCTYPE dialog [
-<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
-<!ENTITY % syncBrandDTD SYSTEM "chrome://browser/locale/syncBrand.dtd">
-<!ENTITY % syncQuotaDTD SYSTEM "chrome://browser/locale/syncQuota.dtd">
-%brandDTD;
-%syncBrandDTD;
-%syncQuotaDTD;
-]>
-<dialog id="quotaDialog"
- windowtype="Sync:ViewQuota"
- persist="screenX screenY width height"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml"
- onload="gSyncQuota.init()"
- buttons="accept,cancel"
- title="&quota.dialogTitle.label;"
- ondialogcancel="return gSyncQuota.onCancel();"
- ondialogaccept="return gSyncQuota.onAccept();">
-
- <script type="application/javascript"
- src="chrome://browser/content/sync/quota.js"/>
-
- <stringbundleset id="stringbundleset">
- <stringbundle id="quotaStrings"
- src="chrome://browser/locale/syncQuota.properties"/>
- </stringbundleset>
-
- <vbox flex="1">
- <label id="usageLabel"
- value="&quota.retrievingInfo.label;"/>
- <separator/>
- <tree id="usageTree"
- seltype="single"
- hidecolumnpicker="true"
- onclick="gUsageTreeView.onTreeClick(event);"
- flex="1">
- <treecols>
- <treecol id="enabled"
- type="checkbox"
- fixed="true"/>
- <splitter class="tree-splitter"/>
- <treecol id="collection"
- label="&quota.typeColumn.label;"
- flex="1"/>
- <splitter class="tree-splitter"/>
- <treecol id="size"
- label="&quota.sizeColumn.label;"
- flex="1"/>
- </treecols>
- <treechildren flex="1"/>
- </tree>
- <separator/>
- <description id="treeCaption"> </description>
- </vbox>
-
-</dialog>
diff --git a/components/sync/setup.js b/components/sync/setup.js
deleted file mode 100644
index e8d67a5..0000000
--- a/components/sync/setup.js
+++ /dev/null
@@ -1,1071 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-var Ci = Components.interfaces;
-var Cc = Components.classes;
-var Cr = Components.results;
-var Cu = Components.utils;
-
-// page consts
-
-const PAIR_PAGE = 0;
-const INTRO_PAGE = 1;
-const NEW_ACCOUNT_START_PAGE = 2;
-const EXISTING_ACCOUNT_CONNECT_PAGE = 3;
-const EXISTING_ACCOUNT_LOGIN_PAGE = 4;
-const OPTIONS_PAGE = 5;
-const OPTIONS_CONFIRM_PAGE = 6;
-
-// Broader than we'd like, but after this changed from api-secure.recaptcha.net
-// we had no choice. At least we only do this for the duration of setup.
-// See discussion in Bugs 508112 and 653307.
-const RECAPTCHA_DOMAIN = "https://www.google.com";
-
-const PIN_PART_LENGTH = 4;
-
-Cu.import("resource://services-sync/main.js");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/PlacesUtils.jsm");
-Cu.import("resource://gre/modules/PluralForm.jsm");
-
-
-function setVisibility(element, visible) {
- element.style.visibility = visible ? "visible" : "hidden";
-}
-
-var gSyncSetup = {
- QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
- Ci.nsIWebProgressListener,
- Ci.nsISupportsWeakReference]),
-
- captchaBrowser: null,
- wizard: null,
- _disabledSites: [],
-
- status: {
- password: false,
- email: false,
- server: false
- },
-
- get _remoteSites() [Weave.Service.serverURL, RECAPTCHA_DOMAIN],
-
- get _usingMainServers() {
- if (this._settingUpNew)
- return document.getElementById("server").selectedIndex == 0;
- return document.getElementById("existingServer").selectedIndex == 0;
- },
-
- init: function () {
- let obs = [
- ["weave:service:change-passphrase", "onResetPassphrase"],
- ["weave:service:login:start", "onLoginStart"],
- ["weave:service:login:error", "onLoginEnd"],
- ["weave:service:login:finish", "onLoginEnd"]];
-
- // Add the observers now and remove them on unload
- let self = this;
- let addRem = function(add) {
- obs.forEach(function([topic, func]) {
- //XXXzpao This should use Services.obs.* but Weave's Obs does nice handling
- // of `this`. Fix in a followup. (bug 583347)
- if (add)
- Weave.Svc.Obs.add(topic, self[func], self);
- else
- Weave.Svc.Obs.remove(topic, self[func], self);
- });
- };
- addRem(true);
- window.addEventListener("unload", function() addRem(false), false);
-
- window.setTimeout(function () {
- // Force Service to be loaded so that engines are registered.
- // See Bug 670082.
- Weave.Service;
- }, 0);
-
- this.captchaBrowser = document.getElementById("captcha");
-
- this.wizardType = null;
- if (window.arguments && window.arguments[0]) {
- this.wizardType = window.arguments[0];
- }
- switch (this.wizardType) {
- case null:
- this.wizard.pageIndex = INTRO_PAGE;
- // Fall through!
- case "pair":
- this.captchaBrowser.addProgressListener(this);
- Weave.Svc.Prefs.set("firstSync", "notReady");
- break;
- case "reset":
- this._resettingSync = true;
- this.wizard.pageIndex = OPTIONS_PAGE;
- break;
- }
-
- this.wizard.getButton("extra1").label =
- this._stringBundle.GetStringFromName("button.syncOptions.label");
-
- // Remember these values because the options pages change them temporarily.
- this._nextButtonLabel = this.wizard.getButton("next").label;
- this._nextButtonAccesskey = this.wizard.getButton("next")
- .getAttribute("accesskey");
- this._backButtonLabel = this.wizard.getButton("back").label;
- this._backButtonAccesskey = this.wizard.getButton("back")
- .getAttribute("accesskey");
- },
-
- startNewAccountSetup: function () {
- if (!Weave.Utils.ensureMPUnlocked())
- return false;
- this._settingUpNew = true;
- this.wizard.pageIndex = NEW_ACCOUNT_START_PAGE;
- },
-
- useExistingAccount: function () {
- if (!Weave.Utils.ensureMPUnlocked())
- return false;
- this._settingUpNew = false;
- if (this.wizardType == "pair") {
- // We're already pairing, so there's no point in pairing again.
- // Go straight to the manual login page.
- this.wizard.pageIndex = EXISTING_ACCOUNT_LOGIN_PAGE;
- } else {
- this.wizard.pageIndex = EXISTING_ACCOUNT_CONNECT_PAGE;
- }
- },
-
- resetPassphrase: function resetPassphrase() {
- // Apply the existing form fields so that
- // Weave.Service.changePassphrase() has the necessary credentials.
- Weave.Service.identity.account = document.getElementById("existingAccountName").value;
- Weave.Service.identity.basicPassword = document.getElementById("existingPassword").value;
-
- // Generate a new passphrase so that Weave.Service.login() will
- // actually do something.
- let passphrase = Weave.Utils.generatePassphrase();
- Weave.Service.identity.syncKey = passphrase;
-
- // Only open the dialog if username + password are actually correct.
- Weave.Service.login();
- if ([Weave.LOGIN_FAILED_INVALID_PASSPHRASE,
- Weave.LOGIN_FAILED_NO_PASSPHRASE,
- Weave.LOGIN_SUCCEEDED].indexOf(Weave.Status.login) == -1) {
- return;
- }
-
- // Hide any errors about the passphrase, we know it's not right.
- let feedback = document.getElementById("existingPassphraseFeedbackRow");
- feedback.hidden = true;
- let el = document.getElementById("existingPassphrase");
- el.value = Weave.Utils.hyphenatePassphrase(passphrase);
-
- // changePassphrase() will sync, make sure we set the "firstSync" pref
- // according to the user's pref.
- Weave.Svc.Prefs.reset("firstSync");
- this.setupInitialSync();
- gSyncUtils.resetPassphrase(true);
- },
-
- onResetPassphrase: function () {
- document.getElementById("existingPassphrase").value =
- Weave.Utils.hyphenatePassphrase(Weave.Service.identity.syncKey);
- this.checkFields();
- this.wizard.advance();
- },
-
- onLoginStart: function () {
- this.toggleLoginFeedback(false);
- },
-
- onLoginEnd: function () {
- this.toggleLoginFeedback(true);
- },
-
- sendCredentialsAfterSync: function () {
- let send = function() {
- Services.obs.removeObserver("weave:service:sync:finish", send);
- Services.obs.removeObserver("weave:service:sync:error", send);
- let credentials = {account: Weave.Service.identity.account,
- password: Weave.Service.identity.basicPassword,
- synckey: Weave.Service.identity.syncKey,
- serverURL: Weave.Service.serverURL};
- this._jpakeclient.sendAndComplete(credentials);
- }.bind(this);
- Services.obs.addObserver("weave:service:sync:finish", send, false);
- Services.obs.addObserver("weave:service:sync:error", send, false);
- },
-
- toggleLoginFeedback: function (stop) {
- document.getElementById("login-throbber").hidden = stop;
- let password = document.getElementById("existingPasswordFeedbackRow");
- let server = document.getElementById("existingServerFeedbackRow");
- let passphrase = document.getElementById("existingPassphraseFeedbackRow");
-
- if (!stop || (Weave.Status.login == Weave.LOGIN_SUCCEEDED)) {
- password.hidden = server.hidden = passphrase.hidden = true;
- return;
- }
-
- let feedback;
- switch (Weave.Status.login) {
- case Weave.LOGIN_FAILED_NETWORK_ERROR:
- case Weave.LOGIN_FAILED_SERVER_ERROR:
- feedback = server;
- break;
- case Weave.LOGIN_FAILED_LOGIN_REJECTED:
- case Weave.LOGIN_FAILED_NO_USERNAME:
- case Weave.LOGIN_FAILED_NO_PASSWORD:
- feedback = password;
- break;
- case Weave.LOGIN_FAILED_INVALID_PASSPHRASE:
- feedback = passphrase;
- break;
- }
- this._setFeedbackMessage(feedback, false, Weave.Status.login);
- },
-
- setupInitialSync: function () {
- let action = document.getElementById("mergeChoiceRadio").selectedItem.id;
- switch (action) {
- case "resetClient":
- // if we're not resetting sync, we don't need to explicitly
- // call resetClient
- if (!this._resettingSync)
- return;
- // otherwise, fall through
- case "wipeClient":
- case "wipeRemote":
- Weave.Svc.Prefs.set("firstSync", action);
- break;
- }
- },
-
- // fun with validation!
- checkFields: function () {
- this.wizard.canAdvance = this.readyToAdvance();
- },
-
- readyToAdvance: function () {
- switch (this.wizard.pageIndex) {
- case INTRO_PAGE:
- return false;
- case NEW_ACCOUNT_START_PAGE:
- for (let i in this.status) {
- if (!this.status[i])
- return false;
- }
- if (this._usingMainServers)
- return document.getElementById("tos").checked;
-
- return true;
- case EXISTING_ACCOUNT_LOGIN_PAGE:
- let hasUser = document.getElementById("existingAccountName").value != "";
- let hasPass = document.getElementById("existingPassword").value != "";
- let hasKey = document.getElementById("existingPassphrase").value != "";
-
- if (hasUser && hasPass && hasKey) {
- if (this._usingMainServers)
- return true;
-
- if (this._validateServer(document.getElementById("existingServer"))) {
- return true;
- }
- }
- return false;
- }
- // Default, e.g. wizard's special page -1 etc.
- return true;
- },
-
- onPINInput: function onPINInput(textbox) {
- if (textbox && textbox.value.length == PIN_PART_LENGTH) {
- this.nextFocusEl[textbox.id].focus();
- }
- this.wizard.canAdvance = (this.pin1.value.length == PIN_PART_LENGTH &&
- this.pin2.value.length == PIN_PART_LENGTH &&
- this.pin3.value.length == PIN_PART_LENGTH);
- },
-
- onEmailInput: function () {
- // Check account validity when the user stops typing for 1 second.
- if (this._checkAccountTimer)
- window.clearTimeout(this._checkAccountTimer);
- this._checkAccountTimer = window.setTimeout(function () {
- gSyncSetup.checkAccount();
- }, 1000);
- },
-
- checkAccount: function() {
- delete this._checkAccountTimer;
- let value = Weave.Utils.normalizeAccount(
- document.getElementById("weaveEmail").value);
- if (!value) {
- this.status.email = false;
- this.checkFields();
- return;
- }
-
- let re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
- let feedback = document.getElementById("emailFeedbackRow");
- let valid = re.test(value);
-
- let str = "";
- if (!valid) {
- str = "invalidEmail.label";
- } else {
- let availCheck = Weave.Service.checkAccount(value);
- valid = availCheck == "available";
- if (!valid) {
- if (availCheck == "notAvailable")
- str = "usernameNotAvailable.label";
- else
- str = availCheck;
- }
- }
-
- this._setFeedbackMessage(feedback, valid, str);
- this.status.email = valid;
- if (valid)
- Weave.Service.identity.account = value;
- this.checkFields();
- },
-
- onPasswordChange: function () {
- let password = document.getElementById("weavePassword");
- let pwconfirm = document.getElementById("weavePasswordConfirm");
- let [valid, errorString] = gSyncUtils.validatePassword(password, pwconfirm);
-
- let feedback = document.getElementById("passwordFeedbackRow");
- this._setFeedback(feedback, valid, errorString);
-
- this.status.password = valid;
- this.checkFields();
- },
-
- onPageShow: function() {
- switch (this.wizard.pageIndex) {
- case PAIR_PAGE:
- this.wizard.getButton("back").hidden = true;
- this.wizard.getButton("extra1").hidden = true;
- this.onPINInput();
- this.pin1.focus();
- break;
- case INTRO_PAGE:
- // We may not need the captcha in the Existing Account branch of the
- // wizard. However, we want to preload it to avoid any flickering while
- // the Create Account page is shown.
- this.loadCaptcha();
- this.wizard.getButton("next").hidden = true;
- this.wizard.getButton("back").hidden = true;
- this.wizard.getButton("extra1").hidden = true;
- this.checkFields();
- break;
- case NEW_ACCOUNT_START_PAGE:
- this.wizard.getButton("extra1").hidden = false;
- this.wizard.getButton("next").hidden = false;
- this.wizard.getButton("back").hidden = false;
- this.onServerCommand();
- this.wizard.canRewind = true;
- this.checkFields();
- break;
- case EXISTING_ACCOUNT_CONNECT_PAGE:
- Weave.Svc.Prefs.set("firstSync", "existingAccount");
- this.wizard.getButton("next").hidden = false;
- this.wizard.getButton("back").hidden = false;
- this.wizard.getButton("extra1").hidden = false;
- this.wizard.canAdvance = false;
- this.wizard.canRewind = true;
- this.startEasySetup();
- break;
- case EXISTING_ACCOUNT_LOGIN_PAGE:
- this.wizard.getButton("next").hidden = false;
- this.wizard.getButton("back").hidden = false;
- this.wizard.getButton("extra1").hidden = false;
- this.wizard.canRewind = true;
- this.checkFields();
- break;
- case OPTIONS_PAGE:
- this.wizard.canRewind = false;
- this.wizard.canAdvance = true;
- if (!this._resettingSync) {
- this.wizard.getButton("next").label =
- this._stringBundle.GetStringFromName("button.syncOptionsDone.label");
- this.wizard.getButton("next").removeAttribute("accesskey");
- }
- this.wizard.getButton("next").hidden = false;
- this.wizard.getButton("back").hidden = true;
- this.wizard.getButton("cancel").hidden = !this._resettingSync;
- this.wizard.getButton("extra1").hidden = true;
- document.getElementById("syncComputerName").value = Weave.Service.clientsEngine.localName;
- document.getElementById("syncOptions").collapsed = this._resettingSync;
- document.getElementById("mergeOptions").collapsed = this._settingUpNew;
- break;
- case OPTIONS_CONFIRM_PAGE:
- this.wizard.canRewind = true;
- this.wizard.canAdvance = true;
- this.wizard.getButton("back").label =
- this._stringBundle.GetStringFromName("button.syncOptionsCancel.label");
- this.wizard.getButton("back").removeAttribute("accesskey");
- this.wizard.getButton("back").hidden = this._resettingSync;
- this.wizard.getButton("next").hidden = false;
- this.wizard.getButton("finish").hidden = true;
- break;
- }
- },
-
- onWizardAdvance: function () {
- // Check pageIndex so we don't prompt before the Sync setup wizard appears.
- // This is a fallback in case the Master Password gets locked mid-wizard.
- if ((this.wizard.pageIndex >= 0) &&
- !Weave.Utils.ensureMPUnlocked()) {
- return false;
- }
-
- switch (this.wizard.pageIndex) {
- case PAIR_PAGE:
- this.startPairing();
- return false;
- case NEW_ACCOUNT_START_PAGE:
- // If the user selects Next (e.g. by hitting enter) when we haven't
- // executed the delayed checks yet, execute them immediately.
- if (this._checkAccountTimer) {
- this.checkAccount();
- }
- if (this._checkServerTimer) {
- this.checkServer();
- }
- if (!this.wizard.canAdvance) {
- return false;
- }
-
- let doc = this.captchaBrowser.contentDocument;
- let getField = function getField(field) {
- let node = doc.getElementById("recaptcha_" + field + "_field");
- return node && node.value;
- };
-
- // Display throbber
- let feedback = document.getElementById("captchaFeedback");
- let image = feedback.firstChild;
- let label = image.nextSibling;
- image.setAttribute("status", "active");
- label.value = this._stringBundle.GetStringFromName("verifying.label");
- setVisibility(feedback, true);
-
- let password = document.getElementById("weavePassword").value;
- let email = Weave.Utils.normalizeAccount(
- document.getElementById("weaveEmail").value);
- let challenge = getField("challenge");
- let response = getField("response");
-
- let error = Weave.Service.createAccount(email, password,
- challenge, response);
-
- if (error == null) {
- Weave.Service.identity.account = email;
- Weave.Service.identity.basicPassword = password;
- Weave.Service.identity.syncKey = Weave.Utils.generatePassphrase();
- this._handleNoScript(false);
- Weave.Svc.Prefs.set("firstSync", "newAccount");
- this.wizardFinish();
- return false;
- }
-
- image.setAttribute("status", "error");
- label.value = Weave.Utils.getErrorString(error);
- return false;
- case EXISTING_ACCOUNT_LOGIN_PAGE:
- Weave.Service.identity.account = Weave.Utils.normalizeAccount(
- document.getElementById("existingAccountName").value);
- Weave.Service.identity.basicPassword =
- document.getElementById("existingPassword").value;
- let pp = document.getElementById("existingPassphrase").value;
- Weave.Service.identity.syncKey = Weave.Utils.normalizePassphrase(pp);
- if (Weave.Service.login()) {
- this.wizardFinish();
- }
- return false;
- case OPTIONS_PAGE:
- let desc = document.getElementById("mergeChoiceRadio").selectedIndex;
- // No confirmation needed on new account setup or merge option
- // with existing account.
- if (this._settingUpNew || (!this._resettingSync && desc == 0))
- return this.returnFromOptions();
- return this._handleChoice();
- case OPTIONS_CONFIRM_PAGE:
- if (this._resettingSync) {
- this.wizardFinish();
- return false;
- }
- return this.returnFromOptions();
- }
- return true;
- },
-
- onWizardBack: function () {
- switch (this.wizard.pageIndex) {
- case NEW_ACCOUNT_START_PAGE:
- case EXISTING_ACCOUNT_LOGIN_PAGE:
- this.wizard.pageIndex = INTRO_PAGE;
- return false;
- case EXISTING_ACCOUNT_CONNECT_PAGE:
- this.abortEasySetup();
- this.wizard.pageIndex = INTRO_PAGE;
- return false;
- case EXISTING_ACCOUNT_LOGIN_PAGE:
- // If we were already pairing on entry, we went straight to the manual
- // login page. If subsequently we go back, return to the page that lets
- // us choose whether we already have an account.
- if (this.wizardType == "pair") {
- this.wizard.pageIndex = INTRO_PAGE;
- return false;
- }
- return true;
- case OPTIONS_CONFIRM_PAGE:
- // Backing up from the confirmation page = resetting first sync to merge.
- document.getElementById("mergeChoiceRadio").selectedIndex = 0;
- return this.returnFromOptions();
- }
- return true;
- },
-
- wizardFinish: function () {
- this.setupInitialSync();
-
- if (this.wizardType == "pair") {
- this.completePairing();
- }
-
- if (!this._resettingSync) {
- function isChecked(element) {
- return document.getElementById(element).hasAttribute("checked");
- }
-
- let prefs = ["engine.bookmarks", "engine.passwords", "engine.history",
- "engine.tabs", "engine.prefs", "engine.addons"];
- for (let i = 0;i < prefs.length;i++) {
- Weave.Svc.Prefs.set(prefs[i], isChecked(prefs[i]));
- }
-
- // XXX: Addons syncing is currently not operational;
- // Make doubly-sure to always disable addons syncing pref
- Weave.Svc.Prefs.set("engine.addons", false);
-
- this._handleNoScript(false);
- if (Weave.Svc.Prefs.get("firstSync", "") == "notReady")
- Weave.Svc.Prefs.reset("firstSync");
-
- Weave.Service.persistLogin();
- Weave.Svc.Obs.notify("weave:service:setup-complete");
-
- gSyncUtils.openFirstSyncProgressPage();
- }
- Weave.Utils.nextTick(Weave.Service.sync, Weave.Service);
- window.close();
- },
-
- onWizardCancel: function () {
- if (this._resettingSync)
- return;
-
- this.abortEasySetup();
- this._handleNoScript(false);
- Weave.Service.startOver();
- },
-
- onSyncOptions: function () {
- this._beforeOptionsPage = this.wizard.pageIndex;
- this.wizard.pageIndex = OPTIONS_PAGE;
- },
-
- returnFromOptions: function() {
- this.wizard.getButton("next").label = this._nextButtonLabel;
- this.wizard.getButton("next").setAttribute("accesskey",
- this._nextButtonAccesskey);
- this.wizard.getButton("back").label = this._backButtonLabel;
- this.wizard.getButton("back").setAttribute("accesskey",
- this._backButtonAccesskey);
- this.wizard.getButton("cancel").hidden = false;
- this.wizard.getButton("extra1").hidden = false;
- this.wizard.pageIndex = this._beforeOptionsPage;
- return false;
- },
-
- startPairing: function startPairing() {
- this.pairDeviceErrorRow.hidden = true;
- // When onAbort is called, Weave may already be gone.
- const JPAKE_ERROR_USERABORT = Weave.JPAKE_ERROR_USERABORT;
-
- let self = this;
- let jpakeclient = this._jpakeclient = new Weave.JPAKEClient({
- onPaired: function onPaired() {
- self.wizard.pageIndex = INTRO_PAGE;
- },
- onComplete: function onComplete() {
- // This method will never be called since SendCredentialsController
- // will take over after the wizard completes.
- },
- onAbort: function onAbort(error) {
- delete self._jpakeclient;
-
- // Aborted by user, ignore. The window is almost certainly going to close
- // or is already closed.
- if (error == JPAKE_ERROR_USERABORT) {
- return;
- }
-
- self.pairDeviceErrorRow.hidden = false;
- self.pairDeviceThrobber.hidden = true;
- self.pin1.value = self.pin2.value = self.pin3.value = "";
- self.pin1.disabled = self.pin2.disabled = self.pin3.disabled = false;
- if (self.wizard.pageIndex == PAIR_PAGE) {
- self.pin1.focus();
- }
- }
- });
- this.pairDeviceThrobber.hidden = false;
- this.pin1.disabled = this.pin2.disabled = this.pin3.disabled = true;
- this.wizard.canAdvance = false;
-
- let pin = this.pin1.value + this.pin2.value + this.pin3.value;
- let expectDelay = true;
- jpakeclient.pairWithPIN(pin, expectDelay);
- },
-
- completePairing: function completePairing() {
- if (!this._jpakeclient) {
- // The channel was aborted while we were setting up the account
- // locally. XXX TODO should we do anything here, e.g. tell
- // the user on the last wizard page that it's ok, they just
- // have to pair again?
- return;
- }
- let controller = new Weave.SendCredentialsController(this._jpakeclient,
- Weave.Service);
- this._jpakeclient.controller = controller;
- },
-
- startEasySetup: function () {
- // Don't do anything if we have a client already (e.g. we went to
- // Sync Options and just came back).
- if (this._jpakeclient)
- return;
-
- // When onAbort is called, Weave may already be gone
- const JPAKE_ERROR_USERABORT = Weave.JPAKE_ERROR_USERABORT;
-
- let self = this;
- this._jpakeclient = new Weave.JPAKEClient({
- displayPIN: function displayPIN(pin) {
- document.getElementById("easySetupPIN1").value = pin.slice(0, 4);
- document.getElementById("easySetupPIN2").value = pin.slice(4, 8);
- document.getElementById("easySetupPIN3").value = pin.slice(8);
- },
-
- onPairingStart: function onPairingStart() {},
-
- onComplete: function onComplete(credentials) {
- Weave.Service.identity.account = credentials.account;
- Weave.Service.identity.basicPassword = credentials.password;
- Weave.Service.identity.syncKey = credentials.synckey;
- Weave.Service.serverURL = credentials.serverURL;
- gSyncSetup.wizardFinish();
- },
-
- onAbort: function onAbort(error) {
- delete self._jpakeclient;
-
- // Ignore if wizard is aborted.
- if (error == JPAKE_ERROR_USERABORT)
- return;
-
- // Automatically go to manual setup if we couldn't acquire a channel.
- if (error == Weave.JPAKE_ERROR_CHANNEL) {
- self.wizard.pageIndex = EXISTING_ACCOUNT_LOGIN_PAGE;
- return;
- }
-
- // Restart on all other errors.
- self.startEasySetup();
- }
- });
- this._jpakeclient.receiveNoPIN();
- },
-
- abortEasySetup: function () {
- document.getElementById("easySetupPIN1").value = "";
- document.getElementById("easySetupPIN2").value = "";
- document.getElementById("easySetupPIN3").value = "";
- if (!this._jpakeclient)
- return;
-
- this._jpakeclient.abort();
- delete this._jpakeclient;
- },
-
- manualSetup: function () {
- this.abortEasySetup();
- this.wizard.pageIndex = EXISTING_ACCOUNT_LOGIN_PAGE;
- },
-
- // _handleNoScript is needed because it blocks the captcha. So we temporarily
- // allow the necessary sites so that we can verify the user is in fact a human.
- // This was done with the help of Giorgio (NoScript author). See bug 508112.
- _handleNoScript: function (addExceptions) {
- // if NoScript isn't installed, or is disabled, bail out.
- let ns = Cc["@maone.net/noscript-service;1"];
- if (ns == null)
- return;
-
- ns = ns.getService().wrappedJSObject;
- if (addExceptions) {
- this._remoteSites.forEach(function(site) {
- site = ns.getSite(site);
- if (!ns.isJSEnabled(site)) {
- this._disabledSites.push(site); // save status
- ns.setJSEnabled(site, true); // allow site
- }
- }, this);
- }
- else {
- this._disabledSites.forEach(function(site) {
- ns.setJSEnabled(site, false);
- });
- this._disabledSites = [];
- }
- },
-
- onExistingServerCommand: function () {
- let control = document.getElementById("existingServer");
- if (control.selectedIndex == 0) {
- control.removeAttribute("editable");
- Weave.Svc.Prefs.reset("serverURL");
- } else {
- control.setAttribute("editable", "true");
- // Force a style flush to ensure that the binding is attached.
- control.clientTop;
- control.value = "";
- control.inputField.focus();
- }
- document.getElementById("existingServerFeedbackRow").hidden = true;
- this.checkFields();
- },
-
- onExistingServerInput: function () {
- // Check custom server validity when the user stops typing for 1 second.
- if (this._existingServerTimer)
- window.clearTimeout(this._existingServerTimer);
- this._existingServerTimer = window.setTimeout(function () {
- gSyncSetup.checkFields();
- }, 1000);
- },
-
- onServerCommand: function () {
- setVisibility(document.getElementById("TOSRow"), this._usingMainServers);
- let control = document.getElementById("server");
- if (!this._usingMainServers) {
- control.setAttribute("editable", "true");
- // Force a style flush to ensure that the binding is attached.
- control.clientTop;
- control.value = "";
- control.inputField.focus();
- // checkServer() will call checkAccount() and checkFields().
- this.checkServer();
- return;
- }
- control.removeAttribute("editable");
- Weave.Svc.Prefs.reset("serverURL");
- if (this._settingUpNew) {
- this.loadCaptcha();
- }
- this.checkAccount();
- this.status.server = true;
- document.getElementById("serverFeedbackRow").hidden = true;
- this.checkFields();
- },
-
- onServerInput: function () {
- // Check custom server validity when the user stops typing for 1 second.
- if (this._checkServerTimer)
- window.clearTimeout(this._checkServerTimer);
- this._checkServerTimer = window.setTimeout(function () {
- gSyncSetup.checkServer();
- }, 1000);
- },
-
- checkServer: function () {
- delete this._checkServerTimer;
- let el = document.getElementById("server");
- let valid = false;
- let feedback = document.getElementById("serverFeedbackRow");
- let str = "";
- if (el.value) {
- valid = this._validateServer(el);
- let str = valid ? "" : "serverInvalid.label";
- this._setFeedbackMessage(feedback, valid, str);
- }
- else
- this._setFeedbackMessage(feedback, true);
-
- // Recheck account against the new server.
- if (valid)
- this.checkAccount();
-
- this.status.server = valid;
- this.checkFields();
- },
-
- _validateServer: function (element) {
- let valid = false;
- let val = element.value;
- if (!val)
- return false;
-
- let uri = Weave.Utils.makeURI(val);
-
- if (!uri)
- uri = Weave.Utils.makeURI("https://" + val);
-
- if (uri && this._settingUpNew) {
- function isValid(uri) {
- Weave.Service.serverURL = uri.spec;
- let check = Weave.Service.checkAccount("a");
- return (check == "available" || check == "notAvailable");
- }
-
- if (uri.schemeIs("http")) {
- uri.scheme = "https";
- if (isValid(uri))
- valid = true;
- else
- // setting the scheme back to http
- uri.scheme = "http";
- }
- if (!valid)
- valid = isValid(uri);
-
- if (valid) {
- this.loadCaptcha();
- }
- }
- else if (uri) {
- valid = true;
- Weave.Service.serverURL = uri.spec;
- }
-
- if (valid)
- element.value = Weave.Service.serverURL;
- else
- Weave.Svc.Prefs.reset("serverURL");
-
- return valid;
- },
-
- _handleChoice: function () {
- let desc = document.getElementById("mergeChoiceRadio").selectedIndex;
- document.getElementById("chosenActionDeck").selectedIndex = desc;
- switch (desc) {
- case 1:
- if (this._case1Setup)
- break;
-
- let places_db = PlacesUtils.history
- .QueryInterface(Ci.nsPIPlacesDatabase)
- .DBConnection;
- if (Weave.Service.engineManager.get("history").enabled) {
- let daysOfHistory = 0;
- let stm = places_db.createStatement(
- "SELECT ROUND(( " +
- "strftime('%s','now','localtime','utc') - " +
- "( " +
- "SELECT visit_date FROM moz_historyvisits " +
- "ORDER BY visit_date ASC LIMIT 1 " +
- ")/1000000 " +
- ")/86400) AS daysOfHistory ");
-
- if (stm.step())
- daysOfHistory = stm.getInt32(0);
- // Support %S for historical reasons (see bug 600141)
- document.getElementById("historyCount").value =
- PluralForm.get(daysOfHistory,
- this._stringBundle.GetStringFromName("historyDaysCount.label"))
- .replace("%S", daysOfHistory)
- .replace("#1", daysOfHistory);
- } else {
- document.getElementById("historyCount").hidden = true;
- }
-
- if (Weave.Service.engineManager.get("bookmarks").enabled) {
- let bookmarks = 0;
- let stm = places_db.createStatement(
- "SELECT count(*) AS bookmarks " +
- "FROM moz_bookmarks b " +
- "LEFT JOIN moz_bookmarks t ON " +
- "b.parent = t.id WHERE b.type = 1 AND t.parent <> :tag");
- stm.params.tag = PlacesUtils.tagsFolderId;
- if (stm.executeStep())
- bookmarks = stm.row.bookmarks;
- // Support %S for historical reasons (see bug 600141)
- document.getElementById("bookmarkCount").value =
- PluralForm.get(bookmarks,
- this._stringBundle.GetStringFromName("bookmarksCount.label"))
- .replace("%S", bookmarks)
- .replace("#1", bookmarks);
- } else {
- document.getElementById("bookmarkCount").hidden = true;
- }
-
- if (Weave.Service.engineManager.get("passwords").enabled) {
- let logins = Services.logins.getAllLogins({});
- // Support %S for historical reasons (see bug 600141)
- document.getElementById("passwordCount").value =
- PluralForm.get(logins.length,
- this._stringBundle.GetStringFromName("passwordsCount.label"))
- .replace("%S", logins.length)
- .replace("#1", logins.length);
- } else {
- document.getElementById("passwordCount").hidden = true;
- }
-
- if (!Weave.Service.engineManager.get("prefs").enabled) {
- document.getElementById("prefsWipe").hidden = true;
- }
-
- let addonsEngine = Weave.Service.engineManager.get("addons");
- if (addonsEngine.enabled) {
- let ids = addonsEngine._store.getAllIDs();
- let blessedcount = 0;
- for each (let i in ids) {
- if (i) {
- blessedcount++;
- }
- }
- // bug 600141 does not apply, as this does not have to support existing strings
- document.getElementById("addonCount").value =
- PluralForm.get(blessedcount,
- this._stringBundle.GetStringFromName("addonsCount.label"))
- .replace("#1", blessedcount);
- } else {
- document.getElementById("addonCount").hidden = true;
- }
-
- this._case1Setup = true;
- break;
- case 2:
- if (this._case2Setup)
- break;
- let count = 0;
- function appendNode(label) {
- let box = document.getElementById("clientList");
- let node = document.createElement("label");
- node.setAttribute("value", label);
- node.setAttribute("class", "data indent");
- box.appendChild(node);
- }
-
- for each (let name in Weave.Service.clientsEngine.stats.names) {
- // Don't list the current client
- if (name == Weave.Service.clientsEngine.localName)
- continue;
-
- // Only show the first several client names
- if (++count <= 5)
- appendNode(name);
- }
- if (count > 5) {
- // Support %S for historical reasons (see bug 600141)
- let label =
- PluralForm.get(count - 5,
- this._stringBundle.GetStringFromName("additionalClientCount.label"))
- .replace("%S", count - 5)
- .replace("#1", count - 5);
- appendNode(label);
- }
- this._case2Setup = true;
- break;
- }
-
- return true;
- },
-
- // sets class and string on a feedback element
- // if no property string is passed in, we clear label/style
- _setFeedback: function (element, success, string) {
- element.hidden = success || !string;
- let classname = success ? "success" : "error";
- let image = element.getElementsByAttribute("class", "statusIcon")[0];
- image.setAttribute("status", classname);
- let label = element.getElementsByAttribute("class", "status")[0];
- label.value = string;
- },
-
- // shim
- _setFeedbackMessage: function (element, success, string) {
- let str = "";
- if (string) {
- try {
- str = this._stringBundle.GetStringFromName(string);
- } catch(e) {}
-
- if (!str)
- str = Weave.Utils.getErrorString(string);
- }
- this._setFeedback(element, success, str);
- },
-
- loadCaptcha: function loadCaptcha() {
- let captchaURI = Weave.Service.miscAPI + "captcha_html";
- // First check for NoScript and whitelist the right sites.
- this._handleNoScript(true);
- if (this.captchaBrowser.currentURI.spec != captchaURI) {
- this.captchaBrowser.loadURI(captchaURI);
- }
- },
-
- onStateChange: function(webProgress, request, stateFlags, status) {
- // We're only looking for the end of the frame load
- if ((stateFlags & Ci.nsIWebProgressListener.STATE_STOP) == 0)
- return;
- if ((stateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK) == 0)
- return;
- if ((stateFlags & Ci.nsIWebProgressListener.STATE_IS_WINDOW) == 0)
- return;
-
- // If we didn't find a captcha, assume it's not needed and don't show it.
- let responseStatus = request.QueryInterface(Ci.nsIHttpChannel).responseStatus;
- setVisibility(this.captchaBrowser, responseStatus != 404);
- //XXX TODO we should really log any responseStatus other than 200
- },
- onProgressChange: function() {},
- onStatusChange: function() {},
- onSecurityChange: function() {},
- onLocationChange: function () {}
-};
-
-// Define lazy getters for various XUL elements.
-//
-// onWizardAdvance() and onPageShow() are run before init(), so we'll even
-// define things that will almost certainly be used (like 'wizard') as a lazy
-// getter here.
-["wizard",
- "pin1",
- "pin2",
- "pin3",
- "pairDeviceErrorRow",
- "pairDeviceThrobber"].forEach(function (id) {
- XPCOMUtils.defineLazyGetter(gSyncSetup, id, function() {
- return document.getElementById(id);
- });
-});
-XPCOMUtils.defineLazyGetter(gSyncSetup, "nextFocusEl", function () {
- return {pin1: this.pin2,
- pin2: this.pin3,
- pin3: this.wizard.getButton("next")};
-});
-XPCOMUtils.defineLazyGetter(gSyncSetup, "_stringBundle", function() {
- return Services.strings.createBundle("chrome://browser/locale/syncSetup.properties");
-});
diff --git a/components/sync/setup.xul b/components/sync/setup.xul
deleted file mode 100644
index cf2cc77..0000000
--- a/components/sync/setup.xul
+++ /dev/null
@@ -1,491 +0,0 @@
-<?xml version="1.0"?>
-
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
-<?xml-stylesheet href="chrome://browser/skin/syncSetup.css" type="text/css"?>
-<?xml-stylesheet href="chrome://browser/skin/syncCommon.css" type="text/css"?>
-
-<!DOCTYPE window [
-<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
-<!ENTITY % syncBrandDTD SYSTEM "chrome://browser/locale/syncBrand.dtd">
-<!ENTITY % syncSetupDTD SYSTEM "chrome://browser/locale/syncSetup.dtd">
-%brandDTD;
-%syncBrandDTD;
-%syncSetupDTD;
-]>
-<wizard id="wizard"
- title="&accountSetupTitle.label;"
- windowtype="Weave:AccountSetup"
- persist="screenX screenY"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml"
- onwizardnext="return gSyncSetup.onWizardAdvance()"
- onwizardback="return gSyncSetup.onWizardBack()"
- onwizardcancel="gSyncSetup.onWizardCancel()"
- onload="gSyncSetup.init()">
-
- <script type="application/javascript"
- src="chrome://browser/content/sync/setup.js"/>
- <script type="application/javascript"
- src="chrome://browser/content/sync/utils.js"/>
- <script type="application/javascript"
- src="chrome://browser/content/utilityOverlay.js"/>
- <script type="application/javascript"
- src="chrome://global/content/printUtils.js"/>
-
- <wizardpage id="addDevicePage"
- label="&pairDevice.title.label;"
- onpageshow="gSyncSetup.onPageShow()">
- <description>
- &pairDevice.dialog.description.label;
- <label class="text-link"
- value="&addDevice.showMeHow.label;"
- href="http://www.palemoon.org/sync/help/easy-setup.shtml"/>
- </description>
- <separator class="groove-thin"/>
- <description>
- &addDevice.dialog.enterCode.label;
- </description>
- <separator class="groove-thin"/>
- <vbox align="center">
- <textbox id="pin1"
- class="pin"
- oninput="gSyncSetup.onPINInput(this);"
- onfocus="this.select();"
- />
- <textbox id="pin2"
- class="pin"
- oninput="gSyncSetup.onPINInput(this);"
- onfocus="this.select();"
- />
- <textbox id="pin3"
- class="pin"
- oninput="gSyncSetup.onPINInput(this);"
- onfocus="this.select();"
- />
- </vbox>
- <separator class="groove-thin"/>
- <vbox id="pairDeviceThrobber" align="center" hidden="true">
- <image/>
- </vbox>
- <hbox id="pairDeviceErrorRow" pack="center" hidden="true">
- <image class="statusIcon" status="error"/>
- <label class="status"
- value="&addDevice.dialog.tryAgain.label;"/>
- </hbox>
- </wizardpage>
-
- <wizardpage id="pickSetupType"
- label="&syncBrand.fullName.label;"
- onpageshow="gSyncSetup.onPageShow()">
- <vbox align="center" flex="1">
- <description style="padding: 0 7em;">
- &setup.pickSetupType.description2;
- </description>
- <spacer flex="3"/>
- <button id="newAccount"
- class="accountChoiceButton"
- label="&button.createNewAccount.label;"
- oncommand="gSyncSetup.startNewAccountSetup()"
- align="center"/>
- <spacer flex="1"/>
- </vbox>
- <separator class="groove"/>
- <vbox align="center" flex="1">
- <spacer flex="1"/>
- <button id="existingAccount"
- class="accountChoiceButton"
- label="&button.haveAccount.label;"
- oncommand="gSyncSetup.useExistingAccount()"/>
- <spacer flex="3"/>
- </vbox>
- </wizardpage>
-
- <wizardpage label="&setup.newAccountDetailsPage.title.label;"
- id="newAccountStart"
- onextra1="gSyncSetup.onSyncOptions()"
- onpageshow="gSyncSetup.onPageShow();">
- <grid>
- <columns>
- <column/>
- <column class="inputColumn" flex="1"/>
- </columns>
- <rows>
- <row id="emailRow" align="center">
- <label value="&setup.emailAddress.label;"
- accesskey="&setup.emailAddress.accesskey;"
- control="weaveEmail"/>
- <textbox id="weaveEmail"
- oninput="gSyncSetup.onEmailInput()"/>
- </row>
- <row id="emailFeedbackRow" align="center" hidden="true">
- <spacer/>
- <hbox>
- <image class="statusIcon"/>
- <label class="status" value=" "/>
- </hbox>
- </row>
- <row id="passwordRow" align="center">
- <label value="&setup.choosePassword.label;"
- accesskey="&setup.choosePassword.accesskey;"
- control="weavePassword"/>
- <textbox id="weavePassword"
- type="password"
- onchange="gSyncSetup.onPasswordChange()"/>
- </row>
- <row id="confirmRow" align="center">
- <label value="&setup.confirmPassword.label;"
- accesskey="&setup.confirmPassword.accesskey;"
- control="weavePasswordConfirm"/>
- <textbox id="weavePasswordConfirm"
- type="password"
- onchange="gSyncSetup.onPasswordChange()"/>
- </row>
- <row id="passwordFeedbackRow" align="center" hidden="true">
- <spacer/>
- <hbox>
- <image class="statusIcon"/>
- <label class="status" value=" "/>
- </hbox>
- </row>
- <row align="center">
- <label control="server"
- value="&server.label;"/>
- <menulist id="server"
- oncommand="gSyncSetup.onServerCommand()"
- oninput="gSyncSetup.onServerInput()">
- <menupopup>
- <menuitem label="&serverType.default.label;"
- value="main"/>
- <menuitem label="&serverType.custom2.label;"
- value="custom"/>
- </menupopup>
- </menulist>
- </row>
- <row id="serverFeedbackRow" align="center" hidden="true">
- <spacer/>
- <hbox>
- <image class="statusIcon"/>
- <label class="status" value=" "/>
- </hbox>
- </row>
- <row id="TOSRow" align="center">
- <spacer/>
- <hbox align="center">
- <checkbox id="tos"
- accesskey="&setup.tosAgree1.accesskey;"
- oncommand="this.focus(); gSyncSetup.checkFields();"/>
- <description id="tosDesc"
- flex="1"
- onclick="document.getElementById('tos').focus();
- document.getElementById('tos').click()">
- &setup.tosAgree1.label;
- <label class="text-link inline-link"
- onclick="event.stopPropagation();gSyncUtils.openToS();">
- &setup.tosLink.label;
- </label>
- &setup.tosAgree2.label;
- <label class="text-link inline-link"
- onclick="event.stopPropagation();gSyncUtils.openPrivacyPolicy();">
- &setup.ppLink.label;
- </label>
- &setup.tosAgree3.label;
- </description>
- </hbox>
- </row>
- </rows>
- </grid>
- <spacer flex="1"/>
- <vbox flex="1" align="center">
- <browser height="150"
- width="500"
- id="captcha"
- type="content"
- disablehistory="true"/>
- <spacer flex="1"/>
- <hbox id="captchaFeedback">
- <image class="statusIcon"/>
- <label class="status" value=" "/>
- </hbox>
- </vbox>
- </wizardpage>
-
- <wizardpage id="addDevice"
- label="&pairDevice.title.label;"
- onextra1="gSyncSetup.onSyncOptions()"
- onpageshow="gSyncSetup.onPageShow()">
- <description>
- &pairDevice.setup.description.label;
- <label class="text-link"
- value="&addDevice.showMeHow.label;"
- href="http://www.palemoon.org/sync/help/easy-setup.shtml"/>
- </description>
- <label value="&addDevice.setup.enterCode.label;"
- control="easySetupPIN1"/>
- <spacer flex="1"/>
- <vbox align="center" flex="1">
- <textbox id="easySetupPIN1"
- class="pin"
- value=""
- readonly="true"
- />
- <textbox id="easySetupPIN2"
- class="pin"
- value=""
- readonly="true"
- />
- <textbox id="easySetupPIN3"
- class="pin"
- value=""
- readonly="true"
- />
- </vbox>
- <spacer flex="3"/>
- <label class="text-link"
- value="&addDevice.dontHaveDevice.label;"
- onclick="gSyncSetup.manualSetup();"/>
- </wizardpage>
-
- <wizardpage id="existingAccount"
- label="&setup.signInPage.title.label;"
- onextra1="gSyncSetup.onSyncOptions()"
- onpageshow="gSyncSetup.onPageShow()">
- <grid>
- <columns>
- <column/>
- <column class="inputColumn" flex="1"/>
- </columns>
- <rows>
- <row id="existingAccountRow" align="center">
- <label id="existingAccountLabel"
- value="&signIn.account2.label;"
- accesskey="&signIn.account2.accesskey;"
- control="existingAccount"/>
- <textbox id="existingAccountName"
- oninput="gSyncSetup.checkFields(event)"
- onchange="gSyncSetup.checkFields(event)"/>
- </row>
- <row id="existingPasswordRow" align="center">
- <label id="existingPasswordLabel"
- value="&signIn.password.label;"
- accesskey="&signIn.password.accesskey;"
- control="existingPassword"/>
- <textbox id="existingPassword"
- type="password"
- onkeyup="gSyncSetup.checkFields(event)"
- onchange="gSyncSetup.checkFields(event)"/>
- </row>
- <row id="existingPasswordFeedbackRow" align="center" hidden="true">
- <spacer/>
- <hbox>
- <image class="statusIcon"/>
- <label class="status" value=" "/>
- </hbox>
- </row>
- <row align="center">
- <spacer/>
- <label class="text-link"
- value="&resetPassword.label;"
- onclick="gSyncUtils.resetPassword(); return false;"/>
- </row>
- <row align="center">
- <label control="existingServer"
- value="&server.label;"/>
- <menulist id="existingServer"
- oncommand="gSyncSetup.onExistingServerCommand()"
- oninput="gSyncSetup.onExistingServerInput()">
- <menupopup>
- <menuitem label="&serverType.default.label;"
- value="main"/>
- <menuitem label="&serverType.custom2.label;"
- value="custom"/>
- </menupopup>
- </menulist>
- </row>
- <row id="existingServerFeedbackRow" align="center" hidden="true">
- <spacer/>
- <hbox>
- <image class="statusIcon"/>
- <vbox>
- <label class="status" value=" "/>
- </vbox>
- </hbox>
- </row>
- </rows>
- </grid>
-
- <groupbox>
- <label id="existingPassphraseLabel"
- value="&signIn.recoveryKey.label;"
- accesskey="&signIn.recoveryKey.accesskey;"
- control="existingPassphrase"/>
- <textbox id="existingPassphrase"
- oninput="gSyncSetup.checkFields()"/>
- <hbox id="login-throbber" hidden="true">
- <image/>
- <label value="&verifying.label;"/>
- </hbox>
- <vbox align="left" id="existingPassphraseFeedbackRow" hidden="true">
- <hbox>
- <image class="statusIcon"/>
- <label class="status" value=" "/>
- </hbox>
- </vbox>
- </groupbox>
-
- <vbox id="passphraseHelpBox">
- <description>
- &existingRecoveryKey.description;
- <label class="text-link"
- href="http://www.palemoon.org/sync/help/recoverykey.shtml">
- &addDevice.showMeHow.label;
- </label>
- <spacer id="passphraseHelpSpacer"/>
- <label class="text-link"
- onclick="gSyncSetup.resetPassphrase(); return false;">
- &resetSyncKey.label;
- </label>
- </description>
- </vbox>
- </wizardpage>
-
- <wizardpage id="syncOptionsPage"
- label="&setup.optionsPage.title;"
- onpageshow="gSyncSetup.onPageShow()">
- <groupbox id="syncOptions">
- <grid>
- <columns>
- <column/>
- <column flex="1" style="-moz-margin-end: 2px"/>
- </columns>
- <rows>
- <row align="center">
- <label value="&syncDeviceName.label;"
- accesskey="&syncDeviceName.accesskey;"
- control="syncComputerName"/>
- <textbox id="syncComputerName" flex="1"
- onchange="gSyncUtils.changeName(this)"/>
- </row>
- <row>
- <label value="&syncMy.label;" />
- <vbox>
- <checkbox label="&engine.addons.label;"
- accesskey="&engine.addons.accesskey;"
- id="engine.addons"
- checked="false"
- hidden="true"/>
- <checkbox label="&engine.bookmarks.label;"
- accesskey="&engine.bookmarks.accesskey;"
- id="engine.bookmarks"
- checked="true"/>
- <checkbox label="&engine.passwords.label;"
- accesskey="&engine.passwords.accesskey;"
- id="engine.passwords"
- checked="true"/>
- <checkbox label="&engine.prefs.label;"
- accesskey="&engine.prefs.accesskey;"
- id="engine.prefs"
- checked="true"/>
- <checkbox label="&engine.history.label;"
- accesskey="&engine.history.accesskey;"
- id="engine.history"
- checked="true"/>
- <checkbox label="&engine.tabs.label;"
- accesskey="&engine.tabs.accesskey;"
- id="engine.tabs"
- checked="true"/>
- </vbox>
- </row>
- </rows>
- </grid>
- </groupbox>
-
- <groupbox id="mergeOptions">
- <radiogroup id="mergeChoiceRadio" pack="start">
- <grid>
- <columns>
- <column/>
- <column flex="1"/>
- </columns>
- <rows flex="1">
- <row align="center">
- <radio id="resetClient"
- class="mergeChoiceButton"
- aria-labelledby="resetClientLabel"/>
- <label id="resetClientLabel" control="resetClient">
- <html:strong>&choice2.merge.recommended.label;</html:strong>
- &choice2a.merge.main.label;
- </label>
- </row>
- <row align="center">
- <radio id="wipeClient"
- class="mergeChoiceButton"
- aria-labelledby="wipeClientLabel"/>
- <label id="wipeClientLabel"
- control="wipeClient">
- &choice2a.client.main.label;
- </label>
- </row>
- <row align="center">
- <radio id="wipeRemote"
- class="mergeChoiceButton"
- aria-labelledby="wipeRemoteLabel"/>
- <label id="wipeRemoteLabel"
- control="wipeRemote">
- &choice2a.server.main.label;
- </label>
- </row>
- </rows>
- </grid>
- </radiogroup>
- </groupbox>
- </wizardpage>
-
- <wizardpage id="syncOptionsConfirm"
- label="&setup.optionsConfirmPage.title;"
- onpageshow="gSyncSetup.onPageShow()">
- <deck id="chosenActionDeck">
- <vbox id="chosenActionMerge" class="confirm">
- <description class="normal">
- &confirm.merge2.label;
- </description>
- </vbox>
- <vbox id="chosenActionWipeClient" class="confirm">
- <description class="normal">
- &confirm.client3.label;
- </description>
- <separator class="thin"/>
- <vbox id="dataList">
- <label class="data indent" id="bookmarkCount"/>
- <label class="data indent" id="historyCount"/>
- <label class="data indent" id="passwordCount"/>
- <label class="data indent" id="addonCount"/>
- <label class="data indent" id="prefsWipe"
- value="&engine.prefs.label;"/>
- </vbox>
- <separator class="thin"/>
- <description class="normal">
- &confirm.client2.moreinfo.label;
- </description>
- </vbox>
- <vbox id="chosenActionWipeServer" class="confirm">
- <description class="normal">
- &confirm.server2.label;
- </description>
- <separator class="thin"/>
- <vbox id="clientList">
- </vbox>
- </vbox>
- </deck>
- </wizardpage>
- <!-- In terms of the wizard flow shown to the user, the 'syncOptionsConfirm'
- page above is not the last wizard page. To prevent the wizard binding from
- assuming that it is, we're inserting this dummy page here. This also means
- that the wizard needs to always be closed manually via wizardFinish(). -->
- <wizardpage>
- </wizardpage>
-</wizard>
-
diff --git a/components/sync/utils.js b/components/sync/utils.js
deleted file mode 100644
index d41ecf1..0000000
--- a/components/sync/utils.js
+++ /dev/null
@@ -1,218 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-// Equivalent to 0o600 permissions; used for saved Sync Recovery Key.
-// This constant can be replaced when the equivalent values are available to
-// chrome JS; see Bug 433295 and Bug 757351.
-const PERMISSIONS_RWUSR = 0x180;
-
-// Weave should always exist before before this file gets included.
-var gSyncUtils = {
- get bundle() {
- delete this.bundle;
- return this.bundle = Services.strings.createBundle("chrome://browser/locale/syncSetup.properties");
- },
-
- // opens in a new window if we're in a modal prefwindow world, in a new tab otherwise
- _openLink: function (url) {
- let thisDocEl = document.documentElement,
- openerDocEl = window.opener && window.opener.document.documentElement;
- if (thisDocEl.id == "accountSetup" && window.opener &&
- openerDocEl.id == "BrowserPreferences" && !openerDocEl.instantApply)
- openUILinkIn(url, "window");
- else if (thisDocEl.id == "BrowserPreferences" && !thisDocEl.instantApply)
- openUILinkIn(url, "window");
- else if (document.documentElement.id == "change-dialog")
- Services.wm.getMostRecentWindow("navigator:browser")
- .openUILinkIn(url, "tab");
- else
- openUILinkIn(url, "tab");
- },
-
- changeName: function changeName(input) {
- // Make sure to update to a modified name, e.g., empty-string -> default
- Weave.Service.clientsEngine.localName = input.value;
- input.value = Weave.Service.clientsEngine.localName;
- },
-
- openChange: function openChange(type, duringSetup) {
- // Just re-show the dialog if it's already open
- let openedDialog = Services.wm.getMostRecentWindow("Sync:" + type);
- if (openedDialog != null) {
- openedDialog.focus();
- return;
- }
-
- // Open up the change dialog
- let changeXUL = "chrome://browser/content/sync/genericChange.xul";
- let changeOpt = "centerscreen,chrome,resizable=no";
- Services.ww.activeWindow.openDialog(changeXUL, "", changeOpt,
- type, duringSetup);
- },
-
- changePassword: function () {
- if (Weave.Utils.ensureMPUnlocked())
- this.openChange("ChangePassword");
- },
-
- resetPassphrase: function (duringSetup) {
- if (Weave.Utils.ensureMPUnlocked())
- this.openChange("ResetPassphrase", duringSetup);
- },
-
- updatePassphrase: function () {
- if (Weave.Utils.ensureMPUnlocked())
- this.openChange("UpdatePassphrase");
- },
-
- resetPassword: function () {
- this._openLink(Weave.Service.pwResetURL);
- },
-
- openToS: function () {
- this._openLink(Weave.Svc.Prefs.get("termsURL"));
- },
-
- openPrivacyPolicy: function () {
- this._openLink(Weave.Svc.Prefs.get("privacyURL"));
- },
-
- openFirstSyncProgressPage: function () {
- this._openLink("about:sync-progress");
- },
-
- /**
- * Prepare an invisible iframe with the passphrase backup document.
- * Used by both the print and saving methods.
- *
- * @param elid : ID of the form element containing the passphrase.
- * @param callback : Function called once the iframe has loaded.
- */
- _preparePPiframe: function(elid, callback) {
- let pp = document.getElementById(elid).value;
-
- // Create an invisible iframe whose contents we can print.
- let iframe = document.createElement("iframe");
- iframe.setAttribute("src", "chrome://browser/content/sync/key.xhtml");
- iframe.collapsed = true;
- document.documentElement.appendChild(iframe);
- iframe.contentWindow.addEventListener("load", function() {
- iframe.contentWindow.removeEventListener("load", arguments.callee, false);
-
- // Insert the Sync Key into the page.
- let el = iframe.contentDocument.getElementById("synckey");
- el.firstChild.nodeValue = pp;
-
- // Insert the TOS and Privacy Policy URLs into the page.
- let termsURL = Weave.Svc.Prefs.get("termsURL");
- el = iframe.contentDocument.getElementById("tosLink");
- el.setAttribute("href", termsURL);
- el.firstChild.nodeValue = termsURL;
-
- let privacyURL = Weave.Svc.Prefs.get("privacyURL");
- el = iframe.contentDocument.getElementById("ppLink");
- el.setAttribute("href", privacyURL);
- el.firstChild.nodeValue = privacyURL;
-
- callback(iframe);
- }, false);
- },
-
- /**
- * Print passphrase backup document.
- *
- * @param elid : ID of the form element containing the passphrase.
- */
- passphrasePrint: function(elid) {
- this._preparePPiframe(elid, function(iframe) {
- let webBrowserPrint = iframe.contentWindow
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebBrowserPrint);
- let printSettings = PrintUtils.getPrintSettings();
-
- // Display no header/footer decoration except for the date.
- printSettings.headerStrLeft
- = printSettings.headerStrCenter
- = printSettings.headerStrRight
- = printSettings.footerStrLeft
- = printSettings.footerStrCenter = "";
- printSettings.footerStrRight = "&D";
-
- try {
- webBrowserPrint.print(printSettings, null);
- } catch (ex) {
- // print()'s return codes are expressed as exceptions. Ignore.
- }
- });
- },
-
- /**
- * Save passphrase backup document to disk as HTML file.
- *
- * @param elid : ID of the form element containing the passphrase.
- */
- passphraseSave: function(elid) {
- let dialogTitle = this.bundle.GetStringFromName("save.recoverykey.title");
- let defaultSaveName = this.bundle.GetStringFromName("save.recoverykey.defaultfilename");
- this._preparePPiframe(elid, function(iframe) {
- let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
- let fpCallback = function fpCallback_done(aResult) {
- if (aResult == Ci.nsIFilePicker.returnOK ||
- aResult == Ci.nsIFilePicker.returnReplace) {
- let stream = Cc["@mozilla.org/network/file-output-stream;1"].
- createInstance(Ci.nsIFileOutputStream);
- stream.init(fp.file, -1, PERMISSIONS_RWUSR, 0);
-
- let serializer = new XMLSerializer();
- let output = serializer.serializeToString(iframe.contentDocument);
- output = output.replace(/<!DOCTYPE (.|\n)*?]>/,
- '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" ' +
- '"DTD/xhtml1-strict.dtd">');
- output = Weave.Utils.encodeUTF8(output);
- stream.write(output, output.length);
- }
- };
-
- fp.init(window, dialogTitle, Ci.nsIFilePicker.modeSave);
- fp.appendFilters(Ci.nsIFilePicker.filterHTML);
- fp.defaultString = defaultSaveName;
- fp.open(fpCallback);
- return false;
- });
- },
-
- /**
- * validatePassword
- *
- * @param el1 : the first textbox element in the form
- * @param el2 : the second textbox element, if omitted it's an update form
- *
- * returns [valid, errorString]
- */
- validatePassword: function (el1, el2) {
- let valid = false;
- let val1 = el1.value;
- let val2 = el2 ? el2.value : "";
- let error = "";
-
- if (!el2)
- valid = val1.length >= Weave.MIN_PASS_LENGTH;
- else if (val1 && val1 == Weave.Service.identity.username)
- error = "change.password.pwSameAsUsername";
- else if (val1 && val1 == Weave.Service.identity.account)
- error = "change.password.pwSameAsEmail";
- else if (val1 && val1 == Weave.Service.identity.basicPassword)
- error = "change.password.pwSameAsPassword";
- else if (val1 && val2) {
- if (val1 == val2 && val1.length >= Weave.MIN_PASS_LENGTH)
- valid = true;
- else if (val1.length < Weave.MIN_PASS_LENGTH)
- error = "change.password.tooShort";
- else if (val1 != val2)
- error = "change.password.mismatch";
- }
- let errorString = error ? Weave.Utils.getErrorString(error) : "";
- return [valid, errorString];
- }
-};